summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bin')
-rw-r--r--bin/Makefile.am1
-rw-r--r--bin/Makefile.in734
-rw-r--r--bin/check/Makefile.am34
-rw-r--r--bin/check/Makefile.in872
-rw-r--r--bin/check/check-tool.c693
-rw-r--r--bin/check/check-tool.h52
-rw-r--r--bin/check/named-checkconf.c754
-rw-r--r--bin/check/named-checkconf.rst108
-rw-r--r--bin/check/named-checkzone.c569
-rw-r--r--bin/check/named-checkzone.rst222
-rw-r--r--bin/check/named-compilezone.rst224
-rw-r--r--bin/confgen/Makefile.am30
-rw-r--r--bin/confgen/Makefile.in876
-rw-r--r--bin/confgen/ddns-confgen.rst96
-rw-r--r--bin/confgen/include/confgen/os.h33
-rw-r--r--bin/confgen/keygen.c178
-rw-r--r--bin/confgen/keygen.h41
-rw-r--r--bin/confgen/os.c36
-rw-r--r--bin/confgen/rndc-confgen.c294
-rw-r--r--bin/confgen/rndc-confgen.rst121
-rw-r--r--bin/confgen/tsig-keygen.c301
-rw-r--r--bin/confgen/tsig-keygen.rst54
-rw-r--r--bin/confgen/util.c49
-rw-r--r--bin/confgen/util.h42
-rw-r--r--bin/delv/Makefile.am21
-rw-r--r--bin/delv/Makefile.in823
-rw-r--r--bin/delv/delv.c1868
-rw-r--r--bin/delv/delv.rst364
-rw-r--r--bin/dig/Makefile.am39
-rw-r--r--bin/dig/Makefile.in897
-rw-r--r--bin/dig/dig.c3102
-rw-r--r--bin/dig/dig.rst809
-rw-r--r--bin/dig/dighost.c4989
-rw-r--r--bin/dig/dighost.h466
-rw-r--r--bin/dig/host.c931
-rw-r--r--bin/dig/host.rst193
-rw-r--r--bin/dig/nslookup.c977
-rw-r--r--bin/dig/nslookup.rst208
-rw-r--r--bin/dig/readline.h58
-rw-r--r--bin/dnssec/Makefile.am38
-rw-r--r--bin/dnssec/Makefile.in976
-rw-r--r--bin/dnssec/dnssec-cds.c1361
-rw-r--r--bin/dnssec/dnssec-cds.rst221
-rw-r--r--bin/dnssec/dnssec-dsfromkey.c561
-rw-r--r--bin/dnssec/dnssec-dsfromkey.rst159
-rw-r--r--bin/dnssec/dnssec-importkey.c477
-rw-r--r--bin/dnssec/dnssec-importkey.rst142
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.c760
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.rst289
-rw-r--r--bin/dnssec/dnssec-keygen.c1292
-rw-r--r--bin/dnssec/dnssec-keygen.rst357
-rw-r--r--bin/dnssec/dnssec-revoke.c263
-rw-r--r--bin/dnssec/dnssec-revoke.rst78
-rw-r--r--bin/dnssec/dnssec-settime.c967
-rw-r--r--bin/dnssec/dnssec-settime.rst271
-rw-r--r--bin/dnssec/dnssec-signzone.c4165
-rw-r--r--bin/dnssec/dnssec-signzone.rst436
-rw-r--r--bin/dnssec/dnssec-verify.c345
-rw-r--r--bin/dnssec/dnssec-verify.rst107
-rw-r--r--bin/dnssec/dnssectool.c585
-rw-r--r--bin/dnssec/dnssectool.h104
-rw-r--r--bin/named/Makefile.am123
-rw-r--r--bin/named/Makefile.in964
-rw-r--r--bin/named/bind9.xsl1106
-rw-r--r--bin/named/builtin.c650
-rw-r--r--bin/named/config.c1034
-rw-r--r--bin/named/control.c307
-rw-r--r--bin/named/controlconf.c1494
-rw-r--r--bin/named/dlz_dlopen_driver.c552
-rw-r--r--bin/named/fuzz.c782
-rw-r--r--bin/named/geoip.c147
-rw-r--r--bin/named/include/dlz/dlz_dlopen_driver.h20
-rw-r--r--bin/named/include/named/builtin.h24
-rw-r--r--bin/named/include/named/config.h82
-rw-r--r--bin/named/include/named/control.h108
-rw-r--r--bin/named/include/named/fuzz.h22
-rw-r--r--bin/named/include/named/geoip.h28
-rw-r--r--bin/named/include/named/globals.h163
-rw-r--r--bin/named/include/named/log.h84
-rw-r--r--bin/named/include/named/logconf.h25
-rw-r--r--bin/named/include/named/main.h36
-rw-r--r--bin/named/include/named/os.h75
-rw-r--r--bin/named/include/named/server.h396
-rw-r--r--bin/named/include/named/smf_globals.h38
-rw-r--r--bin/named/include/named/statschannel.h51
-rw-r--r--bin/named/include/named/tkeyconf.h43
-rw-r--r--bin/named/include/named/transportconf.h43
-rw-r--r--bin/named/include/named/tsigconf.h41
-rw-r--r--bin/named/include/named/types.h38
-rw-r--r--bin/named/include/named/zoneconf.h76
-rw-r--r--bin/named/log.c253
-rw-r--r--bin/named/logconf.c374
-rw-r--r--bin/named/main.c1663
-rw-r--r--bin/named/named.conf.rst67
-rw-r--r--bin/named/named.rst254
-rw-r--r--bin/named/os.c932
-rw-r--r--bin/named/server.c16755
-rw-r--r--bin/named/statschannel.c4084
-rw-r--r--bin/named/tkeyconf.c115
-rw-r--r--bin/named/transportconf.c263
-rw-r--r--bin/named/tsigconf.c181
-rw-r--r--bin/named/xsl_p.h16
-rw-r--r--bin/named/zoneconf.c2114
-rw-r--r--bin/nsupdate/Makefile.am34
-rw-r--r--bin/nsupdate/Makefile.in828
-rw-r--r--bin/nsupdate/nsupdate.c3463
-rw-r--r--bin/nsupdate/nsupdate.rst391
-rw-r--r--bin/plugins/Makefile.am15
-rw-r--r--bin/plugins/Makefile.in847
-rw-r--r--bin/plugins/filter-a.c879
-rw-r--r--bin/plugins/filter-a.rst86
-rw-r--r--bin/plugins/filter-aaaa.c881
-rw-r--r--bin/plugins/filter-aaaa.rst90
-rw-r--r--bin/rndc/Makefile.am26
-rw-r--r--bin/rndc/Makefile.in831
-rw-r--r--bin/rndc/rndc.c1125
-rw-r--r--bin/rndc/rndc.conf.rst158
-rw-r--r--bin/rndc/rndc.rst667
-rw-r--r--bin/rndc/util.c49
-rw-r--r--bin/rndc/util.h42
-rw-r--r--bin/tests/Makefile.am38
-rw-r--r--bin/tests/Makefile.in977
-rwxr-xr-xbin/tests/convert-trs-to-junit.py148
-rw-r--r--bin/tests/system/Makefile.am258
-rw-r--r--bin/tests/system/Makefile.in2416
-rw-r--r--bin/tests/system/README843
-rw-r--r--bin/tests/system/acl/clean.sh26
-rw-r--r--bin/tests/system/acl/ns2/named1.conf.in62
-rw-r--r--bin/tests/system/acl/ns2/named2.conf.in66
-rw-r--r--bin/tests/system/acl/ns2/named3.conf.in75
-rw-r--r--bin/tests/system/acl/ns2/named4.conf.in74
-rw-r--r--bin/tests/system/acl/ns2/named5.conf.in64
-rw-r--r--bin/tests/system/acl/ns3/example.db21
-rw-r--r--bin/tests/system/acl/ns3/named.conf.in36
-rw-r--r--bin/tests/system/acl/ns4/example.db21
-rw-r--r--bin/tests/system/acl/ns4/existing.db21
-rw-r--r--bin/tests/system/acl/ns4/named.conf.in41
-rw-r--r--bin/tests/system/acl/setup.sh21
-rw-r--r--bin/tests/system/acl/tests.sh230
-rw-r--r--bin/tests/system/acl/tests_sh_acl.py14
-rw-r--r--bin/tests/system/additional/clean.sh23
-rw-r--r--bin/tests/system/additional/ns1/mx.db18
-rw-r--r--bin/tests/system/additional/ns1/named.args2
-rw-r--r--bin/tests/system/additional/ns1/named1.conf.in62
-rw-r--r--bin/tests/system/additional/ns1/named2.conf.in62
-rw-r--r--bin/tests/system/additional/ns1/named3.conf.in63
-rw-r--r--bin/tests/system/additional/ns1/named4.conf.in72
-rw-r--r--bin/tests/system/additional/ns1/naptr.db20
-rw-r--r--bin/tests/system/additional/ns1/naptr2.db20
-rw-r--r--bin/tests/system/additional/ns1/nid.db21
-rw-r--r--bin/tests/system/additional/ns1/root.db21
-rw-r--r--bin/tests/system/additional/ns1/rt.db21
-rw-r--r--bin/tests/system/additional/ns1/rt2.db20
-rw-r--r--bin/tests/system/additional/ns1/srv.db18
-rw-r--r--bin/tests/system/additional/ns2/named.conf.in31
-rw-r--r--bin/tests/system/additional/ns2/root.db21
-rw-r--r--bin/tests/system/additional/ns3/ex.db16
-rw-r--r--bin/tests/system/additional/ns3/ex2.db15
-rw-r--r--bin/tests/system/additional/ns3/named.conf.in42
-rw-r--r--bin/tests/system/additional/ns3/root.hint13
-rw-r--r--bin/tests/system/additional/setup.sh19
-rw-r--r--bin/tests/system/additional/tests.sh379
-rw-r--r--bin/tests/system/additional/tests_sh_additional.py14
-rw-r--r--bin/tests/system/addzone/clean.sh44
-rw-r--r--bin/tests/system/addzone/ns1/inlinesec.db26
-rw-r--r--bin/tests/system/addzone/ns1/named.conf.in47
-rw-r--r--bin/tests/system/addzone/ns1/redirect.db.113
-rw-r--r--bin/tests/system/addzone/ns1/redirect.db.213
-rw-r--r--bin/tests/system/addzone/ns2/added.db26
-rw-r--r--bin/tests/system/addzone/ns2/default.nzf.in14
-rw-r--r--bin/tests/system/addzone/ns2/hints.db14
-rw-r--r--bin/tests/system/addzone/ns2/inline.db26
-rw-r--r--bin/tests/system/addzone/ns2/named1.conf.in44
-rw-r--r--bin/tests/system/addzone/ns2/named2.conf.in68
-rw-r--r--bin/tests/system/addzone/ns2/named3.conf.in78
-rw-r--r--bin/tests/system/addzone/ns2/normal.db26
-rw-r--r--bin/tests/system/addzone/ns2/previous.db26
-rw-r--r--bin/tests/system/addzone/ns2/redirect.db.113
-rw-r--r--bin/tests/system/addzone/ns2/redirect.db.213
-rw-r--r--bin/tests/system/addzone/ns3/e.db14
-rw-r--r--bin/tests/system/addzone/ns3/example.db13
-rw-r--r--bin/tests/system/addzone/ns3/named1.conf.in38
-rw-r--r--bin/tests/system/addzone/ns3/named2.conf.in29
-rw-r--r--bin/tests/system/addzone/ns3/redirect.db.114
-rw-r--r--bin/tests/system/addzone/ns3/redirect.db.214
-rw-r--r--bin/tests/system/addzone/setup.sh25
-rwxr-xr-xbin/tests/system/addzone/tests.sh756
-rwxr-xr-xbin/tests/system/addzone/tests_rndc_deadlock.py92
-rw-r--r--bin/tests/system/addzone/tests_sh_addzone.py14
-rw-r--r--bin/tests/system/allow-query/clean.sh24
-rw-r--r--bin/tests/system/allow-query/ns1/named.conf.in26
-rw-r--r--bin/tests/system/allow-query/ns1/root.db18
-rw-r--r--bin/tests/system/allow-query/ns2/generic.db33
-rw-r--r--bin/tests/system/allow-query/ns2/named01.conf.in33
-rw-r--r--bin/tests/system/allow-query/ns2/named02.conf.in34
-rw-r--r--bin/tests/system/allow-query/ns2/named03.conf.in34
-rw-r--r--bin/tests/system/allow-query/ns2/named04.conf.in34
-rw-r--r--bin/tests/system/allow-query/ns2/named05.conf.in34
-rw-r--r--bin/tests/system/allow-query/ns2/named06.conf.in34
-rw-r--r--bin/tests/system/allow-query/ns2/named07.conf.in36
-rw-r--r--bin/tests/system/allow-query/ns2/named08.conf.in36
-rw-r--r--bin/tests/system/allow-query/ns2/named09.conf.in36
-rw-r--r--bin/tests/system/allow-query/ns2/named10.conf.in39
-rw-r--r--bin/tests/system/allow-query/ns2/named11.conf.in45
-rw-r--r--bin/tests/system/allow-query/ns2/named12.conf.in39
-rw-r--r--bin/tests/system/allow-query/ns2/named21.conf.in36
-rw-r--r--bin/tests/system/allow-query/ns2/named22.conf.in39
-rw-r--r--bin/tests/system/allow-query/ns2/named23.conf.in38
-rw-r--r--bin/tests/system/allow-query/ns2/named24.conf.in38
-rw-r--r--bin/tests/system/allow-query/ns2/named25.conf.in38
-rw-r--r--bin/tests/system/allow-query/ns2/named26.conf.in38
-rw-r--r--bin/tests/system/allow-query/ns2/named27.conf.in41
-rw-r--r--bin/tests/system/allow-query/ns2/named28.conf.in40
-rw-r--r--bin/tests/system/allow-query/ns2/named29.conf.in40
-rw-r--r--bin/tests/system/allow-query/ns2/named30.conf.in43
-rw-r--r--bin/tests/system/allow-query/ns2/named31.conf.in50
-rw-r--r--bin/tests/system/allow-query/ns2/named32.conf.in43
-rw-r--r--bin/tests/system/allow-query/ns2/named33.conf.in40
-rw-r--r--bin/tests/system/allow-query/ns2/named34.conf.in39
-rw-r--r--bin/tests/system/allow-query/ns2/named40.conf.in108
-rw-r--r--bin/tests/system/allow-query/ns2/named53.conf.in35
-rw-r--r--bin/tests/system/allow-query/ns2/named54.conf.in35
-rw-r--r--bin/tests/system/allow-query/ns2/named55.conf.in40
-rw-r--r--bin/tests/system/allow-query/ns2/named56.conf.in39
-rw-r--r--bin/tests/system/allow-query/ns2/named57.conf.in43
-rw-r--r--bin/tests/system/allow-query/ns3/named.args2
-rw-r--r--bin/tests/system/allow-query/ns3/named1.conf.in35
-rw-r--r--bin/tests/system/allow-query/ns3/named2.conf.in38
-rw-r--r--bin/tests/system/allow-query/ns3/named3.conf.in38
-rw-r--r--bin/tests/system/allow-query/ns3/named4.conf.in38
-rw-r--r--bin/tests/system/allow-query/setup.sh19
-rw-r--r--bin/tests/system/allow-query/tests.sh739
-rw-r--r--bin/tests/system/allow-query/tests_sh_allowquery.py14
-rw-r--r--bin/tests/system/ans.pl534
-rw-r--r--bin/tests/system/auth/clean.sh20
-rw-r--r--bin/tests/system/auth/ns1/chaos.db23
-rw-r--r--bin/tests/system/auth/ns1/example.com.db25
-rw-r--r--bin/tests/system/auth/ns1/example.net.db22
-rw-r--r--bin/tests/system/auth/ns1/named.conf.in44
-rw-r--r--bin/tests/system/auth/ns2/named.conf.in37
-rw-r--r--bin/tests/system/auth/setup.sh17
-rw-r--r--bin/tests/system/auth/tests.sh192
-rw-r--r--bin/tests/system/auth/tests_sh_auth.py14
-rw-r--r--bin/tests/system/autosign/clean.sh75
-rw-r--r--bin/tests/system/autosign/ns1/keygen.sh53
-rw-r--r--bin/tests/system/autosign/ns1/named.conf.in48
-rw-r--r--bin/tests/system/autosign/ns1/root.db.in26
-rw-r--r--bin/tests/system/autosign/ns2/Xbar.+013+59973.key5
-rw-r--r--bin/tests/system/autosign/ns2/Xbar.+013+59973.private6
-rw-r--r--bin/tests/system/autosign/ns2/Xbar.+013+60101.key5
-rw-r--r--bin/tests/system/autosign/ns2/Xbar.+013+60101.private6
-rw-r--r--bin/tests/system/autosign/ns2/bar.db.in80
-rw-r--r--bin/tests/system/autosign/ns2/child.nsec3.example.db20
-rw-r--r--bin/tests/system/autosign/ns2/child.optout.example.db20
-rw-r--r--bin/tests/system/autosign/ns2/dst.example.db.in21
-rw-r--r--bin/tests/system/autosign/ns2/example.db.in88
-rw-r--r--bin/tests/system/autosign/ns2/insecure.secure.example.db26
-rw-r--r--bin/tests/system/autosign/ns2/keygen.sh65
-rw-r--r--bin/tests/system/autosign/ns2/named.conf.in109
-rw-r--r--bin/tests/system/autosign/ns2/optout-with-ent.db.in22
-rw-r--r--bin/tests/system/autosign/ns2/private.secure.example.db.in27
-rw-r--r--bin/tests/system/autosign/ns3/autonsec3.example.db.in37
-rw-r--r--bin/tests/system/autosign/ns3/cdnskey-delete.example.db.in28
-rw-r--r--bin/tests/system/autosign/ns3/cds-delete.example.db.in28
-rw-r--r--bin/tests/system/autosign/ns3/delay.example.db26
-rw-r--r--bin/tests/system/autosign/ns3/delzsk.example.db.in25
-rw-r--r--bin/tests/system/autosign/ns3/dname-at-apex-nsec3.example.db.in16
-rw-r--r--bin/tests/system/autosign/ns3/inacksk2.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/inacksk3.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/inaczsk.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/inaczsk2.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/inaczsk3.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/insecure.example.db26
-rw-r--r--bin/tests/system/autosign/ns3/jitter.nsec3.example.db.in22
-rw-r--r--bin/tests/system/autosign/ns3/keygen.sh398
-rw-r--r--bin/tests/system/autosign/ns3/kskonly.example.db.in34
-rw-r--r--bin/tests/system/autosign/ns3/named.conf.in335
-rw-r--r--bin/tests/system/autosign/ns3/noksk.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/nozsk.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/nsec-only.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/nsec3-to-nsec.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/nsec3.example.db.in37
-rw-r--r--bin/tests/system/autosign/ns3/nsec3.nsec3.example.db.in35
-rw-r--r--bin/tests/system/autosign/ns3/nsec3.optout.example.db.in35
-rw-r--r--bin/tests/system/autosign/ns3/oldsigs.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/optout.example.db.in38
-rw-r--r--bin/tests/system/autosign/ns3/optout.nsec3.example.db.in35
-rw-r--r--bin/tests/system/autosign/ns3/optout.optout.example.db.in35
-rw-r--r--bin/tests/system/autosign/ns3/rsasha256.example.db.in28
-rw-r--r--bin/tests/system/autosign/ns3/rsasha512.example.db.in28
-rw-r--r--bin/tests/system/autosign/ns3/secure-to-insecure.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/secure-to-insecure2.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/secure.example.db.in37
-rw-r--r--bin/tests/system/autosign/ns3/secure.nsec3.example.db.in35
-rw-r--r--bin/tests/system/autosign/ns3/secure.optout.example.db.in35
-rw-r--r--bin/tests/system/autosign/ns3/sync.example.db.in34
-rw-r--r--bin/tests/system/autosign/ns3/ttl1.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/ttl2.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/ttl3.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns3/ttl4.example.db.in26
-rw-r--r--bin/tests/system/autosign/ns4/named.conf.in35
-rw-r--r--bin/tests/system/autosign/ns5/named.conf.in33
-rw-r--r--bin/tests/system/autosign/setup.sh23
-rwxr-xr-xbin/tests/system/autosign/tests.sh1800
-rw-r--r--bin/tests/system/autosign/tests_sh_autosign.py14
-rw-r--r--bin/tests/system/builtin/clean.sh20
-rw-r--r--bin/tests/system/builtin/ns1/named.conf.in31
-rw-r--r--bin/tests/system/builtin/ns2/named.conf.in32
-rw-r--r--bin/tests/system/builtin/ns3/named.conf.in34
-rw-r--r--bin/tests/system/builtin/setup.sh18
-rw-r--r--bin/tests/system/builtin/tests.sh248
-rw-r--r--bin/tests/system/builtin/tests_sh_builtin.py14
-rw-r--r--bin/tests/system/cacheclean/clean.sh27
-rw-r--r--bin/tests/system/cacheclean/dig.batch924
-rw-r--r--bin/tests/system/cacheclean/knowngood.dig.out953
-rw-r--r--bin/tests/system/cacheclean/ns1/example.db2942
-rw-r--r--bin/tests/system/cacheclean/ns1/expire-test.db21
-rw-r--r--bin/tests/system/cacheclean/ns1/flushtest.db44
-rw-r--r--bin/tests/system/cacheclean/ns1/named.args1
-rw-r--r--bin/tests/system/cacheclean/ns1/named.conf.in42
-rw-r--r--bin/tests/system/cacheclean/ns2/named.args1
-rw-r--r--bin/tests/system/cacheclean/ns2/named.conf.in50
-rw-r--r--bin/tests/system/cacheclean/setup.sh17
-rwxr-xr-xbin/tests/system/cacheclean/tests.sh269
-rw-r--r--bin/tests/system/cacheclean/tests_sh_cacheclean.py14
-rw-r--r--bin/tests/system/case/clean.sh24
-rw-r--r--bin/tests/system/case/dynamic.good6
-rw-r--r--bin/tests/system/case/ns1/dynamic.db.in26
-rw-r--r--bin/tests/system/case/ns1/example.db23
-rw-r--r--bin/tests/system/case/ns1/named.conf.in41
-rw-r--r--bin/tests/system/case/ns2/named.conf.in41
-rw-r--r--bin/tests/system/case/postns1.good6
-rw-r--r--bin/tests/system/case/postupdate.good6
-rw-r--r--bin/tests/system/case/setup.sh18
-rw-r--r--bin/tests/system/case/tests.sh151
-rw-r--r--bin/tests/system/case/tests_sh_case.py14
-rw-r--r--bin/tests/system/catz/clean.sh37
-rw-r--r--bin/tests/system/catz/ns1/catalog-bad1.example.db13
-rw-r--r--bin/tests/system/catz/ns1/catalog-bad2.example.db14
-rw-r--r--bin/tests/system/catz/ns1/catalog-bad3.example.db15
-rw-r--r--bin/tests/system/catz/ns1/catalog-bad4.example.db14
-rw-r--r--bin/tests/system/catz/ns1/catalog-bad5.example.db14
-rw-r--r--bin/tests/system/catz/ns1/catalog.example.db.in14
-rw-r--r--bin/tests/system/catz/ns1/named.conf.in144
-rw-r--r--bin/tests/system/catz/ns2/dom-existing.example.db13
-rw-r--r--bin/tests/system/catz/ns2/named1.conf.in184
-rw-r--r--bin/tests/system/catz/ns2/named2.conf.in127
-rw-r--r--bin/tests/system/catz/ns3/catalog.example.db.in14
-rw-r--r--bin/tests/system/catz/ns3/dom5.example.db13
-rw-r--r--bin/tests/system/catz/ns3/dom6.example.db13
-rw-r--r--bin/tests/system/catz/ns3/named.conf.in58
-rw-r--r--bin/tests/system/catz/ns4/catalog.example.db.in14
-rw-r--r--bin/tests/system/catz/ns4/named.conf.in66
-rw-r--r--bin/tests/system/catz/setup.sh30
-rw-r--r--bin/tests/system/catz/tests.sh2658
-rw-r--r--bin/tests/system/catz/tests_sh_catz.py14
-rw-r--r--bin/tests/system/cds/checkmtime.pl18
-rw-r--r--bin/tests/system/cds/checktime.pl27
-rw-r--r--bin/tests/system/cds/clean.sh23
-rw-r--r--bin/tests/system/cds/mangle.pl19
-rw-r--r--bin/tests/system/cds/setup.sh138
-rw-r--r--bin/tests/system/cds/tests.sh260
-rw-r--r--bin/tests/system/cds/tests_sh_cds.py14
-rw-r--r--bin/tests/system/chain/README22
-rw-r--r--bin/tests/system/chain/ans3/ans.pl131
-rw-r--r--bin/tests/system/chain/ans4/README.anspy24
-rwxr-xr-xbin/tests/system/chain/ans4/ans.py386
-rwxr-xr-xbin/tests/system/chain/clean.sh18
-rw-r--r--bin/tests/system/chain/ns1/named.conf.in27
-rw-r--r--bin/tests/system/chain/ns1/root.db51
-rw-r--r--bin/tests/system/chain/ns2/example.db69
-rw-r--r--bin/tests/system/chain/ns2/generic.db22
-rw-r--r--bin/tests/system/chain/ns2/named.conf.in74
-rw-r--r--bin/tests/system/chain/ns2/sign.sh54
-rw-r--r--bin/tests/system/chain/ns2/sub.db26
-rw-r--r--bin/tests/system/chain/ns2/wildcard-secure.db29
-rw-r--r--bin/tests/system/chain/ns2/wildcard.db28
-rw-r--r--bin/tests/system/chain/ns5/named.conf.in42
-rw-r--r--bin/tests/system/chain/ns5/sub.db26
-rw-r--r--bin/tests/system/chain/ns7/named.conf.in45
-rw-r--r--bin/tests/system/chain/ns7/root.hint14
-rw-r--r--bin/tests/system/chain/setup.sh22
-rw-r--r--bin/tests/system/chain/tests.sh630
-rw-r--r--bin/tests/system/chain/tests_sh_chain.py14
-rw-r--r--bin/tests/system/checkconf/altdb.conf19
-rw-r--r--bin/tests/system/checkconf/altdlz.conf27
-rw-r--r--bin/tests/system/checkconf/ancient.conf19
-rw-r--r--bin/tests/system/checkconf/bad-acl.conf21
-rw-r--r--bin/tests/system/checkconf/bad-also-notify.conf22
-rw-r--r--bin/tests/system/checkconf/bad-catz-zone-dup.conf21
-rw-r--r--bin/tests/system/checkconf/bad-catz-zone-primary-dup.conf27
-rw-r--r--bin/tests/system/checkconf/bad-catz-zone.conf18
-rw-r--r--bin/tests/system/checkconf/bad-checknames-primary-dup-2.conf17
-rw-r--r--bin/tests/system/checkconf/bad-checknames-primary-dup.conf17
-rw-r--r--bin/tests/system/checkconf/bad-checknames-secondary-dup.conf17
-rw-r--r--bin/tests/system/checkconf/bad-dnskey-validity.conf16
-rw-r--r--bin/tests/system/checkconf/bad-dnssec.conf31
-rw-r--r--bin/tests/system/checkconf/bad-doh-1.conf26
-rw-r--r--bin/tests/system/checkconf/bad-doh-2.conf22
-rw-r--r--bin/tests/system/checkconf/bad-doh-3.conf21
-rw-r--r--bin/tests/system/checkconf/bad-doh-badpath-1.conf21
-rw-r--r--bin/tests/system/checkconf/bad-doh-badpath-2.conf21
-rw-r--r--bin/tests/system/checkconf/bad-doh-badpath-3.conf21
-rw-r--r--bin/tests/system/checkconf/bad-doh-default.conf20
-rw-r--r--bin/tests/system/checkconf/bad-doh-duplicates.conf40
-rw-r--r--bin/tests/system/checkconf/bad-dot-1.conf17
-rw-r--r--bin/tests/system/checkconf/bad-dot-allow-transfer-bad-port.conf18
-rw-r--r--bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-1.conf18
-rw-r--r--bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-2.conf18
-rw-r--r--bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-3.conf18
-rw-r--r--bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-4.conf18
-rw-r--r--bin/tests/system/checkconf/bad-dot-badciphers.conf22
-rw-r--r--bin/tests/system/checkconf/bad-dot-badprotocol.conf22
-rw-r--r--bin/tests/system/checkconf/bad-dot-duplicatetls.conf26
-rw-r--r--bin/tests/system/checkconf/bad-dot-ephemeral.conf22
-rw-r--r--bin/tests/system/checkconf/bad-dot-nocert.conf32
-rw-r--r--bin/tests/system/checkconf/bad-dot-nokey.conf32
-rw-r--r--bin/tests/system/checkconf/bad-dot-none.conf22
-rw-r--r--bin/tests/system/checkconf/bad-dot-primaries.conf19
-rw-r--r--bin/tests/system/checkconf/bad-duplicate-key.conf36
-rw-r--r--bin/tests/system/checkconf/bad-duplicate-primaries-1.conf15
-rw-r--r--bin/tests/system/checkconf/bad-duplicate-primaries-2.conf15
-rw-r--r--bin/tests/system/checkconf/bad-duplicate-root-key.conf36
-rw-r--r--bin/tests/system/checkconf/bad-duration.conf16
-rw-r--r--bin/tests/system/checkconf/bad-glue-cache-bogus.conf16
-rw-r--r--bin/tests/system/checkconf/bad-hint.conf18
-rw-r--r--bin/tests/system/checkconf/bad-in-view-dup.conf21
-rw-r--r--bin/tests/system/checkconf/bad-inline-options.conf24
-rw-r--r--bin/tests/system/checkconf/bad-inline-secondary.conf22
-rw-r--r--bin/tests/system/checkconf/bad-inline-view.conf31
-rw-r--r--bin/tests/system/checkconf/bad-interface-interval.conf16
-rw-r--r--bin/tests/system/checkconf/bad-ipv4-prefix-dotted1.conf16
-rw-r--r--bin/tests/system/checkconf/bad-ipv4-prefix-dotted2.conf16
-rw-r--r--bin/tests/system/checkconf/bad-ipv4-prefix2.conf16
-rw-r--r--bin/tests/system/checkconf/bad-kasp-define-default.conf23
-rw-r--r--bin/tests/system/checkconf/bad-kasp-define-insecure.conf23
-rw-r--r--bin/tests/system/checkconf/bad-kasp-define-none.conf23
-rw-r--r--bin/tests/system/checkconf/bad-kasp-duplicate.conf15
-rw-r--r--bin/tests/system/checkconf/bad-kasp-key1.conf24
-rw-r--r--bin/tests/system/checkconf/bad-kasp-key2.conf24
-rw-r--r--bin/tests/system/checkconf/bad-kasp-key3.conf24
-rw-r--r--bin/tests/system/checkconf/bad-kasp-key4.conf24
-rw-r--r--bin/tests/system/checkconf/bad-kasp-keydir1.conf.in50
-rw-r--r--bin/tests/system/checkconf/bad-kasp-keydir2.conf.in48
-rw-r--r--bin/tests/system/checkconf/bad-kasp-keydir3.conf.in55
-rw-r--r--bin/tests/system/checkconf/bad-kasp-keydir4.conf.in52
-rw-r--r--bin/tests/system/checkconf/bad-kasp-keydir5.conf.in52
-rw-r--r--bin/tests/system/checkconf/bad-kasp-nsec3-alg.conf25
-rw-r--r--bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited-view.conf25
-rw-r--r--bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited.conf25
-rw-r--r--bin/tests/system/checkconf/bad-kasp10.conf28
-rw-r--r--bin/tests/system/checkconf/bad-kasp11.conf28
-rw-r--r--bin/tests/system/checkconf/bad-kasp12.conf30
-rw-r--r--bin/tests/system/checkconf/bad-kasp13.conf28
-rw-r--r--bin/tests/system/checkconf/bad-kasp2.conf24
-rw-r--r--bin/tests/system/checkconf/bad-kasp3.conf24
-rw-r--r--bin/tests/system/checkconf/bad-kasp4.conf25
-rw-r--r--bin/tests/system/checkconf/bad-kasp6.conf27
-rw-r--r--bin/tests/system/checkconf/bad-kasp7.conf28
-rw-r--r--bin/tests/system/checkconf/bad-kasp8.conf28
-rw-r--r--bin/tests/system/checkconf/bad-kasp9.conf28
-rw-r--r--bin/tests/system/checkconf/bad-keep-response-order.conf18
-rw-r--r--bin/tests/system/checkconf/bad-ksk-without-zsk.conf24
-rw-r--r--bin/tests/system/checkconf/bad-lifetime.conf16
-rw-r--r--bin/tests/system/checkconf/bad-lmdb-mapsize-bogus.conf16
-rw-r--r--bin/tests/system/checkconf/bad-lmdb-mapsize-toolarge.conf16
-rw-r--r--bin/tests/system/checkconf/bad-lmdb-mapsize-toosmall.conf16
-rw-r--r--bin/tests/system/checkconf/bad-lmdb-mapsize-unlimited.conf16
-rw-r--r--bin/tests/system/checkconf/bad-master-request-ixfr.conf22
-rw-r--r--bin/tests/system/checkconf/bad-masterfile-format-map.conf22
-rw-r--r--bin/tests/system/checkconf/bad-maxcachettl.conf16
-rw-r--r--bin/tests/system/checkconf/bad-maxncachettl-1.conf16
-rw-r--r--bin/tests/system/checkconf/bad-maxncachettl-2.conf16
-rw-r--r--bin/tests/system/checkconf/bad-maxncachettl-3.conf19
-rw-r--r--bin/tests/system/checkconf/bad-maxncachettl-4.conf16
-rw-r--r--bin/tests/system/checkconf/bad-maxratio1.conf19
-rw-r--r--bin/tests/system/checkconf/bad-maxratio2.conf19
-rw-r--r--bin/tests/system/checkconf/bad-mincachettl.conf16
-rw-r--r--bin/tests/system/checkconf/bad-minncachettl.conf16
-rw-r--r--bin/tests/system/checkconf/bad-mirror-allow-recursion-none.conf22
-rw-r--r--bin/tests/system/checkconf/bad-mirror-explicit-notify-yes.conf17
-rw-r--r--bin/tests/system/checkconf/bad-mirror-non-root-zone-without-masters.conf16
-rw-r--r--bin/tests/system/checkconf/bad-mirror-recursion-no.conf20
-rw-r--r--bin/tests/system/checkconf/bad-mirror-zonename.conf17
-rw-r--r--bin/tests/system/checkconf/bad-noddns.conf19
-rw-r--r--bin/tests/system/checkconf/bad-notify-source-v6.conf22
-rw-r--r--bin/tests/system/checkconf/bad-notify-source.conf22
-rw-r--r--bin/tests/system/checkconf/bad-options-also-notify.conf21
-rw-r--r--bin/tests/system/checkconf/bad-parental-agents-def-options.conf21
-rw-r--r--bin/tests/system/checkconf/bad-parental-agents-def-view.conf20
-rw-r--r--bin/tests/system/checkconf/bad-parental-agents-def-view2.conf22
-rw-r--r--bin/tests/system/checkconf/bad-parental-agents-def-zone.conf18
-rw-r--r--bin/tests/system/checkconf/bad-parental-agents-dup.conf19
-rw-r--r--bin/tests/system/checkconf/bad-parental-agents-dupdef.conf26
-rw-r--r--bin/tests/system/checkconf/bad-parental-agents-empty.conf20
-rw-r--r--bin/tests/system/checkconf/bad-parental-agents-empty2.conf18
-rw-r--r--bin/tests/system/checkconf/bad-parental-agents-mirror.conf18
-rw-r--r--bin/tests/system/checkconf/bad-parental-agents-notfound.conf22
-rw-r--r--bin/tests/system/checkconf/bad-parental-source-v6.conf22
-rw-r--r--bin/tests/system/checkconf/bad-parental-source.conf22
-rw-r--r--bin/tests/system/checkconf/bad-port.conf16
-rw-r--r--bin/tests/system/checkconf/bad-primaries-dup.conf18
-rw-r--r--bin/tests/system/checkconf/bad-primaries-key.conf17
-rw-r--r--bin/tests/system/checkconf/bad-primaries-notfound.conf21
-rw-r--r--bin/tests/system/checkconf/bad-primaries-tls.conf17
-rw-r--r--bin/tests/system/checkconf/bad-printtime.conf19
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-acl.conf20
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-all-per-second.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-errors-per-second.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-ipv4-prefix-length.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-ipv6-prefix-length.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-max-table-size.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-nodata-per-second.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-nxdomains-per-second.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-qps-scale.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-referrals-per-second.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-responses-per-second.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-slip.conf18
-rw-r--r--bin/tests/system/checkconf/bad-rate-limit-window.conf18
-rw-r--r--bin/tests/system/checkconf/bad-root-mixed-key.conf41
-rw-r--r--bin/tests/system/checkconf/bad-rpz-too-many-zones.conf148
-rw-r--r--bin/tests/system/checkconf/bad-rpz-ttl.conf24
-rw-r--r--bin/tests/system/checkconf/bad-rpz-update.conf25
-rw-r--r--bin/tests/system/checkconf/bad-rpz-zone.conf18
-rw-r--r--bin/tests/system/checkconf/bad-sharedwritable1.conf22
-rw-r--r--bin/tests/system/checkconf/bad-sharedwritable2.conf23
-rw-r--r--bin/tests/system/checkconf/bad-sharedzone1.conf31
-rw-r--r--bin/tests/system/checkconf/bad-sharedzone2.conf33
-rw-r--r--bin/tests/system/checkconf/bad-sharedzone3.conf25
-rw-r--r--bin/tests/system/checkconf/bad-sig-validity.conf16
-rw-r--r--bin/tests/system/checkconf/bad-static-initial-1.conf17
-rw-r--r--bin/tests/system/checkconf/bad-static-initial-2.conf17
-rw-r--r--bin/tests/system/checkconf/bad-static-initial-3.conf17
-rw-r--r--bin/tests/system/checkconf/bad-static-initial-4.conf17
-rw-r--r--bin/tests/system/checkconf/bad-stub-masters-dialup.conf36
-rw-r--r--bin/tests/system/checkconf/bad-transfer-source-v6.conf22
-rw-r--r--bin/tests/system/checkconf/bad-transfer-source.conf22
-rw-r--r--bin/tests/system/checkconf/bad-tsig.conf19
-rw-r--r--bin/tests/system/checkconf/bad-unpaired-keys.conf27
-rw-r--r--bin/tests/system/checkconf/bad-update-policy1.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy10.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy11.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy12.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy13.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy14.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy15.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy16.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy17.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy18.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy19.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy2.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy20.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy3.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy4.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy5.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy6.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy7.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy8.conf20
-rw-r--r--bin/tests/system/checkconf/bad-update-policy9.conf20
-rw-r--r--bin/tests/system/checkconf/bad-validation-auto-key.conf26
-rw-r--r--bin/tests/system/checkconf/bad-view-also-notify.conf20
-rw-r--r--bin/tests/system/checkconf/bad-zsk-without-ksk.conf24
-rw-r--r--bin/tests/system/checkconf/check-dup-records-fail.conf23
-rw-r--r--bin/tests/system/checkconf/check-dup-records.db33
-rw-r--r--bin/tests/system/checkconf/check-missing-zone.conf26
-rw-r--r--bin/tests/system/checkconf/check-mixed-keys.conf43
-rw-r--r--bin/tests/system/checkconf/check-mx-cname-fail.conf22
-rw-r--r--bin/tests/system/checkconf/check-mx-cname.db26
-rw-r--r--bin/tests/system/checkconf/check-mx-fail.conf22
-rw-r--r--bin/tests/system/checkconf/check-mx.db24
-rw-r--r--bin/tests/system/checkconf/check-names-fail.conf22
-rw-r--r--bin/tests/system/checkconf/check-names.db28
-rw-r--r--bin/tests/system/checkconf/check-root-ksk-2010.conf26
-rw-r--r--bin/tests/system/checkconf/check-root-ksk-2017.conf29
-rw-r--r--bin/tests/system/checkconf/check-root-ksk-both.conf41
-rw-r--r--bin/tests/system/checkconf/check-root-static-ds.conf16
-rw-r--r--bin/tests/system/checkconf/check-root-static-key.conf29
-rw-r--r--bin/tests/system/checkconf/check-root-trusted-key.conf29
-rw-r--r--bin/tests/system/checkconf/check-srv-cname-fail.conf22
-rw-r--r--bin/tests/system/checkconf/check-srv-cname.db28
-rw-r--r--bin/tests/system/checkconf/check-wildcard-no.conf18
-rw-r--r--bin/tests/system/checkconf/check-wildcard.conf18
-rw-r--r--bin/tests/system/checkconf/check-wildcard.db23
-rw-r--r--bin/tests/system/checkconf/clean.sh26
-rw-r--r--bin/tests/system/checkconf/deprecated.conf66
-rw-r--r--bin/tests/system/checkconf/dlz-bad.conf27
-rw-r--r--bin/tests/system/checkconf/dnssec.127
-rw-r--r--bin/tests/system/checkconf/dnssec.234
-rw-r--r--bin/tests/system/checkconf/dnssec.318
-rw-r--r--bin/tests/system/checkconf/good-acl.conf21
-rw-r--r--bin/tests/system/checkconf/good-allow-update-forwarding-view.conf16
-rw-r--r--bin/tests/system/checkconf/good-allow-update-forwarding.conf16
-rw-r--r--bin/tests/system/checkconf/good-allow-update-view.conf16
-rw-r--r--bin/tests/system/checkconf/good-allow-update.conf16
-rw-r--r--bin/tests/system/checkconf/good-class.conf14
-rw-r--r--bin/tests/system/checkconf/good-dnskey-validity-3660.conf16
-rw-r--r--bin/tests/system/checkconf/good-dnskey-validity-zero.conf16
-rw-r--r--bin/tests/system/checkconf/good-doh-1.conf33
-rw-r--r--bin/tests/system/checkconf/good-doh-2.conf29
-rw-r--r--bin/tests/system/checkconf/good-doh-3.conf19
-rw-r--r--bin/tests/system/checkconf/good-doh-4.conf31
-rw-r--r--bin/tests/system/checkconf/good-doh-tlsopts.conf38
-rw-r--r--bin/tests/system/checkconf/good-dot-1.conf21
-rw-r--r--bin/tests/system/checkconf/good-dot-allow-transfer-encrypted.conf49
-rw-r--r--bin/tests/system/checkconf/good-dot-doh-tls-nokeycert.conf18
-rw-r--r--bin/tests/system/checkconf/good-dot-primaries-ephemeral.conf19
-rw-r--r--bin/tests/system/checkconf/good-dot-primaries.conf25
-rw-r--r--bin/tests/system/checkconf/good-dot-tlsopts.conf26
-rw-r--r--bin/tests/system/checkconf/good-ds-key-1.conf17
-rw-r--r--bin/tests/system/checkconf/good-ds-key-2.conf17
-rw-r--r--bin/tests/system/checkconf/good-dup-managed-key.conf33
-rw-r--r--bin/tests/system/checkconf/good-dup-trusted-key.conf33
-rw-r--r--bin/tests/system/checkconf/good-glue-cache.conf16
-rw-r--r--bin/tests/system/checkconf/good-initial-ds.conf16
-rw-r--r--bin/tests/system/checkconf/good-interface-interval.conf16
-rw-r--r--bin/tests/system/checkconf/good-kasp.conf68
-rw-r--r--bin/tests/system/checkconf/good-key-directory.conf73
-rw-r--r--bin/tests/system/checkconf/good-masterfile-format-raw.conf22
-rw-r--r--bin/tests/system/checkconf/good-masterfile-format-text.conf22
-rw-r--r--bin/tests/system/checkconf/good-masters-and-primaries.conf15
-rw-r--r--bin/tests/system/checkconf/good-maxcachettl.conf34
-rw-r--r--bin/tests/system/checkconf/good-maxncachettl.conf34
-rw-r--r--bin/tests/system/checkconf/good-maxratio1.conf19
-rw-r--r--bin/tests/system/checkconf/good-maxratio2.conf19
-rw-r--r--bin/tests/system/checkconf/good-mincachettl.conf28
-rw-r--r--bin/tests/system/checkconf/good-minncachettl.conf28
-rw-r--r--bin/tests/system/checkconf/good-mirror-inherited-notify-yes.conf20
-rw-r--r--bin/tests/system/checkconf/good-mirror-root-zone-without-masters.conf16
-rw-r--r--bin/tests/system/checkconf/good-nested.conf20
-rw-r--r--bin/tests/system/checkconf/good-notify-source-v6.conf22
-rw-r--r--bin/tests/system/checkconf/good-notify-source.conf22
-rw-r--r--bin/tests/system/checkconf/good-options-also-notify.conf22
-rw-r--r--bin/tests/system/checkconf/good-parental-source-v6.conf22
-rw-r--r--bin/tests/system/checkconf/good-parental-source.conf22
-rw-r--r--bin/tests/system/checkconf/good-printtime.conf35
-rw-r--r--bin/tests/system/checkconf/good-response-dot.conf23
-rw-r--r--bin/tests/system/checkconf/good-rpz-ttl.conf24
-rw-r--r--bin/tests/system/checkconf/good-rpz-update.conf25
-rw-r--r--bin/tests/system/checkconf/good-rrset-order-none.conf18
-rw-r--r--bin/tests/system/checkconf/good-server-christmas-tree.conf.in61
-rw-r--r--bin/tests/system/checkconf/good-sig-signing-type.conf18
-rw-r--r--bin/tests/system/checkconf/good-static-ds.conf16
-rw-r--r--bin/tests/system/checkconf/good-transfer-source-v6.conf22
-rw-r--r--bin/tests/system/checkconf/good-transfer-source.conf22
-rw-r--r--bin/tests/system/checkconf/good-update-policy1.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy10.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy11.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy12.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy13.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy2.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy3.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy4.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy5.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy6.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy7.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy8.conf20
-rw-r--r--bin/tests/system/checkconf/good-update-policy9.conf20
-rw-r--r--bin/tests/system/checkconf/good-view-also-notify.conf21
-rw-r--r--bin/tests/system/checkconf/good.conf286
-rw-r--r--bin/tests/system/checkconf/good.zonelist24
-rw-r--r--bin/tests/system/checkconf/hint-nofile.conf17
-rw-r--r--bin/tests/system/checkconf/in-view-good.conf25
-rw-r--r--bin/tests/system/checkconf/inline-bad.conf27
-rw-r--r--bin/tests/system/checkconf/inline-good.conf28
-rw-r--r--bin/tests/system/checkconf/inline-no.conf27
-rw-r--r--bin/tests/system/checkconf/kasp-and-other-dnssec-options.conf28
-rw-r--r--bin/tests/system/checkconf/kasp-bad-keylen.conf24
-rw-r--r--bin/tests/system/checkconf/kasp-bad-lifetime.conf91
-rw-r--r--bin/tests/system/checkconf/kasp-bad-nsec3-alg.conf26
-rw-r--r--bin/tests/system/checkconf/kasp-bad-nsec3-iter.conf61
-rw-r--r--bin/tests/system/checkconf/kasp-bad-nsec3-salt.conf23
-rw-r--r--bin/tests/system/checkconf/kasp-bad-signatures-refresh.conf46
-rw-r--r--bin/tests/system/checkconf/kasp-ignore-keylen.conf27
-rw-r--r--bin/tests/system/checkconf/kasp-warning.conf62
-rw-r--r--bin/tests/system/checkconf/lmdb-mapsize-largest.conf16
-rw-r--r--bin/tests/system/checkconf/lmdb-mapsize-smallest.conf16
-rw-r--r--bin/tests/system/checkconf/max-cache-size-good.conf16
-rw-r--r--bin/tests/system/checkconf/max-ttl.conf34
-rw-r--r--bin/tests/system/checkconf/maxttl-bad.conf24
-rw-r--r--bin/tests/system/checkconf/maxttl-bad.db25
-rw-r--r--bin/tests/system/checkconf/maxttl.db25
-rw-r--r--bin/tests/system/checkconf/notify.conf84
-rw-r--r--bin/tests/system/checkconf/portrange-good.conf22
-rw-r--r--bin/tests/system/checkconf/range.conf16
-rw-r--r--bin/tests/system/checkconf/servestale.stale-refresh-time.0.conf16
-rw-r--r--bin/tests/system/checkconf/servestale.stale-refresh-time.29.conf16
-rw-r--r--bin/tests/system/checkconf/setup.sh20
-rw-r--r--bin/tests/system/checkconf/shared.example.db13
-rw-r--r--bin/tests/system/checkconf/tests.sh664
-rw-r--r--bin/tests/system/checkconf/tests_sh_checkconf.py14
-rw-r--r--bin/tests/system/checkconf/view-class-any1.conf14
-rw-r--r--bin/tests/system/checkconf/view-class-any2.conf14
-rw-r--r--bin/tests/system/checkconf/view-class-in1.conf14
-rw-r--r--bin/tests/system/checkconf/view-class-in2.conf14
-rw-r--r--bin/tests/system/checkconf/warn-kasp-max-zone-ttl.conf27
-rw-r--r--bin/tests/system/checkconf/warn-keydir.conf25
-rw-r--r--bin/tests/system/checkconf/warn-maxratio1.conf19
-rw-r--r--bin/tests/system/checkconf/warn-notify-source.conf22
-rw-r--r--bin/tests/system/checkconf/warn-parental-source.conf22
-rw-r--r--bin/tests/system/checkconf/warn-random-device.conf16
-rw-r--r--bin/tests/system/checkconf/warn-transfer-source.conf22
-rw-r--r--bin/tests/system/checkds/README26
-rw-r--r--bin/tests/system/checkds/clean.sh27
-rw-r--r--bin/tests/system/checkds/ns1/named.conf.in32
-rw-r--r--bin/tests/system/checkds/ns1/root.db.in24
-rw-r--r--bin/tests/system/checkds/ns1/setup.sh46
-rw-r--r--bin/tests/system/checkds/ns10/named.conf.in32
-rw-r--r--bin/tests/system/checkds/ns10/root.db.in24
-rw-r--r--bin/tests/system/checkds/ns2/named.conf.in46
-rw-r--r--bin/tests/system/checkds/ns2/setup.sh36
-rw-r--r--bin/tests/system/checkds/ns2/template.db.in39
-rw-r--r--bin/tests/system/checkds/ns3/named.conf.in41
-rw-r--r--bin/tests/system/checkds/ns4/named.conf.in42
-rw-r--r--bin/tests/system/checkds/ns5/named.conf.in46
-rw-r--r--bin/tests/system/checkds/ns5/setup.sh26
-rw-r--r--bin/tests/system/checkds/ns5/template.db.in40
-rw-r--r--bin/tests/system/checkds/ns6/named.conf.in46
-rw-r--r--bin/tests/system/checkds/ns7/named.conf.in47
-rw-r--r--bin/tests/system/checkds/ns8/named.conf.in41
-rw-r--r--bin/tests/system/checkds/ns8/root.hint14
-rw-r--r--bin/tests/system/checkds/ns9/named.conf.in242
-rw-r--r--bin/tests/system/checkds/ns9/setup.sh63
-rw-r--r--bin/tests/system/checkds/ns9/template.db.in27
-rw-r--r--bin/tests/system/checkds/setup.sh48
-rwxr-xr-xbin/tests/system/checkds/tests_checkds.py470
-rw-r--r--bin/tests/system/checknames/clean.sh27
-rw-r--r--bin/tests/system/checknames/ns1/fail.example.db.in17
-rw-r--r--bin/tests/system/checknames/ns1/fail.update.db.in16
-rw-r--r--bin/tests/system/checknames/ns1/ignore.example.db.in18
-rw-r--r--bin/tests/system/checknames/ns1/ignore.update.db.in16
-rw-r--r--bin/tests/system/checknames/ns1/named.conf.in70
-rw-r--r--bin/tests/system/checknames/ns1/root.db30
-rw-r--r--bin/tests/system/checknames/ns1/warn.example.db.in17
-rw-r--r--bin/tests/system/checknames/ns1/warn.update.db.in16
-rw-r--r--bin/tests/system/checknames/ns2/named.conf.in31
-rw-r--r--bin/tests/system/checknames/ns2/root.hints14
-rw-r--r--bin/tests/system/checknames/ns3/named.conf.in31
-rw-r--r--bin/tests/system/checknames/ns3/root.hints14
-rw-r--r--bin/tests/system/checknames/ns4/named.conf.in44
-rw-r--r--bin/tests/system/checknames/ns4/primary-ignore.update.db.in18
-rw-r--r--bin/tests/system/checknames/ns4/root.hints14
-rw-r--r--bin/tests/system/checknames/ns5/master-ignore.update.db.in18
-rw-r--r--bin/tests/system/checknames/ns5/named.conf.in44
-rw-r--r--bin/tests/system/checknames/ns5/root.hints14
-rw-r--r--bin/tests/system/checknames/setup.sh34
-rw-r--r--bin/tests/system/checknames/tests.sh192
-rw-r--r--bin/tests/system/checknames/tests_sh_checknames.py14
-rw-r--r--bin/tests/system/checkzone/clean.sh17
-rw-r--r--bin/tests/system/checkzone/setup.sh21
-rw-r--r--bin/tests/system/checkzone/tests.sh214
-rw-r--r--bin/tests/system/checkzone/tests_sh_checkzone.py14
-rw-r--r--bin/tests/system/checkzone/zones/.gitattributes1
-rw-r--r--bin/tests/system/checkzone/zones/bad-badclass.rawbin0 -> 104 bytes
-rw-r--r--bin/tests/system/checkzone/zones/bad-caa-rr.dbbin0 -> 601 bytes
-rw-r--r--bin/tests/system/checkzone/zones/bad-cdnskey.db15
-rw-r--r--bin/tests/system/checkzone/zones/bad-cds.db15
-rw-r--r--bin/tests/system/checkzone/zones/bad-dhcid.db13
-rw-r--r--bin/tests/system/checkzone/zones/bad-dns-sd-reverse.db21
-rw-r--r--bin/tests/system/checkzone/zones/bad-ds.db15
-rw-r--r--bin/tests/system/checkzone/zones/bad-eid.db13
-rw-r--r--bin/tests/system/checkzone/zones/bad-generate-garbage.db17
-rw-r--r--bin/tests/system/checkzone/zones/bad-generate-missing-brace.db17
-rw-r--r--bin/tests/system/checkzone/zones/bad-generate-range.db18
-rw-r--r--bin/tests/system/checkzone/zones/bad-generate-tkey.db17
-rw-r--r--bin/tests/system/checkzone/zones/bad-nimloc.db10
-rw-r--r--bin/tests/system/checkzone/zones/bad-nsap-empty.db18
-rw-r--r--bin/tests/system/checkzone/zones/bad-nsap-odd-nibble.db18
-rw-r--r--bin/tests/system/checkzone/zones/bad-nsec3-padded.db21
-rw-r--r--bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db19
-rw-r--r--bin/tests/system/checkzone/zones/bad-svcb-mandatory.db17
-rw-r--r--bin/tests/system/checkzone/zones/bad-svcb-servername.db17
-rw-r--r--bin/tests/system/checkzone/zones/bad-svcb.db17
-rw-r--r--bin/tests/system/checkzone/zones/bad-tkey.db17
-rw-r--r--bin/tests/system/checkzone/zones/bad-tsig.db.in17
-rw-r--r--bin/tests/system/checkzone/zones/bad-unspec.db16
-rw-r--r--bin/tests/system/checkzone/zones/bad1.dbbin0 -> 508 bytes
-rw-r--r--bin/tests/system/checkzone/zones/bad2.db19
-rw-r--r--bin/tests/system/checkzone/zones/bad3.db19
-rw-r--r--bin/tests/system/checkzone/zones/bad4.db19
-rw-r--r--bin/tests/system/checkzone/zones/badttl.db19
-rw-r--r--bin/tests/system/checkzone/zones/crashzone.db62
-rw-r--r--bin/tests/system/checkzone/zones/delegating-ns-address-below-dname.db24
-rw-r--r--bin/tests/system/checkzone/zones/generate-overflow.db17
-rw-r--r--bin/tests/system/checkzone/zones/good-cdnskey.db15
-rw-r--r--bin/tests/system/checkzone/zones/good-cds-unsigned.db16
-rw-r--r--bin/tests/system/checkzone/zones/good-cds.db15
-rw-r--r--bin/tests/system/checkzone/zones/good-dns-sd-reverse.db23
-rw-r--r--bin/tests/system/checkzone/zones/good-gc-msdcs.db16
-rw-r--r--bin/tests/system/checkzone/zones/good-generate-modifier.db20
-rw-r--r--bin/tests/system/checkzone/zones/good-nsap.db18
-rw-r--r--bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db19
-rw-r--r--bin/tests/system/checkzone/zones/good-occulted-ns-by-dname.db22
-rw-r--r--bin/tests/system/checkzone/zones/good-occulted-ns-by-ns.db22
-rw-r--r--bin/tests/system/checkzone/zones/good-spf-exception.db18
-rw-r--r--bin/tests/system/checkzone/zones/good-svcb.db27
-rw-r--r--bin/tests/system/checkzone/zones/good1.db19
-rw-r--r--bin/tests/system/checkzone/zones/inherit.db12
-rw-r--r--bin/tests/system/checkzone/zones/nowarn.inherited.owner.db13
-rw-r--r--bin/tests/system/checkzone/zones/ns-address-below-dname.db22
-rw-r--r--bin/tests/system/checkzone/zones/spf.db18
-rw-r--r--bin/tests/system/checkzone/zones/test1.db17
-rw-r--r--bin/tests/system/checkzone/zones/test2.db18
-rw-r--r--bin/tests/system/checkzone/zones/warn.inherit.origin.db14
-rw-r--r--bin/tests/system/checkzone/zones/warn.inherited.owner.db13
-rw-r--r--bin/tests/system/checkzone/zones/zone1.db21
-rw-r--r--bin/tests/system/ckdnsrps.sh167
-rw-r--r--bin/tests/system/cleanall.sh36
-rw-r--r--bin/tests/system/common/controls.conf.in22
-rw-r--r--bin/tests/system/common/rndc.conf21
-rw-r--r--bin/tests/system/common/rndc.key15
-rw-r--r--bin/tests/system/common/root.hint14
-rw-r--r--bin/tests/system/conf.sh.common738
-rw-r--r--bin/tests/system/conf.sh.in130
-rw-r--r--bin/tests/system/conftest.py639
-rw-r--r--bin/tests/system/cookie/ans9/ans.py308
-rw-r--r--bin/tests/system/cookie/bad-cookie-badaes.conf17
-rw-r--r--bin/tests/system/cookie/bad-cookie-badhex.conf16
-rw-r--r--bin/tests/system/cookie/bad-cookie-badsiphash24.conf17
-rw-r--r--bin/tests/system/cookie/bad-cookie-toolong.conf16
-rw-r--r--bin/tests/system/cookie/clean.sh24
-rw-r--r--bin/tests/system/cookie/good-cookie-aes.conf17
-rw-r--r--bin/tests/system/cookie/good-cookie-siphash24.conf17
-rw-r--r--bin/tests/system/cookie/ns1/example.db24
-rw-r--r--bin/tests/system/cookie/ns1/named.conf.in60
-rw-r--r--bin/tests/system/cookie/ns1/root.hint14
-rw-r--r--bin/tests/system/cookie/ns2/named.conf.in31
-rw-r--r--bin/tests/system/cookie/ns2/root.db28
-rw-r--r--bin/tests/system/cookie/ns3/named.conf.in52
-rw-r--r--bin/tests/system/cookie/ns3/root.hint14
-rw-r--r--bin/tests/system/cookie/ns4/named.conf.in41
-rw-r--r--bin/tests/system/cookie/ns4/root.hint14
-rw-r--r--bin/tests/system/cookie/ns5/named.conf.in42
-rw-r--r--bin/tests/system/cookie/ns5/root.hint14
-rw-r--r--bin/tests/system/cookie/ns6/named.conf.in41
-rw-r--r--bin/tests/system/cookie/ns6/root.hint14
-rw-r--r--bin/tests/system/cookie/ns7/named.conf.in32
-rw-r--r--bin/tests/system/cookie/ns7/root.db24
-rw-r--r--bin/tests/system/cookie/ns8/example.db13
-rw-r--r--bin/tests/system/cookie/ns8/named.conf.in39
-rw-r--r--bin/tests/system/cookie/setup.sh23
-rwxr-xr-xbin/tests/system/cookie/tests.sh550
-rw-r--r--bin/tests/system/cookie/tests_sh_cookie.py14
-rwxr-xr-xbin/tests/system/custom-test-driver162
-rw-r--r--bin/tests/system/database/clean.sh17
-rw-r--r--bin/tests/system/database/ns1/named1.conf.in41
-rw-r--r--bin/tests/system/database/ns1/named2.conf.in41
-rw-r--r--bin/tests/system/database/setup.sh16
-rw-r--r--bin/tests/system/database/tests.sh56
-rw-r--r--bin/tests/system/database/tests_sh_database.py14
-rw-r--r--bin/tests/system/dialup/clean.sh18
-rw-r--r--bin/tests/system/dialup/ns1/example.db19
-rw-r--r--bin/tests/system/dialup/ns1/named.conf.in40
-rw-r--r--bin/tests/system/dialup/ns1/root.db20
-rw-r--r--bin/tests/system/dialup/ns2/hint.db13
-rw-r--r--bin/tests/system/dialup/ns2/named.conf.in40
-rw-r--r--bin/tests/system/dialup/ns3/hint.db13
-rw-r--r--bin/tests/system/dialup/ns3/named.conf.in40
-rw-r--r--bin/tests/system/dialup/setup.sh19
-rw-r--r--bin/tests/system/dialup/tests.sh66
-rw-r--r--bin/tests/system/dialup/tests_sh_dialup.py14
-rw-r--r--bin/tests/system/digcomp.pl164
-rw-r--r--bin/tests/system/digdelv/ans4/startme1
-rw-r--r--bin/tests/system/digdelv/ans5/ans.pl176
-rwxr-xr-xbin/tests/system/digdelv/ans6/ans.pl84
-rwxr-xr-xbin/tests/system/digdelv/ans7/ans.pl68
-rw-r--r--bin/tests/system/digdelv/ans8/ans.py202
-rw-r--r--bin/tests/system/digdelv/clean.sh35
-rw-r--r--bin/tests/system/digdelv/ns1/named.conf.in30
-rw-r--r--bin/tests/system/digdelv/ns1/root.db26
-rw-r--r--bin/tests/system/digdelv/ns2/example.db.in51
-rw-r--r--bin/tests/system/digdelv/ns2/named.conf.in34
-rw-r--r--bin/tests/system/digdelv/ns2/sign.sh29
-rw-r--r--bin/tests/system/digdelv/ns3/named.conf.in28
-rw-r--r--bin/tests/system/digdelv/setup.sh23
-rw-r--r--bin/tests/system/digdelv/tests.sh1403
-rw-r--r--bin/tests/system/digdelv/tests_sh_digdelv.py14
-rw-r--r--bin/tests/system/digdelv/yamlget.py35
-rw-r--r--bin/tests/system/dispatch/ans3/ans.py99
-rw-r--r--bin/tests/system/dispatch/clean.sh16
-rw-r--r--bin/tests/system/dispatch/ns1/named.conf.in45
-rw-r--r--bin/tests/system/dispatch/ns1/root.db16
-rw-r--r--bin/tests/system/dispatch/ns2/example.db17
-rw-r--r--bin/tests/system/dispatch/ns2/named.conf.in50
-rw-r--r--bin/tests/system/dispatch/setup.sh17
-rw-r--r--bin/tests/system/dispatch/tests_connreset.py27
-rw-r--r--bin/tests/system/ditch.pl87
-rw-r--r--bin/tests/system/dlzexternal/clean.sh26
-rw-r--r--bin/tests/system/dlzexternal/driver/Makefile.am13
-rw-r--r--bin/tests/system/dlzexternal/driver/Makefile.in778
-rw-r--r--bin/tests/system/dlzexternal/driver/driver.c862
-rw-r--r--bin/tests/system/dlzexternal/driver/driver.h35
-rw-r--r--bin/tests/system/dlzexternal/ns1/named.conf.in85
-rw-r--r--bin/tests/system/dlzexternal/ns1/root.db26
-rw-r--r--bin/tests/system/dlzexternal/prereq.sh21
-rw-r--r--bin/tests/system/dlzexternal/setup.sh18
-rw-r--r--bin/tests/system/dlzexternal/tests.sh231
-rw-r--r--bin/tests/system/dlzexternal/tests_sh_dlzexternal.py14
-rw-r--r--bin/tests/system/dns64/clean.sh22
-rw-r--r--bin/tests/system/dns64/conf/bad1.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad10.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad11.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad12.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad13.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad14.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad15.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad16.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad17.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad18.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad19.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad2.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad3.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad4.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad5.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad6.conf16
-rw-r--r--bin/tests/system/dns64/conf/bad7.conf18
-rw-r--r--bin/tests/system/dns64/conf/bad8.conf18
-rw-r--r--bin/tests/system/dns64/conf/bad9.conf18
-rw-r--r--bin/tests/system/dns64/conf/good1.conf22
-rw-r--r--bin/tests/system/dns64/conf/good2.conf21
-rw-r--r--bin/tests/system/dns64/conf/good3.conf21
-rw-r--r--bin/tests/system/dns64/conf/good4.conf21
-rw-r--r--bin/tests/system/dns64/conf/good5.conf18
-rw-r--r--bin/tests/system/dns64/ns1/example.db56
-rw-r--r--bin/tests/system/dns64/ns1/ipv4only.arpa.db15
-rw-r--r--bin/tests/system/dns64/ns1/named.conf1.in63
-rw-r--r--bin/tests/system/dns64/ns1/named.conf2.in66
-rw-r--r--bin/tests/system/dns64/ns1/named.conf3.in55
-rw-r--r--bin/tests/system/dns64/ns1/root.db19
-rw-r--r--bin/tests/system/dns64/ns1/sign.sh25
-rw-r--r--bin/tests/system/dns64/ns2/named.conf.in71
-rw-r--r--bin/tests/system/dns64/ns2/rpz.db23
-rw-r--r--bin/tests/system/dns64/setup.sh19
-rw-r--r--bin/tests/system/dns64/tests.sh1456
-rw-r--r--bin/tests/system/dns64/tests_sh_dns64.py14
-rw-r--r--bin/tests/system/dnssec/README32
-rw-r--r--bin/tests/system/dnssec/ans10/ans.py158
-rw-r--r--bin/tests/system/dnssec/clean.sh117
-rw-r--r--bin/tests/system/dnssec/dnssec_update_test.pl99
-rw-r--r--bin/tests/system/dnssec/ns1/named.conf.in36
-rw-r--r--bin/tests/system/dnssec/ns1/root.db.in37
-rw-r--r--bin/tests/system/dnssec/ns1/sign.sh62
-rw-r--r--bin/tests/system/dnssec/ns2/algroll.db.in26
-rw-r--r--bin/tests/system/dnssec/ns2/badparam.db.in21
-rw-r--r--bin/tests/system/dnssec/ns2/cdnskey-auto.secure.db.in14
-rw-r--r--bin/tests/system/dnssec/ns2/cdnskey-kskonly.secure.db.in14
-rw-r--r--bin/tests/system/dnssec/ns2/cdnskey-update.secure.db.in14
-rw-r--r--bin/tests/system/dnssec/ns2/cdnskey.secure.db.in14
-rw-r--r--bin/tests/system/dnssec/ns2/cds-auto.secure.db.in14
-rw-r--r--bin/tests/system/dnssec/ns2/cds-kskonly.secure.db.in14
-rw-r--r--bin/tests/system/dnssec/ns2/cds-update.secure.db.in14
-rw-r--r--bin/tests/system/dnssec/ns2/cds.secure.db.in14
-rw-r--r--bin/tests/system/dnssec/ns2/child.nsec3.example.db20
-rw-r--r--bin/tests/system/dnssec/ns2/child.optout.example.db20
-rw-r--r--bin/tests/system/dnssec/ns2/corp.db23
-rw-r--r--bin/tests/system/dnssec/ns2/dst.example.db.in21
-rw-r--r--bin/tests/system/dnssec/ns2/example.db.in171
-rw-r--r--bin/tests/system/dnssec/ns2/hours-vs-days.db.in167
-rw-r--r--bin/tests/system/dnssec/ns2/in-addr.arpa.db.in19
-rw-r--r--bin/tests/system/dnssec/ns2/insecure.secure.example.db26
-rw-r--r--bin/tests/system/dnssec/ns2/key.db.in45
-rw-r--r--bin/tests/system/dnssec/ns2/named.conf.in205
-rw-r--r--bin/tests/system/dnssec/ns2/private.secure.example.db.in28
-rw-r--r--bin/tests/system/dnssec/ns2/rfc2335.example.db114
-rw-r--r--bin/tests/system/dnssec/ns2/sign.sh332
-rw-r--r--bin/tests/system/dnssec/ns2/single-nsec3.db.in21
-rw-r--r--bin/tests/system/dnssec/ns2/template.secure.db.in14
-rw-r--r--bin/tests/system/dnssec/ns2/too-many-iterations.db.in27
-rw-r--r--bin/tests/system/dnssec/ns3/auto-nsec.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/bogus.example.db.in27
-rw-r--r--bin/tests/system/dnssec/ns3/dname-at-apex-nsec3.example.db.in15
-rw-r--r--bin/tests/system/dnssec/ns3/dnskey-nsec3-unknown.example.db.in29
-rw-r--r--bin/tests/system/dnssec/ns3/dnskey-unknown.example.db.in29
-rw-r--r--bin/tests/system/dnssec/ns3/dnskey-unsupported-2.example.db.in29
-rw-r--r--bin/tests/system/dnssec/ns3/dnskey-unsupported.example.db.in29
-rw-r--r--bin/tests/system/dnssec/ns3/dynamic.example.db.in25
-rw-r--r--bin/tests/system/dnssec/ns3/expired.example.db.in44
-rw-r--r--bin/tests/system/dnssec/ns3/expiring.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/future.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/generic.example.db.in23
-rw-r--r--bin/tests/system/dnssec/ns3/inline.example.db26
-rw-r--r--bin/tests/system/dnssec/ns3/insecure.below-cname.example.db26
-rw-r--r--bin/tests/system/dnssec/ns3/insecure.example.db27
-rw-r--r--bin/tests/system/dnssec/ns3/insecure.nsec3.example.db26
-rw-r--r--bin/tests/system/dnssec/ns3/insecure.optout.example.db26
-rw-r--r--bin/tests/system/dnssec/ns3/insecure2.example.db27
-rw-r--r--bin/tests/system/dnssec/ns3/key.db.in26
-rw-r--r--bin/tests/system/dnssec/ns3/kskonly.example.db.in26
-rw-r--r--bin/tests/system/dnssec/ns3/lower.example.db.in21
-rw-r--r--bin/tests/system/dnssec/ns3/managed-future.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/multiple.example.db.in29
-rw-r--r--bin/tests/system/dnssec/ns3/named.conf.in383
-rw-r--r--bin/tests/system/dnssec/ns3/nosign.example.db.in23
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in29
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3.example.db.in38
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in35
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in35
-rw-r--r--bin/tests/system/dnssec/ns3/occluded.example.db.in26
-rw-r--r--bin/tests/system/dnssec/ns3/optout-unknown.example.db.in29
-rw-r--r--bin/tests/system/dnssec/ns3/optout.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in35
-rw-r--r--bin/tests/system/dnssec/ns3/optout.optout.example.db.in35
-rw-r--r--bin/tests/system/dnssec/ns3/publish-inactive.example.db.in26
-rw-r--r--bin/tests/system/dnssec/ns3/rsasha256.example.db.in28
-rw-r--r--bin/tests/system/dnssec/ns3/rsasha512.example.db.in28
-rw-r--r--bin/tests/system/dnssec/ns3/secure.below-cname.example.db.in26
-rw-r--r--bin/tests/system/dnssec/ns3/secure.example.db.in49
-rw-r--r--bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in35
-rw-r--r--bin/tests/system/dnssec/ns3/secure.optout.example.db.in35
-rw-r--r--bin/tests/system/dnssec/ns3/siginterval.example.db.in21
-rw-r--r--bin/tests/system/dnssec/ns3/siginterval1.conf21
-rw-r--r--bin/tests/system/dnssec/ns3/siginterval2.conf21
-rw-r--r--bin/tests/system/dnssec/ns3/sign.sh674
-rw-r--r--bin/tests/system/dnssec/ns3/split-dnssec.example.db.in38
-rw-r--r--bin/tests/system/dnssec/ns3/split-smart.example.db.in38
-rw-r--r--bin/tests/system/dnssec/ns3/ttlpatch.example.db.in26
-rw-r--r--bin/tests/system/dnssec/ns3/unsupported-algorithm.key1
-rw-r--r--bin/tests/system/dnssec/ns3/update-nsec3.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/upper.example.db.in21
-rw-r--r--bin/tests/system/dnssec/ns4/managed-keys.bind.in21
-rw-r--r--bin/tests/system/dnssec/ns4/named1.conf.in61
-rw-r--r--bin/tests/system/dnssec/ns4/named2.conf.in42
-rw-r--r--bin/tests/system/dnssec/ns4/named3.conf.in43
-rw-r--r--bin/tests/system/dnssec/ns4/named4.conf.in78
-rw-r--r--bin/tests/system/dnssec/ns4/named5.conf.in40
-rw-r--r--bin/tests/system/dnssec/ns5/named1.conf.in43
-rw-r--r--bin/tests/system/dnssec/ns5/named2.conf.in53
-rw-r--r--bin/tests/system/dnssec/ns5/sign.sh39
-rw-r--r--bin/tests/system/dnssec/ns6/named.args1
-rw-r--r--bin/tests/system/dnssec/ns6/named.conf.in40
-rw-r--r--bin/tests/system/dnssec/ns6/optout-tld.db.in22
-rw-r--r--bin/tests/system/dnssec/ns6/sign.sh29
-rw-r--r--bin/tests/system/dnssec/ns7/named.conf.in76
-rw-r--r--bin/tests/system/dnssec/ns7/named.nosoa12
-rw-r--r--bin/tests/system/dnssec/ns7/nosoa.secure.example.db22
-rw-r--r--bin/tests/system/dnssec/ns7/sign.sh44
-rw-r--r--bin/tests/system/dnssec/ns7/split-rrsig.db.in21
-rw-r--r--bin/tests/system/dnssec/ns8/named.conf.in47
-rw-r--r--bin/tests/system/dnssec/ns9/named.conf.in39
-rwxr-xr-xbin/tests/system/dnssec/ntadiff.pl24
-rw-r--r--bin/tests/system/dnssec/setup.sh52
-rw-r--r--bin/tests/system/dnssec/signer/example.db.in17
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key5
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private13
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key5
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private13
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.key5
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.private13
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.key5
-rw-r--r--bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.private13
-rw-r--r--bin/tests/system/dnssec/signer/general/bogus-ksk.key6
-rw-r--r--bin/tests/system/dnssec/signer/general/bogus-zsk.key6
-rw-r--r--bin/tests/system/dnssec/signer/general/test1.zone19
-rw-r--r--bin/tests/system/dnssec/signer/general/test2.zone18
-rw-r--r--bin/tests/system/dnssec/signer/general/test3.zone18
-rw-r--r--bin/tests/system/dnssec/signer/general/test4.zone20
-rw-r--r--bin/tests/system/dnssec/signer/general/test5.zone19
-rw-r--r--bin/tests/system/dnssec/signer/general/test6.zone21
-rw-r--r--bin/tests/system/dnssec/signer/general/test7.zone19
-rw-r--r--bin/tests/system/dnssec/signer/general/test8.zone19
-rw-r--r--bin/tests/system/dnssec/signer/general/test9.zone19
-rw-r--r--bin/tests/system/dnssec/signer/prepub.db.in17
-rw-r--r--bin/tests/system/dnssec/signer/remove.db.in18
-rw-r--r--bin/tests/system/dnssec/signer/remove2.db.in16
-rw-r--r--bin/tests/system/dnssec/tests.sh4446
-rw-r--r--bin/tests/system/dnssec/tests_sh_dnssec.py14
-rw-r--r--bin/tests/system/dnstap/README27
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-reopen-interval.conf16
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-max.conf16
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-min.conf16
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-max.conf16
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-min.conf16
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-max.conf16
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-min.conf16
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-po2.conf16
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-output-notify-threshold.conf16
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-max.conf19
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-min.conf16
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-max.conf16
-rw-r--r--bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-min.conf16
-rw-r--r--bin/tests/system/dnstap/bad-missing-dnstap-output-view.conf16
-rw-r--r--bin/tests/system/dnstap/bad-missing-dnstap-output.conf17
-rw-r--r--bin/tests/system/dnstap/bad-size-version.conf16
-rw-r--r--bin/tests/system/dnstap/clean.sh30
-rw-r--r--bin/tests/system/dnstap/good-dnstap-in-options.conf18
-rw-r--r--bin/tests/system/dnstap/good-dnstap-in-view.conf21
-rw-r--r--bin/tests/system/dnstap/good-fstrm-reopen-interval.conf16
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-buffer-hint.conf16
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-flush-timeout.conf16
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-input-queue-size.conf16
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-output-notify-threshold.conf16
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-output-queue-model-mpsc.conf16
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-output-queue-model-spsc.conf16
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-output-queue-size.conf16
-rw-r--r--bin/tests/system/dnstap/good-fstrm-set-reopen-interval.conf16
-rw-r--r--bin/tests/system/dnstap/good-size-unlimited.conf17
-rw-r--r--bin/tests/system/dnstap/good-size-version.conf17
-rw-r--r--bin/tests/system/dnstap/large-answer.fstrmbin0 -> 981 bytes
-rw-r--r--bin/tests/system/dnstap/ns1/named.conf.in47
-rw-r--r--bin/tests/system/dnstap/ns1/root.db24
-rw-r--r--bin/tests/system/dnstap/ns2/example.db.in30
-rw-r--r--bin/tests/system/dnstap/ns2/named.conf.in53
-rw-r--r--bin/tests/system/dnstap/ns3/named.args2
-rw-r--r--bin/tests/system/dnstap/ns3/named.conf.in50
-rw-r--r--bin/tests/system/dnstap/ns4/named.conf.in49
-rw-r--r--bin/tests/system/dnstap/prereq.sh20
-rw-r--r--bin/tests/system/dnstap/setup.sh21
-rw-r--r--bin/tests/system/dnstap/tests.sh857
-rw-r--r--bin/tests/system/dnstap/tests_dnstap.py83
-rw-r--r--bin/tests/system/dnstap/tests_sh_dnstap.py14
-rw-r--r--bin/tests/system/dnstap/ydump.py29
-rw-r--r--bin/tests/system/doth/CA/CA.cfg121
-rw-r--r--bin/tests/system/doth/CA/CA.pem29
-rw-r--r--bin/tests/system/doth/CA/README2
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.client01.example.com.key6
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.client01.example.com.pem68
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.key6
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.pem68
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.key6
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.pem69
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.crt01.example.com.key6
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.crt01.example.com.pem69
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.key6
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.pem64
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.key6
-rw-r--r--bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.pem69
-rw-r--r--bin/tests/system/doth/CA/certs/srv02.crt01.example.com.key6
-rw-r--r--bin/tests/system/doth/CA/certs/srv02.crt01.example.com.pem69
-rw-r--r--bin/tests/system/doth/CA/certs/srv03.crt01.example.com.key6
-rw-r--r--bin/tests/system/doth/CA/certs/srv03.crt01.example.com.pem69
-rw-r--r--bin/tests/system/doth/CA/certs/srv04.crt01.example.com.key6
-rw-r--r--bin/tests/system/doth/CA/certs/srv04.crt01.example.com.pem69
-rw-r--r--bin/tests/system/doth/CA/index.txt9
-rw-r--r--bin/tests/system/doth/CA/index.txt.attr1
-rw-r--r--bin/tests/system/doth/CA/newcerts/6BB3183CDEF52001.pem69
-rw-r--r--bin/tests/system/doth/CA/newcerts/6BB3183CDEF52002.pem64
-rw-r--r--bin/tests/system/doth/CA/newcerts/6BB3183CDEF52003.pem69
-rw-r--r--bin/tests/system/doth/CA/newcerts/6BB3183CDEF52004.pem69
-rw-r--r--bin/tests/system/doth/CA/newcerts/6BB3183CDEF52005.pem69
-rw-r--r--bin/tests/system/doth/CA/newcerts/6BB3183CDEF52006.pem69
-rw-r--r--bin/tests/system/doth/CA/newcerts/6BB3183CDEF52007.pem68
-rw-r--r--bin/tests/system/doth/CA/newcerts/6BB3183CDEF52008.pem68
-rw-r--r--bin/tests/system/doth/CA/newcerts/6BB3183CDEF52009.pem69
-rw-r--r--bin/tests/system/doth/CA/private/CA.key39
-rw-r--r--bin/tests/system/doth/CA/serial1
-rw-r--r--bin/tests/system/doth/README.curl38
-rw-r--r--bin/tests/system/doth/clean.sh26
-rw-r--r--bin/tests/system/doth/conftest.py47
-rw-r--r--bin/tests/system/doth/dhparam3072.pem11
-rw-r--r--bin/tests/system/doth/example.axfr.good2676
-rw-r--r--bin/tests/system/doth/example8.axfr.good2676
-rwxr-xr-xbin/tests/system/doth/get_openssl_version.py17
-rw-r--r--bin/tests/system/doth/ns1/named.conf.in172
-rw-r--r--bin/tests/system/doth/ns1/root.db10023
-rw-r--r--bin/tests/system/doth/ns2/cert.pem14
-rw-r--r--bin/tests/system/doth/ns2/key.pem8
-rw-r--r--bin/tests/system/doth/ns2/named.conf.in183
-rw-r--r--bin/tests/system/doth/ns3/named.conf.in79
-rw-r--r--bin/tests/system/doth/ns4/named.conf.in73
-rw-r--r--bin/tests/system/doth/prereq.sh20
-rw-r--r--bin/tests/system/doth/setup.sh32
-rwxr-xr-xbin/tests/system/doth/stress_http_quota.py252
-rw-r--r--bin/tests/system/doth/tests.sh889
-rw-r--r--bin/tests/system/doth/tests_gnutls.py108
-rw-r--r--bin/tests/system/doth/tests_sh_doth.py14
-rw-r--r--bin/tests/system/doth/tests_sslyze.py65
-rw-r--r--bin/tests/system/dsdigest/clean.sh24
-rw-r--r--bin/tests/system/dsdigest/ns1/named.conf.in36
-rw-r--r--bin/tests/system/dsdigest/ns1/root.db.in26
-rw-r--r--bin/tests/system/dsdigest/ns1/sign.sh36
-rw-r--r--bin/tests/system/dsdigest/ns2/bad.db.in23
-rw-r--r--bin/tests/system/dsdigest/ns2/good.db.in23
-rw-r--r--bin/tests/system/dsdigest/ns2/named.conf.in46
-rw-r--r--bin/tests/system/dsdigest/ns2/sign.sh43
-rw-r--r--bin/tests/system/dsdigest/ns3/named.conf.in39
-rw-r--r--bin/tests/system/dsdigest/ns4/named.conf.in37
-rw-r--r--bin/tests/system/dsdigest/setup.sh21
-rw-r--r--bin/tests/system/dsdigest/tests.sh55
-rw-r--r--bin/tests/system/dsdigest/tests_sh_dsdigest.py14
-rw-r--r--bin/tests/system/dupsigs/check_journal.pl206
-rw-r--r--bin/tests/system/dupsigs/clean.sh24
-rw-r--r--bin/tests/system/dupsigs/ns1/named.args1
-rw-r--r--bin/tests/system/dupsigs/ns1/named.conf.in34
-rw-r--r--bin/tests/system/dupsigs/ns1/reset_keys.sh99
-rw-r--r--bin/tests/system/dupsigs/ns1/signing.test.db.in18
-rw-r--r--bin/tests/system/dupsigs/setup.sh23
-rw-r--r--bin/tests/system/dupsigs/tests.sh71
-rw-r--r--bin/tests/system/dupsigs/tests_sh_dupsigs.py14
-rw-r--r--bin/tests/system/dyndb/clean.sh25
-rw-r--r--bin/tests/system/dyndb/driver/AUTHORS33
-rw-r--r--bin/tests/system/dyndb/driver/Makefile.am25
-rw-r--r--bin/tests/system/dyndb/driver/Makefile.in811
-rw-r--r--bin/tests/system/dyndb/driver/README92
-rw-r--r--bin/tests/system/dyndb/driver/db.c776
-rw-r--r--bin/tests/system/dyndb/driver/db.h47
-rw-r--r--bin/tests/system/dyndb/driver/driver.c164
-rw-r--r--bin/tests/system/dyndb/driver/instance.c231
-rw-r--r--bin/tests/system/dyndb/driver/instance.h73
-rw-r--r--bin/tests/system/dyndb/driver/lock.c81
-rw-r--r--bin/tests/system/dyndb/driver/lock.h39
-rw-r--r--bin/tests/system/dyndb/driver/log.c44
-rw-r--r--bin/tests/system/dyndb/driver/log.h45
-rw-r--r--bin/tests/system/dyndb/driver/syncptr.c337
-rw-r--r--bin/tests/system/dyndb/driver/syncptr.h46
-rw-r--r--bin/tests/system/dyndb/driver/util.h82
-rw-r--r--bin/tests/system/dyndb/driver/zone.c265
-rw-r--r--bin/tests/system/dyndb/driver/zone.h45
-rw-r--r--bin/tests/system/dyndb/ns1/named.conf.in40
-rw-r--r--bin/tests/system/dyndb/prereq.sh21
-rw-r--r--bin/tests/system/dyndb/setup.sh16
-rw-r--r--bin/tests/system/dyndb/tests.sh166
-rw-r--r--bin/tests/system/dyndb/tests_sh_dyndb.py14
-rw-r--r--bin/tests/system/ecdsa/clean.sh28
-rw-r--r--bin/tests/system/ecdsa/ns1/named.conf.in36
-rw-r--r--bin/tests/system/ecdsa/ns1/root.db.in21
-rw-r--r--bin/tests/system/ecdsa/ns1/sign.sh57
-rw-r--r--bin/tests/system/ecdsa/ns2/named.conf.in36
-rw-r--r--bin/tests/system/ecdsa/ns3/named.conf.in36
-rw-r--r--bin/tests/system/ecdsa/setup.sh32
-rw-r--r--bin/tests/system/ecdsa/tests.sh54
-rw-r--r--bin/tests/system/ecdsa/tests_sh_ecdsa.py14
-rw-r--r--bin/tests/system/eddsa/clean.sh29
-rw-r--r--bin/tests/system/eddsa/ns1/named.conf.in36
-rw-r--r--bin/tests/system/eddsa/ns1/root.db.in21
-rw-r--r--bin/tests/system/eddsa/ns1/sign.sh57
-rw-r--r--bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.key1
-rw-r--r--bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.private4
-rw-r--r--bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.key1
-rw-r--r--bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.private3
-rw-r--r--bin/tests/system/eddsa/ns2/example.com.db.in22
-rw-r--r--bin/tests/system/eddsa/ns2/named.conf.in36
-rw-r--r--bin/tests/system/eddsa/ns2/sign.sh38
-rw-r--r--bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.key1
-rw-r--r--bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.private3
-rw-r--r--bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.key1
-rw-r--r--bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.private3
-rw-r--r--bin/tests/system/eddsa/ns3/example.com.db.in22
-rw-r--r--bin/tests/system/eddsa/ns3/named.conf.in36
-rw-r--r--bin/tests/system/eddsa/ns3/sign.sh37
-rw-r--r--bin/tests/system/eddsa/prereq.sh26
-rw-r--r--bin/tests/system/eddsa/setup.sh41
-rw-r--r--bin/tests/system/eddsa/tests.sh87
-rw-r--r--bin/tests/system/eddsa/tests_sh_eddsa.py14
-rw-r--r--bin/tests/system/ednscompliance/clean.sh19
-rw-r--r--bin/tests/system/ednscompliance/ns1/named.conf.in29
-rw-r--r--bin/tests/system/ednscompliance/ns1/root.db21
-rw-r--r--bin/tests/system/ednscompliance/setup.sh16
-rw-r--r--bin/tests/system/ednscompliance/tests.sh114
-rw-r--r--bin/tests/system/ednscompliance/tests_sh_ednscompliance.py14
-rw-r--r--bin/tests/system/emptyzones/clean.sh19
-rw-r--r--bin/tests/system/emptyzones/ns1/empty.db13
-rw-r--r--bin/tests/system/emptyzones/ns1/named1.conf.in46
-rw-r--r--bin/tests/system/emptyzones/ns1/named2.conf.in49
-rw-r--r--bin/tests/system/emptyzones/ns1/rfc1918.zones32
-rw-r--r--bin/tests/system/emptyzones/ns1/root.hint14
-rw-r--r--bin/tests/system/emptyzones/setup.sh17
-rw-r--r--bin/tests/system/emptyzones/tests.sh46
-rw-r--r--bin/tests/system/emptyzones/tests_sh_emptyzones.py14
-rw-r--r--bin/tests/system/enginepkcs11/2037-pk11_numbits-crash-test.pkt30
-rw-r--r--bin/tests/system/enginepkcs11/clean.sh35
-rw-r--r--bin/tests/system/enginepkcs11/ns1/named.args1
-rw-r--r--bin/tests/system/enginepkcs11/ns1/named.conf.in36
-rw-r--r--bin/tests/system/enginepkcs11/ns1/template.db.in24
-rw-r--r--bin/tests/system/enginepkcs11/prereq.sh21
-rw-r--r--bin/tests/system/enginepkcs11/setup.sh125
-rw-r--r--bin/tests/system/enginepkcs11/tests.sh176
-rw-r--r--bin/tests/system/enginepkcs11/tests_sh_enginepkcs11.py14
-rw-r--r--bin/tests/system/feature-test.c224
-rw-r--r--bin/tests/system/fetchlimit/ans4/ans.pl90
-rw-r--r--bin/tests/system/fetchlimit/clean.sh21
-rw-r--r--bin/tests/system/fetchlimit/ns1/named.conf.in35
-rw-r--r--bin/tests/system/fetchlimit/ns1/root.db24
-rw-r--r--bin/tests/system/fetchlimit/ns2/example.db37
-rw-r--r--bin/tests/system/fetchlimit/ns2/named.conf.in41
-rw-r--r--bin/tests/system/fetchlimit/ns3/named.args1
-rw-r--r--bin/tests/system/fetchlimit/ns3/named1.conf.in47
-rw-r--r--bin/tests/system/fetchlimit/ns3/named2.conf.in45
-rw-r--r--bin/tests/system/fetchlimit/ns3/named3.conf.in45
-rw-r--r--bin/tests/system/fetchlimit/ns3/root.hint14
-rw-r--r--bin/tests/system/fetchlimit/ns5/named1.conf.in46
-rw-r--r--bin/tests/system/fetchlimit/ns5/named2.conf.in49
-rw-r--r--bin/tests/system/fetchlimit/ns5/root.hint14
-rw-r--r--bin/tests/system/fetchlimit/setup.sh19
-rw-r--r--bin/tests/system/fetchlimit/tests.sh325
-rw-r--r--bin/tests/system/fetchlimit/tests_sh_fetchlimit.py14
-rw-r--r--bin/tests/system/filter-aaaa/clean.sh33
-rw-r--r--bin/tests/system/filter-aaaa/conf/bad1.conf17
-rw-r--r--bin/tests/system/filter-aaaa/conf/bad2.conf26
-rw-r--r--bin/tests/system/filter-aaaa/conf/bad3.conf19
-rw-r--r--bin/tests/system/filter-aaaa/conf/bad4.conf19
-rw-r--r--bin/tests/system/filter-aaaa/conf/bad5.conf21
-rw-r--r--bin/tests/system/filter-aaaa/conf/good1.conf16
-rw-r--r--bin/tests/system/filter-aaaa/conf/good2.conf16
-rw-r--r--bin/tests/system/filter-aaaa/conf/good3.conf17
-rw-r--r--bin/tests/system/filter-aaaa/conf/good4.conf17
-rw-r--r--bin/tests/system/filter-aaaa/conf/good5.conf19
-rw-r--r--bin/tests/system/filter-aaaa/ns1/named1.conf.in47
-rw-r--r--bin/tests/system/filter-aaaa/ns1/named2.conf.in44
-rw-r--r--bin/tests/system/filter-aaaa/ns1/root.db25
-rwxr-xr-xbin/tests/system/filter-aaaa/ns1/sign.sh34
-rw-r--r--bin/tests/system/filter-aaaa/ns1/signed.db.in25
-rw-r--r--bin/tests/system/filter-aaaa/ns1/unsigned.db25
-rw-r--r--bin/tests/system/filter-aaaa/ns2/hints16
-rw-r--r--bin/tests/system/filter-aaaa/ns2/named1.conf.in44
-rw-r--r--bin/tests/system/filter-aaaa/ns2/named2.conf.in44
-rw-r--r--bin/tests/system/filter-aaaa/ns3/hints16
-rw-r--r--bin/tests/system/filter-aaaa/ns3/named1.conf.in44
-rw-r--r--bin/tests/system/filter-aaaa/ns3/named2.conf.in44
-rw-r--r--bin/tests/system/filter-aaaa/ns4/named1.conf.in44
-rw-r--r--bin/tests/system/filter-aaaa/ns4/named2.conf.in44
-rw-r--r--bin/tests/system/filter-aaaa/ns4/root.db24
-rwxr-xr-xbin/tests/system/filter-aaaa/ns4/sign.sh27
-rw-r--r--bin/tests/system/filter-aaaa/ns4/signed.db.in25
-rw-r--r--bin/tests/system/filter-aaaa/ns4/unsigned.db25
-rw-r--r--bin/tests/system/filter-aaaa/ns5/hints16
-rw-r--r--bin/tests/system/filter-aaaa/ns5/named.conf.in49
-rw-r--r--bin/tests/system/filter-aaaa/setup.sh23
-rw-r--r--bin/tests/system/filter-aaaa/tests.sh1420
-rw-r--r--bin/tests/system/filter-aaaa/tests_sh_filter_aaaa.py14
-rw-r--r--bin/tests/system/formerr/clean.sh21
-rw-r--r--bin/tests/system/formerr/formerr.pl97
-rw-r--r--bin/tests/system/formerr/nametoolong19
-rw-r--r--bin/tests/system/formerr/noquestions1
-rw-r--r--bin/tests/system/formerr/ns1/named.conf.in29
-rw-r--r--bin/tests/system/formerr/ns1/root.db21
-rw-r--r--bin/tests/system/formerr/setup.sh16
-rw-r--r--bin/tests/system/formerr/tests.sh48
-rw-r--r--bin/tests/system/formerr/tests_sh_formerr.py14
-rw-r--r--bin/tests/system/formerr/twoquestions7
-rw-r--r--bin/tests/system/forward/ans11/ans.py272
-rw-r--r--bin/tests/system/forward/ans6/ans.pl562
-rw-r--r--bin/tests/system/forward/clean.sh26
-rw-r--r--bin/tests/system/forward/ns1/diditwork.net.db22
-rw-r--r--bin/tests/system/forward/ns1/example.db23
-rw-r--r--bin/tests/system/forward/ns1/named.conf.in87
-rw-r--r--bin/tests/system/forward/ns1/net.example.lll15
-rw-r--r--bin/tests/system/forward/ns1/root.db.in36
-rw-r--r--bin/tests/system/forward/ns1/sign.sh34
-rw-r--r--bin/tests/system/forward/ns1/sld.tld.db22
-rw-r--r--bin/tests/system/forward/ns1/spoofed.net.db22
-rw-r--r--bin/tests/system/forward/ns1/sub.local.net.db22
-rw-r--r--bin/tests/system/forward/ns10/fakenet.zone17
-rw-r--r--bin/tests/system/forward/ns10/fakenet2.zone15
-rw-r--r--bin/tests/system/forward/ns10/fakesublocalnet.zone15
-rw-r--r--bin/tests/system/forward/ns10/fakesublocaltld.zone15
-rw-r--r--bin/tests/system/forward/ns10/named.conf.in54
-rw-r--r--bin/tests/system/forward/ns10/net.example.lll15
-rw-r--r--bin/tests/system/forward/ns10/spoofednet.zone16
-rw-r--r--bin/tests/system/forward/ns2/example.db23
-rw-r--r--bin/tests/system/forward/ns2/named.conf.in72
-rw-r--r--bin/tests/system/forward/ns2/root.db30
-rw-r--r--bin/tests/system/forward/ns2/tld.db29
-rw-r--r--bin/tests/system/forward/ns3/named1.conf.in66
-rw-r--r--bin/tests/system/forward/ns3/named2.conf.in43
-rw-r--r--bin/tests/system/forward/ns3/root.db30
-rw-r--r--bin/tests/system/forward/ns3/root2.db21
-rw-r--r--bin/tests/system/forward/ns4/malicious.db24
-rw-r--r--bin/tests/system/forward/ns4/named.conf.in69
-rw-r--r--bin/tests/system/forward/ns4/root.db30
-rw-r--r--bin/tests/system/forward/ns4/sibling.tld.db22
-rw-r--r--bin/tests/system/forward/ns5/named.conf.in36
-rw-r--r--bin/tests/system/forward/ns5/rebind.db24
-rw-r--r--bin/tests/system/forward/ns5/root.db30
-rw-r--r--bin/tests/system/forward/ns7/named.conf.in30
-rw-r--r--bin/tests/system/forward/ns7/root.db30
-rw-r--r--bin/tests/system/forward/ns8/named.conf.in35
-rw-r--r--bin/tests/system/forward/ns8/root.db13
-rw-r--r--bin/tests/system/forward/ns8/sub.local.tld.db15
-rw-r--r--bin/tests/system/forward/ns9/local.net.db16
-rw-r--r--bin/tests/system/forward/ns9/local.tld.db15
-rw-r--r--bin/tests/system/forward/ns9/named1.conf.in67
-rw-r--r--bin/tests/system/forward/ns9/named2.conf.in70
-rw-r--r--bin/tests/system/forward/ns9/named3.conf.in50
-rw-r--r--bin/tests/system/forward/ns9/named4.conf.in47
-rw-r--r--bin/tests/system/forward/ns9/root.db13
-rw-r--r--bin/tests/system/forward/rfc1918-inherited.conf17
-rw-r--r--bin/tests/system/forward/rfc1918-notinherited.conf18
-rw-r--r--bin/tests/system/forward/setup.sh30
-rw-r--r--bin/tests/system/forward/tests.sh406
-rw-r--r--bin/tests/system/forward/tests_sh_forward.py14
-rw-r--r--bin/tests/system/forward/ula-inherited.conf17
-rw-r--r--bin/tests/system/forward/ula-notinherited.conf18
-rw-r--r--bin/tests/system/fromhex.pl47
-rw-r--r--bin/tests/system/genzone.sh511
-rw-r--r--bin/tests/system/geoip2/clean.sh20
-rw-r--r--bin/tests/system/geoip2/conf/bad-areacode.conf38
-rw-r--r--bin/tests/system/geoip2/conf/bad-dbname.conf30
-rw-r--r--bin/tests/system/geoip2/conf/bad-netspeed.conf37
-rw-r--r--bin/tests/system/geoip2/conf/bad-regiondb.conf44
-rw-r--r--bin/tests/system/geoip2/conf/bad-threeletter.conf35
-rw-r--r--bin/tests/system/geoip2/conf/good-options.conf36
-rw-r--r--bin/tests/system/geoip2/data/GeoIP2-City.json506
-rw-r--r--bin/tests/system/geoip2/data/GeoIP2-City.mmdbbin0 -> 3165 bytes
-rw-r--r--bin/tests/system/geoip2/data/GeoIP2-Country.json242
-rw-r--r--bin/tests/system/geoip2/data/GeoIP2-Country.mmdbbin0 -> 2971 bytes
-rw-r--r--bin/tests/system/geoip2/data/GeoIP2-Domain.json72
-rw-r--r--bin/tests/system/geoip2/data/GeoIP2-Domain.mmdbbin0 -> 2524 bytes
-rw-r--r--bin/tests/system/geoip2/data/GeoIP2-ISP.json86
-rw-r--r--bin/tests/system/geoip2/data/GeoIP2-ISP.mmdbbin0 -> 2626 bytes
-rw-r--r--bin/tests/system/geoip2/data/GeoLite2-ASN.json86
-rw-r--r--bin/tests/system/geoip2/data/GeoLite2-ASN.mmdbbin0 -> 2672 bytes
-rw-r--r--bin/tests/system/geoip2/data/README.md23
-rwxr-xr-xbin/tests/system/geoip2/data/write-test-data.pl194
-rw-r--r--bin/tests/system/geoip2/ns2/example.db.in21
-rw-r--r--bin/tests/system/geoip2/ns2/named1.conf.in108
-rw-r--r--bin/tests/system/geoip2/ns2/named10.conf.in100
-rw-r--r--bin/tests/system/geoip2/ns2/named11.conf.in100
-rw-r--r--bin/tests/system/geoip2/ns2/named12.conf.in41
-rw-r--r--bin/tests/system/geoip2/ns2/named2.conf.in108
-rw-r--r--bin/tests/system/geoip2/ns2/named3.conf.in100
-rw-r--r--bin/tests/system/geoip2/ns2/named4.conf.in84
-rw-r--r--bin/tests/system/geoip2/ns2/named5.conf.in92
-rw-r--r--bin/tests/system/geoip2/ns2/named6.conf.in100
-rw-r--r--bin/tests/system/geoip2/ns2/named7.conf.in100
-rw-r--r--bin/tests/system/geoip2/ns2/named8.conf.in100
-rw-r--r--bin/tests/system/geoip2/ns2/named9.conf.in100
-rw-r--r--bin/tests/system/geoip2/prereq.sh20
-rw-r--r--bin/tests/system/geoip2/setup.sh23
-rw-r--r--bin/tests/system/geoip2/tests.sh490
-rw-r--r--bin/tests/system/geoip2/tests_sh_geoip2.py14
-rwxr-xr-xbin/tests/system/get_algorithms.py241
-rwxr-xr-xbin/tests/system/get_core_dumps.sh70
-rwxr-xr-xbin/tests/system/get_ports.sh72
-rw-r--r--bin/tests/system/glue/clean.sh23
-rw-r--r--bin/tests/system/glue/fi.good27
-rw-r--r--bin/tests/system/glue/noglue.good14
-rw-r--r--bin/tests/system/glue/ns1/named.conf.in39
-rw-r--r--bin/tests/system/glue/ns1/net.db34
-rw-r--r--bin/tests/system/glue/ns1/root-servers.nil.db25
-rw-r--r--bin/tests/system/glue/ns1/root.db44
-rw-r--r--bin/tests/system/glue/setup.sh16
-rw-r--r--bin/tests/system/glue/tests.sh35
-rw-r--r--bin/tests/system/glue/tests_sh_glue.py14
-rw-r--r--bin/tests/system/hooks/clean.sh16
-rw-r--r--bin/tests/system/hooks/driver/Makefile.am12
-rw-r--r--bin/tests/system/hooks/driver/Makefile.in775
-rw-r--r--bin/tests/system/hooks/driver/test-async.c348
-rw-r--r--bin/tests/system/hooks/ns1/example.db21
-rw-r--r--bin/tests/system/hooks/ns1/named.conf.in41
-rw-r--r--bin/tests/system/hooks/setup.sh16
-rw-r--r--bin/tests/system/hooks/tests_async_plugin.py27
-rw-r--r--bin/tests/system/host/clean.sh21
-rw-r--r--bin/tests/system/host/ns1/example.net.db31
-rw-r--r--bin/tests/system/host/ns1/named.conf.in34
-rw-r--r--bin/tests/system/host/setup.sh22
-rw-r--r--bin/tests/system/host/tests.sh128
-rw-r--r--bin/tests/system/host/tests_sh_host.py14
-rw-r--r--bin/tests/system/idna/clean.sh19
-rw-r--r--bin/tests/system/idna/ns1/named.conf.in30
-rw-r--r--bin/tests/system/idna/ns1/root.db26
-rw-r--r--bin/tests/system/idna/setup.sh17
-rw-r--r--bin/tests/system/idna/tests.sh393
-rw-r--r--bin/tests/system/idna/tests_sh_idna.py14
-rwxr-xr-xbin/tests/system/ifconfig.sh.in268
-rw-r--r--bin/tests/system/include-multiplecfg/clean.sh23
-rw-r--r--bin/tests/system/include-multiplecfg/ns2/mars.com.db24
-rw-r--r--bin/tests/system/include-multiplecfg/ns2/mars.conf18
-rw-r--r--bin/tests/system/include-multiplecfg/ns2/named.conf.in29
-rw-r--r--bin/tests/system/include-multiplecfg/ns2/zone1.com.db24
-rw-r--r--bin/tests/system/include-multiplecfg/ns2/zone1.conf18
-rw-r--r--bin/tests/system/include-multiplecfg/ns2/zone2.com.db24
-rw-r--r--bin/tests/system/include-multiplecfg/ns2/zone2.conf18
-rw-r--r--bin/tests/system/include-multiplecfg/setup.sh18
-rw-r--r--bin/tests/system/include-multiplecfg/tests.sh64
-rw-r--r--bin/tests/system/include-multiplecfg/tests_sh_include_multiplecfg.py14
-rw-r--r--bin/tests/system/inline/clean.sh27
-rw-r--r--bin/tests/system/inline/ns1/named.conf.in36
-rw-r--r--bin/tests/system/inline/ns1/root.db.in59
-rw-r--r--bin/tests/system/inline/ns1/sign.sh25
-rw-r--r--bin/tests/system/inline/ns2/bits.db.in22
-rw-r--r--bin/tests/system/inline/ns2/named.conf.in86
-rw-r--r--bin/tests/system/inline/ns2/nsec3-loop.db.in25
-rw-r--r--bin/tests/system/inline/ns3/include.db.in12
-rw-r--r--bin/tests/system/inline/ns3/named.conf.in181
-rw-r--r--bin/tests/system/inline/ns3/primary.db.in21
-rw-r--r--bin/tests/system/inline/ns3/primary2.db.in23
-rw-r--r--bin/tests/system/inline/ns3/primary3.db.in24
-rw-r--r--bin/tests/system/inline/ns3/primary4.db.in24
-rw-r--r--bin/tests/system/inline/ns3/primary5.db.in24
-rw-r--r--bin/tests/system/inline/ns3/primary6.db.in26
-rw-r--r--bin/tests/system/inline/ns3/primary7.db.in26
-rwxr-xr-xbin/tests/system/inline/ns3/sign.sh159
-rw-r--r--bin/tests/system/inline/ns4/named.conf.in34
-rw-r--r--bin/tests/system/inline/ns4/noixfr.db.in22
-rw-r--r--bin/tests/system/inline/ns5/named.conf.post42
-rw-r--r--bin/tests/system/inline/ns5/named.conf.pre39
-rw-r--r--bin/tests/system/inline/ns6/named.conf.in41
-rw-r--r--bin/tests/system/inline/ns7/named.conf.in50
-rwxr-xr-xbin/tests/system/inline/ns7/sign.sh24
-rw-r--r--bin/tests/system/inline/ns8/example.com.db.in21
-rw-r--r--bin/tests/system/inline/ns8/example.db.in26
-rw-r--r--bin/tests/system/inline/ns8/example2.db.in26
-rw-r--r--bin/tests/system/inline/ns8/example3.db.in26
-rw-r--r--bin/tests/system/inline/ns8/named.conf.in163
-rwxr-xr-xbin/tests/system/inline/ns8/sign.sh35
-rw-r--r--bin/tests/system/inline/setup.sh56
-rwxr-xr-xbin/tests/system/inline/tests.sh1501
-rw-r--r--bin/tests/system/inline/tests_sh_inline.py14
-rwxr-xr-xbin/tests/system/inline/tests_signed_zone_files.py67
-rw-r--r--bin/tests/system/integrity/clean.sh18
-rw-r--r--bin/tests/system/integrity/ns1/mx-cname.db17
-rw-r--r--bin/tests/system/integrity/ns1/named.conf.in115
-rw-r--r--bin/tests/system/integrity/ns1/srv-cname.db17
-rw-r--r--bin/tests/system/integrity/setup.sh16
-rw-r--r--bin/tests/system/integrity/tests.sh132
-rw-r--r--bin/tests/system/integrity/tests_sh_integrity.py14
-rw-r--r--bin/tests/system/ixfr/ans2/startme0
-rw-r--r--bin/tests/system/ixfr/clean.sh26
-rw-r--r--bin/tests/system/ixfr/ixfr-stats.good3
-rw-r--r--bin/tests/system/ixfr/ns1/named.conf.in34
-rw-r--r--bin/tests/system/ixfr/ns3/named.conf.in53
-rw-r--r--bin/tests/system/ixfr/ns4/named.conf.in51
-rw-r--r--bin/tests/system/ixfr/ns5/named.conf.in51
-rw-r--r--bin/tests/system/ixfr/setup.sh68
-rw-r--r--bin/tests/system/ixfr/tests.sh443
-rw-r--r--bin/tests/system/ixfr/tests_sh_ixfr.py14
-rw-r--r--bin/tests/system/journal/clean.sh22
-rw-r--r--bin/tests/system/journal/ns1/changed.ver1.jnl.savedbin0 -> 707 bytes
-rw-r--r--bin/tests/system/journal/ns1/changed.ver2.jnl.savedbin0 -> 718 bytes
-rw-r--r--bin/tests/system/journal/ns1/d1212.jnl.savedbin0 -> 1478 bytes
-rw-r--r--bin/tests/system/journal/ns1/d2121.jnl.savedbin0 -> 1478 bytes
-rw-r--r--bin/tests/system/journal/ns1/generic.db.in17
-rw-r--r--bin/tests/system/journal/ns1/ixfr.db.in18
-rw-r--r--bin/tests/system/journal/ns1/ixfr.ver1.jnl.savedbin0 -> 686 bytes
-rw-r--r--bin/tests/system/journal/ns1/managed-keys.bind.in2
-rw-r--r--bin/tests/system/journal/ns1/managed-keys.bind.jnl.in704
-rw-r--r--bin/tests/system/journal/ns1/maxjournal.jnl.savedbin0 -> 13660 bytes
-rw-r--r--bin/tests/system/journal/ns1/maxjournal2.jnl.savedbin0 -> 14259 bytes
-rw-r--r--bin/tests/system/journal/ns1/named.conf.in92
-rw-r--r--bin/tests/system/journal/ns1/unchanged.ver1.jnl.savedbin0 -> 512 bytes
-rw-r--r--bin/tests/system/journal/ns1/unchanged.ver2.jnl.savedbin0 -> 512 bytes
-rw-r--r--bin/tests/system/journal/ns2/managed-keys.bind.in14
-rw-r--r--bin/tests/system/journal/ns2/managed-keys.bind.jnl.inbin0 -> 2944 bytes
-rw-r--r--bin/tests/system/journal/ns2/named.conf.in36
-rw-r--r--bin/tests/system/journal/setup.sh51
-rw-r--r--bin/tests/system/journal/tests.sh257
-rw-r--r--bin/tests/system/journal/tests_sh_journal.py14
-rw-r--r--bin/tests/system/kasp.sh1244
-rw-r--r--bin/tests/system/kasp/README23
-rw-r--r--bin/tests/system/kasp/clean.sh36
-rw-r--r--bin/tests/system/kasp/kasp.conf27
-rw-r--r--bin/tests/system/kasp/ns2/named.conf.in62
-rw-r--r--bin/tests/system/kasp/ns2/secondary.kasp.db.in29
-rw-r--r--bin/tests/system/kasp/ns2/secondary.kasp.db.in230
-rw-r--r--bin/tests/system/kasp/ns2/setup.sh35
-rw-r--r--bin/tests/system/kasp/ns2/template.tld.db.in27
-rw-r--r--bin/tests/system/kasp/ns3/ed25519.conf29
-rw-r--r--bin/tests/system/kasp/ns3/ed448.conf29
-rw-r--r--bin/tests/system/kasp/ns3/named-fips.conf.in520
-rw-r--r--bin/tests/system/kasp/ns3/named.conf.in30
-rw-r--r--bin/tests/system/kasp/ns3/policies/autosign.conf.in133
-rw-r--r--bin/tests/system/kasp/ns3/policies/kasp-fips.conf.in118
-rw-r--r--bin/tests/system/kasp/ns3/policies/kasp.conf.in34
-rw-r--r--bin/tests/system/kasp/ns3/setup.sh1470
-rw-r--r--bin/tests/system/kasp/ns3/template.db.in27
-rw-r--r--bin/tests/system/kasp/ns3/template2.db.in27
-rw-r--r--bin/tests/system/kasp/ns4/example1.db.in24
-rw-r--r--bin/tests/system/kasp/ns4/example2.db.in24
-rw-r--r--bin/tests/system/kasp/ns4/named.conf.in177
-rw-r--r--bin/tests/system/kasp/ns4/setup.sh33
-rw-r--r--bin/tests/system/kasp/ns4/template.db.in27
-rw-r--r--bin/tests/system/kasp/ns5/named.conf.in133
-rw-r--r--bin/tests/system/kasp/ns5/setup.sh30
-rw-r--r--bin/tests/system/kasp/ns5/template.db.in27
-rw-r--r--bin/tests/system/kasp/ns6/example.db.in26
-rw-r--r--bin/tests/system/kasp/ns6/example2.db.in26
-rw-r--r--bin/tests/system/kasp/ns6/example3.db.in26
-rw-r--r--bin/tests/system/kasp/ns6/named.conf.in98
-rw-r--r--bin/tests/system/kasp/ns6/named2.conf.in186
-rw-r--r--bin/tests/system/kasp/ns6/policies/csk1.conf.in30
-rw-r--r--bin/tests/system/kasp/ns6/policies/csk2.conf.in30
-rw-r--r--bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in63
-rw-r--r--bin/tests/system/kasp/ns6/policies/kasp.conf.in33
-rw-r--r--bin/tests/system/kasp/ns6/setup.sh409
-rw-r--r--bin/tests/system/kasp/ns6/template.db.in27
-rw-r--r--bin/tests/system/kasp/setup.sh80
-rw-r--r--bin/tests/system/kasp/tests.sh4883
-rw-r--r--bin/tests/system/kasp/tests_sh_kasp.py14
-rw-r--r--bin/tests/system/keepalive/clean.sh21
-rw-r--r--bin/tests/system/keepalive/expected4
-rw-r--r--bin/tests/system/keepalive/ns1/named.conf.in39
-rw-r--r--bin/tests/system/keepalive/ns1/root.db24
-rw-r--r--bin/tests/system/keepalive/ns2/example.db16
-rw-r--r--bin/tests/system/keepalive/ns2/named.conf.in45
-rw-r--r--bin/tests/system/keepalive/ns3/named.conf.in45
-rw-r--r--bin/tests/system/keepalive/setup.sh18
-rw-r--r--bin/tests/system/keepalive/tests.sh99
-rw-r--r--bin/tests/system/keepalive/tests_sh_keepalive.py14
-rw-r--r--bin/tests/system/keyfromlabel/clean.sh27
-rw-r--r--bin/tests/system/keyfromlabel/prereq.sh21
-rw-r--r--bin/tests/system/keyfromlabel/setup.sh22
-rw-r--r--bin/tests/system/keyfromlabel/template.db.in24
-rw-r--r--bin/tests/system/keyfromlabel/tests.sh93
-rw-r--r--bin/tests/system/keyfromlabel/tests_sh_keyfromlabel.py14
-rw-r--r--bin/tests/system/keymgr2kasp/README17
-rw-r--r--bin/tests/system/keymgr2kasp/clean.sh34
-rw-r--r--bin/tests/system/keymgr2kasp/ns3/kasp.conf.in104
-rw-r--r--bin/tests/system/keymgr2kasp/ns3/named.conf.in106
-rw-r--r--bin/tests/system/keymgr2kasp/ns3/named2.conf.in95
-rw-r--r--bin/tests/system/keymgr2kasp/ns3/setup.sh148
-rw-r--r--bin/tests/system/keymgr2kasp/ns3/template.db.in27
-rw-r--r--bin/tests/system/keymgr2kasp/ns4/named.conf.in73
-rw-r--r--bin/tests/system/keymgr2kasp/ns4/named2.conf.in90
-rw-r--r--bin/tests/system/keymgr2kasp/ns4/setup.sh46
-rw-r--r--bin/tests/system/keymgr2kasp/ns4/template.ext.db.in24
-rw-r--r--bin/tests/system/keymgr2kasp/ns4/template.int.db.in24
-rw-r--r--bin/tests/system/keymgr2kasp/setup.sh34
-rw-r--r--bin/tests/system/keymgr2kasp/tests.sh1276
-rw-r--r--bin/tests/system/keymgr2kasp/tests_sh_keymgr2kasp.py14
-rw-r--r--bin/tests/system/legacy.run.sh.in311
-rw-r--r--bin/tests/system/legacy/build.sh21
-rw-r--r--bin/tests/system/legacy/clean.sh31
-rw-r--r--bin/tests/system/legacy/ns1/named1.conf.in38
-rw-r--r--bin/tests/system/legacy/ns1/named2.conf.in31
-rw-r--r--bin/tests/system/legacy/ns1/root.db33
-rw-r--r--bin/tests/system/legacy/ns1/trusted.conf16
-rw-r--r--bin/tests/system/legacy/ns10/ednsrefused.db14
-rw-r--r--bin/tests/system/legacy/ns10/named.conf.in29
-rw-r--r--bin/tests/system/legacy/ns10/named.ednsrefused1
-rw-r--r--bin/tests/system/legacy/ns2/dropedns.db14
-rw-r--r--bin/tests/system/legacy/ns2/named.conf.in29
-rw-r--r--bin/tests/system/legacy/ns2/named.dropedns1
-rw-r--r--bin/tests/system/legacy/ns3/dropedns-notcp.db14
-rw-r--r--bin/tests/system/legacy/ns3/named.conf.in29
-rw-r--r--bin/tests/system/legacy/ns3/named.dropedns1
-rw-r--r--bin/tests/system/legacy/ns3/named.notcp1
-rw-r--r--bin/tests/system/legacy/ns4/named.args1
-rw-r--r--bin/tests/system/legacy/ns4/named.conf.in29
-rw-r--r--bin/tests/system/legacy/ns4/plain.db14
-rw-r--r--bin/tests/system/legacy/ns5/named.args1
-rw-r--r--bin/tests/system/legacy/ns5/named.conf.in29
-rw-r--r--bin/tests/system/legacy/ns5/named.notcp1
-rw-r--r--bin/tests/system/legacy/ns5/plain-notcp.db14
-rw-r--r--bin/tests/system/legacy/ns6/edns512.db.in15
-rw-r--r--bin/tests/system/legacy/ns6/edns512.db.signed226
-rw-r--r--bin/tests/system/legacy/ns6/named.args1
-rw-r--r--bin/tests/system/legacy/ns6/named.conf.in29
-rwxr-xr-xbin/tests/system/legacy/ns6/sign.sh30
-rw-r--r--bin/tests/system/legacy/ns7/edns512-notcp.db.in15
-rw-r--r--bin/tests/system/legacy/ns7/edns512-notcp.db.signed226
-rw-r--r--bin/tests/system/legacy/ns7/named.args1
-rw-r--r--bin/tests/system/legacy/ns7/named.conf.in29
-rw-r--r--bin/tests/system/legacy/ns7/named.notcp1
-rwxr-xr-xbin/tests/system/legacy/ns7/sign.sh33
-rw-r--r--bin/tests/system/legacy/ns8/ednsformerr.db14
-rw-r--r--bin/tests/system/legacy/ns8/named.conf.in29
-rw-r--r--bin/tests/system/legacy/ns8/named.ednsformerr1
-rw-r--r--bin/tests/system/legacy/ns9/ednsnotimp.db14
-rw-r--r--bin/tests/system/legacy/ns9/named.conf.in29
-rw-r--r--bin/tests/system/legacy/ns9/named.ednsnotimp1
-rw-r--r--bin/tests/system/legacy/setup.sh25
-rwxr-xr-xbin/tests/system/legacy/tests.sh269
-rw-r--r--bin/tests/system/legacy/tests_sh_legacy.py14
-rw-r--r--bin/tests/system/limits/clean.sh22
-rw-r--r--bin/tests/system/limits/knowngood.dig.out.10001023
-rw-r--r--bin/tests/system/limits/knowngood.dig.out.20002023
-rw-r--r--bin/tests/system/limits/knowngood.dig.out.30003023
-rw-r--r--bin/tests/system/limits/knowngood.dig.out.40004023
-rw-r--r--bin/tests/system/limits/knowngood.dig.out.a-maximum-rrset4114
-rw-r--r--bin/tests/system/limits/ns1/example.db19112
-rw-r--r--bin/tests/system/limits/ns1/named.conf.in36
-rw-r--r--bin/tests/system/limits/ns1/root.db24
-rw-r--r--bin/tests/system/limits/setup.sh16
-rw-r--r--bin/tests/system/limits/tests.sh57
-rw-r--r--bin/tests/system/limits/tests_sh_limits.py14
-rw-r--r--bin/tests/system/logfileconfig/clean.sh38
-rw-r--r--bin/tests/system/logfileconfig/named1.args1
-rw-r--r--bin/tests/system/logfileconfig/named2.args1
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.abspathconf.in52
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.dirconf.in43
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.incconf.in52
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.iso8601-utc.in43
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.iso8601.in44
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.pipeconf.in43
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.plain.in50
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.plainconf.in34
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.symconf.in43
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.tsconf.in52
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.unlimited.in52
-rw-r--r--bin/tests/system/logfileconfig/ns1/named.versconf.in52
-rw-r--r--bin/tests/system/logfileconfig/setup.sh18
-rw-r--r--bin/tests/system/logfileconfig/tests.sh297
-rw-r--r--bin/tests/system/logfileconfig/tests_sh_logfileconfig.py14
-rw-r--r--bin/tests/system/makejournal.c158
-rw-r--r--bin/tests/system/masterfile/clean.sh20
-rw-r--r--bin/tests/system/masterfile/knowngood.dig.out32
-rw-r--r--bin/tests/system/masterfile/ns1/include.db35
-rw-r--r--bin/tests/system/masterfile/ns1/named.conf.in40
-rw-r--r--bin/tests/system/masterfile/ns1/sub.db15
-rw-r--r--bin/tests/system/masterfile/ns1/ttl1.db27
-rw-r--r--bin/tests/system/masterfile/ns1/ttl2.db30
-rw-r--r--bin/tests/system/masterfile/ns2/example.db21
-rw-r--r--bin/tests/system/masterfile/ns2/named.conf.in42
-rw-r--r--bin/tests/system/masterfile/setup.sh18
-rw-r--r--bin/tests/system/masterfile/tests.sh63
-rw-r--r--bin/tests/system/masterfile/tests_sh_masterfile.py14
-rw-r--r--bin/tests/system/masterfile/zone/inheritownerafterinclude.db14
-rw-r--r--bin/tests/system/masterfile/zone/inheritownerafterinclude.good3
-rw-r--r--bin/tests/system/masterfile/zone/nameservers.db12
-rwxr-xr-xbin/tests/system/masterformat/clean.sh35
-rwxr-xr-xbin/tests/system/masterformat/ns1/compile.sh34
-rw-r--r--bin/tests/system/masterformat/ns1/example.db58
-rw-r--r--bin/tests/system/masterformat/ns1/large.db.in22
-rw-r--r--bin/tests/system/masterformat/ns1/named.conf.in88
-rw-r--r--bin/tests/system/masterformat/ns1/signed.db29
-rw-r--r--bin/tests/system/masterformat/ns2/formerly-text.db.in48
-rw-r--r--bin/tests/system/masterformat/ns2/named.conf.in64
-rw-r--r--bin/tests/system/masterformat/ns3/named.conf.in46
-rwxr-xr-xbin/tests/system/masterformat/setup.sh31
-rwxr-xr-xbin/tests/system/masterformat/tests.sh278
-rw-r--r--bin/tests/system/masterformat/tests_sh_masterformat.py14
-rw-r--r--bin/tests/system/metadata/child.db24
-rw-r--r--bin/tests/system/metadata/clean.sh21
-rw-r--r--bin/tests/system/metadata/parent.db31
-rw-r--r--bin/tests/system/metadata/setup.sh60
-rw-r--r--bin/tests/system/metadata/tests.sh233
-rw-r--r--bin/tests/system/metadata/tests_sh_metadata.py14
-rw-r--r--bin/tests/system/mirror/README26
-rw-r--r--bin/tests/system/mirror/clean.sh30
-rw-r--r--bin/tests/system/mirror/ns1/named.conf.in29
-rw-r--r--bin/tests/system/mirror/ns1/root.db.in19
-rw-r--r--bin/tests/system/mirror/ns1/sign.sh37
-rw-r--r--bin/tests/system/mirror/ns2/example.db.in17
-rw-r--r--bin/tests/system/mirror/ns2/initially-unavailable.db.in16
-rw-r--r--bin/tests/system/mirror/ns2/named.conf.in86
-rw-r--r--bin/tests/system/mirror/ns2/sign.sh79
-rw-r--r--bin/tests/system/mirror/ns2/sub.example.db.in15
-rw-r--r--bin/tests/system/mirror/ns2/verify.db.in15
-rw-r--r--bin/tests/system/mirror/ns3/named.args1
-rw-r--r--bin/tests/system/mirror/ns3/named.conf.in102
-rw-r--r--bin/tests/system/mirror/setup.sh25
-rw-r--r--bin/tests/system/mirror/tests.sh558
-rw-r--r--bin/tests/system/mirror/tests_sh_mirror.py14
-rw-r--r--bin/tests/system/mkeys/README34
-rw-r--r--bin/tests/system/mkeys/clean.sh33
-rw-r--r--bin/tests/system/mkeys/ns1/named1.conf.in59
-rw-r--r--bin/tests/system/mkeys/ns1/named2.conf.in57
-rw-r--r--bin/tests/system/mkeys/ns1/named3.conf.in51
-rw-r--r--bin/tests/system/mkeys/ns1/root.db28
-rw-r--r--bin/tests/system/mkeys/ns1/sign.sh93
-rw-r--r--bin/tests/system/mkeys/ns1/sub.tld.db21
-rw-r--r--bin/tests/system/mkeys/ns1/tld.db23
-rw-r--r--bin/tests/system/mkeys/ns1/unsupported.key1
-rw-r--r--bin/tests/system/mkeys/ns2/named.args1
-rw-r--r--bin/tests/system/mkeys/ns2/named.conf.in43
-rw-r--r--bin/tests/system/mkeys/ns3/named.args1
-rw-r--r--bin/tests/system/mkeys/ns3/named.conf.in45
-rw-r--r--bin/tests/system/mkeys/ns4/named.conf.in48
-rw-r--r--bin/tests/system/mkeys/ns4/sign.sh24
-rw-r--r--bin/tests/system/mkeys/ns4/sub.foo.db21
-rw-r--r--bin/tests/system/mkeys/ns5/foo.db23
-rw-r--r--bin/tests/system/mkeys/ns5/named.conf.in51
-rw-r--r--bin/tests/system/mkeys/ns5/named1.args1
-rw-r--r--bin/tests/system/mkeys/ns5/named2.args1
-rw-r--r--bin/tests/system/mkeys/ns6/named.args1
-rw-r--r--bin/tests/system/mkeys/ns6/named.conf.in44
-rw-r--r--bin/tests/system/mkeys/ns6/setup.sh33
-rw-r--r--bin/tests/system/mkeys/ns6/unsupported-managed.key1
-rw-r--r--bin/tests/system/mkeys/ns7/named.conf.in51
-rw-r--r--bin/tests/system/mkeys/setup.sh43
-rw-r--r--bin/tests/system/mkeys/tests.sh882
-rw-r--r--bin/tests/system/mkeys/tests_sh_mkeys.py14
-rw-r--r--bin/tests/system/names/clean.sh20
-rw-r--r--bin/tests/system/names/ns1/example.db50
-rw-r--r--bin/tests/system/names/ns1/named.conf.in45
-rw-r--r--bin/tests/system/names/setup.sh16
-rw-r--r--bin/tests/system/names/tests.sh48
-rw-r--r--bin/tests/system/names/tests_sh_names.py14
-rw-r--r--bin/tests/system/notify/clean.sh39
-rw-r--r--bin/tests/system/notify/ns1/named.conf.in30
-rw-r--r--bin/tests/system/notify/ns1/root.db24
-rw-r--r--bin/tests/system/notify/ns2/example1.db144
-rw-r--r--bin/tests/system/notify/ns2/example2.db144
-rw-r--r--bin/tests/system/notify/ns2/example3.db144
-rw-r--r--bin/tests/system/notify/ns2/example4.db144
-rw-r--r--bin/tests/system/notify/ns2/generic.db25
-rw-r--r--bin/tests/system/notify/ns2/named.conf.in86
-rw-r--r--bin/tests/system/notify/ns3/named.conf.in44
-rw-r--r--bin/tests/system/notify/ns3/notify-source-port-test.db22
-rw-r--r--bin/tests/system/notify/ns4/named.conf.in36
-rw-r--r--bin/tests/system/notify/ns4/named.port.in1
-rw-r--r--bin/tests/system/notify/ns5/named.conf.in70
-rw-r--r--bin/tests/system/notify/ns5/x21.db22
-rw-r--r--bin/tests/system/notify/setup.sh25
-rw-r--r--bin/tests/system/notify/tests.sh220
-rw-r--r--bin/tests/system/notify/tests_sh_notify.py14
-rw-r--r--bin/tests/system/nsec3/clean.sh22
-rw-r--r--bin/tests/system/nsec3/ns2/named.conf.in47
-rw-r--r--bin/tests/system/nsec3/ns2/setup.sh22
-rw-r--r--bin/tests/system/nsec3/ns2/template.db.in28
-rw-r--r--bin/tests/system/nsec3/ns3/named.conf.in218
-rw-r--r--bin/tests/system/nsec3/ns3/named2.conf.in212
-rw-r--r--bin/tests/system/nsec3/ns3/nsec3-fails-to-load.kasp.db.in19
-rw-r--r--bin/tests/system/nsec3/ns3/setup.sh60
-rw-r--r--bin/tests/system/nsec3/ns3/template.db.in27
-rw-r--r--bin/tests/system/nsec3/setup.sh30
-rw-r--r--bin/tests/system/nsec3/tests.sh553
-rw-r--r--bin/tests/system/nsec3/tests_sh_nsec3.py14
-rw-r--r--bin/tests/system/nslookup/clean.sh21
-rw-r--r--bin/tests/system/nslookup/ns1/example.net.db31
-rw-r--r--bin/tests/system/nslookup/ns1/named.conf.in34
-rw-r--r--bin/tests/system/nslookup/setup.sh20
-rw-r--r--bin/tests/system/nslookup/tests.sh159
-rw-r--r--bin/tests/system/nslookup/tests_sh_nslookup.py14
-rw-r--r--bin/tests/system/nsupdate/ans4/ans.pl65
-rw-r--r--bin/tests/system/nsupdate/clean.sh71
-rw-r--r--bin/tests/system/nsupdate/commandlist15
-rw-r--r--bin/tests/system/nsupdate/knowngood.ns1.after99
-rw-r--r--bin/tests/system/nsupdate/knowngood.ns1.afterstop3
-rw-r--r--bin/tests/system/nsupdate/knowngood.ns1.before98
-rw-r--r--bin/tests/system/nsupdate/krb/setup.sh117
-rw-r--r--bin/tests/system/nsupdate/ns1/example1.db146
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-157.+157+23571.key1
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-157.+157+23571.private7
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-161.+161+23350.key1
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-161.+161+23350.private7
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-162.+162+00032.key1
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-162.+162+00032.private7
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-163.+163+48857.key1
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-163.+163+48857.private7
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-164.+164+09001.key1
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-164.+164+09001.private7
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-165.+165+61012.key1
-rw-r--r--bin/tests/system/nsupdate/ns1/legacy/Klegacy-165.+165+61012.private7
-rw-r--r--bin/tests/system/nsupdate/ns1/many.test.db.in21
-rw-r--r--bin/tests/system/nsupdate/ns1/max-ttl.db29
-rw-r--r--bin/tests/system/nsupdate/ns1/maxjournal.db.in20
-rw-r--r--bin/tests/system/nsupdate/ns1/named.conf.in175
-rw-r--r--bin/tests/system/nsupdate/ns1/sample.db.in19
-rw-r--r--bin/tests/system/nsupdate/ns10/dns.keytabbin0 -> 168 bytes
-rw-r--r--bin/tests/system/nsupdate/ns10/example.com.db.in27
-rw-r--r--bin/tests/system/nsupdate/ns10/in-addr.db.in27
-rw-r--r--bin/tests/system/nsupdate/ns10/machine.ccachebin0 -> 1217 bytes
-rw-r--r--bin/tests/system/nsupdate/ns10/named.conf.in52
-rw-r--r--bin/tests/system/nsupdate/ns2/named.conf.in75
-rw-r--r--bin/tests/system/nsupdate/ns2/sample.db.in21
-rw-r--r--bin/tests/system/nsupdate/ns3/delegation.test.db.in15
-rw-r--r--bin/tests/system/nsupdate/ns3/dnskey.test.db.in15
-rw-r--r--bin/tests/system/nsupdate/ns3/example.db.in15
-rw-r--r--bin/tests/system/nsupdate/ns3/multisigner.test.db.in14
-rw-r--r--bin/tests/system/nsupdate/ns3/named.conf.in73
-rw-r--r--bin/tests/system/nsupdate/ns3/nsec3param.test.db.in15
-rw-r--r--bin/tests/system/nsupdate/ns3/sign.sh50
-rw-r--r--bin/tests/system/nsupdate/ns3/too-big.test.db.in15
-rw-r--r--bin/tests/system/nsupdate/ns5/local.db.in25
-rw-r--r--bin/tests/system/nsupdate/ns5/named.args1
-rw-r--r--bin/tests/system/nsupdate/ns5/named.conf.in41
-rw-r--r--bin/tests/system/nsupdate/ns6/in-addr.db.in21
-rw-r--r--bin/tests/system/nsupdate/ns6/named.args1
-rw-r--r--bin/tests/system/nsupdate/ns6/named.conf.in41
-rw-r--r--bin/tests/system/nsupdate/ns7/dns.keytabbin0 -> 166 bytes
-rw-r--r--bin/tests/system/nsupdate/ns7/example.com.db.in27
-rw-r--r--bin/tests/system/nsupdate/ns7/in-addr.db.in27
-rw-r--r--bin/tests/system/nsupdate/ns7/machine.ccachebin0 -> 1327 bytes
-rw-r--r--bin/tests/system/nsupdate/ns7/named1.conf.in52
-rw-r--r--bin/tests/system/nsupdate/ns7/named2.conf.in53
-rw-r--r--bin/tests/system/nsupdate/ns8/dns-other-than-KRB5_KTNAME.keytabbin0 -> 166 bytes
-rw-r--r--bin/tests/system/nsupdate/ns8/example.com.db.in21
-rw-r--r--bin/tests/system/nsupdate/ns8/in-addr.db.in21
-rw-r--r--bin/tests/system/nsupdate/ns8/machine.ccachebin0 -> 1327 bytes
-rw-r--r--bin/tests/system/nsupdate/ns8/named.conf.in51
-rw-r--r--bin/tests/system/nsupdate/ns9/dns.keytabbin0 -> 166 bytes
-rw-r--r--bin/tests/system/nsupdate/ns9/example.com.db.in21
-rw-r--r--bin/tests/system/nsupdate/ns9/in-addr.db.in21
-rw-r--r--bin/tests/system/nsupdate/ns9/machine.ccachebin0 -> 1215 bytes
-rw-r--r--bin/tests/system/nsupdate/ns9/named.conf.in65
-rw-r--r--bin/tests/system/nsupdate/resolv.conf15
-rw-r--r--bin/tests/system/nsupdate/setup.sh116
-rwxr-xr-xbin/tests/system/nsupdate/tests.sh2262
-rw-r--r--bin/tests/system/nsupdate/tests_sh_nsupdate.py14
-rw-r--r--bin/tests/system/nsupdate/update_test.pl429
-rw-r--r--bin/tests/system/nsupdate/verylarge.in3
-rw-r--r--bin/tests/system/nzd2nzf/clean.sh21
-rw-r--r--bin/tests/system/nzd2nzf/ns1/added.db26
-rw-r--r--bin/tests/system/nzd2nzf/ns1/named.conf.in32
-rw-r--r--bin/tests/system/nzd2nzf/prereq.sh20
-rw-r--r--bin/tests/system/nzd2nzf/setup.sh16
-rw-r--r--bin/tests/system/nzd2nzf/tests.sh85
-rw-r--r--bin/tests/system/nzd2nzf/tests_sh_nzd2nzf.py14
-rw-r--r--bin/tests/system/org.isc.bind.system29
-rw-r--r--bin/tests/system/org.isc.bind.system.plist17
-rw-r--r--bin/tests/system/packet.pl164
-rw-r--r--bin/tests/system/padding/clean.sh21
-rw-r--r--bin/tests/system/padding/ns1/named.conf.in39
-rw-r--r--bin/tests/system/padding/ns1/root.db24
-rw-r--r--bin/tests/system/padding/ns2/example.db15
-rw-r--r--bin/tests/system/padding/ns2/named.conf.in45
-rw-r--r--bin/tests/system/padding/ns3/named.conf.in45
-rw-r--r--bin/tests/system/padding/ns4/named.conf.in45
-rw-r--r--bin/tests/system/padding/setup.sh23
-rw-r--r--bin/tests/system/padding/tests.sh135
-rw-r--r--bin/tests/system/padding/tests_sh_padding.py14
-rw-r--r--bin/tests/system/parallel.sh34
-rw-r--r--bin/tests/system/pending/clean.sh27
-rw-r--r--bin/tests/system/pending/ns1/named.conf.in31
-rw-r--r--bin/tests/system/pending/ns1/root.db.in29
-rw-r--r--bin/tests/system/pending/ns1/sign.sh35
-rw-r--r--bin/tests/system/pending/ns2/example.com.db.in27
-rw-r--r--bin/tests/system/pending/ns2/example.db.in26
-rw-r--r--bin/tests/system/pending/ns2/forgery.db24
-rw-r--r--bin/tests/system/pending/ns2/named.conf.in51
-rw-r--r--bin/tests/system/pending/ns2/sign.sh33
-rw-r--r--bin/tests/system/pending/ns3/hostile.db22
-rw-r--r--bin/tests/system/pending/ns3/mail.example.db23
-rw-r--r--bin/tests/system/pending/ns3/named.conf.in44
-rw-r--r--bin/tests/system/pending/ns4/named.conf.in31
-rw-r--r--bin/tests/system/pending/setup.sh23
-rw-r--r--bin/tests/system/pending/tests.sh200
-rw-r--r--bin/tests/system/pending/tests_sh_pending.py14
-rw-r--r--bin/tests/system/pipelined/ans5/ans.py212
-rw-r--r--bin/tests/system/pipelined/clean.sh19
-rw-r--r--bin/tests/system/pipelined/input8
-rw-r--r--bin/tests/system/pipelined/inputb8
-rw-r--r--bin/tests/system/pipelined/ns1/named.conf.in39
-rw-r--r--bin/tests/system/pipelined/ns1/root.db27
-rw-r--r--bin/tests/system/pipelined/ns2/examplea.db32
-rw-r--r--bin/tests/system/pipelined/ns2/named.conf.in45
-rw-r--r--bin/tests/system/pipelined/ns3/exampleb.db32
-rw-r--r--bin/tests/system/pipelined/ns3/named.conf.in45
-rw-r--r--bin/tests/system/pipelined/ns4/named.conf.in41
-rw-r--r--bin/tests/system/pipelined/pipequeries.c303
-rw-r--r--bin/tests/system/pipelined/ref8
-rw-r--r--bin/tests/system/pipelined/refb8
-rw-r--r--bin/tests/system/pipelined/setup.sh21
-rw-r--r--bin/tests/system/pipelined/tests.sh82
-rw-r--r--bin/tests/system/pipelined/tests_sh_pipelined.py14
-rw-r--r--bin/tests/system/pytest.ini20
-rw-r--r--bin/tests/system/pytest_custom_markers.py60
-rwxr-xr-xbin/tests/system/qmin/ans2/ans.py401
-rwxr-xr-xbin/tests/system/qmin/ans3/ans.py274
-rwxr-xr-xbin/tests/system/qmin/ans4/ans.py320
-rw-r--r--bin/tests/system/qmin/clean.sh20
-rw-r--r--bin/tests/system/qmin/ns1/named.conf.in32
-rw-r--r--bin/tests/system/qmin/ns1/root.db41
-rw-r--r--bin/tests/system/qmin/ns5/named.conf.in43
-rw-r--r--bin/tests/system/qmin/ns6/named.conf.in43
-rw-r--r--bin/tests/system/qmin/ns7/named.conf.in51
-rw-r--r--bin/tests/system/qmin/setup.sh19
-rwxr-xr-xbin/tests/system/qmin/tests.sh537
-rw-r--r--bin/tests/system/qmin/tests_sh_qmin.py18
-rw-r--r--bin/tests/system/reclimit/README19
-rw-r--r--bin/tests/system/reclimit/ans2/ans.pl235
-rw-r--r--bin/tests/system/reclimit/ans4/ans.pl240
-rw-r--r--bin/tests/system/reclimit/ans7/ans.pl76
-rw-r--r--bin/tests/system/reclimit/clean.sh22
-rw-r--r--bin/tests/system/reclimit/ns1/named.conf.in27
-rw-r--r--bin/tests/system/reclimit/ns1/root.db21
-rw-r--r--bin/tests/system/reclimit/ns3/hints.db13
-rw-r--r--bin/tests/system/reclimit/ns3/named1.conf.in39
-rw-r--r--bin/tests/system/reclimit/ns3/named2.conf.in39
-rw-r--r--bin/tests/system/reclimit/ns3/named3.conf.in40
-rw-r--r--bin/tests/system/reclimit/ns3/named4.conf.in40
-rw-r--r--bin/tests/system/reclimit/setup.sh17
-rw-r--r--bin/tests/system/reclimit/tests.sh212
-rw-r--r--bin/tests/system/reclimit/tests_sh_reclimit.py18
-rw-r--r--bin/tests/system/redirect/clean.sh38
-rw-r--r--bin/tests/system/redirect/conf/bad1.conf25
-rw-r--r--bin/tests/system/redirect/conf/bad2.conf25
-rw-r--r--bin/tests/system/redirect/conf/bad3.conf24
-rw-r--r--bin/tests/system/redirect/conf/good1.conf22
-rw-r--r--bin/tests/system/redirect/conf/good2.conf22
-rw-r--r--bin/tests/system/redirect/conf/good3.conf23
-rw-r--r--bin/tests/system/redirect/conf/good4.conf23
-rw-r--r--bin/tests/system/redirect/ns1/example.db50
-rw-r--r--bin/tests/system/redirect/ns1/named.conf.in57
-rw-r--r--bin/tests/system/redirect/ns1/redirect.db20
-rw-r--r--bin/tests/system/redirect/ns1/root.db19
-rw-r--r--bin/tests/system/redirect/ns1/sign.sh36
-rw-r--r--bin/tests/system/redirect/ns2/example.db.in16
-rw-r--r--bin/tests/system/redirect/ns2/named.conf.in57
-rw-r--r--bin/tests/system/redirect/ns2/redirect.db.in20
-rw-r--r--bin/tests/system/redirect/ns3/example.db50
-rw-r--r--bin/tests/system/redirect/ns3/named.conf.in54
-rw-r--r--bin/tests/system/redirect/ns3/redirect.db16
-rw-r--r--bin/tests/system/redirect/ns3/root.db20
-rw-r--r--bin/tests/system/redirect/ns3/sign.sh36
-rw-r--r--bin/tests/system/redirect/ns4/example.db.in16
-rw-r--r--bin/tests/system/redirect/ns4/named.conf.in51
-rw-r--r--bin/tests/system/redirect/ns4/root.hint14
-rw-r--r--bin/tests/system/redirect/ns5/named.conf.in33
-rw-r--r--bin/tests/system/redirect/ns5/root.db.in18
-rw-r--r--bin/tests/system/redirect/ns5/sign.sh44
-rw-r--r--bin/tests/system/redirect/ns5/signed.db.in20
-rw-r--r--bin/tests/system/redirect/ns5/unsigned.db20
-rw-r--r--bin/tests/system/redirect/ns6/named.conf.in33
-rw-r--r--bin/tests/system/redirect/ns6/root.db18
-rw-r--r--bin/tests/system/redirect/setup.sh29
-rw-r--r--bin/tests/system/redirect/tests.sh549
-rw-r--r--bin/tests/system/redirect/tests_sh_redirect.py14
-rw-r--r--bin/tests/system/resolve.c505
-rw-r--r--bin/tests/system/resolver/ans10/ans.py152
-rw-r--r--bin/tests/system/resolver/ans2/ans.pl147
-rw-r--r--bin/tests/system/resolver/ans3/ans.pl191
-rw-r--r--bin/tests/system/resolver/ans8/ans.pl177
-rw-r--r--bin/tests/system/resolver/clean.sh40
-rw-r--r--bin/tests/system/resolver/ns1/chaostest.db16
-rw-r--r--bin/tests/system/resolver/ns1/named.conf.in79
-rw-r--r--bin/tests/system/resolver/ns1/root.hint14
-rw-r--r--bin/tests/system/resolver/ns4/broken.db24
-rw-r--r--bin/tests/system/resolver/ns4/child.server.db23
-rw-r--r--bin/tests/system/resolver/ns4/moves.db22
-rw-r--r--bin/tests/system/resolver/ns4/named.conf.in72
-rw-r--r--bin/tests/system/resolver/ns4/named.noaa12
-rw-r--r--bin/tests/system/resolver/ns4/root.db39
-rw-r--r--bin/tests/system/resolver/ns4/sourcens.db91
-rw-r--r--bin/tests/system/resolver/ns4/tld1.db35
-rw-r--r--bin/tests/system/resolver/ns4/tld2.db35
-rw-r--r--bin/tests/system/resolver/ns4/v4only.net.db22
-rw-r--r--bin/tests/system/resolver/ns5/child.server.db23
-rw-r--r--bin/tests/system/resolver/ns5/moves.db22
-rw-r--r--bin/tests/system/resolver/ns5/named.conf.in60
-rw-r--r--bin/tests/system/resolver/ns5/root.hint14
-rw-r--r--bin/tests/system/resolver/ns6/broken.db28
-rw-r--r--bin/tests/system/resolver/ns6/delegation-only.db33
-rw-r--r--bin/tests/system/resolver/ns6/ds.example.net.db.in15
-rw-r--r--bin/tests/system/resolver/ns6/example.net.db.in34
-rw-r--r--bin/tests/system/resolver/ns6/fetch.tld.db23
-rw-r--r--bin/tests/system/resolver/ns6/keygen.sh38
-rw-r--r--bin/tests/system/resolver/ns6/moves.db22
-rw-r--r--bin/tests/system/resolver/ns6/named.conf.in102
-rw-r--r--bin/tests/system/resolver/ns6/no-edns-version.tld.db14
-rw-r--r--bin/tests/system/resolver/ns6/redirect.com.db27
-rw-r--r--bin/tests/system/resolver/ns6/root.db36
-rw-r--r--bin/tests/system/resolver/ns6/targetns.db25
-rw-r--r--bin/tests/system/resolver/ns6/tld1.db17
-rw-r--r--bin/tests/system/resolver/ns6/to-be-removed.tld.db.in28
-rw-r--r--bin/tests/system/resolver/ns7/all-cnames.db20
-rw-r--r--bin/tests/system/resolver/ns7/edns-version.tld.db14
-rw-r--r--bin/tests/system/resolver/ns7/named1.conf.in75
-rw-r--r--bin/tests/system/resolver/ns7/named2.conf.in75
-rw-r--r--bin/tests/system/resolver/ns7/root.hint14
-rw-r--r--bin/tests/system/resolver/ns7/server.db.in24
-rw-r--r--bin/tests/system/resolver/ns7/sub.tld1.db17
-rw-r--r--bin/tests/system/resolver/ns7/tld2.db18
-rw-r--r--bin/tests/system/resolver/ns9/named.args2
-rw-r--r--bin/tests/system/resolver/ns9/named.conf.in39
-rw-r--r--bin/tests/system/resolver/ns9/named.ipv6-only0
-rw-r--r--bin/tests/system/resolver/ns9/root.hint15
-rw-r--r--bin/tests/system/resolver/setup.sh28
-rwxr-xr-xbin/tests/system/resolver/tests.sh1022
-rw-r--r--bin/tests/system/resolver/tests_sh_resolver.py14
-rw-r--r--bin/tests/system/rndc/clean.sh33
-rw-r--r--bin/tests/system/rndc/gencheck.c90
-rw-r--r--bin/tests/system/rndc/ns2/incl.db13
-rw-r--r--bin/tests/system/rndc/ns2/named.conf.in65
-rw-r--r--bin/tests/system/rndc/ns2/secondkey.conf21
-rw-r--r--bin/tests/system/rndc/ns3/named.conf.in49
-rw-r--r--bin/tests/system/rndc/ns4/named.conf.in38
-rw-r--r--bin/tests/system/rndc/ns5/named.conf.in35
-rw-r--r--bin/tests/system/rndc/ns6/named.args3
-rw-r--r--bin/tests/system/rndc/ns6/named.conf.in30
-rw-r--r--bin/tests/system/rndc/ns7/include.db.in16
-rw-r--r--bin/tests/system/rndc/ns7/include2.db.in16
-rw-r--r--bin/tests/system/rndc/ns7/named.conf.in58
-rw-r--r--bin/tests/system/rndc/ns7/test.db.in13
-rw-r--r--bin/tests/system/rndc/setup.sh64
-rw-r--r--bin/tests/system/rndc/tests.sh814
-rw-r--r--bin/tests/system/rndc/tests_sh_rndc.py14
-rw-r--r--bin/tests/system/rootkeysentinel/clean.sh26
-rw-r--r--bin/tests/system/rootkeysentinel/ns1/named.conf.in32
-rw-r--r--bin/tests/system/rootkeysentinel/ns1/root.db.in24
-rw-r--r--bin/tests/system/rootkeysentinel/ns1/sign.sh35
-rw-r--r--bin/tests/system/rootkeysentinel/ns2/example.db.in21
-rw-r--r--bin/tests/system/rootkeysentinel/ns2/named.conf.in32
-rw-r--r--bin/tests/system/rootkeysentinel/ns2/sign.sh40
-rw-r--r--bin/tests/system/rootkeysentinel/ns3/hint.db13
-rw-r--r--bin/tests/system/rootkeysentinel/ns3/named.conf.in33
-rw-r--r--bin/tests/system/rootkeysentinel/ns4/hint.db13
-rw-r--r--bin/tests/system/rootkeysentinel/ns4/named.conf.in33
-rw-r--r--bin/tests/system/rootkeysentinel/setup.sh22
-rw-r--r--bin/tests/system/rootkeysentinel/tests.sh295
-rw-r--r--bin/tests/system/rootkeysentinel/tests_sh_rootkeysentinel.py14
-rw-r--r--bin/tests/system/rpz/README36
-rw-r--r--bin/tests/system/rpz/clean.sh57
-rw-r--r--bin/tests/system/rpz/dnsrps.c172
-rw-r--r--bin/tests/system/rpz/dnsrpzd-license.conf23
-rw-r--r--bin/tests/system/rpz/dnsrpzd.conf.in62
-rw-r--r--bin/tests/system/rpz/ns1/named.conf.in37
-rw-r--r--bin/tests/system/rpz/ns1/root.db42
-rw-r--r--bin/tests/system/rpz/ns10/hints13
-rw-r--r--bin/tests/system/rpz/ns10/named.conf.in42
-rw-r--r--bin/tests/system/rpz/ns10/stub.db21
-rw-r--r--bin/tests/system/rpz/ns2/base-tld2s.db26
-rw-r--r--bin/tests/system/rpz/ns2/bl.tld2.db.in21
-rw-r--r--bin/tests/system/rpz/ns2/blv2.tld2.db.in19
-rw-r--r--bin/tests/system/rpz/ns2/blv3.tld2.db.in21
-rw-r--r--bin/tests/system/rpz/ns2/hints13
-rw-r--r--bin/tests/system/rpz/ns2/named.conf.in55
-rw-r--r--bin/tests/system/rpz/ns2/stub.db20
-rw-r--r--bin/tests/system/rpz/ns2/tld2.db125
-rw-r--r--bin/tests/system/rpz/ns3/base.db24
-rw-r--r--bin/tests/system/rpz/ns3/broken.db.in18
-rw-r--r--bin/tests/system/rpz/ns3/crash118
-rw-r--r--bin/tests/system/rpz/ns3/crash224
-rw-r--r--bin/tests/system/rpz/ns3/hints13
-rw-r--r--bin/tests/system/rpz/ns3/manual-update-rpz-2.db.in22
-rw-r--r--bin/tests/system/rpz/ns3/manual-update-rpz.db.in21
-rw-r--r--bin/tests/system/rpz/ns3/mixed-case-rpz-1.db.in16
-rw-r--r--bin/tests/system/rpz/ns3/mixed-case-rpz-2.db.in17
-rw-r--r--bin/tests/system/rpz/ns3/named.conf.in160
-rw-r--r--bin/tests/system/rpz/ns4/hints13
-rw-r--r--bin/tests/system/rpz/ns4/named.conf.in45
-rw-r--r--bin/tests/system/rpz/ns4/tld4.db66
-rw-r--r--bin/tests/system/rpz/ns5/empty.db.in14
-rw-r--r--bin/tests/system/rpz/ns5/expire.conf.in19
-rw-r--r--bin/tests/system/rpz/ns5/fast-expire.db.in18
-rw-r--r--bin/tests/system/rpz/ns5/hints13
-rw-r--r--bin/tests/system/rpz/ns5/named.args2
-rw-r--r--bin/tests/system/rpz/ns5/named.conf.in91
-rw-r--r--bin/tests/system/rpz/ns5/tld5.db32
-rw-r--r--bin/tests/system/rpz/ns6/bl.tld2s.db.in20
-rw-r--r--bin/tests/system/rpz/ns6/hints13
-rw-r--r--bin/tests/system/rpz/ns6/named.conf.in67
-rw-r--r--bin/tests/system/rpz/ns7/hints13
-rw-r--r--bin/tests/system/rpz/ns7/named.conf.in59
-rw-r--r--bin/tests/system/rpz/ns8/hints13
-rw-r--r--bin/tests/system/rpz/ns8/manual-update-rpz.db.in21
-rw-r--r--bin/tests/system/rpz/ns8/named.conf.in66
-rw-r--r--bin/tests/system/rpz/ns9/hints13
-rw-r--r--bin/tests/system/rpz/ns9/named.conf.in60
-rw-r--r--bin/tests/system/rpz/ns9/rpz.db16
-rw-r--r--bin/tests/system/rpz/qperf.sh22
-rw-r--r--bin/tests/system/rpz/setup.sh179
-rw-r--r--bin/tests/system/rpz/test199
-rw-r--r--bin/tests/system/rpz/test277
-rw-r--r--bin/tests/system/rpz/test347
-rw-r--r--bin/tests/system/rpz/test436
-rw-r--r--bin/tests/system/rpz/test4a27
-rw-r--r--bin/tests/system/rpz/test560
-rw-r--r--bin/tests/system/rpz/test637
-rw-r--r--bin/tests/system/rpz/tests.sh1020
-rw-r--r--bin/tests/system/rpz/tests_sh_rpz.py14
-rw-r--r--bin/tests/system/rpzextra/clean.sh21
-rw-r--r--bin/tests/system/rpzextra/ns2/allowed.db18
-rw-r--r--bin/tests/system/rpzextra/ns2/baddomain.db27
-rw-r--r--bin/tests/system/rpzextra/ns2/gooddomain.db27
-rw-r--r--bin/tests/system/rpzextra/ns2/named.conf.in57
-rw-r--r--bin/tests/system/rpzextra/ns2/rpz-external.local.db26
-rw-r--r--bin/tests/system/rpzextra/ns3/external-rpz.local.db29
-rw-r--r--bin/tests/system/rpzextra/ns3/first-rpz.local.db29
-rw-r--r--bin/tests/system/rpzextra/ns3/fourth-rpz-extra.local.db32
-rw-r--r--bin/tests/system/rpzextra/ns3/named.args1
-rw-r--r--bin/tests/system/rpzextra/ns3/named.conf.in147
-rw-r--r--bin/tests/system/rpzextra/ns3/root.db30
-rw-r--r--bin/tests/system/rpzextra/ns3/third-rpz-extra.local.db26
-rw-r--r--bin/tests/system/rpzextra/setup.sh21
-rw-r--r--bin/tests/system/rpzextra/tests_rpzextra.py143
-rw-r--r--bin/tests/system/rpzrecurse/README124
-rw-r--r--bin/tests/system/rpzrecurse/ans5/ans.pl81
-rw-r--r--bin/tests/system/rpzrecurse/clean.sh34
-rw-r--r--bin/tests/system/rpzrecurse/ns1/db.l017
-rw-r--r--bin/tests/system/rpzrecurse/ns1/db.l1.l017
-rw-r--r--bin/tests/system/rpzrecurse/ns1/example.com.db18
-rw-r--r--bin/tests/system/rpzrecurse/ns1/example.db16
-rw-r--r--bin/tests/system/rpzrecurse/ns1/named.conf.in75
-rw-r--r--bin/tests/system/rpzrecurse/ns1/root.db24
-rw-r--r--bin/tests/system/rpzrecurse/ns1/test1.example.net.db17
-rw-r--r--bin/tests/system/rpzrecurse/ns1/test2.example.net.db17
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.clientip117
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.clientip216
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.clientip2117
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.given21
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.invalidprefixlength16
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.log116
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.log217
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.log318
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.passthru20
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.wildcard117
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.wildcard2a17
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.wildcard2b17
-rw-r--r--bin/tests/system/rpzrecurse/ns2/db.wildcard316
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.clientip.conf37
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.clientip2.conf37
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.conf.header.in41
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.default.conf25
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.invalidprefixlength.conf30
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.log.conf39
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.max.conf161
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.wildcard1.conf35
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.wildcard2.conf37
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.wildcard3.conf35
-rw-r--r--bin/tests/system/rpzrecurse/ns2/named.wildcard4.conf37
-rw-r--r--bin/tests/system/rpzrecurse/ns2/root.hint14
-rw-r--r--bin/tests/system/rpzrecurse/ns3/example.db17
-rw-r--r--bin/tests/system/rpzrecurse/ns3/named1.conf.in43
-rw-r--r--bin/tests/system/rpzrecurse/ns3/named2.conf.in42
-rw-r--r--bin/tests/system/rpzrecurse/ns3/named3.conf.in40
-rw-r--r--bin/tests/system/rpzrecurse/ns3/policy.db15
-rw-r--r--bin/tests/system/rpzrecurse/ns3/root.db17
-rw-r--r--bin/tests/system/rpzrecurse/ns4/child.example.db18
-rw-r--r--bin/tests/system/rpzrecurse/ns4/named.conf.in38
-rw-r--r--bin/tests/system/rpzrecurse/setup.sh87
-rwxr-xr-xbin/tests/system/rpzrecurse/testgen.pl343
-rw-r--r--bin/tests/system/rpzrecurse/tests.sh563
-rw-r--r--bin/tests/system/rpzrecurse/tests_sh_rpzrecurse.py14
-rw-r--r--bin/tests/system/rrchecker/classlist.good3
-rw-r--r--bin/tests/system/rrchecker/clean.sh15
-rw-r--r--bin/tests/system/rrchecker/privatelist.good0
-rw-r--r--bin/tests/system/rrchecker/tests.sh85
-rw-r--r--bin/tests/system/rrchecker/tests_sh_rrchecker.py14
-rw-r--r--bin/tests/system/rrchecker/typelist.good81
-rw-r--r--bin/tests/system/rrl/broken.conf.in47
-rw-r--r--bin/tests/system/rrl/clean.sh23
-rw-r--r--bin/tests/system/rrl/ns1/named.conf.in28
-rw-r--r--bin/tests/system/rrl/ns1/root.db27
-rw-r--r--bin/tests/system/rrl/ns2/hints13
-rw-r--r--bin/tests/system/rrl/ns2/named.conf.in65
-rw-r--r--bin/tests/system/rrl/ns2/tld2.db42
-rw-r--r--bin/tests/system/rrl/ns3/hints13
-rw-r--r--bin/tests/system/rrl/ns3/named.conf.in48
-rw-r--r--bin/tests/system/rrl/ns3/tld3.db20
-rw-r--r--bin/tests/system/rrl/ns4/hints13
-rw-r--r--bin/tests/system/rrl/ns4/named.conf.in67
-rw-r--r--bin/tests/system/rrl/ns4/tld4.db45
-rw-r--r--bin/tests/system/rrl/setup.sh22
-rw-r--r--bin/tests/system/rrl/tests.sh290
-rw-r--r--bin/tests/system/rrl/tests_sh_rrl.py18
-rw-r--r--bin/tests/system/rrsetorder/clean.sh23
-rw-r--r--bin/tests/system/rrsetorder/ns1/named.conf.in40
-rw-r--r--bin/tests/system/rrsetorder/ns1/root.db51
-rw-r--r--bin/tests/system/rrsetorder/ns2/named.conf.in39
-rw-r--r--bin/tests/system/rrsetorder/ns3/named.conf.in38
-rw-r--r--bin/tests/system/rrsetorder/ns4/named.conf.in34
-rw-r--r--bin/tests/system/rrsetorder/ns5/named.conf.in30
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.fixed.good4
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good14
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good104
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good114
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good124
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good134
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good144
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good154
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good164
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good174
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good184
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good194
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good24
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good204
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good214
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good224
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good234
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good244
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good34
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good44
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good54
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good64
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good74
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good84
-rw-r--r--bin/tests/system/rrsetorder/reference.dig.out.random.good94
-rw-r--r--bin/tests/system/rrsetorder/setup.sh21
-rw-r--r--bin/tests/system/rrsetorder/tests.sh558
-rw-r--r--bin/tests/system/rrsetorder/tests_sh_rrsetorder.py14
-rw-r--r--bin/tests/system/rsabigexponent/README.md39
-rw-r--r--bin/tests/system/rsabigexponent/bigkey.c157
-rw-r--r--bin/tests/system/rsabigexponent/clean.sh23
-rw-r--r--bin/tests/system/rsabigexponent/conf/bad01.conf16
-rw-r--r--bin/tests/system/rsabigexponent/conf/bad02.conf16
-rw-r--r--bin/tests/system/rsabigexponent/conf/bad03.conf16
-rw-r--r--bin/tests/system/rsabigexponent/conf/good01.conf16
-rw-r--r--bin/tests/system/rsabigexponent/conf/good02.conf16
-rw-r--r--bin/tests/system/rsabigexponent/conf/good03.conf16
-rw-r--r--bin/tests/system/rsabigexponent/ns1/named.conf.in34
-rw-r--r--bin/tests/system/rsabigexponent/ns1/root.db.in24
-rwxr-xr-xbin/tests/system/rsabigexponent/ns1/sign.sh33
-rw-r--r--bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.key5
-rw-r--r--bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.private13
-rw-r--r--bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.key2
-rw-r--r--bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.private10
-rw-r--r--bin/tests/system/rsabigexponent/ns2/dsset-example.in1
-rw-r--r--bin/tests/system/rsabigexponent/ns2/example.db.bad156
-rw-r--r--bin/tests/system/rsabigexponent/ns2/example.db.in23
-rw-r--r--bin/tests/system/rsabigexponent/ns2/named.conf.in39
-rwxr-xr-xbin/tests/system/rsabigexponent/ns2/sign.sh28
-rw-r--r--bin/tests/system/rsabigexponent/ns3/named.conf.in35
-rw-r--r--bin/tests/system/rsabigexponent/setup.sh20
-rw-r--r--bin/tests/system/rsabigexponent/tests.sh58
-rw-r--r--bin/tests/system/rsabigexponent/tests_sh_rsabigexponent.py14
-rw-r--r--bin/tests/system/run.gdb1
-rwxr-xr-xbin/tests/system/run.sh27
-rwxr-xr-xbin/tests/system/runall.sh99
-rwxr-xr-xbin/tests/system/runsequential.sh26
-rw-r--r--bin/tests/system/runtime/README13
-rw-r--r--bin/tests/system/runtime/clean.sh25
-rw-r--r--bin/tests/system/runtime/ctrl-chars1
-rw-r--r--bin/tests/system/runtime/long-cmd-line1
-rw-r--r--bin/tests/system/runtime/ns2/named-alt1.conf.in25
-rw-r--r--bin/tests/system/runtime/ns2/named-alt2.conf.in25
-rw-r--r--bin/tests/system/runtime/ns2/named-alt3.conf.in26
-rw-r--r--bin/tests/system/runtime/ns2/named-alt4.conf.in22
-rw-r--r--bin/tests/system/runtime/ns2/named-alt5.conf.in22
-rw-r--r--bin/tests/system/runtime/ns2/named-alt6.conf.in22
-rw-r--r--bin/tests/system/runtime/ns2/named-alt7.conf.in20
-rw-r--r--bin/tests/system/runtime/ns2/named-alt9.conf.in21
-rw-r--r--bin/tests/system/runtime/ns2/named1.conf.in34
-rw-r--r--bin/tests/system/runtime/setup.sh29
-rw-r--r--bin/tests/system/runtime/tests.sh252
-rw-r--r--bin/tests/system/runtime/tests_sh_runtime.py14
-rw-r--r--bin/tests/system/send.pl33
-rw-r--r--bin/tests/system/serve-stale/ans2/ans.pl331
-rw-r--r--bin/tests/system/serve-stale/clean.sh22
-rw-r--r--bin/tests/system/serve-stale/ns1/named1.conf.in44
-rw-r--r--bin/tests/system/serve-stale/ns1/named2.conf.in44
-rw-r--r--bin/tests/system/serve-stale/ns1/named3.conf.in43
-rw-r--r--bin/tests/system/serve-stale/ns1/named4.conf.in49
-rw-r--r--bin/tests/system/serve-stale/ns1/root.db18
-rw-r--r--bin/tests/system/serve-stale/ns1/stale.test.db19
-rw-r--r--bin/tests/system/serve-stale/ns3/named1.conf.in41
-rw-r--r--bin/tests/system/serve-stale/ns3/named2.conf.in51
-rw-r--r--bin/tests/system/serve-stale/ns3/named3.conf.in48
-rw-r--r--bin/tests/system/serve-stale/ns3/named4.conf.in50
-rw-r--r--bin/tests/system/serve-stale/ns3/named5.conf.in49
-rw-r--r--bin/tests/system/serve-stale/ns3/named6.conf.in46
-rw-r--r--bin/tests/system/serve-stale/ns3/named7.conf.in55
-rw-r--r--bin/tests/system/serve-stale/ns3/named8.conf.in47
-rw-r--r--bin/tests/system/serve-stale/ns3/root.db13
-rw-r--r--bin/tests/system/serve-stale/ns4/named.conf.in42
-rw-r--r--bin/tests/system/serve-stale/ns5/named.conf.in43
-rw-r--r--bin/tests/system/serve-stale/setup.sh21
-rwxr-xr-xbin/tests/system/serve-stale/tests.sh2705
-rw-r--r--bin/tests/system/serve-stale/tests_sh_serve_stale.py14
-rw-r--r--bin/tests/system/setup.sh33
-rw-r--r--bin/tests/system/sfcache/README19
-rw-r--r--bin/tests/system/sfcache/clean.sh27
-rw-r--r--bin/tests/system/sfcache/ns1/named.conf.in34
-rw-r--r--bin/tests/system/sfcache/ns1/root.db.in26
-rw-r--r--bin/tests/system/sfcache/ns1/sign.sh38
-rw-r--r--bin/tests/system/sfcache/ns2/example.db.in103
-rw-r--r--bin/tests/system/sfcache/ns2/named.conf.in49
-rw-r--r--bin/tests/system/sfcache/ns2/sign.sh28
-rw-r--r--bin/tests/system/sfcache/ns5/named.conf.in43
-rw-r--r--bin/tests/system/sfcache/ns5/sign.sh21
-rw-r--r--bin/tests/system/sfcache/setup.sh24
-rw-r--r--bin/tests/system/sfcache/tests.sh107
-rw-r--r--bin/tests/system/sfcache/tests_sh_sfcache.py14
-rw-r--r--bin/tests/system/shutdown/clean.sh20
-rw-r--r--bin/tests/system/shutdown/ns1/named.conf.in42
-rw-r--r--bin/tests/system/shutdown/ns1/root.db25
-rw-r--r--bin/tests/system/shutdown/ns2/named.conf.in40
-rw-r--r--bin/tests/system/shutdown/ns2/test.db18
-rw-r--r--bin/tests/system/shutdown/resolver/named.conf.in48
-rw-r--r--bin/tests/system/shutdown/resolver/root.db21
-rw-r--r--bin/tests/system/shutdown/setup.sh22
-rwxr-xr-xbin/tests/system/shutdown/tests_shutdown.py206
-rw-r--r--bin/tests/system/smartsign/child.db24
-rw-r--r--bin/tests/system/smartsign/clean.sh15
-rw-r--r--bin/tests/system/smartsign/parent.db31
-rw-r--r--bin/tests/system/smartsign/tests.sh369
-rw-r--r--bin/tests/system/smartsign/tests_sh_smartsign.py14
-rw-r--r--bin/tests/system/sortlist/clean.sh19
-rw-r--r--bin/tests/system/sortlist/ns1/example.db37
-rw-r--r--bin/tests/system/sortlist/ns1/named.conf.in46
-rw-r--r--bin/tests/system/sortlist/ns1/root.db24
-rw-r--r--bin/tests/system/sortlist/setup.sh16
-rw-r--r--bin/tests/system/sortlist/tests.sh52
-rw-r--r--bin/tests/system/sortlist/tests_sh_sortlist.py14
-rw-r--r--bin/tests/system/spf/clean.sh18
-rw-r--r--bin/tests/system/spf/ns1/named.conf.in43
-rw-r--r--bin/tests/system/spf/ns1/spf.db18
-rw-r--r--bin/tests/system/spf/setup.sh16
-rw-r--r--bin/tests/system/spf/tests.sh47
-rw-r--r--bin/tests/system/spf/tests_sh_spf.py14
-rwxr-xr-xbin/tests/system/start.pl452
-rw-r--r--bin/tests/system/start.sh.in20
-rwxr-xr-xbin/tests/system/staticstub/clean.sh28
-rw-r--r--bin/tests/system/staticstub/conf/bad01.conf32
-rw-r--r--bin/tests/system/staticstub/conf/bad02.conf32
-rw-r--r--bin/tests/system/staticstub/conf/bad03.conf32
-rw-r--r--bin/tests/system/staticstub/conf/bad04.conf32
-rw-r--r--bin/tests/system/staticstub/conf/bad05.conf33
-rw-r--r--bin/tests/system/staticstub/conf/bad06.conf33
-rw-r--r--bin/tests/system/staticstub/conf/bad07.conf33
-rw-r--r--bin/tests/system/staticstub/conf/bad08.conf33
-rw-r--r--bin/tests/system/staticstub/conf/bad09.conf32
-rw-r--r--bin/tests/system/staticstub/conf/bad10.conf34
-rw-r--r--bin/tests/system/staticstub/conf/bad11.conf34
-rw-r--r--bin/tests/system/staticstub/conf/good01.conf33
-rw-r--r--bin/tests/system/staticstub/conf/good02.conf32
-rw-r--r--bin/tests/system/staticstub/conf/good03.conf32
-rw-r--r--bin/tests/system/staticstub/conf/good04.conf32
-rw-r--r--bin/tests/system/staticstub/conf/good05.conf33
-rw-r--r--bin/tests/system/staticstub/knowngood.dig.out.rec18
-rw-r--r--bin/tests/system/staticstub/ns1/named.conf.in25
-rw-r--r--bin/tests/system/staticstub/ns1/root.db19
-rw-r--r--bin/tests/system/staticstub/ns2/named.conf.in62
-rw-r--r--bin/tests/system/staticstub/ns3/example.db.in32
-rw-r--r--bin/tests/system/staticstub/ns3/example.org.db24
-rw-r--r--bin/tests/system/staticstub/ns3/named.conf.in46
-rwxr-xr-xbin/tests/system/staticstub/ns3/sign.sh43
-rw-r--r--bin/tests/system/staticstub/ns3/undelegated.db.in23
-rw-r--r--bin/tests/system/staticstub/ns4/example.com.db23
-rw-r--r--bin/tests/system/staticstub/ns4/example.info.db24
-rw-r--r--bin/tests/system/staticstub/ns4/example.org.db25
-rw-r--r--bin/tests/system/staticstub/ns4/named.conf.in45
-rwxr-xr-xbin/tests/system/staticstub/ns4/sign.sh25
-rw-r--r--bin/tests/system/staticstub/ns4/sub.example.db.in26
-rwxr-xr-xbin/tests/system/staticstub/setup.sh25
-rwxr-xr-xbin/tests/system/staticstub/tests.sh219
-rw-r--r--bin/tests/system/staticstub/tests_sh_staticstub.py14
-rw-r--r--bin/tests/system/statistics/ans4/ans.pl118
-rw-r--r--bin/tests/system/statistics/clean.sh32
-rw-r--r--bin/tests/system/statistics/ns1/named.conf.in44
-rw-r--r--bin/tests/system/statistics/ns1/root.db24
-rw-r--r--bin/tests/system/statistics/ns1/zone.db14
-rw-r--r--bin/tests/system/statistics/ns2/example.db28
-rw-r--r--bin/tests/system/statistics/ns2/internal.db30
-rw-r--r--bin/tests/system/statistics/ns2/named.conf.in50
-rw-r--r--bin/tests/system/statistics/ns2/named2.conf.in51
-rw-r--r--bin/tests/system/statistics/ns3/internal.db28
-rw-r--r--bin/tests/system/statistics/ns3/named.conf.in58
-rw-r--r--bin/tests/system/statistics/ns3/root.hint21
-rw-r--r--bin/tests/system/statistics/setup.sh18
-rw-r--r--bin/tests/system/statistics/tests.sh282
-rw-r--r--bin/tests/system/statistics/tests_sh_statistics.py14
-rw-r--r--bin/tests/system/statschannel/clean.sh35
-rw-r--r--bin/tests/system/statschannel/conftest.py25
-rw-r--r--bin/tests/system/statschannel/fetch.pl43
-rw-r--r--bin/tests/system/statschannel/generic.py108
-rw-r--r--bin/tests/system/statschannel/generic_dnspython.py128
-rw-r--r--bin/tests/system/statschannel/mem-xml.pl21
-rw-r--r--bin/tests/system/statschannel/ns1/example.db49
-rw-r--r--bin/tests/system/statschannel/ns1/named.conf.in44
-rw-r--r--bin/tests/system/statschannel/ns2/dnssec.db.in28
-rw-r--r--bin/tests/system/statschannel/ns2/example.db49
-rw-r--r--bin/tests/system/statschannel/ns2/manykeys.db.in28
-rw-r--r--bin/tests/system/statschannel/ns2/named.conf.in73
-rw-r--r--bin/tests/system/statschannel/ns2/named2.conf.in69
-rw-r--r--bin/tests/system/statschannel/ns2/sign.sh45
-rw-r--r--bin/tests/system/statschannel/ns3/named.conf.in44
-rw-r--r--bin/tests/system/statschannel/server-json.pl35
-rw-r--r--bin/tests/system/statschannel/server-xml.pl25
-rw-r--r--bin/tests/system/statschannel/setup.sh21
-rw-r--r--bin/tests/system/statschannel/tests.sh656
-rwxr-xr-xbin/tests/system/statschannel/tests_json.py105
-rw-r--r--bin/tests/system/statschannel/tests_sh_statschannel.py14
-rwxr-xr-xbin/tests/system/statschannel/tests_xml.py135
-rw-r--r--bin/tests/system/statschannel/traffic-json.pl49
-rw-r--r--bin/tests/system/statschannel/traffic-xml.pl46
-rw-r--r--bin/tests/system/statschannel/traffic.expect.12
-rw-r--r--bin/tests/system/statschannel/traffic.expect.24
-rw-r--r--bin/tests/system/statschannel/traffic.expect.45
-rw-r--r--bin/tests/system/statschannel/traffic.expect.57
-rw-r--r--bin/tests/system/statschannel/traffic.expect.68
-rw-r--r--bin/tests/system/statschannel/zones-json.pl37
-rw-r--r--bin/tests/system/statschannel/zones-xml.pl40
-rw-r--r--bin/tests/system/stop.pl281
-rw-r--r--bin/tests/system/stop.sh.in22
-rw-r--r--bin/tests/system/stopall.sh23
-rw-r--r--bin/tests/system/stress/clean.sh22
-rw-r--r--bin/tests/system/stress/ns2/named.conf.in57
-rw-r--r--bin/tests/system/stress/ns2/zone.template.db21
-rw-r--r--bin/tests/system/stress/ns3/named.conf.in74
-rw-r--r--bin/tests/system/stress/ns4/named.conf.in57
-rw-r--r--bin/tests/system/stress/setup.sh25
-rw-r--r--bin/tests/system/stress/tests_stress_update.py79
-rw-r--r--bin/tests/system/stub/clean.sh23
-rw-r--r--bin/tests/system/stub/knowngood.dig.out.norec21
-rw-r--r--bin/tests/system/stub/knowngood.dig.out.rec18
-rw-r--r--bin/tests/system/stub/ns1/named.conf.in31
-rw-r--r--bin/tests/system/stub/ns1/root.db24
-rw-r--r--bin/tests/system/stub/ns2/child.example.db22
-rw-r--r--bin/tests/system/stub/ns2/named.conf.in36
-rw-r--r--bin/tests/system/stub/ns3/example.db22
-rw-r--r--bin/tests/system/stub/ns3/named.conf.in42
-rw-r--r--bin/tests/system/stub/ns4/example.db23
-rw-r--r--bin/tests/system/stub/ns4/named.conf.in31
-rw-r--r--bin/tests/system/stub/ns5/named.conf.in34
-rw-r--r--bin/tests/system/stub/setup.sh20
-rw-r--r--bin/tests/system/stub/tests.sh88
-rw-r--r--bin/tests/system/stub/tests_sh_stub.py14
-rw-r--r--bin/tests/system/synthfromdnssec/clean.sh50
-rw-r--r--bin/tests/system/synthfromdnssec/ns1/dnamed.db.in17
-rw-r--r--bin/tests/system/synthfromdnssec/ns1/example.db.in25
-rw-r--r--bin/tests/system/synthfromdnssec/ns1/minimal.db.in46
-rw-r--r--bin/tests/system/synthfromdnssec/ns1/named.conf.in72
-rw-r--r--bin/tests/system/synthfromdnssec/ns1/root.db.in24
-rw-r--r--bin/tests/system/synthfromdnssec/ns1/sign.sh76
-rw-r--r--bin/tests/system/synthfromdnssec/ns1/soa-without-dnskey.db.in23
-rw-r--r--bin/tests/system/synthfromdnssec/ns2/example.internal.db16
-rw-r--r--bin/tests/system/synthfromdnssec/ns2/named.conf.in57
-rw-r--r--bin/tests/system/synthfromdnssec/ns2/root.hints13
-rw-r--r--bin/tests/system/synthfromdnssec/ns3/named.conf.in52
-rw-r--r--bin/tests/system/synthfromdnssec/ns3/redirect.db20
-rw-r--r--bin/tests/system/synthfromdnssec/ns3/root.hints13
-rw-r--r--bin/tests/system/synthfromdnssec/ns4/named.conf.in48
-rw-r--r--bin/tests/system/synthfromdnssec/ns4/root.hints13
-rw-r--r--bin/tests/system/synthfromdnssec/ns5/internal2.db17
-rw-r--r--bin/tests/system/synthfromdnssec/ns5/named.conf.in60
-rw-r--r--bin/tests/system/synthfromdnssec/ns5/root.hints13
-rw-r--r--bin/tests/system/synthfromdnssec/ns6/named.conf.in48
-rw-r--r--bin/tests/system/synthfromdnssec/ns6/root.hints13
-rw-r--r--bin/tests/system/synthfromdnssec/setup.sh29
-rw-r--r--bin/tests/system/synthfromdnssec/tests.sh904
-rw-r--r--bin/tests/system/synthfromdnssec/tests_sh_synthfromdnssec.py14
-rw-r--r--bin/tests/system/tcp/1996-alloc_dnsbuf-crash-test.pkt12
-rw-r--r--bin/tests/system/tcp/ans6/ans.py157
-rw-r--r--bin/tests/system/tcp/clean.sh22
-rw-r--r--bin/tests/system/tcp/ns1/named.conf.in40
-rw-r--r--bin/tests/system/tcp/ns1/root.db24
-rw-r--r--bin/tests/system/tcp/ns2/example.db28
-rw-r--r--bin/tests/system/tcp/ns2/named.conf.in47
-rw-r--r--bin/tests/system/tcp/ns3/named.conf.in42
-rw-r--r--bin/tests/system/tcp/ns4/named.conf.in44
-rw-r--r--bin/tests/system/tcp/ns5/named.conf.in45
-rw-r--r--bin/tests/system/tcp/ns7/named.conf.in42
-rw-r--r--bin/tests/system/tcp/ns7/named.dropedns1
-rw-r--r--bin/tests/system/tcp/ns7/root.db24
-rw-r--r--bin/tests/system/tcp/setup.sh23
-rw-r--r--bin/tests/system/tcp/tests.sh203
-rw-r--r--bin/tests/system/tcp/tests_sh_tcp.py14
-rw-r--r--bin/tests/system/tcp/tests_tcp.py116
-rwxr-xr-xbin/tests/system/testcrypto.sh95
-rwxr-xr-xbin/tests/system/testsock.pl55
-rw-r--r--bin/tests/system/testsock6.pl25
-rw-r--r--bin/tests/system/testsummary.sh91
-rw-r--r--bin/tests/system/timeouts/clean.sh21
-rw-r--r--bin/tests/system/timeouts/ns1/example.db25
-rw-r--r--bin/tests/system/timeouts/ns1/named.args1
-rw-r--r--bin/tests/system/timeouts/ns1/named.conf.in47
-rw-r--r--bin/tests/system/timeouts/ns1/root.db24
-rw-r--r--bin/tests/system/timeouts/prereq.sh30
-rw-r--r--bin/tests/system/timeouts/setup.sh30
-rw-r--r--bin/tests/system/timeouts/tests_tcp_timeouts.py279
-rw-r--r--bin/tests/system/tkey/clean.sh26
-rw-r--r--bin/tests/system/tkey/keycreate.c278
-rw-r--r--bin/tests/system/tkey/keydelete.c221
-rw-r--r--bin/tests/system/tkey/ns1/example.db27
-rw-r--r--bin/tests/system/tkey/ns1/named.conf.in50
-rw-r--r--bin/tests/system/tkey/ns1/setup.sh20
-rw-r--r--bin/tests/system/tkey/setup.sh20
-rw-r--r--bin/tests/system/tkey/tests.sh163
-rw-r--r--bin/tests/system/tkey/tests_sh_tkey.py14
-rw-r--r--bin/tests/system/tools/clean.sh17
-rw-r--r--bin/tests/system/tools/setup.sh17
-rw-r--r--bin/tests/system/tools/tests.sh107
-rw-r--r--bin/tests/system/tools/tests_sh_tools.py14
-rw-r--r--bin/tests/system/transport-acl/clean.sh24
-rw-r--r--bin/tests/system/transport-acl/ns1/named.conf.in129
-rw-r--r--bin/tests/system/transport-acl/self-signed-cert.pem28
-rw-r--r--bin/tests/system/transport-acl/self-signed-key.pem40
-rw-r--r--bin/tests/system/transport-acl/setup.sh21
-rw-r--r--bin/tests/system/transport-acl/tests.sh124
-rw-r--r--bin/tests/system/transport-acl/tests_sh_transport_acl.py14
-rw-r--r--bin/tests/system/tsig/ans2/ans.pl52
-rw-r--r--bin/tests/system/tsig/badlocation37
-rw-r--r--bin/tests/system/tsig/badtime37
-rw-r--r--bin/tests/system/tsig/clean.sh26
-rw-r--r--bin/tests/system/tsig/ns1/example.db163
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-md5-legacy.+157+22023.key1
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-md5-legacy.+157+22023.private7
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-sha1-legacy.+161+50591.key1
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-sha1-legacy.+161+50591.private7
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-sha224-legacy.+162+50865.key1
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-sha224-legacy.+162+50865.private7
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-sha256-legacy.+163+38999.key1
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-sha256-legacy.+163+38999.private7
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-sha384-legacy.+164+56610.key1
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-sha384-legacy.+164+56610.private7
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-sha512-legacy.+165+22767.key1
-rw-r--r--bin/tests/system/tsig/ns1/legacy/Khmac-sha512-legacy.+165+22767.private7
-rw-r--r--bin/tests/system/tsig/ns1/named.conf.in120
-rw-r--r--bin/tests/system/tsig/setup.sh39
-rw-r--r--bin/tests/system/tsig/tests.sh322
-rw-r--r--bin/tests/system/tsig/tests_sh_tsig.py14
-rw-r--r--bin/tests/system/tsiggss/authsock.pl91
-rw-r--r--bin/tests/system/tsiggss/clean.sh28
-rw-r--r--bin/tests/system/tsiggss/ns1/administrator.ccachebin0 -> 2315 bytes
-rw-r--r--bin/tests/system/tsiggss/ns1/dns.keytabbin0 -> 1087 bytes
-rw-r--r--bin/tests/system/tsiggss/ns1/example.nil.db.in62
-rw-r--r--bin/tests/system/tsiggss/ns1/named.conf.in50
-rw-r--r--bin/tests/system/tsiggss/ns1/testdenied.ccachebin0 -> 2188 bytes
-rw-r--r--bin/tests/system/tsiggss/prereq.sh22
-rw-r--r--bin/tests/system/tsiggss/setup.sh21
-rw-r--r--bin/tests/system/tsiggss/tests.sh178
-rwxr-xr-xbin/tests/system/tsiggss/tests_isc_spnego_flaws.py219
-rw-r--r--bin/tests/system/tsiggss/tests_sh_tsiggss.py14
-rw-r--r--bin/tests/system/ttl/clean.sh17
-rw-r--r--bin/tests/system/ttl/ns1/max-example.db20
-rw-r--r--bin/tests/system/ttl/ns1/min-example.db20
-rw-r--r--bin/tests/system/ttl/ns1/named.conf.in49
-rw-r--r--bin/tests/system/ttl/ns2/hints.db13
-rw-r--r--bin/tests/system/ttl/ns2/named.conf.in42
-rw-r--r--bin/tests/system/ttl/setup.sh17
-rw-r--r--bin/tests/system/ttl/tests_cache_ttl.py32
-rw-r--r--bin/tests/system/unknown/clean.sh22
-rw-r--r--bin/tests/system/unknown/large.out1
-rw-r--r--bin/tests/system/unknown/ns1/broken1.db23
-rw-r--r--bin/tests/system/unknown/ns1/broken2.db23
-rw-r--r--bin/tests/system/unknown/ns1/broken3.db23
-rw-r--r--bin/tests/system/unknown/ns1/broken4.db23
-rw-r--r--bin/tests/system/unknown/ns1/broken5.db23
-rw-r--r--bin/tests/system/unknown/ns1/class10.hints13
-rw-r--r--bin/tests/system/unknown/ns1/example-class10.db31
-rw-r--r--bin/tests/system/unknown/ns1/example-in.db56
-rw-r--r--bin/tests/system/unknown/ns1/large.db3011
-rw-r--r--bin/tests/system/unknown/ns1/named.conf.in69
-rw-r--r--bin/tests/system/unknown/ns2/named.conf.in33
-rw-r--r--bin/tests/system/unknown/ns3/named.conf.in35
-rw-r--r--bin/tests/system/unknown/ns3/sign.sh20
-rw-r--r--bin/tests/system/unknown/setup.sh20
-rw-r--r--bin/tests/system/unknown/tests.sh235
-rw-r--r--bin/tests/system/unknown/tests_sh_unknown.py14
-rw-r--r--bin/tests/system/unknown/zones/nan.bad12
-rw-r--r--bin/tests/system/upforwd/ans4/ans.pl363
-rw-r--r--bin/tests/system/upforwd/clean.sh35
-rw-r--r--bin/tests/system/upforwd/knowngood.after110
-rw-r--r--bin/tests/system/upforwd/knowngood.after211
-rw-r--r--bin/tests/system/upforwd/knowngood.before8
-rw-r--r--bin/tests/system/upforwd/knowngood.ns2.before6
-rw-r--r--bin/tests/system/upforwd/ns1/example1.db18
-rw-r--r--bin/tests/system/upforwd/ns1/named.conf.in42
-rw-r--r--bin/tests/system/upforwd/ns2/named.conf.in37
-rw-r--r--bin/tests/system/upforwd/ns3/named1.conf.in64
-rw-r--r--bin/tests/system/upforwd/ns3/named2.conf.in44
-rw-r--r--bin/tests/system/upforwd/ns3/noprimary.db14
-rw-r--r--bin/tests/system/upforwd/setup.sh47
-rw-r--r--bin/tests/system/upforwd/tests.sh295
-rw-r--r--bin/tests/system/upforwd/tests_sh_upforwd.py14
-rw-r--r--bin/tests/system/verify/clean.sh21
-rw-r--r--bin/tests/system/verify/setup.sh16
-rw-r--r--bin/tests/system/verify/tests.sh113
-rw-r--r--bin/tests/system/verify/tests_sh_verify.py14
-rw-r--r--bin/tests/system/verify/zones/genzones.sh247
-rw-r--r--bin/tests/system/verify/zones/unsigned.db29
-rw-r--r--bin/tests/system/views/clean.sh38
-rw-r--r--bin/tests/system/views/ns1/named.conf.in30
-rw-r--r--bin/tests/system/views/ns1/root.db24
-rw-r--r--bin/tests/system/views/ns2/1.10.in-addr.arpa.db13
-rw-r--r--bin/tests/system/views/ns2/clone.db25
-rw-r--r--bin/tests/system/views/ns2/example1.db28
-rw-r--r--bin/tests/system/views/ns2/example2.db28
-rw-r--r--bin/tests/system/views/ns2/external/inline.db29
-rw-r--r--bin/tests/system/views/ns2/internal.db30
-rw-r--r--bin/tests/system/views/ns2/internal/inline.db29
-rw-r--r--bin/tests/system/views/ns2/named1.conf.in55
-rw-r--r--bin/tests/system/views/ns2/named2.conf.in103
-rw-r--r--bin/tests/system/views/ns2/named3.conf.in36
-rw-r--r--bin/tests/system/views/ns3/child.clone.db22
-rw-r--r--bin/tests/system/views/ns3/internal.db28
-rw-r--r--bin/tests/system/views/ns3/named1.conf.in51
-rw-r--r--bin/tests/system/views/ns3/named2.conf.in51
-rw-r--r--bin/tests/system/views/ns5/child.clone.db22
-rw-r--r--bin/tests/system/views/ns5/named.conf.in45
-rw-r--r--bin/tests/system/views/setup.sh38
-rw-r--r--bin/tests/system/views/tests.sh189
-rw-r--r--bin/tests/system/views/tests_sh_views.py14
-rw-r--r--bin/tests/system/wildcard/clean.sh28
-rw-r--r--bin/tests/system/wildcard/ns1/allwild.db.in15
-rw-r--r--bin/tests/system/wildcard/ns1/dlv.db.in14
-rw-r--r--bin/tests/system/wildcard/ns1/example.db.in25
-rw-r--r--bin/tests/system/wildcard/ns1/named.conf.in43
-rw-r--r--bin/tests/system/wildcard/ns1/nsec.db.in17
-rw-r--r--bin/tests/system/wildcard/ns1/nsec3.db.in17
-rw-r--r--bin/tests/system/wildcard/ns1/private.nsec.db.in16
-rw-r--r--bin/tests/system/wildcard/ns1/private.nsec3.db.in17
-rw-r--r--bin/tests/system/wildcard/ns1/root.db.in17
-rwxr-xr-xbin/tests/system/wildcard/ns1/sign.sh95
-rw-r--r--bin/tests/system/wildcard/ns2/named.conf.in30
-rw-r--r--bin/tests/system/wildcard/ns3/named.conf.in32
-rw-r--r--bin/tests/system/wildcard/ns4/named.conf.in31
-rw-r--r--bin/tests/system/wildcard/ns5/named.conf.in32
-rw-r--r--bin/tests/system/wildcard/setup.sh22
-rw-r--r--bin/tests/system/wildcard/tests.sh282
-rw-r--r--bin/tests/system/wildcard/tests_sh_wildcard.py14
-rwxr-xr-xbin/tests/system/wildcard/tests_wildcard.py112
-rw-r--r--bin/tests/system/xfer/ans5/badkeydata10
-rw-r--r--bin/tests/system/xfer/ans5/badmessageid10
-rw-r--r--bin/tests/system/xfer/ans5/goodaxfr10
-rw-r--r--bin/tests/system/xfer/ans5/partial11
-rw-r--r--bin/tests/system/xfer/ans5/soamismatch10
-rw-r--r--bin/tests/system/xfer/ans5/unknownkey11
-rw-r--r--bin/tests/system/xfer/ans5/unsigned11
-rw-r--r--bin/tests/system/xfer/ans5/wrongkey11
-rw-r--r--bin/tests/system/xfer/ans5/wrongname10
-rw-r--r--bin/tests/system/xfer/axfr-stats.good3
-rw-r--r--bin/tests/system/xfer/clean.sh41
-rw-r--r--bin/tests/system/xfer/dig1.good178
-rw-r--r--bin/tests/system/xfer/dig2.good178
-rw-r--r--bin/tests/system/xfer/dig3.good6
-rw-r--r--bin/tests/system/xfer/knowngood.mapped26
-rw-r--r--bin/tests/system/xfer/ns1/axfr-max-idle-time.db15
-rw-r--r--bin/tests/system/xfer/ns1/axfr-max-transfer-time.db15
-rw-r--r--bin/tests/system/xfer/ns1/axfr-too-big.db15
-rw-r--r--bin/tests/system/xfer/ns1/dot-fallback.db.in19
-rw-r--r--bin/tests/system/xfer/ns1/ixfr-too-big.db.in18
-rw-r--r--bin/tests/system/xfer/ns1/named1.conf.in77
-rw-r--r--bin/tests/system/xfer/ns1/named2.conf.in41
-rw-r--r--bin/tests/system/xfer/ns1/named3.conf.in41
-rw-r--r--bin/tests/system/xfer/ns1/root.db27
-rw-r--r--bin/tests/system/xfer/ns1/xfer-stats.db15
-rw-r--r--bin/tests/system/xfer/ns2/mapped.db.in28
-rw-r--r--bin/tests/system/xfer/ns2/named.conf.in84
-rw-r--r--bin/tests/system/xfer/ns2/sec.db.in19
-rw-r--r--bin/tests/system/xfer/ns3/named.conf.in81
-rw-r--r--bin/tests/system/xfer/ns4/named.conf.base49
-rw-r--r--bin/tests/system/xfer/ns4/root.db.in14
-rw-r--r--bin/tests/system/xfer/ns6/named.args1
-rw-r--r--bin/tests/system/xfer/ns6/named.conf.in85
-rw-r--r--bin/tests/system/xfer/ns7/named.conf.in55
-rw-r--r--bin/tests/system/xfer/ns8/example.db24
-rw-r--r--bin/tests/system/xfer/ns8/named.conf.in47
-rw-r--r--bin/tests/system/xfer/prereq.sh26
-rw-r--r--bin/tests/system/xfer/setup.sh45
-rwxr-xr-xbin/tests/system/xfer/tests.sh627
-rw-r--r--bin/tests/system/xfer/tests_sh_xfer.py14
-rw-r--r--bin/tests/system/xferquota/clean.sh26
-rw-r--r--bin/tests/system/xferquota/ns1/changing1.db27
-rw-r--r--bin/tests/system/xferquota/ns1/changing2.db27
-rw-r--r--bin/tests/system/xferquota/ns1/named.conf.in46
-rw-r--r--bin/tests/system/xferquota/ns1/root.db29
-rw-r--r--bin/tests/system/xferquota/ns2/example.db146
-rw-r--r--bin/tests/system/xferquota/ns2/named.conf.in41
-rw-r--r--bin/tests/system/xferquota/setup.pl40
-rw-r--r--bin/tests/system/xferquota/setup.sh25
-rwxr-xr-xbin/tests/system/xferquota/tests.sh61
-rw-r--r--bin/tests/system/xferquota/tests_sh_xferquota.py14
-rw-r--r--bin/tests/system/zero/ans5/ans.pl81
-rw-r--r--bin/tests/system/zero/clean.sh22
-rw-r--r--bin/tests/system/zero/ns1/named.conf.in29
-rw-r--r--bin/tests/system/zero/ns1/root.db26
-rw-r--r--bin/tests/system/zero/ns2/named.args1
-rw-r--r--bin/tests/system/zero/ns2/named.conf.in34
-rw-r--r--bin/tests/system/zero/ns2/tld.db20
-rw-r--r--bin/tests/system/zero/ns3/named.args1
-rw-r--r--bin/tests/system/zero/ns3/named.conf.in30
-rw-r--r--bin/tests/system/zero/ns3/root.hint13
-rw-r--r--bin/tests/system/zero/ns4/named.args1
-rw-r--r--bin/tests/system/zero/ns4/named.conf.in35
-rw-r--r--bin/tests/system/zero/ns4/one.tld.db17
-rw-r--r--bin/tests/system/zero/setup.sh21
-rw-r--r--bin/tests/system/zero/tests.sh123
-rw-r--r--bin/tests/system/zero/tests_sh_zero.py14
-rw-r--r--bin/tests/system/zonechecks/a.db14
-rw-r--r--bin/tests/system/zonechecks/aaaa.db14
-rw-r--r--bin/tests/system/zonechecks/bigserial.db14
-rw-r--r--bin/tests/system/zonechecks/clean.sh22
-rw-r--r--bin/tests/system/zonechecks/cname.db14
-rw-r--r--bin/tests/system/zonechecks/dname.db14
-rw-r--r--bin/tests/system/zonechecks/noaddress.db14
-rw-r--r--bin/tests/system/zonechecks/ns1/named.conf.in72
-rw-r--r--bin/tests/system/zonechecks/ns2/named.conf.in42
-rw-r--r--bin/tests/system/zonechecks/nxdomain.db14
-rw-r--r--bin/tests/system/zonechecks/setup.sh33
-rw-r--r--bin/tests/system/zonechecks/tests.sh258
-rw-r--r--bin/tests/system/zonechecks/tests_sh_zonechecks.py14
-rw-r--r--bin/tests/test_client.c453
-rw-r--r--bin/tests/test_server.c326
-rw-r--r--bin/tests/wire_test.c353
-rw-r--r--bin/tools/Makefile.am58
-rw-r--r--bin/tools/Makefile.in968
-rw-r--r--bin/tools/arpaname.c48
-rw-r--r--bin/tools/arpaname.rst35
-rw-r--r--bin/tools/dnstap-read.c428
-rw-r--r--bin/tools/dnstap-read.rst58
-rw-r--r--bin/tools/mdig.c2249
-rw-r--r--bin/tools/mdig.rst375
-rw-r--r--bin/tools/named-journalprint.c134
-rw-r--r--bin/tools/named-journalprint.rst66
-rw-r--r--bin/tools/named-nzd2nzf.c102
-rw-r--r--bin/tools/named-nzd2nzf.rst45
-rw-r--r--bin/tools/named-rrchecker.c346
-rw-r--r--bin/tools/named-rrchecker.rst62
-rw-r--r--bin/tools/nsec3hash.c194
-rw-r--r--bin/tools/nsec3hash.rst70
2763 files changed, 306437 insertions, 0 deletions
diff --git a/bin/Makefile.am b/bin/Makefile.am
new file mode 100644
index 0000000..ba7658e
--- /dev/null
+++ b/bin/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = named rndc dig delv dnssec tools nsupdate check confgen tests plugins
diff --git a/bin/Makefile.in b/bin/Makefile.in
new file mode 100644
index 0000000..d2bb917
--- /dev/null
+++ b/bin/Makefile.in
@@ -0,0 +1,734 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = bin
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir distdir-am
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = named rndc dig delv dnssec tools nsupdate check confgen tests plugins
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+doc: doc-recursive
+
+doc-am: doc-local
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+test: test-recursive
+
+test-am: test-local
+
+uninstall-am:
+
+unit: unit-recursive
+
+unit-am: unit-local
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+ check-am clean clean-generic clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-generic distclean-libtool \
+ distclean-tags distdir doc-am doc-local dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am test-am \
+ test-local uninstall uninstall-am unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/check/Makefile.am b/bin/check/Makefile.am
new file mode 100644
index 0000000..8f63c35
--- /dev/null
+++ b/bin/check/Makefile.am
@@ -0,0 +1,34 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) \
+ $(LIBNS_CFLAGS) \
+ $(LIBISCCFG_CFLAGS) \
+ $(LIBBIND9_CFLAGS)
+
+AM_CPPFLAGS += \
+ -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\"
+
+noinst_LTLIBRARIES = libcheck-tool.la
+
+libcheck_tool_la_SOURCES = \
+ check-tool.h \
+ check-tool.c
+
+LDADD += \
+ libcheck-tool.la \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS) \
+ $(LIBNS_LIBS) \
+ $(LIBISCCFG_LIBS) \
+ $(LIBBIND9_LIBS)
+
+bin_PROGRAMS = named-checkconf named-checkzone
+
+install-exec-hook:
+ ln -f $(DESTDIR)$(bindir)/named-checkzone \
+ $(DESTDIR)$(bindir)/named-compilezone
+
+uninstall-hook:
+ -rm -f $(DESTDIR)$(bindir)/named-compilezone
diff --git a/bin/check/Makefile.in b/bin/check/Makefile.in
new file mode 100644
index 0000000..1f2d67a
--- /dev/null
+++ b/bin/check/Makefile.in
@@ -0,0 +1,872 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+bin_PROGRAMS = named-checkconf$(EXEEXT) named-checkzone$(EXEEXT)
+subdir = bin/check
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libcheck_tool_la_LIBADD =
+am_libcheck_tool_la_OBJECTS = check-tool.lo
+libcheck_tool_la_OBJECTS = $(am_libcheck_tool_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+named_checkconf_SOURCES = named-checkconf.c
+named_checkconf_OBJECTS = named-checkconf.$(OBJEXT)
+named_checkconf_LDADD = $(LDADD)
+named_checkconf_DEPENDENCIES = libcheck-tool.la $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS) $(LIBNS_LIBS) $(LIBISCCFG_LIBS) \
+ $(LIBBIND9_LIBS)
+named_checkzone_SOURCES = named-checkzone.c
+named_checkzone_OBJECTS = named-checkzone.$(OBJEXT)
+named_checkzone_LDADD = $(LDADD)
+named_checkzone_DEPENDENCIES = libcheck-tool.la $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS) $(LIBNS_LIBS) $(LIBISCCFG_LIBS) \
+ $(LIBBIND9_LIBS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/check-tool.Plo \
+ ./$(DEPDIR)/named-checkconf.Po ./$(DEPDIR)/named-checkzone.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libcheck_tool_la_SOURCES) named-checkconf.c \
+ named-checkzone.c
+DIST_SOURCES = $(libcheck_tool_la_SOURCES) named-checkconf.c \
+ named-checkzone.c
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \
+ $(LIBNS_CFLAGS) $(LIBISCCFG_CFLAGS) $(LIBBIND9_CFLAGS) \
+ -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\"
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD = libcheck-tool.la $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBNS_LIBS) \
+ $(LIBISCCFG_LIBS) $(LIBBIND9_LIBS)
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+noinst_LTLIBRARIES = libcheck-tool.la
+libcheck_tool_la_SOURCES = \
+ check-tool.h \
+ check-tool.c
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/check/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/check/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libcheck-tool.la: $(libcheck_tool_la_OBJECTS) $(libcheck_tool_la_DEPENDENCIES) $(EXTRA_libcheck_tool_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libcheck_tool_la_OBJECTS) $(libcheck_tool_la_LIBADD) $(LIBS)
+
+named-checkconf$(EXEEXT): $(named_checkconf_OBJECTS) $(named_checkconf_DEPENDENCIES) $(EXTRA_named_checkconf_DEPENDENCIES)
+ @rm -f named-checkconf$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(named_checkconf_OBJECTS) $(named_checkconf_LDADD) $(LIBS)
+
+named-checkzone$(EXEEXT): $(named_checkzone_OBJECTS) $(named_checkzone_DEPENDENCIES) $(EXTRA_named_checkzone_DEPENDENCIES)
+ @rm -f named-checkzone$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(named_checkzone_OBJECTS) $(named_checkzone_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check-tool.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/named-checkconf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/named-checkzone.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/check-tool.Plo
+ -rm -f ./$(DEPDIR)/named-checkconf.Po
+ -rm -f ./$(DEPDIR)/named-checkzone.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/check-tool.Plo
+ -rm -f ./$(DEPDIR)/named-checkconf.Po
+ -rm -f ./$(DEPDIR)/named-checkzone.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am: uninstall-binPROGRAMS
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-hook
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-exec-am install-strip uninstall-am
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-binPROGRAMS clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir doc-am doc-local dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-exec-hook install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \
+ uninstall-am uninstall-binPROGRAMS uninstall-hook unit-am \
+ unit-local
+
+.PRECIOUS: Makefile
+
+
+install-exec-hook:
+ ln -f $(DESTDIR)$(bindir)/named-checkzone \
+ $(DESTDIR)$(bindir)/named-compilezone
+
+uninstall-hook:
+ -rm -f $(DESTDIR)$(bindir)/named-compilezone
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/check/check-tool.c b/bin/check/check-tool.c
new file mode 100644
index 0000000..fd008dc
--- /dev/null
+++ b/bin/check/check-tool.c
@@ -0,0 +1,693 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <isc/buffer.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/netdb.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/symtab.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+#include <dns/types.h>
+#include <dns/zone.h>
+
+#include <isccfg/log.h>
+
+#include <ns/log.h>
+
+#include "check-tool.h"
+
+#ifndef CHECK_SIBLING
+#define CHECK_SIBLING 1
+#endif /* ifndef CHECK_SIBLING */
+
+#ifndef CHECK_LOCAL
+#define CHECK_LOCAL 1
+#endif /* ifndef CHECK_LOCAL */
+
+#define CHECK(r) \
+ do { \
+ result = (r); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+#define ERR_IS_CNAME 1
+#define ERR_NO_ADDRESSES 2
+#define ERR_LOOKUP_FAILURE 3
+#define ERR_EXTRA_A 4
+#define ERR_EXTRA_AAAA 5
+#define ERR_MISSING_GLUE 5
+#define ERR_IS_MXCNAME 6
+#define ERR_IS_SRVCNAME 7
+
+static const char *dbtype[] = { "rbt" };
+
+int debug = 0;
+const char *journal = NULL;
+bool nomerge = true;
+#if CHECK_LOCAL
+bool docheckmx = true;
+bool dochecksrv = true;
+bool docheckns = true;
+#else /* if CHECK_LOCAL */
+bool docheckmx = false;
+bool dochecksrv = false;
+bool docheckns = false;
+#endif /* if CHECK_LOCAL */
+dns_zoneopt_t zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_CHECKMX |
+ DNS_ZONEOPT_MANYERRORS | DNS_ZONEOPT_CHECKNAMES |
+ DNS_ZONEOPT_CHECKINTEGRITY |
+#if CHECK_SIBLING
+ DNS_ZONEOPT_CHECKSIBLING |
+#endif /* if CHECK_SIBLING */
+ DNS_ZONEOPT_CHECKWILDCARD |
+ DNS_ZONEOPT_WARNMXCNAME | DNS_ZONEOPT_WARNSRVCNAME;
+
+/*
+ * This needs to match the list in bin/named/log.c.
+ */
+static isc_logcategory_t categories[] = { { "", 0 },
+ { "unmatched", 0 },
+ { NULL, 0 } };
+
+static isc_symtab_t *symtab = NULL;
+static isc_mem_t *sym_mctx;
+
+static void
+freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
+ UNUSED(type);
+ UNUSED(value);
+ isc_mem_free(userarg, key);
+}
+
+static void
+add(char *key, int value) {
+ isc_result_t result;
+ isc_symvalue_t symvalue;
+
+ if (sym_mctx == NULL) {
+ isc_mem_create(&sym_mctx);
+ }
+
+ if (symtab == NULL) {
+ result = isc_symtab_create(sym_mctx, 100, freekey, sym_mctx,
+ false, &symtab);
+ if (result != ISC_R_SUCCESS) {
+ return;
+ }
+ }
+
+ key = isc_mem_strdup(sym_mctx, key);
+
+ symvalue.as_pointer = NULL;
+ result = isc_symtab_define(symtab, key, value, symvalue,
+ isc_symexists_reject);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_free(sym_mctx, key);
+ }
+}
+
+static bool
+logged(char *key, int value) {
+ isc_result_t result;
+
+ if (symtab == NULL) {
+ return (false);
+ }
+
+ result = isc_symtab_lookup(symtab, key, value, NULL);
+ if (result == ISC_R_SUCCESS) {
+ return (true);
+ }
+ return (false);
+}
+
+static bool
+checkns(dns_zone_t *zone, const dns_name_t *name, const dns_name_t *owner,
+ dns_rdataset_t *a, dns_rdataset_t *aaaa) {
+ dns_rdataset_t *rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ struct addrinfo hints, *ai, *cur;
+ char namebuf[DNS_NAME_FORMATSIZE + 1];
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
+ bool answer = true;
+ bool match;
+ const char *type;
+ void *ptr = NULL;
+ int result;
+
+ REQUIRE(a == NULL || !dns_rdataset_isassociated(a) ||
+ a->type == dns_rdatatype_a);
+ REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) ||
+ aaaa->type == dns_rdatatype_aaaa);
+
+ if (a == NULL || aaaa == NULL) {
+ return (answer);
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ /*
+ * Turn off search.
+ */
+ if (dns_name_countlabels(name) > 1U) {
+ strlcat(namebuf, ".", sizeof(namebuf));
+ }
+ dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
+
+ result = getaddrinfo(namebuf, NULL, &hints, &ai);
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ switch (result) {
+ case 0:
+ /*
+ * Work around broken getaddrinfo() implementations that
+ * fail to set ai_canonname on first entry.
+ */
+ cur = ai;
+ while (cur != NULL && cur->ai_canonname == NULL &&
+ cur->ai_next != NULL)
+ {
+ cur = cur->ai_next;
+ }
+ if (cur != NULL && cur->ai_canonname != NULL &&
+ strcasecmp(cur->ai_canonname, namebuf) != 0 &&
+ !logged(namebuf, ERR_IS_CNAME))
+ {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/NS '%s' (out of zone) "
+ "is a CNAME '%s' (illegal)",
+ ownerbuf, namebuf, cur->ai_canonname);
+ /* XXX950 make fatal for 9.5.0 */
+ /* answer = false; */
+ add(namebuf, ERR_IS_CNAME);
+ }
+ break;
+ case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif /* if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) */
+ if (!logged(namebuf, ERR_NO_ADDRESSES)) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/NS '%s' (out of zone) "
+ "has no addresses records (A or AAAA)",
+ ownerbuf, namebuf);
+ add(namebuf, ERR_NO_ADDRESSES);
+ }
+ /* XXX950 make fatal for 9.5.0 */
+ return (true);
+
+ default:
+ if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "getaddrinfo(%s) failed: %s", namebuf,
+ gai_strerror(result));
+ add(namebuf, ERR_LOOKUP_FAILURE);
+ }
+ return (true);
+ }
+
+ /*
+ * Check that all glue records really exist.
+ */
+ if (!dns_rdataset_isassociated(a)) {
+ goto checkaaaa;
+ }
+ result = dns_rdataset_first(a);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(a, &rdata);
+ match = false;
+ for (cur = ai; cur != NULL; cur = cur->ai_next) {
+ if (cur->ai_family != AF_INET) {
+ continue;
+ }
+ ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
+ if (memcmp(ptr, rdata.data, rdata.length) == 0) {
+ match = true;
+ break;
+ }
+ }
+ if (!match && !logged(namebuf, ERR_EXTRA_A)) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/NS '%s' "
+ "extra GLUE A record (%s)",
+ ownerbuf, namebuf,
+ inet_ntop(AF_INET, rdata.data, addrbuf,
+ sizeof(addrbuf)));
+ add(namebuf, ERR_EXTRA_A);
+ /* XXX950 make fatal for 9.5.0 */
+ /* answer = false; */
+ }
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(a);
+ }
+
+checkaaaa:
+ if (!dns_rdataset_isassociated(aaaa)) {
+ goto checkmissing;
+ }
+ result = dns_rdataset_first(aaaa);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(aaaa, &rdata);
+ match = false;
+ for (cur = ai; cur != NULL; cur = cur->ai_next) {
+ if (cur->ai_family != AF_INET6) {
+ continue;
+ }
+ ptr = &((struct sockaddr_in6 *)(cur->ai_addr))
+ ->sin6_addr;
+ if (memcmp(ptr, rdata.data, rdata.length) == 0) {
+ match = true;
+ break;
+ }
+ }
+ if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/NS '%s' "
+ "extra GLUE AAAA record (%s)",
+ ownerbuf, namebuf,
+ inet_ntop(AF_INET6, rdata.data, addrbuf,
+ sizeof(addrbuf)));
+ add(namebuf, ERR_EXTRA_AAAA);
+ /* XXX950 make fatal for 9.5.0. */
+ /* answer = false; */
+ }
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(aaaa);
+ }
+
+checkmissing:
+ /*
+ * Check that all addresses appear in the glue.
+ */
+ if (!logged(namebuf, ERR_MISSING_GLUE)) {
+ bool missing_glue = false;
+ for (cur = ai; cur != NULL; cur = cur->ai_next) {
+ switch (cur->ai_family) {
+ case AF_INET:
+ rdataset = a;
+ ptr = &((struct sockaddr_in *)(cur->ai_addr))
+ ->sin_addr;
+ type = "A";
+ break;
+ case AF_INET6:
+ rdataset = aaaa;
+ ptr = &((struct sockaddr_in6 *)(cur->ai_addr))
+ ->sin6_addr;
+ type = "AAAA";
+ break;
+ default:
+ continue;
+ }
+ match = false;
+ if (dns_rdataset_isassociated(rdataset)) {
+ result = dns_rdataset_first(rdataset);
+ } else {
+ result = ISC_R_FAILURE;
+ }
+ while (result == ISC_R_SUCCESS && !match) {
+ dns_rdataset_current(rdataset, &rdata);
+ if (memcmp(ptr, rdata.data, rdata.length) == 0)
+ {
+ match = true;
+ }
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(rdataset);
+ }
+ if (!match) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/NS '%s' "
+ "missing GLUE %s record (%s)",
+ ownerbuf, namebuf, type,
+ inet_ntop(cur->ai_family, ptr,
+ addrbuf,
+ sizeof(addrbuf)));
+ /* XXX950 make fatal for 9.5.0. */
+ /* answer = false; */
+ missing_glue = true;
+ }
+ }
+ if (missing_glue) {
+ add(namebuf, ERR_MISSING_GLUE);
+ }
+ }
+ freeaddrinfo(ai);
+ return (answer);
+}
+
+static bool
+checkmx(dns_zone_t *zone, const dns_name_t *name, const dns_name_t *owner) {
+ struct addrinfo hints, *ai, *cur;
+ char namebuf[DNS_NAME_FORMATSIZE + 1];
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ int result;
+ int level = ISC_LOG_ERROR;
+ bool answer = true;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ /*
+ * Turn off search.
+ */
+ if (dns_name_countlabels(name) > 1U) {
+ strlcat(namebuf, ".", sizeof(namebuf));
+ }
+ dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
+
+ result = getaddrinfo(namebuf, NULL, &hints, &ai);
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ switch (result) {
+ case 0:
+ /*
+ * Work around broken getaddrinfo() implementations that
+ * fail to set ai_canonname on first entry.
+ */
+ cur = ai;
+ while (cur != NULL && cur->ai_canonname == NULL &&
+ cur->ai_next != NULL)
+ {
+ cur = cur->ai_next;
+ }
+ if (cur != NULL && cur->ai_canonname != NULL &&
+ strcasecmp(cur->ai_canonname, namebuf) != 0)
+ {
+ if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0) {
+ level = ISC_LOG_WARNING;
+ }
+ if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) {
+ if (!logged(namebuf, ERR_IS_MXCNAME)) {
+ dns_zone_log(zone, level,
+ "%s/MX '%s' (out of zone)"
+ " is a CNAME '%s' "
+ "(illegal)",
+ ownerbuf, namebuf,
+ cur->ai_canonname);
+ add(namebuf, ERR_IS_MXCNAME);
+ }
+ if (level == ISC_LOG_ERROR) {
+ answer = false;
+ }
+ }
+ }
+ freeaddrinfo(ai);
+ return (answer);
+
+ case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif /* if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) */
+ if (!logged(namebuf, ERR_NO_ADDRESSES)) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/MX '%s' (out of zone) "
+ "has no addresses records (A or AAAA)",
+ ownerbuf, namebuf);
+ add(namebuf, ERR_NO_ADDRESSES);
+ }
+ /* XXX950 make fatal for 9.5.0. */
+ return (true);
+
+ default:
+ if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "getaddrinfo(%s) failed: %s", namebuf,
+ gai_strerror(result));
+ add(namebuf, ERR_LOOKUP_FAILURE);
+ }
+ return (true);
+ }
+}
+
+static bool
+checksrv(dns_zone_t *zone, const dns_name_t *name, const dns_name_t *owner) {
+ struct addrinfo hints, *ai, *cur;
+ char namebuf[DNS_NAME_FORMATSIZE + 1];
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ int result;
+ int level = ISC_LOG_ERROR;
+ bool answer = true;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ /*
+ * Turn off search.
+ */
+ if (dns_name_countlabels(name) > 1U) {
+ strlcat(namebuf, ".", sizeof(namebuf));
+ }
+ dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
+
+ result = getaddrinfo(namebuf, NULL, &hints, &ai);
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ switch (result) {
+ case 0:
+ /*
+ * Work around broken getaddrinfo() implementations that
+ * fail to set ai_canonname on first entry.
+ */
+ cur = ai;
+ while (cur != NULL && cur->ai_canonname == NULL &&
+ cur->ai_next != NULL)
+ {
+ cur = cur->ai_next;
+ }
+ if (cur != NULL && cur->ai_canonname != NULL &&
+ strcasecmp(cur->ai_canonname, namebuf) != 0)
+ {
+ if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0) {
+ level = ISC_LOG_WARNING;
+ }
+ if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) {
+ if (!logged(namebuf, ERR_IS_SRVCNAME)) {
+ dns_zone_log(zone, level,
+ "%s/SRV '%s'"
+ " (out of zone) is a "
+ "CNAME '%s' (illegal)",
+ ownerbuf, namebuf,
+ cur->ai_canonname);
+ add(namebuf, ERR_IS_SRVCNAME);
+ }
+ if (level == ISC_LOG_ERROR) {
+ answer = false;
+ }
+ }
+ }
+ freeaddrinfo(ai);
+ return (answer);
+
+ case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif /* if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) */
+ if (!logged(namebuf, ERR_NO_ADDRESSES)) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/SRV '%s' (out of zone) "
+ "has no addresses records (A or AAAA)",
+ ownerbuf, namebuf);
+ add(namebuf, ERR_NO_ADDRESSES);
+ }
+ /* XXX950 make fatal for 9.5.0. */
+ return (true);
+
+ default:
+ if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "getaddrinfo(%s) failed: %s", namebuf,
+ gai_strerror(result));
+ add(namebuf, ERR_LOOKUP_FAILURE);
+ }
+ return (true);
+ }
+}
+
+isc_result_t
+setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) {
+ isc_logdestination_t destination;
+ isc_logconfig_t *logconfig = NULL;
+ isc_log_t *log = NULL;
+
+ isc_log_create(mctx, &log, &logconfig);
+ isc_log_registercategories(log, categories);
+ isc_log_setcontext(log);
+ dns_log_init(log);
+ dns_log_setcontext(log);
+ cfg_log_init(log);
+ ns_log_init(log);
+
+ destination.file.stream = errout;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC, &destination, 0);
+
+ RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL) ==
+ ISC_R_SUCCESS);
+
+ *logp = log;
+ return (ISC_R_SUCCESS);
+}
+
+/*% load the zone */
+isc_result_t
+load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
+ dns_masterformat_t fileformat, const char *classname,
+ dns_ttl_t maxttl, dns_zone_t **zonep) {
+ isc_result_t result;
+ dns_rdataclass_t rdclass;
+ isc_textregion_t region;
+ isc_buffer_t buffer;
+ dns_fixedname_t fixorigin;
+ dns_name_t *origin;
+ dns_zone_t *zone = NULL;
+
+ REQUIRE(zonep == NULL || *zonep == NULL);
+
+ if (debug) {
+ fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
+ zonename, filename, classname);
+ }
+
+ CHECK(dns_zone_create(&zone, mctx));
+
+ dns_zone_settype(zone, dns_zone_primary);
+
+ isc_buffer_constinit(&buffer, zonename, strlen(zonename));
+ isc_buffer_add(&buffer, strlen(zonename));
+ origin = dns_fixedname_initname(&fixorigin);
+ CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL));
+ CHECK(dns_zone_setorigin(zone, origin));
+ dns_zone_setdbtype(zone, 1, (const char *const *)dbtype);
+ if (strcmp(filename, "-") == 0) {
+ CHECK(dns_zone_setstream(zone, stdin, fileformat,
+ &dns_master_style_default));
+ } else {
+ CHECK(dns_zone_setfile(zone, filename, fileformat,
+ &dns_master_style_default));
+ }
+ if (journal != NULL) {
+ CHECK(dns_zone_setjournal(zone, journal));
+ }
+
+ DE_CONST(classname, region.base);
+ region.length = strlen(classname);
+ CHECK(dns_rdataclass_fromtext(&rdclass, &region));
+
+ dns_zone_setclass(zone, rdclass);
+ dns_zone_setoption(zone, zone_options, true);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge);
+
+ dns_zone_setmaxttl(zone, maxttl);
+
+ if (docheckmx) {
+ dns_zone_setcheckmx(zone, checkmx);
+ }
+ if (docheckns) {
+ dns_zone_setcheckns(zone, checkns);
+ }
+ if (dochecksrv) {
+ dns_zone_setchecksrv(zone, checksrv);
+ }
+
+ CHECK(dns_zone_load(zone, false));
+
+ if (zonep != NULL) {
+ *zonep = zone;
+ zone = NULL;
+ }
+
+cleanup:
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ return (result);
+}
+
+/*% dump the zone */
+isc_result_t
+dump_zone(const char *zonename, dns_zone_t *zone, const char *filename,
+ dns_masterformat_t fileformat, const dns_master_style_t *style,
+ const uint32_t rawversion) {
+ isc_result_t result;
+ FILE *output = stdout;
+ const char *flags;
+
+ flags = (fileformat == dns_masterformat_text) ? "w" : "wb";
+
+ if (debug) {
+ if (filename != NULL && strcmp(filename, "-") != 0) {
+ fprintf(stderr, "dumping \"%s\" to \"%s\"\n", zonename,
+ filename);
+ } else {
+ fprintf(stderr, "dumping \"%s\"\n", zonename);
+ }
+ }
+
+ if (filename != NULL && strcmp(filename, "-") != 0) {
+ result = isc_stdio_open(filename, flags, &output);
+
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "could not open output "
+ "file \"%s\" for writing\n",
+ filename);
+ return (ISC_R_FAILURE);
+ }
+ }
+
+ result = dns_zone_dumptostream(zone, output, fileformat, style,
+ rawversion);
+ if (output != stdout) {
+ (void)isc_stdio_close(output);
+ }
+
+ return (result);
+}
diff --git a/bin/check/check-tool.h b/bin/check/check-tool.h
new file mode 100644
index 0000000..64ac9e7
--- /dev/null
+++ b/bin/check/check-tool.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/stdio.h>
+#include <isc/types.h>
+
+#include <dns/masterdump.h>
+#include <dns/types.h>
+#include <dns/zone.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp);
+
+isc_result_t
+load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
+ dns_masterformat_t fileformat, const char *classname,
+ dns_ttl_t maxttl, dns_zone_t **zonep);
+
+isc_result_t
+dump_zone(const char *zonename, dns_zone_t *zone, const char *filename,
+ dns_masterformat_t fileformat, const dns_master_style_t *style,
+ const uint32_t rawversion);
+
+extern int debug;
+extern const char *journal;
+extern bool nomerge;
+extern bool docheckmx;
+extern bool docheckns;
+extern bool dochecksrv;
+extern dns_zoneopt_t zone_options;
+
+ISC_LANG_ENDDECLS
diff --git a/bin/check/named-checkconf.c b/bin/check/named-checkconf.c
new file mode 100644
index 0000000..fd7cfa5
--- /dev/null
+++ b/bin/check/named-checkconf.c
@@ -0,0 +1,754 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/attributes.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/rootns.h>
+#include <dns/zone.h>
+
+#include <isccfg/grammar.h>
+#include <isccfg/namedconf.h>
+
+#include <bind9/check.h>
+
+#include "check-tool.h"
+
+static const char *program = "named-checkconf";
+
+static bool loadplugins = true;
+
+isc_log_t *logc = NULL;
+
+#define CHECK(r) \
+ do { \
+ result = (r); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+/*% usage */
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr,
+ "usage: %s [-chijlvz] [-p [-x]] [-t directory] "
+ "[named.conf]\n",
+ program);
+ exit(1);
+}
+
+/*% directory callback */
+static isc_result_t
+directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
+ isc_result_t result;
+ const char *directory;
+
+ REQUIRE(strcasecmp("directory", clausename) == 0);
+
+ UNUSED(arg);
+ UNUSED(clausename);
+
+ /*
+ * Change directory.
+ */
+ directory = cfg_obj_asstring(obj);
+ result = isc_dir_chdir(directory);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logc, ISC_LOG_ERROR,
+ "change directory to '%s' failed: %s\n", directory,
+ isc_result_totext(result));
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static bool
+get_maps(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) {
+ int i;
+ for (i = 0;; i++) {
+ if (maps[i] == NULL) {
+ return (false);
+ }
+ if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) {
+ return (true);
+ }
+ }
+}
+
+static bool
+get_checknames(const cfg_obj_t **maps, const cfg_obj_t **obj) {
+ const cfg_listelt_t *element;
+ const cfg_obj_t *checknames;
+ const cfg_obj_t *type;
+ const cfg_obj_t *value;
+ isc_result_t result;
+ int i;
+
+ for (i = 0;; i++) {
+ if (maps[i] == NULL) {
+ return (false);
+ }
+ checknames = NULL;
+ result = cfg_map_get(maps[i], "check-names", &checknames);
+ if (result != ISC_R_SUCCESS) {
+ continue;
+ }
+ if (checknames != NULL && !cfg_obj_islist(checknames)) {
+ *obj = checknames;
+ return (true);
+ }
+ for (element = cfg_list_first(checknames); element != NULL;
+ element = cfg_list_next(element))
+ {
+ value = cfg_listelt_value(element);
+ type = cfg_tuple_get(value, "type");
+ if ((strcasecmp(cfg_obj_asstring(type), "primary") !=
+ 0) &&
+ (strcasecmp(cfg_obj_asstring(type), "master") != 0))
+ {
+ continue;
+ }
+ *obj = cfg_tuple_get(value, "mode");
+ return (true);
+ }
+ }
+}
+
+static isc_result_t
+configure_hint(const char *zfile, const char *zclass, isc_mem_t *mctx) {
+ isc_result_t result;
+ dns_db_t *db = NULL;
+ dns_rdataclass_t rdclass;
+ isc_textregion_t r;
+
+ if (zfile == NULL) {
+ return (ISC_R_FAILURE);
+ }
+
+ DE_CONST(zclass, r.base);
+ r.length = strlen(zclass);
+ result = dns_rdataclass_fromtext(&rdclass, &r);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = dns_rootns_create(mctx, rdclass, zfile, &db);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ dns_db_detach(&db);
+ return (ISC_R_SUCCESS);
+}
+
+/*% configure the zone */
+static isc_result_t
+configure_zone(const char *vclass, const char *view, const cfg_obj_t *zconfig,
+ const cfg_obj_t *vconfig, const cfg_obj_t *config,
+ isc_mem_t *mctx, bool list) {
+ int i = 0;
+ isc_result_t result;
+ const char *zclass;
+ const char *zname;
+ const char *zfile = NULL;
+ const cfg_obj_t *maps[4];
+ const cfg_obj_t *primariesobj = NULL;
+ const cfg_obj_t *inviewobj = NULL;
+ const cfg_obj_t *zoptions = NULL;
+ const cfg_obj_t *classobj = NULL;
+ const cfg_obj_t *typeobj = NULL;
+ const cfg_obj_t *fileobj = NULL;
+ const cfg_obj_t *dlzobj = NULL;
+ const cfg_obj_t *dbobj = NULL;
+ const cfg_obj_t *obj = NULL;
+ const cfg_obj_t *fmtobj = NULL;
+ dns_masterformat_t masterformat;
+ dns_ttl_t maxttl = 0;
+
+ zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_MANYERRORS;
+
+ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+ classobj = cfg_tuple_get(zconfig, "class");
+ if (!cfg_obj_isstring(classobj)) {
+ zclass = vclass;
+ } else {
+ zclass = cfg_obj_asstring(classobj);
+ }
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+ maps[i++] = zoptions;
+ if (vconfig != NULL) {
+ maps[i++] = cfg_tuple_get(vconfig, "options");
+ }
+ if (config != NULL) {
+ cfg_map_get(config, "options", &obj);
+ if (obj != NULL) {
+ maps[i++] = obj;
+ }
+ }
+ maps[i] = NULL;
+
+ cfg_map_get(zoptions, "in-view", &inviewobj);
+ if (inviewobj != NULL && list) {
+ const char *inview = cfg_obj_asstring(inviewobj);
+ printf("%s %s %s in-view %s\n", zname, zclass, view, inview);
+ }
+ if (inviewobj != NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ cfg_map_get(zoptions, "type", &typeobj);
+ if (typeobj == NULL) {
+ return (ISC_R_FAILURE);
+ }
+
+ if (list) {
+ const char *ztype = cfg_obj_asstring(typeobj);
+ printf("%s %s %s %s\n", zname, zclass, view, ztype);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Skip checks when using an alternate data source.
+ */
+ cfg_map_get(zoptions, "database", &dbobj);
+ if (dbobj != NULL && strcmp("rbt", cfg_obj_asstring(dbobj)) != 0 &&
+ strcmp("rbt64", cfg_obj_asstring(dbobj)) != 0)
+ {
+ return (ISC_R_SUCCESS);
+ }
+
+ cfg_map_get(zoptions, "dlz", &dlzobj);
+ if (dlzobj != NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ cfg_map_get(zoptions, "file", &fileobj);
+ if (fileobj != NULL) {
+ zfile = cfg_obj_asstring(fileobj);
+ }
+
+ /*
+ * Check hints files for hint zones.
+ * Skip loading checks for any type other than
+ * master and redirect
+ */
+ if (strcasecmp(cfg_obj_asstring(typeobj), "hint") == 0) {
+ return (configure_hint(zfile, zclass, mctx));
+ } else if ((strcasecmp(cfg_obj_asstring(typeobj), "primary") != 0) &&
+ (strcasecmp(cfg_obj_asstring(typeobj), "master") != 0) &&
+ (strcasecmp(cfg_obj_asstring(typeobj), "redirect") != 0))
+ {
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Is the redirect zone configured as a secondary?
+ */
+ if (strcasecmp(cfg_obj_asstring(typeobj), "redirect") == 0) {
+ cfg_map_get(zoptions, "primaries", &primariesobj);
+ if (primariesobj == NULL) {
+ cfg_map_get(zoptions, "masters", &primariesobj);
+ }
+
+ if (primariesobj != NULL) {
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ if (zfile == NULL) {
+ return (ISC_R_FAILURE);
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "check-dup-records", &obj)) {
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKDUPRR;
+ zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKDUPRR;
+ zone_options |= DNS_ZONEOPT_CHECKDUPRRFAIL;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ zone_options &= ~DNS_ZONEOPT_CHECKDUPRR;
+ zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
+ } else {
+ UNREACHABLE();
+ }
+ } else {
+ zone_options |= DNS_ZONEOPT_CHECKDUPRR;
+ zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "check-mx", &obj)) {
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKMX;
+ zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKMX;
+ zone_options |= DNS_ZONEOPT_CHECKMXFAIL;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ zone_options &= ~DNS_ZONEOPT_CHECKMX;
+ zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
+ } else {
+ UNREACHABLE();
+ }
+ } else {
+ zone_options |= DNS_ZONEOPT_CHECKMX;
+ zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "check-integrity", &obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
+ } else {
+ zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
+ }
+ } else {
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "check-mx-cname", &obj)) {
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ zone_options |= DNS_ZONEOPT_WARNMXCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ zone_options |= DNS_ZONEOPT_WARNMXCNAME;
+ zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
+ } else {
+ UNREACHABLE();
+ }
+ } else {
+ zone_options |= DNS_ZONEOPT_WARNMXCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "check-srv-cname", &obj)) {
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
+ } else {
+ UNREACHABLE();
+ }
+ } else {
+ zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "check-sibling", &obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ zone_options |= DNS_ZONEOPT_CHECKSIBLING;
+ } else {
+ zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
+ }
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "check-spf", &obj)) {
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKSPF;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ zone_options &= ~DNS_ZONEOPT_CHECKSPF;
+ } else {
+ UNREACHABLE();
+ }
+ } else {
+ zone_options |= DNS_ZONEOPT_CHECKSPF;
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "check-wildcard", &obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
+ } else {
+ zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
+ }
+ } else {
+ zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
+ }
+
+ obj = NULL;
+ if (get_checknames(maps, &obj)) {
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKNAMES;
+ zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKNAMES;
+ zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ zone_options &= ~DNS_ZONEOPT_CHECKNAMES;
+ zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
+ } else {
+ UNREACHABLE();
+ }
+ } else {
+ zone_options |= DNS_ZONEOPT_CHECKNAMES;
+ zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL;
+ }
+
+ masterformat = dns_masterformat_text;
+ fmtobj = NULL;
+ if (get_maps(maps, "masterfile-format", &fmtobj)) {
+ const char *masterformatstr = cfg_obj_asstring(fmtobj);
+ if (strcasecmp(masterformatstr, "text") == 0) {
+ masterformat = dns_masterformat_text;
+ } else if (strcasecmp(masterformatstr, "raw") == 0) {
+ masterformat = dns_masterformat_raw;
+ } else {
+ UNREACHABLE();
+ }
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "max-zone-ttl", &obj)) {
+ maxttl = cfg_obj_asduration(obj);
+ zone_options |= DNS_ZONEOPT_CHECKTTL;
+ }
+
+ result = load_zone(mctx, zname, zfile, masterformat, zclass, maxttl,
+ NULL);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "%s/%s/%s: %s\n", view, zname, zclass,
+ isc_result_totext(result));
+ }
+ return (result);
+}
+
+/*% configure a view */
+static isc_result_t
+configure_view(const char *vclass, const char *view, const cfg_obj_t *config,
+ const cfg_obj_t *vconfig, isc_mem_t *mctx, bool list) {
+ const cfg_listelt_t *element;
+ const cfg_obj_t *voptions;
+ const cfg_obj_t *zonelist;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+
+ voptions = NULL;
+ if (vconfig != NULL) {
+ voptions = cfg_tuple_get(vconfig, "options");
+ }
+
+ zonelist = NULL;
+ if (voptions != NULL) {
+ (void)cfg_map_get(voptions, "zone", &zonelist);
+ } else {
+ (void)cfg_map_get(config, "zone", &zonelist);
+ }
+
+ for (element = cfg_list_first(zonelist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *zconfig = cfg_listelt_value(element);
+ tresult = configure_zone(vclass, view, zconfig, vconfig, config,
+ mctx, list);
+ if (tresult != ISC_R_SUCCESS) {
+ result = tresult;
+ }
+ }
+ return (result);
+}
+
+static isc_result_t
+config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass,
+ dns_rdataclass_t *classp) {
+ isc_textregion_t r;
+
+ if (!cfg_obj_isstring(classobj)) {
+ *classp = defclass;
+ return (ISC_R_SUCCESS);
+ }
+ DE_CONST(cfg_obj_asstring(classobj), r.base);
+ r.length = strlen(r.base);
+ return (dns_rdataclass_fromtext(classp, &r));
+}
+
+/*% load zones from the configuration */
+static isc_result_t
+load_zones_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx,
+ bool list_zones) {
+ const cfg_listelt_t *element;
+ const cfg_obj_t *views;
+ const cfg_obj_t *vconfig;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+
+ views = NULL;
+
+ (void)cfg_map_get(config, "view", &views);
+ for (element = cfg_list_first(views); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *classobj;
+ dns_rdataclass_t viewclass;
+ const char *vname;
+ char buf[sizeof("CLASS65535")];
+
+ vconfig = cfg_listelt_value(element);
+ if (vconfig == NULL) {
+ continue;
+ }
+
+ classobj = cfg_tuple_get(vconfig, "class");
+ tresult = config_getclass(classobj, dns_rdataclass_in,
+ &viewclass);
+ if (tresult != ISC_R_SUCCESS) {
+ CHECK(tresult);
+ }
+
+ if (dns_rdataclass_ismeta(viewclass)) {
+ CHECK(ISC_R_FAILURE);
+ }
+
+ dns_rdataclass_format(viewclass, buf, sizeof(buf));
+ vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
+ tresult = configure_view(buf, vname, config, vconfig, mctx,
+ list_zones);
+ if (tresult != ISC_R_SUCCESS) {
+ result = tresult;
+ }
+ }
+
+ if (views == NULL) {
+ tresult = configure_view("IN", "_default", config, NULL, mctx,
+ list_zones);
+ if (tresult != ISC_R_SUCCESS) {
+ result = tresult;
+ }
+ }
+
+cleanup:
+ return (result);
+}
+
+static void
+output(void *closure, const char *text, int textlen) {
+ UNUSED(closure);
+ if (fwrite(text, 1, textlen, stdout) != (size_t)textlen) {
+ perror("fwrite");
+ exit(1);
+ }
+}
+
+/*% The main processing routine */
+int
+main(int argc, char **argv) {
+ int c;
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *config = NULL;
+ const char *conffile = NULL;
+ isc_mem_t *mctx = NULL;
+ isc_result_t result;
+ int exit_status = 0;
+ bool load_zones = false;
+ bool list_zones = false;
+ bool print = false;
+ bool nodeprecate = false;
+ unsigned int flags = 0;
+
+ isc_commandline_errprint = false;
+
+ /*
+ * Process memory debugging argument first.
+ */
+#define CMDLINE_FLAGS "cdhijlm:t:pvxz"
+ while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (c) {
+ case 'm':
+ if (strcasecmp(isc_commandline_argument, "record") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ }
+ if (strcasecmp(isc_commandline_argument, "trace") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
+ }
+ if (strcasecmp(isc_commandline_argument, "usage") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = true;
+
+ isc_mem_create(&mctx);
+
+ while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != EOF) {
+ switch (c) {
+ case 'c':
+ loadplugins = false;
+ break;
+
+ case 'd':
+ debug++;
+ break;
+
+ case 'i':
+ nodeprecate = true;
+ break;
+
+ case 'j':
+ nomerge = false;
+ break;
+
+ case 'l':
+ list_zones = true;
+ break;
+
+ case 'm':
+ break;
+
+ case 't':
+ result = isc_dir_chroot(isc_commandline_argument);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "isc_dir_chroot: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+ break;
+
+ case 'p':
+ print = true;
+ break;
+
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+
+ case 'x':
+ flags |= CFG_PRINTER_XKEY;
+ break;
+
+ case 'z':
+ load_zones = true;
+ docheckmx = false;
+ docheckns = false;
+ dochecksrv = false;
+ break;
+
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ }
+ FALLTHROUGH;
+ case 'h':
+ usage();
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (((flags & CFG_PRINTER_XKEY) != 0) && !print) {
+ fprintf(stderr, "%s: -x cannot be used without -p\n", program);
+ exit(1);
+ }
+ if (print && list_zones) {
+ fprintf(stderr, "%s: -l cannot be used with -p\n", program);
+ exit(1);
+ }
+
+ if (isc_commandline_index + 1 < argc) {
+ usage();
+ }
+ if (argv[isc_commandline_index] != NULL) {
+ conffile = argv[isc_commandline_index];
+ }
+ if (conffile == NULL || conffile[0] == '\0') {
+ conffile = NAMED_CONFFILE;
+ }
+
+ RUNTIME_CHECK(setup_logging(mctx, stdout, &logc) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(cfg_parser_create(mctx, logc, &parser) == ISC_R_SUCCESS);
+
+ if (nodeprecate) {
+ cfg_parser_setflags(parser, CFG_PCTX_NODEPRECATED, true);
+ }
+ cfg_parser_setcallback(parser, directory_callback, NULL);
+
+ if (cfg_parse_file(parser, conffile, &cfg_type_namedconf, &config) !=
+ ISC_R_SUCCESS)
+ {
+ exit(1);
+ }
+
+ result = bind9_check_namedconf(config, loadplugins, nodeprecate, logc,
+ mctx);
+ if (result != ISC_R_SUCCESS) {
+ exit_status = 1;
+ }
+
+ if (result == ISC_R_SUCCESS && (load_zones || list_zones)) {
+ result = load_zones_fromconfig(config, mctx, list_zones);
+ if (result != ISC_R_SUCCESS) {
+ exit_status = 1;
+ }
+ }
+
+ if (print && exit_status == 0) {
+ cfg_printx(config, flags, output, NULL);
+ }
+ cfg_obj_destroy(parser, &config);
+
+ cfg_parser_destroy(&parser);
+
+ isc_log_destroy(&logc);
+
+ isc_mem_destroy(&mctx);
+
+ return (exit_status);
+}
diff --git a/bin/check/named-checkconf.rst b/bin/check/named-checkconf.rst
new file mode 100644
index 0000000..b3065a5
--- /dev/null
+++ b/bin/check/named-checkconf.rst
@@ -0,0 +1,108 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: named-checkconf
+.. program:: named-checkconf
+.. _man_named-checkconf:
+
+named-checkconf - named configuration file syntax checking tool
+---------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`named-checkconf` [**-chjlvz**] [**-p** [**-x** ]] [**-t** directory] {filename}
+
+Description
+~~~~~~~~~~~
+
+:program:`named-checkconf` checks the syntax, but not the semantics, of a
+:iscman:`named` configuration file. The file, along with all files included by it, is parsed and checked for syntax
+errors. If no file is specified,
+|named_conf| is read by default.
+
+Note: files that :iscman:`named` reads in separate parser contexts, such as
+``rndc.key`` and ``bind.keys``, are not automatically read by
+:program:`named-checkconf`. Configuration errors in these files may cause
+:iscman:`named` to fail to run, even if :program:`named-checkconf` was successful.
+However, :program:`named-checkconf` can be run on these files explicitly.
+
+Options
+~~~~~~~
+
+.. option:: -h
+
+ This option prints the usage summary and exits.
+
+.. option:: -j
+
+ When loading a zonefile, this option instructs :iscman:`named` to read the journal if it exists.
+
+.. option:: -l
+
+ This option lists all the configured zones. Each line of output contains the zone
+ name, class (e.g. IN), view, and type (e.g. primary or secondary).
+
+.. option:: -c
+
+ This option specifies that only the "core" configuration should be checked. This suppresses the loading of
+ plugin modules, and causes all parameters to ``plugin`` statements to
+ be ignored.
+
+.. option:: -i
+
+ This option ignores warnings on deprecated options.
+
+.. option:: -p
+
+ This option prints out the :iscman:`named.conf` and included files in canonical form if
+ no errors were detected. See also the :option:`-x` option.
+
+.. option:: -t directory
+
+ This option instructs :iscman:`named` to chroot to ``directory``, so that ``include`` directives in the
+ configuration file are processed as if run by a similarly chrooted
+ :iscman:`named`.
+
+.. option:: -v
+
+ This option prints the version of the :program:`named-checkconf` program and exits.
+
+.. option:: -x
+
+ When printing the configuration files in canonical form, this option obscures
+ shared secrets by replacing them with strings of question marks
+ (``?``). This allows the contents of :iscman:`named.conf` and related files
+ to be shared - for example, when submitting bug reports -
+ without compromising private data. This option cannot be used without
+ :option:`-p`.
+
+.. option:: -z
+
+ This option performs a test load of all zones of type ``primary`` found in :iscman:`named.conf`.
+
+.. option:: filename
+
+ This indicates the name of the configuration file to be checked. If not specified,
+ it defaults to |named_conf|.
+
+Return Values
+~~~~~~~~~~~~~
+
+:program:`named-checkconf` returns an exit status of 1 if errors were detected
+and 0 otherwise.
+
+See Also
+~~~~~~~~
+
+:iscman:`named(8) <named>`, :iscman:`named-checkzone(8) <named-checkzone>`, BIND 9 Administrator Reference Manual.
diff --git a/bin/check/named-checkzone.c b/bin/check/named-checkzone.c
new file mode 100644
index 0000000..5c74660
--- /dev/null
+++ b/bin/check/named-checkzone.c
@@ -0,0 +1,569 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/attributes.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/masterdump.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/types.h>
+#include <dns/zone.h>
+
+#include "check-tool.h"
+
+static int quiet = 0;
+static isc_mem_t *mctx = NULL;
+dns_zone_t *zone = NULL;
+dns_zonetype_t zonetype = dns_zone_primary;
+static int dumpzone = 0;
+static const char *output_filename;
+static const char *prog_name = NULL;
+static const dns_master_style_t *outputstyle = NULL;
+static enum { progmode_check, progmode_compile } progmode;
+
+#define ERRRET(result, function) \
+ do { \
+ if (result != ISC_R_SUCCESS) { \
+ if (!quiet) \
+ fprintf(stderr, "%s() returned %s\n", \
+ function, isc_result_totext(result)); \
+ return (result); \
+ } \
+ } while (0)
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr,
+ "usage: %s [-djqvD] [-c class] "
+ "[-f inputformat] [-F outputformat] [-J filename] "
+ "[-s (full|relative)] [-t directory] [-w directory] "
+ "[-k (ignore|warn|fail)] [-m (ignore|warn|fail)] "
+ "[-n (ignore|warn|fail)] [-r (ignore|warn|fail)] "
+ "[-i (full|full-sibling|local|local-sibling|none)] "
+ "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
+ "[-W (ignore|warn)] "
+ "%s zonename [ (filename|-) ]\n",
+ prog_name,
+ progmode == progmode_check ? "[-o filename]" : "-o filename");
+ exit(1);
+}
+
+static void
+destroy(void) {
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+}
+
+/*% main processing routine */
+int
+main(int argc, char **argv) {
+ int c;
+ char *origin = NULL;
+ const char *filename = NULL;
+ isc_log_t *lctx = NULL;
+ isc_result_t result;
+ char classname_in[] = "IN";
+ char *classname = classname_in;
+ const char *workdir = NULL;
+ const char *inputformatstr = NULL;
+ const char *outputformatstr = NULL;
+ dns_masterformat_t inputformat = dns_masterformat_text;
+ dns_masterformat_t outputformat = dns_masterformat_text;
+ dns_masterrawheader_t header;
+ uint32_t rawversion = 1, serialnum = 0;
+ dns_ttl_t maxttl = 0;
+ bool snset = false;
+ bool logdump = false;
+ FILE *errout = stdout;
+ char *endp;
+
+ /*
+ * Uncomment the following line if memory debugging is needed:
+ * isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ */
+
+ outputstyle = &dns_master_style_full;
+
+ prog_name = strrchr(argv[0], '/');
+ if (prog_name == NULL) {
+ prog_name = strrchr(argv[0], '\\');
+ }
+ if (prog_name != NULL) {
+ prog_name++;
+ } else {
+ prog_name = argv[0];
+ }
+ /*
+ * Libtool doesn't preserve the program name prior to final
+ * installation. Remove the libtool prefix ("lt-").
+ */
+ if (strncmp(prog_name, "lt-", 3) == 0) {
+ prog_name += 3;
+ }
+
+#define PROGCMP(X) \
+ (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
+
+ if (PROGCMP("named-checkzone")) {
+ progmode = progmode_check;
+ } else if (PROGCMP("named-compilezone")) {
+ progmode = progmode_compile;
+ } else {
+ UNREACHABLE();
+ }
+
+ /* Compilation specific defaults */
+ if (progmode == progmode_compile) {
+ zone_options |= (DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_FATALNS |
+ DNS_ZONEOPT_CHECKSPF | DNS_ZONEOPT_CHECKDUPRR |
+ DNS_ZONEOPT_CHECKNAMES |
+ DNS_ZONEOPT_CHECKNAMESFAIL |
+ DNS_ZONEOPT_CHECKWILDCARD);
+ } else {
+ zone_options |= (DNS_ZONEOPT_CHECKDUPRR | DNS_ZONEOPT_CHECKSPF);
+ }
+
+#define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
+
+ isc_commandline_errprint = false;
+
+ while ((c = isc_commandline_parse(argc, argv,
+ "c:df:hi:jJ:k:L:l:m:n:qr:s:t:o:vw:DF:"
+ "M:S:T:W:")) != EOF)
+ {
+ switch (c) {
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+
+ case 'd':
+ debug++;
+ break;
+
+ case 'i':
+ if (ARGCMP("full")) {
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
+ DNS_ZONEOPT_CHECKSIBLING;
+ docheckmx = true;
+ docheckns = true;
+ dochecksrv = true;
+ } else if (ARGCMP("full-sibling")) {
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
+ zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
+ docheckmx = true;
+ docheckns = true;
+ dochecksrv = true;
+ } else if (ARGCMP("local")) {
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
+ zone_options |= DNS_ZONEOPT_CHECKSIBLING;
+ docheckmx = false;
+ docheckns = false;
+ dochecksrv = false;
+ } else if (ARGCMP("local-sibling")) {
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
+ zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
+ docheckmx = false;
+ docheckns = false;
+ dochecksrv = false;
+ } else if (ARGCMP("none")) {
+ zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
+ zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
+ docheckmx = false;
+ docheckns = false;
+ dochecksrv = false;
+ } else {
+ fprintf(stderr, "invalid argument to -i: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'f':
+ inputformatstr = isc_commandline_argument;
+ break;
+
+ case 'F':
+ outputformatstr = isc_commandline_argument;
+ break;
+
+ case 'j':
+ nomerge = false;
+ break;
+
+ case 'J':
+ journal = isc_commandline_argument;
+ nomerge = false;
+ break;
+
+ case 'k':
+ if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_CHECKNAMES;
+ zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
+ } else if (ARGCMP("fail")) {
+ zone_options |= DNS_ZONEOPT_CHECKNAMES |
+ DNS_ZONEOPT_CHECKNAMESFAIL;
+ } else if (ARGCMP("ignore")) {
+ zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
+ DNS_ZONEOPT_CHECKNAMESFAIL);
+ } else {
+ fprintf(stderr, "invalid argument to -k: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'L':
+ snset = true;
+ endp = NULL;
+ serialnum = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fprintf(stderr, "source serial number "
+ "must be numeric");
+ exit(1);
+ }
+ break;
+
+ case 'l':
+ zone_options |= DNS_ZONEOPT_CHECKTTL;
+ endp = NULL;
+ maxttl = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fprintf(stderr, "maximum TTL "
+ "must be numeric");
+ exit(1);
+ }
+ break;
+
+ case 'n':
+ if (ARGCMP("ignore")) {
+ zone_options &= ~(DNS_ZONEOPT_CHECKNS |
+ DNS_ZONEOPT_FATALNS);
+ } else if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_CHECKNS;
+ zone_options &= ~DNS_ZONEOPT_FATALNS;
+ } else if (ARGCMP("fail")) {
+ zone_options |= DNS_ZONEOPT_CHECKNS |
+ DNS_ZONEOPT_FATALNS;
+ } else {
+ fprintf(stderr, "invalid argument to -n: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'm':
+ if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_CHECKMX;
+ zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
+ } else if (ARGCMP("fail")) {
+ zone_options |= DNS_ZONEOPT_CHECKMX |
+ DNS_ZONEOPT_CHECKMXFAIL;
+ } else if (ARGCMP("ignore")) {
+ zone_options &= ~(DNS_ZONEOPT_CHECKMX |
+ DNS_ZONEOPT_CHECKMXFAIL);
+ } else {
+ fprintf(stderr, "invalid argument to -m: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'o':
+ output_filename = isc_commandline_argument;
+ break;
+
+ case 'q':
+ quiet++;
+ break;
+
+ case 'r':
+ if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_CHECKDUPRR;
+ zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
+ } else if (ARGCMP("fail")) {
+ zone_options |= DNS_ZONEOPT_CHECKDUPRR |
+ DNS_ZONEOPT_CHECKDUPRRFAIL;
+ } else if (ARGCMP("ignore")) {
+ zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
+ DNS_ZONEOPT_CHECKDUPRRFAIL);
+ } else {
+ fprintf(stderr, "invalid argument to -r: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 's':
+ if (ARGCMP("full")) {
+ outputstyle = &dns_master_style_full;
+ } else if (ARGCMP("relative")) {
+ outputstyle = &dns_master_style_default;
+ } else {
+ fprintf(stderr,
+ "unknown or unsupported style: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 't':
+ result = isc_dir_chroot(isc_commandline_argument);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "isc_dir_chroot: %s: %s\n",
+ isc_commandline_argument,
+ isc_result_totext(result));
+ exit(1);
+ }
+ break;
+
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+
+ case 'w':
+ workdir = isc_commandline_argument;
+ break;
+
+ case 'D':
+ dumpzone++;
+ break;
+
+ case 'M':
+ if (ARGCMP("fail")) {
+ zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
+ } else if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_WARNMXCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
+ } else if (ARGCMP("ignore")) {
+ zone_options |= DNS_ZONEOPT_WARNMXCNAME;
+ zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
+ } else {
+ fprintf(stderr, "invalid argument to -M: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'S':
+ if (ARGCMP("fail")) {
+ zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
+ } else if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
+ } else if (ARGCMP("ignore")) {
+ zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
+ } else {
+ fprintf(stderr, "invalid argument to -S: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'T':
+ if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_CHECKSPF;
+ } else if (ARGCMP("ignore")) {
+ zone_options &= ~DNS_ZONEOPT_CHECKSPF;
+ } else {
+ fprintf(stderr, "invalid argument to -T: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'W':
+ if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
+ } else if (ARGCMP("ignore")) {
+ zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
+ }
+ break;
+
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ prog_name, isc_commandline_option);
+ }
+ FALLTHROUGH;
+ case 'h':
+ usage();
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", prog_name,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (workdir != NULL) {
+ result = isc_dir_chdir(workdir);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "isc_dir_chdir: %s: %s\n", workdir,
+ isc_result_totext(result));
+ exit(1);
+ }
+ }
+
+ if (inputformatstr != NULL) {
+ if (strcasecmp(inputformatstr, "text") == 0) {
+ inputformat = dns_masterformat_text;
+ } else if (strcasecmp(inputformatstr, "raw") == 0) {
+ inputformat = dns_masterformat_raw;
+ } else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
+ inputformat = dns_masterformat_raw;
+ fprintf(stderr, "WARNING: input format raw, version "
+ "ignored\n");
+ } else {
+ fprintf(stderr, "unknown file format: %s\n",
+ inputformatstr);
+ exit(1);
+ }
+ }
+
+ if (outputformatstr != NULL) {
+ if (strcasecmp(outputformatstr, "text") == 0) {
+ outputformat = dns_masterformat_text;
+ } else if (strcasecmp(outputformatstr, "raw") == 0) {
+ outputformat = dns_masterformat_raw;
+ } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
+ char *end;
+
+ outputformat = dns_masterformat_raw;
+ rawversion = strtol(outputformatstr + 4, &end, 10);
+ if (end == outputformatstr + 4 || *end != '\0' ||
+ rawversion > 1U)
+ {
+ fprintf(stderr, "unknown raw format version\n");
+ exit(1);
+ }
+ } else {
+ fprintf(stderr, "unknown file format: %s\n",
+ outputformatstr);
+ exit(1);
+ }
+ }
+
+ if (progmode == progmode_compile) {
+ dumpzone = 1; /* always dump */
+ logdump = !quiet;
+ if (output_filename == NULL) {
+ fprintf(stderr, "output file required, but not "
+ "specified\n");
+ usage();
+ }
+ }
+
+ if (output_filename != NULL) {
+ dumpzone = 1;
+ }
+
+ /*
+ * If we are printing to stdout then send the informational
+ * output to stderr.
+ */
+ if (dumpzone &&
+ (output_filename == NULL || strcmp(output_filename, "-") == 0 ||
+ strcmp(output_filename, "/dev/fd/1") == 0 ||
+ strcmp(output_filename, "/dev/stdout") == 0))
+ {
+ errout = stderr;
+ logdump = false;
+ }
+
+ if (argc - isc_commandline_index < 1 ||
+ argc - isc_commandline_index > 2)
+ {
+ usage();
+ }
+
+ isc_mem_create(&mctx);
+ if (!quiet) {
+ RUNTIME_CHECK(setup_logging(mctx, errout, &lctx) ==
+ ISC_R_SUCCESS);
+ }
+
+ origin = argv[isc_commandline_index++];
+
+ if (isc_commandline_index == argc) {
+ /* "-" will be interpreted as stdin */
+ filename = "-";
+ } else {
+ filename = argv[isc_commandline_index];
+ }
+
+ isc_commandline_index++;
+
+ result = load_zone(mctx, origin, filename, inputformat, classname,
+ maxttl, &zone);
+
+ if (snset) {
+ dns_master_initrawheader(&header);
+ header.flags = DNS_MASTERRAW_SOURCESERIALSET;
+ header.sourceserial = serialnum;
+ dns_zone_setrawdata(zone, &header);
+ }
+
+ if (result == ISC_R_SUCCESS && dumpzone) {
+ if (logdump) {
+ fprintf(errout, "dump zone to %s...", output_filename);
+ fflush(errout);
+ }
+ result = dump_zone(origin, zone, output_filename, outputformat,
+ outputstyle, rawversion);
+ if (logdump) {
+ fprintf(errout, "done\n");
+ }
+ }
+
+ if (!quiet && result == ISC_R_SUCCESS) {
+ fprintf(errout, "OK\n");
+ }
+ destroy();
+ if (lctx != NULL) {
+ isc_log_destroy(&lctx);
+ }
+ isc_mem_destroy(&mctx);
+
+ return ((result == ISC_R_SUCCESS) ? 0 : 1);
+}
diff --git a/bin/check/named-checkzone.rst b/bin/check/named-checkzone.rst
new file mode 100644
index 0000000..563752f
--- /dev/null
+++ b/bin/check/named-checkzone.rst
@@ -0,0 +1,222 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. BEWARE: Do not forget to edit also named-compilezone.rst!
+
+.. iscman:: named-checkzone
+.. program:: named-checkzone
+.. _man_named-checkzone:
+
+named-checkzone - zone file validation tool
+-------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`named-checkzone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-o** filename] [**-r** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] {zonename} {filename}
+
+Description
+~~~~~~~~~~~
+
+:program:`named-checkzone` checks the syntax and integrity of a zone file. It
+performs the same checks as :iscman:`named` does when loading a zone. This
+makes :program:`named-checkzone` useful for checking zone files before
+configuring them into a name server.
+
+Options
+~~~~~~~
+
+.. option:: -d
+
+ This option enables debugging.
+
+.. option:: -h
+
+ This option prints the usage summary and exits.
+
+.. option:: -q
+
+ This option sets quiet mode, which only sets an exit code to indicate
+ successful or failed completion.
+
+.. option:: -v
+
+ This option prints the version of the :program:`named-checkzone` program and exits.
+
+.. option:: -j
+
+ When loading a zone file, this option tells :iscman:`named` to read the journal if it exists. The journal
+ file name is assumed to be the zone file name with the
+ string ``.jnl`` appended.
+
+.. option:: -J filename
+
+ When loading the zone file, this option tells :iscman:`named` to read the journal from the given file, if
+ it exists. This implies :option:`-j`.
+
+.. option:: -c class
+
+ This option specifies the class of the zone. If not specified, ``IN`` is assumed.
+
+.. option:: -i mode
+
+ This option performs post-load zone integrity checks. Possible modes are
+ ``full`` (the default), ``full-sibling``, ``local``,
+ ``local-sibling``, and ``none``.
+
+ Mode ``full`` checks that MX records refer to A or AAAA records
+ (both in-zone and out-of-zone hostnames). Mode ``local`` only
+ checks MX records which refer to in-zone hostnames.
+
+ Mode ``full`` checks that SRV records refer to A or AAAA records
+ (both in-zone and out-of-zone hostnames). Mode ``local`` only
+ checks SRV records which refer to in-zone hostnames.
+
+ Mode ``full`` checks that delegation NS records refer to A or AAAA
+ records (both in-zone and out-of-zone hostnames). It also checks that
+ glue address records in the zone match those advertised by the child.
+ Mode ``local`` only checks NS records which refer to in-zone
+ hostnames or verifies that some required glue exists, i.e., when the
+ name server is in a child zone.
+
+ Modes ``full-sibling`` and ``local-sibling`` disable sibling glue
+ checks, but are otherwise the same as ``full`` and ``local``,
+ respectively.
+
+ Mode ``none`` disables the checks.
+
+.. option:: -f format
+
+ This option specifies the format of the zone file. Possible formats are
+ ``text`` (the default), and ``raw``.
+
+.. option:: -F format
+
+ This option specifies the format of the output file specified. For
+ :program:`named-checkzone`, this does not have any effect unless it dumps
+ the zone contents.
+
+ Possible formats are ``text`` (the default), which is the standard
+ textual representation of the zone, and ``raw`` and ``raw=N``, which
+ store the zone in a binary format for rapid loading by :iscman:`named`.
+ ``raw=N`` specifies the format version of the raw zone file: if ``N`` is
+ 0, the raw file can be read by any version of :iscman:`named`; if N is 1, the
+ file can only be read by release 9.9.0 or higher. The default is 1.
+
+.. option:: -k mode
+
+ This option performs ``check-names`` checks with the specified failure mode.
+ Possible modes are ``fail``, ``warn`` (the default), and ``ignore``.
+
+.. option:: -l ttl
+
+ This option sets a maximum permissible TTL for the input file. Any record with a
+ TTL higher than this value causes the zone to be rejected. This
+ is similar to using the ``max-zone-ttl`` option in :iscman:`named.conf`.
+
+.. option:: -L serial
+
+ When compiling a zone to ``raw`` format, this option sets the "source
+ serial" value in the header to the specified serial number. This is
+ expected to be used primarily for testing purposes.
+
+.. option:: -m mode
+
+ This option specifies whether MX records should be checked to see if they are
+ addresses. Possible modes are ``fail``, ``warn`` (the default), and
+ ``ignore``.
+
+.. option:: -M mode
+
+ This option checks whether a MX record refers to a CNAME. Possible modes are
+ ``fail``, ``warn`` (the default), and ``ignore``.
+
+.. option:: -n mode
+
+ This option specifies whether NS records should be checked to see if they are
+ addresses. Possible modes are ``fail``, ``warn`` (the default), and ``ignore``.
+
+.. option:: -o filename
+
+ This option writes the zone output to ``filename``. If ``filename`` is ``-``, then
+ the zone output is written to standard output.
+
+.. option:: -r mode
+
+ This option checks for records that are treated as different by DNSSEC but are
+ semantically equal in plain DNS. Possible modes are ``fail``,
+ ``warn`` (the default), and ``ignore``.
+
+.. option:: -s style
+
+ This option specifies the style of the dumped zone file. Possible styles are
+ ``full`` (the default) and ``relative``. The ``full`` format is most
+ suitable for processing automatically by a separate script.
+ The relative format is more human-readable and is thus
+ suitable for editing by hand. This does not have any effect unless it dumps
+ the zone contents. It also does not have any meaning if the output format
+ is not text.
+
+.. option:: -S mode
+
+ This option checks whether an SRV record refers to a CNAME. Possible modes are
+ ``fail``, ``warn`` (the default), and ``ignore``.
+
+.. option:: -t directory
+
+ This option tells :iscman:`named` to chroot to ``directory``, so that ``include`` directives in the
+ configuration file are processed as if run by a similarly chrooted
+ :iscman:`named`.
+
+.. option:: -T mode
+
+ This option checks whether Sender Policy Framework (SPF) records exist and issues a
+ warning if an SPF-formatted TXT record is not also present. Possible
+ modes are ``warn`` (the default) and ``ignore``.
+
+.. option:: -w directory
+
+ This option instructs :iscman:`named` to chdir to ``directory``, so that relative filenames in master file
+ ``$INCLUDE`` directives work. This is similar to the directory clause in
+ :iscman:`named.conf`.
+
+.. option:: -D
+
+ This option dumps the zone file in canonical format.
+
+.. option:: -W mode
+
+ This option specifies whether to check for non-terminal wildcards. Non-terminal
+ wildcards are almost always the result of a failure to understand the
+ wildcard matching algorithm (:rfc:`4592`). Possible modes are ``warn``
+ (the default) and ``ignore``.
+
+.. option:: zonename
+
+ This indicates the domain name of the zone being checked.
+
+.. option:: filename
+
+ This is the name of the zone file.
+
+Return Values
+~~~~~~~~~~~~~
+
+:program:`named-checkzone` returns an exit status of 1 if errors were detected
+and 0 otherwise.
+
+See Also
+~~~~~~~~
+
+:iscman:`named(8) <named>`, :iscman:`named-checkconf(8) <named-checkconf>`, :iscman:`named-compilezone(8) <named-compilezone>`, :rfc:`1035`, BIND 9 Administrator Reference
+Manual.
diff --git a/bin/check/named-compilezone.rst b/bin/check/named-compilezone.rst
new file mode 100644
index 0000000..41ecff7
--- /dev/null
+++ b/bin/check/named-compilezone.rst
@@ -0,0 +1,224 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. BEWARE: Do not forget to edit also named-checkzone.rst!
+
+.. iscman:: named-compilezone
+.. program:: named-compilezone
+.. _man_named-compilezone:
+
+named-compilezone - zone file converting tool
+---------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`named-compilezone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-r** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] {**-o** filename} {zonename} {filename}
+
+Description
+~~~~~~~~~~~
+
+:program:`named-compilezone` checks the syntax and integrity of a zone file,
+and dumps the zone contents to a specified file in a specified format.
+It applies strict check levels by default, since the
+dump output is used as an actual zone file loaded by :iscman:`named`.
+When manually specified otherwise, the check levels must at least be as
+strict as those specified in the :iscman:`named` configuration file.
+
+Options
+~~~~~~~
+
+.. option:: -d
+
+ This option enables debugging.
+
+.. option:: -h
+
+ This option prints the usage summary and exits.
+
+.. option:: -q
+
+ This option sets quiet mode, which only sets an exit code to indicate
+ successful or failed completion.
+
+.. option:: -v
+
+ This option prints the version of the :iscman:`named-checkzone` program and exits.
+
+.. option:: -j
+
+ When loading a zone file, this option tells :iscman:`named` to read the journal if it exists. The journal
+ file name is assumed to be the zone file name with the
+ string ``.jnl`` appended.
+
+.. option:: -J filename
+
+ When loading the zone file, this option tells :iscman:`named` to read the journal from the given file, if
+ it exists. This implies :option:`-j`.
+
+.. option:: -c class
+
+ This option specifies the class of the zone. If not specified, ``IN`` is assumed.
+
+.. option:: -i mode
+
+ This option performs post-load zone integrity checks. Possible modes are
+ ``full`` (the default), ``full-sibling``, ``local``,
+ ``local-sibling``, and ``none``.
+
+ Mode ``full`` checks that MX records refer to A or AAAA records
+ (both in-zone and out-of-zone hostnames). Mode ``local`` only
+ checks MX records which refer to in-zone hostnames.
+
+ Mode ``full`` checks that SRV records refer to A or AAAA records
+ (both in-zone and out-of-zone hostnames). Mode ``local`` only
+ checks SRV records which refer to in-zone hostnames.
+
+ Mode ``full`` checks that delegation NS records refer to A or AAAA
+ records (both in-zone and out-of-zone hostnames). It also checks that
+ glue address records in the zone match those advertised by the child.
+ Mode ``local`` only checks NS records which refer to in-zone
+ hostnames or verifies that some required glue exists, i.e., when the
+ name server is in a child zone.
+
+ Modes ``full-sibling`` and ``local-sibling`` disable sibling glue
+ checks, but are otherwise the same as ``full`` and ``local``,
+ respectively.
+
+ Mode ``none`` disables the checks.
+
+.. option:: -f format
+
+ This option specifies the format of the zone file. Possible formats are
+ ``text`` (the default), and ``raw``.
+
+.. option:: -F format
+
+ This option specifies the format of the output file specified. For
+ :iscman:`named-checkzone`, this does not have any effect unless it dumps
+ the zone contents.
+
+ Possible formats are ``text`` (the default), which is the standard
+ textual representation of the zone, and ``raw`` and ``raw=N``, which
+ store the zone in a binary format for rapid loading by :iscman:`named`.
+ ``raw=N`` specifies the format version of the raw zone file: if ``N`` is
+ 0, the raw file can be read by any version of :iscman:`named`; if N is 1, the
+ file can only be read by release 9.9.0 or higher. The default is 1.
+
+.. option:: -k mode
+
+ This option performs ``check-names`` checks with the specified failure mode.
+ Possible modes are ``fail`` (the default), ``warn``, and ``ignore``.
+
+.. option:: -l ttl
+
+ This option sets a maximum permissible TTL for the input file. Any record with a
+ TTL higher than this value causes the zone to be rejected. This
+ is similar to using the ``max-zone-ttl`` option in :iscman:`named.conf`.
+
+.. option:: -L serial
+
+ When compiling a zone to ``raw`` format, this option sets the "source
+ serial" value in the header to the specified serial number. This is
+ expected to be used primarily for testing purposes.
+
+.. option:: -m mode
+
+ This option specifies whether MX records should be checked to see if they are
+ addresses. Possible modes are ``fail``, ``warn`` (the default), and
+ ``ignore``.
+
+.. option:: -M mode
+
+ This option checks whether a MX record refers to a CNAME. Possible modes are
+ ``fail``, ``warn`` (the default), and ``ignore``.
+
+.. option:: -n mode
+
+ This option specifies whether NS records should be checked to see if they are
+ addresses. Possible modes are ``fail`` (the default), ``warn``, and
+ ``ignore``.
+
+.. option:: -o filename
+
+ This option writes the zone output to ``filename``. If ``filename`` is ``-``, then
+ the zone output is written to standard output. This is mandatory for :program:`named-compilezone`.
+
+.. option:: -r mode
+
+ This option checks for records that are treated as different by DNSSEC but are
+ semantically equal in plain DNS. Possible modes are ``fail``,
+ ``warn`` (the default), and ``ignore``.
+
+.. option:: -s style
+
+ This option specifies the style of the dumped zone file. Possible styles are
+ ``full`` (the default) and ``relative``. The ``full`` format is most
+ suitable for processing automatically by a separate script.
+ The relative format is more human-readable and is thus
+ suitable for editing by hand.
+
+.. option:: -S mode
+
+ This option checks whether an SRV record refers to a CNAME. Possible modes are
+ ``fail``, ``warn`` (the default), and ``ignore``.
+
+.. option:: -t directory
+
+ This option tells :iscman:`named` to chroot to ``directory``, so that ``include`` directives in the
+ configuration file are processed as if run by a similarly chrooted
+ :iscman:`named`.
+
+.. option:: -T mode
+
+ This option checks whether Sender Policy Framework (SPF) records exist and issues a
+ warning if an SPF-formatted TXT record is not also present. Possible
+ modes are ``warn`` (the default) and ``ignore``.
+
+.. option:: -w directory
+
+ This option instructs :iscman:`named` to chdir to ``directory``, so that relative filenames in master file
+ ``$INCLUDE`` directives work. This is similar to the directory clause in
+ :iscman:`named.conf`.
+
+.. option:: -D
+
+ This option dumps the zone file in canonical format. This is always enabled for
+ :program:`named-compilezone`.
+
+.. option:: -W mode
+
+ This option specifies whether to check for non-terminal wildcards. Non-terminal
+ wildcards are almost always the result of a failure to understand the
+ wildcard matching algorithm (:rfc:`4592`). Possible modes are ``warn``
+ (the default) and ``ignore``.
+
+.. option:: zonename
+
+ This indicates the domain name of the zone being checked.
+
+.. option:: filename
+
+ This is the name of the zone file.
+
+Return Values
+~~~~~~~~~~~~~
+
+:program:`named-compilezone` returns an exit status of 1 if errors were detected
+and 0 otherwise.
+
+See Also
+~~~~~~~~
+
+:iscman:`named(8) <named>`, :iscman:`named-checkconf(8) <named-checkconf>`, :iscman:`named-checkzone(8) <named-checkzone>`, :rfc:`1035`,
+BIND 9 Administrator Reference Manual.
diff --git a/bin/confgen/Makefile.am b/bin/confgen/Makefile.am
new file mode 100644
index 0000000..c1dca43
--- /dev/null
+++ b/bin/confgen/Makefile.am
@@ -0,0 +1,30 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) \
+ -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\"
+
+LDADD += \
+ libconfgen.la \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+
+noinst_LTLIBRARIES = libconfgen.la
+
+libconfgen_la_SOURCES = \
+ include/confgen/os.h \
+ keygen.c \
+ keygen.h \
+ os.c \
+ util.c \
+ util.h
+
+sbin_PROGRAMS = tsig-keygen rndc-confgen
+
+install-exec-hook:
+ ln -f $(DESTDIR)$(sbindir)/tsig-keygen \
+ $(DESTDIR)$(sbindir)/ddns-confgen
+
+uninstall-hook:
+ -rm -f $(DESTDIR)$(sbindir)/ddns-confgen
diff --git a/bin/confgen/Makefile.in b/bin/confgen/Makefile.in
new file mode 100644
index 0000000..5589f9e
--- /dev/null
+++ b/bin/confgen/Makefile.in
@@ -0,0 +1,876 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+sbin_PROGRAMS = tsig-keygen$(EXEEXT) rndc-confgen$(EXEEXT)
+subdir = bin/confgen
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)"
+PROGRAMS = $(sbin_PROGRAMS)
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libconfgen_la_LIBADD =
+am_libconfgen_la_OBJECTS = keygen.lo os.lo util.lo
+libconfgen_la_OBJECTS = $(am_libconfgen_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+rndc_confgen_SOURCES = rndc-confgen.c
+rndc_confgen_OBJECTS = rndc-confgen.$(OBJEXT)
+rndc_confgen_LDADD = $(LDADD)
+rndc_confgen_DEPENDENCIES = libconfgen.la $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+tsig_keygen_SOURCES = tsig-keygen.c
+tsig_keygen_OBJECTS = tsig-keygen.$(OBJEXT)
+tsig_keygen_LDADD = $(LDADD)
+tsig_keygen_DEPENDENCIES = libconfgen.la $(LIBISC_LIBS) $(LIBDNS_LIBS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/keygen.Plo ./$(DEPDIR)/os.Plo \
+ ./$(DEPDIR)/rndc-confgen.Po ./$(DEPDIR)/tsig-keygen.Po \
+ ./$(DEPDIR)/util.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libconfgen_la_SOURCES) rndc-confgen.c tsig-keygen.c
+DIST_SOURCES = $(libconfgen_la_SOURCES) rndc-confgen.c tsig-keygen.c
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \
+ -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\"
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD = libconfgen.la $(LIBISC_LIBS) $(LIBDNS_LIBS)
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+noinst_LTLIBRARIES = libconfgen.la
+libconfgen_la_SOURCES = \
+ include/confgen/os.h \
+ keygen.c \
+ keygen.h \
+ os.c \
+ util.c \
+ util.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/confgen/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/confgen/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libconfgen.la: $(libconfgen_la_OBJECTS) $(libconfgen_la_DEPENDENCIES) $(EXTRA_libconfgen_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libconfgen_la_OBJECTS) $(libconfgen_la_LIBADD) $(LIBS)
+
+rndc-confgen$(EXEEXT): $(rndc_confgen_OBJECTS) $(rndc_confgen_DEPENDENCIES) $(EXTRA_rndc_confgen_DEPENDENCIES)
+ @rm -f rndc-confgen$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(rndc_confgen_OBJECTS) $(rndc_confgen_LDADD) $(LIBS)
+
+tsig-keygen$(EXEEXT): $(tsig_keygen_OBJECTS) $(tsig_keygen_DEPENDENCIES) $(EXTRA_tsig_keygen_DEPENDENCIES)
+ @rm -f tsig-keygen$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(tsig_keygen_OBJECTS) $(tsig_keygen_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keygen.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndc-confgen.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsig-keygen.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/keygen.Plo
+ -rm -f ./$(DEPDIR)/os.Plo
+ -rm -f ./$(DEPDIR)/rndc-confgen.Po
+ -rm -f ./$(DEPDIR)/tsig-keygen.Po
+ -rm -f ./$(DEPDIR)/util.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/keygen.Plo
+ -rm -f ./$(DEPDIR)/os.Plo
+ -rm -f ./$(DEPDIR)/rndc-confgen.Po
+ -rm -f ./$(DEPDIR)/tsig-keygen.Po
+ -rm -f ./$(DEPDIR)/util.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am: uninstall-sbinPROGRAMS
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-hook
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-exec-am install-strip uninstall-am
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir doc-am doc-local dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-exec-hook install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \
+ uninstall-am uninstall-hook uninstall-sbinPROGRAMS unit-am \
+ unit-local
+
+.PRECIOUS: Makefile
+
+
+install-exec-hook:
+ ln -f $(DESTDIR)$(sbindir)/tsig-keygen \
+ $(DESTDIR)$(sbindir)/ddns-confgen
+
+uninstall-hook:
+ -rm -f $(DESTDIR)$(sbindir)/ddns-confgen
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/confgen/ddns-confgen.rst b/bin/confgen/ddns-confgen.rst
new file mode 100644
index 0000000..9dd9d5e
--- /dev/null
+++ b/bin/confgen/ddns-confgen.rst
@@ -0,0 +1,96 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. BEWARE: Do not forget to edit also tsig-keygen.rst!
+
+.. iscman:: ddns-confgen
+.. program:: ddns-confgen
+.. _man_ddns-confgen:
+
+ddns-confgen - TSIG key generation tool
+---------------------------------------
+
+Synopsis
+~~~~~~~~
+:program:`ddns-confgen` [**-a** algorithm] [**-h**] [**-k** keyname] [**-q**] [**-s** name] [**-z** zone]
+
+Description
+~~~~~~~~~~~
+
+:program:`ddns-confgen` is an utility that generates keys for use in TSIG signing.
+The resulting keys can be used, for example, to secure dynamic DNS updates
+to a zone, or for the :iscman:`rndc` command channel.
+
+The key name can specified using :option:`-k` parameter and defaults to ``ddns-key``.
+The generated key is accompanied by configuration text and instructions that
+can be used with :iscman:`nsupdate` and :iscman:`named` when setting up dynamic DNS,
+including an example ``update-policy`` statement.
+(This usage is similar to the :iscman:`rndc-confgen` command for setting up
+command-channel security.)
+
+Note that :iscman:`named` itself can configure a local DDNS key for use with
+:option:`nsupdate -l`; it does this when a zone is configured with
+``update-policy local;``. :program:`ddns-confgen` is only needed when a more
+elaborate configuration is required: for instance, if :iscman:`nsupdate` is to
+be used from a remote system.
+
+Options
+~~~~~~~
+
+.. option:: -a algorithm
+
+ This option specifies the algorithm to use for the TSIG key. Available
+ choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384,
+ and hmac-sha512. The default is hmac-sha256. Options are
+ case-insensitive, and the "hmac-" prefix may be omitted.
+
+.. option:: -h
+
+ This option prints a short summary of options and arguments.
+
+.. option:: -k keyname
+
+ This option specifies the key name of the DDNS authentication key. The
+ default is ``ddns-key`` when neither the :option:`-s` nor :option:`-z` option is
+ specified; otherwise, the default is ``ddns-key`` as a separate label
+ followed by the argument of the option, e.g., ``ddns-key.example.com.``
+ The key name must have the format of a valid domain name, consisting of
+ letters, digits, hyphens, and periods.
+
+.. option:: -q
+
+ This option enables quiet mode, which prints only the key, with no
+ explanatory text or usage examples. This is essentially identical to
+ :iscman:`tsig-keygen`.
+
+.. option:: -s name
+
+ This option generates a configuration example to allow dynamic updates
+ of a single hostname. The example :iscman:`named.conf` text shows how to set
+ an update policy for the specified name using the "name" nametype. The
+ default key name is ``ddns-key.name``. Note that the "self" nametype
+ cannot be used, since the name to be updated may differ from the key
+ name. This option cannot be used with the :option:`-z` option.
+
+.. option:: -z zone
+
+ This option generates a configuration example to allow
+ dynamic updates of a zone. The example :iscman:`named.conf` text shows how
+ to set an update policy for the specified zone using the "zonesub"
+ nametype, allowing updates to all subdomain names within that zone.
+ This option cannot be used with the :option:`-s` option.
+
+See Also
+~~~~~~~~
+
+:iscman:`nsupdate(1) <nsupdate>`, :iscman:`named.conf(5) <named.conf>`, :iscman:`named(8) <named>`, BIND 9 Administrator Reference Manual.
diff --git a/bin/confgen/include/confgen/os.h b/bin/confgen/include/confgen/os.h
new file mode 100644
index 0000000..2a924a3
--- /dev/null
+++ b/bin/confgen/include/confgen/os.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#pragma once
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+int
+set_user(FILE *fd, const char *user);
+/*%<
+ * Set the owner of the file referenced by 'fd' to 'user'.
+ * Returns:
+ * 0 success
+ * -1 insufficient permissions, or 'user' does not exist.
+ */
+
+ISC_LANG_ENDDECLS
diff --git a/bin/confgen/keygen.c b/bin/confgen/keygen.c
new file mode 100644
index 0000000..97dfa34
--- /dev/null
+++ b/bin/confgen/keygen.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include "keygen.h"
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+
+#include <dst/dst.h>
+
+#include <confgen/os.h>
+
+#include "util.h"
+
+/*%
+ * Convert string to algorithm type.
+ */
+dns_secalg_t
+alg_fromtext(const char *name) {
+ const char *p = name;
+ if (strncasecmp(p, "hmac-", 5) == 0) {
+ p = &name[5];
+ }
+
+ if (strcasecmp(p, "md5") == 0) {
+ return (DST_ALG_HMACMD5);
+ }
+ if (strcasecmp(p, "sha1") == 0) {
+ return (DST_ALG_HMACSHA1);
+ }
+ if (strcasecmp(p, "sha224") == 0) {
+ return (DST_ALG_HMACSHA224);
+ }
+ if (strcasecmp(p, "sha256") == 0) {
+ return (DST_ALG_HMACSHA256);
+ }
+ if (strcasecmp(p, "sha384") == 0) {
+ return (DST_ALG_HMACSHA384);
+ }
+ if (strcasecmp(p, "sha512") == 0) {
+ return (DST_ALG_HMACSHA512);
+ }
+ return (DST_ALG_UNKNOWN);
+}
+
+/*%
+ * Return default keysize for a given algorithm type.
+ */
+int
+alg_bits(dns_secalg_t alg) {
+ switch (alg) {
+ case DST_ALG_HMACMD5:
+ return (128);
+ case DST_ALG_HMACSHA1:
+ return (160);
+ case DST_ALG_HMACSHA224:
+ return (224);
+ case DST_ALG_HMACSHA256:
+ return (256);
+ case DST_ALG_HMACSHA384:
+ return (384);
+ case DST_ALG_HMACSHA512:
+ return (512);
+ default:
+ return (0);
+ }
+}
+
+/*%
+ * Generate a key of size 'keysize' and place it in 'key_txtbuffer'
+ */
+void
+generate_key(isc_mem_t *mctx, dns_secalg_t alg, int keysize,
+ isc_buffer_t *key_txtbuffer) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_buffer_t key_rawbuffer;
+ isc_region_t key_rawregion;
+ char key_rawsecret[64];
+ dst_key_t *key = NULL;
+
+ switch (alg) {
+ case DST_ALG_HMACMD5:
+ case DST_ALG_HMACSHA1:
+ case DST_ALG_HMACSHA224:
+ case DST_ALG_HMACSHA256:
+ if (keysize < 1 || keysize > 512) {
+ fatal("keysize %d out of range (must be 1-512)\n",
+ keysize);
+ }
+ break;
+ case DST_ALG_HMACSHA384:
+ case DST_ALG_HMACSHA512:
+ if (keysize < 1 || keysize > 1024) {
+ fatal("keysize %d out of range (must be 1-1024)\n",
+ keysize);
+ }
+ break;
+ default:
+ fatal("unsupported algorithm %d\n", alg);
+ }
+
+ DO("initialize dst library", dst_lib_init(mctx, NULL));
+
+ DO("generate key",
+ dst_key_generate(dns_rootname, alg, keysize, 0, 0, DNS_KEYPROTO_ANY,
+ dns_rdataclass_in, mctx, &key, NULL));
+
+ isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret));
+
+ DO("dump key to buffer", dst_key_tobuffer(key, &key_rawbuffer));
+
+ isc_buffer_usedregion(&key_rawbuffer, &key_rawregion);
+
+ DO("bsse64 encode secret",
+ isc_base64_totext(&key_rawregion, -1, "", key_txtbuffer));
+
+ if (key != NULL) {
+ dst_key_free(&key);
+ }
+
+ dst_lib_destroy();
+}
+
+/*%
+ * Write a key file to 'keyfile'. If 'user' is non-NULL,
+ * make that user the owner of the file. The key will have
+ * the name 'keyname' and the secret in the buffer 'secret'.
+ */
+void
+write_key_file(const char *keyfile, const char *user, const char *keyname,
+ isc_buffer_t *secret, dns_secalg_t alg) {
+ isc_result_t result;
+ const char *algname = dst_hmac_algorithm_totext(alg);
+ FILE *fd = NULL;
+
+ DO("create keyfile", isc_file_safecreate(keyfile, &fd));
+
+ if (user != NULL) {
+ if (set_user(fd, user) == -1) {
+ fatal("unable to set file owner\n");
+ }
+ }
+
+ fprintf(fd,
+ "key \"%s\" {\n\talgorithm %s;\n"
+ "\tsecret \"%.*s\";\n};\n",
+ keyname, algname, (int)isc_buffer_usedlength(secret),
+ (char *)isc_buffer_base(secret));
+ fflush(fd);
+ if (ferror(fd)) {
+ fatal("write to %s failed\n", keyfile);
+ }
+ if (fclose(fd)) {
+ fatal("fclose(%s) failed\n", keyfile);
+ }
+}
diff --git a/bin/confgen/keygen.h b/bin/confgen/keygen.h
new file mode 100644
index 0000000..f5b7a55
--- /dev/null
+++ b/bin/confgen/keygen.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <isc/buffer.h>
+#include <isc/lang.h>
+#include <isc/mem.h>
+
+#include <dns/secalg.h>
+
+ISC_LANG_BEGINDECLS
+
+void
+generate_key(isc_mem_t *mctx, dns_secalg_t alg, int keysize,
+ isc_buffer_t *key_txtbuffer);
+
+void
+write_key_file(const char *keyfile, const char *user, const char *keyname,
+ isc_buffer_t *secret, dns_secalg_t alg);
+
+const char *
+alg_totext(dns_secalg_t alg);
+dns_secalg_t
+alg_fromtext(const char *name);
+int
+alg_bits(dns_secalg_t alg);
+
+ISC_LANG_ENDDECLS
diff --git a/bin/confgen/os.c b/bin/confgen/os.c
new file mode 100644
index 0000000..445d64b
--- /dev/null
+++ b/bin/confgen/os.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <confgen/os.h>
+
+int
+set_user(FILE *fd, const char *user) {
+ struct passwd *pw;
+
+ pw = getpwnam(user);
+ if (pw == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ return (fchown(fileno(fd), pw->pw_uid, -1));
+}
diff --git a/bin/confgen/rndc-confgen.c b/bin/confgen/rndc-confgen.c
new file mode 100644
index 0000000..8179295
--- /dev/null
+++ b/bin/confgen/rndc-confgen.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+/**
+ * rndc-confgen generates configuration files for rndc. It can be used
+ * as a convenient alternative to writing the rndc.conf file and the
+ * corresponding controls and key statements in named.conf by hand.
+ * Alternatively, it can be run with the -a option to set up a
+ * rndc.key file and avoid the need for a rndc.conf file and a
+ * controls statement altogether.
+ */
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/assertions.h>
+#include <isc/attributes.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+
+#include <dst/dst.h>
+
+#include <confgen/os.h>
+
+#include "keygen.h"
+#include "util.h"
+
+#define DEFAULT_KEYNAME "rndc-key"
+#define DEFAULT_SERVER "127.0.0.1"
+#define DEFAULT_PORT 953
+
+static char program[256];
+const char *progname;
+
+bool verbose = false;
+
+const char *keyfile, *keydef;
+
+noreturn static void
+usage(int status);
+
+static void
+usage(int status) {
+ fprintf(stderr, "\
+Usage:\n\
+ %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] \
+[-s addr] [-t chrootdir] [-u user]\n\
+ -a: generate just the key clause and write it to keyfile (%s)\n\
+ -A alg: algorithm (default hmac-sha256)\n\
+ -b bits: from 1 through 512, default 256; total length of the secret\n\
+ -c keyfile: specify an alternate key file (requires -a)\n\
+ -k keyname: the name as it will be used in named.conf and rndc.conf\n\
+ -p port: the port named will listen on and rndc will connect to\n\
+ -q: suppress printing written key path\n\
+ -s addr: the address to which rndc should connect\n\
+ -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\
+ -u user: set the keyfile owner to \"user\" (requires -a)\n",
+ progname, keydef);
+
+ exit(status);
+}
+
+int
+main(int argc, char **argv) {
+ bool show_final_mem = false;
+ isc_buffer_t key_txtbuffer;
+ char key_txtsecret[256];
+ isc_mem_t *mctx = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ const char *keyname = NULL;
+ const char *serveraddr = NULL;
+ dns_secalg_t alg;
+ const char *algname;
+ char *p;
+ int ch;
+ int port;
+ int keysize = -1;
+ struct in_addr addr4_dummy;
+ struct in6_addr addr6_dummy;
+ char *chrootdir = NULL;
+ char *user = NULL;
+ bool keyonly = false;
+ bool quiet = false;
+ int len;
+
+ keydef = keyfile = RNDC_KEYFILE;
+
+ result = isc_file_progname(*argv, program, sizeof(program));
+ if (result != ISC_R_SUCCESS) {
+ memmove(program, "rndc-confgen", 13);
+ }
+ progname = program;
+
+ keyname = DEFAULT_KEYNAME;
+ alg = DST_ALG_HMACSHA256;
+ serveraddr = DEFAULT_SERVER;
+ port = DEFAULT_PORT;
+
+ isc_commandline_errprint = false;
+
+ while ((ch = isc_commandline_parse(argc, argv,
+ "aA:b:c:hk:Mmp:r:s:t:u:Vy")) != -1)
+ {
+ switch (ch) {
+ case 'a':
+ keyonly = true;
+ break;
+ case 'A':
+ algname = isc_commandline_argument;
+ alg = alg_fromtext(algname);
+ if (alg == DST_ALG_UNKNOWN) {
+ fatal("Unsupported algorithm '%s'", algname);
+ }
+ break;
+ case 'b':
+ keysize = strtol(isc_commandline_argument, &p, 10);
+ if (*p != '\0' || keysize < 0) {
+ fatal("-b requires a non-negative number");
+ }
+ break;
+ case 'c':
+ keyfile = isc_commandline_argument;
+ break;
+ case 'h':
+ usage(0);
+ case 'k':
+ case 'y': /* Compatible with rndc -y. */
+ keyname = isc_commandline_argument;
+ break;
+ case 'M':
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE;
+ break;
+
+ case 'm':
+ show_final_mem = true;
+ break;
+ case 'p':
+ port = strtol(isc_commandline_argument, &p, 10);
+ if (*p != '\0' || port < 0 || port > 65535) {
+ fatal("port '%s' out of range",
+ isc_commandline_argument);
+ }
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'r':
+ fatal("The -r option has been deprecated.");
+ break;
+ case 's':
+ serveraddr = isc_commandline_argument;
+ if (inet_pton(AF_INET, serveraddr, &addr4_dummy) != 1 &&
+ inet_pton(AF_INET6, serveraddr, &addr6_dummy) != 1)
+ {
+ fatal("-s should be an IPv4 or IPv6 address");
+ }
+ break;
+ case 't':
+ chrootdir = isc_commandline_argument;
+ break;
+ case 'u':
+ user = isc_commandline_argument;
+ break;
+ case 'V':
+ verbose = true;
+ break;
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ usage(1);
+ } else {
+ usage(0);
+ }
+ break;
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+ POST(argv);
+
+ if (argc > 0) {
+ usage(1);
+ }
+
+ if (alg == DST_ALG_HMACMD5) {
+ fprintf(stderr, "warning: use of hmac-md5 for RNDC keys "
+ "is deprecated; hmac-sha256 is now "
+ "recommended.\n");
+ }
+
+ if (keysize < 0) {
+ keysize = alg_bits(alg);
+ }
+ algname = dst_hmac_algorithm_totext(alg);
+
+ isc_mem_create(&mctx);
+ isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret));
+
+ generate_key(mctx, alg, keysize, &key_txtbuffer);
+
+ if (keyonly) {
+ write_key_file(keyfile, chrootdir == NULL ? user : NULL,
+ keyname, &key_txtbuffer, alg);
+ if (!quiet) {
+ printf("wrote key file \"%s\"\n", keyfile);
+ }
+
+ if (chrootdir != NULL) {
+ char *buf;
+ len = strlen(chrootdir) + strlen(keyfile) + 2;
+ buf = isc_mem_get(mctx, len);
+ snprintf(buf, len, "%s%s%s", chrootdir,
+ (*keyfile != '/') ? "/" : "", keyfile);
+
+ write_key_file(buf, user, keyname, &key_txtbuffer, alg);
+ if (!quiet) {
+ printf("wrote key file \"%s\"\n", buf);
+ }
+ isc_mem_put(mctx, buf, len);
+ }
+ } else {
+ printf("\
+# Start of rndc.conf\n\
+key \"%s\" {\n\
+ algorithm %s;\n\
+ secret \"%.*s\";\n\
+};\n\
+\n\
+options {\n\
+ default-key \"%s\";\n\
+ default-server %s;\n\
+ default-port %d;\n\
+};\n\
+# End of rndc.conf\n\
+\n\
+# Use with the following in named.conf, adjusting the allow list as needed:\n\
+# key \"%s\" {\n\
+# algorithm %s;\n\
+# secret \"%.*s\";\n\
+# };\n\
+# \n\
+# controls {\n\
+# inet %s port %d\n\
+# allow { %s; } keys { \"%s\"; };\n\
+# };\n\
+# End of named.conf\n",
+ keyname, algname,
+ (int)isc_buffer_usedlength(&key_txtbuffer),
+ (char *)isc_buffer_base(&key_txtbuffer), keyname,
+ serveraddr, port, keyname, algname,
+ (int)isc_buffer_usedlength(&key_txtbuffer),
+ (char *)isc_buffer_base(&key_txtbuffer), serveraddr,
+ port, serveraddr, keyname);
+ }
+
+ if (show_final_mem) {
+ isc_mem_stats(mctx, stderr);
+ }
+
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/confgen/rndc-confgen.rst b/bin/confgen/rndc-confgen.rst
new file mode 100644
index 0000000..0a91489
--- /dev/null
+++ b/bin/confgen/rndc-confgen.rst
@@ -0,0 +1,121 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: rndc-confgen
+.. program:: rndc-confgen
+.. _man_rndc-confgen:
+
+rndc-confgen - rndc key generation tool
+---------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`rndc-confgen` [**-a**] [**-A** algorithm] [**-b** keysize] [**-c** keyfile] [**-h**] [**-k** keyname] [**-p** port] [**-s** address] [**-t** chrootdir] [**-u** user]
+
+Description
+~~~~~~~~~~~
+
+:program:`rndc-confgen` generates configuration files for :iscman:`rndc`. It can be
+used as a convenient alternative to writing the :iscman:`rndc.conf` file and
+the corresponding ``controls`` and ``key`` statements in :iscman:`named.conf`
+by hand. Alternatively, it can be run with the :option:`-a` option to set up a
+``rndc.key`` file and avoid the need for a :iscman:`rndc.conf` file and a
+``controls`` statement altogether.
+
+Options
+~~~~~~~
+
+.. option:: -a
+
+ This option sets automatic :iscman:`rndc` configuration, which creates a file
+ |rndc_key| that is read by both :iscman:`rndc` and :iscman:`named` on startup.
+ The ``rndc.key`` file defines a default command channel and
+ authentication key allowing :iscman:`rndc` to communicate with :iscman:`named` on
+ the local host with no further configuration.
+
+ If a more elaborate configuration than that generated by
+ :option:`rndc-confgen -a` is required, for example if rndc is to be used
+ remotely, run :program:`rndc-confgen` without the :option:`-a` option
+ and set up :iscman:`rndc.conf` and :iscman:`named.conf` as directed.
+
+.. option:: -A algorithm
+
+ This option specifies the algorithm to use for the TSIG key. Available choices
+ are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384, and
+ hmac-sha512. The default is hmac-sha256.
+
+.. option:: -b keysize
+
+ This option specifies the size of the authentication key in bits. The size must be between
+ 1 and 512 bits; the default is the hash size.
+
+.. option:: -c keyfile
+
+ This option is used with the :option:`-a` option to specify an alternate location for
+ ``rndc.key``.
+
+.. option:: -h
+
+ This option prints a short summary of the options and arguments to
+ :program:`rndc-confgen`.
+
+.. option:: -k keyname
+
+ This option specifies the key name of the :iscman:`rndc` authentication key. This must be a
+ valid domain name. The default is ``rndc-key``.
+
+.. option:: -p port
+
+ This option specifies the command channel port where :iscman:`named` listens for
+ connections from :iscman:`rndc`. The default is 953.
+
+.. option:: -q
+
+ This option prevets printing the written path in automatic configuration mode.
+
+.. option:: -s address
+
+ This option specifies the IP address where :iscman:`named` listens for command-channel
+ connections from :iscman:`rndc`. The default is the loopback address
+ 127.0.0.1.
+
+.. option:: -t chrootdir
+
+ This option is used with the :option:`-a` option to specify a directory where :iscman:`named`
+ runs chrooted. An additional copy of the ``rndc.key`` is
+ written relative to this directory, so that it is found by the
+ chrooted :iscman:`named`.
+
+.. option:: -u user
+
+ This option is used with the :option:`-a` option to set the owner of the generated ``rndc.key`` file.
+ If :option:`-t` is also specified, only the file in the chroot
+ area has its owner changed.
+
+Examples
+~~~~~~~~
+
+To allow :iscman:`rndc` to be used with no manual configuration, run:
+
+``rndc-confgen -a``
+
+To print a sample :iscman:`rndc.conf` file and the corresponding ``controls`` and
+``key`` statements to be manually inserted into :iscman:`named.conf`, run:
+
+:program:`rndc-confgen`
+
+See Also
+~~~~~~~~
+
+:iscman:`rndc(8) <rndc>`, :iscman:`rndc.conf(5) <rndc.conf>`, :iscman:`named(8) <named>`, BIND 9 Administrator Reference Manual.
diff --git a/bin/confgen/tsig-keygen.c b/bin/confgen/tsig-keygen.c
new file mode 100644
index 0000000..b44f1a9
--- /dev/null
+++ b/bin/confgen/tsig-keygen.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+/**
+ * tsig-keygen generates TSIG keys that can be used in named configuration
+ * files for dynamic DNS.
+ */
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/assertions.h>
+#include <isc/attributes.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+
+#include <dst/dst.h>
+
+#include <confgen/os.h>
+
+#include "keygen.h"
+#include "util.h"
+
+#define KEYGEN_DEFAULT "tsig-key"
+#define CONFGEN_DEFAULT "ddns-key"
+
+static char program[256];
+const char *progname;
+static enum { progmode_keygen, progmode_confgen } progmode;
+bool verbose = false; /* needed by util.c but not used here */
+
+noreturn static void
+usage(int status);
+
+static void
+usage(int status) {
+ if (progmode == progmode_confgen) {
+ fprintf(stderr, "\
+Usage:\n\
+ %s [-a alg] [-k keyname] [-q] [-s name | -z zone]\n\
+ -a alg: algorithm (default hmac-sha256)\n\
+ -k keyname: name of the key as it will be used in named.conf\n\
+ -s name: domain name to be updated using the created key\n\
+ -z zone: name of the zone as it will be used in named.conf\n\
+ -q: quiet mode: print the key, with no explanatory text\n",
+ progname);
+ } else {
+ fprintf(stderr, "\
+Usage:\n\
+ %s [-a alg] [keyname]\n\
+ -a alg: algorithm (default hmac-sha256)\n\n",
+ progname);
+ }
+
+ exit(status);
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result = ISC_R_SUCCESS;
+ bool show_final_mem = false;
+ bool quiet = false;
+ isc_buffer_t key_txtbuffer;
+ char key_txtsecret[256];
+ isc_mem_t *mctx = NULL;
+ const char *keyname = NULL;
+ const char *zone = NULL;
+ const char *self_domain = NULL;
+ char *keybuf = NULL;
+ dns_secalg_t alg = DST_ALG_HMACSHA256;
+ const char *algname;
+ int keysize = 256;
+ int len = 0;
+ int ch;
+
+ result = isc_file_progname(*argv, program, sizeof(program));
+ if (result != ISC_R_SUCCESS) {
+ memmove(program, "tsig-keygen", 11);
+ }
+ progname = program;
+
+ /*
+ * Libtool doesn't preserve the program name prior to final
+ * installation. Remove the libtool prefix ("lt-").
+ */
+ if (strncmp(progname, "lt-", 3) == 0) {
+ progname += 3;
+ }
+
+#define PROGCMP(X) \
+ (strcasecmp(progname, X) == 0 || strcasecmp(progname, X ".exe") == 0)
+
+ if (PROGCMP("tsig-keygen")) {
+ progmode = progmode_keygen;
+ quiet = true;
+ } else if (PROGCMP("ddns-confgen")) {
+ progmode = progmode_confgen;
+ } else {
+ UNREACHABLE();
+ }
+
+ isc_commandline_errprint = false;
+
+ while ((ch = isc_commandline_parse(argc, argv, "a:hk:Mmr:qs:y:z:")) !=
+ -1)
+ {
+ switch (ch) {
+ case 'a':
+ algname = isc_commandline_argument;
+ alg = alg_fromtext(algname);
+ if (alg == DST_ALG_UNKNOWN) {
+ fatal("Unsupported algorithm '%s'", algname);
+ }
+ keysize = alg_bits(alg);
+ break;
+ case 'h':
+ usage(0);
+ case 'k':
+ case 'y':
+ if (progmode == progmode_confgen) {
+ keyname = isc_commandline_argument;
+ } else {
+ usage(1);
+ }
+ break;
+ case 'M':
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE;
+ break;
+ case 'm':
+ show_final_mem = true;
+ break;
+ case 'q':
+ if (progmode == progmode_confgen) {
+ quiet = true;
+ } else {
+ usage(1);
+ }
+ break;
+ case 'r':
+ fatal("The -r option has been deprecated.");
+ break;
+ case 's':
+ if (progmode == progmode_confgen) {
+ self_domain = isc_commandline_argument;
+ } else {
+ usage(1);
+ }
+ break;
+ case 'z':
+ if (progmode == progmode_confgen) {
+ zone = isc_commandline_argument;
+ } else {
+ usage(1);
+ }
+ break;
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ usage(1);
+ } else {
+ usage(0);
+ }
+ break;
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (progmode == progmode_keygen) {
+ keyname = argv[isc_commandline_index++];
+ }
+
+ POST(argv);
+
+ if (self_domain != NULL && zone != NULL) {
+ usage(1); /* -s and -z cannot coexist */
+ }
+
+ if (argc > isc_commandline_index) {
+ usage(1);
+ }
+
+ /* Use canonical algorithm name */
+ algname = dst_hmac_algorithm_totext(alg);
+
+ isc_mem_create(&mctx);
+
+ if (keyname == NULL) {
+ const char *suffix = NULL;
+
+ keyname = ((progmode == progmode_keygen) ? KEYGEN_DEFAULT
+ : CONFGEN_DEFAULT);
+ if (self_domain != NULL) {
+ suffix = self_domain;
+ } else if (zone != NULL) {
+ suffix = zone;
+ }
+ if (suffix != NULL) {
+ len = strlen(keyname) + strlen(suffix) + 2;
+ keybuf = isc_mem_get(mctx, len);
+ snprintf(keybuf, len, "%s.%s", keyname, suffix);
+ keyname = (const char *)keybuf;
+ }
+ }
+
+ isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret));
+
+ generate_key(mctx, alg, keysize, &key_txtbuffer);
+
+ if (!quiet) {
+ printf("\
+# To activate this key, place the following in named.conf, and\n\
+# in a separate keyfile on the system or systems from which nsupdate\n\
+# will be run:\n");
+ }
+
+ printf("\
+key \"%s\" {\n\
+ algorithm %s;\n\
+ secret \"%.*s\";\n\
+};\n",
+ keyname, algname, (int)isc_buffer_usedlength(&key_txtbuffer),
+ (char *)isc_buffer_base(&key_txtbuffer));
+
+ if (!quiet) {
+ if (self_domain != NULL) {
+ printf("\n\
+# Then, in the \"zone\" statement for the zone containing the\n\
+# name \"%s\", place an \"update-policy\" statement\n\
+# like this one, adjusted as needed for your preferred permissions:\n\
+update-policy {\n\
+ grant %s name %s ANY;\n\
+};\n",
+ self_domain, keyname, self_domain);
+ } else if (zone != NULL) {
+ printf("\n\
+# Then, in the \"zone\" definition statement for \"%s\",\n\
+# place an \"update-policy\" statement like this one, adjusted as \n\
+# needed for your preferred permissions:\n\
+update-policy {\n\
+ grant %s zonesub ANY;\n\
+};\n",
+ zone, keyname);
+ } else {
+ printf("\n\
+# Then, in the \"zone\" statement for each zone you wish to dynamically\n\
+# update, place an \"update-policy\" statement granting update permission\n\
+# to this key. For example, the following statement grants this key\n\
+# permission to update any name within the zone:\n\
+update-policy {\n\
+ grant %s zonesub ANY;\n\
+};\n",
+ keyname);
+ }
+
+ printf("\n\
+# After the keyfile has been placed, the following command will\n\
+# execute nsupdate using this key:\n\
+nsupdate -k <keyfile>\n");
+ }
+
+ if (keybuf != NULL) {
+ isc_mem_put(mctx, keybuf, len);
+ }
+
+ if (show_final_mem) {
+ isc_mem_stats(mctx, stderr);
+ }
+
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/confgen/tsig-keygen.rst b/bin/confgen/tsig-keygen.rst
new file mode 100644
index 0000000..7420bed
--- /dev/null
+++ b/bin/confgen/tsig-keygen.rst
@@ -0,0 +1,54 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. BEWARE: Do not forget to edit also ddns-confgen.rst!
+
+.. iscman:: tsig-keygen
+.. program:: tsig-keygen
+.. _man_tsig-keygen:
+
+tsig-keygen - TSIG key generation tool
+--------------------------------------
+
+Synopsis
+~~~~~~~~
+:program:`tsig-keygen` [**-a** algorithm] [**-h**] [name]
+
+Description
+~~~~~~~~~~~
+
+:program:`tsig-keygen` is an utility that generates keys for use in TSIG signing.
+The resulting keys can be used, for example, to secure dynamic DNS updates
+to a zone, or for the :iscman:`rndc` command channel.
+
+A domain name can be specified on the command line to be used as the name
+of the generated key. If no name is specified, the default is ``tsig-key``.
+
+Options
+~~~~~~~
+
+.. option:: -a algorithm
+
+ This option specifies the algorithm to use for the TSIG key. Available
+ choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384,
+ and hmac-sha512. The default is hmac-sha256. Options are
+ case-insensitive, and the "hmac-" prefix may be omitted.
+
+.. option:: -h
+
+ This option prints a short summary of options and arguments.
+
+See Also
+~~~~~~~~
+
+:iscman:`nsupdate(1) <nsupdate>`, :iscman:`named.conf(5) <named.conf>`, :iscman:`named(8) <named>`, BIND 9 Administrator Reference Manual.
diff --git a/bin/confgen/util.c b/bin/confgen/util.c
new file mode 100644
index 0000000..b0085fe
--- /dev/null
+++ b/bin/confgen/util.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include "util.h"
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/print.h>
+
+extern bool verbose;
+extern const char *progname;
+
+void
+notify(const char *fmt, ...) {
+ va_list ap;
+
+ if (verbose) {
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+ }
+}
+
+void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fprintf(stderr, "%s: ", progname);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
diff --git a/bin/confgen/util.h b/bin/confgen/util.h
new file mode 100644
index 0000000..4ac83e5
--- /dev/null
+++ b/bin/confgen/util.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <isc/attributes.h>
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+
+#define NS_CONTROL_PORT 953
+
+#undef DO
+#define DO(name, function) \
+ do { \
+ result = function; \
+ if (result != ISC_R_SUCCESS) \
+ fatal("%s: %s", name, isc_result_totext(result)); \
+ else \
+ notify("%s", name); \
+ } while (0)
+
+ISC_LANG_BEGINDECLS
+
+void
+notify(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2);
+
+noreturn void
+fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+ISC_LANG_ENDDECLS
diff --git a/bin/delv/Makefile.am b/bin/delv/Makefile.am
new file mode 100644
index 0000000..5405023
--- /dev/null
+++ b/bin/delv/Makefile.am
@@ -0,0 +1,21 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ -I$(top_builddir)/include \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) \
+ $(LIBISCCFG_CFLAGS) \
+ $(LIBIRS_CFLAGS)
+
+AM_CPPFLAGS += \
+ -DSYSCONFDIR=\"${sysconfdir}\"
+
+bin_PROGRAMS = delv
+
+delv_SOURCES = \
+ delv.c
+delv_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS) \
+ $(LIBISCCFG_LIBS) \
+ $(LIBIRS_LIBS)
diff --git a/bin/delv/Makefile.in b/bin/delv/Makefile.in
new file mode 100644
index 0000000..b86bfb5
--- /dev/null
+++ b/bin/delv/Makefile.in
@@ -0,0 +1,823 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+bin_PROGRAMS = delv$(EXEEXT)
+subdir = bin/delv
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am_delv_OBJECTS = delv.$(OBJEXT)
+delv_OBJECTS = $(am_delv_OBJECTS)
+delv_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBISCCFG_LIBS) \
+ $(LIBIRS_LIBS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/delv.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(delv_SOURCES)
+DIST_SOURCES = $(delv_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include -I$(top_builddir)/include $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) $(LIBISCCFG_CFLAGS) $(LIBIRS_CFLAGS) \
+ -DSYSCONFDIR=\"${sysconfdir}\"
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD =
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+delv_SOURCES = \
+ delv.c
+
+delv_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS) \
+ $(LIBISCCFG_LIBS) \
+ $(LIBIRS_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/delv/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/delv/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+delv$(EXEEXT): $(delv_OBJECTS) $(delv_DEPENDENCIES) $(EXTRA_delv_DEPENDENCIES)
+ @rm -f delv$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(delv_OBJECTS) $(delv_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delv.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/delv.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/delv.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am: uninstall-binPROGRAMS
+
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir doc-am doc-local dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \
+ uninstall-am uninstall-binPROGRAMS unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/delv/delv.c b/bin/delv/delv.c
new file mode 100644
index 0000000..e1e9e7f
--- /dev/null
+++ b/bin/delv/delv.c
@@ -0,0 +1,1868 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <arpa/inet.h>
+#include <bind.keys.h>
+#include <inttypes.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/attributes.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/hex.h>
+#include <isc/log.h>
+#include <isc/managers.h>
+#include <isc/md.h>
+#include <isc/mem.h>
+#include <isc/netmgr.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/client.h>
+#include <dns/fixedname.h>
+#include <dns/keytable.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/masterdump.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/secalg.h>
+#include <dns/view.h>
+
+#include <dst/dst.h>
+
+#include <isccfg/log.h>
+#include <isccfg/namedconf.h>
+
+#include <irs/resconf.h>
+
+#define CHECK(r) \
+ do { \
+ result = (r); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+#define MAXNAME (DNS_NAME_MAXTEXT + 1)
+
+/* Variables used internally by delv. */
+char *progname;
+static isc_mem_t *mctx = NULL;
+static isc_log_t *lctx = NULL;
+
+/* Configurables */
+static char *server = NULL;
+static const char *port = "53";
+static isc_sockaddr_t *srcaddr4 = NULL, *srcaddr6 = NULL;
+static isc_sockaddr_t a4, a6;
+static char *curqname = NULL, *qname = NULL;
+static bool classset = false;
+static dns_rdatatype_t qtype = dns_rdatatype_none;
+static bool typeset = false;
+
+static unsigned int styleflags = 0;
+static uint32_t splitwidth = 0xffffffff;
+static bool showcomments = true, showdnssec = true, showtrust = true,
+ rrcomments = true, noclass = false, nocrypto = false, nottl = false,
+ multiline = false, short_form = false, print_unknown_format = false,
+ yaml = false;
+
+static bool resolve_trace = false, validator_trace = false,
+ message_trace = false;
+
+static bool use_ipv4 = true, use_ipv6 = true;
+
+static bool cdflag = false, no_sigs = false, root_validation = true;
+
+static bool use_tcp = false;
+
+static char *anchorfile = NULL;
+static char *trust_anchor = NULL;
+static int num_keys = 0;
+
+static dns_fixedname_t afn;
+static dns_name_t *anchor_name = NULL;
+
+/* Default bind.keys contents */
+static char anchortext[] = TRUST_ANCHORS;
+
+/*
+ * Static function prototypes
+ */
+static isc_result_t
+get_reverse(char *reverse, size_t len, char *value, bool strict);
+
+static isc_result_t
+parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc);
+
+static void
+usage(void) {
+ fprintf(stderr,
+ "Usage: delv [@server] {q-opt} {d-opt} [domain] [q-type] "
+ "[q-class]\n"
+ "Where: domain is in the Domain Name System\n"
+ " q-class is one of (in,hs,ch,...) [default: in]\n"
+ " q-type is one of "
+ "(a,any,mx,ns,soa,hinfo,axfr,txt,...) "
+ "[default:a]\n"
+ " q-opt is one of:\n"
+ " -4 (use IPv4 query "
+ "transport "
+ "only)\n"
+ " -6 (use IPv6 query "
+ "transport "
+ "only)\n"
+ " -a anchor-file (specify root trust "
+ "anchor)\n"
+ " -b address[#port] (bind to source "
+ "address/port)\n"
+ " -c class (option included for "
+ "compatibility;\n"
+ " -d level (set debugging level)\n"
+ " -h (print help and exit)\n"
+ " -i (disable DNSSEC "
+ "validation)\n"
+ " -m (enable memory usage "
+ "debugging)\n"
+ " -p port (specify port number)\n"
+ " -q name (specify query name)\n"
+ " -t type (specify query type)\n"
+ " only IN is supported)\n"
+ " -v (print version and "
+ "exit)\n"
+ " -x dot-notation (shortcut for reverse "
+ "lookups)\n"
+ " d-opt is of the form +keyword[=value], where "
+ "keyword "
+ "is:\n"
+ " +[no]all (Set or clear all "
+ "display "
+ "flags)\n"
+ " +[no]class (Control display of "
+ "class)\n"
+ " +[no]comments (Control display of "
+ "comment lines)\n"
+ " +[no]crypto (Control display of "
+ "cryptographic\n"
+ " fields in records)\n"
+ " +[no]dlv (Obsolete)\n"
+ " +[no]dnssec (Display DNSSEC "
+ "records)\n"
+ " +[no]mtrace (Trace messages "
+ "received)\n"
+ " +[no]multiline (Print records in an "
+ "expanded format)\n"
+ " +[no]root (DNSSEC validation trust "
+ "anchor)\n"
+ " +[no]rrcomments (Control display of "
+ "per-record "
+ "comments)\n"
+ " +[no]rtrace (Trace resolver "
+ "fetches)\n"
+ " +[no]short (Short form answer)\n"
+ " +[no]split=## (Split hex/base64 fields "
+ "into chunks)\n"
+ " +[no]tcp (TCP mode)\n"
+ " +[no]ttl (Control display of ttls "
+ "in records)\n"
+ " +[no]trust (Control display of "
+ "trust "
+ "level)\n"
+ " +[no]unknownformat (Print RDATA in RFC 3597 "
+ "\"unknown\" format)\n"
+ " +[no]vtrace (Trace validation "
+ "process)\n"
+ " +[no]yaml (Present the results as "
+ "YAML)\n");
+ exit(1);
+}
+
+noreturn static void
+fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+static void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fflush(stdout);
+ fprintf(stderr, "%s: ", progname);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+static void
+warn(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+static void
+warn(const char *format, ...) {
+ va_list args;
+
+ fflush(stdout);
+ fprintf(stderr, "%s: warning: ", progname);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+}
+
+static isc_logcategory_t categories[] = { { "delv", 0 }, { NULL, 0 } };
+#define LOGCATEGORY_DEFAULT (&categories[0])
+#define LOGMODULE_DEFAULT (&modules[0])
+
+static isc_logmodule_t modules[] = { { "delv", 0 }, { NULL, 0 } };
+
+static void
+delv_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
+
+static void
+delv_log(int level, const char *fmt, ...) {
+ va_list ap;
+ char msgbuf[2048];
+
+ if (!isc_log_wouldlog(lctx, level)) {
+ return;
+ }
+
+ va_start(ap, fmt);
+
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ isc_log_write(lctx, LOGCATEGORY_DEFAULT, LOGMODULE_DEFAULT, level, "%s",
+ msgbuf);
+ va_end(ap);
+}
+
+static int loglevel = 0;
+
+static void
+setup_logging(FILE *errout) {
+ isc_result_t result;
+ isc_logdestination_t destination;
+ isc_logconfig_t *logconfig = NULL;
+
+ isc_log_create(mctx, &lctx, &logconfig);
+ isc_log_registercategories(lctx, categories);
+ isc_log_registermodules(lctx, modules);
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+ cfg_log_init(lctx);
+
+ destination.file.stream = errout;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC, &destination,
+ ISC_LOG_PRINTPREFIX);
+
+ isc_log_setdebuglevel(lctx, loglevel);
+ isc_log_settag(logconfig, ";; ");
+
+ result = isc_log_usechannel(logconfig, "stderr",
+ ISC_LOGCATEGORY_DEFAULT, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't attach to log channel 'stderr'");
+ }
+
+ if (resolve_trace && loglevel < 1) {
+ isc_log_createchannel(logconfig, "resolver", ISC_LOG_TOFILEDESC,
+ ISC_LOG_DEBUG(1), &destination,
+ ISC_LOG_PRINTPREFIX);
+
+ result = isc_log_usechannel(logconfig, "resolver",
+ DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't attach to log channel 'resolver'");
+ }
+ }
+
+ if (validator_trace && loglevel < 3) {
+ isc_log_createchannel(logconfig, "validator",
+ ISC_LOG_TOFILEDESC, ISC_LOG_DEBUG(3),
+ &destination, ISC_LOG_PRINTPREFIX);
+
+ result = isc_log_usechannel(logconfig, "validator",
+ DNS_LOGCATEGORY_DNSSEC,
+ DNS_LOGMODULE_VALIDATOR);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't attach to log channel 'validator'");
+ }
+ }
+
+ if (message_trace && loglevel < 10) {
+ isc_log_createchannel(logconfig, "messages", ISC_LOG_TOFILEDESC,
+ ISC_LOG_DEBUG(10), &destination,
+ ISC_LOG_PRINTPREFIX);
+
+ result = isc_log_usechannel(logconfig, "messages",
+ DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_PACKETS);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't attach to log channel 'messagse'");
+ }
+ }
+}
+
+static void
+print_status(dns_rdataset_t *rdataset) {
+ char buf[1024] = { 0 };
+
+ REQUIRE(rdataset != NULL);
+
+ if (!showtrust || !dns_rdataset_isassociated(rdataset)) {
+ return;
+ }
+
+ buf[0] = '\0';
+
+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
+ strlcat(buf, "negative response", sizeof(buf));
+ strlcat(buf, (yaml ? "_" : ", "), sizeof(buf));
+ }
+
+ switch (rdataset->trust) {
+ case dns_trust_none:
+ strlcat(buf, "untrusted", sizeof(buf));
+ break;
+ case dns_trust_pending_additional:
+ strlcat(buf, "signed additional data", sizeof(buf));
+ if (!yaml) {
+ strlcat(buf, ", ", sizeof(buf));
+ }
+ strlcat(buf, "pending validation", sizeof(buf));
+ break;
+ case dns_trust_pending_answer:
+ strlcat(buf, "signed answer", sizeof(buf));
+ if (!yaml) {
+ strlcat(buf, ", ", sizeof(buf));
+ }
+ strlcat(buf, "pending validation", sizeof(buf));
+ break;
+ case dns_trust_additional:
+ strlcat(buf, "unsigned additional data", sizeof(buf));
+ break;
+ case dns_trust_glue:
+ strlcat(buf, "glue data", sizeof(buf));
+ break;
+ case dns_trust_answer:
+ if (root_validation) {
+ strlcat(buf, "unsigned answer", sizeof(buf));
+ } else {
+ strlcat(buf, "answer not validated", sizeof(buf));
+ }
+ break;
+ case dns_trust_authauthority:
+ strlcat(buf, "authority data", sizeof(buf));
+ break;
+ case dns_trust_authanswer:
+ strlcat(buf, "authoritative", sizeof(buf));
+ break;
+ case dns_trust_secure:
+ strlcat(buf, "fully validated", sizeof(buf));
+ break;
+ case dns_trust_ultimate:
+ strlcat(buf, "ultimate trust", sizeof(buf));
+ break;
+ }
+
+ if (yaml) {
+ char *p;
+
+ /* Convert spaces to underscores for YAML */
+ for (p = buf; p != NULL && *p != '\0'; p++) {
+ if (*p == ' ') {
+ *p = '_';
+ }
+ }
+
+ printf(" - %s:\n", buf);
+ } else {
+ printf("; %s\n", buf);
+ }
+}
+
+static isc_result_t
+printdata(dns_rdataset_t *rdataset, dns_name_t *owner,
+ dns_master_style_t *style) {
+ isc_result_t result = ISC_R_SUCCESS;
+ static dns_trust_t trust;
+ static bool first = true;
+ isc_buffer_t target;
+ isc_region_t r;
+ char *t = NULL;
+ int len = 2048;
+
+ if (!dns_rdataset_isassociated(rdataset)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(owner, namebuf, sizeof(namebuf));
+ delv_log(ISC_LOG_DEBUG(4), "WARN: empty rdataset %s", namebuf);
+ return (ISC_R_SUCCESS);
+ }
+
+ if (!showdnssec && rdataset->type == dns_rdatatype_rrsig) {
+ return (ISC_R_SUCCESS);
+ }
+
+ if (first || rdataset->trust != trust) {
+ if (!first && showtrust && !short_form && !yaml) {
+ putchar('\n');
+ }
+ print_status(rdataset);
+ trust = rdataset->trust;
+ first = false;
+ }
+
+ do {
+ t = isc_mem_get(mctx, len);
+
+ isc_buffer_init(&target, t, len);
+ if (short_form) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ if ((rdataset->attributes &
+ DNS_RDATASETATTR_NEGATIVE) != 0)
+ {
+ continue;
+ }
+
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tofmttext(
+ &rdata, dns_rootname, styleflags, 0,
+ splitwidth, " ", &target);
+ if (result != ISC_R_SUCCESS) {
+ break;
+ }
+
+ if (isc_buffer_availablelength(&target) < 1) {
+ result = ISC_R_NOSPACE;
+ break;
+ }
+
+ isc_buffer_putstr(&target, "\n");
+
+ dns_rdata_reset(&rdata);
+ }
+ } else {
+ dns_indent_t indent = { " ", 2 };
+ if (!yaml && (rdataset->attributes &
+ DNS_RDATASETATTR_NEGATIVE) != 0)
+ {
+ isc_buffer_putstr(&target, "; ");
+ }
+ result = dns_master_rdatasettotext(
+ owner, rdataset, style, yaml ? &indent : NULL,
+ &target);
+ }
+
+ if (result == ISC_R_NOSPACE) {
+ isc_mem_put(mctx, t, len);
+ len += 1024;
+ } else if (result == ISC_R_NOMORE) {
+ result = ISC_R_SUCCESS;
+ } else {
+ CHECK(result);
+ }
+ } while (result == ISC_R_NOSPACE);
+
+ isc_buffer_usedregion(&target, &r);
+ printf("%.*s", (int)r.length, (char *)r.base);
+
+cleanup:
+ if (t != NULL) {
+ isc_mem_put(mctx, t, len);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+setup_style(dns_master_style_t **stylep) {
+ isc_result_t result;
+ dns_master_style_t *style = NULL;
+
+ REQUIRE(stylep != NULL && *stylep == NULL);
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ if (yaml) {
+ styleflags |= DNS_STYLEFLAG_YAML;
+ } else {
+ if (showcomments) {
+ styleflags |= DNS_STYLEFLAG_COMMENT;
+ }
+ if (print_unknown_format) {
+ styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
+ }
+ if (rrcomments) {
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+ if (nottl) {
+ styleflags |= DNS_STYLEFLAG_NO_TTL;
+ }
+ if (noclass) {
+ styleflags |= DNS_STYLEFLAG_NO_CLASS;
+ }
+ if (nocrypto) {
+ styleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ }
+ if (multiline) {
+ styleflags |= DNS_STYLEFLAG_MULTILINE;
+ styleflags |= DNS_STYLEFLAG_COMMENT;
+ }
+ }
+
+ if (multiline || (nottl && noclass)) {
+ result = dns_master_stylecreate(&style, styleflags, 24, 24, 24,
+ 32, 80, 8, splitwidth, mctx);
+ } else if (nottl || noclass) {
+ result = dns_master_stylecreate(&style, styleflags, 24, 24, 32,
+ 40, 80, 8, splitwidth, mctx);
+ } else {
+ result = dns_master_stylecreate(&style, styleflags, 24, 32, 40,
+ 48, 80, 8, splitwidth, mctx);
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ *stylep = style;
+ }
+ return (result);
+}
+
+static isc_result_t
+convert_name(dns_fixedname_t *fn, dns_name_t **name, const char *text) {
+ isc_result_t result;
+ isc_buffer_t b;
+ dns_name_t *n;
+ unsigned int len;
+
+ REQUIRE(fn != NULL && name != NULL && text != NULL);
+ len = strlen(text);
+
+ isc_buffer_constinit(&b, text, len);
+ isc_buffer_add(&b, len);
+ n = dns_fixedname_initname(fn);
+
+ result = dns_name_fromtext(n, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ delv_log(ISC_LOG_ERROR, "failed to convert QNAME %s: %s", text,
+ isc_result_totext(result));
+ return (result);
+ }
+
+ *name = n;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+key_fromconfig(const cfg_obj_t *key, dns_client_t *client) {
+ dns_rdata_dnskey_t dnskey;
+ dns_rdata_ds_t ds;
+ uint32_t rdata1, rdata2, rdata3;
+ const char *datastr = NULL, *keynamestr = NULL, *atstr = NULL;
+ unsigned char data[4096];
+ isc_buffer_t databuf;
+ unsigned char rrdata[4096];
+ isc_buffer_t rrdatabuf;
+ isc_region_t r;
+ dns_fixedname_t fkeyname;
+ dns_name_t *keyname;
+ isc_result_t result;
+ bool match_root = false;
+ enum {
+ INITIAL_KEY,
+ STATIC_KEY,
+ INITIAL_DS,
+ STATIC_DS,
+ TRUSTED
+ } anchortype;
+ const cfg_obj_t *obj;
+
+ keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
+ CHECK(convert_name(&fkeyname, &keyname, keynamestr));
+
+ if (!root_validation) {
+ return (ISC_R_SUCCESS);
+ }
+
+ if (anchor_name) {
+ match_root = dns_name_equal(keyname, anchor_name);
+ }
+
+ if (!match_root) {
+ return (ISC_R_SUCCESS);
+ }
+
+ if (!root_validation) {
+ return (ISC_R_SUCCESS);
+ }
+
+ delv_log(ISC_LOG_DEBUG(3), "adding trust anchor %s", trust_anchor);
+
+ /* if DNSKEY, flags; if DS, key tag */
+ rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1"));
+
+ /* if DNSKEY, protocol; if DS, algorithm */
+ rdata2 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata2"));
+
+ /* if DNSKEY, algorithm; if DS, digest type */
+ rdata3 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata3"));
+
+ /* What type of trust anchor is this? */
+ obj = cfg_tuple_get(key, "anchortype");
+ if (cfg_obj_isvoid(obj)) {
+ /*
+ * "anchortype" is not defined, this must be a static-key
+ * configured with trusted-keys.
+ */
+ anchortype = STATIC_KEY;
+ } else {
+ atstr = cfg_obj_asstring(obj);
+ if (strcasecmp(atstr, "static-key") == 0) {
+ anchortype = STATIC_KEY;
+ } else if (strcasecmp(atstr, "static-ds") == 0) {
+ anchortype = STATIC_DS;
+ } else if (strcasecmp(atstr, "initial-key") == 0) {
+ anchortype = INITIAL_KEY;
+ } else if (strcasecmp(atstr, "initial-ds") == 0) {
+ anchortype = INITIAL_DS;
+ } else {
+ delv_log(ISC_LOG_ERROR,
+ "key '%s': invalid initialization method '%s'",
+ keynamestr, atstr);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ }
+
+ isc_buffer_init(&databuf, data, sizeof(data));
+ isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
+
+ if (rdata1 > 0xffff) {
+ CHECK(ISC_R_RANGE);
+ }
+ if (rdata2 > 0xff) {
+ CHECK(ISC_R_RANGE);
+ }
+ if (rdata3 > 0xff) {
+ CHECK(ISC_R_RANGE);
+ }
+
+ switch (anchortype) {
+ case STATIC_KEY:
+ case INITIAL_KEY:
+ case TRUSTED:
+ dnskey.common.rdclass = dns_rdataclass_in;
+ dnskey.common.rdtype = dns_rdatatype_dnskey;
+ dnskey.mctx = NULL;
+
+ ISC_LINK_INIT(&dnskey.common, link);
+
+ dnskey.flags = (uint16_t)rdata1;
+ dnskey.protocol = (uint8_t)rdata2;
+ dnskey.algorithm = (uint8_t)rdata3;
+
+ datastr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
+ CHECK(isc_base64_decodestring(datastr, &databuf));
+ isc_buffer_usedregion(&databuf, &r);
+ dnskey.datalen = r.length;
+ dnskey.data = r.base;
+
+ CHECK(dns_rdata_fromstruct(NULL, dnskey.common.rdclass,
+ dnskey.common.rdtype, &dnskey,
+ &rrdatabuf));
+ CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in,
+ dns_rdatatype_dnskey, keyname,
+ &rrdatabuf));
+ break;
+ case INITIAL_DS:
+ case STATIC_DS:
+ ds.common.rdclass = dns_rdataclass_in;
+ ds.common.rdtype = dns_rdatatype_ds;
+ ds.mctx = NULL;
+
+ ISC_LINK_INIT(&ds.common, link);
+
+ ds.key_tag = (uint16_t)rdata1;
+ ds.algorithm = (uint8_t)rdata2;
+ ds.digest_type = (uint8_t)rdata3;
+
+ datastr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
+ CHECK(isc_hex_decodestring(datastr, &databuf));
+ isc_buffer_usedregion(&databuf, &r);
+
+ switch (ds.digest_type) {
+ case DNS_DSDIGEST_SHA1:
+ if (r.length != ISC_SHA1_DIGESTLENGTH) {
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+ break;
+ case DNS_DSDIGEST_SHA256:
+ if (r.length != ISC_SHA256_DIGESTLENGTH) {
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+ break;
+ case DNS_DSDIGEST_SHA384:
+ if (r.length != ISC_SHA384_DIGESTLENGTH) {
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+ break;
+ }
+
+ ds.length = r.length;
+ ds.digest = r.base;
+
+ CHECK(dns_rdata_fromstruct(NULL, ds.common.rdclass,
+ ds.common.rdtype, &ds, &rrdatabuf));
+ CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in,
+ dns_rdatatype_ds, keyname,
+ &rrdatabuf));
+ }
+
+ num_keys++;
+
+cleanup:
+ if (result == DST_R_NOCRYPTO) {
+ cfg_obj_log(key, lctx, ISC_LOG_ERROR, "no crypto support");
+ } else if (result == DST_R_UNSUPPORTEDALG) {
+ cfg_obj_log(key, lctx, ISC_LOG_WARNING,
+ "skipping trusted key '%s': %s", keynamestr,
+ isc_result_totext(result));
+ result = ISC_R_SUCCESS;
+ } else if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(key, lctx, ISC_LOG_ERROR,
+ "failed to add trusted key '%s': %s", keynamestr,
+ isc_result_totext(result));
+ result = ISC_R_FAILURE;
+ }
+
+ return (result);
+}
+
+static isc_result_t
+load_keys(const cfg_obj_t *keys, dns_client_t *client) {
+ const cfg_listelt_t *elt, *elt2;
+ const cfg_obj_t *key, *keylist;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt))
+ {
+ keylist = cfg_listelt_value(elt);
+
+ for (elt2 = cfg_list_first(keylist); elt2 != NULL;
+ elt2 = cfg_list_next(elt2))
+ {
+ key = cfg_listelt_value(elt2);
+ CHECK(key_fromconfig(key, client));
+ }
+ }
+
+cleanup:
+ if (result == DST_R_NOCRYPTO) {
+ result = ISC_R_SUCCESS;
+ }
+ return (result);
+}
+
+static isc_result_t
+setup_dnsseckeys(dns_client_t *client) {
+ isc_result_t result;
+ cfg_parser_t *parser = NULL;
+ const cfg_obj_t *trusted_keys = NULL;
+ const cfg_obj_t *managed_keys = NULL;
+ const cfg_obj_t *trust_anchors = NULL;
+ cfg_obj_t *bindkeys = NULL;
+ const char *filename = anchorfile;
+
+ if (!root_validation) {
+ return (ISC_R_SUCCESS);
+ }
+
+ if (filename == NULL) {
+ filename = SYSCONFDIR "/bind.keys";
+ }
+
+ if (trust_anchor == NULL) {
+ trust_anchor = isc_mem_strdup(mctx, ".");
+ }
+
+ if (trust_anchor != NULL) {
+ CHECK(convert_name(&afn, &anchor_name, trust_anchor));
+ }
+
+ CHECK(cfg_parser_create(mctx, dns_lctx, &parser));
+
+ if (access(filename, R_OK) != 0) {
+ if (anchorfile != NULL) {
+ fatal("Unable to read key file '%s'", anchorfile);
+ }
+ } else {
+ result = cfg_parse_file(parser, filename, &cfg_type_bindkeys,
+ &bindkeys);
+ if (result != ISC_R_SUCCESS) {
+ if (anchorfile != NULL) {
+ fatal("Unable to load keys from '%s'",
+ anchorfile);
+ }
+ }
+ }
+
+ if (bindkeys == NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, anchortext, sizeof(anchortext) - 1);
+ isc_buffer_add(&b, sizeof(anchortext) - 1);
+ cfg_parser_reset(parser);
+ result = cfg_parse_buffer(parser, &b, NULL, 0,
+ &cfg_type_bindkeys, 0, &bindkeys);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Unable to parse built-in keys");
+ }
+ }
+
+ INSIST(bindkeys != NULL);
+ cfg_map_get(bindkeys, "trusted-keys", &trusted_keys);
+ cfg_map_get(bindkeys, "managed-keys", &managed_keys);
+ cfg_map_get(bindkeys, "trust-anchors", &trust_anchors);
+
+ if (trusted_keys != NULL) {
+ CHECK(load_keys(trusted_keys, client));
+ }
+ if (managed_keys != NULL) {
+ CHECK(load_keys(managed_keys, client));
+ }
+ if (trust_anchors != NULL) {
+ CHECK(load_keys(trust_anchors, client));
+ }
+ result = ISC_R_SUCCESS;
+
+ if (num_keys == 0) {
+ fatal("No trusted keys were loaded");
+ }
+
+cleanup:
+ if (bindkeys != NULL) {
+ cfg_obj_destroy(parser, &bindkeys);
+ }
+ if (parser != NULL) {
+ cfg_parser_destroy(&parser);
+ }
+ if (result != ISC_R_SUCCESS) {
+ delv_log(ISC_LOG_ERROR, "setup_dnsseckeys: %s",
+ isc_result_totext(result));
+ }
+ return (result);
+}
+
+static isc_result_t
+addserver(dns_client_t *client) {
+ struct addrinfo hints, *res, *cur;
+ int gaierror;
+ struct in_addr in4;
+ struct in6_addr in6;
+ isc_sockaddr_t *sa;
+ isc_sockaddrlist_t servers;
+ uint32_t destport;
+ isc_result_t result;
+ dns_name_t *name = NULL;
+
+ result = parse_uint(&destport, port, 0xffff, "port");
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't parse port number");
+ }
+
+ ISC_LIST_INIT(servers);
+
+ if (inet_pton(AF_INET, server, &in4) == 1) {
+ if (!use_ipv4) {
+ fatal("Use of IPv4 disabled by -6");
+ }
+ sa = isc_mem_get(mctx, sizeof(*sa));
+ ISC_LINK_INIT(sa, link);
+ isc_sockaddr_fromin(sa, &in4, destport);
+ ISC_LIST_APPEND(servers, sa, link);
+ } else if (inet_pton(AF_INET6, server, &in6) == 1) {
+ if (!use_ipv6) {
+ fatal("Use of IPv6 disabled by -4");
+ }
+ sa = isc_mem_get(mctx, sizeof(*sa));
+ ISC_LINK_INIT(sa, link);
+ isc_sockaddr_fromin6(sa, &in6, destport);
+ ISC_LIST_APPEND(servers, sa, link);
+ } else {
+ memset(&hints, 0, sizeof(hints));
+ if (!use_ipv6) {
+ hints.ai_family = AF_INET;
+ } else if (!use_ipv4) {
+ hints.ai_family = AF_INET6;
+ } else {
+ hints.ai_family = AF_UNSPEC;
+ }
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ gaierror = getaddrinfo(server, port, &hints, &res);
+ if (gaierror != 0) {
+ delv_log(ISC_LOG_ERROR, "getaddrinfo failed: %s",
+ gai_strerror(gaierror));
+ return (ISC_R_FAILURE);
+ }
+
+ result = ISC_R_SUCCESS;
+ for (cur = res; cur != NULL; cur = cur->ai_next) {
+ if (cur->ai_family != AF_INET &&
+ cur->ai_family != AF_INET6)
+ {
+ continue;
+ }
+ sa = isc_mem_get(mctx, sizeof(*sa));
+ memset(sa, 0, sizeof(*sa));
+ ISC_LINK_INIT(sa, link);
+ memmove(&sa->type, cur->ai_addr, cur->ai_addrlen);
+ sa->length = (unsigned int)cur->ai_addrlen;
+ ISC_LIST_APPEND(servers, sa, link);
+ }
+ freeaddrinfo(res);
+ CHECK(result);
+ }
+
+ CHECK(dns_client_setservers(client, dns_rdataclass_in, name, &servers));
+
+cleanup:
+ while (!ISC_LIST_EMPTY(servers)) {
+ sa = ISC_LIST_HEAD(servers);
+ ISC_LIST_UNLINK(servers, sa, link);
+ isc_mem_put(mctx, sa, sizeof(*sa));
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ delv_log(ISC_LOG_ERROR, "addserver: %s",
+ isc_result_totext(result));
+ }
+
+ return (result);
+}
+
+static isc_result_t
+findserver(dns_client_t *client) {
+ isc_result_t result;
+ irs_resconf_t *resconf = NULL;
+ isc_sockaddrlist_t *nameservers;
+ isc_sockaddr_t *sa, *next;
+ uint32_t destport;
+
+ result = parse_uint(&destport, port, 0xffff, "port");
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't parse port number");
+ }
+
+ result = irs_resconf_load(mctx, "/etc/resolv.conf", &resconf);
+ if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
+ delv_log(ISC_LOG_ERROR, "irs_resconf_load: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ /* Get nameservers from resolv.conf */
+ nameservers = irs_resconf_getnameservers(resconf);
+ for (sa = ISC_LIST_HEAD(*nameservers); sa != NULL; sa = next) {
+ next = ISC_LIST_NEXT(sa, link);
+
+ /* Set destination port */
+ if (sa->type.sa.sa_family == AF_INET && use_ipv4) {
+ sa->type.sin.sin_port = htons(destport);
+ continue;
+ }
+ if (sa->type.sa.sa_family == AF_INET6 && use_ipv6) {
+ sa->type.sin6.sin6_port = htons(destport);
+ continue;
+ }
+
+ /* Incompatible protocol family */
+ ISC_LIST_UNLINK(*nameservers, sa, link);
+ isc_mem_put(mctx, sa, sizeof(*sa));
+ }
+
+ /* None found, use localhost */
+ if (ISC_LIST_EMPTY(*nameservers)) {
+ if (use_ipv4) {
+ struct in_addr localhost;
+ localhost.s_addr = htonl(INADDR_LOOPBACK);
+ sa = isc_mem_get(mctx, sizeof(*sa));
+ isc_sockaddr_fromin(sa, &localhost, destport);
+
+ ISC_LINK_INIT(sa, link);
+ ISC_LIST_APPEND(*nameservers, sa, link);
+ }
+
+ if (use_ipv6) {
+ sa = isc_mem_get(mctx, sizeof(*sa));
+ isc_sockaddr_fromin6(sa, &in6addr_loopback, destport);
+
+ ISC_LINK_INIT(sa, link);
+ ISC_LIST_APPEND(*nameservers, sa, link);
+ }
+ }
+
+ result = dns_client_setservers(client, dns_rdataclass_in, NULL,
+ nameservers);
+ if (result != ISC_R_SUCCESS) {
+ delv_log(ISC_LOG_ERROR, "dns_client_setservers: %s",
+ isc_result_totext(result));
+ }
+
+cleanup:
+ if (resconf != NULL) {
+ irs_resconf_destroy(&resconf);
+ }
+ return (result);
+}
+
+static isc_result_t
+parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc) {
+ uint32_t n;
+ isc_result_t result = isc_parse_uint32(&n, value, 10);
+ if (result == ISC_R_SUCCESS && n > max) {
+ result = ISC_R_RANGE;
+ }
+ if (result != ISC_R_SUCCESS) {
+ printf("invalid %s '%s': %s\n", desc, value,
+ isc_result_totext(result));
+ return (result);
+ }
+ *uip = n;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+plus_option(char *option) {
+ isc_result_t result;
+ char *cmd, *value, *last = NULL;
+ bool state = true;
+
+ INSIST(option != NULL);
+
+ cmd = strtok_r(option, "=", &last);
+ if (cmd == NULL) {
+ printf(";; Invalid option %s\n", option);
+ return;
+ }
+ if (strncasecmp(cmd, "no", 2) == 0) {
+ cmd += 2;
+ state = false;
+ }
+
+ value = strtok_r(NULL, "\0", &last);
+
+#define FULLCHECK(A) \
+ do { \
+ size_t _l = strlen(cmd); \
+ if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \
+ goto invalid_option; \
+ } while (0)
+
+ switch (cmd[0]) {
+ case 'a': /* all */
+ FULLCHECK("all");
+ showcomments = state;
+ rrcomments = state;
+ showtrust = state;
+ break;
+ case 'c':
+ switch (cmd[1]) {
+ case 'd': /* cdflag */
+ FULLCHECK("cdflag");
+ cdflag = state;
+ break;
+ case 'l': /* class */
+ FULLCHECK("class");
+ noclass = !state;
+ break;
+ case 'o': /* comments */
+ FULLCHECK("comments");
+ showcomments = state;
+ break;
+ case 'r': /* crypto */
+ FULLCHECK("crypto");
+ nocrypto = !state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'd':
+ switch (cmd[1]) {
+ case 'l': /* dlv */
+ FULLCHECK("dlv");
+ if (state) {
+ fprintf(stderr, "Invalid option: "
+ "+dlv is obsolete\n");
+ exit(1);
+ }
+ break;
+ case 'n': /* dnssec */
+ FULLCHECK("dnssec");
+ showdnssec = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'm':
+ switch (cmd[1]) {
+ case 't': /* mtrace */
+ message_trace = state;
+ if (state) {
+ resolve_trace = state;
+ }
+ break;
+ case 'u': /* multiline */
+ FULLCHECK("multiline");
+ multiline = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ switch (cmd[1]) {
+ case 'o': /* root */
+ FULLCHECK("root");
+ if (state && no_sigs) {
+ break;
+ }
+ root_validation = state;
+ if (value != NULL) {
+ trust_anchor = isc_mem_strdup(mctx, value);
+ }
+ break;
+ case 'r': /* rrcomments */
+ FULLCHECK("rrcomments");
+ rrcomments = state;
+ break;
+ case 't': /* rtrace */
+ FULLCHECK("rtrace");
+ resolve_trace = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 's':
+ switch (cmd[1]) {
+ case 'h': /* short */
+ FULLCHECK("short");
+ short_form = state;
+ if (short_form) {
+ multiline = false;
+ showcomments = false;
+ showtrust = false;
+ showdnssec = false;
+ }
+ break;
+ case 'p': /* split */
+ FULLCHECK("split");
+ if (value != NULL && !state) {
+ goto invalid_option;
+ }
+ if (!state) {
+ splitwidth = 0;
+ break;
+ } else if (value == NULL) {
+ break;
+ }
+
+ result = parse_uint(&splitwidth, value, 1023, "split");
+ if (splitwidth % 4 != 0) {
+ splitwidth = ((splitwidth + 3) / 4) * 4;
+ warn("split must be a multiple of 4; "
+ "adjusting to %d",
+ splitwidth);
+ }
+ /*
+ * There is an adjustment done in the
+ * totext_<rrtype>() functions which causes
+ * splitwidth to shrink. This is okay when we're
+ * using the default width but incorrect in this
+ * case, so we correct for it
+ */
+ if (splitwidth) {
+ splitwidth += 3;
+ }
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't parse split");
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'u':
+ FULLCHECK("unknownformat");
+ print_unknown_format = state;
+ break;
+ case 't':
+ switch (cmd[1]) {
+ case 'c': /* tcp */
+ FULLCHECK("tcp");
+ use_tcp = state;
+ break;
+ case 'r': /* trust */
+ FULLCHECK("trust");
+ showtrust = state;
+ break;
+ case 't': /* ttl */
+ FULLCHECK("ttl");
+ nottl = !state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'v': /* vtrace */
+ FULLCHECK("vtrace");
+ validator_trace = state;
+ if (state) {
+ resolve_trace = state;
+ }
+ break;
+ case 'y': /* yaml */
+ FULLCHECK("yaml");
+ yaml = state;
+ if (state) {
+ rrcomments = false;
+ }
+ break;
+ default:
+ invalid_option:
+ /*
+ * We can also add a "need_value:" case here if we ever
+ * add a plus-option that requires a specified value
+ */
+ fprintf(stderr, "Invalid option: +%s\n", option);
+ usage();
+ }
+ return;
+}
+
+/*
+ * options: "46a:b:c:d:himp:q:t:vx:";
+ */
+static const char *single_dash_opts = "46himv";
+static const char *dash_opts = "46abcdhimpqtvx";
+
+static bool
+dash_option(char *option, char *next, bool *open_type_class) {
+ char opt, *value;
+ isc_result_t result;
+ bool value_from_next;
+ isc_textregion_t tr;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ char textname[MAXNAME];
+ struct in_addr in4;
+ struct in6_addr in6;
+ in_port_t srcport;
+ uint32_t num;
+ char *hash;
+
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ /*
+ * Since the -[46himv] options do not take an argument,
+ * account for them (in any number and/or combination)
+ * if they appear as the first character(s) of a q-opt.
+ */
+ opt = option[0];
+ switch (opt) {
+ case '4':
+ if (isc_net_probeipv4() != ISC_R_SUCCESS) {
+ fatal("IPv4 networking not available");
+ }
+ if (use_ipv6) {
+ isc_net_disableipv6();
+ use_ipv6 = false;
+ }
+ break;
+ case '6':
+ if (isc_net_probeipv6() != ISC_R_SUCCESS) {
+ fatal("IPv6 networking not available");
+ }
+ if (use_ipv4) {
+ isc_net_disableipv4();
+ use_ipv4 = false;
+ }
+ break;
+ case 'h':
+ usage();
+ exit(0);
+ case 'i':
+ no_sigs = true;
+ root_validation = false;
+ break;
+ case 'm':
+ /* handled in preparse_args() */
+ break;
+ case 'v':
+ fprintf(stderr, "delv %s\n", PACKAGE_VERSION);
+ exit(0);
+ default:
+ UNREACHABLE();
+ }
+ if (strlen(option) > 1U) {
+ option = &option[1];
+ } else {
+ return (false);
+ }
+ }
+ opt = option[0];
+ if (strlen(option) > 1U) {
+ value_from_next = false;
+ value = &option[1];
+ } else {
+ value_from_next = true;
+ value = next;
+ }
+ if (value == NULL) {
+ goto invalid_option;
+ }
+ switch (opt) {
+ case 'a':
+ anchorfile = isc_mem_strdup(mctx, value);
+ return (value_from_next);
+ case 'b':
+ hash = strchr(value, '#');
+ if (hash != NULL) {
+ result = parse_uint(&num, hash + 1, 0xffff, "port");
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't parse port number");
+ }
+ srcport = num;
+ *hash = '\0';
+ } else {
+ srcport = 0;
+ }
+
+ if (inet_pton(AF_INET, value, &in4) == 1) {
+ if (srcaddr4 != NULL) {
+ fatal("Only one local address per family "
+ "can be specified\n");
+ }
+ isc_sockaddr_fromin(&a4, &in4, srcport);
+ srcaddr4 = &a4;
+ } else if (inet_pton(AF_INET6, value, &in6) == 1) {
+ if (srcaddr6 != NULL) {
+ fatal("Only one local address per family "
+ "can be specified\n");
+ }
+ isc_sockaddr_fromin6(&a6, &in6, srcport);
+ srcaddr6 = &a6;
+ } else {
+ if (hash != NULL) {
+ *hash = '#';
+ }
+ fatal("Invalid address %s", value);
+ }
+ if (hash != NULL) {
+ *hash = '#';
+ }
+ return (value_from_next);
+ case 'c':
+ if (classset) {
+ warn("extra query class");
+ }
+
+ *open_type_class = false;
+ tr.base = value;
+ tr.length = strlen(value);
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS) {
+ classset = true;
+ } else if (rdclass != dns_rdataclass_in) {
+ warn("ignoring non-IN query class");
+ } else {
+ warn("ignoring invalid class");
+ }
+ return (value_from_next);
+ case 'd':
+ result = parse_uint(&num, value, 99, "debug level");
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't parse debug level");
+ }
+ loglevel = num;
+ return (value_from_next);
+ case 'p':
+ port = value;
+ return (value_from_next);
+ case 'q':
+ if (curqname != NULL) {
+ warn("extra query name");
+ isc_mem_free(mctx, curqname);
+ }
+ curqname = isc_mem_strdup(mctx, value);
+ return (value_from_next);
+ case 't':
+ *open_type_class = false;
+ tr.base = value;
+ tr.length = strlen(value);
+ result = dns_rdatatype_fromtext(&rdtype,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS) {
+ if (typeset) {
+ warn("extra query type");
+ }
+ if (rdtype == dns_rdatatype_ixfr ||
+ rdtype == dns_rdatatype_axfr)
+ {
+ fatal("Transfer not supported");
+ }
+ qtype = rdtype;
+ typeset = true;
+ } else {
+ warn("ignoring invalid type");
+ }
+ return (value_from_next);
+ case 'x':
+ result = get_reverse(textname, sizeof(textname), value, false);
+ if (result == ISC_R_SUCCESS) {
+ if (curqname != NULL) {
+ isc_mem_free(mctx, curqname);
+ warn("extra query name");
+ }
+ curqname = isc_mem_strdup(mctx, textname);
+ if (typeset) {
+ warn("extra query type");
+ }
+ qtype = dns_rdatatype_ptr;
+ typeset = true;
+ } else {
+ fprintf(stderr, "Invalid IP address %s\n", value);
+ exit(1);
+ }
+ return (value_from_next);
+ invalid_option:
+ default:
+ fprintf(stderr, "Invalid option: -%s\n", option);
+ usage();
+ }
+ UNREACHABLE();
+ return (false);
+}
+
+/*
+ * Check for -m first to determine whether to enable
+ * memory debugging when setting up the memory context.
+ */
+static void
+preparse_args(int argc, char **argv) {
+ bool ipv4only = false, ipv6only = false;
+ char *option;
+
+ for (argc--, argv++; argc > 0; argc--, argv++) {
+ if (argv[0][0] != '-') {
+ continue;
+ }
+
+ option = &argv[0][1];
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ switch (option[0]) {
+ case 'm':
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE |
+ ISC_MEM_DEBUGRECORD;
+ break;
+ case '4':
+ if (ipv6only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv4only = true;
+ break;
+ case '6':
+ if (ipv4only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv6only = true;
+ break;
+ }
+ option = &option[1];
+ }
+
+ if (strlen(option) == 0U) {
+ continue;
+ }
+
+ /* Look for dash value option. */
+ if (strpbrk(option, dash_opts) != &option[0] ||
+ strlen(option) > 1U)
+ {
+ /* Error or value in option. */
+ continue;
+ }
+
+ /* Dash value is next argument so we need to skip it. */
+ argc--;
+ argv++;
+
+ /* Handle missing argument */
+ if (argc == 0) {
+ break;
+ }
+ }
+}
+
+/*
+ * Argument parsing is based on dig, but simplified: only one
+ * QNAME/QCLASS/QTYPE tuple can be specified, and options have
+ * been removed that aren't applicable to delv. The interface
+ * should be familiar to dig users, however.
+ */
+static void
+parse_args(int argc, char **argv) {
+ isc_result_t result;
+ isc_textregion_t tr;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ bool open_type_class = true;
+
+ for (; argc > 0; argc--, argv++) {
+ if (argv[0][0] == '@') {
+ server = &argv[0][1];
+ } else if (argv[0][0] == '+') {
+ plus_option(&argv[0][1]);
+ } else if (argv[0][0] == '-') {
+ if (argc <= 1) {
+ if (dash_option(&argv[0][1], NULL,
+ &open_type_class))
+ {
+ argc--;
+ argv++;
+ }
+ } else {
+ if (dash_option(&argv[0][1], argv[1],
+ &open_type_class))
+ {
+ argc--;
+ argv++;
+ }
+ }
+ } else {
+ /*
+ * Anything which isn't an option
+ */
+ if (open_type_class) {
+ tr.base = argv[0];
+ tr.length = strlen(argv[0]);
+ result = dns_rdatatype_fromtext(
+ &rdtype, (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS) {
+ if (typeset) {
+ warn("extra query type");
+ }
+ if (rdtype == dns_rdatatype_ixfr ||
+ rdtype == dns_rdatatype_axfr)
+ {
+ fatal("Transfer not supported");
+ }
+ qtype = rdtype;
+ typeset = true;
+ continue;
+ }
+ result = dns_rdataclass_fromtext(
+ &rdclass, (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS) {
+ if (classset) {
+ warn("extra query class");
+ } else if (rdclass != dns_rdataclass_in)
+ {
+ warn("ignoring non-IN "
+ "query class");
+ }
+ continue;
+ }
+ }
+
+ if (curqname == NULL) {
+ curqname = isc_mem_strdup(mctx, argv[0]);
+ }
+ }
+ }
+
+ /*
+ * If no qname or qtype specified, search for root/NS
+ * If no qtype specified, use A
+ */
+ if (!typeset) {
+ qtype = dns_rdatatype_a;
+ }
+
+ if (curqname == NULL) {
+ qname = isc_mem_strdup(mctx, ".");
+
+ if (!typeset) {
+ qtype = dns_rdatatype_ns;
+ }
+ } else {
+ qname = curqname;
+ }
+}
+
+static isc_result_t
+append_str(const char *text, int len, char **p, char *end) {
+ if (len > end - *p) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(*p, text, len);
+ *p += len;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+reverse_octets(const char *in, char **p, char *end) {
+ char *dot = strchr(in, '.');
+ int len;
+ if (dot != NULL) {
+ isc_result_t result;
+ result = reverse_octets(dot + 1, p, end);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ result = append_str(".", 1, p, end);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ len = (int)(dot - in);
+ } else {
+ len = strlen(in);
+ }
+ return (append_str(in, len, p, end));
+}
+
+static isc_result_t
+get_reverse(char *reverse, size_t len, char *value, bool strict) {
+ int r;
+ isc_result_t result;
+ isc_netaddr_t addr;
+
+ addr.family = AF_INET6;
+ r = inet_pton(AF_INET6, value, &addr.type.in6);
+ if (r > 0) {
+ /* This is a valid IPv6 address. */
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ unsigned int options = 0;
+
+ name = dns_fixedname_initname(&fname);
+ result = dns_byaddr_createptrname(&addr, options, name);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ dns_name_format(name, reverse, (unsigned int)len);
+ return (ISC_R_SUCCESS);
+ } else {
+ /*
+ * Not a valid IPv6 address. Assume IPv4.
+ * If 'strict' is not set, construct the
+ * in-addr.arpa name by blindly reversing
+ * octets whether or not they look like integers,
+ * so that this can be used for RFC2317 names
+ * and such.
+ */
+ char *p = reverse;
+ char *end = reverse + len;
+ if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) {
+ return (DNS_R_BADDOTTEDQUAD);
+ }
+ result = reverse_octets(value, &p, end);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ result = append_str(".in-addr.arpa.", 15, &p, end);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ return (ISC_R_SUCCESS);
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ dns_client_t *client = NULL;
+ isc_result_t result;
+ dns_fixedname_t qfn;
+ dns_name_t *query_name, *response_name;
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_rdataset_t *rdataset;
+ dns_namelist_t namelist;
+ unsigned int resopt;
+ isc_appctx_t *actx = NULL;
+ isc_nm_t *netmgr = NULL;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_timermgr_t *timermgr = NULL;
+ dns_master_style_t *style = NULL;
+ struct sigaction sa;
+
+ progname = argv[0];
+ preparse_args(argc, argv);
+
+ argc--;
+ argv++;
+
+ isc_mem_create(&mctx);
+
+ result = dst_lib_init(mctx, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dst_lib_init failed: %d", result);
+ }
+
+ CHECK(isc_appctx_create(mctx, &actx));
+
+ isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr, &timermgr);
+
+ parse_args(argc, argv);
+
+ CHECK(setup_style(&style));
+
+ setup_logging(stderr);
+
+ CHECK(isc_app_ctxstart(actx));
+
+ /* Unblock SIGINT if it's been blocked by isc_app_ctxstart() */
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SIG_DFL;
+ if (sigfillset(&sa.sa_mask) != 0 || sigaction(SIGINT, &sa, NULL) < 0) {
+ fatal("Couldn't set up signal handler");
+ }
+
+ /* Create client */
+ result = dns_client_create(mctx, actx, taskmgr, netmgr, timermgr, 0,
+ &client, srcaddr4, srcaddr6);
+ if (result != ISC_R_SUCCESS) {
+ delv_log(ISC_LOG_ERROR, "dns_client_create: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ /* Set the nameserver */
+ if (server != NULL) {
+ addserver(client);
+ } else {
+ findserver(client);
+ }
+
+ CHECK(setup_dnsseckeys(client));
+
+ /* Construct QNAME */
+ CHECK(convert_name(&qfn, &query_name, qname));
+
+ /* Set up resolution options */
+ resopt = DNS_CLIENTRESOPT_NOCDFLAG;
+ if (no_sigs) {
+ resopt |= DNS_CLIENTRESOPT_NODNSSEC;
+ }
+ if (!root_validation) {
+ resopt |= DNS_CLIENTRESOPT_NOVALIDATE;
+ }
+ if (cdflag) {
+ resopt &= ~DNS_CLIENTRESOPT_NOCDFLAG;
+ }
+ if (use_tcp) {
+ resopt |= DNS_CLIENTRESOPT_TCP;
+ }
+
+ /* Perform resolution */
+ ISC_LIST_INIT(namelist);
+ result = dns_client_resolve(client, query_name, dns_rdataclass_in,
+ qtype, resopt, &namelist);
+ if (result != ISC_R_SUCCESS && !yaml) {
+ delv_log(ISC_LOG_ERROR, "resolution failed: %s",
+ isc_result_totext(result));
+ }
+
+ if (yaml) {
+ printf("type: DELV_RESULT\n");
+ dns_name_format(query_name, namestr, sizeof(namestr));
+ printf("query_name: %s\n", namestr);
+ printf("status: %s\n", isc_result_totext(result));
+ printf("records:\n");
+ }
+
+ for (response_name = ISC_LIST_HEAD(namelist); response_name != NULL;
+ response_name = ISC_LIST_NEXT(response_name, link))
+ {
+ for (rdataset = ISC_LIST_HEAD(response_name->list);
+ rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ result = printdata(rdataset, response_name, style);
+ if (result != ISC_R_SUCCESS) {
+ delv_log(ISC_LOG_ERROR, "print data failed");
+ }
+ }
+ }
+
+ dns_client_freeresanswer(client, &namelist);
+
+cleanup:
+ if (trust_anchor != NULL) {
+ isc_mem_free(mctx, trust_anchor);
+ }
+ if (anchorfile != NULL) {
+ isc_mem_free(mctx, anchorfile);
+ }
+ if (qname != NULL) {
+ isc_mem_free(mctx, qname);
+ }
+ if (style != NULL) {
+ dns_master_styledestroy(&style, mctx);
+ }
+ if (client != NULL) {
+ dns_client_detach(&client);
+ }
+
+ isc_managers_destroy(&netmgr, &taskmgr, &timermgr);
+
+ if (actx != NULL) {
+ isc_appctx_destroy(&actx);
+ }
+ if (lctx != NULL) {
+ isc_log_destroy(&lctx);
+ }
+ isc_mem_detach(&mctx);
+
+ dst_lib_destroy();
+
+ return (0);
+}
diff --git a/bin/delv/delv.rst b/bin/delv/delv.rst
new file mode 100644
index 0000000..bf6cce1
--- /dev/null
+++ b/bin/delv/delv.rst
@@ -0,0 +1,364 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: delv
+.. program:: delv
+.. _man_delv:
+
+delv - DNS lookup and validation utility
+----------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`delv` [@server] [ [**-4**] | [**-6**] ] [**-a** anchor-file] [**-b** address] [**-c** class] [**-d** level] [**-i**] [**-m**] [**-p** port#] [**-q** name] [**-t** type] [**-x** addr] [name] [type] [class] [queryopt...]
+
+:program:`delv` [**-h**]
+
+:program:`delv` [**-v**]
+
+:program:`delv` [queryopt...] [query...]
+
+Description
+~~~~~~~~~~~
+
+:program:`delv` is a tool for sending DNS queries and validating the results,
+using the same internal resolver and validator logic as :iscman:`named`.
+
+:program:`delv` sends to a specified name server all queries needed to
+fetch and validate the requested data; this includes the original
+requested query, subsequent queries to follow CNAME or DNAME chains,
+queries for DNSKEY, and DS records to establish a chain of trust for
+DNSSEC validation. It does not perform iterative resolution, but
+simulates the behavior of a name server configured for DNSSEC validating
+and forwarding.
+
+By default, responses are validated using the built-in DNSSEC trust anchor
+for the root zone ("."). Records returned by :program:`delv` are either fully
+validated or were not signed. If validation fails, an explanation of the
+failure is included in the output; the validation process can be traced
+in detail. Because :program:`delv` does not rely on an external server to carry
+out validation, it can be used to check the validity of DNS responses in
+environments where local name servers may not be trustworthy.
+
+Unless it is told to query a specific name server, :program:`delv` tries
+each of the servers listed in ``/etc/resolv.conf``. If no usable server
+addresses are found, :program:`delv` sends queries to the localhost
+addresses (127.0.0.1 for IPv4, ::1 for IPv6).
+
+When no command-line arguments or options are given, :program:`delv`
+performs an NS query for "." (the root zone).
+
+Simple Usage
+~~~~~~~~~~~~
+
+A typical invocation of :program:`delv` looks like:
+
+::
+
+ delv @server name type
+
+where:
+
+.. option:: server
+
+ is the name or IP address of the name server to query. This can be an
+ IPv4 address in dotted-decimal notation or an IPv6 address in
+ colon-delimited notation. When the supplied ``server`` argument is a
+ hostname, :program:`delv` resolves that name before querying that name
+ server (note, however, that this initial lookup is *not* validated by
+ DNSSEC).
+
+ If no ``server`` argument is provided, :program:`delv` consults
+ ``/etc/resolv.conf``; if an address is found there, it queries the
+ name server at that address. If either of the :option:`-4` or :option:`-6`
+ options is in use, then only addresses for the corresponding
+ transport are tried. If no usable addresses are found, :program:`delv`
+ sends queries to the localhost addresses (127.0.0.1 for IPv4, ::1
+ for IPv6).
+
+.. option:: name
+
+ is the domain name to be looked up.
+
+.. option:: type
+
+ indicates what type of query is required - ANY, A, MX, etc.
+ ``type`` can be any valid query type. If no ``type`` argument is
+ supplied, :program:`delv` performs a lookup for an A record.
+
+Options
+~~~~~~~
+
+.. option:: -a anchor-file
+
+ This option specifies a file from which to read DNSSEC trust anchors. The default
+ is |bind_keys|, which is included with BIND 9 and contains one
+ or more trust anchors for the root zone (".").
+
+ Keys that do not match the root zone name are ignored. An alternate
+ key name can be specified using the :option:`+root` option.
+
+ Note: When reading the trust anchor file, :program:`delv` treats ``trust-anchors``,
+ ``initial-key``, and ``static-key`` identically. That is, for a managed key,
+ it is the *initial* key that is trusted; :rfc:`5011` key management is not
+ supported. :program:`delv` does not consult the managed-keys database maintained by
+ :iscman:`named`, which means that if either of the keys in |bind_keys| is
+ revoked and rolled over, |bind_keys| must be updated to
+ use DNSSEC validation in :program:`delv`.
+
+.. option:: -b address
+
+ This option sets the source IP address of the query to ``address``. This must be
+ a valid address on one of the host's network interfaces, or ``0.0.0.0``,
+ or ``::``. An optional source port may be specified by appending
+ ``#<port>``
+
+.. option:: -c class
+
+ This option sets the query class for the requested data. Currently, only class
+ "IN" is supported in :program:`delv` and any other value is ignored.
+
+.. option:: -d level
+
+ This option sets the systemwide debug level to ``level``. The allowed range is
+ from 0 to 99. The default is 0 (no debugging). Debugging traces from
+ :program:`delv` become more verbose as the debug level increases. See the
+ :option:`+mtrace`, :option:`+rtrace`, and :option:`+vtrace` options below for
+ additional debugging details.
+
+.. option:: -h
+
+ This option displays the :program:`delv` help usage output and exits.
+
+.. option:: -i
+
+ This option sets insecure mode, which disables internal DNSSEC validation. (Note,
+ however, that this does not set the CD bit on upstream queries. If the
+ server being queried is performing DNSSEC validation, then it does
+ not return invalid data; this can cause :program:`delv` to time out. When it
+ is necessary to examine invalid data to debug a DNSSEC problem, use
+ :option:`dig +cd`.)
+
+.. option:: -m
+
+ This option enables memory usage debugging.
+
+.. option:: -p port#
+
+ This option specifies a destination port to use for queries, instead of the
+ standard DNS port number 53. This option is used with a name
+ server that has been configured to listen for queries on a
+ non-standard port number.
+
+.. option:: -q name
+
+ This option sets the query name to ``name``. While the query name can be
+ specified without using the :option:`-q` option, it is sometimes necessary to
+ disambiguate names from types or classes (for example, when looking
+ up the name "ns", which could be misinterpreted as the type NS, or
+ "ch", which could be misinterpreted as class CH).
+
+.. option:: -t type
+
+ This option sets the query type to ``type``, which can be any valid query type
+ supported in BIND 9 except for zone transfer types AXFR and IXFR. As
+ with :option:`-q`, this is useful to distinguish query-name types or classes
+ when they are ambiguous. It is sometimes necessary to disambiguate
+ names from types.
+
+ The default query type is "A", unless the :option:`-x` option is supplied
+ to indicate a reverse lookup, in which case it is "PTR".
+
+.. option:: -v
+
+ This option prints the :program:`delv` version and exits.
+
+.. option:: -x addr
+
+ This option performs a reverse lookup, mapping an address to a name. ``addr``
+ is an IPv4 address in dotted-decimal notation, or a colon-delimited
+ IPv6 address. When :option:`-x` is used, there is no need to provide the
+ ``name`` or ``type`` arguments; :program:`delv` automatically performs a
+ lookup for a name like ``11.12.13.10.in-addr.arpa`` and sets the
+ query type to PTR. IPv6 addresses are looked up using nibble format
+ under the IP6.ARPA domain.
+
+.. option:: -4
+
+ This option forces :program:`delv` to only use IPv4.
+
+.. option:: -6
+
+ This option forces :program:`delv` to only use IPv6.
+
+Query Options
+~~~~~~~~~~~~~
+
+:program:`delv` provides a number of query options which affect the way results
+are displayed, and in some cases the way lookups are performed.
+
+Each query option is identified by a keyword preceded by a plus sign
+(``+``). Some keywords set or reset an option. These may be preceded by
+the string ``no`` to negate the meaning of that keyword. Other keywords
+assign values to options like the timeout interval. They have the form
+``+keyword=value``. The query options are:
+
+.. option:: +cdflag, +nocdflag
+
+ This option controls whether to set the CD (checking disabled) bit in queries
+ sent by :program:`delv`. This may be useful when troubleshooting DNSSEC
+ problems from behind a validating resolver. A validating resolver
+ blocks invalid responses, making it difficult to retrieve them
+ for analysis. Setting the CD flag on queries causes the resolver
+ to return invalid responses, which :program:`delv` can then validate
+ internally and report the errors in detail.
+
+.. option:: +class, +noclass
+
+ This option controls whether to display the CLASS when printing a record. The
+ default is to display the CLASS.
+
+.. option:: +ttl, +nottl
+
+ This option controls whether to display the TTL when printing a record. The
+ default is to display the TTL.
+
+.. option:: +rtrace, +nortrace
+
+ This option toggles resolver fetch logging. This reports the name and type of each
+ query sent by :program:`delv` in the process of carrying out the resolution
+ and validation process, including the original query
+ and all subsequent queries to follow CNAMEs and to establish a chain
+ of trust for DNSSEC validation.
+
+ This is equivalent to setting the debug level to 1 in the "resolver"
+ logging category. Setting the systemwide debug level to 1 using the
+ :option:`-d` option produces the same output, but affects other
+ logging categories as well.
+
+.. option:: +mtrace, +nomtrace
+
+ This option toggles message logging. This produces a detailed dump of the
+ responses received by :program:`delv` in the process of carrying out the
+ resolution and validation process.
+
+ This is equivalent to setting the debug level to 10 for the "packets"
+ module of the "resolver" logging category. Setting the systemwide
+ debug level to 10 using the :option:`-d` option produces the same
+ output, but affects other logging categories as well.
+
+.. option:: +vtrace, +novtrace
+
+ This option toggles validation logging. This shows the internal process of the
+ validator as it determines whether an answer is validly signed,
+ unsigned, or invalid.
+
+ This is equivalent to setting the debug level to 3 for the
+ "validator" module of the "dnssec" logging category. Setting the
+ systemwide debug level to 3 using the :option:`-d` option produces the
+ same output, but affects other logging categories as well.
+
+.. option:: +short, +noshort
+
+ This option toggles between verbose and terse answers. The default is to print the answer in a
+ verbose form.
+
+.. option:: +comments, +nocomments
+
+ This option toggles the display of comment lines in the output. The default is to
+ print comments.
+
+.. option:: +rrcomments, +norrcomments
+
+ This option toggles the display of per-record comments in the output (for example,
+ human-readable key information about DNSKEY records). The default is
+ to print per-record comments.
+
+.. option:: +crypto, +nocrypto
+
+ This option toggles the display of cryptographic fields in DNSSEC records. The
+ contents of these fields are unnecessary to debug most DNSSEC
+ validation failures and removing them makes it easier to see the
+ common failures. The default is to display the fields. When omitted,
+ they are replaced by the string ``[omitted]`` or, in the DNSKEY case, the
+ key ID is displayed as the replacement, e.g. ``[ key id = value ]``.
+
+.. option:: +trust, +notrust
+
+ This option controls whether to display the trust level when printing a record.
+ The default is to display the trust level.
+
+.. option:: +split[=W], +nosplit
+
+ This option splits long hex- or base64-formatted fields in resource records into
+ chunks of ``W`` characters (where ``W`` is rounded up to the nearest
+ multiple of 4). ``+nosplit`` or ``+split=0`` causes fields not to be
+ split at all. The default is 56 characters, or 44 characters when
+ multiline mode is active.
+
+.. option:: +all, +noall
+
+ This option sets or clears the display options :option:`+comments`,
+ :option:`+rrcomments`, and :option:`+trust` as a group.
+
+.. option:: +multiline, +nomultiline
+
+ This option prints long records (such as RRSIG, DNSKEY, and SOA records) in a
+ verbose multi-line format with human-readable comments. The default
+ is to print each record on a single line, to facilitate machine
+ parsing of the :program:`delv` output.
+
+.. option:: +dnssec, +nodnssec
+
+ This option indicates whether to display RRSIG records in the :program:`delv` output.
+ The default is to do so. Note that (unlike in :iscman:`dig`) this does
+ *not* control whether to request DNSSEC records or to
+ validate them. DNSSEC records are always requested, and validation
+ always occurs unless suppressed by the use of :option:`-i` or
+ :option:`+noroot`.
+
+.. option:: +root[=ROOT], +noroot
+
+ This option indicates whether to perform conventional DNSSEC validation, and if so,
+ specifies the name of a trust anchor. The default is to validate using a
+ trust anchor of "." (the root zone), for which there is a built-in key. If
+ specifying a different trust anchor, then :option:`-a` must be used to specify a
+ file containing the key.
+
+.. option:: +tcp, +notcp
+
+ This option controls whether to use TCP when sending queries. The default is to
+ use UDP unless a truncated response has been received.
+
+.. option:: +unknownformat, +nounknownformat
+
+ This option prints all RDATA in unknown RR-type presentation format (:rfc:`3597`).
+ The default is to print RDATA for known types in the type's
+ presentation format.
+
+.. option:: +yaml, +noyaml
+
+ This option prints response data in YAML format.
+
+Files
+~~~~~
+
+|bind_keys|
+
+``/etc/resolv.conf``
+
+See Also
+~~~~~~~~
+
+:iscman:`dig(1) <dig>`, :iscman:`named(8) <named>`, :rfc:`4034`, :rfc:`4035`, :rfc:`4431`, :rfc:`5074`, :rfc:`5155`.
diff --git a/bin/dig/Makefile.am b/bin/dig/Makefile.am
new file mode 100644
index 0000000..32dea5b
--- /dev/null
+++ b/bin/dig/Makefile.am
@@ -0,0 +1,39 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) \
+ $(LIBISCCFG_CFLAGS) \
+ $(LIBIRS_CFLAGS) \
+ $(LIBBIND9_CFLAGS) \
+ $(LIBIDN2_CFLAGS)
+
+LDADD += \
+ libdighost.la \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS) \
+ $(LIBISCCFG_LIBS) \
+ $(LIBIRS_LIBS) \
+ $(LIBBIND9_LIBS) \
+ $(LIBIDN2_LIBS)
+
+noinst_LTLIBRARIES = libdighost.la
+
+libdighost_la_SOURCES = \
+ dighost.h \
+ dighost.c
+
+bin_PROGRAMS = dig host nslookup
+
+nslookup_CPPFLAGS = \
+ $(AM_CPPFLAGS)
+
+nslookup_LDADD = \
+ $(LDADD)
+
+if HAVE_READLINE
+nslookup_CPPFLAGS += \
+ $(READLINE_CFLAGS)
+nslookup_LDADD += \
+ $(READLINE_LIBS)
+endif HAVE_READLINE
diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in
new file mode 100644
index 0000000..e5e09ba
--- /dev/null
+++ b/bin/dig/Makefile.in
@@ -0,0 +1,897 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+bin_PROGRAMS = dig$(EXEEXT) host$(EXEEXT) nslookup$(EXEEXT)
+@HAVE_READLINE_TRUE@am__append_2 = \
+@HAVE_READLINE_TRUE@ $(READLINE_CFLAGS)
+
+@HAVE_READLINE_TRUE@am__append_3 = \
+@HAVE_READLINE_TRUE@ $(READLINE_LIBS)
+
+subdir = bin/dig
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libdighost_la_LIBADD =
+am_libdighost_la_OBJECTS = dighost.lo
+libdighost_la_OBJECTS = $(am_libdighost_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+dig_SOURCES = dig.c
+dig_OBJECTS = dig.$(OBJEXT)
+dig_LDADD = $(LDADD)
+am__DEPENDENCIES_1 =
+dig_DEPENDENCIES = libdighost.la $(LIBISC_LIBS) $(LIBDNS_LIBS) \
+ $(LIBISCCFG_LIBS) $(LIBIRS_LIBS) $(LIBBIND9_LIBS) \
+ $(am__DEPENDENCIES_1)
+host_SOURCES = host.c
+host_OBJECTS = host.$(OBJEXT)
+host_LDADD = $(LDADD)
+host_DEPENDENCIES = libdighost.la $(LIBISC_LIBS) $(LIBDNS_LIBS) \
+ $(LIBISCCFG_LIBS) $(LIBIRS_LIBS) $(LIBBIND9_LIBS) \
+ $(am__DEPENDENCIES_1)
+nslookup_SOURCES = nslookup.c
+nslookup_OBJECTS = nslookup-nslookup.$(OBJEXT)
+am__DEPENDENCIES_2 = libdighost.la $(LIBISC_LIBS) $(LIBDNS_LIBS) \
+ $(LIBISCCFG_LIBS) $(LIBIRS_LIBS) $(LIBBIND9_LIBS) \
+ $(am__DEPENDENCIES_1)
+@HAVE_READLINE_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+nslookup_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/dig.Po ./$(DEPDIR)/dighost.Plo \
+ ./$(DEPDIR)/host.Po ./$(DEPDIR)/nslookup-nslookup.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libdighost_la_SOURCES) dig.c host.c nslookup.c
+DIST_SOURCES = $(libdighost_la_SOURCES) dig.c host.c nslookup.c
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \
+ $(LIBISCCFG_CFLAGS) $(LIBIRS_CFLAGS) $(LIBBIND9_CFLAGS) \
+ $(LIBIDN2_CFLAGS)
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD = libdighost.la $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBISCCFG_LIBS) \
+ $(LIBIRS_LIBS) $(LIBBIND9_LIBS) $(LIBIDN2_LIBS)
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+noinst_LTLIBRARIES = libdighost.la
+libdighost_la_SOURCES = \
+ dighost.h \
+ dighost.c
+
+nslookup_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_2)
+nslookup_LDADD = $(LDADD) $(am__append_3)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/dig/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/dig/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libdighost.la: $(libdighost_la_OBJECTS) $(libdighost_la_DEPENDENCIES) $(EXTRA_libdighost_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libdighost_la_OBJECTS) $(libdighost_la_LIBADD) $(LIBS)
+
+dig$(EXEEXT): $(dig_OBJECTS) $(dig_DEPENDENCIES) $(EXTRA_dig_DEPENDENCIES)
+ @rm -f dig$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dig_OBJECTS) $(dig_LDADD) $(LIBS)
+
+host$(EXEEXT): $(host_OBJECTS) $(host_DEPENDENCIES) $(EXTRA_host_DEPENDENCIES)
+ @rm -f host$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(host_OBJECTS) $(host_LDADD) $(LIBS)
+
+nslookup$(EXEEXT): $(nslookup_OBJECTS) $(nslookup_DEPENDENCIES) $(EXTRA_nslookup_DEPENDENCIES)
+ @rm -f nslookup$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(nslookup_OBJECTS) $(nslookup_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dig.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dighost.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/host.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nslookup-nslookup.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+nslookup-nslookup.o: nslookup.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nslookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nslookup-nslookup.o -MD -MP -MF $(DEPDIR)/nslookup-nslookup.Tpo -c -o nslookup-nslookup.o `test -f 'nslookup.c' || echo '$(srcdir)/'`nslookup.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nslookup-nslookup.Tpo $(DEPDIR)/nslookup-nslookup.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nslookup.c' object='nslookup-nslookup.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nslookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nslookup-nslookup.o `test -f 'nslookup.c' || echo '$(srcdir)/'`nslookup.c
+
+nslookup-nslookup.obj: nslookup.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nslookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nslookup-nslookup.obj -MD -MP -MF $(DEPDIR)/nslookup-nslookup.Tpo -c -o nslookup-nslookup.obj `if test -f 'nslookup.c'; then $(CYGPATH_W) 'nslookup.c'; else $(CYGPATH_W) '$(srcdir)/nslookup.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nslookup-nslookup.Tpo $(DEPDIR)/nslookup-nslookup.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nslookup.c' object='nslookup-nslookup.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nslookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nslookup-nslookup.obj `if test -f 'nslookup.c'; then $(CYGPATH_W) 'nslookup.c'; else $(CYGPATH_W) '$(srcdir)/nslookup.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/dig.Po
+ -rm -f ./$(DEPDIR)/dighost.Plo
+ -rm -f ./$(DEPDIR)/host.Po
+ -rm -f ./$(DEPDIR)/nslookup-nslookup.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/dig.Po
+ -rm -f ./$(DEPDIR)/dighost.Plo
+ -rm -f ./$(DEPDIR)/host.Po
+ -rm -f ./$(DEPDIR)/nslookup-nslookup.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am: uninstall-binPROGRAMS
+
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-binPROGRAMS clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir doc-am doc-local dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am test-am test-local uninstall uninstall-am \
+ uninstall-binPROGRAMS unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/dig/dig.c b/bin/dig/dig.c
new file mode 100644
index 0000000..87552be
--- /dev/null
+++ b/bin/dig/dig.c
@@ -0,0 +1,3102 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <isc/app.h>
+#include <isc/attributes.h>
+#include <isc/dir.h>
+#include <isc/netaddr.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/dns64.h>
+#include <dns/fixedname.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rcode.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/tsig.h>
+
+#include "dighost.h"
+
+#define ADD_STRING(b, s) \
+ { \
+ if (strlen(s) >= isc_buffer_availablelength(b)) { \
+ return ((((ISC_R_NOSPACE)))); \
+ } else { \
+ isc_buffer_putstr(b, s); \
+ } \
+ }
+
+#define DIG_MAX_ADDRESSES 20
+
+dig_lookup_t *default_lookup = NULL;
+
+static atomic_uintptr_t batchname = 0;
+static FILE *batchfp = NULL;
+static char *argv0;
+static int addresscount = 0;
+
+static char domainopt[DNS_NAME_MAXTEXT];
+static char hexcookie[81];
+
+static bool short_form = false, printcmd = true, plusquest = false,
+ pluscomm = false, ipv4only = false, ipv6only = false, digrc = true;
+static uint32_t splitwidth = 0xffffffff;
+
+/*% opcode text */
+static const char *const opcodetext[] = {
+ "QUERY", "IQUERY", "STATUS", "RESERVED3",
+ "NOTIFY", "UPDATE", "RESERVED6", "RESERVED7",
+ "RESERVED8", "RESERVED9", "RESERVED10", "RESERVED11",
+ "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15"
+};
+
+static const char *
+rcode_totext(dns_rcode_t rcode) {
+ static char buf[64];
+ isc_buffer_t b;
+ isc_result_t result;
+
+ memset(buf, 0, sizeof(buf));
+ isc_buffer_init(&b, buf + 1, sizeof(buf) - 2);
+ result = dns_rcode_totext(rcode, &b);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (strspn(buf + 1, "0123456789") == strlen(buf + 1)) {
+ buf[0] = '?';
+ return (buf);
+ }
+ return (buf + 1);
+}
+
+/*% print usage */
+static void
+print_usage(FILE *fp) {
+ fprintf(fp,
+ "Usage: dig [@global-server] [domain] [q-type] [q-class] "
+ "{q-opt}\n"
+ " {global-d-opt} host [@local-server] "
+ "{local-d-opt}\n"
+ " [ host [@local-server] {local-d-opt} [...]]\n");
+}
+
+#if TARGET_OS_IPHONE
+static void
+usage(void) {
+ fprintf(stderr, "Press <Help> for complete list of options\n");
+}
+#else /* if TARGET_OS_IPHONE */
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ print_usage(stderr);
+ fprintf(stderr, "\nUse \"dig -h\" (or \"dig -h | more\") "
+ "for complete list of options\n");
+ exit(1);
+}
+#endif /* if TARGET_OS_IPHONE */
+
+/*% version */
+static void
+version(void) {
+ fprintf(stderr, "DiG %s\n", PACKAGE_VERSION);
+}
+
+/*% help */
+static void
+help(void) {
+ print_usage(stdout);
+ printf("Where: domain is in the Domain Name System\n"
+ " q-class is one of (in,hs,ch,...) [default: in]\n"
+ " q-type is one of "
+ "(a,any,mx,ns,soa,hinfo,axfr,txt,...) "
+ "[default:a]\n"
+ " (Use ixfr=version for type ixfr)\n"
+ " q-opt is one of:\n"
+ " -4 (use IPv4 query transport "
+ "only)\n"
+ " -6 (use IPv6 query transport "
+ "only)\n"
+ " -b address[#port] (bind to source "
+ "address/port)\n"
+ " -c class (specify query class)\n"
+ " -f filename (batch mode)\n"
+ " -k keyfile (specify tsig key file)\n"
+ " -m (enable memory usage "
+ "debugging)\n"
+ " -p port (specify port number)\n"
+ " -q name (specify query name)\n"
+ " -r (do not read ~/.digrc)\n"
+ " -t type (specify query type)\n"
+ " -u (display times in usec "
+ "instead of msec)\n"
+ " -x dot-notation (shortcut for reverse "
+ "lookups)\n"
+ " -y [hmac:]name:key (specify named base64 "
+ "tsig "
+ "key)\n"
+ " d-opt is of the form +keyword[=value], where "
+ "keyword "
+ "is:\n"
+ " +[no]aaflag (Set AA flag in query "
+ "(+[no]aaflag))\n"
+ " +[no]aaonly (Set AA flag in query "
+ "(+[no]aaflag))\n"
+ " +[no]additional (Control display of "
+ "additional section)\n"
+ " +[no]adflag (Set AD flag in query "
+ "(default on))\n"
+ " +[no]all (Set or clear all display "
+ "flags)\n"
+ " +[no]answer (Control display of "
+ "answer "
+ "section)\n"
+ " +[no]authority (Control display of "
+ "authority section)\n"
+ " +[no]badcookie (Retry BADCOOKIE "
+ "responses)\n"
+ " +[no]besteffort (Try to parse even "
+ "illegal "
+ "messages)\n"
+ " +bufsize[=###] (Set EDNS0 Max UDP packet "
+ "size)\n"
+ " +[no]cdflag (Set checking disabled "
+ "flag in query)\n"
+ " +[no]class (Control display of class "
+ "in records)\n"
+ " +[no]cmd (Control display of "
+ "command line -\n"
+ " global option)\n"
+ " +[no]comments (Control display of "
+ "packet "
+ "header\n"
+ " and section name "
+ "comments)\n"
+ " +[no]cookie (Add a COOKIE option to "
+ "the request)\n"
+ " +[no]crypto (Control display of "
+ "cryptographic\n"
+ " fields in records)\n"
+ " +[no]defname (Use search list "
+ "(+[no]search))\n"
+ " +[no]dns64prefix (Get the DNS64 prefixes "
+ "from ipv4only.arpa)\n"
+ " +[no]dnssec (Request DNSSEC records)\n"
+ " +domain=### (Set default domainname)\n"
+ " +[no]edns[=###] (Set EDNS version) [0]\n"
+ " +ednsflags=### (Set EDNS flag bits)\n"
+ " +[no]ednsnegotiation (Set EDNS version "
+ "negotiation)\n"
+ " +ednsopt=###[:value] (Send specified EDNS "
+ "option)\n"
+ " +noednsopt (Clear list of +ednsopt "
+ "options)\n"
+ " +[no]expandaaaa (Expand AAAA records)\n"
+ " +[no]expire (Request time to expire)\n"
+ " +[no]fail (Don't try next server on "
+ "SERVFAIL)\n"
+ " +[no]header-only (Send query without a "
+ "question section)\n"
+ " +[no]https[=###] (DNS-over-HTTPS mode) "
+ "[/]\n"
+ " +[no]https-get (Use GET instead of "
+ "default POST method while using HTTPS)\n"
+ " +[no]http-plain[=###] (DNS over plain HTTP "
+ "mode) "
+ "[/]\n"
+ " +[no]http-plain-get (Use GET instead of "
+ "default POST method while using plain HTTP)\n"
+ " +[no]identify (ID responders in short "
+ "answers)\n"
+#ifdef HAVE_LIBIDN2
+ " +[no]idnin (Parse IDN names "
+ "[default=on on tty])\n"
+ " +[no]idnout (Convert IDN response "
+ "[default=on on tty])\n"
+#endif /* ifdef HAVE_LIBIDN2 */
+ " +[no]ignore (Don't revert to TCP for "
+ "TC responses.)\n"
+ " +[no]keepalive (Request EDNS TCP "
+ "keepalive)\n"
+ " +[no]keepopen (Keep the TCP socket open "
+ "between "
+ "queries)\n"
+ " +[no]multiline (Print records in an "
+ "expanded format)\n"
+ " +ndots=### (Set search NDOTS value)\n"
+ " +[no]nsid (Request Name Server ID)\n"
+ " +[no]nssearch (Search all authoritative "
+ "nameservers)\n"
+ " +[no]onesoa (AXFR prints only one soa "
+ "record)\n"
+ " +[no]opcode=### (Set the opcode of the "
+ "request)\n"
+ " +padding=### (Set padding block size "
+ "[0])\n"
+ " +qid=### (Specify the query ID to "
+ "use when sending queries)\n"
+ " +[no]qr (Print question before "
+ "sending)\n"
+ " +[no]question (Control display of "
+ "question section)\n"
+ " +[no]raflag (Set RA flag in query "
+ "(+[no]raflag))\n"
+ " +[no]rdflag (Recursive mode "
+ "(+[no]recurse))\n"
+ " +[no]recurse (Recursive mode "
+ "(+[no]rdflag))\n"
+ " +retry=### (Set number of UDP "
+ "retries) [2]\n"
+ " +[no]rrcomments (Control display of "
+ "per-record "
+ "comments)\n"
+ " +[no]search (Set whether to use "
+ "searchlist)\n"
+ " +[no]short (Display nothing except "
+ "short\n"
+ " form of answers - global "
+ "option)\n"
+ " +[no]showbadcookie (Show BADCOOKIE message)\n"
+ " +[no]showsearch (Search with intermediate "
+ "results)\n"
+ " +[no]split=## (Split hex/base64 fields "
+ "into chunks)\n"
+ " +[no]stats (Control display of "
+ "statistics)\n"
+ " +subnet=addr (Set edns-client-subnet "
+ "option)\n"
+ " +[no]tcflag (Set TC flag in query "
+ "(+[no]tcflag))\n"
+ " +[no]tcp (TCP mode (+[no]vc))\n"
+ " +timeout=### (Set query timeout) [5]\n"
+ " +[no]tls (DNS-over-TLS mode)\n"
+ " +[no]tls-ca[=file] (Enable remote server's "
+ "TLS certificate validation)\n"
+ " +[no]tls-hostname=hostname (Explicitly set "
+ "the expected TLS hostname)\n"
+ " +[no]tls-certfile=file (Load client TLS "
+ "certificate chain from file)\n"
+ " +[no]tls-keyfile=file (Load client TLS "
+ "private key from file)\n"
+ " +[no]trace (Trace delegation down "
+ "from root "
+ "[+dnssec])\n"
+ " +tries=### (Set number of UDP "
+ "attempts) [3]\n"
+ " +[no]ttlid (Control display of ttls "
+ "in records)\n"
+ " +[no]ttlunits (Display TTLs in "
+ "human-readable units)\n"
+ " +[no]unknownformat (Print RDATA in RFC 3597 "
+ "\"unknown\" "
+ "format)\n"
+ " +[no]vc (TCP mode (+[no]tcp))\n"
+ " +[no]yaml (Present the results as "
+ "YAML)\n"
+ " +[no]zflag (Set Z flag in query)\n"
+ " global d-opts and servers (before host name) affect "
+ "all "
+ "queries.\n"
+ " local d-opts and servers (after host name) affect only "
+ "that lookup.\n"
+ " -h (print help and exit)\n"
+ " -v (print version "
+ "and exit)\n");
+}
+
+/*%
+ * Callback from dighost.c to print the received message.
+ */
+static void
+received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
+ uint64_t diff;
+ time_t tnow;
+ struct tm tmnow;
+ char time_str[100];
+ char fromtext[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(from, fromtext, sizeof(fromtext));
+
+ if (short_form || yaml) {
+ return;
+ }
+
+ if (query->lookup->stats) {
+ const char *proto;
+ diff = isc_time_microdiff(&query->time_recv, &query->time_sent);
+ if (query->lookup->use_usec) {
+ printf(";; Query time: %ld usec\n", (long)diff);
+ } else {
+ printf(";; Query time: %ld msec\n", (long)diff / 1000);
+ }
+ if (dig_lookup_is_tls(query->lookup)) {
+ proto = "TLS";
+ } else if (query->lookup->https_mode) {
+ if (query->lookup->http_plain) {
+ proto = query->lookup->https_get ? "HTTP-GET"
+ : "HTTP";
+ } else {
+ proto = query->lookup->https_get ? "HTTPS-GET"
+ : "HTTPS";
+ }
+ } else if (query->lookup->tcp_mode) {
+ proto = "TCP";
+ } else {
+ proto = "UDP";
+ }
+ printf(";; SERVER: %s(%s) (%s)\n", fromtext, query->userarg,
+ proto);
+ time(&tnow);
+ (void)localtime_r(&tnow, &tmnow);
+
+ if (strftime(time_str, sizeof(time_str),
+ "%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U)
+ {
+ printf(";; WHEN: %s\n", time_str);
+ }
+ if (query->lookup->doing_xfr) {
+ printf(";; XFR size: %u records (messages %u, "
+ "bytes %" PRIu64 ")\n",
+ query->rr_count, query->msg_count,
+ query->byte_count);
+ } else {
+ printf(";; MSG SIZE rcvd: %u\n", bytes);
+ }
+ if (tsigkey != NULL) {
+ if (!validated) {
+ puts(";; WARNING -- Some TSIG could not "
+ "be validated");
+ }
+ }
+ if ((tsigkey == NULL) && (keysecret[0] != 0)) {
+ puts(";; WARNING -- TSIG key was not used.");
+ }
+ puts("");
+ } else if (query->lookup->identify) {
+ diff = isc_time_microdiff(&query->time_recv, &query->time_sent);
+ if (query->lookup->use_usec) {
+ printf(";; Received %" PRIu64 " bytes "
+ "from %s(%s) in %ld us\n\n",
+ query->lookup->doing_xfr ? query->byte_count
+ : (uint64_t)bytes,
+ fromtext, query->userarg, (long)diff);
+ } else {
+ printf(";; Received %" PRIu64 " bytes "
+ "from %s(%s) in %ld ms\n\n",
+ query->lookup->doing_xfr ? query->byte_count
+ : (uint64_t)bytes,
+ fromtext, query->userarg, (long)diff / 1000);
+ }
+ }
+}
+
+/*
+ * Callback from dighost.c to print that it is trying a server.
+ * Not used in dig.
+ * XXX print_trying
+ */
+static void
+trying(char *frm, dig_lookup_t *lookup) {
+ UNUSED(frm);
+ UNUSED(lookup);
+}
+
+/*%
+ * Internal print routine used to print short form replies.
+ */
+static isc_result_t
+say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) {
+ isc_result_t result;
+ uint64_t diff;
+ char store[sizeof(" in 18446744073709551616 us.")];
+ unsigned int styleflags = 0;
+
+ if (query->lookup->trace || query->lookup->ns_search_only) {
+ result = dns_rdatatype_totext(rdata->type, buf);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ ADD_STRING(buf, " ");
+ }
+
+ /* Turn on rrcomments if explicitly enabled */
+ if (query->lookup->rrcomments > 0) {
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+ if (query->lookup->nocrypto) {
+ styleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ }
+ if (query->lookup->print_unknown_format) {
+ styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
+ }
+ if (query->lookup->expandaaaa) {
+ styleflags |= DNS_STYLEFLAG_EXPANDAAAA;
+ }
+ result = dns_rdata_tofmttext(rdata, NULL, styleflags, 0, splitwidth,
+ " ", buf);
+ if (result == ISC_R_NOSPACE) {
+ return (result);
+ }
+ check_result(result, "dns_rdata_totext");
+ if (query->lookup->identify) {
+ diff = isc_time_microdiff(&query->time_recv, &query->time_sent);
+ ADD_STRING(buf, " from server ");
+ ADD_STRING(buf, query->servname);
+ if (query->lookup->use_usec) {
+ snprintf(store, sizeof(store), " in %" PRIu64 " us.",
+ diff);
+ } else {
+ snprintf(store, sizeof(store), " in %" PRIu64 " ms.",
+ diff / 1000);
+ }
+ ADD_STRING(buf, store);
+ }
+ ADD_STRING(buf, "\n");
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * short_form message print handler. Calls above say_message()
+ */
+static isc_result_t
+dns64prefix_answer(dns_message_t *msg, isc_buffer_t *buf) {
+ dns_rdataset_t *rdataset = NULL;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_result_t result;
+ isc_netprefix_t prefix[10];
+ size_t i, count = 10;
+
+ name = dns_fixedname_initname(&fixed);
+ result = dns_name_fromstring(name, "ipv4only.arpa", 0, NULL);
+ check_result(result, "dns_name_fromstring");
+
+ result = dns_message_findname(msg, DNS_SECTION_ANSWER, name,
+ dns_rdatatype_aaaa, dns_rdatatype_none,
+ NULL, &rdataset);
+ if (result == DNS_R_NXDOMAIN || result == DNS_R_NXRRSET) {
+ return (ISC_R_SUCCESS);
+ } else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = dns_dns64_findprefix(rdataset, prefix, &count);
+ if (result == ISC_R_NOTFOUND) {
+ return (ISC_R_SUCCESS);
+ }
+ if (count > 10) {
+ count = 10;
+ }
+ for (i = 0; i < count; i++) {
+ result = isc_netaddr_totext(&prefix[i].addr, buf);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ result = isc_buffer_printf(buf, "/%u\n", prefix[i].prefixlen);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * short_form message print handler. Calls above say_message()
+ */
+static isc_result_t
+short_answer(dns_message_t *msg, dns_messagetextflag_t flags, isc_buffer_t *buf,
+ dig_query_t *query) {
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ isc_result_t result, loopresult;
+ dns_name_t empty_name;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ UNUSED(flags);
+
+ dns_name_init(&empty_name, NULL);
+ result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
+ if (result == ISC_R_NOMORE) {
+ return (ISC_R_SUCCESS);
+ } else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+
+ for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ result = say_message(&rdata, query, buf);
+ if (result == ISC_R_NOSPACE) {
+ return (result);
+ }
+ check_result(result, "say_message");
+ loopresult = dns_rdataset_next(rdataset);
+ dns_rdata_reset(&rdata);
+ }
+ }
+ result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
+ if (result == ISC_R_NOMORE) {
+ break;
+ } else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static bool
+isdotlocal(dns_message_t *msg) {
+ isc_result_t result;
+ static unsigned char local_ndata[] = { "\005local" };
+ static unsigned char local_offsets[] = { 0, 6 };
+ static dns_name_t local = DNS_NAME_INITABSOLUTE(local_ndata,
+ local_offsets);
+
+ for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(msg, DNS_SECTION_QUESTION))
+ {
+ dns_name_t *name = NULL;
+ dns_message_currentname(msg, DNS_SECTION_QUESTION, &name);
+ if (dns_name_issubdomain(name, &local)) {
+ return (true);
+ }
+ }
+ return (false);
+}
+
+/*
+ * Callback from dighost.c to print the reply from a server
+ */
+static isc_result_t
+printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg,
+ bool headers) {
+ isc_result_t result;
+ dns_messagetextflag_t flags;
+ isc_buffer_t *buf = NULL;
+ unsigned int len = OUTPUTBUF;
+ dns_master_style_t *style = NULL;
+ unsigned int styleflags = 0;
+ bool isquery = (msg == query->lookup->sendmsg);
+ bool dns64prefix = query->lookup->dns64prefix;
+
+ UNUSED(msgbuf);
+
+ dig_idnsetup(query->lookup, true);
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ if (yaml) {
+ msg->indent.string = " ";
+ msg->indent.count = 3;
+ styleflags |= DNS_STYLEFLAG_YAML;
+ } else {
+ if (query->lookup->comments) {
+ styleflags |= DNS_STYLEFLAG_COMMENT;
+ }
+ if (query->lookup->print_unknown_format) {
+ styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
+ }
+ /* Turn on rrcomments if explicitly enabled */
+ if (query->lookup->rrcomments > 0) {
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+ if (query->lookup->ttlunits) {
+ styleflags |= DNS_STYLEFLAG_TTL_UNITS;
+ }
+ if (query->lookup->nottl) {
+ styleflags |= DNS_STYLEFLAG_NO_TTL;
+ }
+ if (query->lookup->noclass) {
+ styleflags |= DNS_STYLEFLAG_NO_CLASS;
+ }
+ if (query->lookup->nocrypto) {
+ styleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ }
+ if (query->lookup->expandaaaa) {
+ styleflags |= DNS_STYLEFLAG_EXPANDAAAA;
+ }
+ if (query->lookup->multiline) {
+ styleflags |= DNS_STYLEFLAG_OMIT_OWNER;
+ styleflags |= DNS_STYLEFLAG_OMIT_CLASS;
+ styleflags |= DNS_STYLEFLAG_REL_DATA;
+ styleflags |= DNS_STYLEFLAG_OMIT_TTL;
+ styleflags |= DNS_STYLEFLAG_TTL;
+ styleflags |= DNS_STYLEFLAG_MULTILINE;
+ /* Turn on rrcomments unless explicitly disabled */
+ if (query->lookup->rrcomments >= 0) {
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+ }
+ }
+ if (query->lookup->multiline ||
+ (query->lookup->nottl && query->lookup->noclass))
+ {
+ result = dns_master_stylecreate(&style, styleflags, 24, 24, 24,
+ 32, 80, 8, splitwidth, mctx);
+ } else if (query->lookup->nottl || query->lookup->noclass) {
+ result = dns_master_stylecreate(&style, styleflags, 24, 24, 32,
+ 40, 80, 8, splitwidth, mctx);
+ } else {
+ result = dns_master_stylecreate(&style, styleflags, 24, 32, 40,
+ 48, 80, 8, splitwidth, mctx);
+ }
+ check_result(result, "dns_master_stylecreate");
+
+ if (query->lookup->cmdline[0] != 0) {
+ if (!short_form && !dns64prefix && printcmd) {
+ printf("%s", query->lookup->cmdline);
+ }
+ query->lookup->cmdline[0] = '\0';
+ }
+ debug("printmessage(%s %s %s)", headers ? "headers" : "noheaders",
+ query->lookup->comments ? "comments" : "nocomments",
+ short_form ? "short_form"
+ : dns64prefix ? "dns64prefix_form"
+ : "long_form");
+
+ flags = 0;
+ if (!headers) {
+ flags |= DNS_MESSAGETEXTFLAG_NOHEADERS;
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+ }
+ if (query->lookup->onesoa &&
+ query->lookup->rdtype == dns_rdatatype_axfr)
+ {
+ flags |= (query->msg_count == 0) ? DNS_MESSAGETEXTFLAG_ONESOA
+ : DNS_MESSAGETEXTFLAG_OMITSOA;
+ }
+ if (!query->lookup->comments) {
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+ }
+
+ isc_buffer_allocate(mctx, &buf, len);
+
+ if (yaml) {
+ enum { Q = 0x1, R = 0x2 }; /* Q:query; R:ecursive */
+ unsigned int tflag = 0;
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+ uint16_t sport;
+ char *hash;
+ int pf;
+
+ printf("-\n");
+ printf(" type: MESSAGE\n");
+ printf(" message:\n");
+
+ if (isquery) {
+ tflag |= Q;
+ if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
+ tflag |= R;
+ }
+ } else if (((msg->flags & DNS_MESSAGEFLAG_RD) != 0) &&
+ ((msg->flags & DNS_MESSAGEFLAG_RA) != 0))
+ {
+ tflag |= R;
+ }
+
+ if (tflag == (Q | R)) {
+ printf(" type: RECURSIVE_QUERY\n");
+ } else if (tflag == Q) {
+ printf(" type: AUTH_QUERY\n");
+ } else if (tflag == R) {
+ printf(" type: RECURSIVE_RESPONSE\n");
+ } else {
+ printf(" type: AUTH_RESPONSE\n");
+ }
+
+ if (!isc_time_isepoch(&query->time_sent)) {
+ char tbuf[100];
+ if (query->lookup->use_usec) {
+ isc_time_formatISO8601us(&query->time_sent,
+ tbuf, sizeof(tbuf));
+ } else {
+ isc_time_formatISO8601ms(&query->time_sent,
+ tbuf, sizeof(tbuf));
+ }
+ printf(" query_time: !!timestamp %s\n", tbuf);
+ }
+
+ if (!isquery && !isc_time_isepoch(&query->time_recv)) {
+ char tbuf[100];
+ if (query->lookup->use_usec) {
+ isc_time_formatISO8601us(&query->time_recv,
+ tbuf, sizeof(tbuf));
+ } else {
+ isc_time_formatISO8601ms(&query->time_recv,
+ tbuf, sizeof(tbuf));
+ }
+ printf(" response_time: !!timestamp %s\n", tbuf);
+ }
+
+ printf(" message_size: %ub\n",
+ isc_buffer_usedlength(msgbuf));
+
+ pf = isc_sockaddr_pf(&query->sockaddr);
+ if (pf == PF_INET || pf == PF_INET6) {
+ printf(" socket_family: %s\n",
+ pf == PF_INET ? "INET" : "INET6");
+
+ printf(" socket_protocol: %s\n",
+ query->lookup->tcp_mode ? "TCP" : "UDP");
+
+ sport = isc_sockaddr_getport(&query->sockaddr);
+ isc_sockaddr_format(&query->sockaddr, sockstr,
+ sizeof(sockstr));
+ hash = strchr(sockstr, '#');
+ if (hash != NULL) {
+ *hash = '\0';
+ }
+ if (strcmp(sockstr, "::") == 0) {
+ strlcat(sockstr, "0", sizeof(sockstr));
+ }
+
+ printf(" response_address: \"%s\"\n", sockstr);
+ printf(" response_port: %u\n", sport);
+ }
+
+ if (query->handle != NULL) {
+ isc_sockaddr_t saddr =
+ isc_nmhandle_localaddr(query->handle);
+ sport = isc_sockaddr_getport(&saddr);
+ isc_sockaddr_format(&saddr, sockstr, sizeof(sockstr));
+ hash = strchr(sockstr, '#');
+ if (hash != NULL) {
+ *hash = '\0';
+ }
+ if (strcmp(sockstr, "::") == 0) {
+ strlcat(sockstr, "0", sizeof(sockstr));
+ }
+
+ printf(" query_address: \"%s\"\n", sockstr);
+ printf(" query_port: %u\n", sport);
+ }
+
+ printf(" %s:\n", isquery ? "query_message_data"
+ : "response_message_data");
+ result = dns_message_headertotext(msg, style, flags, buf);
+ } else if (query->lookup->comments && !short_form && !dns64prefix) {
+ if (query->lookup->cmdline[0] != '\0' && printcmd) {
+ printf("; %s\n", query->lookup->cmdline);
+ }
+ if (msg == query->lookup->sendmsg) {
+ printf(";; Sending:\n");
+ } else {
+ printf(";; Got answer:\n");
+ }
+
+ if (headers) {
+ if (isdotlocal(msg)) {
+ printf(";; WARNING: .local is reserved for "
+ "Multicast DNS\n;; You are currently "
+ "testing what happens when an mDNS "
+ "query is leaked to DNS\n");
+ }
+ printf(";; ->>HEADER<<- opcode: %s, status: %s, "
+ "id: %u\n",
+ opcodetext[msg->opcode],
+ rcode_totext(msg->rcode), msg->id);
+ printf(";; flags:");
+ if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
+ printf(" qr");
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
+ printf(" aa");
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
+ printf(" tc");
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
+ printf(" rd");
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
+ printf(" ra");
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
+ printf(" ad");
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
+ printf(" cd");
+ }
+ if ((msg->flags & 0x0040U) != 0) {
+ printf("; MBZ: 0x4");
+ }
+
+ printf("; QUERY: %u, ANSWER: %u, "
+ "AUTHORITY: %u, ADDITIONAL: %u\n",
+ msg->counts[DNS_SECTION_QUESTION],
+ msg->counts[DNS_SECTION_ANSWER],
+ msg->counts[DNS_SECTION_AUTHORITY],
+ msg->counts[DNS_SECTION_ADDITIONAL]);
+
+ if (msg != query->lookup->sendmsg &&
+ (msg->flags & DNS_MESSAGEFLAG_RD) != 0 &&
+ (msg->flags & DNS_MESSAGEFLAG_RA) == 0)
+ {
+ printf(";; WARNING: recursion requested "
+ "but not available\n");
+ }
+ }
+ if (msg != query->lookup->sendmsg &&
+ query->lookup->edns != -1 && msg->opt == NULL &&
+ (msg->rcode == dns_rcode_formerr ||
+ msg->rcode == dns_rcode_notimp))
+ {
+ printf("\n;; WARNING: EDNS query returned status "
+ "%s - retry with '%s+noedns'\n",
+ rcode_totext(msg->rcode),
+ query->lookup->dnssec ? "+nodnssec " : "");
+ }
+ if (msg != query->lookup->sendmsg && extrabytes != 0U) {
+ printf(";; WARNING: Message has %u extra byte%s at "
+ "end\n",
+ extrabytes, extrabytes != 0 ? "s" : "");
+ }
+ }
+
+repopulate_buffer:
+
+ if (query->lookup->comments && headers && !short_form && !dns64prefix) {
+ result = dns_message_pseudosectiontotext(
+ msg, DNS_PSEUDOSECTION_OPT, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ buftoosmall:
+ len += OUTPUTBUF;
+ isc_buffer_free(&buf);
+ isc_buffer_allocate(mctx, &buf, len);
+ goto repopulate_buffer;
+ }
+ check_result(result, "dns_message_pseudosectiontotext");
+ }
+
+ if (query->lookup->section_question && headers) {
+ if (!short_form && !dns64prefix) {
+ result = dns_message_sectiontotext(
+ msg, DNS_SECTION_QUESTION, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ check_result(result, "dns_message_sectiontotext");
+ }
+ }
+ if (query->lookup->section_answer) {
+ if (!short_form && !dns64prefix) {
+ result = dns_message_sectiontotext(
+ msg, DNS_SECTION_ANSWER, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ check_result(result, "dns_message_sectiontotext");
+ } else if (dns64prefix) {
+ result = dns64prefix_answer(msg, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ check_result(result, "dns64prefix_answer");
+ } else {
+ result = short_answer(msg, flags, buf, query);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ check_result(result, "short_answer");
+ }
+ }
+ if (query->lookup->section_authority) {
+ if (!short_form && !dns64prefix) {
+ result = dns_message_sectiontotext(
+ msg, DNS_SECTION_AUTHORITY, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ check_result(result, "dns_message_sectiontotext");
+ }
+ }
+ if (query->lookup->section_additional) {
+ if (!short_form && !dns64prefix) {
+ result = dns_message_sectiontotext(
+ msg, DNS_SECTION_ADDITIONAL, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ check_result(result, "dns_message_sectiontotext");
+ /*
+ * Only print the signature on the first record.
+ */
+ if (headers) {
+ result = dns_message_pseudosectiontotext(
+ msg, DNS_PSEUDOSECTION_TSIG, style,
+ flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ check_result(result, "dns_message_"
+ "pseudosectiontotext");
+ result = dns_message_pseudosectiontotext(
+ msg, DNS_PSEUDOSECTION_SIG0, style,
+ flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ check_result(result, "dns_message_"
+ "pseudosectiontotext");
+ }
+ }
+ }
+
+ if (headers && query->lookup->comments && !short_form && !yaml) {
+ printf("\n");
+ }
+
+ printf("%.*s", (int)isc_buffer_usedlength(buf),
+ (char *)isc_buffer_base(buf));
+ isc_buffer_free(&buf);
+
+ if (style != NULL) {
+ dns_master_styledestroy(&style, mctx);
+ }
+
+ dig_idnsetup(query->lookup, false);
+
+ return (result);
+}
+
+/*%
+ * print the greeting message when the program first starts up.
+ */
+static void
+printgreeting(int argc, char **argv, dig_lookup_t *lookup) {
+ int i;
+ static bool first = true;
+ char append[MXNAME];
+
+ if (printcmd) {
+ snprintf(lookup->cmdline, sizeof(lookup->cmdline),
+ "%s; <<>> DiG %s <<>>", first ? "\n" : "",
+ PACKAGE_VERSION);
+ i = 1;
+ while (i < argc) {
+ snprintf(append, sizeof(append), " %s", argv[i++]);
+ strlcat(lookup->cmdline, append,
+ sizeof(lookup->cmdline));
+ }
+ strlcat(lookup->cmdline, "\n", sizeof(lookup->cmdline));
+ if (first && addresscount != 0) {
+ snprintf(append, sizeof(append),
+ "; (%d server%s found)\n", addresscount,
+ addresscount > 1 ? "s" : "");
+ strlcat(lookup->cmdline, append,
+ sizeof(lookup->cmdline));
+ }
+ if (first) {
+ snprintf(append, sizeof(append),
+ ";; global options:%s%s\n",
+ short_form ? " +short" : "",
+ printcmd ? " +cmd" : "");
+ first = false;
+ strlcat(lookup->cmdline, append,
+ sizeof(lookup->cmdline));
+ }
+ }
+}
+
+#define FULLCHECK(A) \
+ do { \
+ size_t _l = strlen(cmd); \
+ if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \
+ goto invalid_option; \
+ } while (0)
+#define FULLCHECK2(A, B) \
+ do { \
+ size_t _l = strlen(cmd); \
+ if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \
+ (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \
+ goto invalid_option; \
+ } while (0)
+#define FULLCHECK6(A, B, C, D, E, F) \
+ do { \
+ size_t _l = strlen(cmd); \
+ if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \
+ (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0) && \
+ (_l >= sizeof(C) || strncasecmp(cmd, C, _l) != 0) && \
+ (_l >= sizeof(D) || strncasecmp(cmd, D, _l) != 0) && \
+ (_l >= sizeof(E) || strncasecmp(cmd, E, _l) != 0) && \
+ (_l >= sizeof(F) || strncasecmp(cmd, F, _l) != 0)) \
+ goto invalid_option; \
+ } while (0)
+
+static bool
+plus_tls_options(const char *cmd, const char *value, const bool state,
+ dig_lookup_t *lookup) {
+ /*
+ * Using TLS implies "TCP-like" mode.
+ */
+ if (!lookup->tcp_mode_set) {
+ lookup->tcp_mode = state;
+ }
+ switch (cmd[3]) {
+ case '-':
+ /*
+ * Assume that if any of the +tls-* options are set, then we
+ * need to verify the remote certificate (compatibility with
+ * kdig).
+ */
+ if (state) {
+ lookup->tls_ca_set = state;
+ }
+ switch (cmd[4]) {
+ case 'c':
+ switch (cmd[5]) {
+ case 'a':
+ FULLCHECK("tls-ca");
+ lookup->tls_ca_set = state;
+ if (state && value != NULL) {
+ lookup->tls_ca_file =
+ isc_mem_strdup(mctx, value);
+ }
+ break;
+ case 'e':
+ FULLCHECK("tls-certfile");
+ lookup->tls_cert_file_set = state;
+ if (state) {
+ if (value != NULL && *value != '\0') {
+ lookup->tls_cert_file =
+ isc_mem_strdup(mctx,
+ value);
+ } else {
+ fprintf(stderr,
+ ";; TLS certificate "
+ "file is "
+ "not specified\n");
+ goto invalid_option;
+ }
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'h':
+ FULLCHECK("tls-hostname");
+ lookup->tls_hostname_set = state;
+ if (state) {
+ if (value != NULL && *value != '\0') {
+ lookup->tls_hostname =
+ isc_mem_strdup(mctx, value);
+ } else {
+ fprintf(stderr, ";; TLS hostname is "
+ "not specified\n");
+ goto invalid_option;
+ }
+ }
+ break;
+ case 'k':
+ FULLCHECK("tls-keyfile");
+ lookup->tls_key_file_set = state;
+ if (state) {
+ if (value != NULL && *value != '\0') {
+ lookup->tls_key_file =
+ isc_mem_strdup(mctx, value);
+ } else {
+ fprintf(stderr,
+ ";; TLS private key file is "
+ "not specified\n");
+ goto invalid_option;
+ }
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case '\0':
+ FULLCHECK("tls");
+ lookup->tls_mode = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+
+ return true;
+invalid_option:
+ return false;
+}
+
+/*%
+ * We're not using isc_commandline_parse() here since the command line
+ * syntax of dig is quite a bit different from that which can be described
+ * by that routine.
+ * XXX doc options
+ */
+
+static dig_lookup_t *
+plus_option(char *option, bool is_batchfile, bool *need_clone,
+ dig_lookup_t *lookup) {
+ isc_result_t result;
+ char *cmd, *value, *last = NULL, *code, *extra;
+ uint32_t num;
+ bool state = true;
+ size_t n;
+
+ INSIST(option != NULL);
+
+ if ((cmd = strtok_r(option, "=", &last)) == NULL) {
+ printf(";; Invalid option %s\n", option);
+ return (lookup);
+ }
+ if (strncasecmp(cmd, "no", 2) == 0) {
+ cmd += 2;
+ state = false;
+ }
+ /* parse the rest of the string */
+ value = strtok_r(NULL, "", &last);
+
+ switch (cmd[0]) {
+ case 'a':
+ switch (cmd[1]) {
+ case 'a': /* aaonly / aaflag */
+ FULLCHECK2("aaonly", "aaflag");
+ lookup->aaonly = state;
+ break;
+ case 'd':
+ switch (cmd[2]) {
+ case 'd': /* additional */
+ FULLCHECK("additional");
+ lookup->section_additional = state;
+ break;
+ case 'f': /* adflag */
+ case '\0': /* +ad is a synonym for +adflag */
+ FULLCHECK("adflag");
+ lookup->adflag = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'l': /* all */
+ FULLCHECK("all");
+ lookup->section_question = state;
+ lookup->section_authority = state;
+ lookup->section_answer = state;
+ lookup->section_additional = state;
+ lookup->comments = state;
+ lookup->stats = state;
+ printcmd = state;
+ break;
+ case 'n': /* answer */
+ FULLCHECK("answer");
+ lookup->section_answer = state;
+ break;
+ case 'u': /* authority */
+ FULLCHECK("authority");
+ lookup->section_authority = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'b':
+ switch (cmd[1]) {
+ case 'a': /* badcookie */
+ FULLCHECK("badcookie");
+ lookup->badcookie = state;
+ break;
+ case 'e': /* besteffort */
+ FULLCHECK("besteffort");
+ lookup->besteffort = state;
+ break;
+ case 'u': /* bufsize */
+ FULLCHECK("bufsize");
+ if (!state) {
+ goto invalid_option;
+ }
+ if (value == NULL) {
+ lookup->udpsize = DEFAULT_EDNS_BUFSIZE;
+ break;
+ }
+ result = parse_uint(&num, value, COMMSIZE,
+ "buffer size");
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse buffer size");
+ goto exit_or_usage;
+ }
+ lookup->udpsize = num;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'c':
+ switch (cmd[1]) {
+ case 'd': /* cdflag */
+ switch (cmd[2]) {
+ case 'f': /* cdflag */
+ case '\0': /* +cd is a synonym for +cdflag */
+ FULLCHECK("cdflag");
+ lookup->cdflag = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'l': /* class */
+ /* keep +cl for backwards compatibility */
+ FULLCHECK2("cl", "class");
+ lookup->noclass = !state;
+ break;
+ case 'm': /* cmd */
+ FULLCHECK("cmd");
+ printcmd = state;
+ break;
+ case 'o': /* comments */
+ switch (cmd[2]) {
+ case 'm':
+ FULLCHECK("comments");
+ lookup->comments = state;
+ if (lookup == default_lookup) {
+ pluscomm = state;
+ }
+ break;
+ case 'o': /* cookie */
+ FULLCHECK("cookie");
+ if (state && lookup->edns == -1) {
+ lookup->edns = DEFAULT_EDNS_VERSION;
+ }
+ lookup->sendcookie = state;
+ if (value != NULL) {
+ n = strlcpy(hexcookie, value,
+ sizeof(hexcookie));
+ if (n >= sizeof(hexcookie)) {
+ warn("COOKIE data too large");
+ goto exit_or_usage;
+ }
+ lookup->cookie = hexcookie;
+ } else {
+ lookup->cookie = NULL;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ FULLCHECK("crypto");
+ lookup->nocrypto = !state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'd':
+ switch (cmd[1]) {
+ case 'e': /* defname */
+ FULLCHECK("defname");
+ if (!lookup->trace) {
+ usesearch = state;
+ }
+ break;
+ case 'n':
+ switch (cmd[2]) {
+ case 's':
+ switch (cmd[3]) {
+ case '6': /* dns64prefix */
+ FULLCHECK("dns64prefix");
+ if (state) {
+ if (*need_clone) {
+ lookup = clone_lookup(
+ default_lookup,
+ true);
+ }
+ *need_clone = true;
+ lookup->dns64prefix = state;
+ strlcpy(lookup->textname,
+ "ipv4only.arpa",
+ sizeof(lookup->textname));
+ printcmd = false;
+ lookup->section_additional =
+ false;
+ lookup->section_answer = true;
+ lookup->section_authority =
+ false;
+ lookup->section_question =
+ false;
+ lookup->comments = false;
+ lookup->stats = false;
+ lookup->rrcomments = -1;
+ lookup->rdtype =
+ dns_rdatatype_aaaa;
+ lookup->rdtypeset = true;
+ ISC_LIST_APPEND(lookup_list,
+ lookup, link);
+ }
+ break;
+ case 's': /* dnssec */
+ FULLCHECK("dnssec");
+ dnssec:
+ if (state && lookup->edns == -1) {
+ lookup->edns =
+ DEFAULT_EDNS_VERSION;
+ }
+ lookup->dnssec = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'o': /* domain ... but treat "do" as synonym for dnssec */
+ if (cmd[2] == '\0') {
+ goto dnssec;
+ }
+ FULLCHECK("domain");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ strlcpy(domainopt, value, sizeof(domainopt));
+ break;
+ case 's': /* dscp */
+ /* obsolete */
+ FULLCHECK("dscp");
+ fprintf(stderr, ";; +dscp option is obsolete "
+ "and has no effect");
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'e':
+ switch (cmd[1]) {
+ case 'd':
+ switch (cmd[2]) {
+ case 'n':
+ switch (cmd[3]) {
+ case 's':
+ switch (cmd[4]) {
+ case 0:
+ FULLCHECK("edns");
+ if (!state) {
+ lookup->edns = -1;
+ break;
+ }
+ if (value == NULL) {
+ lookup->edns =
+ DEFAULT_EDNS_VERSION;
+ break;
+ }
+ result = parse_uint(&num, value,
+ 255,
+ "edns");
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse "
+ "edns");
+ goto exit_or_usage;
+ }
+ lookup->edns = num;
+ break;
+ case 'f':
+ FULLCHECK("ednsflags");
+ if (!state) {
+ lookup->ednsflags = 0;
+ break;
+ }
+ if (value == NULL) {
+ lookup->ednsflags = 0;
+ break;
+ }
+ result = parse_xint(
+ &num, value, 0xffff,
+ "ednsflags");
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse "
+ "ednsflags");
+ goto exit_or_usage;
+ }
+ lookup->ednsflags = num;
+ break;
+ case 'n':
+ FULLCHECK("ednsnegotiation");
+ lookup->ednsneg = state;
+ break;
+ case 'o':
+ FULLCHECK("ednsopt");
+ if (!state) {
+ lookup->ednsoptscnt = 0;
+ break;
+ }
+ code = NULL;
+ if (value != NULL) {
+ code = strtok_r(value,
+ ":",
+ &last);
+ }
+ if (code == NULL) {
+ warn("ednsopt no "
+ "code point "
+ "specified");
+ goto exit_or_usage;
+ }
+ extra = strtok_r(NULL, "\0",
+ &last);
+ save_opt(lookup, code, extra);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'x':
+ switch (cmd[2]) {
+ case 'p':
+ switch (cmd[3]) {
+ case 'a':
+ FULLCHECK("expandaaaa");
+ lookup->expandaaaa = state;
+ break;
+ case 'i':
+ FULLCHECK("expire");
+ lookup->expire = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'f': /* fail */
+ switch (cmd[1]) {
+ case 'a':
+ FULLCHECK("fail");
+ lookup->servfail_stops = state;
+ break;
+ case 'u':
+ FULLCHECK("fuzztime");
+ lookup->fuzzing = state;
+ if (lookup->fuzzing) {
+ if (value == NULL) {
+ lookup->fuzztime = 0x622acce1;
+ break;
+ }
+ result = parse_uint(&num, value, 0xffffffff,
+ "fuzztime");
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse fuzztime");
+ goto exit_or_usage;
+ }
+ lookup->fuzztime = num;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'h':
+ switch (cmd[1]) {
+ case 'e': /* header-only */
+ FULLCHECK("header-only");
+ lookup->header_only = state;
+ break;
+ case 't':
+ FULLCHECK6("https", "https-get", "https-post",
+ "http-plain", "http-plain-get",
+ "http-plain-post");
+#if HAVE_LIBNGHTTP2
+ if (lookup->https_path != NULL) {
+ isc_mem_free(mctx, lookup->https_path);
+ lookup->https_path = NULL;
+ }
+ if (!state) {
+ lookup->https_mode = false;
+ break;
+ }
+ lookup->https_mode = true;
+ if (cmd[4] == '-') {
+ lookup->http_plain = true;
+ switch (cmd[10]) {
+ case '\0':
+ FULLCHECK("http-plain");
+ break;
+ case '-':
+ switch (cmd[11]) {
+ case 'p':
+ FULLCHECK("http-plain-post");
+ break;
+ case 'g':
+ FULLCHECK("http-plain-get");
+ lookup->https_get = true;
+ break;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ } else {
+ switch (cmd[5]) {
+ case '\0':
+ FULLCHECK("https");
+ break;
+ case '-':
+ switch (cmd[6]) {
+ case 'p':
+ FULLCHECK("https-post");
+ break;
+ case 'g':
+ FULLCHECK("https-get");
+ lookup->https_get = true;
+ break;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ }
+ if (!lookup->tcp_mode_set) {
+ lookup->tcp_mode = state;
+ }
+ if (value == NULL) {
+ lookup->https_path = isc_mem_strdup(
+ mctx, ISC_NM_HTTP_DEFAULT_PATH);
+ } else {
+ if (!isc_nm_http_path_isvalid(value)) {
+ fprintf(stderr,
+ ";; The given HTTP path \"%s\" "
+ "is not "
+ "a valid absolute path\n",
+ value);
+ goto invalid_option;
+ }
+ lookup->https_path = isc_mem_strdup(mctx,
+ value);
+ }
+#else
+ fprintf(stderr, ";; DoH support not enabled\n");
+#endif
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'i':
+ switch (cmd[1]) {
+ case 'd': /* identify */
+ switch (cmd[2]) {
+ case 'e':
+ FULLCHECK("identify");
+ lookup->identify = state;
+ break;
+ case 'n':
+ switch (cmd[3]) {
+ case 'i':
+ FULLCHECK("idnin");
+#ifndef HAVE_LIBIDN2
+ fprintf(stderr, ";; IDN input support"
+ " not enabled\n");
+#else /* ifndef HAVE_LIBIDN2 */
+ lookup->idnin = state;
+#endif /* ifndef HAVE_LIBIDN2 */
+ break;
+ case 'o':
+ FULLCHECK("idnout");
+#ifndef HAVE_LIBIDN2
+ fprintf(stderr, ";; IDN output support"
+ " not enabled\n");
+#else /* ifndef HAVE_LIBIDN2 */
+ lookup->idnout = state;
+#endif /* ifndef HAVE_LIBIDN2 */
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'g': /* ignore */
+ default: /*
+ * Inherits default for compatibility (+[no]i*).
+ */
+ FULLCHECK("ignore");
+ lookup->ignore = state;
+ }
+ break;
+ case 'k':
+ switch (cmd[1]) {
+ case 'e':
+ switch (cmd[2]) {
+ case 'e':
+ switch (cmd[3]) {
+ case 'p':
+ switch (cmd[4]) {
+ case 'a':
+ FULLCHECK("keepalive");
+ lookup->tcp_keepalive = state;
+ break;
+ case 'o':
+ FULLCHECK("keepopen");
+ keep_open = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'm': /* multiline */
+ switch (cmd[1]) {
+ case 'a':
+ FULLCHECK("mapped");
+ fprintf(stderr, ";; +mapped option is deprecated");
+ break;
+ case 'u':
+ FULLCHECK("multiline");
+ lookup->multiline = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'n':
+ switch (cmd[1]) {
+ case 'd': /* ndots */
+ FULLCHECK("ndots");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&num, value, MAXNDOTS, "ndots");
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse ndots");
+ goto exit_or_usage;
+ }
+ ndots = num;
+ break;
+ case 's':
+ switch (cmd[2]) {
+ case 'i': /* nsid */
+ FULLCHECK("nsid");
+ if (state && lookup->edns == -1) {
+ lookup->edns = DEFAULT_EDNS_VERSION;
+ }
+ lookup->nsid = state;
+ break;
+ case 's': /* nssearch */
+ FULLCHECK("nssearch");
+ lookup->ns_search_only = state;
+ if (state) {
+ lookup->trace_root = true;
+ lookup->recurse = true;
+ lookup->identify = true;
+ lookup->stats = false;
+ lookup->comments = false;
+ lookup->section_additional = false;
+ lookup->section_authority = false;
+ lookup->section_question = false;
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = true;
+ short_form = true;
+ lookup->rrcomments = 0;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'o':
+ switch (cmd[1]) {
+ case 'n':
+ FULLCHECK("onesoa");
+ lookup->onesoa = state;
+ break;
+ case 'p':
+ FULLCHECK("opcode");
+ if (!state) {
+ lookup->opcode = 0; /* default - query */
+ break;
+ }
+ if (value == NULL) {
+ goto need_value;
+ }
+ for (num = 0;
+ num < sizeof(opcodetext) / sizeof(opcodetext[0]);
+ num++)
+ {
+ if (strcasecmp(opcodetext[num], value) == 0) {
+ break;
+ }
+ }
+ if (num < 16) {
+ lookup->opcode = (dns_opcode_t)num;
+ break;
+ }
+ result = parse_uint(&num, value, 15, "opcode");
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse opcode");
+ goto exit_or_usage;
+ }
+ lookup->opcode = (dns_opcode_t)num;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'p':
+ FULLCHECK("padding");
+ if (state && lookup->edns == -1) {
+ lookup->edns = DEFAULT_EDNS_VERSION;
+ }
+ if (value == NULL) {
+ goto need_value;
+ }
+ result = parse_uint(&num, value, 512, "padding");
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse padding");
+ goto exit_or_usage;
+ }
+ lookup->padding = (uint16_t)num;
+ break;
+ case 'q':
+ switch (cmd[1]) {
+ case 'i': /* qid */
+ FULLCHECK("qid");
+ if (!state) {
+ lookup->setqid = false;
+ lookup->qid = 0;
+ break;
+ }
+ if (value == NULL) {
+ goto need_value;
+ }
+ result = parse_uint(&num, value, MAXQID, "qid");
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse qid");
+ goto exit_or_usage;
+ }
+ lookup->setqid = true;
+ lookup->qid = num;
+ break;
+ case 'r': /* qr */
+ FULLCHECK("qr");
+ lookup->qr = state;
+ break;
+ case 'u': /* question */
+ FULLCHECK("question");
+ lookup->section_question = state;
+ if (lookup == default_lookup) {
+ plusquest = state;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ switch (cmd[1]) {
+ case 'a': /* raflag */
+ FULLCHECK("raflag");
+ lookup->raflag = state;
+ break;
+ case 'd': /* rdflag */
+ FULLCHECK("rdflag");
+ lookup->recurse = state;
+ break;
+ case 'e':
+ switch (cmd[2]) {
+ case 'c': /* recurse */
+ FULLCHECK("recurse");
+ lookup->recurse = state;
+ break;
+ case 't': /* retry / retries */
+ FULLCHECK2("retry", "retries");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&lookup->retries, value,
+ MAXTRIES - 1, "retries");
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse retries");
+ goto exit_or_usage;
+ }
+ lookup->retries++;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r': /* rrcomments */
+ FULLCHECK("rrcomments");
+ lookup->rrcomments = state ? 1 : -1;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 's':
+ switch (cmd[1]) {
+ case 'e': /* search */
+ FULLCHECK("search");
+ if (!lookup->trace) {
+ usesearch = state;
+ }
+ break;
+ case 'h':
+ if (cmd[2] != 'o') {
+ goto invalid_option;
+ }
+ switch (cmd[3]) {
+ case 'r': /* short */
+ FULLCHECK("short");
+ short_form = state;
+ if (state) {
+ printcmd = false;
+ lookup->section_additional = false;
+ lookup->section_answer = true;
+ lookup->section_authority = false;
+ lookup->section_question = false;
+ lookup->comments = false;
+ lookup->stats = false;
+ lookup->rrcomments = -1;
+ }
+ break;
+ case 'w': /* showsearch */
+ switch (cmd[4]) {
+ case 'b':
+ FULLCHECK("showbadcookie");
+ lookup->showbadcookie = state;
+ break;
+ case 's':
+ FULLCHECK("showsearch");
+ if (!lookup->trace) {
+ showsearch = state;
+ usesearch = state;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'i': /* sigchase */
+ FULLCHECK("sigchase");
+ fprintf(stderr, ";; +sigchase option is deprecated");
+ break;
+ case 'p': /* split */
+ FULLCHECK("split");
+ if (value != NULL && !state) {
+ goto invalid_option;
+ }
+ if (!state) {
+ splitwidth = 0;
+ break;
+ } else if (value == NULL) {
+ break;
+ }
+
+ result = parse_uint(&splitwidth, value, 1023, "split");
+ if ((splitwidth % 4) != 0U) {
+ splitwidth = ((splitwidth + 3) / 4) * 4;
+ fprintf(stderr,
+ ";; Warning, split must be "
+ "a multiple of 4; adjusting "
+ "to %u\n",
+ splitwidth);
+ }
+ /*
+ * There is an adjustment done in the
+ * totext_<rrtype>() functions which causes
+ * splitwidth to shrink. This is okay when we're
+ * using the default width but incorrect in this
+ * case, so we correct for it
+ */
+ if (splitwidth) {
+ splitwidth += 3;
+ }
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse split");
+ goto exit_or_usage;
+ }
+ break;
+ case 't': /* stats */
+ FULLCHECK("stats");
+ lookup->stats = state;
+ break;
+ case 'u': /* subnet */
+ FULLCHECK("subnet");
+ if (state && value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ if (lookup->ecs_addr != NULL) {
+ isc_mem_free(mctx, lookup->ecs_addr);
+ lookup->ecs_addr = NULL;
+ }
+ break;
+ }
+ if (lookup->edns == -1) {
+ lookup->edns = DEFAULT_EDNS_VERSION;
+ }
+ if (lookup->ecs_addr != NULL) {
+ isc_mem_free(mctx, lookup->ecs_addr);
+ lookup->ecs_addr = NULL;
+ }
+ result = parse_netprefix(&lookup->ecs_addr, value);
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse client");
+ goto exit_or_usage;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 't':
+ switch (cmd[1]) {
+ case 'c': /* tcp */
+ switch (cmd[2]) {
+ case 'f':
+ FULLCHECK("tcflag");
+ lookup->tcflag = state;
+ break;
+ case 'p':
+ FULLCHECK("tcp");
+ if (!is_batchfile) {
+ lookup->tcp_mode = state;
+ lookup->tcp_mode_set = true;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'i': /* timeout */
+ FULLCHECK("timeout");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&timeout, value, MAXTIMEOUT,
+ "timeout");
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse timeout");
+ goto exit_or_usage;
+ }
+ if (timeout == 0) {
+ timeout = 1;
+ }
+ break;
+ case 'l':
+ switch (cmd[2]) {
+ case 's':
+ if (!plus_tls_options(cmd, value, state,
+ lookup))
+ {
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'o':
+ FULLCHECK("topdown");
+ fprintf(stderr, ";; +topdown option is deprecated");
+ break;
+ case 'r':
+ switch (cmd[2]) {
+ case 'a': /* trace */
+ FULLCHECK("trace");
+ lookup->trace = state;
+ lookup->trace_root = state;
+ if (state) {
+ lookup->recurse = true;
+ lookup->identify = true;
+ lookup->comments = false;
+ lookup->rrcomments = 0;
+ lookup->stats = false;
+ lookup->section_additional = false;
+ lookup->section_authority = true;
+ lookup->section_question = false;
+ lookup->dnssec = true;
+ lookup->sendcookie = true;
+ usesearch = false;
+ }
+ break;
+ case 'i': /* tries */
+ FULLCHECK("tries");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&lookup->retries, value,
+ MAXTRIES, "tries");
+ if (result != ISC_R_SUCCESS) {
+ warn("Couldn't parse tries");
+ goto exit_or_usage;
+ }
+ if (lookup->retries == 0) {
+ lookup->retries = 1;
+ }
+ break;
+ case 'u': /* trusted-key */
+ FULLCHECK("trusted-key");
+ fprintf(stderr, ";; +trusted-key option is "
+ "deprecated");
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 't':
+ switch (cmd[2]) {
+ case 'l':
+ switch (cmd[3]) {
+ case 0:
+ case 'i': /* ttlid */
+ FULLCHECK2("ttl", "ttlid");
+ lookup->nottl = !state;
+ break;
+ case 'u': /* ttlunits */
+ FULLCHECK("ttlunits");
+ lookup->nottl = false;
+ lookup->ttlunits = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'u':
+ switch (cmd[1]) {
+ case 'n':
+ switch (cmd[2]) {
+ case 'e':
+ FULLCHECK("unexpected");
+ fprintf(stderr, ";; +unexpected option "
+ "is deprecated");
+ break;
+ case 'k':
+ FULLCHECK("unknownformat");
+ lookup->print_unknown_format = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+
+ break;
+ case 'v':
+ FULLCHECK("vc");
+ if (!is_batchfile) {
+ lookup->tcp_mode = state;
+ lookup->tcp_mode_set = true;
+ }
+ break;
+ case 'y': /* yaml */
+ FULLCHECK("yaml");
+ yaml = state;
+ if (state) {
+ printcmd = false;
+ lookup->stats = false;
+ lookup->rrcomments = -1;
+ }
+ break;
+ case 'z': /* zflag */
+ FULLCHECK("zflag");
+ lookup->zflag = state;
+ break;
+ default:
+ invalid_option:
+ need_value:
+#if TARGET_OS_IPHONE
+ exit_or_usage:
+#endif /* if TARGET_OS_IPHONE */
+ fprintf(stderr, "Invalid option: +%s\n", option);
+ usage();
+ }
+ return (lookup);
+
+#if !TARGET_OS_IPHONE
+exit_or_usage:
+ cleanup_openssl_refs();
+ digexit();
+#endif /* if !TARGET_OS_IPHONE */
+}
+
+/*%
+ * #true returned if value was used
+ */
+static const char *single_dash_opts = "46dhimnruv";
+static const char *dash_opts = "46bcdfhikmnpqrtvyx";
+static bool
+dash_option(char *option, char *next, dig_lookup_t **lookup,
+ bool *open_type_class, bool *need_clone, bool config_only, int argc,
+ char **argv, bool *firstarg) {
+ char opt, *value, *ptr, *ptr2, *ptr3, *last;
+ isc_result_t result;
+ bool value_from_next;
+ isc_textregion_t tr;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ char textname[MXNAME];
+ struct in_addr in4;
+ struct in6_addr in6;
+ in_port_t srcport;
+ char *hash, *cmd;
+ uint32_t num;
+
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ /*
+ * Since the -[46dhimnuv] options do not take an argument,
+ * account for them (in any number and/or combination)
+ * if they appear as the first character(s) of a q-opt.
+ */
+ opt = option[0];
+ switch (opt) {
+ case '4':
+ if (have_ipv4) {
+ isc_net_disableipv6();
+ have_ipv6 = false;
+ } else {
+ fatal("can't find IPv4 networking");
+ UNREACHABLE();
+ return (false);
+ }
+ break;
+ case '6':
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = false;
+ } else {
+ fatal("can't find IPv6 networking");
+ UNREACHABLE();
+ return (false);
+ }
+ break;
+ case 'd':
+ ptr = strpbrk(&option[1], dash_opts);
+ if (ptr != &option[1]) {
+ cmd = option;
+ FULLCHECK("debug");
+ debugging = true;
+ return (false);
+ } else {
+ debugging = true;
+ }
+ break;
+ case 'h':
+ help();
+ exit(0);
+ break;
+ case 'i':
+ /* deprecated */
+ break;
+ case 'm': /* memdebug */
+ /* memdebug is handled in preparse_args() */
+ break;
+ case 'n':
+ /* deprecated */
+ break;
+ case 'r':
+ debug("digrc (late)");
+ digrc = false;
+ break;
+ case 'u':
+ (*lookup)->use_usec = true;
+ break;
+ case 'v':
+ version();
+ exit(0);
+ break;
+ }
+ if (strlen(option) > 1U) {
+ option = &option[1];
+ } else {
+ return (false);
+ }
+ }
+ opt = option[0];
+ if (strlen(option) > 1U) {
+ value_from_next = false;
+ value = &option[1];
+ } else {
+ value_from_next = true;
+ value = next;
+ }
+ if (value == NULL) {
+ goto invalid_option;
+ }
+ switch (opt) {
+ case 'b':
+ hash = strchr(value, '#');
+ if (hash != NULL) {
+ result = parse_uint(&num, hash + 1, MAXPORT,
+ "port number");
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't parse port number");
+ }
+ srcport = num;
+ *hash = '\0';
+ } else {
+ srcport = 0;
+ }
+ if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) {
+ isc_sockaddr_fromin6(&localaddr, &in6, srcport);
+ isc_net_disableipv4();
+ } else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) {
+ isc_sockaddr_fromin(&localaddr, &in4, srcport);
+ isc_net_disableipv6();
+ } else {
+ if (hash != NULL) {
+ *hash = '#';
+ }
+ fatal("invalid address %s", value);
+ }
+ if (hash != NULL) {
+ *hash = '#';
+ }
+ specified_source = true;
+ return (value_from_next);
+ case 'c':
+ if ((*lookup)->rdclassset) {
+ fprintf(stderr, ";; Warning, extra class option\n");
+ }
+ *open_type_class = false;
+ tr.base = value;
+ tr.length = (unsigned int)strlen(value);
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS) {
+ (*lookup)->rdclass = rdclass;
+ (*lookup)->rdclassset = true;
+ } else {
+ fprintf(stderr,
+ ";; Warning, ignoring "
+ "invalid class %s\n",
+ value);
+ }
+ return (value_from_next);
+ case 'f':
+ atomic_store(&batchname, (uintptr_t)value);
+ return (value_from_next);
+ case 'k':
+ strlcpy(keyfile, value, sizeof(keyfile));
+ return (value_from_next);
+ case 'p':
+ result = parse_uint(&num, value, MAXPORT, "port number");
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't parse port number");
+ }
+ port = num;
+ port_set = true;
+ return (value_from_next);
+ case 'q':
+ if (!config_only) {
+ if (*need_clone) {
+ (*lookup) = clone_lookup(default_lookup, true);
+ }
+ *need_clone = true;
+ strlcpy((*lookup)->textname, value,
+ sizeof((*lookup)->textname));
+ (*lookup)->trace_root = ((*lookup)->trace ||
+ (*lookup)->ns_search_only);
+ (*lookup)->new_search = true;
+ if (*firstarg) {
+ printgreeting(argc, argv, *lookup);
+ *firstarg = false;
+ }
+ ISC_LIST_APPEND(lookup_list, (*lookup), link);
+ debug("looking up %s", (*lookup)->textname);
+ }
+ return (value_from_next);
+ case 't':
+ *open_type_class = false;
+ if (strncasecmp(value, "ixfr=", 5) == 0) {
+ rdtype = dns_rdatatype_ixfr;
+ result = ISC_R_SUCCESS;
+ } else {
+ tr.base = value;
+ tr.length = (unsigned int)strlen(value);
+ result = dns_rdatatype_fromtext(
+ &rdtype, (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS &&
+ rdtype == dns_rdatatype_ixfr)
+ {
+ result = DNS_R_UNKNOWN;
+ }
+ }
+ if (result == ISC_R_SUCCESS) {
+ if ((*lookup)->rdtypeset) {
+ fprintf(stderr, ";; Warning, "
+ "extra type option\n");
+ }
+ if (rdtype == dns_rdatatype_ixfr) {
+ uint32_t serial;
+ (*lookup)->rdtype = dns_rdatatype_ixfr;
+ (*lookup)->rdtypeset = true;
+ result = parse_uint(&serial, &value[5],
+ MAXSERIAL, "serial number");
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't parse serial number");
+ }
+ (*lookup)->ixfr_serial = serial;
+ (*lookup)->section_question = plusquest;
+ (*lookup)->comments = pluscomm;
+ if (!(*lookup)->tcp_mode_set) {
+ (*lookup)->tcp_mode = true;
+ }
+ } else {
+ (*lookup)->rdtype = rdtype;
+ if (!config_only) {
+ (*lookup)->rdtypeset = true;
+ }
+ if (rdtype == dns_rdatatype_axfr) {
+ (*lookup)->section_question = plusquest;
+ (*lookup)->comments = pluscomm;
+ } else if (rdtype == dns_rdatatype_any) {
+ if (!(*lookup)->tcp_mode_set) {
+ (*lookup)->tcp_mode = true;
+ }
+ }
+ (*lookup)->ixfr_serial = false;
+ }
+ } else {
+ fprintf(stderr,
+ ";; Warning, ignoring "
+ "invalid type %s\n",
+ value);
+ }
+ return (value_from_next);
+ case 'y':
+ if ((ptr = strtok_r(value, ":", &last)) == NULL) {
+ usage();
+ }
+ if ((ptr2 = strtok_r(NULL, ":", &last)) == NULL) { /* name or
+ * secret */
+ usage();
+ }
+ if ((ptr3 = strtok_r(NULL, ":", &last)) != NULL) { /* secret or
+ * NULL */
+ parse_hmac(ptr);
+ ptr = ptr2;
+ ptr2 = ptr3;
+ } else {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ digestbits = 0;
+ }
+ /* XXXONDREJ: FIXME */
+ strlcpy(keynametext, ptr, sizeof(keynametext));
+ strlcpy(keysecret, ptr2, sizeof(keysecret));
+ return (value_from_next);
+ case 'x':
+ if (*need_clone) {
+ *lookup = clone_lookup(default_lookup, true);
+ }
+ *need_clone = true;
+ if (get_reverse(textname, sizeof(textname), value, false) ==
+ ISC_R_SUCCESS)
+ {
+ strlcpy((*lookup)->textname, textname,
+ sizeof((*lookup)->textname));
+ debug("looking up %s", (*lookup)->textname);
+ (*lookup)->trace_root = ((*lookup)->trace ||
+ (*lookup)->ns_search_only);
+ if (!(*lookup)->rdtypeset) {
+ (*lookup)->rdtype = dns_rdatatype_ptr;
+ }
+ if (!(*lookup)->rdclassset) {
+ (*lookup)->rdclass = dns_rdataclass_in;
+ }
+ (*lookup)->new_search = true;
+ if (*firstarg) {
+ printgreeting(argc, argv, *lookup);
+ *firstarg = false;
+ }
+ ISC_LIST_APPEND(lookup_list, *lookup, link);
+ } else {
+ fprintf(stderr, "Invalid IP address %s\n", value);
+ exit(1);
+ }
+ return (value_from_next);
+ invalid_option:
+ default:
+ fprintf(stderr, "Invalid option: -%s\n", option);
+ usage();
+ }
+ UNREACHABLE();
+ return (false);
+}
+
+/*%
+ * Because we may be trying to do memory allocation recording, we're going
+ * to need to parse the arguments for the -m *before* we start the main
+ * argument parsing routine.
+ *
+ * I'd prefer not to have to do this, but I am not quite sure how else to
+ * fix the problem. Argument parsing in dig involves memory allocation
+ * by its nature, so it can't be done in the main argument parser.
+ */
+static void
+preparse_args(int argc, char **argv) {
+ int rc;
+ char **rv;
+ char *option;
+
+ rc = argc;
+ rv = argv;
+ for (rc--, rv++; rc > 0; rc--, rv++) {
+ if (rv[0][0] != '-') {
+ continue;
+ }
+ option = &rv[0][1];
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ switch (option[0]) {
+ case 'd':
+ /* For debugging early startup */
+ debugging = true;
+ break;
+ case 'm':
+ memdebugging = true;
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE |
+ ISC_MEM_DEBUGRECORD;
+ break;
+ case 'r':
+ /*
+ * Must be done early, because ~/.digrc
+ * is read before command line parsing
+ */
+ debug("digrc (early)");
+ digrc = false;
+ break;
+ case '4':
+ if (ipv6only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv4only = true;
+ break;
+ case '6':
+ if (ipv4only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv6only = true;
+ break;
+ }
+ option = &option[1];
+ }
+ if (strlen(option) == 0U) {
+ continue;
+ }
+ /* Look for dash value option. */
+ if (strpbrk(option, dash_opts) != &option[0]) {
+ goto invalid_option;
+ }
+ if (strlen(option) > 1U) {
+ /* value in option. */
+ continue;
+ }
+ /* Dash value is next argument so we need to skip it. */
+ rc--, rv++;
+ /* Handle missing argument */
+ if (rc == 0) {
+ invalid_option:
+ fprintf(stderr, "Invalid option: -%s\n", option);
+ usage();
+ }
+ }
+}
+
+static int
+split_batchline(char *batchline, char **bargv, int len, const char *msg) {
+ int bargc;
+ char *last = NULL;
+
+ REQUIRE(batchline != NULL);
+
+ for (bargc = 1, bargv[bargc] = strtok_r(batchline, " \t\r\n", &last);
+ bargc < len && bargv[bargc];
+ bargv[++bargc] = strtok_r(NULL, " \t\r\n", &last))
+ {
+ debug("%s %d: %s", msg, bargc, bargv[bargc]);
+ }
+ return (bargc);
+}
+
+static void
+parse_args(bool is_batchfile, bool config_only, int argc, char **argv) {
+ isc_result_t result;
+ isc_textregion_t tr;
+ bool firstarg = true;
+ dig_lookup_t *lookup = NULL;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ bool open_type_class = true;
+ char batchline[MXNAME];
+ int bargc;
+ char *bargv[64];
+ int rc;
+ char **rv;
+#ifndef NOPOSIX
+ char *homedir;
+ char rcfile[PATH_MAX];
+#endif /* ifndef NOPOSIX */
+ bool need_clone = true;
+
+ /*
+ * The semantics for parsing the args is a bit complex; if
+ * we don't have a host yet, make the arg apply globally,
+ * otherwise make it apply to the latest host. This is
+ * a bit different than the previous versions, but should
+ * form a consistent user interface.
+ *
+ * First, create a "default lookup" which won't actually be used
+ * anywhere, except for cloning into new lookups
+ */
+
+ debug("parse_args()");
+ if (!is_batchfile) {
+ debug("making new lookup");
+ default_lookup = make_empty_lookup();
+ default_lookup->adflag = true;
+ default_lookup->edns = DEFAULT_EDNS_VERSION;
+ default_lookup->sendcookie = true;
+
+#ifndef NOPOSIX
+ /*
+ * Treat ${HOME}/.digrc as a special batchfile
+ */
+ INSIST(batchfp == NULL);
+ homedir = getenv("HOME");
+ if (homedir != NULL && digrc) {
+ unsigned int n;
+ debug("digrc (open)");
+ n = snprintf(rcfile, sizeof(rcfile), "%s/.digrc",
+ homedir);
+ if (n < sizeof(rcfile)) {
+ batchfp = fopen(rcfile, "r");
+ }
+ }
+ if (batchfp != NULL) {
+ while (fgets(batchline, sizeof(batchline), batchfp) !=
+ 0)
+ {
+ debug("config line %s", batchline);
+ bargc = split_batchline(batchline, bargv, 62,
+ ".digrc argv");
+ bargv[0] = argv[0];
+ argv0 = argv[0];
+ parse_args(true, true, bargc, (char **)bargv);
+ }
+ fclose(batchfp);
+ }
+#endif /* ifndef NOPOSIX */
+ }
+
+ if (is_batchfile && !config_only) {
+ /* Processing '-f batchfile'. */
+ lookup = clone_lookup(default_lookup, true);
+ need_clone = false;
+ } else {
+ lookup = default_lookup;
+ }
+
+ rc = argc;
+ rv = argv;
+ for (rc--, rv++; rc > 0; rc--, rv++) {
+ debug("main parsing %s", rv[0]);
+ if (strncmp(rv[0], "%", 1) == 0) {
+ break;
+ }
+ if (rv[0][0] == '@') {
+ if (is_batchfile && !config_only) {
+ addresscount = getaddresses(lookup, &rv[0][1],
+ &result);
+ if (addresscount == 0) {
+ fprintf(stderr,
+ "couldn't get address "
+ "for '%s': %s: skipping "
+ "lookup\n",
+ &rv[0][1],
+ isc_result_totext(result));
+ if (ISC_LINK_LINKED(lookup, link)) {
+ ISC_LIST_DEQUEUE(lookup_list,
+ lookup, link);
+ }
+ destroy_lookup(lookup);
+ return;
+ }
+ } else {
+ addresscount = getaddresses(lookup, &rv[0][1],
+ NULL);
+ if (addresscount == 0) {
+ fatal("no valid addresses for '%s'\n",
+ &rv[0][1]);
+ }
+ }
+ } else if (rv[0][0] == '+') {
+ lookup = plus_option(&rv[0][1], is_batchfile,
+ &need_clone, lookup);
+ } else if (rv[0][0] == '-') {
+ if (rc <= 1) {
+ if (dash_option(&rv[0][1], NULL, &lookup,
+ &open_type_class, &need_clone,
+ config_only, argc, argv,
+ &firstarg))
+ {
+ rc--;
+ rv++;
+ }
+ } else {
+ if (dash_option(&rv[0][1], rv[1], &lookup,
+ &open_type_class, &need_clone,
+ config_only, argc, argv,
+ &firstarg))
+ {
+ rc--;
+ rv++;
+ }
+ }
+ } else {
+ /*
+ * Anything which isn't an option
+ */
+ if (open_type_class) {
+ if (strncasecmp(rv[0], "ixfr=", 5) == 0) {
+ rdtype = dns_rdatatype_ixfr;
+ result = ISC_R_SUCCESS;
+ } else {
+ tr.base = rv[0];
+ tr.length = (unsigned int)strlen(rv[0]);
+ result = dns_rdatatype_fromtext(
+ &rdtype,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS &&
+ rdtype == dns_rdatatype_ixfr)
+ {
+ fprintf(stderr, ";; Warning, "
+ "ixfr requires "
+ "a "
+ "serial "
+ "number\n");
+ continue;
+ }
+ }
+ if (result == ISC_R_SUCCESS) {
+ if (lookup->rdtypeset) {
+ fprintf(stderr, ";; Warning, "
+ "extra type "
+ "option\n");
+ }
+ if (rdtype == dns_rdatatype_ixfr) {
+ uint32_t serial;
+ lookup->rdtype =
+ dns_rdatatype_ixfr;
+ lookup->rdtypeset = true;
+ result = parse_uint(&serial,
+ &rv[0][5],
+ MAXSERIAL,
+ "serial "
+ "number");
+ if (result != ISC_R_SUCCESS) {
+ fatal("Couldn't parse "
+ "serial number");
+ }
+ lookup->ixfr_serial = serial;
+ lookup->section_question =
+ plusquest;
+ lookup->comments = pluscomm;
+ if (!lookup->tcp_mode_set) {
+ lookup->tcp_mode = true;
+ }
+ } else {
+ lookup->rdtype = rdtype;
+ lookup->rdtypeset = true;
+ if (rdtype ==
+ dns_rdatatype_axfr)
+ {
+ lookup->section_question =
+ plusquest;
+ lookup->comments =
+ pluscomm;
+ }
+ if (rdtype ==
+ dns_rdatatype_any &&
+ !lookup->tcp_mode_set)
+ {
+ lookup->tcp_mode = true;
+ }
+ lookup->ixfr_serial = false;
+ }
+ continue;
+ }
+ result = dns_rdataclass_fromtext(
+ &rdclass, (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS) {
+ if (lookup->rdclassset) {
+ fprintf(stderr, ";; Warning, "
+ "extra class "
+ "option\n");
+ }
+ lookup->rdclass = rdclass;
+ lookup->rdclassset = true;
+ continue;
+ }
+ }
+
+ if (!config_only) {
+ if (need_clone) {
+ lookup = clone_lookup(default_lookup,
+ true);
+ }
+ need_clone = true;
+ strlcpy(lookup->textname, rv[0],
+ sizeof(lookup->textname));
+ lookup->trace_root = (lookup->trace ||
+ lookup->ns_search_only);
+ lookup->new_search = true;
+ if (firstarg) {
+ printgreeting(argc, argv, lookup);
+ firstarg = false;
+ }
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ debug("looking up %s", lookup->textname);
+ }
+ /* XXX Error message */
+ }
+ }
+
+ /*
+ * If we have a batchfile, seed the lookup list with the
+ * first entry, then trust the callback in dighost_shutdown
+ * to get the rest
+ */
+ char *filename = (char *)atomic_load(&batchname);
+ if ((filename != NULL) && !(is_batchfile)) {
+ if (strcmp(filename, "-") == 0) {
+ batchfp = stdin;
+ } else {
+ batchfp = fopen(filename, "r");
+ }
+ if (batchfp == NULL) {
+ perror(filename);
+ if (exitcode < 8) {
+ exitcode = 8;
+ }
+ fatal("couldn't open specified batch file");
+ }
+ /* XXX Remove code dup from shutdown code */
+ next_line:
+ if (fgets(batchline, sizeof(batchline), batchfp) != 0) {
+ debug("batch line %s", batchline);
+ if (batchline[0] == '\r' || batchline[0] == '\n' ||
+ batchline[0] == '#' || batchline[0] == ';')
+ {
+ goto next_line;
+ }
+ bargc = split_batchline(batchline, bargv, 14,
+ "batch argv");
+ bargv[0] = argv[0];
+ argv0 = argv[0];
+ parse_args(true, false, bargc, (char **)bargv);
+ return;
+ }
+ return;
+ }
+ /*
+ * If no lookup specified, search for root
+ */
+ if ((lookup_list.head == NULL) && !config_only) {
+ if (need_clone) {
+ lookup = clone_lookup(default_lookup, true);
+ }
+ need_clone = true;
+ lookup->trace_root = (lookup->trace || lookup->ns_search_only);
+ lookup->new_search = true;
+ strlcpy(lookup->textname, ".", sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = true;
+ if (firstarg) {
+ printgreeting(argc, argv, lookup);
+ firstarg = false;
+ }
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ if (!need_clone) {
+ destroy_lookup(lookup);
+ }
+}
+
+/*
+ * Callback from dighost.c to allow program-specific shutdown code.
+ * Here, we're possibly reading from a batch file, then shutting down
+ * for real if there's nothing in the batch file to read.
+ */
+static void
+query_finished(void) {
+ char batchline[MXNAME];
+ int bargc;
+ char *bargv[16];
+
+ if (atomic_load(&batchname) == 0) {
+ isc_app_shutdown();
+ return;
+ }
+
+ fflush(stdout);
+ if (feof(batchfp)) {
+ atomic_store(&batchname, 0);
+ isc_app_shutdown();
+ if (batchfp != stdin) {
+ fclose(batchfp);
+ }
+ return;
+ }
+
+ if (fgets(batchline, sizeof(batchline), batchfp) != 0) {
+ debug("batch line %s", batchline);
+ bargc = split_batchline(batchline, bargv, 14, "batch argv");
+ bargv[0] = argv0;
+ parse_args(true, false, bargc, (char **)bargv);
+ start_lookup();
+ } else {
+ atomic_store(&batchname, 0);
+ if (batchfp != stdin) {
+ fclose(batchfp);
+ }
+ isc_app_shutdown();
+ return;
+ }
+}
+
+static void
+dig_error(const char *format, ...) {
+ va_list args;
+
+ if (yaml) {
+ printf("-\n");
+ printf(" type: DIG_ERROR\n");
+
+ /*
+ * Print an indent before a literal block quote.
+ * Note: this will break if used to print more than
+ * one line of text as only the first line would be
+ * indented.
+ */
+ printf(" message: |\n");
+ printf(" ");
+ } else {
+ printf(";; ");
+ }
+
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+
+ if (!yaml) {
+ printf("\n");
+ }
+}
+
+static void
+dig_warning(const char *format, ...) {
+ va_list args;
+
+ if (!yaml) {
+ printf(";; ");
+
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+
+ printf("\n");
+ }
+}
+
+static void
+dig_comments(dig_lookup_t *lookup, const char *format, ...) {
+ va_list args;
+
+ if (lookup->comments && !yaml) {
+ printf(";; ");
+
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+
+ printf("\n");
+ }
+}
+
+void
+dig_setup(int argc, char **argv) {
+ isc_result_t result;
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ debug("dig_setup()");
+
+ /* setup dighost callbacks */
+ dighost_printmessage = printmessage;
+ dighost_received = received;
+ dighost_trying = trying;
+ dighost_shutdown = query_finished;
+ dighost_error = dig_error;
+ dighost_warning = dig_warning;
+ dighost_comments = dig_comments;
+
+ progname = argv[0];
+ preparse_args(argc, argv);
+
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+
+ setup_libs();
+ setup_system(ipv4only, ipv6only);
+}
+
+void
+dig_query_setup(bool is_batchfile, bool config_only, int argc, char **argv) {
+ debug("dig_query_setup");
+
+ parse_args(is_batchfile, config_only, argc, argv);
+ if (keyfile[0] != 0) {
+ setup_file_key();
+ } else if (keysecret[0] != 0) {
+ setup_text_key();
+ }
+ if (domainopt[0] != '\0') {
+ set_search_domain(domainopt);
+ usesearch = true;
+ }
+}
+
+void
+dig_startup(void) {
+ isc_result_t result;
+
+ debug("dig_startup()");
+
+ result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
+ check_result(result, "isc_app_onrun");
+ isc_app_run();
+}
+
+void
+dig_query_start(void) {
+ start_lookup();
+}
+
+void
+dig_shutdown(void) {
+ destroy_lookup(default_lookup);
+ if (atomic_load(&batchname) != 0) {
+ if (batchfp != stdin) {
+ fclose(batchfp);
+ }
+ atomic_store(&batchname, 0);
+ }
+ cancel_all();
+ destroy_libs();
+ isc_app_finish();
+}
+
+/*% Main processing routine for dig */
+int
+main(int argc, char **argv) {
+ dig_setup(argc, argv);
+ dig_query_setup(false, false, argc, argv);
+ dig_startup();
+ dig_shutdown();
+
+ return (exitcode);
+}
diff --git a/bin/dig/dig.rst b/bin/dig/dig.rst
new file mode 100644
index 0000000..59ac9f1
--- /dev/null
+++ b/bin/dig/dig.rst
@@ -0,0 +1,809 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: dig
+.. program:: dig
+.. _man_dig:
+
+dig - DNS lookup utility
+------------------------
+
+Synopsis
+~~~~~~~~
+:program:`dig` [@server] [**-b** address] [**-c** class] [**-f** filename] [**-k** filename] [**-m**] [**-p** port#] [**-q** name] [**-t** type] [**-v**] [**-x** addr] [**-y** [hmac:]name:key] [ [**-4**] | [**-6**] ] [name] [type] [class] [queryopt...]
+
+:program:`dig` [**-h**]
+
+:program:`dig` [global-queryopt...] [query...]
+
+Description
+~~~~~~~~~~~
+
+:program:`dig` is a flexible tool for interrogating DNS name servers. It
+performs DNS lookups and displays the answers that are returned from the
+name server(s) that were queried. Most DNS administrators use :program:`dig` to
+troubleshoot DNS problems because of its flexibility, ease of use, and
+clarity of output. Other lookup tools tend to have less functionality
+than :program:`dig`.
+
+Although :program:`dig` is normally used with command-line arguments, it also
+has a batch mode of operation for reading lookup requests from a file. A
+brief summary of its command-line arguments and options is printed when
+the :option:`-h` option is given. The BIND 9
+implementation of :program:`dig` allows multiple lookups to be issued from the
+command line.
+
+Unless it is told to query a specific name server, :program:`dig` tries each
+of the servers listed in ``/etc/resolv.conf``. If no usable server
+addresses are found, :program:`dig` sends the query to the local host.
+
+When no command-line arguments or options are given, :program:`dig`
+performs an NS query for "." (the root).
+
+It is possible to set per-user defaults for :program:`dig` via
+``${HOME}/.digrc``. This file is read and any options in it are applied
+before the command-line arguments. The :option:`-r` option disables this
+feature, for scripts that need predictable behavior.
+
+The IN and CH class names overlap with the IN and CH top-level domain
+names. Either use the :option:`-t` and :option:`-c` options to specify the type and
+class, use the :option:`-q` to specify the domain name, or use "IN." and
+"CH." when looking up these top-level domains.
+
+Simple Usage
+~~~~~~~~~~~~
+
+A typical invocation of :program:`dig` looks like:
+
+::
+
+ dig @server name type
+
+where:
+
+.. option:: server
+
+ is the name or IP address of the name server to query. This can be an
+ IPv4 address in dotted-decimal notation or an IPv6 address in
+ colon-delimited notation. When the supplied ``server`` argument is a
+ hostname, :program:`dig` resolves that name before querying that name
+ server.
+
+ If no ``server`` argument is provided, :program:`dig` consults
+ ``/etc/resolv.conf``; if an address is found there, it queries the
+ name server at that address. If either of the :option:`-4` or :option:`-6`
+ options are in use, then only addresses for the corresponding
+ transport are tried. If no usable addresses are found, :program:`dig`
+ sends the query to the local host. The reply from the name server
+ that responds is displayed.
+
+.. option:: name
+
+ is the name of the resource record that is to be looked up.
+
+.. option:: type
+
+ indicates what type of query is required - ANY, A, MX, SIG, etc.
+ ``type`` can be any valid query type. If no ``type`` argument is
+ supplied, :program:`dig` performs a lookup for an A record.
+
+Options
+~~~~~~~
+
+.. option:: -4
+
+ This option indicates that only IPv4 should be used.
+
+.. option:: -6
+
+ This option indicates that only IPv6 should be used.
+
+.. option:: -b address[#port]
+
+ This option sets the source IP address of the query. The ``address`` must be a
+ valid address on one of the host's network interfaces, or "0.0.0.0"
+ or "::". An optional port may be specified by appending ``#port``.
+
+.. option:: -c class
+
+ This option sets the query class. The default ``class`` is IN; other classes are
+ HS for Hesiod records or CH for Chaosnet records.
+
+.. option:: -f file
+
+ This option sets batch mode, in which :program:`dig` reads a list of lookup requests to process from
+ the given ``file``. Each line in the file should be organized in the
+ same way it would be presented as a query to :program:`dig` using the
+ command-line interface.
+
+.. option:: -h
+
+ Print a usage summary.
+
+.. option:: -k keyfile
+
+ This option tells :program:`dig` to sign queries using TSIG or
+ SIG(0) using a key read from the given file. Key files can be
+ generated using :iscman:`tsig-keygen`. When using TSIG authentication
+ with :program:`dig`, the name server that is queried needs to
+ know the key and algorithm that is being used. In BIND, this is
+ done by providing appropriate ``key`` and ``server`` statements
+ in :iscman:`named.conf` for TSIG and by looking up the KEY record
+ in zone data for SIG(0).
+
+.. option:: -m
+
+ This option enables memory usage debugging.
+
+.. option:: -p port
+
+ This option sends the query to a non-standard port on the server, instead of the
+ default port 53. This option is used to test a name server that
+ has been configured to listen for queries on a non-standard port
+ number.
+
+.. option:: -q name
+
+ This option specifies the domain name to query. This is useful to distinguish the ``name``
+ from other arguments.
+
+.. option:: -r
+
+ This option indicates that options from ``${HOME}/.digrc`` should not be read. This is useful for
+ scripts that need predictable behavior.
+
+.. option:: -t type
+
+ This option indicates the resource record type to query, which can be any valid query type. If
+ it is a resource record type supported in BIND 9, it can be given by
+ the type mnemonic (such as ``NS`` or ``AAAA``). The default query type is
+ ``A``, unless the :option:`-x` option is supplied to indicate a reverse
+ lookup. A zone transfer can be requested by specifying a type of
+ AXFR. When an incremental zone transfer (IXFR) is required, set the
+ ``type`` to ``ixfr=N``. The incremental zone transfer contains
+ all changes made to the zone since the serial number in the zone's
+ SOA record was ``N``.
+
+ All resource record types can be expressed as ``TYPEnn``, where ``nn`` is
+ the number of the type. If the resource record type is not supported
+ in BIND 9, the result is displayed as described in :rfc:`3597`.
+
+.. option:: -u
+
+ This option indicates that print query times should be provided in microseconds instead of milliseconds.
+
+.. option:: -v
+
+ This option prints the version number and exits.
+
+.. option:: -x addr
+
+ This option sets simplified reverse lookups, for mapping addresses to names. The
+ ``addr`` is an IPv4 address in dotted-decimal notation, or a
+ colon-delimited IPv6 address. When the :option:`-x` option is used, there is no
+ need to provide the ``name``, ``class``, and ``type`` arguments.
+ :program:`dig` automatically performs a lookup for a name like
+ ``94.2.0.192.in-addr.arpa`` and sets the query type and class to PTR
+ and IN respectively. IPv6 addresses are looked up using nibble format
+ under the IP6.ARPA domain.
+
+.. option:: -y [hmac:]keyname:secret
+
+ This option signs queries using TSIG with the given authentication key.
+ ``keyname`` is the name of the key, and ``secret`` is the
+ base64-encoded shared secret. ``hmac`` is the name of the key algorithm;
+ valid choices are ``hmac-md5``, ``hmac-sha1``, ``hmac-sha224``,
+ ``hmac-sha256``, ``hmac-sha384``, or ``hmac-sha512``. If ``hmac`` is
+ not specified, the default is ``hmac-md5``; if MD5 was disabled, the default is
+ ``hmac-sha256``.
+
+.. note:: Only the :option:`-k` option should be used, rather than the :option:`-y` option,
+ because with :option:`-y` the shared secret is supplied as a command-line
+ argument in clear text. This may be visible in the output from ``ps1`` or
+ in a history file maintained by the user's shell.
+
+Query Options
+~~~~~~~~~~~~~
+
+:program:`dig` provides a number of query options which affect the way in which
+lookups are made and the results displayed. Some of these set or reset
+flag bits in the query header, some determine which sections of the
+answer get printed, and others determine the timeout and retry
+strategies.
+
+Each query option is identified by a keyword preceded by a plus sign
+(``+``). Some keywords set or reset an option; these may be preceded by
+the string ``no`` to negate the meaning of that keyword. Other keywords
+assign values to options, like the timeout interval. They have the form
+``+keyword=value``. Keywords may be abbreviated, provided the
+abbreviation is unambiguous; for example, :option:`+cd` is equivalent to
+:option:`+cdflag`. The query options are:
+
+.. option:: +aaflag, +noaaflag
+
+ This option is a synonym for :option:`+aaonly`, :option:`+noaaonly`.
+
+.. option:: +aaonly, +noaaonly
+
+ This option sets the ``aa`` flag in the query.
+
+.. option:: +additional, +noadditional
+
+ This option displays [or does not display] the additional section of a reply. The
+ default is to display it.
+
+.. option:: +adflag, +noadflag
+
+ This option sets [or does not set] the AD (authentic data) bit in the query. This
+ requests the server to return whether all of the answer and authority
+ sections have been validated as secure, according to the security
+ policy of the server. ``AD=1`` indicates that all records have been
+ validated as secure and the answer is not from a OPT-OUT range. ``AD=0``
+ indicates that some part of the answer was insecure or not validated.
+ This bit is set by default.
+
+.. option:: +all, +noall
+
+ This option sets or clears all display flags.
+
+.. option:: +answer, +noanswer
+
+ This option displays [or does not display] the answer section of a reply. The default
+ is to display it.
+
+.. option:: +authority, +noauthority
+
+ This option displays [or does not display] the authority section of a reply. The
+ default is to display it.
+
+.. option:: +badcookie, +nobadcookie
+
+ This option retries the lookup with a new server cookie if a BADCOOKIE response is
+ received.
+
+.. option:: +besteffort, +nobesteffort
+
+ This option attempts to display the contents of messages which are malformed. The
+ default is to not display malformed answers.
+
+.. option:: +bufsize[=B]
+
+ This option sets the UDP message buffer size advertised using EDNS0 to
+ ``B`` bytes. The maximum and minimum sizes of this buffer are 65535 and
+ 0, respectively. ``+bufsize`` restores the default buffer size.
+
+.. option:: +cd, +cdflag, +nocdflag
+
+ This option sets [or does not set] the CD (checking disabled) bit in the query. This
+ requests the server to not perform DNSSEC validation of responses.
+
+.. option:: +class, +noclass
+
+ This option displays [or does not display] the CLASS when printing the record.
+
+.. option:: +cmd, +nocmd
+
+ This option toggles the printing of the initial comment in the output, identifying the
+ version of :program:`dig` and the query options that have been applied. This option
+ always has a global effect; it cannot be set globally and then overridden on a
+ per-lookup basis. The default is to print this comment.
+
+.. option:: +comments, +nocomments
+
+ This option toggles the display of some comment lines in the output, with
+ information about the packet header and OPT pseudosection, and the names of
+ the response section. The default is to print these comments.
+
+ Other types of comments in the output are not affected by this option, but
+ can be controlled using other command-line switches. These include
+ :option:`+cmd`, :option:`+question`, :option:`+stats`, and :option:`+rrcomments`.
+
+.. option:: +cookie=####, +nocookie
+
+ This option sends [or does not send] a COOKIE EDNS option, with an optional value. Replaying a COOKIE
+ from a previous response allows the server to identify a previous
+ client. The default is ``+cookie``.
+
+ ``+cookie`` is also set when :option:`+trace` is set to better emulate the
+ default queries from a nameserver.
+
+.. option:: +crypto, +nocrypto
+
+ This option toggles the display of cryptographic fields in DNSSEC records. The
+ contents of these fields are unnecessary for debugging most DNSSEC
+ validation failures and removing them makes it easier to see the
+ common failures. The default is to display the fields. When omitted,
+ they are replaced by the string ``[omitted]`` or, in the DNSKEY case, the
+ key ID is displayed as the replacement, e.g. ``[ key id = value ]``.
+
+.. option:: +defname, +nodefname
+
+ This option, which is deprecated, is treated as a synonym for
+ :option:`+search`, :option:`+nosearch`.
+
+.. option:: +dns64prefix, +nodns64prefix
+
+ Lookup IPV4ONLY.ARPA AAAA and print any DNS64 prefixes found.
+
+.. option:: +dnssec, +do, +nodnssec, +nodo
+
+ This option requests that DNSSEC records be sent by setting the DNSSEC OK (DO) bit in
+ the OPT record in the additional section of the query.
+
+.. option:: +domain=somename
+
+ This option sets the search list to contain the single domain ``somename``, as if
+ specified in a ``domain`` directive in ``/etc/resolv.conf``, and
+ enables search list processing as if the :option:`+search` option were
+ given.
+
+.. option:: +dscp=value
+
+ This option formerly set the DSCP value used when sending a query.
+ It is now obsolete, and has no effect.
+
+.. option:: +edns[=#], +noedns
+
+ This option specifies the EDNS version to query with. Valid values are 0 to 255.
+ Setting the EDNS version causes an EDNS query to be sent.
+ ``+noedns`` clears the remembered EDNS version. EDNS is set to 0 by
+ default.
+
+.. option:: +ednsflags[=#], +noednsflags
+
+ This option sets the must-be-zero EDNS flags bits (Z bits) to the specified value.
+ Decimal, hex, and octal encodings are accepted. Setting a named flag
+ (e.g., DO) is silently ignored. By default, no Z bits are set.
+
+.. option:: +ednsnegotiation, +noednsnegotiation
+
+ This option enables/disables EDNS version negotiation. By default, EDNS version
+ negotiation is enabled.
+
+.. option:: +ednsopt[=code[:value]], +noednsopt
+
+ This option specifies the EDNS option with code point ``code`` and an optional payload
+ of ``value`` as a hexadecimal string. ``code`` can be either an EDNS
+ option name (for example, ``NSID`` or ``ECS``) or an arbitrary
+ numeric value. ``+noednsopt`` clears the EDNS options to be sent.
+
+.. option:: +expire, +noexpire
+
+ This option sends an EDNS Expire option.
+
+.. option:: +fail, +nofail
+
+ This option indicates that :iscman:`named` should try [or not try] the next server if a SERVFAIL is received. The default is
+ to not try the next server, which is the reverse of normal stub
+ resolver behavior.
+
+.. option:: +fuzztime[=value], +nofuzztime
+
+ This option allows the signing time to be specified when generating
+ signed messages. If a value is specified it is the seconds since
+ 00:00:00 January 1, 1970 UTC ignoring leap seconds. If no value
+ is specified 1646972129 (Fri 11 Mar 2022 04:15:29 UTC) is used.
+ The default is ``+nofuzztime`` and the current time is used.
+
+.. option:: +header-only, +noheader-only
+
+ This option sends a query with a DNS header without a question section. The
+ default is to add a question section. The query type and query name
+ are ignored when this is set.
+
+.. option:: +https[=value], +nohttps
+
+ This option indicates whether to use DNS over HTTPS (DoH) when querying
+ name servers. When this option is in use, the port number defaults to 443.
+ The HTTP POST request mode is used when sending the query.
+
+ If ``value`` is specified, it will be used as the HTTP endpoint in the
+ query URI; the default is ``/dns-query``. So, for example, ``dig
+ @example.com +https`` will use the URI ``https://example.com/dns-query``.
+
+.. option:: +https-get[=value], +nohttps-get
+
+ Similar to :option:`+https`, except that the HTTP GET request mode is used
+ when sending the query.
+
+.. option:: +https-post[=value], +nohttps-post
+
+ Same as :option:`+https`.
+
+.. option:: +http-plain[=value], +nohttp-plain
+
+ Similar to :option:`+https`, except that HTTP queries will be sent over a
+ non-encrypted channel. When this option is in use, the port number
+ defaults to 80 and the HTTP request mode is POST.
+
+.. option:: +http-plain-get[=value], +nohttp-plain-get
+
+ Similar to :option:`+http-plain`, except that the HTTP request mode is GET.
+
+.. option:: +http-plain-post[=value], +nohttp-plain-post
+
+ Same as :option:`+http-plain`.
+
+.. option:: +identify, +noidentify
+
+ This option shows [or does not show] the IP address and port number that
+ supplied the answer, when the :option:`+short` option is enabled. If short
+ form answers are requested, the default is not to show the source
+ address and port number of the server that provided the answer.
+
+.. option:: +idnin, +noidnin
+
+ This option processes [or does not process] IDN domain names on input. This requires
+ ``IDN SUPPORT`` to have been enabled at compile time.
+
+ The default is to process IDN input when standard output is a tty.
+ The IDN processing on input is disabled when :program:`dig` output is redirected
+ to files, pipes, and other non-tty file descriptors.
+
+.. option:: +idnout, +noidnout
+
+ This option converts [or does not convert] puny code on output. This requires
+ ``IDN SUPPORT`` to have been enabled at compile time.
+
+ The default is to process puny code on output when standard output is
+ a tty. The puny code processing on output is disabled when :program:`dig` output
+ is redirected to files, pipes, and other non-tty file descriptors.
+
+.. option:: +ignore, +noignore
+
+ This option ignores [or does not ignore] truncation in UDP responses instead of retrying with TCP. By
+ default, TCP retries are performed.
+
+.. option:: +keepalive, +nokeepalive
+
+ This option sends [or does not send] an EDNS Keepalive option.
+
+.. option:: +keepopen, +nokeepopen
+
+ This option keeps [or does not keep] the TCP socket open between queries, and reuses it rather than
+ creating a new TCP socket for each lookup. The default is
+ ``+nokeepopen``.
+
+.. option:: +multiline, +nomultiline
+
+ This option prints [or does not print] records, like the SOA records, in a verbose multi-line format
+ with human-readable comments. The default is to print each record on
+ a single line to facilitate machine parsing of the :program:`dig` output.
+
+.. option:: +ndots=D
+
+ This option sets the number of dots (``D``) that must appear in ``name`` for
+ it to be considered absolute. The default value is that defined using
+ the ``ndots`` statement in ``/etc/resolv.conf``, or 1 if no ``ndots``
+ statement is present. Names with fewer dots are interpreted as
+ relative names, and are searched for in the domains listed in the
+ ``search`` or ``domain`` directive in ``/etc/resolv.conf`` if
+ :option:`+search` is set.
+
+.. option:: +nsid, +nonsid
+
+ When enabled, this option includes an EDNS name server ID request when sending a query.
+
+.. option:: +nssearch, +nonssearch
+
+ When this option is set, :program:`dig` attempts to find the authoritative
+ name servers for the zone containing the name being looked up, and
+ display the SOA record that each name server has for the zone.
+ Addresses of servers that did not respond are also printed.
+
+.. option:: +onesoa, +noonesoa
+
+ When enabled, this option prints only one (starting) SOA record when performing an AXFR. The
+ default is to print both the starting and ending SOA records.
+
+.. option:: +opcode=value, +noopcode
+
+ When enabled, this option sets (restores) the DNS message opcode to the specified value. The
+ default value is QUERY (0).
+
+.. option:: +padding=value
+
+ This option pads the size of the query packet using the EDNS Padding option to
+ blocks of ``value`` bytes. For example, ``+padding=32`` causes a
+ 48-byte query to be padded to 64 bytes. The default block size is 0,
+ which disables padding; the maximum is 512. Values are ordinarily
+ expected to be powers of two, such as 128; however, this is not
+ mandatory. Responses to padded queries may also be padded, but only
+ if the query uses TCP or DNS COOKIE.
+
+.. option:: +qid=value
+
+ This option specifies the query ID to use when sending queries.
+
+.. option:: +qr, +noqr
+
+ This option toggles the display of the query message as it is sent. By default, the query
+ is not printed.
+
+.. option:: +question, +noquestion
+
+ This option toggles the display of the question section of a query when an answer is
+ returned. The default is to print the question section as a comment.
+
+.. option:: +raflag, +noraflag
+
+ This option sets [or does not set] the RA (Recursion Available) bit in the query. The
+ default is ``+noraflag``. This bit is ignored by the server for
+ QUERY.
+
+.. option:: +rdflag, +nordflag
+
+ This option is a synonym for :option:`+recurse`, :option:`+norecurse`.
+
+.. option:: +recurse, +norecurse
+
+ This option toggles the setting of the RD (recursion desired) bit in the query.
+ This bit is set by default, which means :program:`dig` normally sends
+ recursive queries. Recursion is automatically disabled when the
+ :option:`+nssearch` or :option:`+trace` query option is used.
+
+.. option:: +retry=T
+
+ This option sets the number of times to retry UDP and TCP queries to server to ``T``
+ instead of the default, 2. Unlike :option:`+tries`, this does not include
+ the initial query.
+
+.. option:: +rrcomments, +norrcomments
+
+ This option toggles the display of per-record comments in the output (for example,
+ human-readable key information about DNSKEY records). The default is
+ not to print record comments unless multiline mode is active.
+
+.. option:: +search, +nosearch
+
+ This option uses [or does not use] the search list defined by the searchlist or domain
+ directive in ``resolv.conf``, if any. The search list is not used by
+ default.
+
+ ``ndots`` from ``resolv.conf`` (default 1), which may be overridden by
+ :option:`+ndots`, determines whether the name is treated as relative
+ and hence whether a search is eventually performed.
+
+.. option:: +short, +noshort
+
+ This option toggles whether a terse answer is provided. The default is to print the answer in a verbose
+ form. This option always has a global effect; it cannot be set globally and
+ then overridden on a per-lookup basis.
+
+.. option:: +showbadcookie, +noshowbadcookie
+
+ This option toggles whether to show the message containing the
+ BADCOOKIE rcode before retrying the request or not. The default
+ is to not show the messages.
+
+.. option:: +showsearch, +noshowsearch
+
+ This option performs [or does not perform] a search showing intermediate results.
+
+.. option:: +sigchase, +nosigchase
+
+ This feature is now obsolete and has been removed; use :iscman:`delv`
+ instead.
+
+.. option:: +split=W
+
+ This option splits long hex- or base64-formatted fields in resource records into
+ chunks of ``W`` characters (where ``W`` is rounded up to the nearest
+ multiple of 4). ``+nosplit`` or ``+split=0`` causes fields not to be
+ split at all. The default is 56 characters, or 44 characters when
+ multiline mode is active.
+
+.. option:: +stats, +nostats
+
+ This option toggles the printing of statistics: when the query was made, the size of the
+ reply, etc. The default behavior is to print the query statistics as a
+ comment after each lookup.
+
+.. option:: +subnet=addr[/prefix-length], +nosubnet
+
+ This option sends [or does not send] an EDNS CLIENT-SUBNET option with the specified IP
+ address or network prefix.
+
+ ``dig +subnet=0.0.0.0/0``, or simply ``dig +subnet=0`` for short,
+ sends an EDNS CLIENT-SUBNET option with an empty address and a source
+ prefix-length of zero, which signals a resolver that the client's
+ address information must *not* be used when resolving this query.
+
+.. option:: +tcflag, +notcflag
+
+ This option sets [or does not set] the TC (TrunCation) bit in the query. The default is
+ ``+notcflag``. This bit is ignored by the server for QUERY.
+
+.. option:: +tcp, +notcp
+
+ This option indicates whether to use TCP when querying name
+ servers. The default behavior is to use UDP unless a type ``any``
+ or ``ixfr=N`` query is requested, in which case the default is
+ TCP. AXFR queries always use TCP. To prevent retry over TCP when
+ TC=1 is returned from a UDP query, use ``+ignore``.
+
+.. option:: +timeout=T
+
+ This option sets the timeout for a query to ``T`` seconds. The default timeout is
+ 5 seconds. An attempt to set ``T`` to less than 1 is silently set to 1.
+
+.. option:: +tls, +notls
+
+ This option indicates whether to use DNS over TLS (DoT) when querying
+ name servers. When this option is in use, the port number defaults
+ to 853.
+
+.. option:: +tls-ca[=file-name], +notls-ca
+
+ This option enables remote server TLS certificate validation for
+ DNS transports, relying on TLS. Certificate authorities
+ certificates are loaded from the specified PEM file
+ (``file-name``). If the file is not specified, the default
+ certificates from the global certificates store are used.
+
+.. option:: +tls-certfile=file-name, +tls-keyfile=file-name, +notls-certfile, +notls-keyfile
+
+ These options set the state of certificate-based client
+ authentication for DNS transports, relying on TLS. Both certificate
+ chain file and private key file are expected to be in PEM format.
+ Both options must be specified at the same time.
+
+.. option:: +tls-hostname=hostname, +notls-hostname
+
+ This option makes :program:`dig` use the provided hostname during remote
+ server TLS certificate verification. Otherwise, the DNS server name
+ is used. This option has no effect if :option:`+tls-ca` is not specified.
+
+.. option:: +topdown, +notopdown
+
+ This feature is related to :option:`dig +sigchase`, which is obsolete and
+ has been removed. Use :iscman:`delv` instead.
+
+.. option:: +trace, +notrace
+
+ This option toggles tracing of the delegation path from the root name servers for
+ the name being looked up. Tracing is disabled by default. When
+ tracing is enabled, :program:`dig` makes iterative queries to resolve the
+ name being looked up. It follows referrals from the root servers,
+ showing the answer from each server that was used to resolve the
+ lookup.
+
+ If ``@server`` is also specified, it affects only the initial query for
+ the root zone name servers.
+
+ :option:`+dnssec` is also set when :option:`+trace` is set, to better emulate the
+ default queries from a name server.
+
+.. option:: +tries=T
+
+ This option sets the number of times to try UDP and TCP queries to server to ``T``
+ instead of the default, 3. If ``T`` is less than or equal to zero,
+ the number of tries is silently rounded up to 1.
+
+.. option:: +trusted-key=####
+
+ This option formerly specified trusted keys for use with :option:`dig +sigchase`. This
+ feature is now obsolete and has been removed; use :iscman:`delv` instead.
+
+.. option:: +ttlid, +nottlid
+
+ This option displays [or does not display] the TTL when printing the record.
+
+.. option:: +ttlunits, +nottlunits
+
+ This option displays [or does not display] the TTL in friendly human-readable time
+ units of ``s``, ``m``, ``h``, ``d``, and ``w``, representing seconds, minutes,
+ hours, days, and weeks. This implies :option:`+ttlid`.
+
+.. option:: +unknownformat, +nounknownformat
+
+ This option prints all RDATA in unknown RR type presentation format (:rfc:`3597`).
+ The default is to print RDATA for known types in the type's
+ presentation format.
+
+.. option:: +vc, +novc
+
+ This option uses [or does not use] TCP when querying name servers. This alternate
+ syntax to :option:`+tcp` is provided for backwards compatibility. The
+ ``vc`` stands for "virtual circuit."
+
+.. option:: +yaml, +noyaml
+
+ When enabled, this option prints the responses (and, if :option:`+qr` is in use, also the
+ outgoing queries) in a detailed YAML format.
+
+.. option:: +zflag, +nozflag
+
+ This option sets [or does not set] the last unassigned DNS header flag in a DNS query.
+ This flag is off by default.
+
+Multiple Queries
+~~~~~~~~~~~~~~~~
+
+The BIND 9 implementation of :program:`dig` supports specifying multiple
+queries on the command line (in addition to supporting the :option:`-f` batch
+file option). Each of those queries can be supplied with its own set of
+flags, options, and query options.
+
+In this case, each ``query`` argument represents an individual query in
+the command-line syntax described above. Each consists of any of the
+standard options and flags, the name to be looked up, an optional query
+type and class, and any query options that should be applied to that
+query.
+
+A global set of query options, which should be applied to all queries,
+can also be supplied. These global query options must precede the first
+tuple of name, class, type, options, flags, and query options supplied
+on the command line. Any global query options (except :option:`+cmd` and
+:option:`+short` options) can be overridden by a query-specific set of
+query options. For example:
+
+::
+
+ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr
+
+shows how :program:`dig` can be used from the command line to make three
+lookups: an ANY query for ``www.isc.org``, a reverse lookup of 127.0.0.1,
+and a query for the NS records of ``isc.org``. A global query option of
+:option:`+qr` is applied, so that :program:`dig` shows the initial query it made for
+each lookup. The final query has a local query option of :option:`+noqr` which
+means that :program:`dig` does not print the initial query when it looks up the
+NS records for ``isc.org``.
+
+IDN Support
+~~~~~~~~~~~
+
+If :program:`dig` has been built with IDN (internationalized domain name)
+support, it can accept and display non-ASCII domain names. :program:`dig`
+appropriately converts character encoding of a domain name before sending
+a request to a DNS server or displaying a reply from the server.
+To turn off IDN support, use the parameters
+:option:`+idnin` and :option:`+idnout`, or define the ``IDN_DISABLE`` environment
+variable.
+
+Return Codes
+~~~~~~~~~~~~
+
+:program:`dig` return codes are:
+
+``0``
+ DNS response received, including NXDOMAIN status
+
+``1``
+ Usage error
+
+``8``
+ Couldn't open batch file
+
+``9``
+ No reply from server
+
+``10``
+ Internal error
+
+Files
+~~~~~
+
+``/etc/resolv.conf``
+
+``${HOME}/.digrc``
+
+See Also
+~~~~~~~~
+
+:iscman:`delv(1) <delv>`, :iscman:`host(1) <host>`, :iscman:`named(8) <named>`, :iscman:`dnssec-keygen(8) <dnssec-keygen>`, :rfc:`1035`.
+
+Bugs
+~~~~
+
+There are probably too many query options.
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
new file mode 100644
index 0000000..55f7bf2
--- /dev/null
+++ b/bin/dig/dighost.c
@@ -0,0 +1,4989 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file
+ * \note
+ * Notice to programmers: Do not use this code as an example of how to
+ * use the ISC library to perform DNS lookups. Dig and Host both operate
+ * on the request level, since they allow fine-tuning of output and are
+ * intended as debugging tools. As a result, they perform many of the
+ * functions which could be better handled using the dns_resolver
+ * functions in most applications.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_LIBIDN2
+#include <idn2.h>
+#endif /* HAVE_LIBIDN2 */
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/file.h>
+#include <isc/hex.h>
+#include <isc/lang.h>
+#include <isc/log.h>
+#include <isc/managers.h>
+#include <isc/netaddr.h>
+#include <isc/netdb.h>
+#include <isc/nonce.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/safe.h>
+#include <isc/serial.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/opcode.h>
+#include <dns/rcode.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/tsig.h>
+
+#include <dst/dst.h>
+
+#include <isccfg/namedconf.h>
+
+#include <irs/resconf.h>
+
+#include <bind9/getaddresses.h>
+
+#include "dighost.h"
+
+#define systemlocale(l) (void)setlocale(l, "")
+#define resetlocale(l) (void)setlocale(l, "C")
+
+dig_lookuplist_t lookup_list;
+dig_serverlist_t server_list;
+dig_searchlistlist_t search_list;
+
+static atomic_bool cancel_now = false;
+
+bool check_ra = false, have_ipv4 = false, have_ipv6 = false,
+ specified_source = false, free_now = false, usesearch = false,
+ showsearch = false, is_dst_up = false, keep_open = false, verbose = false,
+ yaml = false;
+in_port_t port = 53;
+bool port_set = false;
+unsigned int timeout = 0;
+unsigned int extrabytes;
+isc_mem_t *mctx = NULL;
+isc_log_t *lctx = NULL;
+isc_nm_t *netmgr = NULL;
+isc_taskmgr_t *taskmgr = NULL;
+isc_task_t *global_task = NULL;
+isc_sockaddr_t localaddr;
+isc_refcount_t sendcount = 0;
+isc_refcount_t recvcount = 0;
+int ndots = -1;
+int tries = -1;
+int lookup_counter = 0;
+
+static char servercookie[256];
+
+#ifdef HAVE_LIBIDN2
+static void
+idn_locale_to_ace(const char *src, char *dst, size_t dstlen);
+static void
+idn_ace_to_locale(const char *src, char **dst);
+static isc_result_t
+idn_output_filter(isc_buffer_t *buffer, unsigned int used_org);
+#endif /* HAVE_LIBIDN2 */
+
+isc_nmhandle_t *keep = NULL;
+isc_sockaddr_t keepaddr;
+
+/*%
+ * Exit Codes:
+ *
+ *\li 0 Everything went well, including things like NXDOMAIN
+ *\li 1 Usage error
+ *\li 7 Got too many RR's or Names
+ *\li 8 Couldn't open batch file
+ *\li 9 No reply from server
+ *\li 10 Internal error
+ */
+int exitcode = 0;
+int fatalexit = 0;
+char keynametext[MXNAME];
+char keyfile[MXNAME] = "";
+char keysecret[MXNAME] = "";
+unsigned char cookie_secret[33];
+unsigned char cookie[8];
+const dns_name_t *hmacname = NULL;
+unsigned int digestbits = 0;
+isc_buffer_t *namebuf = NULL;
+dns_tsigkey_t *tsigkey = NULL;
+dst_key_t *sig0key = NULL;
+bool validated = true;
+bool debugging = false;
+bool debugtiming = false;
+bool memdebugging = false;
+char *progname = NULL;
+isc_mutex_t lookup_lock;
+dig_lookup_t *current_lookup = NULL;
+
+#define DIG_MAX_ADDRESSES 20
+
+/*%
+ * Apply and clear locks at the event level in global task.
+ * Can I get rid of these using shutdown events? XXX
+ */
+#define LOCK_LOOKUP \
+ { \
+ debug("lock_lookup %s:%d", __FILE__, __LINE__); \
+ check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_" \
+ "lock"); \
+ debug("success"); \
+ }
+#define UNLOCK_LOOKUP \
+ { \
+ debug("unlock_lookup %s:%d", __FILE__, __LINE__); \
+ check_result(isc_mutex_unlock((&lookup_lock)), "isc_mutex_" \
+ "unlock"); \
+ }
+
+static void
+default_warnerr(const char *format, ...) {
+ va_list args;
+
+ printf(";; ");
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ printf("\n");
+}
+
+static void
+default_comments(dig_lookup_t *lookup, const char *format, ...) {
+ va_list args;
+
+ if (lookup->comments) {
+ printf(";; ");
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ printf("\n");
+ }
+}
+
+/* dynamic callbacks */
+
+isc_result_t (*dighost_printmessage)(dig_query_t *query,
+ const isc_buffer_t *msgbuf,
+ dns_message_t *msg, bool headers);
+
+void (*dighost_error)(const char *format, ...) = default_warnerr;
+
+void (*dighost_warning)(const char *format, ...) = default_warnerr;
+
+void (*dighost_comments)(dig_lookup_t *lookup, const char *format,
+ ...) = default_comments;
+
+void (*dighost_received)(unsigned int bytes, isc_sockaddr_t *from,
+ dig_query_t *query);
+
+void (*dighost_trying)(char *frm, dig_lookup_t *lookup);
+
+void (*dighost_shutdown)(void);
+
+/* forward declarations */
+
+#define cancel_lookup(l) _cancel_lookup(l, __FILE__, __LINE__)
+static void
+_cancel_lookup(dig_lookup_t *lookup, const char *file, unsigned int line);
+
+static void
+recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
+ void *arg);
+
+static void
+start_udp(dig_query_t *query);
+
+static void
+start_tcp(dig_query_t *query);
+
+static void
+force_next(dig_query_t *query);
+
+static void
+launch_next_query(dig_query_t *query);
+
+static void
+clear_current_lookup(void);
+
+static bool
+next_origin(dig_lookup_t *oldlookup);
+
+static int
+count_dots(char *string) {
+ char *s;
+ int i = 0;
+
+ s = string;
+ while (*s != '\0') {
+ if (*s == '.') {
+ i++;
+ }
+ s++;
+ }
+ return (i);
+}
+
+static void
+hex_dump(isc_buffer_t *b) {
+ unsigned int len, i;
+ isc_region_t r;
+
+ isc_buffer_usedregion(b, &r);
+
+ printf("%u bytes\n", r.length);
+ for (len = 0; len < r.length; len++) {
+ printf("%02x ", r.base[len]);
+ if (len % 16 == 15) {
+ printf(" ");
+ for (i = len - 15; i <= len; i++) {
+ if (r.base[i] >= '!' && r.base[i] <= '}') {
+ putchar(r.base[i]);
+ } else {
+ putchar('.');
+ }
+ }
+ printf("\n");
+ }
+ }
+ if (len % 16 != 0) {
+ for (i = len; (i % 16) != 0; i++) {
+ printf(" ");
+ }
+ printf(" ");
+ for (i = ((len >> 4) << 4); i < len; i++) {
+ if (r.base[i] >= '!' && r.base[i] <= '}') {
+ putchar(r.base[i]);
+ } else {
+ putchar('.');
+ }
+ }
+ printf("\n");
+ }
+}
+
+/*%
+ * Append 'len' bytes of 'text' at '*p', failing with
+ * ISC_R_NOSPACE if that would advance p past 'end'.
+ */
+static isc_result_t
+append(const char *text, size_t len, char **p, char *end) {
+ if (*p + len > end) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(*p, text, len);
+ *p += len;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+reverse_octets(const char *in, char **p, char *end) {
+ const char *dot = strchr(in, '.');
+ size_t len;
+ if (dot != NULL) {
+ isc_result_t result;
+ result = reverse_octets(dot + 1, p, end);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ result = append(".", 1, p, end);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ len = (int)(dot - in);
+ } else {
+ len = (int)strlen(in);
+ }
+ return (append(in, len, p, end));
+}
+
+isc_result_t
+get_reverse(char *reverse, size_t len, char *value, bool strict) {
+ int r;
+ isc_result_t result;
+ isc_netaddr_t addr;
+
+ addr.family = AF_INET6;
+ r = inet_pton(AF_INET6, value, &addr.type.in6);
+ if (r > 0) {
+ /* This is a valid IPv6 address. */
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ unsigned int options = 0;
+
+ name = dns_fixedname_initname(&fname);
+ result = dns_byaddr_createptrname(&addr, options, name);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ dns_name_format(name, reverse, (unsigned int)len);
+ return (ISC_R_SUCCESS);
+ } else {
+ /*
+ * Not a valid IPv6 address. Assume IPv4.
+ * If 'strict' is not set, construct the
+ * in-addr.arpa name by blindly reversing
+ * octets whether or not they look like integers,
+ * so that this can be used for RFC2317 names
+ * and such.
+ */
+ char *p = reverse;
+ char *end = reverse + len;
+ if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) {
+ return (DNS_R_BADDOTTEDQUAD);
+ }
+ result = reverse_octets(value, &p, end);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ /* Append .in-addr.arpa. and a terminating NUL. */
+ result = append(".in-addr.arpa.", 15, &p, end);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ return (ISC_R_SUCCESS);
+ }
+}
+
+void (*dighost_pre_exit_hook)(void) = NULL;
+
+#if TARGET_OS_IPHONE
+void
+warn(const char *format, ...) {
+ va_list args;
+
+ fflush(stdout);
+ fprintf(stderr, ";; Warning: ");
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+}
+#else /* if TARGET_OS_IPHONE */
+void
+warn(const char *format, ...) {
+ va_list args;
+
+ fflush(stdout);
+ fprintf(stderr, "%s: ", progname);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+}
+#endif /* if TARGET_OS_IPHONE */
+
+void
+digexit(void) {
+ if (exitcode < 10) {
+ exitcode = 10;
+ }
+ if (fatalexit != 0) {
+ exitcode = fatalexit;
+ }
+ if (dighost_pre_exit_hook != NULL) {
+ dighost_pre_exit_hook();
+ }
+ exit(exitcode);
+}
+
+void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fflush(stdout);
+ fprintf(stderr, "%s: ", progname);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ digexit();
+}
+
+void
+debug(const char *format, ...) {
+ va_list args;
+ isc_time_t t;
+
+ if (debugging) {
+ fflush(stdout);
+ if (debugtiming) {
+ TIME_NOW(&t);
+ fprintf(stderr, "%u.%06u: ", isc_time_seconds(&t),
+ isc_time_nanoseconds(&t) / 1000);
+ }
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+void
+check_result(isc_result_t result, const char *msg) {
+ if (result != ISC_R_SUCCESS) {
+ fatal("%s: %s", msg, isc_result_totext(result));
+ }
+}
+
+/*%
+ * Create a server structure, which is part of the lookup structure.
+ * This is little more than a linked list of servers to query in hopes
+ * of finding the answer the user is looking for
+ */
+dig_server_t *
+make_server(const char *servname, const char *userarg) {
+ dig_server_t *srv;
+
+ REQUIRE(servname != NULL);
+
+ debug("make_server(%s)", servname);
+ srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
+ strlcpy(srv->servername, servname, MXNAME);
+ strlcpy(srv->userarg, userarg, MXNAME);
+ ISC_LINK_INIT(srv, link);
+ return (srv);
+}
+
+/*%
+ * Create a copy of the server list from the resolver configuration structure.
+ * The dest list must have already had ISC_LIST_INIT applied.
+ */
+static void
+get_server_list(irs_resconf_t *resconf) {
+ isc_sockaddrlist_t *servers;
+ isc_sockaddr_t *sa;
+ dig_server_t *newsrv;
+ char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
+ sizeof("%4000000000")];
+ debug("get_server_list()");
+ servers = irs_resconf_getnameservers(resconf);
+ for (sa = ISC_LIST_HEAD(*servers); sa != NULL;
+ sa = ISC_LIST_NEXT(sa, link))
+ {
+ int pf = isc_sockaddr_pf(sa);
+ isc_netaddr_t na;
+ isc_result_t result;
+ isc_buffer_t b;
+
+ if (pf == AF_INET && !have_ipv4) {
+ continue;
+ }
+ if (pf == AF_INET6 && !have_ipv6) {
+ continue;
+ }
+
+ isc_buffer_init(&b, tmp, sizeof(tmp));
+ isc_netaddr_fromsockaddr(&na, sa);
+ result = isc_netaddr_totext(&na, &b);
+ if (result != ISC_R_SUCCESS) {
+ continue;
+ }
+ isc_buffer_putuint8(&b, 0);
+ if (pf == AF_INET6 && na.zone != 0) {
+ char buf[sizeof("%4000000000")];
+ snprintf(buf, sizeof(buf), "%%%u", na.zone);
+ strlcat(tmp, buf, sizeof(tmp));
+ }
+ newsrv = make_server(tmp, tmp);
+ ISC_LINK_INIT(newsrv, link);
+ ISC_LIST_APPEND(server_list, newsrv, link);
+ }
+}
+
+void
+flush_server_list(void) {
+ dig_server_t *s, *ps;
+
+ debug("flush_server_list()");
+ s = ISC_LIST_HEAD(server_list);
+ while (s != NULL) {
+ ps = s;
+ s = ISC_LIST_NEXT(s, link);
+ ISC_LIST_DEQUEUE(server_list, ps, link);
+ isc_mem_free(mctx, ps);
+ }
+}
+
+void
+set_nameserver(char *opt) {
+ isc_result_t result;
+ isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
+ isc_netaddr_t netaddr;
+ int count, i;
+ dig_server_t *srv;
+ char tmp[ISC_NETADDR_FORMATSIZE];
+
+ if (opt == NULL) {
+ return;
+ }
+
+ result = bind9_getaddresses(opt, 0, sockaddrs, DIG_MAX_ADDRESSES,
+ &count);
+ if (result != ISC_R_SUCCESS) {
+ fatal("couldn't get address for '%s': %s", opt,
+ isc_result_totext(result));
+ }
+
+ flush_server_list();
+
+ for (i = 0; i < count; i++) {
+ isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
+ isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
+ srv = make_server(tmp, opt);
+ if (srv == NULL) {
+ fatal("memory allocation failure");
+ }
+ ISC_LIST_APPEND(server_list, srv, link);
+ }
+}
+
+/*%
+ * Produce a cloned server list. The dest list must have already had
+ * ISC_LIST_INIT applied.
+ */
+void
+clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
+ dig_server_t *srv, *newsrv;
+
+ debug("clone_server_list()");
+ srv = ISC_LIST_HEAD(src);
+ while (srv != NULL) {
+ newsrv = make_server(srv->servername, srv->userarg);
+ ISC_LINK_INIT(newsrv, link);
+ ISC_LIST_ENQUEUE(*dest, newsrv, link);
+ srv = ISC_LIST_NEXT(srv, link);
+ }
+}
+
+/*%
+ * Create an empty lookup structure, which holds all the information needed
+ * to get an answer to a user's question. This structure contains two
+ * linked lists: the server list (servers to query) and the query list
+ * (outstanding queries which have been made to the listed servers).
+ */
+dig_lookup_t *
+make_empty_lookup(void) {
+ dig_lookup_t *looknew;
+#ifdef HAVE_LIBIDN2
+ bool idn_allowed = isatty(1) ? (getenv("IDN_DISABLE") == NULL) : false;
+#endif /* HAVE_LIBIDN2 */
+
+ debug("make_empty_lookup()");
+
+ INSIST(!free_now);
+
+ looknew = isc_mem_allocate(mctx, sizeof(*looknew));
+ *looknew = (dig_lookup_t){
+ .pending = true,
+ .rdtype = dns_rdatatype_a,
+ .qrdtype = dns_rdatatype_a,
+ .rdclass = dns_rdataclass_in,
+ .servfail_stops = true,
+ .besteffort = true,
+ .opcode = dns_opcode_query,
+ .badcookie = true,
+#ifdef HAVE_LIBIDN2
+ .idnin = idn_allowed,
+ .idnout = idn_allowed,
+#endif /* HAVE_LIBIDN2 */
+ .udpsize = -1,
+ .edns = -1,
+ .recurse = true,
+ .retries = tries,
+ .comments = true,
+ .stats = true,
+ .section_question = true,
+ .section_answer = true,
+ .section_authority = true,
+ .section_additional = true,
+ .ednsneg = true,
+ };
+
+ dns_fixedname_init(&looknew->fdomain);
+ ISC_LINK_INIT(looknew, link);
+ ISC_LIST_INIT(looknew->q);
+ ISC_LIST_INIT(looknew->my_server_list);
+
+ isc_tlsctx_cache_create(mctx, &looknew->tls_ctx_cache);
+
+ isc_refcount_init(&looknew->references, 1);
+
+ looknew->magic = DIG_LOOKUP_MAGIC;
+
+ debug("make_empty_lookup() = %p->references = %" PRIuFAST32, looknew,
+ isc_refcount_current(&looknew->references));
+
+ return (looknew);
+}
+
+#define EDNSOPT_OPTIONS 100U
+
+static void
+cloneopts(dig_lookup_t *looknew, dig_lookup_t *lookold) {
+ size_t len = sizeof(looknew->ednsopts[0]) * EDNSOPT_OPTIONS;
+ size_t i;
+ looknew->ednsopts = isc_mem_allocate(mctx, len);
+ for (i = 0; i < EDNSOPT_OPTIONS; i++) {
+ looknew->ednsopts[i].code = 0;
+ looknew->ednsopts[i].length = 0;
+ looknew->ednsopts[i].value = NULL;
+ }
+ looknew->ednsoptscnt = 0;
+ if (lookold == NULL || lookold->ednsopts == NULL) {
+ return;
+ }
+
+ for (i = 0; i < lookold->ednsoptscnt; i++) {
+ len = lookold->ednsopts[i].length;
+ if (len != 0) {
+ INSIST(lookold->ednsopts[i].value != NULL);
+ looknew->ednsopts[i].value = isc_mem_allocate(mctx,
+ len);
+ memmove(looknew->ednsopts[i].value,
+ lookold->ednsopts[i].value, len);
+ }
+ looknew->ednsopts[i].code = lookold->ednsopts[i].code;
+ looknew->ednsopts[i].length = len;
+ }
+ looknew->ednsoptscnt = lookold->ednsoptscnt;
+}
+
+/*%
+ * Clone a lookup, perhaps copying the server list. This does not clone
+ * the query list, since it will be regenerated by the setup_lookup()
+ * function, nor does it queue up the new lookup for processing.
+ * Caution: If you don't clone the servers, you MUST clone the server
+ * list separately from somewhere else, or construct it by hand.
+ */
+dig_lookup_t *
+clone_lookup(dig_lookup_t *lookold, bool servers) {
+ dig_lookup_t *looknew;
+
+ debug("clone_lookup()");
+
+ INSIST(!free_now);
+
+ looknew = make_empty_lookup();
+ strlcpy(looknew->textname, lookold->textname, MXNAME);
+ strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
+ looknew->textname[MXNAME - 1] = 0;
+ looknew->rdtype = lookold->rdtype;
+ looknew->qrdtype = lookold->qrdtype;
+ looknew->rdclass = lookold->rdclass;
+ looknew->rdtypeset = lookold->rdtypeset;
+ looknew->rdclassset = lookold->rdclassset;
+ looknew->doing_xfr = lookold->doing_xfr;
+ looknew->ixfr_serial = lookold->ixfr_serial;
+ looknew->trace = lookold->trace;
+ looknew->trace_root = lookold->trace_root;
+ looknew->identify = lookold->identify;
+ looknew->identify_previous_line = lookold->identify_previous_line;
+ looknew->ignore = lookold->ignore;
+ looknew->servfail_stops = lookold->servfail_stops;
+ looknew->besteffort = lookold->besteffort;
+ looknew->dns64prefix = lookold->dns64prefix;
+ looknew->dnssec = lookold->dnssec;
+ looknew->ednsflags = lookold->ednsflags;
+ looknew->opcode = lookold->opcode;
+ looknew->expire = lookold->expire;
+ looknew->nsid = lookold->nsid;
+ looknew->tcp_keepalive = lookold->tcp_keepalive;
+ looknew->header_only = lookold->header_only;
+ looknew->https_mode = lookold->https_mode;
+ if (lookold->https_path != NULL) {
+ looknew->https_path = isc_mem_strdup(mctx, lookold->https_path);
+ }
+ looknew->https_get = lookold->https_get;
+ looknew->http_plain = lookold->http_plain;
+
+ looknew->tls_ca_set = lookold->tls_ca_set;
+ if (lookold->tls_ca_file != NULL) {
+ looknew->tls_ca_file = isc_mem_strdup(mctx,
+ lookold->tls_ca_file);
+ };
+
+ looknew->tls_hostname_set = lookold->tls_hostname_set;
+ if (lookold->tls_hostname != NULL) {
+ looknew->tls_hostname = isc_mem_strdup(mctx,
+ lookold->tls_hostname);
+ }
+
+ looknew->tls_key_file_set = lookold->tls_key_file_set;
+ if (lookold->tls_key_file != NULL) {
+ looknew->tls_key_file = isc_mem_strdup(mctx,
+ lookold->tls_key_file);
+ }
+
+ looknew->tls_cert_file_set = lookold->tls_cert_file_set;
+ if (lookold->tls_cert_file != NULL) {
+ looknew->tls_cert_file = isc_mem_strdup(mctx,
+ lookold->tls_cert_file);
+ }
+
+ looknew->showbadcookie = lookold->showbadcookie;
+ looknew->sendcookie = lookold->sendcookie;
+ looknew->seenbadcookie = lookold->seenbadcookie;
+ looknew->badcookie = lookold->badcookie;
+ looknew->cookie = lookold->cookie;
+ if (lookold->ednsopts != NULL) {
+ cloneopts(looknew, lookold);
+ } else {
+ looknew->ednsopts = NULL;
+ looknew->ednsoptscnt = 0;
+ }
+ looknew->ednsneg = lookold->ednsneg;
+ looknew->padding = lookold->padding;
+ looknew->multiline = lookold->multiline;
+ looknew->nottl = lookold->nottl;
+ looknew->noclass = lookold->noclass;
+ looknew->onesoa = lookold->onesoa;
+ looknew->use_usec = lookold->use_usec;
+ looknew->nocrypto = lookold->nocrypto;
+ looknew->ttlunits = lookold->ttlunits;
+ looknew->expandaaaa = lookold->expandaaaa;
+ looknew->qr = lookold->qr;
+ looknew->idnin = lookold->idnin;
+ looknew->idnout = lookold->idnout;
+ looknew->udpsize = lookold->udpsize;
+ looknew->edns = lookold->edns;
+ looknew->recurse = lookold->recurse;
+ looknew->aaonly = lookold->aaonly;
+ looknew->adflag = lookold->adflag;
+ looknew->cdflag = lookold->cdflag;
+ looknew->raflag = lookold->raflag;
+ looknew->tcflag = lookold->tcflag;
+ looknew->print_unknown_format = lookold->print_unknown_format;
+ looknew->zflag = lookold->zflag;
+ looknew->setqid = lookold->setqid;
+ looknew->qid = lookold->qid;
+ looknew->ns_search_only = lookold->ns_search_only;
+ looknew->tcp_mode = lookold->tcp_mode;
+ looknew->tcp_mode_set = lookold->tcp_mode_set;
+ looknew->tls_mode = lookold->tls_mode;
+ looknew->comments = lookold->comments;
+ looknew->stats = lookold->stats;
+ looknew->section_question = lookold->section_question;
+ looknew->section_answer = lookold->section_answer;
+ looknew->section_authority = lookold->section_authority;
+ looknew->section_additional = lookold->section_additional;
+ looknew->origin = lookold->origin;
+ looknew->retries = lookold->retries;
+ looknew->tsigctx = NULL;
+ looknew->need_search = lookold->need_search;
+ looknew->done_as_is = lookold->done_as_is;
+ looknew->rrcomments = lookold->rrcomments;
+ looknew->fuzzing = lookold->fuzzing;
+ looknew->fuzztime = lookold->fuzztime;
+
+ if (lookold->ecs_addr != NULL) {
+ size_t len = sizeof(isc_sockaddr_t);
+ looknew->ecs_addr = isc_mem_allocate(mctx, len);
+ memmove(looknew->ecs_addr, lookold->ecs_addr, len);
+ }
+
+ dns_name_copy(dns_fixedname_name(&lookold->fdomain),
+ dns_fixedname_name(&looknew->fdomain));
+
+ if (servers) {
+ if (lookold->tls_ctx_cache != NULL) {
+ isc_tlsctx_cache_detach(&looknew->tls_ctx_cache);
+ isc_tlsctx_cache_attach(lookold->tls_ctx_cache,
+ &looknew->tls_ctx_cache);
+ }
+ clone_server_list(lookold->my_server_list,
+ &looknew->my_server_list);
+ }
+
+ isc_refcount_init(&looknew->references, 1);
+
+ looknew->magic = DIG_LOOKUP_MAGIC;
+
+ return (looknew);
+}
+
+/*%
+ * Requeue a lookup for further processing, perhaps copying the server
+ * list. The new lookup structure is returned to the caller, and is
+ * queued for processing. If servers are not cloned in the requeue, they
+ * must be added before allowing the current event to complete, since the
+ * completion of the event may result in the next entry on the lookup
+ * queue getting run.
+ */
+dig_lookup_t *
+requeue_lookup(dig_lookup_t *lookold, bool servers) {
+ dig_lookup_t *looknew = NULL;
+
+ debug("requeue_lookup()");
+
+ lookup_counter++;
+ if (lookup_counter > LOOKUP_LIMIT) {
+ fatal("too many lookups");
+ }
+
+ looknew = clone_lookup(lookold, servers);
+ INSIST(looknew != NULL);
+
+ debug("before insertion, init@%p -> %p, new@%p -> %p", lookold,
+ lookold->link.next, looknew, looknew->link.next);
+ ISC_LIST_PREPEND(lookup_list, looknew, link);
+ debug("after insertion, init -> %p, new = %p, new -> %p", lookold,
+ looknew, looknew->link.next);
+ return (looknew);
+}
+
+void
+setup_text_key(void) {
+ isc_result_t result;
+ dns_name_t keyname;
+ isc_buffer_t secretbuf;
+ unsigned int secretsize;
+ unsigned char *secretstore;
+
+ debug("setup_text_key()");
+ isc_buffer_allocate(mctx, &namebuf, MXNAME);
+ dns_name_init(&keyname, NULL);
+ isc_buffer_putstr(namebuf, keynametext);
+ secretsize = (unsigned int)strlen(keysecret) * 3 / 4;
+ secretstore = isc_mem_allocate(mctx, secretsize);
+ isc_buffer_init(&secretbuf, secretstore, secretsize);
+ result = isc_base64_decodestring(keysecret, &secretbuf);
+ if (result != ISC_R_SUCCESS) {
+ goto failure;
+ }
+
+ secretsize = isc_buffer_usedlength(&secretbuf);
+
+ if (hmacname == NULL) {
+ result = DST_R_UNSUPPORTEDALG;
+ goto failure;
+ }
+
+ result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
+ if (result != ISC_R_SUCCESS) {
+ goto failure;
+ }
+
+ result = dns_tsigkey_create(&keyname, hmacname, secretstore,
+ (int)secretsize, false, NULL, 0, 0, mctx,
+ NULL, &tsigkey);
+failure:
+ if (result != ISC_R_SUCCESS) {
+ printf(";; Couldn't create key %s: %s\n", keynametext,
+ isc_result_totext(result));
+ } else {
+ dst_key_setbits(tsigkey->key, digestbits);
+ }
+
+ isc_mem_free(mctx, secretstore);
+ dns_name_invalidate(&keyname);
+ isc_buffer_free(&namebuf);
+}
+
+static isc_result_t
+parse_uint_helper(uint32_t *uip, const char *value, uint32_t max,
+ const char *desc, int base) {
+ uint32_t n;
+ isc_result_t result = isc_parse_uint32(&n, value, base);
+ if (result == ISC_R_SUCCESS && n > max) {
+ result = ISC_R_RANGE;
+ }
+ if (result != ISC_R_SUCCESS) {
+ printf("invalid %s '%s': %s\n", desc, value,
+ isc_result_totext(result));
+ return (result);
+ }
+ *uip = n;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc) {
+ return (parse_uint_helper(uip, value, max, desc, 10));
+}
+
+isc_result_t
+parse_xint(uint32_t *uip, const char *value, uint32_t max, const char *desc) {
+ return (parse_uint_helper(uip, value, max, desc, 0));
+}
+
+static uint32_t
+parse_bits(char *arg, const char *desc, uint32_t max) {
+ isc_result_t result;
+ uint32_t tmp;
+
+ result = parse_uint(&tmp, arg, max, desc);
+ if (result != ISC_R_SUCCESS) {
+ fatal("couldn't parse digest bits");
+ }
+ tmp = (tmp + 7) & ~0x7U;
+ return (tmp);
+}
+
+isc_result_t
+parse_netprefix(isc_sockaddr_t **sap, const char *value) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_sockaddr_t *sa = NULL;
+ struct in_addr in4;
+ struct in6_addr in6;
+ uint32_t prefix_length = 0xffffffff;
+ char *slash = NULL;
+ bool parsed = false;
+ bool prefix_parsed = false;
+ char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX/128")];
+
+ REQUIRE(sap != NULL && *sap == NULL);
+
+ if (strlcpy(buf, value, sizeof(buf)) >= sizeof(buf)) {
+ fatal("invalid prefix '%s'\n", value);
+ }
+
+ sa = isc_mem_allocate(mctx, sizeof(*sa));
+ memset(sa, 0, sizeof(*sa));
+
+ if (strcmp(buf, "0") == 0) {
+ sa->type.sa.sa_family = AF_UNSPEC;
+ prefix_length = 0;
+ goto done;
+ }
+
+ slash = strchr(buf, '/');
+ if (slash != NULL) {
+ *slash = '\0';
+ result = isc_parse_uint32(&prefix_length, slash + 1, 10);
+ if (result != ISC_R_SUCCESS) {
+ fatal("invalid prefix length in '%s': %s\n", value,
+ isc_result_totext(result));
+ }
+ prefix_parsed = true;
+ }
+
+ if (inet_pton(AF_INET6, buf, &in6) == 1) {
+ parsed = true;
+ isc_sockaddr_fromin6(sa, &in6, 0);
+ if (prefix_length > 128) {
+ prefix_length = 128;
+ }
+ } else if (inet_pton(AF_INET, buf, &in4) == 1) {
+ parsed = true;
+ isc_sockaddr_fromin(sa, &in4, 0);
+ if (prefix_length > 32) {
+ prefix_length = 32;
+ }
+ } else if (prefix_parsed) {
+ int i;
+
+ for (i = 0; i < 3 && strlen(buf) < sizeof(buf) - 2; i++) {
+ strlcat(buf, ".0", sizeof(buf));
+ if (inet_pton(AF_INET, buf, &in4) == 1) {
+ parsed = true;
+ isc_sockaddr_fromin(sa, &in4, 0);
+ break;
+ }
+ }
+
+ if (prefix_length > 32) {
+ prefix_length = 32;
+ }
+ }
+
+ if (!parsed) {
+ fatal("invalid address '%s'", value);
+ }
+
+done:
+ sa->length = prefix_length;
+ *sap = sa;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Parse HMAC algorithm specification
+ */
+void
+parse_hmac(const char *hmac) {
+ char buf[20];
+ size_t len;
+
+ REQUIRE(hmac != NULL);
+
+ len = strlen(hmac);
+ if (len >= sizeof(buf)) {
+ fatal("unknown key type '%.*s'", (int)len, hmac);
+ }
+ strlcpy(buf, hmac, sizeof(buf));
+
+ digestbits = 0;
+
+ if (strcasecmp(buf, "hmac-md5") == 0) {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128);
+ } else if (strcasecmp(buf, "hmac-sha1") == 0) {
+ hmacname = DNS_TSIG_HMACSHA1_NAME;
+ digestbits = 0;
+ } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
+ hmacname = DNS_TSIG_HMACSHA1_NAME;
+ digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160);
+ } else if (strcasecmp(buf, "hmac-sha224") == 0) {
+ hmacname = DNS_TSIG_HMACSHA224_NAME;
+ } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA224_NAME;
+ digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224);
+ } else if (strcasecmp(buf, "hmac-sha256") == 0) {
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+ } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+ digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256);
+ } else if (strcasecmp(buf, "hmac-sha384") == 0) {
+ hmacname = DNS_TSIG_HMACSHA384_NAME;
+ } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA384_NAME;
+ digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384);
+ } else if (strcasecmp(buf, "hmac-sha512") == 0) {
+ hmacname = DNS_TSIG_HMACSHA512_NAME;
+ } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA512_NAME;
+ digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512);
+ } else {
+ fprintf(stderr,
+ ";; Warning, ignoring "
+ "invalid TSIG algorithm %s\n",
+ buf);
+ }
+}
+
+/*
+ * Get a key from a named.conf format keyfile
+ */
+static isc_result_t
+read_confkey(void) {
+ cfg_parser_t *pctx = NULL;
+ cfg_obj_t *file = NULL;
+ const cfg_obj_t *keyobj = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ const cfg_obj_t *algorithmobj = NULL;
+ const char *keyname;
+ const char *secretstr;
+ const char *algorithm;
+ isc_result_t result;
+
+ if (!isc_file_exists(keyfile)) {
+ return (ISC_R_FILENOTFOUND);
+ }
+
+ result = cfg_parser_create(mctx, NULL, &pctx);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, &file);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ result = cfg_map_get(file, "key", &keyobj);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ (void)cfg_map_get(keyobj, "secret", &secretobj);
+ (void)cfg_map_get(keyobj, "algorithm", &algorithmobj);
+ if (secretobj == NULL || algorithmobj == NULL) {
+ fatal("key must have algorithm and secret");
+ }
+
+ keyname = cfg_obj_asstring(cfg_map_getname(keyobj));
+ secretstr = cfg_obj_asstring(secretobj);
+ algorithm = cfg_obj_asstring(algorithmobj);
+
+ strlcpy(keynametext, keyname, sizeof(keynametext));
+ strlcpy(keysecret, secretstr, sizeof(keysecret));
+ parse_hmac(algorithm);
+ setup_text_key();
+
+cleanup:
+ if (pctx != NULL) {
+ if (file != NULL) {
+ cfg_obj_destroy(pctx, &file);
+ }
+ cfg_parser_destroy(&pctx);
+ }
+
+ return (result);
+}
+
+void
+setup_file_key(void) {
+ isc_result_t result;
+ dst_key_t *dstkey = NULL;
+
+ debug("setup_file_key()");
+
+ if (sig0key != NULL) {
+ dst_key_free(&sig0key);
+ }
+
+ /* Try reading the key from a K* pair */
+ result = dst_key_fromnamedfile(
+ keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey);
+
+ /* If that didn't work, try reading it as a session.key keyfile */
+ if (result != ISC_R_SUCCESS) {
+ result = read_confkey();
+ if (result == ISC_R_SUCCESS) {
+ return;
+ }
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "Couldn't read key from %s: %s\n", keyfile,
+ isc_result_totext(result));
+ goto failure;
+ }
+
+ switch (dst_key_alg(dstkey)) {
+ case DST_ALG_HMACMD5:
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ break;
+ case DST_ALG_HMACSHA1:
+ hmacname = DNS_TSIG_HMACSHA1_NAME;
+ break;
+ case DST_ALG_HMACSHA224:
+ hmacname = DNS_TSIG_HMACSHA224_NAME;
+ break;
+ case DST_ALG_HMACSHA256:
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+ break;
+ case DST_ALG_HMACSHA384:
+ hmacname = DNS_TSIG_HMACSHA384_NAME;
+ break;
+ case DST_ALG_HMACSHA512:
+ hmacname = DNS_TSIG_HMACSHA512_NAME;
+ break;
+ }
+
+ if (hmacname != NULL) {
+ result = dns_tsigkey_createfromkey(
+ dst_key_name(dstkey), hmacname, dstkey, false, NULL, 0,
+ 0, mctx, NULL, &tsigkey);
+ if (result != ISC_R_SUCCESS) {
+ printf(";; Couldn't create key %s: %s\n", keynametext,
+ isc_result_totext(result));
+ goto failure;
+ }
+ } else {
+ dst_key_attach(dstkey, &sig0key);
+ dst_key_free(&dstkey);
+ }
+failure:
+ if (dstkey != NULL) {
+ dst_key_free(&dstkey);
+ }
+}
+
+static dig_searchlist_t *
+make_searchlist_entry(char *domain) {
+ dig_searchlist_t *search;
+ search = isc_mem_allocate(mctx, sizeof(*search));
+ strlcpy(search->origin, domain, MXNAME);
+ search->origin[MXNAME - 1] = 0;
+ ISC_LINK_INIT(search, link);
+ return (search);
+}
+
+static void
+clear_searchlist(void) {
+ dig_searchlist_t *search;
+ while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
+ ISC_LIST_UNLINK(search_list, search, link);
+ isc_mem_free(mctx, search);
+ }
+}
+
+static void
+create_search_list(irs_resconf_t *resconf) {
+ irs_resconf_searchlist_t *list;
+ irs_resconf_search_t *entry;
+ dig_searchlist_t *search;
+
+ debug("create_search_list()");
+ clear_searchlist();
+
+ list = irs_resconf_getsearchlist(resconf);
+ for (entry = ISC_LIST_HEAD(*list); entry != NULL;
+ entry = ISC_LIST_NEXT(entry, link))
+ {
+ search = make_searchlist_entry(entry->domain);
+ ISC_LIST_APPEND(search_list, search, link);
+ }
+}
+
+/*%
+ * Append 'addr' to the list of servers to be queried. This function is only
+ * called when no server addresses are explicitly specified and either libirs
+ * returns an empty list of servers to use or none of the addresses returned by
+ * libirs are usable due to the specified address family restrictions.
+ */
+static void
+add_fallback_nameserver(const char *addr) {
+ dig_server_t *server = make_server(addr, addr);
+ ISC_LINK_INIT(server, link);
+ ISC_LIST_APPEND(server_list, server, link);
+}
+
+/*%
+ * Setup the system as a whole, reading key information and resolv.conf
+ * settings.
+ */
+void
+setup_system(bool ipv4only, bool ipv6only) {
+ irs_resconf_t *resconf = NULL;
+ isc_result_t result;
+
+ debug("setup_system()");
+
+ if (ipv4only) {
+ if (have_ipv4) {
+ isc_net_disableipv6();
+ have_ipv6 = false;
+ } else {
+ fatal("can't find IPv4 networking");
+ }
+ }
+
+ if (ipv6only) {
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = false;
+ } else {
+ fatal("can't find IPv6 networking");
+ }
+ }
+
+ result = irs_resconf_load(mctx, RESOLV_CONF, &resconf);
+ if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
+ fatal("parse of %s failed", RESOLV_CONF);
+ }
+
+ create_search_list(resconf);
+ if (ndots == -1) {
+ ndots = irs_resconf_getndots(resconf);
+ debug("ndots is %d.", ndots);
+ }
+ if (timeout == 0) {
+ timeout = irs_resconf_gettimeout(resconf);
+ debug("timeout is %d.", timeout);
+ }
+ if (tries == -1) {
+ tries = irs_resconf_getattempts(resconf);
+ if (tries == 0) {
+ tries = 3;
+ }
+ debug("retries is %d.", tries);
+ }
+
+ /* If user doesn't specify server use nameservers from resolv.conf. */
+ if (ISC_LIST_EMPTY(server_list)) {
+ get_server_list(resconf);
+ }
+
+ /* If we don't find a nameserver fall back to localhost */
+ if (ISC_LIST_EMPTY(server_list)) {
+ if (have_ipv6) {
+ add_fallback_nameserver("::1");
+ }
+ if (have_ipv4) {
+ add_fallback_nameserver("127.0.0.1");
+ }
+ }
+
+ irs_resconf_destroy(&resconf);
+
+ if (keyfile[0] != 0) {
+ setup_file_key();
+ } else if (keysecret[0] != 0) {
+ setup_text_key();
+ }
+
+ isc_nonce_buf(cookie_secret, sizeof(cookie_secret));
+}
+
+/*%
+ * Override the search list derived from resolv.conf by 'domain'.
+ */
+void
+set_search_domain(char *domain) {
+ dig_searchlist_t *search;
+
+ clear_searchlist();
+ search = make_searchlist_entry(domain);
+ ISC_LIST_APPEND(search_list, search, link);
+}
+
+/*%
+ * Setup the ISC and DNS libraries for use by the system.
+ */
+void
+setup_libs(void) {
+ isc_result_t result;
+ isc_logconfig_t *logconfig = NULL;
+
+ debug("setup_libs()");
+
+ result = isc_net_probeipv4();
+ if (result == ISC_R_SUCCESS) {
+ have_ipv4 = true;
+ }
+
+ result = isc_net_probeipv6();
+ if (result == ISC_R_SUCCESS) {
+ have_ipv6 = true;
+ }
+ if (!have_ipv6 && !have_ipv4) {
+ fatal("can't find either v4 or v6 networking");
+ }
+
+ isc_mem_create(&mctx);
+ isc_mem_setname(mctx, "dig");
+
+ isc_log_create(mctx, &lctx, &logconfig);
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
+ check_result(result, "isc_log_usechannel");
+
+ isc_log_setdebuglevel(lctx, 0);
+
+ isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr, NULL);
+
+ result = isc_task_create(taskmgr, 0, &global_task);
+ check_result(result, "isc_task_create");
+ isc_task_setname(global_task, "dig", NULL);
+
+ result = dst_lib_init(mctx, NULL);
+ check_result(result, "dst_lib_init");
+ is_dst_up = true;
+
+ isc_mutex_init(&lookup_lock);
+}
+
+typedef struct dig_ednsoptname {
+ uint32_t code;
+ const char *name;
+} dig_ednsoptname_t;
+
+dig_ednsoptname_t optnames[] = {
+ { 1, "LLQ" }, /* draft-sekar-dns-llq */
+ { 3, "NSID" }, /* RFC 5001 */
+ { 5, "DAU" }, /* RFC 6975 */
+ { 6, "DHU" }, /* RFC 6975 */
+ { 7, "N3U" }, /* RFC 6975 */
+ { 8, "ECS" }, /* RFC 7871 */
+ { 9, "EXPIRE" }, /* RFC 7314 */
+ { 10, "COOKIE" }, /* RFC 7873 */
+ { 11, "KEEPALIVE" }, /* RFC 7828 */
+ { 12, "PADDING" }, /* RFC 7830 */
+ { 12, "PAD" }, /* shorthand */
+ { 13, "CHAIN" }, /* RFC 7901 */
+ { 14, "KEY-TAG" }, /* RFC 8145 */
+ { 15, "EDE" }, /* ietf-dnsop-extended-error-16 */
+ { 16, "CLIENT-TAG" }, /* draft-bellis-dnsop-edns-tags */
+ { 17, "SERVER-TAG" }, /* draft-bellis-dnsop-edns-tags */
+ { 26946, "DEVICEID" }, /* Brian Hartvigsen */
+};
+
+#define N_EDNS_OPTNAMES (sizeof(optnames) / sizeof(optnames[0]))
+
+void
+save_opt(dig_lookup_t *lookup, char *code, char *value) {
+ isc_result_t result;
+ uint32_t num = 0;
+ isc_buffer_t b;
+ bool found = false;
+ unsigned int i;
+
+ if (lookup->ednsoptscnt >= EDNSOPT_OPTIONS) {
+ fatal("too many ednsopts");
+ }
+
+ for (i = 0; i < N_EDNS_OPTNAMES; i++) {
+ if (strcasecmp(code, optnames[i].name) == 0) {
+ num = optnames[i].code;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ result = parse_uint(&num, code, 65535, "ednsopt");
+ if (result != ISC_R_SUCCESS) {
+ fatal("bad edns code point: %s", code);
+ }
+ }
+
+ if (lookup->ednsopts == NULL) {
+ cloneopts(lookup, NULL);
+ }
+ INSIST(lookup->ednsopts != NULL);
+
+ if (lookup->ednsopts[lookup->ednsoptscnt].value != NULL) {
+ isc_mem_free(mctx, lookup->ednsopts[lookup->ednsoptscnt].value);
+ }
+
+ lookup->ednsopts[lookup->ednsoptscnt].code = num;
+ lookup->ednsopts[lookup->ednsoptscnt].length = 0;
+ lookup->ednsopts[lookup->ednsoptscnt].value = NULL;
+
+ if (value != NULL) {
+ char *buf;
+ buf = isc_mem_allocate(mctx, strlen(value) / 2 + 1);
+ isc_buffer_init(&b, buf, (unsigned int)strlen(value) / 2 + 1);
+ result = isc_hex_decodestring(value, &b);
+ check_result(result, "isc_hex_decodestring");
+ lookup->ednsopts[lookup->ednsoptscnt].value =
+ isc_buffer_base(&b);
+ lookup->ednsopts[lookup->ednsoptscnt].length =
+ isc_buffer_usedlength(&b);
+ }
+
+ lookup->ednsoptscnt++;
+}
+
+/*%
+ * Add EDNS0 option record to a message. Currently, the only supported
+ * options are UDP buffer size, the DO bit, and EDNS options
+ * (e.g., NSID, COOKIE, client-subnet)
+ */
+static void
+add_opt(dns_message_t *msg, uint16_t udpsize, uint16_t edns, unsigned int flags,
+ dns_ednsopt_t *opts, size_t count) {
+ dns_rdataset_t *rdataset = NULL;
+ isc_result_t result;
+
+ debug("add_opt()");
+ result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
+ opts, count);
+ check_result(result, "dns_message_buildopt");
+ result = dns_message_setopt(msg, rdataset);
+ check_result(result, "dns_message_setopt");
+}
+
+/*%
+ * Add a question section to a message, asking for the specified name,
+ * type, and class.
+ */
+static void
+add_question(dns_message_t *message, dns_name_t *name, dns_rdataclass_t rdclass,
+ dns_rdatatype_t rdtype) {
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+
+ debug("add_question()");
+ rdataset = NULL;
+ result = dns_message_gettemprdataset(message, &rdataset);
+ check_result(result, "dns_message_gettemprdataset()");
+ dns_rdataset_makequestion(rdataset, rdclass, rdtype);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+}
+
+/*%
+ * Check if we're done with all the queued lookups, which is true iff
+ * all sockets, sends, and recvs are accounted for (counters == 0),
+ * and the lookup list is empty.
+ * If we are done, pass control back out to dighost_shutdown() (which is
+ * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
+ * a whole or reseed the lookup list.
+ */
+static void
+check_if_done(void) {
+ dig_lookup_t *lookup = NULL;
+
+ debug("check_if_done()");
+ debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
+
+ lookup = ISC_LIST_HEAD(lookup_list);
+ while (lookup != NULL) {
+ dig_lookup_t *next = NULL;
+ debug("pending lookup %p", lookup);
+ next = ISC_LIST_NEXT(lookup, link);
+ lookup = next;
+ }
+
+ if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
+ isc_refcount_current(&sendcount) == 0)
+ {
+ INSIST(isc_refcount_current(&recvcount) == 0);
+ debug("shutting down");
+ dighost_shutdown();
+ }
+}
+
+/*%
+ * Check if we're done with all the queries in the lookup, except for
+ * the `except_q` query (can be NULL if no exception is required).
+ * Expects `l` to be a valid and locked lookup.
+ */
+static bool
+check_if_queries_done(dig_lookup_t *l, dig_query_t *except_q) {
+ dig_query_t *q = ISC_LIST_HEAD(l->q);
+
+ debug("check_if_queries_done(%p)", l);
+
+ while (q != NULL) {
+ if (!q->started || isc_refcount_current(&q->references) > 1) {
+ if (!q->canceled && q != except_q) {
+ debug("there is a pending query %p", q);
+ return (false);
+ }
+ }
+ q = ISC_LIST_NEXT(q, link);
+ }
+
+ return (true);
+}
+
+static void
+_destroy_lookup(dig_lookup_t *lookup) {
+ dig_server_t *s;
+ void *ptr;
+
+ REQUIRE(lookup != NULL);
+ REQUIRE(ISC_LIST_EMPTY(lookup->q));
+
+ debug("destroy_lookup");
+
+ isc_refcount_destroy(&lookup->references);
+
+ s = ISC_LIST_HEAD(lookup->my_server_list);
+ while (s != NULL) {
+ debug("freeing server %p belonging to %p", s, lookup);
+ ptr = s;
+ s = ISC_LIST_NEXT(s, link);
+ ISC_LIST_DEQUEUE(lookup->my_server_list, (dig_server_t *)ptr,
+ link);
+ isc_mem_free(mctx, ptr);
+ }
+ if (lookup->sendmsg != NULL) {
+ dns_message_detach(&lookup->sendmsg);
+ }
+ if (lookup->querysig != NULL) {
+ debug("freeing buffer %p", lookup->querysig);
+ isc_buffer_free(&lookup->querysig);
+ }
+ if (lookup->sendspace != NULL) {
+ isc_mem_put(mctx, lookup->sendspace, COMMSIZE);
+ }
+
+ if (lookup->tsigctx != NULL) {
+ dst_context_destroy(&lookup->tsigctx);
+ }
+
+ if (lookup->ecs_addr != NULL) {
+ isc_mem_free(mctx, lookup->ecs_addr);
+ }
+
+ if (lookup->ednsopts != NULL) {
+ size_t i;
+ for (i = 0; i < EDNSOPT_OPTIONS; i++) {
+ if (lookup->ednsopts[i].value != NULL) {
+ isc_mem_free(mctx, lookup->ednsopts[i].value);
+ }
+ }
+ isc_mem_free(mctx, lookup->ednsopts);
+ }
+
+ if (lookup->https_path) {
+ isc_mem_free(mctx, lookup->https_path);
+ }
+
+ if (lookup->tls_ctx_cache != NULL) {
+ isc_tlsctx_cache_detach(&lookup->tls_ctx_cache);
+ }
+
+ if (lookup->tls_ca_file != NULL) {
+ isc_mem_free(mctx, lookup->tls_ca_file);
+ }
+
+ if (lookup->tls_hostname != NULL) {
+ isc_mem_free(mctx, lookup->tls_hostname);
+ }
+
+ if (lookup->tls_key_file != NULL) {
+ isc_mem_free(mctx, lookup->tls_key_file);
+ }
+
+ if (lookup->tls_cert_file != NULL) {
+ isc_mem_free(mctx, lookup->tls_cert_file);
+ }
+
+ isc_mem_free(mctx, lookup);
+}
+
+#define lookup_attach(s, t) _lookup_attach(s, t, __FILE__, __LINE__)
+static void
+_lookup_attach(dig_lookup_t *lookup, dig_lookup_t **lookupp, const char *file,
+ unsigned int line) {
+ REQUIRE(DIG_VALID_LOOKUP(lookup));
+ REQUIRE(lookupp != NULL && *lookupp == NULL);
+
+ debug("%s:%u:lookup_attach(%p) = %" PRIuFAST32, file, line, lookup,
+ isc_refcount_current(&lookup->references) + 1);
+
+ (void)isc_refcount_increment(&lookup->references);
+
+ *lookupp = lookup;
+}
+
+#define lookup_detach(l) _lookup_detach(l, __FILE__, __LINE__)
+static void
+_lookup_detach(dig_lookup_t **lookupp, const char *file, unsigned int line) {
+ REQUIRE(DIG_VALID_LOOKUP(*lookupp));
+
+ dig_lookup_t *lookup = *lookupp;
+ *lookupp = NULL;
+
+ debug("%s:%u:lookup_detach(%p) = %" PRIuFAST32, file, line, lookup,
+ isc_refcount_current(&lookup->references) - 1);
+
+ if (isc_refcount_decrement(&lookup->references) == 1) {
+ _destroy_lookup(lookup);
+ if (lookup == current_lookup) {
+ current_lookup = NULL;
+ start_lookup();
+ }
+ }
+}
+
+void
+destroy_lookup(dig_lookup_t *lookup) {
+ REQUIRE(DIG_VALID_LOOKUP(lookup));
+
+ REQUIRE(isc_refcount_decrement(&lookup->references) == 1);
+ _destroy_lookup(lookup);
+}
+
+/*%
+ * Destroy a query when we're done with it. WARNING: This routine
+ * WILL invalidate the query pointer.
+ */
+static void
+destroy_query(dig_query_t *query, const char *file, unsigned int line) {
+ debug("%s:%u:destroy_query(%p) = %" PRIuFAST32, file, line, query,
+ isc_refcount_current(&query->references));
+
+ isc_refcount_destroy(&query->references);
+
+ lookup_detach(&query->lookup);
+
+ INSIST(query->recvspace != NULL);
+
+ isc_mem_put(mctx, query->recvspace, COMMSIZE);
+ isc_mem_put(mctx, query->tmpsendspace, COMMSIZE);
+
+ query->magic = 0;
+ isc_mem_free(mctx, query);
+}
+
+#define query_attach(s, t) _query_attach(s, t, __FILE__, __LINE__)
+
+static void
+_query_attach(dig_query_t *source, dig_query_t **targetp, const char *file,
+ unsigned int line) {
+ REQUIRE(DIG_VALID_QUERY(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ debug("%s:%u:query_attach(%p) = %" PRIuFAST32, file, line, source,
+ isc_refcount_current(&source->references) + 1);
+
+ (void)isc_refcount_increment(&source->references);
+
+ *targetp = source;
+}
+
+#define query_detach(q) _query_detach(q, __FILE__, __LINE__)
+
+static void
+_query_detach(dig_query_t **queryp, const char *file, unsigned int line) {
+ dig_query_t *query = NULL;
+ dig_lookup_t *lookup = NULL;
+
+ REQUIRE(DIG_VALID_QUERY(*queryp));
+
+ query = *queryp;
+ *queryp = NULL;
+
+ lookup = query->lookup;
+
+ if (lookup->current_query == query) {
+ query_detach(&lookup->current_query);
+ }
+
+ debug("%s:%u:query_detach(%p) = %" PRIuFAST32, file, line, query,
+ isc_refcount_current(&query->references) - 1);
+
+ if (isc_refcount_decrement(&query->references) == 1) {
+ INSIST(query->readhandle == NULL);
+ INSIST(query->sendhandle == NULL);
+
+ if (ISC_LINK_LINKED(query, link)) {
+ ISC_LIST_UNLINK(lookup->q, query, link);
+ }
+ destroy_query(query, file, line);
+ }
+}
+
+/*%
+ * If we can, start the next lookup in the queue running.
+ * This assumes that the lookup on the head of the queue hasn't been
+ * started yet. It also removes the lookup from the head of the queue,
+ * setting the current_lookup pointer pointing to it.
+ */
+void
+start_lookup(void) {
+ debug("start_lookup()");
+
+ if (atomic_load(&cancel_now)) {
+ return;
+ }
+
+ /*
+ * If there's a current lookup running, we really shouldn't get
+ * here.
+ */
+ INSIST(current_lookup == NULL);
+
+ current_lookup = ISC_LIST_HEAD(lookup_list);
+
+ /*
+ * Put the current lookup somewhere so cancel_all can find it
+ */
+ if (current_lookup != NULL) {
+ /*
+ * Formally, we should attach the lookup to the current_lookup
+ * and detach it from the lookup_list, but it would be one
+ * attach and one detach.
+ */
+ ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
+ if (setup_lookup(current_lookup)) {
+ do_lookup(current_lookup);
+ } else if (next_origin(current_lookup)) {
+ lookup_detach(&current_lookup);
+ start_lookup();
+ }
+ } else {
+ check_if_done();
+ }
+}
+
+/*%
+ * If we can, clear the current lookup and start the next one running.
+ * (Note that while the reference count of current_lookup may be
+ * decremented, current_lookup will not be set to NULL.)
+ */
+static void
+clear_current_lookup(void) {
+ dig_lookup_t *lookup = current_lookup;
+
+ INSIST(!free_now);
+
+ debug("clear_current_lookup()");
+
+ if (lookup == NULL) {
+ debug("current_lookup is already detached");
+ return;
+ }
+
+ if (lookup->cleared) {
+ debug("current_lookup is already cleared");
+ return;
+ }
+
+ if (ISC_LIST_HEAD(lookup->q) != NULL) {
+ debug("still have a worker");
+ return;
+ }
+
+ lookup->cleared = true;
+ debug("lookup cleared");
+
+ lookup_detach(&lookup);
+}
+
+/*%
+ * Create and queue a new lookup as a followup to the current lookup,
+ * based on the supplied message and section. This is used in trace and
+ * name server search modes to start a new lookup using servers from
+ * NS records in a reply. Returns the number of followup lookups made.
+ */
+static int
+followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section) {
+ dig_lookup_t *lookup = NULL;
+ dig_server_t *srv = NULL;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_name_t *name = NULL;
+ isc_result_t result;
+ bool success = false;
+ int numLookups = 0;
+ int num;
+ isc_result_t lresult, addresses_result;
+ char bad_namestr[DNS_NAME_FORMATSIZE];
+ dns_name_t *domain;
+ bool horizontal = false, bad = false;
+
+ INSIST(!free_now);
+
+ debug("following up %s", query->lookup->textname);
+
+ addresses_result = ISC_R_SUCCESS;
+ bad_namestr[0] = '\0';
+ for (result = dns_message_firstname(msg, section);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(msg, section))
+ {
+ name = NULL;
+ dns_message_currentname(msg, section, &name);
+
+ if (section == DNS_SECTION_AUTHORITY) {
+ rdataset = NULL;
+ result = dns_message_findtype(name, dns_rdatatype_soa,
+ 0, &rdataset);
+ if (result == ISC_R_SUCCESS) {
+ return (0);
+ }
+ }
+ rdataset = NULL;
+ result = dns_message_findtype(name, dns_rdatatype_ns, 0,
+ &rdataset);
+ if (result != ISC_R_SUCCESS) {
+ continue;
+ }
+
+ debug("found NS set");
+
+ if (query->lookup->trace && !query->lookup->trace_root) {
+ dns_namereln_t namereln;
+ unsigned int nlabels;
+ int order;
+
+ domain = dns_fixedname_name(&query->lookup->fdomain);
+ namereln = dns_name_fullcompare(name, domain, &order,
+ &nlabels);
+ if (namereln == dns_namereln_equal) {
+ if (!horizontal) {
+ dighost_warning("BAD (HORIZONTAL) "
+ "REFERRAL");
+ }
+ horizontal = true;
+ } else if (namereln != dns_namereln_subdomain) {
+ if (!bad) {
+ dighost_warning("BAD REFERRAL");
+ }
+ bad = true;
+ continue;
+ }
+ }
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_rdata_ns_t ns;
+
+ if (query->lookup->trace_root &&
+ query->lookup->nsfound >= MXSERV)
+ {
+ break;
+ }
+
+ dns_rdataset_current(rdataset, &rdata);
+
+ query->lookup->nsfound++;
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ dns_name_format(&ns.name, namestr, sizeof(namestr));
+ dns_rdata_freestruct(&ns);
+
+ /* Initialize lookup if we've not yet */
+ debug("found NS %s", namestr);
+ if (!success) {
+ success = true;
+ lookup_counter++;
+ lookup = requeue_lookup(query->lookup, false);
+ cancel_lookup(query->lookup);
+ lookup->doing_xfr = false;
+ if (!lookup->trace_root &&
+ section == DNS_SECTION_ANSWER)
+ {
+ lookup->trace = false;
+ } else {
+ lookup->trace = query->lookup->trace;
+ }
+ lookup->ns_search_only =
+ query->lookup->ns_search_only;
+ lookup->trace_root = false;
+ if (lookup->ns_search_only) {
+ lookup->recurse = false;
+ }
+ domain = dns_fixedname_name(&lookup->fdomain);
+ dns_name_copy(name, domain);
+ }
+ debug("adding server %s", namestr);
+ num = getaddresses(lookup, namestr, &lresult);
+ if (lresult != ISC_R_SUCCESS) {
+ printf("couldn't get address for '%s': %s\n",
+ namestr, isc_result_totext(lresult));
+ if (addresses_result == ISC_R_SUCCESS) {
+ addresses_result = lresult;
+ strlcpy(bad_namestr, namestr,
+ sizeof(bad_namestr));
+ }
+ }
+ numLookups += num;
+ dns_rdata_reset(&rdata);
+ }
+ }
+ if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
+ fatal("couldn't get address for '%s': %s", bad_namestr,
+ isc_result_totext(result));
+ }
+
+ if (lookup == NULL && section == DNS_SECTION_ANSWER &&
+ (query->lookup->trace || query->lookup->ns_search_only))
+ {
+ return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
+ }
+
+ /*
+ * Randomize the order the nameserver will be tried.
+ */
+ if (numLookups > 1) {
+ uint32_t i, j;
+ dig_serverlist_t my_server_list;
+ dig_server_t *next;
+
+ ISC_LIST_INIT(my_server_list);
+
+ i = numLookups;
+ for (srv = ISC_LIST_HEAD(lookup->my_server_list); srv != NULL;
+ srv = ISC_LIST_HEAD(lookup->my_server_list))
+ {
+ INSIST(i > 0);
+ j = isc_random_uniform(i);
+ next = ISC_LIST_NEXT(srv, link);
+ while (j-- > 0 && next != NULL) {
+ srv = next;
+ next = ISC_LIST_NEXT(srv, link);
+ }
+ ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
+ ISC_LIST_APPEND(my_server_list, srv, link);
+ i--;
+ }
+ ISC_LIST_APPENDLIST(lookup->my_server_list, my_server_list,
+ link);
+ }
+
+ return (numLookups);
+}
+
+/*%
+ * Create and queue a new lookup using the next origin from the search
+ * list, read in setup_system().
+ *
+ * Return true iff there was another searchlist entry.
+ */
+static bool
+next_origin(dig_lookup_t *oldlookup) {
+ dig_lookup_t *newlookup;
+ dig_searchlist_t *search;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_result_t result;
+
+ INSIST(!free_now);
+
+ debug("next_origin()");
+ debug("following up %s", oldlookup->textname);
+
+ if (!usesearch) {
+ /*
+ * We're not using a search list, so don't even think
+ * about finding the next entry.
+ */
+ return (false);
+ }
+
+ /*
+ * Check for a absolute name or ndots being met.
+ */
+ name = dns_fixedname_initname(&fixed);
+ result = dns_name_fromstring2(name, oldlookup->textname, NULL, 0, NULL);
+ if (result == ISC_R_SUCCESS &&
+ (dns_name_isabsolute(name) ||
+ (int)dns_name_countlabels(name) > ndots))
+ {
+ return (false);
+ }
+
+ if (oldlookup->origin == NULL && !oldlookup->need_search) {
+ /*
+ * Then we just did rootorg; there's nothing left.
+ */
+ return (false);
+ }
+ if (oldlookup->origin == NULL && oldlookup->need_search) {
+ newlookup = requeue_lookup(oldlookup, true);
+ newlookup->origin = ISC_LIST_HEAD(search_list);
+ newlookup->need_search = false;
+ } else {
+ search = ISC_LIST_NEXT(oldlookup->origin, link);
+ if (search == NULL && oldlookup->done_as_is) {
+ return (false);
+ }
+ newlookup = requeue_lookup(oldlookup, true);
+ newlookup->origin = search;
+ }
+ cancel_lookup(oldlookup);
+ return (true);
+}
+
+/*%
+ * Insert an SOA record into the sendmessage in a lookup. Used for
+ * creating IXFR queries.
+ */
+static void
+insert_soa(dig_lookup_t *lookup) {
+ isc_result_t result;
+ dns_rdata_soa_t soa;
+ dns_rdata_t *rdata = NULL;
+ dns_rdatalist_t *rdatalist = NULL;
+ dns_rdataset_t *rdataset = NULL;
+ dns_name_t *soaname = NULL;
+
+ debug("insert_soa()");
+ soa.mctx = mctx;
+ soa.serial = lookup->ixfr_serial;
+ soa.refresh = 0;
+ soa.retry = 0;
+ soa.expire = 0;
+ soa.minimum = 0;
+ soa.common.rdclass = lookup->rdclass;
+ soa.common.rdtype = dns_rdatatype_soa;
+
+ dns_name_init(&soa.origin, NULL);
+ dns_name_init(&soa.contact, NULL);
+
+ dns_name_clone(dns_rootname, &soa.origin);
+ dns_name_clone(dns_rootname, &soa.contact);
+
+ isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
+ sizeof(lookup->rdatastore));
+
+ result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
+ check_result(result, "dns_message_gettemprdata");
+
+ result = dns_rdata_fromstruct(rdata, lookup->rdclass, dns_rdatatype_soa,
+ &soa, &lookup->rdatabuf);
+ check_result(result, "isc_rdata_fromstruct");
+
+ result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
+ check_result(result, "dns_message_gettemprdatalist");
+
+ result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+
+ dns_rdatalist_init(rdatalist);
+ rdatalist->type = dns_rdatatype_soa;
+ rdatalist->rdclass = lookup->rdclass;
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+
+ result = dns_message_gettempname(lookup->sendmsg, &soaname);
+ check_result(result, "dns_message_gettempname");
+ dns_name_clone(lookup->name, soaname);
+ ISC_LIST_INIT(soaname->list);
+ ISC_LIST_APPEND(soaname->list, rdataset, link);
+ dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
+}
+
+static void
+compute_cookie(unsigned char *clientcookie, size_t len) {
+ /* XXXMPA need to fix, should be per server. */
+ INSIST(len >= 8U);
+ memmove(clientcookie, cookie_secret, 8);
+}
+
+#define new_query(l, s, u) _new_query(l, s, u, __FILE__, __LINE__)
+
+static dig_query_t *
+_new_query(dig_lookup_t *lookup, char *servname, char *userarg,
+ const char *file, unsigned int line) {
+ dig_query_t *query = NULL;
+
+ query = isc_mem_allocate(mctx, sizeof(dig_query_t));
+ debug("create query %p linked to lookup %p", query, lookup);
+ *query = (dig_query_t){ .sendbuf = lookup->renderbuf,
+ .servname = servname,
+ .userarg = userarg,
+ .warn_id = true,
+ .recvspace = isc_mem_get(mctx, COMMSIZE),
+ .tmpsendspace = isc_mem_get(mctx, COMMSIZE) };
+
+ lookup_attach(lookup, &query->lookup);
+
+ isc_refcount_init(&query->references, 1);
+
+ debug("%s:%u:new_query(%p) = %" PRIuFAST32, file, line, query,
+ isc_refcount_current(&query->references));
+
+ if (query->recvspace == NULL) {
+ fatal("memory allocation failure");
+ }
+ if (query->tmpsendspace == NULL) {
+ fatal("memory allocation failure");
+ }
+
+ isc_time_settoepoch(&query->time_sent);
+ isc_time_settoepoch(&query->time_recv);
+
+ ISC_LINK_INIT(query, clink);
+ ISC_LINK_INIT(query, link);
+
+ query->magic = DIG_QUERY_MAGIC;
+ return (query);
+}
+
+/*%
+ * Setup the supplied lookup structure, making it ready to start sending
+ * queries to servers. Create and initialize the message to be sent as
+ * well as the query structures and buffer space for the replies. If the
+ * server list is empty, clone it from the system default list.
+ */
+bool
+setup_lookup(dig_lookup_t *lookup) {
+ isc_result_t result;
+ unsigned int len;
+ dig_server_t *serv;
+ dig_query_t *query;
+ isc_buffer_t b;
+ dns_compress_t cctx;
+ char store[MXNAME];
+ char ecsbuf[20];
+ char cookiebuf[256];
+ char *origin = NULL;
+ char *textname = NULL;
+
+ REQUIRE(lookup != NULL);
+
+#ifdef HAVE_LIBIDN2
+ char idn_origin[MXNAME], idn_textname[MXNAME];
+#endif /* HAVE_LIBIDN2 */
+
+ INSIST(!free_now);
+
+ debug("setup_lookup(%p)", lookup);
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &lookup->sendmsg);
+
+ if (lookup->new_search) {
+ debug("resetting lookup counter.");
+ lookup_counter = 0;
+ }
+
+ if (ISC_LIST_EMPTY(lookup->my_server_list)) {
+ debug("cloning server list");
+ clone_server_list(server_list, &lookup->my_server_list);
+ }
+ result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
+ check_result(result, "dns_message_gettempname");
+
+ isc_buffer_init(&lookup->namebuf, lookup->name_space,
+ sizeof(lookup->name_space));
+ isc_buffer_init(&lookup->onamebuf, lookup->oname_space,
+ sizeof(lookup->oname_space));
+
+ /*
+ * We cannot convert `textname' and `origin' separately.
+ * `textname' doesn't contain TLD, but local mapping needs
+ * TLD.
+ */
+ textname = lookup->textname;
+#ifdef HAVE_LIBIDN2
+ if (lookup->idnin) {
+ idn_locale_to_ace(textname, idn_textname, sizeof(idn_textname));
+ debug("idn_textname: %s", idn_textname);
+ textname = idn_textname;
+ }
+#endif /* HAVE_LIBIDN2 */
+
+ /*
+ * If the name has too many dots, force the origin to be NULL
+ * (which produces an absolute lookup). Otherwise, take the origin
+ * we have if there's one in the struct already. If it's NULL,
+ * take the first entry in the searchlist iff either usesearch
+ * is TRUE or we got a domain line in the resolv.conf file.
+ */
+ if (lookup->new_search) {
+ if ((count_dots(textname) >= ndots) || !usesearch) {
+ lookup->origin = NULL; /* Force abs lookup */
+ lookup->done_as_is = true;
+ lookup->need_search = usesearch;
+ } else if (lookup->origin == NULL && usesearch) {
+ lookup->origin = ISC_LIST_HEAD(search_list);
+ lookup->need_search = false;
+ }
+ }
+
+ if (lookup->origin != NULL) {
+ debug("trying origin %s", lookup->origin->origin);
+ result = dns_message_gettempname(lookup->sendmsg,
+ &lookup->oname);
+ check_result(result, "dns_message_gettempname");
+ /* XXX Helper funct to conv char* to name? */
+ origin = lookup->origin->origin;
+#ifdef HAVE_LIBIDN2
+ if (lookup->idnin) {
+ idn_locale_to_ace(origin, idn_origin,
+ sizeof(idn_origin));
+ debug("trying idn origin %s", idn_origin);
+ origin = idn_origin;
+ }
+#endif /* HAVE_LIBIDN2 */
+ len = (unsigned int)strlen(origin);
+ isc_buffer_init(&b, origin, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(lookup->oname, &b, dns_rootname, 0,
+ &lookup->onamebuf);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg, &lookup->name);
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->oname);
+ fatal("'%s' is not in legal name syntax (%s)", origin,
+ isc_result_totext(result));
+ }
+ if (lookup->trace && lookup->trace_root) {
+ dns_name_clone(dns_rootname, lookup->name);
+ } else {
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+
+ name = dns_fixedname_initname(&fixed);
+ len = (unsigned int)strlen(textname);
+ isc_buffer_init(&b, textname, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(name, &b, NULL, 0, NULL);
+ if (result == ISC_R_SUCCESS) {
+ if (!dns_name_isabsolute(name)) {
+ result = dns_name_concatenate(
+ name, lookup->oname,
+ lookup->name, &lookup->namebuf);
+ } else {
+ dns_name_copy(name, lookup->name);
+ }
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->name);
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->oname);
+ if (result == DNS_R_NAMETOOLONG) {
+ return (false);
+ }
+ fatal("'%s' is not in legal name syntax (%s)",
+ lookup->textname,
+ isc_result_totext(result));
+ }
+ }
+ dns_message_puttempname(lookup->sendmsg, &lookup->oname);
+ } else {
+ debug("using root origin");
+ if (lookup->trace && lookup->trace_root) {
+ dns_name_clone(dns_rootname, lookup->name);
+ } else {
+ len = (unsigned int)strlen(textname);
+ isc_buffer_init(&b, textname, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(lookup->name, &b,
+ dns_rootname, 0,
+ &lookup->namebuf);
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg, &lookup->name);
+ warn("'%s' is not a legal name "
+ "(%s)",
+ lookup->textname, isc_result_totext(result));
+#if TARGET_OS_IPHONE
+ clear_current_lookup();
+ return (false);
+#else /* if TARGET_OS_IPHONE */
+ cleanup_openssl_refs();
+ digexit();
+#endif /* if TARGET_OS_IPHONE */
+ }
+ }
+ dns_name_format(lookup->name, store, sizeof(store));
+ dighost_trying(store, lookup);
+ INSIST(dns_name_isabsolute(lookup->name));
+
+ lookup->sendmsg->id = (dns_messageid_t)isc_random16();
+ lookup->sendmsg->opcode = lookup->opcode;
+ lookup->msgcounter = 0;
+
+ /*
+ * If this is a trace request, completely disallow recursion after
+ * looking up the root name servers, since it's meaningless for traces.
+ */
+ if ((lookup->trace || lookup->ns_search_only) && !lookup->trace_root) {
+ lookup->recurse = false;
+ }
+
+ if (lookup->recurse && lookup->rdtype != dns_rdatatype_axfr &&
+ lookup->rdtype != dns_rdatatype_ixfr)
+ {
+ debug("recursive query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
+ }
+
+ /* XXX aaflag */
+ if (lookup->aaonly) {
+ debug("AA query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
+ }
+
+ if (lookup->adflag) {
+ debug("AD query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
+ }
+
+ if (lookup->cdflag) {
+ debug("CD query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
+ }
+
+ if (lookup->raflag) {
+ debug("RA query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RA;
+ }
+
+ if (lookup->tcflag) {
+ debug("TC query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_TC;
+ }
+
+ if (lookup->zflag) {
+ debug("Z query");
+ lookup->sendmsg->flags |= 0x0040U;
+ }
+
+ if (lookup->setqid) {
+ debug("set QID");
+ lookup->sendmsg->id = lookup->qid;
+ }
+
+ dns_message_addname(lookup->sendmsg, lookup->name,
+ DNS_SECTION_QUESTION);
+
+ if (lookup->trace && lookup->trace_root) {
+ lookup->qrdtype = lookup->rdtype;
+ lookup->rdtype = dns_rdatatype_ns;
+ }
+
+ if ((lookup->rdtype == dns_rdatatype_axfr) ||
+ (lookup->rdtype == dns_rdatatype_ixfr))
+ {
+ /*
+ * Force TCP mode if we're doing an axfr.
+ */
+ if (lookup->rdtype == dns_rdatatype_axfr) {
+ lookup->doing_xfr = true;
+ lookup->tcp_mode = true;
+ } else if (lookup->tcp_mode) {
+ lookup->doing_xfr = true;
+ }
+ }
+
+ if (!lookup->header_only) {
+ add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
+ lookup->rdtype);
+ }
+
+ /* add_soa */
+ if (lookup->rdtype == dns_rdatatype_ixfr) {
+ insert_soa(lookup);
+ }
+
+ /* XXX Insist this? */
+ lookup->tsigctx = NULL;
+ lookup->querysig = NULL;
+ if (tsigkey != NULL) {
+ debug("initializing keys");
+ result = dns_message_settsigkey(lookup->sendmsg, tsigkey);
+ check_result(result, "dns_message_settsigkey");
+ } else if (sig0key != NULL) {
+ debug("initializing keys");
+ result = dns_message_setsig0key(lookup->sendmsg, sig0key);
+ check_result(result, "dns_message_setsig0key");
+ }
+
+ if (lookup->fuzzing) {
+ lookup->sendmsg->fuzzing = true;
+ lookup->sendmsg->fuzztime = lookup->fuzztime;
+ }
+
+ lookup->sendspace = isc_mem_get(mctx, COMMSIZE);
+
+ result = dns_compress_init(&cctx, -1, mctx);
+ check_result(result, "dns_compress_init");
+
+ debug("starting to render the message");
+ isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
+ result = dns_message_renderbegin(lookup->sendmsg, &cctx,
+ &lookup->renderbuf);
+ check_result(result, "dns_message_renderbegin");
+ if (lookup->udpsize > -1 || lookup->dnssec || lookup->edns > -1 ||
+ lookup->ecs_addr != NULL)
+ {
+#define MAXOPTS (EDNSOPT_OPTIONS + DNS_EDNSOPTIONS)
+ dns_ednsopt_t opts[MAXOPTS];
+ unsigned int flags;
+ unsigned int i = 0;
+
+ /*
+ * There can't be more than MAXOPTS options to send:
+ * a maximum of EDNSOPT_OPTIONS set by +ednsopt
+ * and DNS_EDNSOPTIONS set by other arguments
+ * (+nsid, +cookie, etc).
+ */
+ if (lookup->udpsize < 0) {
+ lookup->udpsize = DEFAULT_EDNS_BUFSIZE;
+ }
+ if (lookup->edns < 0) {
+ lookup->edns = DEFAULT_EDNS_VERSION;
+ }
+
+ if (lookup->nsid) {
+ INSIST(i < MAXOPTS);
+ opts[i].code = DNS_OPT_NSID;
+ opts[i].length = 0;
+ opts[i].value = NULL;
+ i++;
+ }
+
+ if (lookup->ecs_addr != NULL) {
+ uint8_t addr[16];
+ uint16_t family = 0;
+ uint32_t plen;
+ struct sockaddr *sa;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ size_t addrl;
+
+ sa = &lookup->ecs_addr->type.sa;
+ plen = lookup->ecs_addr->length;
+
+ /* Round up prefix len to a multiple of 8 */
+ addrl = (plen + 7) / 8;
+
+ INSIST(i < MAXOPTS);
+ opts[i].code = DNS_OPT_CLIENT_SUBNET;
+ opts[i].length = (uint16_t)addrl + 4;
+ check_result(result, "isc_buffer_allocate");
+
+ /*
+ * XXXMUKS: According to RFC7871, "If there is
+ * no ADDRESS set, i.e., SOURCE PREFIX-LENGTH is
+ * set to 0, then FAMILY SHOULD be set to the
+ * transport over which the query is sent."
+ *
+ * However, at this point we don't know what
+ * transport(s) we'll be using, so we can't
+ * set the value now. For now, we're using
+ * IPv4 as the default the +subnet option
+ * used an IPv4 prefix, or for +subnet=0,
+ * and IPv6 if the +subnet option used an
+ * IPv6 prefix.
+ *
+ * (For future work: preserve the offset into
+ * the buffer where the family field is;
+ * that way we can update it in start_udp()
+ * or start_tcp() once we know
+ * what it outght to be.)
+ */
+ switch (sa->sa_family) {
+ case AF_UNSPEC:
+ INSIST(plen == 0);
+ family = 1;
+ break;
+ case AF_INET:
+ INSIST(plen <= 32);
+ family = 1;
+ sin = (struct sockaddr_in *)sa;
+ memmove(addr, &sin->sin_addr, addrl);
+ break;
+ case AF_INET6:
+ INSIST(plen <= 128);
+ family = 2;
+ sin6 = (struct sockaddr_in6 *)sa;
+ memmove(addr, &sin6->sin6_addr, addrl);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf));
+ /* family */
+ isc_buffer_putuint16(&b, family);
+ /* source prefix-length */
+ isc_buffer_putuint8(&b, plen);
+ /* scope prefix-length */
+ isc_buffer_putuint8(&b, 0);
+
+ /* address */
+ if (addrl > 0) {
+ /* Mask off last address byte */
+ if ((plen % 8) != 0) {
+ addr[addrl - 1] &= ~0U
+ << (8 - (plen % 8));
+ }
+ isc_buffer_putmem(&b, addr, (unsigned)addrl);
+ }
+
+ opts[i].value = (uint8_t *)ecsbuf;
+ i++;
+ }
+
+ if (lookup->sendcookie) {
+ INSIST(i < MAXOPTS);
+ opts[i].code = DNS_OPT_COOKIE;
+ if (lookup->cookie != NULL) {
+ isc_buffer_init(&b, cookiebuf,
+ sizeof(cookiebuf));
+ result = isc_hex_decodestring(lookup->cookie,
+ &b);
+ check_result(result, "isc_hex_decodestring");
+ opts[i].value = isc_buffer_base(&b);
+ opts[i].length = isc_buffer_usedlength(&b);
+ } else {
+ compute_cookie(cookie, sizeof(cookie));
+ opts[i].length = 8;
+ opts[i].value = cookie;
+ }
+ i++;
+ }
+
+ if (lookup->expire) {
+ INSIST(i < MAXOPTS);
+ opts[i].code = DNS_OPT_EXPIRE;
+ opts[i].length = 0;
+ opts[i].value = NULL;
+ i++;
+ }
+
+ if (lookup->tcp_keepalive) {
+ INSIST(i < MAXOPTS);
+ opts[i].code = DNS_OPT_TCP_KEEPALIVE;
+ opts[i].length = 0;
+ opts[i].value = NULL;
+ i++;
+ }
+
+ if (lookup->ednsoptscnt != 0) {
+ INSIST(i + lookup->ednsoptscnt <= MAXOPTS);
+ memmove(&opts[i], lookup->ednsopts,
+ sizeof(dns_ednsopt_t) * lookup->ednsoptscnt);
+ i += lookup->ednsoptscnt;
+ }
+
+ if (lookup->padding != 0 && (i >= MAXOPTS)) {
+ debug("turned off padding because of EDNS overflow");
+ lookup->padding = 0;
+ }
+
+ if (lookup->padding != 0) {
+ INSIST(i < MAXOPTS);
+ opts[i].code = DNS_OPT_PAD;
+ opts[i].length = 0;
+ opts[i].value = NULL;
+ i++;
+ dns_message_setpadding(lookup->sendmsg,
+ lookup->padding);
+ }
+
+ flags = lookup->ednsflags;
+ flags &= ~DNS_MESSAGEEXTFLAG_DO;
+ if (lookup->dnssec) {
+ flags |= DNS_MESSAGEEXTFLAG_DO;
+ }
+ add_opt(lookup->sendmsg, lookup->udpsize, lookup->edns, flags,
+ opts, i);
+ }
+
+ result = dns_message_rendersection(lookup->sendmsg,
+ DNS_SECTION_QUESTION, 0);
+ check_result(result, "dns_message_rendersection");
+ result = dns_message_rendersection(lookup->sendmsg,
+ DNS_SECTION_AUTHORITY, 0);
+ check_result(result, "dns_message_rendersection");
+ result = dns_message_renderend(lookup->sendmsg);
+ check_result(result, "dns_message_renderend");
+ debug("done rendering");
+
+ dns_compress_invalidate(&cctx);
+
+ /*
+ * Force TCP mode if the request is larger than 512 bytes.
+ */
+ if (isc_buffer_usedlength(&lookup->renderbuf) > 512) {
+ lookup->tcp_mode = true;
+ }
+
+ lookup->pending = false;
+
+ for (serv = ISC_LIST_HEAD(lookup->my_server_list); serv != NULL;
+ serv = ISC_LIST_NEXT(serv, link))
+ {
+ query = new_query(lookup, serv->servername, serv->userarg);
+ ISC_LIST_ENQUEUE(lookup->q, query, link);
+ }
+
+ return (true);
+}
+
+/*%
+ * NSSEARCH mode special mode handling function to start the next query in the
+ * list. The lookup lock must be held by the caller. The function will detach
+ * both the lookup and the query, and may cancel the lookup and clear the
+ * current lookup.
+ */
+static void
+nssearch_next(dig_lookup_t *l, dig_query_t *q) {
+ dig_query_t *next = ISC_LIST_NEXT(q, link);
+ bool tcp_mode = l->tcp_mode;
+
+ INSIST(l->ns_search_only && !l->trace_root);
+ INSIST(l == current_lookup);
+
+ if (next == NULL) {
+ /*
+ * If this is the last query, and if there was
+ * not a single successful query in the whole
+ * lookup, then treat the situation as an error,
+ * cancel and clear the lookup.
+ */
+ if (check_if_queries_done(l, q) && !l->ns_search_success) {
+ dighost_error("NS servers could not be reached");
+ if (exitcode < 9) {
+ exitcode = 9;
+ }
+
+ cancel_lookup(l);
+ query_detach(&q);
+ lookup_detach(&l);
+ clear_current_lookup();
+ } else {
+ query_detach(&q);
+ lookup_detach(&l);
+ }
+ } else {
+ query_detach(&q);
+ lookup_detach(&l);
+
+ debug("sending next, since searching");
+ if (tcp_mode) {
+ start_tcp(next);
+ } else {
+ start_udp(next);
+ }
+ }
+}
+
+/*%
+ * Event handler for send completion. Track send counter, and clear out
+ * the query if the send was canceled.
+ */
+static void
+send_done(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
+ dig_query_t *query = (dig_query_t *)arg;
+ dig_lookup_t *l = NULL;
+
+ REQUIRE(DIG_VALID_QUERY(query));
+ INSIST(query->sendhandle != NULL);
+ INSIST(handle == query->sendhandle);
+
+ debug("send_done(%p, %s, %p)", handle, isc_result_totext(eresult), arg);
+
+ isc_refcount_decrement0(&sendcount);
+ debug("sendcount=%" PRIuFAST32, isc_refcount_current(&sendcount));
+
+ INSIST(!free_now);
+
+ LOCK_LOOKUP;
+
+ isc_nmhandle_detach(&query->sendhandle);
+
+ lookup_attach(query->lookup, &l);
+
+ if (eresult == ISC_R_CANCELED || query->canceled) {
+ debug("send_done: cancel");
+ if (!query->canceled) {
+ cancel_lookup(l);
+ }
+ query_detach(&query);
+ lookup_detach(&l);
+ UNLOCK_LOOKUP;
+ return;
+ } else if (eresult != ISC_R_SUCCESS) {
+ debug("send failed: %s", isc_result_totext(eresult));
+ }
+
+ if (l->ns_search_only && !l->trace_root) {
+ nssearch_next(l, query);
+ } else {
+ query_detach(&query);
+ lookup_detach(&l);
+ }
+
+ check_if_done();
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Cancel a lookup, sending canceling reads on all existing sockets.
+ */
+
+static void
+_cancel_lookup(dig_lookup_t *lookup, const char *file, unsigned int line) {
+ dig_query_t *query, *next;
+
+ debug("%s:%u:%s()", file, line, __func__);
+ query = ISC_LIST_HEAD(lookup->q);
+ while (query != NULL) {
+ REQUIRE(DIG_VALID_QUERY(query));
+ next = ISC_LIST_NEXT(query, link);
+ ISC_LIST_DEQUEUE(lookup->q, query, link);
+ debug("canceling pending query %p, belonging to %p", query,
+ query->lookup);
+ query->canceled = true;
+ if (query->readhandle != NULL &&
+ !isc_nm_is_http_handle(query->readhandle))
+ {
+ isc_nm_cancelread(query->readhandle);
+ }
+ query_detach(&query);
+ query = next;
+ }
+ lookup->pending = false;
+ lookup->retries = 0;
+ check_if_done();
+}
+
+static isc_tlsctx_t *
+get_create_tls_context(dig_query_t *query, const bool is_https,
+ isc_tlsctx_client_session_cache_t **psess_cache) {
+ isc_result_t result;
+ isc_tlsctx_t *ctx = NULL, *found_ctx = NULL;
+ isc_tls_cert_store_t *store = NULL, *found_store = NULL;
+ char tlsctxname[ISC_SOCKADDR_FORMATSIZE];
+ const uint16_t family = isc_sockaddr_pf(&query->sockaddr) == PF_INET6
+ ? AF_INET6
+ : AF_INET;
+ isc_tlsctx_cache_transport_t transport =
+ is_https ? isc_tlsctx_cache_https : isc_tlsctx_cache_tls;
+ const bool hostname_ignore_subject = !is_https;
+ isc_tlsctx_client_session_cache_t *sess_cache = NULL,
+ *found_sess_cache = NULL;
+
+ if (query->lookup->tls_key_file_set != query->lookup->tls_cert_file_set)
+ {
+ return (NULL);
+ }
+
+ isc_sockaddr_format(&query->sockaddr, tlsctxname, sizeof(tlsctxname));
+
+ result = isc_tlsctx_cache_find(query->lookup->tls_ctx_cache, tlsctxname,
+ transport, family, &found_ctx,
+ &found_store, &found_sess_cache);
+ if (result != ISC_R_SUCCESS) {
+ if (query->lookup->tls_ca_set) {
+ if (found_store == NULL) {
+ result = isc_tls_cert_store_create(
+ query->lookup->tls_ca_file, &store);
+
+ if (result != ISC_R_SUCCESS) {
+ goto failure;
+ }
+ } else {
+ store = found_store;
+ }
+ }
+
+ result = isc_tlsctx_createclient(&ctx);
+ if (result != ISC_R_SUCCESS) {
+ goto failure;
+ }
+
+ if (store != NULL) {
+ const char *hostname =
+ query->lookup->tls_hostname_set
+ ? query->lookup->tls_hostname
+ : query->userarg;
+ /*
+ * According to RFC 8310, Subject field MUST NOT be
+ * inspected when verifying hostname for DoT. Only
+ * SubjectAltName must be checked. That is NOT the case
+ * for HTTPS.
+ */
+ result = isc_tlsctx_enable_peer_verification(
+ ctx, false, store, hostname,
+ hostname_ignore_subject);
+ if (result != ISC_R_SUCCESS) {
+ goto failure;
+ }
+ }
+
+ if (query->lookup->tls_key_file_set &&
+ query->lookup->tls_cert_file_set)
+ {
+ result = isc_tlsctx_load_certificate(
+ ctx, query->lookup->tls_key_file,
+ query->lookup->tls_cert_file);
+ if (result != ISC_R_SUCCESS) {
+ goto failure;
+ }
+ }
+
+ if (!is_https) {
+ isc_tlsctx_enable_dot_client_alpn(ctx);
+ }
+
+#if HAVE_LIBNGHTTP2
+ if (is_https) {
+ isc_tlsctx_enable_http2client_alpn(ctx);
+ }
+#endif /* HAVE_LIBNGHTTP2 */
+
+ isc_tlsctx_client_session_cache_create(
+ mctx, ctx, ISC_TLSCTX_CLIENT_SESSION_CACHE_DEFAULT_SIZE,
+ &sess_cache);
+
+ result = isc_tlsctx_cache_add(
+ query->lookup->tls_ctx_cache, tlsctxname, transport,
+ family, ctx, store, sess_cache, NULL, NULL, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (psess_cache != NULL) {
+ INSIST(*psess_cache == NULL);
+ *psess_cache = sess_cache;
+ }
+ return (ctx);
+ }
+
+ if (psess_cache != NULL) {
+ INSIST(*psess_cache == NULL);
+ *psess_cache = found_sess_cache;
+ }
+
+ INSIST(!query->lookup->tls_ca_set || found_store != NULL);
+ return (found_ctx);
+failure:
+ if (ctx != NULL) {
+ isc_tlsctx_free(&ctx);
+ }
+ /*
+ * The 'found_store' is being managed by the TLS context
+ * cache. Thus, we should keep it as it is, as it will get
+ * destroyed alongside the cache. As there is one store per
+ * multiple TLS contexts, we need to handle store deletion in a
+ * special way.
+ */
+ if (store != NULL && store != found_store) {
+ isc_tls_cert_store_free(&store);
+ }
+ return (NULL);
+}
+
+static void
+tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg);
+
+/*%
+ * Unlike start_udp, this can't be called multiple times with the same
+ * query. When we retry TCP, we requeue the whole lookup, which should
+ * start anew.
+ */
+static void
+start_tcp(dig_query_t *query) {
+ isc_result_t result;
+ dig_query_t *next = NULL;
+ dig_query_t *connectquery = NULL;
+ isc_tlsctx_t *tlsctx = NULL;
+ bool tls_mode = false;
+ isc_tlsctx_client_session_cache_t *sess_cache = NULL;
+ REQUIRE(DIG_VALID_QUERY(query));
+
+ debug("start_tcp(%p)", query);
+
+ query_attach(query, &query->lookup->current_query);
+
+ tls_mode = dig_lookup_is_tls(query->lookup);
+
+ /*
+ * For TLS connections, we want to override the default
+ * port number.
+ */
+ if (!port_set) {
+ if (tls_mode) {
+ port = 853;
+ } else if (query->lookup->https_mode &&
+ !query->lookup->http_plain)
+ {
+ port = 443;
+ } else if (query->lookup->https_mode) {
+ port = 80;
+ } else {
+ port = 53;
+ }
+ }
+
+ debug("query->servname = %s\n", query->servname);
+
+ result = get_address(query->servname, port, &query->sockaddr);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * This servname doesn't have an address. Try the next server
+ * by triggering an immediate 'timeout' (we lie, but the effect
+ * is the same).
+ */
+ force_next(query);
+ return;
+ }
+
+ if (isc_sockaddr_pf(&query->sockaddr) == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr))
+ {
+ isc_netaddr_t netaddr;
+ char buf[ISC_NETADDR_FORMATSIZE];
+
+ isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr);
+ isc_netaddr_format(&netaddr, buf, sizeof(buf));
+ dighost_warning("Skipping mapped address '%s'", buf);
+
+ if (ISC_LINK_LINKED(query, link)) {
+ next = ISC_LIST_NEXT(query, link);
+ } else {
+ next = NULL;
+ }
+ query_detach(&query);
+ if (next == NULL) {
+ dighost_warning("No acceptable nameservers");
+ clear_current_lookup();
+ } else {
+ start_tcp(next);
+ }
+ return;
+ }
+
+ INSIST(query->handle == NULL);
+
+ if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
+ query->handle = keep;
+ launch_next_query(query);
+ query_detach(&query);
+ return;
+ } else {
+ int local_timeout = timeout * 1000;
+ if (local_timeout == 0) {
+ local_timeout = TCP_TIMEOUT * 1000;
+ }
+
+ if (keep != NULL) {
+ isc_nmhandle_detach(&keep);
+ }
+
+ if (!specified_source) {
+ if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
+ have_ipv4)
+ {
+ isc_sockaddr_any(&localaddr);
+ } else {
+ isc_sockaddr_any6(&localaddr);
+ }
+ }
+
+ REQUIRE(query != NULL);
+
+ query_attach(query, &connectquery);
+
+ if (tls_mode) {
+ tlsctx = get_create_tls_context(connectquery, false,
+ &sess_cache);
+ if (tlsctx == NULL) {
+ goto failure_tls;
+ }
+ isc_nm_tlsdnsconnect(netmgr, &localaddr,
+ &query->sockaddr, tcp_connected,
+ connectquery, local_timeout, 0,
+ tlsctx, sess_cache);
+#if HAVE_LIBNGHTTP2
+ } else if (query->lookup->https_mode) {
+ char uri[4096] = { 0 };
+ isc_nm_http_makeuri(!query->lookup->http_plain,
+ &query->sockaddr, query->userarg,
+ port, query->lookup->https_path,
+ uri, sizeof(uri));
+
+ if (!query->lookup->http_plain) {
+ tlsctx = get_create_tls_context(
+ connectquery, true, &sess_cache);
+ if (tlsctx == NULL) {
+ goto failure_tls;
+ }
+ }
+
+ isc_nm_httpconnect(netmgr, &localaddr, &query->sockaddr,
+ uri, !query->lookup->https_get,
+ tcp_connected, connectquery, tlsctx,
+ sess_cache, 0, local_timeout);
+#endif
+ } else {
+ isc_nm_tcpdnsconnect(netmgr, &localaddr,
+ &query->sockaddr, tcp_connected,
+ connectquery, local_timeout, 0);
+ }
+ }
+ return;
+failure_tls:
+ if (query->lookup->tls_key_file_set != query->lookup->tls_cert_file_set)
+ {
+ dighost_warning(
+ "both TLS client certificate and key file must be "
+ "specified a the same time");
+ } else {
+ dighost_warning("TLS context cannot be created");
+ }
+
+ if (ISC_LINK_LINKED(query, link)) {
+ next = ISC_LIST_NEXT(query, link);
+ } else {
+ next = NULL;
+ }
+ query_detach(&connectquery);
+ query_detach(&query);
+ if (next == NULL) {
+ clear_current_lookup();
+ } else {
+ start_tcp(next);
+ }
+}
+
+static void
+print_query_size(dig_query_t *query) {
+ if (!yaml) {
+ printf(";; QUERY SIZE: %u\n\n",
+ isc_buffer_usedlength(&query->lookup->renderbuf));
+ }
+}
+
+static void
+send_udp(dig_query_t *query) {
+ dig_query_t *sendquery = NULL;
+ isc_region_t r;
+
+ query_attach(query, &sendquery);
+
+ isc_buffer_usedregion(&query->sendbuf, &r);
+ debug("sending a request");
+ if (query->lookup->use_usec) {
+ TIME_NOW_HIRES(&query->time_sent);
+ } else {
+ TIME_NOW(&query->time_sent);
+ }
+
+ isc_nmhandle_attach(query->handle, &query->sendhandle);
+
+ isc_nm_send(query->handle, &r, send_done, sendquery);
+ isc_refcount_increment0(&sendcount);
+ debug("sendcount=%" PRIuFAST32, isc_refcount_current(&sendcount));
+
+ /* XXX qrflag, print_query, etc... */
+ if (query->lookup->qr) {
+ extrabytes = 0;
+ dighost_printmessage(query, &query->lookup->renderbuf,
+ query->lookup->sendmsg, true);
+ if (query->lookup->stats) {
+ print_query_size(query);
+ }
+ }
+}
+
+static void
+udp_ready(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
+ dig_query_t *query = (dig_query_t *)arg;
+ dig_query_t *next = NULL;
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+ dig_lookup_t *l = NULL;
+ dig_query_t *readquery = NULL;
+ int local_timeout = timeout * 1000;
+
+ REQUIRE(DIG_VALID_QUERY(query));
+ REQUIRE(query->handle == NULL);
+
+ debug("udp_ready()");
+
+ query->started = true;
+
+ if (atomic_load(&cancel_now)) {
+ query_detach(&query);
+ return;
+ }
+
+ INSIST(!free_now);
+
+ debug("udp_ready(%p, %s, %p)", handle, isc_result_totext(eresult),
+ query);
+
+ LOCK_LOOKUP;
+ lookup_attach(query->lookup, &l);
+
+ if (eresult == ISC_R_CANCELED || query->canceled) {
+ debug("in cancel handler");
+ if (!query->canceled) {
+ cancel_lookup(l);
+ }
+ query_detach(&query);
+ lookup_detach(&l);
+ clear_current_lookup();
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (eresult != ISC_R_SUCCESS) {
+ debug("udp setup failed: %s", isc_result_totext(eresult));
+ isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
+ dighost_warning("UDP setup with %s(%s) for %s failed: %s.",
+ sockstr, query->servname, l->textname,
+ isc_result_totext(eresult));
+
+ /*
+ * NSSEARCH mode: if the current query failed to start properly,
+ * then send_done() will not be called, and we want to make sure
+ * that the next query gets a chance to start in order to not
+ * break the chain.
+ */
+ if (l->ns_search_only && !l->trace_root) {
+ nssearch_next(l, query);
+
+ check_if_done();
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (exitcode < 9) {
+ exitcode = 9;
+ }
+
+ if (l->retries > 1) {
+ l->retries--;
+ debug("making new UDP request, %d tries left",
+ l->retries);
+ requeue_lookup(l, true);
+ next = NULL;
+ } else if ((l->current_query != NULL) &&
+ (ISC_LINK_LINKED(l->current_query, link)))
+ {
+ next = ISC_LIST_NEXT(l->current_query, link);
+ } else {
+ next = NULL;
+ }
+
+ query_detach(&query);
+ if (next == NULL) {
+ cancel_lookup(l);
+ }
+ lookup_detach(&l);
+
+ if (next != NULL) {
+ start_udp(next);
+ check_if_done();
+ } else {
+ clear_current_lookup();
+ }
+
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ exitcode = 0;
+
+ query_attach(query, &readquery);
+
+ debug("recving with lookup=%p, query=%p, handle=%p", query->lookup,
+ query, handle);
+
+ query->handle = handle;
+ isc_nmhandle_attach(handle, &query->readhandle);
+ isc_refcount_increment0(&recvcount);
+ debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount));
+
+ if (local_timeout == 0) {
+ local_timeout = UDP_TIMEOUT * 1000;
+ }
+
+ debug("have local timeout of %d", local_timeout);
+ isc_nmhandle_settimeout(handle, local_timeout);
+
+ isc_nm_read(handle, recv_done, readquery);
+ send_udp(readquery);
+
+ query_detach(&query);
+ lookup_detach(&l);
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Send a UDP packet to the remote nameserver, possible starting the
+ * recv action as well. Also make sure that the timer is running and
+ * is properly reset.
+ */
+static void
+start_udp(dig_query_t *query) {
+ isc_result_t result;
+ dig_query_t *next = NULL;
+ dig_query_t *connectquery = NULL;
+
+ REQUIRE(DIG_VALID_QUERY(query));
+
+ debug("start_udp(%p)", query);
+
+ query_attach(query, &query->lookup->current_query);
+ debug("working on lookup %p, query %p", query->lookup, query);
+
+ if (query->handle != NULL) {
+ launch_next_query(query);
+ query_detach(&query);
+ return;
+ }
+
+ result = get_address(query->servname, port, &query->sockaddr);
+ if (result != ISC_R_SUCCESS) {
+ /* This servname doesn't have an address. */
+ force_next(query);
+ return;
+ }
+
+ if (isc_sockaddr_pf(&query->sockaddr) == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr))
+ {
+ isc_netaddr_t netaddr;
+ char buf[ISC_NETADDR_FORMATSIZE];
+
+ isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr);
+ isc_netaddr_format(&netaddr, buf, sizeof(buf));
+ dighost_warning("Skipping mapped address '%s'", buf);
+ next = ISC_LIST_NEXT(query, link);
+ query_detach(&query);
+ if (next == NULL) {
+ dighost_warning("No acceptable nameservers");
+ clear_current_lookup();
+ } else {
+ start_udp(next);
+ }
+ return;
+ }
+
+ if (!specified_source) {
+ if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) && have_ipv4)
+ {
+ isc_sockaddr_any(&localaddr);
+ } else {
+ isc_sockaddr_any6(&localaddr);
+ }
+ }
+
+ query_attach(query, &connectquery);
+ isc_nm_udpconnect(netmgr, &localaddr, &query->sockaddr, udp_ready,
+ connectquery,
+ (timeout ? timeout : UDP_TIMEOUT) * 1000, 0);
+}
+
+/*%
+ * If there are more servers available for querying within 'lookup', initiate a
+ * TCP or UDP query to the next available server and return true; otherwise,
+ * return false.
+ */
+static bool
+try_next_server(dig_lookup_t *lookup) {
+ dig_query_t *current_query, *next_query;
+
+ current_query = lookup->current_query;
+ if (current_query == NULL || !ISC_LINK_LINKED(current_query, link)) {
+ return (false);
+ }
+
+ next_query = ISC_LIST_NEXT(current_query, link);
+ if (next_query == NULL) {
+ return (false);
+ }
+
+ debug("trying next server...");
+
+ if (lookup->tcp_mode) {
+ start_tcp(next_query);
+ } else {
+ start_udp(next_query);
+ }
+
+ return (true);
+}
+
+static void
+force_next(dig_query_t *query) {
+ dig_lookup_t *l = NULL;
+
+ REQUIRE(DIG_VALID_QUERY(query));
+
+ debug("force_next()");
+
+ LOCK_LOOKUP;
+ INSIST(!free_now);
+
+ if (atomic_load(&cancel_now)) {
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ lookup_attach(query->lookup, &l);
+
+ if (try_next_server(l)) {
+ lookup_detach(&l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (l->retries > 1) {
+ l->retries--;
+ debug("making new %s request, %d tries left",
+ l->tcp_mode ? "TCP" : "UDP", l->retries);
+ requeue_lookup(l, true);
+ lookup_detach(&l);
+ isc_refcount_decrement0(&recvcount);
+ debug("recvcount=%" PRIuFAST32,
+ isc_refcount_current(&recvcount));
+ query_detach(&query);
+ clear_current_lookup();
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (query->readhandle != NULL) {
+ isc_refcount_decrement0(&recvcount);
+ debug("recvcount=%" PRIuFAST32,
+ isc_refcount_current(&recvcount));
+ }
+
+ if (l->ns_search_only) {
+ isc_netaddr_t netaddr;
+ char buf[ISC_NETADDR_FORMATSIZE];
+
+ isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr);
+ isc_netaddr_format(&netaddr, buf, sizeof(buf));
+
+ dighost_error("no response from %s\n", buf);
+ } else {
+ printf("%s", l->cmdline);
+ dighost_error("no servers could be reached\n");
+ }
+
+ if (exitcode < 9) {
+ exitcode = 9;
+ }
+
+ query_detach(&query);
+ cancel_lookup(l);
+ lookup_detach(&l);
+ clear_current_lookup();
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * For transfers that involve multiple recvs (XFR's in particular),
+ * launch the next recv.
+ */
+static void
+launch_next_query(dig_query_t *query) {
+ dig_query_t *readquery = NULL;
+ int local_timeout = timeout * 1000;
+ dig_lookup_t *l = NULL;
+ isc_region_t r;
+ bool xfr;
+
+ REQUIRE(DIG_VALID_QUERY(query));
+ INSIST(!free_now);
+
+ debug("launch_next_query()");
+
+ lookup_attach(query->lookup, &l);
+
+ if (!l->pending) {
+ debug("ignoring launch_next_query because !pending");
+ query_detach(&query);
+ lookup_detach(&l);
+ clear_current_lookup();
+ return;
+ }
+
+ isc_nmhandle_attach(query->handle, &query->readhandle);
+ isc_refcount_increment0(&recvcount);
+ debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount));
+
+ if (local_timeout == 0) {
+ local_timeout = TCP_TIMEOUT * 1000;
+ }
+
+ debug("have local timeout of %d", local_timeout);
+ isc_nmhandle_settimeout(query->handle, local_timeout);
+
+ xfr = query->lookup->rdtype == dns_rdatatype_ixfr ||
+ query->lookup->rdtype == dns_rdatatype_axfr;
+ if (xfr && isc_nm_socket_type(query->handle) == isc_nm_tlsdnssocket) {
+ isc_result_t result = isc_nm_xfr_checkperm(query->handle);
+ if (result != ISC_R_SUCCESS) {
+ dighost_error("zone transfers over the established TLS "
+ "connection are not allowed: %s",
+ isc_result_totext(result));
+ isc_refcount_decrement0(&recvcount);
+ isc_nmhandle_detach(&query->readhandle);
+ cancel_lookup(l);
+ lookup_detach(&l);
+ clear_current_lookup();
+ return;
+ }
+ }
+
+ query_attach(query, &readquery);
+
+ isc_nm_read(query->handle, recv_done, readquery);
+
+ if (!query->first_soa_rcvd) {
+ dig_query_t *sendquery = NULL;
+ debug("sending a request in launch_next_query");
+ if (query->lookup->use_usec) {
+ TIME_NOW_HIRES(&query->time_sent);
+ } else {
+ TIME_NOW(&query->time_sent);
+ }
+
+ query_attach(query, &sendquery);
+ isc_buffer_usedregion(&query->sendbuf, &r);
+ if (keep != NULL) {
+ query->handle = keep;
+ }
+
+ isc_nmhandle_attach(query->handle, &query->sendhandle);
+ isc_nm_send(query->handle, &r, send_done, sendquery);
+ isc_refcount_increment0(&sendcount);
+ debug("sendcount=%" PRIuFAST32,
+ isc_refcount_current(&sendcount));
+
+ /* XXX qrflag, print_query, etc... */
+ if (l->qr) {
+ extrabytes = 0;
+ dighost_printmessage(query, &l->renderbuf, l->sendmsg,
+ true);
+ if (l->stats) {
+ print_query_size(query);
+ }
+ }
+ }
+
+ lookup_detach(&l);
+ return;
+}
+
+/*%
+ * Event handler for TCP connect complete. Make sure the connection was
+ * successful, then pass into launch_next_query to actually send the
+ * question.
+ */
+static void
+tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
+ dig_query_t *query = (dig_query_t *)arg;
+ dig_query_t *next = NULL;
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+ dig_lookup_t *l = NULL;
+
+ REQUIRE(DIG_VALID_QUERY(query));
+ REQUIRE(query->handle == NULL);
+
+ debug("tcp_connected()");
+
+ query->started = true;
+
+ if (atomic_load(&cancel_now)) {
+ query_detach(&query);
+ return;
+ }
+
+ INSIST(!free_now);
+
+ debug("tcp_connected(%p, %s, %p)", handle, isc_result_totext(eresult),
+ query);
+
+ LOCK_LOOKUP;
+ lookup_attach(query->lookup, &l);
+
+ if (eresult == ISC_R_CANCELED || eresult == ISC_R_TLSBADPEERCERT ||
+ query->canceled)
+ {
+ debug("in cancel handler");
+ isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
+ if (eresult == ISC_R_TLSBADPEERCERT) {
+ dighost_warning(
+ "TLS peer certificate verification for "
+ "%s failed: %s",
+ sockstr,
+ isc_nm_verify_tls_peer_result_string(handle));
+ } else if (query->lookup->rdtype == dns_rdatatype_ixfr ||
+ query->lookup->rdtype == dns_rdatatype_axfr)
+ {
+ puts("; Transfer failed.");
+ }
+
+ if (!query->canceled) {
+ cancel_lookup(l);
+ }
+
+ query_detach(&query);
+ lookup_detach(&l);
+ clear_current_lookup();
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (eresult != ISC_R_SUCCESS) {
+ debug("unsuccessful connection: %s",
+ isc_result_totext(eresult));
+ isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
+ dighost_warning("Connection to %s(%s) for %s failed: %s.",
+ sockstr, query->servname, l->textname,
+ isc_result_totext(eresult));
+
+ /*
+ * NSSEARCH mode: if the current query failed to start properly,
+ * then send_done() will not be called, and we want to make sure
+ * that the next query gets a chance to start in order to not
+ * break the chain.
+ */
+ if (l->ns_search_only && !l->trace_root) {
+ nssearch_next(l, query);
+
+ check_if_done();
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ /* XXX Clean up exitcodes */
+ if (exitcode < 9) {
+ exitcode = 9;
+ }
+
+ if (l->retries > 1) {
+ l->retries--;
+ debug("making new TCP request, %d tries left",
+ l->retries);
+ requeue_lookup(l, true);
+ next = NULL;
+ } else if ((l->current_query != NULL) &&
+ (ISC_LINK_LINKED(l->current_query, link)))
+ {
+ next = ISC_LIST_NEXT(l->current_query, link);
+ } else {
+ next = NULL;
+ }
+
+ query_detach(&query);
+ if (next == NULL) {
+ cancel_lookup(l);
+ }
+ lookup_detach(&l);
+
+ if (next != NULL) {
+ start_tcp(next);
+ check_if_done();
+ } else {
+ clear_current_lookup();
+ }
+
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ exitcode = 0;
+
+ query->handle = handle;
+ if (keep_open) {
+ keepaddr = query->sockaddr;
+ if (keep != NULL) {
+ isc_nmhandle_detach(&keep);
+ }
+
+ isc_nmhandle_attach(handle, &keep);
+ }
+
+ launch_next_query(query);
+ query_detach(&query);
+ lookup_detach(&l);
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Check if the ongoing XFR needs more data before it's complete, using
+ * the semantics of IXFR and AXFR protocols. Much of the complexity of
+ * this routine comes from determining when an IXFR is complete.
+ * false means more data is on the way, and the recv has been issued.
+ */
+static bool
+check_for_more_data(dig_lookup_t *lookup, dig_query_t *query,
+ dns_message_t *msg, isc_sockaddr_t *peer, int len) {
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_soa_t soa;
+ uint32_t ixfr_serial = lookup->ixfr_serial, serial;
+ isc_result_t result;
+ bool ixfr = lookup->rdtype == dns_rdatatype_ixfr;
+ bool axfr = lookup->rdtype == dns_rdatatype_axfr;
+
+ if (ixfr) {
+ axfr = query->ixfr_axfr;
+ }
+
+ debug("check_for_more_data()");
+
+ /*
+ * By the time we're in this routine, we know we're doing
+ * either an AXFR or IXFR. If there's no second_rr_type,
+ * then we don't yet know which kind of answer we got back
+ * from the server. Here, we're going to walk through the
+ * rr's in the message, acting as necessary whenever we hit
+ * an SOA rr.
+ */
+
+ query->msg_count++;
+ query->byte_count += len;
+ result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
+ if (result != ISC_R_SUCCESS) {
+ puts("; Transfer failed.");
+ return (true);
+ }
+ do {
+ dns_name_t *name;
+ name = NULL;
+ dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+ for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS) {
+ continue;
+ }
+ do {
+ query->rr_count++;
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ /*
+ * If this is the first rr, make sure
+ * it's an SOA
+ */
+ if ((!query->first_soa_rcvd) &&
+ (rdata.type != dns_rdatatype_soa))
+ {
+ puts("; Transfer failed. "
+ "Didn't start with SOA answer.");
+ return (true);
+ }
+ if ((!query->second_rr_rcvd) &&
+ (rdata.type != dns_rdatatype_soa))
+ {
+ query->second_rr_rcvd = true;
+ query->second_rr_serial = 0;
+ debug("got the second rr as nonsoa");
+ axfr = query->ixfr_axfr = true;
+ goto next_rdata;
+ }
+
+ /*
+ * If the record is anything except an SOA
+ * now, just continue on...
+ */
+ if (rdata.type != dns_rdatatype_soa) {
+ goto next_rdata;
+ }
+
+ /* Now we have an SOA. Work with it. */
+ debug("got an SOA");
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ serial = soa.serial;
+ dns_rdata_freestruct(&soa);
+ if (!query->first_soa_rcvd) {
+ query->first_soa_rcvd = true;
+ query->first_rr_serial = serial;
+ debug("this is the first serial %u",
+ serial);
+ if (ixfr &&
+ isc_serial_ge(ixfr_serial, serial))
+ {
+ debug("got up to date "
+ "response");
+ goto doexit;
+ }
+ goto next_rdata;
+ }
+ if (axfr) {
+ debug("doing axfr, got second SOA");
+ goto doexit;
+ }
+ if (!query->second_rr_rcvd) {
+ if (query->first_rr_serial == serial) {
+ debug("doing ixfr, got "
+ "empty zone");
+ goto doexit;
+ }
+ debug("this is the second serial %u",
+ serial);
+ query->second_rr_rcvd = true;
+ query->second_rr_serial = serial;
+ goto next_rdata;
+ }
+ /*
+ * If we get to this point, we're doing an
+ * IXFR and have to start really looking
+ * at serial numbers.
+ */
+ if (query->first_rr_serial == serial) {
+ debug("got a match for ixfr");
+ if (!query->first_repeat_rcvd) {
+ query->first_repeat_rcvd = true;
+ goto next_rdata;
+ }
+ debug("done with ixfr");
+ goto doexit;
+ }
+ debug("meaningless soa %u", serial);
+ next_rdata:
+ result = dns_rdataset_next(rdataset);
+ } while (result == ISC_R_SUCCESS);
+ }
+ result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
+ } while (result == ISC_R_SUCCESS);
+ isc_nmhandle_detach(&query->readhandle);
+ launch_next_query(query);
+ query_detach(&query);
+ return (false);
+doexit:
+ dighost_received(len, peer, query);
+ return (true);
+}
+
+static void
+process_cookie(dig_lookup_t *l, dns_message_t *msg, isc_buffer_t *optbuf,
+ size_t optlen) {
+ char bb[256];
+ isc_buffer_t hexbuf;
+ size_t len;
+ const unsigned char *sent;
+ bool copy = true;
+ isc_result_t result;
+
+ if (l->cookie != NULL) {
+ isc_buffer_init(&hexbuf, bb, sizeof(bb));
+ result = isc_hex_decodestring(l->cookie, &hexbuf);
+ check_result(result, "isc_hex_decodestring");
+ sent = isc_buffer_base(&hexbuf);
+ len = isc_buffer_usedlength(&hexbuf);
+ } else {
+ sent = cookie;
+ len = sizeof(cookie);
+ }
+
+ INSIST(msg->cc_ok == 0 && msg->cc_bad == 0);
+ if (len >= 8 && optlen >= 8U) {
+ if (isc_safe_memequal(isc_buffer_current(optbuf), sent, 8)) {
+ msg->cc_ok = 1;
+ } else {
+ dighost_warning("Warning: Client COOKIE mismatch");
+ msg->cc_bad = 1;
+ copy = false;
+ }
+ } else {
+ dighost_warning("Warning: COOKIE bad token (too short)");
+ msg->cc_bad = 1;
+ copy = false;
+ }
+ if (copy) {
+ isc_region_t r;
+
+ r.base = isc_buffer_current(optbuf);
+ r.length = (unsigned int)optlen;
+ isc_buffer_init(&hexbuf, servercookie, sizeof(servercookie));
+ result = isc_hex_totext(&r, 2, "", &hexbuf);
+ check_result(result, "isc_hex_totext");
+ if (isc_buffer_availablelength(&hexbuf) > 0) {
+ isc_buffer_putuint8(&hexbuf, 0);
+ l->cookie = servercookie;
+ }
+ }
+ isc_buffer_forward(optbuf, (unsigned int)optlen);
+}
+
+static void
+process_opt(dig_lookup_t *l, dns_message_t *msg) {
+ dns_rdata_t rdata;
+ isc_result_t result;
+ isc_buffer_t optbuf;
+ uint16_t optcode, optlen;
+ dns_rdataset_t *opt = msg->opt;
+ bool seen_cookie = false;
+
+ result = dns_rdataset_first(opt);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(opt, &rdata);
+ isc_buffer_init(&optbuf, rdata.data, rdata.length);
+ isc_buffer_add(&optbuf, rdata.length);
+ while (isc_buffer_remaininglength(&optbuf) >= 4) {
+ optcode = isc_buffer_getuint16(&optbuf);
+ optlen = isc_buffer_getuint16(&optbuf);
+ switch (optcode) {
+ case DNS_OPT_COOKIE:
+ /*
+ * Only process the first cookie option.
+ */
+ if (seen_cookie) {
+ isc_buffer_forward(&optbuf, optlen);
+ break;
+ }
+ process_cookie(l, msg, &optbuf, optlen);
+ seen_cookie = true;
+ break;
+ default:
+ isc_buffer_forward(&optbuf, optlen);
+ break;
+ }
+ }
+ }
+}
+
+static int
+ednsvers(dns_rdataset_t *opt) {
+ return ((opt->ttl >> 16) & 0xff);
+}
+
+/*%
+ * Event handler for recv complete. Perform whatever actions are necessary,
+ * based on the specifics of the user's request.
+ */
+static void
+recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
+ void *arg) {
+ dig_query_t *query = (dig_query_t *)arg;
+ isc_buffer_t b;
+ dns_message_t *msg = NULL;
+ isc_result_t result;
+ dig_lookup_t *n = NULL;
+ dig_lookup_t *l = NULL;
+ bool docancel = false;
+ bool donext = false;
+ bool match = true;
+ bool done_process_opt = false;
+ unsigned int parseflags;
+ dns_messageid_t id;
+ unsigned int msgflags;
+ int newedns;
+ isc_sockaddr_t peer;
+
+ REQUIRE(DIG_VALID_QUERY(query));
+ REQUIRE(query->readhandle != NULL);
+ INSIST(!free_now);
+
+ debug("recv_done(%p, %s, %p, %p)", handle, isc_result_totext(eresult),
+ region, arg);
+
+ LOCK_LOOKUP;
+
+ isc_refcount_decrement0(&recvcount);
+ debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount));
+
+ lookup_attach(query->lookup, &l);
+
+ if (eresult == ISC_R_CANCELED || query->canceled) {
+ debug("recv_done: cancel");
+ isc_nmhandle_detach(&query->readhandle);
+ if (!query->canceled) {
+ cancel_lookup(l);
+ }
+ query_detach(&query);
+ lookup_detach(&l);
+ clear_current_lookup();
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (query->lookup->use_usec) {
+ TIME_NOW_HIRES(&query->time_recv);
+ } else {
+ TIME_NOW(&query->time_recv);
+ }
+
+ if ((!l->pending && !l->ns_search_only) || atomic_load(&cancel_now)) {
+ debug("no longer pending. Got %s", isc_result_totext(eresult));
+
+ goto next_lookup;
+ }
+
+ /*
+ * NSSEARCH mode is special, because the queries in the followup lookup
+ * are independent and they are being started in parallel, so if one of
+ * them fails there is no need to start the next query in the lookup,
+ * and this failure can be treated as a soft error (with a warning
+ * message), because there are usually more than one NS servers in the
+ * lookup's queries list. However, if there was not a single successful
+ * query in the followup lookup, then print an error message and exit
+ * with a non-zero exit code.
+ */
+ if (l->ns_search_only && !l->trace_root) {
+ if (eresult == ISC_R_SUCCESS) {
+ l->ns_search_success = true;
+ } else {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&query->sockaddr, sockstr,
+ sizeof(sockstr));
+
+ dighost_warning("communications error to %s: %s",
+ sockstr, isc_result_totext(eresult));
+
+ /*
+ * If this is not the last query, then we detach the
+ * query, but keep the lookup running.
+ */
+ if (!check_if_queries_done(l, query)) {
+ goto detach_query;
+ }
+
+ /*
+ * This is the last query, and if there was not a
+ * single successful query in the whole lookup, then
+ * treat the situation as an error.
+ */
+ if (!l->ns_search_success) {
+ dighost_error(
+ "NS servers could not be reached");
+ if (exitcode < 9) {
+ exitcode = 9;
+ }
+ }
+
+ goto cancel_lookup;
+ }
+ }
+
+ if (eresult != ISC_R_SUCCESS) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
+ dighost_warning("communications error to %s: %s", sockstr,
+ isc_result_totext(eresult));
+
+ if (l->retries > 1 && !l->tcp_mode) {
+ dig_query_t *newq = NULL;
+
+ /*
+ * For UDP, insert a copy of the current query just
+ * after itself in the list, and start it to retry the
+ * request.
+ */
+ newq = new_query(l, query->servname, query->userarg);
+ ISC_LIST_INSERTAFTER(l->q, query, newq, link);
+ if (l->current_query == query) {
+ query_detach(&l->current_query);
+ }
+ if (l->current_query == NULL) {
+ l->retries--;
+ debug("making new UDP request, %d tries left",
+ l->retries);
+ start_udp(newq);
+ }
+ if (check_if_queries_done(l, query)) {
+ goto cancel_lookup;
+ }
+
+ goto detach_query;
+ } else if (l->retries > 1 && l->tcp_mode) {
+ /*
+ * For TCP, we have to requeue the whole lookup, see
+ * the comments above the start_tcp() function.
+ */
+ l->retries--;
+ debug("making new TCP request, %d tries left",
+ l->retries);
+ requeue_lookup(l, true);
+
+ if (keep != NULL) {
+ isc_nmhandle_detach(&keep);
+ }
+
+ goto cancel_lookup;
+ } else {
+ dig_query_t *next = ISC_LIST_NEXT(query, link);
+
+ /*
+ * No retries left, go to the next query, if there is
+ * one.
+ */
+ if (next != NULL) {
+ if (l->current_query == query) {
+ query_detach(&l->current_query);
+ }
+ if (l->current_query == NULL) {
+ debug("starting next query %p", next);
+ if (l->tcp_mode) {
+ start_tcp(next);
+ } else {
+ start_udp(next);
+ }
+ }
+ if (check_if_queries_done(l, query)) {
+ goto cancel_lookup;
+ }
+
+ goto detach_query;
+ }
+
+ /*
+ * Otherwise, print the cmdline and an error message,
+ * and cancel the lookup.
+ */
+ printf("%s", l->cmdline);
+ dighost_error("no servers could be reached\n");
+
+ if (exitcode < 9) {
+ exitcode = 9;
+ }
+
+ if (keep != NULL) {
+ isc_nmhandle_detach(&keep);
+ }
+
+ goto cancel_lookup;
+ }
+ }
+
+ isc_buffer_init(&b, region->base, region->length);
+ isc_buffer_add(&b, region->length);
+
+ peer = isc_nmhandle_peeraddr(handle);
+
+ result = dns_message_peekheader(&b, &id, &msgflags);
+ if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
+ match = false;
+ if (l->tcp_mode) {
+ bool fail = true;
+ if (result == ISC_R_SUCCESS) {
+ if ((!query->first_soa_rcvd || query->warn_id))
+ {
+ dighost_warning("%s: ID mismatch: "
+ "expected ID %u, got "
+ "%u",
+ query->first_soa_rcvd
+ ? "WARNING"
+ : "ERROR",
+ l->sendmsg->id, id);
+ }
+ if (query->first_soa_rcvd) {
+ fail = false;
+ }
+ query->warn_id = false;
+ } else {
+ dighost_warning("ERROR: short (< header size) "
+ "message");
+ }
+ if (fail) {
+ goto cancel_lookup;
+ }
+ match = true;
+ } else if (result == ISC_R_SUCCESS) {
+ dighost_warning("Warning: ID mismatch: expected ID %u,"
+ " got %u",
+ l->sendmsg->id, id);
+ } else {
+ dighost_warning("Warning: short (< header size) "
+ "message received");
+ }
+ }
+
+ if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0) {
+ dighost_warning("Warning: query response not set");
+ }
+
+ if (!match) {
+ /*
+ * We are still attached to query and the query->readhandle is
+ * also attached
+ */
+ isc_refcount_increment0(&recvcount);
+ debug("recvcount=%" PRIuFAST32,
+ isc_refcount_current(&recvcount));
+ isc_nm_read(handle, recv_done, query);
+ goto keep_query;
+ }
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
+
+ if (tsigkey != NULL) {
+ if (l->querysig == NULL) {
+ debug("getting initial querysig");
+ result = dns_message_getquerytsig(l->sendmsg, mctx,
+ &l->querysig);
+ check_result(result, "dns_message_getquerytsig");
+ }
+ result = dns_message_setquerytsig(msg, l->querysig);
+ check_result(result, "dns_message_setquerytsig");
+ result = dns_message_settsigkey(msg, tsigkey);
+ check_result(result, "dns_message_settsigkey");
+ msg->tsigctx = l->tsigctx;
+ l->tsigctx = NULL;
+ if (l->msgcounter != 0) {
+ msg->tcp_continuation = 1;
+ }
+ l->msgcounter++;
+ }
+
+ debug("before parse starts");
+ parseflags = l->dns64prefix ? 0 : DNS_MESSAGEPARSE_PRESERVEORDER;
+ if (l->besteffort) {
+ parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
+ parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
+ }
+
+ result = dns_message_parse(msg, &b, parseflags);
+ if (result == DNS_R_RECOVERABLE) {
+ dighost_warning("Warning: Message parser reports malformed "
+ "message packet.");
+ } else if (result != ISC_R_SUCCESS) {
+ if (!yaml) {
+ printf(";; Got bad packet: %s\n",
+ isc_result_totext(result));
+ hex_dump(&b);
+ }
+ goto cancel_lookup;
+ }
+
+ if (msg->opcode != l->opcode) {
+ char expect[20] = { 0 }, got[20] = { 0 };
+
+ isc_buffer_init(&b, &expect, sizeof(expect));
+ result = dns_opcode_totext(l->opcode, &b);
+ check_result(result, "dns_opcode_totext");
+
+ isc_buffer_init(&b, &got, sizeof(got));
+ result = dns_opcode_totext(msg->opcode, &b);
+ check_result(result, "dns_opcode_totext");
+
+ dighost_warning("Warning: Opcode mismatch: expected %s, got %s",
+ expect, got);
+
+ isc_refcount_increment0(&recvcount);
+ debug("recvcount=%" PRIuFAST32,
+ isc_refcount_current(&recvcount));
+ isc_nm_read(handle, recv_done, query);
+ goto keep_query;
+ }
+
+ if (msg->counts[DNS_SECTION_QUESTION] != 0) {
+ match = true;
+ for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
+ result == ISC_R_SUCCESS && match;
+ result = dns_message_nextname(msg, DNS_SECTION_QUESTION))
+ {
+ dns_name_t *name = NULL;
+ dns_rdataset_t *rdataset;
+
+ dns_message_currentname(msg, DNS_SECTION_QUESTION,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (l->rdtype != rdataset->type ||
+ l->rdclass != rdataset->rdclass ||
+ !dns_name_equal(l->name, name))
+ {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+ dns_name_format(name, namestr,
+ sizeof(namestr));
+ dns_rdatatype_format(rdataset->type,
+ typebuf,
+ sizeof(typebuf));
+ dns_rdataclass_format(rdataset->rdclass,
+ classbuf,
+ sizeof(classbuf));
+ dighost_warning(";; Question section "
+ "mismatch: got "
+ "%s/%s/%s",
+ namestr, typebuf,
+ classbuf);
+ match = false;
+ }
+ }
+ }
+
+ if (!match) {
+ if (l->tcp_mode) {
+ goto cancel_lookup;
+ }
+
+ /*
+ * We are still attached to query and the
+ * query->readhandle is also attached
+ */
+ isc_refcount_increment0(&recvcount);
+ debug("recvcount=%" PRIuFAST32,
+ isc_refcount_current(&recvcount));
+ isc_nm_read(handle, recv_done, query);
+ goto keep_query;
+ }
+ }
+
+ if (msg->rcode == dns_rcode_badvers && msg->opt != NULL &&
+ (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg)
+ {
+ /*
+ * Add minimum EDNS version required checks here if needed.
+ */
+ dighost_comments(l, "BADVERS, retrying with EDNS version %u.",
+ (unsigned int)newedns);
+ l->edns = newedns;
+ n = requeue_lookup(l, true);
+ if (l->trace && l->trace_root) {
+ n->rdtype = l->qrdtype;
+ }
+ goto cancel_lookup;
+ }
+
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 && !l->ignore &&
+ !l->tcp_mode)
+ {
+ if (l->cookie == NULL && l->sendcookie && msg->opt != NULL) {
+ process_opt(l, msg);
+ }
+ dighost_comments(l, "Truncated, retrying in TCP mode.");
+ n = requeue_lookup(l, true);
+ n->tcp_mode = true;
+ if (l->trace && l->trace_root) {
+ n->rdtype = l->qrdtype;
+ }
+ goto cancel_lookup;
+ }
+
+ if (msg->rcode == dns_rcode_badcookie && !l->tcp_mode &&
+ l->sendcookie && l->badcookie)
+ {
+ process_opt(l, msg);
+ if (msg->cc_ok) {
+ if (l->showbadcookie) {
+ dighost_printmessage(query, &b, msg, true);
+ dighost_received(isc_buffer_usedlength(&b),
+ &peer, query);
+ }
+ dighost_comments(l, "BADCOOKIE, retrying%s.",
+ l->seenbadcookie ? " in TCP mode"
+ : "");
+ n = requeue_lookup(l, true);
+ if (l->seenbadcookie) {
+ n->tcp_mode = true;
+ }
+ n->seenbadcookie = true;
+ if (l->trace && l->trace_root) {
+ n->rdtype = l->qrdtype;
+ }
+ goto cancel_lookup;
+ }
+ done_process_opt = true;
+ }
+
+ if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
+ (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
+ {
+ dig_query_t *next = ISC_LIST_NEXT(query, link);
+ if (l->current_query == query) {
+ query_detach(&l->current_query);
+ }
+ if (next != NULL) {
+ debug("sending query %p", next);
+ if (l->tcp_mode) {
+ start_tcp(next);
+ } else {
+ start_udp(next);
+ }
+ dighost_comments(l,
+ "Got %s from %s, trying next "
+ "server",
+ msg->rcode == dns_rcode_servfail
+ ? "SERVFAIL reply"
+ : "recursion not available",
+ query->servname);
+ if (check_if_queries_done(l, query)) {
+ goto cancel_lookup;
+ }
+
+ goto detach_query;
+ }
+ }
+
+ if (tsigkey != NULL) {
+ result = dns_tsig_verify(&b, msg, NULL, NULL);
+ if (result != ISC_R_SUCCESS) {
+ dighost_warning("Couldn't verify signature: %s",
+ isc_result_totext(result));
+ validated = false;
+ }
+ l->tsigctx = msg->tsigctx;
+ msg->tsigctx = NULL;
+ if (l->querysig != NULL) {
+ debug("freeing querysig buffer %p", l->querysig);
+ isc_buffer_free(&l->querysig);
+ }
+ result = dns_message_getquerytsig(msg, mctx, &l->querysig);
+ check_result(result, "dns_message_getquerytsig");
+ }
+
+ extrabytes = isc_buffer_remaininglength(&b);
+
+ debug("after parse");
+ if (l->doing_xfr && l->xfr_q == NULL) {
+ l->xfr_q = query;
+ /*
+ * Once we are in the XFR message, increase
+ * the timeout to much longer, so brief network
+ * outages won't cause the XFR to abort
+ */
+ if (timeout != INT_MAX && query->timer != NULL) {
+ unsigned int local_timeout;
+
+ if (timeout == 0) {
+ if (l->tcp_mode) {
+ local_timeout = TCP_TIMEOUT * 4000;
+ } else {
+ local_timeout = UDP_TIMEOUT * 4000;
+ }
+ } else {
+ if (timeout < (INT_MAX / 4)) {
+ local_timeout = timeout * 4000;
+ } else {
+ local_timeout = INT_MAX;
+ }
+ }
+
+ debug("have local timeout of %d", local_timeout);
+ isc_nmhandle_settimeout(query->handle, local_timeout);
+ }
+ }
+
+ if (!done_process_opt) {
+ if (l->cookie != NULL) {
+ if (msg->opt == NULL) {
+ dighost_warning("expected opt record in "
+ "response");
+ } else {
+ process_opt(l, msg);
+ }
+ } else if (l->sendcookie && msg->opt != NULL) {
+ process_opt(l, msg);
+ }
+ }
+
+ if (!l->doing_xfr || l->xfr_q == query) {
+ if (msg->rcode == dns_rcode_nxdomain &&
+ (l->origin != NULL || l->need_search))
+ {
+ if (!next_origin(l) || showsearch) {
+ dighost_printmessage(query, &b, msg, true);
+ dighost_received(isc_buffer_usedlength(&b),
+ &peer, query);
+ }
+ } else if (!l->trace && !l->ns_search_only) {
+ dighost_printmessage(query, &b, msg, true);
+ } else if (l->trace) {
+ int nl = 0;
+ int count = msg->counts[DNS_SECTION_ANSWER];
+
+ debug("in TRACE code");
+ if (!l->ns_search_only) {
+ dighost_printmessage(query, &b, msg, true);
+ }
+
+ l->rdtype = l->qrdtype;
+ if (l->trace_root || (l->ns_search_only && count > 0)) {
+ if (!l->trace_root) {
+ l->rdtype = dns_rdatatype_soa;
+ }
+ nl = followup_lookup(msg, query,
+ DNS_SECTION_ANSWER);
+ l->trace_root = false;
+ } else if (count == 0) {
+ nl = followup_lookup(msg, query,
+ DNS_SECTION_AUTHORITY);
+ }
+ if (nl == 0) {
+ docancel = true;
+ }
+ } else {
+ debug("in NSSEARCH code");
+
+ if (l->trace_root) {
+ /*
+ * This is the initial NS query.
+ */
+ int nl;
+
+ l->rdtype = dns_rdatatype_soa;
+ nl = followup_lookup(msg, query,
+ DNS_SECTION_ANSWER);
+ if (nl == 0) {
+ docancel = true;
+ }
+ l->trace_root = false;
+ usesearch = false;
+ } else {
+ /*
+ * This is a query in the followup lookup
+ */
+ dighost_printmessage(query, &b, msg, true);
+
+ docancel = check_if_queries_done(l, query);
+ }
+ }
+ }
+
+ if (l->pending) {
+ debug("still pending.");
+ }
+
+ if (l->doing_xfr) {
+ if (query != l->xfr_q) {
+ goto detach_query;
+ }
+ if (!docancel) {
+ docancel = check_for_more_data(l, query, msg, &peer,
+ region->length);
+ }
+ if (docancel) {
+ goto cancel_lookup;
+ }
+ /*
+ * check_for_more_data() will detach from query->readhandle
+ * and query on its own, as it needs to reuse the query and
+ * reattach to the readhandle in launch_next_query().
+ */
+ goto keep_query;
+ } else {
+ if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
+ dighost_received(isc_buffer_usedlength(&b), &peer,
+ query);
+ }
+
+ if (!l->ns_search_only) {
+ l->pending = false;
+ }
+ if (!l->ns_search_only || l->trace_root || docancel) {
+ goto cancel_lookup;
+ }
+ goto next_lookup;
+ }
+cancel_lookup:
+ docancel = true;
+next_lookup:
+ donext = true;
+detach_query:
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
+ if (docancel) {
+ cancel_lookup(l);
+ }
+keep_query:
+ if (msg != NULL) {
+ dns_message_detach(&msg);
+ }
+ lookup_detach(&l);
+ if (donext) {
+ clear_current_lookup();
+ }
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Turn a name into an address, using system-supplied routines. This is
+ * used in looking up server names, etc... and needs to use system-supplied
+ * routines, since they may be using a non-DNS system for these lookups.
+ */
+isc_result_t
+get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) {
+ int count;
+ isc_result_t result;
+ bool is_running;
+
+ is_running = isc_app_isrunning();
+ if (is_running) {
+ isc_app_block();
+ }
+ result = bind9_getaddresses(host, myport, sockaddr, 1, &count);
+ if (is_running) {
+ isc_app_unblock();
+ }
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ INSIST(count == 1);
+
+ return (ISC_R_SUCCESS);
+}
+
+int
+getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
+ isc_result_t result;
+ isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
+ isc_netaddr_t netaddr;
+ int count, i;
+ dig_server_t *srv;
+ char tmp[ISC_NETADDR_FORMATSIZE];
+
+ result = bind9_getaddresses(host, 0, sockaddrs, DIG_MAX_ADDRESSES,
+ &count);
+ if (resultp != NULL) {
+ *resultp = result;
+ }
+ if (result != ISC_R_SUCCESS) {
+ if (resultp == NULL) {
+ fatal("couldn't get address for '%s': %s", host,
+ isc_result_totext(result));
+ }
+ return (0);
+ }
+
+ for (i = 0; i < count; i++) {
+ isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
+ isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
+ srv = make_server(tmp, host);
+ ISC_LIST_APPEND(lookup->my_server_list, srv, link);
+ }
+
+ return (count);
+}
+
+/*%
+ * Initiate either a TCP or UDP lookup
+ */
+void
+do_lookup(dig_lookup_t *lookup) {
+ dig_query_t *query;
+
+ REQUIRE(lookup != NULL);
+
+ debug("do_lookup()");
+ lookup->pending = true;
+ query = ISC_LIST_HEAD(lookup->q);
+ if (query != NULL) {
+ REQUIRE(DIG_VALID_QUERY(query));
+ if (lookup->tcp_mode) {
+ start_tcp(query);
+ } else {
+ start_udp(query);
+ }
+ }
+}
+
+/*%
+ * Start everything in action upon task startup.
+ */
+void
+onrun_callback(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ isc_event_free(&event);
+ LOCK_LOOKUP;
+ start_lookup();
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Make everything on the lookup queue go away. Mainly used by the
+ * SIGINT handler.
+ */
+void
+cancel_all(void) {
+ dig_lookup_t *l, *n;
+ dig_query_t *q, *nq;
+
+ debug("cancel_all()");
+
+ LOCK_LOOKUP;
+ if (free_now) {
+ UNLOCK_LOOKUP;
+ return;
+ }
+ atomic_store(&cancel_now, true);
+ while (current_lookup != NULL) {
+ for (q = ISC_LIST_HEAD(current_lookup->q); q != NULL; q = nq) {
+ nq = ISC_LIST_NEXT(q, link);
+ debug("canceling pending query %p, belonging to %p", q,
+ current_lookup);
+ q->canceled = true;
+ if (q->readhandle != NULL &&
+ !isc_nm_is_http_handle(q->readhandle))
+ {
+ isc_nm_cancelread(q->readhandle);
+ }
+ query_detach(&q);
+ }
+
+ /*
+ * current_lookup could have been detached via query_detach().
+ */
+ if (current_lookup != NULL) {
+ lookup_detach(&current_lookup);
+ }
+ }
+ l = ISC_LIST_HEAD(lookup_list);
+ while (l != NULL) {
+ n = ISC_LIST_NEXT(l, link);
+ ISC_LIST_DEQUEUE(lookup_list, l, link);
+ lookup_detach(&l);
+ l = n;
+ }
+ UNLOCK_LOOKUP;
+}
+
+void
+cleanup_openssl_refs(void) {
+ if (tsigkey != NULL) {
+ debug("freeing TSIG key %p", tsigkey);
+ dns_tsigkey_detach(&tsigkey);
+ }
+
+ if (sig0key != NULL) {
+ debug("freeing SIG(0) key %p", sig0key);
+ dst_key_free(&sig0key);
+ }
+
+ if (is_dst_up) {
+ debug("destroy DST lib");
+ dst_lib_destroy();
+ is_dst_up = false;
+ }
+}
+
+/*%
+ * Destroy all of the libs we are using, and get everything ready for a
+ * clean shutdown.
+ */
+void
+destroy_libs(void) {
+ if (keep != NULL) {
+ isc_nmhandle_detach(&keep);
+ }
+ debug("destroy_libs()");
+ if (global_task != NULL) {
+ debug("freeing task");
+ isc_task_detach(&global_task);
+ }
+
+ isc_managers_destroy(&netmgr, &taskmgr, NULL);
+
+ LOCK_LOOKUP;
+ isc_refcount_destroy(&recvcount);
+ isc_refcount_destroy(&sendcount);
+
+ INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
+ INSIST(current_lookup == NULL);
+ INSIST(!free_now);
+
+ free_now = true;
+
+ flush_server_list();
+
+ clear_searchlist();
+
+ cleanup_openssl_refs();
+
+ if (namebuf != NULL) {
+ debug("freeing key %p", tsigkey);
+ isc_buffer_free(&namebuf);
+ }
+
+ UNLOCK_LOOKUP;
+ isc_mutex_destroy(&lookup_lock);
+
+ debug("Removing log context");
+ isc_log_destroy(&lctx);
+
+ debug("Destroy memory");
+ if (memdebugging != 0) {
+ isc_mem_stats(mctx, stderr);
+ }
+ if (mctx != NULL) {
+ isc_mem_destroy(&mctx);
+ }
+}
+
+#ifdef HAVE_LIBIDN2
+static isc_result_t
+idn_output_filter(isc_buffer_t *buffer, unsigned int used_org) {
+ char src[MXNAME], *dst = NULL;
+ size_t srclen, dstlen;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ /*
+ * Copy name from 'buffer' to 'src' and terminate it with NULL.
+ */
+ srclen = isc_buffer_usedlength(buffer) - used_org;
+ if (srclen >= sizeof(src)) {
+ warn("Input name too long to perform IDN conversion");
+ goto cleanup;
+ }
+ memmove(src, (char *)isc_buffer_base(buffer) + used_org, srclen);
+ src[srclen] = '\0';
+
+ systemlocale(LC_ALL);
+
+ /*
+ * Convert 'src' to the current locale's character encoding.
+ */
+ idn_ace_to_locale(src, &dst);
+
+ resetlocale(LC_ALL);
+
+ /*
+ * Check whether the converted name will fit back into 'buffer'.
+ */
+ dstlen = strlen(dst);
+ if (isc_buffer_length(buffer) < used_org + dstlen) {
+ result = ISC_R_NOSPACE;
+ goto cleanup;
+ }
+
+ /*
+ * Put the converted name back into 'buffer'.
+ */
+ isc_buffer_subtract(buffer, srclen);
+ memmove(isc_buffer_used(buffer), dst, dstlen);
+ isc_buffer_add(buffer, dstlen);
+
+ /*
+ * Clean up.
+ */
+cleanup:
+ if (dst != NULL) {
+ idn2_free(dst);
+ }
+
+ return (result);
+}
+
+/*%
+ * Convert 'src', which is a string using the current locale's character
+ * encoding, into an ACE string suitable for use in the DNS, storing the
+ * conversion result in 'dst', which is 'dstlen' bytes large.
+ *
+ * 'dst' MUST be large enough to hold any valid domain name.
+ */
+static void
+idn_locale_to_ace(const char *src, char *dst, size_t dstlen) {
+ const char *final_src;
+ char *ascii_src;
+ int res;
+
+ systemlocale(LC_ALL);
+
+ /*
+ * We trust libidn2 to return an error if 'src' is too large to be a
+ * valid domain name.
+ */
+ res = idn2_to_ascii_lz(src, &ascii_src, IDN2_NONTRANSITIONAL);
+ if (res == IDN2_DISALLOWED) {
+ res = idn2_to_ascii_lz(src, &ascii_src, IDN2_TRANSITIONAL);
+ }
+ if (res != IDN2_OK) {
+ fatal("'%s' is not a legal IDNA2008 name (%s), use +noidnin",
+ src, idn2_strerror(res));
+ }
+
+ /*
+ * idn2_to_ascii_lz() normalizes all strings to lower case, but we
+ * generally don't want to lowercase all input strings; make sure to
+ * return the original case if the two strings differ only in case.
+ */
+ final_src = (strcasecmp(src, ascii_src) == 0 ? src : ascii_src);
+
+ (void)strlcpy(dst, final_src, dstlen);
+
+ idn2_free(ascii_src);
+
+ resetlocale(LC_ALL);
+}
+
+/*%
+ * Convert 'src', which is an ACE string suitable for use in the DNS, into a
+ * string using the current locale's character encoding, storing the conversion
+ * result in 'dst'.
+ *
+ * The caller MUST subsequently release 'dst' using idn2_free().
+ */
+static void
+idn_ace_to_locale(const char *src, char **dst) {
+ char *local_src, *utf8_src;
+ int res;
+
+ systemlocale(LC_ALL);
+
+ /*
+ * We need to:
+ *
+ * 1) check whether 'src' is a valid IDNA2008 name,
+ * 2) if it is, output it in the current locale's character encoding.
+ *
+ * Unlike idn2_to_ascii_*(), idn2_to_unicode_*() functions are unable
+ * to perform IDNA2008 validity checks. Thus, we need to decode any
+ * Punycode in 'src', check if the resulting name is a valid IDNA2008
+ * name, and only once we ensure it is, output that name in the current
+ * locale's character encoding.
+ *
+ * We could just use idn2_to_unicode_8zlz() + idn2_to_ascii_lz(), but
+ * then we would not be able to universally tell invalid names and
+ * character encoding errors apart (if the current locale uses ASCII
+ * for character encoding, the former function would fail even for a
+ * valid IDNA2008 name, as long as it contained any non-ASCII
+ * character). Thus, we need to take a longer route.
+ *
+ * First, convert 'src' to UTF-8, ignoring the current locale.
+ */
+ res = idn2_to_unicode_8z8z(src, &utf8_src, 0);
+ if (res != IDN2_OK) {
+ fatal("Bad ACE string '%s' (%s), use +noidnout", src,
+ idn2_strerror(res));
+ }
+
+ /*
+ * Then, check whether decoded 'src' is a valid IDNA2008 name
+ * and if disallowed character is found, fallback to IDNA2003.
+ */
+ res = idn2_to_ascii_8z(utf8_src, NULL, IDN2_NONTRANSITIONAL);
+ if (res == IDN2_DISALLOWED) {
+ res = idn2_to_ascii_8z(utf8_src, NULL, IDN2_TRANSITIONAL);
+ }
+ if (res != IDN2_OK) {
+ fatal("'%s' is not a legal IDNA2008 name (%s), use +noidnout",
+ src, idn2_strerror(res));
+ }
+
+ /*
+ * Finally, try converting the decoded 'src' into the current locale's
+ * character encoding.
+ */
+ res = idn2_to_unicode_8zlz(utf8_src, &local_src, 0);
+ if (res != IDN2_OK) {
+ static bool warned = false;
+
+ res = idn2_to_ascii_8z(utf8_src, &local_src, 0);
+ if (res != IDN2_OK) {
+ fatal("Cannot represent '%s' "
+ "in the current locale nor ascii (%s), "
+ "use +noidnout or a different locale",
+ src, idn2_strerror(res));
+ } else if (!warned) {
+ fprintf(stderr,
+ ";; Warning: cannot represent '%s' "
+ "in the current locale",
+ local_src);
+ warned = true;
+ }
+ }
+
+ /*
+ * Free the interim conversion result.
+ */
+ idn2_free(utf8_src);
+
+ *dst = local_src;
+
+ resetlocale(LC_ALL);
+}
+#endif /* HAVE_LIBIDN2 */
+
+void
+dig_idnsetup(dig_lookup_t *lookup, bool active) {
+#ifdef HAVE_LIBIDN2
+ isc_result_t result;
+ result = dns_name_settotextfilter(
+ (active && lookup->idnout) ? idn_output_filter : NULL);
+ check_result(result, "dns_name_settotextfilter");
+#else
+ UNUSED(lookup);
+ UNUSED(active);
+ return;
+#endif /* HAVE_LIBIDN2 */
+}
+
+bool
+dig_lookup_is_tls(const dig_lookup_t *lookup) {
+ if (lookup->tls_mode || (lookup->tls_ca_set && !lookup->https_mode)) {
+ return (true);
+ }
+
+ return (false);
+}
diff --git a/bin/dig/dighost.h b/bin/dig/dighost.h
new file mode 100644
index 0000000..227c315
--- /dev/null
+++ b/bin/dig/dighost.h
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/list.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/netmgr.h>
+#include <isc/print.h>
+#include <isc/refcount.h>
+#include <isc/sockaddr.h>
+#include <isc/time.h>
+
+#include <dns/rdatalist.h>
+
+#include <dst/dst.h>
+
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#endif /* ifdef __APPLE__ */
+
+#define MXSERV 20
+#define MXNAME (DNS_NAME_MAXTEXT + 1)
+#define MXRD 32
+/*% Buffer Size */
+#define BUFSIZE 512
+#define COMMSIZE 0xffff
+#ifndef RESOLV_CONF
+/*% location of resolve.conf */
+#define RESOLV_CONF "/etc/resolv.conf"
+#endif /* ifndef RESOLV_CONF */
+/*% output buffer */
+#define OUTPUTBUF 32767
+/*% Max RR Limit */
+#define MAXRRLIMIT 0xffffffff
+#define MAXTIMEOUT 0xffff
+/*% Max number of tries */
+#define MAXTRIES 0xffffffff
+/*% Max number of dots */
+#define MAXNDOTS 0xffff
+/*% Max number of ports */
+#define MAXPORT 0xffff
+/*% Max serial number */
+#define MAXSERIAL 0xffffffff
+/*% Max query ID */
+#define MAXQID 0xffff
+
+/*% Default TCP Timeout */
+#define TCP_TIMEOUT 10
+/*% Default UDP Timeout */
+#define UDP_TIMEOUT 5
+
+#define SERVER_TIMEOUT 1
+
+#define LOOKUP_LIMIT 64
+
+#define DEFAULT_EDNS_VERSION 0
+#define DEFAULT_EDNS_BUFSIZE 1232
+
+#define DEFAULT_HTTPS_QUERY "?dns="
+
+/*%
+ * Lookup_limit is just a limiter, keeping too many lookups from being
+ * created. It's job is mainly to prevent the program from running away
+ * in a tight loop of constant lookups. It's value is arbitrary.
+ */
+
+ISC_LANG_BEGINDECLS
+
+typedef struct dig_lookup dig_lookup_t;
+typedef struct dig_query dig_query_t;
+typedef struct dig_server dig_server_t;
+typedef ISC_LIST(dig_server_t) dig_serverlist_t;
+typedef struct dig_searchlist dig_searchlist_t;
+
+#define DIG_LOOKUP_MAGIC ISC_MAGIC('D', 'i', 'g', 'l')
+
+#define DIG_VALID_LOOKUP(x) ISC_MAGIC_VALID((x), DIG_LOOKUP_MAGIC)
+
+#define DIG_QUERY_MAGIC ISC_MAGIC('D', 'i', 'g', 'q')
+
+#define DIG_VALID_QUERY(x) ISC_MAGIC_VALID((x), DIG_QUERY_MAGIC)
+
+/*% The dig_lookup structure */
+struct dig_lookup {
+ unsigned int magic;
+ isc_refcount_t references;
+ bool aaonly, adflag, badcookie, besteffort, cdflag, cleared, comments,
+ dns64prefix, dnssec, doing_xfr, done_as_is, ednsneg, expandaaaa,
+ expire, fuzzing, header_only, identify, /*%< Append an "on
+ server <foo>" message
+ */
+ identify_previous_line, /*% Prepend a "Nameserver <foo>:"
+ message, with newline and tab */
+ idnin, idnout, ignore, multiline, need_search, new_search,
+ noclass, nocrypto, nottl, ns_search_only, /*%< dig +nssearch,
+ host -C */
+ ns_search_success, nsid, /*% Name Server ID (RFC 5001) */
+ onesoa, pending, /*%< Pending a successful answer */
+ print_unknown_format, qr, raflag, recurse, section_additional,
+ section_answer, section_authority, section_question,
+ seenbadcookie, sendcookie, servfail_stops,
+ setqid, /*% use a speciied query ID */
+ showbadcookie, stats, tcflag, tcp_keepalive, tcp_mode,
+ tcp_mode_set, tls_mode, /*% connect using TLS */
+ trace, /*% dig +trace */
+ trace_root, /*% initial query for either +trace or +nssearch */
+ ttlunits, use_usec, waiting_connect, zflag;
+ char textname[MXNAME]; /*% Name we're going to be looking up */
+ char cmdline[MXNAME];
+ dns_rdatatype_t rdtype;
+ dns_rdatatype_t qrdtype;
+ dns_rdataclass_t rdclass;
+ bool rdtypeset;
+ bool rdclassset;
+ char name_space[BUFSIZE];
+ char oname_space[BUFSIZE];
+ isc_buffer_t namebuf;
+ isc_buffer_t onamebuf;
+ isc_buffer_t renderbuf;
+ char *sendspace;
+ dns_name_t *name;
+ isc_interval_t interval;
+ dns_message_t *sendmsg;
+ dns_name_t *oname;
+ ISC_LINK(dig_lookup_t) link;
+ ISC_LIST(dig_query_t) q;
+ ISC_LIST(dig_query_t) connecting;
+ dig_query_t *current_query;
+ dig_serverlist_t my_server_list;
+ dig_searchlist_t *origin;
+ dig_query_t *xfr_q;
+ uint32_t retries;
+ int nsfound;
+ int16_t udpsize;
+ int16_t edns;
+ int16_t padding;
+ uint32_t ixfr_serial;
+ isc_buffer_t rdatabuf;
+ char rdatastore[MXNAME];
+ dst_context_t *tsigctx;
+ isc_buffer_t *querysig;
+ uint32_t msgcounter;
+ dns_fixedname_t fdomain;
+ isc_sockaddr_t *ecs_addr;
+ char *cookie;
+ dns_ednsopt_t *ednsopts;
+ unsigned int ednsoptscnt;
+ unsigned int ednsflags;
+ dns_opcode_t opcode;
+ int rrcomments;
+ uint16_t qid;
+ struct {
+ bool http_plain;
+ bool https_mode;
+ bool https_get;
+ char *https_path;
+ };
+ struct {
+ bool tls_ca_set;
+ char *tls_ca_file;
+ bool tls_hostname_set;
+ char *tls_hostname;
+ bool tls_cert_file_set;
+ char *tls_cert_file;
+ bool tls_key_file_set;
+ char *tls_key_file;
+ isc_tlsctx_cache_t *tls_ctx_cache;
+ };
+ isc_stdtime_t fuzztime;
+};
+
+/*% The dig_query structure */
+struct dig_query {
+ unsigned int magic;
+ dig_lookup_t *lookup;
+ bool started;
+ bool first_soa_rcvd;
+ bool second_rr_rcvd;
+ bool first_repeat_rcvd;
+ bool warn_id;
+ bool canceled;
+ uint32_t first_rr_serial;
+ uint32_t second_rr_serial;
+ uint32_t msg_count;
+ uint32_t rr_count;
+ bool ixfr_axfr;
+ char *servname;
+ char *userarg;
+ isc_buffer_t sendbuf;
+ char *recvspace, *tmpsendspace, lengthspace[4];
+ isc_refcount_t references;
+ isc_nmhandle_t *handle;
+ isc_nmhandle_t *readhandle;
+ isc_nmhandle_t *sendhandle;
+ ISC_LINK(dig_query_t) link;
+ ISC_LINK(dig_query_t) clink;
+ isc_sockaddr_t sockaddr;
+ isc_time_t time_sent;
+ isc_time_t time_recv;
+ uint64_t byte_count;
+ isc_timer_t *timer;
+};
+
+struct dig_server {
+ char servername[MXNAME];
+ char userarg[MXNAME];
+ ISC_LINK(dig_server_t) link;
+};
+
+struct dig_searchlist {
+ char origin[MXNAME];
+ ISC_LINK(dig_searchlist_t) link;
+};
+
+typedef ISC_LIST(dig_searchlist_t) dig_searchlistlist_t;
+typedef ISC_LIST(dig_lookup_t) dig_lookuplist_t;
+
+/*
+ * Externals from dighost.c
+ */
+
+extern dig_lookuplist_t lookup_list;
+extern dig_serverlist_t server_list;
+extern dig_searchlistlist_t search_list;
+extern unsigned int extrabytes;
+
+extern bool check_ra, have_ipv4, have_ipv6, specified_source, usesearch,
+ showsearch, yaml;
+extern in_port_t port;
+extern bool port_set;
+extern unsigned int timeout;
+extern isc_mem_t *mctx;
+extern isc_refcount_t sendcount;
+extern int ndots;
+extern int lookup_counter;
+extern int exitcode;
+extern isc_sockaddr_t localaddr;
+extern char keynametext[MXNAME];
+extern char keyfile[MXNAME];
+extern char keysecret[MXNAME];
+extern const dns_name_t *hmacname;
+extern unsigned int digestbits;
+extern dns_tsigkey_t *tsigkey;
+extern bool validated;
+extern isc_taskmgr_t *taskmgr;
+extern isc_task_t *global_task;
+extern bool free_now;
+extern bool debugging, debugtiming, memdebugging;
+extern bool keep_open;
+
+extern char *progname;
+extern int tries;
+extern int fatalexit;
+extern bool verbose;
+
+/*
+ * Routines in dighost.c.
+ */
+isc_result_t
+get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr);
+
+int
+getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp);
+
+isc_result_t
+get_reverse(char *reverse, size_t len, char *value, bool strict);
+
+noreturn void
+fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+warn(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+noreturn void
+digexit(void);
+
+void
+cleanup_openssl_refs(void);
+
+void
+debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+check_result(isc_result_t result, const char *msg);
+
+bool
+setup_lookup(dig_lookup_t *lookup);
+
+void
+destroy_lookup(dig_lookup_t *lookup);
+
+void
+do_lookup(dig_lookup_t *lookup);
+
+void
+start_lookup(void);
+
+void
+onrun_callback(isc_task_t *task, isc_event_t *event);
+
+int
+dhmain(int argc, char **argv);
+
+void
+setup_libs(void);
+
+void
+setup_system(bool ipv4only, bool ipv6only);
+
+isc_result_t
+parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc);
+
+isc_result_t
+parse_xint(uint32_t *uip, const char *value, uint32_t max, const char *desc);
+
+isc_result_t
+parse_netprefix(isc_sockaddr_t **sap, const char *value);
+
+void
+parse_hmac(const char *hmacstr);
+
+dig_lookup_t *
+requeue_lookup(dig_lookup_t *lookold, bool servers);
+
+dig_lookup_t *
+make_empty_lookup(void);
+
+dig_lookup_t *
+clone_lookup(dig_lookup_t *lookold, bool servers);
+
+dig_server_t *
+make_server(const char *servname, const char *userarg);
+
+void
+flush_server_list(void);
+
+void
+set_nameserver(char *opt);
+
+void
+clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest);
+
+void
+cancel_all(void);
+
+void
+destroy_libs(void);
+
+void
+set_search_domain(char *domain);
+
+/*
+ * Routines to be defined in dig.c, host.c, and nslookup.c. and
+ * then assigned to the appropriate function pointer
+ */
+extern isc_result_t (*dighost_printmessage)(dig_query_t *query,
+ const isc_buffer_t *msgbuf,
+ dns_message_t *msg, bool headers);
+
+/*
+ * Print an error message in the appropriate format.
+ */
+extern void (*dighost_error)(const char *format, ...);
+
+/*
+ * Print a warning message in the appropriate format.
+ */
+extern void (*dighost_warning)(const char *format, ...);
+
+/*
+ * Print a comment in the appropriate format.
+ */
+extern void (*dighost_comments)(dig_lookup_t *lookup, const char *format, ...);
+
+/*%<
+ * Print the final result of the lookup.
+ */
+
+extern void (*dighost_received)(unsigned int bytes, isc_sockaddr_t *from,
+ dig_query_t *query);
+/*%<
+ * Print a message about where and when the response
+ * was received from, like the final comment in the
+ * output of "dig".
+ */
+
+extern void (*dighost_trying)(char *frm, dig_lookup_t *lookup);
+
+extern void (*dighost_shutdown)(void);
+
+extern void (*dighost_pre_exit_hook)(void);
+
+void
+save_opt(dig_lookup_t *lookup, char *code, char *value);
+
+void
+setup_file_key(void);
+void
+setup_text_key(void);
+
+/*
+ * Routines exported from dig.c for use by dig for iOS
+ */
+
+/*%
+ * Call once only to set up libraries, parse global
+ * parameters and initial command line query parameters
+ */
+void
+dig_setup(int argc, char **argv);
+
+/*%
+ * Call to supply new parameters for the next lookup
+ */
+void
+dig_query_setup(bool, bool, int argc, char **argv);
+
+/*%
+ * set the main application event cycle running
+ */
+void
+dig_startup(void);
+
+/*%
+ * Initiates the next lookup cycle
+ */
+void
+dig_query_start(void);
+
+/*%
+ * Activate/deactivate IDN filtering of output.
+ */
+void
+dig_idnsetup(dig_lookup_t *lookup, bool active);
+
+/*%
+ * Cleans up the application
+ */
+void
+dig_shutdown(void);
+
+bool
+dig_lookup_is_tls(const dig_lookup_t *lookup);
+
+ISC_LANG_ENDDECLS
diff --git a/bin/dig/host.c b/bin/dig/host.c
new file mode 100644
index 0000000..011587a
--- /dev/null
+++ b/bin/dig/host.c
@@ -0,0 +1,931 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/attributes.h>
+#include <isc/commandline.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/fixedname.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+
+#include "dighost.h"
+
+static bool short_form = true, listed_server = false;
+static bool default_lookups = true;
+static int seen_error = -1;
+static bool list_addresses = true;
+static bool list_almost_all = false;
+static dns_rdatatype_t list_type = dns_rdatatype_a;
+static bool printed_server = false;
+static bool ipv4only = false, ipv6only = false;
+
+static const char *opcodetext[] = { "QUERY", "IQUERY", "STATUS",
+ "RESERVED3", "NOTIFY", "UPDATE",
+ "RESERVED6", "RESERVED7", "RESERVED8",
+ "RESERVED9", "RESERVED10", "RESERVED11",
+ "RESERVED12", "RESERVED13", "RESERVED14",
+ "RESERVED15" };
+
+static const char *rcodetext[] = { "NOERROR", "FORMERR", "SERVFAIL",
+ "NXDOMAIN", "NOTIMP", "REFUSED",
+ "YXDOMAIN", "YXRRSET", "NXRRSET",
+ "NOTAUTH", "NOTZONE", "RESERVED11",
+ "RESERVED12", "RESERVED13", "RESERVED14",
+ "RESERVED15", "BADVERS" };
+
+struct rtype {
+ unsigned int type;
+ const char *text;
+};
+
+struct rtype rtypes[] = { { 1, "has address" },
+ { 2, "name server" },
+ { 5, "is an alias for" },
+ { 11, "has well known services" },
+ { 12, "domain name pointer" },
+ { 13, "host information" },
+ { 15, "mail is handled by" },
+ { 16, "descriptive text" },
+ { 19, "x25 address" },
+ { 20, "ISDN address" },
+ { 24, "has signature" },
+ { 25, "has key" },
+ { 28, "has IPv6 address" },
+ { 29, "location" },
+ { 0, NULL } };
+
+static char *
+rcode_totext(dns_rcode_t rcode) {
+ static char buf[sizeof("?65535")];
+ union {
+ const char *consttext;
+ char *deconsttext;
+ } totext;
+
+ if (rcode >= (sizeof(rcodetext) / sizeof(rcodetext[0]))) {
+ snprintf(buf, sizeof(buf), "?%u", rcode);
+ totext.deconsttext = buf;
+ } else {
+ totext.consttext = rcodetext[rcode];
+ }
+ return (totext.deconsttext);
+}
+
+noreturn static void
+show_usage(void);
+
+static void
+show_usage(void) {
+ fprintf(stderr,
+ "Usage: host [-aCdilrTvVw] [-c class] [-N ndots] [-t type] [-W "
+ "time]\n"
+ " [-R number] [-m flag] [-p port] hostname "
+ "[server]\n"
+ " -a is equivalent to -v -t ANY\n"
+ " -A is like -a but omits RRSIG, NSEC, NSEC3\n"
+ " -c specifies query class for non-IN data\n"
+ " -C compares SOA records on authoritative nameservers\n"
+ " -d is equivalent to -v\n"
+ " -l lists all hosts in a domain, using AXFR\n"
+ " -m set memory debugging flag (trace|record|usage)\n"
+ " -N changes the number of dots allowed before root "
+ "lookup "
+ "is done\n"
+ " -p specifies the port on the server to query\n"
+ " -r disables recursive processing\n"
+ " -R specifies number of retries for UDP packets\n"
+ " -s a SERVFAIL response should stop query\n"
+ " -t specifies the query type\n"
+ " -T enables TCP/IP mode\n"
+ " -U enables UDP mode\n"
+ " -v enables verbose output\n"
+ " -V print version number and exit\n"
+ " -w specifies to wait forever for a reply\n"
+ " -W specifies how long to wait for a reply\n"
+ " -4 use IPv4 query transport only\n"
+ " -6 use IPv6 query transport only\n");
+ exit(1);
+}
+
+static void
+host_shutdown(void) {
+ (void)isc_app_shutdown();
+}
+
+static void
+received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
+ isc_time_t now;
+ int diff;
+
+ if (!short_form) {
+ char fromtext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(from, fromtext, sizeof(fromtext));
+ if (query->lookup->use_usec) {
+ TIME_NOW_HIRES(&now);
+ } else {
+ TIME_NOW(&now);
+ }
+ diff = (int)isc_time_microdiff(&now, &query->time_sent);
+ printf("Received %u bytes from %s in %d ms\n", bytes, fromtext,
+ diff / 1000);
+ }
+}
+
+static void
+trying(char *frm, dig_lookup_t *lookup) {
+ UNUSED(lookup);
+
+ if (!short_form) {
+ printf("Trying \"%s\"\n", frm);
+ }
+}
+
+static void
+say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata,
+ dig_query_t *query) {
+ isc_buffer_t *b = NULL;
+ char namestr[DNS_NAME_FORMATSIZE];
+ isc_region_t r;
+ isc_result_t result;
+ unsigned int bufsize = BUFSIZ;
+
+ dns_name_format(name, namestr, sizeof(namestr));
+retry:
+ isc_buffer_allocate(mctx, &b, bufsize);
+ result = dns_rdata_totext(rdata, NULL, b);
+ if (result == ISC_R_NOSPACE) {
+ isc_buffer_free(&b);
+ bufsize *= 2;
+ goto retry;
+ }
+ check_result(result, "dns_rdata_totext");
+ isc_buffer_usedregion(b, &r);
+ if (query->lookup->identify_previous_line) {
+ printf("Nameserver %s:\n\t", query->servname);
+ }
+ printf("%s %s %.*s", namestr, msg, (int)r.length, (char *)r.base);
+ if (query->lookup->identify) {
+ printf(" on server %s", query->servname);
+ }
+ printf("\n");
+ isc_buffer_free(&b);
+}
+
+static isc_result_t
+printsection(dns_message_t *msg, dns_section_t sectionid,
+ const char *section_name, bool headers, dig_query_t *query) {
+ dns_name_t *name, *print_name;
+ dns_rdataset_t *rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t target;
+ isc_result_t result, loopresult;
+ isc_region_t r;
+ dns_name_t empty_name;
+ char tbuf[4096] = { 0 };
+ bool first;
+ bool no_rdata = (sectionid == DNS_SECTION_QUESTION);
+
+ if (headers) {
+ printf(";; %s SECTION:\n", section_name);
+ }
+
+ dns_name_init(&empty_name, NULL);
+
+ result = dns_message_firstname(msg, sectionid);
+ if (result == ISC_R_NOMORE) {
+ return (ISC_R_SUCCESS);
+ } else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, sectionid, &name);
+
+ isc_buffer_init(&target, tbuf, sizeof(tbuf));
+ first = true;
+ print_name = name;
+
+ for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (query->lookup->rdtype == dns_rdatatype_axfr &&
+ !((!list_addresses &&
+ (list_type == dns_rdatatype_any ||
+ rdataset->type == list_type)) ||
+ (list_addresses &&
+ (rdataset->type == dns_rdatatype_a ||
+ rdataset->type == dns_rdatatype_aaaa ||
+ rdataset->type == dns_rdatatype_ns ||
+ rdataset->type == dns_rdatatype_ptr))))
+ {
+ continue;
+ }
+ if (list_almost_all &&
+ (rdataset->type == dns_rdatatype_rrsig ||
+ rdataset->type == dns_rdatatype_nsec ||
+ rdataset->type == dns_rdatatype_nsec3))
+ {
+ continue;
+ }
+ if (!short_form) {
+ result = dns_rdataset_totext(rdataset,
+ print_name, false,
+ no_rdata, &target);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+#ifdef USEINITALWS
+ if (first) {
+ print_name = &empty_name;
+ first = false;
+ }
+#else /* ifdef USEINITALWS */
+ UNUSED(first); /* Shut up compiler. */
+#endif /* ifdef USEINITALWS */
+ } else {
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ struct rtype *t;
+ const char *rtt;
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char typebuf2[DNS_RDATATYPE_FORMATSIZE +
+ 20];
+ dns_rdataset_current(rdataset, &rdata);
+
+ for (t = rtypes; t->text != NULL; t++) {
+ if (t->type == rdata.type) {
+ rtt = t->text;
+ goto found;
+ }
+ }
+
+ dns_rdatatype_format(rdata.type,
+ typebuf,
+ sizeof(typebuf));
+ snprintf(typebuf2, sizeof(typebuf2),
+ "has %s record", typebuf);
+ rtt = typebuf2;
+ found:
+ say_message(print_name, rtt, &rdata,
+ query);
+ dns_rdata_reset(&rdata);
+ loopresult =
+ dns_rdataset_next(rdataset);
+ }
+ }
+ }
+ if (!short_form) {
+ isc_buffer_usedregion(&target, &r);
+ if (no_rdata) {
+ printf(";%.*s", (int)r.length, (char *)r.base);
+ } else {
+ printf("%.*s", (int)r.length, (char *)r.base);
+ }
+ }
+
+ result = dns_message_nextname(msg, sectionid);
+ if (result == ISC_R_NOMORE) {
+ break;
+ } else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+printrdata(dns_message_t *msg, dns_rdataset_t *rdataset,
+ const dns_name_t *owner, const char *set_name, bool headers) {
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_region_t r;
+ char tbuf[4096];
+
+ UNUSED(msg);
+ if (headers) {
+ printf(";; %s SECTION:\n", set_name);
+ }
+
+ isc_buffer_init(&target, tbuf, sizeof(tbuf));
+
+ result = dns_rdataset_totext(rdataset, owner, false, false, &target);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ isc_buffer_usedregion(&target, &r);
+ printf("%.*s", (int)r.length, (char *)r.base);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+chase_cnamechain(dns_message_t *msg, dns_name_t *qname) {
+ isc_result_t result;
+ dns_rdataset_t *rdataset;
+ dns_rdata_cname_t cname;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int i = msg->counts[DNS_SECTION_ANSWER];
+
+ while (i-- > 0) {
+ rdataset = NULL;
+ result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
+ dns_rdatatype_cname, 0, NULL,
+ &rdataset);
+ if (result != ISC_R_SUCCESS) {
+ return;
+ }
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "dns_rdataset_first");
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ dns_name_copy(&cname.cname, qname);
+ dns_rdata_freestruct(&cname);
+ }
+}
+
+static isc_result_t
+printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg,
+ bool headers) {
+ bool did_flag = false;
+ dns_rdataset_t *opt, *tsig = NULL;
+ const dns_name_t *tsigname;
+ isc_result_t result = ISC_R_SUCCESS;
+ int force_error;
+
+ UNUSED(msgbuf);
+ UNUSED(headers);
+
+ /*
+ * We get called multiple times.
+ * Preserve any existing error status.
+ */
+ force_error = (seen_error == 1) ? 1 : 0;
+ seen_error = 1;
+ if (listed_server && !printed_server) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+
+ printf("Using domain server:\n");
+ printf("Name: %s\n", query->userarg);
+ isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
+ printf("Address: %s\n", sockstr);
+ printf("Aliases: \n\n");
+ printed_server = true;
+ }
+
+ if (msg->rcode != 0) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(query->lookup->name, namestr, sizeof(namestr));
+
+ if (query->lookup->identify_previous_line) {
+ printf("Nameserver %s:\n\t%s not found: %d(%s)\n",
+ query->servname,
+ (msg->rcode != dns_rcode_nxdomain)
+ ? namestr
+ : query->lookup->textname,
+ msg->rcode, rcode_totext(msg->rcode));
+ } else {
+ printf("Host %s not found: %d(%s)\n",
+ (msg->rcode != dns_rcode_nxdomain)
+ ? namestr
+ : query->lookup->textname,
+ msg->rcode, rcode_totext(msg->rcode));
+ }
+ return (ISC_R_SUCCESS);
+ }
+
+ if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dig_lookup_t *lookup;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+
+ /* Add AAAA and MX lookups. */
+ name = dns_fixedname_initname(&fixed);
+ dns_name_copy(query->lookup->name, name);
+ chase_cnamechain(msg, name);
+ dns_name_format(name, namestr, sizeof(namestr));
+ lookup = clone_lookup(query->lookup, false);
+ if (lookup != NULL) {
+ strlcpy(lookup->textname, namestr,
+ sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_aaaa;
+ lookup->rdtypeset = true;
+ lookup->origin = NULL;
+ lookup->retries = tries;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ lookup = clone_lookup(query->lookup, false);
+ if (lookup != NULL) {
+ strlcpy(lookup->textname, namestr,
+ sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_mx;
+ lookup->rdtypeset = true;
+ lookup->origin = NULL;
+ lookup->retries = tries;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ }
+
+ if (!short_form) {
+ printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n",
+ opcodetext[msg->opcode], rcode_totext(msg->rcode),
+ msg->id);
+ printf(";; flags: ");
+ if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
+ printf("qr");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
+ printf("%saa", did_flag ? " " : "");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
+ printf("%stc", did_flag ? " " : "");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
+ printf("%srd", did_flag ? " " : "");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
+ printf("%sra", did_flag ? " " : "");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
+ printf("%sad", did_flag ? " " : "");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
+ printf("%scd", did_flag ? " " : "");
+ did_flag = true;
+ POST(did_flag);
+ }
+ printf("; QUERY: %u, ANSWER: %u, "
+ "AUTHORITY: %u, ADDITIONAL: %u\n",
+ msg->counts[DNS_SECTION_QUESTION],
+ msg->counts[DNS_SECTION_ANSWER],
+ msg->counts[DNS_SECTION_AUTHORITY],
+ msg->counts[DNS_SECTION_ADDITIONAL]);
+ opt = dns_message_getopt(msg);
+ if (opt != NULL) {
+ printf(";; EDNS: version: %u, udp=%u\n",
+ (unsigned int)((opt->ttl & 0x00ff0000) >> 16),
+ (unsigned int)opt->rdclass);
+ }
+ tsigname = NULL;
+ tsig = dns_message_gettsig(msg, &tsigname);
+ if (tsig != NULL) {
+ printf(";; PSEUDOSECTIONS: TSIG\n");
+ }
+ }
+ if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) && !short_form)
+ {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION",
+ true, query);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
+ if (!short_form) {
+ printf("\n");
+ }
+ result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER",
+ !short_form, query);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) &&
+ !short_form)
+ {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY",
+ true, query);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) &&
+ !short_form)
+ {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_ADDITIONAL, "ADDITIONAL",
+ true, query);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ if ((tsig != NULL) && !short_form) {
+ printf("\n");
+ result = printrdata(msg, tsig, tsigname, "PSEUDOSECTION TSIG",
+ true);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ if (!short_form) {
+ printf("\n");
+ }
+
+ if (short_form && !default_lookups &&
+ ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
+ {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+ dns_name_format(query->lookup->name, namestr, sizeof(namestr));
+ dns_rdatatype_format(query->lookup->rdtype, typestr,
+ sizeof(typestr));
+ printf("%s has no %s record\n", namestr, typestr);
+ }
+ seen_error = force_error;
+ return (result);
+}
+
+static const char *optstring = "46aAc:dilnm:p:rst:vVwCDN:R:TUW:";
+
+/*% version */
+static void
+version(void) {
+ fprintf(stderr, "host %s\n", PACKAGE_VERSION);
+}
+
+static void
+pre_parse_args(int argc, char **argv) {
+ int c;
+
+ while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) {
+ switch (c) {
+ case 'm':
+ memdebugging = true;
+ if (strcasecmp("trace", isc_commandline_argument) == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
+ } else if (strcasecmp("record",
+ isc_commandline_argument) == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ } else if (strcasecmp("usage",
+ isc_commandline_argument) == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
+ }
+ break;
+
+ case '4':
+ if (ipv6only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv4only = true;
+ break;
+ case '6':
+ if (ipv4only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv6only = true;
+ break;
+ case 'a':
+ break;
+ case 'A':
+ break;
+ case 'c':
+ break;
+ case 'C':
+ break;
+ case 'd':
+ break;
+ case 'D':
+ if (debugging) {
+ debugtiming = true;
+ }
+ debugging = true;
+ break;
+ case 'i':
+ break;
+ case 'l':
+ break;
+ case 'n':
+ break;
+ case 'N':
+ break;
+ case 'p':
+ break;
+ case 'r':
+ break;
+ case 'R':
+ break;
+ case 's':
+ break;
+ case 't':
+ break;
+ case 'T':
+ break;
+ case 'U':
+ break;
+ case 'v':
+ break;
+ case 'V':
+ version();
+ exit(0);
+ break;
+ case 'w':
+ break;
+ case 'W':
+ break;
+ default:
+ show_usage();
+ }
+ }
+ isc_commandline_reset = true;
+ isc_commandline_index = 1;
+}
+
+static void
+parse_args(bool is_batchfile, int argc, char **argv) {
+ char hostname[MXNAME];
+ dig_lookup_t *lookup;
+ int c;
+ char store[MXNAME];
+ isc_textregion_t tr;
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ uint32_t serial = 0;
+
+ UNUSED(is_batchfile);
+
+ lookup = make_empty_lookup();
+
+ lookup->servfail_stops = false;
+ lookup->besteffort = false;
+ lookup->comments = false;
+ short_form = !verbose;
+
+ while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) {
+ switch (c) {
+ case 'l':
+ lookup->tcp_mode = true;
+ lookup->rdtype = dns_rdatatype_axfr;
+ lookup->rdtypeset = true;
+ fatalexit = 3;
+ break;
+ case 'v':
+ case 'd':
+ short_form = false;
+ break;
+ case 'r':
+ lookup->recurse = false;
+ break;
+ case 't':
+ if (strncasecmp(isc_commandline_argument, "ixfr=", 5) ==
+ 0)
+ {
+ rdtype = dns_rdatatype_ixfr;
+ /* XXXMPA add error checking */
+ serial = strtoul(isc_commandline_argument + 5,
+ NULL, 10);
+ result = ISC_R_SUCCESS;
+ } else {
+ tr.base = isc_commandline_argument;
+ tr.length = strlen(isc_commandline_argument);
+ result = dns_rdatatype_fromtext(
+ &rdtype, (isc_textregion_t *)&tr);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ fatalexit = 2;
+ fatal("invalid type: %s\n",
+ isc_commandline_argument);
+ }
+ if (!lookup->rdtypeset ||
+ lookup->rdtype != dns_rdatatype_axfr)
+ {
+ lookup->rdtype = rdtype;
+ }
+ lookup->rdtypeset = true;
+ if (rdtype == dns_rdatatype_axfr) {
+ /* -l -t any -v */
+ list_type = dns_rdatatype_any;
+ short_form = false;
+ lookup->tcp_mode = true;
+ } else if (rdtype == dns_rdatatype_ixfr) {
+ lookup->ixfr_serial = serial;
+ lookup->tcp_mode = true;
+ list_type = rdtype;
+ } else if (rdtype == dns_rdatatype_any) {
+ if (!lookup->tcp_mode_set) {
+ lookup->tcp_mode = true;
+ }
+ } else {
+ list_type = rdtype;
+ }
+ list_addresses = false;
+ default_lookups = false;
+ break;
+ case 'c':
+ tr.base = isc_commandline_argument;
+ tr.length = strlen(isc_commandline_argument);
+ result = dns_rdataclass_fromtext(
+ &rdclass, (isc_textregion_t *)&tr);
+
+ if (result != ISC_R_SUCCESS) {
+ fatalexit = 2;
+ fatal("invalid class: %s\n",
+ isc_commandline_argument);
+ } else {
+ lookup->rdclass = rdclass;
+ lookup->rdclassset = true;
+ }
+ default_lookups = false;
+ break;
+ case 'A':
+ list_almost_all = true;
+ FALLTHROUGH;
+ case 'a':
+ if (!lookup->rdtypeset ||
+ lookup->rdtype != dns_rdatatype_axfr)
+ {
+ lookup->rdtype = dns_rdatatype_any;
+ }
+ list_type = dns_rdatatype_any;
+ list_addresses = false;
+ lookup->rdtypeset = true;
+ short_form = false;
+ default_lookups = false;
+ break;
+ case 'i':
+ /* deprecated */
+ break;
+ case 'n':
+ /* deprecated */
+ break;
+ case 'm':
+ /* Handled by pre_parse_args(). */
+ break;
+ case 'w':
+ /*
+ * The timer routines are coded such that
+ * timeout==MAXINT doesn't enable the timer
+ */
+ timeout = INT_MAX;
+ break;
+ case 'W':
+ timeout = atoi(isc_commandline_argument);
+ if (timeout < 1) {
+ timeout = 1;
+ }
+ break;
+ case 'R':
+ tries = atoi(isc_commandline_argument) + 1;
+ if (tries < 2) {
+ tries = 2;
+ }
+ break;
+ case 'T':
+ lookup->tcp_mode = true;
+ lookup->tcp_mode_set = true;
+ break;
+ case 'U':
+ lookup->tcp_mode = false;
+ lookup->tcp_mode_set = true;
+ break;
+ case 'C':
+ debug("showing all SOAs");
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = true;
+ lookup->rdclass = dns_rdataclass_in;
+ lookup->rdclassset = true;
+ lookup->ns_search_only = true;
+ lookup->trace_root = true;
+ lookup->identify_previous_line = true;
+ default_lookups = false;
+ break;
+ case 'N':
+ debug("setting NDOTS to %s", isc_commandline_argument);
+ ndots = atoi(isc_commandline_argument);
+ break;
+ case 'D':
+ /* Handled by pre_parse_args(). */
+ break;
+ case '4':
+ /* Handled by pre_parse_args(). */
+ break;
+ case '6':
+ /* Handled by pre_parse_args(). */
+ break;
+ case 's':
+ lookup->servfail_stops = true;
+ break;
+ case 'p':
+ port = atoi(isc_commandline_argument);
+ port_set = true;
+ break;
+ }
+ }
+
+ lookup->retries = tries;
+
+ if (isc_commandline_index >= argc) {
+ show_usage();
+ }
+
+ strlcpy(hostname, argv[isc_commandline_index], sizeof(hostname));
+
+ if (argc > isc_commandline_index + 1) {
+ set_nameserver(argv[isc_commandline_index + 1]);
+ debug("server is %s", argv[isc_commandline_index + 1]);
+ listed_server = true;
+ } else {
+ check_ra = true;
+ }
+
+ lookup->pending = false;
+ if (get_reverse(store, sizeof(store), hostname, true) == ISC_R_SUCCESS)
+ {
+ strlcpy(lookup->textname, store, sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_ptr;
+ lookup->rdtypeset = true;
+ default_lookups = false;
+ } else {
+ strlcpy(lookup->textname, hostname, sizeof(lookup->textname));
+ usesearch = true;
+ }
+ lookup->new_search = true;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+
+ tries = 2;
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ fatalexit = 1;
+
+ /* setup dighost callbacks */
+ dighost_printmessage = printmessage;
+ dighost_received = received;
+ dighost_trying = trying;
+ dighost_shutdown = host_shutdown;
+
+ debug("main()");
+ progname = argv[0];
+ pre_parse_args(argc, argv);
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+ setup_libs();
+ setup_system(ipv4only, ipv6only);
+ parse_args(false, argc, argv);
+ if (keyfile[0] != 0) {
+ setup_file_key();
+ } else if (keysecret[0] != 0) {
+ setup_text_key();
+ }
+ result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
+ check_result(result, "isc_app_onrun");
+ isc_app_run();
+ cancel_all();
+ destroy_libs();
+ isc_app_finish();
+ return ((seen_error == 0) ? 0 : 1);
+}
diff --git a/bin/dig/host.rst b/bin/dig/host.rst
new file mode 100644
index 0000000..2647d36
--- /dev/null
+++ b/bin/dig/host.rst
@@ -0,0 +1,193 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: host
+.. program:: host
+.. _man_host:
+
+host - DNS lookup utility
+-------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`host` [**-aACdlnrsTUwv**] [**-c** class] [**-N** ndots] [**-p** port] [**-R** number] [**-t** type] [**-W** wait] [**-m** flag] [ [**-4**] | [**-6**] ] [**-v**] [**-V**] {name} [server]
+
+Description
+~~~~~~~~~~~
+
+:program:`host` is a simple utility for performing DNS lookups. It is normally
+used to convert names to IP addresses and vice versa. When no arguments
+or options are given, :program:`host` prints a short summary of its
+command-line arguments and options.
+
+``name`` is the domain name that is to be looked up. It can also be a
+dotted-decimal IPv4 address or a colon-delimited IPv6 address, in which
+case :program:`host` by default performs a reverse lookup for that address.
+``server`` is an optional argument which is either the name or IP
+address of the name server that :program:`host` should query instead of the
+server or servers listed in ``/etc/resolv.conf``.
+
+Options
+~~~~~~~
+
+.. option:: -4
+
+ This option specifies that only IPv4 should be used for query transport. See also the :option:`-6` option.
+
+.. option:: -6
+
+ This option specifies that only IPv6 should be used for query transport. See also the :option:`-4` option.
+
+.. option:: -a
+
+ The :option:`-a` ("all") option is normally equivalent to :option:`-v` :option:`-t ANY <-t>`. It
+ also affects the behavior of the :option:`-l` list zone option.
+
+.. option:: -A
+
+ The :option:`-A` ("almost all") option is equivalent to :option:`-a`, except that RRSIG,
+ NSEC, and NSEC3 records are omitted from the output.
+
+.. option:: -c class
+
+ This option specifies the query class, which can be used to lookup HS (Hesiod) or CH (Chaosnet)
+ class resource records. The default class is IN (Internet).
+
+.. option:: -C
+
+ This option indicates that :iscman:`named` should check consistency, meaning that :program:`host` queries the SOA records for zone
+ ``name`` from all the listed authoritative name servers for that
+ zone. The list of name servers is defined by the NS records that are
+ found for the zone.
+
+.. option:: -d
+
+ This option prints debugging traces, and is equivalent to the :option:`-v` verbose option.
+
+.. option:: -l
+
+ This option tells :iscman:`named` to list the zone, meaning the :program:`host` command performs a zone transfer of zone
+ ``name`` and prints out the NS, PTR, and address records (A/AAAA).
+
+ Together, the :option:`-l` :option:`-a` options print all records in the zone.
+
+.. option:: -N ndots
+
+ This option specifies the number of dots (``ndots``) that have to be in ``name`` for it to be
+ considered absolute. The default value is that defined using the
+ ``ndots`` statement in ``/etc/resolv.conf``, or 1 if no ``ndots`` statement
+ is present. Names with fewer dots are interpreted as relative names,
+ and are searched for in the domains listed in the ``search`` or
+ ``domain`` directive in ``/etc/resolv.conf``.
+
+.. option:: -p port
+
+ This option specifies the port to query on the server. The default is 53.
+
+.. option:: -r
+
+ This option specifies a non-recursive query; setting this option clears the RD (recursion
+ desired) bit in the query. This means that the name server
+ receiving the query does not attempt to resolve ``name``. The :option:`-r`
+ option enables :program:`host` to mimic the behavior of a name server by
+ making non-recursive queries, and expecting to receive answers to
+ those queries that can be referrals to other name servers.
+
+.. option:: -R number
+
+ This option specifies the number of retries for UDP queries. If ``number`` is negative or zero,
+ the number of retries is silently set to 1. The default value is 1, or
+ the value of the ``attempts`` option in ``/etc/resolv.conf``, if set.
+
+.. option:: -s
+
+ This option tells :iscman:`named` *not* to send the query to the next nameserver if any server responds
+ with a SERVFAIL response, which is the reverse of normal stub
+ resolver behavior.
+
+.. option:: -t type
+
+ This option specifies the query type. The ``type`` argument can be any recognized query type:
+ CNAME, NS, SOA, TXT, DNSKEY, AXFR, etc.
+
+ When no query type is specified, :program:`host` automatically selects an
+ appropriate query type. By default, it looks for A, AAAA, and MX
+ records. If the :option:`-C` option is given, queries are made for SOA
+ records. If ``name`` is a dotted-decimal IPv4 address or
+ colon-delimited IPv6 address, :program:`host` queries for PTR records.
+
+ If a query type of IXFR is chosen, the starting serial number can be
+ specified by appending an equals sign (=), followed by the starting serial
+ number, e.g., :option:`-t IXFR=12345678 <-t>`.
+
+.. option:: -T, -U
+
+ This option specifies TCP or UDP. By default, :program:`host` uses UDP when making queries; the
+ :option:`-T` option makes it use a TCP connection when querying the name
+ server. TCP is automatically selected for queries that require
+ it, such as zone transfer (AXFR) requests. Type ``ANY`` queries default
+ to TCP, but can be forced to use UDP initially via :option:`-U`.
+
+.. option:: -m flag
+
+ This option sets memory usage debugging: the flag can be ``record``, ``usage``, or
+ ``trace``. The :option:`-m` option can be specified more than once to set
+ multiple flags.
+
+.. option:: -v
+
+ This option sets verbose output, and is equivalent to the :option:`-d` debug option. Verbose output
+ can also be enabled by setting the ``debug`` option in
+ ``/etc/resolv.conf``.
+
+.. option:: -V
+
+ This option prints the version number and exits.
+
+.. option:: -w
+
+ This option sets "wait forever": the query timeout is set to the maximum possible. See
+ also the :option:`-W` option.
+
+.. option:: -W wait
+
+ This options sets the length of the wait timeout, indicating that :iscman:`named` should wait for up to ``wait`` seconds for a reply. If ``wait`` is
+ less than 1, the wait interval is set to 1 second.
+
+ By default, :program:`host` waits for 5 seconds for UDP responses and 10
+ seconds for TCP connections. These defaults can be overridden by the
+ ``timeout`` option in ``/etc/resolv.conf``.
+
+ See also the :option:`-w` option.
+
+IDN Support
+~~~~~~~~~~~
+
+If :program:`host` has been built with IDN (internationalized domain name)
+support, it can accept and display non-ASCII domain names. :program:`host`
+appropriately converts character encoding of a domain name before sending
+a request to a DNS server or displaying a reply from the server.
+To turn off IDN support, define the ``IDN_DISABLE``
+environment variable. IDN support is disabled if the variable is set
+when :program:`host` runs.
+
+Files
+~~~~~
+
+``/etc/resolv.conf``
+
+See Also
+~~~~~~~~
+
+:iscman:`dig(1) <dig>`, :iscman:`named(8) <named>`.
diff --git a/bin/dig/nslookup.c b/bin/dig/nslookup.c
new file mode 100644
index 0000000..a0f508d
--- /dev/null
+++ b/bin/dig/nslookup.c
@@ -0,0 +1,977 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/event.h>
+#include <isc/netaddr.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/fixedname.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+
+#include "dighost.h"
+#include "readline.h"
+
+static bool short_form = true, tcpmode = false, tcpmode_set = false,
+ identify = false, stats = true, comments = true,
+ section_question = true, section_answer = true,
+ section_authority = true, section_additional = true, recurse = true,
+ aaonly = false, nofail = true, default_lookups = true,
+ a_noanswer = false;
+
+static bool interactive;
+
+static bool in_use = false;
+static char defclass[MXRD] = "IN";
+static char deftype[MXRD] = "A";
+static isc_event_t *global_event = NULL;
+static int query_error = 1, print_error = 0;
+
+static char domainopt[DNS_NAME_MAXTEXT];
+
+static const char *rcodetext[] = { "NOERROR", "FORMERR", "SERVFAIL",
+ "NXDOMAIN", "NOTIMP", "REFUSED",
+ "YXDOMAIN", "YXRRSET", "NXRRSET",
+ "NOTAUTH", "NOTZONE", "RESERVED11",
+ "RESERVED12", "RESERVED13", "RESERVED14",
+ "RESERVED15", "BADVERS" };
+
+static const char *rtypetext[] = {
+ "rtype_0 = ", /* 0 */
+ "internet address = ", /* 1 */
+ "nameserver = ", /* 2 */
+ "md = ", /* 3 */
+ "mf = ", /* 4 */
+ "canonical name = ", /* 5 */
+ "soa = ", /* 6 */
+ "mb = ", /* 7 */
+ "mg = ", /* 8 */
+ "mr = ", /* 9 */
+ "rtype_10 = ", /* 10 */
+ "protocol = ", /* 11 */
+ "name = ", /* 12 */
+ "hinfo = ", /* 13 */
+ "minfo = ", /* 14 */
+ "mail exchanger = ", /* 15 */
+ "text = ", /* 16 */
+ "rp = ", /* 17 */
+ "afsdb = ", /* 18 */
+ "x25 address = ", /* 19 */
+ "isdn address = ", /* 20 */
+ "rt = ", /* 21 */
+ "nsap = ", /* 22 */
+ "nsap_ptr = ", /* 23 */
+ "signature = ", /* 24 */
+ "key = ", /* 25 */
+ "px = ", /* 26 */
+ "gpos = ", /* 27 */
+ "has AAAA address ", /* 28 */
+ "loc = ", /* 29 */
+ "next = ", /* 30 */
+ "rtype_31 = ", /* 31 */
+ "rtype_32 = ", /* 32 */
+ "service = ", /* 33 */
+ "rtype_34 = ", /* 34 */
+ "naptr = ", /* 35 */
+ "kx = ", /* 36 */
+ "cert = ", /* 37 */
+ "v6 address = ", /* 38 */
+ "dname = ", /* 39 */
+ "rtype_40 = ", /* 40 */
+ "optional = " /* 41 */
+};
+
+#define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
+
+static void
+getinput(isc_task_t *task, isc_event_t *event);
+
+static char *
+rcode_totext(dns_rcode_t rcode) {
+ static char buf[sizeof("?65535")];
+ union {
+ const char *consttext;
+ char *deconsttext;
+ } totext;
+
+ if (rcode >= (sizeof(rcodetext) / sizeof(rcodetext[0]))) {
+ snprintf(buf, sizeof(buf), "?%u", rcode);
+ totext.deconsttext = buf;
+ } else {
+ totext.consttext = rcodetext[rcode];
+ }
+ return (totext.deconsttext);
+}
+
+static void
+query_finished(void) {
+ isc_event_t *event = global_event;
+
+ debug("dighost_shutdown()");
+
+ if (!in_use) {
+ isc_app_shutdown();
+ return;
+ }
+
+ isc_task_send(global_task, &event);
+}
+
+static void
+printsoa(dns_rdata_t *rdata) {
+ dns_rdata_soa_t soa;
+ isc_result_t result;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ result = dns_rdata_tostruct(rdata, &soa, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ dns_name_format(&soa.origin, namebuf, sizeof(namebuf));
+ printf("\torigin = %s\n", namebuf);
+ dns_name_format(&soa.contact, namebuf, sizeof(namebuf));
+ printf("\tmail addr = %s\n", namebuf);
+ printf("\tserial = %u\n", soa.serial);
+ printf("\trefresh = %u\n", soa.refresh);
+ printf("\tretry = %u\n", soa.retry);
+ printf("\texpire = %u\n", soa.expire);
+ printf("\tminimum = %u\n", soa.minimum);
+ dns_rdata_freestruct(&soa);
+}
+
+static void
+printaddr(dns_rdata_t *rdata) {
+ isc_result_t result;
+ char text[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, text, sizeof(text));
+ result = dns_rdata_totext(rdata, NULL, &b);
+ check_result(result, "dns_rdata_totext");
+ printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
+ (char *)isc_buffer_base(&b));
+}
+
+static void
+printrdata(dns_rdata_t *rdata) {
+ isc_result_t result;
+ isc_buffer_t *b = NULL;
+ unsigned int size = 1024;
+ bool done = false;
+
+ if (rdata->type < N_KNOWN_RRTYPES) {
+ printf("%s", rtypetext[rdata->type]);
+ } else {
+ printf("rdata_%d = ", rdata->type);
+ }
+
+ while (!done) {
+ isc_buffer_allocate(mctx, &b, size);
+ result = dns_rdata_totext(rdata, NULL, b);
+ if (result == ISC_R_SUCCESS) {
+ printf("%.*s\n", (int)isc_buffer_usedlength(b),
+ (char *)isc_buffer_base(b));
+ done = true;
+ } else if (result != ISC_R_NOSPACE) {
+ check_result(result, "dns_rdata_totext");
+ }
+ isc_buffer_free(&b);
+ size *= 2;
+ }
+}
+
+static isc_result_t
+printsection(dig_query_t *query, dns_message_t *msg, bool headers,
+ dns_section_t section) {
+ isc_result_t result, loopresult;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ UNUSED(query);
+ UNUSED(headers);
+
+ debug("printsection()");
+
+ result = dns_message_firstname(msg, section);
+ if (result == ISC_R_NOMORE) {
+ return (ISC_R_SUCCESS);
+ } else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, section, &name);
+ for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ switch (rdata.type) {
+ case dns_rdatatype_a:
+ case dns_rdatatype_aaaa:
+ if (section != DNS_SECTION_ANSWER) {
+ goto def_short_section;
+ }
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("Name:\t%s\n", namebuf);
+ printaddr(&rdata);
+ break;
+ case dns_rdatatype_soa:
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("%s\n", namebuf);
+ printsoa(&rdata);
+ break;
+ default:
+ def_short_section:
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("%s\t", namebuf);
+ printrdata(&rdata);
+ break;
+ }
+ dns_rdata_reset(&rdata);
+ loopresult = dns_rdataset_next(rdataset);
+ }
+ }
+ result = dns_message_nextname(msg, section);
+ if (result == ISC_R_NOMORE) {
+ break;
+ } else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+detailsection(dig_query_t *query, dns_message_t *msg, bool headers,
+ dns_section_t section) {
+ isc_result_t result, loopresult;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ UNUSED(query);
+
+ debug("detailsection()");
+
+ if (headers) {
+ switch (section) {
+ case DNS_SECTION_QUESTION:
+ puts(" QUESTIONS:");
+ break;
+ case DNS_SECTION_ANSWER:
+ puts(" ANSWERS:");
+ break;
+ case DNS_SECTION_AUTHORITY:
+ puts(" AUTHORITY RECORDS:");
+ break;
+ case DNS_SECTION_ADDITIONAL:
+ puts(" ADDITIONAL RECORDS:");
+ break;
+ }
+ }
+
+ result = dns_message_firstname(msg, section);
+ if (result == ISC_R_NOMORE) {
+ return (ISC_R_SUCCESS);
+ } else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, section, &name);
+ for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (section == DNS_SECTION_QUESTION) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ printf("\t%s, ", namebuf);
+ dns_rdatatype_format(rdataset->type, namebuf,
+ sizeof(namebuf));
+ printf("type = %s, ", namebuf);
+ dns_rdataclass_format(rdataset->rdclass,
+ namebuf, sizeof(namebuf));
+ printf("class = %s\n", namebuf);
+ }
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ printf(" -> %s\n", namebuf);
+
+ switch (rdata.type) {
+ case dns_rdatatype_soa:
+ printsoa(&rdata);
+ break;
+ default:
+ printf("\t");
+ printrdata(&rdata);
+ }
+ dns_rdata_reset(&rdata);
+ printf("\tttl = %u\n", rdataset->ttl);
+ loopresult = dns_rdataset_next(rdataset);
+ }
+ }
+ result = dns_message_nextname(msg, section);
+ if (result == ISC_R_NOMORE) {
+ break;
+ } else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static void
+received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
+ UNUSED(bytes);
+ UNUSED(from);
+ UNUSED(query);
+}
+
+static void
+trying(char *frm, dig_lookup_t *lookup) {
+ UNUSED(frm);
+ UNUSED(lookup);
+}
+
+static void
+chase_cnamechain(dns_message_t *msg, dns_name_t *qname) {
+ isc_result_t result;
+ dns_rdataset_t *rdataset;
+ dns_rdata_cname_t cname;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int i = msg->counts[DNS_SECTION_ANSWER];
+
+ while (i-- > 0) {
+ rdataset = NULL;
+ result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
+ dns_rdatatype_cname, 0, NULL,
+ &rdataset);
+ if (result != ISC_R_SUCCESS) {
+ return;
+ }
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "dns_rdataset_first");
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ dns_name_copy(&cname.cname, qname);
+ dns_rdata_freestruct(&cname);
+ }
+}
+
+static isc_result_t
+printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg,
+ bool headers) {
+ char servtext[ISC_SOCKADDR_FORMATSIZE];
+
+ UNUSED(msgbuf);
+
+ /* I've we've gotten this far, we've reached a server. */
+ query_error = 0;
+
+ debug("printmessage()");
+
+ if (!default_lookups || query->lookup->rdtype == dns_rdatatype_a) {
+ isc_sockaddr_format(&query->sockaddr, servtext,
+ sizeof(servtext));
+ printf("Server:\t\t%s\n", query->userarg);
+ printf("Address:\t%s\n", servtext);
+
+ puts("");
+ }
+
+ if (!short_form) {
+ puts("------------");
+ /* detailheader(query, msg);*/
+ detailsection(query, msg, true, DNS_SECTION_QUESTION);
+ detailsection(query, msg, true, DNS_SECTION_ANSWER);
+ detailsection(query, msg, true, DNS_SECTION_AUTHORITY);
+ detailsection(query, msg, true, DNS_SECTION_ADDITIONAL);
+ puts("------------");
+ }
+
+ if (msg->rcode != 0) {
+ char nametext[DNS_NAME_FORMATSIZE];
+ dns_name_format(query->lookup->name, nametext,
+ sizeof(nametext));
+ printf("** server can't find %s: %s\n", nametext,
+ rcode_totext(msg->rcode));
+ debug("returning with rcode == 0");
+
+ /* the lookup failed */
+ print_error |= 1;
+ return (ISC_R_SUCCESS);
+ }
+
+ if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dig_lookup_t *lookup;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+
+ /* Add AAAA lookup. */
+ name = dns_fixedname_initname(&fixed);
+ dns_name_copy(query->lookup->name, name);
+ chase_cnamechain(msg, name);
+ dns_name_format(name, namestr, sizeof(namestr));
+ lookup = clone_lookup(query->lookup, false);
+ if (lookup != NULL) {
+ strlcpy(lookup->textname, namestr,
+ sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_aaaa;
+ lookup->rdtypeset = true;
+ lookup->origin = NULL;
+ lookup->retries = tries;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ }
+
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0 &&
+ (!default_lookups || query->lookup->rdtype == dns_rdatatype_a))
+ {
+ puts("Non-authoritative answer:");
+ }
+ if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
+ printsection(query, msg, headers, DNS_SECTION_ANSWER);
+ } else {
+ if (default_lookups && query->lookup->rdtype == dns_rdatatype_a)
+ {
+ a_noanswer = true;
+ } else if (!default_lookups ||
+ (query->lookup->rdtype == dns_rdatatype_aaaa &&
+ a_noanswer))
+ {
+ printf("*** Can't find %s: No answer\n",
+ query->lookup->textname);
+ }
+ }
+
+ if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
+ (query->lookup->rdtype != dns_rdatatype_a) &&
+ (query->lookup->rdtype != dns_rdatatype_aaaa))
+ {
+ puts("\nAuthoritative answers can be found from:");
+ printsection(query, msg, headers, DNS_SECTION_AUTHORITY);
+ printsection(query, msg, headers, DNS_SECTION_ADDITIONAL);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static void
+show_settings(bool full, bool serv_only) {
+ dig_server_t *srv;
+ isc_sockaddr_t sockaddr;
+ dig_searchlist_t *listent;
+ isc_result_t result;
+
+ srv = ISC_LIST_HEAD(server_list);
+
+ while (srv != NULL) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+
+ result = get_address(srv->servername, port, &sockaddr);
+ check_result(result, "get_address");
+
+ isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr));
+ printf("Default server: %s\nAddress: %s\n", srv->userarg,
+ sockstr);
+ if (!full) {
+ return;
+ }
+ srv = ISC_LIST_NEXT(srv, link);
+ }
+ if (serv_only) {
+ return;
+ }
+ printf("\nSet options:\n");
+ printf(" %s\t\t\t%s\t\t%s\n", tcpmode ? "vc" : "novc",
+ short_form ? "nodebug" : "debug", debugging ? "d2" : "nod2");
+ printf(" %s\t\t%s\n", usesearch ? "search" : "nosearch",
+ recurse ? "recurse" : "norecurse");
+ printf(" timeout = %u\t\tretry = %d\tport = %u\tndots = %d\n", timeout,
+ tries, port, ndots);
+ printf(" querytype = %-8s\tclass = %s\n", deftype, defclass);
+ printf(" srchlist = ");
+ for (listent = ISC_LIST_HEAD(search_list); listent != NULL;
+ listent = ISC_LIST_NEXT(listent, link))
+ {
+ printf("%s", listent->origin);
+ if (ISC_LIST_NEXT(listent, link) != NULL) {
+ printf("/");
+ }
+ }
+ printf("\n");
+}
+
+static bool
+testtype(char *typetext) {
+ isc_result_t result;
+ isc_textregion_t tr;
+ dns_rdatatype_t rdtype;
+
+ tr.base = typetext;
+ tr.length = strlen(typetext);
+ result = dns_rdatatype_fromtext(&rdtype, &tr);
+ if (result == ISC_R_SUCCESS) {
+ return (true);
+ } else {
+ printf("unknown query type: %s\n", typetext);
+ return (false);
+ }
+}
+
+static bool
+testclass(char *typetext) {
+ isc_result_t result;
+ isc_textregion_t tr;
+ dns_rdataclass_t rdclass;
+
+ tr.base = typetext;
+ tr.length = strlen(typetext);
+ result = dns_rdataclass_fromtext(&rdclass, &tr);
+ if (result == ISC_R_SUCCESS) {
+ return (true);
+ } else {
+ printf("unknown query class: %s\n", typetext);
+ return (false);
+ }
+}
+
+static void
+set_port(const char *value) {
+ uint32_t n;
+ isc_result_t result = parse_uint(&n, value, 65535, "port");
+ if (result == ISC_R_SUCCESS) {
+ port = (uint16_t)n;
+ port_set = true;
+ }
+}
+
+static void
+set_timeout(const char *value) {
+ uint32_t n;
+ isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout");
+ if (result == ISC_R_SUCCESS) {
+ timeout = n;
+ }
+}
+
+static void
+set_tries(const char *value) {
+ uint32_t n;
+ isc_result_t result = parse_uint(&n, value, INT_MAX, "tries");
+ if (result == ISC_R_SUCCESS) {
+ tries = n;
+ }
+}
+
+static void
+set_ndots(const char *value) {
+ uint32_t n;
+ isc_result_t result = parse_uint(&n, value, 128, "ndots");
+ if (result == ISC_R_SUCCESS) {
+ ndots = n;
+ }
+}
+
+static void
+version(void) {
+ fprintf(stderr, "nslookup %s\n", PACKAGE_VERSION);
+}
+
+static void
+setoption(char *opt) {
+ size_t l = strlen(opt);
+
+#define CHECKOPT(A, N) \
+ ((l >= N) && (l < sizeof(A)) && (strncasecmp(opt, A, l) == 0))
+
+ if (CHECKOPT("all", 3)) {
+ show_settings(true, false);
+ } else if (strncasecmp(opt, "class=", 6) == 0) {
+ if (testclass(&opt[6])) {
+ strlcpy(defclass, &opt[6], sizeof(defclass));
+ }
+ } else if (strncasecmp(opt, "cl=", 3) == 0) {
+ if (testclass(&opt[3])) {
+ strlcpy(defclass, &opt[3], sizeof(defclass));
+ }
+ } else if (strncasecmp(opt, "type=", 5) == 0) {
+ if (testtype(&opt[5])) {
+ strlcpy(deftype, &opt[5], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "ty=", 3) == 0) {
+ if (testtype(&opt[3])) {
+ strlcpy(deftype, &opt[3], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "querytype=", 10) == 0) {
+ if (testtype(&opt[10])) {
+ strlcpy(deftype, &opt[10], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "query=", 6) == 0) {
+ if (testtype(&opt[6])) {
+ strlcpy(deftype, &opt[6], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "qu=", 3) == 0) {
+ if (testtype(&opt[3])) {
+ strlcpy(deftype, &opt[3], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "q=", 2) == 0) {
+ if (testtype(&opt[2])) {
+ strlcpy(deftype, &opt[2], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "domain=", 7) == 0) {
+ strlcpy(domainopt, &opt[7], sizeof(domainopt));
+ set_search_domain(domainopt);
+ usesearch = true;
+ } else if (strncasecmp(opt, "do=", 3) == 0) {
+ strlcpy(domainopt, &opt[3], sizeof(domainopt));
+ set_search_domain(domainopt);
+ usesearch = true;
+ } else if (strncasecmp(opt, "port=", 5) == 0) {
+ set_port(&opt[5]);
+ } else if (strncasecmp(opt, "po=", 3) == 0) {
+ set_port(&opt[3]);
+ } else if (strncasecmp(opt, "timeout=", 8) == 0) {
+ set_timeout(&opt[8]);
+ } else if (strncasecmp(opt, "t=", 2) == 0) {
+ set_timeout(&opt[2]);
+ } else if (CHECKOPT("recurse", 3)) {
+ recurse = true;
+ } else if (CHECKOPT("norecurse", 5)) {
+ recurse = false;
+ } else if (strncasecmp(opt, "retry=", 6) == 0) {
+ set_tries(&opt[6]);
+ } else if (strncasecmp(opt, "ret=", 4) == 0) {
+ set_tries(&opt[4]);
+ } else if (CHECKOPT("defname", 3)) {
+ usesearch = true;
+ } else if (CHECKOPT("nodefname", 5)) {
+ usesearch = false;
+ } else if (CHECKOPT("vc", 2)) {
+ tcpmode = true;
+ tcpmode_set = true;
+ } else if (CHECKOPT("novc", 4)) {
+ tcpmode = false;
+ tcpmode_set = true;
+ } else if (CHECKOPT("debug", 3)) {
+ short_form = false;
+ showsearch = true;
+ } else if (CHECKOPT("nodebug", 5)) {
+ short_form = true;
+ showsearch = false;
+ } else if (CHECKOPT("d2", 2)) {
+ debugging = true;
+ } else if (CHECKOPT("nod2", 4)) {
+ debugging = false;
+ } else if (CHECKOPT("search", 3)) {
+ usesearch = true;
+ } else if (CHECKOPT("nosearch", 5)) {
+ usesearch = false;
+ } else if (CHECKOPT("sil", 3)) {
+ /* deprecation_msg = false; */
+ } else if (CHECKOPT("fail", 3)) {
+ nofail = false;
+ } else if (CHECKOPT("nofail", 5)) {
+ nofail = true;
+ } else if (strncasecmp(opt, "ndots=", 6) == 0) {
+ set_ndots(&opt[6]);
+ } else {
+ printf("*** Invalid option: %s\n", opt);
+ }
+}
+
+static void
+addlookup(char *opt) {
+ dig_lookup_t *lookup;
+ isc_result_t result;
+ isc_textregion_t tr;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ char store[MXNAME];
+
+ debug("addlookup()");
+
+ a_noanswer = false;
+
+ tr.base = deftype;
+ tr.length = strlen(deftype);
+ result = dns_rdatatype_fromtext(&rdtype, &tr);
+ if (result != ISC_R_SUCCESS) {
+ printf("unknown query type: %s\n", deftype);
+ rdclass = dns_rdatatype_a;
+ }
+ tr.base = defclass;
+ tr.length = strlen(defclass);
+ result = dns_rdataclass_fromtext(&rdclass, &tr);
+ if (result != ISC_R_SUCCESS) {
+ printf("unknown query class: %s\n", defclass);
+ rdclass = dns_rdataclass_in;
+ }
+ lookup = make_empty_lookup();
+ if (get_reverse(store, sizeof(store), opt, true) == ISC_R_SUCCESS) {
+ strlcpy(lookup->textname, store, sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_ptr;
+ lookup->rdtypeset = true;
+ } else {
+ strlcpy(lookup->textname, opt, sizeof(lookup->textname));
+ lookup->rdtype = rdtype;
+ lookup->rdtypeset = true;
+ }
+ lookup->rdclass = rdclass;
+ lookup->rdclassset = true;
+ lookup->trace = false;
+ lookup->trace_root = lookup->trace;
+ lookup->ns_search_only = false;
+ lookup->identify = identify;
+ lookup->recurse = recurse;
+ lookup->aaonly = aaonly;
+ lookup->retries = tries;
+ lookup->setqid = false;
+ lookup->qid = 0;
+ lookup->comments = comments;
+ if (lookup->rdtype == dns_rdatatype_any && !tcpmode_set) {
+ lookup->tcp_mode = true;
+ } else {
+ lookup->tcp_mode = tcpmode;
+ }
+ lookup->stats = stats;
+ lookup->section_question = section_question;
+ lookup->section_answer = section_answer;
+ lookup->section_authority = section_authority;
+ lookup->section_additional = section_additional;
+ lookup->new_search = true;
+ lookup->besteffort = false;
+ if (nofail) {
+ lookup->servfail_stops = false;
+ }
+ ISC_LIST_INIT(lookup->q);
+ ISC_LINK_INIT(lookup, link);
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ lookup->origin = NULL;
+ ISC_LIST_INIT(lookup->my_server_list);
+ debug("looking up %s", lookup->textname);
+}
+
+static void
+do_next_command(char *input) {
+ char *ptr, *arg, *last;
+
+ if ((ptr = strtok_r(input, " \t\r\n", &last)) == NULL) {
+ return;
+ }
+ arg = strtok_r(NULL, " \t\r\n", &last);
+ if ((strcasecmp(ptr, "set") == 0) && (arg != NULL)) {
+ setoption(arg);
+ } else if ((strcasecmp(ptr, "server") == 0) ||
+ (strcasecmp(ptr, "lserver") == 0))
+ {
+ isc_app_block();
+ set_nameserver(arg);
+ check_ra = false;
+ isc_app_unblock();
+ show_settings(true, true);
+ } else if (strcasecmp(ptr, "exit") == 0) {
+ in_use = false;
+ } else if (strcasecmp(ptr, "help") == 0 || strcasecmp(ptr, "?") == 0) {
+ printf("The '%s' command is not yet implemented.\n", ptr);
+ } else if (strcasecmp(ptr, "finger") == 0 ||
+ strcasecmp(ptr, "root") == 0 || strcasecmp(ptr, "ls") == 0 ||
+ strcasecmp(ptr, "view") == 0)
+ {
+ printf("The '%s' command is not implemented.\n", ptr);
+ } else {
+ addlookup(ptr);
+ }
+}
+
+static void
+get_next_command(void) {
+ char cmdlinebuf[COMMSIZE];
+ char *cmdline, *ptr = NULL;
+
+ isc_app_block();
+ if (interactive) {
+ cmdline = ptr = readline("> ");
+ if (ptr != NULL && *ptr != 0) {
+ add_history(ptr);
+ }
+ } else {
+ cmdline = fgets(cmdlinebuf, COMMSIZE, stdin);
+ }
+ isc_app_unblock();
+ if (cmdline == NULL) {
+ in_use = false;
+ } else {
+ do_next_command(cmdline);
+ }
+ if (ptr != NULL) {
+ free(ptr);
+ }
+}
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " nslookup [-opt ...] # interactive mode "
+ "using default server\n");
+ fprintf(stderr, " nslookup [-opt ...] - server # interactive mode "
+ "using 'server'\n");
+ fprintf(stderr, " nslookup [-opt ...] host # just look up "
+ "'host' using default server\n");
+ fprintf(stderr, " nslookup [-opt ...] host server # just look up "
+ "'host' using 'server'\n");
+ exit(1);
+}
+
+static void
+parse_args(int argc, char **argv) {
+ bool have_lookup = false;
+
+ usesearch = true;
+ for (argc--, argv++; argc > 0 && argv[0] != NULL; argc--, argv++) {
+ debug("main parsing %s", argv[0]);
+ if (argv[0][0] == '-') {
+ if (strncasecmp(argv[0], "-ver", 4) == 0) {
+ version();
+ exit(0);
+ } else if (argv[0][1] != 0) {
+ setoption(&argv[0][1]);
+ } else {
+ have_lookup = true;
+ }
+ } else {
+ if (!have_lookup) {
+ have_lookup = true;
+ in_use = true;
+ addlookup(argv[0]);
+ } else {
+ if (argv[1] != NULL) {
+ usage();
+ }
+ set_nameserver(argv[0]);
+ check_ra = false;
+ }
+ }
+ }
+}
+
+static void
+getinput(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+ if (global_event == NULL) {
+ global_event = event;
+ }
+ while (in_use) {
+ get_next_command();
+ if (ISC_LIST_HEAD(lookup_list) != NULL) {
+ start_lookup();
+ return;
+ }
+ }
+ isc_app_shutdown();
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+
+ interactive = isatty(0);
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ check_ra = true;
+
+ /* setup dighost callbacks */
+ dighost_printmessage = printmessage;
+ dighost_received = received;
+ dighost_trying = trying;
+ dighost_shutdown = query_finished;
+
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+
+ setup_libs();
+ progname = argv[0];
+
+ setup_system(false, false);
+ parse_args(argc, argv);
+ if (keyfile[0] != 0) {
+ setup_file_key();
+ } else if (keysecret[0] != 0) {
+ setup_text_key();
+ }
+ if (domainopt[0] != '\0') {
+ set_search_domain(domainopt);
+ }
+ if (in_use) {
+ result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
+ } else {
+ result = isc_app_onrun(mctx, global_task, getinput, NULL);
+ }
+ check_result(result, "isc_app_onrun");
+ in_use = !in_use;
+
+ (void)isc_app_run();
+
+ puts("");
+ debug("done, and starting to shut down");
+ if (global_event != NULL) {
+ isc_event_free(&global_event);
+ }
+ cancel_all();
+ destroy_libs();
+ isc_app_finish();
+
+ return (query_error | print_error);
+}
diff --git a/bin/dig/nslookup.rst b/bin/dig/nslookup.rst
new file mode 100644
index 0000000..2b92aa7
--- /dev/null
+++ b/bin/dig/nslookup.rst
@@ -0,0 +1,208 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: nslookup
+.. program:: nslookup
+.. _man_nslookup:
+
+nslookup - query Internet name servers interactively
+----------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`nslookup` [-option] [name | -] [server]
+
+Description
+~~~~~~~~~~~
+
+:program:`nslookup` is a program to query Internet domain name servers.
+:program:`nslookup` has two modes: interactive and non-interactive. Interactive
+mode allows the user to query name servers for information about various
+hosts and domains or to print a list of hosts in a domain.
+Non-interactive mode prints just the name and requested
+information for a host or domain.
+
+Arguments
+~~~~~~~~~
+
+Interactive mode is entered in the following cases:
+
+a. when no arguments are given (the default name server is used);
+
+b. when the first argument is a hyphen (-) and the second argument is
+ the host name or Internet address of a name server.
+
+Non-interactive mode is used when the name or Internet address of the
+host to be looked up is given as the first argument. The optional second
+argument specifies the host name or address of a name server.
+
+Options can also be specified on the command line if they precede the
+arguments and are prefixed with a hyphen. For example, to change the
+default query type to host information, with an initial timeout of 10
+seconds, type:
+
+::
+
+ nslookup -query=hinfo -timeout=10
+
+The ``-version`` option causes :program:`nslookup` to print the version number
+and immediately exit.
+
+Interactive Commands
+~~~~~~~~~~~~~~~~~~~~
+
+``host [server]``
+ This command looks up information for :iscman:`host` using the current default server or
+ using ``server``, if specified. If :iscman:`host` is an Internet address and the
+ query type is A or PTR, the name of the host is returned. If :iscman:`host` is
+ a name and does not have a trailing period (``.``), the search list is used
+ to qualify the name.
+
+ To look up a host not in the current domain, append a period to the
+ name.
+
+``server domain`` | ``lserver domain``
+ These commands change the default server to ``domain``; ``lserver`` uses the initial
+ server to look up information about ``domain``, while ``server`` uses the
+ current default server. If an authoritative answer cannot be found,
+ the names of servers that might have the answer are returned.
+
+``root``
+ This command is not implemented.
+
+``finger``
+ This command is not implemented.
+
+``ls``
+ This command is not implemented.
+
+``view``
+ This command is not implemented.
+
+``help``
+ This command is not implemented.
+
+``?``
+ This command is not implemented.
+
+``exit``
+ This command exits the program.
+
+``set keyword[=value]``
+ This command is used to change state information that affects the
+ lookups. Valid keywords are:
+
+ ``all``
+ This keyword prints the current values of the frequently used options to
+ ``set``. Information about the current default server and host is
+ also printed.
+
+ ``class=value``
+ This keyword changes the query class to one of:
+
+ ``IN``
+ the Internet class
+
+ ``CH``
+ the Chaos class
+
+ ``HS``
+ the Hesiod class
+
+ ``ANY``
+ wildcard
+
+ The class specifies the protocol group of the information. The default
+ is ``IN``; the abbreviation for this keyword is ``cl``.
+
+ ``nodebug``
+ This keyword turns on or off the display of the full response packet, and any
+ intermediate response packets, when searching. The default for this keyword is
+ ``nodebug``; the abbreviation for this keyword is ``[no]deb``.
+
+ ``nod2``
+ This keyword turns debugging mode on or off. This displays more about what
+ nslookup is doing. The default is ``nod2``.
+
+ ``domain=name``
+ This keyword sets the search list to ``name``.
+
+ ``nosearch``
+ If the lookup request contains at least one period, but does not end
+ with a trailing period, this keyword appends the domain names in the domain
+ search list to the request until an answer is received. The default is ``search``.
+
+ ``port=value``
+ This keyword changes the default TCP/UDP name server port to ``value`` from
+ its default, port 53. The abbreviation for this keyword is ``po``.
+
+ ``querytype=value`` | ``type=value``
+ This keyword changes the type of the information query to ``value``. The
+ defaults are A and then AAAA; the abbreviations for these keywords are
+ ``q`` and ``ty``.
+
+ Please note that it is only possible to specify one query type. Only the default
+ behavior looks up both when an alternative is not specified.
+
+ ``norecurse``
+ This keyword tells the name server to query other servers if it does not have
+ the information. The default is ``recurse``; the abbreviation for this
+ keyword is ``[no]rec``.
+
+ ``ndots=number``
+ This keyword sets the number of dots (label separators) in a domain that
+ disables searching. Absolute names always stop searching.
+
+ ``retry=number``
+ This keyword sets the number of retries to ``number``.
+
+ ``timeout=number``
+ This keyword changes the initial timeout interval to wait for a reply to
+ ``number``, in seconds.
+
+ ``novc``
+ This keyword indicates that a virtual circuit should always be used when sending requests to the server.
+ ``novc`` is the default.
+
+ ``nofail``
+ This keyword tries the next nameserver if a nameserver responds with SERVFAIL or
+ a referral (nofail), or terminates the query (fail) on such a response. The
+ default is ``nofail``.
+
+Return Values
+~~~~~~~~~~~~~
+
+:program:`nslookup` returns with an exit status of 1 if any query failed, and 0
+otherwise.
+
+IDN Support
+~~~~~~~~~~~
+
+If :program:`nslookup` has been built with IDN (internationalized domain name)
+support, it can accept and display non-ASCII domain names. :program:`nslookup`
+appropriately converts character encoding of a domain name before sending
+a request to a DNS server or displaying a reply from the server.
+To turn off IDN support, define the ``IDN_DISABLE``
+environment variable. IDN support is disabled if the variable is set
+when :program:`nslookup` runs, or when the standard output is not a tty.
+
+Files
+~~~~~
+
+``/etc/resolv.conf``
+
+See Also
+~~~~~~~~
+
+:iscman:`dig(1) <dig>`, :iscman:`host(1) <host>`, :iscman:`named(8) <named>`.
diff --git a/bin/dig/readline.h b/bin/dig/readline.h
new file mode 100644
index 0000000..68a38c3
--- /dev/null
+++ b/bin/dig/readline.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*
+ * A little wrapper around readline(), add_history() and free() to make using
+ * the readline code simpler.
+ */
+
+#if defined(HAVE_READLINE_LIBEDIT)
+#include <editline/readline.h>
+#elif defined(HAVE_READLINE_EDITLINE)
+#include <editline.h>
+#elif defined(HAVE_READLINE_READLINE)
+/* Prevent deprecated functions being declared. */
+#define _FUNCTION_DEF 1
+/* Ensure rl_message() gets prototype. */
+#define USE_VARARGS 1
+#define PREFER_STDARG 1
+#include <readline/history.h>
+#include <readline/readline.h>
+#endif
+
+#if !defined(HAVE_READLINE_LIBEDIT) && !defined(HAVE_READLINE_EDITLINE) && \
+ !defined(HAVE_READLINE_READLINE)
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define RL_MAXCMD (128 * 1024)
+
+static inline char *
+readline(const char *prompt) {
+ char *line, *buf = malloc(RL_MAXCMD);
+ fprintf(stdout, "%s", prompt);
+ fflush(stdout);
+ line = fgets(buf, RL_MAXCMD, stdin);
+ if (line == NULL) {
+ free(buf);
+ return (NULL);
+ }
+ return (buf);
+};
+
+#define add_history(line)
+
+#endif
diff --git a/bin/dnssec/Makefile.am b/bin/dnssec/Makefile.am
new file mode 100644
index 0000000..32c4626
--- /dev/null
+++ b/bin/dnssec/Makefile.am
@@ -0,0 +1,38 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+AM_CPPFLAGS += \
+ -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\"
+
+noinst_LTLIBRARIES = libdnssectool.la
+
+LDADD += \
+ libdnssectool.la \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+
+bin_PROGRAMS = \
+ dnssec-cds \
+ dnssec-dsfromkey \
+ dnssec-importkey \
+ dnssec-keyfromlabel \
+ dnssec-keygen \
+ dnssec-revoke \
+ dnssec-settime \
+ dnssec-signzone \
+ dnssec-verify
+
+libdnssectool_la_SOURCES = \
+ dnssectool.h \
+ dnssectool.c
+
+dnssec_keygen_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBISCCFG_CFLAGS)
+
+dnssec_keygen_LDADD = \
+ $(LDADD) \
+ $(LIBISCCFG_LIBS)
diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in
new file mode 100644
index 0000000..47c7352
--- /dev/null
+++ b/bin/dnssec/Makefile.in
@@ -0,0 +1,976 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+bin_PROGRAMS = dnssec-cds$(EXEEXT) dnssec-dsfromkey$(EXEEXT) \
+ dnssec-importkey$(EXEEXT) dnssec-keyfromlabel$(EXEEXT) \
+ dnssec-keygen$(EXEEXT) dnssec-revoke$(EXEEXT) \
+ dnssec-settime$(EXEEXT) dnssec-signzone$(EXEEXT) \
+ dnssec-verify$(EXEEXT)
+subdir = bin/dnssec
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libdnssectool_la_LIBADD =
+am_libdnssectool_la_OBJECTS = dnssectool.lo
+libdnssectool_la_OBJECTS = $(am_libdnssectool_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+dnssec_cds_SOURCES = dnssec-cds.c
+dnssec_cds_OBJECTS = dnssec-cds.$(OBJEXT)
+dnssec_cds_LDADD = $(LDADD)
+dnssec_cds_DEPENDENCIES = libdnssectool.la $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+dnssec_dsfromkey_SOURCES = dnssec-dsfromkey.c
+dnssec_dsfromkey_OBJECTS = dnssec-dsfromkey.$(OBJEXT)
+dnssec_dsfromkey_LDADD = $(LDADD)
+dnssec_dsfromkey_DEPENDENCIES = libdnssectool.la $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+dnssec_importkey_SOURCES = dnssec-importkey.c
+dnssec_importkey_OBJECTS = dnssec-importkey.$(OBJEXT)
+dnssec_importkey_LDADD = $(LDADD)
+dnssec_importkey_DEPENDENCIES = libdnssectool.la $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+dnssec_keyfromlabel_SOURCES = dnssec-keyfromlabel.c
+dnssec_keyfromlabel_OBJECTS = dnssec-keyfromlabel.$(OBJEXT)
+dnssec_keyfromlabel_LDADD = $(LDADD)
+dnssec_keyfromlabel_DEPENDENCIES = libdnssectool.la $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+dnssec_keygen_SOURCES = dnssec-keygen.c
+dnssec_keygen_OBJECTS = dnssec_keygen-dnssec-keygen.$(OBJEXT)
+dnssec_keygen_DEPENDENCIES = $(LDADD) $(LIBISCCFG_LIBS)
+dnssec_revoke_SOURCES = dnssec-revoke.c
+dnssec_revoke_OBJECTS = dnssec-revoke.$(OBJEXT)
+dnssec_revoke_LDADD = $(LDADD)
+dnssec_revoke_DEPENDENCIES = libdnssectool.la $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+dnssec_settime_SOURCES = dnssec-settime.c
+dnssec_settime_OBJECTS = dnssec-settime.$(OBJEXT)
+dnssec_settime_LDADD = $(LDADD)
+dnssec_settime_DEPENDENCIES = libdnssectool.la $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+dnssec_signzone_SOURCES = dnssec-signzone.c
+dnssec_signzone_OBJECTS = dnssec-signzone.$(OBJEXT)
+dnssec_signzone_LDADD = $(LDADD)
+dnssec_signzone_DEPENDENCIES = libdnssectool.la $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+dnssec_verify_SOURCES = dnssec-verify.c
+dnssec_verify_OBJECTS = dnssec-verify.$(OBJEXT)
+dnssec_verify_LDADD = $(LDADD)
+dnssec_verify_DEPENDENCIES = libdnssectool.la $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/dnssec-cds.Po \
+ ./$(DEPDIR)/dnssec-dsfromkey.Po \
+ ./$(DEPDIR)/dnssec-importkey.Po \
+ ./$(DEPDIR)/dnssec-keyfromlabel.Po \
+ ./$(DEPDIR)/dnssec-revoke.Po ./$(DEPDIR)/dnssec-settime.Po \
+ ./$(DEPDIR)/dnssec-signzone.Po ./$(DEPDIR)/dnssec-verify.Po \
+ ./$(DEPDIR)/dnssec_keygen-dnssec-keygen.Po \
+ ./$(DEPDIR)/dnssectool.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libdnssectool_la_SOURCES) dnssec-cds.c dnssec-dsfromkey.c \
+ dnssec-importkey.c dnssec-keyfromlabel.c dnssec-keygen.c \
+ dnssec-revoke.c dnssec-settime.c dnssec-signzone.c \
+ dnssec-verify.c
+DIST_SOURCES = $(libdnssectool_la_SOURCES) dnssec-cds.c \
+ dnssec-dsfromkey.c dnssec-importkey.c dnssec-keyfromlabel.c \
+ dnssec-keygen.c dnssec-revoke.c dnssec-settime.c \
+ dnssec-signzone.c dnssec-verify.c
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \
+ -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\"
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD = libdnssectool.la $(LIBISC_LIBS) $(LIBDNS_LIBS)
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+noinst_LTLIBRARIES = libdnssectool.la
+libdnssectool_la_SOURCES = \
+ dnssectool.h \
+ dnssectool.c
+
+dnssec_keygen_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBISCCFG_CFLAGS)
+
+dnssec_keygen_LDADD = \
+ $(LDADD) \
+ $(LIBISCCFG_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/dnssec/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/dnssec/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libdnssectool.la: $(libdnssectool_la_OBJECTS) $(libdnssectool_la_DEPENDENCIES) $(EXTRA_libdnssectool_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libdnssectool_la_OBJECTS) $(libdnssectool_la_LIBADD) $(LIBS)
+
+dnssec-cds$(EXEEXT): $(dnssec_cds_OBJECTS) $(dnssec_cds_DEPENDENCIES) $(EXTRA_dnssec_cds_DEPENDENCIES)
+ @rm -f dnssec-cds$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dnssec_cds_OBJECTS) $(dnssec_cds_LDADD) $(LIBS)
+
+dnssec-dsfromkey$(EXEEXT): $(dnssec_dsfromkey_OBJECTS) $(dnssec_dsfromkey_DEPENDENCIES) $(EXTRA_dnssec_dsfromkey_DEPENDENCIES)
+ @rm -f dnssec-dsfromkey$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dnssec_dsfromkey_OBJECTS) $(dnssec_dsfromkey_LDADD) $(LIBS)
+
+dnssec-importkey$(EXEEXT): $(dnssec_importkey_OBJECTS) $(dnssec_importkey_DEPENDENCIES) $(EXTRA_dnssec_importkey_DEPENDENCIES)
+ @rm -f dnssec-importkey$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dnssec_importkey_OBJECTS) $(dnssec_importkey_LDADD) $(LIBS)
+
+dnssec-keyfromlabel$(EXEEXT): $(dnssec_keyfromlabel_OBJECTS) $(dnssec_keyfromlabel_DEPENDENCIES) $(EXTRA_dnssec_keyfromlabel_DEPENDENCIES)
+ @rm -f dnssec-keyfromlabel$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dnssec_keyfromlabel_OBJECTS) $(dnssec_keyfromlabel_LDADD) $(LIBS)
+
+dnssec-keygen$(EXEEXT): $(dnssec_keygen_OBJECTS) $(dnssec_keygen_DEPENDENCIES) $(EXTRA_dnssec_keygen_DEPENDENCIES)
+ @rm -f dnssec-keygen$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dnssec_keygen_OBJECTS) $(dnssec_keygen_LDADD) $(LIBS)
+
+dnssec-revoke$(EXEEXT): $(dnssec_revoke_OBJECTS) $(dnssec_revoke_DEPENDENCIES) $(EXTRA_dnssec_revoke_DEPENDENCIES)
+ @rm -f dnssec-revoke$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dnssec_revoke_OBJECTS) $(dnssec_revoke_LDADD) $(LIBS)
+
+dnssec-settime$(EXEEXT): $(dnssec_settime_OBJECTS) $(dnssec_settime_DEPENDENCIES) $(EXTRA_dnssec_settime_DEPENDENCIES)
+ @rm -f dnssec-settime$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dnssec_settime_OBJECTS) $(dnssec_settime_LDADD) $(LIBS)
+
+dnssec-signzone$(EXEEXT): $(dnssec_signzone_OBJECTS) $(dnssec_signzone_DEPENDENCIES) $(EXTRA_dnssec_signzone_DEPENDENCIES)
+ @rm -f dnssec-signzone$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dnssec_signzone_OBJECTS) $(dnssec_signzone_LDADD) $(LIBS)
+
+dnssec-verify$(EXEEXT): $(dnssec_verify_OBJECTS) $(dnssec_verify_DEPENDENCIES) $(EXTRA_dnssec_verify_DEPENDENCIES)
+ @rm -f dnssec-verify$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dnssec_verify_OBJECTS) $(dnssec_verify_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-cds.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-dsfromkey.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-importkey.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-keyfromlabel.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-revoke.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-settime.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-signzone.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-verify.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec_keygen-dnssec-keygen.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssectool.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+dnssec_keygen-dnssec-keygen.o: dnssec-keygen.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_keygen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dnssec_keygen-dnssec-keygen.o -MD -MP -MF $(DEPDIR)/dnssec_keygen-dnssec-keygen.Tpo -c -o dnssec_keygen-dnssec-keygen.o `test -f 'dnssec-keygen.c' || echo '$(srcdir)/'`dnssec-keygen.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dnssec_keygen-dnssec-keygen.Tpo $(DEPDIR)/dnssec_keygen-dnssec-keygen.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnssec-keygen.c' object='dnssec_keygen-dnssec-keygen.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_keygen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dnssec_keygen-dnssec-keygen.o `test -f 'dnssec-keygen.c' || echo '$(srcdir)/'`dnssec-keygen.c
+
+dnssec_keygen-dnssec-keygen.obj: dnssec-keygen.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_keygen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dnssec_keygen-dnssec-keygen.obj -MD -MP -MF $(DEPDIR)/dnssec_keygen-dnssec-keygen.Tpo -c -o dnssec_keygen-dnssec-keygen.obj `if test -f 'dnssec-keygen.c'; then $(CYGPATH_W) 'dnssec-keygen.c'; else $(CYGPATH_W) '$(srcdir)/dnssec-keygen.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dnssec_keygen-dnssec-keygen.Tpo $(DEPDIR)/dnssec_keygen-dnssec-keygen.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnssec-keygen.c' object='dnssec_keygen-dnssec-keygen.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_keygen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dnssec_keygen-dnssec-keygen.obj `if test -f 'dnssec-keygen.c'; then $(CYGPATH_W) 'dnssec-keygen.c'; else $(CYGPATH_W) '$(srcdir)/dnssec-keygen.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/dnssec-cds.Po
+ -rm -f ./$(DEPDIR)/dnssec-dsfromkey.Po
+ -rm -f ./$(DEPDIR)/dnssec-importkey.Po
+ -rm -f ./$(DEPDIR)/dnssec-keyfromlabel.Po
+ -rm -f ./$(DEPDIR)/dnssec-revoke.Po
+ -rm -f ./$(DEPDIR)/dnssec-settime.Po
+ -rm -f ./$(DEPDIR)/dnssec-signzone.Po
+ -rm -f ./$(DEPDIR)/dnssec-verify.Po
+ -rm -f ./$(DEPDIR)/dnssec_keygen-dnssec-keygen.Po
+ -rm -f ./$(DEPDIR)/dnssectool.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/dnssec-cds.Po
+ -rm -f ./$(DEPDIR)/dnssec-dsfromkey.Po
+ -rm -f ./$(DEPDIR)/dnssec-importkey.Po
+ -rm -f ./$(DEPDIR)/dnssec-keyfromlabel.Po
+ -rm -f ./$(DEPDIR)/dnssec-revoke.Po
+ -rm -f ./$(DEPDIR)/dnssec-settime.Po
+ -rm -f ./$(DEPDIR)/dnssec-signzone.Po
+ -rm -f ./$(DEPDIR)/dnssec-verify.Po
+ -rm -f ./$(DEPDIR)/dnssec_keygen-dnssec-keygen.Po
+ -rm -f ./$(DEPDIR)/dnssectool.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am: uninstall-binPROGRAMS
+
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-binPROGRAMS clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir doc-am doc-local dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am test-am test-local uninstall uninstall-am \
+ uninstall-binPROGRAMS unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/dnssec/dnssec-cds.c b/bin/dnssec/dnssec-cds.c
new file mode 100644
index 0000000..06b1f8c
--- /dev/null
+++ b/bin/dnssec/dnssec-cds.c
@@ -0,0 +1,1361 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Written by Tony Finch <dot@dotat.at> <fanf2@cam.ac.uk>
+ * at Cambridge University Information Services
+ */
+
+/*! \file */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/serial.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/dnssec.h>
+#include <dns/ds.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+#include <dns/time.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-cds";
+
+/*
+ * Infrastructure
+ */
+static isc_log_t *lctx = NULL;
+static isc_mem_t *mctx = NULL;
+
+/*
+ * The domain we are working on
+ */
+static const char *namestr = NULL;
+static dns_fixedname_t fixed;
+static dns_name_t *name = NULL;
+static dns_rdataclass_t rdclass = dns_rdataclass_in;
+
+static const char *startstr = NULL; /* from which we derive notbefore */
+static isc_stdtime_t notbefore = 0; /* restrict sig inception times */
+static dns_rdata_rrsig_t oldestsig; /* for recording inception time */
+
+static int nkey; /* number of child zone DNSKEY records */
+
+/*
+ * The validation strategy of this program is top-down.
+ *
+ * We start with an implicitly trusted authoritative dsset.
+ *
+ * The child DNSKEY RRset is scanned to find out which keys are
+ * authenticated by DS records, and the result is recorded in a key
+ * table as described later in this comment.
+ *
+ * The key table is used up to three times to verify the signatures on
+ * the child DNSKEY, CDNSKEY, and CDS RRsets. In this program, only keys
+ * that have matching DS records are used for validating signatures.
+ *
+ * For replay attack protection, signatures are ignored if their inception
+ * time is before the previously recorded inception time. We use the earliest
+ * signature so that another run of dnssec-cds with the same records will
+ * still accept all the signatures.
+ *
+ * A key table is an array of nkey keyinfo structures, like
+ *
+ * keyinfo_t key_tbl[nkey];
+ *
+ * Each key is decoded into more useful representations, held in
+ * keyinfo->rdata
+ * keyinfo->dst
+ *
+ * If a key has no matching DS record then keyinfo->dst is NULL.
+ *
+ * The key algorithm and ID are saved in keyinfo->algo and
+ * keyinfo->tag for quicky skipping DS and RRSIG records that can't
+ * match.
+ */
+typedef struct keyinfo {
+ dns_rdata_t rdata;
+ dst_key_t *dst;
+ dns_secalg_t algo;
+ dns_keytag_t tag;
+} keyinfo_t;
+
+/* A replaceable function that can generate a DS RRset from some input */
+typedef isc_result_t
+ds_maker_func_t(isc_buffer_t *buf, dns_rdata_t *ds, dns_dsdigest_t dt,
+ dns_rdata_t *crdata);
+
+static dns_rdataset_t cdnskey_set = DNS_RDATASET_INIT;
+static dns_rdataset_t cdnskey_sig = DNS_RDATASET_INIT;
+static dns_rdataset_t cds_set = DNS_RDATASET_INIT;
+static dns_rdataset_t cds_sig = DNS_RDATASET_INIT;
+static dns_rdataset_t dnskey_set = DNS_RDATASET_INIT;
+static dns_rdataset_t dnskey_sig = DNS_RDATASET_INIT;
+static dns_rdataset_t old_ds_set = DNS_RDATASET_INIT;
+static dns_rdataset_t new_ds_set = DNS_RDATASET_INIT;
+
+static keyinfo_t *old_key_tbl = NULL, *new_key_tbl = NULL;
+
+isc_buffer_t *new_ds_buf = NULL; /* backing store for new_ds_set */
+
+static dns_db_t *child_db = NULL;
+static dns_dbnode_t *child_node = NULL;
+static dns_db_t *parent_db = NULL;
+static dns_dbnode_t *parent_node = NULL;
+static dns_db_t *update_db = NULL;
+static dns_dbnode_t *update_node = NULL;
+static dns_dbversion_t *update_version = NULL;
+static bool cleanup_dst = false;
+static bool print_mem_stats = false;
+
+static void
+verbose_time(int level, const char *msg, isc_stdtime_t time) {
+ isc_result_t result;
+ isc_buffer_t timebuf;
+ char timestr[32];
+
+ if (verbose < level) {
+ return;
+ }
+
+ isc_buffer_init(&timebuf, timestr, sizeof(timestr));
+ result = dns_time64_totext(time, &timebuf);
+ check_result(result, "dns_time64_totext()");
+ isc_buffer_putuint8(&timebuf, 0);
+ if (verbose < 3) {
+ vbprintf(level, "%s %s\n", msg, timestr);
+ } else {
+ vbprintf(level, "%s %s (%" PRIu32 ")\n", msg, timestr, time);
+ }
+}
+
+static void
+initname(char *setname) {
+ isc_result_t result;
+ isc_buffer_t buf;
+
+ name = dns_fixedname_initname(&fixed);
+ namestr = setname;
+
+ isc_buffer_init(&buf, setname, strlen(setname));
+ isc_buffer_add(&buf, strlen(setname));
+ result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not initialize name %s", setname);
+ }
+}
+
+static void
+findset(dns_db_t *db, dns_dbnode_t *node, dns_rdatatype_t type,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
+ isc_result_t result;
+
+ dns_rdataset_init(rdataset);
+ if (sigrdataset != NULL) {
+ dns_rdataset_init(sigrdataset);
+ }
+ result = dns_db_findrdataset(db, node, NULL, type, 0, 0, rdataset,
+ sigrdataset);
+ if (result != ISC_R_NOTFOUND) {
+ check_result(result, "dns_db_findrdataset()");
+ }
+}
+
+static void
+freeset(dns_rdataset_t *rdataset) {
+ if (dns_rdataset_isassociated(rdataset)) {
+ dns_rdataset_disassociate(rdataset);
+ }
+}
+
+static void
+freelist(dns_rdataset_t *rdataset) {
+ dns_rdatalist_t *rdlist;
+ dns_rdata_t *rdata;
+
+ if (!dns_rdataset_isassociated(rdataset)) {
+ return;
+ }
+
+ dns_rdatalist_fromrdataset(rdataset, &rdlist);
+
+ for (rdata = ISC_LIST_HEAD(rdlist->rdata); rdata != NULL;
+ rdata = ISC_LIST_HEAD(rdlist->rdata))
+ {
+ ISC_LIST_UNLINK(rdlist->rdata, rdata, link);
+ isc_mem_put(mctx, rdata, sizeof(*rdata));
+ }
+ isc_mem_put(mctx, rdlist, sizeof(*rdlist));
+ dns_rdataset_disassociate(rdataset);
+}
+
+static void
+free_all_sets(void) {
+ freeset(&cdnskey_set);
+ freeset(&cdnskey_sig);
+ freeset(&cds_set);
+ freeset(&cds_sig);
+ freeset(&dnskey_set);
+ freeset(&dnskey_sig);
+ freeset(&old_ds_set);
+ freelist(&new_ds_set);
+ if (new_ds_buf != NULL) {
+ isc_buffer_free(&new_ds_buf);
+ }
+}
+
+static void
+load_db(const char *filename, dns_db_t **dbp, dns_dbnode_t **nodep) {
+ isc_result_t result;
+
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0,
+ NULL, dbp);
+ check_result(result, "dns_db_create()");
+
+ result = dns_db_load(*dbp, filename, dns_masterformat_text,
+ DNS_MASTER_HINT);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
+ fatal("can't load %s: %s", filename, isc_result_totext(result));
+ }
+
+ result = dns_db_findnode(*dbp, name, false, nodep);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't find %s node in %s", namestr, filename);
+ }
+}
+
+static void
+free_db(dns_db_t **dbp, dns_dbnode_t **nodep, dns_dbversion_t **versionp) {
+ if (*dbp != NULL) {
+ if (*nodep != NULL) {
+ dns_db_detachnode(*dbp, nodep);
+ }
+ if (versionp != NULL && *versionp != NULL) {
+ dns_db_closeversion(*dbp, versionp, false);
+ }
+ dns_db_detach(dbp);
+ }
+}
+
+static void
+load_child_sets(const char *file) {
+ load_db(file, &child_db, &child_node);
+ findset(child_db, child_node, dns_rdatatype_dnskey, &dnskey_set,
+ &dnskey_sig);
+ findset(child_db, child_node, dns_rdatatype_cdnskey, &cdnskey_set,
+ &cdnskey_sig);
+ findset(child_db, child_node, dns_rdatatype_cds, &cds_set, &cds_sig);
+ free_db(&child_db, &child_node, NULL);
+}
+
+static void
+get_dsset_name(char *filename, size_t size, const char *path,
+ const char *suffix) {
+ isc_result_t result;
+ isc_buffer_t buf;
+ size_t len;
+
+ isc_buffer_init(&buf, filename, size);
+
+ len = strlen(path);
+
+ /* allow room for a trailing slash */
+ if (isc_buffer_availablelength(&buf) <= len) {
+ fatal("%s: pathname too long", path);
+ }
+ isc_buffer_putstr(&buf, path);
+
+ if (isc_file_isdirectory(path) == ISC_R_SUCCESS) {
+ const char *prefix = "dsset-";
+
+ if (path[len - 1] != '/') {
+ isc_buffer_putstr(&buf, "/");
+ }
+
+ if (isc_buffer_availablelength(&buf) < strlen(prefix)) {
+ fatal("%s: pathname too long", path);
+ }
+ isc_buffer_putstr(&buf, prefix);
+
+ result = dns_name_tofilenametext(name, false, &buf);
+ check_result(result, "dns_name_tofilenametext()");
+ if (isc_buffer_availablelength(&buf) == 0) {
+ fatal("%s: pathname too long", path);
+ }
+ }
+ /* allow room for a trailing nul */
+ if (isc_buffer_availablelength(&buf) <= strlen(suffix)) {
+ fatal("%s: pathname too long", path);
+ }
+ isc_buffer_putstr(&buf, suffix);
+ isc_buffer_putuint8(&buf, 0);
+}
+
+static void
+load_parent_set(const char *path) {
+ isc_result_t result;
+ isc_time_t modtime;
+ char filename[PATH_MAX + 1];
+
+ get_dsset_name(filename, sizeof(filename), path, "");
+
+ result = isc_file_getmodtime(filename, &modtime);
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not get modification time of %s: %s", filename,
+ isc_result_totext(result));
+ }
+ notbefore = isc_time_seconds(&modtime);
+ if (startstr != NULL) {
+ isc_stdtime_t now;
+ isc_stdtime_get(&now);
+ notbefore = strtotime(startstr, now, notbefore, NULL);
+ }
+ verbose_time(1, "child records must not be signed before", notbefore);
+
+ load_db(filename, &parent_db, &parent_node);
+ findset(parent_db, parent_node, dns_rdatatype_ds, &old_ds_set, NULL);
+
+ if (!dns_rdataset_isassociated(&old_ds_set)) {
+ fatal("could not find DS records for %s in %s", namestr,
+ filename);
+ }
+
+ free_db(&parent_db, &parent_node, NULL);
+}
+
+#define MAX_CDS_RDATA_TEXT_SIZE DNS_RDATA_MAXLENGTH * 2
+
+static isc_buffer_t *
+formatset(dns_rdataset_t *rdataset) {
+ isc_result_t result;
+ isc_buffer_t *buf = NULL;
+ dns_master_style_t *style = NULL;
+ unsigned int styleflags;
+
+ styleflags = (rdataset->ttl == 0) ? DNS_STYLEFLAG_NO_TTL : 0;
+
+ /*
+ * This style is for consistency with the output of dnssec-dsfromkey
+ * which just separates fields with spaces. The huge tab stop width
+ * eliminates any tab characters.
+ */
+ result = dns_master_stylecreate(&style, styleflags, 0, 0, 0, 0, 0,
+ 1000000, 0, mctx);
+ check_result(result, "dns_master_stylecreate2 failed");
+
+ isc_buffer_allocate(mctx, &buf, MAX_CDS_RDATA_TEXT_SIZE);
+ result = dns_master_rdatasettotext(name, rdataset, style, NULL, buf);
+ dns_master_styledestroy(&style, mctx);
+
+ if ((result == ISC_R_SUCCESS) && isc_buffer_availablelength(buf) < 1) {
+ result = ISC_R_NOSPACE;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ isc_buffer_free(&buf);
+ check_result(result, "dns_rdataset_totext()");
+ }
+
+ isc_buffer_putuint8(buf, 0);
+ return (buf);
+}
+
+static void
+write_parent_set(const char *path, const char *inplace, bool nsupdate,
+ dns_rdataset_t *rdataset) {
+ isc_result_t result;
+ isc_buffer_t *buf = NULL;
+ isc_region_t r;
+ isc_time_t filetime;
+ char backname[PATH_MAX + 1];
+ char filename[PATH_MAX + 1];
+ char tmpname[PATH_MAX + 1];
+ FILE *fp = NULL;
+
+ if (nsupdate && inplace == NULL) {
+ return;
+ }
+
+ buf = formatset(rdataset);
+ isc_buffer_usedregion(buf, &r);
+
+ /*
+ * Try to ensure a write error doesn't make a zone go insecure!
+ */
+ if (inplace == NULL) {
+ printf("%s", (char *)r.base);
+ isc_buffer_free(&buf);
+ if (fflush(stdout) == EOF) {
+ fatal("error writing to stdout: %s", strerror(errno));
+ }
+ return;
+ }
+
+ if (inplace[0] != '\0') {
+ get_dsset_name(backname, sizeof(backname), path, inplace);
+ }
+ get_dsset_name(filename, sizeof(filename), path, "");
+ get_dsset_name(tmpname, sizeof(tmpname), path, "-XXXXXXXXXX");
+
+ result = isc_file_openunique(tmpname, &fp);
+ if (result != ISC_R_SUCCESS) {
+ isc_buffer_free(&buf);
+ fatal("open %s: %s", tmpname, isc_result_totext(result));
+ }
+ fprintf(fp, "%s", (char *)r.base);
+ isc_buffer_free(&buf);
+ if (fclose(fp) == EOF) {
+ int err = errno;
+ isc_file_remove(tmpname);
+ fatal("error writing to %s: %s", tmpname, strerror(err));
+ }
+
+ isc_time_set(&filetime, oldestsig.timesigned, 0);
+ result = isc_file_settime(tmpname, &filetime);
+ if (result != ISC_R_SUCCESS) {
+ isc_file_remove(tmpname);
+ fatal("can't set modification time of %s: %s", tmpname,
+ isc_result_totext(result));
+ }
+
+ if (inplace[0] != '\0') {
+ isc_file_rename(filename, backname);
+ }
+ isc_file_rename(tmpname, filename);
+}
+
+typedef enum { LOOSE, TIGHT } strictness_t;
+
+/*
+ * Find out if any (C)DS record matches a particular (C)DNSKEY.
+ */
+static bool
+match_key_dsset(keyinfo_t *ki, dns_rdataset_t *dsset, strictness_t strictness) {
+ isc_result_t result;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+
+ for (result = dns_rdataset_first(dsset); result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(dsset))
+ {
+ dns_rdata_ds_t ds;
+ dns_rdata_t dsrdata = DNS_RDATA_INIT;
+ dns_rdata_t newdsrdata = DNS_RDATA_INIT;
+ bool c;
+
+ dns_rdataset_current(dsset, &dsrdata);
+ result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
+ check_result(result, "dns_rdata_tostruct(DS)");
+
+ if (ki->tag != ds.key_tag || ki->algo != ds.algorithm) {
+ continue;
+ }
+
+ result = dns_ds_buildrdata(name, &ki->rdata, ds.digest_type,
+ dsbuf, &newdsrdata);
+ if (result != ISC_R_SUCCESS) {
+ vbprintf(3,
+ "dns_ds_buildrdata("
+ "keytag=%d, algo=%d, digest=%d): %s\n",
+ ds.key_tag, ds.algorithm, ds.digest_type,
+ isc_result_totext(result));
+ continue;
+ }
+ /* allow for both DS and CDS */
+ c = dsrdata.type != dns_rdatatype_ds;
+ dsrdata.type = dns_rdatatype_ds;
+ if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0) {
+ vbprintf(1, "found matching %s %d %d %d\n",
+ c ? "CDS" : "DS", ds.key_tag, ds.algorithm,
+ ds.digest_type);
+ return (true);
+ } else if (strictness == TIGHT) {
+ vbprintf(0,
+ "key does not match %s %d %d %d "
+ "when it looks like it should\n",
+ c ? "CDS" : "DS", ds.key_tag, ds.algorithm,
+ ds.digest_type);
+ return (false);
+ }
+ }
+
+ vbprintf(1, "no matching %s for %s %d %d\n",
+ dsset->type == dns_rdatatype_cds ? "CDS" : "DS",
+ ki->rdata.type == dns_rdatatype_cdnskey ? "CDNSKEY" : "DNSKEY",
+ ki->tag, ki->algo);
+
+ return (false);
+}
+
+/*
+ * Find which (C)DNSKEY records match a (C)DS RRset.
+ * This creates a keyinfo_t key_tbl[nkey] array.
+ */
+static keyinfo_t *
+match_keyset_dsset(dns_rdataset_t *keyset, dns_rdataset_t *dsset,
+ strictness_t strictness) {
+ isc_result_t result;
+ keyinfo_t *keytable, *ki;
+ int i;
+
+ nkey = dns_rdataset_count(keyset);
+
+ keytable = isc_mem_get(mctx, sizeof(keyinfo_t) * nkey);
+
+ for (result = dns_rdataset_first(keyset), i = 0, ki = keytable;
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(keyset), i++, ki++)
+ {
+ dns_rdata_dnskey_t dnskey;
+ dns_rdata_t *keyrdata;
+ isc_region_t r;
+
+ INSIST(i < nkey);
+ keyrdata = &ki->rdata;
+
+ dns_rdata_init(keyrdata);
+ dns_rdataset_current(keyset, keyrdata);
+
+ result = dns_rdata_tostruct(keyrdata, &dnskey, NULL);
+ check_result(result, "dns_rdata_tostruct(DNSKEY)");
+ ki->algo = dnskey.algorithm;
+
+ dns_rdata_toregion(keyrdata, &r);
+ ki->tag = dst_region_computeid(&r);
+
+ ki->dst = NULL;
+ if (!match_key_dsset(ki, dsset, strictness)) {
+ continue;
+ }
+
+ result = dns_dnssec_keyfromrdata(name, keyrdata, mctx,
+ &ki->dst);
+ if (result != ISC_R_SUCCESS) {
+ vbprintf(3,
+ "dns_dnssec_keyfromrdata("
+ "keytag=%d, algo=%d): %s\n",
+ ki->tag, ki->algo, isc_result_totext(result));
+ }
+ }
+
+ return (keytable);
+}
+
+static void
+free_keytable(keyinfo_t **keytable_p) {
+ keyinfo_t *keytable = *keytable_p;
+ *keytable_p = NULL;
+ keyinfo_t *ki;
+ int i;
+
+ REQUIRE(keytable != NULL);
+
+ for (i = 0, ki = keytable; i < nkey; i++, ki++) {
+ if (ki->dst != NULL) {
+ dst_key_free(&ki->dst);
+ }
+ }
+
+ isc_mem_put(mctx, keytable, sizeof(keyinfo_t) * nkey);
+}
+
+/*
+ * Find out which keys have signed an RRset. Keys that do not match a
+ * DS record are skipped.
+ *
+ * The return value is an array with nkey elements, one for each key,
+ * either zero if the key was skipped or did not sign the RRset, or
+ * otherwise the key algorithm. This is used by the signature coverage
+ * check functions below.
+ */
+static dns_secalg_t *
+matching_sigs(keyinfo_t *keytbl, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigset) {
+ isc_result_t result;
+ dns_secalg_t *algo;
+ int i;
+
+ REQUIRE(keytbl != NULL);
+
+ algo = isc_mem_get(mctx, nkey);
+ memset(algo, 0, nkey);
+
+ for (result = dns_rdataset_first(sigset); result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(sigset))
+ {
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t sig;
+
+ dns_rdataset_current(sigset, &sigrdata);
+ result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ check_result(result, "dns_rdata_tostruct(RRSIG)");
+
+ /*
+ * Replay attack protection: check against current age limit
+ */
+ if (isc_serial_lt(sig.timesigned, notbefore)) {
+ vbprintf(1, "skip RRSIG by key %d: too old\n",
+ sig.keyid);
+ continue;
+ }
+
+ for (i = 0; i < nkey; i++) {
+ keyinfo_t *ki = &keytbl[i];
+ if (sig.keyid != ki->tag || sig.algorithm != ki->algo ||
+ !dns_name_equal(&sig.signer, name))
+ {
+ continue;
+ }
+ if (ki->dst == NULL) {
+ vbprintf(1,
+ "skip RRSIG by key %d:"
+ " no matching (C)DS\n",
+ sig.keyid);
+ continue;
+ }
+
+ result = dns_dnssec_verify(name, rdataset, ki->dst,
+ false, 0, mctx, &sigrdata,
+ NULL);
+
+ if (result != ISC_R_SUCCESS &&
+ result != DNS_R_FROMWILDCARD)
+ {
+ vbprintf(1,
+ "skip RRSIG by key %d:"
+ " verification failed: %s\n",
+ sig.keyid, isc_result_totext(result));
+ continue;
+ }
+
+ vbprintf(1, "found RRSIG by key %d\n", ki->tag);
+ algo[i] = sig.algorithm;
+
+ /*
+ * Replay attack protection: work out next age limit,
+ * only after the signature has been verified
+ */
+ if (oldestsig.timesigned == 0 ||
+ isc_serial_lt(sig.timesigned, oldestsig.timesigned))
+ {
+ verbose_time(2, "this is the oldest so far",
+ sig.timesigned);
+ oldestsig = sig;
+ }
+ }
+ }
+
+ return (algo);
+}
+
+/*
+ * Consume the result of matching_sigs(). When checking records
+ * fetched from the child zone, any working signature is enough.
+ */
+static bool
+signed_loose(dns_secalg_t *algo) {
+ bool ok = false;
+ int i;
+ for (i = 0; i < nkey; i++) {
+ if (algo[i] != 0) {
+ ok = true;
+ }
+ }
+ isc_mem_put(mctx, algo, nkey);
+ return (ok);
+}
+
+/*
+ * Consume the result of matching_sigs(). To ensure that the new DS
+ * RRset does not break the chain of trust to the DNSKEY RRset, every
+ * key algorithm in the DS RRset must have a signature in the DNSKEY
+ * RRset.
+ */
+static bool
+signed_strict(dns_rdataset_t *dsset, dns_secalg_t *algo) {
+ isc_result_t result;
+ bool all_ok = true;
+
+ for (result = dns_rdataset_first(dsset); result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(dsset))
+ {
+ dns_rdata_t dsrdata = DNS_RDATA_INIT;
+ dns_rdata_ds_t ds;
+ bool ds_ok;
+ int i;
+
+ dns_rdataset_current(dsset, &dsrdata);
+ result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
+ check_result(result, "dns_rdata_tostruct(DS)");
+
+ ds_ok = false;
+ for (i = 0; i < nkey; i++) {
+ if (algo[i] == ds.algorithm) {
+ ds_ok = true;
+ }
+ }
+ if (!ds_ok) {
+ vbprintf(0,
+ "missing signature for algorithm %d "
+ "(key %d)\n",
+ ds.algorithm, ds.key_tag);
+ all_ok = false;
+ }
+ }
+
+ isc_mem_put(mctx, algo, nkey);
+ return (all_ok);
+}
+
+/*
+ * This basically copies the rdata into the buffer, but going via the
+ * unpacked struct lets us change the rdatatype. (The dns_rdata_cds_t
+ * and dns_rdata_ds_t types are aliases.)
+ */
+static isc_result_t
+ds_from_cds(isc_buffer_t *buf, dns_rdata_t *rds, dns_dsdigest_t dt,
+ dns_rdata_t *cds) {
+ isc_result_t result;
+ dns_rdata_ds_t ds;
+
+ REQUIRE(buf != NULL);
+
+ result = dns_rdata_tostruct(cds, &ds, NULL);
+ check_result(result, "dns_rdata_tostruct(CDS)");
+ ds.common.rdtype = dns_rdatatype_ds;
+
+ if (ds.digest_type != dt) {
+ return (ISC_R_IGNORE);
+ }
+
+ return (dns_rdata_fromstruct(rds, rdclass, dns_rdatatype_ds, &ds, buf));
+}
+
+static isc_result_t
+ds_from_cdnskey(isc_buffer_t *buf, dns_rdata_t *ds, dns_dsdigest_t dt,
+ dns_rdata_t *cdnskey) {
+ isc_result_t result;
+ isc_region_t r;
+
+ REQUIRE(buf != NULL);
+
+ isc_buffer_availableregion(buf, &r);
+ if (r.length < DNS_DS_BUFFERSIZE) {
+ return (ISC_R_NOSPACE);
+ }
+
+ result = dns_ds_buildrdata(name, cdnskey, dt, r.base, ds);
+ if (result == ISC_R_SUCCESS) {
+ isc_buffer_add(buf, DNS_DS_BUFFERSIZE);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+append_new_ds_set(ds_maker_func_t *ds_from_rdata, isc_buffer_t *buf,
+ dns_rdatalist_t *dslist, dns_dsdigest_t dt,
+ dns_rdataset_t *crdset) {
+ isc_result_t result;
+
+ for (result = dns_rdataset_first(crdset); result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(crdset))
+ {
+ dns_rdata_t crdata = DNS_RDATA_INIT;
+ dns_rdata_t *ds = NULL;
+
+ dns_rdataset_current(crdset, &crdata);
+
+ ds = isc_mem_get(mctx, sizeof(*ds));
+ dns_rdata_init(ds);
+
+ result = ds_from_rdata(buf, ds, dt, &crdata);
+
+ switch (result) {
+ case ISC_R_SUCCESS:
+ ISC_LIST_APPEND(dslist->rdata, ds, link);
+ break;
+ case ISC_R_IGNORE:
+ isc_mem_put(mctx, ds, sizeof(*ds));
+ continue;
+ case ISC_R_NOSPACE:
+ isc_mem_put(mctx, ds, sizeof(*ds));
+ return (result);
+ default:
+ isc_mem_put(mctx, ds, sizeof(*ds));
+ check_result(result, "ds_from_rdata()");
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+make_new_ds_set(ds_maker_func_t *ds_from_rdata, uint32_t ttl,
+ dns_rdataset_t *crdset) {
+ isc_result_t result;
+ dns_rdatalist_t *dslist;
+ unsigned int size = 16;
+ unsigned i, n;
+
+ for (;;) {
+ dslist = isc_mem_get(mctx, sizeof(*dslist));
+ dns_rdatalist_init(dslist);
+ dslist->rdclass = rdclass;
+ dslist->type = dns_rdatatype_ds;
+ dslist->ttl = ttl;
+
+ dns_rdataset_init(&new_ds_set);
+ result = dns_rdatalist_tordataset(dslist, &new_ds_set);
+ check_result(result, "dns_rdatalist_tordataset(dslist)");
+
+ isc_buffer_allocate(mctx, &new_ds_buf, size);
+
+ n = sizeof(dtype) / sizeof(dtype[0]);
+ for (i = 0; i < n && dtype[i] != 0; i++) {
+ result = append_new_ds_set(ds_from_rdata, new_ds_buf,
+ dslist, dtype[i], crdset);
+ if (result != ISC_R_SUCCESS) {
+ break;
+ }
+ }
+ if (result == ISC_R_SUCCESS) {
+ return;
+ }
+
+ vbprintf(2, "doubling DS list buffer size from %u\n", size);
+ freelist(&new_ds_set);
+ isc_buffer_free(&new_ds_buf);
+ size *= 2;
+ }
+}
+
+static int
+rdata_cmp(const void *rdata1, const void *rdata2) {
+ return (dns_rdata_compare((const dns_rdata_t *)rdata1,
+ (const dns_rdata_t *)rdata2));
+}
+
+/*
+ * Ensure that every key identified by the DS RRset has the same set of
+ * digest types.
+ */
+static bool
+consistent_digests(dns_rdataset_t *dsset) {
+ isc_result_t result;
+ dns_rdata_t *arrdata;
+ dns_rdata_ds_t *ds;
+ dns_keytag_t key_tag;
+ dns_secalg_t algorithm;
+ bool match;
+ int i, j, n, d;
+
+ /*
+ * First sort the dsset. DS rdata fields are tag, algorithm,
+ * digest, so sorting them brings together all the records for
+ * each key.
+ */
+
+ n = dns_rdataset_count(dsset);
+
+ arrdata = isc_mem_get(mctx, n * sizeof(dns_rdata_t));
+
+ for (result = dns_rdataset_first(dsset), i = 0; result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(dsset), i++)
+ {
+ dns_rdata_init(&arrdata[i]);
+ dns_rdataset_current(dsset, &arrdata[i]);
+ }
+
+ qsort(arrdata, n, sizeof(dns_rdata_t), rdata_cmp);
+
+ /*
+ * Convert sorted arrdata to more accessible format
+ */
+ ds = isc_mem_get(mctx, n * sizeof(dns_rdata_ds_t));
+
+ for (i = 0; i < n; i++) {
+ result = dns_rdata_tostruct(&arrdata[i], &ds[i], NULL);
+ check_result(result, "dns_rdata_tostruct(DS)");
+ }
+
+ /*
+ * Count number of digest types (d) for first key
+ */
+ key_tag = ds[0].key_tag;
+ algorithm = ds[0].algorithm;
+ for (d = 0, i = 0; i < n; i++, d++) {
+ if (ds[i].key_tag != key_tag || ds[i].algorithm != algorithm) {
+ break;
+ }
+ }
+
+ /*
+ * Check subsequent keys match the first one
+ */
+ match = true;
+ while (i < n) {
+ key_tag = ds[i].key_tag;
+ algorithm = ds[i].algorithm;
+ for (j = 0; j < d && i + j < n; j++) {
+ if (ds[i + j].key_tag != key_tag ||
+ ds[i + j].algorithm != algorithm ||
+ ds[i + j].digest_type != ds[j].digest_type)
+ {
+ match = false;
+ }
+ }
+ i += d;
+ }
+
+ /*
+ * Done!
+ */
+ isc_mem_put(mctx, ds, n * sizeof(dns_rdata_ds_t));
+ isc_mem_put(mctx, arrdata, n * sizeof(dns_rdata_t));
+
+ return (match);
+}
+
+static void
+print_diff(const char *cmd, dns_rdataset_t *rdataset) {
+ isc_buffer_t *buf;
+ isc_region_t r;
+ unsigned char *nl;
+ size_t len;
+
+ buf = formatset(rdataset);
+ isc_buffer_usedregion(buf, &r);
+
+ while ((nl = memchr(r.base, '\n', r.length)) != NULL) {
+ len = nl - r.base + 1;
+ printf("update %s %.*s", cmd, (int)len, (char *)r.base);
+ isc_region_consume(&r, len);
+ }
+
+ isc_buffer_free(&buf);
+}
+
+static void
+update_diff(const char *cmd, uint32_t ttl, dns_rdataset_t *addset,
+ dns_rdataset_t *delset) {
+ isc_result_t result;
+ dns_rdataset_t diffset;
+ uint32_t save;
+
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0,
+ NULL, &update_db);
+ check_result(result, "dns_db_create()");
+
+ result = dns_db_newversion(update_db, &update_version);
+ check_result(result, "dns_db_newversion()");
+
+ result = dns_db_findnode(update_db, name, true, &update_node);
+ check_result(result, "dns_db_findnode()");
+
+ dns_rdataset_init(&diffset);
+
+ result = dns_db_addrdataset(update_db, update_node, update_version, 0,
+ addset, DNS_DBADD_MERGE, NULL);
+ check_result(result, "dns_db_addrdataset()");
+
+ result = dns_db_subtractrdataset(update_db, update_node, update_version,
+ delset, 0, &diffset);
+ if (result == DNS_R_UNCHANGED) {
+ save = addset->ttl;
+ addset->ttl = ttl;
+ print_diff(cmd, addset);
+ addset->ttl = save;
+ } else if (result != DNS_R_NXRRSET) {
+ check_result(result, "dns_db_subtractrdataset()");
+ diffset.ttl = ttl;
+ print_diff(cmd, &diffset);
+ dns_rdataset_disassociate(&diffset);
+ }
+
+ free_db(&update_db, &update_node, &update_version);
+}
+
+static void
+nsdiff(uint32_t ttl, dns_rdataset_t *oldset, dns_rdataset_t *newset) {
+ if (ttl == 0) {
+ vbprintf(1, "warning: no TTL in nsupdate script\n");
+ }
+ update_diff("add", ttl, newset, oldset);
+ update_diff("del", 0, oldset, newset);
+ if (verbose > 0) {
+ printf("show\nsend\nanswer\n");
+ } else {
+ printf("send\n");
+ }
+ if (fflush(stdout) == EOF) {
+ fatal("write stdout: %s", strerror(errno));
+ }
+}
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ " %s options [options] -f <file> -d <path> <domain>\n",
+ program);
+ fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
+ fprintf(stderr, "Options:\n"
+ " -a <algorithm> digest algorithm (SHA-1 / "
+ "SHA-256 / SHA-384)\n"
+ " -c <class> of domain (default IN)\n"
+ " -D prefer CDNSKEY records instead "
+ "of CDS\n"
+ " -d <file|dir> where to find parent dsset- "
+ "file\n"
+ " -f <file> child DNSKEY+CDNSKEY+CDS+RRSIG "
+ "records\n"
+ " -i[extension] update dsset- file in place\n"
+ " -s <start-time> oldest permitted child "
+ "signatures\n"
+ " -u emit nsupdate script\n"
+ " -T <ttl> TTL of DS records\n"
+ " -V print version\n"
+ " -v <verbosity>\n");
+ exit(1);
+}
+
+static void
+cleanup(void) {
+ free_db(&child_db, &child_node, NULL);
+ free_db(&parent_db, &parent_node, NULL);
+ free_db(&update_db, &update_node, &update_version);
+ if (old_key_tbl != NULL) {
+ free_keytable(&old_key_tbl);
+ }
+ if (new_key_tbl != NULL) {
+ free_keytable(&new_key_tbl);
+ }
+ free_all_sets();
+ if (lctx != NULL) {
+ cleanup_logging(&lctx);
+ }
+ if (cleanup_dst) {
+ dst_lib_destroy();
+ }
+ if (mctx != NULL) {
+ if (print_mem_stats && verbose > 10) {
+ isc_mem_stats(mctx, stdout);
+ }
+ isc_mem_destroy(&mctx);
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ const char *child_path = NULL;
+ const char *ds_path = NULL;
+ const char *inplace = NULL;
+ isc_result_t result;
+ bool prefer_cdnskey = false;
+ bool nsupdate = false;
+ uint32_t ttl = 0;
+ int ch;
+ char *endp;
+
+ setfatalcallback(cleanup);
+
+ isc_mem_create(&mctx);
+
+ isc_commandline_errprint = false;
+
+#define OPTIONS "a:c:Dd:f:i:ms:T:uv:V"
+ while ((ch = isc_commandline_parse(argc, argv, OPTIONS)) != -1) {
+ switch (ch) {
+ case 'a':
+ add_dtype(strtodsdigest(isc_commandline_argument));
+ break;
+ case 'c':
+ rdclass = strtoclass(isc_commandline_argument);
+ break;
+ case 'D':
+ prefer_cdnskey = true;
+ break;
+ case 'd':
+ ds_path = isc_commandline_argument;
+ break;
+ case 'f':
+ child_path = isc_commandline_argument;
+ break;
+ case 'i':
+ /*
+ * This is a bodge to make the argument
+ * optional, so that it works just like sed(1).
+ */
+ if (isc_commandline_argument ==
+ argv[isc_commandline_index - 1])
+ {
+ isc_commandline_index--;
+ inplace = "";
+ } else {
+ inplace = isc_commandline_argument;
+ }
+ break;
+ case 'm':
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE |
+ ISC_MEM_DEBUGRECORD;
+ break;
+ case 's':
+ startstr = isc_commandline_argument;
+ break;
+ case 'T':
+ ttl = strtottl(isc_commandline_argument);
+ break;
+ case 'u':
+ nsupdate = true;
+ break;
+ case 'V':
+ /* Does not return. */
+ version(program);
+ break;
+ case 'v':
+ verbose = strtoul(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fatal("-v must be followed by a number");
+ }
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ argv += isc_commandline_index;
+ argc -= isc_commandline_index;
+
+ if (argc != 1) {
+ usage();
+ }
+ initname(argv[0]);
+
+ /*
+ * Default digest type if none specified.
+ */
+ if (dtype[0] == 0) {
+ dtype[0] = DNS_DSDIGEST_SHA256;
+ }
+
+ setup_logging(mctx, &lctx);
+
+ result = dst_lib_init(mctx, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not initialize dst: %s",
+ isc_result_totext(result));
+ }
+ cleanup_dst = true;
+
+ if (ds_path == NULL) {
+ fatal("missing -d DS pathname");
+ }
+ load_parent_set(ds_path);
+
+ /*
+ * Preserve the TTL if it wasn't overridden.
+ */
+ if (ttl == 0) {
+ ttl = old_ds_set.ttl;
+ }
+
+ if (child_path == NULL) {
+ fatal("path to file containing child data must be specified");
+ }
+
+ load_child_sets(child_path);
+
+ /*
+ * Check child records have accompanying RRSIGs and DNSKEYs
+ */
+
+ if (!dns_rdataset_isassociated(&dnskey_set) ||
+ !dns_rdataset_isassociated(&dnskey_sig))
+ {
+ fatal("could not find signed DNSKEY RRset for %s", namestr);
+ }
+
+ if (dns_rdataset_isassociated(&cdnskey_set) &&
+ !dns_rdataset_isassociated(&cdnskey_sig))
+ {
+ fatal("missing RRSIG CDNSKEY records for %s", namestr);
+ }
+ if (dns_rdataset_isassociated(&cds_set) &&
+ !dns_rdataset_isassociated(&cds_sig))
+ {
+ fatal("missing RRSIG CDS records for %s", namestr);
+ }
+
+ vbprintf(1, "which child DNSKEY records match parent DS records?\n");
+ old_key_tbl = match_keyset_dsset(&dnskey_set, &old_ds_set, LOOSE);
+
+ /*
+ * We have now identified the keys that are allowed to
+ * authenticate the DNSKEY RRset (RFC 4035 section 5.2 bullet
+ * 2), and CDNSKEY and CDS RRsets (RFC 7344 section 4.1 bullet
+ * 2).
+ */
+
+ vbprintf(1, "verify DNSKEY signature(s)\n");
+ if (!signed_loose(matching_sigs(old_key_tbl, &dnskey_set, &dnskey_sig)))
+ {
+ fatal("could not validate child DNSKEY RRset for %s", namestr);
+ }
+
+ if (dns_rdataset_isassociated(&cdnskey_set)) {
+ vbprintf(1, "verify CDNSKEY signature(s)\n");
+ if (!signed_loose(matching_sigs(old_key_tbl, &cdnskey_set,
+ &cdnskey_sig)))
+ {
+ fatal("could not validate child CDNSKEY RRset for %s",
+ namestr);
+ }
+ }
+ if (dns_rdataset_isassociated(&cds_set)) {
+ vbprintf(1, "verify CDS signature(s)\n");
+ if (!signed_loose(
+ matching_sigs(old_key_tbl, &cds_set, &cds_sig)))
+ {
+ fatal("could not validate child CDS RRset for %s",
+ namestr);
+ }
+ }
+
+ free_keytable(&old_key_tbl);
+
+ /*
+ * Report the result of the replay attack protection checks
+ * used for the output file timestamp
+ */
+ if (oldestsig.timesigned != 0 && verbose > 0) {
+ char type[32];
+ dns_rdatatype_format(oldestsig.covered, type, sizeof(type));
+ verbose_time(1, "child signature inception time",
+ oldestsig.timesigned);
+ vbprintf(2, "from RRSIG %s by key %d\n", type, oldestsig.keyid);
+ }
+
+ /*
+ * Successfully do nothing if there's neither CDNSKEY nor CDS
+ * RFC 7344 section 4.1 first paragraph
+ */
+ if (!dns_rdataset_isassociated(&cdnskey_set) &&
+ !dns_rdataset_isassociated(&cds_set))
+ {
+ vbprintf(1, "%s has neither CDS nor CDNSKEY records\n",
+ namestr);
+ write_parent_set(ds_path, inplace, nsupdate, &old_ds_set);
+ goto cleanup;
+ }
+
+ /*
+ * Make DS records from the CDS or CDNSKEY records
+ * Prefer CDS if present, unless run with -D
+ */
+ if (prefer_cdnskey && dns_rdataset_isassociated(&cdnskey_set)) {
+ make_new_ds_set(ds_from_cdnskey, ttl, &cdnskey_set);
+ } else if (dns_rdataset_isassociated(&cds_set)) {
+ make_new_ds_set(ds_from_cds, ttl, &cds_set);
+ } else {
+ make_new_ds_set(ds_from_cdnskey, ttl, &cdnskey_set);
+ }
+
+ /*
+ * Try to use CDNSKEY records if the CDS records are missing
+ * or did not match.
+ */
+ if (dns_rdataset_count(&new_ds_set) == 0 &&
+ dns_rdataset_isassociated(&cdnskey_set))
+ {
+ vbprintf(1, "CDS records have no allowed digest types; "
+ "using CDNSKEY instead\n");
+ freelist(&new_ds_set);
+ isc_buffer_free(&new_ds_buf);
+ make_new_ds_set(ds_from_cdnskey, ttl, &cdnskey_set);
+ }
+ if (dns_rdataset_count(&new_ds_set) == 0) {
+ fatal("CDS records at %s do not match any -a digest types",
+ namestr);
+ }
+
+ /*
+ * Now we have a candidate DS RRset, we need to check it
+ * won't break the delegation.
+ */
+ vbprintf(1, "which child DNSKEY records match new DS records?\n");
+ new_key_tbl = match_keyset_dsset(&dnskey_set, &new_ds_set, TIGHT);
+
+ if (!consistent_digests(&new_ds_set)) {
+ fatal("CDS records at %s do not cover each key "
+ "with the same set of digest types",
+ namestr);
+ }
+
+ vbprintf(1, "verify DNSKEY signature(s)\n");
+ if (!signed_strict(&new_ds_set, matching_sigs(new_key_tbl, &dnskey_set,
+ &dnskey_sig)))
+ {
+ fatal("could not validate child DNSKEY RRset "
+ "with new DS records for %s",
+ namestr);
+ }
+
+ free_keytable(&new_key_tbl);
+
+ /*
+ * OK, it's all good!
+ */
+ if (nsupdate) {
+ nsdiff(ttl, &old_ds_set, &new_ds_set);
+ }
+
+ write_parent_set(ds_path, inplace, nsupdate, &new_ds_set);
+
+cleanup:
+ print_mem_stats = true;
+ cleanup();
+ exit(0);
+}
diff --git a/bin/dnssec/dnssec-cds.rst b/bin/dnssec/dnssec-cds.rst
new file mode 100644
index 0000000..09960e9
--- /dev/null
+++ b/bin/dnssec/dnssec-cds.rst
@@ -0,0 +1,221 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: dnssec-cds
+.. program:: dnssec-cds
+.. _man_dnssec-cds:
+
+dnssec-cds - change DS records for a child zone based on CDS/CDNSKEY
+--------------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`dnssec-cds` [**-a** alg...] [**-c** class] [**-D**] {**-d** dsset-file} {**-f** child-file} [**-i**[extension]] [**-s** start-time] [**-T** ttl] [**-u**] [**-v** level] [**-V**] {domain}
+
+Description
+~~~~~~~~~~~
+
+The :program:`dnssec-cds` command changes DS records at a delegation point
+based on CDS or CDNSKEY records published in the child zone. If both CDS
+and CDNSKEY records are present in the child zone, the CDS is preferred.
+This enables a child zone to inform its parent of upcoming changes to
+its key-signing keys (KSKs); by polling periodically with :program:`dnssec-cds`, the
+parent can keep the DS records up-to-date and enable automatic rolling
+of KSKs.
+
+Two input files are required. The :option:`-f child-file <-f>` option specifies a
+file containing the child's CDS and/or CDNSKEY records, plus RRSIG and
+DNSKEY records so that they can be authenticated. The :option:`-d path <-d>` option
+specifies the location of a file containing the current DS records. For
+example, this could be a ``dsset-`` file generated by
+:iscman:`dnssec-signzone`, or the output of :iscman:`dnssec-dsfromkey`, or the
+output of a previous run of :program:`dnssec-cds`.
+
+The :program:`dnssec-cds` command uses special DNSSEC validation logic
+specified by :rfc:`7344`. It requires that the CDS and/or CDNSKEY records
+be validly signed by a key represented in the existing DS records. This
+is typically the pre-existing KSK.
+
+For protection against replay attacks, the signatures on the child
+records must not be older than they were on a previous run of
+:program:`dnssec-cds`. Their age is obtained from the modification time of the
+``dsset-`` file, or from the :option:`-s` option.
+
+To protect against breaking the delegation, :program:`dnssec-cds` ensures that
+the DNSKEY RRset can be verified by every key algorithm in the new DS
+RRset, and that the same set of keys are covered by every DS digest
+type.
+
+By default, replacement DS records are written to the standard output;
+with the :option:`-i` option the input file is overwritten in place. The
+replacement DS records are the same as the existing records, when no
+change is required. The output can be empty if the CDS/CDNSKEY records
+specify that the child zone wants to be insecure.
+
+.. warning::
+
+ Be careful not to delete the DS records when :program:`dnssec-cds` fails!
+
+Alternatively, :option`dnssec-cds -u` writes an :iscman:`nsupdate` script to the
+standard output. The :option:`-u` and :option:`-i` options can be used together to
+maintain a ``dsset-`` file as well as emit an :iscman:`nsupdate` script.
+
+Options
+~~~~~~~
+
+.. option:: -a algorithm
+
+ When converting CDS records to DS records, this option specifies
+ the acceptable digest algorithms. This option can be repeated, so
+ that multiple digest types are allowed. If none of the CDS records
+ use an acceptable digest type, :program:`dnssec-cds` will try to use CDNSKEY
+ records instead; if there are no CDNSKEY records, it reports an error.
+
+ When converting CDNSKEY records to DS records, this option specifies the
+ digest algorithm to use. It can be repeated, so that multiple DS records
+ are created for each CDNSKEY records.
+
+ The algorithm must be one of SHA-1, SHA-256, or SHA-384. These values
+ are case-insensitive, and the hyphen may be omitted. If no algorithm
+ is specified, the default is SHA-256 only.
+
+.. option:: -c class
+
+ This option specifies the DNS class of the zones.
+
+.. option:: -D
+
+ This option generates DS records from CDNSKEY records if both CDS and CDNSKEY
+ records are present in the child zone. By default CDS records are
+ preferred.
+
+.. option:: -d path
+
+ This specifies the location of the parent DS records. The path can be the name of a file
+ containing the DS records; if it is a directory, :program:`dnssec-cds`
+ looks for a ``dsset-`` file for the domain inside the directory.
+
+ To protect against replay attacks, child records are rejected if they
+ were signed earlier than the modification time of the ``dsset-``
+ file. This can be adjusted with the :option:`-s` option.
+
+.. option:: -f child-file
+
+ This option specifies the file containing the child's CDS and/or CDNSKEY records, plus its
+ DNSKEY records and the covering RRSIG records, so that they can be
+ authenticated.
+
+ The examples below describe how to generate this file.
+
+.. option:: -i extension
+
+ This option updates the ``dsset-`` file in place, instead of writing DS records to
+ the standard output.
+
+ There must be no space between the :option:`-i` and the extension. If
+ no extension is provided, the old ``dsset-`` is discarded. If an
+ extension is present, a backup of the old ``dsset-`` file is kept
+ with the extension appended to its filename.
+
+ To protect against replay attacks, the modification time of the
+ ``dsset-`` file is set to match the signature inception time of the
+ child records, provided that it is later than the file's current
+ modification time.
+
+.. option:: -s start-time
+
+ This option specifies the date and time after which RRSIG records become
+ acceptable. This can be either an absolute or a relative time. An
+ absolute start time is indicated by a number in YYYYMMDDHHMMSS
+ notation; 20170827133700 denotes 13:37:00 UTC on August 27th, 2017. A
+ time relative to the ``dsset-`` file is indicated with ``-N``, which is N
+ seconds before the file modification time. A time relative to the
+ current time is indicated with ``now+N``.
+
+ If no start-time is specified, the modification time of the
+ ``dsset-`` file is used.
+
+.. option:: -T ttl
+
+ This option specifies a TTL to be used for new DS records. If not specified, the
+ default is the TTL of the old DS records. If they had no explicit TTL,
+ the new DS records also have no explicit TTL.
+
+.. option:: -u
+
+ This option writes an :iscman:`nsupdate` script to the standard output, instead of
+ printing the new DS reords. The output is empty if no change is
+ needed.
+
+ Note: The TTL of new records needs to be specified: it can be done in the
+ original ``dsset-`` file, with the :option:`-T` option, or using the
+ :iscman:`nsupdate` ``ttl`` command.
+
+.. option:: -V
+
+ This option prints version information.
+
+.. option:: -v level
+
+ This option sets the debugging level. Level 1 is intended to be usefully verbose
+ for general users; higher levels are intended for developers.
+
+``domain``
+ This indicates the name of the delegation point/child zone apex.
+
+Exit Status
+~~~~~~~~~~~
+
+The :program:`dnssec-cds` command exits 0 on success, or non-zero if an error
+occurred.
+
+If successful, the DS records may or may not need to be
+changed.
+
+Examples
+~~~~~~~~
+
+Before running :iscman:`dnssec-signzone`, ensure that the delegations
+are up-to-date by running :program:`dnssec-cds` on every ``dsset-`` file.
+
+To fetch the child records required by :program:`dnssec-cds`, invoke
+:iscman:`dig` as in the script below. It is acceptable if the :iscman:`dig` fails, since
+:program:`dnssec-cds` performs all the necessary checking.
+
+::
+
+ for f in dsset-*
+ do
+ d=${f#dsset-}
+ dig +dnssec +noall +answer $d DNSKEY $d CDNSKEY $d CDS |
+ dnssec-cds -i -f /dev/stdin -d $f $d
+ done
+
+When the parent zone is automatically signed by :iscman:`named`,
+:program:`dnssec-cds` can be used with :iscman:`nsupdate` to maintain a delegation as follows.
+The ``dsset-`` file allows the script to avoid having to fetch and
+validate the parent DS records, and it maintains the replay attack
+protection time.
+
+::
+
+ dig +dnssec +noall +answer $d DNSKEY $d CDNSKEY $d CDS |
+ dnssec-cds -u -i -f /dev/stdin -d $f $d |
+ nsupdate -l
+
+See Also
+~~~~~~~~
+
+:iscman:`dig(1) <dig>`, :iscman:`dnssec-settime(8) <dnssec-settime>`, :iscman:`dnssec-signzone(8) <dnssec-signzone>`, :iscman:`nsupdate(1) <nsupdate>`, BIND 9 Administrator
+Reference Manual, :rfc:`7344`.
diff --git a/bin/dnssec/dnssec-dsfromkey.c b/bin/dnssec/dnssec-dsfromkey.c
new file mode 100644
index 0000000..42aa9e5
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.c
@@ -0,0 +1,561 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/ds.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-dsfromkey";
+
+static dns_rdataclass_t rdclass;
+static dns_fixedname_t fixed;
+static dns_name_t *name = NULL;
+static isc_mem_t *mctx = NULL;
+static uint32_t ttl;
+static bool emitttl = false;
+
+static isc_result_t
+initname(char *setname) {
+ isc_result_t result;
+ isc_buffer_t buf;
+
+ name = dns_fixedname_initname(&fixed);
+
+ isc_buffer_init(&buf, setname, strlen(setname));
+ isc_buffer_add(&buf, strlen(setname));
+ result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
+ return (result);
+}
+
+static void
+db_load_from_stream(dns_db_t *db, FILE *fp) {
+ isc_result_t result;
+ dns_rdatacallbacks_t callbacks;
+
+ dns_rdatacallbacks_init(&callbacks);
+ result = dns_db_beginload(db, &callbacks);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_db_beginload failed: %s", isc_result_totext(result));
+ }
+
+ result = dns_master_loadstream(fp, name, name, rdclass, 0, &callbacks,
+ mctx);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't load from input: %s", isc_result_totext(result));
+ }
+
+ result = dns_db_endload(db, &callbacks);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_db_endload failed: %s", isc_result_totext(result));
+ }
+}
+
+static isc_result_t
+loadset(const char *filename, dns_rdataset_t *rdataset) {
+ isc_result_t result;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ char setname[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(name, setname, sizeof(setname));
+
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0,
+ NULL, &db);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't create database");
+ }
+
+ if (strcmp(filename, "-") == 0) {
+ db_load_from_stream(db, stdin);
+ filename = "input";
+ } else {
+ result = dns_db_load(db, filename, dns_masterformat_text, 0);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
+ fatal("can't load %s: %s", filename,
+ isc_result_totext(result));
+ }
+ }
+
+ result = dns_db_findnode(db, name, false, &node);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't find %s node in %s", setname, filename);
+ }
+
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
+ rdataset, NULL);
+
+ if (result == ISC_R_NOTFOUND) {
+ fatal("no DNSKEY RR for %s in %s", setname, filename);
+ } else if (result != ISC_R_SUCCESS) {
+ fatal("dns_db_findrdataset");
+ }
+
+ if (node != NULL) {
+ dns_db_detachnode(db, &node);
+ }
+ if (db != NULL) {
+ dns_db_detach(&db);
+ }
+ return (result);
+}
+
+static isc_result_t
+loadkeyset(char *dirname, dns_rdataset_t *rdataset) {
+ isc_result_t result;
+ char filename[PATH_MAX + 1];
+ isc_buffer_t buf;
+
+ dns_rdataset_init(rdataset);
+
+ isc_buffer_init(&buf, filename, sizeof(filename));
+ if (dirname != NULL) {
+ /* allow room for a trailing slash */
+ if (strlen(dirname) >= isc_buffer_availablelength(&buf)) {
+ return (ISC_R_NOSPACE);
+ }
+ isc_buffer_putstr(&buf, dirname);
+ if (dirname[strlen(dirname) - 1] != '/') {
+ isc_buffer_putstr(&buf, "/");
+ }
+ }
+
+ if (isc_buffer_availablelength(&buf) < 7) {
+ return (ISC_R_NOSPACE);
+ }
+ isc_buffer_putstr(&buf, "keyset-");
+
+ result = dns_name_tofilenametext(name, false, &buf);
+ check_result(result, "dns_name_tofilenametext()");
+ if (isc_buffer_availablelength(&buf) == 0) {
+ return (ISC_R_NOSPACE);
+ }
+ isc_buffer_putuint8(&buf, 0);
+
+ return (loadset(filename, rdataset));
+}
+
+static void
+loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size,
+ dns_rdata_t *rdata) {
+ isc_result_t result;
+ dst_key_t *key = NULL;
+ isc_buffer_t keyb;
+ isc_region_t r;
+
+ dns_rdata_init(rdata);
+
+ isc_buffer_init(&keyb, key_buf, key_buf_size);
+
+ result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC, mctx,
+ &key);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't load %s.key: %s", filename,
+ isc_result_totext(result));
+ }
+
+ if (verbose > 2) {
+ char keystr[DST_KEY_FORMATSIZE];
+
+ dst_key_format(key, keystr, sizeof(keystr));
+ fprintf(stderr, "%s: %s\n", program, keystr);
+ }
+
+ result = dst_key_todns(key, &keyb);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't decode key");
+ }
+
+ isc_buffer_usedregion(&keyb, &r);
+ dns_rdata_fromregion(rdata, dst_key_class(key), dns_rdatatype_dnskey,
+ &r);
+
+ rdclass = dst_key_class(key);
+
+ name = dns_fixedname_initname(&fixed);
+ dns_name_copy(dst_key_name(key), name);
+
+ dst_key_free(&key);
+}
+
+static void
+logkey(dns_rdata_t *rdata) {
+ isc_result_t result;
+ dst_key_t *key = NULL;
+ isc_buffer_t buf;
+ char keystr[DST_KEY_FORMATSIZE];
+
+ isc_buffer_init(&buf, rdata->data, rdata->length);
+ isc_buffer_add(&buf, rdata->length);
+ result = dst_key_fromdns(name, rdclass, &buf, mctx, &key);
+ if (result != ISC_R_SUCCESS) {
+ return;
+ }
+
+ dst_key_format(key, keystr, sizeof(keystr));
+ fprintf(stderr, "%s: %s\n", program, keystr);
+
+ dst_key_free(&key);
+}
+
+static void
+emit(dns_dsdigest_t dt, bool showall, bool cds, dns_rdata_t *rdata) {
+ isc_result_t result;
+ unsigned char buf[DNS_DS_BUFFERSIZE];
+ char text_buf[DST_KEY_MAXTEXTSIZE];
+ char name_buf[DNS_NAME_MAXWIRE];
+ char class_buf[10];
+ isc_buffer_t textb, nameb, classb;
+ isc_region_t r;
+ dns_rdata_t ds;
+ dns_rdata_dnskey_t dnskey;
+
+ isc_buffer_init(&textb, text_buf, sizeof(text_buf));
+ isc_buffer_init(&nameb, name_buf, sizeof(name_buf));
+ isc_buffer_init(&classb, class_buf, sizeof(class_buf));
+
+ dns_rdata_init(&ds);
+
+ result = dns_rdata_tostruct(rdata, &dnskey, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't convert DNSKEY");
+ }
+
+ if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
+ return;
+ }
+
+ if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && !showall) {
+ return;
+ }
+
+ result = dns_ds_buildrdata(name, rdata, dt, buf, &ds);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't build record");
+ }
+
+ result = dns_name_totext(name, false, &nameb);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't print name");
+ }
+
+ result = dns_rdata_tofmttext(&ds, (dns_name_t *)NULL, 0, 0, 0, "",
+ &textb);
+
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't print rdata");
+ }
+
+ result = dns_rdataclass_totext(rdclass, &classb);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't print class");
+ }
+
+ isc_buffer_usedregion(&nameb, &r);
+ printf("%.*s ", (int)r.length, r.base);
+
+ if (emitttl) {
+ printf("%u ", ttl);
+ }
+
+ isc_buffer_usedregion(&classb, &r);
+ printf("%.*s", (int)r.length, r.base);
+
+ if (cds) {
+ printf(" CDS ");
+ } else {
+ printf(" DS ");
+ }
+
+ isc_buffer_usedregion(&textb, &r);
+ printf("%.*s\n", (int)r.length, r.base);
+}
+
+static void
+emits(bool showall, bool cds, dns_rdata_t *rdata) {
+ unsigned i, n;
+
+ n = sizeof(dtype) / sizeof(dtype[0]);
+ for (i = 0; i < n; i++) {
+ if (dtype[i] != 0) {
+ emit(dtype[i], showall, cds, rdata);
+ }
+ }
+}
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s [options] keyfile\n\n", program);
+ fprintf(stderr, " %s [options] -f zonefile [zonename]\n\n", program);
+ fprintf(stderr, " %s [options] -s dnsname\n\n", program);
+ fprintf(stderr, " %s [-h|-V]\n\n", program);
+ fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
+ fprintf(stderr, "Options:\n"
+ " -1: digest algorithm SHA-1\n"
+ " -2: digest algorithm SHA-256\n"
+ " -a algorithm: digest algorithm (SHA-1, SHA-256 or "
+ "SHA-384)\n"
+ " -A: include all keys in DS set, not just KSKs (-f "
+ "only)\n"
+ " -c class: rdata class for DS set (default IN) (-f "
+ "or -s only)\n"
+ " -C: print CDS records\n"
+ " -f zonefile: read keys from a zone file\n"
+ " -h: print help information\n"
+ " -K directory: where to find key or keyset files\n"
+ " -s: read keys from keyset-<dnsname> file\n"
+ " -T: TTL of output records (omitted by default)\n"
+ " -v level: verbosity\n"
+ " -V: print version information\n");
+ fprintf(stderr, "Output: DS or CDS RRs\n");
+
+ exit(-1);
+}
+
+int
+main(int argc, char **argv) {
+ char *classname = NULL;
+ char *filename = NULL, *dir = NULL, *namestr;
+ char *endp, *arg1;
+ int ch;
+ bool cds = false;
+ bool usekeyset = false;
+ bool showall = false;
+ isc_result_t result;
+ isc_log_t *log = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata;
+
+ dns_rdata_init(&rdata);
+
+ if (argc == 1) {
+ usage();
+ }
+
+ isc_mem_create(&mctx);
+
+ isc_commandline_errprint = false;
+
+#define OPTIONS "12Aa:Cc:d:Ff:K:l:sT:v:hV"
+ while ((ch = isc_commandline_parse(argc, argv, OPTIONS)) != -1) {
+ switch (ch) {
+ case '1':
+ add_dtype(DNS_DSDIGEST_SHA1);
+ break;
+ case '2':
+ add_dtype(DNS_DSDIGEST_SHA256);
+ break;
+ case 'A':
+ showall = true;
+ break;
+ case 'a':
+ add_dtype(strtodsdigest(isc_commandline_argument));
+ break;
+ case 'C':
+ cds = true;
+ break;
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'd':
+ fprintf(stderr,
+ "%s: the -d option is deprecated; "
+ "use -K\n",
+ program);
+ /* fall through */
+ case 'K':
+ dir = isc_commandline_argument;
+ if (strlen(dir) == 0U) {
+ fatal("directory must be non-empty string");
+ }
+ break;
+ case 'f':
+ filename = isc_commandline_argument;
+ break;
+ case 'l':
+ fatal("-l option (DLV lookaside) is obsolete");
+ break;
+ case 's':
+ usekeyset = true;
+ break;
+ case 'T':
+ emitttl = true;
+ ttl = strtottl(isc_commandline_argument);
+ break;
+ case 'v':
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fatal("-v must be followed by a number");
+ }
+ break;
+ case 'F':
+ /* Reserved for FIPS mode */
+ FALLTHROUGH;
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ }
+ FALLTHROUGH;
+ case 'h':
+ /* Does not return. */
+ usage();
+
+ case 'V':
+ /* Does not return. */
+ version(program);
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ rdclass = strtoclass(classname);
+
+ if (usekeyset && filename != NULL) {
+ fatal("cannot use both -s and -f");
+ }
+
+ /* When not using -f, -A is implicit */
+ if (filename == NULL) {
+ showall = true;
+ }
+
+ /* Default digest type if none specified. */
+ if (dtype[0] == 0) {
+ dtype[0] = DNS_DSDIGEST_SHA256;
+ }
+
+ /*
+ * Use local variable arg1 so that clang can correctly analyse
+ * reachable paths rather than 'argc < isc_commandline_index + 1'.
+ */
+ arg1 = argv[isc_commandline_index];
+ if (arg1 == NULL && filename == NULL) {
+ fatal("the key file name was not specified");
+ }
+ if (arg1 != NULL && argv[isc_commandline_index + 1] != NULL) {
+ fatal("extraneous arguments");
+ }
+
+ result = dst_lib_init(mctx, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not initialize dst: %s",
+ isc_result_totext(result));
+ }
+
+ setup_logging(mctx, &log);
+
+ dns_rdataset_init(&rdataset);
+
+ if (usekeyset || filename != NULL) {
+ if (arg1 == NULL) {
+ /* using file name as the zone name */
+ namestr = filename;
+ } else {
+ namestr = arg1;
+ }
+
+ result = initname(namestr);
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not initialize name %s", namestr);
+ }
+
+ if (usekeyset) {
+ result = loadkeyset(dir, &rdataset);
+ } else {
+ INSIST(filename != NULL);
+ result = loadset(filename, &rdataset);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not load DNSKEY set: %s\n",
+ isc_result_totext(result));
+ }
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(&rdataset, &rdata);
+
+ if (verbose > 2) {
+ logkey(&rdata);
+ }
+
+ emits(showall, cds, &rdata);
+ }
+ } else {
+ unsigned char key_buf[DST_KEY_MAXSIZE];
+
+ loadkey(arg1, key_buf, DST_KEY_MAXSIZE, &rdata);
+
+ emits(showall, cds, &rdata);
+ }
+
+ if (dns_rdataset_isassociated(&rdataset)) {
+ dns_rdataset_disassociate(&rdataset);
+ }
+ cleanup_logging(&log);
+ dst_lib_destroy();
+ if (verbose > 10) {
+ isc_mem_stats(mctx, stdout);
+ }
+ isc_mem_destroy(&mctx);
+
+ fflush(stdout);
+ if (ferror(stdout)) {
+ fprintf(stderr, "write error\n");
+ return (1);
+ } else {
+ return (0);
+ }
+}
diff --git a/bin/dnssec/dnssec-dsfromkey.rst b/bin/dnssec/dnssec-dsfromkey.rst
new file mode 100644
index 0000000..9ca025a
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.rst
@@ -0,0 +1,159 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: dnssec-dsfromkey
+.. program:: dnssec-dsfromkey
+.. _man_dnssec-dsfromkey:
+
+dnssec-dsfromkey - DNSSEC DS RR generation tool
+-----------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`dnssec-dsfromkey` [ **-1** | **-2** | **-a** alg ] [ **-C** ] [**-T** TTL] [**-v** level] [**-K** directory] {keyfile}
+
+:program:`dnssec-dsfromkey` [ **-1** | **-2** | **-a** alg ] [ **-C** ] [**-T** TTL] [**-v** level] [**-c** class] [**-A**] {**-f** file} [dnsname]
+
+:program:`dnssec-dsfromkey` [ **-1** | **-2** | **-a** alg ] [ **-C** ] [**-T** TTL] [**-v** level] [**-c** class] [**-K** directory] {**-s**} {dnsname}
+
+:program:`dnssec-dsfromkey` [ **-h** | **-V** ]
+
+Description
+~~~~~~~~~~~
+
+The :program:`dnssec-dsfromkey` command outputs DS (Delegation Signer) resource records
+(RRs), or CDS (Child DS) RRs with the :option:`-C` option.
+
+By default, only KSKs are converted (keys with flags = 257). The
+:option:`-A` option includes ZSKs (flags = 256). Revoked keys are never
+included.
+
+The input keys can be specified in a number of ways:
+
+By default, :program:`dnssec-dsfromkey` reads a key file named in the format
+``Knnnn.+aaa+iiiii.key``, as generated by :iscman:`dnssec-keygen`.
+
+With the :option:`-f file <-f>` option, :program:`dnssec-dsfromkey` reads keys from a zone
+file or partial zone file (which can contain just the DNSKEY records).
+
+With the :option:`-s` option, :program:`dnssec-dsfromkey` reads a ``keyset-`` file,
+as generated by :iscman:`dnssec-keygen` :option:`-C`.
+
+Options
+~~~~~~~
+
+.. option:: -1
+
+ This option is an abbreviation for :option:`-a SHA1 <-a>`.
+
+.. option:: -2
+
+ This option is an abbreviation for :option:`-a SHA-256 <-a>`.
+
+.. option:: -a algorithm
+
+ This option specifies a digest algorithm to use when converting DNSKEY records to
+ DS records. This option can be repeated, so that multiple DS records
+ are created for each DNSKEY record.
+
+ The algorithm must be one of SHA-1, SHA-256, or SHA-384. These values
+ are case-insensitive, and the hyphen may be omitted. If no algorithm
+ is specified, the default is SHA-256.
+
+.. option:: -A
+
+ This option indicates that ZSKs are to be included when generating DS records. Without this option, only
+ keys which have the KSK flag set are converted to DS records and
+ printed. This option is only useful in :option:`-f` zone file mode.
+
+.. option:: -c class
+
+ This option specifies the DNS class; the default is IN. This option is only useful in :option:`-s` keyset
+ or :option:`-f` zone file mode.
+
+.. option:: -C
+
+ This option generates CDS records rather than DS records.
+
+.. option:: -f file
+
+ This option sets zone file mode, in which the final dnsname argument of :program:`dnssec-dsfromkey` is the
+ DNS domain name of a zone whose master file can be read from
+ ``file``. If the zone name is the same as ``file``, then it may be
+ omitted.
+
+ If ``file`` is ``-``, then the zone data is read from the standard
+ input. This makes it possible to use the output of the :iscman:`dig`
+ command as input, as in:
+
+ ``dig dnskey example.com | dnssec-dsfromkey -f - example.com``
+
+.. option:: -h
+
+ This option prints usage information.
+
+.. option:: -K directory
+
+ This option tells BIND 9 to look for key files or ``keyset-`` files in ``directory``.
+
+.. option:: -s
+
+ This option enables keyset mode, in which the final dnsname argument from :program:`dnssec-dsfromkey` is the DNS
+ domain name used to locate a ``keyset-`` file.
+
+.. option:: -T TTL
+
+ This option specifies the TTL of the DS records. By default the TTL is omitted.
+
+.. option:: -v level
+
+ This option sets the debugging level.
+
+.. option:: -V
+
+ This option prints version information.
+
+Example
+~~~~~~~
+
+To build the SHA-256 DS RR from the ``Kexample.com.+003+26160`` keyfile,
+issue the following command:
+
+``dnssec-dsfromkey -2 Kexample.com.+003+26160``
+
+The command returns something similar to:
+
+``example.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0C5EA0B94``
+
+Files
+~~~~~
+
+The keyfile can be designated by the key identification
+``Knnnn.+aaa+iiiii`` or the full file name ``Knnnn.+aaa+iiiii.key``, as
+generated by :iscman:`dnssec-keygen`.
+
+The keyset file name is built from the ``directory``, the string
+``keyset-``, and the ``dnsname``.
+
+Caveat
+~~~~~~
+
+A keyfile error may return "file not found," even if the file exists.
+
+See Also
+~~~~~~~~
+
+:iscman:`dnssec-keygen(8) <dnssec-keygen>`, :iscman:`dnssec-signzone(8) <dnssec-signzone>`, BIND 9 Administrator Reference Manual,
+:rfc:`3658` (DS RRs), :rfc:`4509` (SHA-256 for DS RRs),
+:rfc:`6605` (SHA-384 for DS RRs), :rfc:`7344` (CDS and CDNSKEY RRs).
diff --git a/bin/dnssec/dnssec-importkey.c b/bin/dnssec/dnssec-importkey.c
new file mode 100644
index 0000000..441f7c3
--- /dev/null
+++ b/bin/dnssec/dnssec-importkey.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/ds.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-importkey";
+
+static dns_rdataclass_t rdclass;
+static dns_fixedname_t fixed;
+static dns_name_t *name = NULL;
+static isc_mem_t *mctx = NULL;
+static bool setpub = false, setdel = false;
+static bool setttl = false;
+static isc_stdtime_t pub = 0, del = 0;
+static dns_ttl_t ttl = 0;
+static isc_stdtime_t syncadd = 0, syncdel = 0;
+static bool setsyncadd = false;
+static bool setsyncdel = false;
+
+static isc_result_t
+initname(char *setname) {
+ isc_result_t result;
+ isc_buffer_t buf;
+
+ name = dns_fixedname_initname(&fixed);
+
+ isc_buffer_init(&buf, setname, strlen(setname));
+ isc_buffer_add(&buf, strlen(setname));
+ result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
+ return (result);
+}
+
+static void
+db_load_from_stream(dns_db_t *db, FILE *fp) {
+ isc_result_t result;
+ dns_rdatacallbacks_t callbacks;
+
+ dns_rdatacallbacks_init(&callbacks);
+ result = dns_db_beginload(db, &callbacks);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_db_beginload failed: %s", isc_result_totext(result));
+ }
+
+ result = dns_master_loadstream(fp, name, name, rdclass, 0, &callbacks,
+ mctx);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't load from input: %s", isc_result_totext(result));
+ }
+
+ result = dns_db_endload(db, &callbacks);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_db_endload failed: %s", isc_result_totext(result));
+ }
+}
+
+static isc_result_t
+loadset(const char *filename, dns_rdataset_t *rdataset) {
+ isc_result_t result;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ char setname[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(name, setname, sizeof(setname));
+
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0,
+ NULL, &db);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't create database");
+ }
+
+ if (strcmp(filename, "-") == 0) {
+ db_load_from_stream(db, stdin);
+ filename = "input";
+ } else {
+ result = dns_db_load(db, filename, dns_masterformat_text,
+ DNS_MASTER_NOTTL);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
+ fatal("can't load %s: %s", filename,
+ isc_result_totext(result));
+ }
+ }
+
+ result = dns_db_findnode(db, name, false, &node);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't find %s node in %s", setname, filename);
+ }
+
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
+ rdataset, NULL);
+
+ if (result == ISC_R_NOTFOUND) {
+ fatal("no DNSKEY RR for %s in %s", setname, filename);
+ } else if (result != ISC_R_SUCCESS) {
+ fatal("dns_db_findrdataset");
+ }
+
+ if (node != NULL) {
+ dns_db_detachnode(db, &node);
+ }
+ if (db != NULL) {
+ dns_db_detach(&db);
+ }
+ return (result);
+}
+
+static void
+loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size,
+ dns_rdata_t *rdata) {
+ isc_result_t result;
+ dst_key_t *key = NULL;
+ isc_buffer_t keyb;
+ isc_region_t r;
+
+ dns_rdata_init(rdata);
+
+ isc_buffer_init(&keyb, key_buf, key_buf_size);
+
+ result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC, mctx,
+ &key);
+ if (result != ISC_R_SUCCESS) {
+ fatal("invalid keyfile name %s: %s", filename,
+ isc_result_totext(result));
+ }
+
+ if (verbose > 2) {
+ char keystr[DST_KEY_FORMATSIZE];
+
+ dst_key_format(key, keystr, sizeof(keystr));
+ fprintf(stderr, "%s: %s\n", program, keystr);
+ }
+
+ result = dst_key_todns(key, &keyb);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't decode key");
+ }
+
+ isc_buffer_usedregion(&keyb, &r);
+ dns_rdata_fromregion(rdata, dst_key_class(key), dns_rdatatype_dnskey,
+ &r);
+
+ rdclass = dst_key_class(key);
+
+ name = dns_fixedname_initname(&fixed);
+ dns_name_copy(dst_key_name(key), name);
+
+ dst_key_free(&key);
+}
+
+static void
+emit(const char *dir, dns_rdata_t *rdata) {
+ isc_result_t result;
+ char keystr[DST_KEY_FORMATSIZE];
+ char pubname[1024];
+ char priname[1024];
+ isc_buffer_t buf;
+ dst_key_t *key = NULL, *tmp = NULL;
+
+ isc_buffer_init(&buf, rdata->data, rdata->length);
+ isc_buffer_add(&buf, rdata->length);
+ result = dst_key_fromdns(name, rdclass, &buf, mctx, &key);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dst_key_fromdns: %s", isc_result_totext(result));
+ }
+
+ isc_buffer_init(&buf, pubname, sizeof(pubname));
+ result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Failed to build public key filename: %s",
+ isc_result_totext(result));
+ }
+ isc_buffer_init(&buf, priname, sizeof(priname));
+ result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Failed to build private key filename: %s",
+ isc_result_totext(result));
+ }
+
+ result = dst_key_fromfile(
+ dst_key_name(key), dst_key_id(key), dst_key_alg(key),
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, dir, mctx, &tmp);
+ if (result == ISC_R_SUCCESS) {
+ if (dst_key_isprivate(tmp) && !dst_key_isexternal(tmp)) {
+ fatal("Private key already exists in %s", priname);
+ }
+ dst_key_free(&tmp);
+ }
+
+ dst_key_setexternal(key, true);
+ if (setpub) {
+ dst_key_settime(key, DST_TIME_PUBLISH, pub);
+ }
+ if (setdel) {
+ dst_key_settime(key, DST_TIME_DELETE, del);
+ }
+ if (setsyncadd) {
+ dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd);
+ }
+ if (setsyncdel) {
+ dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel);
+ }
+
+ if (setttl) {
+ dst_key_setttl(key, ttl);
+ }
+
+ result = dst_key_tofile(key, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, dir);
+ if (result != ISC_R_SUCCESS) {
+ dst_key_format(key, keystr, sizeof(keystr));
+ fatal("Failed to write key %s: %s", keystr,
+ isc_result_totext(result));
+ }
+ printf("%s\n", pubname);
+
+ isc_buffer_clear(&buf);
+ result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Failed to build private key filename: %s",
+ isc_result_totext(result));
+ }
+ printf("%s\n", priname);
+ dst_key_free(&key);
+}
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s options [-K dir] keyfile\n\n", program);
+ fprintf(stderr, " %s options -f file [keyname]\n\n", program);
+ fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -f file: read key from zone file\n");
+ fprintf(stderr, " -K <directory>: directory in which to store "
+ "the key files\n");
+ fprintf(stderr, " -L ttl: set default key TTL\n");
+ fprintf(stderr, " -v <verbose level>\n");
+ fprintf(stderr, " -V: print version information\n");
+ fprintf(stderr, " -h: print usage and exit\n");
+ fprintf(stderr, "Timing options:\n");
+ fprintf(stderr, " -P date/[+-]offset/none: set/unset key "
+ "publication date\n");
+ fprintf(stderr, " -P sync date/[+-]offset/none: set/unset "
+ "CDS and CDNSKEY publication date\n");
+ fprintf(stderr, " -D date/[+-]offset/none: set/unset key "
+ "deletion date\n");
+ fprintf(stderr, " -D sync date/[+-]offset/none: set/unset "
+ "CDS and CDNSKEY deletion date\n");
+
+ exit(-1);
+}
+
+int
+main(int argc, char **argv) {
+ char *classname = NULL;
+ char *filename = NULL, *dir = NULL, *namestr;
+ char *endp;
+ int ch;
+ isc_result_t result;
+ isc_log_t *log = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata;
+ isc_stdtime_t now;
+
+ dns_rdata_init(&rdata);
+ isc_stdtime_get(&now);
+
+ if (argc == 1) {
+ usage();
+ }
+
+ isc_mem_create(&mctx);
+
+ isc_commandline_errprint = false;
+
+#define CMDLINE_FLAGS "D:f:hK:L:P:v:V"
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case 'D':
+ /* -Dsync ? */
+ if (isoptarg("sync", argv, usage)) {
+ if (setsyncdel) {
+ fatal("-D sync specified more than "
+ "once");
+ }
+
+ syncdel = strtotime(isc_commandline_argument,
+ now, now, &setsyncdel);
+ break;
+ }
+ /* -Ddnskey ? */
+ (void)isoptarg("dnskey", argv, usage);
+ if (setdel) {
+ fatal("-D specified more than once");
+ }
+
+ del = strtotime(isc_commandline_argument, now, now,
+ &setdel);
+ break;
+ case 'K':
+ dir = isc_commandline_argument;
+ if (strlen(dir) == 0U) {
+ fatal("directory must be non-empty string");
+ }
+ break;
+ case 'L':
+ ttl = strtottl(isc_commandline_argument);
+ setttl = true;
+ break;
+ case 'P':
+ /* -Psync ? */
+ if (isoptarg("sync", argv, usage)) {
+ if (setsyncadd) {
+ fatal("-P sync specified more than "
+ "once");
+ }
+
+ syncadd = strtotime(isc_commandline_argument,
+ now, now, &setsyncadd);
+ break;
+ }
+ /* -Pdnskey ? */
+ (void)isoptarg("dnskey", argv, usage);
+ if (setpub) {
+ fatal("-P specified more than once");
+ }
+
+ pub = strtotime(isc_commandline_argument, now, now,
+ &setpub);
+ break;
+ case 'f':
+ filename = isc_commandline_argument;
+ break;
+ case 'v':
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fatal("-v must be followed by a number");
+ }
+ break;
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ }
+ FALLTHROUGH;
+ case 'h':
+ /* Does not return. */
+ usage();
+
+ case 'V':
+ /* Does not return. */
+ version(program);
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ rdclass = strtoclass(classname);
+
+ if (argc < isc_commandline_index + 1 && filename == NULL) {
+ fatal("the key file name was not specified");
+ }
+ if (argc > isc_commandline_index + 1) {
+ fatal("extraneous arguments");
+ }
+
+ result = dst_lib_init(mctx, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not initialize dst: %s",
+ isc_result_totext(result));
+ }
+
+ setup_logging(mctx, &log);
+
+ dns_rdataset_init(&rdataset);
+
+ if (filename != NULL) {
+ if (argc < isc_commandline_index + 1) {
+ /* using filename as zone name */
+ namestr = filename;
+ } else {
+ namestr = argv[isc_commandline_index];
+ }
+
+ result = initname(namestr);
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not initialize name %s", namestr);
+ }
+
+ result = loadset(filename, &rdataset);
+
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not load DNSKEY set: %s\n",
+ isc_result_totext(result));
+ }
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(&rdataset, &rdata);
+ emit(dir, &rdata);
+ }
+ } else {
+ unsigned char key_buf[DST_KEY_MAXSIZE];
+
+ loadkey(argv[isc_commandline_index], key_buf, DST_KEY_MAXSIZE,
+ &rdata);
+
+ emit(dir, &rdata);
+ }
+
+ if (dns_rdataset_isassociated(&rdataset)) {
+ dns_rdataset_disassociate(&rdataset);
+ }
+ cleanup_logging(&log);
+ dst_lib_destroy();
+ if (verbose > 10) {
+ isc_mem_stats(mctx, stdout);
+ }
+ isc_mem_destroy(&mctx);
+
+ fflush(stdout);
+ if (ferror(stdout)) {
+ fprintf(stderr, "write error\n");
+ return (1);
+ } else {
+ return (0);
+ }
+}
diff --git a/bin/dnssec/dnssec-importkey.rst b/bin/dnssec/dnssec-importkey.rst
new file mode 100644
index 0000000..8f6a6b3
--- /dev/null
+++ b/bin/dnssec/dnssec-importkey.rst
@@ -0,0 +1,142 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: dnssec-importkey
+.. program:: dnssec-importkey
+.. _man_dnssec-importkey:
+
+dnssec-importkey - import DNSKEY records from external systems so they can be managed
+-------------------------------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`dnssec-importkey` [**-K** directory] [**-L** ttl] [**-P** date/offset] [**-P** sync date/offset] [**-D** date/offset] [**-D** sync date/offset] [**-h**] [**-v** level] [**-V**] {keyfile}
+
+:program:`dnssec-importkey` {**-f** filename} [**-K** directory] [**-L** ttl] [**-P** date/offset] [**-P** sync date/offset] [**-D** date/offset] [**-D** sync date/offset] [**-h**] [**-v** level] [**-V**] [dnsname]
+
+Description
+~~~~~~~~~~~
+
+:program:`dnssec-importkey` reads a public DNSKEY record and generates a pair
+of .key/.private files. The DNSKEY record may be read from an
+existing .key file, in which case a corresponding .private file is
+generated, or it may be read from any other file or from the standard
+input, in which case both .key and .private files are generated.
+
+The newly created .private file does *not* contain private key data, and
+cannot be used for signing. However, having a .private file makes it
+possible to set publication (:option:`-P`) and deletion (:option:`-D`) times for the
+key, which means the public key can be added to and removed from the
+DNSKEY RRset on schedule even if the true private key is stored offline.
+
+Options
+~~~~~~~
+
+.. option:: -f filename
+
+ This option indicates the zone file mode. Instead of a public keyfile name, the argument is the
+ DNS domain name of a zone master file, which can be read from
+ ``filename``. If the domain name is the same as ``filename``, then it may be
+ omitted.
+
+ If ``filename`` is set to ``"-"``, then the zone data is read from the
+ standard input.
+
+.. option:: -K directory
+
+ This option sets the directory in which the key files are to reside.
+
+.. option:: -L ttl
+
+ This option sets the default TTL to use for this key when it is converted into a
+ DNSKEY RR. This is the TTL used when the key is imported into a zone,
+ unless there was already a DNSKEY RRset in
+ place, in which case the existing TTL takes precedence. Setting the default TTL to ``0`` or ``none``
+ removes it from the key.
+
+.. option:: -h
+
+ This option emits a usage message and exits.
+
+.. option:: -v level
+
+ This option sets the debugging level.
+
+.. option:: -V
+
+ This option prints version information.
+
+Timing Options
+~~~~~~~~~~~~~~
+
+Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+(which is the format used inside key files),
+or 'Day Mon DD HH:MM:SS YYYY' (as printed by ``dnssec-settime -p``),
+or UNIX epoch time (as printed by ``dnssec-settime -up``),
+or the literal ``now``.
+
+The argument can be followed by ``+`` or ``-`` and an offset from the
+given time. The literal ``now`` can be omitted before an offset. The
+offset can be followed by one of the suffixes ``y``, ``mo``, ``w``,
+``d``, ``h``, or ``mi``, so that it is computed in years (defined as
+365 24-hour days, ignoring leap years), months (defined as 30 24-hour
+days), weeks, days, hours, or minutes, respectively. Without a suffix,
+the offset is computed in seconds.
+
+To explicitly prevent a date from being set, use ``none``, ``never``,
+or ``unset``.
+
+All these formats are case-insensitive.
+
+.. option:: -P date/offset
+
+ This option sets the date on which a key is to be published to the zone. After
+ that date, the key is included in the zone but is not used
+ to sign it.
+
+ .. program:: dnssec-importkey -P
+ .. option:: sync date/offset
+
+ This option sets the date on which CDS and CDNSKEY records that match this key
+ are to be published to the zone.
+
+.. program:: dnssec-importkey
+
+.. option:: -D date/offset
+
+ This option sets the date on which the key is to be deleted. After that date, the
+ key is no longer included in the zone. (However, it may remain in the key
+ repository.)
+
+ .. program:: dnssec-importkey -D
+ .. option:: sync date/offset
+
+ This option sets the date on which the CDS and CDNSKEY records that match this
+ key are to be deleted.
+
+.. program:: dnssec-importkey
+
+
+Files
+~~~~~
+
+A keyfile can be designed by the key identification ``Knnnn.+aaa+iiiii``
+or the full file name ``Knnnn.+aaa+iiiii.key``, as generated by
+:iscman:`dnssec-keygen`.
+
+See Also
+~~~~~~~~
+
+:iscman:`dnssec-keygen(8) <dnssec-keygen>`, :iscman:`dnssec-signzone(8) <dnssec-signzone>`, BIND 9 Administrator Reference Manual,
+:rfc:`5011`.
diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c
new file mode 100644
index 0000000..53ca718
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.c
@@ -0,0 +1,760 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/dnssec.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+#define MAX_RSA 4096 /* should be long enough... */
+
+const char *program = "dnssec-keyfromlabel";
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s -l label [options] name\n\n", program);
+ fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
+ fprintf(stderr, "Required options:\n");
+ fprintf(stderr, " -l label: label of the key pair\n");
+ fprintf(stderr, " name: owner of the key\n");
+ fprintf(stderr, "Other options:\n");
+ fprintf(stderr, " -a algorithm: \n"
+ " DH | RSASHA1 |\n"
+ " NSEC3RSASHA1 |\n"
+ " RSASHA256 | RSASHA512 |\n"
+ " ECDSAP256SHA256 | ECDSAP384SHA384 |\n"
+ " ED25519 | ED448\n");
+ fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
+ fprintf(stderr, " -c class (default: IN)\n");
+ fprintf(stderr, " -E <engine>:\n");
+ fprintf(stderr, " name of an OpenSSL engine to use\n");
+ fprintf(stderr, " -f keyflag: KSK | REVOKE\n");
+ fprintf(stderr, " -K directory: directory in which to place "
+ "key files\n");
+ fprintf(stderr, " -k: generate a TYPE=KEY key\n");
+ fprintf(stderr, " -L ttl: default key TTL\n");
+ fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | "
+ "OTHER\n");
+ fprintf(stderr, " (DNSKEY generation defaults to ZONE\n");
+ fprintf(stderr, " -p protocol: default: 3 [dnssec]\n");
+ fprintf(stderr, " -t type: "
+ "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
+ "(default: AUTHCONF)\n");
+ fprintf(stderr, " -y: permit keys that might collide\n");
+ fprintf(stderr, " -v verbose level\n");
+ fprintf(stderr, " -V: print version information\n");
+ fprintf(stderr, "Date options:\n");
+ fprintf(stderr, " -P date/[+-]offset: set key publication date\n");
+ fprintf(stderr, " -P sync date/[+-]offset: set CDS and CDNSKEY "
+ "publication date\n");
+ fprintf(stderr, " -A date/[+-]offset: set key activation date\n");
+ fprintf(stderr, " -R date/[+-]offset: set key revocation date\n");
+ fprintf(stderr, " -I date/[+-]offset: set key inactivation date\n");
+ fprintf(stderr, " -D date/[+-]offset: set key deletion date\n");
+ fprintf(stderr, " -D sync date/[+-]offset: set CDS and CDNSKEY "
+ "deletion date\n");
+ fprintf(stderr, " -G: generate key only; do not set -P or -A\n");
+ fprintf(stderr, " -C: generate a backward-compatible key, omitting"
+ " all dates\n");
+ fprintf(stderr, " -S <key>: generate a successor to an existing "
+ "key\n");
+ fprintf(stderr, " -i <interval>: prepublication interval for "
+ "successor key "
+ "(default: 30 days)\n");
+ fprintf(stderr, "Output:\n");
+ fprintf(stderr, " K<name>+<alg>+<id>.key, "
+ "K<name>+<alg>+<id>.private\n");
+
+ exit(-1);
+}
+
+int
+main(int argc, char **argv) {
+ char *algname = NULL, *freeit = NULL;
+ char *nametype = NULL, *type = NULL;
+ const char *directory = NULL;
+ const char *predecessor = NULL;
+ dst_key_t *prevkey = NULL;
+ const char *engine = NULL;
+ char *classname = NULL;
+ char *endp;
+ dst_key_t *key = NULL;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ uint16_t flags = 0, kskflag = 0, revflag = 0;
+ dns_secalg_t alg;
+ bool oldstyle = false;
+ isc_mem_t *mctx = NULL;
+ int ch;
+ int protocol = -1, signatory = 0;
+ isc_result_t ret;
+ isc_textregion_t r;
+ char filename[255];
+ isc_buffer_t buf;
+ isc_log_t *log = NULL;
+ dns_rdataclass_t rdclass;
+ int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
+ char *label = NULL;
+ dns_ttl_t ttl = 0;
+ isc_stdtime_t publish = 0, activate = 0, revoke = 0;
+ isc_stdtime_t inactive = 0, deltime = 0;
+ isc_stdtime_t now;
+ int prepub = -1;
+ bool setpub = false, setact = false;
+ bool setrev = false, setinact = false;
+ bool setdel = false, setttl = false;
+ bool unsetpub = false, unsetact = false;
+ bool unsetrev = false, unsetinact = false;
+ bool unsetdel = false;
+ bool genonly = false;
+ bool use_nsec3 = false;
+ bool avoid_collisions = true;
+ bool exact;
+ unsigned char c;
+ isc_stdtime_t syncadd = 0, syncdel = 0;
+ bool unsetsyncadd = false, setsyncadd = false;
+ bool unsetsyncdel = false, setsyncdel = false;
+
+ if (argc == 1) {
+ usage();
+ }
+
+ isc_mem_create(&mctx);
+
+ isc_commandline_errprint = false;
+
+ isc_stdtime_get(&now);
+
+#define CMDLINE_FLAGS "3A:a:Cc:D:E:Ff:GhI:i:kK:L:l:n:P:p:R:S:t:v:Vy"
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case '3':
+ use_nsec3 = true;
+ break;
+ case 'a':
+ algname = isc_commandline_argument;
+ break;
+ case 'C':
+ oldstyle = true;
+ break;
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'E':
+ engine = isc_commandline_argument;
+ break;
+ case 'f':
+ c = (unsigned char)(isc_commandline_argument[0]);
+ if (toupper(c) == 'K') {
+ kskflag = DNS_KEYFLAG_KSK;
+ } else if (toupper(c) == 'R') {
+ revflag = DNS_KEYFLAG_REVOKE;
+ } else {
+ fatal("unknown flag '%s'",
+ isc_commandline_argument);
+ }
+ break;
+ case 'K':
+ directory = isc_commandline_argument;
+ ret = try_dir(directory);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("cannot open directory %s: %s", directory,
+ isc_result_totext(ret));
+ }
+ break;
+ case 'k':
+ options |= DST_TYPE_KEY;
+ break;
+ case 'L':
+ ttl = strtottl(isc_commandline_argument);
+ setttl = true;
+ break;
+ case 'l':
+ label = isc_mem_strdup(mctx, isc_commandline_argument);
+ break;
+ case 'n':
+ nametype = isc_commandline_argument;
+ break;
+ case 'p':
+ protocol = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || protocol < 0 || protocol > 255) {
+ fatal("-p must be followed by a number "
+ "[0..255]");
+ }
+ break;
+ case 't':
+ type = isc_commandline_argument;
+ break;
+ case 'v':
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fatal("-v must be followed by a number");
+ }
+ break;
+ case 'y':
+ avoid_collisions = false;
+ break;
+ case 'G':
+ genonly = true;
+ break;
+ case 'P':
+ /* -Psync ? */
+ if (isoptarg("sync", argv, usage)) {
+ if (unsetsyncadd || setsyncadd) {
+ fatal("-P sync specified more than "
+ "once");
+ }
+
+ syncadd = strtotime(isc_commandline_argument,
+ now, now, &setsyncadd);
+ unsetsyncadd = !setsyncadd;
+ break;
+ }
+ /* -Pdnskey ? */
+ (void)isoptarg("dnskey", argv, usage);
+ if (setpub || unsetpub) {
+ fatal("-P specified more than once");
+ }
+
+ publish = strtotime(isc_commandline_argument, now, now,
+ &setpub);
+ unsetpub = !setpub;
+ break;
+ case 'A':
+ if (setact || unsetact) {
+ fatal("-A specified more than once");
+ }
+
+ activate = strtotime(isc_commandline_argument, now, now,
+ &setact);
+ unsetact = !setact;
+ break;
+ case 'R':
+ if (setrev || unsetrev) {
+ fatal("-R specified more than once");
+ }
+
+ revoke = strtotime(isc_commandline_argument, now, now,
+ &setrev);
+ unsetrev = !setrev;
+ break;
+ case 'I':
+ if (setinact || unsetinact) {
+ fatal("-I specified more than once");
+ }
+
+ inactive = strtotime(isc_commandline_argument, now, now,
+ &setinact);
+ unsetinact = !setinact;
+ break;
+ case 'D':
+ /* -Dsync ? */
+ if (isoptarg("sync", argv, usage)) {
+ if (unsetsyncdel || setsyncdel) {
+ fatal("-D sync specified more than "
+ "once");
+ }
+
+ syncdel = strtotime(isc_commandline_argument,
+ now, now, &setsyncdel);
+ unsetsyncdel = !setsyncdel;
+ break;
+ }
+ /* -Ddnskey ? */
+ (void)isoptarg("dnskey", argv, usage);
+ if (setdel || unsetdel) {
+ fatal("-D specified more than once");
+ }
+
+ deltime = strtotime(isc_commandline_argument, now, now,
+ &setdel);
+ unsetdel = !setdel;
+ break;
+ case 'S':
+ predecessor = isc_commandline_argument;
+ break;
+ case 'i':
+ prepub = strtottl(isc_commandline_argument);
+ break;
+ case 'F':
+ /* Reserved for FIPS mode */
+ FALLTHROUGH;
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ }
+ FALLTHROUGH;
+ case 'h':
+ /* Does not return. */
+ usage();
+
+ case 'V':
+ /* Does not return. */
+ version(program);
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ ret = dst_lib_init(mctx, engine);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("could not initialize dst: %s", isc_result_totext(ret));
+ }
+
+ setup_logging(mctx, &log);
+
+ if (predecessor == NULL) {
+ if (label == NULL) {
+ fatal("the key label was not specified");
+ }
+ if (argc < isc_commandline_index + 1) {
+ fatal("the key name was not specified");
+ }
+ if (argc > isc_commandline_index + 1) {
+ fatal("extraneous arguments");
+ }
+
+ name = dns_fixedname_initname(&fname);
+ isc_buffer_init(&buf, argv[isc_commandline_index],
+ strlen(argv[isc_commandline_index]));
+ isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
+ ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("invalid key name %s: %s",
+ argv[isc_commandline_index],
+ isc_result_totext(ret));
+ }
+
+ if (strchr(label, ':') == NULL) {
+ char *l;
+ int len;
+
+ len = strlen(label) + 8;
+ l = isc_mem_allocate(mctx, len);
+ snprintf(l, len, "pkcs11:%s", label);
+ isc_mem_free(mctx, label);
+ label = l;
+ }
+
+ if (algname == NULL) {
+ fatal("no algorithm specified");
+ }
+
+ r.base = algname;
+ r.length = strlen(algname);
+ ret = dns_secalg_fromtext(&alg, &r);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("unknown algorithm %s", algname);
+ }
+ if (alg == DST_ALG_DH) {
+ options |= DST_TYPE_KEY;
+ }
+
+ if (use_nsec3) {
+ switch (alg) {
+ case DST_ALG_RSASHA1:
+ alg = DST_ALG_NSEC3RSASHA1;
+ break;
+ case DST_ALG_NSEC3RSASHA1:
+ case DST_ALG_RSASHA256:
+ case DST_ALG_RSASHA512:
+ case DST_ALG_ECDSA256:
+ case DST_ALG_ECDSA384:
+ case DST_ALG_ED25519:
+ case DST_ALG_ED448:
+ break;
+ default:
+ fatal("%s is incompatible with NSEC3; "
+ "do not use the -3 option",
+ algname);
+ }
+ }
+
+ if (type != NULL && (options & DST_TYPE_KEY) != 0) {
+ if (strcasecmp(type, "NOAUTH") == 0) {
+ flags |= DNS_KEYTYPE_NOAUTH;
+ } else if (strcasecmp(type, "NOCONF") == 0) {
+ flags |= DNS_KEYTYPE_NOCONF;
+ } else if (strcasecmp(type, "NOAUTHCONF") == 0) {
+ flags |= (DNS_KEYTYPE_NOAUTH |
+ DNS_KEYTYPE_NOCONF);
+ } else if (strcasecmp(type, "AUTHCONF") == 0) {
+ /* nothing */
+ } else {
+ fatal("invalid type %s", type);
+ }
+ }
+
+ if (!oldstyle && prepub > 0) {
+ if (setpub && setact && (activate - prepub) < publish) {
+ fatal("Activation and publication dates "
+ "are closer together than the\n\t"
+ "prepublication interval.");
+ }
+
+ if (!setpub && !setact) {
+ setpub = setact = true;
+ publish = now;
+ activate = now + prepub;
+ } else if (setpub && !setact) {
+ setact = true;
+ activate = publish + prepub;
+ } else if (setact && !setpub) {
+ setpub = true;
+ publish = activate - prepub;
+ }
+
+ if ((activate - prepub) < now) {
+ fatal("Time until activation is shorter "
+ "than the\n\tprepublication interval.");
+ }
+ }
+ } else {
+ char keystr[DST_KEY_FORMATSIZE];
+ isc_stdtime_t when;
+ int major, minor;
+
+ if (prepub == -1) {
+ prepub = (30 * 86400);
+ }
+
+ if (algname != NULL) {
+ fatal("-S and -a cannot be used together");
+ }
+ if (nametype != NULL) {
+ fatal("-S and -n cannot be used together");
+ }
+ if (type != NULL) {
+ fatal("-S and -t cannot be used together");
+ }
+ if (setpub || unsetpub) {
+ fatal("-S and -P cannot be used together");
+ }
+ if (setact || unsetact) {
+ fatal("-S and -A cannot be used together");
+ }
+ if (use_nsec3) {
+ fatal("-S and -3 cannot be used together");
+ }
+ if (oldstyle) {
+ fatal("-S and -C cannot be used together");
+ }
+ if (genonly) {
+ fatal("-S and -G cannot be used together");
+ }
+
+ ret = dst_key_fromnamedfile(predecessor, directory,
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+ mctx, &prevkey);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("Invalid keyfile %s: %s", predecessor,
+ isc_result_totext(ret));
+ }
+ if (!dst_key_isprivate(prevkey)) {
+ fatal("%s is not a private key", predecessor);
+ }
+
+ name = dst_key_name(prevkey);
+ alg = dst_key_alg(prevkey);
+ flags = dst_key_flags(prevkey);
+
+ dst_key_format(prevkey, keystr, sizeof(keystr));
+ dst_key_getprivateformat(prevkey, &major, &minor);
+ if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) {
+ fatal("Key %s has incompatible format version %d.%d\n\t"
+ "It is not possible to generate a successor key.",
+ keystr, major, minor);
+ }
+
+ ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("Key %s has no activation date.\n\t"
+ "You must use dnssec-settime -A to set one "
+ "before generating a successor.",
+ keystr);
+ }
+
+ ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &activate);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("Key %s has no inactivation date.\n\t"
+ "You must use dnssec-settime -I to set one "
+ "before generating a successor.",
+ keystr);
+ }
+
+ publish = activate - prepub;
+ if (publish < now) {
+ fatal("Key %s becomes inactive\n\t"
+ "sooner than the prepublication period "
+ "for the new key ends.\n\t"
+ "Either change the inactivation date with "
+ "dnssec-settime -I,\n\t"
+ "or use the -i option to set a shorter "
+ "prepublication interval.",
+ keystr);
+ }
+
+ ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when);
+ if (ret != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "%s: WARNING: Key %s has no removal "
+ "date;\n\t it will remain in the zone "
+ "indefinitely after rollover.\n\t "
+ "You can use dnssec-settime -D to "
+ "change this.\n",
+ program, keystr);
+ }
+
+ setpub = setact = true;
+ }
+
+ if (nametype == NULL) {
+ if ((options & DST_TYPE_KEY) != 0) { /* KEY */
+ fatal("no nametype specified");
+ }
+ flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */
+ } else if (strcasecmp(nametype, "zone") == 0) {
+ flags |= DNS_KEYOWNER_ZONE;
+ } else if ((options & DST_TYPE_KEY) != 0) { /* KEY */
+ if (strcasecmp(nametype, "host") == 0 ||
+ strcasecmp(nametype, "entity") == 0)
+ {
+ flags |= DNS_KEYOWNER_ENTITY;
+ } else if (strcasecmp(nametype, "user") == 0) {
+ flags |= DNS_KEYOWNER_USER;
+ } else {
+ fatal("invalid KEY nametype %s", nametype);
+ }
+ } else if (strcasecmp(nametype, "other") != 0) { /* DNSKEY */
+ fatal("invalid DNSKEY nametype %s", nametype);
+ }
+
+ rdclass = strtoclass(classname);
+
+ if (directory == NULL) {
+ directory = ".";
+ }
+
+ if ((options & DST_TYPE_KEY) != 0) { /* KEY */
+ flags |= signatory;
+ } else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */
+ flags |= kskflag;
+ flags |= revflag;
+ }
+
+ if (protocol == -1) {
+ protocol = DNS_KEYPROTO_DNSSEC;
+ } else if ((options & DST_TYPE_KEY) == 0 &&
+ protocol != DNS_KEYPROTO_DNSSEC)
+ {
+ fatal("invalid DNSKEY protocol: %d", protocol);
+ }
+
+ if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
+ if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) {
+ fatal("specified null key with signing authority");
+ }
+ }
+
+ if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
+ alg == DNS_KEYALG_DH)
+ {
+ fatal("a key with algorithm '%s' cannot be a zone key",
+ algname);
+ }
+
+ isc_buffer_init(&buf, filename, sizeof(filename) - 1);
+
+ /* associate the key */
+ ret = dst_key_fromlabel(name, alg, flags, protocol, rdclass, engine,
+ label, NULL, mctx, &key);
+
+ if (ret != ISC_R_SUCCESS) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char algstr[DNS_SECALG_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ dns_secalg_format(alg, algstr, sizeof(algstr));
+ fatal("failed to get key %s/%s: %s", namestr, algstr,
+ isc_result_totext(ret));
+ UNREACHABLE();
+ exit(-1);
+ }
+
+ /*
+ * Set key timing metadata (unless using -C)
+ *
+ * Publish and activation dates are set to "now" by default, but
+ * can be overridden. Creation date is always set to "now".
+ */
+ if (!oldstyle) {
+ dst_key_settime(key, DST_TIME_CREATED, now);
+
+ if (genonly && (setpub || setact)) {
+ fatal("cannot use -G together with -P or -A options");
+ }
+
+ if (setpub) {
+ dst_key_settime(key, DST_TIME_PUBLISH, publish);
+ } else if (setact) {
+ dst_key_settime(key, DST_TIME_PUBLISH, activate);
+ } else if (!genonly && !unsetpub) {
+ dst_key_settime(key, DST_TIME_PUBLISH, now);
+ }
+
+ if (setact) {
+ dst_key_settime(key, DST_TIME_ACTIVATE, activate);
+ } else if (!genonly && !unsetact) {
+ dst_key_settime(key, DST_TIME_ACTIVATE, now);
+ }
+
+ if (setrev) {
+ if (kskflag == 0) {
+ fprintf(stderr,
+ "%s: warning: Key is "
+ "not flagged as a KSK, but -R "
+ "was used. Revoking a ZSK is "
+ "legal, but undefined.\n",
+ program);
+ }
+ dst_key_settime(key, DST_TIME_REVOKE, revoke);
+ }
+
+ if (setinact) {
+ dst_key_settime(key, DST_TIME_INACTIVE, inactive);
+ }
+
+ if (setdel) {
+ dst_key_settime(key, DST_TIME_DELETE, deltime);
+ }
+ if (setsyncadd) {
+ dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd);
+ }
+ if (setsyncdel) {
+ dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel);
+ }
+ } else {
+ if (setpub || setact || setrev || setinact || setdel ||
+ unsetpub || unsetact || unsetrev || unsetinact ||
+ unsetdel || genonly || setsyncadd || setsyncdel)
+ {
+ fatal("cannot use -C together with "
+ "-P, -A, -R, -I, -D, or -G options");
+ }
+ /*
+ * Compatibility mode: Private-key-format
+ * should be set to 1.2.
+ */
+ dst_key_setprivateformat(key, 1, 2);
+ }
+
+ /* Set default key TTL */
+ if (setttl) {
+ dst_key_setttl(key, ttl);
+ }
+
+ /*
+ * Do not overwrite an existing key. Warn LOUDLY if there
+ * is a risk of ID collision due to this key or another key
+ * being revoked.
+ */
+ if (key_collision(key, name, directory, mctx, &exact)) {
+ isc_buffer_clear(&buf);
+ ret = dst_key_buildfilename(key, 0, directory, &buf);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("dst_key_buildfilename returned: %s\n",
+ isc_result_totext(ret));
+ }
+ if (exact) {
+ fatal("%s: %s already exists\n", program, filename);
+ }
+
+ if (avoid_collisions) {
+ fatal("%s: %s could collide with another key upon "
+ "revokation\n",
+ program, filename);
+ }
+
+ fprintf(stderr,
+ "%s: WARNING: Key %s could collide with "
+ "another key upon revokation. If you plan "
+ "to revoke keys, destroy this key and "
+ "generate a different one.\n",
+ program, filename);
+ }
+
+ ret = dst_key_tofile(key, options, directory);
+ if (ret != ISC_R_SUCCESS) {
+ char keystr[DST_KEY_FORMATSIZE];
+ dst_key_format(key, keystr, sizeof(keystr));
+ fatal("failed to write key %s: %s\n", keystr,
+ isc_result_totext(ret));
+ }
+
+ isc_buffer_clear(&buf);
+ ret = dst_key_buildfilename(key, 0, NULL, &buf);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("dst_key_buildfilename returned: %s\n",
+ isc_result_totext(ret));
+ }
+ printf("%s\n", filename);
+ dst_key_free(&key);
+ if (prevkey != NULL) {
+ dst_key_free(&prevkey);
+ }
+
+ cleanup_logging(&log);
+ dst_lib_destroy();
+ if (verbose > 10) {
+ isc_mem_stats(mctx, stdout);
+ }
+ isc_mem_free(mctx, label);
+ isc_mem_destroy(&mctx);
+
+ if (freeit != NULL) {
+ free(freeit);
+ }
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-keyfromlabel.rst b/bin/dnssec/dnssec-keyfromlabel.rst
new file mode 100644
index 0000000..098feb9
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.rst
@@ -0,0 +1,289 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: dnssec-keyfromlabel
+.. program:: dnssec-keyfromlabel
+.. _man_dnssec-keyfromlabel:
+
+dnssec-keyfromlabel - DNSSEC key generation tool
+------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`dnssec-keyfromlabel` {**-l** label} [**-3**] [**-a** algorithm] [**-A** date/offset] [**-c** class] [**-D** date/offset] [**-D** sync date/offset] [**-E** engine] [**-f** flag] [**-G**] [**-I** date/offset] [**-i** interval] [**-k**] [**-K** directory] [**-L** ttl] [**-n** nametype] [**-P** date/offset] [**-P** sync date/offset] [**-p** protocol] [**-R** date/offset] [**-S** key] [**-t** type] [**-v** level] [**-V**] [**-y**] {name}
+
+Description
+~~~~~~~~~~~
+
+:program:`dnssec-keyfromlabel` generates a pair of key files that reference a
+key object stored in a cryptographic hardware service module (HSM). The
+private key file can be used for DNSSEC signing of zone data as if it
+were a conventional signing key created by :iscman:`dnssec-keygen`, but the
+key material is stored within the HSM and the actual signing takes
+place there.
+
+The ``name`` of the key is specified on the command line. This must
+match the name of the zone for which the key is being generated.
+
+Options
+~~~~~~~
+
+.. option:: -a algorithm
+
+ This option selects the cryptographic algorithm. The value of ``algorithm`` must
+ be one of RSASHA1, NSEC3RSASHA1, RSASHA256, RSASHA512,
+ ECDSAP256SHA256, ECDSAP384SHA384, ED25519, or ED448.
+
+ These values are case-insensitive. In some cases, abbreviations are
+ supported, such as ECDSA256 for ECDSAP256SHA256 and ECDSA384 for
+ ECDSAP384SHA384. If RSASHA1 is specified along with the :option:`-3`
+ option, then NSEC3RSASHA1 is used instead.
+
+ This option is mandatory except when using the
+ :option:`-S` option, which copies the algorithm from the predecessory key.
+
+ .. versionchanged:: 9.12.0
+ The default value RSASHA1 for newly generated keys was removed.
+
+.. option:: -3
+
+ This option uses an NSEC3-capable algorithm to generate a DNSSEC key. If this
+ option is used with an algorithm that has both NSEC and NSEC3
+ versions, then the NSEC3 version is used; for example,
+ ``dnssec-keygen -3a RSASHA1`` specifies the NSEC3RSASHA1 algorithm.
+
+.. option:: -E engine
+
+ This option specifies the cryptographic hardware to use.
+
+ When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL
+ engine identifier that drives the cryptographic accelerator or
+ hardware service module (usually ``pkcs11``).
+
+.. option:: -l label
+
+ This option specifies the label for a key pair in the crypto hardware.
+
+ When BIND 9 is built with OpenSSL-based PKCS#11 support, the label is
+ an arbitrary string that identifies a particular key. It may be
+ preceded by an optional OpenSSL engine name, followed by a colon, as
+ in ``pkcs11:keylabel``.
+
+.. option:: -n nametype
+
+ This option specifies the owner type of the key. The value of ``nametype`` must
+ either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY
+ (for a key associated with a host (KEY)), USER (for a key associated
+ with a user (KEY)), or OTHER (DNSKEY). These values are
+ case-insensitive.
+
+.. option:: -C
+
+ This option enables compatibility mode, which generates an old-style key, without any metadata.
+ By default, :program:`dnssec-keyfromlabel` includes the key's creation
+ date in the metadata stored with the private key; other dates may
+ be set there as well, including publication date, activation date, etc. Keys
+ that include this data may be incompatible with older versions of
+ BIND; the :option:`-C` option suppresses them.
+
+.. option:: -c class
+
+ This option indicates that the DNS record containing the key should have the
+ specified class. If not specified, class IN is used.
+
+.. option:: -f flag
+
+ This option sets the specified flag in the ``flag`` field of the KEY/DNSKEY record.
+ The only recognized flags are KSK (Key-Signing Key) and REVOKE.
+
+.. option:: -G
+
+ This option generates a key, but does not publish it or sign with it. This option is
+ incompatible with :option:`-P` and :option:`-A`.
+
+.. option:: -h
+
+ This option prints a short summary of the options and arguments to
+ :program:`dnssec-keyfromlabel`.
+
+.. option:: -K directory
+
+ This option sets the directory in which the key files are to be written.
+
+.. option:: -k
+
+ This option generates KEY records rather than DNSKEY records.
+
+.. option:: -L ttl
+
+ This option sets the default TTL to use for this key when it is converted into a
+ DNSKEY RR. This is the TTL used when the key is imported into a zone,
+ unless there was already a DNSKEY RRset in
+ place, in which case the existing TTL would take precedence. Setting
+ the default TTL to ``0`` or ``none`` removes it.
+
+.. option:: -p protocol
+
+ This option sets the protocol value for the key. The protocol is a number between
+ 0 and 255. The default is 3 (DNSSEC). Other possible values for this
+ argument are listed in :rfc:`2535` and its successors.
+
+.. option:: -S key
+
+ This option generates a key as an explicit successor to an existing key. The name,
+ algorithm, size, and type of the key are set to match the
+ predecessor. The activation date of the new key is set to the
+ inactivation date of the existing one. The publication date is
+ set to the activation date minus the prepublication interval, which
+ defaults to 30 days.
+
+.. option:: -t type
+
+ This option indicates the type of the key. ``type`` must be one of AUTHCONF,
+ NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. AUTH refers
+ to the ability to authenticate data, and CONF to the ability to encrypt
+ data.
+
+.. option:: -v level
+
+ This option sets the debugging level.
+
+.. option:: -V
+
+ This option prints version information.
+
+.. option:: -y
+
+ This option allows DNSSEC key files to be generated even if the key ID would
+ collide with that of an existing key, in the event of either key
+ being revoked. (This is only safe to enable if
+ :rfc:`5011` trust anchor maintenance is not used with either of the keys
+ involved.)
+
+Timing Options
+~~~~~~~~~~~~~~
+
+Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS
+(which is the format used inside key files),
+or 'Day Mon DD HH:MM:SS YYYY' (as printed by ``dnssec-settime -p``),
+or UNIX epoch time (as printed by ``dnssec-settime -up``),
+or the literal ``now``.
+
+The argument can be followed by ``+`` or ``-`` and an offset from the
+given time. The literal ``now`` can be omitted before an offset. The
+offset can be followed by one of the suffixes ``y``, ``mo``, ``w``,
+``d``, ``h``, or ``mi``, so that it is computed in years (defined as
+365 24-hour days, ignoring leap years), months (defined as 30 24-hour
+days), weeks, days, hours, or minutes, respectively. Without a suffix,
+the offset is computed in seconds.
+
+To explicitly prevent a date from being set, use ``none``, ``never``,
+or ``unset``.
+
+All these formats are case-insensitive.
+
+.. option:: -P date/offset
+
+ This option sets the date on which a key is to be published to the zone. After
+ that date, the key is included in the zone but is not used
+ to sign it. If not set, and if the :option:`-G` option has not been used, the
+ default is the current date.
+
+ .. program:: dnssec-keyfromlabel -P
+ .. option:: sync date/offset
+
+ This option sets the date on which CDS and CDNSKEY records that match this key
+ are to be published to the zone.
+
+.. program:: dnssec-keyfromlabel
+
+.. option:: -A date/offset
+
+ This option sets the date on which the key is to be activated. After that date,
+ the key is included in the zone and used to sign it. If not set,
+ and if the :option:`-G` option has not been used, the default is the current date.
+
+.. option:: -R date/offset
+
+ This option sets the date on which the key is to be revoked. After that date, the
+ key is flagged as revoked. It is included in the zone and
+ is used to sign it.
+
+.. option:: -I date/offset
+
+ This option sets the date on which the key is to be retired. After that date, the
+ key is still included in the zone, but it is not used to
+ sign it.
+
+.. option:: -D date/offset
+
+ This option sets the date on which the key is to be deleted. After that date, the
+ key is no longer included in the zone. (However, it may remain in the key
+ repository.)
+
+ .. program:: dnssec-keyfromlabel -D
+ .. option:: sync date/offset
+
+ This option sets the date on which the CDS and CDNSKEY records that match this
+ key are to be deleted.
+
+.. program:: dnssec-keyfromlabel
+
+.. option:: -i interval
+
+ This option sets the prepublication interval for a key. If set, then the
+ publication and activation dates must be separated by at least this
+ much time. If the activation date is specified but the publication
+ date is not, the publication date defaults to this much time
+ before the activation date; conversely, if the publication date is
+ specified but not the activation date, activation is set to
+ this much time after publication.
+
+ If the key is being created as an explicit successor to another key,
+ then the default prepublication interval is 30 days; otherwise it is
+ zero.
+
+ As with date offsets, if the argument is followed by one of the
+ suffixes ``y``, ``mo``, ``w``, ``d``, ``h``, or ``mi``, the interval is
+ measured in years, months, weeks, days, hours, or minutes,
+ respectively. Without a suffix, the interval is measured in seconds.
+
+Generated Key Files
+~~~~~~~~~~~~~~~~~~~
+
+When :program:`dnssec-keyfromlabel` completes successfully, it prints a string
+of the form ``Knnnn.+aaa+iiiii`` to the standard output. This is an
+identification string for the key files it has generated.
+
+- ``nnnn`` is the key name.
+
+- ``aaa`` is the numeric representation of the algorithm.
+
+- ``iiiii`` is the key identifier (or footprint).
+
+:program:`dnssec-keyfromlabel` creates two files, with names based on the
+printed string. ``Knnnn.+aaa+iiiii.key`` contains the public key, and
+``Knnnn.+aaa+iiiii.private`` contains the private key.
+
+The ``.key`` file contains a DNS KEY record that can be inserted into a
+zone file (directly or with an $INCLUDE statement).
+
+The ``.private`` file contains algorithm-specific fields. For obvious
+security reasons, this file does not have general read permission.
+
+See Also
+~~~~~~~~
+
+:iscman:`dnssec-keygen(8) <dnssec-keygen>`, :iscman:`dnssec-signzone(8) <dnssec-signzone>`, BIND 9 Administrator Reference Manual,
+:rfc:`4034`, :rfc:`7512`.
diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c
new file mode 100644
index 0000000..3d77976
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.c
@@ -0,0 +1,1292 @@
+/*
+ * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * Portions Copyright (C) Network Associates, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/dnssec.h>
+#include <dns/fixedname.h>
+#include <dns/kasp.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+#include <isccfg/cfg.h>
+#include <isccfg/grammar.h>
+#include <isccfg/kaspconf.h>
+#include <isccfg/namedconf.h>
+
+#include "dnssectool.h"
+
+#define MAX_RSA 4096 /* should be long enough... */
+
+const char *program = "dnssec-keygen";
+
+isc_log_t *lctx = NULL;
+
+noreturn static void
+usage(void);
+
+static void
+progress(int p);
+
+struct keygen_ctx {
+ const char *predecessor;
+ const char *policy;
+ const char *configfile;
+ const char *directory;
+ char *algname;
+ char *nametype;
+ char *type;
+ int generator;
+ int protocol;
+ int size;
+ int signatory;
+ dns_rdataclass_t rdclass;
+ int options;
+ int dbits;
+ dns_ttl_t ttl;
+ uint16_t kskflag;
+ uint16_t revflag;
+ dns_secalg_t alg;
+ /* timing data */
+ int prepub;
+ isc_stdtime_t now;
+ isc_stdtime_t publish;
+ isc_stdtime_t activate;
+ isc_stdtime_t inactive;
+ isc_stdtime_t revokekey;
+ isc_stdtime_t deltime;
+ isc_stdtime_t syncadd;
+ isc_stdtime_t syncdel;
+ bool setpub;
+ bool setact;
+ bool setinact;
+ bool setrev;
+ bool setdel;
+ bool setsyncadd;
+ bool setsyncdel;
+ bool unsetpub;
+ bool unsetact;
+ bool unsetinact;
+ bool unsetrev;
+ bool unsetdel;
+ /* how to generate the key */
+ bool setttl;
+ bool use_nsec3;
+ bool genonly;
+ bool showprogress;
+ bool quiet;
+ bool oldstyle;
+ /* state */
+ time_t lifetime;
+ bool ksk;
+ bool zsk;
+};
+
+typedef struct keygen_ctx keygen_ctx_t;
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s [options] name\n\n", program);
+ fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
+ fprintf(stderr, " name: owner of the key\n");
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -K <directory>: write keys into directory\n");
+ fprintf(stderr, " -k <policy>: generate keys for dnssec-policy\n");
+ fprintf(stderr, " -l <file>: configuration file with dnssec-policy "
+ "statement\n");
+ fprintf(stderr, " -a <algorithm>:\n");
+ fprintf(stderr, " RSASHA1 | NSEC3RSASHA1 |\n");
+ fprintf(stderr, " RSASHA256 | RSASHA512 |\n");
+ fprintf(stderr, " ECDSAP256SHA256 | ECDSAP384SHA384 |\n");
+ fprintf(stderr, " ED25519 | ED448 | DH\n");
+ fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
+ fprintf(stderr, " -b <key size in bits>:\n");
+ fprintf(stderr, " RSASHA1:\t[1024..%d]\n", MAX_RSA);
+ fprintf(stderr, " NSEC3RSASHA1:\t[1024..%d]\n", MAX_RSA);
+ fprintf(stderr, " RSASHA256:\t[1024..%d]\n", MAX_RSA);
+ fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA);
+ fprintf(stderr, " DH:\t\t[128..4096]\n");
+ fprintf(stderr, " ECDSAP256SHA256:\tignored\n");
+ fprintf(stderr, " ECDSAP384SHA384:\tignored\n");
+ fprintf(stderr, " ED25519:\tignored\n");
+ fprintf(stderr, " ED448:\tignored\n");
+ fprintf(stderr, " (key size defaults are set according to\n"
+ " algorithm and usage (ZSK or KSK)\n");
+ fprintf(stderr, " -n <nametype>: ZONE | HOST | ENTITY | "
+ "USER | OTHER\n");
+ fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n");
+ fprintf(stderr, " -c <class>: (default: IN)\n");
+ fprintf(stderr, " -d <digest bits> (0 => max, default)\n");
+ fprintf(stderr, " -E <engine>:\n");
+ fprintf(stderr, " name of an OpenSSL engine to use\n");
+ fprintf(stderr, " -f <keyflag>: KSK | REVOKE\n");
+ fprintf(stderr, " -g <generator>: use specified generator "
+ "(DH only)\n");
+ fprintf(stderr, " -L <ttl>: default key TTL\n");
+ fprintf(stderr, " -p <protocol>: (default: 3 [dnssec])\n");
+ fprintf(stderr, " -s <strength>: strength value this key signs DNS "
+ "records with (default: 0)\n");
+ fprintf(stderr, " -T <rrtype>: DNSKEY | KEY (default: DNSKEY; "
+ "use KEY for SIG(0))\n");
+ fprintf(stderr, " -t <type>: "
+ "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
+ "(default: AUTHCONF)\n");
+ fprintf(stderr, " -h: print usage and exit\n");
+ fprintf(stderr, " -m <memory debugging mode>:\n");
+ fprintf(stderr, " usage | trace | record | size | mctx\n");
+ fprintf(stderr, " -v <level>: set verbosity level (0 - 10)\n");
+ fprintf(stderr, " -V: print version information\n");
+ fprintf(stderr, "Timing options:\n");
+ fprintf(stderr, " -P date/[+-]offset/none: set key publication date "
+ "(default: now)\n");
+ fprintf(stderr, " -P sync date/[+-]offset/none: set CDS and CDNSKEY "
+ "publication date\n");
+ fprintf(stderr, " -A date/[+-]offset/none: set key activation date "
+ "(default: now)\n");
+ fprintf(stderr, " -R date/[+-]offset/none: set key "
+ "revocation date\n");
+ fprintf(stderr, " -I date/[+-]offset/none: set key "
+ "inactivation date\n");
+ fprintf(stderr, " -D date/[+-]offset/none: set key deletion date\n");
+ fprintf(stderr, " -D sync date/[+-]offset/none: set CDS and CDNSKEY "
+ "deletion date\n");
+
+ fprintf(stderr, " -G: generate key only; do not set -P or -A\n");
+ fprintf(stderr, " -C: generate a backward-compatible key, omitting "
+ "all dates\n");
+ fprintf(stderr, " -S <key>: generate a successor to an existing "
+ "key\n");
+ fprintf(stderr, " -i <interval>: prepublication interval for "
+ "successor key "
+ "(default: 30 days)\n");
+ fprintf(stderr, "Output:\n");
+ fprintf(stderr, " K<name>+<alg>+<id>.key, "
+ "K<name>+<alg>+<id>.private\n");
+
+ exit(-1);
+}
+
+static void
+progress(int p) {
+ char c = '*';
+
+ switch (p) {
+ case 0:
+ c = '.';
+ break;
+ case 1:
+ c = '+';
+ break;
+ case 2:
+ c = '*';
+ break;
+ case 3:
+ c = ' ';
+ break;
+ default:
+ break;
+ }
+ (void)putc(c, stderr);
+ (void)fflush(stderr);
+}
+
+static void
+kasp_from_conf(cfg_obj_t *config, isc_mem_t *mctx, const char *name,
+ dns_kasp_t **kaspp) {
+ const cfg_listelt_t *element;
+ const cfg_obj_t *kasps = NULL;
+ dns_kasp_t *kasp = NULL, *kasp_next;
+ isc_result_t result = ISC_R_NOTFOUND;
+ dns_kasplist_t kasplist;
+
+ ISC_LIST_INIT(kasplist);
+
+ (void)cfg_map_get(config, "dnssec-policy", &kasps);
+ for (element = cfg_list_first(kasps); element != NULL;
+ element = cfg_list_next(element))
+ {
+ cfg_obj_t *kconfig = cfg_listelt_value(element);
+ kasp = NULL;
+ if (strcmp(cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
+ name) != 0)
+ {
+ continue;
+ }
+
+ result = cfg_kasp_fromconfig(kconfig, NULL, mctx, lctx,
+ &kasplist, &kasp);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to configure dnssec-policy '%s': %s",
+ cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
+ isc_result_totext(result));
+ }
+ INSIST(kasp != NULL);
+ dns_kasp_freeze(kasp);
+ break;
+ }
+
+ *kaspp = kasp;
+
+ /*
+ * Cleanup kasp list.
+ */
+ for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) {
+ kasp_next = ISC_LIST_NEXT(kasp, link);
+ ISC_LIST_UNLINK(kasplist, kasp, link);
+ dns_kasp_detach(&kasp);
+ }
+}
+
+static void
+keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
+ char filename[255];
+ char algstr[DNS_SECALG_FORMATSIZE];
+ uint16_t flags = 0;
+ int param = 0;
+ bool null_key = false;
+ bool conflict = false;
+ bool show_progress = false;
+ isc_buffer_t buf;
+ dns_name_t *name;
+ dns_fixedname_t fname;
+ isc_result_t ret;
+ dst_key_t *key = NULL;
+ dst_key_t *prevkey = NULL;
+
+ UNUSED(argc);
+
+ dns_secalg_format(ctx->alg, algstr, sizeof(algstr));
+
+ if (ctx->predecessor == NULL) {
+ if (ctx->prepub == -1) {
+ ctx->prepub = 0;
+ }
+
+ name = dns_fixedname_initname(&fname);
+ isc_buffer_init(&buf, argv[isc_commandline_index],
+ strlen(argv[isc_commandline_index]));
+ isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
+ ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("invalid key name %s: %s",
+ argv[isc_commandline_index],
+ isc_result_totext(ret));
+ }
+
+ if (!dst_algorithm_supported(ctx->alg)) {
+ fatal("unsupported algorithm: %s", algstr);
+ }
+
+ if (ctx->alg == DST_ALG_DH) {
+ ctx->options |= DST_TYPE_KEY;
+ }
+
+ if (ctx->use_nsec3) {
+ switch (ctx->alg) {
+ case DST_ALG_RSASHA1:
+ ctx->alg = DST_ALG_NSEC3RSASHA1;
+ break;
+ case DST_ALG_NSEC3RSASHA1:
+ case DST_ALG_RSASHA256:
+ case DST_ALG_RSASHA512:
+ case DST_ALG_ECDSA256:
+ case DST_ALG_ECDSA384:
+ case DST_ALG_ED25519:
+ case DST_ALG_ED448:
+ break;
+ default:
+ fatal("algorithm %s is incompatible with NSEC3"
+ ", do not use the -3 option",
+ algstr);
+ }
+ }
+
+ if (ctx->type != NULL && (ctx->options & DST_TYPE_KEY) != 0) {
+ if (strcasecmp(ctx->type, "NOAUTH") == 0) {
+ flags |= DNS_KEYTYPE_NOAUTH;
+ } else if (strcasecmp(ctx->type, "NOCONF") == 0) {
+ flags |= DNS_KEYTYPE_NOCONF;
+ } else if (strcasecmp(ctx->type, "NOAUTHCONF") == 0) {
+ flags |= (DNS_KEYTYPE_NOAUTH |
+ DNS_KEYTYPE_NOCONF);
+ if (ctx->size < 0) {
+ ctx->size = 0;
+ }
+ } else if (strcasecmp(ctx->type, "AUTHCONF") == 0) {
+ /* nothing */
+ } else {
+ fatal("invalid type %s", ctx->type);
+ }
+ }
+
+ if (ctx->size < 0) {
+ switch (ctx->alg) {
+ case DST_ALG_RSASHA1:
+ case DST_ALG_NSEC3RSASHA1:
+ case DST_ALG_RSASHA256:
+ case DST_ALG_RSASHA512:
+ ctx->size = 2048;
+ if (verbose > 0) {
+ fprintf(stderr,
+ "key size not "
+ "specified; defaulting"
+ " to %d\n",
+ ctx->size);
+ }
+ break;
+ case DST_ALG_ECDSA256:
+ case DST_ALG_ECDSA384:
+ case DST_ALG_ED25519:
+ case DST_ALG_ED448:
+ break;
+ default:
+ fatal("key size not specified (-b option)");
+ }
+ }
+
+ if (!ctx->oldstyle && ctx->prepub > 0) {
+ if (ctx->setpub && ctx->setact &&
+ (ctx->activate - ctx->prepub) < ctx->publish)
+ {
+ fatal("Activation and publication dates "
+ "are closer together than the\n\t"
+ "prepublication interval.");
+ }
+
+ if (!ctx->setpub && !ctx->setact) {
+ ctx->setpub = ctx->setact = true;
+ ctx->publish = ctx->now;
+ ctx->activate = ctx->now + ctx->prepub;
+ } else if (ctx->setpub && !ctx->setact) {
+ ctx->setact = true;
+ ctx->activate = ctx->publish + ctx->prepub;
+ } else if (ctx->setact && !ctx->setpub) {
+ ctx->setpub = true;
+ ctx->publish = ctx->activate - ctx->prepub;
+ }
+
+ if ((ctx->activate - ctx->prepub) < ctx->now) {
+ fatal("Time until activation is shorter "
+ "than the\n\tprepublication interval.");
+ }
+ }
+ } else {
+ char keystr[DST_KEY_FORMATSIZE];
+ isc_stdtime_t when;
+ int major, minor;
+
+ if (ctx->prepub == -1) {
+ ctx->prepub = (30 * 86400);
+ }
+
+ if (ctx->alg != 0) {
+ fatal("-S and -a cannot be used together");
+ }
+ if (ctx->size >= 0) {
+ fatal("-S and -b cannot be used together");
+ }
+ if (ctx->nametype != NULL) {
+ fatal("-S and -n cannot be used together");
+ }
+ if (ctx->type != NULL) {
+ fatal("-S and -t cannot be used together");
+ }
+ if (ctx->setpub || ctx->unsetpub) {
+ fatal("-S and -P cannot be used together");
+ }
+ if (ctx->setact || ctx->unsetact) {
+ fatal("-S and -A cannot be used together");
+ }
+ if (ctx->use_nsec3) {
+ fatal("-S and -3 cannot be used together");
+ }
+ if (ctx->oldstyle) {
+ fatal("-S and -C cannot be used together");
+ }
+ if (ctx->genonly) {
+ fatal("-S and -G cannot be used together");
+ }
+
+ ret = dst_key_fromnamedfile(
+ ctx->predecessor, ctx->directory,
+ (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE),
+ mctx, &prevkey);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("Invalid keyfile %s: %s", ctx->predecessor,
+ isc_result_totext(ret));
+ }
+ if (!dst_key_isprivate(prevkey)) {
+ fatal("%s is not a private key", ctx->predecessor);
+ }
+
+ name = dst_key_name(prevkey);
+ ctx->alg = dst_key_alg(prevkey);
+ ctx->size = dst_key_size(prevkey);
+ flags = dst_key_flags(prevkey);
+
+ dst_key_format(prevkey, keystr, sizeof(keystr));
+ dst_key_getprivateformat(prevkey, &major, &minor);
+ if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) {
+ fatal("Key %s has incompatible format version %d.%d\n\t"
+ "It is not possible to generate a successor key.",
+ keystr, major, minor);
+ }
+
+ ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("Key %s has no activation date.\n\t"
+ "You must use dnssec-settime -A to set one "
+ "before generating a successor.",
+ keystr);
+ }
+
+ ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE,
+ &ctx->activate);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("Key %s has no inactivation date.\n\t"
+ "You must use dnssec-settime -I to set one "
+ "before generating a successor.",
+ keystr);
+ }
+
+ ctx->publish = ctx->activate - ctx->prepub;
+ if (ctx->publish < ctx->now) {
+ fatal("Key %s becomes inactive\n\t"
+ "sooner than the prepublication period "
+ "for the new key ends.\n\t"
+ "Either change the inactivation date with "
+ "dnssec-settime -I,\n\t"
+ "or use the -i option to set a shorter "
+ "prepublication interval.",
+ keystr);
+ }
+
+ ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when);
+ if (ret != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "%s: WARNING: Key %s has no removal "
+ "date;\n\t it will remain in the zone "
+ "indefinitely after rollover.\n\t "
+ "You can use dnssec-settime -D to "
+ "change this.\n",
+ program, keystr);
+ }
+
+ ctx->setpub = ctx->setact = true;
+ }
+
+ switch (ctx->alg) {
+ case DNS_KEYALG_RSASHA1:
+ case DNS_KEYALG_NSEC3RSASHA1:
+ case DNS_KEYALG_RSASHA256:
+ if (ctx->size != 0 && (ctx->size < 1024 || ctx->size > MAX_RSA))
+ {
+ fatal("RSA key size %d out of range", ctx->size);
+ }
+ break;
+ case DNS_KEYALG_RSASHA512:
+ if (ctx->size != 0 && (ctx->size < 1024 || ctx->size > MAX_RSA))
+ {
+ fatal("RSA key size %d out of range", ctx->size);
+ }
+ break;
+ case DNS_KEYALG_DH:
+ if (ctx->size != 0 && (ctx->size < 128 || ctx->size > 4096)) {
+ fatal("DH key size %d out of range", ctx->size);
+ }
+ break;
+ case DST_ALG_ECDSA256:
+ ctx->size = 256;
+ break;
+ case DST_ALG_ECDSA384:
+ ctx->size = 384;
+ break;
+ case DST_ALG_ED25519:
+ ctx->size = 256;
+ break;
+ case DST_ALG_ED448:
+ ctx->size = 456;
+ break;
+ }
+
+ if (ctx->alg != DNS_KEYALG_DH && ctx->generator != 0) {
+ fatal("specified DH generator for a non-DH key");
+ }
+
+ if (ctx->nametype == NULL) {
+ if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */
+ fatal("no nametype specified");
+ }
+ flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */
+ } else if (strcasecmp(ctx->nametype, "zone") == 0) {
+ flags |= DNS_KEYOWNER_ZONE;
+ } else if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */
+ if (strcasecmp(ctx->nametype, "host") == 0 ||
+ strcasecmp(ctx->nametype, "entity") == 0)
+ {
+ flags |= DNS_KEYOWNER_ENTITY;
+ } else if (strcasecmp(ctx->nametype, "user") == 0) {
+ flags |= DNS_KEYOWNER_USER;
+ } else {
+ fatal("invalid KEY nametype %s", ctx->nametype);
+ }
+ } else if (strcasecmp(ctx->nametype, "other") != 0) { /* DNSKEY */
+ fatal("invalid DNSKEY nametype %s", ctx->nametype);
+ }
+
+ if (ctx->directory == NULL) {
+ ctx->directory = ".";
+ }
+
+ if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */
+ flags |= ctx->signatory;
+ } else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */
+ flags |= ctx->kskflag;
+ flags |= ctx->revflag;
+ }
+
+ if (ctx->protocol == -1) {
+ ctx->protocol = DNS_KEYPROTO_DNSSEC;
+ } else if ((ctx->options & DST_TYPE_KEY) == 0 &&
+ ctx->protocol != DNS_KEYPROTO_DNSSEC)
+ {
+ fatal("invalid DNSKEY protocol: %d", ctx->protocol);
+ }
+
+ if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
+ if (ctx->size > 0) {
+ fatal("specified null key with non-zero size");
+ }
+ if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) {
+ fatal("specified null key with signing authority");
+ }
+ }
+
+ if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
+ ctx->alg == DNS_KEYALG_DH)
+ {
+ fatal("a key with algorithm %s cannot be a zone key", algstr);
+ }
+
+ switch (ctx->alg) {
+ case DNS_KEYALG_RSASHA1:
+ case DNS_KEYALG_NSEC3RSASHA1:
+ case DNS_KEYALG_RSASHA256:
+ case DNS_KEYALG_RSASHA512:
+ show_progress = true;
+ break;
+
+ case DNS_KEYALG_DH:
+ param = ctx->generator;
+ break;
+
+ case DST_ALG_ECDSA256:
+ case DST_ALG_ECDSA384:
+ case DST_ALG_ED25519:
+ case DST_ALG_ED448:
+ show_progress = true;
+ break;
+ }
+
+ if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
+ null_key = true;
+ }
+
+ isc_buffer_init(&buf, filename, sizeof(filename) - 1);
+
+ do {
+ conflict = false;
+
+ if (!ctx->quiet && show_progress) {
+ fprintf(stderr, "Generating key pair.");
+ ret = dst_key_generate(name, ctx->alg, ctx->size, param,
+ flags, ctx->protocol,
+ ctx->rdclass, mctx, &key,
+ &progress);
+ putc('\n', stderr);
+ fflush(stderr);
+ } else {
+ ret = dst_key_generate(name, ctx->alg, ctx->size, param,
+ flags, ctx->protocol,
+ ctx->rdclass, mctx, &key, NULL);
+ }
+
+ if (ret != ISC_R_SUCCESS) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ fatal("failed to generate key %s/%s: %s\n", namestr,
+ algstr, isc_result_totext(ret));
+ }
+
+ dst_key_setbits(key, ctx->dbits);
+
+ /*
+ * Set key timing metadata (unless using -C)
+ *
+ * Creation date is always set to "now".
+ *
+ * For a new key without an explicit predecessor, publish
+ * and activation dates are set to "now" by default, but
+ * can both be overridden.
+ *
+ * For a successor key, activation is set to match the
+ * predecessor's inactivation date. Publish is set to 30
+ * days earlier than that (XXX: this should be configurable).
+ * If either of the resulting dates are in the past, that's
+ * an error; the inactivation date of the predecessor key
+ * must be updated before a successor key can be created.
+ */
+ if (!ctx->oldstyle) {
+ dst_key_settime(key, DST_TIME_CREATED, ctx->now);
+
+ if (ctx->genonly && (ctx->setpub || ctx->setact)) {
+ fatal("cannot use -G together with "
+ "-P or -A options");
+ }
+
+ if (ctx->setpub) {
+ dst_key_settime(key, DST_TIME_PUBLISH,
+ ctx->publish);
+ } else if (ctx->setact && !ctx->unsetpub) {
+ dst_key_settime(key, DST_TIME_PUBLISH,
+ ctx->activate - ctx->prepub);
+ } else if (!ctx->genonly && !ctx->unsetpub) {
+ dst_key_settime(key, DST_TIME_PUBLISH,
+ ctx->now);
+ }
+
+ if (ctx->setact) {
+ dst_key_settime(key, DST_TIME_ACTIVATE,
+ ctx->activate);
+ } else if (!ctx->genonly && !ctx->unsetact) {
+ dst_key_settime(key, DST_TIME_ACTIVATE,
+ ctx->now);
+ }
+
+ if (ctx->setrev) {
+ if (ctx->kskflag == 0) {
+ fprintf(stderr,
+ "%s: warning: Key is "
+ "not flagged as a KSK, but -R "
+ "was used. Revoking a ZSK is "
+ "legal, but undefined.\n",
+ program);
+ }
+ dst_key_settime(key, DST_TIME_REVOKE,
+ ctx->revokekey);
+ }
+
+ if (ctx->setinact) {
+ dst_key_settime(key, DST_TIME_INACTIVE,
+ ctx->inactive);
+ }
+
+ if (ctx->setdel) {
+ if (ctx->setinact &&
+ ctx->deltime < ctx->inactive)
+ {
+ fprintf(stderr,
+ "%s: warning: Key is "
+ "scheduled to be deleted "
+ "before it is scheduled to be "
+ "made inactive.\n",
+ program);
+ }
+ dst_key_settime(key, DST_TIME_DELETE,
+ ctx->deltime);
+ }
+
+ if (ctx->setsyncadd) {
+ dst_key_settime(key, DST_TIME_SYNCPUBLISH,
+ ctx->syncadd);
+ }
+
+ if (ctx->setsyncdel) {
+ dst_key_settime(key, DST_TIME_SYNCDELETE,
+ ctx->syncdel);
+ }
+ } else {
+ if (ctx->setpub || ctx->setact || ctx->setrev ||
+ ctx->setinact || ctx->setdel || ctx->unsetpub ||
+ ctx->unsetact || ctx->unsetrev || ctx->unsetinact ||
+ ctx->unsetdel || ctx->genonly || ctx->setsyncadd ||
+ ctx->setsyncdel)
+ {
+ fatal("cannot use -C together with "
+ "-P, -A, -R, -I, -D, or -G options");
+ }
+ /*
+ * Compatibility mode: Private-key-format
+ * should be set to 1.2.
+ */
+ dst_key_setprivateformat(key, 1, 2);
+ }
+
+ /* Set the default key TTL */
+ if (ctx->setttl) {
+ dst_key_setttl(key, ctx->ttl);
+ }
+
+ /* Set dnssec-policy related metadata */
+ if (ctx->policy != NULL) {
+ dst_key_setnum(key, DST_NUM_LIFETIME, ctx->lifetime);
+ dst_key_setbool(key, DST_BOOL_KSK, ctx->ksk);
+ dst_key_setbool(key, DST_BOOL_ZSK, ctx->zsk);
+ }
+
+ /*
+ * Do not overwrite an existing key, or create a key
+ * if there is a risk of ID collision due to this key
+ * or another key being revoked.
+ */
+ if (key_collision(key, name, ctx->directory, mctx, NULL)) {
+ conflict = true;
+ if (null_key) {
+ dst_key_free(&key);
+ break;
+ }
+
+ if (verbose > 0) {
+ isc_buffer_clear(&buf);
+ ret = dst_key_buildfilename(
+ key, 0, ctx->directory, &buf);
+ if (ret == ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "%s: %s already exists, or "
+ "might collide with another "
+ "key upon revokation. "
+ "Generating a new key\n",
+ program, filename);
+ }
+ }
+
+ dst_key_free(&key);
+ }
+ } while (conflict);
+
+ if (conflict) {
+ fatal("cannot generate a null key due to possible key ID "
+ "collision");
+ }
+
+ if (ctx->predecessor != NULL && prevkey != NULL) {
+ dst_key_setnum(prevkey, DST_NUM_SUCCESSOR, dst_key_id(key));
+ dst_key_setnum(key, DST_NUM_PREDECESSOR, dst_key_id(prevkey));
+
+ ret = dst_key_tofile(prevkey, ctx->options, ctx->directory);
+ if (ret != ISC_R_SUCCESS) {
+ char keystr[DST_KEY_FORMATSIZE];
+ dst_key_format(prevkey, keystr, sizeof(keystr));
+ fatal("failed to update predecessor %s: %s\n", keystr,
+ isc_result_totext(ret));
+ }
+ }
+
+ ret = dst_key_tofile(key, ctx->options, ctx->directory);
+ if (ret != ISC_R_SUCCESS) {
+ char keystr[DST_KEY_FORMATSIZE];
+ dst_key_format(key, keystr, sizeof(keystr));
+ fatal("failed to write key %s: %s\n", keystr,
+ isc_result_totext(ret));
+ }
+
+ isc_buffer_clear(&buf);
+ ret = dst_key_buildfilename(key, 0, NULL, &buf);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("dst_key_buildfilename returned: %s\n",
+ isc_result_totext(ret));
+ }
+ printf("%s\n", filename);
+
+ dst_key_free(&key);
+ if (prevkey != NULL) {
+ dst_key_free(&prevkey);
+ }
+}
+
+int
+main(int argc, char **argv) {
+ char *algname = NULL, *freeit = NULL;
+ char *classname = NULL;
+ char *endp;
+ isc_mem_t *mctx = NULL;
+ isc_result_t ret;
+ isc_textregion_t r;
+ const char *engine = NULL;
+ unsigned char c;
+ int ch;
+
+ keygen_ctx_t ctx = {
+ .options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC,
+ .prepub = -1,
+ .protocol = -1,
+ .size = -1,
+ };
+
+ if (argc == 1) {
+ usage();
+ }
+
+ isc_commandline_errprint = false;
+
+ /*
+ * Process memory debugging argument first.
+ */
+#define CMDLINE_FLAGS \
+ "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:k:L:l:m:n:P:p:qR:r:S:s:" \
+ "T:t:v:V"
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case 'm':
+ if (strcasecmp(isc_commandline_argument, "record") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ }
+ if (strcasecmp(isc_commandline_argument, "trace") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
+ }
+ if (strcasecmp(isc_commandline_argument, "usage") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = true;
+
+ isc_mem_create(&mctx);
+ isc_stdtime_get(&ctx.now);
+
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case '3':
+ ctx.use_nsec3 = true;
+ break;
+ case 'a':
+ algname = isc_commandline_argument;
+ break;
+ case 'b':
+ ctx.size = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || ctx.size < 0) {
+ fatal("-b requires a non-negative number");
+ }
+ break;
+ case 'C':
+ ctx.oldstyle = true;
+ break;
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'd':
+ ctx.dbits = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || ctx.dbits < 0) {
+ fatal("-d requires a non-negative number");
+ }
+ break;
+ case 'E':
+ engine = isc_commandline_argument;
+ break;
+ case 'e':
+ fprintf(stderr, "phased-out option -e "
+ "(was 'use (RSA) large exponent')\n");
+ break;
+ case 'f':
+ c = (unsigned char)(isc_commandline_argument[0]);
+ if (toupper(c) == 'K') {
+ ctx.kskflag = DNS_KEYFLAG_KSK;
+ } else if (toupper(c) == 'R') {
+ ctx.revflag = DNS_KEYFLAG_REVOKE;
+ } else {
+ fatal("unknown flag '%s'",
+ isc_commandline_argument);
+ }
+ break;
+ case 'g':
+ ctx.generator = strtol(isc_commandline_argument, &endp,
+ 10);
+ if (*endp != '\0' || ctx.generator <= 0) {
+ fatal("-g requires a positive number");
+ }
+ break;
+ case 'K':
+ ctx.directory = isc_commandline_argument;
+ ret = try_dir(ctx.directory);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("cannot open directory %s: %s",
+ ctx.directory, isc_result_totext(ret));
+ }
+ break;
+ case 'k':
+ ctx.policy = isc_commandline_argument;
+ break;
+ case 'L':
+ ctx.ttl = strtottl(isc_commandline_argument);
+ ctx.setttl = true;
+ break;
+ case 'l':
+ ctx.configfile = isc_commandline_argument;
+ break;
+ case 'n':
+ ctx.nametype = isc_commandline_argument;
+ break;
+ case 'm':
+ break;
+ case 'p':
+ ctx.protocol = strtol(isc_commandline_argument, &endp,
+ 10);
+ if (*endp != '\0' || ctx.protocol < 0 ||
+ ctx.protocol > 255)
+ {
+ fatal("-p must be followed by a number "
+ "[0..255]");
+ }
+ break;
+ case 'q':
+ ctx.quiet = true;
+ break;
+ case 'r':
+ fatal("The -r option has been deprecated.\n"
+ "System random data is always used.\n");
+ break;
+ case 's':
+ ctx.signatory = strtol(isc_commandline_argument, &endp,
+ 10);
+ if (*endp != '\0' || ctx.signatory < 0 ||
+ ctx.signatory > 15)
+ {
+ fatal("-s must be followed by a number "
+ "[0..15]");
+ }
+ break;
+ case 'T':
+ if (strcasecmp(isc_commandline_argument, "KEY") == 0) {
+ ctx.options |= DST_TYPE_KEY;
+ } else if (strcasecmp(isc_commandline_argument,
+ "DNSKE"
+ "Y") == 0)
+ {
+ /* default behavior */
+ } else {
+ fatal("unknown type '%s'",
+ isc_commandline_argument);
+ }
+ break;
+ case 't':
+ ctx.type = isc_commandline_argument;
+ break;
+ case 'v':
+ endp = NULL;
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fatal("-v must be followed by a number");
+ }
+ break;
+ case 'G':
+ ctx.genonly = true;
+ break;
+ case 'P':
+ /* -Psync ? */
+ if (isoptarg("sync", argv, usage)) {
+ if (ctx.setsyncadd) {
+ fatal("-P sync specified more than "
+ "once");
+ }
+
+ ctx.syncadd = strtotime(
+ isc_commandline_argument, ctx.now,
+ ctx.now, &ctx.setsyncadd);
+ break;
+ }
+ (void)isoptarg("dnskey", argv, usage);
+ if (ctx.setpub || ctx.unsetpub) {
+ fatal("-P specified more than once");
+ }
+
+ ctx.publish = strtotime(isc_commandline_argument,
+ ctx.now, ctx.now, &ctx.setpub);
+ ctx.unsetpub = !ctx.setpub;
+ break;
+ case 'A':
+ if (ctx.setact || ctx.unsetact) {
+ fatal("-A specified more than once");
+ }
+
+ ctx.activate = strtotime(isc_commandline_argument,
+ ctx.now, ctx.now, &ctx.setact);
+ ctx.unsetact = !ctx.setact;
+ break;
+ case 'R':
+ if (ctx.setrev || ctx.unsetrev) {
+ fatal("-R specified more than once");
+ }
+
+ ctx.revokekey = strtotime(isc_commandline_argument,
+ ctx.now, ctx.now,
+ &ctx.setrev);
+ ctx.unsetrev = !ctx.setrev;
+ break;
+ case 'I':
+ if (ctx.setinact || ctx.unsetinact) {
+ fatal("-I specified more than once");
+ }
+
+ ctx.inactive = strtotime(isc_commandline_argument,
+ ctx.now, ctx.now,
+ &ctx.setinact);
+ ctx.unsetinact = !ctx.setinact;
+ break;
+ case 'D':
+ /* -Dsync ? */
+ if (isoptarg("sync", argv, usage)) {
+ if (ctx.setsyncdel) {
+ fatal("-D sync specified more than "
+ "once");
+ }
+
+ ctx.syncdel = strtotime(
+ isc_commandline_argument, ctx.now,
+ ctx.now, &ctx.setsyncdel);
+ break;
+ }
+ (void)isoptarg("dnskey", argv, usage);
+ if (ctx.setdel || ctx.unsetdel) {
+ fatal("-D specified more than once");
+ }
+
+ ctx.deltime = strtotime(isc_commandline_argument,
+ ctx.now, ctx.now, &ctx.setdel);
+ ctx.unsetdel = !ctx.setdel;
+ break;
+ case 'S':
+ ctx.predecessor = isc_commandline_argument;
+ break;
+ case 'i':
+ ctx.prepub = strtottl(isc_commandline_argument);
+ break;
+ case 'F':
+ /* Reserved for FIPS mode */
+ FALLTHROUGH;
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ }
+ FALLTHROUGH;
+ case 'h':
+ /* Does not return. */
+ usage();
+
+ case 'V':
+ /* Does not return. */
+ version(program);
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (!isatty(0)) {
+ ctx.quiet = true;
+ }
+
+ ret = dst_lib_init(mctx, engine);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("could not initialize dst: %s", isc_result_totext(ret));
+ }
+
+ setup_logging(mctx, &lctx);
+
+ ctx.rdclass = strtoclass(classname);
+
+ if (ctx.configfile == NULL || ctx.configfile[0] == '\0') {
+ ctx.configfile = NAMED_CONFFILE;
+ }
+
+ if (ctx.predecessor == NULL) {
+ if (argc < isc_commandline_index + 1) {
+ fatal("the key name was not specified");
+ }
+ if (argc > isc_commandline_index + 1) {
+ fatal("extraneous arguments");
+ }
+ }
+
+ if (ctx.predecessor == NULL && ctx.policy == NULL) {
+ if (algname == NULL) {
+ fatal("no algorithm specified");
+ }
+ r.base = algname;
+ r.length = strlen(algname);
+ ret = dns_secalg_fromtext(&ctx.alg, &r);
+ if (ret != ISC_R_SUCCESS) {
+ fatal("unknown algorithm %s", algname);
+ }
+ if (!dst_algorithm_supported(ctx.alg)) {
+ fatal("unsupported algorithm: %s", algname);
+ }
+ }
+
+ if (ctx.policy != NULL) {
+ if (ctx.nametype != NULL) {
+ fatal("-k and -n cannot be used together");
+ }
+ if (ctx.predecessor != NULL) {
+ fatal("-k and -S cannot be used together");
+ }
+ if (ctx.oldstyle) {
+ fatal("-k and -C cannot be used together");
+ }
+ if (ctx.setttl) {
+ fatal("-k and -L cannot be used together");
+ }
+ if (ctx.prepub > 0) {
+ fatal("-k and -i cannot be used together");
+ }
+ if (ctx.size != -1) {
+ fatal("-k and -b cannot be used together");
+ }
+ if (ctx.kskflag || ctx.revflag) {
+ fatal("-k and -f cannot be used together");
+ }
+ if (ctx.options & DST_TYPE_KEY) {
+ fatal("-k and -T KEY cannot be used together");
+ }
+ if (ctx.use_nsec3) {
+ fatal("-k and -3 cannot be used together");
+ }
+
+ ctx.options |= DST_TYPE_STATE;
+
+ if (strcmp(ctx.policy, "default") == 0) {
+ ctx.use_nsec3 = false;
+ ctx.alg = DST_ALG_ECDSA256;
+ ctx.size = 0;
+ ctx.kskflag = DNS_KEYFLAG_KSK;
+ ctx.ttl = 3600;
+ ctx.setttl = true;
+ ctx.ksk = true;
+ ctx.zsk = true;
+ ctx.lifetime = 0;
+
+ keygen(&ctx, mctx, argc, argv);
+ } else {
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *config = NULL;
+ dns_kasp_t *kasp = NULL;
+ dns_kasp_key_t *kaspkey = NULL;
+
+ RUNTIME_CHECK(cfg_parser_create(mctx, lctx, &parser) ==
+ ISC_R_SUCCESS);
+ if (cfg_parse_file(parser, ctx.configfile,
+ &cfg_type_namedconf,
+ &config) != ISC_R_SUCCESS)
+ {
+ fatal("unable to load dnssec-policy '%s' from "
+ "'%s'",
+ ctx.policy, ctx.configfile);
+ }
+
+ kasp_from_conf(config, mctx, ctx.policy, &kasp);
+ if (kasp == NULL) {
+ fatal("failed to load dnssec-policy '%s'",
+ ctx.policy);
+ }
+ if (ISC_LIST_EMPTY(dns_kasp_keys(kasp))) {
+ fatal("dnssec-policy '%s' has no keys "
+ "configured",
+ ctx.policy);
+ }
+
+ ctx.ttl = dns_kasp_dnskeyttl(kasp);
+ ctx.setttl = true;
+
+ kaspkey = ISC_LIST_HEAD(dns_kasp_keys(kasp));
+
+ while (kaspkey != NULL) {
+ ctx.use_nsec3 = false;
+ ctx.alg = dns_kasp_key_algorithm(kaspkey);
+ ctx.size = dns_kasp_key_size(kaspkey);
+ ctx.kskflag = dns_kasp_key_ksk(kaspkey)
+ ? DNS_KEYFLAG_KSK
+ : 0;
+ ctx.ksk = dns_kasp_key_ksk(kaspkey);
+ ctx.zsk = dns_kasp_key_zsk(kaspkey);
+ ctx.lifetime = dns_kasp_key_lifetime(kaspkey);
+
+ keygen(&ctx, mctx, argc, argv);
+
+ kaspkey = ISC_LIST_NEXT(kaspkey, link);
+ }
+
+ dns_kasp_detach(&kasp);
+ cfg_obj_destroy(parser, &config);
+ cfg_parser_destroy(&parser);
+ }
+ } else {
+ keygen(&ctx, mctx, argc, argv);
+ }
+
+ cleanup_logging(&lctx);
+ dst_lib_destroy();
+ if (verbose > 10) {
+ isc_mem_stats(mctx, stdout);
+ }
+ isc_mem_destroy(&mctx);
+
+ if (freeit != NULL) {
+ free(freeit);
+ }
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-keygen.rst b/bin/dnssec/dnssec-keygen.rst
new file mode 100644
index 0000000..a06027c
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.rst
@@ -0,0 +1,357 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: dnssec-keygen
+.. program:: dnssec-keygen
+.. _man_dnssec-keygen:
+
+dnssec-keygen: DNSSEC key generation tool
+-----------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`dnssec-keygen` [**-3**] [**-A** date/offset] [**-a** algorithm] [**-b** keysize] [**-C**] [**-c** class] [**-D** date/offset] [**-d** bits] [**-D** sync date/offset] [**-E** engine] [**-f** flag] [**-G**] [**-g** generator] [**-h**] [**-I** date/offset] [**-i** interval] [**-K** directory] [**-k** policy] [**-L** ttl] [**-l** file] [**-n** nametype] [**-P** date/offset] [**-P** sync date/offset] [**-p** protocol] [**-q**] [**-R** date/offset] [**-S** key] [**-s** strength] [**-T** rrtype] [**-t** type] [**-V**] [**-v** level] {name}
+
+Description
+~~~~~~~~~~~
+
+:program:`dnssec-keygen` generates keys for DNSSEC (Secure DNS), as defined in
+:rfc:`2535` and :rfc:`4034`. It can also generate keys for use with TSIG
+(Transaction Signatures) as defined in :rfc:`2845`, or TKEY (Transaction
+Key) as defined in :rfc:`2930`.
+
+The ``name`` of the key is specified on the command line. For DNSSEC
+keys, this must match the name of the zone for which the key is being
+generated.
+
+Options
+~~~~~~~
+
+.. option:: -3
+
+ This option uses an NSEC3-capable algorithm to generate a DNSSEC key. If this
+ option is used with an algorithm that has both NSEC and NSEC3
+ versions, then the NSEC3 version is selected; for example,
+ ``dnssec-keygen -3 -a RSASHA1`` specifies the NSEC3RSASHA1 algorithm.
+
+.. option:: -a algorithm
+
+ This option selects the cryptographic algorithm. For DNSSEC keys, the value of
+ ``algorithm`` must be one of RSASHA1, NSEC3RSASHA1, RSASHA256,
+ RSASHA512, ECDSAP256SHA256, ECDSAP384SHA384, ED25519, or ED448. For
+ TKEY, the value must be DH (Diffie-Hellman); specifying this value
+ automatically sets the :option:`-T KEY <-T>` option as well.
+
+ These values are case-insensitive. In some cases, abbreviations are
+ supported, such as ECDSA256 for ECDSAP256SHA256 and ECDSA384 for
+ ECDSAP384SHA384. If RSASHA1 is specified along with the :option:`-3`
+ option, NSEC3RSASHA1 is used instead.
+
+ This parameter *must* be specified except when using the :option:`-S`
+ option, which copies the algorithm from the predecessor key.
+
+ In prior releases, HMAC algorithms could be generated for use as TSIG
+ keys, but that feature was removed in BIND 9.13.0. Use
+ :iscman:`tsig-keygen` to generate TSIG keys.
+
+.. option:: -b keysize
+
+ This option specifies the number of bits in the key. The choice of key size
+ depends on the algorithm used: RSA keys must be between 1024 and 4096
+ bits; Diffie-Hellman keys must be between 128 and 4096 bits. Elliptic
+ curve algorithms do not need this parameter.
+
+ If the key size is not specified, some algorithms have pre-defined
+ defaults. For example, RSA keys for use as DNSSEC zone-signing keys
+ have a default size of 1024 bits; RSA keys for use as key-signing
+ keys (KSKs, generated with :option:`-f KSK <-f>`) default to 2048 bits.
+
+.. option:: -C
+
+ This option enables compatibility mode, which generates an old-style key, without any timing
+ metadata. By default, :program:`dnssec-keygen` includes the key's
+ creation date in the metadata stored with the private key; other
+ dates may be set there as well, including publication date, activation date,
+ etc. Keys that include this data may be incompatible with older
+ versions of BIND; the :option:`-C` option suppresses them.
+
+.. option:: -c class
+
+ This option indicates that the DNS record containing the key should have the
+ specified class. If not specified, class IN is used.
+
+.. option:: -d bits
+
+ This option specifies the key size in bits. For the algorithms RSASHA1, NSEC3RSASA1, RSASHA256, and
+ RSASHA512 the key size must be between 1024 and 4096 bits; DH size is between 128
+ and 4096 bits. This option is ignored for algorithms ECDSAP256SHA256,
+ ECDSAP384SHA384, ED25519, and ED448.
+
+.. option:: -E engine
+
+ This option specifies the cryptographic hardware to use, when applicable.
+
+ When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL
+ engine identifier that drives the cryptographic accelerator or
+ hardware service module (usually ``pkcs11``).
+
+.. option:: -f flag
+
+ This option sets the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flags are KSK (Key-Signing Key) and REVOKE.
+
+.. option:: -G
+
+ This option generates a key, but does not publish it or sign with it. This option is
+ incompatible with :option:`-P` and :option:`-A`.
+
+.. option:: -g generator
+
+ This option indicates the generator to use if generating a Diffie-Hellman key. Allowed
+ values are 2 and 5. If no generator is specified, a known prime from
+ :rfc:`2539` is used if possible; otherwise the default is 2.
+
+.. option:: -h
+
+ This option prints a short summary of the options and arguments to
+ :program:`dnssec-keygen`.
+
+.. option:: -K directory
+
+ This option sets the directory in which the key files are to be written.
+
+.. option:: -k policy
+
+ This option creates keys for a specific ``dnssec-policy``. If a policy uses multiple keys,
+ :program:`dnssec-keygen` generates multiple keys. This also
+ creates a ".state" file to keep track of the key state.
+
+ This option creates keys according to the ``dnssec-policy`` configuration, hence
+ it cannot be used at the same time as many of the other options that
+ :program:`dnssec-keygen` provides.
+
+.. option:: -L ttl
+
+ This option sets the default TTL to use for this key when it is converted into a
+ DNSKEY RR. This is the TTL used when the key is imported into a zone,
+ unless there was already a DNSKEY RRset in
+ place, in which case the existing TTL takes precedence. If this
+ value is not set and there is no existing DNSKEY RRset, the TTL
+ defaults to the SOA TTL. Setting the default TTL to ``0`` or ``none``
+ is the same as leaving it unset.
+
+.. option:: -l file
+
+ This option provides a configuration file that contains a ``dnssec-policy`` statement
+ (matching the policy set with :option:`-k`).
+
+.. option:: -n nametype
+
+ This option specifies the owner type of the key. The value of ``nametype`` must
+ either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY
+ (for a key associated with a host (KEY)), USER (for a key associated
+ with a user (KEY)), or OTHER (DNSKEY). These values are
+ case-insensitive. The default is ZONE for DNSKEY generation.
+
+.. option:: -p protocol
+
+ This option sets the protocol value for the generated key, for use with
+ :option:`-T KEY <-T>`. The protocol is a number between 0 and 255. The default
+ is 3 (DNSSEC). Other possible values for this argument are listed in
+ :rfc:`2535` and its successors.
+
+.. option:: -q
+
+ This option sets quiet mode, which suppresses unnecessary output, including progress
+ indication. Without this option, when :program:`dnssec-keygen` is run
+ interactively to generate an RSA or DSA key pair, it prints a
+ string of symbols to ``stderr`` indicating the progress of the key
+ generation. A ``.`` indicates that a random number has been found which
+ passed an initial sieve test; ``+`` means a number has passed a single
+ round of the Miller-Rabin primality test; and a space ( ) means that the
+ number has passed all the tests and is a satisfactory key.
+
+.. option:: -S key
+
+ This option creates a new key which is an explicit successor to an existing key.
+ The name, algorithm, size, and type of the key are set to match
+ the existing key. The activation date of the new key is set to
+ the inactivation date of the existing one. The publication date is
+ set to the activation date minus the prepublication interval,
+ which defaults to 30 days.
+
+.. option:: -s strength
+
+ This option specifies the strength value of the key. The strength is a number
+ between 0 and 15, and currently has no defined purpose in DNSSEC.
+
+.. option:: -T rrtype
+
+ This option specifies the resource record type to use for the key. ``rrtype``
+ must be either DNSKEY or KEY. The default is DNSKEY when using a
+ DNSSEC algorithm, but it can be overridden to KEY for use with
+ SIG(0).
+
+.. option:: -t type
+
+ This option indicates the type of the key for use with :option:`-T KEY <-T>`. ``type``
+ must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate data, and
+ CONF to the ability to encrypt data.
+
+.. option:: -V
+
+ This option prints version information.
+
+.. option:: -v level
+
+ This option sets the debugging level.
+
+Timing Options
+~~~~~~~~~~~~~~
+
+Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS
+(which is the format used inside key files),
+or 'Day Mon DD HH:MM:SS YYYY' (as printed by ``dnssec-settime -p``),
+or UNIX epoch time (as printed by ``dnssec-settime -up``),
+or the literal ``now``.
+
+The argument can be followed by ``+`` or ``-`` and an offset from the
+given time. The literal ``now`` can be omitted before an offset. The
+offset can be followed by one of the suffixes ``y``, ``mo``, ``w``,
+``d``, ``h``, or ``mi``, so that it is computed in years (defined as
+365 24-hour days, ignoring leap years), months (defined as 30 24-hour
+days), weeks, days, hours, or minutes, respectively. Without a suffix,
+the offset is computed in seconds.
+
+To unset a date, use ``none``, ``never``, or ``unset``.
+
+.. option:: -P date/offset
+
+ This option sets the date on which a key is to be published to the zone. After
+ that date, the key is included in the zone but is not used
+ to sign it. If not set, and if the :option:`-G` option has not been used, the
+ default is the current date.
+
+ .. program:: dnssec-keygen -P
+ .. option:: sync date/offset
+
+ This option sets the date on which CDS and CDNSKEY records that match this key
+ are to be published to the zone.
+
+.. program:: dnssec-keygen
+
+.. option:: -A date/offset
+
+ This option sets the date on which the key is to be activated. After that date,
+ the key is included in the zone and used to sign it. If not set,
+ and if the :option:`-G` option has not been used, the default is the current date. If set,
+ and :option:`-P` is not set, the publication date is set to the
+ activation date minus the prepublication interval.
+
+.. option:: -R date/offset
+
+ This option sets the date on which the key is to be revoked. After that date, the
+ key is flagged as revoked. It is included in the zone and
+ is used to sign it.
+
+.. option:: -I date/offset
+
+ This option sets the date on which the key is to be retired. After that date, the
+ key is still included in the zone, but it is not used to
+ sign it.
+
+
+.. option:: -D date/offset
+
+ This option sets the date on which the key is to be deleted. After that date, the
+ key is no longer included in the zone. (However, it may remain in the key
+ repository.)
+
+ .. program:: dnssec-keygen -D
+ .. option:: sync date/offset
+
+ This option sets the date on which the CDS and CDNSKEY records that match this
+ key are to be deleted.
+
+.. program:: dnssec-keygen
+
+.. option:: -i interval
+
+ This option sets the prepublication interval for a key. If set, then the
+ publication and activation dates must be separated by at least this
+ much time. If the activation date is specified but the publication
+ date is not, the publication date defaults to this much time
+ before the activation date; conversely, if the publication date is
+ specified but not the activation date, activation is set to
+ this much time after publication.
+
+ If the key is being created as an explicit successor to another key,
+ then the default prepublication interval is 30 days; otherwise it is
+ zero.
+
+ As with date offsets, if the argument is followed by one of the
+ suffixes ``y``, ``mo``, ``w``, ``d``, ``h``, or ``mi``, the interval is
+ measured in years, months, weeks, days, hours, or minutes,
+ respectively. Without a suffix, the interval is measured in seconds.
+
+Generated Keys
+~~~~~~~~~~~~~~
+
+When :program:`dnssec-keygen` completes successfully, it prints a string of the
+form ``Knnnn.+aaa+iiiii`` to the standard output. This is an
+identification string for the key it has generated.
+
+- ``nnnn`` is the key name.
+
+- ``aaa`` is the numeric representation of the algorithm.
+
+- ``iiiii`` is the key identifier (or footprint).
+
+:program:`dnssec-keygen` creates two files, with names based on the printed
+string. ``Knnnn.+aaa+iiiii.key`` contains the public key, and
+``Knnnn.+aaa+iiiii.private`` contains the private key.
+
+The ``.key`` file contains a DNSKEY or KEY record. When a zone is being
+signed by :iscman:`named` or :option:`dnssec-signzone -S`, DNSKEY records are
+included automatically. In other cases, the ``.key`` file can be
+inserted into a zone file manually or with an ``$INCLUDE`` statement.
+
+The ``.private`` file contains algorithm-specific fields. For obvious
+security reasons, this file does not have general read permission.
+
+Example
+~~~~~~~
+
+To generate an ECDSAP256SHA256 zone-signing key for the zone
+``example.com``, issue the command:
+
+``dnssec-keygen -a ECDSAP256SHA256 example.com``
+
+The command prints a string of the form:
+
+``Kexample.com.+013+26160``
+
+In this example, :program:`dnssec-keygen` creates the files
+``Kexample.com.+013+26160.key`` and ``Kexample.com.+013+26160.private``.
+
+To generate a matching key-signing key, issue the command:
+
+``dnssec-keygen -a ECDSAP256SHA256 -f KSK example.com``
+
+See Also
+~~~~~~~~
+
+:iscman:`dnssec-signzone(8) <dnssec-signzone>`, BIND 9 Administrator Reference Manual, :rfc:`2539`,
+:rfc:`2845`, :rfc:`4034`.
diff --git a/bin/dnssec/dnssec-revoke.c b/bin/dnssec/dnssec-revoke.c
new file mode 100644
index 0000000..93ee20c
--- /dev/null
+++ b/bin/dnssec/dnssec-revoke.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/keyvalues.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-revoke";
+
+static isc_mem_t *mctx = NULL;
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s [options] keyfile\n\n", program);
+ fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
+ fprintf(stderr, " -E engine: specify OpenSSL engine\n");
+ fprintf(stderr, " -f: force overwrite\n");
+ fprintf(stderr, " -h: help\n");
+ fprintf(stderr, " -K directory: use directory for key files\n");
+ fprintf(stderr, " -r: remove old keyfiles after "
+ "creating revoked version\n");
+ fprintf(stderr, " -v level: set level of verbosity\n");
+ fprintf(stderr, " -V: print version information\n");
+ fprintf(stderr, "Output:\n");
+ fprintf(stderr, " K<name>+<alg>+<new id>.key, "
+ "K<name>+<alg>+<new id>.private\n");
+
+ exit(-1);
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+ const char *engine = NULL;
+ char const *filename = NULL;
+ char *dir = NULL;
+ char newname[1024], oldname[1024];
+ char keystr[DST_KEY_FORMATSIZE];
+ char *endp;
+ int ch;
+ dst_key_t *key = NULL;
+ uint32_t flags;
+ isc_buffer_t buf;
+ bool force = false;
+ bool removefile = false;
+ bool id = false;
+
+ if (argc == 1) {
+ usage();
+ }
+
+ isc_mem_create(&mctx);
+
+ isc_commandline_errprint = false;
+
+ while ((ch = isc_commandline_parse(argc, argv, "E:fK:rRhv:V")) != -1) {
+ switch (ch) {
+ case 'E':
+ engine = isc_commandline_argument;
+ break;
+ case 'f':
+ force = true;
+ break;
+ case 'K':
+ /*
+ * We don't have to copy it here, but do it to
+ * simplify cleanup later
+ */
+ dir = isc_mem_strdup(mctx, isc_commandline_argument);
+ break;
+ case 'r':
+ removefile = true;
+ break;
+ case 'R':
+ id = true;
+ break;
+ case 'v':
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fatal("-v must be followed by a number");
+ }
+ break;
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ }
+ FALLTHROUGH;
+ case 'h':
+ /* Does not return. */
+ usage();
+
+ case 'V':
+ /* Does not return. */
+ version(program);
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (argc < isc_commandline_index + 1 ||
+ argv[isc_commandline_index] == NULL)
+ {
+ fatal("The key file name was not specified");
+ }
+ if (argc > isc_commandline_index + 1) {
+ fatal("Extraneous arguments");
+ }
+
+ if (dir != NULL) {
+ filename = argv[isc_commandline_index];
+ } else {
+ result = isc_file_splitpath(mctx, argv[isc_commandline_index],
+ &dir, &filename);
+ if (result != ISC_R_SUCCESS) {
+ fatal("cannot process filename %s: %s",
+ argv[isc_commandline_index],
+ isc_result_totext(result));
+ }
+ if (strcmp(dir, ".") == 0) {
+ isc_mem_free(mctx, dir);
+ dir = NULL;
+ }
+ }
+
+ result = dst_lib_init(mctx, engine);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Could not initialize dst: %s",
+ isc_result_totext(result));
+ }
+
+ result = dst_key_fromnamedfile(
+ filename, dir, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &key);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Invalid keyfile name %s: %s", filename,
+ isc_result_totext(result));
+ }
+
+ if (id) {
+ fprintf(stdout, "%u\n", dst_key_rid(key));
+ goto cleanup;
+ }
+ dst_key_format(key, keystr, sizeof(keystr));
+
+ if (verbose > 2) {
+ fprintf(stderr, "%s: %s\n", program, keystr);
+ }
+
+ if (force) {
+ set_keyversion(key);
+ } else {
+ check_keyversion(key, keystr);
+ }
+
+ flags = dst_key_flags(key);
+ if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
+ isc_stdtime_t now;
+
+ if ((flags & DNS_KEYFLAG_KSK) == 0) {
+ fprintf(stderr,
+ "%s: warning: Key is not flagged "
+ "as a KSK. Revoking a ZSK is "
+ "legal, but undefined.\n",
+ program);
+ }
+
+ isc_stdtime_get(&now);
+ dst_key_settime(key, DST_TIME_REVOKE, now);
+
+ dst_key_setflags(key, flags | DNS_KEYFLAG_REVOKE);
+
+ isc_buffer_init(&buf, newname, sizeof(newname));
+ dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);
+
+ if (access(newname, F_OK) == 0 && !force) {
+ fatal("Key file %s already exists; "
+ "use -f to force overwrite",
+ newname);
+ }
+
+ result = dst_key_tofile(key, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+ dir);
+ if (result != ISC_R_SUCCESS) {
+ dst_key_format(key, keystr, sizeof(keystr));
+ fatal("Failed to write key %s: %s", keystr,
+ isc_result_totext(result));
+ }
+
+ isc_buffer_clear(&buf);
+ dst_key_buildfilename(key, 0, dir, &buf);
+ printf("%s\n", newname);
+
+ /*
+ * Remove old key file, if told to (and if
+ * it isn't the same as the new file)
+ */
+ if (removefile) {
+ isc_buffer_init(&buf, oldname, sizeof(oldname));
+ dst_key_setflags(key, flags & ~DNS_KEYFLAG_REVOKE);
+ dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf);
+ if (strcmp(oldname, newname) == 0) {
+ goto cleanup;
+ }
+ (void)unlink(oldname);
+ isc_buffer_clear(&buf);
+ dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);
+ (void)unlink(oldname);
+ }
+ } else {
+ dst_key_format(key, keystr, sizeof(keystr));
+ fatal("Key %s is already revoked", keystr);
+ }
+
+cleanup:
+ dst_key_free(&key);
+ dst_lib_destroy();
+ if (verbose > 10) {
+ isc_mem_stats(mctx, stdout);
+ }
+ if (dir != NULL) {
+ isc_mem_free(mctx, dir);
+ }
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-revoke.rst b/bin/dnssec/dnssec-revoke.rst
new file mode 100644
index 0000000..052865f
--- /dev/null
+++ b/bin/dnssec/dnssec-revoke.rst
@@ -0,0 +1,78 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: dnssec-revoke
+.. program:: dnssec-revoke
+.. _man_dnssec-revoke:
+
+dnssec-revoke - set the REVOKED bit on a DNSSEC key
+---------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`dnssec-revoke` [**-hr**] [**-v** level] [**-V**] [**-K** directory] [**-E** engine] [**-f**] [**-R**] {keyfile}
+
+Description
+~~~~~~~~~~~
+
+:program:`dnssec-revoke` reads a DNSSEC key file, sets the REVOKED bit on the
+key as defined in :rfc:`5011`, and creates a new pair of key files
+containing the now-revoked key.
+
+Options
+~~~~~~~
+
+.. option:: -h
+
+ This option emits a usage message and exits.
+
+.. option:: -K directory
+
+ This option sets the directory in which the key files are to reside.
+
+.. option:: -r
+
+ This option indicates to remove the original keyset files after writing the new keyset files.
+
+.. option:: -v level
+
+ This option sets the debugging level.
+
+.. option:: -V
+
+ This option prints version information.
+
+.. option:: -E engine
+
+ This option specifies the cryptographic hardware to use, when applicable.
+
+ When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL
+ engine identifier that drives the cryptographic accelerator or
+ hardware service module (usually ``pkcs11``).
+
+.. option:: -f
+
+ This option indicates a forced overwrite and causes :program:`dnssec-revoke` to write the new key pair,
+ even if a file already exists matching the algorithm and key ID of
+ the revoked key.
+
+.. option:: -R
+
+ This option prints the key tag of the key with the REVOKE bit set, but does not
+ revoke the key.
+
+See Also
+~~~~~~~~
+
+:iscman:`dnssec-keygen(8) <dnssec-keygen>`, BIND 9 Administrator Reference Manual, :rfc:`5011`.
diff --git a/bin/dnssec/dnssec-settime.c b/bin/dnssec/dnssec-settime.c
new file mode 100644
index 0000000..100ff88
--- /dev/null
+++ b/bin/dnssec/dnssec-settime.c
@@ -0,0 +1,967 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-settime";
+
+static isc_mem_t *mctx = NULL;
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s [options] keyfile\n\n", program);
+ fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
+ fprintf(stderr, "General options:\n");
+ fprintf(stderr, " -E engine: specify OpenSSL engine\n");
+ fprintf(stderr, " -f: force update of old-style "
+ "keys\n");
+ fprintf(stderr, " -K directory: set key file location\n");
+ fprintf(stderr, " -L ttl: set default key TTL\n");
+ fprintf(stderr, " -v level: set level of verbosity\n");
+ fprintf(stderr, " -V: print version information\n");
+ fprintf(stderr, " -h: help\n");
+ fprintf(stderr, "Timing options:\n");
+ fprintf(stderr, " -P date/[+-]offset/none: set/unset key "
+ "publication date\n");
+ fprintf(stderr, " -P ds date/[+-]offset/none: set/unset "
+ "DS publication date\n");
+ fprintf(stderr, " -P sync date/[+-]offset/none: set/unset "
+ "CDS and CDNSKEY publication date\n");
+ fprintf(stderr, " -A date/[+-]offset/none: set/unset key "
+ "activation date\n");
+ fprintf(stderr, " -R date/[+-]offset/none: set/unset key "
+ "revocation date\n");
+ fprintf(stderr, " -I date/[+-]offset/none: set/unset key "
+ "inactivation date\n");
+ fprintf(stderr, " -D date/[+-]offset/none: set/unset key "
+ "deletion date\n");
+ fprintf(stderr, " -D ds date/[+-]offset/none: set/unset "
+ "DS deletion date\n");
+ fprintf(stderr, " -D sync date/[+-]offset/none: set/unset "
+ "CDS and CDNSKEY deletion date\n");
+ fprintf(stderr, " -S <key>: generate a successor to an existing "
+ "key\n");
+ fprintf(stderr, " -i <interval>: prepublication interval for "
+ "successor key "
+ "(default: 30 days)\n");
+ fprintf(stderr, "Key state options:\n");
+ fprintf(stderr, " -s: update key state file (default no)\n");
+ fprintf(stderr, " -g state: set the goal state for this key\n");
+ fprintf(stderr, " -d state date/[+-]offset: set the DS state\n");
+ fprintf(stderr, " -k state date/[+-]offset: set the DNSKEY state\n");
+ fprintf(stderr, " -r state date/[+-]offset: set the RRSIG (KSK) "
+ "state\n");
+ fprintf(stderr, " -z state date/[+-]offset: set the RRSIG (ZSK) "
+ "state\n");
+ fprintf(stderr, "Printing options:\n");
+ fprintf(stderr, " -p C/P/Psync/A/R/I/D/Dsync/all: print a "
+ "particular time value or values\n");
+ fprintf(stderr, " -u: print times in unix epoch "
+ "format\n");
+ fprintf(stderr, "Output:\n");
+ fprintf(stderr, " K<name>+<alg>+<new id>.key, "
+ "K<name>+<alg>+<new id>.private\n");
+
+ exit(-1);
+}
+
+static void
+printtime(dst_key_t *key, int type, const char *tag, bool epoch, FILE *stream) {
+ isc_result_t result;
+ isc_stdtime_t when;
+
+ if (tag != NULL) {
+ fprintf(stream, "%s: ", tag);
+ }
+
+ result = dst_key_gettime(key, type, &when);
+ if (result == ISC_R_NOTFOUND) {
+ fprintf(stream, "UNSET\n");
+ } else if (epoch) {
+ fprintf(stream, "%d\n", (int)when);
+ } else {
+ time_t now = when;
+ struct tm t, *tm = localtime_r(&now, &t);
+ unsigned int flen;
+ char timebuf[80];
+
+ if (tm == NULL) {
+ fprintf(stream, "INVALID\n");
+ return;
+ }
+
+ flen = strftime(timebuf, sizeof(timebuf),
+ "%a %b %e %H:%M:%S %Y", tm);
+ INSIST(flen > 0U && flen < sizeof(timebuf));
+ fprintf(stream, "%s\n", timebuf);
+ }
+}
+
+static void
+writekey(dst_key_t *key, const char *directory, bool write_state) {
+ char newname[1024];
+ char keystr[DST_KEY_FORMATSIZE];
+ isc_buffer_t buf;
+ isc_result_t result;
+ int options = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE;
+
+ if (write_state) {
+ options |= DST_TYPE_STATE;
+ }
+
+ isc_buffer_init(&buf, newname, sizeof(newname));
+ result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &buf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Failed to build public key filename: %s",
+ isc_result_totext(result));
+ }
+
+ result = dst_key_tofile(key, options, directory);
+ if (result != ISC_R_SUCCESS) {
+ dst_key_format(key, keystr, sizeof(keystr));
+ fatal("Failed to write key %s: %s", keystr,
+ isc_result_totext(result));
+ }
+ printf("%s\n", newname);
+
+ isc_buffer_clear(&buf);
+ result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &buf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Failed to build private key filename: %s",
+ isc_result_totext(result));
+ }
+ printf("%s\n", newname);
+
+ if (write_state) {
+ isc_buffer_clear(&buf);
+ result = dst_key_buildfilename(key, DST_TYPE_STATE, directory,
+ &buf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Failed to build key state filename: %s",
+ isc_result_totext(result));
+ }
+ printf("%s\n", newname);
+ }
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+ const char *engine = NULL;
+ const char *filename = NULL;
+ char *directory = NULL;
+ char keystr[DST_KEY_FORMATSIZE];
+ char *endp, *p;
+ int ch;
+ const char *predecessor = NULL;
+ dst_key_t *prevkey = NULL;
+ dst_key_t *key = NULL;
+ dns_name_t *name = NULL;
+ dns_secalg_t alg = 0;
+ unsigned int size = 0;
+ uint16_t flags = 0;
+ int prepub = -1;
+ int options;
+ dns_ttl_t ttl = 0;
+ isc_stdtime_t now;
+ isc_stdtime_t dstime = 0, dnskeytime = 0;
+ isc_stdtime_t krrsigtime = 0, zrrsigtime = 0;
+ isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0;
+ isc_stdtime_t prevact = 0, previnact = 0, prevdel = 0;
+ dst_key_state_t goal = DST_KEY_STATE_NA;
+ dst_key_state_t ds = DST_KEY_STATE_NA;
+ dst_key_state_t dnskey = DST_KEY_STATE_NA;
+ dst_key_state_t krrsig = DST_KEY_STATE_NA;
+ dst_key_state_t zrrsig = DST_KEY_STATE_NA;
+ bool setgoal = false, setds = false, setdnskey = false;
+ bool setkrrsig = false, setzrrsig = false;
+ bool setdstime = false, setdnskeytime = false;
+ bool setkrrsigtime = false, setzrrsigtime = false;
+ bool setpub = false, setact = false;
+ bool setrev = false, setinact = false;
+ bool setdel = false, setttl = false;
+ bool unsetpub = false, unsetact = false;
+ bool unsetrev = false, unsetinact = false;
+ bool unsetdel = false;
+ bool printcreate = false, printpub = false;
+ bool printact = false, printrev = false;
+ bool printinact = false, printdel = false;
+ bool force = false;
+ bool epoch = false;
+ bool changed = false;
+ bool write_state = false;
+ isc_log_t *log = NULL;
+ isc_stdtime_t syncadd = 0, syncdel = 0;
+ bool unsetsyncadd = false, setsyncadd = false;
+ bool unsetsyncdel = false, setsyncdel = false;
+ bool printsyncadd = false, printsyncdel = false;
+ isc_stdtime_t dsadd = 0, dsdel = 0;
+ bool unsetdsadd = false, setdsadd = false;
+ bool unsetdsdel = false, setdsdel = false;
+ bool printdsadd = false, printdsdel = false;
+
+ options = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE;
+
+ if (argc == 1) {
+ usage();
+ }
+
+ isc_mem_create(&mctx);
+
+ setup_logging(mctx, &log);
+
+ isc_commandline_errprint = false;
+
+ isc_stdtime_get(&now);
+
+#define CMDLINE_FLAGS "A:D:d:E:fg:hI:i:K:k:L:P:p:R:r:S:suv:Vz:"
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case 'A':
+ if (setact || unsetact) {
+ fatal("-A specified more than once");
+ }
+
+ changed = true;
+ act = strtotime(isc_commandline_argument, now, now,
+ &setact);
+ unsetact = !setact;
+ break;
+ case 'D':
+ /* -Dsync ? */
+ if (isoptarg("sync", argv, usage)) {
+ if (unsetsyncdel || setsyncdel) {
+ fatal("-D sync specified more than "
+ "once");
+ }
+
+ changed = true;
+ syncdel = strtotime(isc_commandline_argument,
+ now, now, &setsyncdel);
+ unsetsyncdel = !setsyncdel;
+ break;
+ }
+ /* -Dds ? */
+ if (isoptarg("ds", argv, usage)) {
+ if (unsetdsdel || setdsdel) {
+ fatal("-D ds specified more than once");
+ }
+
+ changed = true;
+ dsdel = strtotime(isc_commandline_argument, now,
+ now, &setdsdel);
+ unsetdsdel = !setdsdel;
+ break;
+ }
+ /* -Ddnskey ? */
+ (void)isoptarg("dnskey", argv, usage);
+ if (setdel || unsetdel) {
+ fatal("-D specified more than once");
+ }
+
+ changed = true;
+ del = strtotime(isc_commandline_argument, now, now,
+ &setdel);
+ unsetdel = !setdel;
+ break;
+ case 'd':
+ if (setds) {
+ fatal("-d specified more than once");
+ }
+
+ ds = strtokeystate(isc_commandline_argument);
+ setds = true;
+ /* time */
+ (void)isoptarg(isc_commandline_argument, argv, usage);
+ dstime = strtotime(isc_commandline_argument, now, now,
+ &setdstime);
+ break;
+ case 'E':
+ engine = isc_commandline_argument;
+ break;
+ case 'f':
+ force = true;
+ break;
+ case 'g':
+ if (setgoal) {
+ fatal("-g specified more than once");
+ }
+
+ goal = strtokeystate(isc_commandline_argument);
+ if (goal != DST_KEY_STATE_NA &&
+ goal != DST_KEY_STATE_HIDDEN &&
+ goal != DST_KEY_STATE_OMNIPRESENT)
+ {
+ fatal("-g must be either none, hidden, or "
+ "omnipresent");
+ }
+ setgoal = true;
+ break;
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ }
+ FALLTHROUGH;
+ case 'h':
+ /* Does not return. */
+ usage();
+ case 'I':
+ if (setinact || unsetinact) {
+ fatal("-I specified more than once");
+ }
+
+ changed = true;
+ inact = strtotime(isc_commandline_argument, now, now,
+ &setinact);
+ unsetinact = !setinact;
+ break;
+ case 'i':
+ prepub = strtottl(isc_commandline_argument);
+ break;
+ case 'K':
+ /*
+ * We don't have to copy it here, but do it to
+ * simplify cleanup later
+ */
+ directory = isc_mem_strdup(mctx,
+ isc_commandline_argument);
+ break;
+ case 'k':
+ if (setdnskey) {
+ fatal("-k specified more than once");
+ }
+
+ dnskey = strtokeystate(isc_commandline_argument);
+ setdnskey = true;
+ /* time */
+ (void)isoptarg(isc_commandline_argument, argv, usage);
+ dnskeytime = strtotime(isc_commandline_argument, now,
+ now, &setdnskeytime);
+ break;
+ case 'L':
+ ttl = strtottl(isc_commandline_argument);
+ setttl = true;
+ break;
+ case 'P':
+ /* -Psync ? */
+ if (isoptarg("sync", argv, usage)) {
+ if (unsetsyncadd || setsyncadd) {
+ fatal("-P sync specified more than "
+ "once");
+ }
+
+ changed = true;
+ syncadd = strtotime(isc_commandline_argument,
+ now, now, &setsyncadd);
+ unsetsyncadd = !setsyncadd;
+ break;
+ }
+ /* -Pds ? */
+ if (isoptarg("ds", argv, usage)) {
+ if (unsetdsadd || setdsadd) {
+ fatal("-P ds specified more than once");
+ }
+
+ changed = true;
+ dsadd = strtotime(isc_commandline_argument, now,
+ now, &setdsadd);
+ unsetdsadd = !setdsadd;
+ break;
+ }
+ /* -Pdnskey ? */
+ (void)isoptarg("dnskey", argv, usage);
+ if (setpub || unsetpub) {
+ fatal("-P specified more than once");
+ }
+
+ changed = true;
+ pub = strtotime(isc_commandline_argument, now, now,
+ &setpub);
+ unsetpub = !setpub;
+ break;
+ case 'p':
+ p = isc_commandline_argument;
+ if (!strcasecmp(p, "all")) {
+ printcreate = true;
+ printpub = true;
+ printact = true;
+ printrev = true;
+ printinact = true;
+ printdel = true;
+ printsyncadd = true;
+ printsyncdel = true;
+ printdsadd = true;
+ printdsdel = true;
+ break;
+ }
+
+ do {
+ switch (*p++) {
+ case 'A':
+ printact = true;
+ break;
+ case 'C':
+ printcreate = true;
+ break;
+ case 'D':
+ if (!strncmp(p, "sync", 4)) {
+ p += 4;
+ printsyncdel = true;
+ break;
+ }
+ if (!strncmp(p, "ds", 2)) {
+ p += 2;
+ printdsdel = true;
+ break;
+ }
+ printdel = true;
+ break;
+ case 'I':
+ printinact = true;
+ break;
+ case 'P':
+ if (!strncmp(p, "sync", 4)) {
+ p += 4;
+ printsyncadd = true;
+ break;
+ }
+ if (!strncmp(p, "ds", 2)) {
+ p += 2;
+ printdsadd = true;
+ break;
+ }
+ printpub = true;
+ break;
+ case 'R':
+ printrev = true;
+ break;
+ case ' ':
+ break;
+ default:
+ usage();
+ break;
+ }
+ } while (*p != '\0');
+ break;
+ case 'R':
+ if (setrev || unsetrev) {
+ fatal("-R specified more than once");
+ }
+
+ changed = true;
+ rev = strtotime(isc_commandline_argument, now, now,
+ &setrev);
+ unsetrev = !setrev;
+ break;
+ case 'r':
+ if (setkrrsig) {
+ fatal("-r specified more than once");
+ }
+
+ krrsig = strtokeystate(isc_commandline_argument);
+ setkrrsig = true;
+ /* time */
+ (void)isoptarg(isc_commandline_argument, argv, usage);
+ krrsigtime = strtotime(isc_commandline_argument, now,
+ now, &setkrrsigtime);
+ break;
+ case 'S':
+ predecessor = isc_commandline_argument;
+ break;
+ case 's':
+ write_state = true;
+ break;
+ case 'u':
+ epoch = true;
+ break;
+ case 'V':
+ /* Does not return. */
+ version(program);
+ case 'v':
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fatal("-v must be followed by a number");
+ }
+ break;
+ case 'z':
+ if (setzrrsig) {
+ fatal("-z specified more than once");
+ }
+
+ zrrsig = strtokeystate(isc_commandline_argument);
+ setzrrsig = true;
+ (void)isoptarg(isc_commandline_argument, argv, usage);
+ zrrsigtime = strtotime(isc_commandline_argument, now,
+ now, &setzrrsigtime);
+ break;
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (argc < isc_commandline_index + 1 ||
+ argv[isc_commandline_index] == NULL)
+ {
+ fatal("The key file name was not specified");
+ }
+ if (argc > isc_commandline_index + 1) {
+ fatal("Extraneous arguments");
+ }
+
+ if ((setgoal || setds || setdnskey || setkrrsig || setzrrsig) &&
+ !write_state)
+ {
+ fatal("Options -g, -d, -k, -r and -z require -s to be set");
+ }
+
+ result = dst_lib_init(mctx, engine);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Could not initialize dst: %s",
+ isc_result_totext(result));
+ }
+
+ if (predecessor != NULL) {
+ int major, minor;
+
+ if (prepub == -1) {
+ prepub = (30 * 86400);
+ }
+
+ if (setpub || unsetpub) {
+ fatal("-S and -P cannot be used together");
+ }
+ if (setact || unsetact) {
+ fatal("-S and -A cannot be used together");
+ }
+
+ result = dst_key_fromnamedfile(predecessor, directory, options,
+ mctx, &prevkey);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Invalid keyfile %s: %s", filename,
+ isc_result_totext(result));
+ }
+ if (!dst_key_isprivate(prevkey) && !dst_key_isexternal(prevkey))
+ {
+ fatal("%s is not a private key", filename);
+ }
+
+ name = dst_key_name(prevkey);
+ alg = dst_key_alg(prevkey);
+ size = dst_key_size(prevkey);
+ flags = dst_key_flags(prevkey);
+
+ dst_key_format(prevkey, keystr, sizeof(keystr));
+ dst_key_getprivateformat(prevkey, &major, &minor);
+ if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) {
+ fatal("Predecessor has incompatible format "
+ "version %d.%d\n\t",
+ major, minor);
+ }
+
+ result = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &prevact);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Predecessor has no activation date. "
+ "You must set one before\n\t"
+ "generating a successor.");
+ }
+
+ result = dst_key_gettime(prevkey, DST_TIME_INACTIVE,
+ &previnact);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Predecessor has no inactivation date. "
+ "You must set one before\n\t"
+ "generating a successor.");
+ }
+
+ pub = previnact - prepub;
+ act = previnact;
+
+ if ((previnact - prepub) < now && prepub != 0) {
+ fatal("Time until predecessor inactivation is\n\t"
+ "shorter than the prepublication interval. "
+ "Either change\n\t"
+ "predecessor inactivation date, or use the -i "
+ "option to set\n\t"
+ "a shorter prepublication interval.");
+ }
+
+ result = dst_key_gettime(prevkey, DST_TIME_DELETE, &prevdel);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "%s: warning: Predecessor has no "
+ "removal date;\n\t"
+ "it will remain in the zone "
+ "indefinitely after rollover.\n",
+ program);
+ } else if (prevdel < previnact) {
+ fprintf(stderr,
+ "%s: warning: Predecessor is "
+ "scheduled to be deleted\n\t"
+ "before it is scheduled to be "
+ "inactive.\n",
+ program);
+ }
+
+ changed = setpub = setact = true;
+ } else {
+ if (prepub < 0) {
+ prepub = 0;
+ }
+
+ if (prepub > 0) {
+ if (setpub && setact && (act - prepub) < pub) {
+ fatal("Activation and publication dates "
+ "are closer together than the\n\t"
+ "prepublication interval.");
+ }
+
+ if (setpub && !setact) {
+ setact = true;
+ act = pub + prepub;
+ } else if (setact && !setpub) {
+ setpub = true;
+ pub = act - prepub;
+ }
+
+ if ((act - prepub) < now) {
+ fatal("Time until activation is shorter "
+ "than the\n\tprepublication interval.");
+ }
+ }
+ }
+
+ if (directory != NULL) {
+ filename = argv[isc_commandline_index];
+ } else {
+ result = isc_file_splitpath(mctx, argv[isc_commandline_index],
+ &directory, &filename);
+ if (result != ISC_R_SUCCESS) {
+ fatal("cannot process filename %s: %s",
+ argv[isc_commandline_index],
+ isc_result_totext(result));
+ }
+ }
+
+ result = dst_key_fromnamedfile(filename, directory, options, mctx,
+ &key);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Invalid keyfile %s: %s", filename,
+ isc_result_totext(result));
+ }
+
+ if (!dst_key_isprivate(key) && !dst_key_isexternal(key)) {
+ fatal("%s is not a private key", filename);
+ }
+
+ dst_key_format(key, keystr, sizeof(keystr));
+
+ if (predecessor != NULL) {
+ if (!dns_name_equal(name, dst_key_name(key))) {
+ fatal("Key name mismatch");
+ }
+ if (alg != dst_key_alg(key)) {
+ fatal("Key algorithm mismatch");
+ }
+ if (size != dst_key_size(key)) {
+ fatal("Key size mismatch");
+ }
+ if (flags != dst_key_flags(key)) {
+ fatal("Key flags mismatch");
+ }
+ }
+
+ prevdel = previnact = 0;
+ if ((setdel && setinact && del < inact) ||
+ (dst_key_gettime(key, DST_TIME_INACTIVE, &previnact) ==
+ ISC_R_SUCCESS &&
+ setdel && !setinact && !unsetinact && del < previnact) ||
+ (dst_key_gettime(key, DST_TIME_DELETE, &prevdel) == ISC_R_SUCCESS &&
+ setinact && !setdel && !unsetdel && prevdel < inact) ||
+ (!setdel && !unsetdel && !setinact && !unsetinact && prevdel != 0 &&
+ prevdel < previnact))
+ {
+ fprintf(stderr,
+ "%s: warning: Key is scheduled to "
+ "be deleted before it is\n\t"
+ "scheduled to be inactive.\n",
+ program);
+ }
+
+ if (force) {
+ set_keyversion(key);
+ } else {
+ check_keyversion(key, keystr);
+ }
+
+ if (verbose > 2) {
+ fprintf(stderr, "%s: %s\n", program, keystr);
+ }
+
+ /*
+ * Set time values.
+ */
+ if (setpub) {
+ dst_key_settime(key, DST_TIME_PUBLISH, pub);
+ } else if (unsetpub) {
+ dst_key_unsettime(key, DST_TIME_PUBLISH);
+ }
+
+ if (setact) {
+ dst_key_settime(key, DST_TIME_ACTIVATE, act);
+ } else if (unsetact) {
+ dst_key_unsettime(key, DST_TIME_ACTIVATE);
+ }
+
+ if (setrev) {
+ if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) {
+ fprintf(stderr,
+ "%s: warning: Key %s is already "
+ "revoked; changing the revocation date "
+ "will not affect this.\n",
+ program, keystr);
+ }
+ if ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0) {
+ fprintf(stderr,
+ "%s: warning: Key %s is not flagged as "
+ "a KSK, but -R was used. Revoking a "
+ "ZSK is legal, but undefined.\n",
+ program, keystr);
+ }
+ dst_key_settime(key, DST_TIME_REVOKE, rev);
+ } else if (unsetrev) {
+ if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) {
+ fprintf(stderr,
+ "%s: warning: Key %s is already "
+ "revoked; removing the revocation date "
+ "will not affect this.\n",
+ program, keystr);
+ }
+ dst_key_unsettime(key, DST_TIME_REVOKE);
+ }
+
+ if (setinact) {
+ dst_key_settime(key, DST_TIME_INACTIVE, inact);
+ } else if (unsetinact) {
+ dst_key_unsettime(key, DST_TIME_INACTIVE);
+ }
+
+ if (setdel) {
+ dst_key_settime(key, DST_TIME_DELETE, del);
+ } else if (unsetdel) {
+ dst_key_unsettime(key, DST_TIME_DELETE);
+ }
+
+ if (setsyncadd) {
+ dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd);
+ } else if (unsetsyncadd) {
+ dst_key_unsettime(key, DST_TIME_SYNCPUBLISH);
+ }
+
+ if (setsyncdel) {
+ dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel);
+ } else if (unsetsyncdel) {
+ dst_key_unsettime(key, DST_TIME_SYNCDELETE);
+ }
+
+ if (setdsadd) {
+ dst_key_settime(key, DST_TIME_DSPUBLISH, dsadd);
+ } else if (unsetdsadd) {
+ dst_key_unsettime(key, DST_TIME_DSPUBLISH);
+ }
+
+ if (setdsdel) {
+ dst_key_settime(key, DST_TIME_DSDELETE, dsdel);
+ } else if (unsetdsdel) {
+ dst_key_unsettime(key, DST_TIME_DSDELETE);
+ }
+
+ if (setttl) {
+ dst_key_setttl(key, ttl);
+ }
+
+ if (predecessor != NULL && prevkey != NULL) {
+ dst_key_setnum(prevkey, DST_NUM_SUCCESSOR, dst_key_id(key));
+ dst_key_setnum(key, DST_NUM_PREDECESSOR, dst_key_id(prevkey));
+ }
+
+ /*
+ * No metadata changes were made but we're forcing an upgrade
+ * to the new format anyway: use "-P now -A now" as the default
+ */
+ if (force && !changed) {
+ dst_key_settime(key, DST_TIME_PUBLISH, now);
+ dst_key_settime(key, DST_TIME_ACTIVATE, now);
+ changed = true;
+ }
+
+ /*
+ * Make sure the key state goals are written.
+ */
+ if (write_state) {
+ if (setgoal) {
+ if (goal == DST_KEY_STATE_NA) {
+ dst_key_unsetstate(key, DST_KEY_GOAL);
+ } else {
+ dst_key_setstate(key, DST_KEY_GOAL, goal);
+ }
+ changed = true;
+ }
+ if (setds) {
+ if (ds == DST_KEY_STATE_NA) {
+ dst_key_unsetstate(key, DST_KEY_DS);
+ dst_key_unsettime(key, DST_TIME_DS);
+ } else {
+ dst_key_setstate(key, DST_KEY_DS, ds);
+ dst_key_settime(key, DST_TIME_DS, dstime);
+ }
+ changed = true;
+ }
+ if (setdnskey) {
+ if (dnskey == DST_KEY_STATE_NA) {
+ dst_key_unsetstate(key, DST_KEY_DNSKEY);
+ dst_key_unsettime(key, DST_TIME_DNSKEY);
+ } else {
+ dst_key_setstate(key, DST_KEY_DNSKEY, dnskey);
+ dst_key_settime(key, DST_TIME_DNSKEY,
+ dnskeytime);
+ }
+ changed = true;
+ }
+ if (setkrrsig) {
+ if (krrsig == DST_KEY_STATE_NA) {
+ dst_key_unsetstate(key, DST_KEY_KRRSIG);
+ dst_key_unsettime(key, DST_TIME_KRRSIG);
+ } else {
+ dst_key_setstate(key, DST_KEY_KRRSIG, krrsig);
+ dst_key_settime(key, DST_TIME_KRRSIG,
+ krrsigtime);
+ }
+ changed = true;
+ }
+ if (setzrrsig) {
+ if (zrrsig == DST_KEY_STATE_NA) {
+ dst_key_unsetstate(key, DST_KEY_ZRRSIG);
+ dst_key_unsettime(key, DST_TIME_ZRRSIG);
+ } else {
+ dst_key_setstate(key, DST_KEY_ZRRSIG, zrrsig);
+ dst_key_settime(key, DST_TIME_ZRRSIG,
+ zrrsigtime);
+ }
+ changed = true;
+ }
+ }
+
+ if (!changed && setttl) {
+ changed = true;
+ }
+
+ /*
+ * Print out time values, if -p was used.
+ */
+ if (printcreate) {
+ printtime(key, DST_TIME_CREATED, "Created", epoch, stdout);
+ }
+
+ if (printpub) {
+ printtime(key, DST_TIME_PUBLISH, "Publish", epoch, stdout);
+ }
+
+ if (printact) {
+ printtime(key, DST_TIME_ACTIVATE, "Activate", epoch, stdout);
+ }
+
+ if (printrev) {
+ printtime(key, DST_TIME_REVOKE, "Revoke", epoch, stdout);
+ }
+
+ if (printinact) {
+ printtime(key, DST_TIME_INACTIVE, "Inactive", epoch, stdout);
+ }
+
+ if (printdel) {
+ printtime(key, DST_TIME_DELETE, "Delete", epoch, stdout);
+ }
+
+ if (printsyncadd) {
+ printtime(key, DST_TIME_SYNCPUBLISH, "SYNC Publish", epoch,
+ stdout);
+ }
+
+ if (printsyncdel) {
+ printtime(key, DST_TIME_SYNCDELETE, "SYNC Delete", epoch,
+ stdout);
+ }
+
+ if (printdsadd) {
+ printtime(key, DST_TIME_DSPUBLISH, "DS Publish", epoch, stdout);
+ }
+
+ if (printdsdel) {
+ printtime(key, DST_TIME_DSDELETE, "DS Delete", epoch, stdout);
+ }
+
+ if (changed) {
+ writekey(key, directory, write_state);
+ if (predecessor != NULL && prevkey != NULL) {
+ writekey(prevkey, directory, write_state);
+ }
+ }
+
+ if (prevkey != NULL) {
+ dst_key_free(&prevkey);
+ }
+ dst_key_free(&key);
+ dst_lib_destroy();
+ if (verbose > 10) {
+ isc_mem_stats(mctx, stdout);
+ }
+ cleanup_logging(&log);
+ isc_mem_free(mctx, directory);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-settime.rst b/bin/dnssec/dnssec-settime.rst
new file mode 100644
index 0000000..5cb4ea8
--- /dev/null
+++ b/bin/dnssec/dnssec-settime.rst
@@ -0,0 +1,271 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: dnssec-settime
+.. program:: dnssec-settime
+.. _man_dnssec-settime:
+
+dnssec-settime: set the key timing metadata for a DNSSEC key
+------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`dnssec-settime` [**-f**] [**-K** directory] [**-L** ttl] [**-P** date/offset] [**-P** ds date/offset] [**-P** sync date/offset] [**-A** date/offset] [**-R** date/offset] [**-I** date/offset] [**-D** date/offset] [**-D** ds date/offset] [**-D** sync date/offset] [**-S** key] [**-i** interval] [**-h**] [**-V**] [**-v** level] [**-E** engine] {keyfile} [**-s**] [**-g** state] [**-d** state date/offset] [**-k** state date/offset] [**-r** state date/offset] [**-z** state date/offset]
+
+Description
+~~~~~~~~~~~
+
+:program:`dnssec-settime` reads a DNSSEC private key file and sets the key
+timing metadata as specified by the :option:`-P`, :option:`-A`, :option:`-R`,
+:option:`-I`, and :option:`-D` options. The metadata can then be used by
+:iscman:`dnssec-signzone` or other signing software to determine when a key is
+to be published, whether it should be used for signing a zone, etc.
+
+If none of these options is set on the command line,
+:program:`dnssec-settime` simply prints the key timing metadata already stored
+in the key.
+
+When key metadata fields are changed, both files of a key pair
+(``Knnnn.+aaa+iiiii.key`` and ``Knnnn.+aaa+iiiii.private``) are
+regenerated.
+
+Metadata fields are stored in the private file. A
+human-readable description of the metadata is also placed in comments in
+the key file. The private file's permissions are always set to be
+inaccessible to anyone other than the owner (mode 0600).
+
+When working with state files, it is possible to update the timing metadata in
+those files as well with :option:`-s`. With this option, it is also possible
+to update key states with :option:`-d` (DS), :option:`-k` (DNSKEY), :option:`-r`
+(RRSIG of KSK), or :option:`-z` (RRSIG of ZSK). Allowed states are HIDDEN,
+RUMOURED, OMNIPRESENT, and UNRETENTIVE.
+
+The goal state of the key can also be set with :option:`-g`. This should be either
+HIDDEN or OMNIPRESENT, representing whether the key should be removed from the
+zone or published.
+
+It is NOT RECOMMENDED to manipulate state files manually, except for testing
+purposes.
+
+Options
+~~~~~~~
+
+.. option:: -f
+
+ This option forces an update of an old-format key with no metadata fields. Without
+ this option, :program:`dnssec-settime` fails when attempting to update a
+ legacy key. With this option, the key is recreated in the new
+ format, but with the original key data retained. The key's creation
+ date is set to the present time. If no other values are
+ specified, then the key's publication and activation dates are also
+ set to the present time.
+
+.. option:: -K directory
+
+ This option sets the directory in which the key files are to reside.
+
+.. option:: -L ttl
+
+ This option sets the default TTL to use for this key when it is converted into a
+ DNSKEY RR. This is the TTL used when the key is imported into a zone,
+ unless there was already a DNSKEY RRset in
+ place, in which case the existing TTL takes precedence. If this
+ value is not set and there is no existing DNSKEY RRset, the TTL
+ defaults to the SOA TTL. Setting the default TTL to ``0`` or ``none``
+ removes it from the key.
+
+.. option:: -h
+
+ This option emits a usage message and exits.
+
+.. option:: -V
+
+ This option prints version information.
+
+.. option:: -v level
+
+ This option sets the debugging level.
+
+.. option:: -E engine
+
+ This option specifies the cryptographic hardware to use, when applicable.
+
+ When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL
+ engine identifier that drives the cryptographic accelerator or
+ hardware service module (usually ``pkcs11``).
+
+Timing Options
+~~~~~~~~~~~~~~
+
+Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS
+(which is the format used inside key files),
+or 'Day Mon DD HH:MM:SS YYYY' (as printed by ``dnssec-settime -p``),
+or UNIX epoch time (as printed by ``dnssec-settime -up``),
+or the literal ``now``.
+
+The argument can be followed by ``+`` or ``-`` and an offset from the
+given time. The literal ``now`` can be omitted before an offset. The
+offset can be followed by one of the suffixes ``y``, ``mo``, ``w``,
+``d``, ``h``, or ``mi``, so that it is computed in years (defined as
+365 24-hour days, ignoring leap years), months (defined as 30 24-hour
+days), weeks, days, hours, or minutes, respectively. Without a suffix,
+the offset is computed in seconds.
+
+To unset a date, use ``none``, ``never``, or ``unset``.
+
+All these formats are case-insensitive.
+
+.. option:: -P date/offset
+
+ This option sets the date on which a key is to be published to the zone. After
+ that date, the key is included in the zone but is not used
+ to sign it.
+
+ .. program:: dnssec-settime -P
+ .. option:: ds date/offset
+
+ This option sets the date on which DS records that match this key have been
+ seen in the parent zone.
+
+ .. option:: sync date/offset
+
+ This option sets the date on which CDS and CDNSKEY records that match this key
+ are to be published to the zone.
+
+.. program:: dnssec-settime
+
+.. option:: -A date/offset
+
+ This option sets the date on which the key is to be activated. After that date,
+ the key is included in the zone and used to sign it.
+
+.. option:: -R date/offset
+
+ This option sets the date on which the key is to be revoked. After that date, the
+ key is flagged as revoked. It is included in the zone and
+ is used to sign it.
+
+.. option:: -I date/offset
+
+ This option sets the date on which the key is to be retired. After that date, the
+ key is still included in the zone, but it is not used to
+ sign it.
+
+.. option:: -D date/offset
+
+ This option sets the date on which the key is to be deleted. After that date, the
+ key is no longer included in the zone. (However, it may remain in the key
+ repository.)
+
+ .. program:: dnssec-settime -D
+ .. option:: ds date/offset
+
+ This option sets the date on which the DS records that match this key have
+ been seen removed from the parent zone.
+
+ .. option:: sync date/offset
+
+ This option sets the date on which the CDS and CDNSKEY records that match this
+ key are to be deleted.
+
+.. program:: dnssec-settime
+
+.. option:: -S predecessor key
+
+ This option selects a key for which the key being modified is an explicit
+ successor. The name, algorithm, size, and type of the predecessor key
+ must exactly match those of the key being modified. The activation
+ date of the successor key is set to the inactivation date of the
+ predecessor. The publication date is set to the activation date
+ minus the prepublication interval, which defaults to 30 days.
+
+.. option:: -i interval
+
+ This option sets the prepublication interval for a key. If set, then the
+ publication and activation dates must be separated by at least this
+ much time. If the activation date is specified but the publication
+ date is not, the publication date defaults to this much time
+ before the activation date; conversely, if the publication date is
+ specified but not the activation date, activation is set to
+ this much time after publication.
+
+ If the key is being created as an explicit successor to another key,
+ then the default prepublication interval is 30 days; otherwise it is
+ zero.
+
+ As with date offsets, if the argument is followed by one of the
+ suffixes ``y``, ``mo``, ``w``, ``d``, ``h``, or ``mi``, the interval is
+ measured in years, months, weeks, days, hours, or minutes,
+ respectively. Without a suffix, the interval is measured in seconds.
+
+Key State Options
+~~~~~~~~~~~~~~~~~
+
+To test dnssec-policy it may be necessary to construct keys with artificial
+state information; these options are used by the testing framework for that
+purpose, but should never be used in production.
+
+Known key states are HIDDEN, RUMOURED, OMNIPRESENT, and UNRETENTIVE.
+
+.. option:: -s
+
+ This option indicates that when setting key timing data, the state file should also be updated.
+
+.. option:: -g state
+
+ This option sets the goal state for this key. Must be HIDDEN or OMNIPRESENT.
+
+.. option:: -d state date/offset
+
+ This option sets the DS state for this key as of the specified date, offset from the current date.
+
+.. option:: -k state date/offset
+
+ This option sets the DNSKEY state for this key as of the specified date, offset from the current date.
+
+.. option:: -r state date/offset
+
+ This option sets the RRSIG (KSK) state for this key as of the specified date, offset from the current date.
+
+.. option:: -z state date/offset
+
+ This option sets the RRSIG (ZSK) state for this key as of the specified date, offset from the current date.
+
+Printing Options
+~~~~~~~~~~~~~~~~
+
+:program:`dnssec-settime` can also be used to print the timing metadata
+associated with a key.
+
+.. option:: -u
+
+ This option indicates that times should be printed in Unix epoch format.
+
+.. option:: -p C/P/Pds/Psync/A/R/I/D/Dds/Dsync/all
+
+ This option prints a specific metadata value or set of metadata values.
+ The :option:`-p` option may be followed by one or more of the following letters or
+ strings to indicate which value or values to print: ``C`` for the
+ creation date, ``P`` for the publication date, ``Pds` for the DS publication
+ date, ``Psync`` for the CDS and CDNSKEY publication date, ``A`` for the
+ activation date, ``R`` for the revocation date, ``I`` for the inactivation
+ date, ``D`` for the deletion date, ``Dds`` for the DS deletion date,
+ and ``Dsync`` for the CDS and CDNSKEY deletion date. To print all of the
+ metadata, use ``all``.
+
+See Also
+~~~~~~~~
+
+:iscman:`dnssec-keygen(8) <dnssec-keygen>`, :iscman:`dnssec-signzone(8) <dnssec-signzone>`, BIND 9 Administrator Reference Manual,
+:rfc:`5011`.
diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c
new file mode 100644
index 0000000..f52457c
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.c
@@ -0,0 +1,4165 @@
+/*
+ * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * Portions Copyright (C) Network Associates, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/atomic.h>
+#include <isc/attributes.h>
+#include <isc/base32.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/event.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/hex.h>
+#include <isc/managers.h>
+#include <isc/md.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/os.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/rwlock.h>
+#include <isc/safe.h>
+#include <isc/serial.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/diff.h>
+#include <dns/dnssec.h>
+#include <dns/ds.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/masterdump.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/soa.h>
+#include <dns/time.h>
+#include <dns/update.h>
+#include <dns/zoneverify.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-signzone";
+
+typedef struct hashlist hashlist_t;
+
+static int nsec_datatype = dns_rdatatype_nsec;
+
+#define check_dns_dbiterator_current(result) \
+ check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \
+ "dns_dbiterator_current()")
+
+#define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
+#define OPTOUT(x) (((x)&DNS_NSEC3FLAG_OPTOUT) != 0)
+
+#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
+
+#define BUFSIZE 2048
+#define MAXDSKEYS 8
+
+#define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
+#define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
+#define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
+
+#define SOA_SERIAL_KEEP 0
+#define SOA_SERIAL_INCREMENT 1
+#define SOA_SERIAL_UNIXTIME 2
+#define SOA_SERIAL_DATE 3
+
+typedef struct signer_event sevent_t;
+struct signer_event {
+ ISC_EVENT_COMMON(sevent_t);
+ dns_fixedname_t *fname;
+ dns_dbnode_t *node;
+};
+
+static dns_dnsseckeylist_t keylist;
+static unsigned int keycount = 0;
+static isc_rwlock_t keylist_lock;
+static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now;
+static int cycle = -1;
+static int jitter = 0;
+static bool tryverify = false;
+static bool printstats = false;
+static isc_mem_t *mctx = NULL;
+static dns_ttl_t zone_soa_min_ttl;
+static dns_ttl_t soa_ttl;
+static FILE *outfp = NULL;
+static char *tempfile = NULL;
+static const dns_master_style_t *masterstyle;
+static dns_masterformat_t inputformat = dns_masterformat_text;
+static dns_masterformat_t outputformat = dns_masterformat_text;
+static uint32_t rawversion = 1, serialnum = 0;
+static bool snset = false;
+static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
+static unsigned int nverified = 0, nverifyfailed = 0;
+static const char *directory = NULL, *dsdir = NULL;
+static isc_mutex_t namelock, statslock;
+static isc_nm_t *netmgr = NULL;
+static isc_taskmgr_t *taskmgr = NULL;
+static dns_db_t *gdb; /* The database */
+static dns_dbversion_t *gversion; /* The database version */
+static dns_dbiterator_t *gdbiter; /* The database iterator */
+static dns_rdataclass_t gclass; /* The class */
+static dns_name_t *gorigin; /* The database origin */
+static int nsec3flags = 0;
+static dns_iterations_t nsec3iter = 0U;
+static unsigned char saltbuf[255];
+static unsigned char *gsalt = saltbuf;
+static size_t salt_length = 0;
+static isc_task_t *main_task = NULL;
+static unsigned int ntasks = 0;
+static atomic_bool shuttingdown;
+static atomic_bool finished;
+static bool nokeys = false;
+static bool removefile = false;
+static bool generateds = false;
+static bool ignore_kskflag = false;
+static bool keyset_kskonly = false;
+static dns_master_style_t *dsstyle = NULL;
+static unsigned int serialformat = SOA_SERIAL_KEEP;
+static unsigned int hash_length = 0;
+static bool unknownalg = false;
+static bool disable_zone_check = false;
+static bool update_chain = false;
+static bool set_keyttl = false;
+static dns_ttl_t keyttl;
+static bool smartsign = false;
+static bool remove_orphansigs = false;
+static bool remove_inactkeysigs = false;
+static bool output_dnssec_only = false;
+static bool output_stdout = false;
+static bool set_maxttl = false;
+static dns_ttl_t maxttl = 0;
+static bool no_max_check = false;
+
+#define INCSTAT(counter) \
+ if (printstats) { \
+ LOCK(&statslock); \
+ counter++; \
+ UNLOCK(&statslock); \
+ }
+
+static void
+sign(isc_task_t *task, isc_event_t *event);
+
+/*%
+ * Store a copy of 'name' in 'fzonecut' and return a pointer to that copy.
+ */
+static dns_name_t *
+savezonecut(dns_fixedname_t *fzonecut, dns_name_t *name) {
+ dns_name_t *result;
+
+ result = dns_fixedname_initname(fzonecut);
+ dns_name_copy(name, result);
+
+ return (result);
+}
+
+static void
+dumpnode(dns_name_t *name, dns_dbnode_t *node) {
+ dns_rdataset_t rds;
+ dns_rdatasetiter_t *iter = NULL;
+ isc_buffer_t *buffer = NULL;
+ isc_region_t r;
+ isc_result_t result;
+ unsigned bufsize = 4096;
+
+ if (outputformat != dns_masterformat_text) {
+ return;
+ }
+
+ if (!output_dnssec_only) {
+ result = dns_master_dumpnodetostream(mctx, gdb, gversion, node,
+ name, masterstyle, outfp);
+ check_result(result, "dns_master_dumpnodetostream");
+ return;
+ }
+
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &iter);
+ check_result(result, "dns_db_allrdatasets");
+
+ dns_rdataset_init(&rds);
+
+ isc_buffer_allocate(mctx, &buffer, bufsize);
+
+ for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iter))
+ {
+ dns_rdatasetiter_current(iter, &rds);
+
+ if (rds.type != dns_rdatatype_rrsig &&
+ rds.type != dns_rdatatype_nsec &&
+ rds.type != dns_rdatatype_nsec3 &&
+ rds.type != dns_rdatatype_nsec3param &&
+ (!smartsign || rds.type != dns_rdatatype_dnskey))
+ {
+ dns_rdataset_disassociate(&rds);
+ continue;
+ }
+
+ for (;;) {
+ result = dns_master_rdatasettotext(
+ name, &rds, masterstyle, NULL, buffer);
+ if (result != ISC_R_NOSPACE) {
+ break;
+ }
+
+ bufsize <<= 1;
+ isc_buffer_free(&buffer);
+ isc_buffer_allocate(mctx, &buffer, bufsize);
+ }
+ check_result(result, "dns_master_rdatasettotext");
+
+ isc_buffer_usedregion(buffer, &r);
+ result = isc_stdio_write(r.base, 1, r.length, outfp, NULL);
+ check_result(result, "isc_stdio_write");
+ isc_buffer_clear(buffer);
+
+ dns_rdataset_disassociate(&rds);
+ }
+
+ isc_buffer_free(&buffer);
+ dns_rdatasetiter_destroy(&iter);
+}
+
+/*%
+ * Sign the given RRset with given key, and add the signature record to the
+ * given tuple.
+ */
+static void
+signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
+ dns_ttl_t ttl, dns_diff_t *add, const char *logmsg) {
+ isc_result_t result;
+ isc_stdtime_t jendtime, expiry;
+ char keystr[DST_KEY_FORMATSIZE];
+ dns_rdata_t trdata = DNS_RDATA_INIT;
+ unsigned char array[BUFSIZE];
+ isc_buffer_t b;
+ dns_difftuple_t *tuple;
+
+ dst_key_format(key, keystr, sizeof(keystr));
+ vbprintf(1, "\t%s %s\n", logmsg, keystr);
+
+ if (rdataset->type == dns_rdatatype_dnskey) {
+ expiry = dnskey_endtime;
+ } else {
+ expiry = endtime;
+ }
+
+ jendtime = (jitter != 0) ? expiry - isc_random_uniform(jitter) : expiry;
+ isc_buffer_init(&b, array, sizeof(array));
+ result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
+ mctx, &b, &trdata);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dnskey '%s' failed to sign data: %s", keystr,
+ isc_result_totext(result));
+ }
+ INCSTAT(nsigned);
+
+ if (tryverify) {
+ result = dns_dnssec_verify(name, rdataset, key, true, 0, mctx,
+ &trdata, NULL);
+ if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
+ vbprintf(3, "\tsignature verified\n");
+ INCSTAT(nverified);
+ } else {
+ vbprintf(3, "\tsignature failed to verify\n");
+ INCSTAT(nverifyfailed);
+ }
+ }
+
+ tuple = NULL;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, ttl,
+ &trdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(add, &tuple);
+}
+
+static bool
+issigningkey(dns_dnsseckey_t *key) {
+ return (key->force_sign || key->hint_sign);
+}
+
+static bool
+ispublishedkey(dns_dnsseckey_t *key) {
+ return ((key->force_publish || key->hint_publish) && !key->hint_remove);
+}
+
+static bool
+iszonekey(dns_dnsseckey_t *key) {
+ return (dns_name_equal(dst_key_name(key->key), gorigin) &&
+ dst_key_iszonekey(key->key));
+}
+
+static bool
+isksk(dns_dnsseckey_t *key) {
+ return (key->ksk);
+}
+
+static bool
+iszsk(dns_dnsseckey_t *key) {
+ return (ignore_kskflag || !key->ksk);
+}
+
+/*%
+ * Find the key that generated an RRSIG, if it is in the key list. If
+ * so, return a pointer to it, otherwise return NULL.
+ *
+ * No locking is performed here, this must be done by the caller.
+ */
+static dns_dnsseckey_t *
+keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
+ dns_dnsseckey_t *key;
+
+ for (key = ISC_LIST_HEAD(keylist); key != NULL;
+ key = ISC_LIST_NEXT(key, link))
+ {
+ if (rrsig->keyid == dst_key_id(key->key) &&
+ rrsig->algorithm == dst_key_alg(key->key) &&
+ dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
+ {
+ return (key);
+ }
+ }
+ return (NULL);
+}
+
+/*%
+ * Finds the key that generated a RRSIG, if possible. First look at the keys
+ * that we've loaded already, and then see if there's a key on disk.
+ */
+static dns_dnsseckey_t *
+keythatsigned(dns_rdata_rrsig_t *rrsig) {
+ isc_result_t result;
+ dst_key_t *pubkey = NULL, *privkey = NULL;
+ dns_dnsseckey_t *key = NULL;
+
+ RWLOCK(&keylist_lock, isc_rwlocktype_read);
+ key = keythatsigned_unlocked(rrsig);
+ RWUNLOCK(&keylist_lock, isc_rwlocktype_read);
+ if (key != NULL) {
+ return (key);
+ }
+
+ /*
+ * We did not find the key in our list. Get a write lock now, since
+ * we may be modifying the bits. We could do the tryupgrade() dance,
+ * but instead just get a write lock and check once again to see if
+ * it is on our list. It's possible someone else may have added it
+ * after all.
+ */
+ isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
+ key = keythatsigned_unlocked(rrsig);
+ if (key != NULL) {
+ isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
+ return (key);
+ }
+
+ result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
+ rrsig->algorithm, DST_TYPE_PUBLIC, directory,
+ mctx, &pubkey);
+ if (result != ISC_R_SUCCESS) {
+ isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
+ return (NULL);
+ }
+
+ result = dst_key_fromfile(
+ &rrsig->signer, rrsig->keyid, rrsig->algorithm,
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, directory, mctx, &privkey);
+ if (result == ISC_R_SUCCESS) {
+ dst_key_free(&pubkey);
+ result = dns_dnsseckey_create(mctx, &privkey, &key);
+ } else {
+ result = dns_dnsseckey_create(mctx, &pubkey, &key);
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ key->force_publish = false;
+ key->force_sign = false;
+ key->index = keycount++;
+ ISC_LIST_APPEND(keylist, key, link);
+ }
+
+ isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
+ return (key);
+}
+
+/*%
+ * Check to see if we expect to find a key at this name. If we see a RRSIG
+ * and can't find the signing key that we expect to find, we drop the rrsig.
+ * I'm not sure if this is completely correct, but it seems to work.
+ */
+static bool
+expecttofindkey(dns_name_t *name) {
+ unsigned int options = DNS_DBFIND_NOWILD;
+ dns_fixedname_t fname;
+ isc_result_t result;
+ char namestr[DNS_NAME_FORMATSIZE];
+
+ dns_fixedname_init(&fname);
+ result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
+ 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_NXDOMAIN:
+ case DNS_R_NXRRSET:
+ return (true);
+ case DNS_R_DELEGATION:
+ case DNS_R_CNAME:
+ case DNS_R_DNAME:
+ return (false);
+ default:
+ break;
+ }
+ dns_name_format(name, namestr, sizeof(namestr));
+ fatal("failure looking for '%s DNSKEY' in database: %s", namestr,
+ isc_result_totext(result));
+ UNREACHABLE();
+ return (false); /* removes a warning */
+}
+
+static bool
+setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
+ dns_rdata_t *rrsig) {
+ isc_result_t result;
+ result = dns_dnssec_verify(name, set, key, false, 0, mctx, rrsig, NULL);
+ if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
+ INCSTAT(nverified);
+ return (true);
+ } else {
+ INCSTAT(nverifyfailed);
+ return (false);
+ }
+}
+
+/*%
+ * Signs a set. Goes through contortions to decide if each RRSIG should
+ * be dropped or retained, and then determines if any new SIGs need to
+ * be generated.
+ */
+static void
+signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
+ dns_rdataset_t *set) {
+ dns_rdataset_t sigset;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t rrsig;
+ dns_dnsseckey_t *key;
+ isc_result_t result;
+ bool nosigs = false;
+ bool *wassignedby, *nowsignedby;
+ int arraysize;
+ dns_difftuple_t *tuple;
+ dns_ttl_t ttl;
+ int i;
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+ char sigstr[SIG_FORMATSIZE];
+
+ dns_name_format(name, namestr, sizeof(namestr));
+ dns_rdatatype_format(set->type, typestr, sizeof(typestr));
+
+ ttl = ISC_MIN(set->ttl, endtime - starttime);
+
+ dns_rdataset_init(&sigset);
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
+ set->type, 0, &sigset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ vbprintf(2, "no existing signatures for %s/%s\n", namestr,
+ typestr);
+ result = ISC_R_SUCCESS;
+ nosigs = true;
+ }
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed while looking for '%s RRSIG %s': %s", namestr,
+ typestr, isc_result_totext(result));
+ }
+
+ vbprintf(1, "%s/%s:\n", namestr, typestr);
+
+ arraysize = keycount;
+ if (!nosigs) {
+ arraysize += dns_rdataset_count(&sigset);
+ }
+ wassignedby = isc_mem_get(mctx, arraysize * sizeof(bool));
+ nowsignedby = isc_mem_get(mctx, arraysize * sizeof(bool));
+
+ for (i = 0; i < arraysize; i++) {
+ wassignedby[i] = nowsignedby[i] = false;
+ }
+
+ if (nosigs) {
+ result = ISC_R_NOMORE;
+ } else {
+ result = dns_rdataset_first(&sigset);
+ }
+
+ while (result == ISC_R_SUCCESS) {
+ bool expired, future;
+ bool keep = false, resign = false;
+
+ dns_rdataset_current(&sigset, &sigrdata);
+
+ result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ future = isc_serial_lt(now, rrsig.timesigned);
+
+ key = keythatsigned(&rrsig);
+ sig_format(&rrsig, sigstr, sizeof(sigstr));
+ expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
+
+ if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
+ /* rrsig is dropped and not replaced */
+ vbprintf(2,
+ "\trrsig by %s dropped - "
+ "invalid validity period\n",
+ sigstr);
+ } else if (key == NULL && !future &&
+ expecttofindkey(&rrsig.signer))
+ {
+ /* rrsig is dropped and not replaced */
+ vbprintf(2,
+ "\trrsig by %s dropped - "
+ "private dnskey not found\n",
+ sigstr);
+ } else if (key == NULL || future) {
+ keep = (!expired && !remove_orphansigs);
+ vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
+ keep ? "retained" : "dropped", sigstr);
+ } else if (!dns_dnssec_keyactive(key->key, now) &&
+ remove_inactkeysigs)
+ {
+ keep = false;
+ vbprintf(2, "\trrsig by %s dropped - key inactive\n",
+ sigstr);
+ } else if (issigningkey(key)) {
+ wassignedby[key->index] = true;
+
+ if (!expired && rrsig.originalttl == set->ttl &&
+ setverifies(name, set, key->key, &sigrdata))
+ {
+ vbprintf(2, "\trrsig by %s retained\n", sigstr);
+ keep = true;
+ } else {
+ vbprintf(2, "\trrsig by %s dropped - %s\n",
+ sigstr,
+ expired ? "expired"
+ : rrsig.originalttl != set->ttl
+ ? "ttl change"
+ : "failed to "
+ "verify");
+ resign = true;
+ }
+ } else if (!ispublishedkey(key) && remove_orphansigs) {
+ vbprintf(2, "\trrsig by %s dropped - dnskey removed\n",
+ sigstr);
+ } else if (iszonekey(key)) {
+ wassignedby[key->index] = true;
+
+ if (!expired && rrsig.originalttl == set->ttl &&
+ setverifies(name, set, key->key, &sigrdata))
+ {
+ vbprintf(2, "\trrsig by %s retained\n", sigstr);
+ keep = true;
+ } else {
+ vbprintf(2, "\trrsig by %s dropped - %s\n",
+ sigstr,
+ expired ? "expired"
+ : rrsig.originalttl != set->ttl
+ ? "ttl change"
+ : "failed to "
+ "verify");
+ }
+ } else if (!expired) {
+ vbprintf(2, "\trrsig by %s retained\n", sigstr);
+ keep = true;
+ } else {
+ vbprintf(2, "\trrsig by %s expired\n", sigstr);
+ }
+
+ if (keep) {
+ if (key != NULL) {
+ nowsignedby[key->index] = true;
+ }
+ INCSTAT(nretained);
+ if (sigset.ttl != ttl) {
+ vbprintf(2, "\tfixing ttl %s\n", sigstr);
+ tuple = NULL;
+ result = dns_difftuple_create(
+ mctx, DNS_DIFFOP_DELRESIGN, name,
+ sigset.ttl, &sigrdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(del, &tuple);
+ result = dns_difftuple_create(
+ mctx, DNS_DIFFOP_ADDRESIGN, name, ttl,
+ &sigrdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(add, &tuple);
+ }
+ } else {
+ tuple = NULL;
+ vbprintf(2, "\tremoving signature by %s\n", sigstr);
+ result = dns_difftuple_create(
+ mctx, DNS_DIFFOP_DELRESIGN, name, sigset.ttl,
+ &sigrdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(del, &tuple);
+ INCSTAT(ndropped);
+ }
+
+ if (resign) {
+ INSIST(!keep);
+
+ signwithkey(name, set, key->key, ttl, add,
+ "resigning with dnskey");
+ nowsignedby[key->index] = true;
+ }
+
+ dns_rdata_reset(&sigrdata);
+ dns_rdata_freestruct(&rrsig);
+ result = dns_rdataset_next(&sigset);
+ }
+ if (result == ISC_R_NOMORE) {
+ result = ISC_R_SUCCESS;
+ }
+
+ check_result(result, "dns_rdataset_first/next");
+ if (dns_rdataset_isassociated(&sigset)) {
+ dns_rdataset_disassociate(&sigset);
+ }
+
+ for (key = ISC_LIST_HEAD(keylist); key != NULL;
+ key = ISC_LIST_NEXT(key, link))
+ {
+ if (nowsignedby[key->index]) {
+ continue;
+ }
+
+ if (!issigningkey(key)) {
+ continue;
+ }
+
+ if ((set->type == dns_rdatatype_cds ||
+ set->type == dns_rdatatype_cdnskey ||
+ set->type == dns_rdatatype_dnskey) &&
+ dns_name_equal(name, gorigin))
+ {
+ bool have_ksk;
+ dns_dnsseckey_t *curr;
+
+ have_ksk = isksk(key);
+ for (curr = ISC_LIST_HEAD(keylist); curr != NULL;
+ curr = ISC_LIST_NEXT(curr, link))
+ {
+ if (dst_key_alg(key->key) !=
+ dst_key_alg(curr->key))
+ {
+ continue;
+ }
+ if (REVOKE(curr->key)) {
+ continue;
+ }
+ if (isksk(curr)) {
+ have_ksk = true;
+ }
+ }
+ if (isksk(key) || !have_ksk ||
+ (iszsk(key) && !keyset_kskonly))
+ {
+ signwithkey(name, set, key->key, ttl, add,
+ "signing with dnskey");
+ }
+ } else if (iszsk(key)) {
+ /*
+ * Sign with the ZSK unless there is a predecessor
+ * key that already signs this RRset.
+ */
+ bool have_pre_sig = false;
+ dns_dnsseckey_t *curr;
+ uint32_t pre;
+ isc_result_t ret = dst_key_getnum(
+ key->key, DST_NUM_PREDECESSOR, &pre);
+ if (ret == ISC_R_SUCCESS) {
+ /*
+ * This key has a predecessor, look for the
+ * corresponding key in the keylist. The
+ * key we are looking for must be:
+ * - From the same cryptographic algorithm.
+ * - Have the ZSK type (iszsk).
+ * - Have key ID equal to the predecessor id.
+ * - Have a successor that matches 'key' id.
+ */
+ for (curr = ISC_LIST_HEAD(keylist);
+ curr != NULL;
+ curr = ISC_LIST_NEXT(curr, link))
+ {
+ uint32_t suc;
+
+ if (dst_key_alg(key->key) !=
+ dst_key_alg(curr->key) ||
+ !iszsk(curr) ||
+ dst_key_id(curr->key) != pre)
+ {
+ continue;
+ }
+ ret = dst_key_getnum(curr->key,
+ DST_NUM_SUCCESSOR,
+ &suc);
+ if (ret != ISC_R_SUCCESS ||
+ dst_key_id(key->key) != suc)
+ {
+ continue;
+ }
+
+ /*
+ * curr is the predecessor we were
+ * looking for. Check if this key
+ * signs this RRset.
+ */
+ if (nowsignedby[curr->index]) {
+ have_pre_sig = true;
+ }
+ }
+ }
+
+ /*
+ * If we have a signature of a predecessor key,
+ * skip signing with this key.
+ */
+ if (!have_pre_sig) {
+ signwithkey(name, set, key->key, ttl, add,
+ "signing with dnskey");
+ }
+ }
+ }
+
+ isc_mem_put(mctx, wassignedby, arraysize * sizeof(bool));
+ isc_mem_put(mctx, nowsignedby, arraysize * sizeof(bool));
+}
+
+struct hashlist {
+ unsigned char *hashbuf;
+ size_t entries;
+ size_t size;
+ size_t length;
+};
+
+static void
+hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
+ l->entries = 0;
+ l->length = length + 1;
+
+ if (nodes != 0) {
+ l->size = nodes;
+ l->hashbuf = malloc(l->size * l->length);
+ if (l->hashbuf == NULL) {
+ l->size = 0;
+ }
+ } else {
+ l->size = 0;
+ l->hashbuf = NULL;
+ }
+}
+
+static void
+hashlist_free(hashlist_t *l) {
+ if (l->hashbuf) {
+ free(l->hashbuf);
+ l->hashbuf = NULL;
+ l->entries = 0;
+ l->length = 0;
+ l->size = 0;
+ }
+}
+
+static void
+hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len) {
+ REQUIRE(len <= l->length);
+
+ if (l->entries == l->size) {
+ l->size = l->size * 2 + 100;
+ l->hashbuf = realloc(l->hashbuf, l->size * l->length);
+ if (l->hashbuf == NULL) {
+ fatal("unable to grow hashlist: out of memory");
+ }
+ }
+ memset(l->hashbuf + l->entries * l->length, 0, l->length);
+ memmove(l->hashbuf + l->entries * l->length, hash, len);
+ l->entries++;
+}
+
+static void
+hashlist_add_dns_name(hashlist_t *l,
+ /*const*/ dns_name_t *name, unsigned int hashalg,
+ unsigned int iterations, const unsigned char *salt,
+ size_t salt_len, bool speculative) {
+ char nametext[DNS_NAME_FORMATSIZE];
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
+ unsigned int len;
+ size_t i;
+
+ len = isc_iterated_hash(hash, hashalg, iterations, salt, (int)salt_len,
+ name->ndata, name->length);
+ if (verbose) {
+ dns_name_format(name, nametext, sizeof nametext);
+ for (i = 0; i < len; i++) {
+ fprintf(stderr, "%02x", hash[i]);
+ }
+ fprintf(stderr, " %s\n", nametext);
+ }
+ hash[len++] = speculative ? 1 : 0;
+ hashlist_add(l, hash, len);
+}
+
+static int
+hashlist_comp(const void *a, const void *b) {
+ return (memcmp(a, b, hash_length + 1));
+}
+
+static void
+hashlist_sort(hashlist_t *l) {
+ INSIST(l->hashbuf != NULL || l->length == 0);
+ if (l->length > 0) {
+ qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
+ }
+}
+
+static bool
+hashlist_hasdup(hashlist_t *l) {
+ unsigned char *current;
+ unsigned char *next = l->hashbuf;
+ size_t entries = l->entries;
+
+ /*
+ * Skip initial speculative wild card hashes.
+ */
+ while (entries > 0U && next[l->length - 1] != 0U) {
+ next += l->length;
+ entries--;
+ }
+
+ current = next;
+ while (entries-- > 1U) {
+ next += l->length;
+ if (next[l->length - 1] != 0) {
+ continue;
+ }
+ if (isc_safe_memequal(current, next, l->length - 1)) {
+ return (true);
+ }
+ current = next;
+ }
+ return (false);
+}
+
+static const unsigned char *
+hashlist_findnext(const hashlist_t *l,
+ const unsigned char hash[NSEC3_MAX_HASH_LENGTH]) {
+ size_t entries = l->entries;
+ const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
+ l->length, hashlist_comp);
+ INSIST(next != NULL);
+
+ do {
+ if (next < l->hashbuf + (l->entries - 1) * l->length) {
+ next += l->length;
+ } else {
+ next = l->hashbuf;
+ }
+ if (next[l->length - 1] == 0) {
+ break;
+ }
+ } while (entries-- > 1U);
+ INSIST(entries != 0U);
+ return (next);
+}
+
+static bool
+hashlist_exists(const hashlist_t *l,
+ const unsigned char hash[NSEC3_MAX_HASH_LENGTH]) {
+ if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp)) {
+ return (true);
+ } else {
+ return (false);
+ }
+}
+
+static void
+addnowildcardhash(hashlist_t *l,
+ /*const*/ dns_name_t *name, unsigned int hashalg,
+ unsigned int iterations, const unsigned char *salt,
+ size_t salt_len) {
+ dns_fixedname_t fixed;
+ dns_name_t *wild;
+ dns_dbnode_t *node = NULL;
+ isc_result_t result;
+ char namestr[DNS_NAME_FORMATSIZE];
+
+ wild = dns_fixedname_initname(&fixed);
+
+ result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
+ if (result == ISC_R_NOSPACE) {
+ return;
+ }
+ check_result(result, "addnowildcardhash: dns_name_concatenate()");
+
+ result = dns_db_findnode(gdb, wild, false, &node);
+ if (result == ISC_R_SUCCESS) {
+ dns_db_detachnode(gdb, &node);
+ return;
+ }
+
+ if (verbose) {
+ dns_name_format(wild, namestr, sizeof(namestr));
+ fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
+ }
+
+ hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_len,
+ true);
+}
+
+static void
+opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
+ dns_db_t **dbp) {
+ char filename[PATH_MAX];
+ isc_buffer_t b;
+ isc_result_t result;
+
+ isc_buffer_init(&b, filename, sizeof(filename));
+ if (dsdir != NULL) {
+ /* allow room for a trailing slash */
+ if (strlen(dsdir) >= isc_buffer_availablelength(&b)) {
+ fatal("path '%s' is too long", dsdir);
+ }
+ isc_buffer_putstr(&b, dsdir);
+ if (dsdir[strlen(dsdir) - 1] != '/') {
+ isc_buffer_putstr(&b, "/");
+ }
+ }
+ if (strlen(prefix) > isc_buffer_availablelength(&b)) {
+ fatal("path '%s' is too long", dsdir);
+ }
+ isc_buffer_putstr(&b, prefix);
+ result = dns_name_tofilenametext(name, false, &b);
+ check_result(result, "dns_name_tofilenametext()");
+ if (isc_buffer_availablelength(&b) == 0) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ fatal("name '%s' is too long", namestr);
+ }
+ isc_buffer_putuint8(&b, 0);
+
+ result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
+ rdclass, 0, NULL, dbp);
+ check_result(result, "dns_db_create()");
+
+ result = dns_db_load(*dbp, filename, inputformat, DNS_MASTER_HINT);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
+ dns_db_detach(dbp);
+ }
+}
+
+/*%
+ * Load the DS set for a child zone, if a dsset-* file can be found.
+ * If not, try to find a keyset-* file from an earlier version of
+ * dnssec-signzone, and build DS records from that.
+ */
+static isc_result_t
+loadds(dns_name_t *name, uint32_t ttl, dns_rdataset_t *dsset) {
+ dns_db_t *db = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_dbnode_t *node = NULL;
+ isc_result_t result;
+ dns_rdataset_t keyset;
+ dns_rdata_t key, ds;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+ dns_diff_t diff;
+ dns_difftuple_t *tuple = NULL;
+
+ opendb("dsset-", name, gclass, &db);
+ if (db != NULL) {
+ result = dns_db_findnode(db, name, false, &node);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_init(dsset);
+ result = dns_db_findrdataset(db, node, NULL,
+ dns_rdatatype_ds, 0, 0,
+ dsset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_SUCCESS) {
+ vbprintf(2, "found DS records\n");
+ dsset->ttl = ttl;
+ dns_db_detach(&db);
+ return (result);
+ }
+ }
+ dns_db_detach(&db);
+ }
+
+ /* No DS records found; try again, looking for DNSKEY records */
+ opendb("keyset-", name, gclass, &db);
+ if (db == NULL) {
+ return (ISC_R_NOTFOUND);
+ }
+
+ result = dns_db_findnode(db, name, false, &node);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detach(&db);
+ return (result);
+ }
+
+ dns_rdataset_init(&keyset);
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
+ &keyset, NULL);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ return (result);
+ }
+ vbprintf(2, "found DNSKEY records\n");
+
+ result = dns_db_newversion(db, &ver);
+ check_result(result, "dns_db_newversion");
+ dns_diff_init(mctx, &diff);
+
+ for (result = dns_rdataset_first(&keyset); result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&keyset))
+ {
+ dns_rdata_init(&key);
+ dns_rdata_init(&ds);
+ dns_rdataset_current(&keyset, &key);
+ result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
+ dsbuf, &ds);
+ check_result(result, "dns_ds_buildrdata");
+
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
+ ttl, &ds, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+ }
+
+ result = dns_diff_apply(&diff, db, ver);
+ check_result(result, "dns_diff_apply");
+ dns_diff_clear(&diff);
+
+ dns_db_closeversion(db, &ver, true);
+
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
+ dsset, NULL);
+ check_result(result, "dns_db_findrdataset");
+
+ dns_rdataset_disassociate(&keyset);
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ return (result);
+}
+
+static bool
+secure(dns_name_t *name, dns_dbnode_t *node) {
+ dns_rdataset_t dsset;
+ isc_result_t result;
+
+ if (dns_name_equal(name, gorigin)) {
+ return (false);
+ }
+
+ dns_rdataset_init(&dsset);
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds, 0,
+ 0, &dsset, NULL);
+ if (dns_rdataset_isassociated(&dsset)) {
+ dns_rdataset_disassociate(&dsset);
+ }
+
+ return (result == ISC_R_SUCCESS);
+}
+
+static bool
+is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
+ dns_name_t *name, dns_dbnode_t *node, uint32_t *ttlp) {
+ dns_rdataset_t nsset;
+ isc_result_t result;
+
+ if (dns_name_equal(name, origin)) {
+ return (false);
+ }
+
+ dns_rdataset_init(&nsset);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns, 0, 0,
+ &nsset, NULL);
+ if (dns_rdataset_isassociated(&nsset)) {
+ if (ttlp != NULL) {
+ *ttlp = nsset.ttl;
+ }
+ dns_rdataset_disassociate(&nsset);
+ }
+
+ return ((result == ISC_R_SUCCESS));
+}
+
+/*%
+ * Return true if version 'ver' of database 'db' contains a DNAME RRset at
+ * 'node'; return false otherwise.
+ */
+static bool
+has_dname(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) {
+ dns_rdataset_t dnameset;
+ isc_result_t result;
+
+ dns_rdataset_init(&dnameset);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dname, 0, 0,
+ &dnameset, NULL);
+ if (dns_rdataset_isassociated(&dnameset)) {
+ dns_rdataset_disassociate(&dnameset);
+ }
+
+ return ((result == ISC_R_SUCCESS));
+}
+
+/*%
+ * Signs all records at a name.
+ */
+static void
+signname(dns_dbnode_t *node, dns_name_t *name) {
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdatasetiter_t *rdsiter;
+ bool isdelegation = false;
+ dns_diff_t del, add;
+ char namestr[DNS_NAME_FORMATSIZE];
+
+ dns_rdataset_init(&rdataset);
+ dns_name_format(name, namestr, sizeof(namestr));
+
+ /*
+ * Determine if this is a delegation point.
+ */
+ if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) {
+ isdelegation = true;
+ }
+
+ /*
+ * Now iterate through the rdatasets.
+ */
+ dns_diff_init(mctx, &del);
+ dns_diff_init(mctx, &add);
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+
+ /* If this is a RRSIG set, skip it. */
+ if (rdataset.type == dns_rdatatype_rrsig) {
+ goto skip;
+ }
+
+ /*
+ * If this name is a delegation point, skip all records
+ * except NSEC and DS sets. Otherwise check that there
+ * isn't a DS record.
+ */
+ if (isdelegation) {
+ if (rdataset.type != nsec_datatype &&
+ rdataset.type != dns_rdatatype_ds)
+ {
+ goto skip;
+ }
+ } else if (rdataset.type == dns_rdatatype_ds) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ fatal("'%s': found DS RRset without NS RRset\n",
+ namebuf);
+ }
+
+ signset(&del, &add, node, name, &rdataset);
+
+ skip:
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+ if (result != ISC_R_NOMORE) {
+ fatal("rdataset iteration for name '%s' failed: %s", namestr,
+ isc_result_totext(result));
+ }
+
+ dns_rdatasetiter_destroy(&rdsiter);
+
+ result = dns_diff_applysilently(&del, gdb, gversion);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to delete SIGs at node '%s': %s", namestr,
+ isc_result_totext(result));
+ }
+
+ result = dns_diff_applysilently(&add, gdb, gversion);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to add SIGs at node '%s': %s", namestr,
+ isc_result_totext(result));
+ }
+
+ dns_diff_clear(&del);
+ dns_diff_clear(&add);
+}
+
+/*
+ * See if the node contains any non RRSIG/NSEC records and report to
+ * caller. Clean out extraneous RRSIG records for node.
+ */
+static bool
+active_node(dns_dbnode_t *node) {
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_rdatasetiter_t *rdsiter2 = NULL;
+ bool active = false;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdatatype_t type;
+ dns_rdatatype_t covers;
+ bool found;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ if (rdataset.type != dns_rdatatype_nsec &&
+ rdataset.type != dns_rdatatype_nsec3 &&
+ rdataset.type != dns_rdatatype_rrsig)
+ {
+ active = true;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (!active) {
+ result = dns_rdatasetiter_next(rdsiter);
+ } else {
+ result = ISC_R_NOMORE;
+ }
+ }
+ if (result != ISC_R_NOMORE) {
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ }
+
+ if (!active && nsec_datatype == dns_rdatatype_nsec) {
+ /*%
+ * The node is empty of everything but NSEC / RRSIG records.
+ */
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter))
+ {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ rdataset.type,
+ rdataset.covers);
+ check_result(result, "dns_db_deleterdataset()");
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (result != ISC_R_NOMORE) {
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ }
+ } else {
+ /*
+ * Delete RRSIGs for types that no longer exist.
+ */
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, 0,
+ &rdsiter2);
+ check_result(result, "dns_db_allrdatasets()");
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter))
+ {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ type = rdataset.type;
+ covers = rdataset.covers;
+ dns_rdataset_disassociate(&rdataset);
+ /*
+ * Delete the NSEC chain if we are signing with
+ * NSEC3.
+ */
+ if (nsec_datatype == dns_rdatatype_nsec3 &&
+ (type == dns_rdatatype_nsec ||
+ covers == dns_rdatatype_nsec))
+ {
+ result = dns_db_deleterdataset(
+ gdb, node, gversion, type, covers);
+ check_result(result, "dns_db_deleterdataset("
+ "nsec/rrsig)");
+ continue;
+ }
+ if (type != dns_rdatatype_rrsig) {
+ continue;
+ }
+ found = false;
+ for (result = dns_rdatasetiter_first(rdsiter2);
+ !found && result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter2))
+ {
+ dns_rdatasetiter_current(rdsiter2, &rdataset);
+ if (rdataset.type == covers) {
+ found = true;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (!found) {
+ if (result != ISC_R_NOMORE) {
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ }
+ result = dns_db_deleterdataset(
+ gdb, node, gversion, type, covers);
+ check_result(result, "dns_db_deleterdataset("
+ "rrsig)");
+ } else if (result != ISC_R_NOMORE &&
+ result != ISC_R_SUCCESS)
+ {
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ }
+ }
+ if (result != ISC_R_NOMORE) {
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ }
+ dns_rdatasetiter_destroy(&rdsiter2);
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+
+ return (active);
+}
+
+/*%
+ * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
+ */
+static void
+get_soa_ttls(void) {
+ dns_rdataset_t soaset;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ name = dns_fixedname_initname(&fname);
+ dns_rdataset_init(&soaset);
+ result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa, 0, 0,
+ NULL, name, &soaset, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to find an SOA at the zone apex: %s",
+ isc_result_totext(result));
+ }
+
+ result = dns_rdataset_first(&soaset);
+ check_result(result, "dns_rdataset_first");
+ dns_rdataset_current(&soaset, &rdata);
+ soa_ttl = soaset.ttl;
+ zone_soa_min_ttl = ISC_MIN(dns_soa_getminimum(&rdata), soa_ttl);
+ if (set_maxttl) {
+ zone_soa_min_ttl = ISC_MIN(zone_soa_min_ttl, maxttl);
+ soa_ttl = ISC_MIN(soa_ttl, maxttl);
+ }
+ dns_rdataset_disassociate(&soaset);
+}
+
+/*%
+ * Increment (or set if nonzero) the SOA serial
+ */
+static isc_result_t
+setsoaserial(uint32_t serial, dns_updatemethod_t method) {
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ uint32_t old_serial, new_serial = 0;
+ dns_updatemethod_t used = dns_updatemethod_none;
+
+ result = dns_db_getoriginnode(gdb, &node);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_soa, 0,
+ 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ result = dns_rdataset_first(&rdataset);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ dns_rdataset_current(&rdataset, &rdata);
+
+ old_serial = dns_soa_getserial(&rdata);
+
+ if (method == dns_updatemethod_date ||
+ method == dns_updatemethod_unixtime)
+ {
+ new_serial = dns_update_soaserial(old_serial, method, &used);
+ } else if (serial != 0 || method == dns_updatemethod_none) {
+ /* Set SOA serial to the value provided. */
+ new_serial = serial;
+ used = method;
+ } else {
+ new_serial = dns_update_soaserial(old_serial, method, &used);
+ }
+
+ if (method != used) {
+ fprintf(stderr,
+ "%s: warning: Serial number would not advance, "
+ "using increment method instead\n",
+ program);
+ }
+
+ /* If the new serial is not likely to cause a zone transfer
+ * (a/ixfr) from servers having the old serial, warn the user.
+ *
+ * RFC1982 section 7 defines the maximum increment to be
+ * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
+ * comparison. (5 - 6 == (2^32)-1, not negative-one)
+ */
+ if (new_serial == old_serial || (new_serial - old_serial) > 0x7fffffffU)
+ {
+ fprintf(stderr,
+ "%s: warning: Serial number not advanced, "
+ "zone may not transfer\n",
+ program);
+ }
+
+ dns_soa_setserial(new_serial, &rdata);
+
+ result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_soa,
+ 0);
+ check_result(result, "dns_db_deleterdataset");
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset, 0, NULL);
+ check_result(result, "dns_db_addrdataset");
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+cleanup:
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL) {
+ dns_db_detachnode(gdb, &node);
+ }
+ dns_rdata_reset(&rdata);
+
+ return (result);
+}
+
+/*%
+ * Delete any RRSIG records at a node.
+ */
+static void
+cleannode(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *node) {
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_rdataset_t set;
+ isc_result_t result, dresult;
+
+ if (outputformat != dns_masterformat_text || !disable_zone_check) {
+ return;
+ }
+
+ dns_rdataset_init(&set);
+ result = dns_db_allrdatasets(db, node, dbversion, 0, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ bool destroy = false;
+ dns_rdatatype_t covers = 0;
+ dns_rdatasetiter_current(rdsiter, &set);
+ if (set.type == dns_rdatatype_rrsig) {
+ covers = set.covers;
+ destroy = true;
+ }
+ dns_rdataset_disassociate(&set);
+ result = dns_rdatasetiter_next(rdsiter);
+ if (destroy) {
+ dresult = dns_db_deleterdataset(db, node, dbversion,
+ dns_rdatatype_rrsig,
+ covers);
+ check_result(dresult, "dns_db_deleterdataset");
+ }
+ }
+ if (result != ISC_R_NOMORE) {
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+}
+
+/*%
+ * Set up the iterator and global state before starting the tasks.
+ */
+static void
+presign(void) {
+ isc_result_t result;
+
+ gdbiter = NULL;
+ result = dns_db_createiterator(gdb, 0, &gdbiter);
+ check_result(result, "dns_db_createiterator()");
+}
+
+/*%
+ * Clean up the iterator and global state after the tasks complete.
+ */
+static void
+postsign(void) {
+ dns_dbiterator_destroy(&gdbiter);
+}
+
+/*%
+ * Sign the apex of the zone.
+ * Note the origin may not be the first node if there are out of zone
+ * records.
+ */
+static void
+signapex(void) {
+ dns_dbnode_t *node = NULL;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_result_t result;
+
+ name = dns_fixedname_initname(&fixed);
+ result = dns_dbiterator_seek(gdbiter, gorigin);
+ check_result(result, "dns_dbiterator_seek()");
+ result = dns_dbiterator_current(gdbiter, &node, name);
+ check_dns_dbiterator_current(result);
+ signname(node, name);
+ dumpnode(name, node);
+ cleannode(gdb, gversion, node);
+ dns_db_detachnode(gdb, &node);
+ result = dns_dbiterator_first(gdbiter);
+ if (result == ISC_R_NOMORE) {
+ atomic_store(&finished, true);
+ } else if (result != ISC_R_SUCCESS) {
+ fatal("failure iterating database: %s",
+ isc_result_totext(result));
+ }
+}
+
+/*%
+ * Assigns a node to a worker thread. This is protected by the main task's
+ * lock.
+ */
+static void
+assignwork(isc_task_t *task, isc_task_t *worker) {
+ dns_fixedname_t *fname;
+ dns_name_t *name;
+ dns_dbnode_t *node;
+ sevent_t *sevent;
+ dns_rdataset_t nsec;
+ bool found;
+ isc_result_t result;
+ static dns_name_t *zonecut = NULL; /* Protected by namelock. */
+ static dns_fixedname_t fzonecut; /* Protected by namelock. */
+ static unsigned int ended = 0; /* Protected by namelock. */
+
+ if (atomic_load(&shuttingdown)) {
+ return;
+ }
+
+ LOCK(&namelock);
+ if (atomic_load(&finished)) {
+ ended++;
+ if (ended == ntasks) {
+ isc_task_detach(&task);
+ isc_app_shutdown();
+ }
+ goto unlock;
+ }
+
+ fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
+ name = dns_fixedname_initname(fname);
+ node = NULL;
+ found = false;
+ while (!found) {
+ result = dns_dbiterator_current(gdbiter, &node, name);
+ check_dns_dbiterator_current(result);
+ /*
+ * The origin was handled by signapex().
+ */
+ if (dns_name_equal(name, gorigin)) {
+ dns_db_detachnode(gdb, &node);
+ goto next;
+ }
+ /*
+ * Sort the zone data from the glue and out-of-zone data.
+ * For NSEC zones nodes with zone data have NSEC records.
+ * For NSEC3 zones the NSEC3 nodes are zone data but
+ * outside of the zone name space. For the rest we need
+ * to track the bottom of zone cuts.
+ * Nodes which don't need to be signed are dumped here.
+ */
+ dns_rdataset_init(&nsec);
+ result = dns_db_findrdataset(gdb, node, gversion, nsec_datatype,
+ 0, 0, &nsec, NULL);
+ if (dns_rdataset_isassociated(&nsec)) {
+ dns_rdataset_disassociate(&nsec);
+ }
+ if (result == ISC_R_SUCCESS) {
+ found = true;
+ } else if (nsec_datatype == dns_rdatatype_nsec3) {
+ if (dns_name_issubdomain(name, gorigin) &&
+ (zonecut == NULL ||
+ !dns_name_issubdomain(name, zonecut)))
+ {
+ if (is_delegation(gdb, gversion, gorigin, name,
+ node, NULL))
+ {
+ zonecut = savezonecut(&fzonecut, name);
+ if (!OPTOUT(nsec3flags) ||
+ secure(name, node))
+ {
+ found = true;
+ }
+ } else if (has_dname(gdb, gversion, node)) {
+ zonecut = savezonecut(&fzonecut, name);
+ found = true;
+ } else {
+ found = true;
+ }
+ }
+ }
+
+ if (!found) {
+ dumpnode(name, node);
+ dns_db_detachnode(gdb, &node);
+ }
+
+ next:
+ result = dns_dbiterator_next(gdbiter);
+ if (result == ISC_R_NOMORE) {
+ atomic_store(&finished, true);
+ break;
+ } else if (result != ISC_R_SUCCESS) {
+ fatal("failure iterating database: %s",
+ isc_result_totext(result));
+ }
+ }
+ if (!found) {
+ ended++;
+ if (ended == ntasks) {
+ isc_task_detach(&task);
+ isc_app_shutdown();
+ }
+ isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
+ goto unlock;
+ }
+ sevent = (sevent_t *)isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
+ sign, NULL, sizeof(sevent_t));
+
+ sevent->node = node;
+ sevent->fname = fname;
+ isc_task_send(worker, ISC_EVENT_PTR(&sevent));
+unlock:
+ UNLOCK(&namelock);
+}
+
+/*%
+ * Start a worker task
+ */
+static void
+startworker(isc_task_t *task, isc_event_t *event) {
+ isc_task_t *worker;
+
+ worker = (isc_task_t *)event->ev_arg;
+ assignwork(task, worker);
+ isc_event_free(&event);
+}
+
+/*%
+ * Write a node to the output file, and restart the worker task.
+ */
+static void
+writenode(isc_task_t *task, isc_event_t *event) {
+ isc_task_t *worker;
+ sevent_t *sevent = (sevent_t *)event;
+
+ worker = (isc_task_t *)event->ev_sender;
+ dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
+ cleannode(gdb, gversion, sevent->node);
+ dns_db_detachnode(gdb, &sevent->node);
+ isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
+ assignwork(task, worker);
+ isc_event_free(&event);
+}
+
+/*%
+ * Sign a database node.
+ */
+static void
+sign(isc_task_t *task, isc_event_t *event) {
+ dns_fixedname_t *fname;
+ dns_dbnode_t *node;
+ sevent_t *sevent, *wevent;
+
+ sevent = (sevent_t *)event;
+ node = sevent->node;
+ fname = sevent->fname;
+ isc_event_free(&event);
+
+ signname(node, dns_fixedname_name(fname));
+ wevent = (sevent_t *)isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
+ writenode, NULL,
+ sizeof(sevent_t));
+ wevent->node = node;
+ wevent->fname = fname;
+ isc_task_send(main_task, ISC_EVENT_PTR(&wevent));
+}
+
+/*%
+ * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
+ */
+static void
+add_ds(dns_name_t *name, dns_dbnode_t *node, uint32_t nsttl) {
+ dns_rdataset_t dsset;
+ dns_rdataset_t sigdsset;
+ isc_result_t result;
+
+ dns_rdataset_init(&dsset);
+ dns_rdataset_init(&sigdsset);
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds, 0,
+ 0, &dsset, &sigdsset);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&dsset);
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ dns_rdatatype_ds, 0);
+ check_result(result, "dns_db_deleterdataset");
+ }
+
+ result = loadds(name, nsttl, &dsset);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_db_addrdataset(gdb, node, gversion, 0, &dsset, 0,
+ NULL);
+ check_result(result, "dns_db_addrdataset");
+ dns_rdataset_disassociate(&dsset);
+ if (dns_rdataset_isassociated(&sigdsset)) {
+ dns_rdataset_disassociate(&sigdsset);
+ }
+ } else if (dns_rdataset_isassociated(&sigdsset)) {
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_ds);
+ check_result(result, "dns_db_deleterdataset");
+ dns_rdataset_disassociate(&sigdsset);
+ }
+}
+
+/*
+ * Remove records of the given type and their signatures.
+ */
+static void
+remove_records(dns_dbnode_t *node, dns_rdatatype_t which, bool checknsec) {
+ isc_result_t result;
+ dns_rdatatype_t type, covers;
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+
+ /*
+ * Delete any records of the given type at the apex.
+ */
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter))
+ {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ type = rdataset.type;
+ covers = rdataset.covers;
+ dns_rdataset_disassociate(&rdataset);
+ if (type == which || covers == which) {
+ if (which == dns_rdatatype_nsec && checknsec &&
+ !update_chain)
+ {
+ fatal("Zone contains NSEC records. Use -u "
+ "to update to NSEC3.");
+ }
+ if (which == dns_rdatatype_nsec3param && checknsec &&
+ !update_chain)
+ {
+ fatal("Zone contains NSEC3 chains. Use -u "
+ "to update to NSEC.");
+ }
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ type, covers);
+ check_result(result, "dns_db_deleterdataset()");
+ }
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+}
+
+/*
+ * Remove signatures covering the given type. If type == 0,
+ * then remove all signatures, unless this is a delegation, in
+ * which case remove all signatures except for DS or nsec_datatype
+ */
+static void
+remove_sigs(dns_dbnode_t *node, bool delegation, dns_rdatatype_t which) {
+ isc_result_t result;
+ dns_rdatatype_t type, covers;
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter))
+ {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ type = rdataset.type;
+ covers = rdataset.covers;
+ dns_rdataset_disassociate(&rdataset);
+
+ if (type != dns_rdatatype_rrsig) {
+ continue;
+ }
+
+ if (which == 0 && delegation &&
+ (dns_rdatatype_atparent(covers) ||
+ (nsec_datatype == dns_rdatatype_nsec &&
+ covers == nsec_datatype)))
+ {
+ continue;
+ }
+
+ if (which != 0 && covers != which) {
+ continue;
+ }
+
+ result = dns_db_deleterdataset(gdb, node, gversion, type,
+ covers);
+ check_result(result, "dns_db_deleterdataset()");
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+}
+
+/*%
+ * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
+ */
+static void
+nsecify(void) {
+ dns_dbiterator_t *dbiter = NULL;
+ dns_dbnode_t *node = NULL, *nextnode = NULL;
+ dns_fixedname_t fname, fnextname, fzonecut;
+ dns_name_t *name, *nextname, *zonecut;
+ dns_rdataset_t rdataset;
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_rdatatype_t type, covers;
+ bool done = false;
+ isc_result_t result;
+ uint32_t nsttl = 0;
+
+ dns_rdataset_init(&rdataset);
+ name = dns_fixedname_initname(&fname);
+ nextname = dns_fixedname_initname(&fnextname);
+ zonecut = NULL;
+
+ /*
+ * Remove any NSEC3 chains.
+ */
+ result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+ for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS;
+ result = dns_dbiterator_next(dbiter))
+ {
+ result = dns_dbiterator_current(dbiter, &node, name);
+ check_dns_dbiterator_current(result);
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, 0,
+ &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter))
+ {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ type = rdataset.type;
+ covers = rdataset.covers;
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ type, covers);
+ check_result(result, "dns_db_deleterdataset(nsec3param/"
+ "rrsig)");
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+ dns_db_detachnode(gdb, &node);
+ }
+ dns_dbiterator_destroy(&dbiter);
+
+ result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+
+ while (!done) {
+ result = dns_dbiterator_current(dbiter, &node, name);
+ check_dns_dbiterator_current(result);
+ /*
+ * Skip out-of-zone records.
+ */
+ if (!dns_name_issubdomain(name, gorigin)) {
+ result = dns_dbiterator_next(dbiter);
+ if (result == ISC_R_NOMORE) {
+ done = true;
+ } else {
+ check_result(result, "dns_dbiterator_next()");
+ }
+ dns_db_detachnode(gdb, &node);
+ continue;
+ }
+
+ if (dns_name_equal(name, gorigin)) {
+ remove_records(node, dns_rdatatype_nsec3param, true);
+ /* Clean old rrsigs at apex. */
+ (void)active_node(node);
+ }
+
+ if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) {
+ zonecut = savezonecut(&fzonecut, name);
+ remove_sigs(node, true, 0);
+ if (generateds) {
+ add_ds(name, node, nsttl);
+ }
+ } else if (has_dname(gdb, gversion, node)) {
+ zonecut = savezonecut(&fzonecut, name);
+ }
+
+ result = dns_dbiterator_next(dbiter);
+ nextnode = NULL;
+ while (result == ISC_R_SUCCESS) {
+ bool active = false;
+ result = dns_dbiterator_current(dbiter, &nextnode,
+ nextname);
+ check_dns_dbiterator_current(result);
+ active = active_node(nextnode);
+ if (!active) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (!dns_name_issubdomain(nextname, gorigin) ||
+ (zonecut != NULL &&
+ dns_name_issubdomain(nextname, zonecut)))
+ {
+ remove_sigs(nextnode, false, 0);
+ remove_records(nextnode, dns_rdatatype_nsec,
+ false);
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ dns_db_detachnode(gdb, &nextnode);
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ dns_name_clone(gorigin, nextname);
+ done = true;
+ } else if (result != ISC_R_SUCCESS) {
+ fatal("iterating through the database failed: %s",
+ isc_result_totext(result));
+ }
+ dns_dbiterator_pause(dbiter);
+ result = dns_nsec_build(gdb, gversion, node, nextname,
+ zone_soa_min_ttl);
+ check_result(result, "dns_nsec_build()");
+ dns_db_detachnode(gdb, &node);
+ }
+
+ dns_dbiterator_destroy(&dbiter);
+}
+
+static void
+addnsec3param(const unsigned char *salt, size_t salt_len,
+ dns_iterations_t iterations) {
+ dns_dbnode_t *node = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ unsigned char nsec3parambuf[5 + 255];
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+
+ nsec3param.common.rdclass = gclass;
+ nsec3param.common.rdtype = dns_rdatatype_nsec3param;
+ ISC_LINK_INIT(&nsec3param.common, link);
+ nsec3param.mctx = NULL;
+ nsec3param.flags = 0;
+ nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
+ nsec3param.iterations = iterations;
+ nsec3param.salt_length = (unsigned char)salt_len;
+ DE_CONST(salt, nsec3param.salt);
+
+ isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
+ result = dns_rdata_fromstruct(&rdata, gclass, dns_rdatatype_nsec3param,
+ &nsec3param, &b);
+ check_result(result, "dns_rdata_fromstruct()");
+ dns_rdatalist_init(&rdatalist);
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.type = rdata.type;
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+ result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
+ check_result(result, "dns_rdatalist_tordataset()");
+
+ result = dns_db_findnode(gdb, gorigin, true, &node);
+ check_result(result, "dns_db_findnode(gorigin)");
+
+ /*
+ * Delete any current NSEC3PARAM records.
+ */
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ dns_rdatatype_nsec3param, 0);
+ if (result == DNS_R_UNCHANGED) {
+ result = ISC_R_SUCCESS;
+ }
+ check_result(result, "dddnsec3param: dns_db_deleterdataset()");
+
+ result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
+ DNS_DBADD_MERGE, NULL);
+ if (result == DNS_R_UNCHANGED) {
+ result = ISC_R_SUCCESS;
+ }
+ check_result(result, "addnsec3param: dns_db_addrdataset()");
+ dns_db_detachnode(gdb, &node);
+}
+
+static void
+addnsec3(dns_name_t *name, dns_dbnode_t *node, const unsigned char *salt,
+ size_t salt_len, unsigned int iterations, hashlist_t *hashlist,
+ dns_ttl_t ttl) {
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH];
+ const unsigned char *nexthash;
+ unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
+ dns_fixedname_t hashname;
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ dns_dbnode_t *nsec3node = NULL;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ size_t hash_len;
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+
+ dns_fixedname_init(&hashname);
+ dns_rdataset_init(&rdataset);
+
+ dns_name_downcase(name, name, NULL);
+ result = dns_nsec3_hashname(&hashname, hash, &hash_len, name, gorigin,
+ dns_hash_sha1, iterations, salt, salt_len);
+ check_result(result, "addnsec3: dns_nsec3_hashname()");
+ nexthash = hashlist_findnext(hashlist, hash);
+ result = dns_nsec3_buildrdata(
+ gdb, gversion, node,
+ unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1, nsec3flags,
+ iterations, salt, salt_len, nexthash, ISC_SHA1_DIGESTLENGTH,
+ nsec3buffer, &rdata);
+ check_result(result, "addnsec3: dns_nsec3_buildrdata()");
+ dns_rdatalist_init(&rdatalist);
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.type = rdata.type;
+ rdatalist.ttl = ttl;
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+ result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
+ check_result(result, "dns_rdatalist_tordataset()");
+ result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname), true,
+ &nsec3node);
+ check_result(result, "addnsec3: dns_db_findnode()");
+ result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset, 0,
+ NULL);
+ if (result == DNS_R_UNCHANGED) {
+ result = ISC_R_SUCCESS;
+ }
+ check_result(result, "addnsec3: dns_db_addrdataset()");
+ dns_db_detachnode(gdb, &nsec3node);
+}
+
+/*%
+ * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
+ *
+ * Extract the hash from the first label of 'name' then see if it
+ * is in hashlist. If 'name' is not in the hashlist then delete the
+ * any NSEC3 records which have the same parameters as the chain we
+ * are building.
+ *
+ * XXXMPA Should we also check that it of the form &lt;hash&gt;.&lt;origin&gt;?
+ */
+static void
+nsec3clean(dns_name_t *name, dns_dbnode_t *node, unsigned int hashalg,
+ unsigned int iterations, const unsigned char *salt, size_t salt_len,
+ hashlist_t *hashlist) {
+ dns_label_t label;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata, delrdata;
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset, delrdataset;
+ bool delete_rrsigs = false;
+ isc_buffer_t target;
+ isc_result_t result;
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
+ bool exists;
+
+ /*
+ * Get the first label.
+ */
+ dns_name_getlabel(name, 0, &label);
+
+ /*
+ * We want just the label contents.
+ */
+ isc_region_consume(&label, 1);
+
+ /*
+ * Decode base32hex string.
+ */
+ isc_buffer_init(&target, hash, sizeof(hash) - 1);
+ result = isc_base32hex_decoderegion(&label, &target);
+ if (result != ISC_R_SUCCESS) {
+ return;
+ }
+
+ hash[isc_buffer_usedlength(&target)] = 0;
+
+ exists = hashlist_exists(hashlist, hash);
+
+ /*
+ * Verify that the NSEC3 parameters match the current ones
+ * otherwise we are dealing with a different NSEC3 chain.
+ */
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&delrdataset);
+
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return;
+ }
+
+ /*
+ * Delete any NSEC3 records which are not part of the current
+ * NSEC3 chain.
+ */
+ for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ if (exists && nsec3.hash == hashalg &&
+ nsec3.iterations == iterations &&
+ nsec3.salt_length == salt_len &&
+ isc_safe_memequal(nsec3.salt, salt, salt_len))
+ {
+ continue;
+ }
+ dns_rdatalist_init(&rdatalist);
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.type = rdata.type;
+ if (set_maxttl) {
+ rdatalist.ttl = ISC_MIN(rdataset.ttl, maxttl);
+ }
+ dns_rdata_init(&delrdata);
+ dns_rdata_clone(&rdata, &delrdata);
+ ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
+ result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
+ check_result(result, "dns_rdatalist_tordataset()");
+ result = dns_db_subtractrdataset(gdb, node, gversion,
+ &delrdataset, 0, NULL);
+ dns_rdataset_disassociate(&delrdataset);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET) {
+ check_result(result, "dns_db_subtractrdataset(NSEC3)");
+ }
+ delete_rrsigs = true;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_NOMORE) {
+ check_result(result, "dns_rdataset_first/next");
+ }
+
+ if (!delete_rrsigs) {
+ return;
+ }
+ /*
+ * Delete the NSEC3 RRSIGs
+ */
+ result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_rrsig,
+ dns_rdatatype_nsec3);
+ if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) {
+ check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
+ }
+}
+
+static void
+rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset, dns_diff_t *add,
+ dns_diff_t *del) {
+ isc_result_t result;
+ unsigned int count1 = 0;
+ dns_rdataset_t tmprdataset;
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+
+ dns_name_format(name, namestr, sizeof(namestr));
+ dns_rdatatype_format(rdataset->type, typestr, sizeof(typestr));
+
+ dns_rdataset_init(&tmprdataset);
+ for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ dns_rdata_t rdata1 = DNS_RDATA_INIT;
+ unsigned int count2 = 0;
+
+ count1++;
+ dns_rdataset_current(rdataset, &rdata1);
+ dns_rdataset_clone(rdataset, &tmprdataset);
+ for (result = dns_rdataset_first(&tmprdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&tmprdataset))
+ {
+ dns_rdata_t rdata2 = DNS_RDATA_INIT;
+ dns_difftuple_t *tuple = NULL;
+ count2++;
+ dns_rdataset_current(&tmprdataset, &rdata2);
+ if (count1 < count2 &&
+ dns_rdata_casecompare(&rdata1, &rdata2) == 0)
+ {
+ vbprintf(2, "removing duplicate at %s/%s\n",
+ namestr, typestr);
+ result = dns_difftuple_create(
+ mctx, DNS_DIFFOP_DELRESIGN, name,
+ rdataset->ttl, &rdata2, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(del, &tuple);
+ } else if (set_maxttl && rdataset->ttl > maxttl) {
+ vbprintf(2,
+ "reducing ttl of %s/%s "
+ "from %d to %d\n",
+ namestr, typestr, rdataset->ttl,
+ maxttl);
+ result = dns_difftuple_create(
+ mctx, DNS_DIFFOP_DELRESIGN, name,
+ rdataset->ttl, &rdata2, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(del, &tuple);
+ tuple = NULL;
+ result = dns_difftuple_create(
+ mctx, DNS_DIFFOP_ADDRESIGN, name,
+ maxttl, &rdata2, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(add, &tuple);
+ }
+ }
+ dns_rdataset_disassociate(&tmprdataset);
+ }
+}
+
+static void
+cleanup_zone(void) {
+ isc_result_t result;
+ dns_dbiterator_t *dbiter = NULL;
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_diff_t add, del;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+
+ dns_diff_init(mctx, &add);
+ dns_diff_init(mctx, &del);
+ name = dns_fixedname_initname(&fname);
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_createiterator(gdb, 0, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS;
+ result = dns_dbiterator_next(dbiter))
+ {
+ result = dns_dbiterator_current(dbiter, &node, name);
+ check_dns_dbiterator_current(result);
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, 0,
+ &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter))
+ {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ rrset_cleanup(name, &rdataset, &add, &del);
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (result != ISC_R_NOMORE) {
+ fatal("rdatasets iteration failed.");
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+ dns_db_detachnode(gdb, &node);
+ }
+ if (result != ISC_R_NOMORE) {
+ fatal("zone iteration failed.");
+ }
+
+ result = dns_diff_applysilently(&del, gdb, gversion);
+ check_result(result, "dns_diff_applysilently");
+
+ result = dns_diff_applysilently(&add, gdb, gversion);
+ check_result(result, "dns_diff_applysilently");
+
+ dns_diff_clear(&del);
+ dns_diff_clear(&add);
+ dns_dbiterator_destroy(&dbiter);
+}
+
+/*
+ * Generate NSEC3 records for the zone.
+ */
+static void
+nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
+ const unsigned char *salt, size_t salt_len, hashlist_t *hashlist) {
+ dns_dbiterator_t *dbiter = NULL;
+ dns_dbnode_t *node = NULL, *nextnode = NULL;
+ dns_fixedname_t fname, fnextname, fzonecut;
+ dns_name_t *name, *nextname, *zonecut;
+ dns_rdataset_t rdataset;
+ int order;
+ bool active;
+ bool done = false;
+ isc_result_t result;
+ uint32_t nsttl = 0;
+ unsigned int count, nlabels;
+
+ dns_rdataset_init(&rdataset);
+ name = dns_fixedname_initname(&fname);
+ nextname = dns_fixedname_initname(&fnextname);
+ zonecut = NULL;
+
+ /*
+ * Walk the zone generating the hash names.
+ */
+ result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+
+ while (!done) {
+ result = dns_dbiterator_current(dbiter, &node, name);
+ check_dns_dbiterator_current(result);
+ /*
+ * Skip out-of-zone records.
+ */
+ if (!dns_name_issubdomain(name, gorigin)) {
+ result = dns_dbiterator_next(dbiter);
+ if (result == ISC_R_NOMORE) {
+ done = true;
+ } else {
+ check_result(result, "dns_dbiterator_next()");
+ }
+ dns_db_detachnode(gdb, &node);
+ continue;
+ }
+
+ if (dns_name_equal(name, gorigin)) {
+ remove_records(node, dns_rdatatype_nsec, true);
+ /* Clean old rrsigs at apex. */
+ (void)active_node(node);
+ }
+
+ if (has_dname(gdb, gversion, node)) {
+ zonecut = savezonecut(&fzonecut, name);
+ }
+
+ result = dns_dbiterator_next(dbiter);
+ nextnode = NULL;
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbiter, &nextnode,
+ nextname);
+ check_dns_dbiterator_current(result);
+ active = active_node(nextnode);
+ if (!active) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (!dns_name_issubdomain(nextname, gorigin) ||
+ (zonecut != NULL &&
+ dns_name_issubdomain(nextname, zonecut)))
+ {
+ remove_sigs(nextnode, false, 0);
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (is_delegation(gdb, gversion, gorigin, nextname,
+ nextnode, &nsttl))
+ {
+ zonecut = savezonecut(&fzonecut, nextname);
+ remove_sigs(nextnode, true, 0);
+ if (generateds) {
+ add_ds(nextname, nextnode, nsttl);
+ }
+ if (OPTOUT(nsec3flags) &&
+ !secure(nextname, nextnode))
+ {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ } else if (has_dname(gdb, gversion, nextnode)) {
+ zonecut = savezonecut(&fzonecut, nextname);
+ }
+ dns_db_detachnode(gdb, &nextnode);
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ dns_name_copy(gorigin, nextname);
+ done = true;
+ } else if (result != ISC_R_SUCCESS) {
+ fatal("iterating through the database failed: %s",
+ isc_result_totext(result));
+ }
+ dns_name_downcase(name, name, NULL);
+ hashlist_add_dns_name(hashlist, name, hashalg, iterations, salt,
+ salt_len, false);
+ dns_db_detachnode(gdb, &node);
+ /*
+ * Add hashes for empty nodes. Use closest encloser logic.
+ * The closest encloser either has data or is a empty
+ * node for another <name,nextname> span so we don't add
+ * it here. Empty labels on nextname are within the span.
+ */
+ dns_name_downcase(nextname, nextname, NULL);
+ dns_name_fullcompare(name, nextname, &order, &nlabels);
+ addnowildcardhash(hashlist, name, hashalg, iterations, salt,
+ salt_len);
+ count = dns_name_countlabels(nextname);
+ while (count > nlabels + 1) {
+ count--;
+ dns_name_split(nextname, count, NULL, nextname);
+ hashlist_add_dns_name(hashlist, nextname, hashalg,
+ iterations, salt, salt_len,
+ false);
+ addnowildcardhash(hashlist, nextname, hashalg,
+ iterations, salt, salt_len);
+ }
+ }
+ dns_dbiterator_destroy(&dbiter);
+
+ /*
+ * We have all the hashes now so we can sort them.
+ */
+ hashlist_sort(hashlist);
+
+ /*
+ * Check for duplicate hashes. If found the salt needs to
+ * be changed.
+ */
+ if (hashlist_hasdup(hashlist)) {
+ fatal("Duplicate hash detected. Pick a different salt.");
+ }
+
+ /*
+ * Generate the nsec3 records.
+ */
+ zonecut = NULL;
+ done = false;
+
+ addnsec3param(salt, salt_len, iterations);
+
+ /*
+ * Clean out NSEC3 records which don't match this chain.
+ */
+ result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS;
+ result = dns_dbiterator_next(dbiter))
+ {
+ result = dns_dbiterator_current(dbiter, &node, name);
+ check_dns_dbiterator_current(result);
+ nsec3clean(name, node, hashalg, iterations, salt, salt_len,
+ hashlist);
+ dns_db_detachnode(gdb, &node);
+ }
+ dns_dbiterator_destroy(&dbiter);
+
+ /*
+ * Generate / complete the new chain.
+ */
+ result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+
+ while (!done) {
+ result = dns_dbiterator_current(dbiter, &node, name);
+ check_dns_dbiterator_current(result);
+ /*
+ * Skip out-of-zone records.
+ */
+ if (!dns_name_issubdomain(name, gorigin)) {
+ result = dns_dbiterator_next(dbiter);
+ if (result == ISC_R_NOMORE) {
+ done = true;
+ } else {
+ check_result(result, "dns_dbiterator_next()");
+ }
+ dns_db_detachnode(gdb, &node);
+ continue;
+ }
+
+ if (has_dname(gdb, gversion, node)) {
+ zonecut = savezonecut(&fzonecut, name);
+ }
+
+ result = dns_dbiterator_next(dbiter);
+ nextnode = NULL;
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbiter, &nextnode,
+ nextname);
+ check_dns_dbiterator_current(result);
+ active = active_node(nextnode);
+ if (!active) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (!dns_name_issubdomain(nextname, gorigin) ||
+ (zonecut != NULL &&
+ dns_name_issubdomain(nextname, zonecut)))
+ {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (is_delegation(gdb, gversion, gorigin, nextname,
+ nextnode, NULL))
+ {
+ zonecut = savezonecut(&fzonecut, nextname);
+ if (OPTOUT(nsec3flags) &&
+ !secure(nextname, nextnode))
+ {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ } else if (has_dname(gdb, gversion, nextnode)) {
+ zonecut = savezonecut(&fzonecut, nextname);
+ }
+ dns_db_detachnode(gdb, &nextnode);
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ dns_name_copy(gorigin, nextname);
+ done = true;
+ } else if (result != ISC_R_SUCCESS) {
+ fatal("iterating through the database failed: %s",
+ isc_result_totext(result));
+ }
+ /*
+ * We need to pause here to release the lock on the database.
+ */
+ dns_dbiterator_pause(dbiter);
+ addnsec3(name, node, salt, salt_len, iterations, hashlist,
+ zone_soa_min_ttl);
+ dns_db_detachnode(gdb, &node);
+ /*
+ * Add NSEC3's for empty nodes. Use closest encloser logic.
+ */
+ dns_name_fullcompare(name, nextname, &order, &nlabels);
+ count = dns_name_countlabels(nextname);
+ while (count > nlabels + 1) {
+ count--;
+ dns_name_split(nextname, count, NULL, nextname);
+ addnsec3(nextname, NULL, salt, salt_len, iterations,
+ hashlist, zone_soa_min_ttl);
+ }
+ }
+ dns_dbiterator_destroy(&dbiter);
+}
+
+/*%
+ * Load the zone file from disk
+ */
+static void
+loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
+ isc_buffer_t b;
+ int len;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result;
+
+ len = strlen(origin);
+ isc_buffer_init(&b, origin, len);
+ isc_buffer_add(&b, len);
+
+ name = dns_fixedname_initname(&fname);
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed converting name '%s' to dns format: %s", origin,
+ isc_result_totext(result));
+ }
+
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0,
+ NULL, db);
+ check_result(result, "dns_db_create()");
+
+ result = dns_db_load(*db, file, inputformat, 0);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
+ fatal("failed loading zone from '%s': %s", file,
+ isc_result_totext(result));
+ }
+}
+
+/*%
+ * Finds all public zone keys in the zone, and attempts to load the
+ * private keys from disk.
+ */
+static void
+loadzonekeys(bool preserve_keys, bool load_public) {
+ dns_dbnode_t *node;
+ dns_dbversion_t *currentversion = NULL;
+ isc_result_t result;
+ dns_rdataset_t rdataset, keysigs, soasigs;
+
+ node = NULL;
+ result = dns_db_findnode(gdb, gorigin, false, &node);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to find the zone's origin: %s",
+ isc_result_totext(result));
+ }
+
+ dns_db_currentversion(gdb, &currentversion);
+
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&soasigs);
+ dns_rdataset_init(&keysigs);
+
+ /* Make note of the keys which signed the SOA, if any */
+ result = dns_db_findrdataset(gdb, node, currentversion,
+ dns_rdatatype_soa, 0, 0, &rdataset,
+ &soasigs);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ /* Preserve the TTL of the DNSKEY RRset, if any */
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_db_findrdataset(gdb, node, currentversion,
+ dns_rdatatype_dnskey, 0, 0, &rdataset,
+ &keysigs);
+
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ if (set_keyttl && keyttl != rdataset.ttl) {
+ fprintf(stderr,
+ "User-specified TTL %u conflicts "
+ "with existing DNSKEY RRset TTL.\n",
+ keyttl);
+ fprintf(stderr,
+ "Imported keys will use the RRSet "
+ "TTL %u instead.\n",
+ rdataset.ttl);
+ }
+ keyttl = rdataset.ttl;
+
+ /* Load keys corresponding to the existing DNSKEY RRset. */
+ result = dns_dnssec_keylistfromrdataset(
+ gorigin, directory, mctx, &rdataset, &keysigs, &soasigs,
+ preserve_keys, load_public, &keylist);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to load the zone keys: %s",
+ isc_result_totext(result));
+ }
+
+cleanup:
+ if (dns_rdataset_isassociated(&rdataset)) {
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (dns_rdataset_isassociated(&keysigs)) {
+ dns_rdataset_disassociate(&keysigs);
+ }
+ if (dns_rdataset_isassociated(&soasigs)) {
+ dns_rdataset_disassociate(&soasigs);
+ }
+ dns_db_detachnode(gdb, &node);
+ dns_db_closeversion(gdb, &currentversion, false);
+}
+
+static void
+loadexplicitkeys(char *keyfiles[], int n, bool setksk) {
+ isc_result_t result;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dns_dnsseckey_t *key = NULL;
+ dst_key_t *newkey = NULL;
+
+ result = dst_key_fromnamedfile(
+ keyfiles[i], directory,
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &newkey);
+ if (result != ISC_R_SUCCESS) {
+ fatal("cannot load dnskey %s: %s", keyfiles[i],
+ isc_result_totext(result));
+ }
+
+ if (!dns_name_equal(gorigin, dst_key_name(newkey))) {
+ fatal("key %s not at origin\n", keyfiles[i]);
+ }
+
+ if (!dst_key_isprivate(newkey)) {
+ fatal("cannot sign zone with non-private dnskey %s",
+ keyfiles[i]);
+ }
+
+ /* Skip any duplicates */
+ for (key = ISC_LIST_HEAD(keylist); key != NULL;
+ key = ISC_LIST_NEXT(key, link))
+ {
+ if (dst_key_id(key->key) == dst_key_id(newkey) &&
+ dst_key_alg(key->key) == dst_key_alg(newkey))
+ {
+ break;
+ }
+ }
+
+ if (key == NULL) {
+ /* We haven't seen this key before */
+ dns_dnsseckey_create(mctx, &newkey, &key);
+ ISC_LIST_APPEND(keylist, key, link);
+ key->source = dns_keysource_user;
+ } else {
+ dst_key_free(&key->key);
+ key->key = newkey;
+ }
+
+ key->force_publish = true;
+ key->force_sign = true;
+
+ if (setksk) {
+ key->ksk = true;
+ }
+ }
+}
+
+static void
+report(const char *format, ...) {
+ if (!quiet) {
+ FILE *out = output_stdout ? stderr : stdout;
+ char buf[4096];
+ va_list args;
+
+ va_start(args, format);
+ vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+ fprintf(out, "%s\n", buf);
+ }
+}
+
+static void
+clear_keylist(dns_dnsseckeylist_t *list) {
+ dns_dnsseckey_t *key;
+ while (!ISC_LIST_EMPTY(*list)) {
+ key = ISC_LIST_HEAD(*list);
+ ISC_LIST_UNLINK(*list, key, link);
+ dns_dnsseckey_destroy(mctx, &key);
+ }
+}
+
+static void
+build_final_keylist(void) {
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_diff_t diff;
+ dns_dnsseckeylist_t rmkeys, matchkeys;
+ char name[DNS_NAME_FORMATSIZE];
+ dns_rdataset_t cdsset, cdnskeyset, soaset;
+
+ ISC_LIST_INIT(rmkeys);
+ ISC_LIST_INIT(matchkeys);
+
+ dns_rdataset_init(&soaset);
+ dns_rdataset_init(&cdsset);
+ dns_rdataset_init(&cdnskeyset);
+
+ /*
+ * Find keys that match this zone in the key repository.
+ */
+ result = dns_dnssec_findmatchingkeys(gorigin, directory, now, mctx,
+ &matchkeys);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ }
+ check_result(result, "dns_dnssec_findmatchingkeys");
+
+ result = dns_db_newversion(gdb, &ver);
+ check_result(result, "dns_db_newversion");
+
+ result = dns_db_getoriginnode(gdb, &node);
+ check_result(result, "dns_db_getoriginnode");
+
+ /* Get the CDS rdataset */
+ result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cds,
+ dns_rdatatype_none, 0, &cdsset, NULL);
+ if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
+ dns_rdataset_disassociate(&cdsset);
+ }
+
+ /* Get the CDNSKEY rdataset */
+ result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cdnskey,
+ dns_rdatatype_none, 0, &cdnskeyset, NULL);
+ if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
+ dns_rdataset_disassociate(&cdnskeyset);
+ }
+
+ dns_diff_init(mctx, &diff);
+
+ /*
+ * Update keylist with information from from the key repository.
+ */
+ dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
+ &diff, mctx, report);
+
+ /*
+ * Update keylist with sync records.
+ */
+ dns_dnssec_syncupdate(&keylist, &rmkeys, &cdsset, &cdnskeyset, now,
+ keyttl, &diff, mctx);
+
+ dns_name_format(gorigin, name, sizeof(name));
+
+ result = dns_diff_applysilently(&diff, gdb, ver);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to update DNSKEY RRset at node '%s': %s", name,
+ isc_result_totext(result));
+ }
+
+ dns_db_detachnode(gdb, &node);
+ dns_db_closeversion(gdb, &ver, true);
+
+ dns_diff_clear(&diff);
+
+ if (dns_rdataset_isassociated(&cdsset)) {
+ dns_rdataset_disassociate(&cdsset);
+ }
+ if (dns_rdataset_isassociated(&cdnskeyset)) {
+ dns_rdataset_disassociate(&cdnskeyset);
+ }
+
+ clear_keylist(&rmkeys);
+ clear_keylist(&matchkeys);
+}
+
+static void
+warnifallksk(dns_db_t *db) {
+ dns_dbversion_t *currentversion = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ dns_rdata_dnskey_t dnskey;
+ bool have_non_ksk = false;
+
+ dns_db_currentversion(db, &currentversion);
+
+ result = dns_db_findnode(db, gorigin, false, &node);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to find the zone's origin: %s",
+ isc_result_totext(result));
+ }
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, currentversion,
+ dns_rdatatype_dnskey, 0, 0, &rdataset,
+ NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to find keys at the zone apex: %s",
+ isc_result_totext(result));
+ }
+ result = dns_rdataset_first(&rdataset);
+ check_result(result, "dns_rdataset_first");
+ while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
+ have_non_ksk = true;
+ result = ISC_R_NOMORE;
+ } else {
+ result = dns_rdataset_next(&rdataset);
+ }
+ dns_rdata_freestruct(&dnskey);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &node);
+ dns_db_closeversion(db, &currentversion, false);
+ if (!have_non_ksk && !ignore_kskflag) {
+ if (disable_zone_check) {
+ fprintf(stderr,
+ "%s: warning: No non-KSK DNSKEY found; "
+ "supply a ZSK or use '-z'.\n",
+ program);
+ } else {
+ fatal("No non-KSK DNSKEY found; "
+ "supply a ZSK or use '-z'.");
+ }
+ }
+}
+
+static void
+set_nsec3params(bool update, bool set_salt, bool set_optout, bool set_iter) {
+ isc_result_t result;
+ dns_dbversion_t *ver = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec3_t nsec3;
+ dns_fixedname_t fname;
+ dns_name_t *hashname;
+ unsigned char orig_salt[255];
+ size_t orig_saltlen;
+ dns_hash_t orig_hash;
+ uint16_t orig_iter;
+
+ dns_db_currentversion(gdb, &ver);
+ dns_rdataset_init(&rdataset);
+
+ orig_saltlen = sizeof(orig_salt);
+ result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
+ &orig_iter, orig_salt,
+ &orig_saltlen);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ nsec_datatype = dns_rdatatype_nsec3;
+
+ if (!update && set_salt) {
+ if (salt_length != orig_saltlen ||
+ !isc_safe_memequal(saltbuf, orig_salt, salt_length))
+ {
+ fatal("An NSEC3 chain exists with a different salt. "
+ "Use -u to update it.");
+ }
+ } else if (!set_salt) {
+ salt_length = orig_saltlen;
+ memmove(saltbuf, orig_salt, orig_saltlen);
+ gsalt = saltbuf;
+ }
+
+ if (!update && set_iter) {
+ if (nsec3iter != orig_iter) {
+ fatal("An NSEC3 chain exists with different "
+ "iterations. Use -u to update it.");
+ }
+ } else if (!set_iter) {
+ nsec3iter = orig_iter;
+ }
+
+ /*
+ * Find an NSEC3 record to get the current OPTOUT value.
+ * (This assumes all NSEC3 records agree.)
+ */
+
+ hashname = dns_fixedname_initname(&fname);
+ result = dns_nsec3_hashname(&fname, NULL, NULL, gorigin, gorigin,
+ dns_hash_sha1, orig_iter, orig_salt,
+ orig_saltlen);
+ check_result(result, "dns_nsec3_hashname");
+
+ result = dns_db_findnsec3node(gdb, hashname, false, &node);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3, 0, 0,
+ &rdataset, NULL);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ result = dns_rdataset_first(&rdataset);
+ check_result(result, "dns_rdataset_first");
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ if (!update && set_optout) {
+ if (nsec3flags != nsec3.flags) {
+ fatal("An NSEC3 chain exists with%s OPTOUT. "
+ "Use -u -%s to %s it.",
+ OPTOUT(nsec3.flags) ? "" : "out",
+ OPTOUT(nsec3.flags) ? "AA" : "A",
+ OPTOUT(nsec3.flags) ? "clear" : "set");
+ }
+ } else if (!set_optout) {
+ nsec3flags = nsec3.flags;
+ }
+
+ dns_rdata_freestruct(&nsec3);
+
+cleanup:
+ if (dns_rdataset_isassociated(&rdataset)) {
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (node != NULL) {
+ dns_db_detachnode(gdb, &node);
+ }
+ dns_db_closeversion(gdb, &ver, false);
+}
+
+static void
+writeset(const char *prefix, dns_rdatatype_t type) {
+ char *filename;
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_db_t *db = NULL;
+ dns_dbversion_t *dbversion = NULL;
+ dns_diff_t diff;
+ dns_difftuple_t *tuple = NULL;
+ dns_name_t *name;
+ dns_rdata_t rdata, ds;
+ bool have_ksk = false;
+ bool have_non_ksk = false;
+ isc_buffer_t b;
+ isc_buffer_t namebuf;
+ isc_region_t r;
+ isc_result_t result;
+ dns_dnsseckey_t *key, *curr;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+ unsigned char keybuf[DST_KEY_MAXSIZE];
+ unsigned int filenamelen;
+ const dns_master_style_t *style = (type == dns_rdatatype_dnskey)
+ ? masterstyle
+ : dsstyle;
+
+ isc_buffer_init(&namebuf, namestr, sizeof(namestr));
+ result = dns_name_tofilenametext(gorigin, false, &namebuf);
+ check_result(result, "dns_name_tofilenametext");
+ isc_buffer_putuint8(&namebuf, 0);
+ filenamelen = strlen(prefix) + strlen(namestr) + 1;
+ if (dsdir != NULL) {
+ filenamelen += strlen(dsdir) + 1;
+ }
+ filename = isc_mem_get(mctx, filenamelen);
+ if (dsdir != NULL) {
+ snprintf(filename, filenamelen, "%s/", dsdir);
+ } else {
+ filename[0] = 0;
+ }
+ strlcat(filename, prefix, filenamelen);
+ strlcat(filename, namestr, filenamelen);
+
+ dns_diff_init(mctx, &diff);
+
+ name = gorigin;
+
+ for (key = ISC_LIST_HEAD(keylist); key != NULL;
+ key = ISC_LIST_NEXT(key, link))
+ {
+ if (REVOKE(key->key)) {
+ continue;
+ }
+ if (isksk(key)) {
+ have_ksk = true;
+ have_non_ksk = false;
+ } else {
+ have_ksk = false;
+ have_non_ksk = true;
+ }
+ for (curr = ISC_LIST_HEAD(keylist); curr != NULL;
+ curr = ISC_LIST_NEXT(curr, link))
+ {
+ if (dst_key_alg(key->key) != dst_key_alg(curr->key)) {
+ continue;
+ }
+ if (REVOKE(curr->key)) {
+ continue;
+ }
+ if (isksk(curr)) {
+ have_ksk = true;
+ } else {
+ have_non_ksk = true;
+ }
+ }
+ if (have_ksk && have_non_ksk && !isksk(key)) {
+ continue;
+ }
+ dns_rdata_init(&rdata);
+ dns_rdata_init(&ds);
+ isc_buffer_init(&b, keybuf, sizeof(keybuf));
+ result = dst_key_todns(key->key, &b);
+ check_result(result, "dst_key_todns");
+ isc_buffer_usedregion(&b, &r);
+ dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
+ if (type != dns_rdatatype_dnskey) {
+ result = dns_ds_buildrdata(gorigin, &rdata,
+ DNS_DSDIGEST_SHA256, dsbuf,
+ &ds);
+ check_result(result, "dns_ds_buildrdata");
+ result = dns_difftuple_create(mctx,
+ DNS_DIFFOP_ADDRESIGN,
+ name, 0, &ds, &tuple);
+ } else {
+ result = dns_difftuple_create(
+ mctx, DNS_DIFFOP_ADDRESIGN, gorigin,
+ zone_soa_min_ttl, &rdata, &tuple);
+ }
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+ }
+
+ result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
+ gclass, 0, NULL, &db);
+ check_result(result, "dns_db_create");
+
+ result = dns_db_newversion(db, &dbversion);
+ check_result(result, "dns_db_newversion");
+
+ result = dns_diff_apply(&diff, db, dbversion);
+ check_result(result, "dns_diff_apply");
+ dns_diff_clear(&diff);
+
+ result = dns_master_dump(mctx, db, dbversion, style, filename,
+ dns_masterformat_text, NULL);
+ check_result(result, "dns_master_dump");
+
+ isc_mem_put(mctx, filename, filenamelen);
+
+ dns_db_closeversion(db, &dbversion, false);
+ dns_db_detach(&db);
+}
+
+static void
+print_time(FILE *fp) {
+ time_t currenttime = time(NULL);
+ struct tm t, *tm = localtime_r(&currenttime, &t);
+ unsigned int flen;
+ char timebuf[80];
+
+ if (tm == NULL || outputformat != dns_masterformat_text) {
+ return;
+ }
+
+ flen = strftime(timebuf, sizeof(timebuf), "%a %b %e %H:%M:%S %Y", tm);
+ INSIST(flen > 0U && flen < sizeof(timebuf));
+ fprintf(fp, "; File written on %s\n", timebuf);
+}
+
+static void
+print_version(FILE *fp) {
+ if (outputformat != dns_masterformat_text) {
+ return;
+ }
+
+ fprintf(fp, "; dnssec_signzone version %s\n", PACKAGE_VERSION);
+}
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
+
+ fprintf(stderr, "Options: (default value in parenthesis) \n");
+ fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
+ "\t\tfor the zone and determines how they are to "
+ "be used\n");
+ fprintf(stderr, "\t-K directory:\n");
+ fprintf(stderr, "\t\tdirectory to find key files (.)\n");
+ fprintf(stderr, "\t-d directory:\n");
+ fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
+ fprintf(stderr, "\t-g:\t");
+ fprintf(stderr, "update DS records based on child zones' "
+ "dsset-* files\n");
+ fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
+ fprintf(stderr, "\t\tRRSIG start time "
+ "- absolute|offset (now - 1 hour)\n");
+ fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
+ fprintf(stderr, "\t\tRRSIG end time "
+ "- absolute|from start|from now "
+ "(now + 30 days)\n");
+ fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
+ fprintf(stderr, "\t\tDNSKEY RRSIG end "
+ "- absolute|from start|from now "
+ "(matches -e)\n");
+ fprintf(stderr, "\t-i interval:\n");
+ fprintf(stderr, "\t\tcycle interval - resign "
+ "if < interval from end ( (end-start)/4 )\n");
+ fprintf(stderr, "\t-j jitter:\n");
+ fprintf(stderr, "\t\trandomize signature end time up to jitter "
+ "seconds\n");
+ fprintf(stderr, "\t-v debuglevel (0)\n");
+ fprintf(stderr, "\t-q quiet\n");
+ fprintf(stderr, "\t-V:\tprint version information\n");
+ fprintf(stderr, "\t-o origin:\n");
+ fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
+ fprintf(stderr, "\t-f outfile:\n");
+ fprintf(stderr, "\t\tfile the signed zone is written in "
+ "(zonefile + .signed)\n");
+ fprintf(stderr, "\t-I format:\n");
+ fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
+ fprintf(stderr, "\t-O format:\n");
+ fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
+ fprintf(stderr, "\t-N format:\n");
+ fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
+ fprintf(stderr, "\t-D:\n");
+ fprintf(stderr, "\t\toutput only DNSSEC-related records\n");
+ fprintf(stderr, "\t-a:\t");
+ fprintf(stderr, "verify generated signatures\n");
+ fprintf(stderr, "\t-c class (IN)\n");
+ fprintf(stderr, "\t-E engine:\n");
+ fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
+ fprintf(stderr, "\t-P:\t");
+ fprintf(stderr, "disable post-sign verification\n");
+ fprintf(stderr, "\t-Q:\t");
+ fprintf(stderr, "remove signatures from keys that are no "
+ "longer active\n");
+ fprintf(stderr, "\t-R:\t");
+ fprintf(stderr, "remove signatures from keys that no longer exist\n");
+ fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
+ fprintf(stderr, "\t-t:\t");
+ fprintf(stderr, "print statistics\n");
+ fprintf(stderr, "\t-u:\t");
+ fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
+ fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
+ fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
+ fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
+ "\t\twith older versions of dnssec-signzone -g\n");
+ fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
+ fprintf(stderr, "\t-k key_signing_key\n");
+ fprintf(stderr, "\t-3 NSEC3 salt\n");
+ fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
+ fprintf(stderr, "\t-A NSEC3 optout\n");
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Signing Keys: ");
+ fprintf(stderr, "(default: all zone keys that have private keys)\n");
+ fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
+
+ exit(0);
+}
+
+static void
+removetempfile(void) {
+ if (removefile) {
+ isc_file_remove(tempfile);
+ }
+}
+
+static void
+print_stats(isc_time_t *timer_start, isc_time_t *timer_finish,
+ isc_time_t *sign_start, isc_time_t *sign_finish) {
+ uint64_t time_us; /* Time in microseconds */
+ uint64_t time_ms; /* Time in milliseconds */
+ uint64_t sig_ms; /* Signatures per millisecond */
+ FILE *out = output_stdout ? stderr : stdout;
+
+ fprintf(out, "Signatures generated: %10u\n", nsigned);
+ fprintf(out, "Signatures retained: %10u\n", nretained);
+ fprintf(out, "Signatures dropped: %10u\n", ndropped);
+ fprintf(out, "Signatures successfully verified: %10u\n", nverified);
+ fprintf(out,
+ "Signatures unsuccessfully "
+ "verified: %10u\n",
+ nverifyfailed);
+
+ time_us = isc_time_microdiff(sign_finish, sign_start);
+ time_ms = time_us / 1000;
+ fprintf(out, "Signing time in seconds: %7u.%03u\n",
+ (unsigned int)(time_ms / 1000), (unsigned int)(time_ms % 1000));
+ if (time_us > 0) {
+ sig_ms = ((uint64_t)nsigned * 1000000000) / time_us;
+ fprintf(out, "Signatures per second: %7u.%03u\n",
+ (unsigned int)sig_ms / 1000,
+ (unsigned int)sig_ms % 1000);
+ }
+
+ time_us = isc_time_microdiff(timer_finish, timer_start);
+ time_ms = time_us / 1000;
+ fprintf(out, "Runtime in seconds: %7u.%03u\n",
+ (unsigned int)(time_ms / 1000), (unsigned int)(time_ms % 1000));
+}
+
+int
+main(int argc, char *argv[]) {
+ int i, ch;
+ char *startstr = NULL, *endstr = NULL, *classname = NULL;
+ char *dnskey_endstr = NULL;
+ char *origin = NULL, *file = NULL, *output = NULL;
+ char *inputformatstr = NULL, *outputformatstr = NULL;
+ char *serialformatstr = NULL;
+ char *dskeyfile[MAXDSKEYS];
+ int ndskeys = 0;
+ char *endp;
+ isc_time_t timer_start, timer_finish;
+ isc_time_t sign_start, sign_finish;
+ dns_dnsseckey_t *key;
+ isc_result_t result, vresult;
+ isc_log_t *log = NULL;
+ const char *engine = NULL;
+ bool free_output = false;
+ int tempfilelen = 0;
+ dns_rdataclass_t rdclass;
+ isc_task_t **tasks = NULL;
+ hashlist_t hashlist;
+ bool make_keyset = false;
+ bool set_salt = false;
+ bool set_optout = false;
+ bool set_iter = false;
+ bool nonsecify = false;
+
+ atomic_init(&shuttingdown, false);
+ atomic_init(&finished, false);
+
+ /* Unused letters: Bb G J q Yy (and F is reserved). */
+#define CMDLINE_FLAGS \
+ "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:M:n:N:o:O:PpQqRr:s:ST:tuUv:VX:" \
+ "xzZ:"
+
+ /*
+ * Process memory debugging argument first.
+ */
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case 'm':
+ if (strcasecmp(isc_commandline_argument, "record") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ }
+ if (strcasecmp(isc_commandline_argument, "trace") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
+ }
+ if (strcasecmp(isc_commandline_argument, "usage") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = true;
+
+ masterstyle = &dns_master_style_explicitttl;
+
+ check_result(isc_app_start(), "isc_app_start");
+
+ isc_mem_create(&mctx);
+
+ isc_commandline_errprint = false;
+
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case '3':
+ set_salt = true;
+ nsec_datatype = dns_rdatatype_nsec3;
+ if (strcmp(isc_commandline_argument, "-") != 0) {
+ isc_buffer_t target;
+ char *sarg;
+
+ sarg = isc_commandline_argument;
+ isc_buffer_init(&target, saltbuf,
+ sizeof(saltbuf));
+ result = isc_hex_decodestring(sarg, &target);
+ check_result(result, "isc_hex_decodestring("
+ "salt)");
+ salt_length = isc_buffer_usedlength(&target);
+ }
+ break;
+
+ case 'A':
+ set_optout = true;
+ if (OPTOUT(nsec3flags)) {
+ nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
+ } else {
+ nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
+ }
+ break;
+
+ case 'a':
+ tryverify = true;
+ break;
+
+ case 'C':
+ make_keyset = true;
+ break;
+
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+
+ case 'd':
+ dsdir = isc_commandline_argument;
+ if (strlen(dsdir) == 0U) {
+ fatal("DS directory must be non-empty string");
+ }
+ result = try_dir(dsdir);
+ if (result != ISC_R_SUCCESS) {
+ fatal("cannot open directory %s: %s", dsdir,
+ isc_result_totext(result));
+ }
+ break;
+
+ case 'D':
+ output_dnssec_only = true;
+ break;
+
+ case 'E':
+ engine = isc_commandline_argument;
+ break;
+
+ case 'e':
+ endstr = isc_commandline_argument;
+ break;
+
+ case 'f':
+ output = isc_commandline_argument;
+ if (strcmp(output, "-") == 0) {
+ output_stdout = true;
+ }
+ break;
+
+ case 'g':
+ generateds = true;
+ break;
+
+ case 'H':
+ set_iter = true;
+ /* too-many is NOT DOCUMENTED */
+ if (strcmp(isc_commandline_argument, "too-many") == 0) {
+ nsec3iter = 151;
+ no_max_check = true;
+ break;
+ }
+ nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fatal("iterations must be numeric");
+ }
+ if (nsec3iter > 0xffffU) {
+ fatal("iterations too big");
+ }
+ break;
+
+ case 'I':
+ inputformatstr = isc_commandline_argument;
+ break;
+
+ case 'i':
+ endp = NULL;
+ cycle = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0' || cycle < 0) {
+ fatal("cycle period must be numeric and "
+ "positive");
+ }
+ break;
+
+ case 'j':
+ endp = NULL;
+ jitter = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0' || jitter < 0) {
+ fatal("jitter must be numeric and positive");
+ }
+ break;
+
+ case 'K':
+ directory = isc_commandline_argument;
+ break;
+
+ case 'k':
+ if (ndskeys == MAXDSKEYS) {
+ fatal("too many key-signing keys specified");
+ }
+ dskeyfile[ndskeys++] = isc_commandline_argument;
+ break;
+
+ case 'L':
+ snset = true;
+ endp = NULL;
+ serialnum = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fprintf(stderr, "source serial number "
+ "must be numeric");
+ exit(1);
+ }
+ break;
+
+ case 'l':
+ fatal("-l option (DLV lookaside) is obsolete");
+ break;
+
+ case 'M':
+ endp = NULL;
+ set_maxttl = true;
+ maxttl = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fprintf(stderr, "maximum TTL "
+ "must be numeric");
+ exit(1);
+ }
+ break;
+
+ case 'm':
+ break;
+
+ case 'N':
+ serialformatstr = isc_commandline_argument;
+ break;
+
+ case 'n':
+ endp = NULL;
+ ntasks = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0' || ntasks > INT32_MAX) {
+ fatal("number of cpus must be numeric");
+ }
+ break;
+
+ case 'O':
+ outputformatstr = isc_commandline_argument;
+ break;
+
+ case 'o':
+ origin = isc_commandline_argument;
+ break;
+
+ case 'P':
+ disable_zone_check = true;
+ break;
+
+ case 'p':
+ fatal("The -p option has been deprecated.\n");
+ break;
+
+ case 'Q':
+ remove_inactkeysigs = true;
+ break;
+
+ case 'R':
+ remove_orphansigs = true;
+ break;
+
+ case 'r':
+ fatal("The -r options has been deprecated.\n");
+ break;
+
+ case 'S':
+ smartsign = true;
+ break;
+
+ case 's':
+ startstr = isc_commandline_argument;
+ break;
+
+ case 'T':
+ endp = NULL;
+ set_keyttl = true;
+ keyttl = strtottl(isc_commandline_argument);
+ break;
+
+ case 't':
+ printstats = true;
+ break;
+
+ case 'U': /* Undocumented for testing only. */
+ unknownalg = true;
+ break;
+
+ case 'u':
+ update_chain = true;
+ break;
+
+ case 'v':
+ endp = NULL;
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fatal("verbose level must be numeric");
+ }
+ break;
+
+ case 'q':
+ quiet = true;
+ break;
+
+ case 'X':
+ dnskey_endstr = isc_commandline_argument;
+ break;
+
+ case 'x':
+ keyset_kskonly = true;
+ break;
+
+ case 'z':
+ ignore_kskflag = true;
+ break;
+
+ case 'F':
+ /* Reserved for FIPS mode */
+ FALLTHROUGH;
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ }
+ FALLTHROUGH;
+ case 'h':
+ /* Does not return. */
+ usage();
+
+ case 'V':
+ /* Does not return. */
+ version(program);
+
+ case 'Z': /* Undocumented test options */
+ if (!strcmp(isc_commandline_argument, "nonsecify")) {
+ nonsecify = true;
+ }
+ break;
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ result = dst_lib_init(mctx, engine);
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not initialize dst: %s",
+ isc_result_totext(result));
+ }
+
+ isc_stdtime_get(&now);
+
+ if (startstr != NULL) {
+ starttime = strtotime(startstr, now, now, NULL);
+ } else {
+ starttime = now - 3600; /* Allow for some clock skew. */
+ }
+
+ if (endstr != NULL) {
+ endtime = strtotime(endstr, now, starttime, NULL);
+ } else {
+ endtime = starttime + (30 * 24 * 60 * 60);
+ }
+
+ if (dnskey_endstr != NULL) {
+ dnskey_endtime = strtotime(dnskey_endstr, now, starttime, NULL);
+ if (endstr != NULL && dnskey_endtime == endtime) {
+ fprintf(stderr, "WARNING: -e and -X were both set, "
+ "but have identical values.\n");
+ }
+ } else {
+ dnskey_endtime = endtime;
+ }
+
+ if (cycle == -1) {
+ cycle = (endtime - starttime) / 4;
+ }
+
+ if (ntasks == 0) {
+ ntasks = isc_os_ncpus() * 2;
+ }
+ vbprintf(4, "using %d cpus\n", ntasks);
+
+ rdclass = strtoclass(classname);
+
+ if (directory == NULL) {
+ directory = ".";
+ }
+
+ setup_logging(mctx, &log);
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc < 1) {
+ usage();
+ }
+
+ file = argv[0];
+
+ argc -= 1;
+ argv += 1;
+
+ if (origin == NULL) {
+ origin = file;
+ }
+
+ if (output == NULL) {
+ size_t size;
+ free_output = true;
+ size = strlen(file) + strlen(".signed") + 1;
+ output = isc_mem_allocate(mctx, size);
+ snprintf(output, size, "%s.signed", file);
+ }
+
+ if (inputformatstr != NULL) {
+ if (strcasecmp(inputformatstr, "text") == 0) {
+ inputformat = dns_masterformat_text;
+ } else if (strcasecmp(inputformatstr, "raw") == 0) {
+ inputformat = dns_masterformat_raw;
+ } else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
+ inputformat = dns_masterformat_raw;
+ fprintf(stderr, "WARNING: input format version "
+ "ignored\n");
+ } else {
+ fatal("unknown file format: %s", inputformatstr);
+ }
+ }
+
+ if (outputformatstr != NULL) {
+ if (strcasecmp(outputformatstr, "text") == 0) {
+ outputformat = dns_masterformat_text;
+ } else if (strcasecmp(outputformatstr, "full") == 0) {
+ outputformat = dns_masterformat_text;
+ masterstyle = &dns_master_style_full;
+ } else if (strcasecmp(outputformatstr, "raw") == 0) {
+ outputformat = dns_masterformat_raw;
+ } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
+ char *end;
+
+ outputformat = dns_masterformat_raw;
+ rawversion = strtol(outputformatstr + 4, &end, 10);
+ if (end == outputformatstr + 4 || *end != '\0' ||
+ rawversion > 1U)
+ {
+ fprintf(stderr, "unknown raw format version\n");
+ exit(1);
+ }
+ } else {
+ fatal("unknown file format: %s", outputformatstr);
+ }
+ }
+
+ if (serialformatstr != NULL) {
+ if (strcasecmp(serialformatstr, "keep") == 0) {
+ serialformat = SOA_SERIAL_KEEP;
+ } else if (strcasecmp(serialformatstr, "increment") == 0 ||
+ strcasecmp(serialformatstr, "incr") == 0)
+ {
+ serialformat = SOA_SERIAL_INCREMENT;
+ } else if (strcasecmp(serialformatstr, "unixtime") == 0) {
+ serialformat = SOA_SERIAL_UNIXTIME;
+ } else if (strcasecmp(serialformatstr, "date") == 0) {
+ serialformat = SOA_SERIAL_DATE;
+ } else {
+ fatal("unknown soa serial format: %s", serialformatstr);
+ }
+ }
+
+ if (output_dnssec_only && outputformat != dns_masterformat_text) {
+ fatal("option -D can only be used with \"-O text\"");
+ }
+
+ if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP) {
+ fatal("option -D can only be used with \"-N keep\"");
+ }
+
+ if (output_dnssec_only && set_maxttl) {
+ fatal("option -D cannot be used with -M");
+ }
+
+ result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL, 0, 24,
+ 0, 0, 0, 8, 0xffffffff, mctx);
+ check_result(result, "dns_master_stylecreate");
+
+ gdb = NULL;
+ TIME_NOW(&timer_start);
+ loadzone(file, origin, rdclass, &gdb);
+ gorigin = dns_db_origin(gdb);
+ gclass = dns_db_class(gdb);
+ get_soa_ttls();
+
+ if (set_maxttl && set_keyttl && keyttl > maxttl) {
+ fprintf(stderr,
+ "%s: warning: Specified key TTL %u "
+ "exceeds maximum zone TTL; reducing to %u\n",
+ program, keyttl, maxttl);
+ keyttl = maxttl;
+ }
+
+ if (!set_keyttl) {
+ keyttl = soa_ttl;
+ }
+
+ /*
+ * Check for any existing NSEC3 parameters in the zone,
+ * and use them as defaults if -u was not specified.
+ */
+ if (update_chain && !set_optout && !set_iter && !set_salt) {
+ nsec_datatype = dns_rdatatype_nsec;
+ } else {
+ set_nsec3params(update_chain, set_salt, set_optout, set_iter);
+ }
+
+ /*
+ * We need to do this early on, as we start messing with the list
+ * of keys rather early.
+ */
+ ISC_LIST_INIT(keylist);
+ isc_rwlock_init(&keylist_lock, 0, 0);
+
+ /*
+ * Fill keylist with:
+ * 1) Keys listed in the DNSKEY set that have
+ * private keys associated, *if* no keys were
+ * set on the command line.
+ * 2) ZSKs set on the command line
+ * 3) KSKs set on the command line
+ * 4) Any keys remaining in the DNSKEY set which
+ * do not have private keys associated and were
+ * not specified on the command line.
+ */
+ if (argc == 0 || smartsign) {
+ loadzonekeys(!smartsign, false);
+ }
+ loadexplicitkeys(argv, argc, false);
+ loadexplicitkeys(dskeyfile, ndskeys, true);
+ loadzonekeys(!smartsign, true);
+
+ /*
+ * If we're doing smart signing, look in the key repository for
+ * key files with metadata, and merge them with the keylist
+ * we have now.
+ */
+ if (smartsign) {
+ build_final_keylist();
+ }
+
+ /* Now enumerate the key list */
+ for (key = ISC_LIST_HEAD(keylist); key != NULL;
+ key = ISC_LIST_NEXT(key, link))
+ {
+ key->index = keycount++;
+ }
+
+ if (keycount == 0) {
+ if (disable_zone_check) {
+ fprintf(stderr,
+ "%s: warning: No keys specified "
+ "or found\n",
+ program);
+ } else {
+ fatal("No signing keys specified or found.");
+ }
+ nokeys = true;
+ }
+
+ warnifallksk(gdb);
+
+ if (IS_NSEC3) {
+ bool answer;
+
+ hash_length = dns_nsec3_hashlength(dns_hash_sha1);
+ hashlist_init(&hashlist,
+ dns_db_nodecount(gdb, dns_dbtree_main) * 2,
+ hash_length);
+ result = dns_nsec_nseconly(gdb, gversion, NULL, &answer);
+ if (result == ISC_R_NOTFOUND) {
+ fprintf(stderr,
+ "%s: warning: NSEC3 generation "
+ "requested with no DNSKEY; ignoring\n",
+ program);
+ } else if (result != ISC_R_SUCCESS) {
+ check_result(result, "dns_nsec_nseconly");
+ } else if (answer) {
+ fatal("NSEC3 generation requested with "
+ "NSEC-only DNSKEY");
+ }
+
+ if (nsec3iter > dns_nsec3_maxiterations()) {
+ if (no_max_check) {
+ fprintf(stderr,
+ "Ignoring max iterations check.\n");
+ } else {
+ fatal("NSEC3 iterations too big. Maximum "
+ "iterations allowed %u.",
+ dns_nsec3_maxiterations());
+ }
+ }
+ } else {
+ hashlist_init(&hashlist, 0, 0); /* silence clang */
+ }
+
+ gversion = NULL;
+ result = dns_db_newversion(gdb, &gversion);
+ check_result(result, "dns_db_newversion()");
+
+ switch (serialformat) {
+ case SOA_SERIAL_INCREMENT:
+ setsoaserial(0, dns_updatemethod_increment);
+ break;
+ case SOA_SERIAL_UNIXTIME:
+ setsoaserial(now, dns_updatemethod_unixtime);
+ break;
+ case SOA_SERIAL_DATE:
+ setsoaserial(now, dns_updatemethod_date);
+ break;
+ case SOA_SERIAL_KEEP:
+ default:
+ /* do nothing */
+ break;
+ }
+
+ /* Remove duplicates and cap TTLs at maxttl */
+ cleanup_zone();
+
+ if (!nonsecify) {
+ if (IS_NSEC3) {
+ nsec3ify(dns_hash_sha1, nsec3iter, gsalt, salt_length,
+ &hashlist);
+ } else {
+ nsecify();
+ }
+ }
+
+ if (!nokeys) {
+ writeset("dsset-", dns_rdatatype_ds);
+ if (make_keyset) {
+ writeset("keyset-", dns_rdatatype_dnskey);
+ }
+ }
+
+ if (output_stdout) {
+ outfp = stdout;
+ if (outputformatstr == NULL) {
+ masterstyle = &dns_master_style_full;
+ }
+ } else {
+ tempfilelen = strlen(output) + 20;
+ tempfile = isc_mem_get(mctx, tempfilelen);
+
+ result = isc_file_mktemplate(output, tempfile, tempfilelen);
+ check_result(result, "isc_file_mktemplate");
+
+ if (outputformat == dns_masterformat_text) {
+ result = isc_file_openunique(tempfile, &outfp);
+ } else {
+ result = isc_file_bopenunique(tempfile, &outfp);
+ }
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to open temporary output file: %s",
+ isc_result_totext(result));
+ }
+ removefile = true;
+ setfatalcallback(&removetempfile);
+ }
+
+ print_time(outfp);
+ print_version(outfp);
+
+ isc_managers_create(mctx, ntasks, 0, &netmgr, &taskmgr, NULL);
+
+ main_task = NULL;
+ result = isc_task_create(taskmgr, 0, &main_task);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to create task: %s", isc_result_totext(result));
+ }
+
+ tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
+ for (i = 0; i < (int)ntasks; i++) {
+ tasks[i] = NULL;
+ result = isc_task_create(taskmgr, 0, &tasks[i]);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to create task: %s",
+ isc_result_totext(result));
+ }
+ }
+
+ isc_mutex_init(&namelock);
+
+ if (printstats) {
+ isc_mutex_init(&statslock);
+ }
+
+ presign();
+ TIME_NOW(&sign_start);
+ signapex();
+ if (!atomic_load(&finished)) {
+ /*
+ * There is more work to do. Spread it out over multiple
+ * processors if possible.
+ */
+ for (i = 0; i < (int)ntasks; i++) {
+ result = isc_app_onrun(mctx, main_task, startworker,
+ tasks[i]);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to start task: %s",
+ isc_result_totext(result));
+ }
+ }
+ (void)isc_app_run();
+ if (!atomic_load(&finished)) {
+ fatal("process aborted by user");
+ }
+ } else {
+ isc_task_detach(&main_task);
+ }
+ atomic_store(&shuttingdown, true);
+ for (i = 0; i < (int)ntasks; i++) {
+ isc_task_detach(&tasks[i]);
+ }
+ isc_managers_destroy(&netmgr, &taskmgr, NULL);
+ isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
+ postsign();
+ TIME_NOW(&sign_finish);
+
+ if (disable_zone_check) {
+ vresult = ISC_R_SUCCESS;
+ } else {
+ vresult = dns_zoneverify_dnssec(NULL, gdb, gversion, gorigin,
+ NULL, mctx, ignore_kskflag,
+ keyset_kskonly, report);
+ if (vresult != ISC_R_SUCCESS) {
+ fprintf(output_stdout ? stderr : stdout,
+ "Zone verification failed (%s)\n",
+ isc_result_totext(vresult));
+ }
+ }
+
+ if (outputformat != dns_masterformat_text) {
+ dns_masterrawheader_t header;
+ dns_master_initrawheader(&header);
+ if (rawversion == 0U) {
+ header.flags = DNS_MASTERRAW_COMPAT;
+ } else if (snset) {
+ header.flags = DNS_MASTERRAW_SOURCESERIALSET;
+ header.sourceserial = serialnum;
+ }
+ result = dns_master_dumptostream(mctx, gdb, gversion,
+ masterstyle, outputformat,
+ &header, outfp);
+ check_result(result, "dns_master_dumptostream3");
+ }
+
+ isc_mutex_destroy(&namelock);
+ if (printstats) {
+ isc_mutex_destroy(&statslock);
+ }
+
+ if (!output_stdout) {
+ result = isc_stdio_close(outfp);
+ check_result(result, "isc_stdio_close");
+ removefile = false;
+
+ if (vresult == ISC_R_SUCCESS) {
+ result = isc_file_rename(tempfile, output);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to rename temp file to %s: %s",
+ output, isc_result_totext(result));
+ }
+ printf("%s\n", output);
+ } else {
+ isc_file_remove(tempfile);
+ }
+ }
+
+ dns_db_closeversion(gdb, &gversion, false);
+ dns_db_detach(&gdb);
+
+ hashlist_free(&hashlist);
+
+ while (!ISC_LIST_EMPTY(keylist)) {
+ key = ISC_LIST_HEAD(keylist);
+ ISC_LIST_UNLINK(keylist, key, link);
+ dns_dnsseckey_destroy(mctx, &key);
+ }
+
+ if (tempfilelen != 0) {
+ isc_mem_put(mctx, tempfile, tempfilelen);
+ }
+
+ if (free_output) {
+ isc_mem_free(mctx, output);
+ }
+
+ dns_master_styledestroy(&dsstyle, mctx);
+
+ cleanup_logging(&log);
+ dst_lib_destroy();
+ if (verbose > 10) {
+ isc_mem_stats(mctx, stdout);
+ }
+ isc_mem_destroy(&mctx);
+
+ (void)isc_app_finish();
+
+ if (printstats) {
+ TIME_NOW(&timer_finish);
+ print_stats(&timer_start, &timer_finish, &sign_start,
+ &sign_finish);
+ }
+
+ return (vresult == ISC_R_SUCCESS ? 0 : 1);
+}
diff --git a/bin/dnssec/dnssec-signzone.rst b/bin/dnssec/dnssec-signzone.rst
new file mode 100644
index 0000000..668d7f3
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.rst
@@ -0,0 +1,436 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: dnssec-signzone
+.. program:: dnssec-signzone
+.. _man_dnssec-signzone:
+
+dnssec-signzone - DNSSEC zone signing tool
+------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`dnssec-signzone` [**-a**] [**-c** class] [**-d** directory] [**-D**] [**-E** engine] [**-e** end-time] [**-f** output-file] [**-g**] [**-h**] [**-i** interval] [**-I** input-format] [**-j** jitter] [**-K** directory] [**-k** key] [**-L** serial] [**-M** maxttl] [**-N** soa-serial-format] [**-o** origin] [**-O** output-format] [**-P**] [**-Q**] [**-q**] [**-R**] [**-S**] [**-s** start-time] [**-T** ttl] [**-t**] [**-u**] [**-v** level] [**-V**] [**-X** extended end-time] [**-x**] [**-z**] [**-3** salt] [**-H** iterations] [**-A**] {zonefile} [key...]
+
+Description
+~~~~~~~~~~~
+
+:program:`dnssec-signzone` signs a zone; it generates NSEC and RRSIG records
+and produces a signed version of the zone. The security status of
+delegations from the signed zone (that is, whether the child zones are
+secure) is determined by the presence or absence of a ``keyset``
+file for each child zone.
+
+Options
+~~~~~~~
+
+.. option:: -a
+
+ This option verifies all generated signatures.
+
+.. option:: -c class
+
+ This option specifies the DNS class of the zone.
+
+.. option:: -C
+
+ This option sets compatibility mode, in which a ``keyset-zonename`` file is generated in addition
+ to ``dsset-zonename`` when signing a zone, for use by older versions
+ of :program:`dnssec-signzone`.
+
+.. option:: -d directory
+
+ This option indicates the directory where BIND 9 should look for ``dsset-`` or ``keyset-`` files.
+
+.. option:: -D
+
+ This option indicates that only those record types automatically managed by
+ :program:`dnssec-signzone`, i.e., RRSIG, NSEC, NSEC3 and NSEC3PARAM records, should be included in the output.
+ If smart signing (:option:`-S`) is used, DNSKEY records are also included.
+ The resulting file can be included in the original zone file with
+ ``$INCLUDE``. This option cannot be combined with :option:`-O raw <-O>`
+ or serial-number updating.
+
+.. option:: -E engine
+
+ This option specifies the hardware to use for cryptographic
+ operations, such as a secure key store used for signing, when applicable.
+
+ When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL
+ engine identifier that drives the cryptographic accelerator or
+ hardware service module (usually ``pkcs11``).
+
+.. option:: -g
+
+ This option indicates that DS records for child zones should be generated from a ``dsset-`` or ``keyset-``
+ file. Existing DS records are removed.
+
+.. option:: -K directory
+
+ This option specifies the directory to search for DNSSEC keys. If not
+ specified, it defaults to the current directory.
+
+.. option:: -k key
+
+ This option tells BIND 9 to treat the specified key as a key-signing key, ignoring any key flags. This
+ option may be specified multiple times.
+
+.. option:: -M maxttl
+
+ This option sets the maximum TTL for the signed zone. Any TTL higher than ``maxttl``
+ in the input zone is reduced to ``maxttl`` in the output. This
+ provides certainty as to the largest possible TTL in the signed zone,
+ which is useful to know when rolling keys. The maxttl is the longest
+ possible time before signatures that have been retrieved by resolvers
+ expire from resolver caches. Zones that are signed with this
+ option should be configured to use a matching ``max-zone-ttl`` in
+ :iscman:`named.conf`. (Note: This option is incompatible with :option:`-D`,
+ because it modifies non-DNSSEC data in the output zone.)
+
+.. option:: -s start-time
+
+ This option specifies the date and time when the generated RRSIG records become
+ valid. This can be either an absolute or relative time. An absolute
+ start time is indicated by a number in YYYYMMDDHHMMSS notation;
+ 20000530144500 denotes 14:45:00 UTC on May 30th, 2000. A relative
+ start time is indicated by ``+N``, which is N seconds from the current
+ time. If no ``start-time`` is specified, the current time minus 1
+ hour (to allow for clock skew) is used.
+
+.. option:: -e end-time
+
+ This option specifies the date and time when the generated RRSIG records expire. As
+ with ``start-time``, an absolute time is indicated in YYYYMMDDHHMMSS
+ notation. A time relative to the start time is indicated with ``+N``,
+ which is N seconds from the start time. A time relative to the
+ current time is indicated with ``now+N``. If no ``end-time`` is
+ specified, 30 days from the start time is the default.
+ ``end-time`` must be later than ``start-time``.
+
+.. option:: -X extended end-time
+
+ This option specifies the date and time when the generated RRSIG records for the
+ DNSKEY RRset expire. This is to be used in cases when the DNSKEY
+ signatures need to persist longer than signatures on other records;
+ e.g., when the private component of the KSK is kept offline and the
+ KSK signature is to be refreshed manually.
+
+ As with ``end-time``, an absolute time is indicated in
+ YYYYMMDDHHMMSS notation. A time relative to the start time is
+ indicated with ``+N``, which is N seconds from the start time. A time
+ relative to the current time is indicated with ``now+N``. If no
+ ``extended end-time`` is specified, the value of ``end-time`` is used
+ as the default. (``end-time``, in turn, defaults to 30 days from the
+ start time.) ``extended end-time`` must be later than ``start-time``.
+
+.. option:: -f output-file
+
+ This option indicates the name of the output file containing the signed zone. The default
+ is to append ``.signed`` to the input filename. If ``output-file`` is
+ set to ``-``, then the signed zone is written to the standard
+ output, with a default output format of ``full``.
+
+.. option:: -h
+
+ This option prints a short summary of the options and arguments to
+ :program:`dnssec-signzone`.
+
+.. option:: -V
+
+ This option prints version information.
+
+.. option:: -i interval
+
+ This option indicates that, when a previously signed zone is passed as input, records may be
+ re-signed. The ``interval`` option specifies the cycle interval as an
+ offset from the current time, in seconds. If a RRSIG record expires
+ after the cycle interval, it is retained; otherwise, it is considered
+ to be expiring soon and it is replaced.
+
+ The default cycle interval is one quarter of the difference between
+ the signature end and start times. So if neither ``end-time`` nor
+ ``start-time`` is specified, :program:`dnssec-signzone` generates
+ signatures that are valid for 30 days, with a cycle interval of 7.5
+ days. Therefore, if any existing RRSIG records are due to expire in
+ less than 7.5 days, they are replaced.
+
+.. option:: -I input-format
+
+ This option sets the format of the input zone file. Possible formats are
+ ``text`` (the default), and ``raw``. This option is primarily
+ intended to be used for dynamic signed zones, so that the dumped zone
+ file in a non-text format containing updates can be signed directly.
+ This option is not useful for non-dynamic zones.
+
+.. option:: -j jitter
+
+ When signing a zone with a fixed signature lifetime, all RRSIG
+ records issued at the time of signing expire simultaneously. If the
+ zone is incrementally signed, i.e., a previously signed zone is passed
+ as input to the signer, all expired signatures must be regenerated
+ at approximately the same time. The ``jitter`` option specifies a jitter
+ window that is used to randomize the signature expire time, thus
+ spreading incremental signature regeneration over time.
+
+ Signature lifetime jitter also, to some extent, benefits validators and
+ servers by spreading out cache expiration, i.e., if large numbers of
+ RRSIGs do not expire at the same time from all caches, there is
+ less congestion than if all validators need to refetch at around the
+ same time.
+
+.. option:: -L serial
+
+ When writing a signed zone to "raw" format, this option sets the "source
+ serial" value in the header to the specified ``serial`` number. (This is
+ expected to be used primarily for testing purposes.)
+
+.. option:: -n ncpus
+
+ This option specifies the number of threads to use. By default, one thread is
+ started for each detected CPU.
+
+.. option:: -N soa-serial-format
+
+ This option sets the SOA serial number format of the signed zone. Possible formats are
+ ``keep`` (the default), ``increment``, ``unixtime``, and
+ ``date``.
+
+ **keep**
+ This format indicates that the SOA serial number should not be modified.
+
+ **increment**
+ This format increments the SOA serial number using :rfc:`1982` arithmetic.
+
+ **unixtime**
+ This format sets the SOA serial number to the number of seconds
+ since the beginning of the Unix epoch, unless the serial
+ number is already greater than or equal to that value, in
+ which case it is simply incremented by one.
+
+ **date**
+ This format sets the SOA serial number to today's date, in
+ YYYYMMDDNN format, unless the serial number is already greater
+ than or equal to that value, in which case it is simply
+ incremented by one.
+
+.. option:: -o origin
+
+ This option sets the zone origin. If not specified, the name of the zone file is
+ assumed to be the origin.
+
+.. option:: -O output-format
+
+ This option sets the format of the output file containing the signed
+ zone. Possible formats are ``text`` (the default), which is the standard
+ textual representation of the zone; ``full``, which is text output in a
+ format suitable for processing by external scripts; and ``raw`` and
+ ``raw=N``, which store the zone in binary formats for rapid loading by
+ :iscman:`named`. ``raw=N`` specifies the format version of the raw zone file:
+ if N is 0, the raw file can be read by any version of :iscman:`named`; if N is
+ 1, the file can be read by release 9.9.0 or higher. The default is 1.
+
+.. option:: -P
+
+ This option disables post-sign verification tests.
+
+ The post-sign verification tests ensure that for each algorithm in
+ use there is at least one non-revoked self-signed KSK key, that all
+ revoked KSK keys are self-signed, and that all records in the zone
+ are signed by the algorithm. This option skips these tests.
+
+.. option:: -Q
+
+ This option removes signatures from keys that are no longer active.
+
+ Normally, when a previously signed zone is passed as input to the
+ signer, and a DNSKEY record has been removed and replaced with a new
+ one, signatures from the old key that are still within their validity
+ period are retained. This allows the zone to continue to validate
+ with cached copies of the old DNSKEY RRset. The :option:`-Q` option forces
+ :program:`dnssec-signzone` to remove signatures from keys that are no longer
+ active. This enables ZSK rollover using the procedure described in
+ :rfc:`4641#4.2.1.1` ("Pre-Publish Key Rollover").
+
+.. option:: -q
+
+ This option enables quiet mode, which suppresses unnecessary output. Without this option, when
+ :program:`dnssec-signzone` is run it prints three pieces of information to standard output: the number of
+ keys in use; the algorithms used to verify the zone was signed correctly and
+ other status information; and the filename containing the signed
+ zone. With the option that output is suppressed, leaving only the filename.
+
+.. option:: -R
+
+ This option removes signatures from keys that are no longer published.
+
+ This option is similar to :option:`-Q`, except it forces
+ :program:`dnssec-signzone` to remove signatures from keys that are no longer
+ published. This enables ZSK rollover using the procedure described in
+ :rfc:`4641#4.2.1.2` ("Double Signature Zone Signing Key
+ Rollover").
+
+.. option:: -S
+
+ This option enables smart signing, which instructs :program:`dnssec-signzone` to search the key
+ repository for keys that match the zone being signed, and to include
+ them in the zone if appropriate.
+
+ When a key is found, its timing metadata is examined to determine how
+ it should be used, according to the following rules. Each successive
+ rule takes priority over the prior ones:
+
+ If no timing metadata has been set for the key, the key is
+ published in the zone and used to sign the zone.
+
+ If the key's publication date is set and is in the past, the key
+ is published in the zone.
+
+ If the key's activation date is set and is in the past, the key is
+ published (regardless of publication date) and used to sign the
+ zone.
+
+ If the key's revocation date is set and is in the past, and the key
+ is published, then the key is revoked, and the revoked key is used
+ to sign the zone.
+
+ If either the key's unpublication or deletion date is set and
+ in the past, the key is NOT published or used to sign the zone,
+ regardless of any other metadata.
+
+ If the key's sync publication date is set and is in the past,
+ synchronization records (type CDS and/or CDNSKEY) are created.
+
+ If the key's sync deletion date is set and is in the past,
+ synchronization records (type CDS and/or CDNSKEY) are removed.
+
+.. option:: -T ttl
+
+ This option specifies a TTL to be used for new DNSKEY records imported into the
+ zone from the key repository. If not specified, the default is the
+ TTL value from the zone's SOA record. This option is ignored when
+ signing without :option:`-S`, since DNSKEY records are not imported from
+ the key repository in that case. It is also ignored if there are any
+ pre-existing DNSKEY records at the zone apex, in which case new
+ records' TTL values are set to match them, or if any of the
+ imported DNSKEY records had a default TTL value. In the event of a
+ conflict between TTL values in imported keys, the shortest one is
+ used.
+
+.. option:: -t
+
+ This option prints statistics at completion.
+
+.. option:: -u
+
+ This option updates the NSEC/NSEC3 chain when re-signing a previously signed zone.
+ With this option, a zone signed with NSEC can be switched to NSEC3,
+ or a zone signed with NSEC3 can be switched to NSEC or to NSEC3 with
+ different parameters. Without this option, :program:`dnssec-signzone`
+ retains the existing chain when re-signing.
+
+.. option:: -v level
+
+ This option sets the debugging level.
+
+.. option:: -x
+
+ This option indicates that BIND 9 should only sign the DNSKEY, CDNSKEY, and CDS RRsets with key-signing keys,
+ and should omit signatures from zone-signing keys. (This is similar to the
+ ``dnssec-dnskey-kskonly yes;`` zone option in :iscman:`named`.)
+
+.. option:: -z
+
+ This option indicates that BIND 9 should ignore the KSK flag on keys when determining what to sign. This causes
+ KSK-flagged keys to sign all records, not just the DNSKEY RRset.
+ (This is similar to the ``update-check-ksk no;`` zone option in
+ :iscman:`named`.)
+
+.. option:: -3 salt
+
+ This option generates an NSEC3 chain with the given hex-encoded salt. A dash
+ (-) can be used to indicate that no salt is to be used when
+ generating the NSEC3 chain.
+
+ .. note::
+ ``-3 -`` is the recommended configuration. Adding salt provides no practical benefits.
+
+.. option:: -H iterations
+
+ This option indicates that, when generating an NSEC3 chain, BIND 9 should use this many iterations. The default
+ is 0.
+
+ .. warning::
+ Values greater than 0 cause interoperability issues and also increase the risk of CPU-exhausting DoS attacks.
+
+.. option:: -A
+
+ This option indicates that, when generating an NSEC3 chain, BIND 9 should set the OPTOUT flag on all NSEC3
+ records and should not generate NSEC3 records for insecure delegations.
+
+ .. warning::
+ Do not use this option unless all its implications are fully understood. This option is intended only for extremely large zones (comparable to ``com.``) with sparse secure delegations.
+
+.. option:: -AA
+
+ This option turns the OPTOUT flag off for
+ all records. This is useful when using the :option:`-u` option to modify an
+ NSEC3 chain which previously had OPTOUT set.
+
+.. option:: zonefile
+
+ This option sets the file containing the zone to be signed.
+
+.. option:: key
+
+ This option specifies which keys should be used to sign the zone. If no keys are
+ specified, the zone is examined for DNSKEY records at the
+ zone apex. If these records are found and there are matching private keys in
+ the current directory, they are used for signing.
+
+Example
+~~~~~~~
+
+The following command signs the ``example.com`` zone with the
+ECDSAP256SHA256 key generated by :iscman:`dnssec-keygen`
+(Kexample.com.+013+17247). Because the :option:`-S` option is not being used,
+the zone's keys must be in the master file (``db.example.com``). This
+invocation looks for ``dsset`` files in the current directory, so that
+DS records can be imported from them (:option:`-g`).
+
+::
+
+ % dnssec-signzone -g -o example.com db.example.com \
+ Kexample.com.+013+17247
+ db.example.com.signed
+ %
+
+In the above example, :program:`dnssec-signzone` creates the file
+``db.example.com.signed``. This file should be referenced in a zone
+statement in the :iscman:`named.conf` file.
+
+This example re-signs a previously signed zone with default parameters.
+The private keys are assumed to be in the current directory.
+
+::
+
+ % cp db.example.com.signed db.example.com
+ % dnssec-signzone -o example.com db.example.com
+ db.example.com.signed
+ %
+
+See Also
+~~~~~~~~
+
+:iscman:`dnssec-keygen(8) <dnssec-keygen>`, BIND 9 Administrator Reference Manual, :rfc:`4033`,
+:rfc:`4641`.
diff --git a/bin/dnssec/dnssec-verify.c b/bin/dnssec/dnssec-verify.c
new file mode 100644
index 0000000..5f2f2d1
--- /dev/null
+++ b/bin/dnssec/dnssec-verify.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <isc/app.h>
+#include <isc/attributes.h>
+#include <isc/base32.h>
+#include <isc/commandline.h>
+#include <isc/event.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/hex.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/os.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/rwlock.h>
+#include <isc/serial.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/diff.h>
+#include <dns/dnssec.h>
+#include <dns/ds.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/masterdump.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/soa.h>
+#include <dns/time.h>
+#include <dns/zoneverify.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-verify";
+
+static isc_stdtime_t now;
+static isc_mem_t *mctx = NULL;
+static dns_masterformat_t inputformat = dns_masterformat_text;
+static dns_db_t *gdb; /* The database */
+static dns_dbversion_t *gversion; /* The database version */
+static dns_rdataclass_t gclass; /* The class */
+static dns_name_t *gorigin; /* The database origin */
+static bool ignore_kskflag = false;
+static bool keyset_kskonly = false;
+
+static void
+report(const char *format, ...) {
+ if (!quiet) {
+ char buf[4096];
+ va_list args;
+
+ va_start(args, format);
+ vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+ fprintf(stdout, "%s\n", buf);
+ }
+}
+
+/*%
+ * Load the zone file from disk
+ */
+static void
+loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
+ isc_buffer_t b;
+ int len;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result;
+
+ len = strlen(origin);
+ isc_buffer_init(&b, origin, len);
+ isc_buffer_add(&b, len);
+
+ name = dns_fixedname_initname(&fname);
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed converting name '%s' to dns format: %s", origin,
+ isc_result_totext(result));
+ }
+
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0,
+ NULL, db);
+ check_result(result, "dns_db_create()");
+
+ result = dns_db_load(*db, file, inputformat, 0);
+ switch (result) {
+ case DNS_R_SEENINCLUDE:
+ case ISC_R_SUCCESS:
+ break;
+ case DNS_R_NOTZONETOP:
+ /*
+ * Comparing pointers (vs. using strcmp()) is intentional: we
+ * want to check whether -o was supplied on the command line,
+ * not whether origin and file contain the same string.
+ */
+ if (origin == file) {
+ fatal("failed loading zone '%s' from file '%s': "
+ "use -o to specify a different zone origin",
+ origin, file);
+ }
+ FALLTHROUGH;
+ default:
+ fatal("failed loading zone from '%s': %s", file,
+ isc_result_totext(result));
+ }
+}
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
+
+ fprintf(stderr, "Options: (default value in parenthesis) \n");
+ fprintf(stderr, "\t-v debuglevel (0)\n");
+ fprintf(stderr, "\t-q quiet\n");
+ fprintf(stderr, "\t-V:\tprint version information\n");
+ fprintf(stderr, "\t-o origin:\n");
+ fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
+ fprintf(stderr, "\t-I format:\n");
+ fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
+ fprintf(stderr, "\t-c class (IN)\n");
+ fprintf(stderr, "\t-E engine:\n");
+ fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
+ fprintf(stderr, "\t-x:\tDNSKEY record signed with KSKs only, "
+ "not ZSKs\n");
+ fprintf(stderr, "\t-z:\tAll records signed with KSKs\n");
+ exit(0);
+}
+
+int
+main(int argc, char *argv[]) {
+ char *origin = NULL, *file = NULL;
+ char *inputformatstr = NULL;
+ isc_result_t result;
+ isc_log_t *log = NULL;
+ const char *engine = NULL;
+ char *classname = NULL;
+ dns_rdataclass_t rdclass;
+ char *endp;
+ int ch;
+
+#define CMDLINE_FLAGS "c:E:hm:o:I:qv:Vxz"
+
+ /*
+ * Process memory debugging argument first.
+ */
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case 'm':
+ if (strcasecmp(isc_commandline_argument, "record") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ }
+ if (strcasecmp(isc_commandline_argument, "trace") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
+ }
+ if (strcasecmp(isc_commandline_argument, "usage") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = true;
+ check_result(isc_app_start(), "isc_app_start");
+
+ isc_mem_create(&mctx);
+
+ isc_commandline_errprint = false;
+
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+
+ case 'E':
+ engine = isc_commandline_argument;
+ break;
+
+ case 'I':
+ inputformatstr = isc_commandline_argument;
+ break;
+
+ case 'm':
+ break;
+
+ case 'o':
+ origin = isc_commandline_argument;
+ break;
+
+ case 'v':
+ endp = NULL;
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0') {
+ fatal("verbose level must be numeric");
+ }
+ break;
+
+ case 'q':
+ quiet = true;
+ break;
+
+ case 'x':
+ keyset_kskonly = true;
+ break;
+
+ case 'z':
+ ignore_kskflag = true;
+ break;
+
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ }
+ FALLTHROUGH;
+
+ case 'h':
+ /* Does not return. */
+ usage();
+
+ case 'V':
+ /* Does not return. */
+ version(program);
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ result = dst_lib_init(mctx, engine);
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not initialize dst: %s",
+ isc_result_totext(result));
+ }
+
+ isc_stdtime_get(&now);
+
+ rdclass = strtoclass(classname);
+
+ setup_logging(mctx, &log);
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc < 1) {
+ usage();
+ }
+
+ file = argv[0];
+
+ argc -= 1;
+ argv += 1;
+
+ POST(argc);
+ POST(argv);
+
+ if (origin == NULL) {
+ origin = file;
+ }
+
+ if (inputformatstr != NULL) {
+ if (strcasecmp(inputformatstr, "text") == 0) {
+ inputformat = dns_masterformat_text;
+ } else if (strcasecmp(inputformatstr, "raw") == 0) {
+ inputformat = dns_masterformat_raw;
+ } else {
+ fatal("unknown file format: %s\n", inputformatstr);
+ }
+ }
+
+ gdb = NULL;
+ report("Loading zone '%s' from file '%s'\n", origin, file);
+ loadzone(file, origin, rdclass, &gdb);
+ gorigin = dns_db_origin(gdb);
+ gclass = dns_db_class(gdb);
+
+ gversion = NULL;
+ result = dns_db_newversion(gdb, &gversion);
+ check_result(result, "dns_db_newversion()");
+
+ result = dns_zoneverify_dnssec(NULL, gdb, gversion, gorigin, NULL, mctx,
+ ignore_kskflag, keyset_kskonly, report);
+
+ dns_db_closeversion(gdb, &gversion, false);
+ dns_db_detach(&gdb);
+
+ cleanup_logging(&log);
+ dst_lib_destroy();
+ if (verbose > 10) {
+ isc_mem_stats(mctx, stdout);
+ }
+ isc_mem_destroy(&mctx);
+
+ (void)isc_app_finish();
+
+ return (result == ISC_R_SUCCESS ? 0 : 1);
+}
diff --git a/bin/dnssec/dnssec-verify.rst b/bin/dnssec/dnssec-verify.rst
new file mode 100644
index 0000000..8700894
--- /dev/null
+++ b/bin/dnssec/dnssec-verify.rst
@@ -0,0 +1,107 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: dnssec-verify
+.. program:: dnssec-verify
+.. _man_dnssec-verify:
+
+dnssec-verify - DNSSEC zone verification tool
+---------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`dnssec-verify` [**-c** class] [**-E** engine] [**-I** input-format] [**-o** origin] [**-q**] [**-v** level] [**-V**] [**-x**] [**-z**] {zonefile}
+
+Description
+~~~~~~~~~~~
+
+:program:`dnssec-verify` verifies that a zone is fully signed for each
+algorithm found in the DNSKEY RRset for the zone, and that the
+NSEC/NSEC3 chains are complete.
+
+Options
+~~~~~~~
+
+.. option:: -c class
+
+ This option specifies the DNS class of the zone.
+
+.. option:: -E engine
+
+ This option specifies the cryptographic hardware to use, when applicable.
+
+ When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL
+ engine identifier that drives the cryptographic accelerator or
+ hardware service module (usually ``pkcs11``).
+
+.. option:: -I input-format
+
+ This option sets the format of the input zone file. Possible formats are ``text``
+ (the default) and ``raw``. This option is primarily intended to be used
+ for dynamic signed zones, so that the dumped zone file in a non-text
+ format containing updates can be verified independently.
+ This option is not useful for non-dynamic zones.
+
+.. option:: -o origin
+
+ This option indicates the zone origin. If not specified, the name of the zone file is
+ assumed to be the origin.
+
+.. option:: -v level
+
+ This option sets the debugging level.
+
+.. option:: -V
+
+ This option prints version information.
+
+.. option:: -q
+
+ This option sets quiet mode, which suppresses output. Without this option, when :program:`dnssec-verify`
+ is run it prints to standard output the number of keys in use, the
+ algorithms used to verify the zone was signed correctly, and other status
+ information. With this option, all non-error output is suppressed, and only the exit
+ code indicates success.
+
+.. option:: -x
+
+ This option verifies only that the DNSKEY RRset is signed with key-signing keys.
+ Without this flag, it is assumed that the DNSKEY RRset is signed
+ by all active keys. When this flag is set, it is not an error if
+ the DNSKEY RRset is not signed by zone-signing keys. This corresponds
+ to the :option:`-x option in dnssec-signzone <dnssec-signzone -x>`.
+
+.. option:: -z
+
+ This option indicates that the KSK flag on the keys should be ignored when determining whether the zone is
+ correctly signed. Without this flag, it is assumed that there is
+ a non-revoked, self-signed DNSKEY with the KSK flag set for each
+ algorithm, and that RRsets other than DNSKEY RRset are signed with
+ a different DNSKEY without the KSK flag set.
+
+ With this flag set, BIND 9 only requires that for each algorithm, there
+ be at least one non-revoked, self-signed DNSKEY, regardless of
+ the KSK flag state, and that other RRsets be signed by a
+ non-revoked key for the same algorithm that includes the self-signed
+ key; the same key may be used for both purposes. This corresponds to
+ the :option:`-z option in dnssec-signzone <dnssec-signzone -z>`.
+
+.. option:: zonefile
+
+ This option indicates the file containing the zone to be signed.
+
+See Also
+~~~~~~~~
+
+:iscman:`dnssec-signzone(8) <dnssec-signzone>`, BIND 9 Administrator Reference Manual, :rfc:`4033`.
diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c
new file mode 100644
index 0000000..c07e091
--- /dev/null
+++ b/bin/dnssec/dnssectool.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+/*%
+ * DNSSEC Support Routines.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/base32.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/file.h>
+#include <isc/heap.h>
+#include <isc/list.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/tm.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/dnssec.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/secalg.h>
+#include <dns/time.h>
+
+#include "dnssectool.h"
+
+#define KEYSTATES_NVALUES 4
+static const char *keystates[KEYSTATES_NVALUES] = {
+ "hidden",
+ "rumoured",
+ "omnipresent",
+ "unretentive",
+};
+
+int verbose = 0;
+bool quiet = false;
+dns_dsdigest_t dtype[8];
+
+static fatalcallback_t *fatalcallback = NULL;
+
+void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fprintf(stderr, "%s: fatal: ", program);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ if (fatalcallback != NULL) {
+ (*fatalcallback)();
+ }
+ exit(1);
+}
+
+void
+setfatalcallback(fatalcallback_t *callback) {
+ fatalcallback = callback;
+}
+
+void
+check_result(isc_result_t result, const char *message) {
+ if (result != ISC_R_SUCCESS) {
+ fatal("%s: %s", message, isc_result_totext(result));
+ }
+}
+
+void
+vbprintf(int level, const char *fmt, ...) {
+ va_list ap;
+ if (level > verbose) {
+ return;
+ }
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: ", program);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+void
+version(const char *name) {
+ fprintf(stderr, "%s %s\n", name, PACKAGE_VERSION);
+ exit(0);
+}
+
+void
+sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char algstr[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(&sig->signer, namestr, sizeof(namestr));
+ dns_secalg_format(sig->algorithm, algstr, sizeof(algstr));
+ snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid);
+}
+
+void
+setup_logging(isc_mem_t *mctx, isc_log_t **logp) {
+ isc_logdestination_t destination;
+ isc_logconfig_t *logconfig = NULL;
+ isc_log_t *log = NULL;
+ int level;
+
+ if (verbose < 0) {
+ verbose = 0;
+ }
+ switch (verbose) {
+ case 0:
+ /*
+ * We want to see warnings about things like out-of-zone
+ * data in the master file even when not verbose.
+ */
+ level = ISC_LOG_WARNING;
+ break;
+ case 1:
+ level = ISC_LOG_INFO;
+ break;
+ default:
+ level = ISC_LOG_DEBUG(verbose - 2 + 1);
+ break;
+ }
+
+ isc_log_create(mctx, &log, &logconfig);
+ isc_log_setcontext(log);
+ dns_log_init(log);
+ dns_log_setcontext(log);
+ isc_log_settag(logconfig, program);
+
+ /*
+ * Set up a channel similar to default_stderr except:
+ * - the logging level is passed in
+ * - the program name and logging level are printed
+ * - no time stamp is printed
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, level,
+ &destination,
+ ISC_LOG_PRINTTAG | ISC_LOG_PRINTLEVEL);
+
+ RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL) ==
+ ISC_R_SUCCESS);
+
+ *logp = log;
+}
+
+void
+cleanup_logging(isc_log_t **logp) {
+ isc_log_t *log;
+
+ REQUIRE(logp != NULL);
+
+ log = *logp;
+ *logp = NULL;
+
+ if (log == NULL) {
+ return;
+ }
+
+ isc_log_destroy(&log);
+ isc_log_setcontext(NULL);
+ dns_log_setcontext(NULL);
+}
+
+static isc_stdtime_t
+time_units(isc_stdtime_t offset, char *suffix, const char *str) {
+ switch (suffix[0]) {
+ case 'Y':
+ case 'y':
+ return (offset * (365 * 24 * 3600));
+ case 'M':
+ case 'm':
+ switch (suffix[1]) {
+ case 'O':
+ case 'o':
+ return (offset * (30 * 24 * 3600));
+ case 'I':
+ case 'i':
+ return (offset * 60);
+ case '\0':
+ fatal("'%s' ambiguous: use 'mi' for minutes "
+ "or 'mo' for months",
+ str);
+ default:
+ fatal("time value %s is invalid", str);
+ }
+ UNREACHABLE();
+ break;
+ case 'W':
+ case 'w':
+ return (offset * (7 * 24 * 3600));
+ case 'D':
+ case 'd':
+ return (offset * (24 * 3600));
+ case 'H':
+ case 'h':
+ return (offset * 3600);
+ case 'S':
+ case 's':
+ case '\0':
+ return (offset);
+ default:
+ fatal("time value %s is invalid", str);
+ }
+ UNREACHABLE();
+ return (0); /* silence compiler warning */
+}
+
+static bool
+isnone(const char *str) {
+ return ((strcasecmp(str, "none") == 0) ||
+ (strcasecmp(str, "never") == 0) ||
+ (strcasecmp(str, "unset") == 0));
+}
+
+dns_ttl_t
+strtottl(const char *str) {
+ const char *orig = str;
+ dns_ttl_t ttl;
+ char *endp;
+
+ if (isnone(str)) {
+ return ((dns_ttl_t)0);
+ }
+
+ ttl = strtol(str, &endp, 0);
+ if (ttl == 0 && endp == str) {
+ fatal("TTL must be numeric");
+ }
+ ttl = time_units(ttl, endp, orig);
+ return (ttl);
+}
+
+dst_key_state_t
+strtokeystate(const char *str) {
+ if (isnone(str)) {
+ return (DST_KEY_STATE_NA);
+ }
+
+ for (int i = 0; i < KEYSTATES_NVALUES; i++) {
+ if (keystates[i] != NULL && strcasecmp(str, keystates[i]) == 0)
+ {
+ return ((dst_key_state_t)i);
+ }
+ }
+ fatal("unknown key state %s", str);
+}
+
+isc_stdtime_t
+strtotime(const char *str, int64_t now, int64_t base, bool *setp) {
+ int64_t val, offset;
+ isc_result_t result;
+ const char *orig = str;
+ char *endp;
+ size_t n;
+ struct tm tm;
+
+ if (isnone(str)) {
+ if (setp != NULL) {
+ *setp = false;
+ }
+ return ((isc_stdtime_t)0);
+ }
+
+ if (setp != NULL) {
+ *setp = true;
+ }
+
+ if ((str[0] == '0' || str[0] == '-') && str[1] == '\0') {
+ return ((isc_stdtime_t)0);
+ }
+
+ /*
+ * We accept times in the following formats:
+ * now([+-]offset)
+ * YYYYMMDD([+-]offset)
+ * YYYYMMDDhhmmss([+-]offset)
+ * Day Mon DD HH:MM:SS YYYY([+-]offset)
+ * 1234567890([+-]offset)
+ * [+-]offset
+ */
+ n = strspn(str, "0123456789");
+ if ((n == 8u || n == 14u) &&
+ (str[n] == '\0' || str[n] == '-' || str[n] == '+'))
+ {
+ char timestr[15];
+
+ strlcpy(timestr, str, sizeof(timestr));
+ timestr[n] = 0;
+ if (n == 8u) {
+ strlcat(timestr, "000000", sizeof(timestr));
+ }
+ result = dns_time64_fromtext(timestr, &val);
+ if (result != ISC_R_SUCCESS) {
+ fatal("time value %s is invalid: %s", orig,
+ isc_result_totext(result));
+ }
+ base = val;
+ str += n;
+ } else if (n == 10u &&
+ (str[n] == '\0' || str[n] == '-' || str[n] == '+'))
+ {
+ base = strtoll(str, &endp, 0);
+ str += 10;
+ } else if (strncmp(str, "now", 3) == 0) {
+ base = now;
+ str += 3;
+ } else if (str[0] >= 'A' && str[0] <= 'Z') {
+ /* parse ctime() format as written by `dnssec-settime -p` */
+ endp = isc_tm_strptime(str, "%a %b %d %H:%M:%S %Y", &tm);
+ if (endp != str + 24) {
+ fatal("time value %s is invalid", orig);
+ }
+ base = mktime(&tm);
+ str += 24;
+ }
+
+ if (str[0] == '\0') {
+ return ((isc_stdtime_t)base);
+ } else if (str[0] == '+') {
+ offset = strtol(str + 1, &endp, 0);
+ offset = time_units((isc_stdtime_t)offset, endp, orig);
+ val = base + offset;
+ } else if (str[0] == '-') {
+ offset = strtol(str + 1, &endp, 0);
+ offset = time_units((isc_stdtime_t)offset, endp, orig);
+ val = base - offset;
+ } else {
+ fatal("time value %s is invalid", orig);
+ }
+
+ return ((isc_stdtime_t)val);
+}
+
+dns_rdataclass_t
+strtoclass(const char *str) {
+ isc_textregion_t r;
+ dns_rdataclass_t rdclass;
+ isc_result_t result;
+
+ if (str == NULL) {
+ return (dns_rdataclass_in);
+ }
+ DE_CONST(str, r.base);
+ r.length = strlen(str);
+ result = dns_rdataclass_fromtext(&rdclass, &r);
+ if (result != ISC_R_SUCCESS) {
+ fatal("unknown class %s", str);
+ }
+ return (rdclass);
+}
+
+unsigned int
+strtodsdigest(const char *str) {
+ isc_textregion_t r;
+ dns_dsdigest_t alg;
+ isc_result_t result;
+
+ DE_CONST(str, r.base);
+ r.length = strlen(str);
+ result = dns_dsdigest_fromtext(&alg, &r);
+ if (result != ISC_R_SUCCESS) {
+ fatal("unknown DS algorithm %s", str);
+ }
+ return (alg);
+}
+
+static int
+cmp_dtype(const void *ap, const void *bp) {
+ int a = *(const uint8_t *)ap;
+ int b = *(const uint8_t *)bp;
+ return (a - b);
+}
+
+void
+add_dtype(unsigned int dt) {
+ unsigned i, n;
+
+ /* ensure there is space for a zero terminator */
+ n = sizeof(dtype) / sizeof(dtype[0]) - 1;
+ for (i = 0; i < n; i++) {
+ if (dtype[i] == dt) {
+ return;
+ }
+ if (dtype[i] == 0) {
+ dtype[i] = dt;
+ qsort(dtype, i + 1, 1, cmp_dtype);
+ return;
+ }
+ }
+ fatal("too many -a digest type arguments");
+}
+
+isc_result_t
+try_dir(const char *dirname) {
+ isc_result_t result;
+ isc_dir_t d;
+
+ isc_dir_init(&d);
+ result = isc_dir_open(&d, dirname);
+ if (result == ISC_R_SUCCESS) {
+ isc_dir_close(&d);
+ }
+ return (result);
+}
+
+/*
+ * Check private key version compatibility.
+ */
+void
+check_keyversion(dst_key_t *key, char *keystr) {
+ int major, minor;
+ dst_key_getprivateformat(key, &major, &minor);
+ INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */
+
+ if (major < DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) {
+ fatal("Key %s has incompatible format version %d.%d, "
+ "use -f to force upgrade to new version.",
+ keystr, major, minor);
+ }
+ if (minor > DST_MINOR_VERSION) {
+ fatal("Key %s has incompatible format version %d.%d, "
+ "use -f to force downgrade to current version.",
+ keystr, major, minor);
+ }
+}
+
+void
+set_keyversion(dst_key_t *key) {
+ int major, minor;
+ dst_key_getprivateformat(key, &major, &minor);
+ INSIST(major <= DST_MAJOR_VERSION);
+
+ if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION) {
+ dst_key_setprivateformat(key, DST_MAJOR_VERSION,
+ DST_MINOR_VERSION);
+ }
+
+ /*
+ * If the key is from a version older than 1.3, set
+ * set the creation date
+ */
+ if (major < 1 || (major == 1 && minor <= 2)) {
+ isc_stdtime_t now;
+ isc_stdtime_get(&now);
+ dst_key_settime(key, DST_TIME_CREATED, now);
+ }
+}
+
+bool
+key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
+ isc_mem_t *mctx, bool *exact) {
+ isc_result_t result;
+ bool conflict = false;
+ dns_dnsseckeylist_t matchkeys;
+ dns_dnsseckey_t *key = NULL;
+ uint16_t id, oldid;
+ uint32_t rid, roldid;
+ dns_secalg_t alg;
+ char filename[NAME_MAX];
+ isc_buffer_t fileb;
+ isc_stdtime_t now;
+
+ if (exact != NULL) {
+ *exact = false;
+ }
+
+ id = dst_key_id(dstkey);
+ rid = dst_key_rid(dstkey);
+ alg = dst_key_alg(dstkey);
+
+ /*
+ * For Diffie Hellman just check if there is a direct collision as
+ * they can't be revoked. Additionally dns_dnssec_findmatchingkeys
+ * only handles DNSKEY which is not used for HMAC.
+ */
+ if (alg == DST_ALG_DH) {
+ isc_buffer_init(&fileb, filename, sizeof(filename));
+ result = dst_key_buildfilename(dstkey, DST_TYPE_PRIVATE, dir,
+ &fileb);
+ if (result != ISC_R_SUCCESS) {
+ return (true);
+ }
+ return (isc_file_exists(filename));
+ }
+
+ ISC_LIST_INIT(matchkeys);
+ isc_stdtime_get(&now);
+ result = dns_dnssec_findmatchingkeys(name, dir, now, mctx, &matchkeys);
+ if (result == ISC_R_NOTFOUND) {
+ return (false);
+ }
+
+ while (!ISC_LIST_EMPTY(matchkeys) && !conflict) {
+ key = ISC_LIST_HEAD(matchkeys);
+ if (dst_key_alg(key->key) != alg) {
+ goto next;
+ }
+
+ oldid = dst_key_id(key->key);
+ roldid = dst_key_rid(key->key);
+
+ if (oldid == rid || roldid == id || id == oldid) {
+ conflict = true;
+ if (id != oldid) {
+ if (verbose > 1) {
+ fprintf(stderr,
+ "Key ID %d could "
+ "collide with %d\n",
+ id, oldid);
+ }
+ } else {
+ if (exact != NULL) {
+ *exact = true;
+ }
+ if (verbose > 1) {
+ fprintf(stderr, "Key ID %d exists\n",
+ id);
+ }
+ }
+ }
+
+ next:
+ ISC_LIST_UNLINK(matchkeys, key, link);
+ dns_dnsseckey_destroy(mctx, &key);
+ }
+
+ /* Finish freeing the list */
+ while (!ISC_LIST_EMPTY(matchkeys)) {
+ key = ISC_LIST_HEAD(matchkeys);
+ ISC_LIST_UNLINK(matchkeys, key, link);
+ dns_dnsseckey_destroy(mctx, &key);
+ }
+
+ return (conflict);
+}
+
+bool
+isoptarg(const char *arg, char **argv, void (*usage)(void)) {
+ if (!strcasecmp(isc_commandline_argument, arg)) {
+ if (argv[isc_commandline_index] == NULL) {
+ fprintf(stderr, "%s: missing argument -%c %s\n",
+ program, isc_commandline_option,
+ isc_commandline_argument);
+ usage();
+ }
+ isc_commandline_argument = argv[isc_commandline_index];
+ /* skip to next argument */
+ isc_commandline_index++;
+ return (true);
+ }
+ return (false);
+}
diff --git a/bin/dnssec/dnssectool.h b/bin/dnssec/dnssectool.h
new file mode 100644
index 0000000..f38bc55
--- /dev/null
+++ b/bin/dnssec/dnssectool.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/attributes.h>
+#include <isc/log.h>
+#include <isc/stdtime.h>
+
+#include <dns/rdatastruct.h>
+
+#include <dst/dst.h>
+
+/*! verbosity: set by -v and -q option in each program, defined in dnssectool.c
+ */
+extern int verbose;
+extern bool quiet;
+
+/*! program name, statically initialized in each program */
+extern const char *program;
+
+/*!
+ * List of DS digest types used by dnssec-cds and dnssec-dsfromkey,
+ * defined in dnssectool.c. Filled in by add_dtype() from -a
+ * arguments, sorted (so that DS records are in a canonical order) and
+ * terminated by a zero. The size of the array is an arbitrary limit
+ * which should be greater than the number of known digest types.
+ */
+extern uint8_t dtype[8];
+
+typedef void(fatalcallback_t)(void);
+
+noreturn void
+fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+setfatalcallback(fatalcallback_t *callback);
+
+void
+check_result(isc_result_t result, const char *message);
+
+void
+vbprintf(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
+
+noreturn void
+version(const char *program);
+
+void
+sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size);
+#define SIG_FORMATSIZE \
+ (DNS_NAME_FORMATSIZE + DNS_SECALG_FORMATSIZE + sizeof("65535"))
+
+void
+setup_logging(isc_mem_t *mctx, isc_log_t **logp);
+
+void
+cleanup_logging(isc_log_t **logp);
+
+dns_ttl_t
+strtottl(const char *str);
+
+dst_key_state_t
+strtokeystate(const char *str);
+
+isc_stdtime_t
+strtotime(const char *str, int64_t now, int64_t base, bool *setp);
+
+dns_rdataclass_t
+strtoclass(const char *str);
+
+unsigned int
+strtodsdigest(const char *str);
+
+void
+add_dtype(unsigned int dt);
+
+isc_result_t
+try_dir(const char *dirname);
+
+void
+check_keyversion(dst_key_t *key, char *keystr);
+
+void
+set_keyversion(dst_key_t *key);
+
+bool
+key_collision(dst_key_t *key, dns_name_t *name, const char *dir,
+ isc_mem_t *mctx, bool *exact);
+
+bool
+isoptarg(const char *arg, char **argv, void (*usage)(void));
diff --git a/bin/named/Makefile.am b/bin/named/Makefile.am
new file mode 100644
index 0000000..57a023b
--- /dev/null
+++ b/bin/named/Makefile.am
@@ -0,0 +1,123 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ -I$(top_builddir)/include \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) \
+ $(LIBNS_CFLAGS) \
+ $(LIBISCCC_CFLAGS) \
+ $(LIBISCCFG_CFLAGS) \
+ $(LIBBIND9_CFLAGS) \
+ $(OPENSSL_CFLAGS) \
+ $(LIBCAP_CFLAGS) \
+ $(LMDB_CFLAGS) \
+ $(MAXMINDDB_CFLAGS) \
+ $(DNSTAP_CFLAGS) \
+ $(LIBUV_CFLAGS) \
+ $(ZLIB_CFLAGS)
+
+if HAVE_JSON_C
+AM_CPPFLAGS += \
+ $(JSON_C_CFLAGS)
+endif HAVE_JSON_C
+
+if HAVE_LIBNGHTTP2
+AM_CPPFLAGS += \
+ $(LIBNGHTTP2_CFLAGS)
+endif HAVE_LIBNGHTTP2
+
+if HAVE_LIBXML2
+AM_CPPFLAGS += \
+ $(LIBXML2_CFLAGS)
+endif HAVE_LIBXML2
+
+AM_CPPFLAGS += \
+ -DNAMED_LOCALSTATEDIR=\"${localstatedir}\" \
+ -DNAMED_SYSCONFDIR=\"${sysconfdir}\"
+
+sbin_PROGRAMS = named
+
+nodist_named_SOURCES = xsl.c
+BUILT_SOURCES = xsl.c
+CLEANFILES = xsl.c
+
+EXTRA_DIST = bind9.xsl
+
+xsl.c: bind9.xsl Makefile
+ (echo 'const char xslmsg[] =' && \
+ $(SED) -e 's,\",\\\",g' \
+ -e 's,^,\",' \
+ -e 's,$$,\\n\",' && \
+ echo ";") \
+ < "${srcdir}/bind9.xsl" > $@
+
+named_SOURCES = \
+ builtin.c \
+ config.c \
+ control.c \
+ controlconf.c \
+ dlz_dlopen_driver.c \
+ fuzz.c \
+ log.c \
+ logconf.c \
+ main.c \
+ os.c \
+ server.c \
+ statschannel.c \
+ tkeyconf.c \
+ transportconf.c \
+ tsigconf.c \
+ zoneconf.c \
+ include/dlz/dlz_dlopen_driver.h \
+ include/named/builtin.h \
+ include/named/config.h \
+ include/named/control.h \
+ include/named/fuzz.h \
+ include/named/geoip.h \
+ include/named/globals.h \
+ include/named/log.h \
+ include/named/logconf.h \
+ include/named/main.h \
+ include/named/os.h \
+ include/named/server.h \
+ include/named/smf_globals.h \
+ include/named/statschannel.h \
+ include/named/tkeyconf.h \
+ include/named/transportconf.h \
+ include/named/tsigconf.h \
+ include/named/types.h \
+ include/named/zoneconf.h \
+ xsl_p.h
+
+if HAVE_GEOIP2
+AM_CPPFLAGS += \
+ -DMAXMINDDB_PREFIX=\"@MAXMINDDB_PREFIX@\"
+named_SOURCES += \
+ geoip.c
+endif
+
+named_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS) \
+ $(LIBNS_LIBS) \
+ $(LIBISCCC_LIBS) \
+ $(LIBISCCFG_LIBS) \
+ $(LIBBIND9_LIBS) \
+ $(OPENSSL_LIBS) \
+ $(LIBCAP_LIBS) \
+ $(LMDB_LIBS) \
+ $(MAXMINDDB_LIBS) \
+ $(DNSTAP_LIBS) \
+ $(LIBUV_LIBS) \
+ $(LIBXML2_LIBS) \
+ $(ZLIB_LIBS)
+
+if HAVE_JSON_C
+named_LDADD += \
+ $(JSON_C_LIBS)
+endif HAVE_JSON_C
+
+if HAVE_LIBNGHTTP2
+named_LDADD += \
+ $(LIBNGHTTP2_LIBS)
+endif HAVE_LIBNGHTTP2
diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in
new file mode 100644
index 0000000..a38ce3b
--- /dev/null
+++ b/bin/named/Makefile.in
@@ -0,0 +1,964 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+@HAVE_JSON_C_TRUE@am__append_2 = \
+@HAVE_JSON_C_TRUE@ $(JSON_C_CFLAGS)
+
+@HAVE_LIBNGHTTP2_TRUE@am__append_3 = \
+@HAVE_LIBNGHTTP2_TRUE@ $(LIBNGHTTP2_CFLAGS)
+
+@HAVE_LIBXML2_TRUE@am__append_4 = \
+@HAVE_LIBXML2_TRUE@ $(LIBXML2_CFLAGS)
+
+sbin_PROGRAMS = named$(EXEEXT)
+@HAVE_GEOIP2_TRUE@am__append_5 = \
+@HAVE_GEOIP2_TRUE@ -DMAXMINDDB_PREFIX=\"@MAXMINDDB_PREFIX@\"
+
+@HAVE_GEOIP2_TRUE@am__append_6 = \
+@HAVE_GEOIP2_TRUE@ geoip.c
+
+@HAVE_JSON_C_TRUE@am__append_7 = \
+@HAVE_JSON_C_TRUE@ $(JSON_C_LIBS)
+
+@HAVE_LIBNGHTTP2_TRUE@am__append_8 = \
+@HAVE_LIBNGHTTP2_TRUE@ $(LIBNGHTTP2_LIBS)
+
+subdir = bin/named
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)"
+PROGRAMS = $(sbin_PROGRAMS)
+am__named_SOURCES_DIST = builtin.c config.c control.c controlconf.c \
+ dlz_dlopen_driver.c fuzz.c log.c logconf.c main.c os.c \
+ server.c statschannel.c tkeyconf.c transportconf.c tsigconf.c \
+ zoneconf.c include/dlz/dlz_dlopen_driver.h \
+ include/named/builtin.h include/named/config.h \
+ include/named/control.h include/named/fuzz.h \
+ include/named/geoip.h include/named/globals.h \
+ include/named/log.h include/named/logconf.h \
+ include/named/main.h include/named/os.h include/named/server.h \
+ include/named/smf_globals.h include/named/statschannel.h \
+ include/named/tkeyconf.h include/named/transportconf.h \
+ include/named/tsigconf.h include/named/types.h \
+ include/named/zoneconf.h xsl_p.h geoip.c
+@HAVE_GEOIP2_TRUE@am__objects_1 = geoip.$(OBJEXT)
+am_named_OBJECTS = builtin.$(OBJEXT) config.$(OBJEXT) \
+ control.$(OBJEXT) controlconf.$(OBJEXT) \
+ dlz_dlopen_driver.$(OBJEXT) fuzz.$(OBJEXT) log.$(OBJEXT) \
+ logconf.$(OBJEXT) main.$(OBJEXT) os.$(OBJEXT) server.$(OBJEXT) \
+ statschannel.$(OBJEXT) tkeyconf.$(OBJEXT) \
+ transportconf.$(OBJEXT) tsigconf.$(OBJEXT) zoneconf.$(OBJEXT) \
+ $(am__objects_1)
+nodist_named_OBJECTS = xsl.$(OBJEXT)
+named_OBJECTS = $(am_named_OBJECTS) $(nodist_named_OBJECTS)
+am__DEPENDENCIES_1 =
+@HAVE_JSON_C_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+@HAVE_LIBNGHTTP2_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+named_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBNS_LIBS) \
+ $(LIBISCCC_LIBS) $(LIBISCCFG_LIBS) $(LIBBIND9_LIBS) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/builtin.Po ./$(DEPDIR)/config.Po \
+ ./$(DEPDIR)/control.Po ./$(DEPDIR)/controlconf.Po \
+ ./$(DEPDIR)/dlz_dlopen_driver.Po ./$(DEPDIR)/fuzz.Po \
+ ./$(DEPDIR)/geoip.Po ./$(DEPDIR)/log.Po ./$(DEPDIR)/logconf.Po \
+ ./$(DEPDIR)/main.Po ./$(DEPDIR)/os.Po ./$(DEPDIR)/server.Po \
+ ./$(DEPDIR)/statschannel.Po ./$(DEPDIR)/tkeyconf.Po \
+ ./$(DEPDIR)/transportconf.Po ./$(DEPDIR)/tsigconf.Po \
+ ./$(DEPDIR)/xsl.Po ./$(DEPDIR)/zoneconf.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(named_SOURCES) $(nodist_named_SOURCES)
+DIST_SOURCES = $(am__named_SOURCES_DIST)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include -I$(top_builddir)/include $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) $(LIBNS_CFLAGS) $(LIBISCCC_CFLAGS) \
+ $(LIBISCCFG_CFLAGS) $(LIBBIND9_CFLAGS) $(OPENSSL_CFLAGS) \
+ $(LIBCAP_CFLAGS) $(LMDB_CFLAGS) $(MAXMINDDB_CFLAGS) \
+ $(DNSTAP_CFLAGS) $(LIBUV_CFLAGS) $(ZLIB_CFLAGS) \
+ $(am__append_2) $(am__append_3) $(am__append_4) \
+ -DNAMED_LOCALSTATEDIR=\"${localstatedir}\" \
+ -DNAMED_SYSCONFDIR=\"${sysconfdir}\" $(am__append_5)
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD =
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+nodist_named_SOURCES = xsl.c
+BUILT_SOURCES = xsl.c
+CLEANFILES = xsl.c
+EXTRA_DIST = bind9.xsl
+named_SOURCES = builtin.c config.c control.c controlconf.c \
+ dlz_dlopen_driver.c fuzz.c log.c logconf.c main.c os.c \
+ server.c statschannel.c tkeyconf.c transportconf.c tsigconf.c \
+ zoneconf.c include/dlz/dlz_dlopen_driver.h \
+ include/named/builtin.h include/named/config.h \
+ include/named/control.h include/named/fuzz.h \
+ include/named/geoip.h include/named/globals.h \
+ include/named/log.h include/named/logconf.h \
+ include/named/main.h include/named/os.h include/named/server.h \
+ include/named/smf_globals.h include/named/statschannel.h \
+ include/named/tkeyconf.h include/named/transportconf.h \
+ include/named/tsigconf.h include/named/types.h \
+ include/named/zoneconf.h xsl_p.h $(am__append_6)
+named_LDADD = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBNS_LIBS) \
+ $(LIBISCCC_LIBS) $(LIBISCCFG_LIBS) $(LIBBIND9_LIBS) \
+ $(OPENSSL_LIBS) $(LIBCAP_LIBS) $(LMDB_LIBS) $(MAXMINDDB_LIBS) \
+ $(DNSTAP_LIBS) $(LIBUV_LIBS) $(LIBXML2_LIBS) $(ZLIB_LIBS) \
+ $(am__append_7) $(am__append_8)
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/named/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/named/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+named$(EXEEXT): $(named_OBJECTS) $(named_DEPENDENCIES) $(EXTRA_named_DEPENDENCIES)
+ @rm -f named$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(named_OBJECTS) $(named_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builtin.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/control.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/controlconf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlz_dlopen_driver.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/geoip.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logconf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statschannel.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tkeyconf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transportconf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsigconf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xsl.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoneconf.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/builtin.Po
+ -rm -f ./$(DEPDIR)/config.Po
+ -rm -f ./$(DEPDIR)/control.Po
+ -rm -f ./$(DEPDIR)/controlconf.Po
+ -rm -f ./$(DEPDIR)/dlz_dlopen_driver.Po
+ -rm -f ./$(DEPDIR)/fuzz.Po
+ -rm -f ./$(DEPDIR)/geoip.Po
+ -rm -f ./$(DEPDIR)/log.Po
+ -rm -f ./$(DEPDIR)/logconf.Po
+ -rm -f ./$(DEPDIR)/main.Po
+ -rm -f ./$(DEPDIR)/os.Po
+ -rm -f ./$(DEPDIR)/server.Po
+ -rm -f ./$(DEPDIR)/statschannel.Po
+ -rm -f ./$(DEPDIR)/tkeyconf.Po
+ -rm -f ./$(DEPDIR)/transportconf.Po
+ -rm -f ./$(DEPDIR)/tsigconf.Po
+ -rm -f ./$(DEPDIR)/xsl.Po
+ -rm -f ./$(DEPDIR)/zoneconf.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/builtin.Po
+ -rm -f ./$(DEPDIR)/config.Po
+ -rm -f ./$(DEPDIR)/control.Po
+ -rm -f ./$(DEPDIR)/controlconf.Po
+ -rm -f ./$(DEPDIR)/dlz_dlopen_driver.Po
+ -rm -f ./$(DEPDIR)/fuzz.Po
+ -rm -f ./$(DEPDIR)/geoip.Po
+ -rm -f ./$(DEPDIR)/log.Po
+ -rm -f ./$(DEPDIR)/logconf.Po
+ -rm -f ./$(DEPDIR)/main.Po
+ -rm -f ./$(DEPDIR)/os.Po
+ -rm -f ./$(DEPDIR)/server.Po
+ -rm -f ./$(DEPDIR)/statschannel.Po
+ -rm -f ./$(DEPDIR)/tkeyconf.Po
+ -rm -f ./$(DEPDIR)/transportconf.Po
+ -rm -f ./$(DEPDIR)/tsigconf.Po
+ -rm -f ./$(DEPDIR)/xsl.Po
+ -rm -f ./$(DEPDIR)/zoneconf.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am: uninstall-sbinPROGRAMS
+
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: all check install install-am install-exec install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-sbinPROGRAMS cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir doc-am doc-local dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \
+ uninstall-am uninstall-sbinPROGRAMS unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+xsl.c: bind9.xsl Makefile
+ (echo 'const char xslmsg[] =' && \
+ $(SED) -e 's,\",\\\",g' \
+ -e 's,^,\",' \
+ -e 's,$$,\\n\",' && \
+ echo ";") \
+ < "${srcdir}/bind9.xsl" > $@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/named/bind9.xsl b/bin/named/bind9.xsl
new file mode 100644
index 0000000..9dda61d
--- /dev/null
+++ b/bin/named/bind9.xsl
@@ -0,0 +1,1106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - SPDX-License-Identifier: MPL-2.0
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" version="1.0">
+ <xsl:output method="html" indent="yes" version="4.0"/>
+ <!-- the version number **below** must match version in bin/named/statschannel.c -->
+ <!-- don't forget to update "/xml/v<STATS_XML_VERSION_MAJOR>" in the HTTP endpoints listed below -->
+ <xsl:template match="statistics[@version=&quot;3.13&quot;]">
+ <html>
+ <head>
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
+ <script type="text/javascript">
+ $(function($) {
+ var wid=0;
+ $('table.zones').each(function(i) { if( $(this).width() > wid ) wid = $(this).width(); return true; });
+ $('table.zones').css('min-width', wid );
+ $("h2+table,h3+table,h4+table,h2+div,h3+div,h2+script,h3+script").prev().append(' <a class="tabletoggle" href="#" style="font-size:small">Show/Hide</a>');
+ $(".tabletoggle").click(function(){
+ var n = $(this).closest("h2,h3,h4").next();
+ if (n.is("script")) { n = n.next(); }
+ if (n.is("div")) { n.toggleClass("hidden"); n = n.next(); }
+ if (n.is("table")) { n.toggleClass("hidden"); }
+ return false;
+ });
+ });
+ </script>
+
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <!-- Non Mozilla specific markup -->
+ <script type="text/javascript" src="https://www.google.com/jsapi"/>
+ <script type="text/javascript">
+
+ google.load("visualization", "1", {packages:["corechart"]});
+ google.setOnLoadCallback(loadGraphs);
+
+ var graphs=[];
+
+ function drawChart(chart_title,target,style,data) {
+ var data = google.visualization.arrayToDataTable(data);
+
+ var options = {
+ title: chart_title
+ };
+
+ var chart;
+ if (style == "barchart") {
+ chart = new google.visualization.BarChart(document.getElementById(target));
+ chart.draw(data, options);
+ } else if (style == "piechart") {
+ chart = new google.visualization.PieChart(document.getElementById(target));
+ chart.draw(data, options);
+ }
+ }
+
+ function loadGraphs(){
+ var g;
+
+ while(g = graphs.shift()){
+ // alert("going for: " + g.target);
+ if(g.data.length > 1){
+ drawChart(g.title,g.target,g.style,g.data);
+ }
+ }
+ }
+
+ <xsl:if test="server/counters[@type=&quot;qtype&quot;]/counter">
+ // Server Incoming Query Types
+ graphs.push({
+ 'title' : "Server Incoming Query Types",
+ 'target': 'chart_incoming_qtypes',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type=&quot;qtype&quot;]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+ </xsl:if>
+
+ <xsl:if test="server/counters[@type=&quot;opcode&quot;]/counter">
+ // Server Incoming Requests by opcode
+ graphs.push({
+ 'title' : "Server Incoming Requests by DNS Opcode",
+ 'target': 'chart_incoming_opcodes',
+ 'style': 'barchart',
+ 'data': [['Opcode','Counter'],<xsl:for-each select="server/counters[@type=&quot;opcode&quot;]/counter[. &gt; 0 or substring(@name,1,3) != 'RES']">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]});
+ </xsl:if>
+ </script>
+ </xsl:if>
+ <style type="text/css">
+ body {
+ font-family: sans-serif;
+ background-color: #ffffff;
+ color: #000000;
+ font-size: 10pt;
+ }
+
+ .hidden{
+ display: none;
+ }
+
+ .odd{
+ background-color: #f0f0f0;
+ }
+
+ .even{
+ background-color: #ffffff;
+ }
+
+ p.footer{
+ font-style:italic;
+ color: grey;
+ }
+
+ table {
+ border-collapse: collapse;
+ border: 1px solid grey;
+ }
+
+ table.counters{
+ border: 1px solid grey;
+ width: 500px;
+ }
+ table.counters th {
+ text-align: right;
+ border: 1px solid grey;
+ width: 150px;
+ }
+ table.counters td {
+ text-align: right;
+ font-family: monospace;
+ }
+ table.counters tr:hover{
+ background-color: #99ddff;
+ }
+
+ table.info {
+ border: 1px solid grey;
+ width: 500px;
+ }
+ table.info th {
+ text-align: center;
+ border: 1px solid grey;
+ width: 150px;
+ }
+ table.info td {
+ text-align: center;
+ }
+ table.info tr:hover{
+ background-color: #99ddff;
+ }
+
+ table.tasks {
+ border: 1px solid grey;
+ width: 500px;
+ }
+ table.tasks th {
+ text-align: center;
+ border: 1px solid grey;
+ width: 150px;
+ }
+ table.tasks td {
+ text-align: right;
+ font-family: monospace;
+ }
+ table.tasks td:nth-child(2) {
+ text-align: center;
+ }
+ table.tasks td:nth-child(4) {
+ text-align: center;
+ }
+ table.tasks tr:hover{
+ background-color: #99ddff;
+ }
+
+ table.netstat {
+ border: 1px solid grey;
+ width: 500px;
+ }
+ table.netstat th {
+ text-align: center;
+ border: 1px solid grey;
+ width: 150px;
+ }
+ table.netstat td {
+ text-align: center;
+ }
+ table.netstat td:nth-child(4) {
+ text-align: right;
+ font-family: monospace;
+ }
+ table.netstat td:nth-child(7) {
+ text-align: left;
+ }
+ table.netstat tr:hover{
+ background-color: #99ddff;
+ }
+
+ table.mctx {
+ border: 1px solid grey;
+ width: 500px;
+ }
+ table.mctx th {
+ text-align: center;
+ border: 1px solid grey;
+ }
+ table.mctx td {
+ text-align: right;
+ font-family: monospace;
+ }
+ table.mctx td:nth-child(-n+2) {
+ text-align: left;
+ width: 100px;
+ }
+ table.mctx tr:hover{
+ background-color: #99ddff;
+ }
+
+ table.zones {
+ border: 1px solid grey;
+ width: 500px;
+ }
+ table.zones th {
+ text-align: center;
+ border: 1px solid grey;
+ }
+ table.zones td {
+ text-align: center;
+ font-family: monospace;
+ }
+ table.zones td:nth-child(1) {
+ text-align: right;
+ }
+ table.zones td:nth-child(4) {
+ text-align: right;
+ }
+
+ .totals {
+ background-color: rgb(1,169,206);
+ color: #ffffff;
+ }
+ table.zones {
+ border: 1px solid grey;
+ }
+ table.zones td {
+ text-align: right;
+ font-family: monospace;
+ }
+ table.zones td:nth-child(2) {
+ text-align: center;
+ }
+ table.zones td:nth-child(3) {
+ text-align: left;
+ }
+ table.zones tr:hover{
+ background-color: #99ddff;
+ }
+
+ td, th {
+ padding-right: 5px;
+ padding-left: 5px;
+ border: 1px solid grey;
+ }
+
+ .header h1 {
+ color: rgb(1,169,206);
+ padding: 0px;
+ }
+
+ .content {
+ background-color: #ffffff;
+ color: #000000;
+ padding: 4px;
+ }
+
+ .item {
+ padding: 4px;
+ text-align: right;
+ }
+
+ .value {
+ padding: 4px;
+ font-weight: bold;
+ }
+
+
+ h2 {
+ color: grey;
+ font-size: 14pt;
+ width:500px;
+ text-align:center;
+ }
+
+ h3 {
+ color: #444444;
+ font-size: 12pt;
+ width:500px;
+ text-align:center;
+ }
+ h4 {
+ color: rgb(1,169,206);
+ font-size: 10pt;
+ width:500px;
+ text-align:center;
+ }
+
+ .pie {
+ width:500px;
+ height: 500px;
+ }
+
+ </style>
+ <title>ISC BIND 9 Statistics</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>ISC Bind 9 Configuration and Statistics</h1>
+ </div>
+ <p>Alternate statistics views: <a href="/">All</a>,
+ <a href="/xml/v3/status">Status</a>,
+ <a href="/xml/v3/server">Server</a>,
+ <a href="/xml/v3/zones">Zones</a>,
+ <a href="/xml/v3/net">Network</a>,
+ <a href="/xml/v3/tasks">Tasks</a>,
+ <a href="/xml/v3/mem">Memory</a> and
+ <a href="/xml/v3/traffic">Traffic Size</a></p>
+ <hr/>
+ <h2>Server Status</h2>
+ <table class="info">
+ <tr class="odd">
+ <th>Boot time:</th>
+ <td>
+ <xsl:value-of select="server/boot-time"/>
+ </td>
+ </tr>
+ <tr class="even">
+ <th>Last reconfigured:</th>
+ <td>
+ <xsl:value-of select="server/config-time"/>
+ </td>
+ </tr>
+ <tr class="odd">
+ <th>Current time:</th>
+ <td>
+ <xsl:value-of select="server/current-time"/>
+ </td>
+ </tr>
+ <tr class="even">
+ <th>Server version:</th>
+ <td>
+ <xsl:value-of select="server/version"/>
+ </td>
+ </tr>
+ </table>
+ <br/>
+ <xsl:if test="server/counters[@type=&quot;opcode&quot;]/counter[. &gt; 0]">
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <h2>Incoming Requests by DNS Opcode</h2>
+ <!-- Non Mozilla specific markup -->
+ <div class="pie" id="chart_incoming_opcodes">
+ [cannot display chart]
+ </div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="server/counters[@type=&quot;opcode&quot;]/counter[. &gt; 0 or substring(@name,1,3) != 'RES']">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class0">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class0}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ <tr>
+ <th class="totals">Total:</th>
+ <td class="totals">
+ <xsl:value-of select="sum(server/counters[@type=&quot;opcode&quot;]/counter)"/>
+ </td>
+ </tr>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="server/counters[@type=&quot;qtype&quot;]/counter">
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <!-- Non Mozilla specific markup -->
+ <h3>Incoming Queries by Query Type</h3>
+ <div class="pie" id="chart_incoming_qtypes">
+ [cannot display chart]
+ </div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="server/counters[@type=&quot;qtype&quot;]/counter">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ <tr>
+ <th class="totals">Total:</th>
+ <td class="totals">
+ <xsl:value-of select="sum(server/counters[@type=&quot;qtype&quot;]/counter)"/>
+ </td>
+ </tr>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="views/view[count(counters[@type=&quot;resqtype&quot;]/counter) &gt; 0]">
+ <h2>Outgoing Queries per view</h2>
+ <xsl:for-each select="views/view[count(counters[@type=&quot;resqtype&quot;]/counter) &gt; 0]">
+ <h3>View <xsl:value-of select="@name"/></h3>
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <!-- Non Mozilla specific markup -->
+ <script type="text/javascript">
+ graphs.push({
+ 'title': "Outgoing Queries for view: <xsl:value-of select="@name"/>",
+ 'target': 'chart_outgoing_queries_view_<xsl:value-of select="@name"/>',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="counters[@type=&quot;resqtype&quot;]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+ </script>
+ <xsl:variable name="target">
+ <xsl:value-of select="@name"/>
+ </xsl:variable>
+ <div class="pie" id="chart_outgoing_queries_view_{$target}">[no data to display]</div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="counters[@type=&quot;resqtype&quot;]/counter">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class1">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class1}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="server/counters[@type=&quot;nsstat&quot;]/counter[.&gt;0]">
+ <h2>Server Statistics</h2>
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <!-- Non Mozilla specific markup -->
+ <script type="text/javascript">
+ graphs.push({
+ 'title' : "Server Counters",
+ 'target': 'chart_server_nsstat_restype',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type=&quot;nsstat&quot;]/counter[.&gt;0]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+ </script>
+ <div class="pie" id="chart_server_nsstat_restype">[no data to display]</div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="server/counters[@type=&quot;nsstat&quot;]/counter[.&gt;0]">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class2">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class2}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="server/counters[@type=&quot;zonestat&quot;]/counter[.&gt;0]">
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <h2>Zone Maintenance Statistics</h2>
+ <script type="text/javascript">
+ graphs.push({
+ 'title' : "Zone Maintenance Stats",
+ 'target': 'chart_server_zone_maint',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type=&quot;zonestat&quot;]/counter[.&gt;0]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+ </script>
+ <!-- Non Mozilla specific markup -->
+ <div class="pie" id="chart_server_zone_maint">[no data to display]</div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="server/counters[@type=&quot;zonestat&quot;]/counter">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class3">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class3}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
+ <xsl:if test="server/counters[@type=&quot;resstat&quot;]/counter[.&gt;0]">
+ <h2>Resolver Statistics (Common)</h2>
+ <table class="counters">
+ <xsl:for-each select="server/counters[@type=&quot;resstat&quot;]/counter">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class4">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class4}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
+ <xsl:for-each select="views/view">
+ <xsl:if test="counters[@type=&quot;resstats&quot;]/counter[.&gt;0]">
+ <h3>Resolver Statistics for View <xsl:value-of select="@name"/></h3>
+ <table class="counters">
+ <xsl:for-each select="counters[@type=&quot;resstats&quot;]/counter[.&gt;0]">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class5">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class5}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="views/view">
+ <xsl:if test="counters[@type=&quot;adbstat&quot;]/counter[.&gt;0]">
+ <h3>ADB Statistics for View <xsl:value-of select="@name"/></h3>
+ <table class="counters">
+ <xsl:for-each select="counters[@type=&quot;adbstat&quot;]/counter[.&gt;0]">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class5">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class5}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="views/view">
+ <xsl:if test="counters[@type=&quot;cachestats&quot;]/counter[.&gt;0]">
+ <h3>Cache Statistics for View <xsl:value-of select="@name"/></h3>
+ <table class="counters">
+ <xsl:for-each select="counters[@type=&quot;cachestats&quot;]/counter[.&gt;0]">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class5">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class5}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="views/view">
+ <xsl:if test="cache/rrset">
+ <h3>Cache DB RRsets for View <xsl:value-of select="@name"/></h3>
+ <table class="counters">
+ <xsl:for-each select="cache/rrset">
+ <xsl:variable name="css-class6">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class6}">
+ <th>
+ <xsl:value-of select="name"/>
+ </th>
+ <td>
+ <xsl:value-of select="counter"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="traffic//udp/counters[@type=&quot;request-size&quot;]/counter[.&gt;0] or traffic//udp/counters[@type=&quot;response-size&quot;]/counter[.&gt;0] or traffic//tcp/counters[@type=&quot;request-size&quot;]/counter[.&gt;0] or traffic//tcp/counters[@type=&quot;response-size&quot;]/counter[.&gt;0]">
+ <h2>Traffic Size Statistics</h2>
+ </xsl:if>
+ <xsl:if test="traffic//udp/counters[@type=&quot;request-size&quot;]/counter[.&gt;0]">
+ <h4>UDP Requests Received</h4>
+ <table class="counters">
+ <xsl:for-each select="traffic//udp/counters[@type=&quot;request-size&quot;]/counter[.&gt;0]">
+ <xsl:variable name="css-class7">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class7}">
+ <th><xsl:value-of select="local-name(../../..)"/></th>
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="traffic//udp/counters[@type=&quot;response-size&quot;]/counter[.&gt;0]">
+ <h4>UDP Responses Sent</h4>
+ <table class="counters">
+ <xsl:for-each select="traffic//udp/counters[@type=&quot;response-size&quot;]/counter[.&gt;0]">
+ <xsl:variable name="css-class7">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class7}">
+ <th><xsl:value-of select="local-name(../../..)"/></th>
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="traffic//tcp/counters[@type=&quot;request-size&quot;]/counter[.&gt;0]">
+ <h4>TCP Requests Received</h4>
+ <table class="counters">
+ <xsl:for-each select="traffic//tcp/counters[@type=&quot;request-size&quot;]/counter[.&gt;0]">
+ <xsl:variable name="css-class7">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class7}">
+ <th><xsl:value-of select="local-name(../../..)"/></th>
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="traffic//tcp/counters[@type=&quot;response-size&quot;]/counter[.&gt;0]">
+ <h4>TCP Responses Sent</h4>
+ <table class="counters">
+ <xsl:for-each select="traffic//tcp/counters[@type=&quot;response-size&quot;]/counter[.&gt;0]">
+ <xsl:variable name="css-class7">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class7}">
+ <th><xsl:value-of select="local-name(../../..)"/></th>
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="server/counters[@type=&quot;sockstat&quot;]/counter[.&gt;0]">
+ <h2>Socket I/O Statistics</h2>
+ <table class="counters">
+ <xsl:for-each select="server/counters[@type=&quot;sockstat&quot;]/counter[.&gt;0]">
+ <xsl:variable name="css-class7">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class7}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="views/view/zones/zone">
+ <xsl:for-each select="views/view">
+ <h3>Zones for View <xsl:value-of select="@name"/></h3>
+ <table class="zones">
+ <thead><tr><th>Name</th><th>Class</th><th>Type</th><th>Serial</th><th>Loaded</th><th>Expires</th><th>Refresh</th></tr></thead>
+ <tbody>
+ <xsl:for-each select="zones/zone">
+ <xsl:variable name="css-class15">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class15}">
+ <td><xsl:value-of select="@name"/></td>
+ <td><xsl:value-of select="@rdataclass"/></td>
+ <td><xsl:value-of select="type"/></td>
+ <td><xsl:value-of select="serial"/></td>
+ <td><xsl:value-of select="loaded"/></td>
+ <td><xsl:value-of select="expires"/></td>
+ <td><xsl:value-of select="refresh"/></td></tr>
+ </xsl:for-each>
+ </tbody>
+ </table>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="views/view[zones/zone/counters[@type=&quot;qtype&quot;]/counter &gt;0]">
+ <h2>Received QTYPES per view/zone</h2>
+ <xsl:for-each select="views/view[zones/zone/counters[@type=&quot;qtype&quot;]/counter &gt;0]">
+ <h3>View <xsl:value-of select="@name"/></h3>
+ <xsl:variable name="thisview">
+ <xsl:value-of select="@name"/>
+ </xsl:variable>
+ <xsl:for-each select="zones/zone">
+ <xsl:if test="counters[@type=&quot;qtype&quot;]/counter[count(.) &gt; 0]">
+ <h4>Zone <xsl:value-of select="@name"/></h4>
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <!-- Non Mozilla specific markup -->
+ <script type="text/javascript">
+ graphs.push({
+ 'title': "Query types for zone <xsl:value-of select="@name"/>",
+ 'target': 'chart_qtype_<xsl:value-of select="../../@name"/>_<xsl:value-of select="@name"/>',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="counters[@type=&quot;qtype&quot;]/counter[.&gt;0 and @name != &quot;QryAuthAns&quot;]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+
+ </script>
+ <xsl:variable name="target">
+ <xsl:value-of select="@name"/>
+ </xsl:variable>
+ <div class="pie" id="chart_qtype_{$thisview}_{$target}">[no data to display]</div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="counters[@type=&quot;qtype&quot;]/counter">
+ <xsl:sort select="."/>
+ <xsl:variable name="css-class10">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class10}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="views/view[zones/zone/counters[@type=&quot;rcode&quot;]/counter &gt;0]">
+ <h2>Response Codes per view/zone</h2>
+ <xsl:for-each select="views/view[zones/zone/counters[@type=&quot;rcode&quot;]/counter &gt;0]">
+ <h3>View <xsl:value-of select="@name"/></h3>
+ <xsl:variable name="thisview2">
+ <xsl:value-of select="@name"/>
+ </xsl:variable>
+ <xsl:for-each select="zones/zone">
+ <xsl:if test="counters[@type=&quot;rcode&quot;]/counter[. &gt; 0]">
+ <h4>Zone <xsl:value-of select="@name"/></h4>
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <!-- Non Mozilla specific markup -->
+ <script type="text/javascript">
+ graphs.push({
+ 'title': "Response codes for zone <xsl:value-of select="@name"/>",
+ 'target': 'chart_rescode_<xsl:value-of select="../../@name"/>_<xsl:value-of select="@name"/>',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="counters[@type=&quot;rcode&quot;]/counter[.&gt;0 and @name != &quot;QryAuthAns&quot;]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+
+ </script>
+ <xsl:variable name="target">
+ <xsl:value-of select="@name"/>
+ </xsl:variable>
+ <div class="pie" id="chart_rescode_{$thisview2}_{$target}">[no data to display]</div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="counters[@type=&quot;rcode&quot;]/counter[.&gt;0 and @name != &quot;QryAuthAns&quot;]">
+ <xsl:sort select="."/>
+ <xsl:variable name="css-class11">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class11}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="views/view[zones/zone/counters[@type=&quot;gluecache&quot;]/counter &gt;0]">
+ <h2>Glue cache statistics</h2>
+ <xsl:for-each select="views/view[zones/zone/counters[@type=&quot;gluecache&quot;]/counter &gt;0]">
+ <h3>View <xsl:value-of select="@name"/></h3>
+ <xsl:variable name="thisview2">
+ <xsl:value-of select="@name"/>
+ </xsl:variable>
+ <xsl:for-each select="zones/zone">
+ <xsl:if test="counters[@type=&quot;gluecache&quot;]/counter[. &gt; 0]">
+ <h4>Zone <xsl:value-of select="@name"/></h4>
+ <table class="counters">
+ <xsl:for-each select="counters[@type=&quot;gluecache&quot;]/counter[. &gt; 0]">
+ <xsl:sort select="."/>
+ <xsl:variable name="css-class11">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class11}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="taskmgr/thread-model/type">
+ <h2>Task Manager Configuration</h2>
+ <table class="counters">
+ <tr>
+ <th class="even">Thread-Model</th>
+ <td>
+ <xsl:value-of select="taskmgr/thread-model/type"/>
+ </td>
+ </tr>
+ <tr class="odd">
+ <th>Worker Threads</th>
+ <td>
+ <xsl:value-of select="taskmgr/thread-model/worker-threads"/>
+ </td>
+ </tr>
+ <tr class="even">
+ <th>Default Quantum</th>
+ <td>
+ <xsl:value-of select="taskmgr/thread-model/default-quantum"/>
+ </td>
+ </tr>
+ <tr class="odd">
+ <th>Tasks Running</th>
+ <td>
+ <xsl:value-of select="taskmgr/thread-model/tasks-running"/>
+ </td>
+ </tr>
+ <tr class="even">
+ <th>Tasks Ready</th>
+ <td>
+ <xsl:value-of select="taskmgr/thread-model/tasks-ready"/>
+ </td>
+ </tr>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="taskmgr/tasks/task">
+ <h2>Tasks</h2>
+ <table class="tasks">
+ <tr>
+ <th>ID</th>
+ <th>Name</th>
+ <th>References</th>
+ <th>State</th>
+ <th>Quantum</th>
+ <th>Events</th>
+ </tr>
+ <xsl:for-each select="taskmgr/tasks/task">
+ <xsl:sort select="name"/>
+ <xsl:variable name="css-class14">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class14}">
+ <td>
+ <xsl:value-of select="id"/>
+ </td>
+ <td>
+ <xsl:value-of select="name"/>
+ </td>
+ <td>
+ <xsl:value-of select="references"/>
+ </td>
+ <td>
+ <xsl:value-of select="state"/>
+ </td>
+ <td>
+ <xsl:value-of select="quantum"/>
+ </td>
+ <td>
+ <xsl:value-of select="events"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="memory/summary">
+ <h2>Memory Usage Summary</h2>
+ <table class="counters">
+ <xsl:for-each select="memory/summary/*">
+ <xsl:variable name="css-class13">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class13}">
+ <th>
+ <xsl:value-of select="name()"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="memory/contexts/context">
+ <h2>Memory Contexts</h2>
+ <table class="mctx">
+ <tr>
+ <th>ID</th>
+ <th>Name</th>
+ <th>References</th>
+ <th>TotalUse</th>
+ <th>InUse</th>
+ <th>MaxUse</th>
+ <th>Malloced</th>
+ <th>MaxMalloced</th>
+ <th>BlockSize</th>
+ <th>Pools</th>
+ <th>HiWater</th>
+ <th>LoWater</th>
+ </tr>
+ <xsl:for-each select="memory/contexts/context">
+ <xsl:sort select="total" data-type="number" order="descending"/>
+ <xsl:variable name="css-class14">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class14}">
+ <td>
+ <xsl:value-of select="id"/>
+ </td>
+ <td>
+ <xsl:value-of select="name"/>
+ </td>
+ <td>
+ <xsl:value-of select="references"/>
+ </td>
+ <td>
+ <xsl:value-of select="total"/>
+ </td>
+ <td>
+ <xsl:value-of select="inuse"/>
+ </td>
+ <td>
+ <xsl:value-of select="maxinuse"/>
+ </td>
+ <td>
+ <xsl:value-of select="malloced"/>
+ </td>
+ <td>
+ <xsl:value-of select="maxmalloced"/>
+ </td>
+ <td>
+ <xsl:value-of select="blocksize"/>
+ </td>
+ <td>
+ <xsl:value-of select="pools"/>
+ </td>
+ <td>
+ <xsl:value-of select="hiwater"/>
+ </td>
+ <td>
+ <xsl:value-of select="lowater"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
+ <hr/>
+ <p class="footer">Internet Systems Consortium Inc.<br/><a href="http://www.isc.org">http://www.isc.org</a></p>
+ </body>
+ </html>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/bin/named/builtin.c b/bin/named/builtin.c
new file mode 100644
index 0000000..26348fd
--- /dev/null
+++ b/bin/named/builtin.c
@@ -0,0 +1,650 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file
+ * \brief
+ * The built-in "version", "hostname", "id", "authors" and "empty" databases.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/sdb.h>
+
+#include <named/builtin.h>
+#include <named/globals.h>
+#include <named/os.h>
+#include <named/server.h>
+
+typedef struct builtin builtin_t;
+
+static isc_result_t
+do_authors_lookup(dns_sdblookup_t *lookup);
+static isc_result_t
+do_dns64_lookup(dns_sdblookup_t *lookup);
+static isc_result_t
+do_empty_lookup(dns_sdblookup_t *lookup);
+static isc_result_t
+do_hostname_lookup(dns_sdblookup_t *lookup);
+static isc_result_t
+do_id_lookup(dns_sdblookup_t *lookup);
+static isc_result_t
+do_ipv4only_lookup(dns_sdblookup_t *lookup);
+static isc_result_t
+do_ipv4reverse_lookup(dns_sdblookup_t *lookup);
+static isc_result_t
+do_version_lookup(dns_sdblookup_t *lookup);
+
+/*
+ * We can't use function pointers as the db_data directly
+ * because ANSI C does not guarantee that function pointers
+ * can safely be cast to void pointers and back.
+ */
+
+struct builtin {
+ isc_result_t (*do_lookup)(dns_sdblookup_t *lookup);
+ char *server;
+ char *contact;
+};
+
+static builtin_t authors_builtin = { do_authors_lookup, NULL, NULL };
+static builtin_t dns64_builtin = { do_dns64_lookup, NULL, NULL };
+static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL };
+static builtin_t hostname_builtin = { do_hostname_lookup, NULL, NULL };
+static builtin_t id_builtin = { do_id_lookup, NULL, NULL };
+static builtin_t ipv4only_builtin = { do_ipv4only_lookup, NULL, NULL };
+static builtin_t ipv4reverse_builtin = { do_ipv4reverse_lookup, NULL, NULL };
+static builtin_t version_builtin = { do_version_lookup, NULL, NULL };
+
+static dns_sdbimplementation_t *builtin_impl;
+static dns_sdbimplementation_t *dns64_impl;
+
+/*
+ * Pre computed HEX * 16 or 1 table.
+ */
+static const unsigned char hex16[256] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*00*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*20*/
+ 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 1, 1, 1, 1, 1, 1, /*30*/
+ 1, 160, 176, 192, 208, 224, 240, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*50*/
+ 1, 160, 176, 192, 208, 224, 240, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*60*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*70*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*A0*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*B0*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*C0*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*D0*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*E0*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /*F0*/
+};
+
+static const unsigned char decimal[] = "0123456789";
+static const unsigned char ipv4only[] = "\010ipv4only\004arpa";
+
+static size_t
+dns64_rdata(unsigned char *v, size_t start, unsigned char *rdata) {
+ size_t i, j = 0;
+
+ for (i = 0; i < 4U; i++) {
+ unsigned char c = v[start++];
+ if (start == 7U) {
+ start++;
+ }
+ if (c > 99) {
+ rdata[j++] = 3;
+ rdata[j++] = decimal[c / 100];
+ c = c % 100;
+ rdata[j++] = decimal[c / 10];
+ c = c % 10;
+ rdata[j++] = decimal[c];
+ } else if (c > 9) {
+ rdata[j++] = 2;
+ rdata[j++] = decimal[c / 10];
+ c = c % 10;
+ rdata[j++] = decimal[c];
+ } else {
+ rdata[j++] = 1;
+ rdata[j++] = decimal[c];
+ }
+ }
+ memmove(&rdata[j], "\07in-addr\04arpa", 14);
+ return (j + 14);
+}
+
+static isc_result_t
+dns64_cname(const dns_name_t *zone, const dns_name_t *name,
+ dns_sdblookup_t *lookup) {
+ size_t zlen, nlen, j, len;
+ unsigned char v[16], n;
+ unsigned int i;
+ unsigned char rdata[sizeof("123.123.123.123.in-addr.arpa.")];
+ unsigned char *ndata;
+
+ /*
+ * The combined length of the zone and name is 74.
+ *
+ * The minimum zone length is 10 ((3)ip6(4)arpa(0)).
+ *
+ * The length of name should always be even as we are expecting
+ * a series of nibbles.
+ */
+ zlen = zone->length;
+ nlen = name->length;
+ if ((zlen + nlen) > 74U || zlen < 10U || (nlen % 2) != 0U) {
+ return (ISC_R_NOTFOUND);
+ }
+
+ /*
+ * We assume the zone name is well formed.
+ */
+
+ /*
+ * XXXMPA We could check the dns64 suffix here if we need to.
+ */
+ /*
+ * Check that name is a series of nibbles.
+ * Compute the byte values that correspond to the nibbles as we go.
+ *
+ * Shift the final result 4 bits, by setting 'i' to 1, if we if we
+ * have a odd number of nibbles so that "must be zero" tests below
+ * are byte aligned and we correctly return ISC_R_NOTFOUND or
+ * ISC_R_SUCCESS. We will not generate a CNAME in this case.
+ */
+ ndata = name->ndata;
+ i = (nlen % 4) == 2U ? 1 : 0;
+ j = nlen;
+ memset(v, 0, sizeof(v));
+ while (j != 0U) {
+ INSIST((i / 2) < sizeof(v));
+ if (ndata[0] != 1) {
+ return (ISC_R_NOTFOUND);
+ }
+ n = hex16[ndata[1] & 0xff];
+ if (n == 1) {
+ return (ISC_R_NOTFOUND);
+ }
+ v[i / 2] = n | (v[i / 2] >> 4);
+ j -= 2;
+ ndata += 2;
+ i++;
+ }
+
+ /*
+ * If we get here then we know name only consisted of nibbles.
+ * Now we need to determine if the name exists or not and whether
+ * it corresponds to a empty node in the zone or there should be
+ * a CNAME.
+ */
+#define ZLEN(x) (10 + (x) / 2)
+ switch (zlen) {
+ case ZLEN(32): /* prefix len 32 */
+ /*
+ * The nibbles that map to this byte must be zero for 'name'
+ * to exist in the zone.
+ */
+ if (nlen > 16U && v[(nlen - 1) / 4 - 4] != 0) {
+ return (ISC_R_NOTFOUND);
+ }
+ /*
+ * If the total length is not 74 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 74U) {
+ return (ISC_R_SUCCESS);
+ }
+ len = dns64_rdata(v, 8, rdata);
+ break;
+ case ZLEN(40): /* prefix len 40 */
+ /*
+ * The nibbles that map to this byte must be zero for 'name'
+ * to exist in the zone.
+ */
+ if (nlen > 12U && v[(nlen - 1) / 4 - 3] != 0) {
+ return (ISC_R_NOTFOUND);
+ }
+ /*
+ * If the total length is not 74 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 74U) {
+ return (ISC_R_SUCCESS);
+ }
+ len = dns64_rdata(v, 6, rdata);
+ break;
+ case ZLEN(48): /* prefix len 48 */
+ /*
+ * The nibbles that map to this byte must be zero for 'name'
+ * to exist in the zone.
+ */
+ if (nlen > 8U && v[(nlen - 1) / 4 - 2] != 0) {
+ return (ISC_R_NOTFOUND);
+ }
+ /*
+ * If the total length is not 74 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 74U) {
+ return (ISC_R_SUCCESS);
+ }
+ len = dns64_rdata(v, 5, rdata);
+ break;
+ case ZLEN(56): /* prefix len 56 */
+ /*
+ * The nibbles that map to this byte must be zero for 'name'
+ * to exist in the zone.
+ */
+ if (nlen > 4U && v[(nlen - 1) / 4 - 1] != 0) {
+ return (ISC_R_NOTFOUND);
+ }
+ /*
+ * If the total length is not 74 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 74U) {
+ return (ISC_R_SUCCESS);
+ }
+ len = dns64_rdata(v, 4, rdata);
+ break;
+ case ZLEN(64): /* prefix len 64 */
+ /*
+ * The nibbles that map to this byte must be zero for 'name'
+ * to exist in the zone.
+ */
+ if (v[(nlen - 1) / 4] != 0) {
+ return (ISC_R_NOTFOUND);
+ }
+ /*
+ * If the total length is not 74 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 74U) {
+ return (ISC_R_SUCCESS);
+ }
+ len = dns64_rdata(v, 3, rdata);
+ break;
+ case ZLEN(96): /* prefix len 96 */
+ /*
+ * If the total length is not 74 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 74U) {
+ return (ISC_R_SUCCESS);
+ }
+ len = dns64_rdata(v, 0, rdata);
+ break;
+ default:
+ /*
+ * This should never be reached unless someone adds a
+ * zone declaration with this internal type to named.conf.
+ */
+ return (ISC_R_NOTFOUND);
+ }
+
+ /*
+ * Reverse of 192.0.0.170 or 192.0.0.171 maps to ipv4only.arpa.
+ */
+ if ((v[0] == 170 || v[0] == 171) && v[1] == 0 && v[2] == 0 &&
+ v[3] == 192)
+ {
+ return (dns_sdb_putrdata(lookup, dns_rdatatype_ptr, 3600,
+ ipv4only, sizeof(ipv4only)));
+ }
+
+ return (dns_sdb_putrdata(lookup, dns_rdatatype_cname, 600, rdata,
+ (unsigned int)len));
+}
+
+static isc_result_t
+builtin_lookup(const char *zone, const char *name, void *dbdata,
+ dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo) {
+ builtin_t *b = (builtin_t *)dbdata;
+
+ UNUSED(zone);
+ UNUSED(methods);
+ UNUSED(clientinfo);
+
+ if (strcmp(name, "@") == 0) {
+ return (b->do_lookup(lookup));
+ } else {
+ return (ISC_R_NOTFOUND);
+ }
+}
+
+static isc_result_t
+dns64_lookup(const dns_name_t *zone, const dns_name_t *name, void *dbdata,
+ dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo) {
+ builtin_t *b = (builtin_t *)dbdata;
+
+ UNUSED(methods);
+ UNUSED(clientinfo);
+
+ if (name->labels == 0 && name->length == 0) {
+ return (b->do_lookup(lookup));
+ } else {
+ return (dns64_cname(zone, name, lookup));
+ }
+}
+
+static isc_result_t
+put_txt(dns_sdblookup_t *lookup, const char *text) {
+ unsigned char buf[256];
+ unsigned int len = strlen(text);
+ if (len > 255) {
+ len = 255; /* Silently truncate */
+ }
+ buf[0] = len;
+ memmove(&buf[1], text, len);
+ return (dns_sdb_putrdata(lookup, dns_rdatatype_txt, 0, buf, len + 1));
+}
+
+static isc_result_t
+do_version_lookup(dns_sdblookup_t *lookup) {
+ if (named_g_server->version_set) {
+ if (named_g_server->version == NULL) {
+ return (ISC_R_SUCCESS);
+ } else {
+ return (put_txt(lookup, named_g_server->version));
+ }
+ } else {
+ return (put_txt(lookup, PACKAGE_VERSION));
+ }
+}
+
+static isc_result_t
+do_hostname_lookup(dns_sdblookup_t *lookup) {
+ if (named_g_server->hostname_set) {
+ if (named_g_server->hostname == NULL) {
+ return (ISC_R_SUCCESS);
+ } else {
+ return (put_txt(lookup, named_g_server->hostname));
+ }
+ } else {
+ char buf[256];
+ if (gethostname(buf, sizeof(buf)) != 0) {
+ return (ISC_R_FAILURE);
+ }
+ return (put_txt(lookup, buf));
+ }
+}
+
+static isc_result_t
+do_authors_lookup(dns_sdblookup_t *lookup) {
+ isc_result_t result;
+ const char **p;
+ static const char *authors[] = {
+ "Mark Andrews", "Curtis Blackburn", "James Brister",
+ "Ben Cottrell", "John H. DuBois III", "Francis Dupont",
+ "Michael Graff", "Andreas Gustafsson", "Bob Halley",
+ "Evan Hunt", "JINMEI Tatuya", "Witold Krecicki",
+ "David Lawrence", "Scott Mann", "Danny Mayer",
+ "Damien Neil", "Matt Nelson", "Jeremy C. Reed",
+ "Michael Sawyer", "Brian Wellington", NULL
+ };
+
+ /*
+ * If a version string is specified, disable the authors.bind zone.
+ */
+ if (named_g_server->version_set) {
+ return (ISC_R_SUCCESS);
+ }
+
+ for (p = authors; *p != NULL; p++) {
+ result = put_txt(lookup, *p);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+do_id_lookup(dns_sdblookup_t *lookup) {
+ if (named_g_server->sctx->usehostname) {
+ char buf[256];
+ if (gethostname(buf, sizeof(buf)) != 0) {
+ return (ISC_R_FAILURE);
+ }
+ return (put_txt(lookup, buf));
+ } else if (named_g_server->sctx->server_id != NULL) {
+ return (put_txt(lookup, named_g_server->sctx->server_id));
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+}
+
+static isc_result_t
+do_dns64_lookup(dns_sdblookup_t *lookup) {
+ UNUSED(lookup);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+do_empty_lookup(dns_sdblookup_t *lookup) {
+ UNUSED(lookup);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+do_ipv4only_lookup(dns_sdblookup_t *lookup) {
+ isc_result_t result;
+ unsigned char data[2][4] = { { 192, 0, 0, 170 }, { 192, 0, 0, 171 } };
+
+ for (int i = 0; i < 2; i++) {
+ result = dns_sdb_putrdata(lookup, dns_rdatatype_a, 3600,
+ data[i], 4);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+do_ipv4reverse_lookup(dns_sdblookup_t *lookup) {
+ isc_result_t result;
+
+ result = dns_sdb_putrdata(lookup, dns_rdatatype_ptr, 3600, ipv4only,
+ sizeof(ipv4only));
+ return (result);
+}
+
+static isc_result_t
+builtin_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
+ isc_result_t result;
+ const char *contact = "hostmaster";
+ const char *server = "@";
+ builtin_t *b = (builtin_t *)dbdata;
+
+ UNUSED(zone);
+ UNUSED(dbdata);
+
+ if (b == &empty_builtin) {
+ server = ".";
+ contact = ".";
+ } else {
+ if (b->server != NULL) {
+ server = b->server;
+ }
+ if (b->contact != NULL) {
+ contact = b->contact;
+ }
+ }
+
+ result = dns_sdb_putsoa(lookup, server, contact, 0);
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_FAILURE);
+ }
+
+ result = dns_sdb_putrr(lookup, "ns", 0, server);
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_FAILURE);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+builtin_create(const char *zone, int argc, char **argv, void *driverdata,
+ void **dbdata) {
+ REQUIRE(argc >= 1);
+
+ UNUSED(zone);
+ UNUSED(driverdata);
+
+ if (strcmp(argv[0], "dns64") == 0 || strcmp(argv[0], "empty") == 0 ||
+ strcmp(argv[0], "ipv4only") == 0 ||
+ strcmp(argv[0], "ipv4reverse") == 0)
+ {
+ if (argc != 3) {
+ return (DNS_R_SYNTAX);
+ }
+ } else if (argc != 1) {
+ return (DNS_R_SYNTAX);
+ }
+
+ if (strcmp(argv[0], "authors") == 0) {
+ *dbdata = &authors_builtin;
+ } else if (strcmp(argv[0], "hostname") == 0) {
+ *dbdata = &hostname_builtin;
+ } else if (strcmp(argv[0], "id") == 0) {
+ *dbdata = &id_builtin;
+ } else if (strcmp(argv[0], "version") == 0) {
+ *dbdata = &version_builtin;
+ } else if (strcmp(argv[0], "dns64") == 0 ||
+ strcmp(argv[0], "empty") == 0 ||
+ strcmp(argv[0], "ipv4only") == 0 ||
+ strcmp(argv[0], "ipv4reverse") == 0)
+ {
+ builtin_t *empty;
+ char *server;
+ char *contact;
+
+ if (argc != 3) {
+ return (DNS_R_SYNTAX);
+ }
+
+ /*
+ * We don't want built-in zones to fail. Fallback to
+ * the static configuration if memory allocation fails.
+ */
+ empty = isc_mem_get(named_g_mctx, sizeof(*empty));
+ server = isc_mem_strdup(named_g_mctx, argv[1]);
+ contact = isc_mem_strdup(named_g_mctx, argv[2]);
+ if (empty == NULL || server == NULL || contact == NULL) {
+ if (strcmp(argv[0], "dns64") == 0) {
+ *dbdata = &dns64_builtin;
+ } else if (strcmp(argv[0], "empty") == 0) {
+ *dbdata = &empty_builtin;
+ } else if (strcmp(argv[0], "ipv4only") == 0) {
+ *dbdata = &ipv4only_builtin;
+ } else {
+ *dbdata = &ipv4reverse_builtin;
+ }
+ if (server != NULL) {
+ isc_mem_free(named_g_mctx, server);
+ }
+ if (contact != NULL) {
+ isc_mem_free(named_g_mctx, contact);
+ }
+ if (empty != NULL) {
+ isc_mem_put(named_g_mctx, empty,
+ sizeof(*empty));
+ }
+ } else {
+ if (strcmp(argv[0], "dns64") == 0) {
+ memmove(empty, &dns64_builtin,
+ sizeof(empty_builtin));
+ } else if (strcmp(argv[0], "empty") == 0) {
+ memmove(empty, &empty_builtin,
+ sizeof(empty_builtin));
+ } else if (strcmp(argv[0], "ipv4only") == 0) {
+ memmove(empty, &ipv4only_builtin,
+ sizeof(empty_builtin));
+ } else {
+ memmove(empty, &ipv4reverse_builtin,
+ sizeof(empty_builtin));
+ }
+ empty->server = server;
+ empty->contact = contact;
+ *dbdata = empty;
+ }
+ } else {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static void
+builtin_destroy(const char *zone, void *driverdata, void **dbdata) {
+ builtin_t *b = (builtin_t *)*dbdata;
+
+ UNUSED(zone);
+ UNUSED(driverdata);
+
+ /*
+ * Don't free the static versions.
+ */
+ if (*dbdata == &authors_builtin || *dbdata == &dns64_builtin ||
+ *dbdata == &empty_builtin || *dbdata == &hostname_builtin ||
+ *dbdata == &id_builtin || *dbdata == &ipv4only_builtin ||
+ *dbdata == &ipv4reverse_builtin || *dbdata == &version_builtin)
+ {
+ return;
+ }
+
+ isc_mem_free(named_g_mctx, b->server);
+ isc_mem_free(named_g_mctx, b->contact);
+ isc_mem_put(named_g_mctx, b, sizeof(*b));
+}
+
+static dns_sdbmethods_t builtin_methods = {
+ builtin_lookup, builtin_authority, NULL, /* allnodes */
+ builtin_create, builtin_destroy, NULL
+};
+
+static dns_sdbmethods_t dns64_methods = {
+ NULL, builtin_authority, NULL, /* allnodes */
+ builtin_create, builtin_destroy, dns64_lookup,
+};
+
+isc_result_t
+named_builtin_init(void) {
+ RUNTIME_CHECK(dns_sdb_register("_builtin", &builtin_methods, NULL,
+ DNS_SDBFLAG_RELATIVEOWNER |
+ DNS_SDBFLAG_RELATIVERDATA,
+ named_g_mctx,
+ &builtin_impl) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_sdb_register("_dns64", &dns64_methods, NULL,
+ DNS_SDBFLAG_RELATIVEOWNER |
+ DNS_SDBFLAG_RELATIVERDATA |
+ DNS_SDBFLAG_DNS64,
+ named_g_mctx,
+ &dns64_impl) == ISC_R_SUCCESS);
+ return (ISC_R_SUCCESS);
+}
+
+void
+named_builtin_deinit(void) {
+ dns_sdb_unregister(&builtin_impl);
+ dns_sdb_unregister(&dns64_impl);
+}
diff --git a/bin/named/config.c b/bin/named/config.c
new file mode 100644
index 0000000..7f318a2
--- /dev/null
+++ b/bin/named/config.c
@@ -0,0 +1,1034 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <bind.keys.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/netmgr.h>
+#include <isc/parseint.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/kasp.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+#include <dns/tsig.h>
+#include <dns/zone.h>
+
+#include <dst/dst.h>
+
+#include <isccfg/grammar.h>
+#include <isccfg/namedconf.h>
+
+#include <named/config.h>
+#include <named/globals.h>
+
+/*% default configuration */
+static char defaultconf[] = "\
+options {\n\
+ answer-cookie true;\n\
+ automatic-interface-scan yes;\n\
+ bindkeys-file \"" NAMED_SYSCONFDIR "/bind.keys\";\n\
+# blackhole {none;};\n"
+ " cookie-algorithm siphash24;\n"
+ " coresize default;\n\
+ datasize default;\n"
+ "\
+# directory <none>\n\
+ dnssec-policy \"none\";\n\
+ dump-file \"named_dump.db\";\n\
+ edns-udp-size 1232;\n\
+ files unlimited;\n"
+#if defined(HAVE_GEOIP2)
+ "\
+ geoip-directory \"" MAXMINDDB_PREFIX "/share/GeoIP\";\n"
+#elif defined(HAVE_GEOIP2)
+ "\
+ geoip-directory \".\";\n"
+#endif /* if defined(HAVE_GEOIP2) */
+ "\
+ heartbeat-interval 60;\n\
+ interface-interval 60;\n\
+# keep-response-order {none;};\n\
+ listen-on {any;};\n\
+ listen-on-v6 {any;};\n\
+# lock-file \"" NAMED_LOCALSTATEDIR "/run/named/named.lock\";\n\
+ match-mapped-addresses no;\n\
+ max-ixfr-ratio 100%;\n\
+ max-rsa-exponent-size 0; /* no limit */\n\
+ max-udp-size 1232;\n\
+ memstatistics-file \"named.memstats\";\n\
+ nocookie-udp-size 4096;\n\
+ notify-rate 20;\n\
+ nta-lifetime 3600;\n\
+ nta-recheck 300;\n\
+# pid-file \"" NAMED_LOCALSTATEDIR "/run/named/named.pid\"; \n\
+ port 53;\n"
+#if HAVE_SO_REUSEPORT_LB
+ "\
+ reuseport yes;\n"
+#else
+ "\
+ reuseport no;\n"
+#endif
+ "\
+ tls-port 853;\n"
+#if HAVE_LIBNGHTTP2
+ "\
+ http-port 80;\n\
+ https-port 443;\n\
+ http-listener-clients 300;\n\
+ http-streams-per-connection 100;\n"
+#endif
+ "\
+ prefetch 2 9;\n\
+ recursing-file \"named.recursing\";\n\
+ recursive-clients 1000;\n\
+ request-nsid false;\n\
+ reserved-sockets 512;\n\
+ resolver-query-timeout 10;\n\
+ rrset-order { order random; };\n\
+ secroots-file \"named.secroots\";\n\
+ send-cookie true;\n\
+ serial-query-rate 20;\n\
+ server-id none;\n\
+ session-keyalg hmac-sha256;\n\
+# session-keyfile \"" NAMED_LOCALSTATEDIR "/run/named/session.key\";\n\
+ session-keyname local-ddns;\n\
+ stacksize default;\n\
+ startup-notify-rate 20;\n\
+ statistics-file \"named.stats\";\n\
+ tcp-advertised-timeout 300;\n\
+ tcp-clients 150;\n\
+ tcp-idle-timeout 300;\n\
+ tcp-initial-timeout 300;\n\
+ tcp-keepalive-timeout 300;\n\
+ tcp-listen-queue 10;\n\
+ tcp-receive-buffer 0;\n\
+ tcp-send-buffer 0;\n\
+# tkey-dhkey <none>\n\
+# tkey-domain <none>\n\
+# tkey-gssapi-credential <none>\n\
+ transfer-message-size 20480;\n\
+ transfers-in 10;\n\
+ transfers-out 10;\n\
+ transfers-per-ns 2;\n\
+ trust-anchor-telemetry yes;\n\
+ udp-receive-buffer 0;\n\
+ udp-send-buffer 0;\n\
+ update-quota 100;\n\
+\n\
+ /* view */\n\
+ allow-new-zones no;\n\
+ allow-notify {none;};\n\
+ allow-query-cache { localnets; localhost; };\n\
+ allow-query-cache-on { any; };\n\
+ allow-recursion { localnets; localhost; };\n\
+ allow-recursion-on { any; };\n\
+ allow-update-forwarding {none;};\n\
+ auth-nxdomain false;\n\
+ check-dup-records warn;\n\
+ check-mx warn;\n\
+ check-names primary fail;\n\
+ check-names response ignore;\n\
+ check-names secondary warn;\n\
+ check-spf warn;\n\
+ clients-per-query 10;\n\
+ dnssec-accept-expired no;\n\
+ dnssec-validation " VALIDATION_DEFAULT "; \n"
+#ifdef HAVE_DNSTAP
+ " dnstap-identity hostname;\n"
+#endif /* ifdef HAVE_DNSTAP */
+ "\
+ fetch-quota-params 100 0.1 0.3 0.7;\n\
+ fetches-per-server 0;\n\
+ fetches-per-zone 0;\n\
+ glue-cache yes;\n\
+ lame-ttl 0;\n"
+#ifdef HAVE_LMDB
+ " lmdb-mapsize 32M;\n"
+#endif /* ifdef HAVE_LMDB */
+ " max-cache-size 90%;\n\
+ max-cache-ttl 604800; /* 1 week */\n\
+ max-clients-per-query 100;\n\
+ max-ncache-ttl 10800; /* 3 hours */\n\
+ max-recursion-depth 7;\n\
+ max-recursion-queries 100;\n\
+ max-stale-ttl 86400; /* 1 day */\n\
+ message-compression yes;\n\
+ min-ncache-ttl 0; /* 0 hours */\n\
+ min-cache-ttl 0; /* 0 seconds */\n\
+ minimal-any false;\n\
+ minimal-responses no-auth-recursive;\n\
+ notify-source *;\n\
+ notify-source-v6 *;\n\
+ nsec3-test-zone no;\n\
+ parental-source *;\n\
+ parental-source-v6 *;\n\
+ provide-ixfr true;\n\
+ qname-minimization relaxed;\n\
+ query-source address *;\n\
+ query-source-v6 address *;\n\
+ recursion true;\n\
+ request-expire true;\n\
+ request-ixfr true;\n\
+ require-server-cookie no;\n\
+ resolver-nonbackoff-tries 3;\n\
+ resolver-retry-interval 800; /* in milliseconds */\n\
+ root-key-sentinel yes;\n\
+ servfail-ttl 1;\n\
+# sortlist <none>\n\
+ stale-answer-client-timeout off;\n\
+ stale-answer-enable false;\n\
+ stale-answer-ttl 30; /* 30 seconds */\n\
+ stale-cache-enable false;\n\
+ stale-refresh-time 30; /* 30 seconds */\n\
+ synth-from-dnssec yes;\n\
+# topology <none>\n\
+ transfer-format many-answers;\n\
+ v6-bias 50;\n\
+ zero-no-soa-ttl-cache no;\n\
+\n\
+ /* zone */\n\
+ allow-query {any;};\n\
+ allow-query-on {any;};\n\
+ allow-transfer {any;};\n\
+# also-notify <none>\n\
+ alt-transfer-source *;\n\
+ alt-transfer-source-v6 *;\n\
+ check-integrity yes;\n\
+ check-mx-cname warn;\n\
+ check-sibling yes;\n\
+ check-srv-cname warn;\n\
+ check-wildcard yes;\n\
+ dialup no;\n\
+ dnssec-dnskey-kskonly yes;\n\
+ dnssec-loadkeys-interval 60;\n\
+ dnssec-secure-to-insecure no;\n\
+ dnssec-update-mode maintain;\n\
+# forward <none>\n\
+# forwarders <none>\n\
+# inline-signing no;\n\
+ ixfr-from-differences false;\n\
+ max-journal-size default;\n\
+ max-records 0;\n\
+ max-refresh-time 2419200; /* 4 weeks */\n\
+ max-retry-time 1209600; /* 2 weeks */\n\
+ max-transfer-idle-in 60;\n\
+ max-transfer-idle-out 60;\n\
+ max-transfer-time-in 120;\n\
+ max-transfer-time-out 120;\n\
+ min-refresh-time 300;\n\
+ min-retry-time 500;\n\
+ multi-master no;\n\
+ notify yes;\n\
+ notify-delay 5;\n\
+ notify-to-soa no;\n\
+ serial-update-method increment;\n\
+ sig-signing-nodes 100;\n\
+ sig-signing-signatures 10;\n\
+ sig-signing-type 65534;\n\
+ sig-validity-interval 30; /* days */\n\
+ dnskey-sig-validity 0; /* default: sig-validity-interval */\n\
+ transfer-source *;\n\
+ transfer-source-v6 *;\n\
+ try-tcp-refresh yes; /* BIND 8 compat */\n\
+ update-check-ksk yes;\n\
+ zero-no-soa-ttl yes;\n\
+ zone-statistics terse;\n\
+};\n\
+"
+
+ "#\n\
+# Zones in the \"_bind\" view are NOT counted in the count of zones.\n\
+#\n\
+view \"_bind\" chaos {\n\
+ recursion no;\n\
+ notify no;\n\
+ allow-new-zones no;\n\
+ max-cache-size 2M;\n\
+\n\
+ # Prevent use of this zone in DNS amplified reflection DoS attacks\n\
+ rate-limit {\n\
+ responses-per-second 3;\n\
+ slip 0;\n\
+ min-table-size 10;\n\
+ };\n\
+\n\
+ zone \"version.bind\" chaos {\n\
+ type primary;\n\
+ database \"_builtin version\";\n\
+ };\n\
+\n\
+ zone \"hostname.bind\" chaos {\n\
+ type primary;\n\
+ database \"_builtin hostname\";\n\
+ };\n\
+\n\
+ zone \"authors.bind\" chaos {\n\
+ type primary;\n\
+ database \"_builtin authors\";\n\
+ };\n\
+\n\
+ zone \"id.server\" chaos {\n\
+ type primary;\n\
+ database \"_builtin id\";\n\
+ };\n\
+};\n\
+"
+ "#\n\
+# Built-in DNSSEC key and signing policies.\n\
+#\n\
+dnssec-policy \"default\" {\n\
+ keys {\n\
+ csk key-directory lifetime unlimited algorithm 13;\n\
+ };\n\
+\n\
+ dnskey-ttl " DNS_KASP_KEY_TTL ";\n\
+ publish-safety " DNS_KASP_PUBLISH_SAFETY "; \n\
+ retire-safety " DNS_KASP_RETIRE_SAFETY "; \n\
+ purge-keys " DNS_KASP_PURGE_KEYS "; \n\
+ signatures-refresh " DNS_KASP_SIG_REFRESH "; \n\
+ signatures-validity " DNS_KASP_SIG_VALIDITY "; \n\
+ signatures-validity-dnskey " DNS_KASP_SIG_VALIDITY_DNSKEY "; \n\
+ max-zone-ttl " DNS_KASP_ZONE_MAXTTL "; \n\
+ zone-propagation-delay " DNS_KASP_ZONE_PROPDELAY "; \n\
+ parent-ds-ttl " DNS_KASP_DS_TTL "; \n\
+ parent-propagation-delay " DNS_KASP_PARENT_PROPDELAY "; \n\
+};\n\
+\n\
+dnssec-policy \"insecure\" {\n\
+ max-zone-ttl 0; \n\
+ keys { };\n\
+};\n\
+\n\
+"
+ "#\n\
+# Default trusted key(s), used if \n\
+# \"dnssec-validation auto;\" is set and\n\
+# " NAMED_SYSCONFDIR "/bind.keys doesn't exist).\n\
+#\n\
+# BEGIN TRUST ANCHORS\n"
+
+ /* Imported from bind.keys.h: */
+ TRUST_ANCHORS
+
+ "# END TRUST ANCHORS\n\
+\n\
+primaries " DEFAULT_IANA_ROOT_ZONE_PRIMARIES " {\n\
+ 2001:500:200::b; # b.root-servers.net\n\
+ 2001:500:2::c; # c.root-servers.net\n\
+ 2001:500:2f::f; # f.root-servers.net\n\
+ 2001:500:12::d0d; # g.root-servers.net\n\
+ 2001:7fd::1; # k.root-servers.net\n\
+ 2620:0:2830:202::132; # xfr.cjr.dns.icann.org\n\
+ 2620:0:2d0:202::132; # xfr.lax.dns.icann.org\n\
+ 199.9.14.201; # b.root-servers.net\n\
+ 192.33.4.12; # c.root-servers.net\n\
+ 192.5.5.241; # f.root-servers.net\n\
+ 192.112.36.4; # g.root-servers.net\n\
+ 193.0.14.129; # k.root-servers.net\n\
+ 192.0.47.132; # xfr.cjr.dns.icann.org\n\
+ 192.0.32.132; # xfr.lax.dns.icann.org\n\
+};\n\
+";
+
+isc_result_t
+named_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1);
+ isc_buffer_add(&b, sizeof(defaultconf) - 1);
+ return (cfg_parse_buffer(parser, &b, __FILE__, 0, &cfg_type_namedconf,
+ CFG_PCTX_NODEPRECATED, conf));
+}
+
+const char *
+named_config_getdefault(void) {
+ return (defaultconf);
+}
+
+isc_result_t
+named_config_get(cfg_obj_t const *const *maps, const char *name,
+ const cfg_obj_t **obj) {
+ int i;
+
+ for (i = 0; maps[i] != NULL; i++) {
+ if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) {
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+named_checknames_get(const cfg_obj_t **maps, const char *const names[],
+ const cfg_obj_t **obj) {
+ const cfg_listelt_t *element;
+ const cfg_obj_t *checknames;
+ const cfg_obj_t *type;
+ const cfg_obj_t *value;
+ int i;
+
+ REQUIRE(maps != NULL);
+ REQUIRE(names != NULL);
+ REQUIRE(obj != NULL && *obj == NULL);
+
+ for (i = 0; maps[i] != NULL; i++) {
+ checknames = NULL;
+ if (cfg_map_get(maps[i], "check-names", &checknames) ==
+ ISC_R_SUCCESS)
+ {
+ /*
+ * Zone map entry is not a list.
+ */
+ if (checknames != NULL && !cfg_obj_islist(checknames)) {
+ *obj = checknames;
+ return (ISC_R_SUCCESS);
+ }
+ for (element = cfg_list_first(checknames);
+ element != NULL; element = cfg_list_next(element))
+ {
+ value = cfg_listelt_value(element);
+ type = cfg_tuple_get(value, "type");
+
+ for (size_t j = 0; names[j] != NULL; j++) {
+ if (strcasecmp(cfg_obj_asstring(type),
+ names[j]) == 0)
+ {
+ *obj = cfg_tuple_get(value,
+ "mode");
+ return (ISC_R_SUCCESS);
+ }
+ }
+ }
+ }
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+int
+named_config_listcount(const cfg_obj_t *list) {
+ const cfg_listelt_t *e;
+ int i = 0;
+
+ for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e)) {
+ i++;
+ }
+
+ return (i);
+}
+
+isc_result_t
+named_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass,
+ dns_rdataclass_t *classp) {
+ isc_textregion_t r;
+ isc_result_t result;
+
+ if (!cfg_obj_isstring(classobj)) {
+ *classp = defclass;
+ return (ISC_R_SUCCESS);
+ }
+ DE_CONST(cfg_obj_asstring(classobj), r.base);
+ r.length = strlen(r.base);
+ result = dns_rdataclass_fromtext(classp, &r);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(classobj, named_g_lctx, ISC_LOG_ERROR,
+ "unknown class '%s'", r.base);
+ }
+ return (result);
+}
+
+isc_result_t
+named_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype,
+ dns_rdatatype_t *typep) {
+ isc_textregion_t r;
+ isc_result_t result;
+
+ if (!cfg_obj_isstring(typeobj)) {
+ *typep = deftype;
+ return (ISC_R_SUCCESS);
+ }
+ DE_CONST(cfg_obj_asstring(typeobj), r.base);
+ r.length = strlen(r.base);
+ result = dns_rdatatype_fromtext(typep, &r);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(typeobj, named_g_lctx, ISC_LOG_ERROR,
+ "unknown type '%s'", r.base);
+ }
+ return (result);
+}
+
+dns_zonetype_t
+named_config_getzonetype(const cfg_obj_t *zonetypeobj) {
+ dns_zonetype_t ztype = dns_zone_none;
+ const char *str;
+
+ str = cfg_obj_asstring(zonetypeobj);
+ if (strcasecmp(str, "primary") == 0 || strcasecmp(str, "master") == 0) {
+ ztype = dns_zone_primary;
+ } else if (strcasecmp(str, "secondary") == 0 ||
+ strcasecmp(str, "slave") == 0)
+ {
+ ztype = dns_zone_secondary;
+ } else if (strcasecmp(str, "mirror") == 0) {
+ ztype = dns_zone_mirror;
+ } else if (strcasecmp(str, "stub") == 0) {
+ ztype = dns_zone_stub;
+ } else if (strcasecmp(str, "static-stub") == 0) {
+ ztype = dns_zone_staticstub;
+ } else if (strcasecmp(str, "redirect") == 0) {
+ ztype = dns_zone_redirect;
+ } else {
+ UNREACHABLE();
+ }
+ return (ztype);
+}
+
+isc_result_t
+named_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
+ in_port_t defport, isc_mem_t *mctx,
+ isc_sockaddr_t **addrsp, uint32_t *countp) {
+ int count, i = 0;
+ const cfg_obj_t *addrlist = NULL;
+ const cfg_obj_t *portobj = NULL;
+ const cfg_listelt_t *element = NULL;
+ isc_sockaddr_t *addrs = NULL;
+ in_port_t port;
+ isc_result_t result;
+
+ INSIST(addrsp != NULL && *addrsp == NULL);
+ INSIST(countp != NULL);
+
+ addrlist = cfg_tuple_get(list, "addresses");
+ count = named_config_listcount(addrlist);
+
+ portobj = cfg_tuple_get(list, "port");
+ if (cfg_obj_isuint32(portobj)) {
+ uint32_t val = cfg_obj_asuint32(portobj);
+ if (val > UINT16_MAX) {
+ cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ return (ISC_R_RANGE);
+ }
+ port = (in_port_t)val;
+ } else if (defport != 0) {
+ port = defport;
+ } else {
+ result = named_config_getport(config, "port", &port);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
+
+ for (element = cfg_list_first(addrlist); element != NULL;
+ element = cfg_list_next(element), i++)
+ {
+ const cfg_obj_t *addr;
+ INSIST(i < count);
+ addr = cfg_listelt_value(element);
+ addrs[i] = *cfg_obj_assockaddr(addr);
+ if (isc_sockaddr_getport(&addrs[i]) == 0) {
+ isc_sockaddr_setport(&addrs[i], port);
+ }
+ }
+ INSIST(i == count);
+
+ *addrsp = addrs;
+ *countp = count;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+named_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
+ uint32_t count) {
+ INSIST(addrsp != NULL && *addrsp != NULL);
+
+ isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
+ *addrsp = NULL;
+}
+
+static isc_result_t
+getremotesdef(const cfg_obj_t *cctx, const char *list, const char *name,
+ const cfg_obj_t **ret) {
+ isc_result_t result;
+ const cfg_obj_t *obj = NULL;
+ const cfg_listelt_t *elt;
+
+ REQUIRE(cctx != NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(ret != NULL && *ret == NULL);
+
+ result = cfg_map_get(cctx, list, &obj);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ elt = cfg_list_first(obj);
+ while (elt != NULL) {
+ obj = cfg_listelt_value(elt);
+ if (strcasecmp(cfg_obj_asstring(cfg_tuple_get(obj, "name")),
+ name) == 0)
+ {
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+ }
+ elt = cfg_list_next(elt);
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+named_config_getremotesdef(const cfg_obj_t *cctx, const char *list,
+ const char *name, const cfg_obj_t **ret) {
+ isc_result_t result;
+
+ if (strcmp(list, "parental-agents") == 0) {
+ return (getremotesdef(cctx, list, name, ret));
+ } else if (strcmp(list, "primaries") == 0) {
+ result = getremotesdef(cctx, list, name, ret);
+ if (result != ISC_R_SUCCESS) {
+ result = getremotesdef(cctx, "masters", name, ret);
+ }
+ return (result);
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+named_config_getname(isc_mem_t *mctx, const cfg_obj_t *obj,
+ dns_name_t **namep) {
+ REQUIRE(namep != NULL && *namep == NULL);
+
+ const char *objstr;
+ isc_result_t result;
+ isc_buffer_t b;
+ dns_fixedname_t fname;
+
+ if (!cfg_obj_isstring(obj)) {
+ *namep = NULL;
+ return (ISC_R_SUCCESS);
+ }
+
+ *namep = isc_mem_get(mctx, sizeof(**namep));
+ dns_name_init(*namep, NULL);
+
+ objstr = cfg_obj_asstring(obj);
+ isc_buffer_constinit(&b, objstr, strlen(objstr));
+ isc_buffer_add(&b, strlen(objstr));
+ dns_fixedname_init(&fname);
+ result = dns_name_fromtext(dns_fixedname_name(&fname), &b, dns_rootname,
+ 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, *namep, sizeof(**namep));
+ *namep = NULL;
+ return (result);
+ }
+ dns_name_dup(dns_fixedname_name(&fname), mctx, *namep);
+
+ return (ISC_R_SUCCESS);
+}
+
+#define grow_array(mctx, array, newlen, oldlen) \
+ if (newlen >= oldlen) { \
+ size_t newsize = (newlen + 16) * sizeof(array[0]); \
+ size_t oldsize = oldlen * sizeof(array[0]); \
+ void *tmp = isc_mem_get(mctx, newsize); \
+ memset(tmp, 0, newsize); \
+ if (oldlen != 0) { \
+ memmove(tmp, array, oldsize); \
+ isc_mem_put(mctx, array, oldsize); \
+ } \
+ array = tmp; \
+ oldlen = newlen + 16; \
+ }
+
+#define shrink_array(mctx, array, newlen, oldlen) \
+ if (newlen < oldlen) { \
+ void *tmp = NULL; \
+ size_t newsize = newlen * sizeof(array[0]); \
+ size_t oldsize = oldlen * sizeof(array[0]); \
+ if (newlen != 0) { \
+ tmp = isc_mem_get(mctx, newsize); \
+ memset(tmp, 0, newsize); \
+ memmove(tmp, array, newsize); \
+ } else { \
+ tmp = NULL; \
+ } \
+ isc_mem_put(mctx, array, oldsize); \
+ array = tmp; \
+ oldlen = newlen; \
+ }
+
+isc_result_t
+named_config_getipandkeylist(const cfg_obj_t *config, const char *listtype,
+ const cfg_obj_t *list, isc_mem_t *mctx,
+ dns_ipkeylist_t *ipkl) {
+ uint32_t addrcount = 0, keycount = 0, tlscount = 0, i = 0;
+ uint32_t listcount = 0, l = 0, j;
+ uint32_t stackcount = 0, pushed = 0;
+ isc_result_t result;
+ const cfg_listelt_t *element;
+ const cfg_obj_t *addrlist;
+ const cfg_obj_t *portobj;
+ in_port_t port = (in_port_t)0;
+ in_port_t def_port;
+ in_port_t def_tlsport;
+ isc_sockaddr_t *addrs = NULL;
+ dns_name_t **keys = NULL;
+ dns_name_t **tlss = NULL;
+ struct {
+ const char *name;
+ in_port_t port;
+ isc_sockaddr_t *src4s;
+ isc_sockaddr_t *src6s;
+ } *lists = NULL;
+ struct {
+ const cfg_listelt_t *element;
+ in_port_t port;
+ } *stack = NULL;
+
+ REQUIRE(ipkl != NULL);
+ REQUIRE(ipkl->count == 0);
+ REQUIRE(ipkl->addrs == NULL);
+ REQUIRE(ipkl->keys == NULL);
+ REQUIRE(ipkl->tlss == NULL);
+ REQUIRE(ipkl->labels == NULL);
+ REQUIRE(ipkl->allocated == 0);
+
+ /*
+ * Get system defaults.
+ */
+ result = named_config_getport(config, "port", &def_port);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ result = named_config_getport(config, "tls-port", &def_tlsport);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+newlist:
+ addrlist = cfg_tuple_get(list, "addresses");
+ portobj = cfg_tuple_get(list, "port");
+
+ if (cfg_obj_isuint32(portobj)) {
+ uint32_t val = cfg_obj_asuint32(portobj);
+ if (val > UINT16_MAX) {
+ cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ port = (in_port_t)val;
+ }
+
+ result = ISC_R_NOMEMORY;
+
+ element = cfg_list_first(addrlist);
+resume:
+ for (; element != NULL; element = cfg_list_next(element)) {
+ const cfg_obj_t *addr;
+ const cfg_obj_t *key;
+ const cfg_obj_t *tls;
+
+ addr = cfg_tuple_get(cfg_listelt_value(element),
+ "remoteselement");
+ key = cfg_tuple_get(cfg_listelt_value(element), "key");
+ tls = cfg_tuple_get(cfg_listelt_value(element), "tls");
+
+ if (!cfg_obj_issockaddr(addr)) {
+ const char *listname = cfg_obj_asstring(addr);
+ isc_result_t tresult;
+
+ /* Grow lists? */
+ grow_array(mctx, lists, l, listcount);
+
+ /* Seen? */
+ for (j = 0; j < l; j++) {
+ if (strcasecmp(lists[j].name, listname) == 0) {
+ break;
+ }
+ }
+ if (j < l) {
+ continue;
+ }
+ list = NULL;
+ tresult = named_config_getremotesdef(config, listtype,
+ listname, &list);
+ if (tresult == ISC_R_NOTFOUND) {
+ cfg_obj_log(addr, named_g_lctx, ISC_LOG_ERROR,
+ "%s \"%s\" not found", listtype,
+ listname);
+
+ result = tresult;
+ goto cleanup;
+ }
+ if (tresult != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ lists[l++].name = listname;
+ /* Grow stack? */
+ grow_array(mctx, stack, pushed, stackcount);
+ /*
+ * We want to resume processing this list on the
+ * next element.
+ */
+ stack[pushed].element = cfg_list_next(element);
+ stack[pushed].port = port;
+ pushed++;
+ goto newlist;
+ }
+
+ grow_array(mctx, addrs, i, addrcount);
+ grow_array(mctx, keys, i, keycount);
+ grow_array(mctx, tlss, i, tlscount);
+
+ addrs[i] = *cfg_obj_assockaddr(addr);
+
+ result = named_config_getname(mctx, key, &keys[i]);
+ if (result != ISC_R_SUCCESS) {
+ i++; /* Increment here so that cleanup on error works.
+ */
+ goto cleanup;
+ }
+
+ result = named_config_getname(mctx, tls, &tlss[i]);
+ if (result != ISC_R_SUCCESS) {
+ i++; /* Increment here so that cleanup on error works.
+ */
+ goto cleanup;
+ }
+
+ /* If the port is unset, take it from one of the upper levels */
+ if (isc_sockaddr_getport(&addrs[i]) == 0) {
+ in_port_t addr_port = port;
+
+ /* If unset, use the default port or tls-port */
+ if (addr_port == 0) {
+ if (tlss[i] != NULL) {
+ addr_port = def_tlsport;
+ } else {
+ addr_port = def_port;
+ }
+ }
+
+ isc_sockaddr_setport(&addrs[i], addr_port);
+ }
+
+ i++;
+ }
+ if (pushed != 0) {
+ pushed--;
+ element = stack[pushed].element;
+ port = stack[pushed].port;
+ goto resume;
+ }
+
+ shrink_array(mctx, addrs, i, addrcount);
+ shrink_array(mctx, keys, i, keycount);
+ shrink_array(mctx, tlss, i, tlscount);
+
+ if (lists != NULL) {
+ isc_mem_put(mctx, lists, listcount * sizeof(lists[0]));
+ }
+ if (stack != NULL) {
+ isc_mem_put(mctx, stack, stackcount * sizeof(stack[0]));
+ }
+
+ INSIST(keycount == addrcount);
+ INSIST(tlscount == addrcount);
+
+ ipkl->addrs = addrs;
+ ipkl->keys = keys;
+ ipkl->tlss = tlss;
+ ipkl->count = addrcount;
+ ipkl->allocated = addrcount;
+
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (addrs != NULL) {
+ isc_mem_put(mctx, addrs, addrcount * sizeof(addrs[0]));
+ }
+ if (keys != NULL) {
+ for (j = 0; j < i; j++) {
+ if (keys[j] == NULL) {
+ continue;
+ }
+ if (dns_name_dynamic(keys[j])) {
+ dns_name_free(keys[j], mctx);
+ }
+ isc_mem_put(mctx, keys[j], sizeof(*keys[j]));
+ }
+ isc_mem_put(mctx, keys, keycount * sizeof(keys[0]));
+ }
+ if (tlss != NULL) {
+ for (j = 0; j < i; j++) {
+ if (tlss[j] == NULL) {
+ continue;
+ }
+ if (dns_name_dynamic(tlss[j])) {
+ dns_name_free(tlss[j], mctx);
+ }
+ isc_mem_put(mctx, tlss[j], sizeof(*tlss[j]));
+ }
+ isc_mem_put(mctx, tlss, tlscount * sizeof(tlss[0]));
+ }
+ if (lists != NULL) {
+ isc_mem_put(mctx, lists, listcount * sizeof(lists[0]));
+ }
+ if (stack != NULL) {
+ isc_mem_put(mctx, stack, stackcount * sizeof(stack[0]));
+ }
+ return (result);
+}
+
+isc_result_t
+named_config_getport(const cfg_obj_t *config, const char *type,
+ in_port_t *portp) {
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *portobj = NULL;
+ isc_result_t result;
+ int i;
+
+ (void)cfg_map_get(config, "options", &options);
+ i = 0;
+ if (options != NULL) {
+ maps[i++] = options;
+ }
+ maps[i++] = named_g_defaults;
+ maps[i] = NULL;
+
+ result = named_config_get(maps, type, &portobj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_asuint32(portobj) >= UINT16_MAX) {
+ cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR,
+ "port '%u' out of range",
+ cfg_obj_asuint32(portobj));
+ return (ISC_R_RANGE);
+ }
+ *portp = (in_port_t)cfg_obj_asuint32(portobj);
+ return (ISC_R_SUCCESS);
+}
+
+struct keyalgorithms {
+ const char *str;
+ enum {
+ hmacnone,
+ hmacmd5,
+ hmacsha1,
+ hmacsha224,
+ hmacsha256,
+ hmacsha384,
+ hmacsha512
+ } hmac;
+ unsigned int type;
+ uint16_t size;
+} algorithms[] = { { "hmac-md5", hmacmd5, DST_ALG_HMACMD5, 128 },
+ { "hmac-md5.sig-alg.reg.int", hmacmd5, DST_ALG_HMACMD5, 0 },
+ { "hmac-md5.sig-alg.reg.int.", hmacmd5, DST_ALG_HMACMD5, 0 },
+ { "hmac-sha1", hmacsha1, DST_ALG_HMACSHA1, 160 },
+ { "hmac-sha224", hmacsha224, DST_ALG_HMACSHA224, 224 },
+ { "hmac-sha256", hmacsha256, DST_ALG_HMACSHA256, 256 },
+ { "hmac-sha384", hmacsha384, DST_ALG_HMACSHA384, 384 },
+ { "hmac-sha512", hmacsha512, DST_ALG_HMACSHA512, 512 },
+ { NULL, hmacnone, DST_ALG_UNKNOWN, 0 } };
+
+isc_result_t
+named_config_getkeyalgorithm(const char *str, const dns_name_t **name,
+ uint16_t *digestbits) {
+ return (named_config_getkeyalgorithm2(str, name, NULL, digestbits));
+}
+
+isc_result_t
+named_config_getkeyalgorithm2(const char *str, const dns_name_t **name,
+ unsigned int *typep, uint16_t *digestbits) {
+ int i;
+ size_t len = 0;
+ uint16_t bits;
+ isc_result_t result;
+
+ for (i = 0; algorithms[i].str != NULL; i++) {
+ len = strlen(algorithms[i].str);
+ if (strncasecmp(algorithms[i].str, str, len) == 0 &&
+ (str[len] == '\0' ||
+ (algorithms[i].size != 0 && str[len] == '-')))
+ {
+ break;
+ }
+ }
+ if (algorithms[i].str == NULL) {
+ return (ISC_R_NOTFOUND);
+ }
+ if (str[len] == '-') {
+ result = isc_parse_uint16(&bits, str + len + 1, 10);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ if (bits > algorithms[i].size) {
+ return (ISC_R_RANGE);
+ }
+ } else if (algorithms[i].size == 0) {
+ bits = 128;
+ } else {
+ bits = algorithms[i].size;
+ }
+
+ if (name != NULL) {
+ switch (algorithms[i].hmac) {
+ case hmacmd5:
+ *name = dns_tsig_hmacmd5_name;
+ break;
+ case hmacsha1:
+ *name = dns_tsig_hmacsha1_name;
+ break;
+ case hmacsha224:
+ *name = dns_tsig_hmacsha224_name;
+ break;
+ case hmacsha256:
+ *name = dns_tsig_hmacsha256_name;
+ break;
+ case hmacsha384:
+ *name = dns_tsig_hmacsha384_name;
+ break;
+ case hmacsha512:
+ *name = dns_tsig_hmacsha512_name;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ if (typep != NULL) {
+ *typep = algorithms[i].type;
+ }
+ if (digestbits != NULL) {
+ *digestbits = bits;
+ }
+ return (ISC_R_SUCCESS);
+}
diff --git a/bin/named/control.c b/bin/named/control.c
new file mode 100644
index 0000000..454c128
--- /dev/null
+++ b/bin/named/control.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <stdbool.h>
+
+#include <isc/app.h>
+#include <isc/event.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <isccc/alist.h>
+#include <isccc/cc.h>
+
+#include <named/control.h>
+#include <named/globals.h>
+#include <named/log.h>
+#include <named/os.h>
+#include <named/server.h>
+#ifdef HAVE_LIBSCF
+#include <named/smf_globals.h>
+#endif /* ifdef HAVE_LIBSCF */
+
+static isc_result_t
+getcommand(isc_lex_t *lex, char **cmdp) {
+ isc_result_t result;
+ isc_token_t token;
+
+ REQUIRE(cmdp != NULL && *cmdp == NULL);
+
+ result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF, &token);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ isc_lex_ungettoken(lex, &token);
+
+ if (token.type != isc_tokentype_string) {
+ return (ISC_R_FAILURE);
+ }
+
+ *cmdp = token.value.as_textregion.base;
+
+ return (ISC_R_SUCCESS);
+}
+
+static bool
+command_compare(const char *str, const char *command) {
+ return (strcasecmp(str, command) == 0);
+}
+
+/*%
+ * This function is called to process the incoming command
+ * when a control channel message is received.
+ */
+isc_result_t
+named_control_docommand(isccc_sexpr_t *message, bool readonly,
+ isc_buffer_t **text) {
+ isccc_sexpr_t *data;
+ char *cmdline = NULL;
+ char *command = NULL;
+ isc_result_t result;
+ int log_level;
+ isc_buffer_t src;
+ isc_lex_t *lex = NULL;
+#ifdef HAVE_LIBSCF
+ named_smf_want_disable = 0;
+#endif /* ifdef HAVE_LIBSCF */
+
+ data = isccc_alist_lookup(message, "_data");
+ if (!isccc_alist_alistp(data)) {
+ /*
+ * No data section.
+ */
+ return (ISC_R_FAILURE);
+ }
+
+ result = isccc_cc_lookupstring(data, "type", &cmdline);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * We have no idea what this is.
+ */
+ return (result);
+ }
+
+ result = isc_lex_create(named_g_mctx, strlen(cmdline), &lex);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ isc_buffer_init(&src, cmdline, strlen(cmdline));
+ isc_buffer_add(&src, strlen(cmdline));
+ result = isc_lex_openbuffer(lex, &src);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ result = getcommand(lex, &command);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ /*
+ * Compare the 'command' parameter against all known control commands.
+ */
+ if ((command_compare(command, NAMED_COMMAND_NULL) &&
+ strlen(cmdline) == 4) ||
+ command_compare(command, NAMED_COMMAND_STATUS))
+ {
+ log_level = ISC_LOG_DEBUG(1);
+ } else {
+ log_level = ISC_LOG_INFO;
+ }
+
+ /*
+ * If this listener should have read-only access, reject
+ * restricted commands here. rndc nta is handled specially
+ * below.
+ */
+ if (readonly && !command_compare(command, NAMED_COMMAND_NTA) &&
+ !command_compare(command, NAMED_COMMAND_NULL) &&
+ !command_compare(command, NAMED_COMMAND_STATUS) &&
+ !command_compare(command, NAMED_COMMAND_SHOWZONE) &&
+ !command_compare(command, NAMED_COMMAND_TESTGEN) &&
+ !command_compare(command, NAMED_COMMAND_ZONESTATUS))
+ {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, log_level,
+ "rejecting restricted control channel "
+ "command '%s'",
+ cmdline);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, log_level,
+ "received control channel command '%s'", cmdline);
+
+ /*
+ * After the lengthy "halt" and "stop", the commands are
+ * handled in alphabetical order of the NAMED_COMMAND_ macros.
+ */
+ if (command_compare(command, NAMED_COMMAND_HALT)) {
+#ifdef HAVE_LIBSCF
+ /*
+ * If we are managed by smf(5), AND in chroot, then
+ * we cannot connect to the smf repository, so just
+ * return with an appropriate message back to rndc.
+ */
+ if (named_smf_got_instance == 1 && named_smf_chroot == 1) {
+ result = named_smf_add_message(text);
+ goto cleanup;
+ }
+ /*
+ * If we are managed by smf(5) but not in chroot,
+ * try to disable ourselves the smf way.
+ */
+ if (named_smf_got_instance == 1 && named_smf_chroot == 0) {
+ named_smf_want_disable = 1;
+ }
+ /*
+ * If named_smf_got_instance = 0, named_smf_chroot
+ * is not relevant and we fall through to
+ * isc_app_shutdown below.
+ */
+#endif /* ifdef HAVE_LIBSCF */
+ /* Do not flush master files */
+ named_server_flushonshutdown(named_g_server, false);
+ named_os_shutdownmsg(cmdline, *text);
+ result = ISC_R_SHUTTINGDOWN;
+ } else if (command_compare(command, NAMED_COMMAND_STOP)) {
+ /*
+ * "stop" is the same as "halt" except it does
+ * flush master files.
+ */
+#ifdef HAVE_LIBSCF
+ if (named_smf_got_instance == 1 && named_smf_chroot == 1) {
+ result = named_smf_add_message(text);
+ goto cleanup;
+ }
+ if (named_smf_got_instance == 1 && named_smf_chroot == 0) {
+ named_smf_want_disable = 1;
+ }
+#endif /* ifdef HAVE_LIBSCF */
+ named_server_flushonshutdown(named_g_server, true);
+ named_os_shutdownmsg(cmdline, *text);
+ result = ISC_R_SHUTTINGDOWN;
+ } else if (command_compare(command, NAMED_COMMAND_ADDZONE) ||
+ command_compare(command, NAMED_COMMAND_MODZONE))
+ {
+ result = named_server_changezone(named_g_server, cmdline, text);
+ } else if (command_compare(command, NAMED_COMMAND_DELZONE)) {
+ result = named_server_delzone(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_DNSSEC)) {
+ result = named_server_dnssec(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_DNSTAP) ||
+ command_compare(command, NAMED_COMMAND_DNSTAPREOPEN))
+ {
+ result = named_server_dnstap(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_DUMPDB)) {
+ named_server_dumpdb(named_g_server, lex, text);
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NAMED_COMMAND_DUMPSTATS)) {
+ result = named_server_dumpstats(named_g_server);
+ } else if (command_compare(command, NAMED_COMMAND_FLUSH)) {
+ result = named_server_flushcache(named_g_server, lex);
+ } else if (command_compare(command, NAMED_COMMAND_FLUSHNAME)) {
+ result = named_server_flushnode(named_g_server, lex, false);
+ } else if (command_compare(command, NAMED_COMMAND_FLUSHTREE)) {
+ result = named_server_flushnode(named_g_server, lex, true);
+ } else if (command_compare(command, NAMED_COMMAND_FREEZE)) {
+ result = named_server_freeze(named_g_server, true, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_LOADKEYS) ||
+ command_compare(command, NAMED_COMMAND_SIGN))
+ {
+ result = named_server_rekey(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_MKEYS)) {
+ result = named_server_mkeys(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_NOTIFY)) {
+ result = named_server_notifycommand(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_NOTRACE)) {
+ named_g_debuglevel = 0;
+ isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel);
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NAMED_COMMAND_NTA)) {
+ result = named_server_nta(named_g_server, lex, readonly, text);
+ } else if (command_compare(command, NAMED_COMMAND_NULL)) {
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NAMED_COMMAND_QUERYLOG)) {
+ result = named_server_togglequerylog(named_g_server, lex);
+ } else if (command_compare(command, NAMED_COMMAND_RECONFIG)) {
+ result = named_server_reconfigcommand(named_g_server);
+ } else if (command_compare(command, NAMED_COMMAND_RECURSING)) {
+ result = named_server_dumprecursing(named_g_server);
+ } else if (command_compare(command, NAMED_COMMAND_REFRESH)) {
+ result = named_server_refreshcommand(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_RELOAD)) {
+ result = named_server_reloadcommand(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_RETRANSFER)) {
+ result = named_server_retransfercommand(named_g_server, lex,
+ text);
+ } else if (command_compare(command, NAMED_COMMAND_SCAN)) {
+ named_server_scan_interfaces(named_g_server);
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NAMED_COMMAND_SECROOTS)) {
+ result = named_server_dumpsecroots(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_SERVESTALE)) {
+ result = named_server_servestale(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_SHOWZONE)) {
+ result = named_server_showzone(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_SIGNING)) {
+ result = named_server_signing(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_STATUS)) {
+ result = named_server_status(named_g_server, text);
+ } else if (command_compare(command, NAMED_COMMAND_SYNC)) {
+ result = named_server_sync(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_TCPTIMEOUTS)) {
+ result = named_server_tcptimeouts(lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_TESTGEN)) {
+ result = named_server_testgen(lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_THAW) ||
+ command_compare(command, NAMED_COMMAND_UNFREEZE))
+ {
+ result = named_server_freeze(named_g_server, false, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_TIMERPOKE)) {
+ isc_timermgr_poke(named_g_timermgr);
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NAMED_COMMAND_TRACE)) {
+ result = named_server_setdebuglevel(named_g_server, lex);
+ } else if (command_compare(command, NAMED_COMMAND_TSIGDELETE)) {
+ result = named_server_tsigdelete(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_TSIGLIST)) {
+ result = named_server_tsiglist(named_g_server, text);
+ } else if (command_compare(command, NAMED_COMMAND_VALIDATION)) {
+ result = named_server_validation(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_ZONESTATUS)) {
+ result = named_server_zonestatus(named_g_server, lex, text);
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "unknown control channel command '%s'", command);
+ result = DNS_R_UNKNOWNCOMMAND;
+ }
+
+cleanup:
+ if (lex != NULL) {
+ isc_lex_destroy(&lex);
+ }
+
+ return (result);
+}
diff --git a/bin/named/controlconf.c b/bin/named/controlconf.c
new file mode 100644
index 0000000..d402155
--- /dev/null
+++ b/bin/named/controlconf.c
@@ -0,0 +1,1494 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/event.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/netaddr.h>
+#include <isc/netmgr.h>
+#include <isc/nonce.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/stdtime.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <isccc/alist.h>
+#include <isccc/cc.h>
+#include <isccc/ccmsg.h>
+#include <isccc/events.h>
+#include <isccc/sexpr.h>
+#include <isccc/symtab.h>
+#include <isccc/util.h>
+
+#include <isccfg/namedconf.h>
+
+#include <bind9/check.h>
+
+#include <named/config.h>
+#include <named/control.h>
+#include <named/log.h>
+#include <named/server.h>
+
+typedef struct controlkey controlkey_t;
+typedef ISC_LIST(controlkey_t) controlkeylist_t;
+
+typedef struct controlconnection controlconnection_t;
+typedef ISC_LIST(controlconnection_t) controlconnectionlist_t;
+
+typedef struct controllistener controllistener_t;
+typedef ISC_LIST(controllistener_t) controllistenerlist_t;
+
+struct controlkey {
+ char *keyname;
+ uint32_t algorithm;
+ isc_region_t secret;
+ ISC_LINK(controlkey_t) link;
+};
+
+struct controlconnection {
+ isc_nmhandle_t *readhandle;
+ isc_nmhandle_t *sendhandle;
+ isc_nmhandle_t *cmdhandle;
+ isccc_ccmsg_t ccmsg;
+ bool reading;
+ bool sending;
+ controllistener_t *listener;
+ isccc_sexpr_t *ctrl;
+ isc_buffer_t *buffer;
+ isc_buffer_t *text;
+ isccc_sexpr_t *request;
+ isccc_sexpr_t *response;
+ uint32_t alg;
+ isccc_region_t secret;
+ uint32_t nonce;
+ isc_stdtime_t now;
+ isc_result_t result;
+ ISC_LINK(controlconnection_t) link;
+};
+
+struct controllistener {
+ named_controls_t *controls;
+ isc_mem_t *mctx;
+ isc_sockaddr_t address;
+ isc_nmsocket_t *sock;
+ dns_acl_t *acl;
+ bool exiting;
+ isc_refcount_t refs;
+ controlkeylist_t keys;
+ isc_mutex_t connections_lock;
+ controlconnectionlist_t connections;
+ isc_socktype_t type;
+ uint32_t perm;
+ uint32_t owner;
+ uint32_t group;
+ bool readonly;
+ ISC_LINK(controllistener_t) link;
+};
+
+struct named_controls {
+ named_server_t *server;
+ controllistenerlist_t listeners;
+ atomic_bool shuttingdown;
+ isc_mutex_t symtab_lock;
+ isccc_symtab_t *symtab;
+};
+
+static isc_result_t
+control_newconn(isc_nmhandle_t *handle, isc_result_t result, void *arg);
+static void
+control_recvmessage(isc_nmhandle_t *handle, isc_result_t result, void *arg);
+
+#define CLOCKSKEW 300
+
+static void
+free_controlkey(controlkey_t *key, isc_mem_t *mctx) {
+ if (key->keyname != NULL) {
+ isc_mem_free(mctx, key->keyname);
+ }
+ if (key->secret.base != NULL) {
+ isc_mem_put(mctx, key->secret.base, key->secret.length);
+ }
+ isc_mem_put(mctx, key, sizeof(*key));
+}
+
+static void
+free_controlkeylist(controlkeylist_t *keylist, isc_mem_t *mctx) {
+ while (!ISC_LIST_EMPTY(*keylist)) {
+ controlkey_t *key = ISC_LIST_HEAD(*keylist);
+ ISC_LIST_UNLINK(*keylist, key, link);
+ free_controlkey(key, mctx);
+ }
+}
+
+static void
+free_listener(controllistener_t *listener) {
+ INSIST(listener->exiting);
+ INSIST(ISC_LIST_EMPTY(listener->connections));
+
+ isc_refcount_destroy(&listener->refs);
+
+ if (listener->sock != NULL) {
+ isc_nmsocket_close(&listener->sock);
+ }
+
+ free_controlkeylist(&listener->keys, listener->mctx);
+
+ if (listener->acl != NULL) {
+ dns_acl_detach(&listener->acl);
+ }
+ isc_mutex_destroy(&listener->connections_lock);
+
+ isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener));
+}
+
+static void
+maybe_free_listener(controllistener_t *listener) {
+ if (isc_refcount_decrement(&listener->refs) == 1) {
+ free_listener(listener);
+ }
+}
+
+static void
+shutdown_listener(controllistener_t *listener) {
+ if (!listener->exiting) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+
+ ISC_LIST_UNLINK(listener->controls->listeners, listener, link);
+
+ isc_sockaddr_format(&listener->address, socktext,
+ sizeof(socktext));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
+ "stopping command channel on %s", socktext);
+#if 0
+ /* XXX: no unix domain socket support */
+ if (listener->type == isc_socktype_unix) {
+ isc_socket_cleanunix(&listener->address, true);
+ }
+#endif
+ listener->exiting = true;
+ }
+
+ isc_nm_stoplistening(listener->sock);
+ maybe_free_listener(listener);
+}
+
+static bool
+address_ok(isc_sockaddr_t *sockaddr, controllistener_t *listener) {
+ dns_aclenv_t *env =
+ ns_interfacemgr_getaclenv(named_g_server->interfacemgr);
+ isc_netaddr_t netaddr;
+ isc_result_t result;
+ int match;
+
+ /* ACL doesn't apply to unix domain sockets */
+ if (listener->type != isc_socktype_tcp) {
+ return (true);
+ }
+
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+
+ result = dns_acl_match(&netaddr, NULL, listener->acl, env, &match,
+ NULL);
+ return (result == ISC_R_SUCCESS && match > 0);
+}
+
+static void
+control_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
+ controlconnection_t *conn = (controlconnection_t *)arg;
+ controllistener_t *listener = conn->listener;
+ isc_sockaddr_t peeraddr = isc_nmhandle_peeraddr(handle);
+
+ REQUIRE(conn->sending);
+
+ conn->sending = false;
+
+ if (conn->result == ISC_R_SHUTTINGDOWN) {
+ isc_app_shutdown();
+ goto cleanup_sendhandle;
+ }
+
+ if (atomic_load_acquire(&listener->controls->shuttingdown) ||
+ result == ISC_R_SHUTTINGDOWN)
+ {
+ goto cleanup_sendhandle;
+ } else if (result != ISC_R_SUCCESS) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "error sending command response to %s: %s",
+ socktext, isc_result_totext(result));
+ goto cleanup_sendhandle;
+ }
+
+ isc_nmhandle_attach(handle, &conn->readhandle);
+ conn->reading = true;
+
+ isc_nmhandle_detach(&conn->sendhandle);
+
+ isccc_ccmsg_readmessage(&conn->ccmsg, control_recvmessage, conn);
+ return;
+
+cleanup_sendhandle:
+ isc_nmhandle_detach(&conn->sendhandle);
+}
+
+static void
+log_invalid(isccc_ccmsg_t *ccmsg, isc_result_t result) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t peeraddr = isc_nmhandle_peeraddr(ccmsg->handle);
+
+ isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_ERROR,
+ "invalid command from %s: %s", socktext,
+ isc_result_totext(result));
+}
+
+static void
+conn_cleanup(controlconnection_t *conn) {
+ controllistener_t *listener = conn->listener;
+
+ if (conn->response != NULL) {
+ isccc_sexpr_free(&conn->response);
+ }
+ if (conn->request != NULL) {
+ isccc_sexpr_free(&conn->request);
+ }
+ if (conn->secret.rstart != NULL) {
+ isc_mem_put(listener->mctx, conn->secret.rstart,
+ REGION_SIZE(conn->secret));
+ }
+ if (conn->text != NULL) {
+ isc_buffer_free(&conn->text);
+ }
+}
+
+static void
+control_respond(isc_nmhandle_t *handle, controlconnection_t *conn) {
+ controllistener_t *listener = conn->listener;
+ isccc_sexpr_t *data = NULL;
+ isc_buffer_t b;
+ isc_region_t r;
+ isc_result_t result;
+
+ result = isccc_cc_createresponse(conn->request, conn->now,
+ conn->now + 60, &conn->response);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ if (conn->result == ISC_R_SHUTTINGDOWN) {
+ result = ISC_R_SUCCESS;
+ } else {
+ result = conn->result;
+ }
+
+ data = isccc_alist_lookup(conn->response, "_data");
+ if (data != NULL) {
+ if (isccc_cc_defineuint32(data, "result", result) == NULL) {
+ goto cleanup;
+ }
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ if (data != NULL) {
+ const char *estr = isc_result_totext(result);
+ if (isccc_cc_definestring(data, "err", estr) == NULL) {
+ goto cleanup;
+ }
+ }
+ }
+
+ if (isc_buffer_usedlength(conn->text) > 0) {
+ if (data != NULL) {
+ char *str = (char *)isc_buffer_base(conn->text);
+ if (isccc_cc_definestring(data, "text", str) == NULL) {
+ goto cleanup;
+ }
+ }
+ }
+
+ conn->ctrl = isccc_alist_lookup(conn->response, "_ctrl");
+ if (conn->ctrl == NULL ||
+ isccc_cc_defineuint32(conn->ctrl, "_nonce", conn->nonce) == NULL)
+ {
+ goto cleanup;
+ }
+
+ if (conn->buffer == NULL) {
+ isc_buffer_allocate(listener->mctx, &conn->buffer, 2 * 2048);
+ }
+
+ isc_buffer_clear(conn->buffer);
+ /* Skip the length field (4 bytes) */
+ isc_buffer_add(conn->buffer, 4);
+
+ result = isccc_cc_towire(conn->response, &conn->buffer, conn->alg,
+ &conn->secret);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ isc_buffer_init(&b, conn->buffer->base, 4);
+ isc_buffer_putuint32(&b, conn->buffer->used - 4);
+
+ r.base = conn->buffer->base;
+ r.length = conn->buffer->used;
+
+ isc_nmhandle_attach(handle, &conn->sendhandle);
+ conn->sending = true;
+ conn_cleanup(conn);
+
+ isc_nmhandle_detach(&conn->cmdhandle);
+
+ isc_nm_send(conn->sendhandle, &r, control_senddone, conn);
+
+ return;
+
+cleanup:
+ conn_cleanup(conn);
+ isc_nmhandle_detach(&conn->cmdhandle);
+}
+
+static void
+control_command(isc_task_t *task, isc_event_t *event) {
+ controlconnection_t *conn = event->ev_arg;
+ controllistener_t *listener = conn->listener;
+
+ UNUSED(task);
+
+ if (atomic_load_acquire(&listener->controls->shuttingdown)) {
+ conn_cleanup(conn);
+ isc_nmhandle_detach(&conn->cmdhandle);
+ goto done;
+ }
+
+ conn->result = named_control_docommand(conn->request,
+ listener->readonly, &conn->text);
+ control_respond(conn->cmdhandle, conn);
+
+done:
+ isc_event_free(&event);
+}
+
+static void
+control_recvmessage(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
+ controlconnection_t *conn = (controlconnection_t *)arg;
+ controllistener_t *listener = conn->listener;
+ controlkey_t *key = NULL;
+ isc_event_t *event = NULL;
+ isccc_time_t sent;
+ isccc_time_t exp;
+ uint32_t nonce;
+
+ conn->reading = false;
+
+ /* Is the server shutting down? */
+ if (atomic_load_acquire(&listener->controls->shuttingdown)) {
+ goto cleanup_readhandle;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_SHUTTINGDOWN) {
+ atomic_store_release(&listener->controls->shuttingdown,
+ true);
+ } else if (result != ISC_R_EOF) {
+ log_invalid(&conn->ccmsg, result);
+ }
+
+ goto cleanup_readhandle;
+ }
+
+ for (key = ISC_LIST_HEAD(listener->keys); key != NULL;
+ key = ISC_LIST_NEXT(key, link))
+ {
+ isccc_region_t ccregion;
+
+ ccregion.rstart = isc_buffer_base(conn->ccmsg.buffer);
+ ccregion.rend = isc_buffer_used(conn->ccmsg.buffer);
+ conn->secret.rstart = isc_mem_get(listener->mctx,
+ key->secret.length);
+ memmove(conn->secret.rstart, key->secret.base,
+ key->secret.length);
+ conn->secret.rend = conn->secret.rstart + key->secret.length;
+ conn->alg = key->algorithm;
+ result = isccc_cc_fromwire(&ccregion, &conn->request, conn->alg,
+ &conn->secret);
+ if (result == ISC_R_SUCCESS) {
+ break;
+ }
+ isc_mem_put(listener->mctx, conn->secret.rstart,
+ REGION_SIZE(conn->secret));
+ }
+
+ if (key == NULL) {
+ log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
+ goto cleanup;
+ }
+
+ /* We shouldn't be getting a reply. */
+ if (isccc_cc_isreply(conn->request)) {
+ log_invalid(&conn->ccmsg, ISC_R_FAILURE);
+ goto cleanup;
+ }
+
+ isc_stdtime_get(&conn->now);
+
+ /*
+ * Limit exposure to replay attacks.
+ */
+ conn->ctrl = isccc_alist_lookup(conn->request, "_ctrl");
+ if (!isccc_alist_alistp(conn->ctrl)) {
+ log_invalid(&conn->ccmsg, ISC_R_FAILURE);
+ goto cleanup;
+ }
+
+ if (isccc_cc_lookupuint32(conn->ctrl, "_tim", &sent) == ISC_R_SUCCESS) {
+ if ((sent + CLOCKSKEW) < conn->now ||
+ (sent - CLOCKSKEW) > conn->now)
+ {
+ log_invalid(&conn->ccmsg, ISCCC_R_CLOCKSKEW);
+ goto cleanup;
+ }
+ } else {
+ log_invalid(&conn->ccmsg, ISC_R_FAILURE);
+ goto cleanup;
+ }
+
+ /*
+ * Expire messages that are too old.
+ */
+ if (isccc_cc_lookupuint32(conn->ctrl, "_exp", &exp) == ISC_R_SUCCESS &&
+ conn->now > exp)
+ {
+ log_invalid(&conn->ccmsg, ISCCC_R_EXPIRED);
+ goto cleanup;
+ }
+
+ /*
+ * Duplicate suppression (required for UDP).
+ */
+ LOCK(&listener->controls->symtab_lock);
+ isccc_cc_cleansymtab(listener->controls->symtab, conn->now);
+ result = isccc_cc_checkdup(listener->controls->symtab, conn->request,
+ conn->now);
+ UNLOCK(&listener->controls->symtab_lock);
+ if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_EXISTS) {
+ result = ISCCC_R_DUPLICATE;
+ }
+ log_invalid(&conn->ccmsg, result);
+ goto cleanup;
+ }
+
+ if (conn->nonce != 0 &&
+ (isccc_cc_lookupuint32(conn->ctrl, "_nonce", &nonce) !=
+ ISC_R_SUCCESS ||
+ conn->nonce != nonce))
+ {
+ log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
+ goto cleanup;
+ }
+
+ isc_buffer_allocate(listener->mctx, &conn->text, 2 * 2048);
+
+ isc_nmhandle_attach(handle, &conn->cmdhandle);
+ isc_nmhandle_detach(&conn->readhandle);
+
+ if (conn->nonce == 0) {
+ /*
+ * Establish nonce.
+ */
+ while (conn->nonce == 0) {
+ isc_nonce_buf(&conn->nonce, sizeof(conn->nonce));
+ }
+ conn->result = ISC_R_SUCCESS;
+ control_respond(handle, conn);
+ return;
+ }
+
+ /*
+ * Trigger the command.
+ */
+
+ event = isc_event_allocate(listener->mctx, conn, NAMED_EVENT_COMMAND,
+ control_command, conn, sizeof(isc_event_t));
+ isc_task_send(named_g_server->task, &event);
+
+ return;
+
+cleanup:
+ conn_cleanup(conn);
+
+cleanup_readhandle:
+ /*
+ * readhandle could be NULL if we're shutting down,
+ * but if not we need to detach it.
+ */
+ if (conn->readhandle != NULL) {
+ isc_nmhandle_detach(&conn->readhandle);
+ }
+}
+
+static void
+conn_reset(void *arg) {
+ controlconnection_t *conn = (controlconnection_t *)arg;
+ controllistener_t *listener = conn->listener;
+
+ if (conn->buffer != NULL) {
+ isc_buffer_free(&conn->buffer);
+ }
+
+ if (conn->reading) {
+ isccc_ccmsg_cancelread(&conn->ccmsg);
+ return;
+ }
+
+ LOCK(&listener->connections_lock);
+ ISC_LIST_UNLINK(listener->connections, conn, link);
+ UNLOCK(&listener->connections_lock);
+#ifdef ENABLE_AFL
+ if (named_g_fuzz_type == isc_fuzz_rndc) {
+ named_fuzz_notify();
+ }
+#endif /* ifdef ENABLE_AFL */
+
+ isccc_ccmsg_invalidate(&conn->ccmsg);
+}
+
+static void
+conn_put(void *arg) {
+ controlconnection_t *conn = (controlconnection_t *)arg;
+ controllistener_t *listener = conn->listener;
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_DEBUG(3),
+ "freeing control connection");
+ maybe_free_listener(listener);
+}
+
+static void
+newconnection(controllistener_t *listener, isc_nmhandle_t *handle) {
+ controlconnection_t *conn = NULL;
+
+ conn = isc_nmhandle_getdata(handle);
+ if (conn == NULL) {
+ conn = isc_nmhandle_getextra(handle);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_DEBUG(3),
+ "allocate new control connection");
+ isc_nmhandle_setdata(handle, conn, conn_reset, conn_put);
+ isc_refcount_increment(&listener->refs);
+ }
+
+ *conn = (controlconnection_t){ .listener = listener,
+ .reading = false,
+ .alg = DST_ALG_UNKNOWN };
+
+ isccc_ccmsg_init(listener->mctx, handle, &conn->ccmsg);
+
+ /* Set a 32 KiB upper limit on incoming message. */
+ isccc_ccmsg_setmaxsize(&conn->ccmsg, 32768);
+
+ LOCK(&listener->connections_lock);
+ ISC_LIST_INITANDAPPEND(listener->connections, conn, link);
+ UNLOCK(&listener->connections_lock);
+
+ isc_nmhandle_attach(handle, &conn->readhandle);
+ conn->reading = true;
+
+ isccc_ccmsg_readmessage(&conn->ccmsg, control_recvmessage, conn);
+}
+
+static isc_result_t
+control_newconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
+ controllistener_t *listener = arg;
+ isc_sockaddr_t peeraddr;
+
+ if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_SHUTTINGDOWN) {
+ shutdown_listener(listener);
+ }
+ return (result);
+ }
+
+ peeraddr = isc_nmhandle_peeraddr(handle);
+ if (!address_ok(&peeraddr, listener)) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "rejected command channel message from %s",
+ socktext);
+ return (ISC_R_FAILURE);
+ }
+
+ newconnection(listener, handle);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+controls_shutdown(named_controls_t *controls) {
+ controllistener_t *listener = NULL;
+ controllistener_t *next = NULL;
+
+ for (listener = ISC_LIST_HEAD(controls->listeners); listener != NULL;
+ listener = next)
+ {
+ /*
+ * This is asynchronous. As listeners shut down, they will
+ * call their callbacks.
+ */
+ next = ISC_LIST_NEXT(listener, link);
+ shutdown_listener(listener);
+ }
+}
+
+void
+named_controls_shutdown(named_controls_t *controls) {
+ controls_shutdown(controls);
+ atomic_store_release(&controls->shuttingdown, true);
+}
+
+static isc_result_t
+cfgkeylist_find(const cfg_obj_t *keylist, const char *keyname,
+ const cfg_obj_t **objp) {
+ const cfg_listelt_t *element = NULL;
+ const char *str = NULL;
+ const cfg_obj_t *obj = NULL;
+
+ for (element = cfg_list_first(keylist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ str = cfg_obj_asstring(cfg_map_getname(obj));
+ if (strcasecmp(str, keyname) == 0) {
+ break;
+ }
+ }
+ if (element == NULL) {
+ return (ISC_R_NOTFOUND);
+ }
+ obj = cfg_listelt_value(element);
+ *objp = obj;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+controlkeylist_fromcfg(const cfg_obj_t *keylist, isc_mem_t *mctx,
+ controlkeylist_t *keyids) {
+ const cfg_listelt_t *element = NULL;
+ char *newstr = NULL;
+ const char *str = NULL;
+ const cfg_obj_t *obj = NULL;
+ controlkey_t *key = NULL;
+
+ for (element = cfg_list_first(keylist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ str = cfg_obj_asstring(obj);
+ newstr = isc_mem_strdup(mctx, str);
+ key = isc_mem_get(mctx, sizeof(*key));
+ key->keyname = newstr;
+ key->algorithm = DST_ALG_UNKNOWN;
+ key->secret.base = NULL;
+ key->secret.length = 0;
+ ISC_LINK_INIT(key, link);
+ ISC_LIST_APPEND(*keyids, key, link);
+ newstr = NULL;
+ }
+}
+
+static void
+register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist,
+ controlkeylist_t *keyids, isc_mem_t *mctx, const char *socktext) {
+ controlkey_t *keyid = NULL, *next = NULL;
+ const cfg_obj_t *keydef = NULL;
+ char secret[1024];
+ isc_buffer_t b;
+ isc_result_t result;
+
+ /*
+ * Find the keys corresponding to the keyids used by this listener.
+ */
+ for (keyid = ISC_LIST_HEAD(*keyids); keyid != NULL; keyid = next) {
+ next = ISC_LIST_NEXT(keyid, link);
+
+ result = cfgkeylist_find(keylist, keyid->keyname, &keydef);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING,
+ "couldn't find key '%s' for use with "
+ "command channel %s",
+ keyid->keyname, socktext);
+ ISC_LIST_UNLINK(*keyids, keyid, link);
+ free_controlkey(keyid, mctx);
+ } else {
+ const cfg_obj_t *algobj = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ const char *algstr = NULL;
+ const char *secretstr = NULL;
+ unsigned int algtype;
+
+ (void)cfg_map_get(keydef, "algorithm", &algobj);
+ (void)cfg_map_get(keydef, "secret", &secretobj);
+ INSIST(algobj != NULL && secretobj != NULL);
+
+ algstr = cfg_obj_asstring(algobj);
+ secretstr = cfg_obj_asstring(secretobj);
+
+ result = named_config_getkeyalgorithm2(algstr, NULL,
+ &algtype, NULL);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(control, named_g_lctx,
+ ISC_LOG_WARNING,
+ "unsupported algorithm '%s' in "
+ "key '%s' for use with command "
+ "channel %s",
+ algstr, keyid->keyname, socktext);
+ ISC_LIST_UNLINK(*keyids, keyid, link);
+ free_controlkey(keyid, mctx);
+ continue;
+ }
+
+ keyid->algorithm = algtype;
+ isc_buffer_init(&b, secret, sizeof(secret));
+ result = isc_base64_decodestring(secretstr, &b);
+
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(keydef, named_g_lctx,
+ ISC_LOG_WARNING,
+ "secret for key '%s' on "
+ "command channel %s: %s",
+ keyid->keyname, socktext,
+ isc_result_totext(result));
+ ISC_LIST_UNLINK(*keyids, keyid, link);
+ free_controlkey(keyid, mctx);
+ continue;
+ }
+
+ keyid->secret.length = isc_buffer_usedlength(&b);
+ keyid->secret.base = isc_mem_get(mctx,
+ keyid->secret.length);
+ memmove(keyid->secret.base, isc_buffer_base(&b),
+ keyid->secret.length);
+ }
+ }
+}
+
+#define CHECK(x) \
+ do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) { \
+ goto cleanup; \
+ } \
+ } while (0)
+
+static isc_result_t
+get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) {
+ isc_result_t result;
+ cfg_parser_t *pctx = NULL;
+ cfg_obj_t *config = NULL;
+ const cfg_obj_t *key = NULL;
+ const cfg_obj_t *algobj = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ const char *algstr = NULL;
+ const char *secretstr = NULL;
+ controlkey_t *keyid = NULL;
+ char secret[1024];
+ unsigned int algtype;
+ isc_buffer_t b;
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_INFO,
+ "configuring command channel from '%s'", named_g_keyfile);
+ if (!isc_file_exists(named_g_keyfile)) {
+ return (ISC_R_FILENOTFOUND);
+ }
+
+ CHECK(cfg_parser_create(mctx, named_g_lctx, &pctx));
+ CHECK(cfg_parse_file(pctx, named_g_keyfile, &cfg_type_rndckey,
+ &config));
+ CHECK(cfg_map_get(config, "key", &key));
+
+ keyid = isc_mem_get(mctx, sizeof(*keyid));
+ keyid->keyname = isc_mem_strdup(mctx,
+ cfg_obj_asstring(cfg_map_getname(key)));
+ keyid->secret.base = NULL;
+ keyid->secret.length = 0;
+ keyid->algorithm = DST_ALG_UNKNOWN;
+ ISC_LINK_INIT(keyid, link);
+ if (keyid->keyname == NULL) {
+ CHECK(ISC_R_NOMEMORY);
+ }
+
+ CHECK(bind9_check_key(key, named_g_lctx));
+
+ (void)cfg_map_get(key, "algorithm", &algobj);
+ (void)cfg_map_get(key, "secret", &secretobj);
+ INSIST(algobj != NULL && secretobj != NULL);
+
+ algstr = cfg_obj_asstring(algobj);
+ secretstr = cfg_obj_asstring(secretobj);
+
+ result = named_config_getkeyalgorithm2(algstr, NULL, &algtype, NULL);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
+ "unsupported algorithm '%s' in "
+ "key '%s' for use with command "
+ "channel",
+ algstr, keyid->keyname);
+ goto cleanup;
+ }
+
+ keyid->algorithm = algtype;
+ isc_buffer_init(&b, secret, sizeof(secret));
+ result = isc_base64_decodestring(secretstr, &b);
+
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
+ "secret for key '%s' on command channel: %s",
+ keyid->keyname, isc_result_totext(result));
+ goto cleanup;
+ }
+
+ keyid->secret.length = isc_buffer_usedlength(&b);
+ keyid->secret.base = isc_mem_get(mctx, keyid->secret.length);
+ memmove(keyid->secret.base, isc_buffer_base(&b), keyid->secret.length);
+ ISC_LIST_APPEND(*keyids, keyid, link);
+ keyid = NULL;
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (keyid != NULL) {
+ free_controlkey(keyid, mctx);
+ }
+ if (config != NULL) {
+ cfg_obj_destroy(pctx, &config);
+ }
+ if (pctx != NULL) {
+ cfg_parser_destroy(&pctx);
+ }
+ return (result);
+}
+
+/*
+ * Ensures that both '*global_keylistp' and '*control_keylistp' are
+ * valid or both are NULL.
+ */
+static void
+get_key_info(const cfg_obj_t *config, const cfg_obj_t *control,
+ const cfg_obj_t **global_keylistp,
+ const cfg_obj_t **control_keylistp) {
+ isc_result_t result;
+ const cfg_obj_t *control_keylist = NULL;
+ const cfg_obj_t *global_keylist = NULL;
+
+ REQUIRE(global_keylistp != NULL && *global_keylistp == NULL);
+ REQUIRE(control_keylistp != NULL && *control_keylistp == NULL);
+
+ control_keylist = cfg_tuple_get(control, "keys");
+
+ if (!cfg_obj_isvoid(control_keylist) &&
+ cfg_list_first(control_keylist) != NULL)
+ {
+ result = cfg_map_get(config, "key", &global_keylist);
+
+ if (result == ISC_R_SUCCESS) {
+ *global_keylistp = global_keylist;
+ *control_keylistp = control_keylist;
+ }
+ }
+}
+
+static void
+update_listener(named_controls_t *cp, controllistener_t **listenerp,
+ const cfg_obj_t *control, const cfg_obj_t *config,
+ isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
+ const char *socktext, isc_socktype_t type) {
+ controllistener_t *listener = NULL;
+ const cfg_obj_t *allow = NULL;
+ const cfg_obj_t *global_keylist = NULL;
+ const cfg_obj_t *control_keylist = NULL;
+ dns_acl_t *new_acl = NULL;
+ controlkeylist_t keys;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ for (listener = ISC_LIST_HEAD(cp->listeners); listener != NULL;
+ listener = ISC_LIST_NEXT(listener, link))
+ {
+ if (isc_sockaddr_equal(addr, &listener->address)) {
+ break;
+ }
+ }
+
+ if (listener == NULL) {
+ *listenerp = NULL;
+ return;
+ }
+
+ /*
+ * There is already a listener for this sockaddr.
+ * Update the access list and key information.
+ *
+ * First try to deal with the key situation. There are a few
+ * possibilities:
+ * (a) It had an explicit keylist and still has an explicit keylist.
+ * (b) It had an automagic key and now has an explicit keylist.
+ * (c) It had an explicit keylist and now needs an automagic key.
+ * (d) It has an automagic key and still needs the automagic key.
+ *
+ * (c) and (d) are the annoying ones. The caller needs to know
+ * that it should use the automagic configuration for key information
+ * in place of the named.conf configuration.
+ *
+ * XXXDCL There is one other hazard that has not been dealt with,
+ * the problem that if a key change is being caused by a control
+ * channel reload, then the response will be with the new key
+ * and not able to be decrypted by the client.
+ */
+ if (control != NULL) {
+ get_key_info(config, control, &global_keylist,
+ &control_keylist);
+ }
+
+ if (control_keylist != NULL) {
+ INSIST(global_keylist != NULL);
+
+ ISC_LIST_INIT(keys);
+ controlkeylist_fromcfg(control_keylist, listener->mctx, &keys);
+ free_controlkeylist(&listener->keys, listener->mctx);
+ listener->keys = keys;
+ register_keys(control, global_keylist, &listener->keys,
+ listener->mctx, socktext);
+ } else {
+ free_controlkeylist(&listener->keys, listener->mctx);
+ result = get_rndckey(listener->mctx, &listener->keys);
+ }
+
+ if (result != ISC_R_SUCCESS && global_keylist != NULL) {
+ /*
+ * This message might be a little misleading since the
+ * "new keys" might in fact be identical to the old ones,
+ * but tracking whether they are identical just for the
+ * sake of avoiding this message would be too much trouble.
+ */
+ if (control != NULL) {
+ cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING,
+ "couldn't install new keys for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "couldn't install new keys for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ }
+ }
+
+ /*
+ * Now, keep the old access list unless a new one can be made.
+ */
+ if (control != NULL && type == isc_socktype_tcp) {
+ allow = cfg_tuple_get(control, "allow");
+ result = cfg_acl_fromconfig(allow, config, named_g_lctx,
+ aclconfctx, listener->mctx, 0,
+ &new_acl);
+ } else {
+ result = dns_acl_any(listener->mctx, &new_acl);
+ }
+
+ if (control != NULL) {
+ const cfg_obj_t *readonly = NULL;
+
+ readonly = cfg_tuple_get(control, "read-only");
+ if (!cfg_obj_isvoid(readonly)) {
+ listener->readonly = cfg_obj_asboolean(readonly);
+ }
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ dns_acl_detach(&listener->acl);
+ dns_acl_attach(new_acl, &listener->acl);
+ dns_acl_detach(&new_acl);
+ /* XXXDCL say the old acl is still used? */
+ } else if (control != NULL) {
+ cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING,
+ "couldn't install new acl for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "couldn't install new acl for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ }
+
+#if 0
+ /* XXX: no unix socket support yet */
+ if (result == ISC_R_SUCCESS && type == isc_socktype_unix) {
+ uint32_t perm, owner, group;
+ perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm"));
+ owner = cfg_obj_asuint32(cfg_tuple_get(control, "owner"));
+ group = cfg_obj_asuint32(cfg_tuple_get(control, "group"));
+ result = ISC_R_SUCCESS;
+ if (listener->perm != perm || listener->owner != owner ||
+ listener->group != group)
+ {
+ result = isc_socket_permunix(&listener->address, perm,
+ owner, group);
+ }
+ if (result == ISC_R_SUCCESS) {
+ listener->perm = perm;
+ listener->owner = owner;
+ listener->group = group;
+ } else if (control != NULL) {
+ cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING,
+ "couldn't update ownership/permission for "
+ "command channel %s",
+ socktext);
+ }
+ }
+#endif
+
+ *listenerp = listener;
+}
+
+static void
+add_listener(named_controls_t *cp, controllistener_t **listenerp,
+ const cfg_obj_t *control, const cfg_obj_t *config,
+ isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
+ const char *socktext, isc_socktype_t type) {
+ isc_mem_t *mctx = cp->server->mctx;
+ controllistener_t *listener = NULL;
+ const cfg_obj_t *allow = NULL;
+ const cfg_obj_t *global_keylist = NULL;
+ const cfg_obj_t *control_keylist = NULL;
+ dns_acl_t *new_acl = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ int pf;
+
+ listener = isc_mem_get(mctx, sizeof(*listener));
+ *listener = (controllistener_t){ .controls = cp,
+ .address = *addr,
+ .type = type };
+ isc_mem_attach(mctx, &listener->mctx);
+ isc_mutex_init(&listener->connections_lock);
+ ISC_LINK_INIT(listener, link);
+ ISC_LIST_INIT(listener->keys);
+ ISC_LIST_INIT(listener->connections);
+ isc_refcount_init(&listener->refs, 1);
+
+ /*
+ * Make the ACL.
+ */
+ if (control != NULL && type == isc_socktype_tcp) {
+ const cfg_obj_t *readonly = NULL;
+
+ allow = cfg_tuple_get(control, "allow");
+ CHECK(cfg_acl_fromconfig(allow, config, named_g_lctx,
+ aclconfctx, mctx, 0, &new_acl));
+
+ readonly = cfg_tuple_get(control, "read-only");
+ if (!cfg_obj_isvoid(readonly)) {
+ listener->readonly = cfg_obj_asboolean(readonly);
+ }
+ } else {
+ CHECK(dns_acl_any(mctx, &new_acl));
+ }
+
+ dns_acl_attach(new_acl, &listener->acl);
+ dns_acl_detach(&new_acl);
+
+ if (config != NULL) {
+ get_key_info(config, control, &global_keylist,
+ &control_keylist);
+ }
+
+ if (control_keylist != NULL) {
+ controlkeylist_fromcfg(control_keylist, listener->mctx,
+ &listener->keys);
+ register_keys(control, global_keylist, &listener->keys,
+ listener->mctx, socktext);
+ } else {
+ result = get_rndckey(mctx, &listener->keys);
+ if (result != ISC_R_SUCCESS && control != NULL) {
+ cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING,
+ "couldn't install keys for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ }
+ }
+
+ pf = isc_sockaddr_pf(&listener->address);
+ if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
+ (pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) ||
+ (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
+ {
+ CHECK(ISC_R_FAMILYNOSUPPORT);
+ }
+
+#if 0
+ /* XXX: no unix socket support yet */
+ if (type == isc_socktype_unix) {
+ isc_socket_cleanunix(&listener->address, false);
+ }
+#endif
+
+ CHECK(isc_nm_listentcp(
+ named_g_netmgr, &listener->address, control_newconn, listener,
+ sizeof(controlconnection_t), 5, NULL, &listener->sock));
+#if 0
+ /* XXX: no unix socket support yet */
+ if (type == isc_socktype_unix) {
+ listener->perm =
+ cfg_obj_asuint32(cfg_tuple_get(control, "perm"));
+ listener->owner =
+ cfg_obj_asuint32(cfg_tuple_get(control, "owner"));
+ listener->group =
+ cfg_obj_asuint32(cfg_tuple_get(control, "group"));
+ result = isc_socket_permunix(&listener->address, listener->perm,
+ listener->owner, listener->group);
+ }
+#endif
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
+ "command channel listening on %s", socktext);
+ *listenerp = listener;
+ return;
+
+cleanup:
+ isc_refcount_decrement(&listener->refs);
+ listener->exiting = true;
+ free_listener(listener);
+
+ if (control != NULL) {
+ cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING,
+ "couldn't add command channel %s: %s", socktext,
+ isc_result_totext(result));
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
+ "couldn't add command channel %s: %s", socktext,
+ isc_result_totext(result));
+ }
+
+ *listenerp = NULL;
+
+ /* XXXDCL return error results? fail hard? */
+}
+
+isc_result_t
+named_controls_configure(named_controls_t *cp, const cfg_obj_t *config,
+ cfg_aclconfctx_t *aclconfctx) {
+ controllistener_t *listener = NULL;
+ controllistenerlist_t new_listeners;
+ const cfg_obj_t *controlslist = NULL;
+ const cfg_listelt_t *element, *element2;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+
+ ISC_LIST_INIT(new_listeners);
+
+ /*
+ * Get the list of named.conf 'controls' statements.
+ */
+ (void)cfg_map_get(config, "controls", &controlslist);
+
+ /*
+ * Run through the new control channel list, noting sockets that
+ * are already being listened on and moving them to the new list.
+ *
+ * Identifying duplicate addr/port combinations is left to either
+ * the underlying config code, or to the bind attempt getting an
+ * address-in-use error.
+ */
+ if (controlslist != NULL) {
+ for (element = cfg_list_first(controlslist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *controls = NULL;
+ const cfg_obj_t *inetcontrols = NULL;
+
+ controls = cfg_listelt_value(element);
+ (void)cfg_map_get(controls, "inet", &inetcontrols);
+ if (inetcontrols == NULL) {
+ continue;
+ }
+
+ for (element2 = cfg_list_first(inetcontrols);
+ element2 != NULL;
+ element2 = cfg_list_next(element2))
+ {
+ const cfg_obj_t *control = NULL;
+ const cfg_obj_t *obj = NULL;
+ isc_sockaddr_t addr;
+
+ /*
+ * The parser handles BIND 8 configuration file
+ * syntax, so it allows unix phrases as well
+ * inet phrases with no keys{} clause.
+ */
+ control = cfg_listelt_value(element2);
+
+ obj = cfg_tuple_get(control, "address");
+ addr = *cfg_obj_assockaddr(obj);
+ if (isc_sockaddr_getport(&addr) == 0) {
+ isc_sockaddr_setport(
+ &addr, NAMED_CONTROL_PORT);
+ }
+
+ isc_sockaddr_format(&addr, socktext,
+ sizeof(socktext));
+
+ isc_log_write(named_g_lctx,
+ NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL,
+ ISC_LOG_DEBUG(9),
+ "processing control channel %s",
+ socktext);
+
+ update_listener(cp, &listener, control, config,
+ &addr, aclconfctx, socktext,
+ isc_socktype_tcp);
+
+ if (listener != NULL) {
+ /*
+ * Remove the listener from the old
+ * list, so it won't be shut down.
+ */
+ ISC_LIST_UNLINK(cp->listeners, listener,
+ link);
+ } else {
+ /*
+ * This is a new listener.
+ */
+ add_listener(cp, &listener, control,
+ config, &addr, aclconfctx,
+ socktext,
+ isc_socktype_tcp);
+ }
+
+ if (listener != NULL) {
+ ISC_LIST_APPEND(new_listeners, listener,
+ link);
+ }
+ }
+ }
+ for (element = cfg_list_first(controlslist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *controls = NULL;
+ const cfg_obj_t *unixcontrols = NULL;
+
+ controls = cfg_listelt_value(element);
+ (void)cfg_map_get(controls, "unix", &unixcontrols);
+ if (unixcontrols == NULL) {
+ continue;
+ }
+
+ cfg_obj_log(controls, named_g_lctx, ISC_LOG_ERROR,
+ "UNIX domain sockets not yet supported");
+ return (ISC_R_FAILURE);
+
+#if 0
+ /* XXX: no unix domain socket support in netmgr */
+ for (element2 = cfg_list_first(unixcontrols);
+ element2 != NULL;
+ element2 = cfg_list_next(element2))
+ {
+ const cfg_obj_t *control = NULL;
+ const cfg_obj_t *path = NULL;
+ isc_sockaddr_t addr;
+ isc_result_t result;
+
+ /*
+ * The parser handles BIND 8 configuration file
+ * syntax, so it allows unix phrases as well
+ * inet phrases with no keys{} clause.
+ */
+ control = cfg_listelt_value(element2);
+
+ path = cfg_tuple_get(control, "path");
+ result = isc_sockaddr_frompath(
+ &addr, cfg_obj_asstring(path));
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(
+ named_g_lctx,
+ NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL,
+ ISC_LOG_DEBUG(9),
+ "control channel '%s': %s",
+ cfg_obj_asstring(path),
+ isc_result_totext(result));
+ continue;
+ }
+
+ isc_log_write(named_g_lctx,
+ NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL,
+ ISC_LOG_DEBUG(9),
+ "processing control channel '%s'",
+ cfg_obj_asstring(path));
+
+ update_listener(cp, &listener, control, config,
+ &addr, aclconfctx,
+ cfg_obj_asstring(path),
+ isc_socktype_unix);
+
+ if (listener != NULL) {
+ /*
+ * Remove the listener from the old
+ * list, so it won't be shut down.
+ */
+ ISC_LIST_UNLINK(cp->listeners, listener,
+ link);
+ } else {
+ /*
+ * This is a new listener.
+ */
+ add_listener(cp, &listener, control,
+ config, &addr, aclconfctx,
+ cfg_obj_asstring(path),
+ isc_socktype_unix);
+ }
+
+ if (listener != NULL) {
+ ISC_LIST_APPEND(new_listeners, listener,
+ link);
+ }
+ }
+#endif
+ }
+ } else {
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ isc_sockaddr_t addr;
+
+ if (i == 0) {
+ struct in_addr localhost;
+
+ if (isc_net_probeipv4() != ISC_R_SUCCESS) {
+ continue;
+ }
+ localhost.s_addr = htonl(INADDR_LOOPBACK);
+ isc_sockaddr_fromin(&addr, &localhost, 0);
+ } else {
+ if (isc_net_probeipv6() != ISC_R_SUCCESS) {
+ continue;
+ }
+ isc_sockaddr_fromin6(&addr, &in6addr_loopback,
+ 0);
+ }
+ isc_sockaddr_setport(&addr, NAMED_CONTROL_PORT);
+
+ isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+
+ update_listener(cp, &listener, NULL, NULL, &addr, NULL,
+ socktext, isc_socktype_tcp);
+
+ if (listener != NULL) {
+ /*
+ * Remove the listener from the old
+ * list, so it won't be shut down.
+ */
+ ISC_LIST_UNLINK(cp->listeners, listener, link);
+ } else {
+ /*
+ * This is a new listener.
+ */
+ add_listener(cp, &listener, NULL, NULL, &addr,
+ NULL, socktext, isc_socktype_tcp);
+ }
+
+ if (listener != NULL) {
+ ISC_LIST_APPEND(new_listeners, listener, link);
+ }
+ }
+ }
+
+ /*
+ * named_control_shutdown() will stop whatever is on the global
+ * listeners list, which currently only has whatever sockaddrs
+ * were in the previous configuration (if any) that do not
+ * remain in the current configuration.
+ */
+ controls_shutdown(cp);
+
+ /*
+ * Put all of the valid listeners on the listeners list.
+ * Anything already on listeners in the process of shutting
+ * down will be taken care of by listen_done().
+ */
+ ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+named_controls_create(named_server_t *server, named_controls_t **ctrlsp) {
+ isc_mem_t *mctx = server->mctx;
+ isc_result_t result;
+ named_controls_t *controls = isc_mem_get(mctx, sizeof(*controls));
+
+ *controls = (named_controls_t){
+ .server = server,
+ };
+
+ ISC_LIST_INIT(controls->listeners);
+
+ atomic_init(&controls->shuttingdown, false);
+ isc_mutex_init(&controls->symtab_lock);
+ LOCK(&controls->symtab_lock);
+ result = isccc_cc_createsymtab(&controls->symtab);
+ UNLOCK(&controls->symtab_lock);
+
+ if (result != ISC_R_SUCCESS) {
+ isc_mutex_destroy(&controls->symtab_lock);
+ isc_mem_put(server->mctx, controls, sizeof(*controls));
+ return (result);
+ }
+ *ctrlsp = controls;
+ return (ISC_R_SUCCESS);
+}
+
+void
+named_controls_destroy(named_controls_t **ctrlsp) {
+ named_controls_t *controls = *ctrlsp;
+ *ctrlsp = NULL;
+
+ REQUIRE(ISC_LIST_EMPTY(controls->listeners));
+
+ LOCK(&controls->symtab_lock);
+ isccc_symtab_destroy(&controls->symtab);
+ UNLOCK(&controls->symtab_lock);
+ isc_mutex_destroy(&controls->symtab_lock);
+ isc_mem_put(controls->server->mctx, controls, sizeof(*controls));
+}
diff --git a/bin/named/dlz_dlopen_driver.c b/bin/named/dlz_dlopen_driver.c
new file mode 100644
index 0000000..f636cd2
--- /dev/null
+++ b/bin/named/dlz_dlopen_driver.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uv.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/dlz_dlopen.h>
+#include <dns/log.h>
+
+#include <dlz/dlz_dlopen_driver.h>
+#include <named/globals.h>
+
+static dns_sdlzimplementation_t *dlz_dlopen = NULL;
+
+typedef struct dlopen_data {
+ isc_mem_t *mctx;
+ char *dl_path;
+ char *dlzname;
+ uv_lib_t dl_handle;
+ void *dbdata;
+ unsigned int flags;
+ isc_mutex_t lock;
+ int version;
+ bool in_configure;
+
+ dlz_dlopen_version_t *dlz_version;
+ dlz_dlopen_create_t *dlz_create;
+ dlz_dlopen_findzonedb_t *dlz_findzonedb;
+ dlz_dlopen_lookup_t *dlz_lookup;
+ dlz_dlopen_authority_t *dlz_authority;
+ dlz_dlopen_allnodes_t *dlz_allnodes;
+ dlz_dlopen_allowzonexfr_t *dlz_allowzonexfr;
+ dlz_dlopen_newversion_t *dlz_newversion;
+ dlz_dlopen_closeversion_t *dlz_closeversion;
+ dlz_dlopen_configure_t *dlz_configure;
+ dlz_dlopen_ssumatch_t *dlz_ssumatch;
+ dlz_dlopen_addrdataset_t *dlz_addrdataset;
+ dlz_dlopen_subrdataset_t *dlz_subrdataset;
+ dlz_dlopen_delrdataset_t *dlz_delrdataset;
+ dlz_dlopen_destroy_t *dlz_destroy;
+} dlopen_data_t;
+
+/* Modules can choose whether they are lock-safe or not. */
+#define MAYBE_LOCK(cd) \
+ do { \
+ if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \
+ !cd->in_configure) \
+ LOCK(&cd->lock); \
+ } while (0)
+
+#define MAYBE_UNLOCK(cd) \
+ do { \
+ if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \
+ !cd->in_configure) \
+ UNLOCK(&cd->lock); \
+ } while (0)
+
+/*
+ * Log a message at the given level.
+ */
+static void
+dlopen_log(int level, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ,
+ ISC_LOG_DEBUG(level), fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * SDLZ methods
+ */
+
+static isc_result_t
+dlopen_dlz_allnodes(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzallnodes_t *allnodes) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+ isc_result_t result;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_allnodes == NULL) {
+ return (ISC_R_NOPERM);
+ }
+
+ MAYBE_LOCK(cd);
+ result = cd->dlz_allnodes(zone, cd->dbdata, allnodes);
+ MAYBE_UNLOCK(cd);
+ return (result);
+}
+
+static isc_result_t
+dlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name,
+ const char *client) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+ isc_result_t result;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_allowzonexfr == NULL) {
+ return (ISC_R_NOPERM);
+ }
+
+ MAYBE_LOCK(cd);
+ result = cd->dlz_allowzonexfr(cd->dbdata, name, client);
+ MAYBE_UNLOCK(cd);
+ return (result);
+}
+
+static isc_result_t
+dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzlookup_t *lookup) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+ isc_result_t result;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_authority == NULL) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ MAYBE_LOCK(cd);
+ result = cd->dlz_authority(zone, cd->dbdata, lookup);
+ MAYBE_UNLOCK(cd);
+ return (result);
+}
+
+static isc_result_t
+dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+ isc_result_t result;
+
+ UNUSED(driverarg);
+
+ MAYBE_LOCK(cd);
+ result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo);
+ MAYBE_UNLOCK(cd);
+ return (result);
+}
+
+static isc_result_t
+dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg,
+ void *dbdata, dns_sdlzlookup_t *lookup,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+ isc_result_t result;
+
+ UNUSED(driverarg);
+
+ MAYBE_LOCK(cd);
+ result = cd->dlz_lookup(zone, name, cd->dbdata, lookup, methods,
+ clientinfo);
+ MAYBE_UNLOCK(cd);
+ return (result);
+}
+
+/*
+ * Load a symbol from the library
+ */
+static void *
+dl_load_symbol(dlopen_data_t *cd, const char *symbol, bool mandatory) {
+ void *ptr = NULL;
+ int r = uv_dlsym(&cd->dl_handle, symbol, &ptr);
+ if (r != 0) {
+ const char *errmsg = uv_dlerror(&cd->dl_handle);
+ if (errmsg == NULL) {
+ errmsg = "returned function pointer is NULL";
+ }
+ if (mandatory) {
+ dlopen_log(ISC_LOG_ERROR,
+ "dlz_dlopen: library '%s' is missing "
+ "required symbol '%s': %s",
+ cd->dl_path, symbol, errmsg);
+ }
+ }
+
+ return (ptr);
+}
+
+static void
+dlopen_dlz_destroy(void *driverarg, void *dbdata);
+
+/*
+ * Called at startup for each dlopen zone in named.conf
+ */
+static isc_result_t
+dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
+ void *driverarg, void **dbdata) {
+ dlopen_data_t *cd;
+ isc_mem_t *mctx = NULL;
+ isc_result_t result = ISC_R_FAILURE;
+ int r;
+
+ UNUSED(driverarg);
+
+ if (argc < 2) {
+ dlopen_log(ISC_LOG_ERROR,
+ "dlz_dlopen driver for '%s' needs a path to "
+ "the shared library",
+ dlzname);
+ return (ISC_R_FAILURE);
+ }
+
+ isc_mem_create(&mctx);
+ cd = isc_mem_get(mctx, sizeof(*cd));
+ memset(cd, 0, sizeof(*cd));
+
+ cd->mctx = mctx;
+
+ cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]);
+ cd->dlzname = isc_mem_strdup(cd->mctx, dlzname);
+
+ /* Initialize the lock */
+ isc_mutex_init(&cd->lock);
+
+ r = uv_dlopen(cd->dl_path, &cd->dl_handle);
+ if (r != 0) {
+ const char *errmsg = uv_dlerror(&cd->dl_handle);
+ if (errmsg == NULL) {
+ errmsg = "unknown error";
+ }
+ dlopen_log(ISC_LOG_ERROR,
+ "dlz_dlopen failed to open library '%s': %s",
+ cd->dl_path, errmsg);
+ result = ISC_R_FAILURE;
+ goto failed;
+ }
+
+ /* Find the symbols */
+ cd->dlz_version =
+ (dlz_dlopen_version_t *)dl_load_symbol(cd, "dlz_version", true);
+ cd->dlz_create = (dlz_dlopen_create_t *)dl_load_symbol(cd, "dlz_create",
+ true);
+ cd->dlz_lookup = (dlz_dlopen_lookup_t *)dl_load_symbol(cd, "dlz_lookup",
+ true);
+ cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *)dl_load_symbol(
+ cd, "dlz_findzonedb", true);
+
+ if (cd->dlz_create == NULL || cd->dlz_version == NULL ||
+ cd->dlz_lookup == NULL || cd->dlz_findzonedb == NULL)
+ {
+ /* We're missing a required symbol */
+ result = ISC_R_FAILURE;
+ goto failed;
+ }
+
+ cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *)dl_load_symbol(
+ cd, "dlz_allowzonexfr", false);
+ cd->dlz_allnodes = (dlz_dlopen_allnodes_t *)dl_load_symbol(
+ cd, "dlz_allnodes", (cd->dlz_allowzonexfr != NULL));
+ cd->dlz_authority = (dlz_dlopen_authority_t *)dl_load_symbol(
+ cd, "dlz_authority", false);
+ cd->dlz_newversion = (dlz_dlopen_newversion_t *)dl_load_symbol(
+ cd, "dlz_newversion", false);
+ cd->dlz_closeversion = (dlz_dlopen_closeversion_t *)dl_load_symbol(
+ cd, "dlz_closeversion", (cd->dlz_newversion != NULL));
+ cd->dlz_configure = (dlz_dlopen_configure_t *)dl_load_symbol(
+ cd, "dlz_configure", false);
+ cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *)dl_load_symbol(
+ cd, "dlz_ssumatch", false);
+ cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *)dl_load_symbol(
+ cd, "dlz_addrdataset", false);
+ cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *)dl_load_symbol(
+ cd, "dlz_subrdataset", false);
+ cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *)dl_load_symbol(
+ cd, "dlz_delrdataset", false);
+ cd->dlz_destroy = (dlz_dlopen_destroy_t *)dl_load_symbol(
+ cd, "dlz_destroy", false);
+
+ /* Check the version of the API is the same */
+ cd->version = cd->dlz_version(&cd->flags);
+ if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) ||
+ cd->version > DLZ_DLOPEN_VERSION)
+ {
+ dlopen_log(ISC_LOG_ERROR,
+ "dlz_dlopen: %s: incorrect driver API version %d, "
+ "requires %d",
+ cd->dl_path, cd->version, DLZ_DLOPEN_VERSION);
+ result = ISC_R_FAILURE;
+ goto failed;
+ }
+
+ /*
+ * Call the library's create function. Note that this is an
+ * extended version of dlz create, with the addition of
+ * named function pointers for helper functions that the
+ * driver will need. This avoids the need for the backend to
+ * link the BIND9 libraries
+ */
+ MAYBE_LOCK(cd);
+ result = cd->dlz_create(dlzname, argc - 1, argv + 1, &cd->dbdata, "log",
+ dlopen_log, "putrr", dns_sdlz_putrr,
+ "putnamedrr", dns_sdlz_putnamedrr,
+ "writeable_zone", dns_dlz_writeablezone, NULL);
+ MAYBE_UNLOCK(cd);
+ if (result != ISC_R_SUCCESS) {
+ goto failed;
+ }
+
+ *dbdata = cd;
+
+ return (ISC_R_SUCCESS);
+
+failed:
+ dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname);
+
+ dlopen_dlz_destroy(NULL, cd);
+
+ return (result);
+}
+
+/*
+ * Called when bind is shutting down
+ */
+static void
+dlopen_dlz_destroy(void *driverarg, void *dbdata) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_destroy && cd->dbdata) {
+ MAYBE_LOCK(cd);
+ cd->dlz_destroy(cd->dbdata);
+ MAYBE_UNLOCK(cd);
+ }
+
+ uv_dlclose(&cd->dl_handle);
+ isc_mutex_destroy(&cd->lock);
+ isc_mem_free(cd->mctx, cd->dl_path);
+ isc_mem_free(cd->mctx, cd->dlzname);
+ isc_mem_putanddetach(&cd->mctx, cd, sizeof(*cd));
+}
+
+/*
+ * Called to start a transaction
+ */
+static isc_result_t
+dlopen_dlz_newversion(const char *zone, void *driverarg, void *dbdata,
+ void **versionp) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+ isc_result_t result;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_newversion == NULL) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ MAYBE_LOCK(cd);
+ result = cd->dlz_newversion(zone, cd->dbdata, versionp);
+ MAYBE_UNLOCK(cd);
+ return (result);
+}
+
+/*
+ * Called to end a transaction
+ */
+static void
+dlopen_dlz_closeversion(const char *zone, bool commit, void *driverarg,
+ void *dbdata, void **versionp) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_newversion == NULL) {
+ *versionp = NULL;
+ return;
+ }
+
+ MAYBE_LOCK(cd);
+ cd->dlz_closeversion(zone, commit, cd->dbdata, versionp);
+ MAYBE_UNLOCK(cd);
+}
+
+/*
+ * Called on startup to configure any writeable zones
+ */
+static isc_result_t
+dlopen_dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *driverarg,
+ void *dbdata) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+ isc_result_t result;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_configure == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ MAYBE_LOCK(cd);
+ cd->in_configure = true;
+ result = cd->dlz_configure(view, dlzdb, cd->dbdata);
+ cd->in_configure = false;
+ MAYBE_UNLOCK(cd);
+
+ return (result);
+}
+
+/*
+ * Check for authority to change a name.
+ */
+static bool
+dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
+ const char *type, const char *key, uint32_t keydatalen,
+ unsigned char *keydata, void *driverarg, void *dbdata) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+ bool ret;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_ssumatch == NULL) {
+ return (false);
+ }
+
+ MAYBE_LOCK(cd);
+ ret = cd->dlz_ssumatch(signer, name, tcpaddr, type, key, keydatalen,
+ keydata, cd->dbdata);
+ MAYBE_UNLOCK(cd);
+
+ return (ret);
+}
+
+/*
+ * Add an rdataset.
+ */
+static isc_result_t
+dlopen_dlz_addrdataset(const char *name, const char *rdatastr, void *driverarg,
+ void *dbdata, void *version) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+ isc_result_t result;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_addrdataset == NULL) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ MAYBE_LOCK(cd);
+ result = cd->dlz_addrdataset(name, rdatastr, cd->dbdata, version);
+ MAYBE_UNLOCK(cd);
+
+ return (result);
+}
+
+/*
+ * Subtract an rdataset.
+ */
+static isc_result_t
+dlopen_dlz_subrdataset(const char *name, const char *rdatastr, void *driverarg,
+ void *dbdata, void *version) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+ isc_result_t result;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_subrdataset == NULL) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ MAYBE_LOCK(cd);
+ result = cd->dlz_subrdataset(name, rdatastr, cd->dbdata, version);
+ MAYBE_UNLOCK(cd);
+
+ return (result);
+}
+
+/*
+ * Delete a rdataset.
+ */
+static isc_result_t
+dlopen_dlz_delrdataset(const char *name, const char *type, void *driverarg,
+ void *dbdata, void *version) {
+ dlopen_data_t *cd = (dlopen_data_t *)dbdata;
+ isc_result_t result;
+
+ UNUSED(driverarg);
+
+ if (cd->dlz_delrdataset == NULL) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ MAYBE_LOCK(cd);
+ result = cd->dlz_delrdataset(name, type, cd->dbdata, version);
+ MAYBE_UNLOCK(cd);
+
+ return (result);
+}
+
+static dns_sdlzmethods_t dlz_dlopen_methods = {
+ dlopen_dlz_create, dlopen_dlz_destroy, dlopen_dlz_findzonedb,
+ dlopen_dlz_lookup, dlopen_dlz_authority, dlopen_dlz_allnodes,
+ dlopen_dlz_allowzonexfr, dlopen_dlz_newversion, dlopen_dlz_closeversion,
+ dlopen_dlz_configure, dlopen_dlz_ssumatch, dlopen_dlz_addrdataset,
+ dlopen_dlz_subrdataset, dlopen_dlz_delrdataset
+};
+
+/*
+ * Register driver with BIND
+ */
+isc_result_t
+dlz_dlopen_init(isc_mem_t *mctx) {
+ isc_result_t result;
+
+ dlopen_log(2, "Registering DLZ_dlopen driver");
+
+ result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL,
+ DNS_SDLZFLAG_RELATIVEOWNER |
+ DNS_SDLZFLAG_RELATIVERDATA |
+ DNS_SDLZFLAG_THREADSAFE,
+ mctx, &dlz_dlopen);
+
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR("dns_sdlzregister() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ }
+
+ return (result);
+}
+
+/*
+ * Unregister the driver
+ */
+void
+dlz_dlopen_clear(void) {
+ dlopen_log(2, "Unregistering DLZ_dlopen driver");
+ if (dlz_dlopen != NULL) {
+ dns_sdlzunregister(&dlz_dlopen);
+ }
+}
diff --git a/bin/named/fuzz.c b/bin/named/fuzz.c
new file mode 100644
index 0000000..fb0d56f
--- /dev/null
+++ b/bin/named/fuzz.c
@@ -0,0 +1,782 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <named/fuzz.h>
+
+#ifdef ENABLE_AFL
+#include <arpa/inet.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/condition.h>
+#include <isc/mutex.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+
+#include <dns/log.h>
+
+#include <named/globals.h>
+#include <named/log.h>
+#include <named/server.h>
+
+/*
+ * We are using pthreads directly because we might be using it with
+ * unthreaded version of BIND, where all thread functions are
+ * mocks. Since AFL for now only works on Linux it's not a problem.
+ */
+static pthread_cond_t cond;
+static pthread_mutex_t mutex;
+static bool ready;
+
+/*
+ * In "client:" mode, this thread reads fuzzed query messages from AFL
+ * from standard input and sends it to named's listening port (DNS) that
+ * is passed in the -A client:<address>:<port> option. It can be used to
+ * test named from the client side.
+ */
+static void *
+fuzz_thread_client(void *arg) {
+ char *host;
+ char *port;
+ struct sockaddr_in servaddr;
+ int sockfd;
+ void *buf;
+
+ UNUSED(arg);
+
+ /*
+ * Parse named -A argument in the "address:port" syntax. Due to
+ * the syntax used, this only supports IPv4 addresses.
+ */
+ host = strdup(named_g_fuzz_addr);
+ RUNTIME_CHECK(host != NULL);
+
+ port = strchr(host, ':');
+ RUNTIME_CHECK(port != NULL);
+ *port = 0;
+ ++port;
+
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ RUNTIME_CHECK(inet_pton(AF_INET, host, &servaddr.sin_addr) == 1);
+ servaddr.sin_port = htons(atoi(port));
+
+ free(host);
+
+ /*
+ * Wait for named to start. This is set in run_server() in the
+ * named thread.
+ */
+ while (!named_g_run_done) {
+ usleep(10000);
+ }
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ RUNTIME_CHECK(sockfd != -1);
+
+ buf = malloc(65536);
+ RUNTIME_CHECK(buf != NULL);
+
+ /*
+ * Processing fuzzed packets 100,000 times before shutting down
+ * the app.
+ */
+#ifdef __AFL_LOOP
+ for (int loop = 0; loop < 100000; loop++) {
+#else /* ifdef __AFL_LOOP */
+ {
+#endif /* ifdef __AFL_LOOP */
+ ssize_t length;
+ ssize_t sent;
+
+ length = read(0, buf, 65536);
+ if (length <= 0) {
+ usleep(1000000);
+ goto next;
+ }
+
+ /*
+ * Ignore packets that are larger than 4096 bytes.
+ */
+ if (length > 4096) {
+ /*
+ * AFL_CMIN doesn't support persistent mode, so
+ * shutdown the server.
+ */
+ if (getenv("AFL_CMIN")) {
+ free(buf);
+ close(sockfd);
+ named_server_flushonshutdown(named_g_server,
+ false);
+ isc_app_shutdown();
+ return (NULL);
+ }
+ raise(SIGSTOP);
+ goto next;
+ }
+
+ RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
+
+ ready = false;
+
+ sent = sendto(sockfd, buf, length, 0,
+ (struct sockaddr *)&servaddr, sizeof(servaddr));
+ RUNTIME_CHECK(sent == length);
+
+ /*
+ * Read the reply message from named to unclog it. Don't
+ * bother if there isn't a reply.
+ */
+ (void)recvfrom(sockfd, buf, 65536, MSG_DONTWAIT, NULL, NULL);
+
+ while (!ready) {
+ pthread_cond_wait(&cond, &mutex);
+ }
+
+ RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
+ next:;
+ }
+
+ free(buf);
+ close(sockfd);
+
+ named_server_flushonshutdown(named_g_server, false);
+ isc_app_shutdown();
+
+ return (NULL);
+}
+
+/*
+ * In "resolver:" mode, this thread reads fuzzed reply messages from AFL
+ * from standard input. It also sets up a listener as a remote
+ * authoritative server and sends a driver query to the client side of
+ * named(resolver). When named(resolver) connects to this authoritative
+ * server, this thread writes the fuzzed reply message from AFL to it.
+ *
+ * -A resolver:<saddress>:<sport>:<raddress>:<rport>
+ *
+ * Here, <saddress>:<sport> is where named(resolver) is listening on.
+ * <raddress>:<rport> is where the thread is supposed to setup the
+ * authoritative server. This address should be configured via the root
+ * zone to be the authoritiative server for aaaaaaaaaa.example.
+ *
+ * named(resolver) when being fuzzed will not cache answers.
+ */
+static void *
+fuzz_thread_resolver(void *arg) {
+ char *sqtype, *shost, *sport, *rhost, *rport;
+ struct sockaddr_in servaddr, recaddr, recvaddr;
+ /*
+ * Query for aaaaaaaaaa.example./A in wire format with RD=1,
+ * EDNS and DO=1. 0x88, 0x0c at the start is the ID field which
+ * will be updated for each query.
+ */
+ char respacket[] = { 0x88, 0x0c, 0x01, 0x20, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x0a, 0x61, 0x61, 0x61,
+ 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x07,
+ 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x29, 0x10,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 };
+ /*
+ * Response for example./DNSKEY in wire format. Note that RRSIGs
+ * were generated with this DNSKEY that are used as seeds for
+ * AFL in the DNSSEC fuzzing job. So the DNSKEY content of this
+ * message must not change, or the corresponding RRSIGs will
+ * have to be updated. 0x8d, 0xf6 at the start is the ID field
+ * which will be made to match the query.
+ */
+ const uint8_t dnskey_wf[] = {
+ 0x8d, 0xf6, 0x84, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x01, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+ 0x00, 0x00, 0x30, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x30, 0x00,
+ 0x01, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x08, 0x01, 0x00, 0x03,
+ 0x08, 0x03, 0x01, 0x00, 0x01, 0xbd, 0x81, 0xdc, 0x7f, 0x16,
+ 0xd4, 0x81, 0x7c, 0x1f, 0x9f, 0x6a, 0x68, 0xdd, 0xd4, 0xda,
+ 0x48, 0xd9, 0x1c, 0xbd, 0xa6, 0x46, 0x1a, 0xf0, 0xb4, 0xb9,
+ 0xec, 0x3d, 0x6c, 0x0b, 0x57, 0xc7, 0xd6, 0x54, 0x66, 0xe6,
+ 0x6c, 0xd5, 0x90, 0x3a, 0x78, 0x7d, 0x7f, 0x78, 0x80, 0xa2,
+ 0x89, 0x61, 0x6d, 0x8a, 0x2b, 0xcd, 0x0a, 0x77, 0x7a, 0xad,
+ 0xc9, 0x61, 0x53, 0x53, 0x8c, 0x99, 0x72, 0x86, 0x14, 0x74,
+ 0x9c, 0x49, 0x2a, 0x47, 0x23, 0xf7, 0x02, 0x07, 0x73, 0x1c,
+ 0x5c, 0x2e, 0xb4, 0x9a, 0xa4, 0xd7, 0x98, 0x42, 0xc3, 0xd2,
+ 0xfe, 0xbf, 0xf3, 0xb3, 0x6a, 0x52, 0x92, 0xd5, 0xfa, 0x47,
+ 0x00, 0xe3, 0xd9, 0x59, 0x31, 0x95, 0x48, 0x40, 0xfc, 0x06,
+ 0x73, 0x90, 0xc6, 0x73, 0x96, 0xba, 0x29, 0x91, 0xe2, 0xac,
+ 0xa3, 0xa5, 0x6d, 0x91, 0x6d, 0x52, 0xb9, 0x34, 0xba, 0x68,
+ 0x4f, 0xad, 0xf0, 0xc3, 0xf3, 0x1d, 0x6d, 0x61, 0x76, 0xe5,
+ 0x3d, 0xa3, 0x9b, 0x2a, 0x0c, 0x92, 0xb3, 0x78, 0x6b, 0xf1,
+ 0x20, 0xd6, 0x90, 0xb7, 0xac, 0xe2, 0xf8, 0x2b, 0x94, 0x10,
+ 0x79, 0xce, 0xa8, 0x60, 0x42, 0xea, 0x6a, 0x18, 0x2f, 0xc0,
+ 0xd8, 0x05, 0x0a, 0x3b, 0x06, 0x0f, 0x02, 0x7e, 0xff, 0x33,
+ 0x46, 0xee, 0xb6, 0x21, 0x25, 0x90, 0x63, 0x4b, 0x3b, 0x5e,
+ 0xb2, 0x72, 0x3a, 0xcb, 0x91, 0x41, 0xf4, 0x20, 0x50, 0x78,
+ 0x1c, 0x93, 0x95, 0xda, 0xfa, 0xae, 0x85, 0xc5, 0xd7, 0x6b,
+ 0x92, 0x0c, 0x70, 0x6b, 0xe4, 0xb7, 0x29, 0x3a, 0x2e, 0x18,
+ 0x88, 0x82, 0x33, 0x7c, 0xa8, 0xea, 0xb8, 0x31, 0x8f, 0xaf,
+ 0x50, 0xc5, 0x9c, 0x08, 0x56, 0x8f, 0x09, 0x76, 0x4e, 0xdf,
+ 0x97, 0x75, 0x9d, 0x00, 0x52, 0x7f, 0xdb, 0xec, 0x30, 0xcb,
+ 0x1c, 0x4c, 0x2a, 0x21, 0x93, 0xc4, 0x6d, 0x85, 0xa9, 0x40,
+ 0x3b, 0xc0, 0x0c, 0x00, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x01,
+ 0x2c, 0x01, 0x1b, 0x00, 0x30, 0x08, 0x01, 0x00, 0x00, 0x01,
+ 0x2c, 0x67, 0x74, 0x85, 0x80, 0x58, 0xb3, 0xc5, 0x17, 0x36,
+ 0x90, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00,
+ 0x45, 0xac, 0xd3, 0x82, 0x69, 0xf3, 0x10, 0x3a, 0x97, 0x2c,
+ 0x6a, 0xa9, 0x78, 0x99, 0xea, 0xb0, 0xcc, 0xf7, 0xaf, 0x33,
+ 0x51, 0x5b, 0xdf, 0x77, 0x04, 0x18, 0x14, 0x99, 0x61, 0xeb,
+ 0x8d, 0x76, 0x3f, 0xd1, 0x71, 0x14, 0x43, 0x80, 0x53, 0xc2,
+ 0x3b, 0x9f, 0x09, 0x4f, 0xb3, 0x51, 0x04, 0x89, 0x0e, 0xc8,
+ 0x54, 0x12, 0xcd, 0x07, 0x20, 0xbe, 0x94, 0xc2, 0xda, 0x99,
+ 0xdd, 0x1e, 0xf8, 0xb0, 0x84, 0x2e, 0xf9, 0x19, 0x35, 0x36,
+ 0xf5, 0xd0, 0x5d, 0x82, 0x18, 0x74, 0xa0, 0x00, 0xb6, 0x15,
+ 0x57, 0x40, 0x5f, 0x78, 0x2d, 0x27, 0xac, 0xc7, 0x8a, 0x29,
+ 0x55, 0xa9, 0xcd, 0xbc, 0xf7, 0x3e, 0xff, 0xae, 0x1a, 0x5a,
+ 0x1d, 0xac, 0x0d, 0x78, 0x0e, 0x08, 0x33, 0x6c, 0x59, 0x70,
+ 0x40, 0xb9, 0x65, 0xbd, 0x35, 0xbb, 0x9a, 0x70, 0xdc, 0x93,
+ 0x66, 0xb0, 0xef, 0xfe, 0xf0, 0x32, 0xa6, 0xee, 0xb7, 0x03,
+ 0x89, 0xa2, 0x4d, 0xe0, 0xf1, 0x20, 0xdf, 0x39, 0xe8, 0xe3,
+ 0xcc, 0x95, 0xe9, 0x9a, 0xad, 0xbf, 0xbd, 0x7c, 0xf7, 0xd7,
+ 0xde, 0x47, 0x9e, 0xf6, 0x17, 0xbb, 0x84, 0xa9, 0xed, 0xf2,
+ 0x45, 0x61, 0x6d, 0x13, 0x0b, 0x06, 0x29, 0x50, 0xde, 0xfd,
+ 0x42, 0xb0, 0x66, 0x2c, 0x1c, 0x2b, 0x63, 0xcb, 0x4e, 0xb9,
+ 0x31, 0xc4, 0xea, 0xd2, 0x07, 0x3a, 0x08, 0x79, 0x19, 0x4b,
+ 0x4c, 0x50, 0x97, 0x02, 0xd7, 0x26, 0x41, 0x2f, 0xdd, 0x57,
+ 0xaa, 0xb0, 0xa0, 0x21, 0x4e, 0x74, 0xb6, 0x97, 0x4b, 0x8b,
+ 0x09, 0x9c, 0x3d, 0x29, 0xfb, 0x12, 0x27, 0x47, 0x8f, 0xb8,
+ 0xc5, 0x8e, 0x65, 0xcd, 0xca, 0x2f, 0xba, 0xf5, 0x3e, 0xec,
+ 0x56, 0xc3, 0xc9, 0xa1, 0x62, 0x7d, 0xf2, 0x9f, 0x90, 0x16,
+ 0x1d, 0xbf, 0x97, 0x28, 0xe1, 0x92, 0xb1, 0x53, 0xab, 0xc4,
+ 0xe0, 0x99, 0xbb, 0x19, 0x90, 0x7c, 0x00, 0x00, 0x29, 0x10,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00
+ };
+
+ int sockfd;
+ int listenfd;
+ int loop;
+ uint16_t qtype;
+ char *buf, *rbuf;
+ char *nameptr;
+ unsigned int i;
+ uint8_t llen;
+ uint64_t seed;
+
+ UNUSED(arg);
+
+ /*
+ * Parse named -A argument in the "qtype:saddress:sport:raddress:rport"
+ * syntax. Due to the syntax used, this only supports IPv4 addresses.
+ */
+ sqtype = strdup(named_g_fuzz_addr);
+ RUNTIME_CHECK(sqtype != NULL);
+
+ shost = strchr(sqtype, ':');
+ RUNTIME_CHECK(shost != NULL);
+ *shost = 0;
+ shost++;
+
+ sport = strchr(shost, ':');
+ RUNTIME_CHECK(sport != NULL);
+ *sport = 0;
+ sport++;
+
+ rhost = strchr(sport, ':');
+ RUNTIME_CHECK(rhost != NULL);
+ *rhost = 0;
+ rhost++;
+
+ rport = strchr(rhost, ':');
+ RUNTIME_CHECK(rport != NULL);
+ *rport = 0;
+ rport++;
+
+ /*
+ * Patch in the qtype into the question section of respacket.
+ */
+ qtype = atoi(sqtype);
+ respacket[32] = (qtype >> 8) & 0xff;
+ respacket[33] = qtype & 0xff;
+
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ RUNTIME_CHECK(inet_pton(AF_INET, shost, &servaddr.sin_addr) == 1);
+ servaddr.sin_port = htons(atoi(sport));
+
+ memset(&recaddr, 0, sizeof(recaddr));
+ recaddr.sin_family = AF_INET;
+ RUNTIME_CHECK(inet_pton(AF_INET, rhost, &recaddr.sin_addr) == 1);
+ recaddr.sin_port = htons(atoi(rport));
+
+ free(sqtype);
+
+ /*
+ * Wait for named to start. This is set in run_server() in the
+ * named thread.
+ */
+ while (!named_g_run_done) {
+ usleep(10000);
+ }
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ RUNTIME_CHECK(sockfd != -1);
+
+ listenfd = socket(AF_INET, SOCK_DGRAM, 0);
+ RUNTIME_CHECK(listenfd != -1);
+
+ RUNTIME_CHECK(bind(listenfd, (struct sockaddr *)&recaddr,
+ sizeof(struct sockaddr_in)) == 0);
+
+ buf = malloc(65536);
+ rbuf = malloc(65536);
+ RUNTIME_CHECK(buf != NULL);
+ RUNTIME_CHECK(rbuf != NULL);
+
+ seed = 42;
+
+ /*
+ * Processing fuzzed packets 100,000 times before shutting down
+ * the app.
+ */
+ for (loop = 0; loop < 100000; loop++) {
+ ssize_t length;
+ ssize_t sent;
+ unsigned short id;
+ socklen_t socklen;
+
+ memset(buf, 0, 12);
+ length = read(0, buf, 65536);
+ if (length <= 0) {
+ usleep(1000000);
+ continue;
+ }
+
+ if (length > 4096) {
+ if (getenv("AFL_CMIN")) {
+ free(buf);
+ free(rbuf);
+ close(sockfd);
+ close(listenfd);
+ named_server_flushonshutdown(named_g_server,
+ false);
+ isc_app_shutdown();
+ return (NULL);
+ }
+ raise(SIGSTOP);
+ continue;
+ }
+
+ if (length < 12) {
+ length = 12;
+ }
+
+ RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
+
+ ready = false;
+
+ /* Use a unique query ID. */
+ seed = 1664525 * seed + 1013904223;
+ id = seed & 0xffff;
+ respacket[0] = (id >> 8) & 0xff;
+ respacket[1] = id & 0xff;
+
+ /*
+ * Flush any pending data on the authoritative server.
+ */
+ socklen = sizeof(recvaddr);
+ (void)recvfrom(listenfd, rbuf, 65536, MSG_DONTWAIT,
+ (struct sockaddr *)&recvaddr, &socklen);
+
+ /*
+ * Send a fixed client query to named(resolver) of
+ * aaaaaaaaaa.example./A. This is the starting query
+ * driver.
+ */
+ sent = sendto(sockfd, respacket, sizeof(respacket), 0,
+ (struct sockaddr *)&servaddr, sizeof(servaddr));
+ RUNTIME_CHECK(sent == sizeof(respacket));
+
+ /*
+ * named(resolver) will process the query above and send
+ * an upstream query to the authoritative server. We
+ * handle that here as the upstream authoritative server
+ * on listenfd.
+ */
+ socklen = sizeof(recvaddr);
+ sent = recvfrom(listenfd, rbuf, 65536, 0,
+ (struct sockaddr *)&recvaddr, &socklen);
+ RUNTIME_CHECK(sent > 0);
+
+ /*
+ * Copy QID and set QR so that response is always
+ * accepted by named(resolver).
+ */
+ buf[0] = rbuf[0];
+ buf[1] = rbuf[1];
+ buf[2] |= 0x80;
+
+ /*
+ * NOTE: We are not copying the QNAME or setting
+ * rcode=NOERROR each time. So the resolver may fail the
+ * client query (driver) / wander due to this. AA flag
+ * may also not be set based on the contents of the AFL
+ * fuzzed packet.
+ */
+
+ /*
+ * A hack - set QTYPE to the one from query so that we
+ * can easily share packets between instances. If we
+ * write over something else we'll get FORMERR anyway.
+ */
+
+ /* Skip DNS header to get to the name */
+ nameptr = buf + 12;
+
+ /* Skip the name to get to the qtype */
+ i = 0;
+ while (((llen = nameptr[i]) != 0) && (i < 255) &&
+ (((nameptr + i + 1 + llen) - buf) < length))
+ {
+ i += 1 + llen;
+ }
+
+ if (i <= 255) {
+ nameptr += 1 + i;
+ /* Patch the qtype */
+ if ((nameptr - buf) < (length - 2)) {
+ *nameptr++ = (qtype >> 8) & 0xff;
+ *nameptr++ = qtype & 0xff;
+ }
+ /* Patch the qclass */
+ if ((nameptr - buf) < (length - 2)) {
+ *nameptr++ = 0;
+ *nameptr++ = 1;
+ }
+ }
+
+ /*
+ * Send the reply to named(resolver).
+ */
+ sent = sendto(listenfd, buf, length, 0,
+ (struct sockaddr *)&recvaddr, sizeof(recvaddr));
+ RUNTIME_CHECK(sent == length);
+
+ /* We might get additional questions here (e.g. for CNAME). */
+ for (;;) {
+ fd_set fds;
+ struct timeval tv;
+ int rv;
+ int max;
+
+ FD_ZERO(&fds);
+ FD_SET(listenfd, &fds);
+ FD_SET(sockfd, &fds);
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+ max = (listenfd > sockfd ? listenfd : sockfd) + 1;
+
+ rv = select(max, &fds, NULL, NULL, &tv);
+ RUNTIME_CHECK(rv > 0);
+
+ if (FD_ISSET(sockfd, &fds)) {
+ /*
+ * It's the reply from named(resolver)
+ * to the client(query driver), so we're
+ * done.
+ */
+ (void)recvfrom(sockfd, buf, 65536, 0, NULL,
+ NULL);
+ break;
+ }
+
+ /*
+ * We've got additional question (eg. due to
+ * CNAME). Bounce it - setting QR flag and
+ * NOERROR rcode and sending it back.
+ */
+ length = recvfrom(listenfd, buf, 65536, 0,
+ (struct sockaddr *)&recvaddr,
+ &socklen);
+
+ /*
+ * If this is a DNSKEY query, send the DNSKEY,
+ * otherwise, bounce the query.
+ */
+
+ /* Skip DNS header to get to the name */
+ nameptr = buf + 12;
+
+ /* Skip the name to get to the qtype */
+ i = 0;
+ while (((llen = nameptr[i]) != 0) && (i < 255) &&
+ (((nameptr + i + 1 + llen) - buf) < length))
+ {
+ i += 1 + llen;
+ }
+
+ if (i <= 255) {
+ nameptr += 1 + i;
+ /*
+ * Patch in the DNSKEY reply without
+ * touching the ID field. Note that we
+ * don't compare the name in the
+ * question section in the query, but we
+ * don't expect to receive any query for
+ * type DNSKEY but for the name
+ * "example."
+ */
+ if ((nameptr - buf) < (length - 2)) {
+ uint8_t hb, lb;
+ hb = *nameptr++;
+ lb = *nameptr++;
+ qtype = (hb << 8) | lb;
+
+ if (qtype == 48) {
+ memmove(buf + 2, dnskey_wf + 2,
+ sizeof(dnskey_wf) - 2);
+ length = sizeof(dnskey_wf);
+ }
+ }
+ }
+
+ buf[2] |= 0x80;
+ buf[3] &= 0xF0;
+ sent = sendto(listenfd, buf, length, 0,
+ (struct sockaddr *)&recvaddr,
+ sizeof(recvaddr));
+ RUNTIME_CHECK(sent == length);
+ }
+
+ while (!ready) {
+ pthread_cond_wait(&cond, &mutex);
+ }
+
+ RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
+ }
+
+ free(buf);
+ free(rbuf);
+ close(sockfd);
+ close(listenfd);
+ named_server_flushonshutdown(named_g_server, false);
+ isc_app_shutdown();
+
+#ifdef __AFL_LOOP
+ /*
+ * This is here just for the signature, that's how AFL detects
+ * if it's a 'persistent mode' binary. It has to occur somewhere
+ * in the file, that's all. < wpk_> AFL checks the binary for
+ * this signature ("##SIG_AFL_PERSISTENT##") and runs the binary
+ * in persistent mode if it's present.
+ */
+ __AFL_LOOP(0);
+#endif /* ifdef __AFL_LOOP */
+
+ return (NULL);
+}
+
+/*
+ * In "tcp:", "http:" and "rndc:" modes, this thread reads fuzzed query
+ * blobs from AFL from standard input and sends it to the corresponding
+ * TCP listening port of named (port 53 DNS, or the HTTP statistics
+ * channels listener or the rndc port) that is passed in the -A
+ * <mode>:<address>:<port> option. It can be used to test named from the
+ * client side.
+ */
+static void *
+fuzz_thread_tcp(void *arg) {
+ char *host;
+ char *port;
+ struct sockaddr_in servaddr;
+ int sockfd;
+ char *buf;
+ int loop;
+
+ UNUSED(arg);
+
+ /*
+ * Parse named -A argument in the "address:port" syntax. Due to
+ * the syntax used, this only supports IPv4 addresses.
+ */
+ host = strdup(named_g_fuzz_addr);
+ RUNTIME_CHECK(host != NULL);
+
+ port = strchr(host, ':');
+ RUNTIME_CHECK(port != NULL);
+ *port = 0;
+ ++port;
+
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ RUNTIME_CHECK(inet_pton(AF_INET, host, &servaddr.sin_addr) == 1);
+ servaddr.sin_port = htons(atoi(port));
+
+ free(host);
+
+ /*
+ * Wait for named to start. This is set in run_server() in the
+ * named thread.
+ */
+ while (!named_g_run_done) {
+ usleep(10000);
+ }
+
+ buf = malloc(65539);
+ RUNTIME_CHECK(buf != NULL);
+
+ /*
+ * Processing fuzzed packets 100,000 times before shutting down
+ * the app.
+ */
+ for (loop = 0; loop < 100000; loop++) {
+ ssize_t length;
+ ssize_t sent;
+ int yes;
+ int r;
+
+ if (named_g_fuzz_type == isc_fuzz_tcpclient) {
+ /*
+ * To fuzz DNS TCP client we have to put 16-bit
+ * message length preceding the start of packet.
+ */
+ length = read(0, buf + 2, 65535);
+ buf[0] = (length >> 8) & 0xff;
+ buf[1] = length & 0xff;
+ length += 2;
+ } else {
+ /*
+ * Other types of TCP clients such as HTTP, etc.
+ */
+ length = read(0, buf, 65535);
+ }
+ if (length <= 0) {
+ usleep(1000000);
+ continue;
+ }
+ if (named_g_fuzz_type == isc_fuzz_http) {
+ /*
+ * This guarantees that the request will be
+ * processed.
+ */
+ INSIST(length <= 65535);
+ buf[length++] = '\r';
+ buf[length++] = '\n';
+ buf[length++] = '\r';
+ buf[length++] = '\n';
+ }
+
+ RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
+
+ ready = false;
+ yes = 1;
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ RUNTIME_CHECK(sockfd != -1);
+ RUNTIME_CHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
+ sizeof(int)) == 0);
+
+ do {
+ r = connect(sockfd, (struct sockaddr *)&servaddr,
+ sizeof(servaddr));
+ if (r != 0) {
+ usleep(10000);
+ }
+ } while (r != 0);
+
+ /*
+ * Send the fuzzed query blob to the target server.
+ */
+ sent = write(sockfd, buf, length);
+ RUNTIME_CHECK(sent == length);
+
+ close(sockfd);
+
+ while (!ready) {
+ pthread_cond_wait(&cond, &mutex);
+ }
+
+ RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
+ }
+
+ free(buf);
+ close(sockfd);
+ named_server_flushonshutdown(named_g_server, false);
+ isc_app_shutdown();
+
+ return (NULL);
+}
+
+#endif /* ENABLE_AFL */
+
+/*
+ * named has finished processing a message and has sent the
+ * reply. Signal the fuzz thread using the condition variable, to read
+ * and process the next item from AFL.
+ */
+void
+named_fuzz_notify(void) {
+#ifdef ENABLE_AFL
+ if (getenv("AFL_CMIN")) {
+ named_server_flushonshutdown(named_g_server, false);
+ isc_app_shutdown();
+ return;
+ }
+
+ raise(SIGSTOP);
+
+ RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
+
+ ready = true;
+
+ RUNTIME_CHECK(pthread_cond_signal(&cond) == 0);
+ RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
+#endif /* ENABLE_AFL */
+}
+
+void
+named_fuzz_setup(void) {
+#ifdef ENABLE_AFL
+ if (getenv("__AFL_PERSISTENT") || getenv("AFL_CMIN")) {
+ pthread_t thread;
+ void *(fn) = NULL;
+
+ switch (named_g_fuzz_type) {
+ case isc_fuzz_client:
+ fn = fuzz_thread_client;
+ break;
+
+ case isc_fuzz_http:
+ case isc_fuzz_tcpclient:
+ case isc_fuzz_rndc:
+ fn = fuzz_thread_tcp;
+ break;
+
+ case isc_fuzz_resolver:
+ fn = fuzz_thread_resolver;
+ break;
+
+ default:
+ RUNTIME_CHECK(fn != NULL);
+ }
+
+ RUNTIME_CHECK(pthread_mutex_init(&mutex, NULL) == 0);
+ RUNTIME_CHECK(pthread_cond_init(&cond, NULL) == 0);
+ RUNTIME_CHECK(pthread_create(&thread, NULL, fn, NULL) == 0);
+ }
+#endif /* ENABLE_AFL */
+}
diff --git a/bin/named/geoip.c b/bin/named/geoip.c
new file mode 100644
index 0000000..0ba4ef0
--- /dev/null
+++ b/bin/named/geoip.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#if defined(HAVE_GEOIP2)
+#include <maxminddb.h>
+#endif /* if defined(HAVE_GEOIP2) */
+
+#include <isc/dir.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/geoip.h>
+
+#include <named/geoip.h>
+#include <named/log.h>
+
+static dns_geoip_databases_t geoip_table;
+
+#if defined(HAVE_GEOIP2)
+static MMDB_s geoip_country, geoip_city, geoip_as, geoip_isp, geoip_domain;
+
+static MMDB_s *
+open_geoip2(const char *dir, const char *dbfile, MMDB_s *mmdb) {
+ char pathbuf[PATH_MAX];
+ unsigned int n;
+ int ret;
+
+ n = snprintf(pathbuf, sizeof(pathbuf), "%s/%s", dir, dbfile);
+ if (n >= sizeof(pathbuf)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "GeoIP2 database '%s/%s': path too long", dir,
+ dbfile);
+ return (NULL);
+ }
+
+ ret = MMDB_open(pathbuf, MMDB_MODE_MMAP, mmdb);
+ if (ret == MMDB_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "opened GeoIP2 database '%s'", pathbuf);
+ return (mmdb);
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
+ "unable to open GeoIP2 database '%s' (status %d)",
+ pathbuf, ret);
+
+ return (NULL);
+}
+#endif /* HAVE_GEOIP2 */
+
+void
+named_geoip_init(void) {
+#if defined(HAVE_GEOIP2)
+ if (named_g_geoip == NULL) {
+ named_g_geoip = &geoip_table;
+ }
+#else /* if defined(HAVE_GEOIP2) */
+ return;
+#endif /* if defined(HAVE_GEOIP2) */
+}
+
+void
+named_geoip_load(char *dir) {
+#if defined(HAVE_GEOIP2)
+ REQUIRE(dir != NULL);
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "looking for GeoIP2 databases in '%s'", dir);
+
+ named_g_geoip->country = open_geoip2(dir, "GeoIP2-Country.mmdb",
+ &geoip_country);
+ if (named_g_geoip->country == NULL) {
+ named_g_geoip->country = open_geoip2(
+ dir, "GeoLite2-Country.mmdb", &geoip_country);
+ }
+
+ named_g_geoip->city = open_geoip2(dir, "GeoIP2-City.mmdb", &geoip_city);
+ if (named_g_geoip->city == NULL) {
+ named_g_geoip->city = open_geoip2(dir, "GeoLite2-City.mmdb",
+ &geoip_city);
+ }
+
+ named_g_geoip->as = open_geoip2(dir, "GeoIP2-ASN.mmdb", &geoip_as);
+ if (named_g_geoip->as == NULL) {
+ named_g_geoip->as = open_geoip2(dir, "GeoLite2-ASN.mmdb",
+ &geoip_as);
+ }
+
+ named_g_geoip->isp = open_geoip2(dir, "GeoIP2-ISP.mmdb", &geoip_isp);
+ named_g_geoip->domain = open_geoip2(dir, "GeoIP2-Domain.mmdb",
+ &geoip_domain);
+#else /* if defined(HAVE_GEOIP2) */
+ UNUSED(dir);
+
+ return;
+#endif /* if defined(HAVE_GEOIP2) */
+}
+
+void
+named_geoip_unload(void) {
+#ifdef HAVE_GEOIP2
+ if (named_g_geoip->country != NULL) {
+ MMDB_close(named_g_geoip->country);
+ named_g_geoip->country = NULL;
+ }
+ if (named_g_geoip->city != NULL) {
+ MMDB_close(named_g_geoip->city);
+ named_g_geoip->city = NULL;
+ }
+ if (named_g_geoip->as != NULL) {
+ MMDB_close(named_g_geoip->as);
+ named_g_geoip->as = NULL;
+ }
+ if (named_g_geoip->isp != NULL) {
+ MMDB_close(named_g_geoip->isp);
+ named_g_geoip->isp = NULL;
+ }
+ if (named_g_geoip->domain != NULL) {
+ MMDB_close(named_g_geoip->domain);
+ named_g_geoip->domain = NULL;
+ }
+#endif /* ifdef HAVE_GEOIP2 */
+}
+
+void
+named_geoip_shutdown(void) {
+#ifdef HAVE_GEOIP2
+ named_geoip_unload();
+#endif /* HAVE_GEOIP2 */
+}
diff --git a/bin/named/include/dlz/dlz_dlopen_driver.h b/bin/named/include/dlz/dlz_dlopen_driver.h
new file mode 100644
index 0000000..64d6388
--- /dev/null
+++ b/bin/named/include/dlz/dlz_dlopen_driver.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+isc_result_t
+dlz_dlopen_init(isc_mem_t *mctx);
+
+void
+dlz_dlopen_clear(void);
diff --git a/bin/named/include/named/builtin.h b/bin/named/include/named/builtin.h
new file mode 100644
index 0000000..fbfc599
--- /dev/null
+++ b/bin/named/include/named/builtin.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <isc/types.h>
+
+isc_result_t
+named_builtin_init(void);
+
+void
+named_builtin_deinit(void);
diff --git a/bin/named/include/named/config.h b/bin/named/include/named/config.h
new file mode 100644
index 0000000..d9c5aa3
--- /dev/null
+++ b/bin/named/include/named/config.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <inttypes.h>
+
+#include <dns/types.h>
+#include <dns/zone.h>
+
+#include <isccfg/cfg.h>
+
+#define DEFAULT_IANA_ROOT_ZONE_PRIMARIES "_default_iana_root_zone_primaries"
+
+isc_result_t
+named_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf);
+
+const char *
+named_config_getdefault(void);
+
+isc_result_t
+named_config_get(cfg_obj_t const *const *maps, const char *name,
+ const cfg_obj_t **obj);
+
+isc_result_t
+named_checknames_get(const cfg_obj_t **maps, const char *const names[],
+ const cfg_obj_t **obj);
+
+int
+named_config_listcount(const cfg_obj_t *list);
+
+isc_result_t
+named_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass,
+ dns_rdataclass_t *classp);
+
+isc_result_t
+named_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype,
+ dns_rdatatype_t *typep);
+
+dns_zonetype_t
+named_config_getzonetype(const cfg_obj_t *zonetypeobj);
+
+isc_result_t
+named_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
+ in_port_t defport, isc_mem_t *mctx,
+ isc_sockaddr_t **addrsp, uint32_t *countp);
+
+void
+named_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
+ uint32_t count);
+
+isc_result_t
+named_config_getremotesdef(const cfg_obj_t *cctx, const char *list,
+ const char *name, const cfg_obj_t **ret);
+
+isc_result_t
+named_config_getipandkeylist(const cfg_obj_t *config, const char *listtype,
+ const cfg_obj_t *list, isc_mem_t *mctx,
+ dns_ipkeylist_t *ipkl);
+
+isc_result_t
+named_config_getport(const cfg_obj_t *config, const char *type,
+ in_port_t *portp);
+
+isc_result_t
+named_config_getkeyalgorithm(const char *str, const dns_name_t **name,
+ uint16_t *digestbits);
+isc_result_t
+named_config_getkeyalgorithm2(const char *str, const dns_name_t **name,
+ unsigned int *typep, uint16_t *digestbits);
diff --git a/bin/named/include/named/control.h b/bin/named/include/named/control.h
new file mode 100644
index 0000000..29b5677
--- /dev/null
+++ b/bin/named/include/named/control.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file
+ * \brief
+ * The name server command channel.
+ */
+
+#include <stdbool.h>
+
+#include <isccfg/aclconf.h>
+
+#include <isccc/types.h>
+#include <named/types.h>
+
+#define NAMED_CONTROL_PORT 953
+
+#define NAMED_COMMAND_STOP "stop"
+#define NAMED_COMMAND_HALT "halt"
+#define NAMED_COMMAND_RELOAD "reload"
+#define NAMED_COMMAND_RECONFIG "reconfig"
+#define NAMED_COMMAND_REFRESH "refresh"
+#define NAMED_COMMAND_RETRANSFER "retransfer"
+#define NAMED_COMMAND_DUMPSTATS "stats"
+#define NAMED_COMMAND_QUERYLOG "querylog"
+#define NAMED_COMMAND_DUMPDB "dumpdb"
+#define NAMED_COMMAND_SECROOTS "secroots"
+#define NAMED_COMMAND_TRACE "trace"
+#define NAMED_COMMAND_NOTRACE "notrace"
+#define NAMED_COMMAND_FLUSH "flush"
+#define NAMED_COMMAND_FLUSHNAME "flushname"
+#define NAMED_COMMAND_FLUSHTREE "flushtree"
+#define NAMED_COMMAND_STATUS "status"
+#define NAMED_COMMAND_TSIGLIST "tsig-list"
+#define NAMED_COMMAND_TSIGDELETE "tsig-delete"
+#define NAMED_COMMAND_FREEZE "freeze"
+#define NAMED_COMMAND_UNFREEZE "unfreeze"
+#define NAMED_COMMAND_THAW "thaw"
+#define NAMED_COMMAND_TIMERPOKE "timerpoke"
+#define NAMED_COMMAND_RECURSING "recursing"
+#define NAMED_COMMAND_NULL "null"
+#define NAMED_COMMAND_NOTIFY "notify"
+#define NAMED_COMMAND_VALIDATION "validation"
+#define NAMED_COMMAND_SCAN "scan"
+#define NAMED_COMMAND_SIGN "sign"
+#define NAMED_COMMAND_LOADKEYS "loadkeys"
+#define NAMED_COMMAND_ADDZONE "addzone"
+#define NAMED_COMMAND_MODZONE "modzone"
+#define NAMED_COMMAND_DELZONE "delzone"
+#define NAMED_COMMAND_SHOWZONE "showzone"
+#define NAMED_COMMAND_SYNC "sync"
+#define NAMED_COMMAND_SIGNING "signing"
+#define NAMED_COMMAND_DNSSEC "dnssec"
+#define NAMED_COMMAND_ZONESTATUS "zonestatus"
+#define NAMED_COMMAND_NTA "nta"
+#define NAMED_COMMAND_TESTGEN "testgen"
+#define NAMED_COMMAND_MKEYS "managed-keys"
+#define NAMED_COMMAND_DNSTAPREOPEN "dnstap-reopen"
+#define NAMED_COMMAND_DNSTAP "dnstap"
+#define NAMED_COMMAND_TCPTIMEOUTS "tcp-timeouts"
+#define NAMED_COMMAND_SERVESTALE "serve-stale"
+
+isc_result_t
+named_controls_create(named_server_t *server, named_controls_t **ctrlsp);
+/*%<
+ * Create an initial, empty set of command channels for 'server'.
+ */
+
+void
+named_controls_destroy(named_controls_t **ctrlsp);
+/*%<
+ * Destroy a set of command channels.
+ *
+ * Requires:
+ * Shutdown of the channels has completed.
+ */
+
+isc_result_t
+named_controls_configure(named_controls_t *controls, const cfg_obj_t *config,
+ cfg_aclconfctx_t *aclconfctx);
+/*%<
+ * Configure zero or more command channels into 'controls'
+ * as defined in the configuration parse tree 'config'.
+ * The channels will evaluate ACLs in the context of
+ * 'aclconfctx'.
+ */
+
+void
+named_controls_shutdown(named_controls_t *controls);
+/*%<
+ * Initiate shutdown of all the command channels in 'controls'.
+ */
+
+isc_result_t
+named_control_docommand(isccc_sexpr_t *message, bool readonly,
+ isc_buffer_t **text);
diff --git a/bin/named/include/named/fuzz.h b/bin/named/include/named/fuzz.h
new file mode 100644
index 0000000..69af8da
--- /dev/null
+++ b/bin/named/include/named/fuzz.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <isc/fuzz.h>
+
+#pragma once
+
+void
+named_fuzz_notify(void);
+
+void
+named_fuzz_setup(void);
diff --git a/bin/named/include/named/geoip.h b/bin/named/include/named/geoip.h
new file mode 100644
index 0000000..d1852ef
--- /dev/null
+++ b/bin/named/include/named/geoip.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+extern dns_geoip_databases_t *named_g_geoip;
+
+void
+named_geoip_init(void);
+
+void
+named_geoip_load(char *dir);
+
+void
+named_geoip_unload(void);
+
+void
+named_geoip_shutdown(void);
diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h
new file mode 100644
index 0000000..c65e933
--- /dev/null
+++ b/bin/named/include/named/globals.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <stdbool.h>
+
+#include <isc/log.h>
+#include <isc/net.h>
+#include <isc/netmgr.h>
+#include <isc/rwlock.h>
+
+#include <dns/acl.h>
+#include <dns/zone.h>
+
+#include <isccfg/aclconf.h>
+#include <isccfg/cfg.h>
+
+#include <dst/dst.h>
+#include <named/fuzz.h>
+#include <named/types.h>
+
+#undef EXTERN
+#undef INIT
+#ifdef NAMED_MAIN
+#define EXTERN
+#define INIT(v) = (v)
+#else /* ifdef NAMED_MAIN */
+#define EXTERN extern
+#define INIT(v)
+#endif /* ifdef NAMED_MAIN */
+
+#ifndef NAMED_RUN_PID_DIR
+#define NAMED_RUN_PID_DIR 1
+#endif /* ifndef NAMED_RUN_PID_DIR */
+
+EXTERN isc_mem_t *named_g_mctx INIT(NULL);
+EXTERN unsigned int named_g_cpus INIT(0);
+EXTERN unsigned int named_g_udpdisp INIT(0);
+EXTERN isc_taskmgr_t *named_g_taskmgr INIT(NULL);
+EXTERN dns_dispatchmgr_t *named_g_dispatchmgr INIT(NULL);
+EXTERN unsigned int named_g_cpus_detected INIT(1);
+
+#ifdef ENABLE_AFL
+EXTERN bool named_g_run_done INIT(false);
+#endif /* ifdef ENABLE_AFL */
+/*
+ * XXXRTH We're going to want multiple timer managers eventually. One
+ * for really short timers, another for client timers, and one
+ * for zone timers.
+ */
+EXTERN isc_timermgr_t *named_g_timermgr INIT(NULL);
+EXTERN isc_nm_t *named_g_netmgr INIT(NULL);
+EXTERN cfg_parser_t *named_g_parser INIT(NULL);
+EXTERN cfg_parser_t *named_g_addparser INIT(NULL);
+EXTERN const char *named_g_version INIT(PACKAGE_VERSION);
+EXTERN const char *named_g_product INIT(PACKAGE_NAME);
+EXTERN const char *named_g_description INIT(PACKAGE_DESCRIPTION);
+EXTERN const char *named_g_srcid INIT(PACKAGE_SRCID);
+EXTERN const char *named_g_configargs INIT(PACKAGE_CONFIGARGS);
+EXTERN const char *named_g_builder INIT(PACKAGE_BUILDER);
+EXTERN in_port_t named_g_port INIT(0);
+EXTERN in_port_t named_g_tlsport INIT(0);
+EXTERN in_port_t named_g_httpsport INIT(0);
+EXTERN in_port_t named_g_httpport INIT(0);
+
+EXTERN in_port_t named_g_http_listener_clients INIT(0);
+EXTERN in_port_t named_g_http_streams_per_conn INIT(0);
+
+EXTERN named_server_t *named_g_server INIT(NULL);
+
+/*
+ * Logging.
+ */
+EXTERN isc_log_t *named_g_lctx INIT(NULL);
+EXTERN isc_logcategory_t *named_g_categories INIT(NULL);
+EXTERN isc_logmodule_t *named_g_modules INIT(NULL);
+EXTERN unsigned int named_g_debuglevel INIT(0);
+
+/*
+ * Current configuration information.
+ */
+EXTERN cfg_obj_t *named_g_config INIT(NULL);
+EXTERN const cfg_obj_t *named_g_defaults INIT(NULL);
+EXTERN const char *named_g_conffile INIT(NAMED_SYSCONFDIR "/named.conf");
+EXTERN const char *named_g_defaultbindkeys INIT(NAMED_SYSCONFDIR "/bind.keys");
+EXTERN const char *named_g_keyfile INIT(NAMED_SYSCONFDIR "/rndc.key");
+
+EXTERN dns_tsigkey_t *named_g_sessionkey INIT(NULL);
+EXTERN dns_name_t named_g_sessionkeyname;
+EXTERN bool named_g_conffileset INIT(false);
+EXTERN cfg_aclconfctx_t *named_g_aclconfctx INIT(NULL);
+
+/*
+ * Initial resource limits.
+ */
+EXTERN isc_resourcevalue_t named_g_initstacksize INIT(0);
+EXTERN isc_resourcevalue_t named_g_initdatasize INIT(0);
+EXTERN isc_resourcevalue_t named_g_initcoresize INIT(0);
+EXTERN isc_resourcevalue_t named_g_initopenfiles INIT(0);
+
+/*
+ * Misc.
+ */
+EXTERN bool named_g_coreok INIT(true);
+EXTERN const char *named_g_chrootdir INIT(NULL);
+EXTERN bool named_g_foreground INIT(false);
+EXTERN bool named_g_logstderr INIT(false);
+EXTERN bool named_g_nosyslog INIT(false);
+EXTERN const char *named_g_logfile INIT(NULL);
+
+EXTERN const char *named_g_defaultsessionkeyfile INIT(NAMED_LOCALSTATEDIR
+ "/run/named/"
+ "session.key");
+EXTERN const char *named_g_defaultlockfile INIT(NAMED_LOCALSTATEDIR "/run/"
+ "named/"
+ "named."
+ "lock");
+EXTERN bool named_g_forcelock INIT(false);
+
+#if NAMED_RUN_PID_DIR
+EXTERN const char *named_g_defaultpidfile INIT(NAMED_LOCALSTATEDIR "/run/named/"
+ "named.pid");
+#else /* if NAMED_RUN_PID_DIR */
+EXTERN const char *named_g_defaultpidfile INIT(NAMED_LOCALSTATEDIR "/run/"
+ "named.pid");
+#endif /* if NAMED_RUN_PID_DIR */
+
+EXTERN const char *named_g_username INIT(NULL);
+
+EXTERN const char *named_g_engine INIT(NULL);
+
+EXTERN isc_time_t named_g_boottime;
+EXTERN isc_time_t named_g_configtime;
+EXTERN bool named_g_memstatistics INIT(false);
+EXTERN bool named_g_keepstderr INIT(false);
+
+EXTERN unsigned int named_g_tat_interval INIT(24 * 3600);
+EXTERN unsigned int named_g_maxcachesize INIT(0);
+
+#if defined(HAVE_GEOIP2)
+EXTERN dns_geoip_databases_t *named_g_geoip INIT(NULL);
+#endif /* if defined(HAVE_GEOIP2) */
+
+EXTERN const char *named_g_fuzz_addr INIT(NULL);
+EXTERN isc_fuzztype_t named_g_fuzz_type INIT(isc_fuzz_none);
+
+EXTERN dns_acl_t *named_g_mapped INIT(NULL);
+
+#undef EXTERN
+#undef INIT
diff --git a/bin/named/include/named/log.h b/bin/named/include/named/log.h
new file mode 100644
index 0000000..f18e93a
--- /dev/null
+++ b/bin/named/include/named/log.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <isc/log.h>
+#include <isc/types.h>
+
+#include <dns/log.h>
+
+#include <named/globals.h> /* Required for named_g_(categories|modules). */
+
+/* Unused slot 0. */
+#define NAMED_LOGCATEGORY_UNMATCHED (&named_g_categories[1])
+
+/*
+ * Backwards compatibility.
+ */
+#define NAMED_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL
+
+#define NAMED_LOGMODULE_MAIN (&named_g_modules[0])
+#define NAMED_LOGMODULE_SERVER (&named_g_modules[1])
+#define NAMED_LOGMODULE_CONTROL (&named_g_modules[2])
+
+isc_result_t
+named_log_init(bool safe);
+/*%
+ * Initialize the logging system and set up an initial default
+ * logging default configuration that will be used until the
+ * config file has been read.
+ *
+ * If 'safe' is true, use a default configuration that refrains
+ * from opening files. This is to avoid creating log files
+ * as root.
+ */
+
+void
+named_log_setdefaultchannels(isc_logconfig_t *lcfg);
+/*%
+ * Set up logging channels according to the named defaults, which
+ * may differ from the logging library defaults. Currently,
+ * this just means setting up default_debug.
+ */
+
+void
+named_log_setsafechannels(isc_logconfig_t *lcfg);
+/*%
+ * Like named_log_setdefaultchannels(), but omits any logging to files.
+ */
+
+void
+named_log_setdefaultsslkeylogfile(isc_logconfig_t *lcfg);
+/*%
+ * If the SSLKEYLOGFILE environment variable is set, sets up a default
+ * logging channel for writing TLS pre-master secrets to the path stored
+ * in that environment variable (for debugging purposes).
+ */
+
+isc_result_t
+named_log_setdefaultcategory(isc_logconfig_t *lcfg);
+/*%
+ * Set up "category default" to go to the right places.
+ */
+
+isc_result_t
+named_log_setunmatchedcategory(isc_logconfig_t *lcfg);
+/*%
+ * Set up "category unmatched" to go to the right places.
+ */
+
+void
+named_log_shutdown(void);
diff --git a/bin/named/include/named/logconf.h b/bin/named/include/named/logconf.h
new file mode 100644
index 0000000..65add46
--- /dev/null
+++ b/bin/named/include/named/logconf.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <isc/log.h>
+
+isc_result_t
+named_logconfig(isc_logconfig_t *logconf, const cfg_obj_t *logstmt);
+/*%<
+ * Set up the logging configuration in '*logconf' according to
+ * the named.conf data in 'logstmt'.
+ */
diff --git a/bin/named/include/named/main.h b/bin/named/include/named/main.h
new file mode 100644
index 0000000..42fd138
--- /dev/null
+++ b/bin/named/include/named/main.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <isc/attributes.h>
+
+/*! \file */
+
+#ifdef ISC_MAIN_HOOK
+#define main(argc, argv) bindmain(argc, argv)
+#endif /* ifdef ISC_MAIN_HOOK */
+
+/*
+ * Commandline arguments for named;
+ */
+#define NAMED_MAIN_ARGS "46A:c:Cd:D:E:fFgL:M:m:n:N:p:sS:t:T:U:u:vVx:X:"
+
+noreturn void
+named_main_earlyfatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+named_main_earlywarning(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+named_main_setmemstats(const char *);
diff --git a/bin/named/include/named/os.h b/bin/named/include/named/os.h
new file mode 100644
index 0000000..0f7c1c5
--- /dev/null
+++ b/bin/named/include/named/os.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <pwd.h>
+#include <stdbool.h>
+
+#include <isc/types.h>
+
+void
+named_os_init(const char *progname);
+
+void
+named_os_daemonize(void);
+
+void
+named_os_opendevnull(void);
+
+void
+named_os_closedevnull(void);
+
+void
+named_os_chroot(const char *root);
+
+void
+named_os_inituserinfo(const char *username);
+
+void
+named_os_changeuser(void);
+
+uid_t
+ns_os_uid(void);
+
+void
+named_os_adjustnofile(void);
+
+void
+named_os_minprivs(void);
+
+FILE *
+named_os_openfile(const char *filename, mode_t mode, bool switch_user);
+
+void
+named_os_writepidfile(const char *filename, bool first_time);
+
+bool
+named_os_issingleton(const char *filename);
+
+void
+named_os_shutdown(void);
+
+void
+named_os_shutdownmsg(char *command, isc_buffer_t *text);
+
+void
+named_os_tzset(void);
+
+void
+named_os_started(void);
+
+const char *
+named_os_uname(void);
diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h
new file mode 100644
index 0000000..075e2ec
--- /dev/null
+++ b/bin/named/include/named/server.h
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/log.h>
+#include <isc/magic.h>
+#include <isc/quota.h>
+#include <isc/sockaddr.h>
+#include <isc/tls.h>
+#include <isc/types.h>
+
+#include <dns/acl.h>
+#include <dns/dnstap.h>
+#include <dns/stats.h>
+#include <dns/types.h>
+
+#include <ns/interfacemgr.h>
+#include <ns/server.h>
+#include <ns/stats.h>
+#include <ns/types.h>
+
+#include <named/types.h>
+
+#define NAMED_EVENTCLASS ISC_EVENTCLASS(0x4E43)
+#define NAMED_EVENT_RELOAD (NAMED_EVENTCLASS + 0)
+#define NAMED_EVENT_DELZONE (NAMED_EVENTCLASS + 1)
+#define NAMED_EVENT_COMMAND (NAMED_EVENTCLASS + 2)
+#define NAMED_EVENT_TATSEND (NAMED_EVENTCLASS + 3)
+
+/*%
+ * Name server state. Better here than in lots of separate global variables.
+ */
+struct named_server {
+ unsigned int magic;
+ isc_mem_t *mctx;
+
+ ns_server_t *sctx;
+
+ isc_task_t *task;
+
+ char *statsfile; /*%< Statistics file name */
+ char *dumpfile; /*%< Dump file name */
+ char *secrootsfile; /*%< Secroots file name */
+ char *bindkeysfile; /*%< bind.keys file name
+ * */
+ char *recfile; /*%< Recursive file name */
+ bool version_set; /*%< User has set version
+ * */
+ char *version; /*%< User-specified version */
+ bool hostname_set; /*%< User has set hostname
+ * */
+ char *hostname; /*%< User-specified hostname
+ * */
+
+ /* Server data structures. */
+ dns_loadmgr_t *loadmgr;
+ dns_zonemgr_t *zonemgr;
+ dns_viewlist_t viewlist;
+ dns_kasplist_t kasplist;
+ ns_interfacemgr_t *interfacemgr;
+ dns_db_t *in_roothints;
+
+ isc_timer_t *interface_timer;
+ isc_timer_t *heartbeat_timer;
+ isc_timer_t *pps_timer;
+ isc_timer_t *tat_timer;
+
+ uint32_t interface_interval;
+ uint32_t heartbeat_interval;
+
+ atomic_int reload_status;
+
+ bool flushonshutdown;
+
+ named_cachelist_t cachelist; /*%< Possibly shared caches
+ * */
+ isc_stats_t *zonestats; /*% Zone management stats */
+ isc_stats_t *resolverstats; /*% Resolver stats */
+ isc_stats_t *sockstats; /*%< Socket stats */
+
+ named_controls_t *controls; /*%< Control channels */
+ unsigned int dispatchgen;
+ named_dispatchlist_t dispatches;
+
+ named_statschannellist_t statschannels;
+
+ dst_key_t *sessionkey;
+ char *session_keyfile;
+ dns_name_t *session_keyname;
+ unsigned int session_keyalg;
+ uint16_t session_keybits;
+ bool interface_auto;
+ unsigned char secret[32]; /*%< Server Cookie Secret */
+ ns_cookiealg_t cookiealg;
+
+ dns_dtenv_t *dtenv; /*%< Dnstap environment */
+
+ char *lockfile;
+
+ isc_tlsctx_cache_t *tlsctx_server_cache;
+ isc_tlsctx_cache_t *tlsctx_client_cache;
+};
+
+#define NAMED_SERVER_MAGIC ISC_MAGIC('S', 'V', 'E', 'R')
+#define NAMED_SERVER_VALID(s) ISC_MAGIC_VALID(s, NAMED_SERVER_MAGIC)
+
+void
+named_server_create(isc_mem_t *mctx, named_server_t **serverp);
+/*%<
+ * Create a server object with default settings.
+ * This function either succeeds or causes the program to exit
+ * with a fatal error.
+ */
+
+void
+named_server_destroy(named_server_t **serverp);
+/*%<
+ * Destroy a server object, freeing its memory.
+ */
+
+void
+named_server_reloadwanted(named_server_t *server);
+/*%<
+ * Inform a server that a reload is wanted. This function
+ * may be called asynchronously, from outside the server's task.
+ * If a reload is already scheduled or in progress, the call
+ * is ignored.
+ */
+
+void
+named_server_scan_interfaces(named_server_t *server);
+/*%<
+ * Trigger a interface scan.
+ * Must only be called when running under server->task.
+ */
+
+void
+named_server_flushonshutdown(named_server_t *server, bool flush);
+/*%<
+ * Inform the server that the zones should be flushed to disk on shutdown.
+ */
+
+isc_result_t
+named_server_reloadcommand(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+/*%<
+ * Act on a "reload" command from the command channel.
+ */
+
+isc_result_t
+named_server_reconfigcommand(named_server_t *server);
+/*%<
+ * Act on a "reconfig" command from the command channel.
+ */
+
+isc_result_t
+named_server_notifycommand(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+/*%<
+ * Act on a "notify" command from the command channel.
+ */
+
+isc_result_t
+named_server_refreshcommand(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+/*%<
+ * Act on a "refresh" command from the command channel.
+ */
+
+isc_result_t
+named_server_retransfercommand(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+/*%<
+ * Act on a "retransfer" command from the command channel.
+ */
+
+isc_result_t
+named_server_togglequerylog(named_server_t *server, isc_lex_t *lex);
+/*%<
+ * Enable/disable logging of queries. (Takes "yes" or "no" argument,
+ * but can also be used as a toggle for backward comptibility.)
+ */
+
+/*%
+ * Save the current NTAs for all views to files.
+ */
+isc_result_t
+named_server_saventa(named_server_t *server);
+
+/*%
+ * Load NTAs for all views from files.
+ */
+isc_result_t
+named_server_loadnta(named_server_t *server);
+
+/*%
+ * Dump the current statistics to the statistics file.
+ */
+isc_result_t
+named_server_dumpstats(named_server_t *server);
+
+/*%
+ * Dump the current cache to the dump file.
+ */
+isc_result_t
+named_server_dumpdb(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Dump the current security roots to the secroots file.
+ */
+isc_result_t
+named_server_dumpsecroots(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Change or increment the server debug level.
+ */
+isc_result_t
+named_server_setdebuglevel(named_server_t *server, isc_lex_t *lex);
+
+/*%
+ * Flush the server's cache(s)
+ */
+isc_result_t
+named_server_flushcache(named_server_t *server, isc_lex_t *lex);
+
+/*%
+ * Flush a particular name from the server's cache. If 'tree' is false,
+ * also flush the name from the ADB and badcache. If 'tree' is true, also
+ * flush all the names under the specified name.
+ */
+isc_result_t
+named_server_flushnode(named_server_t *server, isc_lex_t *lex, bool tree);
+
+/*%
+ * Report the server's status.
+ */
+isc_result_t
+named_server_status(named_server_t *server, isc_buffer_t **text);
+
+/*%
+ * Report a list of dynamic and static tsig keys, per view.
+ */
+isc_result_t
+named_server_tsiglist(named_server_t *server, isc_buffer_t **text);
+
+/*%
+ * Delete a specific key (with optional view).
+ */
+isc_result_t
+named_server_tsigdelete(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Enable or disable updates for a zone.
+ */
+isc_result_t
+named_server_freeze(named_server_t *server, bool freeze, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Dump zone updates to disk, optionally removing the journal file
+ */
+isc_result_t
+named_server_sync(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
+
+/*%
+ * Update a zone's DNSKEY set from the key repository. If
+ * the command that triggered the call to this function was "sign",
+ * then force a full signing of the zone. If it was "loadkeys",
+ * then don't sign the zone; any needed changes to signatures can
+ * take place incrementally.
+ */
+isc_result_t
+named_server_rekey(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
+
+/*%
+ * Dump the current recursive queries.
+ */
+isc_result_t
+named_server_dumprecursing(named_server_t *server);
+
+/*%
+ * Maintain a list of dispatches that require reserved ports.
+ */
+void
+named_add_reserved_dispatch(named_server_t *server, const isc_sockaddr_t *addr);
+
+/*%
+ * Enable or disable dnssec validation.
+ */
+isc_result_t
+named_server_validation(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Add a zone to a running process, or modify an existing zone
+ */
+isc_result_t
+named_server_changezone(named_server_t *server, char *command,
+ isc_buffer_t **text);
+
+/*%
+ * Deletes a zone from a running process
+ */
+isc_result_t
+named_server_delzone(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Show current configuration for a given zone
+ */
+isc_result_t
+named_server_showzone(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Lists the status of the signing records for a given zone.
+ */
+isc_result_t
+named_server_signing(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Lists the DNSSEC status for a given zone.
+ */
+isc_result_t
+named_server_dnssec(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Lists status information for a given zone (e.g., name, type, files,
+ * load time, expiry, etc).
+ */
+isc_result_t
+named_server_zonestatus(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Adds/updates a Negative Trust Anchor (NTA) for a specified name and
+ * duration, in a particular view if specified, or in all views.
+ */
+isc_result_t
+named_server_nta(named_server_t *server, isc_lex_t *lex, bool readonly,
+ isc_buffer_t **text);
+
+/*%
+ * Generates a test sequence that is only for use in system tests. The
+ * argument is the size of required output in bytes.
+ */
+isc_result_t
+named_server_testgen(isc_lex_t *lex, isc_buffer_t **text);
+
+/*%
+ * Force fefresh or print status for managed keys zones.
+ */
+isc_result_t
+named_server_mkeys(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
+
+/*%
+ * Close and reopen DNSTAP output file.
+ */
+isc_result_t
+named_server_dnstap(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
+
+/*%
+ * Display or update tcp-{initial,idle,keepalive,advertised}-timeout options.
+ */
+isc_result_t
+named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text);
+
+/*%
+ * Control whether stale answers are served or not when configured in
+ * named.conf.
+ */
+isc_result_t
+named_server_servestale(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text);
diff --git a/bin/named/include/named/smf_globals.h b/bin/named/include/named/smf_globals.h
new file mode 100644
index 0000000..b052822
--- /dev/null
+++ b/bin/named/include/named/smf_globals.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <libscf.h>
+
+#undef EXTERN
+#undef INIT
+#ifdef NAMED_MAIN
+#define EXTERN
+#define INIT(v) = (v)
+#else /* ifdef NAMED_MAIN */
+#define EXTERN extern
+#define INIT(v)
+#endif /* ifdef NAMED_MAIN */
+
+EXTERN unsigned int named_smf_got_instance INIT(0);
+EXTERN unsigned int named_smf_chroot INIT(0);
+EXTERN unsigned int named_smf_want_disable INIT(0);
+
+isc_result_t
+named_smf_add_message(isc_buffer_t **text);
+isc_result_t
+named_smf_get_instance(char **name, int debug, isc_mem_t *mctx);
+
+#undef EXTERN
+#undef INIT
diff --git a/bin/named/include/named/statschannel.h b/bin/named/include/named/statschannel.h
new file mode 100644
index 0000000..8240dc1
--- /dev/null
+++ b/bin/named/include/named/statschannel.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file
+ * \brief
+ * The statistics channels built-in the name server.
+ */
+
+#include <isccfg/aclconf.h>
+
+#include <isccc/types.h>
+#include <named/types.h>
+
+#define NAMED_STATSCHANNEL_HTTPPORT 80
+
+isc_result_t
+named_statschannels_configure(named_server_t *server, const cfg_obj_t *config,
+ cfg_aclconfctx_t *aclconfctx);
+/*%<
+ * [Re]configure the statistics channels.
+ *
+ * If it is no longer there but was previously configured, destroy
+ * it here.
+ *
+ * If the IP address or port has changed, destroy the old server
+ * and create a new one.
+ */
+
+void
+named_statschannels_shutdown(named_server_t *server);
+/*%<
+ * Initiate shutdown of all the statistics channel listeners.
+ */
+
+isc_result_t
+named_stats_dump(named_server_t *server, FILE *fp);
+/*%<
+ * Dump statistics counters managed by the server to the file fp.
+ */
diff --git a/bin/named/include/named/tkeyconf.h b/bin/named/include/named/tkeyconf.h
new file mode 100644
index 0000000..79639d6
--- /dev/null
+++ b/bin/named/include/named/tkeyconf.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <isccfg/cfg.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+named_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
+ dns_tkeyctx_t **tctxp);
+/*%<
+ * Create a TKEY context and configure it, including the default DH key
+ * and default domain, according to 'options'.
+ *
+ * Requires:
+ *\li 'cfg' is a valid configuration options object.
+ *\li 'mctx' is not NULL
+ *\li 'tctx' is not NULL
+ *\li '*tctx' is NULL
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOMEMORY
+ */
+
+ISC_LANG_ENDDECLS
diff --git a/bin/named/include/named/transportconf.h b/bin/named/include/named/transportconf.h
new file mode 100644
index 0000000..1e472ff
--- /dev/null
+++ b/bin/named/include/named/transportconf.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <dns/transport.h>
+
+#include <isccfg/cfg.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+named_transports_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ isc_mem_t *mctx, dns_transport_list_t **listp);
+/*%<
+ * Create a list of transport objects (DoT or DoH) and configure them
+ * according to 'key-file', 'cert-file', 'ca-file' or 'hostname'
+ * statements.
+ *
+ * Requires:
+ * \li 'config' is not NULL.
+ * \li 'vconfig' is not NULL.
+ * \li 'mctx' is not NULL
+ * \li 'listp' is not NULL, and '*listp' is NULL
+ *
+ */
+
+ISC_LANG_ENDDECLS
diff --git a/bin/named/include/named/tsigconf.h b/bin/named/include/named/tsigconf.h
new file mode 100644
index 0000000..32a0120
--- /dev/null
+++ b/bin/named/include/named/tsigconf.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+named_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ isc_mem_t *mctx, dns_tsig_keyring_t **ringp);
+/*%<
+ * Create a TSIG key ring and configure it according to the 'key'
+ * statements in the global and view configuration objects.
+ *
+ * Requires:
+ * \li 'config' is not NULL.
+ * \li 'vconfig' is not NULL.
+ * \li 'mctx' is not NULL
+ * \li 'ringp' is not NULL, and '*ringp' is NULL
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOMEMORY
+ */
+
+ISC_LANG_ENDDECLS
diff --git a/bin/named/include/named/types.h b/bin/named/include/named/types.h
new file mode 100644
index 0000000..585c141
--- /dev/null
+++ b/bin/named/include/named/types.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <dns/types.h>
+
+typedef struct named_cache named_cache_t;
+typedef ISC_LIST(named_cache_t) named_cachelist_t;
+typedef struct named_server named_server_t;
+typedef struct named_xmld named_xmld_t;
+typedef struct named_xmldmgr named_xmldmgr_t;
+typedef struct named_controls named_controls_t;
+typedef struct named_dispatch named_dispatch_t;
+typedef ISC_LIST(named_dispatch_t) named_dispatchlist_t;
+typedef struct named_statschannel named_statschannel_t;
+typedef ISC_LIST(named_statschannel_t) named_statschannellist_t;
+
+/*%
+ * Used for server->reload_status as printed by `rndc status`
+ */
+typedef enum {
+ NAMED_RELOAD_DONE,
+ NAMED_RELOAD_IN_PROGRESS,
+ NAMED_RELOAD_FAILED,
+} named_reload_t;
diff --git a/bin/named/include/named/zoneconf.h b/bin/named/include/named/zoneconf.h
new file mode 100644
index 0000000..387d8a1
--- /dev/null
+++ b/bin/named/include/named/zoneconf.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <isccfg/aclconf.h>
+#include <isccfg/cfg.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
+ dns_kasplist_t *kasplist, dns_zone_t *zone,
+ dns_zone_t *raw);
+/*%<
+ * Configure or reconfigure a zone according to the named.conf
+ * data.
+ *
+ * The zone origin is not configured, it is assumed to have been set
+ * at zone creation time.
+ *
+ * Require:
+ * \li 'ac' to point to an initialized cfg_aclconfctx_t.
+ * \li 'kasplist' to be initialized.
+ * \li 'zone' to be initialized.
+ */
+
+bool
+named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig);
+/*%<
+ * If 'zone' can be safely reconfigured according to the configuration
+ * data in 'zconfig', return true. If the configuration data is so
+ * different from the current zone state that the zone needs to be destroyed
+ * and recreated, return false.
+ */
+
+bool
+named_zone_inlinesigning(const cfg_obj_t *zconfig);
+/*%<
+ * Determine if zone uses inline-signing. This is true if inline-signing
+ * is set to yes.
+ */
+
+isc_result_t
+named_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone,
+ dns_rdataclass_t rdclass, dns_name_t *name);
+/*%>
+ * configure a DLZ zone, setting up the database methods and calling
+ * postload to load the origin values
+ *
+ * Require:
+ * \li 'dlzdatabase' to be a valid dlz database
+ * \li 'zone' to be initialized.
+ * \li 'rdclass' to be a valid rdataclass
+ * \li 'name' to be a valid zone origin name
+ */
+
+ISC_LANG_ENDDECLS
diff --git a/bin/named/log.c b/bin/named/log.c
new file mode 100644
index 0000000..6efea02
--- /dev/null
+++ b/bin/named/log.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <stdlib.h>
+
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/log.h>
+
+#include <isccfg/log.h>
+
+#include <ns/log.h>
+
+#include <named/log.h>
+
+#ifndef ISC_FACILITY
+#define ISC_FACILITY LOG_DAEMON
+#endif /* ifndef ISC_FACILITY */
+
+/*%
+ * When adding a new category, be sure to add the appropriate
+ * \#define to <named/log.h> and to update the list in
+ * bin/check/check-tool.c.
+ */
+static isc_logcategory_t categories[] = { { "", 0 },
+ { "unmatched", 0 },
+ { NULL, 0 } };
+
+/*%
+ * When adding a new module, be sure to add the appropriate
+ * \#define to <dns/log.h>.
+ */
+static isc_logmodule_t modules[] = {
+ { "main", 0 }, { "server", 0 }, { "control", 0 }, { NULL, 0 }
+};
+
+isc_result_t
+named_log_init(bool safe) {
+ isc_result_t result;
+ isc_logconfig_t *lcfg = NULL;
+
+ named_g_categories = categories;
+ named_g_modules = modules;
+
+ /*
+ * Setup a logging context.
+ */
+ isc_log_create(named_g_mctx, &named_g_lctx, &lcfg);
+
+ /*
+ * named-checktool.c:setup_logging() needs to be kept in sync.
+ */
+ isc_log_registercategories(named_g_lctx, named_g_categories);
+ isc_log_registermodules(named_g_lctx, named_g_modules);
+ isc_log_setcontext(named_g_lctx);
+ dns_log_init(named_g_lctx);
+ dns_log_setcontext(named_g_lctx);
+ cfg_log_init(named_g_lctx);
+ ns_log_init(named_g_lctx);
+ ns_log_setcontext(named_g_lctx);
+
+ if (safe) {
+ named_log_setsafechannels(lcfg);
+ } else {
+ named_log_setdefaultchannels(lcfg);
+ }
+
+ result = named_log_setdefaultcategory(lcfg);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ named_log_setdefaultsslkeylogfile(lcfg);
+
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ isc_log_destroy(&named_g_lctx);
+ isc_log_setcontext(NULL);
+ dns_log_setcontext(NULL);
+
+ return (result);
+}
+
+void
+named_log_setdefaultchannels(isc_logconfig_t *lcfg) {
+ isc_logdestination_t destination;
+
+ /*
+ * By default, the logging library makes "default_debug" log to
+ * stderr. In BIND, we want to override this and log to named.run
+ * instead, unless the -g option was given.
+ */
+ if (!named_g_logstderr) {
+ destination.file.stream = NULL;
+ destination.file.name = "named.run";
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ isc_log_createchannel(lcfg, "default_debug", ISC_LOG_TOFILE,
+ ISC_LOG_DYNAMIC, &destination,
+ ISC_LOG_PRINTTIME | ISC_LOG_DEBUGONLY);
+ }
+
+ if (named_g_logfile != NULL) {
+ destination.file.stream = NULL;
+ destination.file.name = named_g_logfile;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ isc_log_createchannel(lcfg, "default_logfile", ISC_LOG_TOFILE,
+ ISC_LOG_DYNAMIC, &destination,
+ ISC_LOG_PRINTTIME |
+ ISC_LOG_PRINTCATEGORY |
+ ISC_LOG_PRINTLEVEL);
+ }
+
+#if ISC_FACILITY != LOG_DAEMON
+ destination.facility = ISC_FACILITY;
+ isc_log_createchannel(lcfg, "default_syslog", ISC_LOG_TOSYSLOG,
+ ISC_LOG_INFO, &destination, 0);
+#endif /* if ISC_FACILITY != LOG_DAEMON */
+
+ /*
+ * Set the initial debug level.
+ */
+ isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel);
+}
+
+void
+named_log_setsafechannels(isc_logconfig_t *lcfg) {
+ isc_logdestination_t destination;
+
+ if (!named_g_logstderr) {
+ isc_log_createchannel(lcfg, "default_debug", ISC_LOG_TONULL,
+ ISC_LOG_DYNAMIC, NULL, 0);
+
+ /*
+ * Setting the debug level to zero should get the output
+ * discarded a bit faster.
+ */
+ isc_log_setdebuglevel(named_g_lctx, 0);
+ } else {
+ isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel);
+ }
+
+ if (named_g_logfile != NULL) {
+ destination.file.stream = NULL;
+ destination.file.name = named_g_logfile;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ isc_log_createchannel(lcfg, "default_logfile", ISC_LOG_TOFILE,
+ ISC_LOG_DYNAMIC, &destination,
+ ISC_LOG_PRINTTIME |
+ ISC_LOG_PRINTCATEGORY |
+ ISC_LOG_PRINTLEVEL);
+ }
+
+#if ISC_FACILITY != LOG_DAEMON
+ destination.facility = ISC_FACILITY;
+ isc_log_createchannel(lcfg, "default_syslog", ISC_LOG_TOSYSLOG,
+ ISC_LOG_INFO, &destination, 0);
+#endif /* if ISC_FACILITY != LOG_DAEMON */
+}
+
+/*
+ * If the SSLKEYLOGFILE environment variable is set, TLS pre-master secrets are
+ * logged (for debugging purposes) to the file whose path is provided in that
+ * variable. Set up a default logging channel which maintains up to 10 files
+ * containing TLS pre-master secrets, each up to 100 MB in size. If the
+ * SSLKEYLOGFILE environment variable is set to the string "config", suppress
+ * creation of the default channel, allowing custom logging channel
+ * configuration for TLS pre-master secrets to be provided via the "logging"
+ * stanza in the configuration file.
+ */
+void
+named_log_setdefaultsslkeylogfile(isc_logconfig_t *lcfg) {
+ const char *sslkeylogfile_path = getenv("SSLKEYLOGFILE");
+ isc_logdestination_t destination = {
+ .file = {
+ .name = sslkeylogfile_path,
+ .versions = 10,
+ .suffix = isc_log_rollsuffix_timestamp,
+ .maximum_size = 100 * 1024 * 1024,
+ },
+ };
+ isc_result_t result;
+
+ if (sslkeylogfile_path == NULL ||
+ strcmp(sslkeylogfile_path, "config") == 0)
+ {
+ return;
+ }
+
+ isc_log_createchannel(lcfg, "default_sslkeylogfile", ISC_LOG_TOFILE,
+ ISC_LOG_INFO, &destination, 0);
+ result = isc_log_usechannel(lcfg, "default_sslkeylogfile",
+ ISC_LOGCATEGORY_SSLKEYLOG, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+}
+
+isc_result_t
+named_log_setdefaultcategory(isc_logconfig_t *lcfg) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ result = isc_log_usechannel(lcfg, "default_debug",
+ ISC_LOGCATEGORY_DEFAULT, NULL);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ if (!named_g_logstderr) {
+ if (named_g_logfile != NULL) {
+ result = isc_log_usechannel(lcfg, "default_logfile",
+ ISC_LOGCATEGORY_DEFAULT,
+ NULL);
+ } else if (!named_g_nosyslog) {
+ result = isc_log_usechannel(lcfg, "default_syslog",
+ ISC_LOGCATEGORY_DEFAULT,
+ NULL);
+ }
+ }
+
+cleanup:
+ return (result);
+}
+
+isc_result_t
+named_log_setunmatchedcategory(isc_logconfig_t *lcfg) {
+ isc_result_t result;
+
+ result = isc_log_usechannel(lcfg, "null", NAMED_LOGCATEGORY_UNMATCHED,
+ NULL);
+ return (result);
+}
+
+void
+named_log_shutdown(void) {
+ isc_log_destroy(&named_g_lctx);
+ isc_log_setcontext(NULL);
+ dns_log_setcontext(NULL);
+}
diff --git a/bin/named/logconf.c b/bin/named/logconf.c
new file mode 100644
index 0000000..5fd0904
--- /dev/null
+++ b/bin/named/logconf.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/file.h>
+#include <isc/offset.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/syslog.h>
+#include <isc/util.h>
+
+#include <isccfg/cfg.h>
+#include <isccfg/log.h>
+
+#include <named/log.h>
+#include <named/logconf.h>
+
+#define CHECK(op) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+/*%
+ * Set up a logging category according to the named.conf data
+ * in 'ccat' and add it to 'logconfig'.
+ */
+static isc_result_t
+category_fromconf(const cfg_obj_t *ccat, isc_logconfig_t *logconfig) {
+ isc_result_t result;
+ const char *catname;
+ isc_logcategory_t *category;
+ isc_logmodule_t *module;
+ const cfg_obj_t *destinations = NULL;
+ const cfg_listelt_t *element = NULL;
+
+ catname = cfg_obj_asstring(cfg_tuple_get(ccat, "name"));
+ category = isc_log_categorybyname(named_g_lctx, catname);
+ if (category == NULL) {
+ cfg_obj_log(ccat, named_g_lctx, ISC_LOG_ERROR,
+ "unknown logging category '%s' ignored", catname);
+ /*
+ * Allow further processing by returning success.
+ */
+ return (ISC_R_SUCCESS);
+ }
+
+ if (logconfig == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ module = NULL;
+
+ destinations = cfg_tuple_get(ccat, "destinations");
+ for (element = cfg_list_first(destinations); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *channel = cfg_listelt_value(element);
+ const char *channelname = cfg_obj_asstring(channel);
+
+ result = isc_log_usechannel(logconfig, channelname, category,
+ module);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, CFG_LOGCATEGORY_CONFIG,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "logging channel '%s': %s", channelname,
+ isc_result_totext(result));
+ return (result);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Set up a logging channel according to the named.conf data
+ * in 'cchan' and add it to 'logconfig'.
+ */
+static isc_result_t
+channel_fromconf(const cfg_obj_t *channel, isc_logconfig_t *logconfig) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_logdestination_t dest;
+ unsigned int type;
+ unsigned int flags = 0;
+ int level;
+ const char *channelname;
+ const cfg_obj_t *fileobj = NULL;
+ const cfg_obj_t *syslogobj = NULL;
+ const cfg_obj_t *nullobj = NULL;
+ const cfg_obj_t *stderrobj = NULL;
+ const cfg_obj_t *severity = NULL;
+ int i;
+
+ channelname = cfg_obj_asstring(cfg_map_getname(channel));
+
+ (void)cfg_map_get(channel, "file", &fileobj);
+ (void)cfg_map_get(channel, "syslog", &syslogobj);
+ (void)cfg_map_get(channel, "null", &nullobj);
+ (void)cfg_map_get(channel, "stderr", &stderrobj);
+
+ i = 0;
+ if (fileobj != NULL) {
+ i++;
+ }
+ if (syslogobj != NULL) {
+ i++;
+ }
+ if (nullobj != NULL) {
+ i++;
+ }
+ if (stderrobj != NULL) {
+ i++;
+ }
+
+ if (i != 1) {
+ cfg_obj_log(channel, named_g_lctx, ISC_LOG_ERROR,
+ "channel '%s': exactly one of file, syslog, "
+ "null, and stderr must be present",
+ channelname);
+ return (ISC_R_FAILURE);
+ }
+
+ type = ISC_LOG_TONULL;
+
+ if (fileobj != NULL) {
+ const cfg_obj_t *pathobj = cfg_tuple_get(fileobj, "file");
+ const cfg_obj_t *sizeobj = cfg_tuple_get(fileobj, "size");
+ const cfg_obj_t *versionsobj = cfg_tuple_get(fileobj,
+ "versions");
+ const cfg_obj_t *suffixobj = cfg_tuple_get(fileobj, "suffix");
+ int32_t versions = ISC_LOG_ROLLNEVER;
+ isc_log_rollsuffix_t suffix = isc_log_rollsuffix_increment;
+ isc_offset_t size = 0;
+ uint64_t maxoffset;
+
+ /*
+ * isc_offset_t is a signed integer type, so the maximum
+ * value is all 1s except for the MSB.
+ */
+ switch (sizeof(isc_offset_t)) {
+ case 4:
+ maxoffset = 0x7fffffffULL;
+ break;
+ case 8:
+ maxoffset = 0x7fffffffffffffffULL;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ type = ISC_LOG_TOFILE;
+
+ if (versionsobj != NULL && cfg_obj_isuint32(versionsobj)) {
+ versions = cfg_obj_asuint32(versionsobj);
+ } else if (versionsobj != NULL &&
+ cfg_obj_isstring(versionsobj) &&
+ strcasecmp(cfg_obj_asstring(versionsobj),
+ "unlimited") == 0)
+ {
+ versions = ISC_LOG_ROLLINFINITE;
+ }
+ if (sizeobj != NULL && cfg_obj_isuint64(sizeobj) &&
+ cfg_obj_asuint64(sizeobj) < maxoffset)
+ {
+ size = (isc_offset_t)cfg_obj_asuint64(sizeobj);
+ }
+ if (suffixobj != NULL && cfg_obj_isstring(suffixobj) &&
+ strcasecmp(cfg_obj_asstring(suffixobj), "timestamp") == 0)
+ {
+ suffix = isc_log_rollsuffix_timestamp;
+ }
+
+ dest.file.stream = NULL;
+ dest.file.name = cfg_obj_asstring(pathobj);
+ dest.file.versions = versions;
+ dest.file.suffix = suffix;
+ dest.file.maximum_size = size;
+ } else if (syslogobj != NULL) {
+ int facility = LOG_DAEMON;
+
+ type = ISC_LOG_TOSYSLOG;
+
+ if (cfg_obj_isstring(syslogobj)) {
+ const char *facilitystr = cfg_obj_asstring(syslogobj);
+ (void)isc_syslog_facilityfromstring(facilitystr,
+ &facility);
+ }
+ dest.facility = facility;
+ } else if (stderrobj != NULL) {
+ type = ISC_LOG_TOFILEDESC;
+ dest.file.stream = stderr;
+ dest.file.name = NULL;
+ dest.file.versions = ISC_LOG_ROLLNEVER;
+ dest.file.suffix = isc_log_rollsuffix_increment;
+ dest.file.maximum_size = 0;
+ }
+
+ /*
+ * Munge flags.
+ */
+ {
+ const cfg_obj_t *printcat = NULL;
+ const cfg_obj_t *printsev = NULL;
+ const cfg_obj_t *printtime = NULL;
+ const cfg_obj_t *buffered = NULL;
+
+ (void)cfg_map_get(channel, "print-category", &printcat);
+ (void)cfg_map_get(channel, "print-severity", &printsev);
+ (void)cfg_map_get(channel, "print-time", &printtime);
+ (void)cfg_map_get(channel, "buffered", &buffered);
+
+ if (printcat != NULL && cfg_obj_asboolean(printcat)) {
+ flags |= ISC_LOG_PRINTCATEGORY;
+ }
+ if (printsev != NULL && cfg_obj_asboolean(printsev)) {
+ flags |= ISC_LOG_PRINTLEVEL;
+ }
+ if (buffered != NULL && cfg_obj_asboolean(buffered)) {
+ flags |= ISC_LOG_BUFFERED;
+ }
+ if (printtime != NULL && cfg_obj_isboolean(printtime)) {
+ if (cfg_obj_asboolean(printtime)) {
+ flags |= ISC_LOG_PRINTTIME;
+ }
+ } else if (printtime != NULL) { /* local/iso8601/iso8601-utc */
+ const char *s = cfg_obj_asstring(printtime);
+ flags |= ISC_LOG_PRINTTIME;
+ if (strcasecmp(s, "iso8601") == 0) {
+ flags |= ISC_LOG_ISO8601;
+ } else if (strcasecmp(s, "iso8601-utc") == 0) {
+ flags |= ISC_LOG_ISO8601 | ISC_LOG_UTC;
+ }
+ }
+ }
+
+ level = ISC_LOG_INFO;
+ if (cfg_map_get(channel, "severity", &severity) == ISC_R_SUCCESS) {
+ if (cfg_obj_isstring(severity)) {
+ const char *str = cfg_obj_asstring(severity);
+ if (strcasecmp(str, "critical") == 0) {
+ level = ISC_LOG_CRITICAL;
+ } else if (strcasecmp(str, "error") == 0) {
+ level = ISC_LOG_ERROR;
+ } else if (strcasecmp(str, "warning") == 0) {
+ level = ISC_LOG_WARNING;
+ } else if (strcasecmp(str, "notice") == 0) {
+ level = ISC_LOG_NOTICE;
+ } else if (strcasecmp(str, "info") == 0) {
+ level = ISC_LOG_INFO;
+ } else if (strcasecmp(str, "dynamic") == 0) {
+ level = ISC_LOG_DYNAMIC;
+ }
+ } else {
+ /* debug */
+ level = cfg_obj_asuint32(severity);
+ }
+ }
+
+ if (logconfig != NULL) {
+ isc_log_createchannel(logconfig, channelname, type, level,
+ &dest, flags);
+ }
+
+ if (type == ISC_LOG_TOFILE) {
+ FILE *fp;
+
+ /*
+ * Test to make sure that file is a plain file.
+ * Fix defect #22771
+ */
+ result = isc_file_isplainfile(dest.file.name);
+ if (result == ISC_R_SUCCESS || result == ISC_R_FILENOTFOUND) {
+ /*
+ * Test that the file can be opened, since
+ * isc_log_open() can't effectively report
+ * failures when called in isc_log_doit().
+ */
+ result = isc_stdio_open(dest.file.name, "a", &fp);
+ if (result != ISC_R_SUCCESS) {
+ if (logconfig != NULL && !named_g_nosyslog) {
+ syslog(LOG_ERR,
+ "isc_stdio_open '%s' failed: "
+ "%s",
+ dest.file.name,
+ isc_result_totext(result));
+ }
+ } else {
+ (void)isc_stdio_close(fp);
+ }
+ goto done;
+ }
+ if (logconfig != NULL && !named_g_nosyslog) {
+ syslog(LOG_ERR, "isc_file_isplainfile '%s' failed: %s",
+ dest.file.name, isc_result_totext(result));
+ }
+ }
+
+done:
+ return (result);
+}
+
+isc_result_t
+named_logconfig(isc_logconfig_t *logconfig, const cfg_obj_t *logstmt) {
+ isc_result_t result;
+ const cfg_obj_t *channels = NULL;
+ const cfg_obj_t *categories = NULL;
+ const cfg_listelt_t *element;
+ bool default_set = false;
+ bool unmatched_set = false;
+ const cfg_obj_t *catname;
+
+ if (logconfig != NULL) {
+ named_log_setdefaultchannels(logconfig);
+ named_log_setdefaultsslkeylogfile(logconfig);
+ }
+
+ (void)cfg_map_get(logstmt, "channel", &channels);
+ for (element = cfg_list_first(channels); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *channel = cfg_listelt_value(element);
+ CHECK(channel_fromconf(channel, logconfig));
+ }
+
+ (void)cfg_map_get(logstmt, "category", &categories);
+ for (element = cfg_list_first(categories); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *category = cfg_listelt_value(element);
+ CHECK(category_fromconf(category, logconfig));
+ if (!default_set) {
+ catname = cfg_tuple_get(category, "name");
+ if (strcmp(cfg_obj_asstring(catname), "default") == 0) {
+ default_set = true;
+ }
+ }
+ if (!unmatched_set) {
+ catname = cfg_tuple_get(category, "name");
+ if (strcmp(cfg_obj_asstring(catname), "unmatched") == 0)
+ {
+ unmatched_set = true;
+ }
+ }
+ }
+
+ if (logconfig != NULL && !default_set) {
+ CHECK(named_log_setdefaultcategory(logconfig));
+ }
+
+ if (logconfig != NULL && !unmatched_set) {
+ CHECK(named_log_setunmatchedcategory(logconfig));
+ }
+
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ return (result);
+}
diff --git a/bin/named/main.c b/bin/named/main.c
new file mode 100644
index 0000000..154e17e
--- /dev/null
+++ b/bin/named/main.c
@@ -0,0 +1,1663 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uv.h>
+
+#ifdef HAVE_DNSTAP
+#include <protobuf-c/protobuf-c.h>
+#endif
+
+#include <isc/app.h>
+#include <isc/attributes.h>
+#include <isc/backtrace.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/httpd.h>
+#include <isc/managers.h>
+#include <isc/netmgr.h>
+#include <isc/os.h>
+#include <isc/print.h>
+#include <isc/resource.h>
+#include <isc/result.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/dispatch.h>
+#include <dns/dyndb.h>
+#include <dns/name.h>
+#include <dns/resolver.h>
+#include <dns/view.h>
+
+#include <dlz/dlz_dlopen_driver.h>
+
+#ifdef HAVE_GPERFTOOLS_PROFILER
+#include <gperftools/profiler.h>
+#endif /* ifdef HAVE_GPERFTOOLS_PROFILER */
+
+#ifdef HAVE_JSON_C
+#include <json_c_version.h>
+#endif /* HAVE_JSON_C */
+
+#ifdef HAVE_GEOIP2
+#include <maxminddb.h>
+#endif /* ifdef HAVE_GEOIP2 */
+
+/*
+ * Defining NAMED_MAIN provides storage declarations (rather than extern)
+ * for variables in named/globals.h.
+ */
+#define NAMED_MAIN 1
+
+#include <ns/interfacemgr.h>
+
+#include <named/builtin.h>
+#include <named/config.h>
+#include <named/control.h>
+#include <named/fuzz.h>
+#include <named/globals.h> /* Explicit, though named/log.h includes it. */
+#include <named/log.h>
+#include <named/main.h>
+#include <named/os.h>
+#include <named/server.h>
+#ifdef HAVE_LIBSCF
+#include <named/smf_globals.h>
+#endif /* ifdef HAVE_LIBSCF */
+
+#include <openssl/crypto.h>
+#include <openssl/opensslv.h>
+#ifdef HAVE_LIBXML2
+#include <libxml/parser.h>
+#include <libxml/xmlversion.h>
+#endif /* ifdef HAVE_LIBXML2 */
+#ifdef HAVE_ZLIB
+#include <zlib.h>
+#endif /* ifdef HAVE_ZLIB */
+#ifdef HAVE_LIBNGHTTP2
+#include <nghttp2/nghttp2.h>
+#endif
+/*
+ * Include header files for database drivers here.
+ */
+/* #include "xxdb.h" */
+
+/*
+ * The maximum number of stack frames to dump on assertion failure.
+ */
+#ifndef BACKTRACE_MAXFRAME
+#define BACKTRACE_MAXFRAME 128
+#endif /* ifndef BACKTRACE_MAXFRAME */
+
+extern unsigned int dns_zone_mkey_hour;
+extern unsigned int dns_zone_mkey_day;
+extern unsigned int dns_zone_mkey_month;
+
+static bool want_stats = false;
+static char program_name[NAME_MAX] = "named";
+static char absolute_conffile[PATH_MAX];
+static char saved_command_line[4096] = { 0 };
+static char ellipsis[5] = { 0 };
+static char version[512];
+static int maxudp = 0;
+
+/*
+ * -T options:
+ */
+static bool dropedns = false;
+static bool ednsformerr = false;
+static bool ednsnotimp = false;
+static bool ednsrefused = false;
+static bool fixedlocal = false;
+static bool noaa = false;
+static bool noedns = false;
+static bool nonearest = false;
+static bool nosoa = false;
+static bool notcp = false;
+static bool sigvalinsecs = false;
+static bool transferinsecs = false;
+static bool transferslowly = false;
+static bool transferstuck = false;
+
+/*
+ * -4 and -6
+ */
+static bool disable6 = false;
+static bool disable4 = false;
+
+void
+named_main_earlywarning(const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ if (named_g_lctx != NULL) {
+ isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_WARNING, format,
+ args);
+ } else {
+ fprintf(stderr, "%s: ", program_name);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+ va_end(args);
+}
+
+void
+named_main_earlyfatal(const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ if (named_g_lctx != NULL) {
+ isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, format,
+ args);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "exiting (due to early fatal error)");
+ } else {
+ fprintf(stderr, "%s: ", program_name);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+ va_end(args);
+
+ exit(1);
+}
+
+noreturn static void
+assertion_failed(const char *file, int line, isc_assertiontype_t type,
+ const char *cond);
+
+static void
+assertion_failed(const char *file, int line, isc_assertiontype_t type,
+ const char *cond) {
+ void *tracebuf[BACKTRACE_MAXFRAME];
+ int nframes;
+
+ /*
+ * Handle assertion failures.
+ */
+
+ if (named_g_lctx != NULL) {
+ /*
+ * Reset the assertion callback in case it is the log
+ * routines causing the assertion.
+ */
+ isc_assertion_setcallback(NULL);
+
+ nframes = isc_backtrace(tracebuf, BACKTRACE_MAXFRAME);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "%s:%d: %s(%s) failed%s", file, line,
+ isc_assertion_typetotext(type), cond,
+ (nframes > 0) ? ", back trace" : "");
+ if (nframes > 0) {
+ char **strs = isc_backtrace_symbols(tracebuf, nframes);
+ if (strs != NULL) {
+ for (int i = 0; i < nframes; i++) {
+ isc_log_write(named_g_lctx,
+ NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN,
+ ISC_LOG_CRITICAL, "%s",
+ strs[i]);
+ }
+ }
+ }
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "exiting (due to assertion failure)");
+ } else {
+ fprintf(stderr, "%s:%d: %s(%s) failed\n", file, line,
+ isc_assertion_typetotext(type), cond);
+ fflush(stderr);
+ }
+
+ if (named_g_coreok) {
+ abort();
+ }
+ exit(1);
+}
+
+noreturn static void
+library_fatal_error(const char *file, int line, const char *func,
+ const char *format, va_list args) ISC_FORMAT_PRINTF(3, 0);
+
+static void
+library_fatal_error(const char *file, int line, const char *func,
+ const char *format, va_list args) {
+ /*
+ * Handle isc_error_fatal() calls from our libraries.
+ */
+
+ if (named_g_lctx != NULL) {
+ /*
+ * Reset the error callback in case it is the log
+ * routines causing the assertion.
+ */
+ isc_error_setfatal(NULL);
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "%s:%d:%s(): fatal error: ", file, line, func);
+ isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, format,
+ args);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "exiting (due to fatal error in library)");
+ } else {
+ fprintf(stderr, "%s:%d:%s(): fatal error: ", file, line, func);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+
+ if (named_g_coreok) {
+ abort();
+ }
+ exit(1);
+}
+
+static void
+library_unexpected_error(const char *file, int line, const char *func,
+ const char *format, va_list args)
+ ISC_FORMAT_PRINTF(3, 0);
+
+static void
+library_unexpected_error(const char *file, int line, const char *func,
+ const char *format, va_list args) {
+ /*
+ * Handle isc_error_unexpected() calls from our libraries.
+ */
+
+ if (named_g_lctx != NULL) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_ERROR,
+ "%s:%d:%s(): unexpected error: ", file, line,
+ func);
+ isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_ERROR, format,
+ args);
+ } else {
+ fprintf(stderr, "%s:%d:%s(): fatal error: ", file, line, func);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "usage: named [-4|-6] [-c conffile] [-d debuglevel] "
+ "[-D comment] [-E engine]\n"
+ " [-f|-g] [-L logfile] [-n number_of_cpus] "
+ "[-p port] [-s]\n"
+ " [-S sockets] [-t chrootdir] [-u "
+ "username] [-U listeners]\n"
+ " [-X lockfile] [-m "
+ "{usage|trace|record|size|mctx}]\n"
+ " [-M fill|nofill]\n"
+ "usage: named [-v|-V|-C]\n");
+}
+
+static void
+save_command_line(int argc, char *argv[]) {
+ int i;
+ char *dst = saved_command_line;
+ char *eob = saved_command_line + sizeof(saved_command_line) - 1;
+ char *rollback = dst;
+
+ for (i = 1; i < argc && dst < eob; i++) {
+ char *src = argv[i];
+ bool quoted = false;
+
+ rollback = dst;
+ *dst++ = ' ';
+
+ while (*src != '\0' && dst < eob) {
+ if (isalnum(*(unsigned char *)src) || *src == ',' ||
+ *src == '-' || *src == '_' || *src == '.' ||
+ *src == '/')
+ {
+ *dst++ = *src++;
+ } else if (isprint(*(unsigned char *)src)) {
+ if (dst + 2 >= eob) {
+ goto add_ellipsis;
+ }
+ *dst++ = '\\';
+ *dst++ = *src++;
+ } else {
+ /*
+ * Control character found in the input,
+ * quote the whole arg and restart
+ */
+ if (!quoted) {
+ dst = rollback;
+ src = argv[i];
+
+ if (dst + 3 >= eob) {
+ goto add_ellipsis;
+ }
+
+ *dst++ = ' ';
+ *dst++ = '$';
+ *dst++ = '\'';
+
+ quoted = true;
+ continue;
+ } else {
+ char tmp[5];
+ int c = snprintf(tmp, sizeof(tmp),
+ "\\%03o", *src++);
+ if (dst + c >= eob) {
+ goto add_ellipsis;
+ }
+ memmove(dst, tmp, c);
+ dst += c;
+ }
+ }
+ }
+ if (quoted) {
+ if (dst == eob) {
+ goto add_ellipsis;
+ }
+ *dst++ = '\'';
+ }
+ }
+
+ if (dst < eob) {
+ return;
+ }
+add_ellipsis:
+ dst = rollback;
+ *dst = '\0';
+ strlcpy(ellipsis, " ...", sizeof(ellipsis));
+}
+
+static int
+parse_int(char *arg, const char *desc) {
+ char *endp;
+ int tmp;
+ long int ltmp;
+
+ ltmp = strtol(arg, &endp, 10);
+ tmp = (int)ltmp;
+ if (*endp != '\0') {
+ named_main_earlyfatal("%s '%s' must be numeric", desc, arg);
+ }
+ if (tmp < 0 || tmp != ltmp) {
+ named_main_earlyfatal("%s '%s' out of range", desc, arg);
+ }
+ return (tmp);
+}
+
+static struct flag_def {
+ const char *name;
+ unsigned int value;
+ bool negate;
+} mem_debug_flags[] = { { "none", 0, false },
+ { "trace", ISC_MEM_DEBUGTRACE, false },
+ { "record", ISC_MEM_DEBUGRECORD, false },
+ { "usage", ISC_MEM_DEBUGUSAGE, false },
+ { NULL, 0, false } },
+ mem_context_flags[] = { { "fill", ISC_MEMFLAG_FILL, false },
+ { "nofill", ISC_MEMFLAG_FILL, true },
+ { NULL, 0, false } };
+
+static void
+set_flags(const char *arg, struct flag_def *defs, unsigned int *ret) {
+ bool clear = false;
+
+ for (;;) {
+ const struct flag_def *def;
+ const char *end = strchr(arg, ',');
+ int arglen;
+ if (end == NULL) {
+ end = arg + strlen(arg);
+ }
+ arglen = (int)(end - arg);
+ for (def = defs; def->name != NULL; def++) {
+ if (arglen == (int)strlen(def->name) &&
+ memcmp(arg, def->name, arglen) == 0)
+ {
+ if (def->value == 0) {
+ clear = true;
+ }
+ if (def->negate) {
+ *ret &= ~(def->value);
+ } else {
+ *ret |= def->value;
+ }
+ goto found;
+ }
+ }
+ named_main_earlyfatal("unrecognized flag '%.*s'", arglen, arg);
+ found:
+ if (clear || (*end == '\0')) {
+ break;
+ }
+ arg = end + 1;
+ }
+
+ if (clear) {
+ *ret = 0;
+ }
+}
+
+static void
+list_dnssec_algorithms(isc_buffer_t *b) {
+ for (dst_algorithm_t i = DST_ALG_UNKNOWN; i < DST_MAX_ALGS; i++) {
+ if (i == DST_ALG_DH || i == DST_ALG_GSSAPI ||
+ (i >= DST_ALG_HMAC_FIRST && i <= DST_ALG_HMAC_LAST))
+ {
+ continue;
+ }
+ if (dst_algorithm_supported(i)) {
+ isc_buffer_putstr(b, " ");
+ (void)dns_secalg_totext(i, b);
+ }
+ }
+}
+
+static void
+list_ds_algorithms(isc_buffer_t *b) {
+ for (size_t i = 0; i < 256; i++) {
+ if (dst_ds_digest_supported(i)) {
+ isc_buffer_putstr(b, " ");
+ (void)dns_dsdigest_totext(i, b);
+ }
+ }
+}
+
+static void
+list_hmac_algorithms(isc_buffer_t *b) {
+ isc_buffer_t sb = *b;
+ for (dst_algorithm_t i = DST_ALG_HMAC_FIRST; i <= DST_ALG_HMAC_LAST;
+ i++)
+ {
+ if (i == DST_ALG_GSSAPI) {
+ continue;
+ }
+ if (dst_algorithm_supported(i)) {
+ isc_buffer_putstr(b, " ");
+ isc_buffer_putstr(b, dst_hmac_algorithm_totext(i));
+ }
+ }
+ for (unsigned char *s = isc_buffer_used(&sb); s != isc_buffer_used(b);
+ s++)
+ {
+ *s = toupper(*s);
+ }
+}
+
+static void
+logit(isc_buffer_t *b) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "%.*s",
+ (int)isc_buffer_usedlength(b),
+ (char *)isc_buffer_base(b));
+}
+
+static void
+printit(isc_buffer_t *b) {
+ printf("%.*s\n", (int)isc_buffer_usedlength(b),
+ (char *)isc_buffer_base(b));
+}
+
+static void
+format_supported_algorithms(void (*emit)(isc_buffer_t *b)) {
+ isc_buffer_t b;
+ char buf[512];
+
+ isc_buffer_init(&b, buf, sizeof(buf));
+ isc_buffer_putstr(&b, "DNSSEC algorithms:");
+ list_dnssec_algorithms(&b);
+ (*emit)(&b);
+
+ isc_buffer_init(&b, buf, sizeof(buf));
+ isc_buffer_putstr(&b, "DS algorithms:");
+ list_ds_algorithms(&b);
+ (*emit)(&b);
+
+ isc_buffer_init(&b, buf, sizeof(buf));
+ isc_buffer_putstr(&b, "HMAC algorithms:");
+ list_hmac_algorithms(&b);
+ (*emit)(&b);
+
+ isc_buffer_init(&b, buf, sizeof(buf));
+ isc_buffer_printf(&b, "TKEY mode 2 support (Diffie-Hellman): %s",
+ (dst_algorithm_supported(DST_ALG_DH) &&
+ dst_algorithm_supported(DST_ALG_HMACMD5))
+ ? "yes"
+ : "non");
+ (*emit)(&b);
+
+ isc_buffer_init(&b, buf, sizeof(buf));
+ isc_buffer_printf(&b, "TKEY mode 3 support (GSS-API): %s",
+ dst_algorithm_supported(DST_ALG_GSSAPI) ? "yes"
+ : "no");
+ (*emit)(&b);
+}
+
+static void
+printversion(bool verbose) {
+ char rndcconf[PATH_MAX], *dot = NULL;
+ isc_mem_t *mctx = NULL;
+ isc_result_t result;
+ isc_buffer_t b;
+ char buf[512];
+#if defined(HAVE_GEOIP2)
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *config = NULL;
+ const cfg_obj_t *defaults = NULL, *obj = NULL;
+#endif /* if defined(HAVE_GEOIP2) */
+
+ printf("%s%s <id:%s>\n", PACKAGE_STRING, PACKAGE_DESCRIPTION,
+ PACKAGE_SRCID);
+
+ if (!verbose) {
+ return;
+ }
+
+ printf("running on %s\n", named_os_uname());
+ printf("built by %s with %s\n", PACKAGE_BUILDER, PACKAGE_CONFIGARGS);
+#ifdef __clang__
+ printf("compiled by CLANG %s\n", __VERSION__);
+#else /* ifdef __clang__ */
+#if defined(__ICC) || defined(__INTEL_COMPILER)
+ printf("compiled by ICC %s\n", __VERSION__);
+#else /* if defined(__ICC) || defined(__INTEL_COMPILER) */
+#ifdef __GNUC__
+ printf("compiled by GCC %s\n", __VERSION__);
+#endif /* ifdef __GNUC__ */
+#endif /* if defined(__ICC) || defined(__INTEL_COMPILER) */
+#endif /* ifdef __clang__ */
+#ifdef _MSC_VER
+ printf("compiled by MSVC %d\n", _MSC_VER);
+#endif /* ifdef _MSC_VER */
+#ifdef __SUNPRO_C
+ printf("compiled by Solaris Studio %x\n", __SUNPRO_C);
+#endif /* ifdef __SUNPRO_C */
+ printf("compiled with OpenSSL version: %s\n", OPENSSL_VERSION_TEXT);
+#if !defined(LIBRESSL_VERSION_NUMBER) && \
+ OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 or higher */
+ printf("linked to OpenSSL version: %s\n",
+ OpenSSL_version(OPENSSL_VERSION));
+
+#else /* if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= \
+ * 0x10100000L */
+ printf("linked to OpenSSL version: %s\n",
+ SSLeay_version(SSLEAY_VERSION));
+#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+ printf("compiled with libuv version: %d.%d.%d\n", UV_VERSION_MAJOR,
+ UV_VERSION_MINOR, UV_VERSION_PATCH);
+ printf("linked to libuv version: %s\n", uv_version_string());
+#if HAVE_LIBNGHTTP2
+ nghttp2_info *nginfo = NULL;
+ printf("compiled with libnghttp2 version: %s\n", NGHTTP2_VERSION);
+ nginfo = nghttp2_version(1);
+ printf("linked to libnghttp2 version: %s\n", nginfo->version_str);
+#endif
+#ifdef HAVE_LIBXML2
+ printf("compiled with libxml2 version: %s\n", LIBXML_DOTTED_VERSION);
+ printf("linked to libxml2 version: %s\n", xmlParserVersion);
+#endif /* ifdef HAVE_LIBXML2 */
+#if defined(HAVE_JSON_C)
+ printf("compiled with json-c version: %s\n", JSON_C_VERSION);
+ printf("linked to json-c version: %s\n", json_c_version());
+#endif /* if defined(HAVE_JSON_C) */
+#if defined(HAVE_ZLIB) && defined(ZLIB_VERSION)
+ printf("compiled with zlib version: %s\n", ZLIB_VERSION);
+ printf("linked to zlib version: %s\n", zlibVersion());
+#endif /* if defined(HAVE_ZLIB) && defined(ZLIB_VERSION) */
+#if defined(HAVE_GEOIP2)
+ /* Unfortunately, no version define on link time */
+ printf("linked to maxminddb version: %s\n", MMDB_lib_version());
+#endif /* if defined(HAVE_GEOIP2) */
+#if defined(HAVE_DNSTAP)
+ printf("compiled with protobuf-c version: %s\n", PROTOBUF_C_VERSION);
+ printf("linked to protobuf-c version: %s\n", protobuf_c_version());
+#endif /* if defined(HAVE_DNSTAP) */
+ printf("threads support is enabled\n");
+
+ isc_mem_create(&mctx);
+ result = dst_lib_init(mctx, named_g_engine);
+ if (result == ISC_R_SUCCESS) {
+ isc_buffer_init(&b, buf, sizeof(buf));
+ format_supported_algorithms(printit);
+ printf("\n");
+ dst_lib_destroy();
+ } else {
+ printf("DST initialization failure: %s\n",
+ isc_result_totext(result));
+ }
+
+ /*
+ * The default rndc.conf and rndc.key paths are in the same
+ * directory, but named only has rndc.key defined internally.
+ * We construct the rndc.conf path from it.
+ */
+ strlcpy(rndcconf, named_g_keyfile, sizeof(rndcconf));
+ dot = strrchr(rndcconf, '.');
+ if (dot != NULL) {
+ size_t len = dot - rndcconf + 1;
+ snprintf(dot + 1, PATH_MAX - len, "conf");
+ }
+
+ /*
+ * Print default configuration paths.
+ */
+ printf("default paths:\n");
+ printf(" named configuration: %s\n", named_g_conffile);
+ printf(" rndc configuration: %s\n", rndcconf);
+ printf(" DNSSEC root key: %s\n", named_g_defaultbindkeys);
+ printf(" nsupdate session key: %s\n", named_g_defaultsessionkeyfile);
+ printf(" named PID file: %s\n", named_g_defaultpidfile);
+ printf(" named lock file: %s\n", named_g_defaultlockfile);
+#if defined(HAVE_GEOIP2)
+#define RTC(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
+ RTC(cfg_parser_create(mctx, named_g_lctx, &parser));
+ RTC(named_config_parsedefaults(parser, &config));
+ RTC(cfg_map_get(config, "options", &defaults));
+ RTC(cfg_map_get(defaults, "geoip-directory", &obj));
+ if (cfg_obj_isstring(obj)) {
+ printf(" geoip-directory: %s\n", cfg_obj_asstring(obj));
+ }
+ cfg_obj_destroy(parser, &config);
+ cfg_parser_destroy(&parser);
+ isc_mem_detach(&mctx);
+#endif /* HAVE_GEOIP2 */
+}
+
+static void
+parse_fuzz_arg(void) {
+ if (!strncmp(isc_commandline_argument, "client:", 7)) {
+ named_g_fuzz_addr = isc_commandline_argument + 7;
+ named_g_fuzz_type = isc_fuzz_client;
+ } else if (!strncmp(isc_commandline_argument, "tcp:", 4)) {
+ named_g_fuzz_addr = isc_commandline_argument + 4;
+ named_g_fuzz_type = isc_fuzz_tcpclient;
+ } else if (!strncmp(isc_commandline_argument, "resolver:", 9)) {
+ named_g_fuzz_addr = isc_commandline_argument + 9;
+ named_g_fuzz_type = isc_fuzz_resolver;
+ } else if (!strncmp(isc_commandline_argument, "http:", 5)) {
+ named_g_fuzz_addr = isc_commandline_argument + 5;
+ named_g_fuzz_type = isc_fuzz_http;
+ } else if (!strncmp(isc_commandline_argument, "rndc:", 5)) {
+ named_g_fuzz_addr = isc_commandline_argument + 5;
+ named_g_fuzz_type = isc_fuzz_rndc;
+ } else {
+ named_main_earlyfatal("unknown fuzzing type '%s'",
+ isc_commandline_argument);
+ }
+}
+
+static void
+parse_T_opt(char *option) {
+ const char *p;
+ char *last = NULL;
+ /*
+ * force the server to behave (or misbehave) in
+ * specified ways for testing purposes.
+ */
+ if (!strcmp(option, "dropedns")) {
+ dropedns = true;
+ } else if (!strcmp(option, "ednsformerr")) {
+ ednsformerr = true;
+ } else if (!strcmp(option, "ednsnotimp")) {
+ ednsnotimp = true;
+ } else if (!strcmp(option, "ednsrefused")) {
+ ednsrefused = true;
+ } else if (!strcmp(option, "fixedlocal")) {
+ fixedlocal = true;
+ } else if (!strcmp(option, "keepstderr")) {
+ named_g_keepstderr = true;
+ } else if (!strcmp(option, "noaa")) {
+ noaa = true;
+ } else if (!strcmp(option, "noedns")) {
+ noedns = true;
+ } else if (!strcmp(option, "nonearest")) {
+ nonearest = true;
+ } else if (!strcmp(option, "nosoa")) {
+ nosoa = true;
+ } else if (!strcmp(option, "nosyslog")) {
+ named_g_nosyslog = true;
+ } else if (!strcmp(option, "notcp")) {
+ notcp = true;
+ } else if (!strncmp(option, "maxcachesize=", 13)) {
+ named_g_maxcachesize = atoi(option + 13);
+ } else if (!strcmp(option, "maxudp512")) {
+ maxudp = 512;
+ } else if (!strcmp(option, "maxudp1460")) {
+ maxudp = 1460;
+ } else if (!strncmp(option, "maxudp=", 7)) {
+ maxudp = atoi(option + 7);
+ if (maxudp <= 0) {
+ named_main_earlyfatal("bad maxudp");
+ }
+ } else if (!strncmp(option, "mkeytimers=", 11)) {
+ p = strtok_r(option + 11, "/", &last);
+ if (p == NULL) {
+ named_main_earlyfatal("bad mkeytimer");
+ }
+
+ dns_zone_mkey_hour = atoi(p);
+ if (dns_zone_mkey_hour == 0) {
+ named_main_earlyfatal("bad mkeytimer");
+ }
+
+ p = strtok_r(NULL, "/", &last);
+ if (p == NULL) {
+ dns_zone_mkey_day = (24 * dns_zone_mkey_hour);
+ dns_zone_mkey_month = (30 * dns_zone_mkey_day);
+ return;
+ }
+
+ dns_zone_mkey_day = atoi(p);
+ if (dns_zone_mkey_day < dns_zone_mkey_hour) {
+ named_main_earlyfatal("bad mkeytimer");
+ }
+
+ p = strtok_r(NULL, "/", &last);
+ if (p == NULL) {
+ dns_zone_mkey_month = (30 * dns_zone_mkey_day);
+ return;
+ }
+
+ dns_zone_mkey_month = atoi(p);
+ if (dns_zone_mkey_month < dns_zone_mkey_day) {
+ named_main_earlyfatal("bad mkeytimer");
+ }
+ } else if (!strcmp(option, "sigvalinsecs")) {
+ sigvalinsecs = true;
+ } else if (!strcmp(option, "transferinsecs")) {
+ transferinsecs = true;
+ } else if (!strcmp(option, "transferslowly")) {
+ transferslowly = true;
+ } else if (!strcmp(option, "transferstuck")) {
+ transferstuck = true;
+ } else if (!strncmp(option, "tat=", 4)) {
+ named_g_tat_interval = atoi(option + 4);
+ } else {
+ fprintf(stderr, "unknown -T flag '%s'\n", option);
+ }
+}
+
+static void
+parse_port(char *arg) {
+ enum { DNSPORT, TLSPORT, HTTPSPORT, HTTPPORT } ptype = DNSPORT;
+ char *value = arg;
+ int port;
+
+ if (strncmp(arg, "dns=", 4) == 0) {
+ value = arg + 4;
+ } else if (strncmp(arg, "tls=", 4) == 0) {
+ value = arg + 4;
+ ptype = TLSPORT;
+ } else if (strncmp(arg, "https=", 6) == 0) {
+ value = arg + 6;
+ ptype = HTTPSPORT;
+ } else if (strncmp(arg, "http=", 5) == 0) {
+ value = arg + 6;
+ ptype = HTTPPORT;
+ }
+
+ port = parse_int(value, "port");
+ if (port < 1 || port > 65535) {
+ named_main_earlyfatal("port '%s' out of range", value);
+ }
+
+ switch (ptype) {
+ case DNSPORT:
+ named_g_port = port;
+ break;
+ case TLSPORT:
+ named_g_tlsport = port;
+ break;
+ case HTTPSPORT:
+ named_g_httpsport = port;
+ break;
+ case HTTPPORT:
+ named_g_httpport = port;
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+static void
+parse_command_line(int argc, char *argv[]) {
+ int ch;
+ const char *p;
+
+ save_command_line(argc, argv);
+
+ /*
+ * NAMED_MAIN_ARGS is defined in main.h, so that it can be used
+ * both by named and by ntservice hooks.
+ */
+ isc_commandline_errprint = false;
+ while ((ch = isc_commandline_parse(argc, argv, NAMED_MAIN_ARGS)) != -1)
+ {
+ switch (ch) {
+ case '4':
+ if (disable4) {
+ named_main_earlyfatal("cannot specify "
+ "-4 and -6");
+ }
+ if (isc_net_probeipv4() != ISC_R_SUCCESS) {
+ named_main_earlyfatal("IPv4 not supported "
+ "by OS");
+ }
+ isc_net_disableipv6();
+ disable6 = true;
+ break;
+ case '6':
+ if (disable6) {
+ named_main_earlyfatal("cannot specify "
+ "-4 and -6");
+ }
+ if (isc_net_probeipv6() != ISC_R_SUCCESS) {
+ named_main_earlyfatal("IPv6 not supported "
+ "by OS");
+ }
+ isc_net_disableipv4();
+ disable4 = true;
+ break;
+ case 'A':
+ parse_fuzz_arg();
+ break;
+ case 'c':
+ named_g_conffile = isc_commandline_argument;
+ named_g_conffileset = true;
+ break;
+ case 'C':
+ printf("# Built-in default values. "
+ "This is NOT the run-time configuration!\n");
+ printf("%s", named_config_getdefault());
+ exit(0);
+ case 'd':
+ named_g_debuglevel = parse_int(isc_commandline_argument,
+ "debug "
+ "level");
+ break;
+ case 'D':
+ /* Descriptive comment for 'ps'. */
+ break;
+ case 'E':
+ named_g_engine = isc_commandline_argument;
+ break;
+ case 'f':
+ named_g_foreground = true;
+ break;
+ case 'g':
+ named_g_foreground = true;
+ named_g_logstderr = true;
+ break;
+ case 'L':
+ named_g_logfile = isc_commandline_argument;
+ break;
+ case 'M':
+ set_flags(isc_commandline_argument, mem_context_flags,
+ &isc_mem_defaultflags);
+ break;
+ case 'm':
+ set_flags(isc_commandline_argument, mem_debug_flags,
+ &isc_mem_debugging);
+ break;
+ case 'N': /* Deprecated. */
+ case 'n':
+ named_g_cpus = parse_int(isc_commandline_argument,
+ "number of cpus");
+ if (named_g_cpus == 0) {
+ named_g_cpus = 1;
+ }
+ break;
+ case 'p':
+ parse_port(isc_commandline_argument);
+ break;
+ case 's':
+ /* XXXRTH temporary syntax */
+ want_stats = true;
+ break;
+ case 'S':
+ /* Formerly maxsocks */
+ break;
+ case 't':
+ /* XXXJAB should we make a copy? */
+ named_g_chrootdir = isc_commandline_argument;
+ break;
+ case 'T': /* NOT DOCUMENTED */
+ parse_T_opt(isc_commandline_argument);
+ break;
+ case 'U':
+ named_g_udpdisp = parse_int(isc_commandline_argument,
+ "number of UDP listeners "
+ "per interface");
+ break;
+ case 'u':
+ named_g_username = isc_commandline_argument;
+ break;
+ case 'v':
+ printversion(false);
+ exit(0);
+ case 'V':
+ printversion(true);
+ exit(0);
+ case 'x':
+ /* Obsolete. No longer in use. Ignore. */
+ break;
+ case 'X':
+ named_g_forcelock = true;
+ if (strcasecmp(isc_commandline_argument, "none") != 0) {
+ named_g_defaultlockfile =
+ isc_commandline_argument;
+ } else {
+ named_g_defaultlockfile = NULL;
+ }
+ break;
+ case 'F':
+ /* Reserved for FIPS mode */
+ FALLTHROUGH;
+ case '?':
+ usage();
+ if (isc_commandline_option == '?') {
+ exit(0);
+ }
+ p = strchr(NAMED_MAIN_ARGS, isc_commandline_option);
+ if (p == NULL || *++p != ':') {
+ named_main_earlyfatal("unknown option '-%c'",
+ isc_commandline_option);
+ } else {
+ named_main_earlyfatal("option '-%c' requires "
+ "an argument",
+ isc_commandline_option);
+ }
+ FALLTHROUGH;
+ default:
+ named_main_earlyfatal("parsing options returned %d",
+ ch);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+ POST(argv);
+
+ if (argc > 0) {
+ usage();
+ named_main_earlyfatal("extra command line arguments");
+ }
+}
+
+static isc_result_t
+create_managers(void) {
+ isc_result_t result;
+
+ INSIST(named_g_cpus_detected > 0);
+
+ if (named_g_cpus == 0) {
+ named_g_cpus = named_g_cpus_detected;
+ }
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "found %u CPU%s, using %u worker thread%s",
+ named_g_cpus_detected, named_g_cpus_detected == 1 ? "" : "s",
+ named_g_cpus, named_g_cpus == 1 ? "" : "s");
+ if (named_g_udpdisp == 0) {
+ named_g_udpdisp = named_g_cpus_detected;
+ }
+ if (named_g_udpdisp > named_g_cpus) {
+ named_g_udpdisp = named_g_cpus;
+ }
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "using %u UDP listener%s per interface", named_g_udpdisp,
+ named_g_udpdisp == 1 ? "" : "s");
+
+ result = isc_managers_create(named_g_mctx, named_g_cpus,
+ 0 /* quantum */, &named_g_netmgr,
+ &named_g_taskmgr, &named_g_timermgr);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ isc_nm_maxudp(named_g_netmgr, maxudp);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+destroy_managers(void) {
+ isc_managers_destroy(&named_g_netmgr, &named_g_taskmgr,
+ &named_g_timermgr);
+}
+
+static void
+setup(void) {
+ isc_result_t result;
+ isc_resourcevalue_t old_openfiles;
+ ns_server_t *sctx;
+#ifdef HAVE_LIBSCF
+ char *instance = NULL;
+#endif /* ifdef HAVE_LIBSCF */
+
+ /*
+ * Get the user and group information before changing the root
+ * directory, so the administrator does not need to keep a copy
+ * of the user and group databases in the chroot'ed environment.
+ */
+ named_os_inituserinfo(named_g_username);
+
+ /*
+ * Initialize time conversion information
+ */
+ named_os_tzset();
+
+ named_os_opendevnull();
+
+#ifdef HAVE_LIBSCF
+ /* Check if named is under smf control, before chroot. */
+ result = named_smf_get_instance(&instance, 0, named_g_mctx);
+ /* We don't care about instance, just check if we got one. */
+ if (result == ISC_R_SUCCESS) {
+ named_smf_got_instance = 1;
+ } else {
+ named_smf_got_instance = 0;
+ }
+ if (instance != NULL) {
+ isc_mem_free(named_g_mctx, instance);
+ }
+#endif /* HAVE_LIBSCF */
+
+ /*
+ * Check for the number of cpu's before named_os_chroot().
+ */
+ named_g_cpus_detected = isc_os_ncpus();
+
+ named_os_chroot(named_g_chrootdir);
+
+ /*
+ * For operating systems which have a capability mechanism, now
+ * is the time to switch to minimal privs and change our user id.
+ * On traditional UNIX systems, this call will be a no-op, and we
+ * will change the user ID after reading the config file the first
+ * time. (We need to read the config file to know which possibly
+ * privileged ports to bind() to.)
+ */
+ named_os_minprivs();
+
+ result = named_log_init(named_g_username != NULL);
+ if (result != ISC_R_SUCCESS) {
+ named_main_earlyfatal("named_log_init() failed: %s",
+ isc_result_totext(result));
+ }
+
+ /*
+ * Now is the time to daemonize (if we're not running in the
+ * foreground). We waited until now because we wanted to get
+ * a valid logging context setup. We cannot daemonize any later,
+ * because calling create_managers() will create threads, which
+ * would be lost after fork().
+ */
+ if (!named_g_foreground) {
+ named_os_daemonize();
+ }
+
+ /*
+ * We call isc_app_start() here as some versions of FreeBSD's fork()
+ * destroys all the signal handling it sets up.
+ */
+ result = isc_app_start();
+ if (result != ISC_R_SUCCESS) {
+ named_main_earlyfatal("isc_app_start() failed: %s",
+ isc_result_totext(result));
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "starting %s%s <id:%s>", PACKAGE_STRING,
+ PACKAGE_DESCRIPTION, PACKAGE_SRCID);
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "running on %s",
+ named_os_uname());
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "built with %s",
+ PACKAGE_CONFIGARGS);
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "running as: %s%s%s", program_name, saved_command_line,
+ ellipsis);
+#ifdef __clang__
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled by CLANG %s", __VERSION__);
+#else /* ifdef __clang__ */
+#if defined(__ICC) || defined(__INTEL_COMPILER)
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled by ICC %s", __VERSION__);
+#else /* if defined(__ICC) || defined(__INTEL_COMPILER) */
+#ifdef __GNUC__
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled by GCC %s", __VERSION__);
+#endif /* ifdef __GNUC__ */
+#endif /* if defined(__ICC) || defined(__INTEL_COMPILER) */
+#endif /* ifdef __clang__ */
+#ifdef _MSC_VER
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled by MSVC %d", _MSC_VER);
+#endif /* ifdef _MSC_VER */
+#ifdef __SUNPRO_C
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled by Solaris Studio %x", __SUNPRO_C);
+#endif /* ifdef __SUNPRO_C */
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled with OpenSSL version: %s",
+ OPENSSL_VERSION_TEXT);
+#if !defined(LIBRESSL_VERSION_NUMBER) && \
+ OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 or higher */
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "linked to OpenSSL version: %s",
+ OpenSSL_version(OPENSSL_VERSION));
+#else /* if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= \
+ * 0x10100000L */
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "linked to OpenSSL version: %s",
+ SSLeay_version(SSLEAY_VERSION));
+#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled with libuv version: %d.%d.%d", UV_VERSION_MAJOR,
+ UV_VERSION_MINOR, UV_VERSION_PATCH);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "linked to libuv version: %s", uv_version_string());
+#ifdef HAVE_LIBXML2
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled with libxml2 version: %s",
+ LIBXML_DOTTED_VERSION);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "linked to libxml2 version: %s", xmlParserVersion);
+#endif /* ifdef HAVE_LIBXML2 */
+#if defined(HAVE_JSON_C)
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled with json-c version: %s", JSON_C_VERSION);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "linked to json-c version: %s", json_c_version());
+#endif /* if defined(HAVE_JSON_C) */
+#if defined(HAVE_ZLIB) && defined(ZLIB_VERSION)
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "compiled with zlib version: %s", ZLIB_VERSION);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "linked to zlib version: %s", zlibVersion());
+#endif /* if defined(HAVE_ZLIB) && defined(ZLIB_VERSION) */
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "----------------------------------------------------");
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "BIND 9 is maintained by Internet Systems Consortium,");
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "Inc. (ISC), a non-profit 501(c)(3) public-benefit ");
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "corporation. Support and training for BIND 9 are ");
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "available at https://www.isc.org/support");
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "----------------------------------------------------");
+
+ /*
+ * Get the initial resource limits.
+ */
+ RUNTIME_CHECK(isc_resource_getlimit(isc_resource_stacksize,
+ &named_g_initstacksize) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_resource_getlimit(isc_resource_datasize,
+ &named_g_initdatasize) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_resource_getlimit(isc_resource_coresize,
+ &named_g_initcoresize) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_resource_getlimit(isc_resource_openfiles,
+ &named_g_initopenfiles) ==
+ ISC_R_SUCCESS);
+
+ /*
+ * System resources cannot effectively be tuned on some systems.
+ * Raise the limit in such cases for safety.
+ */
+ old_openfiles = named_g_initopenfiles;
+ named_os_adjustnofile();
+ RUNTIME_CHECK(isc_resource_getlimit(isc_resource_openfiles,
+ &named_g_initopenfiles) ==
+ ISC_R_SUCCESS);
+ if (old_openfiles != named_g_initopenfiles) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "adjusted limit on open files from "
+ "%" PRIu64 " to "
+ "%" PRIu64,
+ old_openfiles, named_g_initopenfiles);
+ }
+
+ /*
+ * If the named configuration filename is relative, prepend the current
+ * directory's name before possibly changing to another directory.
+ */
+ if (!isc_file_isabsolute(named_g_conffile)) {
+ result = isc_file_absolutepath(named_g_conffile,
+ absolute_conffile,
+ sizeof(absolute_conffile));
+ if (result != ISC_R_SUCCESS) {
+ named_main_earlyfatal("could not construct "
+ "absolute path "
+ "of configuration file: %s",
+ isc_result_totext(result));
+ }
+ named_g_conffile = absolute_conffile;
+ }
+
+ /*
+ * Record the server's startup time.
+ */
+ result = isc_time_now(&named_g_boottime);
+ if (result != ISC_R_SUCCESS) {
+ named_main_earlyfatal("isc_time_now() failed: %s",
+ isc_result_totext(result));
+ }
+
+ result = create_managers();
+ if (result != ISC_R_SUCCESS) {
+ named_main_earlyfatal("create_managers() failed: %s",
+ isc_result_totext(result));
+ }
+
+ named_builtin_init();
+
+ /*
+ * Add calls to register sdb drivers here.
+ */
+ /* xxdb_init(); */
+
+ /*
+ * Register the DLZ "dlopen" driver.
+ */
+ result = dlz_dlopen_init(named_g_mctx);
+ if (result != ISC_R_SUCCESS) {
+ named_main_earlyfatal("dlz_dlopen_init() failed: %s",
+ isc_result_totext(result));
+ }
+
+ named_server_create(named_g_mctx, &named_g_server);
+ ENSURE(named_g_server != NULL);
+ sctx = named_g_server->sctx;
+
+ /*
+ * Report supported algorithms now that dst_lib_init() has
+ * been called via named_server_create().
+ */
+ format_supported_algorithms(logit);
+
+ /*
+ * Modify server context according to command line options
+ */
+ if (disable4) {
+ ns_server_setoption(sctx, NS_SERVER_DISABLE4, true);
+ }
+ if (disable6) {
+ ns_server_setoption(sctx, NS_SERVER_DISABLE6, true);
+ }
+ if (dropedns) {
+ ns_server_setoption(sctx, NS_SERVER_DROPEDNS, true);
+ }
+ if (ednsformerr) { /* STD13 server */
+ ns_server_setoption(sctx, NS_SERVER_EDNSFORMERR, true);
+ }
+ if (ednsnotimp) {
+ ns_server_setoption(sctx, NS_SERVER_EDNSNOTIMP, true);
+ }
+ if (ednsrefused) {
+ ns_server_setoption(sctx, NS_SERVER_EDNSREFUSED, true);
+ }
+ if (fixedlocal) {
+ ns_server_setoption(sctx, NS_SERVER_FIXEDLOCAL, true);
+ }
+ if (noaa) {
+ ns_server_setoption(sctx, NS_SERVER_NOAA, true);
+ }
+ if (noedns) {
+ ns_server_setoption(sctx, NS_SERVER_NOEDNS, true);
+ }
+ if (nonearest) {
+ ns_server_setoption(sctx, NS_SERVER_NONEAREST, true);
+ }
+ if (nosoa) {
+ ns_server_setoption(sctx, NS_SERVER_NOSOA, true);
+ }
+ if (notcp) {
+ ns_server_setoption(sctx, NS_SERVER_NOTCP, true);
+ }
+ if (sigvalinsecs) {
+ ns_server_setoption(sctx, NS_SERVER_SIGVALINSECS, true);
+ }
+ if (transferinsecs) {
+ ns_server_setoption(sctx, NS_SERVER_TRANSFERINSECS, true);
+ }
+ if (transferslowly) {
+ ns_server_setoption(sctx, NS_SERVER_TRANSFERSLOWLY, true);
+ }
+ if (transferstuck) {
+ ns_server_setoption(sctx, NS_SERVER_TRANSFERSTUCK, true);
+ }
+}
+
+static void
+cleanup(void) {
+ destroy_managers();
+
+ if (named_g_mapped != NULL) {
+ dns_acl_detach(&named_g_mapped);
+ }
+
+ named_server_destroy(&named_g_server);
+
+ named_builtin_deinit();
+
+ /*
+ * Add calls to unregister sdb drivers here.
+ */
+ /* xxdb_clear(); */
+
+ /*
+ * Unregister "dlopen" DLZ driver.
+ */
+ dlz_dlopen_clear();
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "exiting");
+ named_log_shutdown();
+}
+
+static char *memstats = NULL;
+
+void
+named_main_setmemstats(const char *filename) {
+ /*
+ * Caller has to ensure locking.
+ */
+
+ if (memstats != NULL) {
+ free(memstats);
+ memstats = NULL;
+ }
+
+ if (filename == NULL) {
+ return;
+ }
+
+ memstats = strdup(filename);
+}
+
+#ifdef HAVE_LIBSCF
+/*
+ * Get FMRI for the named process.
+ */
+isc_result_t
+named_smf_get_instance(char **ins_name, int debug, isc_mem_t *mctx) {
+ scf_handle_t *h = NULL;
+ int namelen;
+ char *instance;
+
+ REQUIRE(ins_name != NULL && *ins_name == NULL);
+
+ if ((h = scf_handle_create(SCF_VERSION)) == NULL) {
+ if (debug) {
+ UNEXPECTED_ERROR("scf_handle_create() failed: %s",
+ scf_strerror(scf_error()));
+ }
+ return (ISC_R_FAILURE);
+ }
+
+ if (scf_handle_bind(h) == -1) {
+ if (debug) {
+ UNEXPECTED_ERROR("scf_handle_bind() failed: %s",
+ scf_strerror(scf_error()));
+ }
+ scf_handle_destroy(h);
+ return (ISC_R_FAILURE);
+ }
+
+ if ((namelen = scf_myname(h, NULL, 0)) == -1) {
+ if (debug) {
+ UNEXPECTED_ERROR("scf_myname() failed: %s",
+ scf_strerror(scf_error()));
+ }
+ scf_handle_destroy(h);
+ return (ISC_R_FAILURE);
+ }
+
+ if ((instance = isc_mem_allocate(mctx, namelen + 1)) == NULL) {
+ UNEXPECTED_ERROR("named_smf_get_instance memory "
+ "allocation failed: %s",
+ isc_result_totext(ISC_R_NOMEMORY));
+ scf_handle_destroy(h);
+ return (ISC_R_FAILURE);
+ }
+
+ if (scf_myname(h, instance, namelen + 1) == -1) {
+ if (debug) {
+ UNEXPECTED_ERROR("scf_myname() failed: %s",
+ scf_strerror(scf_error()));
+ }
+ scf_handle_destroy(h);
+ isc_mem_free(mctx, instance);
+ return (ISC_R_FAILURE);
+ }
+
+ scf_handle_destroy(h);
+ *ins_name = instance;
+ return (ISC_R_SUCCESS);
+}
+#endif /* HAVE_LIBSCF */
+
+/* main entry point, possibly hooked */
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+#ifdef HAVE_LIBSCF
+ char *instance = NULL;
+#endif /* ifdef HAVE_LIBSCF */
+
+#ifdef HAVE_GPERFTOOLS_PROFILER
+ (void)ProfilerStart(NULL);
+#endif /* ifdef HAVE_GPERFTOOLS_PROFILER */
+
+#ifdef HAVE_LIBXML2
+ xmlInitParser();
+#endif /* HAVE_LIBXML2 */
+
+ /*
+ * Technically, this call is superfluous because on startup of the main
+ * program, the portable "C" locale is selected by default. This
+ * explicit call here is for a reference that the BIND 9 code base is
+ * not locale aware and the locale MUST be set to "C" (or "POSIX") when
+ * calling any BIND 9 library code. If you are calling external
+ * libraries that use locale, such calls must be wrapped into
+ * setlocale(LC_ALL, ""); before the call and setlocale(LC_ALL, "C");
+ * after the call, and no BIND 9 library calls must be made in between.
+ */
+ setlocale(LC_ALL, "C");
+
+ /*
+ * Record version in core image.
+ * strings named.core | grep "named version:"
+ */
+ strlcat(version,
+#if defined(NO_VERSION_DATE) || !defined(__DATE__)
+ "named version: BIND " PACKAGE_VERSION " <" PACKAGE_SRCID ">",
+#else
+ "named version: BIND " PACKAGE_VERSION " <" PACKAGE_SRCID
+ "> (" __DATE__ ")",
+#endif
+ sizeof(version));
+ result = isc_file_progname(*argv, program_name, sizeof(program_name));
+ if (result != ISC_R_SUCCESS) {
+ named_main_earlyfatal("program name too long");
+ }
+
+ isc_assertion_setcallback(assertion_failed);
+ isc_error_setfatal(library_fatal_error);
+ isc_error_setunexpected(library_unexpected_error);
+
+ named_os_init(program_name);
+
+ parse_command_line(argc, argv);
+
+#ifdef ENABLE_AFL
+ if (named_g_fuzz_type != isc_fuzz_none) {
+ named_fuzz_setup();
+ }
+
+ if (named_g_fuzz_type == isc_fuzz_resolver) {
+ dns_resolver_setfuzzing();
+ } else if (named_g_fuzz_type == isc_fuzz_http) {
+ isc_httpd_setfinishhook(named_fuzz_notify);
+ }
+#endif /* ifdef ENABLE_AFL */
+ /*
+ * Warn about common configuration error.
+ */
+ if (named_g_chrootdir != NULL) {
+ int len = strlen(named_g_chrootdir);
+ if (strncmp(named_g_chrootdir, named_g_conffile, len) == 0 &&
+ (named_g_conffile[len] == '/' ||
+ named_g_conffile[len] == '\\'))
+ {
+ named_main_earlywarning("config filename (-c %s) "
+ "contains chroot path (-t %s)",
+ named_g_conffile,
+ named_g_chrootdir);
+ }
+ }
+
+ isc_mem_create(&named_g_mctx);
+ isc_mem_setname(named_g_mctx, "main");
+
+ setup();
+ INSIST(named_g_server != NULL);
+
+ /*
+ * Start things running and then wait for a shutdown request
+ * or reload.
+ */
+ do {
+ result = isc_app_run();
+
+ if (result == ISC_R_RELOAD) {
+ named_server_reloadwanted(named_g_server);
+ } else if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR("isc_app_run(): %s",
+ isc_result_totext(result));
+ /*
+ * Force exit.
+ */
+ result = ISC_R_SUCCESS;
+ }
+ } while (result != ISC_R_SUCCESS);
+
+#ifdef HAVE_LIBSCF
+ if (named_smf_want_disable == 1) {
+ result = named_smf_get_instance(&instance, 1, named_g_mctx);
+ if (result == ISC_R_SUCCESS && instance != NULL) {
+ if (smf_disable_instance(instance, 0) != 0) {
+ UNEXPECTED_ERROR("smf_disable_instance() "
+ "failed for %s : %s",
+ instance,
+ scf_strerror(scf_error()));
+ }
+ }
+ if (instance != NULL) {
+ isc_mem_free(named_g_mctx, instance);
+ }
+ }
+#endif /* HAVE_LIBSCF */
+
+ cleanup();
+
+ if (want_stats) {
+ isc_mem_stats(named_g_mctx, stdout);
+ }
+
+ if (named_g_memstatistics && memstats != NULL) {
+ FILE *fp = NULL;
+ result = isc_stdio_open(memstats, "w", &fp);
+ if (result == ISC_R_SUCCESS) {
+ isc_mem_stats(named_g_mctx, fp);
+ (void)isc_stdio_close(fp);
+ }
+ }
+ isc_mem_destroy(&named_g_mctx);
+ isc_mem_checkdestroyed(stderr);
+
+ named_main_setmemstats(NULL);
+
+ isc_app_finish();
+
+ named_os_closedevnull();
+
+ named_os_shutdown();
+
+#ifdef HAVE_LIBXML2
+ xmlCleanupParser();
+#endif /* HAVE_LIBXML2 */
+
+#ifdef HAVE_GPERFTOOLS_PROFILER
+ ProfilerStop();
+#endif /* ifdef HAVE_GPERFTOOLS_PROFILER */
+
+ return (0);
+}
diff --git a/bin/named/named.conf.rst b/bin/named/named.conf.rst
new file mode 100644
index 0000000..8e93f8b
--- /dev/null
+++ b/bin/named/named.conf.rst
@@ -0,0 +1,67 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: named.conf
+
+named.conf - configuration file for **named**
+---------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`named.conf`
+
+Description
+~~~~~~~~~~~
+
+:file:`named.conf` is the configuration file for :iscman:`named`.
+
+For complete documentation about the configuration statements, please refer to
+the Configuration Reference section in the BIND 9 Administrator Reference
+Manual.
+
+Statements are enclosed in braces and terminated with a semi-colon.
+Clauses in the statements are also semi-colon terminated. The usual
+comment styles are supported:
+
+C style: /\* \*/
+
+C++ style: // to end of line
+
+Unix style: # to end of line
+
+.. literalinclude:: ../../doc/misc/options
+
+Any of these zone statements can also be set inside the view statement.
+
+.. literalinclude:: ../../doc/misc/primary.zoneopt
+.. literalinclude:: ../../doc/misc/secondary.zoneopt
+.. literalinclude:: ../../doc/misc/mirror.zoneopt
+.. literalinclude:: ../../doc/misc/forward.zoneopt
+.. literalinclude:: ../../doc/misc/hint.zoneopt
+.. literalinclude:: ../../doc/misc/redirect.zoneopt
+.. literalinclude:: ../../doc/misc/static-stub.zoneopt
+.. literalinclude:: ../../doc/misc/stub.zoneopt
+.. literalinclude:: ../../doc/misc/delegation-only.zoneopt
+.. literalinclude:: ../../doc/misc/in-view.zoneopt
+
+Files
+~~~~~
+
+|named_conf|
+
+See Also
+~~~~~~~~
+
+:iscman:`named(8) <named>`, :iscman:`named-checkconf(8) <named-checkconf>`, :iscman:`rndc(8) <rndc>`, :iscman:`rndc-confgen(8) <rndc-confgen>`, :iscman:`tsig-keygen(8) <tsig-keygen>`, BIND 9 Administrator Reference Manual.
+
diff --git a/bin/named/named.rst b/bin/named/named.rst
new file mode 100644
index 0000000..dc6e46d
--- /dev/null
+++ b/bin/named/named.rst
@@ -0,0 +1,254 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: named
+.. program:: named
+.. _man_named:
+
+named - Internet domain name server
+-----------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`named` [ [**-4**] | [**-6**] ] [**-c** config-file] [**-C**] [**-d** debug-level] [**-D** string] [**-E** engine-name] [**-f**] [**-g**] [**-L** logfile] [**-M** option] [**-m** flag] [**-n** #cpus] [**-p** port] [**-s**] [**-t** directory] [**-U** #listeners] [**-u** user] [**-v**] [**-V**] [**-X** lock-file]
+
+Description
+~~~~~~~~~~~
+
+:program:`named` is a Domain Name System (DNS) server, part of the BIND 9
+distribution from ISC. For more information on the DNS, see :rfc:`1033`,
+:rfc:`1034`, and :rfc:`1035`.
+
+When invoked without arguments, :program:`named` reads the default
+configuration file |named_conf|, reads any initial data, and
+listens for queries.
+
+Options
+~~~~~~~
+
+.. option:: -4
+
+ This option tells :program:`named` to use only IPv4, even if the host machine is capable of IPv6. :option:`-4` and
+ :option:`-6` are mutually exclusive.
+
+.. option:: -6
+
+ This option tells :program:`named` to use only IPv6, even if the host machine is capable of IPv4. :option:`-4` and
+ :option:`-6` are mutually exclusive.
+
+.. option:: -c config-file
+
+ This option tells :program:`named` to use ``config-file`` as its configuration file instead of the default,
+ |named_conf|. To ensure that the configuration file
+ can be reloaded after the server has changed its working directory
+ due to to a possible ``directory`` option in the configuration file,
+ ``config-file`` should be an absolute pathname.
+
+.. option:: -C
+
+ This option prints out the default built-in configuration and exits.
+
+ NOTE: This is for debugging purposes only and is not an
+ accurate representation of the actual configuration used by :iscman:`named`
+ at runtime.
+
+.. option:: -d debug-level
+
+ This option sets the daemon's debug level to ``debug-level``. Debugging traces from
+ :program:`named` become more verbose as the debug level increases.
+
+.. option:: -D string
+
+ This option specifies a string that is used to identify a instance of :program:`named`
+ in a process listing. The contents of ``string`` are not examined.
+
+.. option:: -E engine-name
+
+ When applicable, this option specifies the hardware to use for cryptographic
+ operations, such as a secure key store used for signing.
+
+ When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL
+ engine identifier that drives the cryptographic accelerator or
+ hardware service module (usually ``pkcs11``).
+
+.. option:: -f
+
+ This option runs the server in the foreground (i.e., do not daemonize).
+
+.. option:: -g
+
+ This option runs the server in the foreground and forces all logging to ``stderr``.
+
+.. option:: -L logfile
+
+ This option sets the log to the file ``logfile`` by default, instead of the system log.
+
+.. option:: -M option
+
+ This option sets the default (comma-separated) memory context
+ options. The possible flags are:
+
+ - ``fill``: fill blocks of memory with tag values when they are
+ allocated or freed, to assist debugging of memory problems; this is
+ the implicit default if :program:`named` has been compiled with
+ ``--enable-developer``.
+
+ - ``nofill``: disable the behavior enabled by ``fill``; this is the
+ implicit default unless :program:`named` has been compiled with
+ ``--enable-developer``.
+
+.. option:: -m flag
+
+ This option turns on memory usage debugging flags. Possible flags are ``usage``,
+ ``trace``, ``record``, ``size``, and ``mctx``. These correspond to the
+ ``ISC_MEM_DEBUGXXXX`` flags described in ``<isc/mem.h>``.
+
+.. option:: -n #cpus
+
+ This option creates ``#cpus`` worker threads to take advantage of multiple CPUs. If
+ not specified, :program:`named` tries to determine the number of CPUs
+ present and creates one thread per CPU. If it is unable to determine
+ the number of CPUs, a single worker thread is created.
+
+.. option:: -p value
+
+ This option specifies the port(s) on which the server will listen
+ for queries. If ``value`` is of the form ``<portnum>`` or
+ ``dns=<portnum>``, the server will listen for DNS queries on
+ ``portnum``; if not not specified, the default is port 53. If
+ ``value`` is of the form ``tls=<portnum>``, the server will
+ listen for TLS queries on ``portnum``; the default is 853.
+ If ``value`` is of the form ``https=<portnum>``, the server will
+ listen for HTTPS queries on ``portnum``; the default is 443.
+ If ``value`` is of the form ``http=<portnum>``, the server will
+ listen for HTTP queries on ``portnum``; the default is 80.
+
+.. option:: -s
+
+ This option writes memory usage statistics to ``stdout`` on exit.
+
+.. note::
+
+ This option is mainly of interest to BIND 9 developers and may be
+ removed or changed in a future release.
+
+.. option:: -S #max-socks
+
+ This option is deprecated and no longer has any function.
+
+.. warning::
+
+ This option should be unnecessary for the vast majority of users.
+ The use of this option could even be harmful, because the specified
+ value may exceed the limitation of the underlying system API. It
+ is therefore set only when the default configuration causes
+ exhaustion of file descriptors and the operational environment is
+ known to support the specified number of sockets. Note also that
+ the actual maximum number is normally slightly fewer than the
+ specified value, because :program:`named` reserves some file descriptors
+ for its internal use.
+
+.. option:: -t directory
+
+ This option tells :program:`named` to chroot to ``directory`` after processing the command-line arguments, but
+ before reading the configuration file.
+
+.. warning::
+
+ This option should be used in conjunction with the :option:`-u` option,
+ as chrooting a process running as root doesn't enhance security on
+ most systems; the way ``chroot`` is defined allows a process
+ with root privileges to escape a chroot jail.
+
+.. option:: -U #listeners
+
+ This option tells :program:`named` the number of ``#listeners`` worker threads to listen on, for incoming UDP packets on
+ each address. If not specified, :program:`named` calculates a default
+ value based on the number of detected CPUs: 1 for 1 CPU, and the
+ number of detected CPUs minus one for machines with more than 1 CPU.
+ This cannot be increased to a value higher than the number of CPUs.
+ If :option:`-n` has been set to a higher value than the number of detected
+ CPUs, then :option:`-U` may be increased as high as that value, but no
+ higher.
+
+.. option:: -u user
+
+ This option sets the setuid to ``user`` after completing privileged operations, such as
+ creating sockets that listen on privileged ports.
+
+.. note::
+
+ On Linux, :program:`named` uses the kernel's capability mechanism to drop
+ all root privileges except the ability to ``bind`` to a
+ privileged port and set process resource limits. Unfortunately,
+ this means that the :option:`-u` option only works when :program:`named` is run
+ on kernel 2.2.18 or later, or kernel 2.3.99-pre3 or later, since
+ previous kernels did not allow privileges to be retained after
+ ``setuid``.
+
+.. option:: -v
+
+ This option reports the version number and exits.
+
+.. option:: -V
+
+ This option reports the version number, build options, supported
+ cryptographics algorithms, and exits.
+
+.. option:: -X lock-file
+
+ This option acquires a lock on the specified file at runtime; this helps to
+ prevent duplicate :program:`named` instances from running simultaneously.
+ Use of this option overrides the ``lock-file`` option in
+ :iscman:`named.conf`. If set to ``none``, the lock file check is disabled.
+
+Signals
+~~~~~~~
+
+In routine operation, signals should not be used to control the
+nameserver; :iscman:`rndc` should be used instead.
+
+SIGHUP
+ This signal forces a reload of the server.
+
+SIGINT, SIGTERM
+ These signals shut down the server.
+
+The result of sending any other signals to the server is undefined.
+
+Configuration
+~~~~~~~~~~~~~
+
+The :program:`named` configuration file is too complex to describe in detail
+here. A complete description is provided in the BIND 9 Administrator
+Reference Manual.
+
+:program:`named` inherits the ``umask`` (file creation mode mask) from the
+parent process. If files created by :program:`named`, such as journal files,
+need to have custom permissions, the ``umask`` should be set explicitly
+in the script used to start the :program:`named` process.
+
+Files
+~~~~~
+
+|named_conf|
+ The default configuration file.
+
+|named_pid|
+ The default process-id file.
+
+See Also
+~~~~~~~~
+
+:rfc:`1033`, :rfc:`1034`, :rfc:`1035`, :iscman:`named-checkconf(8) <named-checkconf>`, :iscman:`named-checkzone(8) <named-checkzone>`, :iscman:`rndc(8) <rndc>`, :iscman:`named.conf(5) <named.conf>`, BIND 9 Administrator Reference Manual.
diff --git a/bin/named/os.c b/bin/named/os.c
new file mode 100644
index 0000000..7af4729
--- /dev/null
+++ b/bin/named/os.c
@@ -0,0 +1,932 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/types.h> /* dev_t FreeBSD 2.1 */
+#ifdef HAVE_UNAME
+#include <sys/utsname.h>
+#endif /* ifdef HAVE_UNAME */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#ifdef HAVE_TZSET
+#include <time.h>
+#endif /* ifdef HAVE_TZSET */
+#include <unistd.h>
+
+#include <isc/buffer.h>
+#include <isc/file.h>
+#include <isc/print.h>
+#include <isc/resource.h>
+#include <isc/result.h>
+#include <isc/strerr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <named/globals.h>
+#include <named/main.h>
+#include <named/os.h>
+#ifdef HAVE_LIBSCF
+#include <named/smf_globals.h>
+#endif /* ifdef HAVE_LIBSCF */
+
+static char *pidfile = NULL;
+static char *lockfile = NULL;
+static int devnullfd = -1;
+static int singletonfd = -1;
+
+#ifndef ISC_FACILITY
+#define ISC_FACILITY LOG_DAEMON
+#endif /* ifndef ISC_FACILITY */
+
+static struct passwd *runas_pw = NULL;
+static bool done_setuid = false;
+static int dfd[2] = { -1, -1 };
+
+#ifdef HAVE_SYS_CAPABILITY_H
+
+static bool non_root = false;
+static bool non_root_caps = false;
+
+#include <sys/capability.h>
+#include <sys/prctl.h>
+
+static void
+linux_setcaps(cap_t caps) {
+ char strbuf[ISC_STRERRORSIZE];
+
+ if ((getuid() != 0 && !non_root_caps) || non_root) {
+ return;
+ }
+ if (cap_set_proc(caps) < 0) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlyfatal("cap_set_proc() failed: %s:"
+ " please ensure that the capset kernel"
+ " module is loaded. see insmod(8)",
+ strbuf);
+ }
+}
+
+#define SET_CAP(flag) \
+ do { \
+ cap_flag_value_t curval; \
+ capval = (flag); \
+ err = cap_get_flag(curcaps, capval, CAP_PERMITTED, &curval); \
+ if (err != -1 && curval) { \
+ err = cap_set_flag(caps, CAP_EFFECTIVE, 1, &capval, \
+ CAP_SET); \
+ if (err == -1) { \
+ strerror_r(errno, strbuf, sizeof(strbuf)); \
+ named_main_earlyfatal("cap_set_proc failed: " \
+ "%s", \
+ strbuf); \
+ } \
+ \
+ err = cap_set_flag(caps, CAP_PERMITTED, 1, &capval, \
+ CAP_SET); \
+ if (err == -1) { \
+ strerror_r(errno, strbuf, sizeof(strbuf)); \
+ named_main_earlyfatal("cap_set_proc failed: " \
+ "%s", \
+ strbuf); \
+ } \
+ } \
+ } while (0)
+#define INIT_CAP \
+ do { \
+ caps = cap_init(); \
+ if (caps == NULL) { \
+ strerror_r(errno, strbuf, sizeof(strbuf)); \
+ named_main_earlyfatal("cap_init failed: %s", strbuf); \
+ } \
+ curcaps = cap_get_proc(); \
+ if (curcaps == NULL) { \
+ strerror_r(errno, strbuf, sizeof(strbuf)); \
+ named_main_earlyfatal("cap_get_proc failed: %s", \
+ strbuf); \
+ } \
+ } while (0)
+#define FREE_CAP \
+ { \
+ cap_free(caps); \
+ cap_free(curcaps); \
+ } \
+ while (0)
+
+static void
+linux_initialprivs(void) {
+ cap_t caps;
+ cap_t curcaps;
+ cap_value_t capval;
+ char strbuf[ISC_STRERRORSIZE];
+ int err;
+
+ /*%
+ * We don't need most privileges, so we drop them right away.
+ * Later on linux_minprivs() will be called, which will drop our
+ * capabilities to the minimum needed to run the server.
+ */
+ INIT_CAP;
+
+ /*
+ * We need to be able to bind() to privileged ports, notably port 53!
+ */
+ SET_CAP(CAP_NET_BIND_SERVICE);
+
+ /*
+ * We need chroot() initially too.
+ */
+ SET_CAP(CAP_SYS_CHROOT);
+
+ /*
+ * We need setuid() as the kernel supports keeping capabilities after
+ * setuid().
+ */
+ SET_CAP(CAP_SETUID);
+
+ /*
+ * Since we call initgroups, we need this.
+ */
+ SET_CAP(CAP_SETGID);
+
+ /*
+ * Without this, we run into problems reading a configuration file
+ * owned by a non-root user and non-world-readable on startup.
+ */
+ SET_CAP(CAP_DAC_READ_SEARCH);
+
+ /*
+ * XXX We might want to add CAP_SYS_RESOURCE, though it's not
+ * clear it would work right given the way linuxthreads work.
+ * XXXDCL But since we need to be able to set the maximum number
+ * of files, the stack size, data size, and core dump size to
+ * support named.conf options, this is now being added to test.
+ */
+ SET_CAP(CAP_SYS_RESOURCE);
+
+ /*
+ * We need to be able to set the ownership of the containing
+ * directory of the pid file when we create it.
+ */
+ SET_CAP(CAP_CHOWN);
+
+ linux_setcaps(caps);
+
+ FREE_CAP;
+}
+
+static void
+linux_minprivs(void) {
+ cap_t caps;
+ cap_t curcaps;
+ cap_value_t capval;
+ char strbuf[ISC_STRERRORSIZE];
+ int err;
+
+ INIT_CAP;
+ /*%
+ * Drop all privileges except the ability to bind() to privileged
+ * ports.
+ *
+ * It's important that we drop CAP_SYS_CHROOT. If we didn't, it
+ * chroot() could be used to escape from the chrooted area.
+ */
+
+ SET_CAP(CAP_NET_BIND_SERVICE);
+
+ /*
+ * XXX We might want to add CAP_SYS_RESOURCE, though it's not
+ * clear it would work right given the way linuxthreads work.
+ * XXXDCL But since we need to be able to set the maximum number
+ * of files, the stack size, data size, and core dump size to
+ * support named.conf options, this is now being added to test.
+ */
+ SET_CAP(CAP_SYS_RESOURCE);
+
+ linux_setcaps(caps);
+
+ FREE_CAP;
+}
+
+static void
+linux_keepcaps(void) {
+ char strbuf[ISC_STRERRORSIZE];
+ /*%
+ * Ask the kernel to allow us to keep our capabilities after we
+ * setuid().
+ */
+
+ if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
+ if (errno != EINVAL) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlyfatal("prctl() failed: %s", strbuf);
+ }
+ } else {
+ non_root_caps = true;
+ if (getuid() != 0) {
+ non_root = true;
+ }
+ }
+}
+
+#endif /* HAVE_SYS_CAPABILITY_H */
+
+static void
+setup_syslog(const char *progname) {
+ int options;
+
+ options = LOG_PID;
+#ifdef LOG_NDELAY
+ options |= LOG_NDELAY;
+#endif /* ifdef LOG_NDELAY */
+ openlog(isc_file_basename(progname), options, ISC_FACILITY);
+}
+
+void
+named_os_init(const char *progname) {
+ setup_syslog(progname);
+#ifdef HAVE_SYS_CAPABILITY_H
+ linux_initialprivs();
+#endif /* ifdef HAVE_SYS_CAPABILITY_H */
+#ifdef SIGXFSZ
+ signal(SIGXFSZ, SIG_IGN);
+#endif /* ifdef SIGXFSZ */
+}
+
+void
+named_os_daemonize(void) {
+ pid_t pid;
+ char strbuf[ISC_STRERRORSIZE];
+
+ if (pipe(dfd) == -1) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlyfatal("pipe(): %s", strbuf);
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlyfatal("fork(): %s", strbuf);
+ }
+ if (pid != 0) {
+ int n;
+ /*
+ * Wait for the child to finish loading for the first time.
+ * This would be so much simpler if fork() worked once we
+ * were multi-threaded.
+ */
+ (void)close(dfd[1]);
+ do {
+ char buf;
+ n = read(dfd[0], &buf, 1);
+ if (n == 1) {
+ _exit(0);
+ }
+ } while (n == -1 && errno == EINTR);
+ _exit(1);
+ }
+ (void)close(dfd[0]);
+
+ /*
+ * We're the child.
+ */
+
+ if (setsid() == -1) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlyfatal("setsid(): %s", strbuf);
+ }
+
+ /*
+ * Try to set stdin, stdout, and stderr to /dev/null, but press
+ * on even if it fails.
+ *
+ * XXXMLG The close() calls here are unneeded on all but NetBSD, but
+ * are harmless to include everywhere. dup2() is supposed to close
+ * the FD if it is in use, but unproven-pthreads-0.16 is broken
+ * and will end up closing the wrong FD. This will be fixed eventually,
+ * and these calls will be removed.
+ */
+ if (devnullfd != -1) {
+ if (devnullfd != STDIN_FILENO) {
+ (void)close(STDIN_FILENO);
+ (void)dup2(devnullfd, STDIN_FILENO);
+ }
+ if (devnullfd != STDOUT_FILENO) {
+ (void)close(STDOUT_FILENO);
+ (void)dup2(devnullfd, STDOUT_FILENO);
+ }
+ if (devnullfd != STDERR_FILENO && !named_g_keepstderr) {
+ (void)close(STDERR_FILENO);
+ (void)dup2(devnullfd, STDERR_FILENO);
+ }
+ }
+}
+
+void
+named_os_started(void) {
+ char buf = 0;
+
+ /*
+ * Signal to the parent that we started successfully.
+ */
+ if (dfd[0] != -1 && dfd[1] != -1) {
+ if (write(dfd[1], &buf, 1) != 1) {
+ named_main_earlyfatal("unable to signal parent that we "
+ "otherwise started "
+ "successfully.");
+ }
+ close(dfd[1]);
+ dfd[0] = dfd[1] = -1;
+ }
+}
+
+void
+named_os_opendevnull(void) {
+ devnullfd = open("/dev/null", O_RDWR, 0);
+}
+
+void
+named_os_closedevnull(void) {
+ if (devnullfd != STDIN_FILENO && devnullfd != STDOUT_FILENO &&
+ devnullfd != STDERR_FILENO)
+ {
+ close(devnullfd);
+ devnullfd = -1;
+ }
+}
+
+static bool
+all_digits(const char *s) {
+ if (*s == '\0') {
+ return (false);
+ }
+ while (*s != '\0') {
+ if (!isdigit((unsigned char)(*s))) {
+ return (false);
+ }
+ s++;
+ }
+ return (true);
+}
+
+void
+named_os_chroot(const char *root) {
+ char strbuf[ISC_STRERRORSIZE];
+#ifdef HAVE_LIBSCF
+ named_smf_chroot = 0;
+#endif /* ifdef HAVE_LIBSCF */
+ if (root != NULL) {
+#ifdef HAVE_CHROOT
+ if (chroot(root) < 0) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlyfatal("chroot(): %s", strbuf);
+ }
+#else /* ifdef HAVE_CHROOT */
+ named_main_earlyfatal("chroot(): disabled");
+#endif /* ifdef HAVE_CHROOT */
+ if (chdir("/") < 0) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlyfatal("chdir(/): %s", strbuf);
+ }
+#ifdef HAVE_LIBSCF
+ /* Set named_smf_chroot flag on successful chroot. */
+ named_smf_chroot = 1;
+#endif /* ifdef HAVE_LIBSCF */
+ }
+}
+
+void
+named_os_inituserinfo(const char *username) {
+ if (username == NULL) {
+ return;
+ }
+
+ if (all_digits(username)) {
+ runas_pw = getpwuid((uid_t)atoi(username));
+ } else {
+ runas_pw = getpwnam(username);
+ }
+ endpwent();
+
+ if (runas_pw == NULL) {
+ named_main_earlyfatal("user '%s' unknown", username);
+ }
+
+ if (getuid() == 0) {
+ char strbuf[ISC_STRERRORSIZE];
+ if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlyfatal("initgroups(): %s", strbuf);
+ }
+ }
+}
+
+void
+named_os_changeuser(void) {
+ char strbuf[ISC_STRERRORSIZE];
+ if (runas_pw == NULL || done_setuid) {
+ return;
+ }
+
+ done_setuid = true;
+
+ if (setgid(runas_pw->pw_gid) < 0) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlyfatal("setgid(): %s", strbuf);
+ }
+
+ if (setuid(runas_pw->pw_uid) < 0) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlyfatal("setuid(): %s", strbuf);
+ }
+
+#if defined(HAVE_SYS_CAPABILITY_H)
+ /*
+ * Restore the ability of named to drop core after the setuid()
+ * call has disabled it.
+ */
+ if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlywarning("prctl(PR_SET_DUMPABLE) failed: %s",
+ strbuf);
+ }
+
+ linux_minprivs();
+#endif /* if defined(HAVE_SYS_CAPABILITY_H) */
+}
+
+uid_t
+ns_os_uid(void) {
+ if (runas_pw == NULL) {
+ return (0);
+ }
+ return (runas_pw->pw_uid);
+}
+
+void
+named_os_adjustnofile(void) {
+#if defined(__linux__) || defined(__sun)
+ isc_result_t result;
+ isc_resourcevalue_t newvalue;
+
+ /*
+ * Linux: max number of open files specified by one thread doesn't seem
+ * to apply to other threads on Linux.
+ * Sun: restriction needs to be removed sooner when hundreds of CPUs
+ * are available.
+ */
+ newvalue = ISC_RESOURCE_UNLIMITED;
+
+ result = isc_resource_setlimit(isc_resource_openfiles, newvalue);
+ if (result != ISC_R_SUCCESS) {
+ named_main_earlywarning("couldn't adjust limit on open files");
+ }
+#endif /* if defined(__linux__) || defined(__sun) */
+}
+
+void
+named_os_minprivs(void) {
+#if defined(HAVE_SYS_CAPABILITY_H)
+ linux_keepcaps();
+ named_os_changeuser();
+ linux_minprivs();
+#endif /* if defined(HAVE_SYS_CAPABILITY_H) */
+}
+
+static int
+safe_open(const char *filename, mode_t mode, bool append) {
+ int fd;
+ struct stat sb;
+
+ if (stat(filename, &sb) == -1) {
+ if (errno != ENOENT) {
+ return (-1);
+ }
+ } else if ((sb.st_mode & S_IFREG) == 0) {
+ errno = EOPNOTSUPP;
+ return (-1);
+ }
+
+ if (append) {
+ fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, mode);
+ } else {
+ if (unlink(filename) < 0 && errno != ENOENT) {
+ return (-1);
+ }
+ fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, mode);
+ }
+ return (fd);
+}
+
+static void
+cleanup_pidfile(void) {
+ int n;
+ if (pidfile != NULL) {
+ n = unlink(pidfile);
+ if (n == -1 && errno != ENOENT) {
+ named_main_earlywarning("unlink '%s': failed", pidfile);
+ }
+ free(pidfile);
+ }
+ pidfile = NULL;
+}
+
+static void
+cleanup_lockfile(void) {
+ if (singletonfd != -1) {
+ close(singletonfd);
+ singletonfd = -1;
+ }
+
+ if (lockfile != NULL) {
+ int n = unlink(lockfile);
+ if (n == -1 && errno != ENOENT) {
+ named_main_earlywarning("unlink '%s': failed",
+ lockfile);
+ }
+ free(lockfile);
+ lockfile = NULL;
+ }
+}
+
+/*
+ * Ensure that a directory exists.
+ * NOTE: This function overwrites the '/' characters in 'filename' with
+ * nulls. The caller should copy the filename to a fresh buffer first.
+ */
+static int
+mkdirpath(char *filename, void (*report)(const char *, ...)) {
+ char *slash = strrchr(filename, '/');
+ char strbuf[ISC_STRERRORSIZE];
+ unsigned int mode;
+
+ if (slash != NULL && slash != filename) {
+ struct stat sb;
+ *slash = '\0';
+
+ if (stat(filename, &sb) == -1) {
+ if (errno != ENOENT) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ (*report)("couldn't stat '%s': %s", filename,
+ strbuf);
+ goto error;
+ }
+ if (mkdirpath(filename, report) == -1) {
+ goto error;
+ }
+ /*
+ * Handle "//", "/./" and "/../" in path.
+ */
+ if (!strcmp(slash + 1, "") || !strcmp(slash + 1, ".") ||
+ !strcmp(slash + 1, ".."))
+ {
+ *slash = '/';
+ return (0);
+ }
+ mode = S_IRUSR | S_IWUSR | S_IXUSR; /* u=rwx */
+ mode |= S_IRGRP | S_IXGRP; /* g=rx */
+ mode |= S_IROTH | S_IXOTH; /* o=rx */
+ if (mkdir(filename, mode) == -1) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ (*report)("couldn't mkdir '%s': %s", filename,
+ strbuf);
+ goto error;
+ }
+ if (runas_pw != NULL &&
+ chown(filename, runas_pw->pw_uid,
+ runas_pw->pw_gid) == -1)
+ {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ (*report)("couldn't chown '%s': %s", filename,
+ strbuf);
+ }
+ }
+ *slash = '/';
+ }
+ return (0);
+
+error:
+ *slash = '/';
+ return (-1);
+}
+
+#if !HAVE_SYS_CAPABILITY_H
+static void
+setperms(uid_t uid, gid_t gid) {
+#if defined(HAVE_SETEGID) || defined(HAVE_SETRESGID)
+ char strbuf[ISC_STRERRORSIZE];
+#endif /* if defined(HAVE_SETEGID) || defined(HAVE_SETRESGID) */
+#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID)
+ gid_t oldgid, tmpg;
+#endif /* if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */
+#if !defined(HAVE_SETEUID) && defined(HAVE_SETRESUID)
+ uid_t olduid, tmpu;
+#endif /* if !defined(HAVE_SETEUID) && defined(HAVE_SETRESUID) */
+#if defined(HAVE_SETEGID)
+ if (getegid() != gid && setegid(gid) == -1) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlywarning("unable to set effective "
+ "gid to %ld: %s",
+ (long)gid, strbuf);
+ }
+#elif defined(HAVE_SETRESGID)
+ if (getresgid(&tmpg, &oldgid, &tmpg) == -1 || oldgid != gid) {
+ if (setresgid(-1, gid, -1) == -1) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlywarning("unable to set effective "
+ "gid to %d: %s",
+ gid, strbuf);
+ }
+ }
+#endif /* if defined(HAVE_SETEGID) */
+
+#if defined(HAVE_SETEUID)
+ if (geteuid() != uid && seteuid(uid) == -1) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlywarning("unable to set effective "
+ "uid to %ld: %s",
+ (long)uid, strbuf);
+ }
+#elif defined(HAVE_SETRESUID)
+ if (getresuid(&tmpu, &olduid, &tmpu) == -1 || olduid != uid) {
+ if (setresuid(-1, uid, -1) == -1) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlywarning("unable to set effective "
+ "uid to %d: %s",
+ uid, strbuf);
+ }
+ }
+#endif /* if defined(HAVE_SETEUID) */
+}
+#endif /* !HAVE_SYS_CAPABILITY_H */
+
+FILE *
+named_os_openfile(const char *filename, mode_t mode, bool switch_user) {
+ char strbuf[ISC_STRERRORSIZE], *f;
+ FILE *fp;
+ int fd;
+
+ /*
+ * Make the containing directory if it doesn't exist.
+ */
+ f = strdup(filename);
+ if (f == NULL) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlywarning("couldn't strdup() '%s': %s", filename,
+ strbuf);
+ return (NULL);
+ }
+ if (mkdirpath(f, named_main_earlywarning) == -1) {
+ free(f);
+ return (NULL);
+ }
+ free(f);
+
+ if (switch_user && runas_pw != NULL) {
+ uid_t olduid = getuid();
+ gid_t oldgid = getgid();
+#if HAVE_SYS_CAPABILITY_H
+ REQUIRE(olduid == runas_pw->pw_uid);
+ REQUIRE(oldgid == runas_pw->pw_gid);
+#else /* HAVE_SYS_CAPABILITY_H */
+ /* Set UID/GID to the one we'll be running with eventually */
+ setperms(runas_pw->pw_uid, runas_pw->pw_gid);
+#endif
+ fd = safe_open(filename, mode, false);
+
+#if !HAVE_SYS_CAPABILITY_H
+ /* Restore UID/GID to previous uid/gid */
+ setperms(olduid, oldgid);
+#endif
+
+ if (fd == -1) {
+ fd = safe_open(filename, mode, false);
+ if (fd != -1) {
+ named_main_earlywarning("Required root "
+ "permissions to open "
+ "'%s'.",
+ filename);
+ } else {
+ named_main_earlywarning("Could not open "
+ "'%s'.",
+ filename);
+ }
+ named_main_earlywarning("Please check file and "
+ "directory permissions "
+ "or reconfigure the filename.");
+ }
+ } else {
+ fd = safe_open(filename, mode, false);
+ }
+
+ if (fd < 0) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlywarning("could not open file '%s': %s",
+ filename, strbuf);
+ return (NULL);
+ }
+
+ fp = fdopen(fd, "w");
+ if (fp == NULL) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlywarning("could not fdopen() file '%s': %s",
+ filename, strbuf);
+ }
+
+ return (fp);
+}
+
+void
+named_os_writepidfile(const char *filename, bool first_time) {
+ FILE *fh;
+ pid_t pid;
+ char strbuf[ISC_STRERRORSIZE];
+ void (*report)(const char *, ...);
+
+ /*
+ * The caller must ensure any required synchronization.
+ */
+
+ report = first_time ? named_main_earlyfatal : named_main_earlywarning;
+
+ cleanup_pidfile();
+
+ if (filename == NULL) {
+ return;
+ }
+
+ pidfile = strdup(filename);
+ if (pidfile == NULL) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ (*report)("couldn't strdup() '%s': %s", filename, strbuf);
+ return;
+ }
+
+ fh = named_os_openfile(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH,
+ first_time);
+ if (fh == NULL) {
+ cleanup_pidfile();
+ return;
+ }
+ pid = getpid();
+ if (fprintf(fh, "%ld\n", (long)pid) < 0) {
+ (*report)("fprintf() to pid file '%s' failed", filename);
+ (void)fclose(fh);
+ cleanup_pidfile();
+ return;
+ }
+ if (fflush(fh) == EOF) {
+ (*report)("fflush() to pid file '%s' failed", filename);
+ (void)fclose(fh);
+ cleanup_pidfile();
+ return;
+ }
+ (void)fclose(fh);
+}
+
+bool
+named_os_issingleton(const char *filename) {
+ char strbuf[ISC_STRERRORSIZE];
+ struct flock lock;
+
+ if (singletonfd != -1) {
+ return (true);
+ }
+
+ if (strcasecmp(filename, "none") == 0) {
+ return (true);
+ }
+
+ /*
+ * Make the containing directory if it doesn't exist.
+ */
+ lockfile = strdup(filename);
+ if (lockfile == NULL) {
+ strerror_r(errno, strbuf, sizeof(strbuf));
+ named_main_earlyfatal("couldn't allocate memory for '%s': %s",
+ filename, strbuf);
+ } else {
+ int ret = mkdirpath(lockfile, named_main_earlywarning);
+ if (ret == -1) {
+ named_main_earlywarning("couldn't create '%s'",
+ filename);
+ cleanup_lockfile();
+ return (false);
+ }
+ }
+
+ /*
+ * named_os_openfile() uses safeopen() which removes any existing
+ * files. We can't use that here.
+ */
+ singletonfd = open(filename, O_WRONLY | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (singletonfd == -1) {
+ cleanup_lockfile();
+ return (false);
+ }
+
+ memset(&lock, 0, sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 1;
+
+ /* Non-blocking (does not wait for lock) */
+ if (fcntl(singletonfd, F_SETLK, &lock) == -1) {
+ close(singletonfd);
+ singletonfd = -1;
+ return (false);
+ }
+
+ return (true);
+}
+
+void
+named_os_shutdown(void) {
+ closelog();
+ cleanup_pidfile();
+ cleanup_lockfile();
+}
+
+void
+named_os_shutdownmsg(char *command, isc_buffer_t *text) {
+ char *last, *ptr;
+ pid_t pid;
+
+ /* Skip the command name. */
+ if (strtok_r(command, " \t", &last) == NULL) {
+ return;
+ }
+
+ if ((ptr = strtok_r(NULL, " \t", &last)) == NULL) {
+ return;
+ }
+
+ if (strcmp(ptr, "-p") != 0) {
+ return;
+ }
+
+ pid = getpid();
+
+ (void)isc_buffer_printf(text, "pid: %ld", (long)pid);
+}
+
+void
+named_os_tzset(void) {
+#ifdef HAVE_TZSET
+ tzset();
+#endif /* ifdef HAVE_TZSET */
+}
+
+#ifdef HAVE_UNAME
+static char unamebuf[sizeof(struct utsname)];
+#else
+static const char unamebuf[] = { "unknown architecture" };
+#endif
+static const char *unamep = NULL;
+
+static void
+getuname(void) {
+#ifdef HAVE_UNAME
+ struct utsname uts;
+
+ memset(&uts, 0, sizeof(uts));
+ if (uname(&uts) < 0) {
+ snprintf(unamebuf, sizeof(unamebuf), "unknown architecture");
+ return;
+ }
+
+ snprintf(unamebuf, sizeof(unamebuf), "%s %s %s %s", uts.sysname,
+ uts.machine, uts.release, uts.version);
+#endif /* ifdef HAVE_UNAME */
+ unamep = unamebuf;
+}
+
+const char *
+named_os_uname(void) {
+ if (unamep == NULL) {
+ getuname();
+ }
+ return (unamep);
+}
diff --git a/bin/named/server.c b/bin/named/server.c
new file mode 100644
index 0000000..2f21fc5
--- /dev/null
+++ b/bin/named/server.c
@@ -0,0 +1,16755 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef HAVE_DNSTAP
+#include <fstrm.h>
+#endif
+
+#include <isc/aes.h>
+#include <isc/app.h>
+#include <isc/attributes.h>
+#include <isc/base64.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/hex.h>
+#include <isc/hmac.h>
+#include <isc/httpd.h>
+#include <isc/lex.h>
+#include <isc/meminfo.h>
+#include <isc/netmgr.h>
+#include <isc/nonce.h>
+#include <isc/parseint.h>
+#include <isc/portset.h>
+#include <isc/print.h>
+#include <isc/refcount.h>
+#include <isc/resource.h>
+#include <isc/result.h>
+#include <isc/siphash.h>
+#include <isc/stat.h>
+#include <isc/stats.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/badcache.h>
+#include <dns/cache.h>
+#include <dns/catz.h>
+#include <dns/db.h>
+#include <dns/dispatch.h>
+#include <dns/dlz.h>
+#include <dns/dns64.h>
+#include <dns/dnsrps.h>
+#include <dns/dnssec.h>
+#include <dns/dyndb.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/forward.h>
+#include <dns/geoip.h>
+#include <dns/journal.h>
+#include <dns/kasp.h>
+#include <dns/keymgr.h>
+#include <dns/keytable.h>
+#include <dns/keyvalues.h>
+#include <dns/master.h>
+#include <dns/masterdump.h>
+#include <dns/nsec3.h>
+#include <dns/nta.h>
+#include <dns/order.h>
+#include <dns/peer.h>
+#include <dns/private.h>
+#include <dns/rbt.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/resolver.h>
+#include <dns/rootns.h>
+#include <dns/rriterator.h>
+#include <dns/secalg.h>
+#include <dns/soa.h>
+#include <dns/stats.h>
+#include <dns/time.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+#include <dns/ttl.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+#include <dst/dst.h>
+
+#include <isccfg/grammar.h>
+#include <isccfg/kaspconf.h>
+#include <isccfg/namedconf.h>
+
+#include <ns/client.h>
+#include <ns/hooks.h>
+#include <ns/interfacemgr.h>
+#include <ns/listenlist.h>
+
+#include <bind9/check.h>
+
+#include <named/config.h>
+#include <named/control.h>
+#if defined(HAVE_GEOIP2)
+#include <named/geoip.h>
+#endif /* HAVE_GEOIP2 */
+#include <named/log.h>
+#include <named/logconf.h>
+#include <named/main.h>
+#include <named/os.h>
+#include <named/server.h>
+#include <named/statschannel.h>
+#include <named/tkeyconf.h>
+#include <named/transportconf.h>
+#include <named/tsigconf.h>
+#include <named/zoneconf.h>
+#ifdef HAVE_LIBSCF
+#include <stdlib.h>
+
+#include <named/smf_globals.h>
+#endif /* ifdef HAVE_LIBSCF */
+
+#ifdef HAVE_LMDB
+#include <lmdb.h>
+#define count_newzones count_newzones_db
+#define configure_newzones configure_newzones_db
+#define dumpzone dumpzone_db
+#else /* HAVE_LMDB */
+#define count_newzones count_newzones_file
+#define configure_newzones configure_newzones_file
+#define dumpzone dumpzone_file
+#endif /* HAVE_LMDB */
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t)-1)
+#endif /* ifndef SIZE_MAX */
+
+#ifndef SIZE_AS_PERCENT
+#define SIZE_AS_PERCENT ((size_t)-2)
+#endif /* ifndef SIZE_AS_PERCENT */
+
+#ifdef TUNE_LARGE
+#define RESOLVER_NTASKS_PERCPU 32
+#else
+#define RESOLVER_NTASKS_PERCPU 8
+#endif /* TUNE_LARGE */
+
+/* RFC7828 defines timeout as 16-bit value specified in units of 100
+ * milliseconds, so the maximum and minimum advertised and keepalive
+ * timeouts are capped by the data type (it's ~109 minutes)
+ */
+#define MIN_INITIAL_TIMEOUT UINT32_C(2500) /* 2.5 seconds */
+#define MAX_INITIAL_TIMEOUT UINT32_C(120000) /* 2 minutes */
+#define MIN_IDLE_TIMEOUT UINT32_C(100) /* 0.1 seconds */
+#define MAX_IDLE_TIMEOUT UINT32_C(120000) /* 2 minutes */
+#define MIN_KEEPALIVE_TIMEOUT UINT32_C(100) /* 0.1 seconds */
+#define MAX_KEEPALIVE_TIMEOUT UINT32_C(UINT16_MAX * 100)
+#define MIN_ADVERTISED_TIMEOUT UINT32_C(0) /* No minimum */
+#define MAX_ADVERTISED_TIMEOUT UINT32_C(UINT16_MAX * 100)
+
+/*%
+ * Check an operation for failure. Assumes that the function
+ * using it has a 'result' variable and a 'cleanup' label.
+ */
+#define CHECK(op) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+#define TCHECK(op) \
+ do { \
+ tresult = (op); \
+ if (tresult != ISC_R_SUCCESS) { \
+ isc_buffer_clear(*text); \
+ goto cleanup; \
+ } \
+ } while (0)
+
+#define CHECKM(op, msg) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, \
+ "%s: %s", msg, \
+ isc_result_totext(result)); \
+ goto cleanup; \
+ } \
+ } while (0)
+
+#define CHECKMF(op, msg, file) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, \
+ "%s '%s': %s", msg, file, \
+ isc_result_totext(result)); \
+ goto cleanup; \
+ } \
+ } while (0)
+
+#define CHECKFATAL(op, msg) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) \
+ fatal(server, msg, result); \
+ } while (0)
+
+/*%
+ * Maximum ADB size for views that share a cache. Use this limit to suppress
+ * the total of memory footprint, which should be the main reason for sharing
+ * a cache. Only effective when a finite max-cache-size is specified.
+ * This is currently defined to be 8MB.
+ */
+#define MAX_ADB_SIZE_FOR_CACHESHARE 8388608U
+
+struct named_dispatch {
+ isc_sockaddr_t addr;
+ unsigned int dispatchgen;
+ dns_dispatch_t *dispatch;
+ ISC_LINK(struct named_dispatch) link;
+};
+
+struct named_cache {
+ dns_cache_t *cache;
+ dns_view_t *primaryview;
+ bool needflush;
+ bool adbsizeadjusted;
+ dns_rdataclass_t rdclass;
+ ISC_LINK(named_cache_t) link;
+};
+
+struct dumpcontext {
+ isc_mem_t *mctx;
+ bool dumpcache;
+ bool dumpzones;
+ bool dumpadb;
+ bool dumpbad;
+ bool dumpexpired;
+ bool dumpfail;
+ FILE *fp;
+ ISC_LIST(struct viewlistentry) viewlist;
+ struct viewlistentry *view;
+ struct zonelistentry *zone;
+ dns_dumpctx_t *mdctx;
+ dns_db_t *db;
+ dns_db_t *cache;
+ isc_task_t *task;
+ dns_dbversion_t *version;
+};
+
+struct viewlistentry {
+ dns_view_t *view;
+ ISC_LINK(struct viewlistentry) link;
+ ISC_LIST(struct zonelistentry) zonelist;
+};
+
+struct zonelistentry {
+ dns_zone_t *zone;
+ ISC_LINK(struct zonelistentry) link;
+};
+
+/*%
+ * Configuration context to retain for each view that allows
+ * new zones to be added at runtime.
+ */
+typedef struct ns_cfgctx {
+ isc_mem_t *mctx;
+ cfg_parser_t *conf_parser;
+ cfg_parser_t *add_parser;
+ cfg_obj_t *config;
+ cfg_obj_t *vconfig;
+ cfg_obj_t *nzf_config;
+ cfg_aclconfctx_t *actx;
+} ns_cfgctx_t;
+
+/*%
+ * A function to write out added-zone configuration to the new_zone_file
+ * specified in 'view'. Maybe called by delete_zoneconf().
+ */
+typedef isc_result_t (*nzfwriter_t)(const cfg_obj_t *config, dns_view_t *view);
+
+/*%
+ * Holds state information for the initial zone loading process.
+ * Uses the isc_refcount structure to count the number of views
+ * with pending zone loads, dereferencing as each view finishes.
+ */
+typedef struct {
+ named_server_t *server;
+ bool reconfig;
+ isc_refcount_t refs;
+} ns_zoneload_t;
+
+typedef struct {
+ named_server_t *server;
+} catz_cb_data_t;
+
+typedef struct catz_chgzone_event {
+ ISC_EVENT_COMMON(struct catz_chgzone_event);
+ dns_catz_entry_t *entry;
+ dns_catz_zone_t *origin;
+ dns_view_t *view;
+ catz_cb_data_t *cbd;
+ bool mod;
+} catz_chgzone_event_t;
+
+typedef struct {
+ unsigned int magic;
+#define DZARG_MAGIC ISC_MAGIC('D', 'z', 'a', 'r')
+ isc_buffer_t **text;
+ isc_result_t result;
+} ns_dzarg_t;
+
+/*
+ * These zones should not leak onto the Internet.
+ */
+const char *empty_zones[] = {
+ /* RFC 1918 */
+ "10.IN-ADDR.ARPA", "16.172.IN-ADDR.ARPA", "17.172.IN-ADDR.ARPA",
+ "18.172.IN-ADDR.ARPA", "19.172.IN-ADDR.ARPA", "20.172.IN-ADDR.ARPA",
+ "21.172.IN-ADDR.ARPA", "22.172.IN-ADDR.ARPA", "23.172.IN-ADDR.ARPA",
+ "24.172.IN-ADDR.ARPA", "25.172.IN-ADDR.ARPA", "26.172.IN-ADDR.ARPA",
+ "27.172.IN-ADDR.ARPA", "28.172.IN-ADDR.ARPA", "29.172.IN-ADDR.ARPA",
+ "30.172.IN-ADDR.ARPA", "31.172.IN-ADDR.ARPA", "168.192.IN-ADDR.ARPA",
+
+ /* RFC 6598 */
+ "64.100.IN-ADDR.ARPA", "65.100.IN-ADDR.ARPA", "66.100.IN-ADDR.ARPA",
+ "67.100.IN-ADDR.ARPA", "68.100.IN-ADDR.ARPA", "69.100.IN-ADDR.ARPA",
+ "70.100.IN-ADDR.ARPA", "71.100.IN-ADDR.ARPA", "72.100.IN-ADDR.ARPA",
+ "73.100.IN-ADDR.ARPA", "74.100.IN-ADDR.ARPA", "75.100.IN-ADDR.ARPA",
+ "76.100.IN-ADDR.ARPA", "77.100.IN-ADDR.ARPA", "78.100.IN-ADDR.ARPA",
+ "79.100.IN-ADDR.ARPA", "80.100.IN-ADDR.ARPA", "81.100.IN-ADDR.ARPA",
+ "82.100.IN-ADDR.ARPA", "83.100.IN-ADDR.ARPA", "84.100.IN-ADDR.ARPA",
+ "85.100.IN-ADDR.ARPA", "86.100.IN-ADDR.ARPA", "87.100.IN-ADDR.ARPA",
+ "88.100.IN-ADDR.ARPA", "89.100.IN-ADDR.ARPA", "90.100.IN-ADDR.ARPA",
+ "91.100.IN-ADDR.ARPA", "92.100.IN-ADDR.ARPA", "93.100.IN-ADDR.ARPA",
+ "94.100.IN-ADDR.ARPA", "95.100.IN-ADDR.ARPA", "96.100.IN-ADDR.ARPA",
+ "97.100.IN-ADDR.ARPA", "98.100.IN-ADDR.ARPA", "99.100.IN-ADDR.ARPA",
+ "100.100.IN-ADDR.ARPA", "101.100.IN-ADDR.ARPA", "102.100.IN-ADDR.ARPA",
+ "103.100.IN-ADDR.ARPA", "104.100.IN-ADDR.ARPA", "105.100.IN-ADDR.ARPA",
+ "106.100.IN-ADDR.ARPA", "107.100.IN-ADDR.ARPA", "108.100.IN-ADDR.ARPA",
+ "109.100.IN-ADDR.ARPA", "110.100.IN-ADDR.ARPA", "111.100.IN-ADDR.ARPA",
+ "112.100.IN-ADDR.ARPA", "113.100.IN-ADDR.ARPA", "114.100.IN-ADDR.ARPA",
+ "115.100.IN-ADDR.ARPA", "116.100.IN-ADDR.ARPA", "117.100.IN-ADDR.ARPA",
+ "118.100.IN-ADDR.ARPA", "119.100.IN-ADDR.ARPA", "120.100.IN-ADDR.ARPA",
+ "121.100.IN-ADDR.ARPA", "122.100.IN-ADDR.ARPA", "123.100.IN-ADDR.ARPA",
+ "124.100.IN-ADDR.ARPA", "125.100.IN-ADDR.ARPA", "126.100.IN-ADDR.ARPA",
+ "127.100.IN-ADDR.ARPA",
+
+ /* RFC 5735 and RFC 5737 */
+ "0.IN-ADDR.ARPA", /* THIS NETWORK */
+ "127.IN-ADDR.ARPA", /* LOOPBACK */
+ "254.169.IN-ADDR.ARPA", /* LINK LOCAL */
+ "2.0.192.IN-ADDR.ARPA", /* TEST NET */
+ "100.51.198.IN-ADDR.ARPA", /* TEST NET 2 */
+ "113.0.203.IN-ADDR.ARPA", /* TEST NET 3 */
+ "255.255.255.255.IN-ADDR.ARPA", /* BROADCAST */
+
+ /* Local IPv6 Unicast Addresses */
+ "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6."
+ "ARPA",
+ "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6."
+ "ARPA",
+ /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */
+ "D.F.IP6.ARPA", "8.E.F.IP6.ARPA", /* LINK LOCAL */
+ "9.E.F.IP6.ARPA", /* LINK LOCAL */
+ "A.E.F.IP6.ARPA", /* LINK LOCAL */
+ "B.E.F.IP6.ARPA", /* LINK LOCAL */
+
+ /* Example Prefix, RFC 3849. */
+ "8.B.D.0.1.0.0.2.IP6.ARPA",
+
+ /* RFC 7534 */
+ "EMPTY.AS112.ARPA",
+
+ /* RFC 8375 */
+ "HOME.ARPA",
+
+ NULL
+};
+
+noreturn static void
+fatal(named_server_t *server, const char *msg, isc_result_t result);
+
+static void
+named_server_reload(isc_task_t *task, isc_event_t *event);
+
+#ifdef HAVE_LIBNGHTTP2
+static isc_result_t
+listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls,
+ const ns_listen_tls_params_t *tls_params,
+ isc_tlsctx_cache_t *tlsctx_cache, in_port_t port,
+ isc_mem_t *mctx, ns_listenelt_t **target);
+#endif
+
+static isc_result_t
+listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family,
+ isc_tlsctx_cache_t *tlsctx_cache, ns_listenelt_t **target);
+
+static isc_result_t
+listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family,
+ isc_tlsctx_cache_t *tlsctx_cache,
+ ns_listenlist_t **target);
+
+static isc_result_t
+configure_forward(const cfg_obj_t *config, dns_view_t *view,
+ const dns_name_t *origin, const cfg_obj_t *forwarders,
+ const cfg_obj_t *forwardtype);
+
+static isc_result_t
+configure_alternates(const cfg_obj_t *config, dns_view_t *view,
+ const cfg_obj_t *alternates);
+
+static isc_result_t
+configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
+ const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
+ dns_viewlist_t *viewlist, dns_kasplist_t *kasplist,
+ cfg_aclconfctx_t *aclconf, bool added, bool old_rpz_ok,
+ bool modify);
+
+static void
+configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig,
+ dns_view_t *view);
+
+static isc_result_t
+configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
+ isc_mem_t *mctx, cfg_aclconfctx_t *actx);
+
+static isc_result_t
+add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx);
+
+static void
+end_reserved_dispatches(named_server_t *server, bool all);
+
+static void
+newzone_cfgctx_destroy(void **cfgp);
+
+static isc_result_t
+putstr(isc_buffer_t **b, const char *str);
+
+static isc_result_t
+putmem(isc_buffer_t **b, const char *str, size_t len);
+
+static isc_result_t
+putuint8(isc_buffer_t **b, uint8_t val);
+
+static isc_result_t
+putnull(isc_buffer_t **b);
+
+static int
+count_zones(const cfg_obj_t *conf);
+
+#ifdef HAVE_LMDB
+static isc_result_t
+migrate_nzf(dns_view_t *view);
+
+static isc_result_t
+nzd_writable(dns_view_t *view);
+
+static isc_result_t
+nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi);
+
+static isc_result_t
+nzd_env_reopen(dns_view_t *view);
+
+static void
+nzd_env_close(dns_view_t *view);
+
+static isc_result_t
+nzd_close(MDB_txn **txnp, bool commit);
+
+static isc_result_t
+nzd_count(dns_view_t *view, int *countp);
+#else /* ifdef HAVE_LMDB */
+static isc_result_t
+nzf_append(dns_view_t *view, const cfg_obj_t *zconfig);
+#endif /* ifdef HAVE_LMDB */
+
+/*%
+ * Configure a single view ACL at '*aclp'. Get its configuration from
+ * 'vconfig' (for per-view configuration) and maybe from 'config'
+ */
+static isc_result_t
+configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
+ const cfg_obj_t *gconfig, const char *aclname,
+ const char *acltuplename, cfg_aclconfctx_t *actx,
+ isc_mem_t *mctx, dns_acl_t **aclp) {
+ isc_result_t result;
+ const cfg_obj_t *maps[4];
+ const cfg_obj_t *aclobj = NULL;
+ int i = 0;
+
+ if (*aclp != NULL) {
+ dns_acl_detach(aclp);
+ }
+ if (vconfig != NULL) {
+ maps[i++] = cfg_tuple_get(vconfig, "options");
+ }
+ if (config != NULL) {
+ const cfg_obj_t *options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL) {
+ maps[i++] = options;
+ }
+ }
+ if (gconfig != NULL) {
+ const cfg_obj_t *options = NULL;
+ (void)cfg_map_get(gconfig, "options", &options);
+ if (options != NULL) {
+ maps[i++] = options;
+ }
+ }
+ maps[i] = NULL;
+
+ (void)named_config_get(maps, aclname, &aclobj);
+ if (aclobj == NULL) {
+ /*
+ * No value available. *aclp == NULL.
+ */
+ return (ISC_R_SUCCESS);
+ }
+
+ if (acltuplename != NULL) {
+ /*
+ * If the ACL is given in an optional tuple, retrieve it.
+ * The parser should have ensured that a valid object be
+ * returned.
+ */
+ aclobj = cfg_tuple_get(aclobj, acltuplename);
+ }
+
+ result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 0,
+ aclp);
+
+ return (result);
+}
+
+/*%
+ * Configure a sortlist at '*aclp'. Essentially the same as
+ * configure_view_acl() except it calls cfg_acl_fromconfig with a
+ * nest_level value of 2.
+ */
+static isc_result_t
+configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx,
+ dns_acl_t **aclp) {
+ isc_result_t result;
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *aclobj = NULL;
+ int i = 0;
+
+ if (*aclp != NULL) {
+ dns_acl_detach(aclp);
+ }
+ if (vconfig != NULL) {
+ maps[i++] = cfg_tuple_get(vconfig, "options");
+ }
+ if (config != NULL) {
+ const cfg_obj_t *options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL) {
+ maps[i++] = options;
+ }
+ }
+ maps[i] = NULL;
+
+ (void)named_config_get(maps, "sortlist", &aclobj);
+ if (aclobj == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Use a nest level of 3 for the "top level" of the sortlist;
+ * this means each entry in the top three levels will be stored
+ * as lists of separate, nested ACLs, rather than merged together
+ * into IP tables as is usually done with ACLs.
+ */
+ result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 3,
+ aclp);
+
+ return (result);
+}
+
+static isc_result_t
+configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config,
+ const char *confname, const char *conftuplename,
+ isc_mem_t *mctx, dns_rbt_t **rbtp) {
+ isc_result_t result;
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *obj = NULL;
+ const cfg_listelt_t *element;
+ int i = 0;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t b;
+ const char *str;
+ const cfg_obj_t *nameobj;
+
+ if (*rbtp != NULL) {
+ dns_rbt_destroy(rbtp);
+ }
+ if (vconfig != NULL) {
+ maps[i++] = cfg_tuple_get(vconfig, "options");
+ }
+ if (config != NULL) {
+ const cfg_obj_t *options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL) {
+ maps[i++] = options;
+ }
+ }
+ maps[i] = NULL;
+
+ (void)named_config_get(maps, confname, &obj);
+ if (obj == NULL) {
+ /*
+ * No value available. *rbtp == NULL.
+ */
+ return (ISC_R_SUCCESS);
+ }
+
+ if (conftuplename != NULL) {
+ obj = cfg_tuple_get(obj, conftuplename);
+ if (cfg_obj_isvoid(obj)) {
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ result = dns_rbt_create(mctx, NULL, NULL, rbtp);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ name = dns_fixedname_initname(&fixed);
+ for (element = cfg_list_first(obj); element != NULL;
+ element = cfg_list_next(element))
+ {
+ nameobj = cfg_listelt_value(element);
+ str = cfg_obj_asstring(nameobj);
+ isc_buffer_constinit(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+ /*
+ * We don't need the node data, but need to set dummy data to
+ * avoid a partial match with an empty node. For example, if
+ * we have foo.example.com and bar.example.com, we'd get a match
+ * for baz.example.com, which is not the expected result.
+ * We simply use (void *)1 as the dummy data.
+ */
+ result = dns_rbt_addname(*rbtp, name, (void *)1);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(nameobj, named_g_lctx, ISC_LOG_ERROR,
+ "failed to add %s for %s: %s", str,
+ confname, isc_result_totext(result));
+ goto cleanup;
+ }
+ }
+
+ return (result);
+
+cleanup:
+ dns_rbt_destroy(rbtp);
+ return (result);
+}
+
+static isc_result_t
+ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp,
+ unsigned char *digest, dns_rdata_ds_t *ds) {
+ isc_result_t result;
+ dns_rdata_dnskey_t keystruct;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ uint32_t rdata1, rdata2, rdata3;
+ const char *datastr = NULL, *namestr = NULL;
+ unsigned char data[4096];
+ isc_buffer_t databuf;
+ unsigned char rrdata[4096];
+ isc_buffer_t rrdatabuf;
+ isc_region_t r;
+ dns_fixedname_t fname;
+ dns_name_t *name = NULL;
+ isc_buffer_t namebuf;
+ const char *atstr = NULL;
+ enum {
+ INIT_DNSKEY,
+ STATIC_DNSKEY,
+ INIT_DS,
+ STATIC_DS,
+ TRUSTED
+ } anchortype;
+
+ REQUIRE(namestrp != NULL && *namestrp == NULL);
+ REQUIRE(ds != NULL);
+
+ /* if DNSKEY, flags; if DS, key tag */
+ rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1"));
+
+ /* if DNSKEY, protocol; if DS, algorithm */
+ rdata2 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata2"));
+
+ /* if DNSKEY, algorithm; if DS, digest type */
+ rdata3 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata3"));
+
+ namestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
+ *namestrp = namestr;
+
+ name = dns_fixedname_initname(&fname);
+ isc_buffer_constinit(&namebuf, namestr, strlen(namestr));
+ isc_buffer_add(&namebuf, strlen(namestr));
+ CHECK(dns_name_fromtext(name, &namebuf, dns_rootname, 0, NULL));
+
+ if (*initialp) {
+ atstr = cfg_obj_asstring(cfg_tuple_get(key, "anchortype"));
+
+ if (strcasecmp(atstr, "static-key") == 0) {
+ *initialp = false;
+ anchortype = STATIC_DNSKEY;
+ } else if (strcasecmp(atstr, "static-ds") == 0) {
+ *initialp = false;
+ anchortype = STATIC_DS;
+ } else if (strcasecmp(atstr, "initial-key") == 0) {
+ anchortype = INIT_DNSKEY;
+ } else if (strcasecmp(atstr, "initial-ds") == 0) {
+ anchortype = INIT_DS;
+ } else {
+ cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
+ "key '%s': "
+ "invalid initialization method '%s'",
+ namestr, atstr);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ } else {
+ anchortype = TRUSTED;
+ }
+
+ isc_buffer_init(&databuf, data, sizeof(data));
+ isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
+
+ *ds = (dns_rdata_ds_t){ .common.rdclass = dns_rdataclass_in,
+ .common.rdtype = dns_rdatatype_ds };
+
+ ISC_LINK_INIT(&ds->common, link);
+
+ switch (anchortype) {
+ case INIT_DNSKEY:
+ case STATIC_DNSKEY:
+ case TRUSTED:
+ /*
+ * This function should never be reached for view
+ * class other than IN
+ */
+ keystruct.common.rdclass = dns_rdataclass_in;
+ keystruct.common.rdtype = dns_rdatatype_dnskey;
+
+ /*
+ * The key data in keystruct is not dynamically allocated.
+ */
+ keystruct.mctx = NULL;
+
+ ISC_LINK_INIT(&keystruct.common, link);
+
+ if (rdata1 > 0xffff) {
+ CHECKM(ISC_R_RANGE, "key flags");
+ }
+ if (rdata1 & DNS_KEYFLAG_REVOKE) {
+ CHECKM(DST_R_BADKEYTYPE, "key flags revoke bit set");
+ }
+ if (rdata2 > 0xff) {
+ CHECKM(ISC_R_RANGE, "key protocol");
+ }
+ if (rdata3 > 0xff) {
+ CHECKM(ISC_R_RANGE, "key algorithm");
+ }
+
+ keystruct.flags = (uint16_t)rdata1;
+ keystruct.protocol = (uint8_t)rdata2;
+ keystruct.algorithm = (uint8_t)rdata3;
+
+ if (!dst_algorithm_supported(keystruct.algorithm)) {
+ CHECK(DST_R_UNSUPPORTEDALG);
+ }
+
+ datastr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
+ CHECK(isc_base64_decodestring(datastr, &databuf));
+ isc_buffer_usedregion(&databuf, &r);
+ keystruct.datalen = r.length;
+ keystruct.data = r.base;
+
+ CHECK(dns_rdata_fromstruct(&rdata, keystruct.common.rdclass,
+ keystruct.common.rdtype, &keystruct,
+ &rrdatabuf));
+ CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
+ digest, ds));
+ break;
+
+ case INIT_DS:
+ case STATIC_DS:
+ if (rdata1 > 0xffff) {
+ CHECKM(ISC_R_RANGE, "key tag");
+ }
+ if (rdata2 > 0xff) {
+ CHECKM(ISC_R_RANGE, "key algorithm");
+ }
+ if (rdata3 > 0xff) {
+ CHECKM(ISC_R_RANGE, "digest type");
+ }
+
+ ds->key_tag = (uint16_t)rdata1;
+ ds->algorithm = (uint8_t)rdata2;
+ ds->digest_type = (uint8_t)rdata3;
+
+ datastr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
+ CHECK(isc_hex_decodestring(datastr, &databuf));
+ isc_buffer_usedregion(&databuf, &r);
+
+ switch (ds->digest_type) {
+ case DNS_DSDIGEST_SHA1:
+ if (r.length != ISC_SHA1_DIGESTLENGTH) {
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+ break;
+ case DNS_DSDIGEST_SHA256:
+ if (r.length != ISC_SHA256_DIGESTLENGTH) {
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+ break;
+ case DNS_DSDIGEST_SHA384:
+ if (r.length != ISC_SHA384_DIGESTLENGTH) {
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+ break;
+ default:
+ cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
+ "key '%s': "
+ "unknown ds digest type %u",
+ namestr, ds->digest_type);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ break;
+ }
+
+ ds->length = r.length;
+ ds->digest = digest;
+ memmove(ds->digest, r.base, r.length);
+
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ return (result);
+}
+
+static void
+sfd_add(const dns_name_t *name, void *arg) {
+ if (arg != NULL) {
+ dns_view_sfd_add(arg, name);
+ }
+}
+
+/*%
+ * Parse 'key' in the context of view configuration 'vconfig'. If successful,
+ * add the key to 'secroots' if both of the following conditions are true:
+ *
+ * - 'keyname_match' is NULL or it matches the owner name of 'key',
+ * - support for the algorithm used by 'key' is not disabled by 'resolver'
+ * for the owner name of 'key'.
+ *
+ * 'managed' is true for managed keys and false for trusted keys. 'mctx' is
+ * the memory context to use for allocating memory.
+ */
+static isc_result_t
+process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
+ const dns_name_t *keyname_match, dns_view_t *view, bool managed) {
+ dns_fixedname_t fkeyname;
+ dns_name_t *keyname = NULL;
+ const char *namestr = NULL;
+ dns_rdata_ds_t ds;
+ isc_result_t result;
+ bool initializing = managed;
+ unsigned char digest[ISC_MAX_MD_SIZE];
+ isc_buffer_t b;
+
+ result = ta_fromconfig(key, &initializing, &namestr, digest, &ds);
+
+ switch (result) {
+ case ISC_R_SUCCESS:
+ /*
+ * Trust anchor was parsed correctly.
+ */
+ isc_buffer_constinit(&b, namestr, strlen(namestr));
+ isc_buffer_add(&b, strlen(namestr));
+ keyname = dns_fixedname_initname(&fkeyname);
+ result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ break;
+ case DST_R_UNSUPPORTEDALG:
+ case DST_R_BADKEYTYPE:
+ /*
+ * Key was parsed correctly, but it cannot be used; this is not
+ * a fatal error - log a warning about this key being ignored,
+ * but do not prevent any further ones from being processed.
+ */
+ cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
+ "ignoring %s for '%s': %s",
+ initializing ? "initial-key" : "static-key",
+ namestr, isc_result_totext(result));
+ return (ISC_R_SUCCESS);
+ case DST_R_NOCRYPTO:
+ /*
+ * Crypto support is not available.
+ */
+ cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
+ "ignoring %s for '%s': no crypto support",
+ initializing ? "initial-key" : "static-key",
+ namestr);
+ return (result);
+ default:
+ /*
+ * Something unexpected happened; we have no choice but to
+ * indicate an error so that the configuration loading process
+ * is interrupted.
+ */
+ cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
+ "configuring %s for '%s': %s",
+ initializing ? "initial-key" : "static-key",
+ namestr, isc_result_totext(result));
+ return (ISC_R_FAILURE);
+ }
+
+ /*
+ * If the caller requested to only load keys for a specific name and
+ * the owner name of this key does not match the requested name, do not
+ * load it.
+ */
+ if (keyname_match != NULL && !dns_name_equal(keyname_match, keyname)) {
+ goto done;
+ }
+
+ /*
+ * Ensure that 'resolver' allows using the algorithm of this key for
+ * its owner name. If it does not, do not load the key and log a
+ * warning, but do not prevent further keys from being processed.
+ */
+ if (!dns_resolver_algorithm_supported(view->resolver, keyname,
+ ds.algorithm))
+ {
+ cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
+ "ignoring %s for '%s': algorithm is disabled",
+ initializing ? "initial-key" : "static-key",
+ namestr);
+ goto done;
+ }
+
+ /*
+ * Add the key to 'secroots'. Keys from a "trust-anchors" or
+ * "managed-keys" statement may be either static or initializing
+ * keys. If it's not initializing, we don't want to treat it as
+ * managed, so we use 'initializing' twice here, for both the
+ * 'managed' and 'initializing' arguments to dns_keytable_add().
+ */
+ result = dns_keytable_add(secroots, initializing, initializing, keyname,
+ &ds, sfd_add, view);
+
+done:
+ return (result);
+}
+
+/*
+ * Load keys from configuration into key table. If 'keyname' is specified,
+ * only load keys matching that name. If 'managed' is true, load the key as
+ * an initializing key.
+ */
+static isc_result_t
+load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed,
+ const dns_name_t *keyname) {
+ const cfg_listelt_t *elt, *elt2;
+ const cfg_obj_t *keylist;
+ isc_result_t result;
+ dns_keytable_t *secroots = NULL;
+
+ CHECK(dns_view_getsecroots(view, &secroots));
+
+ for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt))
+ {
+ keylist = cfg_listelt_value(elt);
+
+ for (elt2 = cfg_list_first(keylist); elt2 != NULL;
+ elt2 = cfg_list_next(elt2))
+ {
+ CHECK(process_key(cfg_listelt_value(elt2), secroots,
+ keyname, view, managed));
+ }
+ }
+
+cleanup:
+ if (secroots != NULL) {
+ dns_keytable_detach(&secroots);
+ }
+ if (result == DST_R_NOCRYPTO) {
+ result = ISC_R_SUCCESS;
+ }
+ return (result);
+}
+
+/*%
+ * Check whether a key has been successfully loaded.
+ */
+static bool
+keyloaded(dns_view_t *view, const dns_name_t *name) {
+ isc_result_t result;
+ dns_keytable_t *secroots = NULL;
+ dns_keynode_t *keynode = NULL;
+
+ result = dns_view_getsecroots(view, &secroots);
+ if (result != ISC_R_SUCCESS) {
+ return (false);
+ }
+
+ result = dns_keytable_find(secroots, name, &keynode);
+
+ if (keynode != NULL) {
+ dns_keytable_detachkeynode(secroots, &keynode);
+ }
+ if (secroots != NULL) {
+ dns_keytable_detach(&secroots);
+ }
+
+ return (result == ISC_R_SUCCESS);
+}
+
+/*%
+ * Configure DNSSEC keys for a view.
+ *
+ * The per-view configuration values and the server-global defaults are read
+ * from 'vconfig' and 'config'.
+ */
+static isc_result_t
+configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
+ const cfg_obj_t *config, const cfg_obj_t *bindkeys,
+ bool auto_root, isc_mem_t *mctx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ const cfg_obj_t *view_keys = NULL;
+ const cfg_obj_t *global_keys = NULL;
+ const cfg_obj_t *view_managed_keys = NULL;
+ const cfg_obj_t *view_trust_anchors = NULL;
+ const cfg_obj_t *global_managed_keys = NULL;
+ const cfg_obj_t *global_trust_anchors = NULL;
+ const cfg_obj_t *maps[4];
+ const cfg_obj_t *voptions = NULL;
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *obj = NULL;
+ const char *directory;
+ int i = 0;
+
+ /* We don't need trust anchors for the _bind view */
+ if (strcmp(view->name, "_bind") == 0 &&
+ view->rdclass == dns_rdataclass_chaos)
+ {
+ return (ISC_R_SUCCESS);
+ }
+
+ if (vconfig != NULL) {
+ voptions = cfg_tuple_get(vconfig, "options");
+ if (voptions != NULL) {
+ (void)cfg_map_get(voptions, "trusted-keys", &view_keys);
+
+ /* managed-keys and trust-anchors are synonyms. */
+ (void)cfg_map_get(voptions, "managed-keys",
+ &view_managed_keys);
+ (void)cfg_map_get(voptions, "trust-anchors",
+ &view_trust_anchors);
+
+ maps[i++] = voptions;
+ }
+ }
+
+ if (config != NULL) {
+ (void)cfg_map_get(config, "trusted-keys", &global_keys);
+
+ /* managed-keys and trust-anchors are synonyms. */
+ (void)cfg_map_get(config, "managed-keys", &global_managed_keys);
+ (void)cfg_map_get(config, "trust-anchors",
+ &global_trust_anchors);
+
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL) {
+ maps[i++] = options;
+ }
+ }
+
+ maps[i++] = named_g_defaults;
+ maps[i] = NULL;
+
+ result = dns_view_initsecroots(view, mctx);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "couldn't create keytable");
+ return (ISC_R_UNEXPECTED);
+ }
+
+ result = dns_view_initntatable(view, named_g_taskmgr, named_g_timermgr);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "couldn't create NTA table");
+ return (ISC_R_UNEXPECTED);
+ }
+
+ if (auto_root && view->rdclass == dns_rdataclass_in) {
+ const cfg_obj_t *builtin_keys = NULL;
+
+ /*
+ * If bind.keys exists and is populated, it overrides
+ * the trust-anchors clause hard-coded in named_g_config.
+ */
+ if (bindkeys != NULL) {
+ isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "obtaining root key for view %s "
+ "from '%s'",
+ view->name, named_g_server->bindkeysfile);
+
+ (void)cfg_map_get(bindkeys, "trust-anchors",
+ &builtin_keys);
+
+ if (builtin_keys == NULL) {
+ isc_log_write(
+ named_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "dnssec-validation auto: "
+ "WARNING: root zone key "
+ "not found");
+ }
+ }
+
+ if (builtin_keys == NULL) {
+ isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "using built-in root key for view %s",
+ view->name);
+
+ (void)cfg_map_get(named_g_config, "trust-anchors",
+ &builtin_keys);
+ }
+
+ if (builtin_keys != NULL) {
+ CHECK(load_view_keys(builtin_keys, view, true,
+ dns_rootname));
+ }
+
+ if (!keyloaded(view, dns_rootname)) {
+ isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "root key not loaded");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ }
+
+ if (view->rdclass == dns_rdataclass_in) {
+ CHECK(load_view_keys(view_keys, view, false, NULL));
+ CHECK(load_view_keys(view_trust_anchors, view, true, NULL));
+ CHECK(load_view_keys(view_managed_keys, view, true, NULL));
+
+ CHECK(load_view_keys(global_keys, view, false, NULL));
+ CHECK(load_view_keys(global_trust_anchors, view, true, NULL));
+ CHECK(load_view_keys(global_managed_keys, view, true, NULL));
+ }
+
+ /*
+ * Add key zone for managed keys.
+ */
+ obj = NULL;
+ (void)named_config_get(maps, "managed-keys-directory", &obj);
+ directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL);
+ if (directory != NULL) {
+ result = isc_file_isdirectory(directory);
+ }
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "invalid managed-keys-directory %s: %s",
+ directory, isc_result_totext(result));
+ goto cleanup;
+ } else if (directory != NULL) {
+ if (!isc_file_isdirwritable(directory)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "managed-keys-directory '%s' "
+ "is not writable",
+ directory);
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
+ }
+
+ CHECK(add_keydata_zone(view, directory, named_g_mctx));
+
+cleanup:
+ return (result);
+}
+
+static isc_result_t
+mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) {
+ const cfg_listelt_t *element;
+ const cfg_obj_t *obj;
+ const char *str;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ bool value;
+ isc_result_t result;
+ isc_buffer_t b;
+
+ name = dns_fixedname_initname(&fixed);
+ for (element = cfg_list_first(mbs); element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
+ isc_buffer_constinit(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+ value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
+ CHECK(dns_resolver_setmustbesecure(resolver, name, value));
+ }
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ return (result);
+}
+
+/*%
+ * Get a dispatch appropriate for the resolver of a given view.
+ */
+static isc_result_t
+get_view_querysource_dispatch(const cfg_obj_t **maps, int af,
+ dns_dispatch_t **dispatchp, bool is_firstview) {
+ isc_result_t result = ISC_R_FAILURE;
+ dns_dispatch_t *disp = NULL;
+ isc_sockaddr_t sa;
+ const cfg_obj_t *obj = NULL;
+
+ switch (af) {
+ case AF_INET:
+ result = named_config_get(maps, "query-source", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ break;
+ case AF_INET6:
+ result = named_config_get(maps, "query-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ sa = *(cfg_obj_assockaddr(obj));
+ INSIST(isc_sockaddr_pf(&sa) == af);
+
+ /*
+ * If we don't support this address family, we're done!
+ */
+ switch (af) {
+ case AF_INET:
+ result = isc_net_probeipv4();
+ break;
+ case AF_INET6:
+ result = isc_net_probeipv6();
+ break;
+ default:
+ UNREACHABLE();
+ }
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Try to find a dispatcher that we can share.
+ */
+ if (isc_sockaddr_getport(&sa) != 0) {
+ INSIST(obj != NULL);
+ if (is_firstview) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO,
+ "using specific query-source port "
+ "suppresses port randomization and can be "
+ "insecure.");
+ }
+ }
+
+ result = dns_dispatch_createudp(named_g_dispatchmgr, &sa, &disp);
+ if (result != ISC_R_SUCCESS) {
+ isc_sockaddr_t any;
+ char buf[ISC_SOCKADDR_FORMATSIZE];
+
+ switch (af) {
+ case AF_INET:
+ isc_sockaddr_any(&any);
+ break;
+ case AF_INET6:
+ isc_sockaddr_any6(&any);
+ break;
+ }
+ if (isc_sockaddr_equal(&sa, &any)) {
+ return (ISC_R_SUCCESS);
+ }
+ isc_sockaddr_format(&sa, buf, sizeof(buf));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "could not get query source dispatcher (%s)",
+ buf);
+ return (result);
+ }
+
+ *dispatchp = disp;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+configure_order(dns_order_t *order, const cfg_obj_t *ent) {
+ dns_rdataclass_t rdclass;
+ dns_rdatatype_t rdtype;
+ const cfg_obj_t *obj;
+ dns_fixedname_t fixed;
+ unsigned int mode = 0;
+ const char *str;
+ isc_buffer_t b;
+ isc_result_t result;
+ bool addroot;
+
+ result = named_config_getclass(cfg_tuple_get(ent, "class"),
+ dns_rdataclass_any, &rdclass);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = named_config_gettype(cfg_tuple_get(ent, "type"),
+ dns_rdatatype_any, &rdtype);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ obj = cfg_tuple_get(ent, "name");
+ if (cfg_obj_isstring(obj)) {
+ str = cfg_obj_asstring(obj);
+ } else {
+ str = "*";
+ }
+ addroot = (strcmp(str, "*") == 0);
+ isc_buffer_constinit(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ dns_fixedname_init(&fixed);
+ result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, dns_rootname,
+ 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ obj = cfg_tuple_get(ent, "ordering");
+ INSIST(cfg_obj_isstring(obj));
+ str = cfg_obj_asstring(obj);
+ if (!strcasecmp(str, "fixed")) {
+#if DNS_RDATASET_FIXED
+ mode = DNS_RDATASETATTR_FIXEDORDER;
+#else /* if DNS_RDATASET_FIXED */
+ mode = DNS_RDATASETATTR_CYCLIC;
+#endif /* DNS_RDATASET_FIXED */
+ } else if (!strcasecmp(str, "random")) {
+ mode = DNS_RDATASETATTR_RANDOMIZE;
+ } else if (!strcasecmp(str, "cyclic")) {
+ mode = DNS_RDATASETATTR_CYCLIC;
+ } else if (!strcasecmp(str, "none")) {
+ mode = DNS_RDATASETATTR_NONE;
+ } else {
+ UNREACHABLE();
+ }
+
+ /*
+ * "*" should match everything including the root (BIND 8 compat).
+ * As dns_name_matcheswildcard(".", "*.") returns FALSE add a
+ * explicit entry for "." when the name is "*".
+ */
+ if (addroot) {
+ result = dns_order_add(order, dns_rootname, rdtype, rdclass,
+ mode);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ return (dns_order_add(order, dns_fixedname_name(&fixed), rdtype,
+ rdclass, mode));
+}
+
+static isc_result_t
+configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
+ isc_netaddr_t na;
+ dns_peer_t *peer;
+ const cfg_obj_t *obj;
+ const char *str;
+ isc_result_t result;
+ unsigned int prefixlen;
+
+ cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen);
+
+ peer = NULL;
+ result = dns_peer_newprefix(mctx, &na, prefixlen, &peer);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "bogus", &obj);
+ if (obj != NULL) {
+ CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj)));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "provide-ixfr", &obj);
+ if (obj != NULL) {
+ CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "request-expire", &obj);
+ if (obj != NULL) {
+ CHECK(dns_peer_setrequestexpire(peer, cfg_obj_asboolean(obj)));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "request-ixfr", &obj);
+ if (obj != NULL) {
+ CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "request-nsid", &obj);
+ if (obj != NULL) {
+ CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj)));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "send-cookie", &obj);
+ if (obj != NULL) {
+ CHECK(dns_peer_setsendcookie(peer, cfg_obj_asboolean(obj)));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "edns", &obj);
+ if (obj != NULL) {
+ CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj)));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "edns-udp-size", &obj);
+ if (obj != NULL) {
+ uint32_t udpsize = cfg_obj_asuint32(obj);
+ if (udpsize < 512U) {
+ udpsize = 512U;
+ }
+ if (udpsize > 4096U) {
+ udpsize = 4096U;
+ }
+ CHECK(dns_peer_setudpsize(peer, (uint16_t)udpsize));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "edns-version", &obj);
+ if (obj != NULL) {
+ uint32_t ednsversion = cfg_obj_asuint32(obj);
+ if (ednsversion > 255U) {
+ ednsversion = 255U;
+ }
+ CHECK(dns_peer_setednsversion(peer, (uint8_t)ednsversion));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "max-udp-size", &obj);
+ if (obj != NULL) {
+ uint32_t udpsize = cfg_obj_asuint32(obj);
+ if (udpsize < 512U) {
+ udpsize = 512U;
+ }
+ if (udpsize > 4096U) {
+ udpsize = 4096U;
+ }
+ CHECK(dns_peer_setmaxudp(peer, (uint16_t)udpsize));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "padding", &obj);
+ if (obj != NULL) {
+ uint32_t padding = cfg_obj_asuint32(obj);
+ if (padding > 512U) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "server padding value cannot "
+ "exceed 512: lowering");
+ padding = 512U;
+ }
+ CHECK(dns_peer_setpadding(peer, (uint16_t)padding));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "tcp-only", &obj);
+ if (obj != NULL) {
+ CHECK(dns_peer_setforcetcp(peer, cfg_obj_asboolean(obj)));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "tcp-keepalive", &obj);
+ if (obj != NULL) {
+ CHECK(dns_peer_settcpkeepalive(peer, cfg_obj_asboolean(obj)));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "transfers", &obj);
+ if (obj != NULL) {
+ CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj)));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "transfer-format", &obj);
+ if (obj != NULL) {
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "many-answers") == 0) {
+ CHECK(dns_peer_settransferformat(peer,
+ dns_many_answers));
+ } else if (strcasecmp(str, "one-answer") == 0) {
+ CHECK(dns_peer_settransferformat(peer, dns_one_answer));
+ } else {
+ UNREACHABLE();
+ }
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "keys", &obj);
+ if (obj != NULL) {
+ result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj));
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ }
+
+ obj = NULL;
+ if (na.family == AF_INET) {
+ (void)cfg_map_get(cpeer, "transfer-source", &obj);
+ } else {
+ (void)cfg_map_get(cpeer, "transfer-source-v6", &obj);
+ }
+ if (obj != NULL) {
+ result = dns_peer_settransfersource(peer,
+ cfg_obj_assockaddr(obj));
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ named_add_reserved_dispatch(named_g_server,
+ cfg_obj_assockaddr(obj));
+ }
+
+ obj = NULL;
+ if (na.family == AF_INET) {
+ (void)cfg_map_get(cpeer, "notify-source", &obj);
+ } else {
+ (void)cfg_map_get(cpeer, "notify-source-v6", &obj);
+ }
+ if (obj != NULL) {
+ result = dns_peer_setnotifysource(peer,
+ cfg_obj_assockaddr(obj));
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ named_add_reserved_dispatch(named_g_server,
+ cfg_obj_assockaddr(obj));
+ }
+
+ obj = NULL;
+ if (na.family == AF_INET) {
+ (void)cfg_map_get(cpeer, "query-source", &obj);
+ } else {
+ (void)cfg_map_get(cpeer, "query-source-v6", &obj);
+ }
+ if (obj != NULL) {
+ result = dns_peer_setquerysource(peer, cfg_obj_assockaddr(obj));
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ named_add_reserved_dispatch(named_g_server,
+ cfg_obj_assockaddr(obj));
+ }
+
+ *peerp = peer;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ dns_peer_detach(&peer);
+ return (result);
+}
+
+static isc_result_t
+configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx,
+ const dns_dyndbctx_t *dctx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ const cfg_obj_t *obj;
+ const char *name, *library;
+
+ /* Get the name of the dyndb instance and the library path . */
+ name = cfg_obj_asstring(cfg_tuple_get(dyndb, "name"));
+ library = cfg_obj_asstring(cfg_tuple_get(dyndb, "library"));
+
+ obj = cfg_tuple_get(dyndb, "parameters");
+ if (obj != NULL) {
+ result = dns_dyndb_load(library, name, cfg_obj_asstring(obj),
+ cfg_obj_file(obj), cfg_obj_line(obj),
+ mctx, dctx);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dynamic database '%s' configuration failed: %s",
+ name, isc_result_totext(result));
+ }
+ return (result);
+}
+
+static isc_result_t
+disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
+ isc_result_t result;
+ const cfg_obj_t *algorithms;
+ const cfg_listelt_t *element;
+ const char *str;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t b;
+
+ name = dns_fixedname_initname(&fixed);
+ str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
+ isc_buffer_constinit(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+
+ algorithms = cfg_tuple_get(disabled, "algorithms");
+ for (element = cfg_list_first(algorithms); element != NULL;
+ element = cfg_list_next(element))
+ {
+ isc_textregion_t r;
+ dns_secalg_t alg;
+
+ DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
+ r.length = strlen(r.base);
+
+ result = dns_secalg_fromtext(&alg, &r);
+ if (result != ISC_R_SUCCESS) {
+ uint8_t ui;
+ result = isc_parse_uint8(&ui, r.base, 10);
+ alg = ui;
+ }
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(cfg_listelt_value(element), named_g_lctx,
+ ISC_LOG_ERROR, "invalid algorithm");
+ CHECK(result);
+ }
+ CHECK(dns_resolver_disable_algorithm(resolver, name, alg));
+ }
+cleanup:
+ return (result);
+}
+
+static isc_result_t
+disable_ds_digests(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
+ isc_result_t result;
+ const cfg_obj_t *digests;
+ const cfg_listelt_t *element;
+ const char *str;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t b;
+
+ name = dns_fixedname_initname(&fixed);
+ str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
+ isc_buffer_constinit(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+
+ digests = cfg_tuple_get(disabled, "digests");
+ for (element = cfg_list_first(digests); element != NULL;
+ element = cfg_list_next(element))
+ {
+ isc_textregion_t r;
+ dns_dsdigest_t digest;
+
+ DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
+ r.length = strlen(r.base);
+
+ /* disable_ds_digests handles numeric values. */
+ result = dns_dsdigest_fromtext(&digest, &r);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(cfg_listelt_value(element), named_g_lctx,
+ ISC_LOG_ERROR, "invalid algorithm");
+ CHECK(result);
+ }
+ CHECK(dns_resolver_disable_ds_digest(resolver, name, digest));
+ }
+cleanup:
+ return (result);
+}
+
+static bool
+on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) {
+ const cfg_listelt_t *element;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_result_t result;
+ const cfg_obj_t *value;
+ const char *str;
+ isc_buffer_t b;
+
+ name = dns_fixedname_initname(&fixed);
+
+ for (element = cfg_list_first(disablelist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ value = cfg_listelt_value(element);
+ str = cfg_obj_asstring(value);
+ isc_buffer_constinit(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (dns_name_equal(name, zonename)) {
+ return (true);
+ }
+ }
+ return (false);
+}
+
+static isc_result_t
+check_dbtype(dns_zone_t *zone, unsigned int dbtypec, const char **dbargv,
+ isc_mem_t *mctx) {
+ char **argv = NULL;
+ unsigned int i;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ CHECK(dns_zone_getdbtype(zone, &argv, mctx));
+
+ /*
+ * Check that all the arguments match.
+ */
+ for (i = 0; i < dbtypec; i++) {
+ if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) {
+ CHECK(ISC_R_FAILURE);
+
+ /*
+ * Check that there are not extra arguments.
+ */
+ }
+ }
+
+ /*
+ * Check that there are not extra arguments.
+ */
+ if (i == dbtypec && argv[i] != NULL) {
+ result = ISC_R_FAILURE;
+ }
+
+cleanup:
+ isc_mem_free(mctx, argv);
+ return (result);
+}
+
+static isc_result_t
+setquerystats(dns_zone_t *zone, isc_mem_t *mctx, dns_zonestat_level_t level) {
+ isc_result_t result;
+ isc_stats_t *zoneqrystats;
+
+ dns_zone_setstatlevel(zone, level);
+
+ zoneqrystats = NULL;
+ if (level == dns_zonestat_full) {
+ result = isc_stats_create(mctx, &zoneqrystats,
+ ns_statscounter_max);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ dns_zone_setrequeststats(zone, zoneqrystats);
+ if (zoneqrystats != NULL) {
+ isc_stats_detach(&zoneqrystats);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static named_cache_t *
+cachelist_find(named_cachelist_t *cachelist, const char *cachename,
+ dns_rdataclass_t rdclass) {
+ named_cache_t *nsc;
+
+ for (nsc = ISC_LIST_HEAD(*cachelist); nsc != NULL;
+ nsc = ISC_LIST_NEXT(nsc, link))
+ {
+ if (nsc->rdclass == rdclass &&
+ strcmp(dns_cache_getname(nsc->cache), cachename) == 0)
+ {
+ return (nsc);
+ }
+ }
+
+ return (NULL);
+}
+
+static bool
+cache_reusable(dns_view_t *originview, dns_view_t *view,
+ bool new_zero_no_soattl) {
+ if (originview->rdclass != view->rdclass ||
+ originview->checknames != view->checknames ||
+ dns_resolver_getzeronosoattl(originview->resolver) !=
+ new_zero_no_soattl ||
+ originview->acceptexpired != view->acceptexpired ||
+ originview->enablevalidation != view->enablevalidation ||
+ originview->maxcachettl != view->maxcachettl ||
+ originview->maxncachettl != view->maxncachettl)
+ {
+ return (false);
+ }
+
+ return (true);
+}
+
+static bool
+cache_sharable(dns_view_t *originview, dns_view_t *view,
+ bool new_zero_no_soattl, uint64_t new_max_cache_size,
+ uint32_t new_stale_ttl, uint32_t new_stale_refresh_time) {
+ /*
+ * If the cache cannot even reused for the same view, it cannot be
+ * shared with other views.
+ */
+ if (!cache_reusable(originview, view, new_zero_no_soattl)) {
+ return (false);
+ }
+
+ /*
+ * Check other cache related parameters that must be consistent among
+ * the sharing views.
+ */
+ if (dns_cache_getservestalettl(originview->cache) != new_stale_ttl ||
+ dns_cache_getservestalerefresh(originview->cache) !=
+ new_stale_refresh_time ||
+ dns_cache_getcachesize(originview->cache) != new_max_cache_size)
+ {
+ return (false);
+ }
+
+ return (true);
+}
+
+/*
+ * Callback from DLZ configure when the driver sets up a writeable zone
+ */
+static isc_result_t
+dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) {
+ dns_name_t *origin = dns_zone_getorigin(zone);
+ dns_rdataclass_t zclass = view->rdclass;
+ isc_result_t result;
+
+ result = dns_zonemgr_managezone(named_g_server->zonemgr, zone);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ dns_zone_setstats(zone, named_g_server->zonestats);
+
+ return (named_zone_configure_writeable_dlz(dlzdb, zone, zclass,
+ origin));
+}
+
+static isc_result_t
+dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na,
+ unsigned int prefixlen, const char *server, const char *contact) {
+ char reverse[48 + sizeof("ip6.arpa.")] = { 0 };
+ char buf[sizeof("x.x.")];
+ const char *dns64_dbtype[4] = { "_dns64", "dns64", ".", "." };
+ const char *sep = ": view ";
+ const char *viewname = view->name;
+ const unsigned char *s6;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ dns_zone_t *zone = NULL;
+ int dns64_dbtypec = 4;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 ||
+ prefixlen == 56 || prefixlen == 64 || prefixlen == 96);
+
+ if (!strcmp(viewname, "_default")) {
+ sep = "";
+ viewname = "";
+ }
+
+ /*
+ * Construct the reverse name of the zone.
+ */
+ s6 = na->type.in6.s6_addr;
+ while (prefixlen > 0) {
+ prefixlen -= 8;
+ snprintf(buf, sizeof(buf), "%x.%x.", s6[prefixlen / 8] & 0xf,
+ (s6[prefixlen / 8] >> 4) & 0xf);
+ strlcat(reverse, buf, sizeof(reverse));
+ }
+ strlcat(reverse, "ip6.arpa.", sizeof(reverse));
+
+ /*
+ * Create the actual zone.
+ */
+ if (server != NULL) {
+ dns64_dbtype[2] = server;
+ }
+ if (contact != NULL) {
+ dns64_dbtype[3] = contact;
+ }
+ name = dns_fixedname_initname(&fixed);
+ isc_buffer_constinit(&b, reverse, strlen(reverse));
+ isc_buffer_add(&b, strlen(reverse));
+ CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+ CHECK(dns_zone_create(&zone, mctx));
+ CHECK(dns_zone_setorigin(zone, name));
+ dns_zone_setview(zone, view);
+ CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
+ dns_zone_setclass(zone, view->rdclass);
+ dns_zone_settype(zone, dns_zone_primary);
+ dns_zone_setstats(zone, named_g_server->zonestats);
+ dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype);
+ if (view->queryacl != NULL) {
+ dns_zone_setqueryacl(zone, view->queryacl);
+ }
+ if (view->queryonacl != NULL) {
+ dns_zone_setqueryonacl(zone, view->queryonacl);
+ }
+ dns_zone_setdialup(zone, dns_dialuptype_no);
+ dns_zone_setnotifytype(zone, dns_notifytype_no);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true);
+ CHECK(setquerystats(zone, mctx, dns_zonestat_none)); /* XXXMPA */
+ CHECK(dns_view_addzone(view, zone));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dns64 reverse zone%s%s: %s", sep, viewname, reverse);
+
+cleanup:
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ return (result);
+}
+
+#ifdef USE_DNSRPS
+typedef struct conf_dnsrps_ctx conf_dnsrps_ctx_t;
+struct conf_dnsrps_ctx {
+ isc_result_t result;
+ char *cstr;
+ size_t cstr_size;
+ isc_mem_t *mctx;
+};
+
+/*
+ * Add to the DNSRPS configuration string.
+ */
+static bool
+conf_dnsrps_sadd(conf_dnsrps_ctx_t *ctx, const char *p, ...) {
+ size_t new_len, cur_len, new_cstr_size;
+ char *new_cstr;
+ va_list args;
+
+ if (ctx->cstr == NULL) {
+ ctx->cstr = isc_mem_get(ctx->mctx, 256);
+ ctx->cstr[0] = '\0';
+ ctx->cstr_size = 256;
+ }
+
+ cur_len = strlen(ctx->cstr);
+ va_start(args, p);
+ new_len = vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p,
+ args) +
+ 1;
+ va_end(args);
+
+ if (cur_len + new_len <= ctx->cstr_size) {
+ return (true);
+ }
+
+ new_cstr_size = ((cur_len + new_len) / 256 + 1) * 256;
+ new_cstr = isc_mem_get(ctx->mctx, new_cstr_size);
+
+ memmove(new_cstr, ctx->cstr, cur_len);
+ isc_mem_put(ctx->mctx, ctx->cstr, ctx->cstr_size);
+ ctx->cstr_size = new_cstr_size;
+ ctx->cstr = new_cstr;
+
+ /* cannot use args twice after a single va_start()on some systems */
+ va_start(args, p);
+ vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, args);
+ va_end(args);
+ return (true);
+}
+
+/*
+ * Get an DNSRPS configuration value using the global and view options
+ * for the default. Return false upon failure.
+ */
+static bool
+conf_dnsrps_get(const cfg_obj_t **sub_obj, const cfg_obj_t **maps,
+ const cfg_obj_t *obj, const char *name,
+ conf_dnsrps_ctx_t *ctx) {
+ if (ctx != NULL && ctx->result != ISC_R_SUCCESS) {
+ *sub_obj = NULL;
+ return (false);
+ }
+
+ *sub_obj = cfg_tuple_get(obj, name);
+ if (cfg_obj_isvoid(*sub_obj)) {
+ *sub_obj = NULL;
+ if (maps != NULL &&
+ ISC_R_SUCCESS != named_config_get(maps, name, sub_obj))
+ {
+ *sub_obj = NULL;
+ }
+ }
+ return (true);
+}
+
+/*
+ * Handle a DNSRPS boolean configuration value with the global and view
+ * options providing the default.
+ */
+static void
+conf_dnsrps_yes_no(const cfg_obj_t *obj, const char *name,
+ conf_dnsrps_ctx_t *ctx) {
+ const cfg_obj_t *sub_obj;
+
+ if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) {
+ return;
+ }
+ if (sub_obj == NULL) {
+ return;
+ }
+ if (ctx == NULL) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
+ "\"%s\" without \"dnsrps-enable yes\"", name);
+ return;
+ }
+
+ conf_dnsrps_sadd(ctx, " %s %s", name,
+ cfg_obj_asboolean(sub_obj) ? "yes" : "no");
+}
+
+static void
+conf_dnsrps_num(const cfg_obj_t *obj, const char *name,
+ conf_dnsrps_ctx_t *ctx) {
+ const cfg_obj_t *sub_obj;
+
+ if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) {
+ return;
+ }
+ if (sub_obj == NULL) {
+ return;
+ }
+ if (ctx == NULL) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
+ "\"%s\" without \"dnsrps-enable yes\"", name);
+ return;
+ }
+
+ if (cfg_obj_isduration(sub_obj)) {
+ conf_dnsrps_sadd(ctx, " %s %d", name,
+ cfg_obj_asduration(sub_obj));
+ } else {
+ conf_dnsrps_sadd(ctx, " %s %d", name,
+ cfg_obj_asuint32(sub_obj));
+ }
+}
+
+/*
+ * Convert the parsed RPZ configuration statement to a string for
+ * dns_rpz_new_zones().
+ */
+static isc_result_t
+conf_dnsrps(dns_view_t *view, const cfg_obj_t **maps, bool nsip_enabled,
+ bool nsdname_enabled, dns_rpz_zbits_t *nsip_on,
+ dns_rpz_zbits_t *nsdname_on, char **rps_cstr, size_t *rps_cstr_size,
+ const cfg_obj_t *rpz_obj, const cfg_listelt_t *zone_element) {
+ conf_dnsrps_ctx_t ctx;
+ const cfg_obj_t *zone_obj, *obj;
+ dns_rpz_num_t rpz_num;
+ bool on;
+ const char *s;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.result = ISC_R_SUCCESS;
+ ctx.mctx = view->mctx;
+
+ for (rpz_num = 0; zone_element != NULL && ctx.result == ISC_R_SUCCESS;
+ ++rpz_num)
+ {
+ zone_obj = cfg_listelt_value(zone_element);
+
+ s = cfg_obj_asstring(cfg_tuple_get(zone_obj, "zone name"));
+ conf_dnsrps_sadd(&ctx, "zone \"%s\"", s);
+
+ obj = cfg_tuple_get(zone_obj, "policy");
+ if (!cfg_obj_isvoid(obj)) {
+ s = cfg_obj_asstring(cfg_tuple_get(obj, "policy name"));
+ conf_dnsrps_sadd(&ctx, " policy %s", s);
+ if (strcasecmp(s, "cname") == 0) {
+ s = cfg_obj_asstring(
+ cfg_tuple_get(obj, "cname"));
+ conf_dnsrps_sadd(&ctx, " %s", s);
+ }
+ }
+
+ conf_dnsrps_yes_no(zone_obj, "recursive-only", &ctx);
+ conf_dnsrps_yes_no(zone_obj, "log", &ctx);
+ conf_dnsrps_num(zone_obj, "max-policy-ttl", &ctx);
+ obj = cfg_tuple_get(rpz_obj, "nsip-enable");
+ if (!cfg_obj_isvoid(obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ *nsip_on |= DNS_RPZ_ZBIT(rpz_num);
+ } else {
+ *nsip_on &= ~DNS_RPZ_ZBIT(rpz_num);
+ }
+ }
+ on = ((*nsip_on & DNS_RPZ_ZBIT(rpz_num)) != 0);
+ if (nsip_enabled != on) {
+ conf_dnsrps_sadd(&ctx, on ? " nsip-enable yes "
+ : " nsip-enable no ");
+ }
+ obj = cfg_tuple_get(rpz_obj, "nsdname-enable");
+ if (!cfg_obj_isvoid(obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ *nsdname_on |= DNS_RPZ_ZBIT(rpz_num);
+ } else {
+ *nsdname_on &= ~DNS_RPZ_ZBIT(rpz_num);
+ }
+ }
+ on = ((*nsdname_on & DNS_RPZ_ZBIT(rpz_num)) != 0);
+ if (nsdname_enabled != on) {
+ conf_dnsrps_sadd(&ctx, on ? " nsdname-enable yes "
+ : " nsdname-enable no ");
+ }
+ conf_dnsrps_sadd(&ctx, ";\n");
+ zone_element = cfg_list_next(zone_element);
+ }
+
+ conf_dnsrps_yes_no(rpz_obj, "recursive-only", &ctx);
+ conf_dnsrps_num(rpz_obj, "max-policy-ttl", &ctx);
+ conf_dnsrps_num(rpz_obj, "min-ns-dots", &ctx);
+ conf_dnsrps_yes_no(rpz_obj, "qname-wait-recurse", &ctx);
+ conf_dnsrps_yes_no(rpz_obj, "break-dnssec", &ctx);
+ if (!nsip_enabled) {
+ conf_dnsrps_sadd(&ctx, " nsip-enable no ");
+ }
+ if (!nsdname_enabled) {
+ conf_dnsrps_sadd(&ctx, " nsdname-enable no ");
+ }
+
+ /*
+ * Get the general dnsrpzd parameters from the response-policy
+ * statement in the view and the general options.
+ */
+ if (conf_dnsrps_get(&obj, maps, rpz_obj, "dnsrps-options", &ctx) &&
+ obj != NULL)
+ {
+ conf_dnsrps_sadd(&ctx, " %s\n", cfg_obj_asstring(obj));
+ }
+
+ if (ctx.result == ISC_R_SUCCESS) {
+ *rps_cstr = ctx.cstr;
+ *rps_cstr_size = ctx.cstr_size;
+ } else {
+ if (ctx.cstr != NULL) {
+ isc_mem_put(ctx.mctx, ctx.cstr, ctx.cstr_size);
+ }
+ *rps_cstr = NULL;
+ *rps_cstr_size = 0;
+ }
+ return (ctx.result);
+}
+#endif /* ifdef USE_DNSRPS */
+
+static isc_result_t
+configure_rpz_name(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name,
+ const char *str, const char *msg) {
+ isc_result_t result;
+
+ result = dns_name_fromstring(name, str, DNS_NAME_DOWNCASE, view->mctx);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "invalid %s '%s'", msg, str);
+ }
+ return (result);
+}
+
+static isc_result_t
+configure_rpz_name2(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name,
+ const char *str, const dns_name_t *origin) {
+ isc_result_t result;
+
+ result = dns_name_fromstring2(name, str, origin, DNS_NAME_DOWNCASE,
+ view->mctx);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "invalid zone '%s'", str);
+ }
+ return (result);
+}
+
+static isc_result_t
+configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element,
+ bool recursive_only_default, bool add_soa_default,
+ dns_ttl_t ttl_default, uint32_t minupdateinterval_default,
+ const dns_rpz_zone_t *old, bool *old_rpz_okp) {
+ const cfg_obj_t *rpz_obj, *obj;
+ const char *str;
+ dns_rpz_zone_t *zone = NULL;
+ isc_result_t result;
+ dns_rpz_num_t rpz_num;
+
+ REQUIRE(old != NULL || !*old_rpz_okp);
+
+ rpz_obj = cfg_listelt_value(element);
+
+ if (view->rpzs->p.num_zones >= DNS_RPZ_MAX_ZONES) {
+ cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "limit of %d response policy zones exceeded",
+ DNS_RPZ_MAX_ZONES);
+ return (ISC_R_FAILURE);
+ }
+
+ result = dns_rpz_new_zone(view->rpzs, &zone);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "Error creating new RPZ zone : %s",
+ isc_result_totext(result));
+ return (result);
+ }
+
+ obj = cfg_tuple_get(rpz_obj, "recursive-only");
+ if (cfg_obj_isvoid(obj) ? recursive_only_default
+ : cfg_obj_asboolean(obj))
+ {
+ view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(zone->num);
+ } else {
+ view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(zone->num);
+ }
+
+ obj = cfg_tuple_get(rpz_obj, "log");
+ if (!cfg_obj_isvoid(obj) && !cfg_obj_asboolean(obj)) {
+ view->rpzs->p.no_log |= DNS_RPZ_ZBIT(zone->num);
+ } else {
+ view->rpzs->p.no_log &= ~DNS_RPZ_ZBIT(zone->num);
+ }
+
+ obj = cfg_tuple_get(rpz_obj, "max-policy-ttl");
+ if (cfg_obj_isduration(obj)) {
+ zone->max_policy_ttl = cfg_obj_asduration(obj);
+ } else {
+ zone->max_policy_ttl = ttl_default;
+ }
+ if (*old_rpz_okp && zone->max_policy_ttl != old->max_policy_ttl) {
+ *old_rpz_okp = false;
+ }
+
+ obj = cfg_tuple_get(rpz_obj, "min-update-interval");
+ if (cfg_obj_isduration(obj)) {
+ zone->min_update_interval = cfg_obj_asduration(obj);
+ } else {
+ zone->min_update_interval = minupdateinterval_default;
+ }
+ if (*old_rpz_okp &&
+ zone->min_update_interval != old->min_update_interval)
+ {
+ *old_rpz_okp = false;
+ }
+
+ str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name"));
+ result = configure_rpz_name(view, rpz_obj, &zone->origin, str, "zone");
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ if (dns_name_equal(&zone->origin, dns_rootname)) {
+ cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "invalid zone name '%s'", str);
+ return (DNS_R_EMPTYLABEL);
+ }
+ if (!view->rpzs->p.dnsrps_enabled) {
+ for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones - 1;
+ ++rpz_num)
+ {
+ if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin,
+ &zone->origin))
+ {
+ cfg_obj_log(rpz_obj, named_g_lctx,
+ DNS_RPZ_ERROR_LEVEL,
+ "duplicate '%s'", str);
+ result = DNS_R_DUPLICATE;
+ return (result);
+ }
+ }
+ }
+ if (*old_rpz_okp && !dns_name_equal(&old->origin, &zone->origin)) {
+ *old_rpz_okp = false;
+ }
+
+ result = configure_rpz_name2(view, rpz_obj, &zone->client_ip,
+ DNS_RPZ_CLIENT_IP_ZONE, &zone->origin);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = configure_rpz_name2(view, rpz_obj, &zone->ip, DNS_RPZ_IP_ZONE,
+ &zone->origin);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = configure_rpz_name2(view, rpz_obj, &zone->nsdname,
+ DNS_RPZ_NSDNAME_ZONE, &zone->origin);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = configure_rpz_name2(view, rpz_obj, &zone->nsip,
+ DNS_RPZ_NSIP_ZONE, &zone->origin);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = configure_rpz_name(view, rpz_obj, &zone->passthru,
+ DNS_RPZ_PASSTHRU_NAME, "name");
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = configure_rpz_name(view, rpz_obj, &zone->drop,
+ DNS_RPZ_DROP_NAME, "name");
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = configure_rpz_name(view, rpz_obj, &zone->tcp_only,
+ DNS_RPZ_TCP_ONLY_NAME, "name");
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ obj = cfg_tuple_get(rpz_obj, "policy");
+ if (cfg_obj_isvoid(obj)) {
+ zone->policy = DNS_RPZ_POLICY_GIVEN;
+ } else {
+ str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name"));
+ zone->policy = dns_rpz_str2policy(str);
+ INSIST(zone->policy != DNS_RPZ_POLICY_ERROR);
+ if (zone->policy == DNS_RPZ_POLICY_CNAME) {
+ str = cfg_obj_asstring(cfg_tuple_get(obj, "cname"));
+ result = configure_rpz_name(view, rpz_obj, &zone->cname,
+ str, "cname");
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ }
+ if (*old_rpz_okp && (zone->policy != old->policy ||
+ !dns_name_equal(&old->cname, &zone->cname)))
+ {
+ *old_rpz_okp = false;
+ }
+
+ obj = cfg_tuple_get(rpz_obj, "add-soa");
+ if (cfg_obj_isvoid(obj)) {
+ zone->addsoa = add_soa_default;
+ } else {
+ zone->addsoa = cfg_obj_asboolean(obj);
+ }
+ if (*old_rpz_okp && zone->addsoa != old->addsoa) {
+ *old_rpz_okp = false;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+configure_rpz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t **maps,
+ const cfg_obj_t *rpz_obj, bool *old_rpz_okp) {
+ bool dnsrps_enabled;
+ const cfg_listelt_t *zone_element;
+ char *rps_cstr;
+ size_t rps_cstr_size;
+ const cfg_obj_t *sub_obj;
+ bool recursive_only_default, add_soa_default;
+ bool nsip_enabled, nsdname_enabled;
+ dns_rpz_zbits_t nsip_on, nsdname_on;
+ dns_ttl_t ttl_default;
+ uint32_t minupdateinterval_default;
+ dns_rpz_zones_t *zones;
+ const dns_rpz_zones_t *old;
+ bool pview_must_detach = false;
+ const dns_rpz_zone_t *old_zone;
+ isc_result_t result;
+ int i;
+
+ *old_rpz_okp = false;
+
+ zone_element = cfg_list_first(cfg_tuple_get(rpz_obj, "zone list"));
+ if (zone_element == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ nsip_enabled = true;
+ sub_obj = cfg_tuple_get(rpz_obj, "nsip-enable");
+ if (!cfg_obj_isvoid(sub_obj)) {
+ nsip_enabled = cfg_obj_asboolean(sub_obj);
+ }
+ nsip_on = nsip_enabled ? DNS_RPZ_ALL_ZBITS : 0;
+
+ nsdname_enabled = true;
+ sub_obj = cfg_tuple_get(rpz_obj, "nsdname-enable");
+ if (!cfg_obj_isvoid(sub_obj)) {
+ nsdname_enabled = cfg_obj_asboolean(sub_obj);
+ }
+ nsdname_on = nsdname_enabled ? DNS_RPZ_ALL_ZBITS : 0;
+
+ /*
+ * "dnsrps-enable yes|no" can be either a global or response-policy
+ * clause.
+ */
+ dnsrps_enabled = false;
+ rps_cstr = NULL;
+ rps_cstr_size = 0;
+ sub_obj = NULL;
+ (void)named_config_get(maps, "dnsrps-enable", &sub_obj);
+ if (sub_obj != NULL) {
+ dnsrps_enabled = cfg_obj_asboolean(sub_obj);
+ }
+ sub_obj = cfg_tuple_get(rpz_obj, "dnsrps-enable");
+ if (!cfg_obj_isvoid(sub_obj)) {
+ dnsrps_enabled = cfg_obj_asboolean(sub_obj);
+ }
+#ifndef USE_DNSRPS
+ if (dnsrps_enabled) {
+ cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "\"dnsrps-enable yes\" but"
+ " without `./configure --enable-dnsrps`");
+ return (ISC_R_FAILURE);
+ }
+#else /* ifndef USE_DNSRPS */
+ if (dnsrps_enabled) {
+ if (librpz == NULL) {
+ cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "\"dnsrps-enable yes\" but %s",
+ librpz_lib_open_emsg.c);
+ return (ISC_R_FAILURE);
+ }
+
+ /*
+ * Generate the DNS Response Policy Service
+ * configuration string.
+ */
+ result = conf_dnsrps(view, maps, nsip_enabled, nsdname_enabled,
+ &nsip_on, &nsdname_on, &rps_cstr,
+ &rps_cstr_size, rpz_obj, zone_element);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+#endif /* ifndef USE_DNSRPS */
+
+ result = dns_rpz_new_zones(view->mctx, named_g_taskmgr,
+ named_g_timermgr, rps_cstr, rps_cstr_size,
+ &view->rpzs);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ zones = view->rpzs;
+
+ zones->p.nsip_on = nsip_on;
+ zones->p.nsdname_on = nsdname_on;
+
+ sub_obj = cfg_tuple_get(rpz_obj, "recursive-only");
+ if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) {
+ recursive_only_default = false;
+ } else {
+ recursive_only_default = true;
+ }
+
+ sub_obj = cfg_tuple_get(rpz_obj, "add-soa");
+ if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) {
+ add_soa_default = false;
+ } else {
+ add_soa_default = true;
+ }
+
+ sub_obj = cfg_tuple_get(rpz_obj, "break-dnssec");
+ if (!cfg_obj_isvoid(sub_obj) && cfg_obj_asboolean(sub_obj)) {
+ zones->p.break_dnssec = true;
+ } else {
+ zones->p.break_dnssec = false;
+ }
+
+ sub_obj = cfg_tuple_get(rpz_obj, "max-policy-ttl");
+ if (cfg_obj_isduration(sub_obj)) {
+ ttl_default = cfg_obj_asduration(sub_obj);
+ } else {
+ ttl_default = DNS_RPZ_MAX_TTL_DEFAULT;
+ }
+
+ sub_obj = cfg_tuple_get(rpz_obj, "min-update-interval");
+ if (cfg_obj_isduration(sub_obj)) {
+ minupdateinterval_default = cfg_obj_asduration(sub_obj);
+ } else {
+ minupdateinterval_default = DNS_RPZ_MINUPDATEINTERVAL_DEFAULT;
+ }
+
+ sub_obj = cfg_tuple_get(rpz_obj, "min-ns-dots");
+ if (cfg_obj_isuint32(sub_obj)) {
+ zones->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1;
+ } else {
+ zones->p.min_ns_labels = 2;
+ }
+
+ sub_obj = cfg_tuple_get(rpz_obj, "qname-wait-recurse");
+ if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) {
+ zones->p.qname_wait_recurse = true;
+ } else {
+ zones->p.qname_wait_recurse = false;
+ }
+
+ sub_obj = cfg_tuple_get(rpz_obj, "nsdname-wait-recurse");
+ if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) {
+ zones->p.nsdname_wait_recurse = true;
+ } else {
+ zones->p.nsdname_wait_recurse = false;
+ }
+
+ sub_obj = cfg_tuple_get(rpz_obj, "nsip-wait-recurse");
+ if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) {
+ zones->p.nsip_wait_recurse = true;
+ } else {
+ zones->p.nsip_wait_recurse = false;
+ }
+
+ if (pview != NULL) {
+ old = pview->rpzs;
+ } else {
+ result = dns_viewlist_find(&named_g_server->viewlist,
+ view->name, view->rdclass, &pview);
+ if (result == ISC_R_SUCCESS) {
+ pview_must_detach = true;
+ old = pview->rpzs;
+ } else {
+ old = NULL;
+ }
+ }
+
+ if (old == NULL) {
+ *old_rpz_okp = false;
+ } else {
+ *old_rpz_okp = true;
+ }
+
+ for (i = 0; zone_element != NULL;
+ ++i, zone_element = cfg_list_next(zone_element))
+ {
+ INSIST(!*old_rpz_okp || old != NULL);
+ if (*old_rpz_okp && i < old->p.num_zones) {
+ old_zone = old->zones[i];
+ } else {
+ *old_rpz_okp = false;
+ old_zone = NULL;
+ }
+ result = configure_rpz_zone(
+ view, zone_element, recursive_only_default,
+ add_soa_default, ttl_default, minupdateinterval_default,
+ old_zone, old_rpz_okp);
+ if (result != ISC_R_SUCCESS) {
+ if (pview_must_detach) {
+ dns_view_detach(&pview);
+ }
+ return (result);
+ }
+ }
+
+ /*
+ * If this is a reloading and the parameters and list of policy
+ * zones are unchanged, then use the same policy data.
+ * Data for individual zones that must be reloaded will be merged.
+ */
+ if (*old_rpz_okp) {
+ if (old != NULL &&
+ memcmp(&old->p, &zones->p, sizeof(zones->p)) != 0)
+ {
+ *old_rpz_okp = false;
+ } else if ((old == NULL || old->rps_cstr == NULL) !=
+ (zones->rps_cstr == NULL))
+ {
+ *old_rpz_okp = false;
+ } else if (old != NULL && zones->rps_cstr != NULL &&
+ strcmp(old->rps_cstr, zones->rps_cstr) != 0)
+ {
+ *old_rpz_okp = false;
+ }
+ }
+
+ if (*old_rpz_okp) {
+ dns_rpz_shutdown_rpzs(view->rpzs);
+ dns_rpz_detach_rpzs(&view->rpzs);
+ dns_rpz_attach_rpzs(pview->rpzs, &view->rpzs);
+ dns_rpz_detach_rpzs(&pview->rpzs);
+ } else if (old != NULL && pview != NULL) {
+ ++pview->rpzs->rpz_ver;
+ view->rpzs->rpz_ver = pview->rpzs->rpz_ver;
+ cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_DEBUG_LEVEL1,
+ "updated RPZ policy: version %d",
+ view->rpzs->rpz_ver);
+ }
+
+ if (pview_must_detach) {
+ dns_view_detach(&pview);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+catz_addmodzone_taskaction(isc_task_t *task, isc_event_t *event0) {
+ catz_chgzone_event_t *ev = (catz_chgzone_event_t *)event0;
+ isc_result_t result;
+ dns_forwarders_t *dnsforwarders = NULL;
+ dns_name_t *name = NULL;
+ isc_buffer_t namebuf;
+ isc_buffer_t *confbuf;
+ char nameb[DNS_NAME_FORMATSIZE];
+ const cfg_obj_t *zlist = NULL;
+ cfg_obj_t *zoneconf = NULL;
+ cfg_obj_t *zoneobj = NULL;
+ ns_cfgctx_t *cfg;
+ dns_zone_t *zone = NULL;
+
+ cfg = (ns_cfgctx_t *)ev->view->new_zone_config;
+ if (cfg == NULL) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "catz: allow-new-zones statement missing from "
+ "config; cannot add zone from the catalog");
+ goto cleanup;
+ }
+
+ name = dns_catz_entry_getname(ev->entry);
+
+ isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE);
+ dns_name_totext(name, true, &namebuf);
+ isc_buffer_putuint8(&namebuf, 0);
+
+ result = dns_fwdtable_find(ev->view->fwdtable, name, NULL,
+ &dnsforwarders);
+ if (result == ISC_R_SUCCESS &&
+ dnsforwarders->fwdpolicy == dns_fwdpolicy_only)
+ {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: catz_addmodzone_taskaction: "
+ "zone '%s' will not be processed because of the "
+ "explicitly configured forwarding for that zone",
+ nameb);
+ goto cleanup;
+ }
+
+ result = dns_zt_find(ev->view->zonetable, name, 0, NULL, &zone);
+
+ if (ev->mod) {
+ dns_catz_zone_t *parentcatz;
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: error \"%s\" while trying to "
+ "modify zone '%s'",
+ isc_result_totext(result), nameb);
+ goto cleanup;
+ }
+
+ if (!dns_zone_getadded(zone)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: catz_addmodzone_taskaction: "
+ "zone '%s' is not a dynamically "
+ "added zone",
+ nameb);
+ goto cleanup;
+ }
+
+ parentcatz = dns_zone_get_parentcatz(zone);
+
+ if (parentcatz == NULL) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: catz_addmodzone_taskaction: "
+ "zone '%s' exists and is not added by "
+ "a catalog zone, so won't be modified",
+ nameb);
+ goto cleanup;
+ }
+ if (parentcatz != ev->origin) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: catz_addmodzone_taskaction: "
+ "zone '%s' exists in multiple "
+ "catalog zones",
+ nameb);
+ goto cleanup;
+ }
+
+ dns_zone_detach(&zone);
+ } else {
+ /* Zone shouldn't already exist when adding */
+ if (result == ISC_R_SUCCESS) {
+ if (dns_zone_get_parentcatz(zone) == NULL) {
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: "
+ "catz_addmodzone_taskaction: "
+ "zone '%s' will not be added "
+ "because it is an explicitly "
+ "configured zone",
+ nameb);
+ } else {
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: "
+ "catz_addmodzone_taskaction: "
+ "zone '%s' will not be added "
+ "because another catalog zone "
+ "already contains an entry with "
+ "that zone",
+ nameb);
+ }
+ goto cleanup;
+ } else if (result != ISC_R_NOTFOUND &&
+ result != DNS_R_PARTIALMATCH)
+ {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: error \"%s\" while trying to "
+ "add zone '%s'",
+ isc_result_totext(result), nameb);
+ goto cleanup;
+ } else { /* this can happen in case of DNS_R_PARTIALMATCH */
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ }
+ }
+ RUNTIME_CHECK(zone == NULL);
+ /* Create a config for new zone */
+ confbuf = NULL;
+ result = dns_catz_generate_zonecfg(ev->origin, ev->entry, &confbuf);
+ if (result == ISC_R_SUCCESS) {
+ cfg_parser_reset(cfg->add_parser);
+ result = cfg_parse_buffer(cfg->add_parser, confbuf, "catz", 0,
+ &cfg_type_addzoneconf, 0, &zoneconf);
+ isc_buffer_free(&confbuf);
+ }
+ /*
+ * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer3()
+ * failed.
+ */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "catz: error \"%s\" while trying to generate "
+ "config for zone '%s'",
+ isc_result_totext(result), nameb);
+ goto cleanup;
+ }
+ CHECK(cfg_map_get(zoneconf, "zone", &zlist));
+ if (!cfg_obj_islist(zlist)) {
+ CHECK(ISC_R_FAILURE);
+ }
+
+ /* For now we only support adding one zone at a time */
+ zoneobj = cfg_listelt_value(cfg_list_first(zlist));
+
+ /* Mark view unfrozen so that zone can be added */
+
+ result = isc_task_beginexclusive(task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_view_thaw(ev->view);
+ result = configure_zone(
+ cfg->config, zoneobj, cfg->vconfig, ev->cbd->server->mctx,
+ ev->view, &ev->cbd->server->viewlist,
+ &ev->cbd->server->kasplist, cfg->actx, true, false, ev->mod);
+ dns_view_freeze(ev->view);
+ isc_task_endexclusive(task);
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: failed to configure zone '%s' - %d", nameb,
+ result);
+ goto cleanup;
+ }
+
+ /* Is it there yet? */
+ CHECK(dns_zt_find(ev->view->zonetable, name, 0, NULL, &zone));
+
+ /*
+ * Load the zone from the master file. If this fails, we'll
+ * need to undo the configuration we've done already.
+ */
+ result = dns_zone_load(zone, true);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_t *dbp = NULL;
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "catz: dns_zone_load() failed "
+ "with %s; reverting.",
+ isc_result_totext(result));
+
+ /* If the zone loaded partially, unload it */
+ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
+ dns_db_detach(&dbp);
+ dns_zone_unload(zone);
+ }
+
+ /* Remove the zone from the zone table */
+ dns_zt_unmount(ev->view->zonetable, zone);
+ goto cleanup;
+ }
+
+ /* Flag the zone as having been added at runtime */
+ dns_zone_setadded(zone, true);
+ dns_zone_set_parentcatz(zone, ev->origin);
+
+cleanup:
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ if (zoneconf != NULL) {
+ cfg_obj_destroy(cfg->add_parser, &zoneconf);
+ }
+ dns_catz_entry_detach(ev->origin, &ev->entry);
+ dns_catz_detach_catz(&ev->origin);
+ dns_view_detach(&ev->view);
+ isc_event_free(ISC_EVENT_PTR(&ev));
+}
+
+static void
+catz_delzone_taskaction(isc_task_t *task, isc_event_t *event0) {
+ catz_chgzone_event_t *ev = (catz_chgzone_event_t *)event0;
+ isc_result_t result;
+ dns_zone_t *zone = NULL;
+ dns_db_t *dbp = NULL;
+ char cname[DNS_NAME_FORMATSIZE];
+ const char *file;
+
+ result = isc_task_beginexclusive(task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ dns_name_format(dns_catz_entry_getname(ev->entry), cname,
+ DNS_NAME_FORMATSIZE);
+ result = dns_zt_find(ev->view->zonetable,
+ dns_catz_entry_getname(ev->entry), 0, NULL, &zone);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: catz_delzone_taskaction: "
+ "zone '%s' not found",
+ cname);
+ goto cleanup;
+ }
+
+ if (!dns_zone_getadded(zone)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: catz_delzone_taskaction: "
+ "zone '%s' is not a dynamically added zone",
+ cname);
+ goto cleanup;
+ }
+
+ if (dns_zone_get_parentcatz(zone) != ev->origin) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: catz_delzone_taskaction: zone "
+ "'%s' exists in multiple catalog zones",
+ cname);
+ goto cleanup;
+ }
+
+ /* Stop answering for this zone */
+ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
+ dns_db_detach(&dbp);
+ dns_zone_unload(zone);
+ }
+
+ CHECK(dns_zt_unmount(ev->view->zonetable, zone));
+ file = dns_zone_getfile(zone);
+ if (file != NULL) {
+ isc_file_remove(file);
+ file = dns_zone_getjournal(zone);
+ if (file != NULL) {
+ isc_file_remove(file);
+ }
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "catz: catz_delzone_taskaction: "
+ "zone '%s' deleted",
+ cname);
+cleanup:
+ isc_task_endexclusive(task);
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ dns_catz_entry_detach(ev->origin, &ev->entry);
+ dns_catz_detach_catz(&ev->origin);
+ dns_view_detach(&ev->view);
+ isc_event_free(ISC_EVENT_PTR(&ev));
+}
+
+static isc_result_t
+catz_create_chg_task(dns_catz_entry_t *entry, dns_catz_zone_t *origin,
+ dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata,
+ isc_eventtype_t type) {
+ catz_chgzone_event_t *event = NULL;
+ isc_task_t *task = NULL;
+ isc_result_t result;
+ isc_taskaction_t action = NULL;
+
+ result = isc_taskmgr_excltask(taskmgr, &task);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ switch (type) {
+ case DNS_EVENT_CATZADDZONE:
+ case DNS_EVENT_CATZMODZONE:
+ action = catz_addmodzone_taskaction;
+ break;
+ case DNS_EVENT_CATZDELZONE:
+ action = catz_delzone_taskaction;
+ break;
+ default:
+ REQUIRE(0);
+ UNREACHABLE();
+ }
+
+ event = (catz_chgzone_event_t *)isc_event_allocate(
+ view->mctx, origin, type, action, NULL, sizeof(*event));
+
+ event->cbd = (catz_cb_data_t *)udata;
+ event->entry = NULL;
+ event->origin = NULL;
+ event->view = NULL;
+ event->mod = (type == DNS_EVENT_CATZMODZONE);
+
+ dns_catz_entry_attach(entry, &event->entry);
+ dns_catz_attach_catz(origin, &event->origin);
+ dns_view_attach(view, &event->view);
+
+ isc_task_send(task, ISC_EVENT_PTR(&event));
+ isc_task_detach(&task);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+catz_addzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view,
+ isc_taskmgr_t *taskmgr, void *udata) {
+ return (catz_create_chg_task(entry, origin, view, taskmgr, udata,
+ DNS_EVENT_CATZADDZONE));
+}
+
+static isc_result_t
+catz_delzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view,
+ isc_taskmgr_t *taskmgr, void *udata) {
+ return (catz_create_chg_task(entry, origin, view, taskmgr, udata,
+ DNS_EVENT_CATZDELZONE));
+}
+
+static isc_result_t
+catz_modzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view,
+ isc_taskmgr_t *taskmgr, void *udata) {
+ return (catz_create_chg_task(entry, origin, view, taskmgr, udata,
+ DNS_EVENT_CATZMODZONE));
+}
+
+static isc_result_t
+configure_catz_zone(dns_view_t *view, dns_view_t *pview,
+ const cfg_obj_t *config, const cfg_listelt_t *element) {
+ const cfg_obj_t *catz_obj, *obj;
+ dns_catz_zone_t *zone = NULL;
+ const char *str;
+ isc_result_t result;
+ dns_name_t origin;
+ dns_catz_options_t *opts;
+
+ dns_name_init(&origin, NULL);
+ catz_obj = cfg_listelt_value(element);
+
+ str = cfg_obj_asstring(cfg_tuple_get(catz_obj, "zone name"));
+
+ result = dns_name_fromstring(&origin, str, DNS_NAME_DOWNCASE,
+ view->mctx);
+ if (result == ISC_R_SUCCESS && dns_name_equal(&origin, dns_rootname)) {
+ result = DNS_R_EMPTYLABEL;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(catz_obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL,
+ "catz: invalid zone name '%s'", str);
+ goto cleanup;
+ }
+
+ result = dns_catz_add_zone(view->catzs, &origin, &zone);
+ if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
+ cfg_obj_log(catz_obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL,
+ "catz: unable to create catalog zone '%s', "
+ "error %s",
+ str, isc_result_totext(result));
+ goto cleanup;
+ }
+
+ if (result == ISC_R_EXISTS) {
+ isc_ht_iter_t *it = NULL;
+
+ RUNTIME_CHECK(pview != NULL);
+
+ /*
+ * xxxwpk todo: reconfigure the zone!!!!
+ */
+ cfg_obj_log(catz_obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL,
+ "catz: catalog zone '%s' will not be reconfigured",
+ str);
+ /*
+ * We have to walk through all the member zones and attach
+ * them to current view
+ */
+ dns_catz_get_iterator(zone, &it);
+
+ for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
+ result = isc_ht_iter_next(it))
+ {
+ dns_name_t *name = NULL;
+ dns_zone_t *dnszone = NULL;
+ dns_catz_entry_t *entry = NULL;
+ isc_result_t tresult;
+
+ isc_ht_iter_current(it, (void **)&entry);
+ name = dns_catz_entry_getname(entry);
+
+ tresult = dns_view_findzone(pview, name, &dnszone);
+ if (tresult != ISC_R_SUCCESS) {
+ continue;
+ }
+
+ dns_zone_setview(dnszone, view);
+ dns_view_addzone(view, dnszone);
+
+ /*
+ * The dns_view_findzone() call above increments the
+ * zone's reference count, which we need to decrement
+ * back. However, as dns_zone_detach() sets the
+ * supplied pointer to NULL, calling it is deferred
+ * until the dnszone variable is no longer used.
+ */
+ dns_zone_detach(&dnszone);
+ }
+
+ isc_ht_iter_destroy(&it);
+
+ result = ISC_R_SUCCESS;
+ }
+
+ dns_catz_zone_resetdefoptions(zone);
+ opts = dns_catz_zone_getdefoptions(zone);
+
+ obj = cfg_tuple_get(catz_obj, "default-masters");
+ if (obj == NULL || !cfg_obj_istuple(obj)) {
+ obj = cfg_tuple_get(catz_obj, "default-primaries");
+ }
+ if (obj != NULL && cfg_obj_istuple(obj)) {
+ result = named_config_getipandkeylist(
+ config, "primaries", obj, view->mctx, &opts->masters);
+ }
+
+ obj = cfg_tuple_get(catz_obj, "in-memory");
+ if (obj != NULL && cfg_obj_isboolean(obj)) {
+ opts->in_memory = cfg_obj_asboolean(obj);
+ }
+
+ obj = cfg_tuple_get(catz_obj, "zone-directory");
+ if (!opts->in_memory && obj != NULL && cfg_obj_isstring(obj)) {
+ opts->zonedir = isc_mem_strdup(view->mctx,
+ cfg_obj_asstring(obj));
+ if (isc_file_isdirectory(opts->zonedir) != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL,
+ "catz: zone-directory '%s' "
+ "not found; zone files will not be "
+ "saved",
+ opts->zonedir);
+ opts->in_memory = true;
+ }
+ }
+
+ obj = cfg_tuple_get(catz_obj, "min-update-interval");
+ if (obj != NULL && cfg_obj_isduration(obj)) {
+ opts->min_update_interval = cfg_obj_asduration(obj);
+ }
+
+cleanup:
+ dns_name_free(&origin, view->mctx);
+
+ return (result);
+}
+
+static catz_cb_data_t ns_catz_cbdata;
+static dns_catz_zonemodmethods_t ns_catz_zonemodmethods = {
+ catz_addzone, catz_modzone, catz_delzone, &ns_catz_cbdata
+};
+
+static isc_result_t
+configure_catz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t *config,
+ const cfg_obj_t *catz_obj) {
+ const cfg_listelt_t *zone_element = NULL;
+ const dns_catz_zones_t *old = NULL;
+ bool pview_must_detach = false;
+ isc_result_t result;
+
+ /* xxxwpk TODO do it cleaner, once, somewhere */
+ ns_catz_cbdata.server = named_g_server;
+
+ zone_element = cfg_list_first(cfg_tuple_get(catz_obj, "zone list"));
+ if (zone_element == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ CHECK(dns_catz_new_zones(view->mctx, named_g_taskmgr, named_g_timermgr,
+ &view->catzs, &ns_catz_zonemodmethods));
+
+ if (pview != NULL) {
+ old = pview->catzs;
+ } else {
+ result = dns_viewlist_find(&named_g_server->viewlist,
+ view->name, view->rdclass, &pview);
+ if (result == ISC_R_SUCCESS) {
+ pview_must_detach = true;
+ old = pview->catzs;
+ }
+ }
+
+ if (old != NULL) {
+ dns_catz_shutdown_catzs(view->catzs);
+ dns_catz_detach_catzs(&view->catzs);
+ dns_catz_attach_catzs(pview->catzs, &view->catzs);
+ dns_catz_detach_catzs(&pview->catzs);
+ dns_catz_prereconfig(view->catzs);
+ }
+
+ while (zone_element != NULL) {
+ CHECK(configure_catz_zone(view, pview, config, zone_element));
+ zone_element = cfg_list_next(zone_element);
+ }
+
+ if (old != NULL) {
+ dns_catz_postreconfig(view->catzs);
+ }
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (pview_must_detach) {
+ dns_view_detach(&pview);
+ }
+
+ return (result);
+}
+
+#define CHECK_RRL(cond, pat, val1, val2) \
+ do { \
+ if (!(cond)) { \
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, pat, \
+ val1, val2); \
+ result = ISC_R_RANGE; \
+ goto cleanup; \
+ } \
+ } while (0)
+
+#define CHECK_RRL_RATE(rate, def, max_rate, name) \
+ do { \
+ obj = NULL; \
+ rrl->rate.str = name; \
+ result = cfg_map_get(map, name, &obj); \
+ if (result == ISC_R_SUCCESS) { \
+ rrl->rate.r = cfg_obj_asuint32(obj); \
+ CHECK_RRL(rrl->rate.r <= max_rate, name " %d > %d", \
+ rrl->rate.r, max_rate); \
+ } else { \
+ rrl->rate.r = def; \
+ } \
+ rrl->rate.scaled = rrl->rate.r; \
+ } while (0)
+
+static isc_result_t
+configure_rrl(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *map) {
+ const cfg_obj_t *obj;
+ dns_rrl_t *rrl;
+ isc_result_t result;
+ int min_entries, i, j;
+
+ /*
+ * Most DNS servers have few clients, but intentinally open
+ * recursive and authoritative servers often have many.
+ * So start with a small number of entries unless told otherwise
+ * to reduce cold-start costs.
+ */
+ min_entries = 500;
+ obj = NULL;
+ result = cfg_map_get(map, "min-table-size", &obj);
+ if (result == ISC_R_SUCCESS) {
+ min_entries = cfg_obj_asuint32(obj);
+ if (min_entries < 1) {
+ min_entries = 1;
+ }
+ }
+ result = dns_rrl_init(&rrl, view, min_entries);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ i = ISC_MAX(20000, min_entries);
+ obj = NULL;
+ result = cfg_map_get(map, "max-table-size", &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ CHECK_RRL(i >= min_entries,
+ "max-table-size %d < min-table-size %d", i,
+ min_entries);
+ }
+ rrl->max_entries = i;
+
+ CHECK_RRL_RATE(responses_per_second, 0, DNS_RRL_MAX_RATE,
+ "responses-per-second");
+ CHECK_RRL_RATE(referrals_per_second, rrl->responses_per_second.r,
+ DNS_RRL_MAX_RATE, "referrals-per-second");
+ CHECK_RRL_RATE(nodata_per_second, rrl->responses_per_second.r,
+ DNS_RRL_MAX_RATE, "nodata-per-second");
+ CHECK_RRL_RATE(nxdomains_per_second, rrl->responses_per_second.r,
+ DNS_RRL_MAX_RATE, "nxdomains-per-second");
+ CHECK_RRL_RATE(errors_per_second, rrl->responses_per_second.r,
+ DNS_RRL_MAX_RATE, "errors-per-second");
+
+ CHECK_RRL_RATE(all_per_second, 0, DNS_RRL_MAX_RATE, "all-per-second");
+
+ CHECK_RRL_RATE(slip, 2, DNS_RRL_MAX_SLIP, "slip");
+
+ i = 15;
+ obj = NULL;
+ result = cfg_map_get(map, "window", &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ CHECK_RRL(i >= 1 && i <= DNS_RRL_MAX_WINDOW,
+ "window %d < 1 or > %d", i, DNS_RRL_MAX_WINDOW);
+ }
+ rrl->window = i;
+
+ i = 0;
+ obj = NULL;
+ result = cfg_map_get(map, "qps-scale", &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ CHECK_RRL(i >= 1, "invalid 'qps-scale %d'%s", i, "");
+ }
+ rrl->qps_scale = i;
+ rrl->qps = 1.0;
+
+ i = 24;
+ obj = NULL;
+ result = cfg_map_get(map, "ipv4-prefix-length", &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ CHECK_RRL(i >= 8 && i <= 32,
+ "invalid 'ipv4-prefix-length %d'%s", i, "");
+ }
+ rrl->ipv4_prefixlen = i;
+ if (i == 32) {
+ rrl->ipv4_mask = 0xffffffff;
+ } else {
+ rrl->ipv4_mask = htonl(0xffffffff << (32 - i));
+ }
+
+ i = 56;
+ obj = NULL;
+ result = cfg_map_get(map, "ipv6-prefix-length", &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ CHECK_RRL(i >= 16 && i <= DNS_RRL_MAX_PREFIX,
+ "ipv6-prefix-length %d < 16 or > %d", i,
+ DNS_RRL_MAX_PREFIX);
+ }
+ rrl->ipv6_prefixlen = i;
+ for (j = 0; j < 4; ++j) {
+ if (i <= 0) {
+ rrl->ipv6_mask[j] = 0;
+ } else if (i < 32) {
+ rrl->ipv6_mask[j] = htonl(0xffffffff << (32 - i));
+ } else {
+ rrl->ipv6_mask[j] = 0xffffffff;
+ }
+ i -= 32;
+ }
+
+ obj = NULL;
+ result = cfg_map_get(map, "exempt-clients", &obj);
+ if (result == ISC_R_SUCCESS) {
+ result = cfg_acl_fromconfig(obj, config, named_g_lctx,
+ named_g_aclconfctx, named_g_mctx, 0,
+ &rrl->exempt);
+ CHECK_RRL(result == ISC_R_SUCCESS, "invalid %s%s",
+ "address match list", "");
+ }
+
+ obj = NULL;
+ result = cfg_map_get(map, "log-only", &obj);
+ if (result == ISC_R_SUCCESS && cfg_obj_asboolean(obj)) {
+ rrl->log_only = true;
+ } else {
+ rrl->log_only = false;
+ }
+
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ dns_rrl_view_destroy(view);
+ return (result);
+}
+
+static isc_result_t
+add_soa(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name,
+ const dns_name_t *origin, const dns_name_t *contact) {
+ dns_dbnode_t *node = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+ unsigned char buf[DNS_SOA_BUFFERSIZE];
+
+ CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), 0, 28800,
+ 7200, 604800, 86400, buf, &rdata));
+
+ dns_rdatalist_init(&rdatalist);
+ rdatalist.type = rdata.type;
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.ttl = 86400;
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+
+ dns_rdataset_init(&rdataset);
+ CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
+ CHECK(dns_db_findnode(db, name, true, &node));
+ CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL));
+
+cleanup:
+ if (node != NULL) {
+ dns_db_detachnode(db, &node);
+ }
+ return (result);
+}
+
+static isc_result_t
+add_ns(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name,
+ const dns_name_t *nsname) {
+ dns_dbnode_t *node = NULL;
+ dns_rdata_ns_t ns;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+ isc_buffer_t b;
+ unsigned char buf[DNS_NAME_MAXWIRE];
+
+ isc_buffer_init(&b, buf, sizeof(buf));
+
+ ns.common.rdtype = dns_rdatatype_ns;
+ ns.common.rdclass = dns_db_class(db);
+ ns.mctx = NULL;
+ dns_name_init(&ns.name, NULL);
+ dns_name_clone(nsname, &ns.name);
+ CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns,
+ &ns, &b));
+
+ dns_rdatalist_init(&rdatalist);
+ rdatalist.type = rdata.type;
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.ttl = 86400;
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+
+ dns_rdataset_init(&rdataset);
+ CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
+ CHECK(dns_db_findnode(db, name, true, &node));
+ CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL));
+
+cleanup:
+ if (node != NULL) {
+ dns_db_detachnode(db, &node);
+ }
+ return (result);
+}
+
+static isc_result_t
+create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view,
+ const cfg_obj_t *zonelist, const char **empty_dbtype,
+ int empty_dbtypec, dns_zonestat_level_t statlevel) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ const cfg_listelt_t *element;
+ const cfg_obj_t *obj;
+ const cfg_obj_t *zconfig;
+ const cfg_obj_t *zoptions;
+ const char *rbt_dbtype[4] = { "rbt" };
+ const char *sep = ": view ";
+ const char *str;
+ const char *viewname = view->name;
+ dns_db_t *db = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_fixedname_t cfixed;
+ dns_fixedname_t fixed;
+ dns_fixedname_t nsfixed;
+ dns_name_t *contact;
+ dns_name_t *ns;
+ dns_name_t *zname;
+ dns_zone_t *zone = NULL;
+ int rbt_dbtypec = 1;
+ isc_result_t result;
+ dns_namereln_t namereln;
+ int order;
+ unsigned int nlabels;
+
+ zname = dns_fixedname_initname(&fixed);
+ ns = dns_fixedname_initname(&nsfixed);
+ contact = dns_fixedname_initname(&cfixed);
+
+ /*
+ * Look for forward "zones" beneath this empty zone and if so
+ * create a custom db for the empty zone.
+ */
+ for (element = cfg_list_first(zonelist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ zconfig = cfg_listelt_value(element);
+ str = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+ CHECK(dns_name_fromstring(zname, str, 0, NULL));
+ namereln = dns_name_fullcompare(zname, name, &order, &nlabels);
+ if (namereln != dns_namereln_subdomain) {
+ continue;
+ }
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "type", &obj);
+ if (obj != NULL &&
+ strcasecmp(cfg_obj_asstring(obj), "forward") == 0)
+ {
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "forward", &obj);
+ if (obj == NULL) {
+ continue;
+ }
+ if (strcasecmp(cfg_obj_asstring(obj), "only") != 0) {
+ continue;
+ }
+ }
+ if (db == NULL) {
+ CHECK(dns_db_create(view->mctx, "rbt", name,
+ dns_dbtype_zone, view->rdclass, 0,
+ NULL, &db));
+ CHECK(dns_db_newversion(db, &version));
+ if (strcmp(empty_dbtype[2], "@") == 0) {
+ dns_name_clone(name, ns);
+ } else {
+ CHECK(dns_name_fromstring(ns, empty_dbtype[2],
+ 0, NULL));
+ }
+ CHECK(dns_name_fromstring(contact, empty_dbtype[3], 0,
+ NULL));
+ CHECK(add_soa(db, version, name, ns, contact));
+ CHECK(add_ns(db, version, name, ns));
+ }
+ CHECK(add_ns(db, version, zname, dns_rootname));
+ }
+
+ /*
+ * Is the existing zone the ok to use?
+ */
+ if (pzone != NULL) {
+ unsigned int typec;
+ const char **dbargv;
+
+ if (db != NULL) {
+ typec = rbt_dbtypec;
+ dbargv = rbt_dbtype;
+ } else {
+ typec = empty_dbtypec;
+ dbargv = empty_dbtype;
+ }
+
+ result = check_dbtype(pzone, typec, dbargv, view->mctx);
+ if (result != ISC_R_SUCCESS) {
+ pzone = NULL;
+ }
+
+ if (pzone != NULL &&
+ dns_zone_gettype(pzone) != dns_zone_primary)
+ {
+ pzone = NULL;
+ }
+ if (pzone != NULL && dns_zone_getfile(pzone) != NULL) {
+ pzone = NULL;
+ }
+ if (pzone != NULL) {
+ dns_zone_getraw(pzone, &zone);
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ pzone = NULL;
+ }
+ }
+ }
+
+ if (pzone == NULL) {
+ CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone));
+ CHECK(dns_zone_setorigin(zone, name));
+ CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
+ if (db == NULL) {
+ dns_zone_setdbtype(zone, empty_dbtypec, empty_dbtype);
+ }
+ dns_zone_setclass(zone, view->rdclass);
+ dns_zone_settype(zone, dns_zone_primary);
+ dns_zone_setstats(zone, named_g_server->zonestats);
+ } else {
+ dns_zone_attach(pzone, &zone);
+ }
+
+ dns_zone_setoption(zone, ~DNS_ZONEOPT_NOCHECKNS, false);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true);
+ dns_zone_setnotifytype(zone, dns_notifytype_no);
+ dns_zone_setdialup(zone, dns_dialuptype_no);
+ dns_zone_setautomatic(zone, true);
+ if (view->queryacl != NULL) {
+ dns_zone_setqueryacl(zone, view->queryacl);
+ } else {
+ dns_zone_clearqueryacl(zone);
+ }
+ if (view->queryonacl != NULL) {
+ dns_zone_setqueryonacl(zone, view->queryonacl);
+ } else {
+ dns_zone_clearqueryonacl(zone);
+ }
+ dns_zone_clearupdateacl(zone);
+ if (view->transferacl != NULL) {
+ dns_zone_setxfracl(zone, view->transferacl);
+ } else {
+ dns_zone_clearxfracl(zone);
+ }
+
+ CHECK(setquerystats(zone, view->mctx, statlevel));
+ if (db != NULL) {
+ dns_db_closeversion(db, &version, true);
+ CHECK(dns_zone_replacedb(zone, db, false));
+ }
+ dns_zone_setoption(zone, DNS_ZONEOPT_AUTOEMPTY, true);
+ dns_zone_setview(zone, view);
+ CHECK(dns_view_addzone(view, zone));
+
+ if (!strcmp(viewname, "_default")) {
+ sep = "";
+ viewname = "";
+ }
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ isc_log_write(named_g_lctx, DNS_LOGCATEGORY_ZONELOAD,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "automatic empty zone%s%s: %s", sep, viewname, namebuf);
+
+cleanup:
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ if (version != NULL) {
+ dns_db_closeversion(db, &version, false);
+ }
+ if (db != NULL) {
+ dns_db_detach(&db);
+ }
+
+ INSIST(version == NULL);
+
+ return (result);
+}
+
+static isc_result_t
+create_ipv4only_zone(dns_zone_t *pzone, dns_view_t *view,
+ const dns_name_t *name, const char *type, isc_mem_t *mctx,
+ const char *server, const char *contact) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ const char *dbtype[4] = { "_builtin", NULL, "@", "." };
+ const char *sep = ": view ";
+ const char *viewname = view->name;
+ dns_zone_t *zone = NULL;
+ int dbtypec = 4;
+ isc_result_t result;
+
+ REQUIRE(type != NULL);
+
+ if (!strcmp(viewname, "_default")) {
+ sep = "";
+ viewname = "";
+ }
+
+ dbtype[1] = type;
+ if (server != NULL) {
+ dbtype[2] = server;
+ }
+ if (contact != NULL) {
+ dbtype[3] = contact;
+ }
+
+ if (pzone != NULL) {
+ result = check_dbtype(pzone, dbtypec, dbtype, view->mctx);
+ if (result != ISC_R_SUCCESS) {
+ pzone = NULL;
+ }
+ }
+
+ if (pzone == NULL) {
+ /*
+ * Create the actual zone.
+ */
+ CHECK(dns_zone_create(&zone, mctx));
+ CHECK(dns_zone_setorigin(zone, name));
+ CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
+ dns_zone_setclass(zone, view->rdclass);
+ dns_zone_settype(zone, dns_zone_primary);
+ dns_zone_setstats(zone, named_g_server->zonestats);
+ dns_zone_setdbtype(zone, dbtypec, dbtype);
+ dns_zone_setdialup(zone, dns_dialuptype_no);
+ dns_zone_setnotifytype(zone, dns_notifytype_no);
+ dns_zone_setautomatic(zone, true);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true);
+ } else {
+ dns_zone_attach(pzone, &zone);
+ }
+ if (view->queryacl != NULL) {
+ dns_zone_setqueryacl(zone, view->queryacl);
+ } else {
+ dns_zone_clearqueryacl(zone);
+ }
+ if (view->queryonacl != NULL) {
+ dns_zone_setqueryonacl(zone, view->queryonacl);
+ } else {
+ dns_zone_clearqueryonacl(zone);
+ }
+ dns_zone_setview(zone, view);
+ CHECK(dns_view_addzone(view, zone));
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "automatic ipv4only zone%s%s: %s", sep, viewname,
+ namebuf);
+
+cleanup:
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ return (result);
+}
+
+#ifdef HAVE_DNSTAP
+static isc_result_t
+configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) {
+ isc_result_t result;
+ const cfg_obj_t *obj, *obj2;
+ const cfg_listelt_t *element;
+ const char *dpath;
+ const cfg_obj_t *dlist = NULL;
+ dns_dtmsgtype_t dttypes = 0;
+ unsigned int i;
+ struct fstrm_iothr_options *fopt = NULL;
+
+ result = named_config_get(maps, "dnstap", &dlist);
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_SUCCESS);
+ }
+
+ for (element = cfg_list_first(dlist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const char *str;
+ dns_dtmsgtype_t dt = 0;
+
+ obj = cfg_listelt_value(element);
+ obj2 = cfg_tuple_get(obj, "type");
+ str = cfg_obj_asstring(obj2);
+ if (strcasecmp(str, "client") == 0) {
+ dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR;
+ } else if (strcasecmp(str, "auth") == 0) {
+ dt |= DNS_DTTYPE_AQ | DNS_DTTYPE_AR;
+ } else if (strcasecmp(str, "resolver") == 0) {
+ dt |= DNS_DTTYPE_RQ | DNS_DTTYPE_RR;
+ } else if (strcasecmp(str, "forwarder") == 0) {
+ dt |= DNS_DTTYPE_FQ | DNS_DTTYPE_FR;
+ } else if (strcasecmp(str, "update") == 0) {
+ dt |= DNS_DTTYPE_UQ | DNS_DTTYPE_UR;
+ } else if (strcasecmp(str, "all") == 0) {
+ dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR | DNS_DTTYPE_AQ |
+ DNS_DTTYPE_AR | DNS_DTTYPE_RQ | DNS_DTTYPE_RR |
+ DNS_DTTYPE_FQ | DNS_DTTYPE_FR | DNS_DTTYPE_UQ |
+ DNS_DTTYPE_UR;
+ }
+
+ obj2 = cfg_tuple_get(obj, "mode");
+ if (obj2 == NULL || cfg_obj_isvoid(obj2)) {
+ dttypes |= dt;
+ continue;
+ }
+
+ str = cfg_obj_asstring(obj2);
+ if (strcasecmp(str, "query") == 0) {
+ dt &= ~DNS_DTTYPE_RESPONSE;
+ } else if (strcasecmp(str, "response") == 0) {
+ dt &= ~DNS_DTTYPE_QUERY;
+ }
+
+ dttypes |= dt;
+ }
+
+ if (named_g_server->dtenv == NULL && dttypes != 0) {
+ dns_dtmode_t dmode;
+ uint64_t max_size = 0;
+ uint32_t rolls = 0;
+ isc_log_rollsuffix_t suffix = isc_log_rollsuffix_increment;
+
+ obj = NULL;
+ CHECKM(named_config_get(maps, "dnstap-output", &obj),
+ "'dnstap-output' must be set if 'dnstap' is set");
+
+ obj2 = cfg_tuple_get(obj, "mode");
+ if (obj2 == NULL) {
+ CHECKM(ISC_R_FAILURE, "dnstap-output mode not found");
+ }
+ if (strcasecmp(cfg_obj_asstring(obj2), "file") == 0) {
+ dmode = dns_dtmode_file;
+ } else {
+ dmode = dns_dtmode_unix;
+ }
+
+ obj2 = cfg_tuple_get(obj, "path");
+ if (obj2 == NULL) {
+ CHECKM(ISC_R_FAILURE, "dnstap-output path not found");
+ }
+
+ dpath = cfg_obj_asstring(obj2);
+
+ obj2 = cfg_tuple_get(obj, "size");
+ if (obj2 != NULL && cfg_obj_isuint64(obj2)) {
+ max_size = cfg_obj_asuint64(obj2);
+ if (max_size > SIZE_MAX) {
+ cfg_obj_log(obj2, named_g_lctx, ISC_LOG_WARNING,
+ "'dnstap-output size "
+ "%" PRIu64 "' "
+ "is too large for this "
+ "system; reducing to %lu",
+ max_size, (unsigned long)SIZE_MAX);
+ max_size = SIZE_MAX;
+ }
+ }
+
+ obj2 = cfg_tuple_get(obj, "versions");
+ if (obj2 != NULL && cfg_obj_isuint32(obj2)) {
+ rolls = cfg_obj_asuint32(obj2);
+ } else {
+ rolls = ISC_LOG_ROLLINFINITE;
+ }
+
+ obj2 = cfg_tuple_get(obj, "suffix");
+ if (obj2 != NULL && cfg_obj_isstring(obj2) &&
+ strcasecmp(cfg_obj_asstring(obj2), "timestamp") == 0)
+ {
+ suffix = isc_log_rollsuffix_timestamp;
+ }
+
+ fopt = fstrm_iothr_options_init();
+ /*
+ * Both network threads and worker threads may log dnstap data.
+ */
+ fstrm_iothr_options_set_num_input_queues(fopt,
+ 2 * named_g_cpus);
+ fstrm_iothr_options_set_queue_model(
+ fopt, FSTRM_IOTHR_QUEUE_MODEL_MPSC);
+
+ obj = NULL;
+ result = named_config_get(maps, "fstrm-set-buffer-hint", &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_buffer_hint(fopt, i);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "fstrm-set-flush-timeout",
+ &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_flush_timeout(fopt, i);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "fstrm-set-input-queue-size",
+ &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_input_queue_size(fopt, i);
+ }
+
+ obj = NULL;
+ result = named_config_get(
+ maps, "fstrm-set-output-notify-threshold", &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_queue_notify_threshold(fopt, i);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "fstrm-set-output-queue-model",
+ &obj);
+ if (result == ISC_R_SUCCESS) {
+ if (strcasecmp(cfg_obj_asstring(obj), "spsc") == 0) {
+ i = FSTRM_IOTHR_QUEUE_MODEL_SPSC;
+ } else {
+ i = FSTRM_IOTHR_QUEUE_MODEL_MPSC;
+ }
+ fstrm_iothr_options_set_queue_model(fopt, i);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "fstrm-set-output-queue-size",
+ &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_output_queue_size(fopt, i);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "fstrm-set-reopen-interval",
+ &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asduration(obj);
+ fstrm_iothr_options_set_reopen_interval(fopt, i);
+ }
+
+ CHECKM(dns_dt_create(named_g_mctx, dmode, dpath, &fopt,
+ named_g_server->task,
+ &named_g_server->dtenv),
+ "unable to create dnstap environment");
+
+ CHECKM(dns_dt_setupfile(named_g_server->dtenv, max_size, rolls,
+ suffix),
+ "unable to set up dnstap logfile");
+ }
+
+ if (named_g_server->dtenv == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "dnstap-version", &obj);
+ if (result != ISC_R_SUCCESS) {
+ /* not specified; use the product and version */
+ dns_dt_setversion(named_g_server->dtenv, PACKAGE_STRING);
+ } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) {
+ /* Quoted string */
+ dns_dt_setversion(named_g_server->dtenv, cfg_obj_asstring(obj));
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "dnstap-identity", &obj);
+ if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
+ /* "hostname" is interpreted as boolean true */
+ char buf[256];
+ if (gethostname(buf, sizeof(buf)) == 0) {
+ dns_dt_setidentity(named_g_server->dtenv, buf);
+ }
+ } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) {
+ /* Quoted string */
+ dns_dt_setidentity(named_g_server->dtenv,
+ cfg_obj_asstring(obj));
+ }
+
+ dns_dt_attach(named_g_server->dtenv, &view->dtenv);
+ view->dttypes = dttypes;
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (fopt != NULL) {
+ fstrm_iothr_options_destroy(&fopt);
+ }
+
+ return (result);
+}
+#endif /* HAVE_DNSTAP */
+
+static isc_result_t
+create_mapped_acl(void) {
+ isc_result_t result;
+ dns_acl_t *acl = NULL;
+ struct in6_addr in6 = IN6ADDR_V4MAPPED_INIT;
+ isc_netaddr_t addr;
+
+ isc_netaddr_fromin6(&addr, &in6);
+
+ result = dns_acl_create(named_g_mctx, 1, &acl);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = dns_iptable_addprefix(acl->iptable, &addr, 96, true);
+ if (result == ISC_R_SUCCESS) {
+ dns_acl_attach(acl, &named_g_mapped);
+ }
+ dns_acl_detach(&acl);
+ return (result);
+}
+
+/*%
+ * A callback for the cfg_pluginlist_foreach() call in configure_view() below.
+ * If registering any plugin fails, registering subsequent ones is not
+ * attempted.
+ */
+static isc_result_t
+register_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj,
+ const char *plugin_path, const char *parameters,
+ void *callback_data) {
+ dns_view_t *view = callback_data;
+ char full_path[PATH_MAX];
+ isc_result_t result;
+
+ result = ns_plugin_expandpath(plugin_path, full_path,
+ sizeof(full_path));
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "%s: plugin configuration failed: "
+ "unable to get full plugin path: %s",
+ plugin_path, isc_result_totext(result));
+ return (result);
+ }
+
+ result = ns_plugin_register(full_path, parameters, config,
+ cfg_obj_file(obj), cfg_obj_line(obj),
+ named_g_mctx, named_g_lctx,
+ named_g_aclconfctx, view);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "%s: plugin configuration failed: %s", full_path,
+ isc_result_totext(result));
+ }
+
+ return (result);
+}
+
+/*
+ * Determine if a minimal-sized cache can be used for a given view, according
+ * to 'maps' (implicit defaults, global options, view options) and 'optionmaps'
+ * (global options, view options). This is only allowed for views which have
+ * recursion disabled and do not have "max-cache-size" set explicitly. Using
+ * minimal-sized caches prevents a situation in which all explicitly configured
+ * and built-in views inherit the default "max-cache-size 90%;" setting, which
+ * could lead to memory exhaustion with multiple views configured.
+ */
+static bool
+minimal_cache_allowed(const cfg_obj_t *maps[4],
+ const cfg_obj_t *optionmaps[3]) {
+ const cfg_obj_t *obj;
+
+ /*
+ * Do not use a minimal-sized cache for a view with recursion enabled.
+ */
+ obj = NULL;
+ (void)named_config_get(maps, "recursion", &obj);
+ INSIST(obj != NULL);
+ if (cfg_obj_asboolean(obj)) {
+ return (false);
+ }
+
+ /*
+ * Do not use a minimal-sized cache if a specific size was requested.
+ */
+ obj = NULL;
+ (void)named_config_get(optionmaps, "max-cache-size", &obj);
+ if (obj != NULL) {
+ return (false);
+ }
+
+ return (true);
+}
+
+static const char *const response_synonyms[] = { "response", NULL };
+
+static const dns_name_t *
+algorithm_name(unsigned int alg) {
+ switch (alg) {
+ case DST_ALG_HMACMD5:
+ return (dns_tsig_hmacmd5_name);
+ case DST_ALG_HMACSHA1:
+ return (dns_tsig_hmacsha1_name);
+ case DST_ALG_HMACSHA224:
+ return (dns_tsig_hmacsha224_name);
+ case DST_ALG_HMACSHA256:
+ return (dns_tsig_hmacsha256_name);
+ case DST_ALG_HMACSHA384:
+ return (dns_tsig_hmacsha384_name);
+ case DST_ALG_HMACSHA512:
+ return (dns_tsig_hmacsha512_name);
+ case DST_ALG_GSSAPI:
+ return (dns_tsig_gssapi_name);
+ default:
+ UNREACHABLE();
+ }
+}
+
+/*
+ * Configure 'view' according to 'vconfig', taking defaults from
+ * 'config' where values are missing in 'vconfig'.
+ *
+ * When configuring the default view, 'vconfig' will be NULL and the
+ * global defaults in 'config' used exclusively.
+ */
+static isc_result_t
+configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
+ cfg_obj_t *vconfig, named_cachelist_t *cachelist,
+ dns_kasplist_t *kasplist, const cfg_obj_t *bindkeys,
+ isc_mem_t *mctx, cfg_aclconfctx_t *actx, bool need_hints) {
+ const cfg_obj_t *maps[4];
+ const cfg_obj_t *cfgmaps[3];
+ const cfg_obj_t *optionmaps[3];
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *voptions = NULL;
+ const cfg_obj_t *forwardtype;
+ const cfg_obj_t *forwarders;
+ const cfg_obj_t *alternates;
+ const cfg_obj_t *zonelist;
+ const cfg_obj_t *dlzlist;
+ const cfg_obj_t *dlz;
+ const cfg_obj_t *prefetch_trigger;
+ const cfg_obj_t *prefetch_eligible;
+ unsigned int dlzargc;
+ char **dlzargv;
+ const cfg_obj_t *dyndb_list, *plugin_list;
+ const cfg_obj_t *disabled;
+ const cfg_obj_t *obj, *obj2;
+ const cfg_listelt_t *element = NULL;
+ const cfg_listelt_t *zone_element_latest = NULL;
+ in_port_t port;
+ dns_cache_t *cache = NULL;
+ isc_result_t result;
+ size_t max_cache_size;
+ uint32_t max_cache_size_percent = 0;
+ size_t max_adb_size;
+ uint32_t lame_ttl, fail_ttl;
+ uint32_t max_stale_ttl = 0;
+ uint32_t stale_refresh_time = 0;
+ dns_tsig_keyring_t *ring = NULL;
+ dns_transport_list_t *transports = NULL;
+ dns_view_t *pview = NULL; /* Production view */
+ isc_mem_t *cmctx = NULL, *hmctx = NULL;
+ dns_dispatch_t *dispatch4 = NULL;
+ dns_dispatch_t *dispatch6 = NULL;
+ bool rpz_configured = false;
+ bool catz_configured = false;
+ bool shared_cache = false;
+ int i = 0, j = 0, k = 0;
+ const char *str;
+ const char *cachename = NULL;
+ dns_order_t *order = NULL;
+ uint32_t udpsize;
+ uint32_t maxbits;
+ unsigned int resopts = 0;
+ dns_zone_t *zone = NULL;
+ uint32_t max_clients_per_query;
+ bool empty_zones_enable;
+ const cfg_obj_t *disablelist = NULL;
+ isc_stats_t *resstats = NULL;
+ dns_stats_t *resquerystats = NULL;
+ bool auto_root = false;
+ named_cache_t *nsc;
+ bool zero_no_soattl;
+ dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL;
+ unsigned int query_timeout, ndisp;
+ bool old_rpz_ok = false;
+ dns_dyndbctx_t *dctx = NULL;
+ unsigned int resolver_param;
+ dns_ntatable_t *ntatable = NULL;
+ const char *qminmode = NULL;
+
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ if (config != NULL) {
+ (void)cfg_map_get(config, "options", &options);
+ }
+
+ /*
+ * maps: view options, options, defaults
+ * cfgmaps: view options, config
+ * optionmaps: view options, options
+ */
+ if (vconfig != NULL) {
+ voptions = cfg_tuple_get(vconfig, "options");
+ maps[i++] = voptions;
+ optionmaps[j++] = voptions;
+ cfgmaps[k++] = voptions;
+ }
+ if (options != NULL) {
+ maps[i++] = options;
+ optionmaps[j++] = options;
+ }
+
+ maps[i++] = named_g_defaults;
+ maps[i] = NULL;
+ optionmaps[j] = NULL;
+ if (config != NULL) {
+ cfgmaps[k++] = config;
+ }
+ cfgmaps[k] = NULL;
+
+ /*
+ * Set the view's port number for outgoing queries.
+ */
+ CHECKM(named_config_getport(config, "port", &port), "port");
+ dns_view_setdstport(view, port);
+
+ /*
+ * Make the list of response policy zone names for a view that
+ * is used for real lookups and so cares about hints.
+ */
+ obj = NULL;
+ if (view->rdclass == dns_rdataclass_in && need_hints &&
+ named_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS)
+ {
+ CHECK(configure_rpz(view, NULL, maps, obj, &old_rpz_ok));
+ rpz_configured = true;
+ }
+
+ obj = NULL;
+ if (view->rdclass != dns_rdataclass_in && need_hints &&
+ named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS)
+ {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "'catalog-zones' option is only supported "
+ "for views with class IN");
+ }
+
+ obj = NULL;
+ if (view->rdclass == dns_rdataclass_in && need_hints &&
+ named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS)
+ {
+ CHECK(configure_catz(view, NULL, config, obj));
+ catz_configured = true;
+ }
+
+ /*
+ * Configure the zones.
+ */
+ zonelist = NULL;
+ if (voptions != NULL) {
+ (void)cfg_map_get(voptions, "zone", &zonelist);
+ } else {
+ (void)cfg_map_get(config, "zone", &zonelist);
+ }
+
+ /*
+ * Load zone configuration
+ */
+ for (element = cfg_list_first(zonelist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *zconfig = cfg_listelt_value(element);
+ CHECK(configure_zone(config, zconfig, vconfig, mctx, view,
+ viewlist, kasplist, actx, false,
+ old_rpz_ok, false));
+ zone_element_latest = element;
+ }
+
+ /*
+ * Check that a primary or secondary zone was found for each
+ * zone named in the response policy statement, unless we are
+ * using RPZ service interface.
+ */
+ if (view->rpzs != NULL && !view->rpzs->p.dnsrps_enabled) {
+ dns_rpz_num_t n;
+
+ for (n = 0; n < view->rpzs->p.num_zones; ++n) {
+ if ((view->rpzs->defined & DNS_RPZ_ZBIT(n)) == 0) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(&view->rpzs->zones[n]->origin,
+ namebuf, sizeof(namebuf));
+ isc_log_write(named_g_lctx,
+ NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER,
+ DNS_RPZ_ERROR_LEVEL,
+ "rpz '%s' is not a primary or a "
+ "secondary zone",
+ namebuf);
+ result = ISC_R_NOTFOUND;
+ goto cleanup;
+ }
+ }
+ }
+
+ /*
+ * If we're allowing added zones, then load zone configuration
+ * from the newzone file for zones that were added during previous
+ * runs.
+ */
+ CHECK(configure_newzones(view, config, vconfig, mctx, actx));
+
+ /*
+ * Create Dynamically Loadable Zone driver.
+ */
+ dlzlist = NULL;
+ if (voptions != NULL) {
+ (void)cfg_map_get(voptions, "dlz", &dlzlist);
+ } else {
+ (void)cfg_map_get(config, "dlz", &dlzlist);
+ }
+
+ for (element = cfg_list_first(dlzlist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ dlz = cfg_listelt_value(element);
+
+ obj = NULL;
+ (void)cfg_map_get(dlz, "database", &obj);
+ if (obj != NULL) {
+ dns_dlzdb_t *dlzdb = NULL;
+ const cfg_obj_t *name, *search = NULL;
+ char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
+
+ if (s == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ result = isc_commandline_strtoargv(mctx, s, &dlzargc,
+ &dlzargv, 0);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_free(mctx, s);
+ goto cleanup;
+ }
+
+ name = cfg_map_getname(dlz);
+ result = dns_dlzcreate(mctx, cfg_obj_asstring(name),
+ dlzargv[0], dlzargc, dlzargv,
+ &dlzdb);
+ isc_mem_free(mctx, s);
+ isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv));
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ /*
+ * If the DLZ backend supports configuration,
+ * and is searchable, then call its configure
+ * method now. If not searchable, we'll take
+ * care of it when we process the zone statement.
+ */
+ (void)cfg_map_get(dlz, "search", &search);
+ if (search == NULL || cfg_obj_asboolean(search)) {
+ dlzdb->search = true;
+ result = dns_dlzconfigure(
+ view, dlzdb, dlzconfigure_callback);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ ISC_LIST_APPEND(view->dlz_searched, dlzdb,
+ link);
+ } else {
+ dlzdb->search = false;
+ ISC_LIST_APPEND(view->dlz_unsearched, dlzdb,
+ link);
+ }
+ }
+ }
+
+ /*
+ * Obtain configuration parameters that affect the decision of whether
+ * we can reuse/share an existing cache.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "max-cache-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ /*
+ * If "-T maxcachesize=..." is in effect, it overrides any other
+ * "max-cache-size" setting found in configuration, either implicit or
+ * explicit. For simplicity, the value passed to that command line
+ * option is always treated as the number of bytes to set
+ * "max-cache-size" to.
+ */
+ if (named_g_maxcachesize != 0) {
+ max_cache_size = named_g_maxcachesize;
+ } else if (minimal_cache_allowed(maps, optionmaps)) {
+ /*
+ * dns_cache_setcachesize() will adjust this to the smallest
+ * allowed value.
+ */
+ max_cache_size = 1;
+ } else if (cfg_obj_isstring(obj)) {
+ str = cfg_obj_asstring(obj);
+ INSIST(strcasecmp(str, "unlimited") == 0);
+ max_cache_size = 0;
+ } else if (cfg_obj_ispercentage(obj)) {
+ max_cache_size = SIZE_AS_PERCENT;
+ max_cache_size_percent = cfg_obj_aspercentage(obj);
+ } else {
+ isc_resourcevalue_t value;
+ value = cfg_obj_asuint64(obj);
+ if (value > SIZE_MAX) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "'max-cache-size "
+ "%" PRIu64 "' "
+ "is too large for this "
+ "system; reducing to %lu",
+ value, (unsigned long)SIZE_MAX);
+ value = SIZE_MAX;
+ }
+ max_cache_size = (size_t)value;
+ }
+
+ if (max_cache_size == SIZE_AS_PERCENT) {
+ uint64_t totalphys = isc_meminfo_totalphys();
+
+ max_cache_size =
+ (size_t)(totalphys * max_cache_size_percent / 100);
+ if (totalphys == 0) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "Unable to determine amount of physical "
+ "memory, setting 'max-cache-size' to "
+ "unlimited");
+ } else {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO,
+ "'max-cache-size %d%%' "
+ "- setting to %" PRIu64 "MB "
+ "(out of %" PRIu64 "MB)",
+ max_cache_size_percent,
+ (uint64_t)(max_cache_size / (1024 * 1024)),
+ totalphys / (1024 * 1024));
+ }
+ }
+
+ /* Check-names. */
+ obj = NULL;
+ result = named_checknames_get(maps, response_synonyms, &obj);
+ INSIST(result == ISC_R_SUCCESS);
+
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "fail") == 0) {
+ resopts |= DNS_RESOLVER_CHECKNAMES |
+ DNS_RESOLVER_CHECKNAMESFAIL;
+ view->checknames = true;
+ } else if (strcasecmp(str, "warn") == 0) {
+ resopts |= DNS_RESOLVER_CHECKNAMES;
+ view->checknames = false;
+ } else if (strcasecmp(str, "ignore") == 0) {
+ view->checknames = false;
+ } else {
+ UNREACHABLE();
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "zero-no-soa-ttl-cache", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ zero_no_soattl = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "dns64", &obj);
+ if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") &&
+ strcmp(view->name, "_meta"))
+ {
+ isc_netaddr_t na, suffix, *sp;
+ unsigned int prefixlen;
+ const char *server, *contact;
+ const cfg_obj_t *myobj;
+
+ myobj = NULL;
+ result = named_config_get(maps, "dns64-server", &myobj);
+ if (result == ISC_R_SUCCESS) {
+ server = cfg_obj_asstring(myobj);
+ } else {
+ server = NULL;
+ }
+
+ myobj = NULL;
+ result = named_config_get(maps, "dns64-contact", &myobj);
+ if (result == ISC_R_SUCCESS) {
+ contact = cfg_obj_asstring(myobj);
+ } else {
+ contact = NULL;
+ }
+
+ for (element = cfg_list_first(obj); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *map = cfg_listelt_value(element);
+ dns_dns64_t *dns64 = NULL;
+ unsigned int dns64options = 0;
+
+ cfg_obj_asnetprefix(cfg_map_getname(map), &na,
+ &prefixlen);
+
+ obj = NULL;
+ (void)cfg_map_get(map, "suffix", &obj);
+ if (obj != NULL) {
+ sp = &suffix;
+ isc_netaddr_fromsockaddr(
+ sp, cfg_obj_assockaddr(obj));
+ } else {
+ sp = NULL;
+ }
+
+ clients = mapped = excluded = NULL;
+ obj = NULL;
+ (void)cfg_map_get(map, "clients", &obj);
+ if (obj != NULL) {
+ result = cfg_acl_fromconfig(obj, config,
+ named_g_lctx, actx,
+ mctx, 0, &clients);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ }
+ obj = NULL;
+ (void)cfg_map_get(map, "mapped", &obj);
+ if (obj != NULL) {
+ result = cfg_acl_fromconfig(obj, config,
+ named_g_lctx, actx,
+ mctx, 0, &mapped);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ }
+ obj = NULL;
+ (void)cfg_map_get(map, "exclude", &obj);
+ if (obj != NULL) {
+ result = cfg_acl_fromconfig(obj, config,
+ named_g_lctx, actx,
+ mctx, 0, &excluded);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ } else {
+ if (named_g_mapped == NULL) {
+ result = create_mapped_acl();
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ }
+ dns_acl_attach(named_g_mapped, &excluded);
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(map, "recursive-only", &obj);
+ if (obj != NULL && cfg_obj_asboolean(obj)) {
+ dns64options |= DNS_DNS64_RECURSIVE_ONLY;
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(map, "break-dnssec", &obj);
+ if (obj != NULL && cfg_obj_asboolean(obj)) {
+ dns64options |= DNS_DNS64_BREAK_DNSSEC;
+ }
+
+ result = dns_dns64_create(mctx, &na, prefixlen, sp,
+ clients, mapped, excluded,
+ dns64options, &dns64);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ dns_dns64_append(&view->dns64, dns64);
+ view->dns64cnt++;
+ result = dns64_reverse(view, mctx, &na, prefixlen,
+ server, contact);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ if (clients != NULL) {
+ dns_acl_detach(&clients);
+ }
+ if (mapped != NULL) {
+ dns_acl_detach(&mapped);
+ }
+ if (excluded != NULL) {
+ dns_acl_detach(&excluded);
+ }
+ }
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "dnssec-accept-expired", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->acceptexpired = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ /* 'optionmaps', not 'maps': don't check named_g_defaults yet */
+ (void)named_config_get(optionmaps, "dnssec-validation", &obj);
+ if (obj == NULL) {
+ /*
+ * Default to VALIDATION_DEFAULT as set in config.c.
+ */
+ (void)cfg_map_get(named_g_defaults, "dnssec-validation", &obj);
+ INSIST(obj != NULL);
+ }
+ if (obj != NULL) {
+ if (cfg_obj_isboolean(obj)) {
+ view->enablevalidation = cfg_obj_asboolean(obj);
+ } else {
+ /*
+ * If dnssec-validation is set but not boolean,
+ * then it must be "auto"
+ */
+ view->enablevalidation = true;
+ auto_root = true;
+ }
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "max-cache-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->maxcachettl = cfg_obj_asduration(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "max-ncache-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->maxncachettl = cfg_obj_asduration(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "min-cache-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->mincachettl = cfg_obj_asduration(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "min-ncache-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->minncachettl = cfg_obj_asduration(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "synth-from-dnssec", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->synthfromdnssec = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "stale-cache-enable", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_asboolean(obj)) {
+ obj = NULL;
+ result = named_config_get(maps, "max-stale-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ max_stale_ttl = ISC_MAX(cfg_obj_asduration(obj), 1);
+ }
+ /*
+ * If 'stale-cache-enable' is false, max_stale_ttl is set to 0,
+ * meaning keeping stale RRsets in cache is disabled.
+ */
+
+ obj = NULL;
+ result = named_config_get(maps, "stale-answer-enable", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->staleanswersenable = cfg_obj_asboolean(obj);
+
+ result = dns_viewlist_find(&named_g_server->viewlist, view->name,
+ view->rdclass, &pview);
+ if (result == ISC_R_SUCCESS) {
+ view->staleanswersok = pview->staleanswersok;
+ dns_view_detach(&pview);
+ } else {
+ view->staleanswersok = dns_stale_answer_conf;
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "stale-answer-client-timeout", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isstring(obj)) {
+ /*
+ * The only string values available for this option
+ * are "disabled" and "off".
+ * We use (uint32_t) -1 to represent disabled since
+ * a value of zero means that stale data can be used
+ * to promptly answer the query, while an attempt to
+ * refresh the RRset will still be made in background.
+ */
+ view->staleanswerclienttimeout = (uint32_t)-1;
+ } else {
+ view->staleanswerclienttimeout = cfg_obj_asuint32(obj);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "stale-refresh-time", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ stale_refresh_time = cfg_obj_asduration(obj);
+
+ /*
+ * Configure the view's cache.
+ *
+ * First, check to see if there are any attach-cache options. If yes,
+ * attempt to lookup an existing cache at attach it to the view. If
+ * there is not one, then try to reuse an existing cache if possible;
+ * otherwise create a new cache.
+ *
+ * Note that the ADB is not preserved or shared in either case.
+ *
+ * When a matching view is found, the associated statistics are also
+ * retrieved and reused.
+ *
+ * XXX Determining when it is safe to reuse or share a cache is tricky.
+ * When the view's configuration changes, the cached data may become
+ * invalid because it reflects our old view of the world. We check
+ * some of the configuration parameters that could invalidate the cache
+ * or otherwise make it unshareable, but there are other configuration
+ * options that should be checked. For example, if a view uses a
+ * forwarder, changes in the forwarder configuration may invalidate
+ * the cache. At the moment, it's the administrator's responsibility to
+ * ensure these configuration options don't invalidate reusing/sharing.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "attach-cache", &obj);
+ if (result == ISC_R_SUCCESS) {
+ cachename = cfg_obj_asstring(obj);
+ } else {
+ cachename = view->name;
+ }
+ cache = NULL;
+ nsc = cachelist_find(cachelist, cachename, view->rdclass);
+ if (nsc != NULL) {
+ if (!cache_sharable(nsc->primaryview, view, zero_no_soattl,
+ max_cache_size, max_stale_ttl,
+ stale_refresh_time))
+ {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "views %s and %s can't share the cache "
+ "due to configuration parameter mismatch",
+ nsc->primaryview->name, view->name);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ dns_cache_attach(nsc->cache, &cache);
+ shared_cache = true;
+ } else {
+ if (strcmp(cachename, view->name) == 0) {
+ result = dns_viewlist_find(&named_g_server->viewlist,
+ cachename, view->rdclass,
+ &pview);
+ if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
+ {
+ goto cleanup;
+ }
+ if (pview != NULL) {
+ if (!cache_reusable(pview, view,
+ zero_no_soattl))
+ {
+ isc_log_write(named_g_lctx,
+ NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER,
+ ISC_LOG_DEBUG(1),
+ "cache cannot be reused "
+ "for view %s due to "
+ "configuration parameter "
+ "mismatch",
+ view->name);
+ } else {
+ INSIST(pview->cache != NULL);
+ isc_log_write(named_g_lctx,
+ NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER,
+ ISC_LOG_DEBUG(3),
+ "reusing existing cache");
+ dns_cache_attach(pview->cache, &cache);
+ }
+ dns_view_getresstats(pview, &resstats);
+ dns_view_getresquerystats(pview,
+ &resquerystats);
+ dns_view_detach(&pview);
+ }
+ }
+ if (cache == NULL) {
+ /*
+ * Create a cache with the desired name. This normally
+ * equals the view name, but may also be a forward
+ * reference to a view that share the cache with this
+ * view but is not yet configured. If it is not the
+ * view name but not a forward reference either, then it
+ * is simply a named cache that is not shared.
+ *
+ * We use two separate memory contexts for the
+ * cache, for the main cache memory and the heap
+ * memory.
+ */
+ isc_mem_create(&cmctx);
+ isc_mem_setname(cmctx, "cache");
+ isc_mem_create(&hmctx);
+ isc_mem_setname(hmctx, "cache_heap");
+ CHECK(dns_cache_create(cmctx, hmctx, named_g_taskmgr,
+ named_g_timermgr, view->rdclass,
+ cachename, "rbt", 0, NULL,
+ &cache));
+ isc_mem_detach(&cmctx);
+ isc_mem_detach(&hmctx);
+ }
+ nsc = isc_mem_get(mctx, sizeof(*nsc));
+ nsc->cache = NULL;
+ dns_cache_attach(cache, &nsc->cache);
+ nsc->primaryview = view;
+ nsc->needflush = false;
+ nsc->adbsizeadjusted = false;
+ nsc->rdclass = view->rdclass;
+ ISC_LINK_INIT(nsc, link);
+ ISC_LIST_APPEND(*cachelist, nsc, link);
+ }
+ dns_view_setcache(view, cache, shared_cache);
+
+ dns_cache_setcachesize(cache, max_cache_size);
+ dns_cache_setservestalettl(cache, max_stale_ttl);
+ dns_cache_setservestalerefresh(cache, stale_refresh_time);
+
+ dns_cache_detach(&cache);
+
+ obj = NULL;
+ result = named_config_get(maps, "stale-answer-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->staleanswerttl = ISC_MAX(cfg_obj_asduration(obj), 1);
+
+ /*
+ * Resolver.
+ */
+ CHECK(get_view_querysource_dispatch(
+ maps, AF_INET, &dispatch4,
+ (ISC_LIST_PREV(view, link) == NULL)));
+ CHECK(get_view_querysource_dispatch(
+ maps, AF_INET6, &dispatch6,
+ (ISC_LIST_PREV(view, link) == NULL)));
+ if (dispatch4 == NULL && dispatch6 == NULL) {
+ UNEXPECTED_ERROR("unable to obtain either an IPv4 or"
+ " an IPv6 dispatch");
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+
+ if (resstats == NULL) {
+ CHECK(isc_stats_create(mctx, &resstats,
+ dns_resstatscounter_max));
+ }
+ dns_view_setresstats(view, resstats);
+ if (resquerystats == NULL) {
+ CHECK(dns_rdatatypestats_create(mctx, &resquerystats));
+ }
+ dns_view_setresquerystats(view, resquerystats);
+
+ ndisp = 4 * ISC_MIN(named_g_udpdisp, MAX_UDP_DISPATCH);
+ CHECK(dns_view_createresolver(
+ view, named_g_taskmgr, RESOLVER_NTASKS_PERCPU * named_g_cpus,
+ ndisp, named_g_netmgr, named_g_timermgr, resopts,
+ named_g_dispatchmgr, dispatch4, dispatch6));
+
+ /*
+ * Set the ADB cache size to 1/8th of the max-cache-size or
+ * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared.
+ */
+ max_adb_size = 0;
+ if (max_cache_size != 0U) {
+ max_adb_size = max_cache_size / 8;
+ if (max_adb_size == 0U) {
+ max_adb_size = 1; /* Force minimum. */
+ }
+ if (view != nsc->primaryview &&
+ max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE)
+ {
+ max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE;
+ if (!nsc->adbsizeadjusted) {
+ dns_adb_setadbsize(nsc->primaryview->adb,
+ MAX_ADB_SIZE_FOR_CACHESHARE);
+ nsc->adbsizeadjusted = true;
+ }
+ }
+ }
+ dns_adb_setadbsize(view->adb, max_adb_size);
+
+ /*
+ * Set up ADB quotas
+ */
+ {
+ uint32_t fps, freq;
+ double low, high, discount;
+
+ obj = NULL;
+ result = named_config_get(maps, "fetches-per-server", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ obj2 = cfg_tuple_get(obj, "fetches");
+ fps = cfg_obj_asuint32(obj2);
+ obj2 = cfg_tuple_get(obj, "response");
+ if (!cfg_obj_isvoid(obj2)) {
+ const char *resp = cfg_obj_asstring(obj2);
+ isc_result_t r = DNS_R_SERVFAIL;
+
+ if (strcasecmp(resp, "drop") == 0) {
+ r = DNS_R_DROP;
+ } else if (strcasecmp(resp, "fail") == 0) {
+ r = DNS_R_SERVFAIL;
+ } else {
+ UNREACHABLE();
+ }
+
+ dns_resolver_setquotaresponse(view->resolver,
+ dns_quotatype_server, r);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "fetch-quota-params", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+
+ obj2 = cfg_tuple_get(obj, "frequency");
+ freq = cfg_obj_asuint32(obj2);
+
+ obj2 = cfg_tuple_get(obj, "low");
+ low = (double)cfg_obj_asfixedpoint(obj2) / 100.0;
+
+ obj2 = cfg_tuple_get(obj, "high");
+ high = (double)cfg_obj_asfixedpoint(obj2) / 100.0;
+
+ obj2 = cfg_tuple_get(obj, "discount");
+ discount = (double)cfg_obj_asfixedpoint(obj2) / 100.0;
+
+ dns_adb_setquota(view->adb, fps, freq, low, high, discount);
+ }
+
+ /*
+ * Set resolver's lame-ttl.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "lame-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ lame_ttl = cfg_obj_asduration(obj);
+ if (lame_ttl > 0) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "disabling lame cache despite lame-ttl > 0 as it "
+ "may cause performance issues");
+ lame_ttl = 0;
+ }
+ dns_resolver_setlamettl(view->resolver, lame_ttl);
+
+ /*
+ * Set the resolver's query timeout.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "resolver-query-timeout", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ query_timeout = cfg_obj_asuint32(obj);
+ dns_resolver_settimeout(view->resolver, query_timeout);
+
+ /*
+ * Adjust stale-answer-client-timeout upper bound
+ * to be resolver-query-timeout - 1s.
+ * This assignment is safe as dns_resolver_settimeout()
+ * ensures that resolver->querytimeout value will be in the
+ * [MINIMUM_QUERY_TIMEOUT, MAXIMUM_QUERY_TIMEOUT] range and
+ * MINIMUM_QUERY_TIMEOUT is > 1000 (in ms).
+ */
+ if (view->staleanswerclienttimeout != (uint32_t)-1 &&
+ view->staleanswerclienttimeout >
+ (dns_resolver_gettimeout(view->resolver) - 1000))
+ {
+ view->staleanswerclienttimeout =
+ dns_resolver_gettimeout(view->resolver) - 1000;
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "stale-answer-client-timeout adjusted to %" PRIu32,
+ view->staleanswerclienttimeout);
+ }
+
+ /* Specify whether to use 0-TTL for negative response for SOA query */
+ dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl);
+
+ /*
+ * Set the resolver's EDNS UDP size.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "edns-udp-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ udpsize = cfg_obj_asuint32(obj);
+ if (udpsize < 512) {
+ udpsize = 512;
+ }
+ if (udpsize > 4096) {
+ udpsize = 4096;
+ }
+ dns_resolver_setudpsize(view->resolver, (uint16_t)udpsize);
+
+ /*
+ * Set the maximum UDP response size.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "max-udp-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ udpsize = cfg_obj_asuint32(obj);
+ if (udpsize < 512) {
+ udpsize = 512;
+ }
+ if (udpsize > 4096) {
+ udpsize = 4096;
+ }
+ view->maxudp = udpsize;
+
+ /*
+ * Set the maximum UDP when a COOKIE is not provided.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "nocookie-udp-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ udpsize = cfg_obj_asuint32(obj);
+ if (udpsize < 128) {
+ udpsize = 128;
+ }
+ if (udpsize > view->maxudp) {
+ udpsize = view->maxudp;
+ }
+ view->nocookieudp = udpsize;
+
+ /*
+ * Set the maximum rsa exponent bits.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "max-rsa-exponent-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ maxbits = cfg_obj_asuint32(obj);
+ if (maxbits != 0 && maxbits < 35) {
+ maxbits = 35;
+ }
+ if (maxbits > 4096) {
+ maxbits = 4096;
+ }
+ view->maxbits = maxbits;
+
+ /*
+ * Set resolver retry parameters.
+ */
+ obj = NULL;
+ CHECK(named_config_get(maps, "resolver-retry-interval", &obj));
+ resolver_param = cfg_obj_asuint32(obj);
+ if (resolver_param > 0) {
+ dns_resolver_setretryinterval(view->resolver, resolver_param);
+ }
+
+ obj = NULL;
+ CHECK(named_config_get(maps, "resolver-nonbackoff-tries", &obj));
+ resolver_param = cfg_obj_asuint32(obj);
+ if (resolver_param > 0) {
+ dns_resolver_setnonbackofftries(view->resolver, resolver_param);
+ }
+
+ /*
+ * Set supported DNSSEC algorithms.
+ */
+ dns_resolver_reset_algorithms(view->resolver);
+ disabled = NULL;
+ (void)named_config_get(maps, "disable-algorithms", &disabled);
+ if (disabled != NULL) {
+ for (element = cfg_list_first(disabled); element != NULL;
+ element = cfg_list_next(element))
+ {
+ CHECK(disable_algorithms(cfg_listelt_value(element),
+ view->resolver));
+ }
+ }
+
+ /*
+ * Set supported DS digest types.
+ */
+ dns_resolver_reset_ds_digests(view->resolver);
+ disabled = NULL;
+ (void)named_config_get(maps, "disable-ds-digests", &disabled);
+ if (disabled != NULL) {
+ for (element = cfg_list_first(disabled); element != NULL;
+ element = cfg_list_next(element))
+ {
+ CHECK(disable_ds_digests(cfg_listelt_value(element),
+ view->resolver));
+ }
+ }
+
+ /*
+ * A global or view "forwarders" option, if present,
+ * creates an entry for "." in the forwarding table.
+ */
+ forwardtype = NULL;
+ forwarders = NULL;
+ (void)named_config_get(maps, "forward", &forwardtype);
+ (void)named_config_get(maps, "forwarders", &forwarders);
+ if (forwarders != NULL) {
+ CHECK(configure_forward(config, view, dns_rootname, forwarders,
+ forwardtype));
+ }
+
+ /*
+ * Dual Stack Servers.
+ */
+ alternates = NULL;
+ (void)named_config_get(maps, "dual-stack-servers", &alternates);
+ if (alternates != NULL) {
+ CHECK(configure_alternates(config, view, alternates));
+ }
+
+ /*
+ * We have default hints for class IN if we need them.
+ */
+ if (view->rdclass == dns_rdataclass_in && view->hints == NULL) {
+ dns_view_sethints(view, named_g_server->in_roothints);
+ }
+
+ /*
+ * If we still have no hints, this is a non-IN view with no
+ * "hints zone" configured. Issue a warning, except if this
+ * is a root server. Root servers never need to consult
+ * their hints, so it's no point requiring users to configure
+ * them.
+ */
+ if (view->hints == NULL) {
+ dns_zone_t *rootzone = NULL;
+ (void)dns_view_findzone(view, dns_rootname, &rootzone);
+ if (rootzone != NULL) {
+ dns_zone_detach(&rootzone);
+ need_hints = false;
+ }
+ if (need_hints) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "no root hints for view '%s'",
+ view->name);
+ }
+ }
+
+ /*
+ * Configure the view's transports (DoT/DoH)
+ */
+ CHECK(named_transports_fromconfig(config, vconfig, view->mctx,
+ &transports));
+ dns_view_settransports(view, transports);
+ dns_transport_list_detach(&transports);
+
+ /*
+ * Configure the view's TSIG keys.
+ */
+ CHECK(named_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring));
+ if (named_g_server->sessionkey != NULL) {
+ dns_tsigkey_t *tsigkey = NULL;
+ result = dns_tsigkey_createfromkey(
+ named_g_server->session_keyname,
+ algorithm_name(named_g_server->session_keyalg),
+ named_g_server->sessionkey, false, NULL, 0, 0, mctx,
+ NULL, &tsigkey);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_tsigkeyring_add(
+ ring, named_g_server->session_keyname, tsigkey);
+ dns_tsigkey_detach(&tsigkey);
+ }
+ CHECK(result);
+ }
+ dns_view_setkeyring(view, ring);
+ dns_tsigkeyring_detach(&ring);
+
+ /*
+ * See if we can re-use a dynamic key ring.
+ */
+ result = dns_viewlist_find(&named_g_server->viewlist, view->name,
+ view->rdclass, &pview);
+ if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ if (pview != NULL) {
+ dns_view_getdynamickeyring(pview, &ring);
+ if (ring != NULL) {
+ dns_view_setdynamickeyring(view, ring);
+ }
+ dns_tsigkeyring_detach(&ring);
+ dns_view_detach(&pview);
+ } else {
+ dns_view_restorekeyring(view);
+ }
+
+ /*
+ * Configure the view's peer list.
+ */
+ {
+ const cfg_obj_t *peers = NULL;
+ dns_peerlist_t *newpeers = NULL;
+
+ (void)named_config_get(cfgmaps, "server", &peers);
+ CHECK(dns_peerlist_new(mctx, &newpeers));
+ for (element = cfg_list_first(peers); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *cpeer = cfg_listelt_value(element);
+ dns_peer_t *peer;
+
+ CHECK(configure_peer(cpeer, mctx, &peer));
+ dns_peerlist_addpeer(newpeers, peer);
+ dns_peer_detach(&peer);
+ }
+ dns_peerlist_detach(&view->peers);
+ view->peers = newpeers; /* Transfer ownership. */
+ }
+
+ /*
+ * Configure the views rrset-order.
+ */
+ {
+ const cfg_obj_t *rrsetorder = NULL;
+
+ (void)named_config_get(maps, "rrset-order", &rrsetorder);
+ CHECK(dns_order_create(mctx, &order));
+ for (element = cfg_list_first(rrsetorder); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *ent = cfg_listelt_value(element);
+
+ CHECK(configure_order(order, ent));
+ }
+ if (view->order != NULL) {
+ dns_order_detach(&view->order);
+ }
+ dns_order_attach(order, &view->order);
+ dns_order_detach(&order);
+ }
+ /*
+ * Copy the aclenv object.
+ */
+ dns_aclenv_copy(view->aclenv, ns_interfacemgr_getaclenv(
+ named_g_server->interfacemgr));
+
+ /*
+ * Configure the "match-clients" and "match-destinations" ACL.
+ * (These are only meaningful at the view level, but 'config'
+ * must be passed so that named ACLs defined at the global level
+ * can be retrieved.)
+ */
+ CHECK(configure_view_acl(vconfig, config, NULL, "match-clients", NULL,
+ actx, named_g_mctx, &view->matchclients));
+ CHECK(configure_view_acl(vconfig, config, NULL, "match-destinations",
+ NULL, actx, named_g_mctx,
+ &view->matchdestinations));
+
+ /*
+ * Configure the "match-recursive-only" option.
+ */
+ obj = NULL;
+ (void)named_config_get(maps, "match-recursive-only", &obj);
+ if (obj != NULL && cfg_obj_asboolean(obj)) {
+ view->matchrecursiveonly = true;
+ } else {
+ view->matchrecursiveonly = false;
+ }
+
+ /*
+ * Configure other configurable data.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "recursion", &obj);
+ 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);
+ qminmode = cfg_obj_asstring(obj);
+ INSIST(qminmode != NULL);
+ if (!strcmp(qminmode, "strict")) {
+ view->qminimization = true;
+ view->qmin_strict = true;
+ } else if (!strcmp(qminmode, "relaxed")) {
+ view->qminimization = true;
+ view->qmin_strict = false;
+ } else { /* "disabled" or "off" */
+ view->qminimization = false;
+ view->qmin_strict = false;
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "auth-nxdomain", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->auth_nxdomain = cfg_obj_asboolean(obj);
+
+ /* deprecated */
+ obj = NULL;
+ result = named_config_get(maps, "glue-cache", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->use_glue_cache = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "minimal-any", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->minimal_any = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "minimal-responses", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ view->minimalresponses = dns_minimal_yes;
+ } else {
+ view->minimalresponses = dns_minimal_no;
+ }
+ } else {
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "no-auth") == 0) {
+ view->minimalresponses = dns_minimal_noauth;
+ } else if (strcasecmp(str, "no-auth-recursive") == 0) {
+ view->minimalresponses = dns_minimal_noauthrec;
+ } else {
+ UNREACHABLE();
+ }
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "transfer-format", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "many-answers") == 0) {
+ view->transfer_format = dns_many_answers;
+ } else if (strcasecmp(str, "one-answer") == 0) {
+ view->transfer_format = dns_one_answer;
+ } else {
+ UNREACHABLE();
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "trust-anchor-telemetry", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->trust_anchor_telemetry = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "root-key-sentinel", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->root_key_sentinel = cfg_obj_asboolean(obj);
+
+ /*
+ * Set the "allow-query", "allow-query-cache", "allow-recursion",
+ * "allow-recursion-on" and "allow-query-cache-on" ACLs if
+ * configured in named.conf, but NOT from the global defaults.
+ * This is done by leaving the third argument to configure_view_acl()
+ * NULL.
+ *
+ * We ignore the global defaults here because these ACLs
+ * can inherit from each other. If any are still unset after
+ * applying the inheritance rules, we'll look up the defaults at
+ * that time.
+ */
+
+ /* named.conf only */
+ CHECK(configure_view_acl(vconfig, config, NULL, "allow-query", NULL,
+ actx, named_g_mctx, &view->queryacl));
+
+ /* named.conf only */
+ CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache",
+ NULL, actx, named_g_mctx, &view->cacheacl));
+ /* named.conf only */
+ CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache-on",
+ NULL, actx, named_g_mctx, &view->cacheonacl));
+
+ if (strcmp(view->name, "_bind") != 0 &&
+ view->rdclass != dns_rdataclass_chaos)
+ {
+ /* named.conf only */
+ CHECK(configure_view_acl(vconfig, config, NULL,
+ "allow-recursion", NULL, actx,
+ named_g_mctx, &view->recursionacl));
+ /* named.conf only */
+ CHECK(configure_view_acl(vconfig, config, NULL,
+ "allow-recursion-on", NULL, actx,
+ named_g_mctx, &view->recursiononacl));
+ }
+
+ if (view->recursion) {
+ /*
+ * "allow-query-cache" inherits from "allow-recursion" if set,
+ * otherwise from "allow-query" if set.
+ */
+ if (view->cacheacl == NULL) {
+ if (view->recursionacl != NULL) {
+ dns_acl_attach(view->recursionacl,
+ &view->cacheacl);
+ } else if (view->queryacl != NULL) {
+ dns_acl_attach(view->queryacl, &view->cacheacl);
+ }
+ }
+
+ /*
+ * "allow-recursion" inherits from "allow-query-cache" if set,
+ * otherwise from "allow-query" if set.
+ */
+ if (view->recursionacl == NULL) {
+ if (view->cacheacl != NULL) {
+ dns_acl_attach(view->cacheacl,
+ &view->recursionacl);
+ } else if (view->queryacl != NULL) {
+ dns_acl_attach(view->queryacl,
+ &view->recursionacl);
+ }
+ }
+
+ /*
+ * "allow-query-cache-on" inherits from "allow-recursion-on"
+ * if set.
+ */
+ if (view->cacheonacl == NULL) {
+ if (view->recursiononacl != NULL) {
+ dns_acl_attach(view->recursiononacl,
+ &view->cacheonacl);
+ }
+ }
+
+ /*
+ * "allow-recursion-on" inherits from "allow-query-cache-on"
+ * if set.
+ */
+ if (view->recursiononacl == NULL) {
+ if (view->cacheonacl != NULL) {
+ dns_acl_attach(view->cacheonacl,
+ &view->recursiononacl);
+ }
+ }
+
+ /*
+ * If any are still unset at this point, we now get default
+ * values for from the global config.
+ */
+
+ if (view->recursionacl == NULL) {
+ /* global default only */
+ CHECK(configure_view_acl(
+ NULL, NULL, named_g_config, "allow-recursion",
+ NULL, actx, named_g_mctx, &view->recursionacl));
+ }
+ if (view->recursiononacl == NULL) {
+ /* global default only */
+ CHECK(configure_view_acl(NULL, NULL, named_g_config,
+ "allow-recursion-on", NULL,
+ actx, named_g_mctx,
+ &view->recursiononacl));
+ }
+ if (view->cacheacl == NULL) {
+ /* global default only */
+ CHECK(configure_view_acl(
+ NULL, NULL, named_g_config, "allow-query-cache",
+ NULL, actx, named_g_mctx, &view->cacheacl));
+ }
+ if (view->cacheonacl == NULL) {
+ /* global default only */
+ CHECK(configure_view_acl(NULL, NULL, named_g_config,
+ "allow-query-cache-on", NULL,
+ actx, named_g_mctx,
+ &view->cacheonacl));
+ }
+ } else {
+ /*
+ * We're not recursive; if the query-cache ACLs haven't
+ * been set at the options/view level, set them to none.
+ */
+ if (view->cacheacl == NULL) {
+ CHECK(dns_acl_none(mctx, &view->cacheacl));
+ }
+ if (view->cacheonacl == NULL) {
+ CHECK(dns_acl_none(mctx, &view->cacheonacl));
+ }
+ }
+
+ /*
+ * Finished setting recursion and query-cache ACLs, so now we
+ * can get the allow-query default if it wasn't set in named.conf
+ */
+ if (view->queryacl == NULL) {
+ /* global default only */
+ CHECK(configure_view_acl(NULL, NULL, named_g_config,
+ "allow-query", NULL, actx,
+ named_g_mctx, &view->queryacl));
+ }
+
+ /*
+ * Ignore case when compressing responses to the specified
+ * clients. This causes case not always to be preserved,
+ * and is needed by some broken clients.
+ */
+ CHECK(configure_view_acl(vconfig, config, named_g_config,
+ "no-case-compress", NULL, actx, named_g_mctx,
+ &view->nocasecompress));
+
+ /*
+ * Disable name compression completely, this is a tradeoff
+ * between CPU and network usage.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "message-compression", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->msgcompression = cfg_obj_asboolean(obj);
+
+ /*
+ * Filter setting on addresses in the answer section.
+ */
+ CHECK(configure_view_acl(vconfig, config, named_g_config,
+ "deny-answer-addresses", "acl", actx,
+ named_g_mctx, &view->denyansweracl));
+ CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses",
+ "except-from", named_g_mctx,
+ &view->answeracl_exclude));
+
+ /*
+ * Filter setting on names (CNAME/DNAME targets) in the answer section.
+ */
+ CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases",
+ "name", named_g_mctx,
+ &view->denyanswernames));
+ CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases",
+ "except-from", named_g_mctx,
+ &view->answernames_exclude));
+
+ /*
+ * Configure sortlist, if set
+ */
+ CHECK(configure_view_sortlist(vconfig, config, actx, named_g_mctx,
+ &view->sortlist));
+
+ /*
+ * Configure default allow-update and allow-update-forwarding ACLs,
+ * so they can be inherited by zones. (XXX: These are not
+ * read from the options/view level here. However, they may be
+ * read from there in zoneconf.c:configure_zone_acl() later.)
+ */
+ if (view->updateacl == NULL) {
+ CHECK(configure_view_acl(NULL, NULL, named_g_config,
+ "allow-update", NULL, actx,
+ named_g_mctx, &view->updateacl));
+ }
+ if (view->upfwdacl == NULL) {
+ CHECK(configure_view_acl(NULL, NULL, named_g_config,
+ "allow-update-forwarding", NULL, actx,
+ named_g_mctx, &view->upfwdacl));
+ }
+
+ /*
+ * Configure default allow-transfer and allow-notify ACLs so they
+ * can be inherited by zones.
+ */
+ if (view->transferacl == NULL) {
+ CHECK(configure_view_acl(vconfig, config, named_g_config,
+ "allow-transfer", NULL, actx,
+ named_g_mctx, &view->transferacl));
+ }
+ if (view->notifyacl == NULL) {
+ CHECK(configure_view_acl(vconfig, config, named_g_config,
+ "allow-notify", NULL, actx,
+ named_g_mctx, &view->notifyacl));
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "provide-ixfr", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->provideixfr = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "request-nsid", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->requestnsid = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "send-cookie", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->sendcookie = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ if (view->pad_acl != NULL) {
+ dns_acl_detach(&view->pad_acl);
+ }
+ result = named_config_get(optionmaps, "response-padding", &obj);
+ if (result == ISC_R_SUCCESS) {
+ const cfg_obj_t *padobj = cfg_tuple_get(obj, "block-size");
+ const cfg_obj_t *aclobj = cfg_tuple_get(obj, "acl");
+ uint32_t padding = cfg_obj_asuint32(padobj);
+
+ if (padding > 512U) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "response-padding block-size cannot "
+ "exceed 512: lowering");
+ padding = 512U;
+ }
+ view->padding = (uint16_t)padding;
+ CHECK(cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx,
+ named_g_mctx, 0, &view->pad_acl));
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "require-server-cookie", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->requireservercookie = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "v6-bias", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->v6bias = cfg_obj_asuint32(obj) * 1000;
+
+ obj = NULL;
+ result = named_config_get(maps, "max-clients-per-query", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ max_clients_per_query = cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "clients-per-query", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_resolver_setclientsperquery(view->resolver, cfg_obj_asuint32(obj),
+ max_clients_per_query);
+
+ obj = NULL;
+ result = named_config_get(maps, "max-recursion-depth", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "max-recursion-queries", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "fetches-per-zone", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ obj2 = cfg_tuple_get(obj, "fetches");
+ dns_resolver_setfetchesperzone(view->resolver, cfg_obj_asuint32(obj2));
+ obj2 = cfg_tuple_get(obj, "response");
+ if (!cfg_obj_isvoid(obj2)) {
+ const char *resp = cfg_obj_asstring(obj2);
+ isc_result_t r = DNS_R_SERVFAIL;
+
+ if (strcasecmp(resp, "drop") == 0) {
+ r = DNS_R_DROP;
+ } else if (strcasecmp(resp, "fail") == 0) {
+ r = DNS_R_SERVFAIL;
+ } else {
+ UNREACHABLE();
+ }
+
+ dns_resolver_setquotaresponse(view->resolver,
+ dns_quotatype_zone, r);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "prefetch", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ prefetch_trigger = cfg_tuple_get(obj, "trigger");
+ view->prefetch_trigger = cfg_obj_asuint32(prefetch_trigger);
+ if (view->prefetch_trigger > 10) {
+ view->prefetch_trigger = 10;
+ }
+ prefetch_eligible = cfg_tuple_get(obj, "eligible");
+ if (cfg_obj_isvoid(prefetch_eligible)) {
+ int m;
+ for (m = 1; maps[m] != NULL; m++) {
+ obj = NULL;
+ result = named_config_get(&maps[m], "prefetch", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ prefetch_eligible = cfg_tuple_get(obj, "eligible");
+ if (cfg_obj_isuint32(prefetch_eligible)) {
+ break;
+ }
+ }
+ INSIST(cfg_obj_isuint32(prefetch_eligible));
+ }
+ view->prefetch_eligible = cfg_obj_asuint32(prefetch_eligible);
+ if (view->prefetch_eligible < view->prefetch_trigger + 6) {
+ view->prefetch_eligible = view->prefetch_trigger + 6;
+ }
+
+ /*
+ * For now, there is only one kind of trusted keys, the
+ * "security roots".
+ */
+ CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys,
+ auto_root, mctx));
+ dns_resolver_resetmustbesecure(view->resolver);
+ obj = NULL;
+ result = named_config_get(maps, "dnssec-must-be-secure", &obj);
+ if (result == ISC_R_SUCCESS) {
+ CHECK(mustbesecure(obj, view->resolver));
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "nta-recheck", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->nta_recheck = cfg_obj_asduration(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "nta-lifetime", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->nta_lifetime = cfg_obj_asduration(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "preferred-glue", &obj);
+ if (result == ISC_R_SUCCESS) {
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "a") == 0) {
+ view->preferred_glue = dns_rdatatype_a;
+ } else if (strcasecmp(str, "aaaa") == 0) {
+ view->preferred_glue = dns_rdatatype_aaaa;
+ } else {
+ view->preferred_glue = 0;
+ }
+ } else {
+ view->preferred_glue = 0;
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "root-delegation-only", &obj);
+ if (result == ISC_R_SUCCESS) {
+ dns_view_setrootdelonly(view, true);
+ }
+ if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) {
+ const cfg_obj_t *exclude;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+
+ name = dns_fixedname_initname(&fixed);
+ for (element = cfg_list_first(obj); element != NULL;
+ element = cfg_list_next(element))
+ {
+ exclude = cfg_listelt_value(element);
+ CHECK(dns_name_fromstring(
+ name, cfg_obj_asstring(exclude), 0, NULL));
+ dns_view_excludedelegationonly(view, name);
+ }
+ } else {
+ dns_view_setrootdelonly(view, false);
+ }
+
+ /*
+ * Load DynDB modules.
+ */
+ dyndb_list = NULL;
+ if (voptions != NULL) {
+ (void)cfg_map_get(voptions, "dyndb", &dyndb_list);
+ } else {
+ (void)cfg_map_get(config, "dyndb", &dyndb_list);
+ }
+
+ for (element = cfg_list_first(dyndb_list); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *dyndb = cfg_listelt_value(element);
+
+ if (dctx == NULL) {
+ const void *hashinit = isc_hash_get_initializer();
+ CHECK(dns_dyndb_createctx(mctx, hashinit, named_g_lctx,
+ view, named_g_server->zonemgr,
+ named_g_server->task,
+ named_g_timermgr, &dctx));
+ }
+
+ CHECK(configure_dyndb(dyndb, mctx, dctx));
+ }
+
+ /*
+ * Load plugins.
+ */
+ plugin_list = NULL;
+ if (voptions != NULL) {
+ (void)cfg_map_get(voptions, "plugin", &plugin_list);
+ } else {
+ (void)cfg_map_get(config, "plugin", &plugin_list);
+ }
+
+ if (plugin_list != NULL) {
+ INSIST(view->hooktable == NULL);
+ CHECK(ns_hooktable_create(view->mctx,
+ (ns_hooktable_t **)&view->hooktable));
+ view->hooktable_free = ns_hooktable_free;
+
+ ns_plugins_create(view->mctx, (ns_plugins_t **)&view->plugins);
+ view->plugins_free = ns_plugins_free;
+
+ CHECK(cfg_pluginlist_foreach(config, plugin_list, named_g_lctx,
+ register_one_plugin, view));
+ }
+
+ /*
+ * Setup automatic empty zones. If recursion is off then
+ * they are disabled by default.
+ */
+ obj = NULL;
+ (void)named_config_get(maps, "empty-zones-enable", &obj);
+ (void)named_config_get(maps, "disable-empty-zone", &disablelist);
+ if (obj == NULL && disablelist == NULL &&
+ view->rdclass == dns_rdataclass_in)
+ {
+ empty_zones_enable = view->recursion;
+ } else if (view->rdclass == dns_rdataclass_in) {
+ if (obj != NULL) {
+ empty_zones_enable = cfg_obj_asboolean(obj);
+ } else {
+ empty_zones_enable = view->recursion;
+ }
+ } else {
+ empty_zones_enable = false;
+ }
+
+ if (empty_zones_enable) {
+ const char *empty;
+ int empty_zone = 0;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t buffer;
+ char server[DNS_NAME_FORMATSIZE + 1];
+ char contact[DNS_NAME_FORMATSIZE + 1];
+ const char *empty_dbtype[4] = { "_builtin", "empty", NULL,
+ NULL };
+ int empty_dbtypec = 4;
+ dns_zonestat_level_t statlevel = dns_zonestat_none;
+
+ name = dns_fixedname_initname(&fixed);
+
+ obj = NULL;
+ result = named_config_get(maps, "empty-server", &obj);
+ if (result == ISC_R_SUCCESS) {
+ CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj),
+ 0, NULL));
+ isc_buffer_init(&buffer, server, sizeof(server) - 1);
+ CHECK(dns_name_totext(name, false, &buffer));
+ server[isc_buffer_usedlength(&buffer)] = 0;
+ empty_dbtype[2] = server;
+ } else {
+ empty_dbtype[2] = "@";
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "empty-contact", &obj);
+ if (result == ISC_R_SUCCESS) {
+ CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj),
+ 0, NULL));
+ isc_buffer_init(&buffer, contact, sizeof(contact) - 1);
+ CHECK(dns_name_totext(name, false, &buffer));
+ contact[isc_buffer_usedlength(&buffer)] = 0;
+ empty_dbtype[3] = contact;
+ } else {
+ empty_dbtype[3] = ".";
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "zone-statistics", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ statlevel = dns_zonestat_full;
+ } else {
+ statlevel = dns_zonestat_none;
+ }
+ } else {
+ const char *levelstr = cfg_obj_asstring(obj);
+ if (strcasecmp(levelstr, "full") == 0) {
+ statlevel = dns_zonestat_full;
+ } else if (strcasecmp(levelstr, "terse") == 0) {
+ statlevel = dns_zonestat_terse;
+ } else if (strcasecmp(levelstr, "none") == 0) {
+ statlevel = dns_zonestat_none;
+ } else {
+ UNREACHABLE();
+ }
+ }
+
+ for (empty = empty_zones[empty_zone]; empty != NULL;
+ empty = empty_zones[++empty_zone])
+ {
+ dns_forwarders_t *dnsforwarders = NULL;
+
+ /*
+ * Look for zone on drop list.
+ */
+ CHECK(dns_name_fromstring(name, empty, 0, NULL));
+ if (disablelist != NULL &&
+ on_disable_list(disablelist, name))
+ {
+ continue;
+ }
+
+ /*
+ * This zone already exists.
+ */
+ (void)dns_view_findzone(view, name, &zone);
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ continue;
+ }
+
+ /*
+ * If we would forward this name don't add a
+ * empty zone for it.
+ */
+ result = dns_fwdtable_find(view->fwdtable, name, NULL,
+ &dnsforwarders);
+ if ((result == ISC_R_SUCCESS ||
+ result == DNS_R_PARTIALMATCH) &&
+ dnsforwarders->fwdpolicy == dns_fwdpolicy_only)
+ {
+ continue;
+ }
+
+ /*
+ * See if we can re-use a existing zone.
+ */
+ result = dns_viewlist_find(&named_g_server->viewlist,
+ view->name, view->rdclass,
+ &pview);
+ if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
+ {
+ goto cleanup;
+ }
+
+ if (pview != NULL) {
+ (void)dns_view_findzone(pview, name, &zone);
+ dns_view_detach(&pview);
+ }
+
+ CHECK(create_empty_zone(zone, name, view, zonelist,
+ empty_dbtype, empty_dbtypec,
+ statlevel));
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ }
+ }
+
+ obj = NULL;
+ if (view->rdclass == dns_rdataclass_in) {
+ (void)named_config_get(maps, "ipv4only-enable", &obj);
+ }
+ if (view->rdclass == dns_rdataclass_in && (obj != NULL)
+ ? cfg_obj_asboolean(obj)
+ : !ISC_LIST_EMPTY(view->dns64))
+ {
+ const char *server, *contact;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ struct {
+ const char *name;
+ const char *type;
+ } zones[] = {
+ { "ipv4only.arpa", "ipv4only" },
+ { "170.0.0.192.in-addr.arpa", "ipv4reverse" },
+ { "171.0.0.192.in-addr.arpa", "ipv4reverse" },
+ };
+ size_t ipv4only_zone;
+
+ obj = NULL;
+ result = named_config_get(maps, "ipv4only-server", &obj);
+ if (result == ISC_R_SUCCESS) {
+ server = cfg_obj_asstring(obj);
+ } else {
+ server = NULL;
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "ipv4only-contact", &obj);
+ if (result == ISC_R_SUCCESS) {
+ contact = cfg_obj_asstring(obj);
+ } else {
+ contact = NULL;
+ }
+
+ name = dns_fixedname_initname(&fixed);
+ for (ipv4only_zone = 0; ipv4only_zone < ARRAY_SIZE(zones);
+ ipv4only_zone++)
+ {
+ dns_forwarders_t *dnsforwarders = NULL;
+
+ CHECK(dns_name_fromstring(
+ name, zones[ipv4only_zone].name, 0, NULL));
+
+ (void)dns_view_findzone(view, name, &zone);
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ continue;
+ }
+
+ /*
+ * If we would forward this name don't add it.
+ */
+ result = dns_fwdtable_find(view->fwdtable, name, NULL,
+ &dnsforwarders);
+ if ((result == ISC_R_SUCCESS ||
+ result == DNS_R_PARTIALMATCH) &&
+ dnsforwarders->fwdpolicy == dns_fwdpolicy_only)
+ {
+ continue;
+ }
+
+ /*
+ * See if we can re-use a existing zone.
+ */
+ result = dns_viewlist_find(&named_g_server->viewlist,
+ view->name, view->rdclass,
+ &pview);
+ if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
+ {
+ goto cleanup;
+ }
+
+ if (pview != NULL) {
+ (void)dns_view_findzone(pview, name, &zone);
+ dns_view_detach(&pview);
+ }
+
+ CHECK(create_ipv4only_zone(zone, view, name,
+ zones[ipv4only_zone].type,
+ mctx, server, contact));
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ }
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "rate-limit", &obj);
+ if (result == ISC_R_SUCCESS) {
+ result = configure_rrl(view, config, obj);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Set the servfail-ttl.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "servfail-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ fail_ttl = cfg_obj_asduration(obj);
+ if (fail_ttl > 30) {
+ fail_ttl = 30;
+ }
+ dns_view_setfailttl(view, fail_ttl);
+
+ /*
+ * Name space to look up redirect information in.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "nxdomain-redirect", &obj);
+ if (result == ISC_R_SUCCESS) {
+ dns_name_t *name = dns_fixedname_name(&view->redirectfixed);
+ CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 0,
+ NULL));
+ view->redirectzone = name;
+ } else {
+ view->redirectzone = NULL;
+ }
+
+ /*
+ * Exceptions to DNSSEC validation.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "validate-except", &obj);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_view_getntatable(view, &ntatable);
+ }
+ if (result == ISC_R_SUCCESS) {
+ for (element = cfg_list_first(obj); element != NULL;
+ element = cfg_list_next(element))
+ {
+ dns_fixedname_t fntaname;
+ dns_name_t *ntaname;
+
+ ntaname = dns_fixedname_initname(&fntaname);
+ obj = cfg_listelt_value(element);
+ CHECK(dns_name_fromstring(
+ ntaname, cfg_obj_asstring(obj), 0, NULL));
+ CHECK(dns_ntatable_add(ntatable, ntaname, true, 0,
+ 0xffffffffU));
+ }
+ }
+
+#ifdef HAVE_DNSTAP
+ /*
+ * Set up the dnstap environment and configure message
+ * types to log.
+ */
+ CHECK(configure_dnstap(maps, view));
+#endif /* HAVE_DNSTAP */
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ /*
+ * Revert to the old view if there was an error.
+ */
+ if (result != ISC_R_SUCCESS) {
+ isc_result_t result2;
+
+ result2 = dns_viewlist_find(&named_g_server->viewlist,
+ view->name, view->rdclass, &pview);
+ if (result2 == ISC_R_SUCCESS) {
+ dns_view_thaw(pview);
+
+ obj = NULL;
+ if (rpz_configured &&
+ pview->rdclass == dns_rdataclass_in && need_hints &&
+ named_config_get(maps, "response-policy", &obj) ==
+ ISC_R_SUCCESS)
+ {
+ /*
+ * We are swapping the places of the `view` and
+ * `pview` in the function's parameters list
+ * because we are reverting the same operation
+ * done previously in the "correct" order.
+ */
+ result2 = configure_rpz(pview, view, maps, obj,
+ &old_rpz_ok);
+ if (result2 != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx,
+ NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER,
+ ISC_LOG_ERROR,
+ "rpz configuration "
+ "revert failed for view "
+ "'%s'",
+ pview->name);
+ }
+ }
+
+ obj = NULL;
+ if (catz_configured &&
+ pview->rdclass == dns_rdataclass_in && need_hints &&
+ named_config_get(maps, "catalog-zones", &obj) ==
+ ISC_R_SUCCESS)
+ {
+ /*
+ * We are swapping the places of the `view` and
+ * `pview` in the function's parameters list
+ * because we are reverting the same operation
+ * done previously in the "correct" order.
+ */
+ result2 = configure_catz(pview, view, config,
+ obj);
+ if (result2 != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx,
+ NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER,
+ ISC_LOG_ERROR,
+ "catz configuration "
+ "revert failed for view "
+ "'%s'",
+ pview->name);
+ }
+ }
+
+ dns_view_freeze(pview);
+ }
+
+ if (pview != NULL) {
+ dns_view_detach(&pview);
+ }
+
+ if (zone_element_latest != NULL) {
+ for (element = cfg_list_first(zonelist);
+ element != NULL; element = cfg_list_next(element))
+ {
+ const cfg_obj_t *zconfig =
+ cfg_listelt_value(element);
+ configure_zone_setviewcommit(result, zconfig,
+ view);
+ if (element == zone_element_latest) {
+ /*
+ * This was the latest element that was
+ * successfully configured earlier.
+ */
+ break;
+ }
+ }
+ }
+ }
+
+ if (ntatable != NULL) {
+ dns_ntatable_detach(&ntatable);
+ }
+ if (clients != NULL) {
+ dns_acl_detach(&clients);
+ }
+ if (mapped != NULL) {
+ dns_acl_detach(&mapped);
+ }
+ if (excluded != NULL) {
+ dns_acl_detach(&excluded);
+ }
+ if (ring != NULL) {
+ dns_tsigkeyring_detach(&ring);
+ }
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ if (dispatch4 != NULL) {
+ dns_dispatch_detach(&dispatch4);
+ }
+ if (dispatch6 != NULL) {
+ dns_dispatch_detach(&dispatch6);
+ }
+ if (resstats != NULL) {
+ isc_stats_detach(&resstats);
+ }
+ if (resquerystats != NULL) {
+ dns_stats_detach(&resquerystats);
+ }
+ if (order != NULL) {
+ dns_order_detach(&order);
+ }
+ if (cmctx != NULL) {
+ isc_mem_detach(&cmctx);
+ }
+ if (hmctx != NULL) {
+ isc_mem_detach(&hmctx);
+ }
+ if (cache != NULL) {
+ dns_cache_detach(&cache);
+ }
+ if (dctx != NULL) {
+ dns_dyndb_destroyctx(&dctx);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+configure_hints(dns_view_t *view, const char *filename) {
+ isc_result_t result;
+ dns_db_t *db;
+
+ db = NULL;
+ result = dns_rootns_create(view->mctx, view->rdclass, filename, &db);
+ if (result == ISC_R_SUCCESS) {
+ dns_view_sethints(view, db);
+ dns_db_detach(&db);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+configure_alternates(const cfg_obj_t *config, dns_view_t *view,
+ const cfg_obj_t *alternates) {
+ const cfg_obj_t *portobj;
+ const cfg_obj_t *addresses;
+ const cfg_listelt_t *element;
+ isc_result_t result = ISC_R_SUCCESS;
+ in_port_t port;
+
+ /*
+ * Determine which port to send requests to.
+ */
+ CHECKM(named_config_getport(config, "port", &port), "port");
+
+ if (alternates != NULL) {
+ portobj = cfg_tuple_get(alternates, "port");
+ if (cfg_obj_isuint32(portobj)) {
+ uint32_t val = cfg_obj_asuint32(portobj);
+ if (val > UINT16_MAX) {
+ cfg_obj_log(portobj, named_g_lctx,
+ ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ return (ISC_R_RANGE);
+ }
+ port = (in_port_t)val;
+ }
+ }
+
+ addresses = NULL;
+ if (alternates != NULL) {
+ addresses = cfg_tuple_get(alternates, "addresses");
+ }
+
+ for (element = cfg_list_first(addresses); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *alternate = cfg_listelt_value(element);
+ isc_sockaddr_t sa;
+
+ if (!cfg_obj_issockaddr(alternate)) {
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ const char *str = cfg_obj_asstring(
+ cfg_tuple_get(alternate, "name"));
+ isc_buffer_t buffer;
+ in_port_t myport = port;
+
+ isc_buffer_constinit(&buffer, str, strlen(str));
+ isc_buffer_add(&buffer, strlen(str));
+ name = dns_fixedname_initname(&fixed);
+ CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0,
+ NULL));
+
+ portobj = cfg_tuple_get(alternate, "port");
+ if (cfg_obj_isuint32(portobj)) {
+ uint32_t val = cfg_obj_asuint32(portobj);
+ if (val > UINT16_MAX) {
+ cfg_obj_log(portobj, named_g_lctx,
+ ISC_LOG_ERROR,
+ "port '%u' out of range",
+ val);
+ return (ISC_R_RANGE);
+ }
+ myport = (in_port_t)val;
+ }
+ dns_resolver_addalternate(view->resolver, NULL, name,
+ myport);
+ continue;
+ }
+
+ sa = *cfg_obj_assockaddr(alternate);
+ if (isc_sockaddr_getport(&sa) == 0) {
+ isc_sockaddr_setport(&sa, port);
+ }
+ dns_resolver_addalternate(view->resolver, &sa, NULL, 0);
+ }
+
+cleanup:
+ return (result);
+}
+
+static isc_result_t
+configure_forward(const cfg_obj_t *config, dns_view_t *view,
+ const dns_name_t *origin, const cfg_obj_t *forwarders,
+ const cfg_obj_t *forwardtype) {
+ const cfg_obj_t *portobj = NULL;
+ const cfg_obj_t *faddresses = NULL;
+ const cfg_listelt_t *element = NULL;
+ dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none;
+ dns_forwarderlist_t fwdlist;
+ dns_forwarder_t *fwd = NULL;
+ isc_result_t result;
+ in_port_t port;
+
+ ISC_LIST_INIT(fwdlist);
+
+ /*
+ * Determine which port to send forwarded requests to.
+ */
+ CHECKM(named_config_getport(config, "port", &port), "port");
+
+ if (forwarders != NULL) {
+ portobj = cfg_tuple_get(forwarders, "port");
+ if (cfg_obj_isuint32(portobj)) {
+ uint32_t val = cfg_obj_asuint32(portobj);
+ if (val > UINT16_MAX) {
+ cfg_obj_log(portobj, named_g_lctx,
+ ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ return (ISC_R_RANGE);
+ }
+ port = (in_port_t)val;
+ }
+ }
+
+ faddresses = NULL;
+ if (forwarders != NULL) {
+ faddresses = cfg_tuple_get(forwarders, "addresses");
+ }
+
+ for (element = cfg_list_first(faddresses); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *forwarder = cfg_listelt_value(element);
+ fwd = isc_mem_get(view->mctx, sizeof(dns_forwarder_t));
+ fwd->addr = *cfg_obj_assockaddr(forwarder);
+ if (isc_sockaddr_getport(&fwd->addr) == 0) {
+ isc_sockaddr_setport(&fwd->addr, port);
+ }
+ ISC_LINK_INIT(fwd, link);
+ ISC_LIST_APPEND(fwdlist, fwd, link);
+ }
+
+ if (ISC_LIST_EMPTY(fwdlist)) {
+ if (forwardtype != NULL) {
+ cfg_obj_log(forwardtype, named_g_lctx, ISC_LOG_WARNING,
+ "no forwarders seen; disabling "
+ "forwarding");
+ }
+ fwdpolicy = dns_fwdpolicy_none;
+ } else {
+ if (forwardtype == NULL) {
+ fwdpolicy = dns_fwdpolicy_first;
+ } else {
+ const char *forwardstr = cfg_obj_asstring(forwardtype);
+ if (strcasecmp(forwardstr, "first") == 0) {
+ fwdpolicy = dns_fwdpolicy_first;
+ } else if (strcasecmp(forwardstr, "only") == 0) {
+ fwdpolicy = dns_fwdpolicy_only;
+ } else {
+ UNREACHABLE();
+ }
+ }
+ }
+
+ result = dns_fwdtable_addfwd(view->fwdtable, origin, &fwdlist,
+ fwdpolicy);
+ if (result != ISC_R_SUCCESS) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(origin, namebuf, sizeof(namebuf));
+ cfg_obj_log(forwarders, named_g_lctx, ISC_LOG_WARNING,
+ "could not set up forwarding for domain '%s': %s",
+ namebuf, isc_result_totext(result));
+ goto cleanup;
+ }
+
+ if (fwdpolicy == dns_fwdpolicy_only) {
+ dns_view_sfd_add(view, origin);
+ }
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+
+ while (!ISC_LIST_EMPTY(fwdlist)) {
+ fwd = ISC_LIST_HEAD(fwdlist);
+ ISC_LIST_UNLINK(fwdlist, fwd, link);
+ isc_mem_put(view->mctx, fwd, sizeof(dns_forwarder_t));
+ }
+
+ return (result);
+}
+
+static isc_result_t
+get_viewinfo(const cfg_obj_t *vconfig, const char **namep,
+ dns_rdataclass_t *classp) {
+ isc_result_t result = ISC_R_SUCCESS;
+ const char *viewname;
+ dns_rdataclass_t viewclass;
+
+ REQUIRE(namep != NULL && *namep == NULL);
+ REQUIRE(classp != NULL);
+
+ if (vconfig != NULL) {
+ const cfg_obj_t *classobj = NULL;
+
+ viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
+ classobj = cfg_tuple_get(vconfig, "class");
+ CHECK(named_config_getclass(classobj, dns_rdataclass_in,
+ &viewclass));
+ if (dns_rdataclass_ismeta(viewclass)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "view '%s': class must not be meta",
+ viewname);
+ CHECK(ISC_R_FAILURE);
+ }
+ } else {
+ viewname = "_default";
+ viewclass = dns_rdataclass_in;
+ }
+
+ *namep = viewname;
+ *classp = viewclass;
+
+cleanup:
+ return (result);
+}
+
+/*
+ * Find a view based on its configuration info and attach to it.
+ *
+ * If 'vconfig' is NULL, attach to the default view.
+ */
+static isc_result_t
+find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
+ dns_view_t **viewp) {
+ isc_result_t result;
+ const char *viewname = NULL;
+ dns_rdataclass_t viewclass;
+ dns_view_t *view = NULL;
+
+ result = get_viewinfo(vconfig, &viewname, &viewclass);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ *viewp = view;
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Create a new view and add it to the list.
+ *
+ * If 'vconfig' is NULL, create the default view.
+ *
+ * The view created is attached to '*viewp'.
+ */
+static isc_result_t
+create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
+ dns_view_t **viewp) {
+ isc_result_t result;
+ const char *viewname = NULL;
+ dns_rdataclass_t viewclass;
+ dns_view_t *view = NULL;
+
+ result = get_viewinfo(vconfig, &viewname, &viewclass);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
+ if (result == ISC_R_SUCCESS) {
+ return (ISC_R_EXISTS);
+ }
+ if (result != ISC_R_NOTFOUND) {
+ return (result);
+ }
+ INSIST(view == NULL);
+
+ result = dns_view_create(named_g_mctx, viewclass, viewname, &view);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ isc_nonce_buf(view->secret, sizeof(view->secret));
+
+ ISC_LIST_APPEND(*viewlist, view, link);
+ dns_view_attach(view, viewp);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Configure or reconfigure a zone.
+ */
+static isc_result_t
+configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
+ const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
+ dns_viewlist_t *viewlist, dns_kasplist_t *kasplist,
+ cfg_aclconfctx_t *aclconf, bool added, bool old_rpz_ok,
+ bool modify) {
+ dns_view_t *pview = NULL; /* Production view */
+ dns_zone_t *zone = NULL; /* New or reused zone */
+ dns_zone_t *raw = NULL; /* New or reused raw zone */
+ dns_zone_t *dupzone = NULL;
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *zoptions = NULL;
+ const cfg_obj_t *typeobj = NULL;
+ const cfg_obj_t *forwarders = NULL;
+ const cfg_obj_t *forwardtype = NULL;
+ const cfg_obj_t *ixfrfromdiffs = NULL;
+ const cfg_obj_t *only = NULL;
+ const cfg_obj_t *viewobj = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ isc_buffer_t buffer;
+ dns_fixedname_t fixorigin;
+ dns_name_t *origin;
+ const char *zname;
+ dns_rdataclass_t zclass;
+ const char *ztypestr;
+ dns_rpz_num_t rpz_num;
+ bool zone_is_catz = false;
+ bool zone_maybe_inline = false;
+ bool inline_signing = false;
+ bool fullsign = false;
+
+ options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+
+ /*
+ * Get the zone origin as a dns_name_t.
+ */
+ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+ isc_buffer_constinit(&buffer, zname, strlen(zname));
+ isc_buffer_add(&buffer, strlen(zname));
+ dns_fixedname_init(&fixorigin);
+ CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), &buffer,
+ dns_rootname, 0, NULL));
+ origin = dns_fixedname_name(&fixorigin);
+
+ CHECK(named_config_getclass(cfg_tuple_get(zconfig, "class"),
+ view->rdclass, &zclass));
+ if (zclass != view->rdclass) {
+ const char *vname = NULL;
+ if (vconfig != NULL) {
+ vname = cfg_obj_asstring(
+ cfg_tuple_get(vconfig, "name"));
+ } else {
+ vname = "<default view>";
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "zone '%s': wrong class for view '%s'", zname,
+ vname);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ (void)cfg_map_get(zoptions, "in-view", &viewobj);
+ if (viewobj != NULL) {
+ const char *inview = cfg_obj_asstring(viewobj);
+ dns_view_t *otherview = NULL;
+
+ if (viewlist == NULL) {
+ cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
+ "'in-view' option is not permitted in "
+ "dynamically added zones");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ result = dns_viewlist_find(viewlist, inview, view->rdclass,
+ &otherview);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
+ "view '%s' is not yet defined.", inview);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ result = dns_view_findzone(otherview, origin, &zone);
+ dns_view_detach(&otherview);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
+ "zone '%s' not defined in view '%s'", zname,
+ inview);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ CHECK(dns_view_addzone(view, zone));
+ dns_zone_detach(&zone);
+
+ /*
+ * If the zone contains a 'forwarders' statement, configure
+ * selective forwarding. Note: this is not inherited from the
+ * other view.
+ */
+ forwarders = NULL;
+ result = cfg_map_get(zoptions, "forwarders", &forwarders);
+ if (result == ISC_R_SUCCESS) {
+ forwardtype = NULL;
+ (void)cfg_map_get(zoptions, "forward", &forwardtype);
+ CHECK(configure_forward(config, view, origin,
+ forwarders, forwardtype));
+ }
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+ (void)cfg_map_get(zoptions, "type", &typeobj);
+ if (typeobj == NULL) {
+ cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
+ "zone '%s' 'type' not specified", zname);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ ztypestr = cfg_obj_asstring(typeobj);
+
+ /*
+ * "hints zones" aren't zones. If we've got one,
+ * configure it and return.
+ */
+ if (strcasecmp(ztypestr, "hint") == 0) {
+ const cfg_obj_t *fileobj = NULL;
+ if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "zone '%s': 'file' not specified", zname);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ if (dns_name_equal(origin, dns_rootname)) {
+ const char *hintsfile = cfg_obj_asstring(fileobj);
+
+ CHECK(configure_hints(view, hintsfile));
+
+ /*
+ * Hint zones may also refer to delegation only points.
+ */
+ only = NULL;
+ tresult = cfg_map_get(zoptions, "delegation-only",
+ &only);
+ if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only))
+ {
+ dns_view_adddelegationonly(view, origin);
+ }
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "ignoring non-root hint zone '%s'",
+ zname);
+ result = ISC_R_SUCCESS;
+ }
+ /* Skip ordinary zone processing. */
+ goto cleanup;
+ }
+
+ /*
+ * "forward zones" aren't zones either. Translate this syntax into
+ * the appropriate selective forwarding configuration and return.
+ */
+ if (strcasecmp(ztypestr, "forward") == 0) {
+ forwardtype = NULL;
+ forwarders = NULL;
+
+ (void)cfg_map_get(zoptions, "forward", &forwardtype);
+ (void)cfg_map_get(zoptions, "forwarders", &forwarders);
+ CHECK(configure_forward(config, view, origin, forwarders,
+ forwardtype));
+
+ /*
+ * Forward zones may also set delegation only.
+ */
+ only = NULL;
+ tresult = cfg_map_get(zoptions, "delegation-only", &only);
+ if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only)) {
+ dns_view_adddelegationonly(view, origin);
+ }
+ goto cleanup;
+ }
+
+ /*
+ * "delegation-only zones" aren't zones either.
+ */
+ if (strcasecmp(ztypestr, "delegation-only") == 0) {
+ dns_view_adddelegationonly(view, origin);
+ goto cleanup;
+ }
+
+ /*
+ * Redirect zones only require minimal configuration.
+ */
+ if (strcasecmp(ztypestr, "redirect") == 0) {
+ if (view->redirect != NULL) {
+ cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
+ "redirect zone already exists");
+ result = ISC_R_EXISTS;
+ goto cleanup;
+ }
+ result = dns_viewlist_find(viewlist, view->name, view->rdclass,
+ &pview);
+ if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ if (pview != NULL && pview->redirect != NULL) {
+ dns_zone_attach(pview->redirect, &zone);
+ dns_zone_setview(zone, view);
+ } else {
+ CHECK(dns_zonemgr_createzone(named_g_server->zonemgr,
+ &zone));
+ CHECK(dns_zone_setorigin(zone, origin));
+ dns_zone_setview(zone, view);
+ CHECK(dns_zonemgr_managezone(named_g_server->zonemgr,
+ zone));
+ dns_zone_setstats(zone, named_g_server->zonestats);
+ }
+ CHECK(named_zone_configure(config, vconfig, zconfig, aclconf,
+ kasplist, zone, NULL));
+ dns_zone_attach(zone, &view->redirect);
+ goto cleanup;
+ }
+
+ if (!modify) {
+ /*
+ * Check for duplicates in the new zone table.
+ */
+ result = dns_view_findzone(view, origin, &dupzone);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We already have this zone!
+ */
+ cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
+ "zone '%s' already exists", zname);
+ dns_zone_detach(&dupzone);
+ result = ISC_R_EXISTS;
+ goto cleanup;
+ }
+ INSIST(dupzone == NULL);
+ }
+
+ /*
+ * Note whether this is a response policy zone and which one if so,
+ * unless we are using RPZ service interface. In that case, the
+ * BIND zone database has nothing to do with rpz and so we don't care.
+ */
+ for (rpz_num = 0;; ++rpz_num) {
+ if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones ||
+ view->rpzs->p.dnsrps_enabled)
+ {
+ rpz_num = DNS_RPZ_INVALID_NUM;
+ break;
+ }
+ if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, origin))
+ {
+ break;
+ }
+ }
+
+ if (view->catzs != NULL &&
+ dns_catz_get_zone(view->catzs, origin) != NULL)
+ {
+ zone_is_catz = true;
+ }
+
+ /*
+ * See if we can reuse an existing zone. This is
+ * only possible if all of these are true:
+ * - The zone's view exists
+ * - A zone with the right name exists in the view
+ * - The zone is compatible with the config
+ * options (e.g., an existing primary zone cannot
+ * be reused if the options specify a secondary zone)
+ * - The zone was not and is still not a response policy zone
+ * or the zone is a policy zone with an unchanged number
+ * and we are using the old policy zone summary data.
+ */
+ result = dns_viewlist_find(&named_g_server->viewlist, view->name,
+ view->rdclass, &pview);
+ if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ if (pview != NULL) {
+ result = dns_view_findzone(pview, origin, &zone);
+ }
+ if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ if (zone != NULL && !named_zone_reusable(zone, zconfig)) {
+ dns_zone_detach(&zone);
+ fullsign = true;
+ }
+
+ if (zone != NULL && (rpz_num != dns_zone_get_rpz_num(zone) ||
+ (rpz_num != DNS_RPZ_INVALID_NUM && !old_rpz_ok)))
+ {
+ dns_zone_detach(&zone);
+ }
+
+ if (zone != NULL) {
+ /*
+ * We found a reusable zone. Make it use the
+ * new view.
+ */
+ dns_zone_setview(zone, view);
+ } else {
+ /*
+ * We cannot reuse an existing zone, we have
+ * to create a new one.
+ */
+ CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone));
+ CHECK(dns_zone_setorigin(zone, origin));
+ dns_zone_setview(zone, view);
+ CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
+ dns_zone_setstats(zone, named_g_server->zonestats);
+ }
+ if (rpz_num != DNS_RPZ_INVALID_NUM) {
+ result = dns_zone_rpz_enable(zone, view->rpzs, rpz_num);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "zone '%s': incompatible"
+ " masterfile-format or database"
+ " for a response policy zone",
+ zname);
+ goto cleanup;
+ }
+ }
+
+ if (zone_is_catz) {
+ dns_zone_catz_enable(zone, view->catzs);
+ } else if (dns_zone_catz_is_enabled(zone)) {
+ dns_zone_catz_disable(zone);
+ }
+
+ /*
+ * If the zone contains a 'forwarders' statement, configure
+ * selective forwarding.
+ */
+ forwarders = NULL;
+ if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) {
+ forwardtype = NULL;
+ (void)cfg_map_get(zoptions, "forward", &forwardtype);
+ CHECK(configure_forward(config, view, origin, forwarders,
+ forwardtype));
+ }
+
+ /*
+ * Stub and forward zones may also refer to delegation only points.
+ */
+ only = NULL;
+ if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS) {
+ if (cfg_obj_asboolean(only)) {
+ dns_view_adddelegationonly(view, origin);
+ }
+ }
+
+ /*
+ * Mark whether the zone was originally added at runtime or not
+ */
+ dns_zone_setadded(zone, added);
+
+ /*
+ * Determine if we need to set up inline signing.
+ */
+ zone_maybe_inline = ((strcasecmp(ztypestr, "primary") == 0 ||
+ strcasecmp(ztypestr, "master") == 0 ||
+ strcasecmp(ztypestr, "secondary") == 0 ||
+ strcasecmp(ztypestr, "slave") == 0));
+
+ if (zone_maybe_inline) {
+ inline_signing = named_zone_inlinesigning(zconfig);
+ }
+ if (inline_signing) {
+ dns_zone_getraw(zone, &raw);
+ if (raw == NULL) {
+ CHECK(dns_zone_create(&raw, mctx));
+ CHECK(dns_zone_setorigin(raw, origin));
+ dns_zone_setview(raw, view);
+ dns_zone_setstats(raw, named_g_server->zonestats);
+ CHECK(dns_zone_link(zone, raw));
+ }
+ if (cfg_map_get(zoptions, "ixfr-from-differences",
+ &ixfrfromdiffs) == ISC_R_SUCCESS)
+ {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "zone '%s': 'ixfr-from-differences' is "
+ "ignored for inline-signed zones",
+ zname);
+ }
+ }
+
+ /*
+ * Configure the zone.
+ */
+ CHECK(named_zone_configure(config, vconfig, zconfig, aclconf, kasplist,
+ zone, raw));
+
+ /*
+ * Add the zone to its view in the new view list.
+ */
+ if (!modify) {
+ CHECK(dns_view_addzone(view, zone));
+ }
+
+ if (zone_is_catz) {
+ /*
+ * force catz reload if the zone is loaded;
+ * if it's not it'll get reloaded on zone load
+ */
+ dns_db_t *db = NULL;
+
+ tresult = dns_zone_getdb(zone, &db);
+ if (tresult == ISC_R_SUCCESS) {
+ dns_catz_dbupdate_callback(db, view->catzs);
+ dns_db_detach(&db);
+ }
+ }
+
+ /*
+ * Ensure that zone keys are reloaded on reconfig
+ */
+ if ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0) {
+ dns_zone_rekey(zone, fullsign);
+ }
+
+cleanup:
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ if (raw != NULL) {
+ dns_zone_detach(&raw);
+ }
+ if (pview != NULL) {
+ dns_view_detach(&pview);
+ }
+
+ return (result);
+}
+
+/*
+ * Configure built-in zone for storing managed-key data.
+ */
+static isc_result_t
+add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) {
+ isc_result_t result;
+ dns_view_t *pview = NULL;
+ dns_zone_t *zone = NULL;
+ dns_acl_t *none = NULL;
+ char filename[PATH_MAX];
+ bool defaultview;
+
+ REQUIRE(view != NULL);
+
+ /* See if we can re-use an existing keydata zone. */
+ result = dns_viewlist_find(&named_g_server->viewlist, view->name,
+ view->rdclass, &pview);
+ if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ if (pview != NULL) {
+ if (pview->managed_keys != NULL) {
+ dns_zone_attach(pview->managed_keys,
+ &view->managed_keys);
+ dns_zone_setview(pview->managed_keys, view);
+ dns_zone_setviewcommit(pview->managed_keys);
+ dns_view_detach(&pview);
+ dns_zone_synckeyzone(view->managed_keys);
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_view_detach(&pview);
+ }
+
+ /* No existing keydata zone was found; create one */
+ CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone));
+ CHECK(dns_zone_setorigin(zone, dns_rootname));
+
+ defaultview = (strcmp(view->name, "_default") == 0);
+ CHECK(isc_file_sanitize(
+ directory, defaultview ? "managed-keys" : view->name,
+ defaultview ? "bind" : "mkeys", filename, sizeof(filename)));
+ CHECK(dns_zone_setfile(zone, filename, dns_masterformat_text,
+ &dns_master_style_default));
+
+ dns_zone_setview(zone, view);
+ dns_zone_settype(zone, dns_zone_key);
+ dns_zone_setclass(zone, view->rdclass);
+
+ CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
+
+ CHECK(dns_acl_none(mctx, &none));
+ dns_zone_setqueryacl(zone, none);
+ dns_zone_setqueryonacl(zone, none);
+ dns_acl_detach(&none);
+
+ dns_zone_setdialup(zone, dns_dialuptype_no);
+ dns_zone_setnotifytype(zone, dns_notifytype_no);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true);
+ dns_zone_setjournalsize(zone, 0);
+
+ dns_zone_setstats(zone, named_g_server->zonestats);
+ CHECK(setquerystats(zone, mctx, dns_zonestat_none));
+
+ if (view->managed_keys != NULL) {
+ dns_zone_detach(&view->managed_keys);
+ }
+ dns_zone_attach(zone, &view->managed_keys);
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "set up managed keys zone for view %s, file '%s'",
+ view->name, filename);
+
+cleanup:
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ if (none != NULL) {
+ dns_acl_detach(&none);
+ }
+
+ return (result);
+}
+
+/*
+ * Configure a single server quota.
+ */
+static void
+configure_server_quota(const cfg_obj_t **maps, const char *name,
+ isc_quota_t *quota) {
+ const cfg_obj_t *obj = NULL;
+ isc_result_t result;
+
+ result = named_config_get(maps, name, &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ isc_quota_max(quota, cfg_obj_asuint32(obj));
+}
+
+/*
+ * This function is called as soon as the 'directory' statement has been
+ * parsed. This can be extended to support other options if necessary.
+ */
+static isc_result_t
+directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
+ isc_result_t result;
+ const char *directory;
+
+ REQUIRE(strcasecmp("directory", clausename) == 0);
+
+ UNUSED(arg);
+ UNUSED(clausename);
+
+ /*
+ * Change directory.
+ */
+ directory = cfg_obj_asstring(obj);
+
+ if (!isc_file_ischdiridempotent(directory)) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "option 'directory' contains relative path '%s'",
+ directory);
+ }
+
+ if (!isc_file_isdirwritable(directory)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "directory '%s' is not writable", directory);
+ return (ISC_R_NOPERM);
+ }
+
+ result = isc_dir_chdir(directory);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
+ "change directory to '%s' failed: %s", directory,
+ isc_result_totext(result));
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This event callback is invoked to do periodic network interface
+ * scanning.
+ */
+
+static void
+interface_timer_tick(isc_task_t *task, isc_event_t *event) {
+ named_server_t *server = (named_server_t *)event->ev_arg;
+ INSIST(task == server->task);
+ UNUSED(task);
+
+ isc_event_free(&event);
+ ns_interfacemgr_scan(server->interfacemgr, false, false);
+}
+
+static void
+heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) {
+ named_server_t *server = (named_server_t *)event->ev_arg;
+ dns_view_t *view;
+
+ UNUSED(task);
+ isc_event_free(&event);
+ view = ISC_LIST_HEAD(server->viewlist);
+ while (view != NULL) {
+ dns_view_dialup(view);
+ view = ISC_LIST_NEXT(view, link);
+ }
+}
+
+typedef struct {
+ isc_mem_t *mctx;
+ isc_task_t *task;
+ dns_fetch_t *fetch;
+ dns_view_t *view;
+ dns_fixedname_t tatname;
+ dns_fixedname_t keyname;
+ dns_rdataset_t rdataset;
+ dns_rdataset_t sigrdataset;
+} ns_tat_t;
+
+static int
+cid(const void *a, const void *b) {
+ const uint16_t ida = *(const uint16_t *)a;
+ const uint16_t idb = *(const uint16_t *)b;
+ if (ida < idb) {
+ return (-1);
+ } else if (ida > idb) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+static void
+tat_done(isc_task_t *task, isc_event_t *event) {
+ dns_fetchevent_t *devent;
+ ns_tat_t *tat;
+
+ INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
+ INSIST(event->ev_arg != NULL);
+
+ UNUSED(task);
+
+ tat = event->ev_arg;
+ devent = (dns_fetchevent_t *)event;
+
+ /* Free resources which are not of interest */
+ if (devent->node != NULL) {
+ dns_db_detachnode(devent->db, &devent->node);
+ }
+ if (devent->db != NULL) {
+ dns_db_detach(&devent->db);
+ }
+ isc_event_free(&event);
+ dns_resolver_destroyfetch(&tat->fetch);
+ if (dns_rdataset_isassociated(&tat->rdataset)) {
+ dns_rdataset_disassociate(&tat->rdataset);
+ }
+ if (dns_rdataset_isassociated(&tat->sigrdataset)) {
+ dns_rdataset_disassociate(&tat->sigrdataset);
+ }
+ dns_view_detach(&tat->view);
+ isc_task_detach(&tat->task);
+ isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat));
+}
+
+struct dotat_arg {
+ dns_view_t *view;
+ isc_task_t *task;
+};
+
+/*%
+ * Prepare the QNAME for the TAT query to be sent by processing the trust
+ * anchors present at 'keynode' of 'keytable'. Store the result in 'dst' and
+ * the domain name which 'keynode' is associated with in 'origin'.
+ *
+ * A maximum of 12 key IDs can be reported in a single TAT query due to the
+ * 63-octet length limit for any single label in a domain name. If there are
+ * more than 12 keys configured at 'keynode', only the first 12 will be
+ * reported in the TAT query.
+ */
+static isc_result_t
+get_tat_qname(dns_name_t *target, dns_name_t *keyname, dns_keynode_t *keynode) {
+ dns_rdataset_t dsset;
+ unsigned int i, n = 0;
+ uint16_t ids[12];
+ isc_textregion_t r;
+ char label[64];
+ int m;
+
+ dns_rdataset_init(&dsset);
+ if (dns_keynode_dsset(keynode, &dsset)) {
+ isc_result_t result;
+
+ for (result = dns_rdataset_first(&dsset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&dsset))
+ {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_ds_t ds;
+
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&dsset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &ds, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (n < (sizeof(ids) / sizeof(ids[0]))) {
+ ids[n] = ds.key_tag;
+ n++;
+ }
+ }
+ dns_rdataset_disassociate(&dsset);
+ }
+
+ if (n == 0) {
+ return (DNS_R_EMPTYNAME);
+ }
+
+ if (n > 1) {
+ qsort(ids, n, sizeof(ids[0]), cid);
+ }
+
+ /*
+ * Encoded as "_ta-xxxx\(-xxxx\)*" where xxxx is the hex version of
+ * of the keyid.
+ */
+ label[0] = 0;
+ r.base = label;
+ r.length = sizeof(label);
+ m = snprintf(r.base, r.length, "_ta");
+ if (m < 0 || (unsigned)m > r.length) {
+ return (ISC_R_FAILURE);
+ }
+ isc_textregion_consume(&r, m);
+ for (i = 0; i < n; i++) {
+ m = snprintf(r.base, r.length, "-%04x", ids[i]);
+ if (m < 0 || (unsigned)m > r.length) {
+ return (ISC_R_FAILURE);
+ }
+ isc_textregion_consume(&r, m);
+ }
+
+ return (dns_name_fromstring2(target, label, keyname, 0, NULL));
+}
+
+static void
+tat_send(isc_task_t *task, isc_event_t *event) {
+ ns_tat_t *tat;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fdomain;
+ dns_name_t *domain;
+ dns_rdataset_t nameservers;
+ isc_result_t result;
+ dns_name_t *keyname;
+ dns_name_t *tatname;
+
+ INSIST(event != NULL && event->ev_type == NAMED_EVENT_TATSEND);
+ INSIST(event->ev_arg != NULL);
+
+ UNUSED(task);
+
+ tat = event->ev_arg;
+
+ keyname = dns_fixedname_name(&tat->keyname);
+ tatname = dns_fixedname_name(&tat->tatname);
+
+ dns_name_format(tatname, namebuf, sizeof(namebuf));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "%s: sending trust-anchor-telemetry query '%s/NULL'",
+ tat->view->name, namebuf);
+
+ /*
+ * TAT queries should be sent to the authoritative servers for a given
+ * zone. If this function is called for a keytable node corresponding
+ * to a locally served zone, calling dns_resolver_createfetch() with
+ * NULL 'domain' and 'nameservers' arguments will cause 'tatname' to be
+ * resolved locally, without sending any TAT queries upstream.
+ *
+ * Work around this issue by calling dns_view_findzonecut() first. If
+ * the zone is served locally, the NS RRset for the given domain name
+ * will be retrieved from local data; if it is not, the deepest zone
+ * cut we have for it will be retrieved from cache. In either case,
+ * passing the results to dns_resolver_createfetch() will prevent it
+ * from returning NXDOMAIN for 'tatname' while still allowing it to
+ * chase down any potential delegations returned by upstream servers in
+ * order to eventually find the destination host to send the TAT query
+ * to.
+ *
+ * After the dns_view_findzonecut() call, 'domain' will hold the
+ * deepest zone cut we can find for 'keyname' while 'nameservers' will
+ * hold the NS RRset at that zone cut.
+ */
+ domain = dns_fixedname_initname(&fdomain);
+ dns_rdataset_init(&nameservers);
+ result = dns_view_findzonecut(tat->view, keyname, domain, NULL, 0, 0,
+ true, true, &nameservers, NULL);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_resolver_createfetch(
+ tat->view->resolver, tatname, dns_rdatatype_null,
+ domain, &nameservers, NULL, NULL, 0, 0, 0, NULL,
+ tat->task, tat_done, tat, &tat->rdataset,
+ &tat->sigrdataset, &tat->fetch);
+ }
+
+ /*
+ * 'domain' holds the dns_name_t pointer inside a dst_key_t structure.
+ * dns_resolver_createfetch() creates its own copy of 'domain' if it
+ * succeeds. Thus, 'domain' is not freed here.
+ *
+ * Even if dns_view_findzonecut() returned something else than
+ * ISC_R_SUCCESS, it still could have associated 'nameservers'.
+ * dns_resolver_createfetch() creates its own copy of 'nameservers' if
+ * it succeeds. Thus, we need to check whether 'nameservers' is
+ * associated and release it if it is.
+ */
+ if (dns_rdataset_isassociated(&nameservers)) {
+ dns_rdataset_disassociate(&nameservers);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ dns_view_detach(&tat->view);
+ isc_task_detach(&tat->task);
+ isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat));
+ }
+ isc_event_free(&event);
+}
+
+static void
+dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, dns_name_t *keyname,
+ void *arg) {
+ struct dotat_arg *dotat_arg = arg;
+ isc_result_t result;
+ dns_view_t *view;
+ isc_task_t *task;
+ ns_tat_t *tat;
+ isc_event_t *event;
+
+ REQUIRE(keytable != NULL);
+ REQUIRE(keynode != NULL);
+ REQUIRE(dotat_arg != NULL);
+
+ view = dotat_arg->view;
+ task = dotat_arg->task;
+
+ tat = isc_mem_get(dotat_arg->view->mctx, sizeof(*tat));
+
+ tat->fetch = NULL;
+ tat->mctx = NULL;
+ tat->task = NULL;
+ tat->view = NULL;
+ dns_rdataset_init(&tat->rdataset);
+ dns_rdataset_init(&tat->sigrdataset);
+ dns_name_copy(keyname, dns_fixedname_initname(&tat->keyname));
+ result = get_tat_qname(dns_fixedname_initname(&tat->tatname), keyname,
+ keynode);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(dotat_arg->view->mctx, tat, sizeof(*tat));
+ return;
+ }
+ isc_mem_attach(dotat_arg->view->mctx, &tat->mctx);
+ isc_task_attach(task, &tat->task);
+ dns_view_attach(view, &tat->view);
+
+ /*
+ * We don't want to be holding the keytable lock when calling
+ * dns_view_findzonecut() as it creates a lock order loop so
+ * call dns_view_findzonecut() in a event handler.
+ *
+ * zone->lock (dns_zone_setviewcommit) while holding view->lock
+ * (dns_view_setviewcommit)
+ *
+ * keytable->lock (dns_keytable_find) while holding zone->lock
+ * (zone_asyncload)
+ *
+ * view->lock (dns_view_findzonecut) while holding keytable->lock
+ * (dns_keytable_forall)
+ */
+ event = isc_event_allocate(tat->mctx, keytable, NAMED_EVENT_TATSEND,
+ tat_send, tat, sizeof(isc_event_t));
+ isc_task_send(task, &event);
+}
+
+static void
+tat_timer_tick(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ named_server_t *server = (named_server_t *)event->ev_arg;
+ struct dotat_arg arg;
+ dns_view_t *view;
+ dns_keytable_t *secroots = NULL;
+
+ isc_event_free(&event);
+
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (!view->trust_anchor_telemetry || !view->enablevalidation) {
+ continue;
+ }
+
+ result = dns_view_getsecroots(view, &secroots);
+ if (result != ISC_R_SUCCESS) {
+ continue;
+ }
+
+ arg.view = view;
+ arg.task = task;
+ (void)dns_keytable_forall(secroots, dotat, &arg);
+ dns_keytable_detach(&secroots);
+ }
+}
+
+static void
+pps_timer_tick(isc_task_t *task, isc_event_t *event) {
+ static unsigned int oldrequests = 0;
+ unsigned int requests = atomic_load_relaxed(&ns_client_requests);
+
+ UNUSED(task);
+ isc_event_free(&event);
+
+ /*
+ * Don't worry about wrapping as the overflow result will be right.
+ */
+ dns_pps = (requests - oldrequests) / 1200;
+ oldrequests = requests;
+}
+
+/*
+ * Replace the current value of '*field', a dynamically allocated
+ * string or NULL, with a dynamically allocated copy of the
+ * null-terminated string pointed to by 'value', or NULL.
+ */
+static isc_result_t
+setstring(named_server_t *server, char **field, const char *value) {
+ char *copy;
+
+ if (value != NULL) {
+ copy = isc_mem_strdup(server->mctx, value);
+ } else {
+ copy = NULL;
+ }
+
+ if (*field != NULL) {
+ isc_mem_free(server->mctx, *field);
+ }
+
+ *field = copy;
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Replace the current value of '*field', a dynamically allocated
+ * string or NULL, with another dynamically allocated string
+ * or NULL if whether 'obj' is a string or void value, respectively.
+ */
+static isc_result_t
+setoptstring(named_server_t *server, char **field, const cfg_obj_t *obj) {
+ if (cfg_obj_isvoid(obj)) {
+ return (setstring(server, field, NULL));
+ } else {
+ return (setstring(server, field, cfg_obj_asstring(obj)));
+ }
+}
+
+static void
+set_limit(const cfg_obj_t **maps, const char *configname,
+ const char *description, isc_resource_t resourceid,
+ isc_resourcevalue_t defaultvalue) {
+ const cfg_obj_t *obj = NULL;
+ const char *resource;
+ isc_resourcevalue_t value;
+ isc_result_t result;
+
+ if (named_config_get(maps, configname, &obj) != ISC_R_SUCCESS) {
+ return;
+ }
+
+ if (cfg_obj_isstring(obj)) {
+ resource = cfg_obj_asstring(obj);
+ if (strcasecmp(resource, "unlimited") == 0) {
+ value = ISC_RESOURCE_UNLIMITED;
+ } else {
+ INSIST(strcasecmp(resource, "default") == 0);
+ value = defaultvalue;
+ }
+ } else {
+ value = cfg_obj_asuint64(obj);
+ }
+
+ result = isc_resource_setlimit(resourceid, value);
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
+ result == ISC_R_SUCCESS ? ISC_LOG_DEBUG(3) : ISC_LOG_WARNING,
+ "set maximum %s to %" PRIu64 ": %s", description, value,
+ isc_result_totext(result));
+}
+
+#define SETLIMIT(cfgvar, resource, description) \
+ set_limit(maps, cfgvar, description, isc_resource_##resource, \
+ named_g_init##resource)
+
+static void
+set_limits(const cfg_obj_t **maps) {
+ SETLIMIT("stacksize", stacksize, "stack size");
+ SETLIMIT("datasize", datasize, "data size");
+ SETLIMIT("coresize", coresize, "core size");
+ SETLIMIT("files", openfiles, "open files");
+}
+
+static void
+portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports,
+ bool positive) {
+ const cfg_listelt_t *element;
+
+ for (element = cfg_list_first(ports); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *obj = cfg_listelt_value(element);
+
+ if (cfg_obj_isuint32(obj)) {
+ in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
+
+ if (positive) {
+ isc_portset_add(portset, port);
+ } else {
+ isc_portset_remove(portset, port);
+ }
+ } else {
+ const cfg_obj_t *obj_loport, *obj_hiport;
+ in_port_t loport, hiport;
+
+ obj_loport = cfg_tuple_get(obj, "loport");
+ loport = (in_port_t)cfg_obj_asuint32(obj_loport);
+ obj_hiport = cfg_tuple_get(obj, "hiport");
+ hiport = (in_port_t)cfg_obj_asuint32(obj_hiport);
+
+ if (positive) {
+ isc_portset_addrange(portset, loport, hiport);
+ } else {
+ isc_portset_removerange(portset, loport,
+ hiport);
+ }
+ }
+ }
+}
+
+static isc_result_t
+removed(dns_zone_t *zone, void *uap) {
+ if (dns_zone_getview(zone) != uap) {
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed",
+ dns_zonetype_name(dns_zone_gettype(zone)));
+ return (ISC_R_SUCCESS);
+}
+
+static void
+cleanup_session_key(named_server_t *server, isc_mem_t *mctx) {
+ if (server->session_keyfile != NULL) {
+ isc_file_remove(server->session_keyfile);
+ isc_mem_free(mctx, server->session_keyfile);
+ server->session_keyfile = NULL;
+ }
+
+ if (server->session_keyname != NULL) {
+ if (dns_name_dynamic(server->session_keyname)) {
+ dns_name_free(server->session_keyname, mctx);
+ }
+ isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t));
+ server->session_keyname = NULL;
+ }
+
+ if (server->sessionkey != NULL) {
+ dst_key_free(&server->sessionkey);
+ }
+
+ server->session_keyalg = DST_ALG_UNKNOWN;
+ server->session_keybits = 0;
+}
+
+static isc_result_t
+generate_session_key(const char *filename, const char *keynamestr,
+ const dns_name_t *keyname, const char *algstr,
+ unsigned int algtype, uint16_t bits, isc_mem_t *mctx,
+ bool first_time, dst_key_t **keyp) {
+ isc_result_t result = ISC_R_SUCCESS;
+ dst_key_t *key = NULL;
+ isc_buffer_t key_txtbuffer;
+ isc_buffer_t key_rawbuffer;
+ char key_txtsecret[256];
+ char key_rawsecret[64];
+ isc_region_t key_rawregion;
+ FILE *fp = NULL;
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "generating session key for dynamic DNS");
+
+ /* generate key */
+ result = dst_key_generate(keyname, algtype, bits, 1, 0,
+ DNS_KEYPROTO_ANY, dns_rdataclass_in, mctx,
+ &key, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ /*
+ * Dump the key to the buffer for later use.
+ */
+ isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret));
+ CHECK(dst_key_tobuffer(key, &key_rawbuffer));
+
+ isc_buffer_usedregion(&key_rawbuffer, &key_rawregion);
+ isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret));
+ CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer));
+
+ /* Dump the key to the key file. */
+ fp = named_os_openfile(filename, S_IRUSR | S_IWUSR, first_time);
+ if (fp == NULL) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "could not create %s", filename);
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
+
+ fprintf(fp,
+ "key \"%s\" {\n"
+ "\talgorithm %s;\n"
+ "\tsecret \"%.*s\";\n};\n",
+ keynamestr, algstr, (int)isc_buffer_usedlength(&key_txtbuffer),
+ (char *)isc_buffer_base(&key_txtbuffer));
+
+ CHECK(isc_stdio_flush(fp));
+ result = isc_stdio_close(fp);
+ fp = NULL;
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ *keyp = key;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed to generate session key "
+ "for dynamic DNS: %s",
+ isc_result_totext(result));
+ if (fp != NULL) {
+ (void)isc_stdio_close(fp);
+ (void)isc_file_remove(filename);
+ }
+ if (key != NULL) {
+ dst_key_free(&key);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+configure_session_key(const cfg_obj_t **maps, named_server_t *server,
+ isc_mem_t *mctx, bool first_time) {
+ const char *keyfile, *keynamestr, *algstr;
+ unsigned int algtype;
+ dns_fixedname_t fname;
+ dns_name_t *keyname;
+ const dns_name_t *algname;
+ isc_buffer_t buffer;
+ uint16_t bits;
+ const cfg_obj_t *obj;
+ bool need_deleteold = false;
+ bool need_createnew = false;
+ isc_result_t result;
+
+ obj = NULL;
+ result = named_config_get(maps, "session-keyfile", &obj);
+ if (result == ISC_R_SUCCESS) {
+ if (cfg_obj_isvoid(obj)) {
+ keyfile = NULL; /* disable it */
+ } else {
+ keyfile = cfg_obj_asstring(obj);
+ }
+ } else {
+ keyfile = named_g_defaultsessionkeyfile;
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "session-keyname", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ keynamestr = cfg_obj_asstring(obj);
+ isc_buffer_constinit(&buffer, keynamestr, strlen(keynamestr));
+ isc_buffer_add(&buffer, strlen(keynamestr));
+ keyname = dns_fixedname_initname(&fname);
+ result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "session-keyalg", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ algstr = cfg_obj_asstring(obj);
+ algname = NULL;
+ result = named_config_getkeyalgorithm2(algstr, &algname, &algtype,
+ &bits);
+ if (result != ISC_R_SUCCESS) {
+ const char *s = " (keeping current key)";
+
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
+ "session-keyalg: "
+ "unsupported or unknown algorithm '%s'%s",
+ algstr, server->session_keyfile != NULL ? s : "");
+ return (result);
+ }
+
+ /* See if we need to (re)generate a new key. */
+ if (keyfile == NULL) {
+ if (server->session_keyfile != NULL) {
+ need_deleteold = true;
+ }
+ } else if (server->session_keyfile == NULL) {
+ need_createnew = true;
+ } else if (strcmp(keyfile, server->session_keyfile) != 0 ||
+ !dns_name_equal(server->session_keyname, keyname) ||
+ server->session_keyalg != algtype ||
+ server->session_keybits != bits)
+ {
+ need_deleteold = true;
+ need_createnew = true;
+ }
+
+ if (need_deleteold) {
+ INSIST(server->session_keyfile != NULL);
+ INSIST(server->session_keyname != NULL);
+ INSIST(server->sessionkey != NULL);
+
+ cleanup_session_key(server, mctx);
+ }
+
+ if (need_createnew) {
+ INSIST(server->sessionkey == NULL);
+ INSIST(server->session_keyfile == NULL);
+ INSIST(server->session_keyname == NULL);
+ INSIST(server->session_keyalg == DST_ALG_UNKNOWN);
+ INSIST(server->session_keybits == 0);
+
+ server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t));
+ dns_name_init(server->session_keyname, NULL);
+ dns_name_dup(keyname, mctx, server->session_keyname);
+
+ server->session_keyfile = isc_mem_strdup(mctx, keyfile);
+
+ server->session_keyalg = algtype;
+ server->session_keybits = bits;
+
+ CHECK(generate_session_key(keyfile, keynamestr, keyname, algstr,
+ algtype, bits, mctx, first_time,
+ &server->sessionkey));
+ }
+
+ return (result);
+
+cleanup:
+ cleanup_session_key(server, mctx);
+ return (result);
+}
+
+#ifndef HAVE_LMDB
+static isc_result_t
+count_newzones(dns_view_t *view, ns_cfgctx_t *nzcfg, int *num_zonesp) {
+ isc_result_t result;
+
+ /* The new zone file may not exist. That is OK. */
+ if (!isc_file_exists(view->new_zone_file)) {
+ *num_zonesp = 0;
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * In the case of NZF files, we also parse the configuration in
+ * the file at this stage.
+ *
+ * This may be called in multiple views, so we reset
+ * the parser each time.
+ */
+ cfg_parser_reset(named_g_addparser);
+ result = cfg_parse_file(named_g_addparser, view->new_zone_file,
+ &cfg_type_addzoneconf, &nzcfg->nzf_config);
+ if (result == ISC_R_SUCCESS) {
+ int num_zones;
+
+ num_zones = count_zones(nzcfg->nzf_config);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "NZF file '%s' contains %d zones",
+ view->new_zone_file, num_zones);
+ if (num_zonesp != NULL) {
+ *num_zonesp = num_zones;
+ }
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "Error parsing NZF file '%s': %s",
+ view->new_zone_file, isc_result_totext(result));
+ }
+
+ return (result);
+}
+
+#else /* HAVE_LMDB */
+
+static isc_result_t
+count_newzones(dns_view_t *view, ns_cfgctx_t *nzcfg, int *num_zonesp) {
+ isc_result_t result;
+ int n;
+
+ UNUSED(nzcfg);
+
+ REQUIRE(num_zonesp != NULL);
+
+ LOCK(&view->new_zone_lock);
+
+ CHECK(migrate_nzf(view));
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "loading NZD zone count from '%s' "
+ "for view '%s'",
+ view->new_zone_db, view->name);
+
+ CHECK(nzd_count(view, &n));
+
+ *num_zonesp = n;
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "NZD database '%s' contains %d zones", view->new_zone_db,
+ n);
+
+cleanup:
+ if (result != ISC_R_SUCCESS) {
+ *num_zonesp = 0;
+ }
+
+ UNLOCK(&view->new_zone_lock);
+
+ return (ISC_R_SUCCESS);
+}
+
+#endif /* HAVE_LMDB */
+
+static isc_result_t
+setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
+ cfg_parser_t *conf_parser, cfg_aclconfctx_t *actx,
+ int *num_zones) {
+ isc_result_t result = ISC_R_SUCCESS;
+ bool allow = false;
+ ns_cfgctx_t *nzcfg = NULL;
+ const cfg_obj_t *maps[4];
+ const cfg_obj_t *options = NULL, *voptions = NULL;
+ const cfg_obj_t *nz = NULL;
+ const cfg_obj_t *nzdir = NULL;
+ const char *dir = NULL;
+ const cfg_obj_t *obj = NULL;
+ int i = 0;
+ uint64_t mapsize = 0ULL;
+
+ REQUIRE(config != NULL);
+
+ if (vconfig != NULL) {
+ voptions = cfg_tuple_get(vconfig, "options");
+ }
+ if (voptions != NULL) {
+ maps[i++] = voptions;
+ }
+ result = cfg_map_get(config, "options", &options);
+ if (result == ISC_R_SUCCESS) {
+ maps[i++] = options;
+ }
+ maps[i++] = named_g_defaults;
+ maps[i] = NULL;
+
+ result = named_config_get(maps, "allow-new-zones", &nz);
+ if (result == ISC_R_SUCCESS) {
+ allow = cfg_obj_asboolean(nz);
+ }
+ result = named_config_get(maps, "new-zones-directory", &nzdir);
+ if (result == ISC_R_SUCCESS) {
+ dir = cfg_obj_asstring(nzdir);
+ result = isc_file_isdirectory(dir);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "invalid new-zones-directory %s: %s", dir,
+ isc_result_totext(result));
+ return (result);
+ }
+ if (!isc_file_isdirwritable(dir)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "new-zones-directory '%s' "
+ "is not writable",
+ dir);
+ return (ISC_R_NOPERM);
+ }
+
+ dns_view_setnewzonedir(view, dir);
+ }
+
+#ifdef HAVE_LMDB
+ result = named_config_get(maps, "lmdb-mapsize", &obj);
+ if (result == ISC_R_SUCCESS && obj != NULL) {
+ mapsize = cfg_obj_asuint64(obj);
+ if (mapsize < (1ULL << 20)) { /* 1 megabyte */
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
+ "'lmdb-mapsize "
+ "%" PRId64 "' "
+ "is too small",
+ mapsize);
+ return (ISC_R_FAILURE);
+ } else if (mapsize > (1ULL << 40)) { /* 1 terabyte */
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
+ "'lmdb-mapsize "
+ "%" PRId64 "' "
+ "is too large",
+ mapsize);
+ return (ISC_R_FAILURE);
+ }
+ }
+#else /* ifdef HAVE_LMDB */
+ UNUSED(obj);
+#endif /* HAVE_LMDB */
+
+ /*
+ * A non-empty catalog-zones statement implies allow-new-zones
+ */
+ if (!allow) {
+ const cfg_obj_t *cz = NULL;
+ result = named_config_get(maps, "catalog-zones", &cz);
+ if (result == ISC_R_SUCCESS) {
+ const cfg_listelt_t *e =
+ cfg_list_first(cfg_tuple_get(cz, "zone list"));
+ if (e != NULL) {
+ allow = true;
+ }
+ }
+ }
+
+ if (!allow) {
+ dns_view_setnewzones(view, false, NULL, NULL, 0ULL);
+ if (num_zones != NULL) {
+ *num_zones = 0;
+ }
+ return (ISC_R_SUCCESS);
+ }
+
+ nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg));
+
+ /*
+ * We attach the parser that was used for config as well
+ * as the one that will be used for added zones, to avoid
+ * a shutdown race later.
+ */
+ memset(nzcfg, 0, sizeof(*nzcfg));
+ cfg_parser_attach(conf_parser, &nzcfg->conf_parser);
+ cfg_parser_attach(named_g_addparser, &nzcfg->add_parser);
+ isc_mem_attach(view->mctx, &nzcfg->mctx);
+ cfg_aclconfctx_attach(actx, &nzcfg->actx);
+
+ result = dns_view_setnewzones(view, true, nzcfg, newzone_cfgctx_destroy,
+ mapsize);
+ if (result != ISC_R_SUCCESS) {
+ dns_view_setnewzones(view, false, NULL, NULL, 0ULL);
+ return (result);
+ }
+
+ cfg_obj_attach(config, &nzcfg->config);
+ if (vconfig != NULL) {
+ cfg_obj_attach(vconfig, &nzcfg->vconfig);
+ }
+
+ result = count_newzones(view, nzcfg, num_zones);
+ return (result);
+}
+
+static void
+configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig,
+ dns_view_t *view) {
+ const char *zname;
+ dns_fixedname_t fixorigin;
+ dns_name_t *origin;
+ isc_result_t result2;
+ dns_view_t *pview = NULL;
+ dns_zone_t *zone = NULL;
+
+ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+ origin = dns_fixedname_initname(&fixorigin);
+
+ result2 = dns_name_fromstring(origin, zname, 0, NULL);
+ if (result2 != ISC_R_SUCCESS) {
+ return;
+ }
+
+ result2 = dns_viewlist_find(&named_g_server->viewlist, view->name,
+ view->rdclass, &pview);
+ if (result2 != ISC_R_SUCCESS) {
+ return;
+ }
+
+ result2 = dns_view_findzone(pview, origin, &zone);
+ if (result2 != ISC_R_SUCCESS) {
+ dns_view_detach(&pview);
+ return;
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ dns_zone_setviewcommit(zone);
+ } else {
+ dns_zone_setviewrevert(zone);
+ }
+
+ dns_zone_detach(&zone);
+ dns_view_detach(&pview);
+}
+
+#ifndef HAVE_LMDB
+
+static isc_result_t
+configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
+ isc_mem_t *mctx, cfg_aclconfctx_t *actx) {
+ isc_result_t result;
+ ns_cfgctx_t *nzctx;
+ const cfg_obj_t *zonelist;
+ const cfg_listelt_t *element;
+
+ nzctx = view->new_zone_config;
+ if (nzctx == NULL || nzctx->nzf_config == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "loading additional zones for view '%s'", view->name);
+
+ zonelist = NULL;
+ cfg_map_get(nzctx->nzf_config, "zone", &zonelist);
+
+ for (element = cfg_list_first(zonelist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *zconfig = cfg_listelt_value(element);
+ CHECK(configure_zone(config, zconfig, vconfig, mctx, view,
+ &named_g_server->viewlist,
+ &named_g_server->kasplist, actx, true,
+ false, false));
+ }
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ for (element = cfg_list_first(zonelist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *zconfig = cfg_listelt_value(element);
+ configure_zone_setviewcommit(result, zconfig, view);
+ }
+
+ return (result);
+}
+
+#else /* HAVE_LMDB */
+
+static isc_result_t
+data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text,
+ cfg_obj_t **zoneconfig) {
+ isc_result_t result;
+ const char *zone_name;
+ size_t zone_name_len;
+ const char *zone_config;
+ size_t zone_config_len;
+ cfg_obj_t *zoneconf = NULL;
+ char bufname[DNS_NAME_FORMATSIZE];
+
+ REQUIRE(view != NULL);
+ REQUIRE(key != NULL);
+ REQUIRE(data != NULL);
+ REQUIRE(text != NULL);
+ REQUIRE(zoneconfig != NULL && *zoneconfig == NULL);
+
+ if (*text == NULL) {
+ isc_buffer_allocate(view->mctx, text, 256);
+ } else {
+ isc_buffer_clear(*text);
+ }
+
+ zone_name = (const char *)key->mv_data;
+ zone_name_len = key->mv_size;
+ INSIST(zone_name != NULL && zone_name_len > 0);
+
+ zone_config = (const char *)data->mv_data;
+ zone_config_len = data->mv_size;
+ INSIST(zone_config != NULL && zone_config_len > 0);
+
+ /* zone zonename { config; }; */
+ result = isc_buffer_reserve(text, 6 + zone_name_len + 2 +
+ zone_config_len + 2);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ CHECK(putstr(text, "zone \""));
+ CHECK(putmem(text, (const void *)zone_name, zone_name_len));
+ CHECK(putstr(text, "\" "));
+ CHECK(putmem(text, (const void *)zone_config, zone_config_len));
+ CHECK(putstr(text, ";\n"));
+
+ snprintf(bufname, sizeof(bufname), "%.*s", (int)zone_name_len,
+ zone_name);
+
+ cfg_parser_reset(named_g_addparser);
+ result = cfg_parse_buffer(named_g_addparser, *text, bufname, 0,
+ &cfg_type_addzoneconf, 0, &zoneconf);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "parsing config for zone '%.*s' in "
+ "NZD database '%s' failed",
+ (int)zone_name_len, zone_name, view->new_zone_db);
+ goto cleanup;
+ }
+
+ *zoneconfig = zoneconf;
+ zoneconf = NULL;
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (zoneconf != NULL) {
+ cfg_obj_destroy(named_g_addparser, &zoneconf);
+ }
+
+ return (result);
+}
+
+/*%
+ * Prototype for a callback which can be used with for_all_newzone_cfgs().
+ */
+typedef isc_result_t (*newzone_cfg_cb_t)(const cfg_obj_t *zconfig,
+ cfg_obj_t *config, cfg_obj_t *vconfig,
+ isc_mem_t *mctx, dns_view_t *view,
+ cfg_aclconfctx_t *actx);
+
+/*%
+ * For each zone found in a NZD opened by the caller, create an object
+ * representing its configuration and invoke "callback" with the created
+ * object, "config", "vconfig", "mctx", "view" and "actx" as arguments (all
+ * these are non-global variables required to invoke configure_zone()).
+ * Immediately interrupt processing if an error is encountered while
+ * transforming NZD data into a zone configuration object or if "callback"
+ * returns an error.
+ *
+ * Caller must hold 'view->new_zone_lock'.
+ */
+static isc_result_t
+for_all_newzone_cfgs(newzone_cfg_cb_t callback, cfg_obj_t *config,
+ cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
+ cfg_aclconfctx_t *actx, MDB_txn *txn, MDB_dbi dbi) {
+ const cfg_obj_t *zconfig, *zlist;
+ isc_result_t result = ISC_R_SUCCESS;
+ cfg_obj_t *zconfigobj = NULL;
+ isc_buffer_t *text = NULL;
+ MDB_cursor *cursor = NULL;
+ MDB_val data, key;
+ int status;
+
+ status = mdb_cursor_open(txn, dbi, &cursor);
+ if (status != MDB_SUCCESS) {
+ return (ISC_R_FAILURE);
+ }
+
+ for (status = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
+ status == MDB_SUCCESS;
+ status = mdb_cursor_get(cursor, &key, &data, MDB_NEXT))
+ {
+ /*
+ * Create a configuration object from data fetched from NZD.
+ */
+ result = data_to_cfg(view, &key, &data, &text, &zconfigobj);
+ if (result != ISC_R_SUCCESS) {
+ break;
+ }
+
+ /*
+ * Extract zone configuration from configuration object.
+ */
+ zlist = NULL;
+ result = cfg_map_get(zconfigobj, "zone", &zlist);
+ if (result != ISC_R_SUCCESS) {
+ break;
+ } else if (!cfg_obj_islist(zlist)) {
+ result = ISC_R_FAILURE;
+ break;
+ }
+ zconfig = cfg_listelt_value(cfg_list_first(zlist));
+
+ /*
+ * Invoke callback.
+ */
+ result = callback(zconfig, config, vconfig, mctx, view, actx);
+ if (result != ISC_R_SUCCESS) {
+ break;
+ }
+
+ /*
+ * Destroy the configuration object created in this iteration.
+ */
+ cfg_obj_destroy(named_g_addparser, &zconfigobj);
+ }
+
+ if (text != NULL) {
+ isc_buffer_free(&text);
+ }
+ if (zconfigobj != NULL) {
+ cfg_obj_destroy(named_g_addparser, &zconfigobj);
+ }
+ mdb_cursor_close(cursor);
+
+ return (result);
+}
+
+/*%
+ * Attempt to configure a zone found in NZD and return the result.
+ */
+static isc_result_t
+configure_newzone(const cfg_obj_t *zconfig, cfg_obj_t *config,
+ cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
+ cfg_aclconfctx_t *actx) {
+ return (configure_zone(
+ config, zconfig, vconfig, mctx, view, &named_g_server->viewlist,
+ &named_g_server->kasplist, actx, true, false, false));
+}
+
+/*%
+ * Revert new view assignment for a zone found in NZD.
+ */
+static isc_result_t
+configure_newzone_revert(const cfg_obj_t *zconfig, cfg_obj_t *config,
+ cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
+ cfg_aclconfctx_t *actx) {
+ UNUSED(config);
+ UNUSED(vconfig);
+ UNUSED(mctx);
+ UNUSED(actx);
+
+ configure_zone_setviewcommit(ISC_R_FAILURE, zconfig, view);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
+ isc_mem_t *mctx, cfg_aclconfctx_t *actx) {
+ isc_result_t result;
+ MDB_txn *txn = NULL;
+ MDB_dbi dbi;
+
+ if (view->new_zone_config == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ LOCK(&view->new_zone_lock);
+
+ result = nzd_open(view, MDB_RDONLY, &txn, &dbi);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK(&view->new_zone_lock);
+ return (ISC_R_SUCCESS);
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "loading NZD configs from '%s' "
+ "for view '%s'",
+ view->new_zone_db, view->name);
+
+ result = for_all_newzone_cfgs(configure_newzone, config, vconfig, mctx,
+ view, actx, txn, dbi);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * An error was encountered while attempting to configure zones
+ * found in NZD. As this error may have been caused by a
+ * configure_zone() failure, try restoring a sane configuration
+ * by reattaching all zones found in NZD to the old view. If
+ * this also fails, too bad, there is nothing more we can do in
+ * terms of trying to make things right.
+ */
+ (void)for_all_newzone_cfgs(configure_newzone_revert, config,
+ vconfig, mctx, view, actx, txn, dbi);
+ }
+
+ (void)nzd_close(&txn, false);
+
+ UNLOCK(&view->new_zone_lock);
+
+ return (result);
+}
+
+static isc_result_t
+get_newzone_config(dns_view_t *view, const char *zonename,
+ cfg_obj_t **zoneconfig) {
+ isc_result_t result;
+ int status;
+ cfg_obj_t *zoneconf = NULL;
+ isc_buffer_t *text = NULL;
+ MDB_txn *txn = NULL;
+ MDB_dbi dbi;
+ MDB_val key, data;
+ char zname[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_buffer_t b;
+
+ INSIST(zoneconfig != NULL && *zoneconfig == NULL);
+
+ LOCK(&view->new_zone_lock);
+
+ CHECK(nzd_open(view, MDB_RDONLY, &txn, &dbi));
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "loading NZD config from '%s' "
+ "for zone '%s'",
+ view->new_zone_db, zonename);
+
+ /* Normalize zone name */
+ isc_buffer_constinit(&b, zonename, strlen(zonename));
+ isc_buffer_add(&b, strlen(zonename));
+ name = dns_fixedname_initname(&fname);
+ CHECK(dns_name_fromtext(name, &b, dns_rootname, DNS_NAME_DOWNCASE,
+ NULL));
+ dns_name_format(name, zname, sizeof(zname));
+
+ key.mv_data = zname;
+ key.mv_size = strlen(zname);
+
+ status = mdb_get(txn, dbi, &key, &data);
+ if (status != MDB_SUCCESS) {
+ CHECK(ISC_R_FAILURE);
+ }
+
+ CHECK(data_to_cfg(view, &key, &data, &text, &zoneconf));
+
+ *zoneconfig = zoneconf;
+ zoneconf = NULL;
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ (void)nzd_close(&txn, false);
+
+ UNLOCK(&view->new_zone_lock);
+
+ if (zoneconf != NULL) {
+ cfg_obj_destroy(named_g_addparser, &zoneconf);
+ }
+ if (text != NULL) {
+ isc_buffer_free(&text);
+ }
+
+ return (result);
+}
+
+#endif /* HAVE_LMDB */
+
+static int
+count_zones(const cfg_obj_t *conf) {
+ const cfg_obj_t *zonelist = NULL;
+ const cfg_listelt_t *element;
+ int n = 0;
+
+ REQUIRE(conf != NULL);
+
+ cfg_map_get(conf, "zone", &zonelist);
+ for (element = cfg_list_first(zonelist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ n++;
+ }
+
+ return (n);
+}
+
+static isc_result_t
+check_lockfile(named_server_t *server, const cfg_obj_t *config,
+ bool first_time) {
+ isc_result_t result;
+ const char *filename = NULL;
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *options;
+ const cfg_obj_t *obj;
+ int i;
+
+ i = 0;
+ options = NULL;
+ result = cfg_map_get(config, "options", &options);
+ if (result == ISC_R_SUCCESS) {
+ maps[i++] = options;
+ }
+ maps[i++] = named_g_defaults;
+ maps[i] = NULL;
+
+ obj = NULL;
+ (void)named_config_get(maps, "lock-file", &obj);
+
+ if (!first_time) {
+ if (obj != NULL && !cfg_obj_isstring(obj) &&
+ server->lockfile != NULL &&
+ strcmp(cfg_obj_asstring(obj), server->lockfile) != 0)
+ {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "changing 'lock-file' "
+ "has no effect until the "
+ "server is restarted");
+ }
+
+ return (ISC_R_SUCCESS);
+ }
+
+ if (obj != NULL) {
+ if (cfg_obj_isvoid(obj)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
+ "skipping lock-file check ");
+ return (ISC_R_SUCCESS);
+ } else if (named_g_forcelock) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "'lock-file' has no effect "
+ "because the server was run with -X");
+ server->lockfile = isc_mem_strdup(
+ server->mctx, named_g_defaultlockfile);
+ } else {
+ filename = cfg_obj_asstring(obj);
+ server->lockfile = isc_mem_strdup(server->mctx,
+ filename);
+ }
+
+ if (server->lockfile == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+ }
+
+ if (named_g_forcelock && named_g_defaultlockfile != NULL) {
+ INSIST(server->lockfile == NULL);
+ server->lockfile = isc_mem_strdup(server->mctx,
+ named_g_defaultlockfile);
+ }
+
+ if (server->lockfile == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ if (named_os_issingleton(server->lockfile)) {
+ return (ISC_R_SUCCESS);
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "could not lock %s; another named "
+ "process may be running",
+ server->lockfile);
+ return (ISC_R_FAILURE);
+}
+
+static isc_result_t
+load_configuration(const char *filename, named_server_t *server,
+ bool first_time) {
+ cfg_obj_t *config = NULL, *bindkeys = NULL;
+ cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL;
+ const cfg_listelt_t *element;
+ const cfg_obj_t *builtin_views;
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *obj;
+ const cfg_obj_t *options;
+ const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports;
+ const cfg_obj_t *kasps;
+ dns_kasp_t *kasp = NULL;
+ dns_kasp_t *kasp_next = NULL;
+ dns_kasp_t *default_kasp = NULL;
+ dns_kasplist_t tmpkasplist, kasplist;
+ const cfg_obj_t *views;
+ dns_view_t *view = NULL;
+ dns_view_t *view_next = NULL;
+ dns_viewlist_t tmpviewlist;
+ dns_viewlist_t viewlist, builtin_viewlist;
+ in_port_t listen_port, udpport_low, udpport_high;
+ int i, backlog;
+ int num_zones = 0;
+ bool exclusive = false;
+ isc_interval_t interval;
+ isc_logconfig_t *logc = NULL;
+ isc_portset_t *v4portset = NULL;
+ isc_portset_t *v6portset = NULL;
+ isc_result_t result, tresult;
+ uint32_t heartbeat_interval;
+ uint32_t interface_interval;
+ uint32_t udpsize;
+ uint32_t transfer_message_size;
+ uint32_t recv_tcp_buffer_size;
+ uint32_t send_tcp_buffer_size;
+ uint32_t recv_udp_buffer_size;
+ uint32_t send_udp_buffer_size;
+ named_cache_t *nsc;
+ named_cachelist_t cachelist, tmpcachelist;
+ ns_altsecret_t *altsecret;
+ ns_altsecretlist_t altsecrets, tmpaltsecrets;
+ uint32_t softquota = 0;
+ uint32_t max;
+ uint64_t initial, idle, keepalive, advertised;
+ bool loadbalancesockets;
+ dns_aclenv_t *env =
+ ns_interfacemgr_getaclenv(named_g_server->interfacemgr);
+
+ ISC_LIST_INIT(kasplist);
+ ISC_LIST_INIT(viewlist);
+ ISC_LIST_INIT(builtin_viewlist);
+ ISC_LIST_INIT(cachelist);
+ ISC_LIST_INIT(altsecrets);
+
+ /* Create the ACL configuration context */
+ if (named_g_aclconfctx != NULL) {
+ cfg_aclconfctx_detach(&named_g_aclconfctx);
+ }
+ CHECK(cfg_aclconfctx_create(named_g_mctx, &named_g_aclconfctx));
+
+ /*
+ * Shut down all dyndb instances.
+ */
+ dns_dyndb_cleanup(false);
+
+ /*
+ * Parse the global default pseudo-config file.
+ */
+ if (first_time) {
+ result = named_config_parsedefaults(named_g_parser,
+ &named_g_config);
+ if (result != ISC_R_SUCCESS) {
+ named_main_earlyfatal("unable to load "
+ "internal defaults: %s",
+ isc_result_totext(result));
+ }
+ RUNTIME_CHECK(cfg_map_get(named_g_config, "options",
+ &named_g_defaults) == ISC_R_SUCCESS);
+ }
+
+ /*
+ * Parse the configuration file using the new config code.
+ */
+ config = NULL;
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "loading configuration from '%s'", filename);
+ CHECK(cfg_parser_create(named_g_mctx, named_g_lctx, &conf_parser));
+ cfg_parser_setcallback(conf_parser, directory_callback, NULL);
+ result = cfg_parse_file(conf_parser, filename, &cfg_type_namedconf,
+ &config);
+
+ CHECK(result);
+
+ /*
+ * Check the validity of the configuration.
+ *
+ * (Ignore plugin parameters for now; they will be
+ * checked later when the modules are actually loaded and
+ * registered.)
+ */
+ CHECK(bind9_check_namedconf(config, false, false, named_g_lctx,
+ named_g_mctx));
+
+ /* Let's recreate the TLS context cache */
+ if (server->tlsctx_server_cache != NULL) {
+ isc_tlsctx_cache_detach(&server->tlsctx_server_cache);
+ }
+
+ isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_server_cache);
+
+ if (server->tlsctx_client_cache != NULL) {
+ isc_tlsctx_cache_detach(&server->tlsctx_client_cache);
+ }
+
+ isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_client_cache);
+
+ dns_zonemgr_set_tlsctx_cache(server->zonemgr,
+ server->tlsctx_client_cache);
+
+ /*
+ * Fill in the maps array, used for resolving defaults.
+ */
+ i = 0;
+ options = NULL;
+ result = cfg_map_get(config, "options", &options);
+ if (result == ISC_R_SUCCESS) {
+ maps[i++] = options;
+ }
+ maps[i++] = named_g_defaults;
+ maps[i] = NULL;
+
+#if HAVE_LIBNGHTTP2
+ obj = NULL;
+ result = named_config_get(maps, "http-port", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ named_g_httpport = (in_port_t)cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "https-port", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ named_g_httpsport = (in_port_t)cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "http-listener-clients", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ named_g_http_listener_clients = cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "http-streams-per-connection", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ named_g_http_streams_per_conn = cfg_obj_asuint32(obj);
+#endif
+
+ /*
+ * If bind.keys exists, load it. If "dnssec-validation auto"
+ * is turned on, the root key found there will be used as a
+ * default trust anchor.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "bindkeys-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->bindkeysfile, cfg_obj_asstring(obj)),
+ "strdup");
+ INSIST(server->bindkeysfile != NULL);
+
+ if (access(server->bindkeysfile, R_OK) == 0) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "reading built-in trust anchors "
+ "from file '%s'",
+ server->bindkeysfile);
+
+ CHECK(cfg_parser_create(named_g_mctx, named_g_lctx,
+ &bindkeys_parser));
+
+ result = cfg_parse_file(bindkeys_parser, server->bindkeysfile,
+ &cfg_type_bindkeys, &bindkeys);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "unable to parse '%s' error '%s'; using "
+ "built-in keys instead",
+ server->bindkeysfile,
+ isc_result_totext(result));
+ }
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "unable to open '%s'; using built-in keys "
+ "instead",
+ server->bindkeysfile);
+ }
+
+ /* Ensure exclusive access to configuration data. */
+ if (!exclusive) {
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ exclusive = true;
+ }
+
+ /*
+ * Set process limits, which (usually) needs to be done as root.
+ */
+ set_limits(maps);
+
+ /*
+ * Check the process lockfile.
+ */
+ CHECK(check_lockfile(server, config, first_time));
+
+#if defined(HAVE_GEOIP2)
+ /*
+ * Release any previously opened GeoIP2 databases.
+ */
+ named_geoip_unload();
+
+ /*
+ * Initialize GeoIP databases from the configured location.
+ * This should happen before configuring any ACLs, so that we
+ * know what databases are available and can reject any GeoIP
+ * ACLs that can't work.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "geoip-directory", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isstring(obj)) {
+ char *dir;
+ DE_CONST(cfg_obj_asstring(obj), dir);
+ named_geoip_load(dir);
+ }
+ named_g_aclconfctx->geoip = named_g_geoip;
+#endif /* HAVE_GEOIP2 */
+
+ /*
+ * Configure various server options.
+ */
+ configure_server_quota(maps, "transfers-out",
+ &server->sctx->xfroutquota);
+ configure_server_quota(maps, "tcp-clients", &server->sctx->tcpquota);
+ configure_server_quota(maps, "recursive-clients",
+ &server->sctx->recursionquota);
+ configure_server_quota(maps, "update-quota", &server->sctx->updquota);
+
+ max = isc_quota_getmax(&server->sctx->recursionquota);
+ if (max > 1000) {
+ unsigned margin = ISC_MAX(100, named_g_cpus + 1);
+ if (margin + 100 > max) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "'recursive-clients %d' too low when "
+ "running with %d worker threads",
+ max, named_g_cpus);
+ CHECK(ISC_R_RANGE);
+ }
+ softquota = max - margin;
+ } else {
+ softquota = (max * 90) / 100;
+ }
+
+ isc_quota_soft(&server->sctx->recursionquota, softquota);
+
+ /*
+ * Set "blackhole". Only legal at options level; there is
+ * no default.
+ */
+ CHECK(configure_view_acl(NULL, config, NULL, "blackhole", NULL,
+ named_g_aclconfctx, named_g_mctx,
+ &server->sctx->blackholeacl));
+ if (server->sctx->blackholeacl != NULL) {
+ dns_dispatchmgr_setblackhole(named_g_dispatchmgr,
+ server->sctx->blackholeacl);
+ }
+
+ /*
+ * Set "keep-response-order". Only legal at options or
+ * global defaults level.
+ */
+ CHECK(configure_view_acl(NULL, config, named_g_config,
+ "keep-response-order", NULL,
+ named_g_aclconfctx, named_g_mctx,
+ &server->sctx->keepresporder));
+
+ obj = NULL;
+ result = named_config_get(maps, "match-mapped-addresses", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ env->match_mapped = cfg_obj_asboolean(obj);
+
+ CHECKM(named_statschannels_configure(named_g_server, config,
+ named_g_aclconfctx),
+ "configuring statistics server(s)");
+
+ /*
+ * Configure the network manager
+ */
+ obj = NULL;
+ result = named_config_get(maps, "tcp-initial-timeout", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ initial = cfg_obj_asuint32(obj) * 100;
+ if (initial > MAX_INITIAL_TIMEOUT) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "tcp-initial-timeout value is out of range: "
+ "lowering to %" PRIu32,
+ MAX_INITIAL_TIMEOUT / 100);
+ initial = MAX_INITIAL_TIMEOUT;
+ } else if (initial < MIN_INITIAL_TIMEOUT) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "tcp-initial-timeout value is out of range: "
+ "raising to %" PRIu32,
+ MIN_INITIAL_TIMEOUT / 100);
+ initial = MIN_INITIAL_TIMEOUT;
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "tcp-idle-timeout", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ idle = cfg_obj_asuint32(obj) * 100;
+ if (idle > MAX_IDLE_TIMEOUT) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "tcp-idle-timeout value is out of range: "
+ "lowering to %" PRIu32,
+ MAX_IDLE_TIMEOUT / 100);
+ idle = MAX_IDLE_TIMEOUT;
+ } else if (idle < MIN_IDLE_TIMEOUT) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "tcp-idle-timeout value is out of range: "
+ "raising to %" PRIu32,
+ MIN_IDLE_TIMEOUT / 100);
+ idle = MIN_IDLE_TIMEOUT;
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "tcp-keepalive-timeout", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ keepalive = cfg_obj_asuint32(obj) * 100;
+ if (keepalive > MAX_KEEPALIVE_TIMEOUT) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "tcp-keepalive-timeout value is out of range: "
+ "lowering to %" PRIu32,
+ MAX_KEEPALIVE_TIMEOUT / 100);
+ keepalive = MAX_KEEPALIVE_TIMEOUT;
+ } else if (keepalive < MIN_KEEPALIVE_TIMEOUT) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "tcp-keepalive-timeout value is out of range: "
+ "raising to %" PRIu32,
+ MIN_KEEPALIVE_TIMEOUT / 100);
+ keepalive = MIN_KEEPALIVE_TIMEOUT;
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "tcp-advertised-timeout", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ advertised = cfg_obj_asuint32(obj) * 100;
+ if (advertised > MAX_ADVERTISED_TIMEOUT) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "tcp-advertized-timeout value is out of range: "
+ "lowering to %" PRIu32,
+ MAX_ADVERTISED_TIMEOUT / 100);
+ advertised = MAX_ADVERTISED_TIMEOUT;
+ }
+
+ isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive,
+ advertised);
+
+#define CAP_IF_NOT_ZERO(v, min, max) \
+ if (v > 0 && v < min) { \
+ v = min; \
+ } else if (v > max) { \
+ v = max; \
+ }
+
+ /* Set the kernel send and receive buffer sizes */
+ obj = NULL;
+ result = named_config_get(maps, "tcp-receive-buffer", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ recv_tcp_buffer_size = cfg_obj_asuint32(obj);
+ CAP_IF_NOT_ZERO(recv_tcp_buffer_size, 4096, INT32_MAX);
+
+ obj = NULL;
+ result = named_config_get(maps, "tcp-send-buffer", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ send_tcp_buffer_size = cfg_obj_asuint32(obj);
+ CAP_IF_NOT_ZERO(send_tcp_buffer_size, 4096, INT32_MAX);
+
+ obj = NULL;
+ result = named_config_get(maps, "udp-receive-buffer", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ recv_udp_buffer_size = cfg_obj_asuint32(obj);
+ CAP_IF_NOT_ZERO(recv_udp_buffer_size, 4096, INT32_MAX);
+
+ obj = NULL;
+ result = named_config_get(maps, "udp-send-buffer", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ send_udp_buffer_size = cfg_obj_asuint32(obj);
+ CAP_IF_NOT_ZERO(send_udp_buffer_size, 4096, INT32_MAX);
+
+ isc_nm_setnetbuffers(named_g_netmgr, recv_tcp_buffer_size,
+ send_tcp_buffer_size, recv_udp_buffer_size,
+ send_udp_buffer_size);
+
+#undef CAP_IF_NOT_ZERO
+
+ /*
+ * Configure sets of UDP query source ports.
+ */
+ CHECKM(isc_portset_create(named_g_mctx, &v4portset), "creating UDP "
+ "port set");
+ CHECKM(isc_portset_create(named_g_mctx, &v6portset), "creating UDP "
+ "port set");
+
+ usev4ports = NULL;
+ usev6ports = NULL;
+ avoidv4ports = NULL;
+ avoidv6ports = NULL;
+
+ (void)named_config_get(maps, "use-v4-udp-ports", &usev4ports);
+ if (usev4ports != NULL) {
+ portset_fromconf(v4portset, usev4ports, true);
+ } else {
+ CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low,
+ &udpport_high),
+ "get the default UDP/IPv4 port range");
+ if (udpport_low == udpport_high) {
+ isc_portset_add(v4portset, udpport_low);
+ } else {
+ isc_portset_addrange(v4portset, udpport_low,
+ udpport_high);
+ }
+ if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE4)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "using default UDP/IPv4 port range: "
+ "[%d, %d]",
+ udpport_low, udpport_high);
+ }
+ }
+ (void)named_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports);
+ if (avoidv4ports != NULL) {
+ portset_fromconf(v4portset, avoidv4ports, false);
+ }
+
+ (void)named_config_get(maps, "use-v6-udp-ports", &usev6ports);
+ if (usev6ports != NULL) {
+ portset_fromconf(v6portset, usev6ports, true);
+ } else {
+ CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low,
+ &udpport_high),
+ "get the default UDP/IPv6 port range");
+ if (udpport_low == udpport_high) {
+ isc_portset_add(v6portset, udpport_low);
+ } else {
+ isc_portset_addrange(v6portset, udpport_low,
+ udpport_high);
+ }
+ if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE6)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "using default UDP/IPv6 port range: "
+ "[%d, %d]",
+ udpport_low, udpport_high);
+ }
+ }
+ (void)named_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports);
+ if (avoidv6ports != NULL) {
+ portset_fromconf(v6portset, avoidv6ports, false);
+ }
+
+ dns_dispatchmgr_setavailports(named_g_dispatchmgr, v4portset,
+ v6portset);
+
+ /*
+ * Set the EDNS UDP size when we don't match a view.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "edns-udp-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ udpsize = cfg_obj_asuint32(obj);
+ if (udpsize < 512) {
+ udpsize = 512;
+ }
+ if (udpsize > 4096) {
+ udpsize = 4096;
+ }
+ server->sctx->udpsize = (uint16_t)udpsize;
+
+ /* Set the transfer message size for TCP */
+ obj = NULL;
+ result = named_config_get(maps, "transfer-message-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ transfer_message_size = cfg_obj_asuint32(obj);
+ if (transfer_message_size < 512) {
+ transfer_message_size = 512;
+ } else if (transfer_message_size > 65535) {
+ transfer_message_size = 65535;
+ }
+ server->sctx->transfer_tcp_message_size =
+ (uint16_t)transfer_message_size;
+
+ /*
+ * Configure the zone manager.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "transfers-in", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "transfers-per-ns", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "notify-rate", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_setnotifyrate(server->zonemgr, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "startup-notify-rate", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_setstartupnotifyrate(server->zonemgr,
+ cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "serial-query-rate", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj));
+
+ /*
+ * Determine which port to use for listening for incoming connections.
+ */
+ if (named_g_port != 0) {
+ listen_port = named_g_port;
+ } else {
+ CHECKM(named_config_getport(config, "port", &listen_port),
+ "port");
+ }
+
+ /*
+ * Find the listen queue depth.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "tcp-listen-queue", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ backlog = cfg_obj_asuint32(obj);
+ if ((backlog > 0) && (backlog < 10)) {
+ backlog = 10;
+ }
+ ns_interfacemgr_setbacklog(server->interfacemgr, backlog);
+
+ obj = NULL;
+ result = named_config_get(maps, "reuseport", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ loadbalancesockets = cfg_obj_asboolean(obj);
+#if HAVE_SO_REUSEPORT_LB
+ if (first_time) {
+ isc_nm_setloadbalancesockets(named_g_netmgr,
+ cfg_obj_asboolean(obj));
+ } else if (loadbalancesockets !=
+ isc_nm_getloadbalancesockets(named_g_netmgr))
+ {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "changing reuseport value requires server restart");
+ }
+#else
+ if (loadbalancesockets) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
+ "reuseport has no effect on this system");
+ }
+#endif
+
+ /*
+ * Configure the interface manager according to the "listen-on"
+ * statement.
+ */
+ {
+ const cfg_obj_t *clistenon = NULL;
+ ns_listenlist_t *listenon = NULL;
+
+ clistenon = NULL;
+ /*
+ * Even though listen-on is present in the default
+ * configuration, this way is easier.
+ */
+ if (options != NULL) {
+ (void)cfg_map_get(options, "listen-on", &clistenon);
+ }
+ if (clistenon != NULL) {
+ CHECK(listenlist_fromconfig(
+ clistenon, config, named_g_aclconfctx,
+ named_g_mctx, AF_INET,
+ server->tlsctx_server_cache, &listenon));
+ } else {
+ /*
+ * Not specified, use default.
+ */
+ CHECK(ns_listenlist_default(named_g_mctx, listen_port,
+ true, AF_INET, &listenon));
+ }
+ if (listenon != NULL) {
+ ns_interfacemgr_setlistenon4(server->interfacemgr,
+ listenon);
+ ns_listenlist_detach(&listenon);
+ }
+ }
+ /*
+ * Ditto for IPv6.
+ */
+ {
+ const cfg_obj_t *clistenon = NULL;
+ ns_listenlist_t *listenon = NULL;
+
+ if (options != NULL) {
+ (void)cfg_map_get(options, "listen-on-v6", &clistenon);
+ }
+ if (clistenon != NULL) {
+ CHECK(listenlist_fromconfig(
+ clistenon, config, named_g_aclconfctx,
+ named_g_mctx, AF_INET6,
+ server->tlsctx_server_cache, &listenon));
+ } else {
+ /*
+ * Not specified, use default.
+ */
+ CHECK(ns_listenlist_default(named_g_mctx, listen_port,
+ true, AF_INET6, &listenon));
+ }
+ if (listenon != NULL) {
+ ns_interfacemgr_setlistenon6(server->interfacemgr,
+ listenon);
+ ns_listenlist_detach(&listenon);
+ }
+ }
+
+ /*
+ * Rescan the interface list to pick up changes in the
+ * listen-on option. It's important that we do this before we try
+ * to configure the query source, since the dispatcher we use might
+ * be shared with an interface.
+ */
+ result = ns_interfacemgr_scan(server->interfacemgr, true, true);
+
+ /*
+ * Check that named is able to TCP listen on at least one
+ * interface. Otherwise, another named process could be running
+ * and we should fail.
+ */
+ if (first_time && (result == ISC_R_ADDRINUSE)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "unable to listen on any configured interfaces");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ /*
+ * Arrange for further interface scanning to occur periodically
+ * as specified by the "interface-interval" option.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "interface-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ interface_interval = cfg_obj_asduration(obj);
+ if (interface_interval == 0) {
+ CHECK(isc_timer_reset(server->interface_timer,
+ isc_timertype_inactive, NULL, NULL,
+ true));
+ } else if (server->interface_interval != interface_interval) {
+ isc_interval_set(&interval, interface_interval, 0);
+ CHECK(isc_timer_reset(server->interface_timer,
+ isc_timertype_ticker, NULL, &interval,
+ false));
+ }
+ server->interface_interval = interface_interval;
+
+ /*
+ * Enable automatic interface scans.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "automatic-interface-scan", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ server->sctx->interface_auto = cfg_obj_asboolean(obj);
+
+ /*
+ * Configure the dialup heartbeat timer.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "heartbeat-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ heartbeat_interval = cfg_obj_asuint32(obj) * 60;
+ if (heartbeat_interval == 0) {
+ CHECK(isc_timer_reset(server->heartbeat_timer,
+ isc_timertype_inactive, NULL, NULL,
+ true));
+ } else if (server->heartbeat_interval != heartbeat_interval) {
+ isc_interval_set(&interval, heartbeat_interval, 0);
+ CHECK(isc_timer_reset(server->heartbeat_timer,
+ isc_timertype_ticker, NULL, &interval,
+ false));
+ }
+ server->heartbeat_interval = heartbeat_interval;
+
+ isc_interval_set(&interval, 1200, 0);
+ CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL,
+ &interval, false));
+
+ isc_interval_set(&interval, named_g_tat_interval, 0);
+ CHECK(isc_timer_reset(server->tat_timer, isc_timertype_ticker, NULL,
+ &interval, false));
+
+ /*
+ * Write the PID file.
+ */
+ obj = NULL;
+ if (named_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) {
+ if (cfg_obj_isvoid(obj)) {
+ named_os_writepidfile(NULL, first_time);
+ } else {
+ named_os_writepidfile(cfg_obj_asstring(obj),
+ first_time);
+ }
+ } else {
+ named_os_writepidfile(named_g_defaultpidfile, first_time);
+ }
+
+ /*
+ * Configure the server-wide session key. This must be done before
+ * configure views because zone configuration may need to know
+ * session-keyname.
+ *
+ * Failure of session key generation isn't fatal at this time; if it
+ * turns out that a session key is really needed but doesn't exist,
+ * we'll treat it as a fatal error then.
+ */
+ (void)configure_session_key(maps, server, named_g_mctx, first_time);
+
+ /*
+ * Create the built-in kasp policies ("default", "insecure").
+ */
+ kasps = NULL;
+ (void)cfg_map_get(named_g_config, "dnssec-policy", &kasps);
+ for (element = cfg_list_first(kasps); element != NULL;
+ element = cfg_list_next(element))
+ {
+ cfg_obj_t *kconfig = cfg_listelt_value(element);
+
+ kasp = NULL;
+ CHECK(cfg_kasp_fromconfig(kconfig, default_kasp, named_g_mctx,
+ named_g_lctx, &kasplist, &kasp));
+ INSIST(kasp != NULL);
+ dns_kasp_freeze(kasp);
+
+ /* Insist that the first built-in policy is the default one. */
+ if (default_kasp == NULL) {
+ INSIST(strcmp(dns_kasp_getname(kasp), "default") == 0);
+ dns_kasp_attach(kasp, &default_kasp);
+ }
+
+ dns_kasp_detach(&kasp);
+ }
+ INSIST(default_kasp != NULL);
+
+ /*
+ * Create the DNSSEC key and signing policies (KASP).
+ */
+ kasps = NULL;
+ (void)cfg_map_get(config, "dnssec-policy", &kasps);
+ for (element = cfg_list_first(kasps); element != NULL;
+ element = cfg_list_next(element))
+ {
+ cfg_obj_t *kconfig = cfg_listelt_value(element);
+ kasp = NULL;
+ CHECK(cfg_kasp_fromconfig(kconfig, default_kasp, named_g_mctx,
+ named_g_lctx, &kasplist, &kasp));
+ INSIST(kasp != NULL);
+ dns_kasp_freeze(kasp);
+ dns_kasp_detach(&kasp);
+ }
+
+ dns_kasp_detach(&default_kasp);
+ tmpkasplist = server->kasplist;
+ server->kasplist = kasplist;
+ kasplist = tmpkasplist;
+
+ /*
+ * Configure the views.
+ */
+ views = NULL;
+ (void)cfg_map_get(config, "view", &views);
+
+ /*
+ * Create the views and count all the configured zones in
+ * order to correctly size the zone manager's task table.
+ * (We only count zones for configured views; the built-in
+ * "bind" view can be ignored as it only adds a negligible
+ * number of zones.)
+ *
+ * If we're allowing new zones, we need to be able to find the
+ * new zone file and count those as well. So we setup the new
+ * zone configuration context, but otherwise view configuration
+ * waits until after the zone manager's task list has been sized.
+ */
+ for (element = cfg_list_first(views); element != NULL;
+ element = cfg_list_next(element))
+ {
+ cfg_obj_t *vconfig = cfg_listelt_value(element);
+ const cfg_obj_t *voptions = cfg_tuple_get(vconfig, "options");
+ int nzf_num_zones;
+
+ view = NULL;
+
+ CHECK(create_view(vconfig, &viewlist, &view));
+ INSIST(view != NULL);
+
+ num_zones += count_zones(voptions);
+
+ CHECK(setup_newzones(view, config, vconfig, conf_parser,
+ named_g_aclconfctx, &nzf_num_zones));
+ num_zones += nzf_num_zones;
+
+ dns_view_detach(&view);
+ }
+
+ /*
+ * If there were no explicit views then we do the default
+ * view here.
+ */
+ if (views == NULL) {
+ int nzf_num_zones;
+
+ CHECK(create_view(NULL, &viewlist, &view));
+ INSIST(view != NULL);
+
+ num_zones = count_zones(config);
+
+ CHECK(setup_newzones(view, config, NULL, conf_parser,
+ named_g_aclconfctx, &nzf_num_zones));
+ num_zones += nzf_num_zones;
+
+ dns_view_detach(&view);
+ }
+
+ /*
+ * Zones have been counted; set the zone manager task pool size.
+ */
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "sizing zone task pool based on %d zones", num_zones);
+ CHECK(dns_zonemgr_setsize(named_g_server->zonemgr, num_zones));
+
+ /*
+ * Configure and freeze all explicit views. Explicit
+ * views that have zones were already created at parsing
+ * time, but views with no zones must be created here.
+ */
+ for (element = cfg_list_first(views); element != NULL;
+ element = cfg_list_next(element))
+ {
+ cfg_obj_t *vconfig = cfg_listelt_value(element);
+
+ view = NULL;
+ CHECK(find_view(vconfig, &viewlist, &view));
+ CHECK(configure_view(view, &viewlist, config, vconfig,
+ &cachelist, &server->kasplist, bindkeys,
+ named_g_mctx, named_g_aclconfctx, true));
+ dns_view_freeze(view);
+ dns_view_detach(&view);
+ }
+
+ /*
+ * Make sure we have a default view if and only if there
+ * were no explicit views.
+ */
+ if (views == NULL) {
+ view = NULL;
+ CHECK(find_view(NULL, &viewlist, &view));
+ CHECK(configure_view(view, &viewlist, config, NULL, &cachelist,
+ &server->kasplist, bindkeys, named_g_mctx,
+ named_g_aclconfctx, true));
+ dns_view_freeze(view);
+ dns_view_detach(&view);
+ }
+
+ /*
+ * Create (or recreate) the built-in views.
+ */
+ builtin_views = NULL;
+ RUNTIME_CHECK(cfg_map_get(named_g_config, "view", &builtin_views) ==
+ ISC_R_SUCCESS);
+ for (element = cfg_list_first(builtin_views); element != NULL;
+ element = cfg_list_next(element))
+ {
+ cfg_obj_t *vconfig = cfg_listelt_value(element);
+
+ CHECK(create_view(vconfig, &builtin_viewlist, &view));
+ CHECK(configure_view(view, &viewlist, config, vconfig,
+ &cachelist, &server->kasplist, bindkeys,
+ named_g_mctx, named_g_aclconfctx, false));
+ dns_view_freeze(view);
+ dns_view_detach(&view);
+ view = NULL;
+ }
+
+ /* Now combine the two viewlists into one */
+ ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link);
+
+ /*
+ * Commit any dns_zone_setview() calls on all zones in the new
+ * view.
+ */
+ for (view = ISC_LIST_HEAD(viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ dns_view_setviewcommit(view);
+ }
+
+ /* Swap our new view list with the production one. */
+ tmpviewlist = server->viewlist;
+ server->viewlist = viewlist;
+ viewlist = tmpviewlist;
+
+ /* Make the view list available to each of the views */
+ view = ISC_LIST_HEAD(server->viewlist);
+ while (view != NULL) {
+ view->viewlist = &server->viewlist;
+ view = ISC_LIST_NEXT(view, link);
+ }
+
+ /* Swap our new cache list with the production one. */
+ tmpcachelist = server->cachelist;
+ server->cachelist = cachelist;
+ cachelist = tmpcachelist;
+
+ /* Load the TKEY information from the configuration. */
+ if (options != NULL) {
+ dns_tkeyctx_t *t = NULL;
+ CHECKM(named_tkeyctx_fromconfig(options, named_g_mctx, &t),
+ "configuring TKEY");
+ if (server->sctx->tkeyctx != NULL) {
+ dns_tkeyctx_destroy(&server->sctx->tkeyctx);
+ }
+ server->sctx->tkeyctx = t;
+ }
+
+ /*
+ * Bind the control port(s).
+ */
+ CHECKM(named_controls_configure(named_g_server->controls, config,
+ named_g_aclconfctx),
+ "binding control channel(s)");
+
+#ifdef HAVE_LMDB
+ /*
+ * If we're using LMDB, we may have created newzones databases
+ * as root, making it impossible to reopen them later after
+ * switching to a new userid. We close them now, and reopen
+ * after relinquishing privileges them.
+ */
+ if (first_time) {
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ nzd_env_close(view);
+ }
+ }
+#endif /* HAVE_LMDB */
+
+ /*
+ * Relinquish root privileges.
+ */
+ if (first_time) {
+ named_os_changeuser();
+ }
+
+ /*
+ * Check that the working directory is writable.
+ */
+ if (!isc_file_isdirwritable(".")) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "the working directory is not writable");
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
+
+#ifdef HAVE_LMDB
+ /*
+ * Reopen NZD databases.
+ */
+ if (first_time) {
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ nzd_env_reopen(view);
+ }
+ }
+#endif /* HAVE_LMDB */
+
+ /*
+ * Configure the logging system.
+ *
+ * Do this after changing UID to make sure that any log
+ * files specified in named.conf get created by the
+ * unprivileged user, not root.
+ */
+ if (named_g_logstderr) {
+ const cfg_obj_t *logobj = NULL;
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "not using config file logging "
+ "statement for logging due to "
+ "-g option");
+
+ (void)cfg_map_get(config, "logging", &logobj);
+ if (logobj != NULL) {
+ result = named_logconfig(NULL, logobj);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "checking logging configuration "
+ "failed: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ }
+ } else {
+ const cfg_obj_t *logobj = NULL;
+
+ isc_logconfig_create(named_g_lctx, &logc);
+
+ logobj = NULL;
+ (void)cfg_map_get(config, "logging", &logobj);
+ if (logobj != NULL) {
+ CHECKM(named_logconfig(logc, logobj),
+ "configuring logging");
+ } else {
+ named_log_setdefaultchannels(logc);
+ named_log_setdefaultsslkeylogfile(logc);
+ CHECKM(named_log_setunmatchedcategory(logc),
+ "setting up default 'category unmatched'");
+ CHECKM(named_log_setdefaultcategory(logc),
+ "setting up default 'category default'");
+ }
+
+ isc_logconfig_use(named_g_lctx, logc);
+ logc = NULL;
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
+ "now using logging configuration from "
+ "config file");
+ }
+
+ /*
+ * Set the default value of the query logging flag depending
+ * whether a "queries" category has been defined. This is
+ * a disgusting hack, but we need to do this for BIND 8
+ * compatibility.
+ */
+ if (first_time) {
+ const cfg_obj_t *logobj = NULL;
+ const cfg_obj_t *categories = NULL;
+
+ obj = NULL;
+ if (named_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) {
+ ns_server_setoption(server->sctx, NS_SERVER_LOGQUERIES,
+ cfg_obj_asboolean(obj));
+ } else {
+ (void)cfg_map_get(config, "logging", &logobj);
+ if (logobj != NULL) {
+ (void)cfg_map_get(logobj, "category",
+ &categories);
+ }
+ if (categories != NULL) {
+ for (element = cfg_list_first(categories);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *catobj;
+ const char *str;
+
+ obj = cfg_listelt_value(element);
+ catobj = cfg_tuple_get(obj, "name");
+ str = cfg_obj_asstring(catobj);
+ if (strcasecmp(str, "queries") == 0) {
+ ns_server_setoption(
+ server->sctx,
+ NS_SERVER_LOGQUERIES,
+ true);
+ }
+ }
+ }
+ }
+ }
+
+ obj = NULL;
+ if (options != NULL &&
+ cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS)
+ {
+ named_g_memstatistics = cfg_obj_asboolean(obj);
+ } else {
+ named_g_memstatistics =
+ ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0);
+ }
+
+ obj = NULL;
+ if (named_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS)
+ {
+ named_main_setmemstats(cfg_obj_asstring(obj));
+ } else if (named_g_memstatistics) {
+ named_main_setmemstats("named.memstats");
+ } else {
+ named_main_setmemstats(NULL);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "statistics-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)),
+ "strdup");
+
+ obj = NULL;
+ result = named_config_get(maps, "dump-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)),
+ "strdup");
+
+ obj = NULL;
+ result = named_config_get(maps, "secroots-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)),
+ "strdup");
+
+ obj = NULL;
+ result = named_config_get(maps, "recursing-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)),
+ "strdup");
+
+ obj = NULL;
+ result = named_config_get(maps, "version", &obj);
+ if (result == ISC_R_SUCCESS) {
+ CHECKM(setoptstring(server, &server->version, obj), "strdup");
+ server->version_set = true;
+ } else {
+ server->version_set = false;
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "hostname", &obj);
+ if (result == ISC_R_SUCCESS) {
+ CHECKM(setoptstring(server, &server->hostname, obj), "strdup");
+ server->hostname_set = true;
+ } else {
+ server->hostname_set = false;
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "server-id", &obj);
+ server->sctx->usehostname = false;
+ if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
+ /* The parser translates "hostname" to true */
+ server->sctx->usehostname = true;
+ result = ns_server_setserverid(server->sctx, NULL);
+ } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) {
+ /* Found a quoted string */
+ result = ns_server_setserverid(server->sctx,
+ cfg_obj_asstring(obj));
+ } else {
+ result = ns_server_setserverid(server->sctx, NULL);
+ }
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ obj = NULL;
+ result = named_config_get(maps, "flush-zones-on-shutdown", &obj);
+ if (result == ISC_R_SUCCESS) {
+ server->flushonshutdown = cfg_obj_asboolean(obj);
+ } else {
+ server->flushonshutdown = false;
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "answer-cookie", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ server->sctx->answercookie = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "cookie-algorithm", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (strcasecmp(cfg_obj_asstring(obj), "siphash24") == 0) {
+ server->sctx->cookiealg = ns_cookiealg_siphash24;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "aes") == 0) {
+ server->sctx->cookiealg = ns_cookiealg_aes;
+ } else {
+ UNREACHABLE();
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "cookie-secret", &obj);
+ if (result == ISC_R_SUCCESS) {
+ const char *str;
+ bool first = true;
+ isc_buffer_t b;
+ unsigned int usedlength;
+ unsigned int expectedlength;
+
+ for (element = cfg_list_first(obj); element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ str = cfg_obj_asstring(obj);
+
+ if (first) {
+ memset(server->sctx->secret, 0,
+ sizeof(server->sctx->secret));
+ isc_buffer_init(&b, server->sctx->secret,
+ sizeof(server->sctx->secret));
+ result = isc_hex_decodestring(str, &b);
+ if (result != ISC_R_SUCCESS &&
+ result != ISC_R_NOSPACE)
+ {
+ goto cleanup;
+ }
+ first = false;
+ } else {
+ altsecret = isc_mem_get(server->sctx->mctx,
+ sizeof(*altsecret));
+ isc_buffer_init(&b, altsecret->secret,
+ sizeof(altsecret->secret));
+ result = isc_hex_decodestring(str, &b);
+ if (result != ISC_R_SUCCESS &&
+ result != ISC_R_NOSPACE)
+ {
+ isc_mem_put(server->sctx->mctx,
+ altsecret,
+ sizeof(*altsecret));
+ goto cleanup;
+ }
+ ISC_LIST_INITANDAPPEND(altsecrets, altsecret,
+ link);
+ }
+
+ usedlength = isc_buffer_usedlength(&b);
+ switch (server->sctx->cookiealg) {
+ case ns_cookiealg_siphash24:
+ expectedlength = ISC_SIPHASH24_KEY_LENGTH;
+ if (usedlength != expectedlength) {
+ CHECKM(ISC_R_RANGE, "SipHash-2-4 "
+ "cookie-secret "
+ "must be 128 bits");
+ }
+ break;
+ case ns_cookiealg_aes:
+ expectedlength = ISC_AES128_KEYLENGTH;
+ if (usedlength != expectedlength) {
+ CHECKM(ISC_R_RANGE, "AES cookie-secret "
+ "must be 128 bits");
+ }
+ break;
+ }
+ }
+ } else {
+ isc_nonce_buf(server->sctx->secret,
+ sizeof(server->sctx->secret));
+ }
+
+ /*
+ * Swap altsecrets lists.
+ */
+ tmpaltsecrets = server->sctx->altsecrets;
+ server->sctx->altsecrets = altsecrets;
+ altsecrets = tmpaltsecrets;
+
+ (void)named_server_loadnta(server);
+
+#ifdef USE_DNSRPS
+ /*
+ * Start and connect to the DNS Response Policy Service
+ * daemon, dnsrpzd, for each view that uses DNSRPS.
+ */
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ result = dns_dnsrps_connect(view->rpzs);
+ if (result != ISC_R_SUCCESS) {
+ view = NULL;
+ goto cleanup;
+ }
+ }
+#endif /* ifdef USE_DNSRPS */
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (logc != NULL) {
+ isc_logconfig_destroy(&logc);
+ }
+
+ if (v4portset != NULL) {
+ isc_portset_destroy(named_g_mctx, &v4portset);
+ }
+
+ if (v6portset != NULL) {
+ isc_portset_destroy(named_g_mctx, &v6portset);
+ }
+
+ if (conf_parser != NULL) {
+ if (config != NULL) {
+ cfg_obj_destroy(conf_parser, &config);
+ }
+ cfg_parser_destroy(&conf_parser);
+ }
+
+ if (bindkeys_parser != NULL) {
+ if (bindkeys != NULL) {
+ cfg_obj_destroy(bindkeys_parser, &bindkeys);
+ }
+ cfg_parser_destroy(&bindkeys_parser);
+ }
+
+ if (view != NULL) {
+ dns_view_detach(&view);
+ }
+
+ if (kasp != NULL) {
+ dns_kasp_detach(&kasp);
+ }
+
+ ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link);
+
+ /*
+ * This cleans up either the old production view list
+ * or our temporary list depending on whether they
+ * were swapped above or not.
+ */
+ for (view = ISC_LIST_HEAD(viewlist); view != NULL; view = view_next) {
+ view_next = ISC_LIST_NEXT(view, link);
+ ISC_LIST_UNLINK(viewlist, view, link);
+ if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0)
+ {
+ dns_view_setviewrevert(view);
+ (void)dns_zt_apply(view->zonetable, isc_rwlocktype_read,
+ false, NULL, removed, view);
+ }
+ dns_view_detach(&view);
+ }
+
+ /*
+ * Same cleanup for kasp list.
+ */
+ for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) {
+ kasp_next = ISC_LIST_NEXT(kasp, link);
+ ISC_LIST_UNLINK(kasplist, kasp, link);
+ dns_kasp_detach(&kasp);
+ }
+
+ /* Same cleanup for cache list. */
+ while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) {
+ ISC_LIST_UNLINK(cachelist, nsc, link);
+ dns_cache_detach(&nsc->cache);
+ isc_mem_put(server->mctx, nsc, sizeof(*nsc));
+ }
+
+ /* Cleanup for altsecrets list. */
+ while ((altsecret = ISC_LIST_HEAD(altsecrets)) != NULL) {
+ ISC_LIST_UNLINK(altsecrets, altsecret, link);
+ isc_mem_put(server->sctx->mctx, altsecret, sizeof(*altsecret));
+ }
+
+ /*
+ * Record the time of most recent configuration
+ */
+ tresult = isc_time_now(&named_g_configtime);
+ if (tresult != ISC_R_SUCCESS) {
+ named_main_earlyfatal("isc_time_now() failed: %s",
+ isc_result_totext(result));
+ }
+
+ /* Relinquish exclusive access to configuration data. */
+ if (exclusive) {
+ isc_task_endexclusive(server->task);
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
+ "load_configuration: %s", isc_result_totext(result));
+
+ return (result);
+}
+
+static isc_result_t
+view_loaded(void *arg) {
+ isc_result_t result;
+ ns_zoneload_t *zl = (ns_zoneload_t *)arg;
+
+ /*
+ * Force zone maintenance. Do this after loading
+ * so that we know when we need to force AXFR of
+ * secondary zones whose master files are missing.
+ *
+ * We use the zoneload reference counter to let us
+ * know when all views are finished.
+ */
+ if (isc_refcount_decrement(&zl->refs) == 1) {
+ named_server_t *server = zl->server;
+ bool reconfig = zl->reconfig;
+ dns_view_t *view = NULL;
+
+ isc_refcount_destroy(&zl->refs);
+ isc_mem_put(server->mctx, zl, sizeof(*zl));
+
+ /*
+ * To maintain compatibility with log parsing tools that might
+ * be looking for this string after "rndc reconfig", we keep it
+ * as it is
+ */
+ if (reconfig) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "any newly configured zones are now "
+ "loaded");
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE,
+ "all zones loaded");
+ }
+
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (view->managed_keys != NULL) {
+ result = dns_zone_synckeyzone(
+ view->managed_keys);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(
+ named_g_lctx,
+ DNS_LOGCATEGORY_DNSSEC,
+ DNS_LOGMODULE_DNSSEC,
+ ISC_LOG_ERROR,
+ "failed to initialize "
+ "managed-keys for view %s "
+ "(%s): DNSSEC validation is "
+ "at risk",
+ view->name,
+ isc_result_totext(result));
+ }
+ }
+ }
+
+ CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr),
+ "forcing zone maintenance");
+
+ named_os_started();
+
+#ifdef HAVE_FIPS_MODE
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE,
+ "FIPS mode is %s",
+ FIPS_mode() ? "enabled" : "disabled");
+#endif /* ifdef HAVE_FIPS_MODE */
+ atomic_store(&server->reload_status, NAMED_RELOAD_DONE);
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE,
+ "running");
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+load_zones(named_server_t *server, bool init, bool reconfig) {
+ isc_result_t result;
+ isc_taskmgr_t *taskmgr = dns_zonemgr_gettaskmgr(server->zonemgr);
+ ns_zoneload_t *zl = NULL;
+ dns_view_t *view = NULL;
+
+ zl = isc_mem_get(server->mctx, sizeof(*zl));
+ zl->server = server;
+ zl->reconfig = reconfig;
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ isc_refcount_init(&zl->refs, 1);
+
+ /*
+ * Schedule zones to be loaded from disk.
+ */
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (view->managed_keys != NULL) {
+ result = dns_zone_load(view->managed_keys, false);
+ if (result != ISC_R_SUCCESS &&
+ result != DNS_R_UPTODATE &&
+ result != DNS_R_CONTINUE)
+ {
+ goto cleanup;
+ }
+ }
+ if (view->redirect != NULL) {
+ result = dns_zone_load(view->redirect, false);
+ if (result != ISC_R_SUCCESS &&
+ result != DNS_R_UPTODATE &&
+ result != DNS_R_CONTINUE)
+ {
+ goto cleanup;
+ }
+ }
+
+ /*
+ * 'dns_view_asyncload' calls view_loaded if there are no
+ * zones.
+ */
+ isc_refcount_increment(&zl->refs);
+ result = dns_view_asyncload(view, reconfig, view_loaded, zl);
+ if (result != ISC_R_SUCCESS) {
+ isc_refcount_decrement1(&zl->refs);
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (isc_refcount_decrement(&zl->refs) == 1) {
+ isc_refcount_destroy(&zl->refs);
+ isc_mem_put(server->mctx, zl, sizeof(*zl));
+ }
+
+ if (init) {
+ /*
+ * If we're setting up the server for the first time, set
+ * the task manager into privileged mode; this ensures
+ * that no other tasks will begin to run until after zone
+ * loading is complete. We won't return from exclusive mode
+ * until the loading is finished; we can then drop out of
+ * privileged mode.
+ *
+ * We do *not* want to do this in the case of reload or
+ * reconfig, as loading a large zone could cause the server
+ * to be inactive for too long a time.
+ */
+ isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged);
+ isc_task_endexclusive(server->task);
+ isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_normal);
+ } else {
+ isc_task_endexclusive(server->task);
+ }
+
+ return (result);
+}
+
+static void
+run_server(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ named_server_t *server = (named_server_t *)event->ev_arg;
+ dns_geoip_databases_t *geoip;
+
+ INSIST(task == server->task);
+
+ isc_event_free(&event);
+
+ CHECKFATAL(dns_dispatchmgr_create(named_g_mctx, named_g_netmgr,
+ &named_g_dispatchmgr),
+ "creating dispatch manager");
+
+ dns_dispatchmgr_setstats(named_g_dispatchmgr, server->resolverstats);
+
+#if defined(HAVE_GEOIP2)
+ geoip = named_g_geoip;
+#else /* if defined(HAVE_GEOIP2) */
+ geoip = NULL;
+#endif /* if defined(HAVE_GEOIP2) */
+
+ CHECKFATAL(ns_interfacemgr_create(named_g_mctx, server->sctx,
+ named_g_taskmgr, named_g_timermgr,
+ named_g_netmgr, named_g_dispatchmgr,
+ server->task, geoip, named_g_cpus,
+ true, &server->interfacemgr),
+ "creating interface manager");
+
+ CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive,
+ NULL, NULL, server->task,
+ interface_timer_tick, server,
+ &server->interface_timer),
+ "creating interface timer");
+
+ CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive,
+ NULL, NULL, server->task,
+ heartbeat_timer_tick, server,
+ &server->heartbeat_timer),
+ "creating heartbeat timer");
+
+ CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive,
+ NULL, NULL, server->task, tat_timer_tick,
+ server, &server->tat_timer),
+ "creating trust anchor telemetry timer");
+
+ CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive,
+ NULL, NULL, server->task, pps_timer_tick,
+ server, &server->pps_timer),
+ "creating pps timer");
+
+ CHECKFATAL(
+ cfg_parser_create(named_g_mctx, named_g_lctx, &named_g_parser),
+ "creating default configuration parser");
+
+ CHECKFATAL(cfg_parser_create(named_g_mctx, named_g_lctx,
+ &named_g_addparser),
+ "creating additional configuration parser");
+
+ CHECKFATAL(load_configuration(named_g_conffile, server, true),
+ "loading configuration");
+
+ CHECKFATAL(load_zones(server, true, false), "loading zones");
+#ifdef ENABLE_AFL
+ named_g_run_done = true;
+#endif /* ifdef ENABLE_AFL */
+}
+
+void
+named_server_flushonshutdown(named_server_t *server, bool flush) {
+ REQUIRE(NAMED_SERVER_VALID(server));
+
+ server->flushonshutdown = flush;
+}
+
+static void
+shutdown_server(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ dns_view_t *view, *view_next = NULL;
+ dns_kasp_t *kasp, *kasp_next = NULL;
+ named_server_t *server = (named_server_t *)event->ev_arg;
+ bool flush = server->flushonshutdown;
+ named_cache_t *nsc;
+
+ UNUSED(task);
+ INSIST(task == server->task);
+
+ /*
+ * We need to shutdown the interface before going
+ * exclusive (which would pause the netmgr).
+ */
+ ns_interfacemgr_shutdown(server->interfacemgr);
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "shutting down%s",
+ flush ? ": flushing changes" : "");
+
+ named_statschannels_shutdown(server);
+ named_controls_shutdown(server->controls);
+ end_reserved_dispatches(server, true);
+ cleanup_session_key(server, server->mctx);
+
+ if (named_g_aclconfctx != NULL) {
+ cfg_aclconfctx_detach(&named_g_aclconfctx);
+ }
+
+ cfg_obj_destroy(named_g_parser, &named_g_config);
+ cfg_parser_destroy(&named_g_parser);
+ cfg_parser_destroy(&named_g_addparser);
+
+ (void)named_server_saventa(server);
+
+ for (kasp = ISC_LIST_HEAD(server->kasplist); kasp != NULL;
+ kasp = kasp_next)
+ {
+ kasp_next = ISC_LIST_NEXT(kasp, link);
+ ISC_LIST_UNLINK(server->kasplist, kasp, link);
+ dns_kasp_detach(&kasp);
+ }
+
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = view_next)
+ {
+ view_next = ISC_LIST_NEXT(view, link);
+ ISC_LIST_UNLINK(server->viewlist, view, link);
+ if (flush) {
+ dns_view_flushanddetach(&view);
+ } else {
+ dns_view_detach(&view);
+ }
+ }
+
+ /*
+ * Shut down all dyndb instances.
+ */
+ dns_dyndb_cleanup(true);
+
+ while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) {
+ ISC_LIST_UNLINK(server->cachelist, nsc, link);
+ dns_cache_detach(&nsc->cache);
+ isc_mem_put(server->mctx, nsc, sizeof(*nsc));
+ }
+
+ isc_timer_destroy(&server->interface_timer);
+ isc_timer_destroy(&server->heartbeat_timer);
+ isc_timer_destroy(&server->pps_timer);
+ isc_timer_destroy(&server->tat_timer);
+
+ ns_interfacemgr_detach(&server->interfacemgr);
+
+ dns_dispatchmgr_detach(&named_g_dispatchmgr);
+
+ dns_zonemgr_shutdown(server->zonemgr);
+
+ if (named_g_sessionkey != NULL) {
+ dns_tsigkey_detach(&named_g_sessionkey);
+ dns_name_free(&named_g_sessionkeyname, server->mctx);
+ }
+#if defined(HAVE_GEOIP2)
+ named_geoip_shutdown();
+#endif /* HAVE_GEOIP2 */
+
+ dns_db_detach(&server->in_roothints);
+
+ isc_task_endexclusive(server->task);
+
+ isc_task_detach(&server->task);
+
+ isc_event_free(&event);
+}
+
+/*%
+ * Find a view that matches the source and destination addresses of a query.
+ */
+static isc_result_t
+get_matching_view(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr,
+ dns_message_t *message, dns_aclenv_t *env,
+ isc_result_t *sigresult, dns_view_t **viewp) {
+ dns_view_t *view;
+
+ REQUIRE(message != NULL);
+ REQUIRE(sigresult != NULL);
+ REQUIRE(viewp != NULL && *viewp == NULL);
+
+ for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (message->rdclass == view->rdclass ||
+ message->rdclass == dns_rdataclass_any)
+ {
+ const dns_name_t *tsig = NULL;
+
+ *sigresult = dns_message_rechecksig(message, view);
+ if (*sigresult == ISC_R_SUCCESS) {
+ dns_tsigkey_t *tsigkey;
+
+ tsigkey = message->tsigkey;
+ tsig = dns_tsigkey_identity(tsigkey);
+ }
+
+ if (dns_acl_allowed(srcaddr, tsig, view->matchclients,
+ env) &&
+ dns_acl_allowed(destaddr, tsig,
+ view->matchdestinations, env) &&
+ !(view->matchrecursiveonly &&
+ (message->flags & DNS_MESSAGEFLAG_RD) == 0))
+ {
+ dns_view_attach(view, viewp);
+ return (ISC_R_SUCCESS);
+ }
+ }
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+void
+named_server_create(isc_mem_t *mctx, named_server_t **serverp) {
+ isc_result_t result;
+ named_server_t *server = isc_mem_get(mctx, sizeof(*server));
+
+ *server = (named_server_t){
+ .mctx = mctx,
+ .statsfile = isc_mem_strdup(mctx, "named.stats"),
+ .bindkeysfile = isc_mem_strdup(mctx, named_g_defaultbindkeys),
+ .dumpfile = isc_mem_strdup(mctx, "named_dump.db"),
+ .secrootsfile = isc_mem_strdup(mctx, "named.secroots"),
+ .recfile = isc_mem_strdup(mctx, "named.recursing"),
+ };
+
+#ifdef USE_DNSRPS
+ CHECKFATAL(dns_dnsrps_server_create(), "initializing RPZ service "
+ "interface");
+#endif /* ifdef USE_DNSRPS */
+
+ /* Initialize server data structures. */
+ ISC_LIST_INIT(server->kasplist);
+ ISC_LIST_INIT(server->viewlist);
+
+ /* Must be first. */
+ CHECKFATAL(dst_lib_init(named_g_mctx, named_g_engine), "initializing "
+ "DST");
+
+ CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,
+ &server->in_roothints),
+ "setting up root hints");
+
+ atomic_init(&server->reload_status, NAMED_RELOAD_IN_PROGRESS);
+
+ /*
+ * Setup the server task, which is responsible for coordinating
+ * startup and shutdown of the server, as well as all exclusive
+ * tasks.
+ */
+ CHECKFATAL(isc_task_create_bound(named_g_taskmgr, 0, &server->task, 0),
+ "creating server task");
+ isc_task_setname(server->task, "server", server);
+ isc_taskmgr_setexcltask(named_g_taskmgr, server->task);
+
+ CHECKFATAL(ns_server_create(mctx, get_matching_view, &server->sctx),
+ "creating server context");
+
+#if defined(HAVE_GEOIP2)
+ /*
+ * GeoIP must be initialized before the interface
+ * manager (which includes the ACL environment)
+ * is created.
+ */
+ named_geoip_init();
+#endif /* HAVE_GEOIP2 */
+
+#ifdef ENABLE_AFL
+ server->sctx->fuzztype = named_g_fuzz_type;
+ server->sctx->fuzznotify = named_fuzz_notify;
+#endif /* ifdef ENABLE_AFL */
+
+ CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),
+ "isc_task_onshutdown");
+ CHECKFATAL(
+ isc_app_onrun(named_g_mctx, server->task, run_server, server),
+ "isc_app_onrun");
+
+ CHECKFATAL(dns_zonemgr_create(named_g_mctx, named_g_taskmgr,
+ named_g_timermgr, named_g_netmgr,
+ &server->zonemgr),
+ "dns_zonemgr_create");
+ CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000), "dns_zonemgr_"
+ "setsize");
+
+ CHECKFATAL(isc_stats_create(server->mctx, &server->sockstats,
+ isc_sockstatscounter_max),
+ "isc_stats_create");
+ isc_nm_setstats(named_g_netmgr, server->sockstats);
+
+ CHECKFATAL(isc_stats_create(named_g_mctx, &server->zonestats,
+ dns_zonestatscounter_max),
+ "dns_stats_create (zone)");
+
+ CHECKFATAL(isc_stats_create(named_g_mctx, &server->resolverstats,
+ dns_resstatscounter_max),
+ "dns_stats_create (resolver)");
+
+ CHECKFATAL(named_controls_create(server, &server->controls),
+ "named_controls_create");
+
+ ISC_LIST_INIT(server->dispatches);
+
+ ISC_LIST_INIT(server->statschannels);
+
+ ISC_LIST_INIT(server->cachelist);
+
+ server->magic = NAMED_SERVER_MAGIC;
+
+ *serverp = server;
+}
+
+void
+named_server_destroy(named_server_t **serverp) {
+ named_server_t *server = *serverp;
+ REQUIRE(NAMED_SERVER_VALID(server));
+
+#ifdef HAVE_DNSTAP
+ if (server->dtenv != NULL) {
+ dns_dt_detach(&server->dtenv);
+ }
+#endif /* HAVE_DNSTAP */
+
+#ifdef USE_DNSRPS
+ dns_dnsrps_server_destroy();
+#endif /* ifdef USE_DNSRPS */
+
+ named_controls_destroy(&server->controls);
+
+ isc_stats_detach(&server->zonestats);
+ isc_stats_detach(&server->sockstats);
+ isc_stats_detach(&server->resolverstats);
+
+ if (server->sctx != NULL) {
+ ns_server_detach(&server->sctx);
+ }
+
+ isc_mem_free(server->mctx, server->statsfile);
+ isc_mem_free(server->mctx, server->bindkeysfile);
+ isc_mem_free(server->mctx, server->dumpfile);
+ isc_mem_free(server->mctx, server->secrootsfile);
+ isc_mem_free(server->mctx, server->recfile);
+
+ if (server->version != NULL) {
+ isc_mem_free(server->mctx, server->version);
+ }
+ if (server->hostname != NULL) {
+ isc_mem_free(server->mctx, server->hostname);
+ }
+ if (server->lockfile != NULL) {
+ isc_mem_free(server->mctx, server->lockfile);
+ }
+
+ if (server->zonemgr != NULL) {
+ dns_zonemgr_detach(&server->zonemgr);
+ }
+
+ dst_lib_destroy();
+
+ INSIST(ISC_LIST_EMPTY(server->kasplist));
+ INSIST(ISC_LIST_EMPTY(server->viewlist));
+ INSIST(ISC_LIST_EMPTY(server->cachelist));
+
+ if (server->tlsctx_server_cache != NULL) {
+ isc_tlsctx_cache_detach(&server->tlsctx_server_cache);
+ }
+
+ if (server->tlsctx_client_cache != NULL) {
+ isc_tlsctx_cache_detach(&server->tlsctx_client_cache);
+ }
+
+ server->magic = 0;
+ isc_mem_put(server->mctx, server, sizeof(*server));
+ *serverp = NULL;
+}
+
+static void
+fatal(named_server_t *server, const char *msg, isc_result_t result) {
+ if (server != NULL && server->task != NULL) {
+ /*
+ * Prevent races between the OpenSSL on_exit registered
+ * function and any other OpenSSL calls from other tasks
+ * by requesting exclusive access to the task manager.
+ */
+ (void)isc_task_beginexclusive(server->task);
+ }
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, "%s: %s", msg,
+ isc_result_totext(result));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL,
+ "exiting (due to fatal error)");
+ named_os_shutdown();
+ exit(1);
+}
+
+static void
+start_reserved_dispatches(named_server_t *server) {
+ REQUIRE(NAMED_SERVER_VALID(server));
+
+ server->dispatchgen++;
+}
+
+static void
+end_reserved_dispatches(named_server_t *server, bool all) {
+ named_dispatch_t *dispatch, *nextdispatch;
+
+ REQUIRE(NAMED_SERVER_VALID(server));
+
+ for (dispatch = ISC_LIST_HEAD(server->dispatches); dispatch != NULL;
+ dispatch = nextdispatch)
+ {
+ nextdispatch = ISC_LIST_NEXT(dispatch, link);
+ if (!all && server->dispatchgen == dispatch->dispatchgen) {
+ continue;
+ }
+ ISC_LIST_UNLINK(server->dispatches, dispatch, link);
+ dns_dispatch_detach(&dispatch->dispatch);
+ isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
+ }
+}
+
+void
+named_add_reserved_dispatch(named_server_t *server,
+ const isc_sockaddr_t *addr) {
+ named_dispatch_t *dispatch;
+ in_port_t port;
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+ isc_result_t result;
+
+ REQUIRE(NAMED_SERVER_VALID(server));
+
+ port = isc_sockaddr_getport(addr);
+ if (port == 0 || port >= 1024) {
+ return;
+ }
+
+ for (dispatch = ISC_LIST_HEAD(server->dispatches); dispatch != NULL;
+ dispatch = ISC_LIST_NEXT(dispatch, link))
+ {
+ if (isc_sockaddr_equal(&dispatch->addr, addr)) {
+ break;
+ }
+ }
+ if (dispatch != NULL) {
+ dispatch->dispatchgen = server->dispatchgen;
+ return;
+ }
+
+ dispatch = isc_mem_get(server->mctx, sizeof(*dispatch));
+
+ dispatch->addr = *addr;
+ dispatch->dispatchgen = server->dispatchgen;
+ dispatch->dispatch = NULL;
+
+ result = dns_dispatch_createudp(named_g_dispatchmgr, &dispatch->addr,
+ &dispatch->dispatch);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link);
+
+ return;
+
+cleanup:
+ isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
+ isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "unable to create dispatch for reserved port %s: %s",
+ addrbuf, isc_result_totext(result));
+}
+
+static isc_result_t
+loadconfig(named_server_t *server) {
+ isc_result_t result;
+ start_reserved_dispatches(server);
+ result = load_configuration(named_g_conffile, server, false);
+ if (result == ISC_R_SUCCESS) {
+ end_reserved_dispatches(server, false);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "reloading configuration succeeded");
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "reloading configuration failed: %s",
+ isc_result_totext(result));
+ atomic_store(&server->reload_status, NAMED_RELOAD_FAILED);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+reload(named_server_t *server) {
+ isc_result_t result;
+
+ atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS);
+
+ CHECK(loadconfig(server));
+
+ result = load_zones(server, false, false);
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "reloading zones succeeded");
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "reloading zones failed: %s",
+ isc_result_totext(result));
+ atomic_store(&server->reload_status, NAMED_RELOAD_FAILED);
+ }
+cleanup:
+ return (result);
+}
+
+/*
+ * Handle a reload event (from SIGHUP).
+ */
+static void
+named_server_reload(isc_task_t *task, isc_event_t *event) {
+ named_server_t *server = (named_server_t *)event->ev_sender;
+
+ INSIST(task == server->task);
+ UNUSED(task);
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "received SIGHUP signal to reload zones");
+ (void)reload(server);
+
+ isc_event_free(&event);
+}
+
+void
+named_server_reloadwanted(named_server_t *server) {
+ isc_event_t *event = isc_event_allocate(
+ named_g_mctx, server, NAMED_EVENT_RELOAD, named_server_reload,
+ NULL, sizeof(isc_event_t));
+ isc_task_send(server->task, &event);
+}
+
+void
+named_server_scan_interfaces(named_server_t *server) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
+ "automatic interface rescan");
+
+ ns_interfacemgr_scan(server->interfacemgr, true, false);
+}
+
+/*
+ * Get the next token from lexer 'lex'.
+ *
+ * NOTE: the token value for string tokens always uses the same pointer
+ * value. Multiple calls to this function on the same lexer will always
+ * return either that value (lex->data) or NULL. It is necessary to copy
+ * the token into local storage if it needs to be referenced after the next
+ * call to next_token().
+ */
+static char *
+next_token(isc_lex_t *lex, isc_buffer_t **text) {
+ isc_result_t result;
+ isc_token_t token;
+
+ token.type = isc_tokentype_unknown;
+ result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF | ISC_LEXOPT_QSTRING,
+ &token);
+
+ switch (result) {
+ case ISC_R_NOMORE:
+ (void)isc_lex_close(lex);
+ break;
+ case ISC_R_SUCCESS:
+ if (token.type == isc_tokentype_eof) {
+ (void)isc_lex_close(lex);
+ }
+ break;
+ case ISC_R_NOSPACE:
+ if (text != NULL) {
+ (void)putstr(text, "token too large");
+ (void)putnull(text);
+ }
+ return (NULL);
+ default:
+ if (text != NULL) {
+ (void)putstr(text, isc_result_totext(result));
+ (void)putnull(text);
+ }
+ return (NULL);
+ }
+
+ if (token.type == isc_tokentype_string ||
+ token.type == isc_tokentype_qstring)
+ {
+ return (token.value.as_textregion.base);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Find the zone specified in the control channel command, if any.
+ * If a zone is specified, point '*zonep' at it, otherwise
+ * set '*zonep' to NULL, and f 'zonename' is not NULL, copy
+ * the zone name into it (N.B. 'zonename' must have space to hold
+ * a full DNS name).
+ *
+ * If 'zonetxt' is set, the caller has already pulled a token
+ * off the command line that is to be used as the zone name. (This
+ * is sometimes done when it's necessary to check for an optional
+ * argument before the zone name, as in "rndc sync [-clean] zone".)
+ */
+static isc_result_t
+zone_from_args(named_server_t *server, isc_lex_t *lex, const char *zonetxt,
+ dns_zone_t **zonep, char *zonename, isc_buffer_t **text,
+ bool skip) {
+ char *ptr;
+ char *classtxt;
+ const char *viewtxt = NULL;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result;
+ dns_view_t *view = NULL;
+ dns_rdataclass_t rdclass;
+ char problem[DNS_NAME_FORMATSIZE + 500] = "";
+ char zonebuf[DNS_NAME_FORMATSIZE];
+ bool redirect = false;
+
+ REQUIRE(zonep != NULL && *zonep == NULL);
+
+ if (skip) {
+ /* Skip the command name. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ }
+
+ /* Look for the zone name. */
+ if (zonetxt == NULL) {
+ zonetxt = next_token(lex, text);
+ }
+ if (zonetxt == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /* Copy zonetxt because it'll be overwritten by next_token() */
+ /* To locate a zone named "-redirect" use "-redirect." */
+ if (strcmp(zonetxt, "-redirect") == 0) {
+ redirect = true;
+ strlcpy(zonebuf, ".", DNS_NAME_FORMATSIZE);
+ } else {
+ strlcpy(zonebuf, zonetxt, DNS_NAME_FORMATSIZE);
+ }
+ if (zonename != NULL) {
+ strlcpy(zonename, redirect ? "." : zonetxt,
+ DNS_NAME_FORMATSIZE);
+ }
+
+ name = dns_fixedname_initname(&fname);
+ CHECK(dns_name_fromstring(name, zonebuf, 0, NULL));
+
+ /* Look for the optional class name. */
+ classtxt = next_token(lex, text);
+ if (classtxt != NULL) {
+ isc_textregion_t r;
+ r.base = classtxt;
+ r.length = strlen(classtxt);
+ CHECK(dns_rdataclass_fromtext(&rdclass, &r));
+
+ /* Look for the optional view name. */
+ viewtxt = next_token(lex, text);
+ } else {
+ rdclass = dns_rdataclass_in;
+ }
+
+ if (viewtxt == NULL) {
+ if (redirect) {
+ result = dns_viewlist_find(&server->viewlist,
+ "_default",
+ dns_rdataclass_in, &view);
+ if (result != ISC_R_SUCCESS || view->redirect == NULL) {
+ result = ISC_R_NOTFOUND;
+ snprintf(problem, sizeof(problem),
+ "redirect zone not found in "
+ "_default view");
+ } else {
+ dns_zone_attach(view->redirect, zonep);
+ result = ISC_R_SUCCESS;
+ }
+ } else {
+ result = dns_viewlist_findzone(&server->viewlist, name,
+ (classtxt == NULL),
+ rdclass, zonep);
+ if (result == ISC_R_NOTFOUND) {
+ snprintf(problem, sizeof(problem),
+ "no matching zone '%s' in any view",
+ zonebuf);
+ } else if (result == ISC_R_MULTIPLE) {
+ snprintf(problem, sizeof(problem),
+ "zone '%s' was found in multiple "
+ "views",
+ zonebuf);
+ }
+ }
+ } else {
+ result = dns_viewlist_find(&server->viewlist, viewtxt, rdclass,
+ &view);
+ if (result != ISC_R_SUCCESS) {
+ snprintf(problem, sizeof(problem),
+ "no matching view '%s'", viewtxt);
+ goto report;
+ }
+
+ if (redirect) {
+ if (view->redirect != NULL) {
+ dns_zone_attach(view->redirect, zonep);
+ result = ISC_R_SUCCESS;
+ } else {
+ result = ISC_R_NOTFOUND;
+ }
+ } else {
+ result = dns_zt_find(view->zonetable, name, 0, NULL,
+ zonep);
+ }
+ if (result != ISC_R_SUCCESS) {
+ snprintf(problem, sizeof(problem),
+ "no matching zone '%s' in view '%s'", zonebuf,
+ viewtxt);
+ }
+ }
+
+ /* Partial match? */
+ if (result != ISC_R_SUCCESS && *zonep != NULL) {
+ dns_zone_detach(zonep);
+ }
+ if (result == DNS_R_PARTIALMATCH) {
+ result = ISC_R_NOTFOUND;
+ }
+report:
+ if (result != ISC_R_SUCCESS) {
+ isc_result_t tresult;
+
+ tresult = putstr(text, problem);
+ if (tresult == ISC_R_SUCCESS) {
+ (void)putnull(text);
+ }
+ }
+
+cleanup:
+ if (view != NULL) {
+ dns_view_detach(&view);
+ }
+
+ return (result);
+}
+
+/*
+ * Act on a "retransfer" command from the command channel.
+ */
+isc_result_t
+named_server_retransfercommand(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result;
+ dns_zone_t *zone = NULL;
+ dns_zone_t *raw = NULL;
+ dns_zonetype_t type;
+
+ REQUIRE(text != NULL);
+
+ result = zone_from_args(server, lex, NULL, &zone, NULL, text, true);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ if (zone == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ dns_zone_getraw(zone, &raw);
+ if (raw != NULL) {
+ dns_zone_detach(&zone);
+ dns_zone_attach(raw, &zone);
+ dns_zone_detach(&raw);
+ }
+ type = dns_zone_gettype(zone);
+ if (type == dns_zone_secondary || type == dns_zone_mirror ||
+ type == dns_zone_stub ||
+ (type == dns_zone_redirect &&
+ dns_zone_getredirecttype(zone) == dns_zone_secondary))
+ {
+ dns_zone_forcereload(zone);
+ } else {
+ (void)putstr(text, "retransfer: inappropriate zone type: ");
+ (void)putstr(text, dns_zonetype_name(type));
+ if (type == dns_zone_redirect) {
+ type = dns_zone_getredirecttype(zone);
+ (void)putstr(text, "(");
+ (void)putstr(text, dns_zonetype_name(type));
+ (void)putstr(text, ")");
+ }
+ (void)putnull(text);
+ result = ISC_R_FAILURE;
+ }
+ dns_zone_detach(&zone);
+ return (result);
+}
+
+/*
+ * Act on a "reload" command from the command channel.
+ */
+isc_result_t
+named_server_reloadcommand(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result;
+ dns_zone_t *zone = NULL;
+ dns_zonetype_t type;
+ const char *msg = NULL;
+
+ REQUIRE(text != NULL);
+
+ result = zone_from_args(server, lex, NULL, &zone, NULL, text, true);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ if (zone == NULL) {
+ result = reload(server);
+ if (result == ISC_R_SUCCESS) {
+ msg = "server reload successful";
+ }
+ } else {
+ type = dns_zone_gettype(zone);
+ if (type == dns_zone_secondary || type == dns_zone_mirror ||
+ type == dns_zone_stub)
+ {
+ dns_zone_refresh(zone);
+ dns_zone_detach(&zone);
+ msg = "zone refresh queued";
+ } else {
+ result = dns_zone_load(zone, false);
+ dns_zone_detach(&zone);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ msg = "zone reload successful";
+ break;
+ case DNS_R_CONTINUE:
+ msg = "zone reload queued";
+ result = ISC_R_SUCCESS;
+ break;
+ case DNS_R_UPTODATE:
+ msg = "zone reload up-to-date";
+ result = ISC_R_SUCCESS;
+ break;
+ default:
+ /* failure message will be generated by rndc */
+ break;
+ }
+ }
+ }
+ if (msg != NULL) {
+ (void)putstr(text, msg);
+ (void)putnull(text);
+ }
+ return (result);
+}
+
+/*
+ * Act on a "reconfig" command from the command channel.
+ */
+isc_result_t
+named_server_reconfigcommand(named_server_t *server) {
+ isc_result_t result;
+ atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS);
+
+ CHECK(loadconfig(server));
+
+ result = load_zones(server, false, true);
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "scheduled loading new zones");
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "loading new zones failed: %s",
+ isc_result_totext(result));
+ atomic_store(&server->reload_status, NAMED_RELOAD_FAILED);
+ }
+cleanup:
+ return (result);
+}
+
+/*
+ * Act on a "notify" command from the command channel.
+ */
+isc_result_t
+named_server_notifycommand(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result;
+ dns_zone_t *zone = NULL;
+ const char msg[] = "zone notify queued";
+
+ REQUIRE(text != NULL);
+
+ result = zone_from_args(server, lex, NULL, &zone, NULL, text, true);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ if (zone == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ dns_zone_notify(zone);
+ dns_zone_detach(&zone);
+ (void)putstr(text, msg);
+ (void)putnull(text);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Act on a "refresh" command from the command channel.
+ */
+isc_result_t
+named_server_refreshcommand(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result;
+ dns_zone_t *zone = NULL, *raw = NULL;
+ const char msg1[] = "zone refresh queued";
+ const char msg2[] = "not a secondary, mirror, or stub zone";
+ dns_zonetype_t type;
+
+ REQUIRE(text != NULL);
+
+ result = zone_from_args(server, lex, NULL, &zone, NULL, text, true);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ if (zone == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ dns_zone_getraw(zone, &raw);
+ if (raw != NULL) {
+ dns_zone_detach(&zone);
+ dns_zone_attach(raw, &zone);
+ dns_zone_detach(&raw);
+ }
+
+ type = dns_zone_gettype(zone);
+ if (type == dns_zone_secondary || type == dns_zone_mirror ||
+ type == dns_zone_stub)
+ {
+ dns_zone_refresh(zone);
+ dns_zone_detach(&zone);
+ (void)putstr(text, msg1);
+ (void)putnull(text);
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_zone_detach(&zone);
+ (void)putstr(text, msg2);
+ (void)putnull(text);
+ return (ISC_R_FAILURE);
+}
+
+isc_result_t
+named_server_togglequerylog(named_server_t *server, isc_lex_t *lex) {
+ bool prev, value;
+ char *ptr;
+
+ /* Skip the command name. */
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ prev = ns_server_getoption(server->sctx, NS_SERVER_LOGQUERIES);
+
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ value = !prev;
+ } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") ||
+ !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true"))
+ {
+ value = true;
+ } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") ||
+ !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false"))
+ {
+ value = false;
+ } else {
+ return (DNS_R_SYNTAX);
+ }
+
+ if (value == prev) {
+ return (ISC_R_SUCCESS);
+ }
+
+ ns_server_setoption(server->sctx, NS_SERVER_LOGQUERIES, value);
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "query logging is now %s", value ? "on" : "off");
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family,
+ isc_tlsctx_cache_t *tlsctx_cache,
+ ns_listenlist_t **target) {
+ isc_result_t result;
+ const cfg_listelt_t *element;
+ ns_listenlist_t *dlist = NULL;
+
+ REQUIRE(target != NULL && *target == NULL);
+
+ result = ns_listenlist_create(mctx, &dlist);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ for (element = cfg_list_first(listenlist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ ns_listenelt_t *delt = NULL;
+ const cfg_obj_t *listener = cfg_listelt_value(element);
+ result = listenelt_fromconfig(listener, config, actx, mctx,
+ family, tlsctx_cache, &delt);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ ISC_LIST_APPEND(dlist->elts, delt, link);
+ }
+ *target = dlist;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ ns_listenlist_detach(&dlist);
+ return (result);
+}
+
+static const cfg_obj_t *
+find_maplist(const cfg_obj_t *config, const char *listname, const char *name) {
+ isc_result_t result;
+ const cfg_obj_t *maplist = NULL;
+ const cfg_listelt_t *elt = NULL;
+
+ REQUIRE(config != NULL);
+ REQUIRE(name != NULL);
+
+ result = cfg_map_get(config, listname, &maplist);
+ if (result != ISC_R_SUCCESS) {
+ return (NULL);
+ }
+
+ for (elt = cfg_list_first(maplist); elt != NULL;
+ elt = cfg_list_next(elt))
+ {
+ const cfg_obj_t *map = cfg_listelt_value(elt);
+ if (strcasecmp(cfg_obj_asstring(cfg_map_getname(map)), name) ==
+ 0)
+ {
+ return (map);
+ }
+ }
+
+ return (NULL);
+}
+
+/*
+ * Create a listen list from the corresponding configuration
+ * data structure.
+ */
+static isc_result_t
+listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family,
+ isc_tlsctx_cache_t *tlsctx_cache,
+ ns_listenelt_t **target) {
+ isc_result_t result;
+ const cfg_obj_t *ltup = NULL;
+ const cfg_obj_t *tlsobj = NULL, *httpobj = NULL;
+ const cfg_obj_t *portobj = NULL;
+ const cfg_obj_t *http_server = NULL;
+ in_port_t port = 0;
+ const char *key = NULL, *cert = NULL, *ca_file = NULL,
+ *dhparam_file = NULL, *ciphers = NULL;
+ bool tls_prefer_server_ciphers = false,
+ tls_prefer_server_ciphers_set = false;
+ bool tls_session_tickets = false, tls_session_tickets_set = false;
+ bool do_tls = false, no_tls = false, http = false;
+ ns_listenelt_t *delt = NULL;
+ uint32_t tls_protos = 0;
+ ns_listen_tls_params_t tls_params = { 0 };
+ const char *tlsname = NULL;
+
+ REQUIRE(target != NULL && *target == NULL);
+
+ ltup = cfg_tuple_get(listener, "tuple");
+ RUNTIME_CHECK(ltup != NULL);
+
+ tlsobj = cfg_tuple_get(ltup, "tls");
+ if (tlsobj != NULL && cfg_obj_isstring(tlsobj)) {
+ tlsname = cfg_obj_asstring(tlsobj);
+
+ if (strcasecmp(tlsname, "none") == 0) {
+ no_tls = true;
+ } else if (strcasecmp(tlsname, "ephemeral") == 0) {
+ do_tls = true;
+ } else {
+ const cfg_obj_t *keyobj = NULL, *certobj = NULL,
+ *ca_obj = NULL, *dhparam_obj = NULL;
+ const cfg_obj_t *tlsmap = NULL;
+ const cfg_obj_t *tls_proto_list = NULL;
+ const cfg_obj_t *ciphers_obj = NULL;
+ const cfg_obj_t *prefer_server_ciphers_obj = NULL;
+ const cfg_obj_t *session_tickets_obj = NULL;
+
+ do_tls = true;
+
+ tlsmap = find_maplist(config, "tls", tlsname);
+ if (tlsmap == NULL) {
+ cfg_obj_log(tlsobj, named_g_lctx, ISC_LOG_ERROR,
+ "tls '%s' is not defined",
+ cfg_obj_asstring(tlsobj));
+ return (ISC_R_FAILURE);
+ }
+
+ CHECK(cfg_map_get(tlsmap, "key-file", &keyobj));
+ key = cfg_obj_asstring(keyobj);
+
+ CHECK(cfg_map_get(tlsmap, "cert-file", &certobj));
+ cert = cfg_obj_asstring(certobj);
+
+ if (cfg_map_get(tlsmap, "ca-file", &ca_obj) ==
+ ISC_R_SUCCESS)
+ {
+ ca_file = cfg_obj_asstring(ca_obj);
+ }
+
+ if (cfg_map_get(tlsmap, "protocols", &tls_proto_list) ==
+ ISC_R_SUCCESS)
+ {
+ const cfg_listelt_t *proto = NULL;
+ INSIST(tls_proto_list != NULL);
+ for (proto = cfg_list_first(tls_proto_list);
+ proto != 0; proto = cfg_list_next(proto))
+ {
+ const cfg_obj_t *tls_proto_obj =
+ cfg_listelt_value(proto);
+ const char *tls_sver =
+ cfg_obj_asstring(tls_proto_obj);
+ const isc_tls_protocol_version_t ver =
+ isc_tls_protocol_name_to_version(
+ tls_sver);
+
+ INSIST(ver !=
+ ISC_TLS_PROTO_VER_UNDEFINED);
+ INSIST(isc_tls_protocol_supported(ver));
+ tls_protos |= ver;
+ }
+ }
+
+ if (cfg_map_get(tlsmap, "dhparam-file", &dhparam_obj) ==
+ ISC_R_SUCCESS)
+ {
+ dhparam_file = cfg_obj_asstring(dhparam_obj);
+ }
+
+ if (cfg_map_get(tlsmap, "ciphers", &ciphers_obj) ==
+ ISC_R_SUCCESS)
+ {
+ ciphers = cfg_obj_asstring(ciphers_obj);
+ }
+
+ if (cfg_map_get(tlsmap, "prefer-server-ciphers",
+ &prefer_server_ciphers_obj) ==
+ ISC_R_SUCCESS)
+ {
+ tls_prefer_server_ciphers = cfg_obj_asboolean(
+ prefer_server_ciphers_obj);
+ tls_prefer_server_ciphers_set = true;
+ }
+
+ if (cfg_map_get(tlsmap, "session-tickets",
+ &session_tickets_obj) == ISC_R_SUCCESS)
+ {
+ tls_session_tickets =
+ cfg_obj_asboolean(session_tickets_obj);
+ tls_session_tickets_set = true;
+ }
+ }
+ }
+
+ tls_params = (ns_listen_tls_params_t){
+ .name = tlsname,
+ .key = key,
+ .cert = cert,
+ .ca_file = ca_file,
+ .protocols = tls_protos,
+ .dhparam_file = dhparam_file,
+ .ciphers = ciphers,
+ .prefer_server_ciphers = tls_prefer_server_ciphers,
+ .prefer_server_ciphers_set = tls_prefer_server_ciphers_set,
+ .session_tickets = tls_session_tickets,
+ .session_tickets_set = tls_session_tickets_set
+ };
+
+ httpobj = cfg_tuple_get(ltup, "http");
+ if (httpobj != NULL && cfg_obj_isstring(httpobj)) {
+ const char *httpname = cfg_obj_asstring(httpobj);
+
+ if (!do_tls && !no_tls) {
+ return (ISC_R_FAILURE);
+ }
+
+ http_server = find_maplist(config, "http", httpname);
+ if (http_server == NULL && strcasecmp(httpname, "default") != 0)
+ {
+ cfg_obj_log(httpobj, named_g_lctx, ISC_LOG_ERROR,
+ "http '%s' is not defined",
+ cfg_obj_asstring(httpobj));
+ return (ISC_R_FAILURE);
+ }
+
+ http = true;
+ }
+
+ portobj = cfg_tuple_get(ltup, "port");
+ if (!cfg_obj_isuint32(portobj)) {
+ if (http && do_tls) {
+ if (named_g_httpsport != 0) {
+ port = named_g_httpsport;
+ } else {
+ result = named_config_getport(
+ config, "https-port", &port);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ } else if (http && !do_tls) {
+ if (named_g_httpport != 0) {
+ port = named_g_httpport;
+ } else {
+ result = named_config_getport(
+ config, "http-port", &port);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ } else if (do_tls) {
+ if (named_g_tlsport != 0) {
+ port = named_g_tlsport;
+ } else {
+ result = named_config_getport(
+ config, "tls-port", &port);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ } else {
+ if (named_g_port != 0) {
+ port = named_g_port;
+ } else {
+ result = named_config_getport(config, "port",
+ &port);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ }
+ } else {
+ if (cfg_obj_asuint32(portobj) >= UINT16_MAX) {
+ return (ISC_R_RANGE);
+ }
+ port = (in_port_t)cfg_obj_asuint32(portobj);
+ }
+
+#ifdef HAVE_LIBNGHTTP2
+ if (http) {
+ CHECK(listenelt_http(http_server, family, do_tls, &tls_params,
+ tlsctx_cache, port, mctx, &delt));
+ }
+#endif /* HAVE_LIBNGHTTP2 */
+
+ if (!http) {
+ CHECK(ns_listenelt_create(mctx, port, NULL, family, do_tls,
+ &tls_params, tlsctx_cache, &delt));
+ }
+
+ result = cfg_acl_fromconfig2(cfg_tuple_get(listener, "acl"), config,
+ named_g_lctx, actx, mctx, 0, family,
+ &delt->acl);
+ if (result != ISC_R_SUCCESS) {
+ ns_listenelt_destroy(delt);
+ return (result);
+ }
+ *target = delt;
+
+cleanup:
+ return (result);
+}
+
+#ifdef HAVE_LIBNGHTTP2
+static isc_result_t
+listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls,
+ const ns_listen_tls_params_t *tls_params,
+ isc_tlsctx_cache_t *tlsctx_cache, in_port_t port,
+ isc_mem_t *mctx, ns_listenelt_t **target) {
+ isc_result_t result = ISC_R_SUCCESS;
+ ns_listenelt_t *delt = NULL;
+ char **endpoints = NULL;
+ const cfg_obj_t *eplist = NULL;
+ const cfg_listelt_t *elt = NULL;
+ size_t len = 1, i = 0;
+ uint32_t max_clients = named_g_http_listener_clients;
+ uint32_t max_streams = named_g_http_streams_per_conn;
+
+ REQUIRE(target != NULL && *target == NULL);
+
+ if (tls) {
+ INSIST(tls_params != NULL);
+ INSIST((tls_params->key == NULL) == (tls_params->cert == NULL));
+ }
+
+ if (port == 0) {
+ port = tls ? named_g_httpsport : named_g_httpport;
+ }
+
+ /*
+ * If "default" was used, we set up the default endpoint
+ * of "/dns-query".
+ */
+ if (http != NULL) {
+ const cfg_obj_t *cfg_max_clients = NULL;
+ const cfg_obj_t *cfg_max_streams = NULL;
+
+ if (cfg_map_get(http, "endpoints", &eplist) == ISC_R_SUCCESS) {
+ INSIST(eplist != NULL);
+ len = cfg_list_length(eplist, false);
+ }
+
+ if (cfg_map_get(http, "listener-clients", &cfg_max_clients) ==
+ ISC_R_SUCCESS)
+ {
+ INSIST(cfg_max_clients != NULL);
+ max_clients = cfg_obj_asuint32(cfg_max_clients);
+ }
+
+ if (cfg_map_get(http, "streams-per-connection",
+ &cfg_max_streams) == ISC_R_SUCCESS)
+ {
+ INSIST(cfg_max_streams != NULL);
+ max_streams = cfg_obj_asuint32(cfg_max_streams);
+ }
+ }
+
+ endpoints = isc_mem_allocate(mctx, sizeof(endpoints[0]) * len);
+
+ if (http != NULL && eplist != NULL) {
+ for (elt = cfg_list_first(eplist); elt != NULL;
+ elt = cfg_list_next(elt))
+ {
+ const cfg_obj_t *ep = cfg_listelt_value(elt);
+ const char *path = cfg_obj_asstring(ep);
+ endpoints[i++] = isc_mem_strdup(mctx, path);
+ }
+ } else {
+ endpoints[i++] = isc_mem_strdup(mctx, ISC_NM_HTTP_DEFAULT_PATH);
+ }
+
+ INSIST(i == len);
+
+ result = ns_listenelt_create_http(mctx, port, NULL, family, tls,
+ tls_params, tlsctx_cache, endpoints,
+ len, max_clients, max_streams, &delt);
+ if (result != ISC_R_SUCCESS) {
+ goto error;
+ }
+
+ *target = delt;
+
+ return (result);
+error:
+ if (delt != NULL) {
+ ns_listenelt_destroy(delt);
+ }
+ return (result);
+}
+#endif /* HAVE_LIBNGHTTP2 */
+
+isc_result_t
+named_server_dumpstats(named_server_t *server) {
+ isc_result_t result;
+ FILE *fp = NULL;
+
+ CHECKMF(isc_stdio_open(server->statsfile, "a", &fp),
+ "could not open statistics dump file", server->statsfile);
+
+ result = named_stats_dump(server, fp);
+
+cleanup:
+ if (fp != NULL) {
+ (void)isc_stdio_close(fp);
+ }
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumpstats complete");
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumpstats failed: %s",
+ isc_result_totext(result));
+ }
+ return (result);
+}
+
+static isc_result_t
+add_zone_tolist(dns_zone_t *zone, void *uap) {
+ struct dumpcontext *dctx = uap;
+ struct zonelistentry *zle;
+
+ zle = isc_mem_get(dctx->mctx, sizeof *zle);
+ zle->zone = NULL;
+ dns_zone_attach(zone, &zle->zone);
+ ISC_LINK_INIT(zle, link);
+ ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
+ struct viewlistentry *vle;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ /*
+ * Prevent duplicate views.
+ */
+ for (vle = ISC_LIST_HEAD(dctx->viewlist); vle != NULL;
+ vle = ISC_LIST_NEXT(vle, link))
+ {
+ if (vle->view == view) {
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ vle = isc_mem_get(dctx->mctx, sizeof *vle);
+ vle->view = NULL;
+ dns_view_attach(view, &vle->view);
+ ISC_LINK_INIT(vle, link);
+ ISC_LIST_INIT(vle->zonelist);
+ ISC_LIST_APPEND(dctx->viewlist, vle, link);
+ if (dctx->dumpzones) {
+ result = dns_zt_apply(view->zonetable, isc_rwlocktype_read,
+ true, NULL, add_zone_tolist, dctx);
+ }
+ return (result);
+}
+
+static void
+dumpcontext_destroy(struct dumpcontext *dctx) {
+ struct viewlistentry *vle;
+ struct zonelistentry *zle;
+
+ vle = ISC_LIST_HEAD(dctx->viewlist);
+ while (vle != NULL) {
+ ISC_LIST_UNLINK(dctx->viewlist, vle, link);
+ zle = ISC_LIST_HEAD(vle->zonelist);
+ while (zle != NULL) {
+ ISC_LIST_UNLINK(vle->zonelist, zle, link);
+ dns_zone_detach(&zle->zone);
+ isc_mem_put(dctx->mctx, zle, sizeof *zle);
+ zle = ISC_LIST_HEAD(vle->zonelist);
+ }
+ dns_view_detach(&vle->view);
+ isc_mem_put(dctx->mctx, vle, sizeof *vle);
+ vle = ISC_LIST_HEAD(dctx->viewlist);
+ }
+ if (dctx->version != NULL) {
+ dns_db_closeversion(dctx->db, &dctx->version, false);
+ }
+ if (dctx->db != NULL) {
+ dns_db_detach(&dctx->db);
+ }
+ if (dctx->cache != NULL) {
+ dns_db_detach(&dctx->cache);
+ }
+ if (dctx->task != NULL) {
+ isc_task_detach(&dctx->task);
+ }
+ if (dctx->fp != NULL) {
+ (void)isc_stdio_close(dctx->fp);
+ }
+ if (dctx->mdctx != NULL) {
+ dns_dumpctx_detach(&dctx->mdctx);
+ }
+ isc_mem_put(dctx->mctx, dctx, sizeof *dctx);
+}
+
+static void
+dumpdone(void *arg, isc_result_t result) {
+ struct dumpcontext *dctx = arg;
+ char buf[1024 + 32];
+ const dns_master_style_t *style;
+
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ if (dctx->mdctx != NULL) {
+ dns_dumpctx_detach(&dctx->mdctx);
+ }
+ if (dctx->view == NULL) {
+ dctx->view = ISC_LIST_HEAD(dctx->viewlist);
+ if (dctx->view == NULL) {
+ goto done;
+ }
+ INSIST(dctx->zone == NULL);
+ } else {
+ goto resume;
+ }
+nextview:
+ fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name);
+resume:
+ if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) {
+ fprintf(dctx->fp, ";\n; Cache of view '%s' is shared as '%s'\n",
+ dctx->view->view->name,
+ dns_cache_getname(dctx->view->view->cache));
+ } else if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache)
+ {
+ if (dctx->dumpexpired) {
+ style = &dns_master_style_cache_with_expired;
+ } else {
+ style = &dns_master_style_cache;
+ }
+ /* start cache dump */
+ if (dctx->view->view->cachedb != NULL) {
+ dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
+ }
+ if (dctx->cache != NULL) {
+ fprintf(dctx->fp,
+ ";\n; Cache dump of view '%s' (cache %s)\n;\n",
+ dctx->view->view->name,
+ dns_cache_getname(dctx->view->view->cache));
+ result = dns_master_dumptostreamasync(
+ dctx->mctx, dctx->cache, NULL, style, dctx->fp,
+ dctx->task, dumpdone, dctx, &dctx->mdctx);
+ if (result == DNS_R_CONTINUE) {
+ return;
+ }
+ if (result == ISC_R_NOTIMPLEMENTED) {
+ fprintf(dctx->fp, "; %s\n",
+ isc_result_totext(result));
+ } else if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ }
+ }
+
+ if ((dctx->dumpadb || dctx->dumpbad || dctx->dumpfail) &&
+ dctx->cache == NULL && dctx->view->view->cachedb != NULL)
+ {
+ dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
+ }
+
+ if (dctx->cache != NULL) {
+ if (dctx->dumpadb) {
+ dns_adb_dump(dctx->view->view->adb, dctx->fp);
+ }
+ if (dctx->dumpbad) {
+ dns_resolver_printbadcache(dctx->view->view->resolver,
+ dctx->fp);
+ }
+ if (dctx->dumpfail) {
+ dns_badcache_print(dctx->view->view->failcache,
+ "SERVFAIL cache", dctx->fp);
+ }
+ dns_db_detach(&dctx->cache);
+ }
+ if (dctx->dumpzones) {
+ style = &dns_master_style_full;
+ nextzone:
+ if (dctx->version != NULL) {
+ dns_db_closeversion(dctx->db, &dctx->version, false);
+ }
+ if (dctx->db != NULL) {
+ dns_db_detach(&dctx->db);
+ }
+ if (dctx->zone == NULL) {
+ dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist);
+ } else {
+ dctx->zone = ISC_LIST_NEXT(dctx->zone, link);
+ }
+ if (dctx->zone != NULL) {
+ /* start zone dump */
+ dns_zone_name(dctx->zone->zone, buf, sizeof(buf));
+ fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf);
+ result = dns_zone_getdb(dctx->zone->zone, &dctx->db);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(dctx->fp, "; %s\n",
+ isc_result_totext(result));
+ goto nextzone;
+ }
+ dns_db_currentversion(dctx->db, &dctx->version);
+ result = dns_master_dumptostreamasync(
+ dctx->mctx, dctx->db, dctx->version, style,
+ dctx->fp, dctx->task, dumpdone, dctx,
+ &dctx->mdctx);
+ if (result == DNS_R_CONTINUE) {
+ return;
+ }
+ if (result == ISC_R_NOTIMPLEMENTED) {
+ fprintf(dctx->fp, "; %s\n",
+ isc_result_totext(result));
+ result = ISC_R_SUCCESS;
+ POST(result);
+ goto nextzone;
+ }
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ }
+ }
+ if (dctx->view != NULL) {
+ dctx->view = ISC_LIST_NEXT(dctx->view, link);
+ if (dctx->view != NULL) {
+ goto nextview;
+ }
+ }
+done:
+ fprintf(dctx->fp, "; Dump complete\n");
+ result = isc_stdio_flush(dctx->fp);
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumpdb complete");
+ }
+cleanup:
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumpdb failed: %s", isc_result_totext(result));
+ }
+ dumpcontext_destroy(dctx);
+}
+
+isc_result_t
+named_server_dumpdb(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ struct dumpcontext *dctx = NULL;
+ dns_view_t *view;
+ isc_result_t result;
+ char *ptr;
+ const char *sep;
+ bool found;
+
+ REQUIRE(text != NULL);
+
+ /* Skip the command name. */
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ dctx = isc_mem_get(server->mctx, sizeof(*dctx));
+
+ dctx->mctx = server->mctx;
+ dctx->dumpcache = true;
+ dctx->dumpadb = true;
+ dctx->dumpbad = true;
+ dctx->dumpexpired = false;
+ dctx->dumpfail = true;
+ dctx->dumpzones = false;
+ dctx->fp = NULL;
+ ISC_LIST_INIT(dctx->viewlist);
+ dctx->view = NULL;
+ dctx->zone = NULL;
+ dctx->cache = NULL;
+ dctx->mdctx = NULL;
+ dctx->db = NULL;
+ dctx->cache = NULL;
+ dctx->task = NULL;
+ dctx->version = NULL;
+ isc_task_attach(server->task, &dctx->task);
+
+ CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp),
+ "could not open dump file", server->dumpfile);
+
+ ptr = next_token(lex, NULL);
+ sep = (ptr == NULL) ? "" : ": ";
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumpdb started%s%s", sep, (ptr != NULL) ? ptr : "");
+
+ if (ptr != NULL && strcmp(ptr, "-all") == 0) {
+ /* also dump zones */
+ dctx->dumpzones = true;
+ ptr = next_token(lex, NULL);
+ } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) {
+ /* this is the default */
+ ptr = next_token(lex, NULL);
+ } else if (ptr != NULL && strcmp(ptr, "-expired") == 0) {
+ /* this is the same as -cache but includes expired data */
+ dctx->dumpexpired = true;
+ ptr = next_token(lex, NULL);
+ } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) {
+ /* only dump zones, suppress caches */
+ dctx->dumpadb = false;
+ dctx->dumpbad = false;
+ dctx->dumpcache = false;
+ dctx->dumpfail = false;
+ dctx->dumpzones = true;
+ ptr = next_token(lex, NULL);
+ } else if (ptr != NULL && strcmp(ptr, "-adb") == 0) {
+ /* only dump adb, suppress other caches */
+ dctx->dumpbad = false;
+ dctx->dumpcache = false;
+ dctx->dumpfail = false;
+ ptr = next_token(lex, NULL);
+ } else if (ptr != NULL && strcmp(ptr, "-bad") == 0) {
+ /* only dump badcache, suppress other caches */
+ dctx->dumpadb = false;
+ dctx->dumpcache = false;
+ dctx->dumpfail = false;
+ ptr = next_token(lex, NULL);
+ } else if (ptr != NULL && strcmp(ptr, "-fail") == 0) {
+ /* only dump servfail cache, suppress other caches */
+ dctx->dumpadb = false;
+ dctx->dumpbad = false;
+ dctx->dumpcache = false;
+ ptr = next_token(lex, NULL);
+ }
+
+nextview:
+ found = false;
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (ptr != NULL && strcmp(view->name, ptr) != 0) {
+ continue;
+ }
+ found = true;
+ CHECK(add_view_tolist(dctx, view));
+ }
+ if (ptr != NULL) {
+ if (!found) {
+ CHECK(putstr(text, "view '"));
+ CHECK(putstr(text, ptr));
+ CHECK(putstr(text, "' not found"));
+ CHECK(putnull(text));
+ result = ISC_R_NOTFOUND;
+ dumpdone(dctx, result);
+ return (result);
+ }
+ ptr = next_token(lex, NULL);
+ if (ptr != NULL) {
+ goto nextview;
+ }
+ }
+ dumpdone(dctx, ISC_R_SUCCESS);
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ dumpcontext_destroy(dctx);
+ return (result);
+}
+
+isc_result_t
+named_server_dumpsecroots(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ dns_view_t *view;
+ dns_keytable_t *secroots = NULL;
+ dns_ntatable_t *ntatable = NULL;
+ isc_result_t result;
+ char *ptr;
+ FILE *fp = NULL;
+ isc_time_t now;
+ char tbuf[64];
+ unsigned int used = isc_buffer_usedlength(*text);
+ bool first = true;
+
+ REQUIRE(text != NULL);
+
+ /* Skip the command name. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* "-" here means print the output instead of dumping to file */
+ ptr = next_token(lex, text);
+ if (ptr != NULL && strcmp(ptr, "-") == 0) {
+ ptr = next_token(lex, text);
+ } else {
+ result = isc_stdio_open(server->secrootsfile, "w", &fp);
+ if (result != ISC_R_SUCCESS) {
+ (void)putstr(text, "could not open ");
+ (void)putstr(text, server->secrootsfile);
+ CHECKMF(result, "could not open secroots dump file",
+ server->secrootsfile);
+ }
+ }
+
+ TIME_NOW(&now);
+ isc_time_formattimestamp(&now, tbuf, sizeof(tbuf));
+ CHECK(putstr(text, "secure roots as of "));
+ CHECK(putstr(text, tbuf));
+ CHECK(putstr(text, ":\n"));
+ used = isc_buffer_usedlength(*text);
+
+ do {
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (ptr != NULL && strcmp(view->name, ptr) != 0) {
+ continue;
+ }
+ if (secroots != NULL) {
+ dns_keytable_detach(&secroots);
+ }
+ result = dns_view_getsecroots(view, &secroots);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ continue;
+ }
+ if (first || used != isc_buffer_usedlength(*text)) {
+ CHECK(putstr(text, "\n"));
+ first = false;
+ }
+ CHECK(putstr(text, " Start view "));
+ CHECK(putstr(text, view->name));
+ CHECK(putstr(text, "\n Secure roots:\n\n"));
+ used = isc_buffer_usedlength(*text);
+ CHECK(dns_keytable_totext(secroots, text));
+
+ if (ntatable != NULL) {
+ dns_ntatable_detach(&ntatable);
+ }
+ result = dns_view_getntatable(view, &ntatable);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ continue;
+ }
+ if (used != isc_buffer_usedlength(*text)) {
+ CHECK(putstr(text, "\n"));
+ }
+ CHECK(putstr(text, " Negative trust anchors:\n\n"));
+ used = isc_buffer_usedlength(*text);
+ CHECK(dns_ntatable_totext(ntatable, NULL, text));
+ }
+
+ if (ptr != NULL) {
+ ptr = next_token(lex, text);
+ }
+ } while (ptr != NULL);
+
+cleanup:
+ if (secroots != NULL) {
+ dns_keytable_detach(&secroots);
+ }
+ if (ntatable != NULL) {
+ dns_ntatable_detach(&ntatable);
+ }
+
+ if (fp != NULL) {
+ if (used != isc_buffer_usedlength(*text)) {
+ (void)putstr(text, "\n");
+ }
+ fprintf(fp, "%.*s", (int)isc_buffer_usedlength(*text),
+ (char *)isc_buffer_base(*text));
+ isc_buffer_clear(*text);
+ (void)isc_stdio_close(fp);
+ } else if (isc_buffer_usedlength(*text) > 0) {
+ (void)putnull(text);
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumpsecroots complete");
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumpsecroots failed: %s",
+ isc_result_totext(result));
+ }
+ return (result);
+}
+
+isc_result_t
+named_server_dumprecursing(named_server_t *server) {
+ FILE *fp = NULL;
+ dns_view_t *view;
+ isc_result_t result;
+
+ CHECKMF(isc_stdio_open(server->recfile, "w", &fp),
+ "could not open dump file", server->recfile);
+ fprintf(fp, ";\n; Recursing Queries\n;\n");
+ ns_interfacemgr_dumprecursing(fp, server->interfacemgr);
+
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ fprintf(fp, ";\n; Active fetch domains [view: %s]\n;\n",
+ view->name);
+ dns_resolver_dumpfetches(view->resolver, isc_statsformat_file,
+ fp);
+ }
+
+ fprintf(fp, "; Dump complete\n");
+
+cleanup:
+ if (fp != NULL) {
+ result = isc_stdio_close(fp);
+ }
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumprecursing complete");
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumprecursing failed: %s",
+ isc_result_totext(result));
+ }
+ return (result);
+}
+
+isc_result_t
+named_server_setdebuglevel(named_server_t *server, isc_lex_t *lex) {
+ char *ptr;
+ char *endp;
+ long newlevel;
+
+ UNUSED(server);
+
+ /* Skip the command name. */
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* Look for the new level name. */
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ if (named_g_debuglevel < 99) {
+ named_g_debuglevel++;
+ }
+ } else {
+ newlevel = strtol(ptr, &endp, 10);
+ if (*endp != '\0' || newlevel < 0 || newlevel > 99) {
+ return (ISC_R_RANGE);
+ }
+ named_g_debuglevel = (unsigned int)newlevel;
+ }
+ isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "debug level is now %u", named_g_debuglevel);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+named_server_validation(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ char *ptr;
+ dns_view_t *view;
+ bool changed = false;
+ isc_result_t result;
+ bool enable = true, set = true, first = true;
+
+ REQUIRE(text != NULL);
+
+ /* Skip the command name. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* Find out what we are to do. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") ||
+ !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true"))
+ {
+ enable = true;
+ } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") ||
+ !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false"))
+ {
+ enable = false;
+ } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) {
+ set = false;
+ } else {
+ return (DNS_R_SYNTAX);
+ }
+
+ /* Look for the view name. */
+ ptr = next_token(lex, text);
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if ((ptr != NULL && strcasecmp(ptr, view->name) != 0) ||
+ strcasecmp("_bind", view->name) == 0)
+ {
+ continue;
+ }
+
+ if (set) {
+ CHECK(dns_view_flushcache(view, false));
+ view->enablevalidation = enable;
+ changed = true;
+ } else {
+ if (!first) {
+ CHECK(putstr(text, "\n"));
+ }
+ CHECK(putstr(text, "DNSSEC validation is "));
+ CHECK(putstr(text, view->enablevalidation
+ ? "enabled"
+ : "disabled"));
+ CHECK(putstr(text, " (view "));
+ CHECK(putstr(text, view->name));
+ CHECK(putstr(text, ")"));
+ first = false;
+ }
+ }
+ CHECK(putnull(text));
+
+ if (!set) {
+ result = ISC_R_SUCCESS;
+ } else if (changed) {
+ result = ISC_R_SUCCESS;
+ } else {
+ result = ISC_R_FAILURE;
+ }
+cleanup:
+ isc_task_endexclusive(server->task);
+ return (result);
+}
+
+isc_result_t
+named_server_flushcache(named_server_t *server, isc_lex_t *lex) {
+ char *ptr;
+ dns_view_t *view;
+ bool flushed;
+ bool found;
+ isc_result_t result;
+ named_cache_t *nsc;
+
+ /* Skip the command name. */
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* Look for the view name. */
+ ptr = next_token(lex, NULL);
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ flushed = true;
+ found = false;
+
+ /*
+ * Flushing a cache is tricky when caches are shared by multiple views.
+ * We first identify which caches should be flushed in the local cache
+ * list, flush these caches, and then update other views that refer to
+ * the flushed cache DB.
+ */
+ if (ptr != NULL) {
+ /*
+ * Mark caches that need to be flushed. This is an O(#view^2)
+ * operation in the very worst case, but should be normally
+ * much more lightweight because only a few (most typically just
+ * one) views will match.
+ */
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (strcasecmp(ptr, view->name) != 0) {
+ continue;
+ }
+ found = true;
+ for (nsc = ISC_LIST_HEAD(server->cachelist);
+ nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link))
+ {
+ if (nsc->cache == view->cache) {
+ break;
+ }
+ }
+ INSIST(nsc != NULL);
+ nsc->needflush = true;
+ }
+ } else {
+ found = true;
+ }
+
+ /* Perform flush */
+ for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL;
+ nsc = ISC_LIST_NEXT(nsc, link))
+ {
+ if (ptr != NULL && !nsc->needflush) {
+ continue;
+ }
+ nsc->needflush = true;
+ result = dns_view_flushcache(nsc->primaryview, false);
+ if (result != ISC_R_SUCCESS) {
+ flushed = false;
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "flushing cache in view '%s' failed: %s",
+ nsc->primaryview->name,
+ isc_result_totext(result));
+ }
+ }
+
+ /*
+ * Fix up views that share a flushed cache: let the views update the
+ * cache DB they're referring to. This could also be an expensive
+ * operation, but should typically be marginal: the inner loop is only
+ * necessary for views that share a cache, and if there are many such
+ * views the number of shared cache should normally be small.
+ * A worst case is that we have n views and n/2 caches, each shared by
+ * two views. Then this will be a O(n^2/4) operation.
+ */
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (!dns_view_iscacheshared(view)) {
+ continue;
+ }
+ for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL;
+ nsc = ISC_LIST_NEXT(nsc, link))
+ {
+ if (!nsc->needflush || nsc->cache != view->cache) {
+ continue;
+ }
+ result = dns_view_flushcache(view, true);
+ if (result != ISC_R_SUCCESS) {
+ flushed = false;
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "fixing cache in view '%s' "
+ "failed: %s",
+ view->name, isc_result_totext(result));
+ }
+ }
+ }
+
+ /* Cleanup the cache list. */
+ for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL;
+ nsc = ISC_LIST_NEXT(nsc, link))
+ {
+ nsc->needflush = false;
+ }
+
+ if (flushed && found) {
+ if (ptr != NULL) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing cache in view '%s' succeeded",
+ ptr);
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing caches in all views succeeded");
+ }
+ result = ISC_R_SUCCESS;
+ } else {
+ if (!found) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "flushing cache in view '%s' failed: "
+ "view not found",
+ ptr);
+ result = ISC_R_NOTFOUND;
+ } else {
+ result = ISC_R_FAILURE;
+ }
+ }
+ isc_task_endexclusive(server->task);
+ return (result);
+}
+
+isc_result_t
+named_server_flushnode(named_server_t *server, isc_lex_t *lex, bool tree) {
+ char *ptr, *viewname;
+ char target[DNS_NAME_FORMATSIZE];
+ dns_view_t *view;
+ bool flushed;
+ bool found;
+ isc_result_t result;
+ isc_buffer_t b;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+
+ /* Skip the command name. */
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* Find the domain name to flush. */
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ strlcpy(target, ptr, DNS_NAME_FORMATSIZE);
+ isc_buffer_constinit(&b, target, strlen(target));
+ isc_buffer_add(&b, strlen(target));
+ name = dns_fixedname_initname(&fixed);
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ /* Look for the view name. */
+ viewname = next_token(lex, NULL);
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ flushed = true;
+ found = false;
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (viewname != NULL && strcasecmp(viewname, view->name) != 0) {
+ continue;
+ }
+ found = true;
+ /*
+ * It's a little inefficient to try flushing name for all views
+ * if some of the views share a single cache. But since the
+ * operation is lightweight we prefer simplicity here.
+ */
+ result = dns_view_flushnode(view, name, tree);
+ if (result != ISC_R_SUCCESS) {
+ flushed = false;
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "flushing %s '%s' in cache view '%s' "
+ "failed: %s",
+ tree ? "tree" : "name", target,
+ view->name, isc_result_totext(result));
+ }
+ }
+ if (flushed && found) {
+ if (viewname != NULL) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing %s '%s' in cache view '%s' "
+ "succeeded",
+ tree ? "tree" : "name", target, viewname);
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing %s '%s' in all cache views "
+ "succeeded",
+ tree ? "tree" : "name", target);
+ }
+ result = ISC_R_SUCCESS;
+ } else {
+ if (!found) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "flushing %s '%s' in cache view '%s' "
+ "failed: view not found",
+ tree ? "tree" : "name", target, viewname);
+ }
+ result = ISC_R_FAILURE;
+ }
+ isc_task_endexclusive(server->task);
+ return (result);
+}
+
+isc_result_t
+named_server_status(named_server_t *server, isc_buffer_t **text) {
+ isc_result_t result;
+ unsigned int zonecount, xferrunning, xferdeferred, soaqueries;
+ unsigned int automatic;
+ const char *ob = "", *cb = "", *alt = "";
+ char boottime[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ char configtime[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ char line[1024], hostname[256];
+ named_reload_t reload_status;
+
+ REQUIRE(text != NULL);
+
+ if (named_g_server->version_set) {
+ ob = " (";
+ cb = ")";
+ if (named_g_server->version == NULL) {
+ alt = "version.bind/txt/ch disabled";
+ } else {
+ alt = named_g_server->version;
+ }
+ }
+ zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY);
+ xferrunning = dns_zonemgr_getcount(server->zonemgr,
+ DNS_ZONESTATE_XFERRUNNING);
+ xferdeferred = dns_zonemgr_getcount(server->zonemgr,
+ DNS_ZONESTATE_XFERDEFERRED);
+ soaqueries = dns_zonemgr_getcount(server->zonemgr,
+ DNS_ZONESTATE_SOAQUERY);
+ automatic = dns_zonemgr_getcount(server->zonemgr,
+ DNS_ZONESTATE_AUTOMATIC);
+
+ isc_time_formathttptimestamp(&named_g_boottime, boottime,
+ sizeof(boottime));
+ isc_time_formathttptimestamp(&named_g_configtime, configtime,
+ sizeof(configtime));
+
+ snprintf(line, sizeof(line), "version: %s%s <id:%s>%s%s%s\n",
+ PACKAGE_STRING, PACKAGE_DESCRIPTION, PACKAGE_SRCID, ob, alt,
+ cb);
+ CHECK(putstr(text, line));
+
+ if (gethostname(hostname, sizeof(hostname)) == 0) {
+ strlcpy(hostname, "localhost", sizeof(hostname));
+ }
+ snprintf(line, sizeof(line), "running on %s: %s\n", hostname,
+ named_os_uname());
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "boot time: %s\n", boottime);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "last configured: %s\n", configtime);
+ CHECK(putstr(text, line));
+
+ if (named_g_chrootdir != NULL) {
+ snprintf(line, sizeof(line), "configuration file: %s (%s%s)\n",
+ named_g_conffile, named_g_chrootdir, named_g_conffile);
+ } else {
+ snprintf(line, sizeof(line), "configuration file: %s\n",
+ named_g_conffile);
+ }
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "CPUs found: %u\n", named_g_cpus_detected);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "worker threads: %u\n", named_g_cpus);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "UDP listeners per interface: %u\n",
+ named_g_udpdisp);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "number of zones: %u (%u automatic)\n",
+ zonecount, automatic);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "debug level: %u\n", named_g_debuglevel);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "xfers running: %u\n", xferrunning);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "xfers deferred: %u\n", xferdeferred);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "soa queries in progress: %u\n",
+ soaqueries);
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "query logging is %s\n",
+ ns_server_getoption(server->sctx, NS_SERVER_LOGQUERIES)
+ ? "ON"
+ : "OFF");
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "recursive clients: %u/%u/%u\n",
+ isc_quota_getused(&server->sctx->recursionquota),
+ isc_quota_getsoft(&server->sctx->recursionquota),
+ isc_quota_getmax(&server->sctx->recursionquota));
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "tcp clients: %u/%u\n",
+ isc_quota_getused(&server->sctx->tcpquota),
+ isc_quota_getmax(&server->sctx->tcpquota));
+ CHECK(putstr(text, line));
+
+ snprintf(line, sizeof(line), "TCP high-water: %u\n",
+ (unsigned)ns_stats_get_counter(server->sctx->nsstats,
+ ns_statscounter_tcphighwater));
+ CHECK(putstr(text, line));
+
+ reload_status = atomic_load(&server->reload_status);
+ if (reload_status != NAMED_RELOAD_DONE) {
+ snprintf(line, sizeof(line), "reload/reconfig %s\n",
+ (reload_status == NAMED_RELOAD_FAILED
+ ? "failed"
+ : "in progress"));
+ CHECK(putstr(text, line));
+ }
+
+ CHECK(putstr(text, "server is up and running"));
+ CHECK(putnull(text));
+
+ return (ISC_R_SUCCESS);
+cleanup:
+ return (result);
+}
+
+isc_result_t
+named_server_testgen(isc_lex_t *lex, isc_buffer_t **text) {
+ isc_result_t result;
+ char *ptr;
+ unsigned long count;
+ unsigned long i;
+ const unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789";
+
+ REQUIRE(text != NULL);
+
+ /* Skip the command name. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ count = 26;
+ } else {
+ count = strtoul(ptr, NULL, 10);
+ }
+
+ CHECK(isc_buffer_reserve(text, count));
+ for (i = 0; i < count; i++) {
+ CHECK(putuint8(text, chars[i % (sizeof(chars) - 1)]));
+ }
+
+ CHECK(putnull(text));
+
+cleanup:
+ return (result);
+}
+
+static isc_result_t
+delete_keynames(dns_tsig_keyring_t *ring, char *target,
+ unsigned int *foundkeys) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ isc_result_t result;
+ dns_rbtnodechain_t chain;
+ dns_name_t foundname;
+ dns_fixedname_t fixedorigin;
+ dns_name_t *origin;
+ dns_rbtnode_t *node;
+ dns_tsigkey_t *tkey;
+
+ dns_name_init(&foundname, NULL);
+ origin = dns_fixedname_initname(&fixedorigin);
+
+again:
+ dns_rbtnodechain_init(&chain);
+ result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, origin);
+ if (result == ISC_R_NOTFOUND) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+ }
+
+ for (;;) {
+ node = NULL;
+ dns_rbtnodechain_current(&chain, &foundname, origin, &node);
+ tkey = node->data;
+
+ if (tkey != NULL) {
+ if (!tkey->generated) {
+ goto nextkey;
+ }
+
+ dns_name_format(&tkey->name, namestr, sizeof(namestr));
+ if (strcmp(namestr, target) == 0) {
+ (*foundkeys)++;
+ dns_rbtnodechain_invalidate(&chain);
+ (void)dns_rbt_deletename(ring->keys,
+ &tkey->name, false);
+ goto again;
+ }
+ }
+
+ nextkey:
+ result = dns_rbtnodechain_next(&chain, &foundname, origin);
+ if (result == ISC_R_NOMORE) {
+ break;
+ }
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+named_server_tsigdelete(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result;
+ dns_view_t *view;
+ unsigned int foundkeys = 0;
+ char *ptr, *viewname;
+ char target[DNS_NAME_FORMATSIZE];
+ char fbuf[16];
+
+ REQUIRE(text != NULL);
+
+ (void)next_token(lex, text); /* skip command name */
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ strlcpy(target, ptr, DNS_NAME_FORMATSIZE);
+
+ viewname = next_token(lex, text);
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (viewname == NULL || strcmp(view->name, viewname) == 0) {
+ RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_write);
+ result = delete_keynames(view->dynamickeys, target,
+ &foundkeys);
+ RWUNLOCK(&view->dynamickeys->lock,
+ isc_rwlocktype_write);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_endexclusive(server->task);
+ return (result);
+ }
+ }
+ }
+ isc_task_endexclusive(server->task);
+
+ snprintf(fbuf, sizeof(fbuf), "%u", foundkeys);
+
+ CHECK(putstr(text, fbuf));
+ CHECK(putstr(text, " tsig keys deleted."));
+ CHECK(putnull(text));
+
+cleanup:
+ return (result);
+}
+
+static isc_result_t
+list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t **text,
+ unsigned int *foundkeys) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char creatorstr[DNS_NAME_FORMATSIZE];
+ isc_result_t result;
+ dns_rbtnodechain_t chain;
+ dns_name_t foundname;
+ dns_fixedname_t fixedorigin;
+ dns_name_t *origin;
+ dns_rbtnode_t *node;
+ dns_tsigkey_t *tkey;
+ const char *viewname;
+
+ if (view != NULL) {
+ viewname = view->name;
+ } else {
+ viewname = "(global)";
+ }
+
+ dns_name_init(&foundname, NULL);
+ origin = dns_fixedname_initname(&fixedorigin);
+ dns_rbtnodechain_init(&chain);
+ result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, origin);
+ if (result == ISC_R_NOTFOUND) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+ }
+
+ for (;;) {
+ node = NULL;
+ dns_rbtnodechain_current(&chain, &foundname, origin, &node);
+ tkey = node->data;
+
+ if (tkey != NULL) {
+ dns_name_format(&tkey->name, namestr, sizeof(namestr));
+ if (tkey->generated) {
+ dns_name_format(tkey->creator, creatorstr,
+ sizeof(creatorstr));
+ if (*foundkeys != 0) {
+ CHECK(putstr(text, "\n"));
+ }
+ CHECK(putstr(text, "view \""));
+ CHECK(putstr(text, viewname));
+ CHECK(putstr(text, "\"; type \"dynamic\"; key "
+ "\""));
+ CHECK(putstr(text, namestr));
+ CHECK(putstr(text, "\"; creator \""));
+ CHECK(putstr(text, creatorstr));
+ CHECK(putstr(text, "\";"));
+ } else {
+ if (*foundkeys != 0) {
+ CHECK(putstr(text, "\n"));
+ }
+ CHECK(putstr(text, "view \""));
+ CHECK(putstr(text, viewname));
+ CHECK(putstr(text, "\"; type \"static\"; key "
+ "\""));
+ CHECK(putstr(text, namestr));
+ CHECK(putstr(text, "\";"));
+ }
+ (*foundkeys)++;
+ }
+ result = dns_rbtnodechain_next(&chain, &foundname, origin);
+ if (result == ISC_R_NOMORE || result == DNS_R_NEWORIGIN) {
+ break;
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+cleanup:
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+}
+
+isc_result_t
+named_server_tsiglist(named_server_t *server, isc_buffer_t **text) {
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_view_t *view;
+ unsigned int foundkeys = 0;
+
+ REQUIRE(text != NULL);
+
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ RWLOCK(&view->statickeys->lock, isc_rwlocktype_read);
+ result = list_keynames(view, view->statickeys, text,
+ &foundkeys);
+ RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
+ result = list_keynames(view, view->dynamickeys, text,
+ &foundkeys);
+ RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ if (foundkeys == 0) {
+ CHECK(putstr(text, "no tsig keys found."));
+ }
+
+ if (isc_buffer_usedlength(*text) > 0) {
+ CHECK(putnull(text));
+ }
+
+cleanup:
+ return (result);
+}
+
+/*
+ * Act on a "sign" or "loadkeys" command from the command channel.
+ */
+isc_result_t
+named_server_rekey(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result;
+ dns_zone_t *zone = NULL;
+ dns_zonetype_t type;
+ uint16_t keyopts;
+ bool fullsign = false;
+ char *ptr;
+
+ REQUIRE(text != NULL);
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ if (strcasecmp(ptr, NAMED_COMMAND_SIGN) == 0) {
+ fullsign = true;
+ }
+
+ REQUIRE(text != NULL);
+
+ result = zone_from_args(server, lex, NULL, &zone, NULL, text, false);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ if (zone == NULL) {
+ return (ISC_R_UNEXPECTEDEND); /* XXX: or do all zones? */
+ }
+
+ type = dns_zone_gettype(zone);
+ if (type != dns_zone_primary) {
+ dns_zone_detach(&zone);
+ return (DNS_R_NOTPRIMARY);
+ }
+
+ keyopts = dns_zone_getkeyopts(zone);
+
+ /*
+ * "rndc loadkeys" requires "auto-dnssec maintain"
+ * or a "dnssec-policy".
+ */
+ if ((keyopts & DNS_ZONEKEY_ALLOW) == 0) {
+ result = ISC_R_NOPERM;
+ } else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign) {
+ result = ISC_R_NOPERM;
+ } else {
+ dns_zone_rekey(zone, fullsign);
+ }
+
+ dns_zone_detach(&zone);
+ return (result);
+}
+
+/*
+ * Act on a "sync" command from the command channel.
+ */
+static isc_result_t
+synczone(dns_zone_t *zone, void *uap) {
+ bool cleanup = *(bool *)uap;
+ isc_result_t result;
+ dns_zone_t *raw = NULL;
+ char *journal;
+
+ dns_zone_getraw(zone, &raw);
+ if (raw != NULL) {
+ synczone(raw, uap);
+ dns_zone_detach(&raw);
+ }
+
+ result = dns_zone_flush(zone);
+ if (result != ISC_R_SUCCESS) {
+ cleanup = false;
+ }
+ if (cleanup) {
+ journal = dns_zone_getjournal(zone);
+ if (journal != NULL) {
+ (void)isc_file_remove(journal);
+ }
+ }
+
+ return (result);
+}
+
+isc_result_t
+named_server_sync(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) {
+ isc_result_t result, tresult;
+ dns_view_t *view;
+ dns_zone_t *zone = NULL;
+ char classstr[DNS_RDATACLASS_FORMATSIZE];
+ char zonename[DNS_NAME_FORMATSIZE];
+ const char *vname, *sep, *arg;
+ bool cleanup = false;
+
+ REQUIRE(text != NULL);
+
+ (void)next_token(lex, text);
+
+ arg = next_token(lex, text);
+ if (arg != NULL &&
+ (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0))
+ {
+ cleanup = true;
+ arg = next_token(lex, text);
+ }
+
+ REQUIRE(text != NULL);
+
+ result = zone_from_args(server, lex, arg, &zone, NULL, text, false);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ if (zone == NULL) {
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ tresult = ISC_R_SUCCESS;
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ result = dns_zt_apply(view->zonetable,
+ isc_rwlocktype_none, false, NULL,
+ synczone, &cleanup);
+ if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS)
+ {
+ tresult = result;
+ }
+ }
+ isc_task_endexclusive(server->task);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumping all zones%s: %s",
+ cleanup ? ", removing journal files" : "",
+ isc_result_totext(result));
+ return (tresult);
+ }
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = synczone(zone, &cleanup);
+ isc_task_endexclusive(server->task);
+
+ view = dns_zone_getview(zone);
+ if (strcmp(view->name, "_default") == 0 ||
+ strcmp(view->name, "_bind") == 0)
+ {
+ vname = "";
+ sep = "";
+ } else {
+ vname = view->name;
+ sep = " ";
+ }
+ dns_rdataclass_format(dns_zone_getclass(zone), classstr,
+ sizeof(classstr));
+ dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename));
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "sync: dumping zone '%s/%s'%s%s%s: %s", zonename,
+ classstr, sep, vname, cleanup ? ", removing journal file" : "",
+ isc_result_totext(result));
+ dns_zone_detach(&zone);
+ return (result);
+}
+
+/*
+ * Act on a "freeze" or "thaw" command from the command channel.
+ */
+isc_result_t
+named_server_freeze(named_server_t *server, bool freeze, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result, tresult;
+ dns_zone_t *mayberaw = NULL, *raw = NULL;
+ dns_zonetype_t type;
+ char classstr[DNS_RDATACLASS_FORMATSIZE];
+ char zonename[DNS_NAME_FORMATSIZE];
+ dns_view_t *view;
+ const char *vname, *sep;
+ bool frozen;
+ const char *msg = NULL;
+
+ REQUIRE(text != NULL);
+
+ result = zone_from_args(server, lex, NULL, &mayberaw, NULL, text, true);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ if (mayberaw == NULL) {
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ tresult = ISC_R_SUCCESS;
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ result = dns_view_freezezones(view, freeze);
+ if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS)
+ {
+ tresult = result;
+ }
+ }
+ isc_task_endexclusive(server->task);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "%s all zones: %s",
+ freeze ? "freezing" : "thawing",
+ isc_result_totext(tresult));
+ return (tresult);
+ }
+ dns_zone_getraw(mayberaw, &raw);
+ if (raw != NULL) {
+ dns_zone_detach(&mayberaw);
+ dns_zone_attach(raw, &mayberaw);
+ dns_zone_detach(&raw);
+ }
+ type = dns_zone_gettype(mayberaw);
+ if (type != dns_zone_primary) {
+ dns_zone_detach(&mayberaw);
+ return (DNS_R_NOTPRIMARY);
+ }
+
+ if (freeze && !dns_zone_isdynamic(mayberaw, true)) {
+ dns_zone_detach(&mayberaw);
+ return (DNS_R_NOTDYNAMIC);
+ }
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ frozen = dns_zone_getupdatedisabled(mayberaw);
+ if (freeze) {
+ if (frozen) {
+ msg = "WARNING: The zone was already frozen.\n"
+ "Someone else may be editing it or "
+ "it may still be re-loading.";
+ result = DNS_R_FROZEN;
+ }
+ if (result == ISC_R_SUCCESS) {
+ result = dns_zone_flush(mayberaw);
+ if (result != ISC_R_SUCCESS) {
+ msg = "Flushing the zone updates to "
+ "disk failed.";
+ }
+ }
+ if (result == ISC_R_SUCCESS) {
+ dns_zone_setupdatedisabled(mayberaw, freeze);
+ }
+ } else {
+ if (frozen) {
+ result = dns_zone_loadandthaw(mayberaw);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_UPTODATE:
+ msg = "The zone reload and thaw was "
+ "successful.";
+ result = ISC_R_SUCCESS;
+ break;
+ case DNS_R_CONTINUE:
+ msg = "A zone reload and thaw was started.\n"
+ "Check the logs to see the result.";
+ result = ISC_R_SUCCESS;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ isc_task_endexclusive(server->task);
+
+ if (msg != NULL) {
+ (void)putstr(text, msg);
+ (void)putnull(text);
+ }
+
+ view = dns_zone_getview(mayberaw);
+ if (strcmp(view->name, "_default") == 0 ||
+ strcmp(view->name, "_bind") == 0)
+ {
+ vname = "";
+ sep = "";
+ } else {
+ vname = view->name;
+ sep = " ";
+ }
+ dns_rdataclass_format(dns_zone_getclass(mayberaw), classstr,
+ sizeof(classstr));
+ dns_name_format(dns_zone_getorigin(mayberaw), zonename,
+ sizeof(zonename));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "%s zone '%s/%s'%s%s: %s",
+ freeze ? "freezing" : "thawing", zonename, classstr, sep,
+ vname, isc_result_totext(result));
+ dns_zone_detach(&mayberaw);
+ return (result);
+}
+
+#ifdef HAVE_LIBSCF
+/*
+ * This function adds a message for rndc to echo if named
+ * is managed by smf and is also running chroot.
+ */
+isc_result_t
+named_smf_add_message(isc_buffer_t **text) {
+ REQUIRE(text != NULL);
+
+ return (putstr(text, "use svcadm(1M) to manage named"));
+}
+#endif /* HAVE_LIBSCF */
+
+#ifndef HAVE_LMDB
+
+/*
+ * Emit a comment at the top of the nzf file containing the viewname
+ * Expects the fp to already be open for writing
+ */
+#define HEADER1 "# New zone file for view: "
+#define HEADER2 \
+ "\n# This file contains configuration for zones added by\n" \
+ "# the 'rndc addzone' command. DO NOT EDIT BY HAND.\n"
+static isc_result_t
+add_comment(FILE *fp, const char *viewname) {
+ isc_result_t result;
+ CHECK(isc_stdio_write(HEADER1, sizeof(HEADER1) - 1, 1, fp, NULL));
+ CHECK(isc_stdio_write(viewname, strlen(viewname), 1, fp, NULL));
+ CHECK(isc_stdio_write(HEADER2, sizeof(HEADER2) - 1, 1, fp, NULL));
+cleanup:
+ return (result);
+}
+
+static void
+dumpzone(void *arg, const char *buf, int len) {
+ FILE *fp = arg;
+
+ (void)isc_stdio_write(buf, len, 1, fp, NULL);
+}
+
+static isc_result_t
+nzf_append(dns_view_t *view, const cfg_obj_t *zconfig) {
+ isc_result_t result;
+ off_t offset;
+ FILE *fp = NULL;
+ bool offsetok = false;
+
+ LOCK(&view->new_zone_lock);
+
+ CHECK(isc_stdio_open(view->new_zone_file, "a", &fp));
+ CHECK(isc_stdio_seek(fp, 0, SEEK_END));
+
+ CHECK(isc_stdio_tell(fp, &offset));
+ offsetok = true;
+ if (offset == 0) {
+ CHECK(add_comment(fp, view->name));
+ }
+
+ CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL));
+ cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp);
+ CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL));
+ CHECK(isc_stdio_flush(fp));
+ result = isc_stdio_close(fp);
+ fp = NULL;
+
+cleanup:
+ if (fp != NULL) {
+ (void)isc_stdio_close(fp);
+ if (offsetok) {
+ isc_result_t result2;
+
+ result2 = isc_file_truncate(view->new_zone_file,
+ offset);
+ if (result2 != ISC_R_SUCCESS) {
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "Error truncating NZF file '%s' "
+ "during rollback from append: "
+ "%s",
+ view->new_zone_file,
+ isc_result_totext(result2));
+ }
+ }
+ }
+ UNLOCK(&view->new_zone_lock);
+ return (result);
+}
+
+static isc_result_t
+nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) {
+ const cfg_obj_t *zl = NULL;
+ cfg_list_t *list;
+ const cfg_listelt_t *elt;
+
+ FILE *fp = NULL;
+ char tmp[1024];
+ isc_result_t result;
+
+ result = isc_file_template(view->new_zone_file, "nzf-XXXXXXXX", tmp,
+ sizeof(tmp));
+ if (result == ISC_R_SUCCESS) {
+ result = isc_file_openunique(tmp, &fp);
+ }
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ cfg_map_get(config, "zone", &zl);
+ if (!cfg_obj_islist(zl)) {
+ CHECK(ISC_R_FAILURE);
+ }
+
+ DE_CONST(&zl->value.list, list);
+
+ CHECK(add_comment(fp, view->name)); /* force a comment */
+
+ for (elt = ISC_LIST_HEAD(*list); elt != NULL;
+ elt = ISC_LIST_NEXT(elt, link))
+ {
+ const cfg_obj_t *zconfig = cfg_listelt_value(elt);
+
+ CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL));
+ cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp);
+ CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL));
+ }
+
+ CHECK(isc_stdio_flush(fp));
+ result = isc_stdio_close(fp);
+ fp = NULL;
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ CHECK(isc_file_rename(tmp, view->new_zone_file));
+ return (result);
+
+cleanup:
+ if (fp != NULL) {
+ (void)isc_stdio_close(fp);
+ }
+ (void)isc_file_remove(tmp);
+ return (result);
+}
+
+#else /* HAVE_LMDB */
+
+static void
+nzd_setkey(MDB_val *key, dns_name_t *name, char *namebuf, size_t buflen) {
+ dns_fixedname_t fixed;
+
+ dns_fixedname_init(&fixed);
+ dns_name_downcase(name, dns_fixedname_name(&fixed), NULL);
+ dns_name_format(dns_fixedname_name(&fixed), namebuf, buflen);
+
+ key->mv_data = namebuf;
+ key->mv_size = strlen(namebuf);
+}
+
+static void
+dumpzone(void *arg, const char *buf, int len) {
+ ns_dzarg_t *dzarg = arg;
+ isc_result_t result;
+
+ REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC));
+
+ result = putmem(dzarg->text, buf, len);
+ if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) {
+ dzarg->result = result;
+ }
+}
+
+static isc_result_t
+nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone,
+ const cfg_obj_t *zconfig) {
+ isc_result_t result;
+ int status;
+ dns_view_t *view;
+ bool commit = false;
+ isc_buffer_t *text = NULL;
+ char namebuf[1024];
+ MDB_val key, data;
+ ns_dzarg_t dzarg;
+
+ view = dns_zone_getview(zone);
+
+ nzd_setkey(&key, dns_zone_getorigin(zone), namebuf, sizeof(namebuf));
+
+ if (zconfig == NULL) {
+ /* We're deleting the zone from the database */
+ status = mdb_del(*txnp, dbi, &key, NULL);
+ if (status != MDB_SUCCESS && status != MDB_NOTFOUND) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "Error deleting zone %s "
+ "from NZD database: %s",
+ namebuf, mdb_strerror(status));
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ } else if (status != MDB_NOTFOUND) {
+ commit = true;
+ }
+ } else {
+ /* We're creating or overwriting the zone */
+ const cfg_obj_t *zoptions;
+
+ isc_buffer_allocate(view->mctx, &text, 256);
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+ if (zoptions == NULL) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "Unable to get options from config in "
+ "nzd_save()");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ dzarg.magic = DZARG_MAGIC;
+ dzarg.text = &text;
+ dzarg.result = ISC_R_SUCCESS;
+ cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg);
+ if (dzarg.result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "Error writing zone config to "
+ "buffer in nzd_save(): %s",
+ isc_result_totext(dzarg.result));
+ result = dzarg.result;
+ goto cleanup;
+ }
+
+ data.mv_data = isc_buffer_base(text);
+ data.mv_size = isc_buffer_usedlength(text);
+
+ status = mdb_put(*txnp, dbi, &key, &data, 0);
+ if (status != MDB_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "Error inserting zone in "
+ "NZD database: %s",
+ mdb_strerror(status));
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ commit = true;
+ }
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (!commit || result != ISC_R_SUCCESS) {
+ (void)mdb_txn_abort(*txnp);
+ } else {
+ status = mdb_txn_commit(*txnp);
+ if (status != MDB_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "Error committing "
+ "NZD database: %s",
+ mdb_strerror(status));
+ result = ISC_R_FAILURE;
+ }
+ }
+ *txnp = NULL;
+
+ if (text != NULL) {
+ isc_buffer_free(&text);
+ }
+
+ return (result);
+}
+
+/*
+ * Check whether the new zone database for 'view' can be opened for writing.
+ *
+ * Caller must hold 'view->new_zone_lock'.
+ */
+static isc_result_t
+nzd_writable(dns_view_t *view) {
+ isc_result_t result = ISC_R_SUCCESS;
+ int status;
+ MDB_dbi dbi;
+ MDB_txn *txn = NULL;
+
+ REQUIRE(view != NULL);
+
+ status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, 0, &txn);
+ if (status != MDB_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "mdb_txn_begin: %s", mdb_strerror(status));
+ return (ISC_R_FAILURE);
+ }
+
+ status = mdb_dbi_open(txn, NULL, 0, &dbi);
+ if (status != MDB_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "mdb_dbi_open: %s", mdb_strerror(status));
+ result = ISC_R_FAILURE;
+ }
+
+ mdb_txn_abort(txn);
+ return (result);
+}
+
+/*
+ * Open the new zone database for 'view' and start a transaction for it.
+ *
+ * Caller must hold 'view->new_zone_lock'.
+ */
+static isc_result_t
+nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) {
+ int status;
+ MDB_txn *txn = NULL;
+
+ REQUIRE(view != NULL);
+ REQUIRE(txnp != NULL && *txnp == NULL);
+ REQUIRE(dbi != NULL);
+
+ status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, flags, &txn);
+ if (status != MDB_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "mdb_txn_begin: %s", mdb_strerror(status));
+ goto cleanup;
+ }
+
+ status = mdb_dbi_open(txn, NULL, 0, dbi);
+ if (status != MDB_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "mdb_dbi_open: %s", mdb_strerror(status));
+ goto cleanup;
+ }
+
+ *txnp = txn;
+
+cleanup:
+ if (status != MDB_SUCCESS) {
+ if (txn != NULL) {
+ mdb_txn_abort(txn);
+ }
+ return (ISC_R_FAILURE);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * nzd_env_close() and nzd_env_reopen are a kluge to address the
+ * problem of an NZD file possibly being created before we drop
+ * root privileges.
+ */
+static void
+nzd_env_close(dns_view_t *view) {
+ const char *dbpath = NULL;
+ char dbpath_copy[PATH_MAX];
+ char lockpath[PATH_MAX];
+ int status, ret;
+
+ if (view->new_zone_dbenv == NULL) {
+ return;
+ }
+
+ status = mdb_env_get_path(view->new_zone_dbenv, &dbpath);
+ INSIST(status == MDB_SUCCESS);
+ snprintf(lockpath, sizeof(lockpath), "%s-lock", dbpath);
+ strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy));
+ mdb_env_close((MDB_env *)view->new_zone_dbenv);
+
+ /*
+ * Database files must be owned by the eventual user, not by root.
+ */
+ ret = chown(dbpath_copy, ns_os_uid(), -1);
+ UNUSED(ret);
+
+ /*
+ * Some platforms need the lockfile not to exist when we reopen the
+ * environment.
+ */
+ (void)isc_file_remove(lockpath);
+
+ view->new_zone_dbenv = NULL;
+}
+
+static isc_result_t
+nzd_env_reopen(dns_view_t *view) {
+ isc_result_t result;
+ MDB_env *env = NULL;
+ int status;
+
+ if (view->new_zone_db == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+
+ nzd_env_close(view);
+
+ status = mdb_env_create(&env);
+ if (status != MDB_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
+ "mdb_env_create failed: %s",
+ mdb_strerror(status));
+ CHECK(ISC_R_FAILURE);
+ }
+
+ if (view->new_zone_mapsize != 0ULL) {
+ status = mdb_env_set_mapsize(env, view->new_zone_mapsize);
+ if (status != MDB_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
+ "mdb_env_set_mapsize failed: %s",
+ mdb_strerror(status));
+ CHECK(ISC_R_FAILURE);
+ }
+ }
+
+ status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600);
+ if (status != MDB_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
+ "mdb_env_open of '%s' failed: %s",
+ view->new_zone_db, mdb_strerror(status));
+ CHECK(ISC_R_FAILURE);
+ }
+
+ view->new_zone_dbenv = env;
+ env = NULL;
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (env != NULL) {
+ mdb_env_close(env);
+ }
+ return (result);
+}
+
+/*
+ * If 'commit' is true, commit the new zone database transaction pointed to by
+ * 'txnp'; otherwise, abort that transaction.
+ *
+ * Caller must hold 'view->new_zone_lock' for the view that the transaction
+ * pointed to by 'txnp' was started for.
+ */
+static isc_result_t
+nzd_close(MDB_txn **txnp, bool commit) {
+ isc_result_t result = ISC_R_SUCCESS;
+ int status;
+
+ REQUIRE(txnp != NULL);
+
+ if (*txnp != NULL) {
+ if (commit) {
+ status = mdb_txn_commit(*txnp);
+ if (status != MDB_SUCCESS) {
+ result = ISC_R_FAILURE;
+ }
+ } else {
+ mdb_txn_abort(*txnp);
+ }
+ *txnp = NULL;
+ }
+
+ return (result);
+}
+
+/*
+ * Count the zones configured in the new zone database for 'view' and store the
+ * result in 'countp'.
+ *
+ * Caller must hold 'view->new_zone_lock'.
+ */
+static isc_result_t
+nzd_count(dns_view_t *view, int *countp) {
+ isc_result_t result;
+ int status;
+ MDB_txn *txn = NULL;
+ MDB_dbi dbi;
+ MDB_stat statbuf;
+
+ REQUIRE(countp != NULL);
+
+ result = nzd_open(view, MDB_RDONLY, &txn, &dbi);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ status = mdb_stat(txn, dbi, &statbuf);
+ if (status != MDB_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "mdb_stat: %s", mdb_strerror(status));
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ *countp = statbuf.ms_entries;
+
+cleanup:
+ (void)nzd_close(&txn, false);
+
+ return (result);
+}
+
+/*
+ * Migrate zone configuration from an NZF file to an NZD database.
+ * Caller must hold view->new_zone_lock.
+ */
+static isc_result_t
+migrate_nzf(dns_view_t *view) {
+ isc_result_t result;
+ cfg_obj_t *nzf_config = NULL;
+ int status, n;
+ isc_buffer_t *text = NULL;
+ bool commit = false;
+ const cfg_obj_t *zonelist;
+ const cfg_listelt_t *element;
+ char tempname[PATH_MAX];
+ MDB_txn *txn = NULL;
+ MDB_dbi dbi;
+ MDB_val key, data;
+ ns_dzarg_t dzarg;
+
+ /*
+ * If NZF file doesn't exist, or NZD DB exists and already
+ * has data, return without attempting migration.
+ */
+ if (!isc_file_exists(view->new_zone_file)) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+ result = nzd_count(view, &n);
+ if (result == ISC_R_SUCCESS && n > 0) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "Migrating zones from NZF file '%s' to "
+ "NZD database '%s'",
+ view->new_zone_file, view->new_zone_db);
+ /*
+ * Instead of blindly copying lines, we parse the NZF file using
+ * the configuration parser, because it validates it against the
+ * config type, giving us a guarantee that valid configuration
+ * will be written to DB.
+ */
+ cfg_parser_reset(named_g_addparser);
+ result = cfg_parse_file(named_g_addparser, view->new_zone_file,
+ &cfg_type_addzoneconf, &nzf_config);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "Error parsing NZF file '%s': %s",
+ view->new_zone_file, isc_result_totext(result));
+ goto cleanup;
+ }
+
+ zonelist = NULL;
+ CHECK(cfg_map_get(nzf_config, "zone", &zonelist));
+ if (!cfg_obj_islist(zonelist)) {
+ CHECK(ISC_R_FAILURE);
+ }
+
+ CHECK(nzd_open(view, 0, &txn, &dbi));
+
+ isc_buffer_allocate(view->mctx, &text, 256);
+
+ for (element = cfg_list_first(zonelist); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *zconfig;
+ const cfg_obj_t *zoptions;
+ char zname[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ const char *origin;
+ isc_buffer_t b;
+
+ zconfig = cfg_listelt_value(element);
+
+ origin = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+ if (origin == NULL) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ /* Normalize zone name */
+ isc_buffer_constinit(&b, origin, strlen(origin));
+ isc_buffer_add(&b, strlen(origin));
+ name = dns_fixedname_initname(&fname);
+ CHECK(dns_name_fromtext(name, &b, dns_rootname,
+ DNS_NAME_DOWNCASE, NULL));
+ dns_name_format(name, zname, sizeof(zname));
+
+ key.mv_data = zname;
+ key.mv_size = strlen(zname);
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+ if (zoptions == NULL) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ isc_buffer_clear(text);
+ dzarg.magic = DZARG_MAGIC;
+ dzarg.text = &text;
+ dzarg.result = ISC_R_SUCCESS;
+ cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg);
+ if (dzarg.result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "Error writing zone config to "
+ "buffer in migrate_nzf(): %s",
+ isc_result_totext(result));
+ result = dzarg.result;
+ goto cleanup;
+ }
+
+ data.mv_data = isc_buffer_base(text);
+ data.mv_size = isc_buffer_usedlength(text);
+
+ status = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE);
+ if (status != MDB_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "Error inserting zone in "
+ "NZD database: %s",
+ mdb_strerror(status));
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ commit = true;
+ }
+
+ result = ISC_R_SUCCESS;
+
+ /*
+ * Leaving the NZF file in place is harmless as we won't use it
+ * if an NZD database is found for the view. But we rename NZF file
+ * to a backup name here.
+ */
+ strlcpy(tempname, view->new_zone_file, sizeof(tempname));
+ if (strlen(tempname) < sizeof(tempname) - 1) {
+ strlcat(tempname, "~", sizeof(tempname));
+ isc_file_rename(view->new_zone_file, tempname);
+ }
+
+cleanup:
+ if (result != ISC_R_SUCCESS) {
+ (void)nzd_close(&txn, false);
+ } else {
+ result = nzd_close(&txn, commit);
+ }
+
+ if (text != NULL) {
+ isc_buffer_free(&text);
+ }
+
+ if (nzf_config != NULL) {
+ cfg_obj_destroy(named_g_addparser, &nzf_config);
+ }
+
+ return (result);
+}
+
+#endif /* HAVE_LMDB */
+
+static isc_result_t
+newzone_parse(named_server_t *server, char *command, dns_view_t **viewp,
+ cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp,
+ bool *redirectp, isc_buffer_t **text) {
+ isc_result_t result;
+ isc_buffer_t argbuf;
+ bool redirect = false;
+ cfg_obj_t *zoneconf = NULL;
+ const cfg_obj_t *zlist = NULL;
+ const cfg_obj_t *zoneobj = NULL;
+ const cfg_obj_t *zoptions = NULL;
+ const cfg_obj_t *obj = NULL;
+ const char *viewname = NULL;
+ dns_rdataclass_t rdclass;
+ dns_view_t *view = NULL;
+ const char *bn = NULL;
+
+ REQUIRE(viewp != NULL && *viewp == NULL);
+ REQUIRE(zoneobjp != NULL && *zoneobjp == NULL);
+ REQUIRE(zoneconfp != NULL && *zoneconfp == NULL);
+ REQUIRE(redirectp != NULL);
+
+ /* Try to parse the argument string */
+ isc_buffer_init(&argbuf, command, (unsigned int)strlen(command));
+ isc_buffer_add(&argbuf, strlen(command));
+
+ if (strncasecmp(command, "add", 3) == 0) {
+ bn = "addzone";
+ } else if (strncasecmp(command, "mod", 3) == 0) {
+ bn = "modzone";
+ } else {
+ UNREACHABLE();
+ }
+
+ /*
+ * Convert the "addzone" or "modzone" to just "zone", for
+ * the benefit of the parser
+ */
+ isc_buffer_forward(&argbuf, 3);
+
+ cfg_parser_reset(named_g_addparser);
+ CHECK(cfg_parse_buffer(named_g_addparser, &argbuf, bn, 0,
+ &cfg_type_addzoneconf, 0, &zoneconf));
+ CHECK(cfg_map_get(zoneconf, "zone", &zlist));
+ if (!cfg_obj_islist(zlist)) {
+ CHECK(ISC_R_FAILURE);
+ }
+
+ /* For now we only support adding one zone at a time */
+ zoneobj = cfg_listelt_value(cfg_list_first(zlist));
+
+ /* Check the zone type for ones that are not supported by addzone. */
+ zoptions = cfg_tuple_get(zoneobj, "options");
+
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "type", &obj);
+ if (obj == NULL) {
+ (void)cfg_map_get(zoptions, "in-view", &obj);
+ if (obj != NULL) {
+ (void)putstr(text, "'in-view' zones not supported by ");
+ (void)putstr(text, bn);
+ } else {
+ (void)putstr(text, "zone type not specified");
+ }
+ CHECK(ISC_R_FAILURE);
+ }
+
+ if (strcasecmp(cfg_obj_asstring(obj), "hint") == 0 ||
+ strcasecmp(cfg_obj_asstring(obj), "forward") == 0 ||
+ strcasecmp(cfg_obj_asstring(obj), "delegation-only") == 0)
+ {
+ (void)putstr(text, "'");
+ (void)putstr(text, cfg_obj_asstring(obj));
+ (void)putstr(text, "' zones not supported by ");
+ (void)putstr(text, bn);
+ CHECK(ISC_R_FAILURE);
+ }
+
+ if (strcasecmp(cfg_obj_asstring(obj), "redirect") == 0) {
+ redirect = true;
+ }
+
+ /* Make sense of optional class argument */
+ obj = cfg_tuple_get(zoneobj, "class");
+ CHECK(named_config_getclass(obj, dns_rdataclass_in, &rdclass));
+
+ /* Make sense of optional view argument */
+ obj = cfg_tuple_get(zoneobj, "view");
+ if (obj && cfg_obj_isstring(obj)) {
+ viewname = cfg_obj_asstring(obj);
+ }
+ if (viewname == NULL || *viewname == '\0') {
+ viewname = "_default";
+ }
+ result = dns_viewlist_find(&server->viewlist, viewname, rdclass, &view);
+ if (result == ISC_R_NOTFOUND) {
+ (void)putstr(text, "no matching view found for '");
+ (void)putstr(text, viewname);
+ (void)putstr(text, "'");
+ goto cleanup;
+ } else if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ *viewp = view;
+ *zoneobjp = zoneobj;
+ *zoneconfp = zoneconf;
+ *redirectp = redirect;
+
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (zoneconf != NULL) {
+ cfg_obj_destroy(named_g_addparser, &zoneconf);
+ }
+ if (view != NULL) {
+ dns_view_detach(&view);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config,
+ const dns_name_t *zname, nzfwriter_t nzfwriter) {
+ isc_result_t result = ISC_R_NOTFOUND;
+ const cfg_listelt_t *elt = NULL;
+ const cfg_obj_t *zl = NULL;
+ cfg_list_t *list;
+ dns_fixedname_t myfixed;
+ dns_name_t *myname;
+
+ REQUIRE(view != NULL);
+ REQUIRE(pctx != NULL);
+ REQUIRE(config != NULL);
+ REQUIRE(zname != NULL);
+
+ LOCK(&view->new_zone_lock);
+
+ cfg_map_get(config, "zone", &zl);
+
+ if (!cfg_obj_islist(zl)) {
+ CHECK(ISC_R_FAILURE);
+ }
+
+ DE_CONST(&zl->value.list, list);
+
+ myname = dns_fixedname_initname(&myfixed);
+
+ for (elt = ISC_LIST_HEAD(*list); elt != NULL;
+ elt = ISC_LIST_NEXT(elt, link))
+ {
+ const cfg_obj_t *zconf = cfg_listelt_value(elt);
+ const char *zn;
+ cfg_listelt_t *e;
+
+ zn = cfg_obj_asstring(cfg_tuple_get(zconf, "name"));
+ result = dns_name_fromstring(myname, zn, 0, NULL);
+ if (result != ISC_R_SUCCESS || !dns_name_equal(zname, myname)) {
+ continue;
+ }
+
+ DE_CONST(elt, e);
+ ISC_LIST_UNLINK(*list, e, link);
+ cfg_obj_destroy(pctx, &e->obj);
+ isc_mem_put(pctx->mctx, e, sizeof(*e));
+ result = ISC_R_SUCCESS;
+ break;
+ }
+
+ /*
+ * Write config to NZF file if appropriate
+ */
+ if (nzfwriter != NULL && view->new_zone_file != NULL) {
+ result = nzfwriter(config, view);
+ }
+
+cleanup:
+ UNLOCK(&view->new_zone_lock);
+ return (result);
+}
+
+static isc_result_t
+do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
+ dns_name_t *name, cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj,
+ bool redirect, isc_buffer_t **text) {
+ isc_result_t result, tresult;
+ dns_zone_t *zone = NULL;
+#ifndef HAVE_LMDB
+ FILE *fp = NULL;
+ bool cleanup_config = false;
+#else /* HAVE_LMDB */
+ MDB_txn *txn = NULL;
+ MDB_dbi dbi;
+ bool locked = false;
+
+ UNUSED(zoneconf);
+#endif
+
+ /* Zone shouldn't already exist */
+ if (redirect) {
+ result = (view->redirect != NULL) ? ISC_R_SUCCESS
+ : ISC_R_NOTFOUND;
+ } else {
+ result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+ }
+ if (result == ISC_R_SUCCESS) {
+ result = ISC_R_EXISTS;
+ goto cleanup;
+ } else if (result == DNS_R_PARTIALMATCH) {
+ /* Create our sub-zone anyway */
+ dns_zone_detach(&zone);
+ zone = NULL;
+ } else if (result != ISC_R_NOTFOUND) {
+ goto cleanup;
+ }
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+#ifndef HAVE_LMDB
+ /*
+ * Make sure we can open the configuration save file
+ */
+ result = isc_stdio_open(view->new_zone_file, "a", &fp);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_endexclusive(server->task);
+ TCHECK(putstr(text, "unable to create '"));
+ TCHECK(putstr(text, view->new_zone_file));
+ TCHECK(putstr(text, "': "));
+ TCHECK(putstr(text, isc_result_totext(result)));
+ goto cleanup;
+ }
+
+ (void)isc_stdio_close(fp);
+ fp = NULL;
+#else /* HAVE_LMDB */
+ LOCK(&view->new_zone_lock);
+ locked = true;
+ /* Make sure we can open the NZD database */
+ result = nzd_writable(view);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_endexclusive(server->task);
+ TCHECK(putstr(text, "unable to open NZD database for '"));
+ TCHECK(putstr(text, view->new_zone_db));
+ TCHECK(putstr(text, "'"));
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+#endif /* HAVE_LMDB */
+
+ /* Mark view unfrozen and configure zone */
+ dns_view_thaw(view);
+ result = configure_zone(cfg->config, zoneobj, cfg->vconfig,
+ server->mctx, view, &server->viewlist,
+ &server->kasplist, cfg->actx, true, false,
+ false);
+ dns_view_freeze(view);
+
+ isc_task_endexclusive(server->task);
+
+ if (result != ISC_R_SUCCESS) {
+ TCHECK(putstr(text, "configure_zone failed: "));
+ TCHECK(putstr(text, isc_result_totext(result)));
+ goto cleanup;
+ }
+
+ /* Is it there yet? */
+ if (redirect) {
+ if (view->redirect == NULL) {
+ CHECK(ISC_R_NOTFOUND);
+ }
+ dns_zone_attach(view->redirect, &zone);
+ } else {
+ result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "added new zone was not found: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ }
+
+#ifndef HAVE_LMDB
+ /*
+ * If there wasn't a previous newzone config, just save the one
+ * we've created. If there was a previous one, merge the new
+ * zone into it.
+ */
+ if (cfg->nzf_config == NULL) {
+ cfg_obj_attach(zoneconf, &cfg->nzf_config);
+ } else {
+ cfg_obj_t *z;
+ DE_CONST(zoneobj, z);
+ CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z,
+ "zone"));
+ }
+ cleanup_config = true;
+#endif /* HAVE_LMDB */
+
+ /*
+ * Load the zone from the master file. If this fails, we'll
+ * need to undo the configuration we've done already.
+ */
+ result = dns_zone_load(zone, true);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_t *dbp = NULL;
+
+ TCHECK(putstr(text, "dns_zone_loadnew failed: "));
+ TCHECK(putstr(text, isc_result_totext(result)));
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "addzone failed; reverting.");
+
+ /* If the zone loaded partially, unload it */
+ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
+ dns_db_detach(&dbp);
+ dns_zone_unload(zone);
+ }
+
+ /* Remove the zone from the zone table */
+ dns_zt_unmount(view->zonetable, zone);
+ goto cleanup;
+ }
+
+ /* Flag the zone as having been added at runtime */
+ dns_zone_setadded(zone, true);
+
+#ifdef HAVE_LMDB
+ /* Save the new zone configuration into the NZD */
+ CHECK(nzd_open(view, 0, &txn, &dbi));
+ CHECK(nzd_save(&txn, dbi, zone, zoneobj));
+#else /* ifdef HAVE_LMDB */
+ /* Append the zone configuration to the NZF */
+ result = nzf_append(view, zoneobj);
+#endif /* HAVE_LMDB */
+
+cleanup:
+
+#ifndef HAVE_LMDB
+ if (fp != NULL) {
+ (void)isc_stdio_close(fp);
+ }
+ if (result != ISC_R_SUCCESS && cleanup_config) {
+ tresult = delete_zoneconf(view, cfg->add_parser,
+ cfg->nzf_config, name, NULL);
+ RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
+ }
+#else /* HAVE_LMDB */
+ if (txn != NULL) {
+ (void)nzd_close(&txn, false);
+ }
+ if (locked) {
+ UNLOCK(&view->new_zone_lock);
+ }
+#endif /* HAVE_LMDB */
+
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
+ dns_name_t *name, const char *zname, const cfg_obj_t *zoneobj,
+ bool redirect, isc_buffer_t **text) {
+ isc_result_t result, tresult;
+ dns_zone_t *zone = NULL;
+ bool added;
+ bool exclusive = false;
+#ifndef HAVE_LMDB
+ FILE *fp = NULL;
+ cfg_obj_t *z;
+#else /* HAVE_LMDB */
+ MDB_txn *txn = NULL;
+ MDB_dbi dbi;
+ bool locked = false;
+#endif /* HAVE_LMDB */
+
+ /* Zone must already exist */
+ if (redirect) {
+ if (view->redirect != NULL) {
+ dns_zone_attach(view->redirect, &zone);
+ result = ISC_R_SUCCESS;
+ } else {
+ result = ISC_R_NOTFOUND;
+ }
+ } else {
+ result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+ }
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ added = dns_zone_getadded(zone);
+ dns_zone_detach(&zone);
+
+#ifndef HAVE_LMDB
+ cfg = (ns_cfgctx_t *)view->new_zone_config;
+ if (cfg == NULL) {
+ TCHECK(putstr(text, "new zone config is not set"));
+ CHECK(ISC_R_FAILURE);
+ }
+#endif /* ifndef HAVE_LMDB */
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ exclusive = true;
+
+#ifndef HAVE_LMDB
+ /* Make sure we can open the configuration save file */
+ result = isc_stdio_open(view->new_zone_file, "a", &fp);
+ if (result != ISC_R_SUCCESS) {
+ TCHECK(putstr(text, "unable to open '"));
+ TCHECK(putstr(text, view->new_zone_file));
+ TCHECK(putstr(text, "': "));
+ TCHECK(putstr(text, isc_result_totext(result)));
+ goto cleanup;
+ }
+ (void)isc_stdio_close(fp);
+ fp = NULL;
+#else /* HAVE_LMDB */
+ LOCK(&view->new_zone_lock);
+ locked = true;
+ /* Make sure we can open the NZD database */
+ result = nzd_writable(view);
+ if (result != ISC_R_SUCCESS) {
+ TCHECK(putstr(text, "unable to open NZD database for '"));
+ TCHECK(putstr(text, view->new_zone_db));
+ TCHECK(putstr(text, "'"));
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+#endif /* HAVE_LMDB */
+
+ /* Reconfigure the zone */
+ dns_view_thaw(view);
+ result = configure_zone(cfg->config, zoneobj, cfg->vconfig,
+ server->mctx, view, &server->viewlist,
+ &server->kasplist, cfg->actx, true, false,
+ true);
+ dns_view_freeze(view);
+
+ exclusive = false;
+ isc_task_endexclusive(server->task);
+
+ if (result != ISC_R_SUCCESS) {
+ TCHECK(putstr(text, "configure_zone failed: "));
+ TCHECK(putstr(text, isc_result_totext(result)));
+ goto cleanup;
+ }
+
+ /* Is it there yet? */
+ if (redirect) {
+ if (view->redirect == NULL) {
+ CHECK(ISC_R_NOTFOUND);
+ }
+ dns_zone_attach(view->redirect, &zone);
+ } else {
+ CHECK(dns_zt_find(view->zonetable, name, 0, NULL, &zone));
+ }
+
+#ifndef HAVE_LMDB
+ /* Remove old zone from configuration (and NZF file if applicable) */
+ if (added) {
+ result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config,
+ dns_zone_getorigin(zone),
+ nzf_writeconf);
+ if (result != ISC_R_SUCCESS) {
+ TCHECK(putstr(text, "former zone configuration "
+ "not deleted: "));
+ TCHECK(putstr(text, isc_result_totext(result)));
+ goto cleanup;
+ }
+ }
+#endif /* HAVE_LMDB */
+
+ if (!added) {
+ if (cfg->vconfig == NULL) {
+ result = delete_zoneconf(
+ view, cfg->conf_parser, cfg->config,
+ dns_zone_getorigin(zone), NULL);
+ } else {
+ const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig,
+ "options");
+ result = delete_zoneconf(
+ view, cfg->conf_parser, voptions,
+ dns_zone_getorigin(zone), NULL);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ TCHECK(putstr(text, "former zone configuration "
+ "not deleted: "));
+ TCHECK(putstr(text, isc_result_totext(result)));
+ goto cleanup;
+ }
+ }
+
+ /* Load the zone from the master file if it needs reloading. */
+ result = dns_zone_load(zone, true);
+
+ /*
+ * Dynamic zones need no reloading, so we can pass this result.
+ */
+ if (result == DNS_R_DYNAMIC) {
+ result = ISC_R_SUCCESS;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ dns_db_t *dbp = NULL;
+
+ TCHECK(putstr(text, "failed to load zone '"));
+ TCHECK(putstr(text, zname));
+ TCHECK(putstr(text, "': "));
+ TCHECK(putstr(text, isc_result_totext(result)));
+ TCHECK(putstr(text, "\nThe zone is no longer being served. "));
+ TCHECK(putstr(text, "Use 'rndc addzone' to correct\n"));
+ TCHECK(putstr(text, "the problem and restore service."));
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "modzone failed; removing zone.");
+
+ /* If the zone loaded partially, unload it */
+ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
+ dns_db_detach(&dbp);
+ dns_zone_unload(zone);
+ }
+
+ /* Remove the zone from the zone table */
+ dns_zt_unmount(view->zonetable, zone);
+ goto cleanup;
+ }
+
+#ifndef HAVE_LMDB
+ /* Store the new zone configuration; also in NZF if applicable */
+ DE_CONST(zoneobj, z);
+ CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, "zone"));
+#endif /* HAVE_LMDB */
+
+ if (added) {
+#ifdef HAVE_LMDB
+ CHECK(nzd_open(view, 0, &txn, &dbi));
+ CHECK(nzd_save(&txn, dbi, zone, zoneobj));
+#else /* ifdef HAVE_LMDB */
+ result = nzf_append(view, zoneobj);
+ if (result != ISC_R_SUCCESS) {
+ TCHECK(putstr(text, "\nNew zone config not saved: "));
+ TCHECK(putstr(text, isc_result_totext(result)));
+ goto cleanup;
+ }
+#endif /* HAVE_LMDB */
+
+ TCHECK(putstr(text, "zone '"));
+ TCHECK(putstr(text, zname));
+ TCHECK(putstr(text, "' reconfigured."));
+ } else {
+ TCHECK(putstr(text, "zone '"));
+ TCHECK(putstr(text, zname));
+ TCHECK(putstr(text, "' must also be reconfigured in\n"));
+ TCHECK(putstr(text, "named.conf to make changes permanent."));
+ }
+
+cleanup:
+ if (exclusive) {
+ isc_task_endexclusive(server->task);
+ }
+
+#ifndef HAVE_LMDB
+ if (fp != NULL) {
+ (void)isc_stdio_close(fp);
+ }
+#else /* HAVE_LMDB */
+ if (txn != NULL) {
+ (void)nzd_close(&txn, false);
+ }
+ if (locked) {
+ UNLOCK(&view->new_zone_lock);
+ }
+#endif /* HAVE_LMDB */
+
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+
+ return (result);
+}
+
+/*
+ * Act on an "addzone" or "modzone" command from the command channel.
+ */
+isc_result_t
+named_server_changezone(named_server_t *server, char *command,
+ isc_buffer_t **text) {
+ isc_result_t result;
+ bool addzone;
+ bool redirect = false;
+ ns_cfgctx_t *cfg = NULL;
+ cfg_obj_t *zoneconf = NULL;
+ const cfg_obj_t *zoneobj = NULL;
+ const char *zonename;
+ dns_view_t *view = NULL;
+ isc_buffer_t buf;
+ dns_fixedname_t fname;
+ dns_name_t *dnsname;
+
+ REQUIRE(text != NULL);
+
+ if (strncasecmp(command, "add", 3) == 0) {
+ addzone = true;
+ } else {
+ INSIST(strncasecmp(command, "mod", 3) == 0);
+ addzone = false;
+ }
+
+ CHECK(newzone_parse(server, command, &view, &zoneconf, &zoneobj,
+ &redirect, text));
+
+ /* Are we accepting new zones in this view? */
+#ifdef HAVE_LMDB
+ if (view->new_zone_db == NULL)
+#else /* ifdef HAVE_LMDB */
+ if (view->new_zone_file == NULL)
+#endif /* HAVE_LMDB */
+ {
+ (void)putstr(text, "Not allowing new zones in view '");
+ (void)putstr(text, view->name);
+ (void)putstr(text, "'");
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
+
+ cfg = (ns_cfgctx_t *)view->new_zone_config;
+ if (cfg == NULL) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ zonename = cfg_obj_asstring(cfg_tuple_get(zoneobj, "name"));
+ isc_buffer_constinit(&buf, zonename, strlen(zonename));
+ isc_buffer_add(&buf, strlen(zonename));
+
+ dnsname = dns_fixedname_initname(&fname);
+ CHECK(dns_name_fromtext(dnsname, &buf, dns_rootname, 0, NULL));
+
+ if (redirect) {
+ if (!dns_name_equal(dnsname, dns_rootname)) {
+ (void)putstr(text, "redirect zones must be called "
+ "\".\"");
+ CHECK(ISC_R_FAILURE);
+ }
+ }
+
+ if (addzone) {
+ CHECK(do_addzone(server, cfg, view, dnsname, zoneconf, zoneobj,
+ redirect, text));
+ } else {
+ CHECK(do_modzone(server, cfg, view, dnsname, zonename, zoneobj,
+ redirect, text));
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "%s zone %s in view %s via %s",
+ addzone ? "added" : "updated", zonename, view->name,
+ addzone ? NAMED_COMMAND_ADDZONE : NAMED_COMMAND_MODZONE);
+
+ /* Changing a zone counts as reconfiguration */
+ CHECK(isc_time_now(&named_g_configtime));
+
+cleanup:
+ if (isc_buffer_usedlength(*text) > 0) {
+ (void)putnull(text);
+ }
+ if (zoneconf != NULL) {
+ cfg_obj_destroy(named_g_addparser, &zoneconf);
+ }
+ if (view != NULL) {
+ dns_view_detach(&view);
+ }
+
+ return (result);
+}
+
+static bool
+inuse(const char *file, bool first, isc_buffer_t **text) {
+ if (file != NULL && isc_file_exists(file)) {
+ if (first) {
+ (void)putstr(text, "The following files were in use "
+ "and may now be removed:\n");
+ } else {
+ (void)putstr(text, "\n");
+ }
+ (void)putstr(text, file);
+ (void)putnull(text);
+ return (false);
+ }
+ return (first);
+}
+
+typedef struct {
+ dns_zone_t *zone;
+ bool cleanup;
+} ns_dzctx_t;
+
+/*
+ * Carry out a zone deletion scheduled by named_server_delzone().
+ */
+static void
+rmzone(isc_task_t *task, isc_event_t *event) {
+ ns_dzctx_t *dz = (ns_dzctx_t *)event->ev_arg;
+ dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL;
+ dns_catz_zone_t *catz = NULL;
+ char zonename[DNS_NAME_FORMATSIZE];
+ dns_view_t *view = NULL;
+ ns_cfgctx_t *cfg = NULL;
+ dns_db_t *dbp = NULL;
+ bool added;
+ isc_result_t result;
+#ifdef HAVE_LMDB
+ MDB_txn *txn = NULL;
+ MDB_dbi dbi;
+#endif /* ifdef HAVE_LMDB */
+
+ REQUIRE(dz != NULL);
+
+ isc_event_free(&event);
+
+ /* Dig out configuration for this zone */
+ zone = dz->zone;
+ view = dns_zone_getview(zone);
+ cfg = (ns_cfgctx_t *)view->new_zone_config;
+ dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename));
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "deleting zone %s in view %s via delzone", zonename,
+ view->name);
+
+ /*
+ * Remove the zone from configuration (and NZF file if applicable)
+ * (If this is a catalog zone member then nzf_config can be NULL)
+ */
+ added = dns_zone_getadded(zone);
+ catz = dns_zone_get_parentcatz(zone);
+
+ if (added && catz == NULL && cfg != NULL) {
+#ifdef HAVE_LMDB
+ /* Make sure we can open the NZD database */
+ LOCK(&view->new_zone_lock);
+ result = nzd_open(view, 0, &txn, &dbi);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "unable to open NZD database for '%s'",
+ view->new_zone_db);
+ } else {
+ result = nzd_save(&txn, dbi, zone, NULL);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "unable to delete zone configuration: %s",
+ isc_result_totext(result));
+ }
+
+ if (txn != NULL) {
+ (void)nzd_close(&txn, false);
+ }
+ UNLOCK(&view->new_zone_lock);
+#else /* ifdef HAVE_LMDB */
+ result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config,
+ dns_zone_getorigin(zone),
+ nzf_writeconf);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "unable to delete zone configuration: %s",
+ isc_result_totext(result));
+ }
+#endif /* HAVE_LMDB */
+ }
+
+ if (!added && cfg != NULL) {
+ if (cfg->vconfig != NULL) {
+ const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig,
+ "options");
+ result = delete_zoneconf(
+ view, cfg->conf_parser, voptions,
+ dns_zone_getorigin(zone), NULL);
+ } else {
+ result = delete_zoneconf(
+ view, cfg->conf_parser, cfg->config,
+ dns_zone_getorigin(zone), NULL);
+ }
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "unable to delete zone configuration: %s",
+ isc_result_totext(result));
+ }
+ }
+
+ /* Unload zone database */
+ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
+ dns_db_detach(&dbp);
+ dns_zone_unload(zone);
+ }
+
+ /* Clean up stub/secondary zone files if requested to do so */
+ dns_zone_getraw(zone, &raw);
+ mayberaw = (raw != NULL) ? raw : zone;
+
+ if (added && dz->cleanup) {
+ const char *file;
+
+ file = dns_zone_getfile(mayberaw);
+ result = isc_file_remove(file);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "file %s not removed: %s", file,
+ isc_result_totext(result));
+ }
+
+ file = dns_zone_getjournal(mayberaw);
+ result = isc_file_remove(file);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "file %s not removed: %s", file,
+ isc_result_totext(result));
+ }
+
+ if (zone != mayberaw) {
+ file = dns_zone_getfile(zone);
+ result = isc_file_remove(file);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "file %s not removed: %s", file,
+ isc_result_totext(result));
+ }
+
+ file = dns_zone_getjournal(zone);
+ result = isc_file_remove(file);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "file %s not removed: %s", file,
+ isc_result_totext(result));
+ }
+ }
+ }
+
+ if (raw != NULL) {
+ dns_zone_detach(&raw);
+ }
+ dns_zone_detach(&zone);
+ isc_mem_put(named_g_mctx, dz, sizeof(*dz));
+ isc_task_detach(&task);
+}
+
+/*
+ * Act on a "delzone" command from the command channel.
+ */
+isc_result_t
+named_server_delzone(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result, tresult;
+ dns_zone_t *zone = NULL;
+ dns_zone_t *raw = NULL;
+ dns_zone_t *mayberaw;
+ dns_view_t *view = NULL;
+ char zonename[DNS_NAME_FORMATSIZE];
+ bool cleanup = false;
+ const char *ptr;
+ bool added;
+ ns_dzctx_t *dz = NULL;
+ isc_event_t *dzevent = NULL;
+ isc_task_t *task = NULL;
+
+ REQUIRE(text != NULL);
+
+ /* Skip the command name. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* Find out what we are to do. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ if (strcmp(ptr, "-clean") == 0 || strcmp(ptr, "-clear") == 0) {
+ cleanup = true;
+ ptr = next_token(lex, text);
+ }
+
+ CHECK(zone_from_args(server, lex, ptr, &zone, zonename, text, false));
+ if (zone == NULL) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto cleanup;
+ }
+
+ INSIST(zonename != NULL);
+
+ /* Is this a policy zone? */
+ if (dns_zone_get_rpz_num(zone) != DNS_RPZ_INVALID_NUM) {
+ TCHECK(putstr(text, "zone '"));
+ TCHECK(putstr(text, zonename));
+ TCHECK(putstr(text,
+ "' cannot be deleted: response-policy zone."));
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ view = dns_zone_getview(zone);
+ if (dns_zone_gettype(zone) == dns_zone_redirect) {
+ dns_zone_detach(&view->redirect);
+ } else {
+ CHECK(dns_zt_unmount(view->zonetable, zone));
+ }
+
+ /* Send cleanup event */
+ dz = isc_mem_get(named_g_mctx, sizeof(*dz));
+
+ dz->cleanup = cleanup;
+ dz->zone = NULL;
+ dns_zone_attach(zone, &dz->zone);
+ dzevent = isc_event_allocate(named_g_mctx, server, NAMED_EVENT_DELZONE,
+ rmzone, dz, sizeof(isc_event_t));
+
+ dns_zone_gettask(zone, &task);
+ isc_task_send(task, &dzevent);
+ dz = NULL;
+
+ /* Inform user about cleaning up stub/secondary zone files */
+ dns_zone_getraw(zone, &raw);
+ mayberaw = (raw != NULL) ? raw : zone;
+
+ added = dns_zone_getadded(zone);
+ if (!added) {
+ TCHECK(putstr(text, "zone '"));
+ TCHECK(putstr(text, zonename));
+ TCHECK(putstr(text, "' is no longer active and will be "
+ "deleted.\n"));
+ TCHECK(putstr(text, "To keep it from returning "));
+ TCHECK(putstr(text, "when the server is restarted, it\n"));
+ TCHECK(putstr(text, "must also be removed from named.conf."));
+ } else if (cleanup) {
+ TCHECK(putstr(text, "zone '"));
+ TCHECK(putstr(text, zonename));
+ TCHECK(putstr(text, "' and associated files will be deleted."));
+ } else if (dns_zone_gettype(mayberaw) == dns_zone_secondary ||
+ dns_zone_gettype(mayberaw) == dns_zone_mirror ||
+ dns_zone_gettype(mayberaw) == dns_zone_stub)
+ {
+ bool first;
+ const char *file;
+
+ TCHECK(putstr(text, "zone '"));
+ TCHECK(putstr(text, zonename));
+ TCHECK(putstr(text, "' will be deleted."));
+
+ file = dns_zone_getfile(mayberaw);
+ first = inuse(file, true, text);
+
+ file = dns_zone_getjournal(mayberaw);
+ first = inuse(file, first, text);
+
+ if (zone != mayberaw) {
+ file = dns_zone_getfile(zone);
+ first = inuse(file, first, text);
+
+ file = dns_zone_getjournal(zone);
+ (void)inuse(file, first, text);
+ }
+ }
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "zone %s scheduled for removal via delzone", zonename);
+
+ /* Removing a zone counts as reconfiguration */
+ CHECK(isc_time_now(&named_g_configtime));
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (isc_buffer_usedlength(*text) > 0) {
+ (void)putnull(text);
+ }
+ if (raw != NULL) {
+ dns_zone_detach(&raw);
+ }
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+
+ return (result);
+}
+
+static const cfg_obj_t *
+find_name_in_list_from_map(const cfg_obj_t *config,
+ const char *map_key_for_list, const char *name,
+ bool redirect) {
+ const cfg_obj_t *list = NULL;
+ const cfg_listelt_t *element;
+ const cfg_obj_t *obj = NULL;
+ dns_fixedname_t fixed1, fixed2;
+ dns_name_t *name1 = NULL, *name2 = NULL;
+ isc_result_t result;
+
+ if (strcmp(map_key_for_list, "zone") == 0) {
+ name1 = dns_fixedname_initname(&fixed1);
+ name2 = dns_fixedname_initname(&fixed2);
+ result = dns_name_fromstring(name1, name, 0, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ }
+
+ cfg_map_get(config, map_key_for_list, &list);
+ for (element = cfg_list_first(list); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const char *vname;
+
+ obj = cfg_listelt_value(element);
+ INSIST(obj != NULL);
+ vname = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
+ if (vname == NULL) {
+ obj = NULL;
+ continue;
+ }
+
+ if (name1 != NULL) {
+ result = dns_name_fromstring(name2, vname, 0, NULL);
+ if (result == ISC_R_SUCCESS &&
+ dns_name_equal(name1, name2))
+ {
+ const cfg_obj_t *zoptions;
+ const cfg_obj_t *typeobj = NULL;
+ zoptions = cfg_tuple_get(obj, "options");
+
+ if (zoptions != NULL) {
+ cfg_map_get(zoptions, "type", &typeobj);
+ }
+ if (redirect && typeobj != NULL &&
+ strcasecmp(cfg_obj_asstring(typeobj),
+ "redirect") == 0)
+ {
+ break;
+ } else if (!redirect) {
+ break;
+ }
+ }
+ } else if (strcasecmp(vname, name) == 0) {
+ break;
+ }
+
+ obj = NULL;
+ }
+
+ return (obj);
+}
+
+static void
+emitzone(void *arg, const char *buf, int len) {
+ ns_dzarg_t *dzarg = arg;
+ isc_result_t result;
+
+ REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC));
+ result = putmem(dzarg->text, buf, len);
+ if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) {
+ dzarg->result = result;
+ }
+}
+
+/*
+ * Act on a "showzone" command from the command channel.
+ */
+isc_result_t
+named_server_showzone(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result;
+ const cfg_obj_t *vconfig = NULL, *zconfig = NULL;
+ char zonename[DNS_NAME_FORMATSIZE];
+ const cfg_obj_t *map;
+ dns_view_t *view = NULL;
+ dns_zone_t *zone = NULL;
+ ns_cfgctx_t *cfg = NULL;
+#ifdef HAVE_LMDB
+ cfg_obj_t *nzconfig = NULL;
+#endif /* HAVE_LMDB */
+ bool added, redirect;
+ ns_dzarg_t dzarg;
+
+ REQUIRE(text != NULL);
+
+ /* Parse parameters */
+ CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true));
+ if (zone == NULL) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto cleanup;
+ }
+
+ redirect = dns_zone_gettype(zone) == dns_zone_redirect;
+ added = dns_zone_getadded(zone);
+ view = dns_zone_getview(zone);
+ dns_zone_detach(&zone);
+
+ cfg = (ns_cfgctx_t *)view->new_zone_config;
+ if (cfg == NULL) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ if (!added) {
+ /* Find the view statement */
+ vconfig = find_name_in_list_from_map(cfg->config, "view",
+ view->name, false);
+
+ /* Find the zone statement */
+ if (vconfig != NULL) {
+ map = cfg_tuple_get(vconfig, "options");
+ } else {
+ map = cfg->config;
+ }
+
+ zconfig = find_name_in_list_from_map(map, "zone", zonename,
+ redirect);
+ }
+
+#ifndef HAVE_LMDB
+ if (zconfig == NULL && cfg->nzf_config != NULL) {
+ zconfig = find_name_in_list_from_map(cfg->nzf_config, "zone",
+ zonename, redirect);
+ }
+#else /* HAVE_LMDB */
+ if (zconfig == NULL) {
+ const cfg_obj_t *zlist = NULL;
+ CHECK(get_newzone_config(view, zonename, &nzconfig));
+ CHECK(cfg_map_get(nzconfig, "zone", &zlist));
+ if (!cfg_obj_islist(zlist)) {
+ CHECK(ISC_R_FAILURE);
+ }
+
+ zconfig = cfg_listelt_value(cfg_list_first(zlist));
+ }
+#endif /* HAVE_LMDB */
+
+ if (zconfig == NULL) {
+ CHECK(ISC_R_NOTFOUND);
+ }
+
+ CHECK(putstr(text, "zone "));
+ dzarg.magic = DZARG_MAGIC;
+ dzarg.text = text;
+ dzarg.result = ISC_R_SUCCESS;
+ cfg_printx(zconfig, CFG_PRINTER_ONELINE, emitzone, &dzarg);
+ CHECK(dzarg.result);
+
+ CHECK(putstr(text, ";"));
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+#ifdef HAVE_LMDB
+ if (nzconfig != NULL) {
+ cfg_obj_destroy(named_g_addparser, &nzconfig);
+ }
+#endif /* HAVE_LMDB */
+ if (isc_buffer_usedlength(*text) > 0) {
+ (void)putnull(text);
+ }
+
+ return (result);
+}
+
+static void
+newzone_cfgctx_destroy(void **cfgp) {
+ ns_cfgctx_t *cfg;
+
+ REQUIRE(cfgp != NULL && *cfgp != NULL);
+
+ cfg = *cfgp;
+
+ if (cfg->conf_parser != NULL) {
+ if (cfg->config != NULL) {
+ cfg_obj_destroy(cfg->conf_parser, &cfg->config);
+ }
+ if (cfg->vconfig != NULL) {
+ cfg_obj_destroy(cfg->conf_parser, &cfg->vconfig);
+ }
+ cfg_parser_destroy(&cfg->conf_parser);
+ }
+ if (cfg->add_parser != NULL) {
+ if (cfg->nzf_config != NULL) {
+ cfg_obj_destroy(cfg->add_parser, &cfg->nzf_config);
+ }
+ cfg_parser_destroy(&cfg->add_parser);
+ }
+
+ if (cfg->actx != NULL) {
+ cfg_aclconfctx_detach(&cfg->actx);
+ }
+
+ isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg));
+ *cfgp = NULL;
+}
+
+isc_result_t
+named_server_signing(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_zone_t *zone = NULL;
+ dns_name_t *origin;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_rdatatype_t privatetype;
+ dns_rdataset_t privset;
+ bool first = true;
+ bool list = false, clear = false;
+ bool chain = false;
+ bool setserial = false;
+ bool resalt = false;
+ uint32_t serial = 0;
+ char keystr[DNS_SECALG_FORMATSIZE + 7]; /* <5-digit keyid>/<alg> */
+ unsigned short hash = 0, flags = 0, iter = 0, saltlen = 0;
+ unsigned char salt[255];
+ const char *ptr;
+ size_t n;
+
+ REQUIRE(text != NULL);
+
+ dns_rdataset_init(&privset);
+
+ /* Skip the command name. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* Find out what we are to do. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ if (strcasecmp(ptr, "-list") == 0) {
+ list = true;
+ } else if ((strcasecmp(ptr, "-clear") == 0) ||
+ (strcasecmp(ptr, "-clean") == 0))
+ {
+ clear = true;
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ strlcpy(keystr, ptr, sizeof(keystr));
+ } else if (strcasecmp(ptr, "-nsec3param") == 0) {
+ char hashbuf[64], flagbuf[64], iterbuf[64];
+ char nbuf[256];
+
+ chain = true;
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ if (strcasecmp(ptr, "none") == 0) {
+ hash = 0;
+ } else {
+ strlcpy(hashbuf, ptr, sizeof(hashbuf));
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ strlcpy(flagbuf, ptr, sizeof(flagbuf));
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ strlcpy(iterbuf, ptr, sizeof(iterbuf));
+ n = snprintf(nbuf, sizeof(nbuf), "%s %s %s", hashbuf,
+ flagbuf, iterbuf);
+ if (n == sizeof(nbuf)) {
+ return (ISC_R_NOSPACE);
+ }
+ n = sscanf(nbuf, "%hu %hu %hu", &hash, &flags, &iter);
+ if (n != 3U) {
+ return (ISC_R_BADNUMBER);
+ }
+
+ if (hash > 0xffU || flags > 0xffU ||
+ iter > dns_nsec3_maxiterations())
+ {
+ return (ISC_R_RANGE);
+ }
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ } else if (strcasecmp(ptr, "auto") == 0) {
+ /* Auto-generate a random salt.
+ * XXXMUKS: This currently uses the
+ * minimum recommended length by RFC
+ * 5155 (64 bits). It should be made
+ * configurable.
+ */
+ saltlen = 8;
+ resalt = true;
+ } else if (strcmp(ptr, "-") != 0) {
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, salt, sizeof(salt));
+ CHECK(isc_hex_decodestring(ptr, &buf));
+ saltlen = isc_buffer_usedlength(&buf);
+ }
+ }
+ } else if (strcasecmp(ptr, "-serial") == 0) {
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ CHECK(isc_parse_uint32(&serial, ptr, 10));
+ setserial = true;
+ } else {
+ CHECK(DNS_R_SYNTAX);
+ }
+
+ CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false));
+ if (zone == NULL) {
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+
+ if (dns_zone_getkasp(zone) != NULL) {
+ (void)putstr(text, "zone uses dnssec-policy, use rndc dnssec "
+ "command instead");
+ (void)putnull(text);
+ goto cleanup;
+ }
+
+ if (clear) {
+ CHECK(dns_zone_keydone(zone, keystr));
+ (void)putstr(text, "request queued");
+ (void)putnull(text);
+ } else if (chain) {
+ CHECK(dns_zone_setnsec3param(
+ zone, (uint8_t)hash, (uint8_t)flags, iter,
+ (uint8_t)saltlen, salt, true, resalt));
+ (void)putstr(text, "nsec3param request queued");
+ (void)putnull(text);
+ } else if (setserial) {
+ CHECK(dns_zone_setserial(zone, serial));
+ (void)putstr(text, "serial request queued");
+ (void)putnull(text);
+ } else if (list) {
+ privatetype = dns_zone_getprivatetype(zone);
+ origin = dns_zone_getorigin(zone);
+ CHECK(dns_zone_getdb(zone, &db));
+ CHECK(dns_db_findnode(db, origin, false, &node));
+ dns_db_currentversion(db, &version);
+
+ result = dns_db_findrdataset(db, node, version, privatetype,
+ dns_rdatatype_none, 0, &privset,
+ NULL);
+ if (result == ISC_R_NOTFOUND) {
+ (void)putstr(text, "No signing records found");
+ (void)putnull(text);
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+ for (result = dns_rdataset_first(&privset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&privset))
+ {
+ dns_rdata_t priv = DNS_RDATA_INIT;
+ /*
+ * In theory, the output buffer could hold a full RDATA
+ * record which is 16-bit and then some text around
+ * it
+ */
+ char output[UINT16_MAX + BUFSIZ];
+ isc_buffer_t buf;
+
+ dns_rdataset_current(&privset, &priv);
+
+ isc_buffer_init(&buf, output, sizeof(output));
+ CHECK(dns_private_totext(&priv, &buf));
+ if (!first) {
+ CHECK(putstr(text, "\n"));
+ }
+ CHECK(putstr(text, output));
+ first = false;
+ }
+ if (!first) {
+ CHECK(putnull(text));
+ }
+
+ if (result == ISC_R_NOMORE) {
+ result = ISC_R_SUCCESS;
+ }
+ }
+
+cleanup:
+ if (dns_rdataset_isassociated(&privset)) {
+ dns_rdataset_disassociate(&privset);
+ }
+ if (node != NULL) {
+ dns_db_detachnode(db, &node);
+ }
+ if (version != NULL) {
+ dns_db_closeversion(db, &version, false);
+ }
+ if (db != NULL) {
+ dns_db_detach(&db);
+ }
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+
+ return (result);
+}
+
+static bool
+argcheck(char *cmd, const char *full) {
+ size_t l;
+
+ if (cmd == NULL || cmd[0] != '-') {
+ return (false);
+ }
+
+ cmd++;
+ l = strlen(cmd);
+ if (l > strlen(full) || strncasecmp(cmd, full, l) != 0) {
+ return (false);
+ }
+
+ return (true);
+}
+
+isc_result_t
+named_server_dnssec(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_zone_t *zone = NULL;
+ dns_kasp_t *kasp = NULL;
+ dns_dnsseckeylist_t keys;
+ dns_dnsseckey_t *key;
+ char *ptr, *zonetext = NULL;
+ const char *msg = NULL;
+ /* variables for -checkds */
+ bool checkds = false, dspublish = false;
+ /* variables for -rollover */
+ bool rollover = false;
+ /* variables for -key */
+ bool use_keyid = false;
+ dns_keytag_t keyid = 0;
+ uint8_t algorithm = 0;
+ /* variables for -status */
+ bool status = false;
+ char output[4096];
+ isc_stdtime_t now, when;
+ isc_time_t timenow, timewhen;
+ const char *dir;
+ dns_db_t *db = NULL;
+ dns_dbversion_t *version = NULL;
+
+ REQUIRE(text != NULL);
+
+ /* Skip the command name. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* Find out what we are to do. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* Initialize current time and key list. */
+ TIME_NOW(&timenow);
+ now = isc_time_seconds(&timenow);
+ when = now;
+
+ ISC_LIST_INIT(keys);
+
+ if (strcasecmp(ptr, "-status") == 0) {
+ status = true;
+ } else if (strcasecmp(ptr, "-rollover") == 0) {
+ rollover = true;
+ } else if (strcasecmp(ptr, "-checkds") == 0) {
+ checkds = true;
+ } else {
+ CHECK(DNS_R_SYNTAX);
+ }
+
+ if (rollover || checkds) {
+ /* Check for options */
+ for (;;) {
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ msg = "Bad format";
+ CHECK(ISC_R_UNEXPECTEDEND);
+ } else if (argcheck(ptr, "alg")) {
+ isc_consttextregion_t alg;
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ msg = "No key algorithm specified";
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+ alg.base = ptr;
+ alg.length = strlen(alg.base);
+ result = dns_secalg_fromtext(
+ &algorithm, (isc_textregion_t *)&alg);
+ if (result != ISC_R_SUCCESS) {
+ msg = "Bad algorithm";
+ CHECK(DNS_R_SYNTAX);
+ }
+ continue;
+ } else if (argcheck(ptr, "key")) {
+ uint16_t id;
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ msg = "No key identifier specified";
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+ CHECK(isc_parse_uint16(&id, ptr, 10));
+ keyid = (dns_keytag_t)id;
+ use_keyid = true;
+ continue;
+ } else if (argcheck(ptr, "when")) {
+ uint32_t tw;
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ msg = "No time specified";
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+ CHECK(dns_time32_fromtext(ptr, &tw));
+ when = (isc_stdtime_t)tw;
+ continue;
+ } else if (ptr[0] == '-') {
+ msg = "Unknown option";
+ CHECK(DNS_R_SYNTAX);
+ } else if (checkds) {
+ /*
+ * No arguments provided, so we must be
+ * parsing "published|withdrawn".
+ */
+ if (strcasecmp(ptr, "published") == 0) {
+ dspublish = true;
+ } else if (strcasecmp(ptr, "withdrawn") != 0) {
+ CHECK(DNS_R_SYNTAX);
+ }
+ } else if (rollover) {
+ /*
+ * No arguments provided, so we must be
+ * parsing the zone.
+ */
+ zonetext = ptr;
+ }
+ break;
+ }
+
+ if (rollover && !use_keyid) {
+ msg = "Key id is required when scheduling rollover";
+ CHECK(DNS_R_SYNTAX);
+ }
+
+ if (algorithm > 0 && !use_keyid) {
+ msg = "Key id is required when setting algorithm";
+ CHECK(DNS_R_SYNTAX);
+ }
+ }
+
+ /* Get zone. */
+ CHECK(zone_from_args(server, lex, zonetext, &zone, NULL, text, false));
+ if (zone == NULL) {
+ msg = "Zone not found";
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+
+ /* Trailing garbage? */
+ ptr = next_token(lex, text);
+ if (ptr != NULL) {
+ msg = "Too many arguments";
+ CHECK(DNS_R_SYNTAX);
+ }
+
+ /* Get dnssec-policy. */
+ kasp = dns_zone_getkasp(zone);
+ if (kasp == NULL) {
+ msg = "Zone does not have dnssec-policy";
+ goto cleanup;
+ }
+
+ /* Get DNSSEC keys. */
+ dir = dns_zone_getkeydirectory(zone);
+ CHECK(dns_zone_getdb(zone, &db));
+ dns_db_currentversion(db, &version);
+ LOCK(&kasp->lock);
+ result = dns_zone_getdnsseckeys(zone, db, version, now, &keys);
+ UNLOCK(&kasp->lock);
+ if (result != ISC_R_SUCCESS) {
+ if (result != ISC_R_NOTFOUND) {
+ goto cleanup;
+ }
+ }
+
+ if (status) {
+ /*
+ * Output the DNSSEC status of the key and signing policy.
+ */
+ LOCK(&kasp->lock);
+ dns_keymgr_status(kasp, &keys, now, &output[0], sizeof(output));
+ UNLOCK(&kasp->lock);
+ CHECK(putstr(text, output));
+ } else if (checkds) {
+ /*
+ * Mark DS record has been seen, so it may move to the
+ * rumoured state.
+ */
+ char whenbuf[80];
+ isc_time_set(&timewhen, when, 0);
+ isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf));
+ isc_result_t ret;
+
+ LOCK(&kasp->lock);
+ if (use_keyid) {
+ result = dns_keymgr_checkds_id(kasp, &keys, dir, now,
+ when, dspublish, keyid,
+ (unsigned int)algorithm);
+ } else {
+ result = dns_keymgr_checkds(kasp, &keys, dir, now, when,
+ dspublish);
+ }
+ UNLOCK(&kasp->lock);
+
+ switch (result) {
+ case ISC_R_SUCCESS:
+ /*
+ * Rekey after checkds command because the next key
+ * event may have changed.
+ */
+ dns_zone_rekey(zone, false);
+
+ if (use_keyid) {
+ char tagbuf[6];
+ snprintf(tagbuf, sizeof(tagbuf), "%u", keyid);
+ CHECK(putstr(text, "KSK "));
+ CHECK(putstr(text, tagbuf));
+ CHECK(putstr(text, ": "));
+ }
+ CHECK(putstr(text, "Marked DS as "));
+ if (dspublish) {
+ CHECK(putstr(text, "published "));
+ } else {
+ CHECK(putstr(text, "withdrawn "));
+ }
+ CHECK(putstr(text, "since "));
+ CHECK(putstr(text, whenbuf));
+ break;
+ case DNS_R_TOOMANYKEYS:
+ CHECK(putstr(text,
+ "Error: multiple possible keys found, "
+ "retry command with -key id"));
+ break;
+ default:
+ ret = result;
+ CHECK(putstr(text,
+ "Error executing checkds command: "));
+ CHECK(putstr(text, isc_result_totext(ret)));
+ break;
+ }
+ } else if (rollover) {
+ /*
+ * Manually rollover a key.
+ */
+ char whenbuf[80];
+ isc_time_set(&timewhen, when, 0);
+ isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf));
+ isc_result_t ret;
+
+ LOCK(&kasp->lock);
+ result = dns_keymgr_rollover(kasp, &keys, dir, now, when, keyid,
+ (unsigned int)algorithm);
+ UNLOCK(&kasp->lock);
+
+ switch (result) {
+ case ISC_R_SUCCESS:
+ /*
+ * Rekey after rollover command because the next key
+ * event may have changed.
+ */
+ dns_zone_rekey(zone, false);
+
+ if (use_keyid) {
+ char tagbuf[6];
+ snprintf(tagbuf, sizeof(tagbuf), "%u", keyid);
+ CHECK(putstr(text, "Key "));
+ CHECK(putstr(text, tagbuf));
+ CHECK(putstr(text, ": "));
+ }
+ CHECK(putstr(text, "Rollover scheduled on "));
+ CHECK(putstr(text, whenbuf));
+ break;
+ case DNS_R_TOOMANYKEYS:
+ CHECK(putstr(text,
+ "Error: multiple possible keys found, "
+ "retry command with -alg algorithm"));
+ break;
+ default:
+ ret = result;
+ CHECK(putstr(text,
+ "Error executing rollover command: "));
+ CHECK(putstr(text, isc_result_totext(ret)));
+ break;
+ }
+ }
+ CHECK(putnull(text));
+
+cleanup:
+ if (msg != NULL) {
+ (void)putstr(text, msg);
+ (void)putnull(text);
+ }
+
+ if (version != NULL) {
+ dns_db_closeversion(db, &version, false);
+ }
+ if (db != NULL) {
+ dns_db_detach(&db);
+ }
+
+ while (!ISC_LIST_EMPTY(keys)) {
+ key = ISC_LIST_HEAD(keys);
+ ISC_LIST_UNLINK(keys, key, link);
+ dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
+ }
+
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+putmem(isc_buffer_t **b, const char *str, size_t len) {
+ isc_result_t result;
+
+ result = isc_buffer_reserve(b, (unsigned int)len);
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_NOSPACE);
+ }
+
+ isc_buffer_putmem(*b, (const unsigned char *)str, (unsigned int)len);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+putstr(isc_buffer_t **b, const char *str) {
+ return (putmem(b, str, strlen(str)));
+}
+
+static isc_result_t
+putuint8(isc_buffer_t **b, uint8_t val) {
+ isc_result_t result;
+
+ result = isc_buffer_reserve(b, 1);
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_NOSPACE);
+ }
+
+ isc_buffer_putuint8(*b, val);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+putnull(isc_buffer_t **b) {
+ return (putuint8(b, 0));
+}
+
+isc_result_t
+named_server_zonestatus(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL;
+ const char *type, *file;
+ char zonename[DNS_NAME_FORMATSIZE];
+ uint32_t serial, signed_serial, nodes;
+ char serbuf[16], sserbuf[16], nodebuf[16];
+ char resignbuf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + 2];
+ char lbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ char xbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ char kbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ char rtbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ isc_time_t loadtime, expiretime, refreshtime;
+ isc_time_t refreshkeytime, resigntime;
+ dns_zonetype_t zonetype;
+ bool dynamic = false, frozen = false;
+ bool hasraw = false;
+ bool secure, maintain, allow;
+ dns_db_t *db = NULL, *rawdb = NULL;
+ char **incfiles = NULL;
+ int nfiles = 0;
+
+ REQUIRE(text != NULL);
+
+ isc_time_settoepoch(&loadtime);
+ isc_time_settoepoch(&refreshtime);
+ isc_time_settoepoch(&expiretime);
+ isc_time_settoepoch(&refreshkeytime);
+ isc_time_settoepoch(&resigntime);
+
+ CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true));
+ if (zone == NULL) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto cleanup;
+ }
+
+ /* Inline signing? */
+ CHECK(dns_zone_getdb(zone, &db));
+ dns_zone_getraw(zone, &raw);
+ hasraw = (raw != NULL);
+ if (hasraw) {
+ mayberaw = raw;
+ zonetype = dns_zone_gettype(raw);
+ CHECK(dns_zone_getdb(raw, &rawdb));
+ } else {
+ mayberaw = zone;
+ zonetype = dns_zone_gettype(zone);
+ }
+
+ type = dns_zonetype_name(zonetype);
+
+ /* Serial number */
+ result = dns_zone_getserial(mayberaw, &serial);
+
+ /* This is to mirror old behavior with dns_zone_getserial */
+ if (result != ISC_R_SUCCESS) {
+ serial = 0;
+ }
+
+ snprintf(serbuf, sizeof(serbuf), "%u", serial);
+ if (hasraw) {
+ result = dns_zone_getserial(zone, &signed_serial);
+ if (result != ISC_R_SUCCESS) {
+ serial = 0;
+ }
+ snprintf(sserbuf, sizeof(sserbuf), "%u", signed_serial);
+ }
+
+ /* Database node count */
+ nodes = dns_db_nodecount(hasraw ? rawdb : db, dns_dbtree_main);
+ snprintf(nodebuf, sizeof(nodebuf), "%u", nodes);
+
+ /* Security */
+ secure = dns_db_issecure(db);
+ allow = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_ALLOW) != 0);
+ maintain = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0);
+
+ /* Master files */
+ file = dns_zone_getfile(mayberaw);
+ nfiles = dns_zone_getincludes(mayberaw, &incfiles);
+
+ /* Load time */
+ dns_zone_getloadtime(zone, &loadtime);
+ isc_time_formathttptimestamp(&loadtime, lbuf, sizeof(lbuf));
+
+ /* Refresh/expire times */
+ if (zonetype == dns_zone_secondary || zonetype == dns_zone_mirror ||
+ zonetype == dns_zone_stub || zonetype == dns_zone_redirect)
+ {
+ dns_zone_getexpiretime(mayberaw, &expiretime);
+ isc_time_formathttptimestamp(&expiretime, xbuf, sizeof(xbuf));
+ dns_zone_getrefreshtime(mayberaw, &refreshtime);
+ isc_time_formathttptimestamp(&refreshtime, rbuf, sizeof(rbuf));
+ }
+
+ /* Key refresh time */
+ if (zonetype == dns_zone_primary ||
+ (zonetype == dns_zone_secondary && hasraw))
+ {
+ dns_zone_getrefreshkeytime(zone, &refreshkeytime);
+ isc_time_formathttptimestamp(&refreshkeytime, kbuf,
+ sizeof(kbuf));
+ }
+
+ /* Dynamic? */
+ if (zonetype == dns_zone_primary) {
+ dynamic = dns_zone_isdynamic(mayberaw, true);
+ frozen = dynamic && !dns_zone_isdynamic(mayberaw, false);
+ }
+
+ /* Next resign event */
+ if (secure &&
+ (zonetype == dns_zone_primary ||
+ (zonetype == dns_zone_secondary && hasraw)) &&
+ ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_NORESIGN) == 0))
+ {
+ dns_name_t *name;
+ dns_fixedname_t fixed;
+ dns_rdataset_t next;
+
+ dns_rdataset_init(&next);
+ name = dns_fixedname_initname(&fixed);
+
+ result = dns_db_getsigningtime(db, &next, name);
+ if (result == ISC_R_SUCCESS) {
+ isc_stdtime_t timenow;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+
+ isc_stdtime_get(&timenow);
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(next.covers, typebuf,
+ sizeof(typebuf));
+ snprintf(resignbuf, sizeof(resignbuf), "%s/%s", namebuf,
+ typebuf);
+ isc_time_set(
+ &resigntime,
+ next.resign -
+ dns_zone_getsigresigninginterval(zone),
+ 0);
+ isc_time_formathttptimestamp(&resigntime, rtbuf,
+ sizeof(rtbuf));
+ dns_rdataset_disassociate(&next);
+ }
+ }
+
+ /* Create text */
+ CHECK(putstr(text, "name: "));
+ CHECK(putstr(text, zonename));
+
+ CHECK(putstr(text, "\ntype: "));
+ CHECK(putstr(text, type));
+
+ if (file != NULL) {
+ int i;
+ CHECK(putstr(text, "\nfiles: "));
+ CHECK(putstr(text, file));
+ for (i = 0; i < nfiles; i++) {
+ CHECK(putstr(text, ", "));
+ if (incfiles[i] != NULL) {
+ CHECK(putstr(text, incfiles[i]));
+ }
+ }
+ }
+
+ CHECK(putstr(text, "\nserial: "));
+ CHECK(putstr(text, serbuf));
+ if (hasraw) {
+ CHECK(putstr(text, "\nsigned serial: "));
+ CHECK(putstr(text, sserbuf));
+ }
+
+ CHECK(putstr(text, "\nnodes: "));
+ CHECK(putstr(text, nodebuf));
+
+ if (!isc_time_isepoch(&loadtime)) {
+ CHECK(putstr(text, "\nlast loaded: "));
+ CHECK(putstr(text, lbuf));
+ }
+
+ if (!isc_time_isepoch(&refreshtime)) {
+ CHECK(putstr(text, "\nnext refresh: "));
+ CHECK(putstr(text, rbuf));
+ }
+
+ if (!isc_time_isepoch(&expiretime)) {
+ CHECK(putstr(text, "\nexpires: "));
+ CHECK(putstr(text, xbuf));
+ }
+
+ if (secure) {
+ CHECK(putstr(text, "\nsecure: yes"));
+ if (hasraw) {
+ CHECK(putstr(text, "\ninline signing: yes"));
+ } else {
+ CHECK(putstr(text, "\ninline signing: no"));
+ }
+ } else {
+ CHECK(putstr(text, "\nsecure: no"));
+ }
+
+ if (maintain) {
+ CHECK(putstr(text, "\nkey maintenance: automatic"));
+ if (!isc_time_isepoch(&refreshkeytime)) {
+ CHECK(putstr(text, "\nnext key event: "));
+ CHECK(putstr(text, kbuf));
+ }
+ } else if (allow) {
+ CHECK(putstr(text, "\nkey maintenance: on command"));
+ } else if (secure || hasraw) {
+ CHECK(putstr(text, "\nkey maintenance: none"));
+ }
+
+ if (!isc_time_isepoch(&resigntime)) {
+ CHECK(putstr(text, "\nnext resign node: "));
+ CHECK(putstr(text, resignbuf));
+ CHECK(putstr(text, "\nnext resign time: "));
+ CHECK(putstr(text, rtbuf));
+ }
+
+ if (dynamic) {
+ CHECK(putstr(text, "\ndynamic: yes"));
+ if (frozen) {
+ CHECK(putstr(text, "\nfrozen: yes"));
+ } else {
+ CHECK(putstr(text, "\nfrozen: no"));
+ }
+ } else {
+ CHECK(putstr(text, "\ndynamic: no"));
+ }
+
+ CHECK(putstr(text, "\nreconfigurable via modzone: "));
+ CHECK(putstr(text, dns_zone_getadded(zone) ? "yes" : "no"));
+
+cleanup:
+ /* Indicate truncated output if possible. */
+ if (result == ISC_R_NOSPACE) {
+ (void)putstr(text, "\n...");
+ }
+ if ((result == ISC_R_SUCCESS || result == ISC_R_NOSPACE)) {
+ (void)putnull(text);
+ }
+
+ if (db != NULL) {
+ dns_db_detach(&db);
+ }
+ if (rawdb != NULL) {
+ dns_db_detach(&rawdb);
+ }
+ if (incfiles != NULL && mayberaw != NULL) {
+ int i;
+ isc_mem_t *mctx = dns_zone_getmctx(mayberaw);
+
+ for (i = 0; i < nfiles; i++) {
+ if (incfiles[i] != NULL) {
+ isc_mem_free(mctx, incfiles[i]);
+ }
+ }
+ isc_mem_free(mctx, incfiles);
+ }
+ if (raw != NULL) {
+ dns_zone_detach(&raw);
+ }
+ if (zone != NULL) {
+ dns_zone_detach(&zone);
+ }
+ return (result);
+}
+
+isc_result_t
+named_server_nta(named_server_t *server, isc_lex_t *lex, bool readonly,
+ isc_buffer_t **text) {
+ dns_view_t *view;
+ dns_ntatable_t *ntatable = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ char *ptr, *nametext = NULL, *viewname;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char viewbuf[DNS_NAME_FORMATSIZE];
+ isc_stdtime_t now, when;
+ isc_time_t t;
+ char tbuf[64];
+ const char *msg = NULL;
+ bool dump = false, force = false;
+ dns_fixedname_t fn;
+ const dns_name_t *ntaname;
+ dns_name_t *fname;
+ dns_ttl_t ntattl;
+ bool ttlset = false, excl = false, viewfound = false;
+ dns_rdataclass_t rdclass = dns_rdataclass_in;
+ bool first = true;
+
+ REQUIRE(text != NULL);
+
+ UNUSED(force);
+
+ fname = dns_fixedname_initname(&fn);
+
+ /* Skip the command name. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ for (;;) {
+ /* Check for options */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ if (strcmp(ptr, "--") == 0) {
+ break;
+ } else if (argcheck(ptr, "dump")) {
+ dump = true;
+ } else if (argcheck(ptr, "remove")) {
+ ntattl = 0;
+ ttlset = true;
+ } else if (argcheck(ptr, "force")) {
+ force = true;
+ continue;
+ } else if (argcheck(ptr, "lifetime")) {
+ isc_textregion_t tr;
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ msg = "No lifetime specified";
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+
+ tr.base = ptr;
+ tr.length = strlen(ptr);
+ result = dns_ttl_fromtext(&tr, &ntattl);
+ if (result != ISC_R_SUCCESS) {
+ msg = "could not parse NTA lifetime";
+ CHECK(result);
+ }
+
+ if (ntattl > 604800) {
+ msg = "NTA lifetime cannot exceed one week";
+ CHECK(ISC_R_RANGE);
+ }
+
+ ttlset = true;
+ continue;
+ } else if (argcheck(ptr, "class")) {
+ isc_textregion_t tr;
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ msg = "No class specified";
+ CHECK(ISC_R_UNEXPECTEDEND);
+ }
+
+ tr.base = ptr;
+ tr.length = strlen(ptr);
+ CHECK(dns_rdataclass_fromtext(&rdclass, &tr));
+ continue;
+ } else if (ptr[0] == '-') {
+ msg = "Unknown option";
+ CHECK(DNS_R_SYNTAX);
+ } else {
+ nametext = ptr;
+ }
+
+ break;
+ }
+
+ /*
+ * If -dump was specified, list NTA's and return
+ */
+ if (dump) {
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (ntatable != NULL) {
+ dns_ntatable_detach(&ntatable);
+ }
+ result = dns_view_getntatable(view, &ntatable);
+ if (result == ISC_R_NOTFOUND) {
+ continue;
+ }
+
+ CHECK(dns_ntatable_totext(ntatable, view->name, text));
+ }
+ CHECK(putnull(text));
+
+ goto cleanup;
+ }
+
+ if (readonly) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_CONTROL, ISC_LOG_INFO,
+ "rejecting restricted control channel "
+ "NTA command");
+ CHECK(ISC_R_FAILURE);
+ }
+
+ /* Get the NTA name if not found above. */
+ if (nametext == NULL) {
+ nametext = next_token(lex, text);
+ }
+ if (nametext == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* Copy nametext as it'll be overwritten by next_token() */
+ strlcpy(namebuf, nametext, DNS_NAME_FORMATSIZE);
+
+ if (strcmp(namebuf, ".") == 0) {
+ ntaname = dns_rootname;
+ } else {
+ isc_buffer_t b;
+ isc_buffer_init(&b, namebuf, strlen(namebuf));
+ isc_buffer_add(&b, strlen(namebuf));
+ CHECK(dns_name_fromtext(fname, &b, dns_rootname, 0, NULL));
+ ntaname = fname;
+ }
+
+ /* Look for the view name. */
+ viewname = next_token(lex, text);
+ if (viewname != NULL) {
+ strlcpy(viewbuf, viewname, DNS_NAME_FORMATSIZE);
+ viewname = viewbuf;
+ }
+
+ if (next_token(lex, text) != NULL) {
+ CHECK(DNS_R_SYNTAX);
+ }
+
+ isc_stdtime_get(&now);
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ excl = true;
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (viewname != NULL && strcmp(view->name, viewname) != 0) {
+ continue;
+ }
+ viewfound = true;
+
+ if (view->rdclass != rdclass && rdclass != dns_rdataclass_any) {
+ continue;
+ }
+
+ if (view->nta_lifetime == 0) {
+ continue;
+ }
+
+ if (!ttlset) {
+ ntattl = view->nta_lifetime;
+ }
+
+ if (ntatable != NULL) {
+ dns_ntatable_detach(&ntatable);
+ }
+
+ result = dns_view_getntatable(view, &ntatable);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ continue;
+ }
+
+ result = dns_view_flushnode(view, ntaname, true);
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flush tree '%s' in cache view '%s': %s", namebuf,
+ view->name, isc_result_totext(result));
+
+ if (ntattl != 0) {
+ CHECK(dns_ntatable_add(ntatable, ntaname, force, now,
+ ntattl));
+
+ when = now + ntattl;
+ isc_time_set(&t, when, 0);
+ isc_time_formattimestamp(&t, tbuf, sizeof(tbuf));
+
+ if (!first) {
+ CHECK(putstr(text, "\n"));
+ }
+ first = false;
+
+ CHECK(putstr(text, "Negative trust anchor added: "));
+ CHECK(putstr(text, namebuf));
+ CHECK(putstr(text, "/"));
+ CHECK(putstr(text, view->name));
+ CHECK(putstr(text, ", expires "));
+ CHECK(putstr(text, tbuf));
+
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "added NTA '%s' (%d sec) in view '%s'",
+ namebuf, ntattl, view->name);
+ } else {
+ bool wasremoved;
+
+ result = dns_ntatable_delete(ntatable, ntaname);
+ if (result == ISC_R_SUCCESS) {
+ wasremoved = true;
+ } else if (result == ISC_R_NOTFOUND) {
+ wasremoved = false;
+ } else {
+ goto cleanup;
+ }
+
+ if (!first) {
+ CHECK(putstr(text, "\n"));
+ }
+ first = false;
+
+ CHECK(putstr(text, "Negative trust anchor "));
+ CHECK(putstr(text,
+ wasremoved ? "removed: " : "not found: "));
+ CHECK(putstr(text, namebuf));
+ CHECK(putstr(text, "/"));
+ CHECK(putstr(text, view->name));
+
+ if (wasremoved) {
+ isc_log_write(
+ named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "removed NTA '%s' in view %s", namebuf,
+ view->name);
+ }
+ }
+
+ result = dns_view_saventa(view);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "error writing NTA file "
+ "for view '%s': %s",
+ view->name, isc_result_totext(result));
+ }
+ }
+
+ if (!viewfound) {
+ msg = "No such view";
+ CHECK(ISC_R_NOTFOUND);
+ }
+
+ (void)putnull(text);
+
+cleanup:
+ if (msg != NULL) {
+ (void)putstr(text, msg);
+ (void)putnull(text);
+ }
+
+ if (excl) {
+ isc_task_endexclusive(server->task);
+ }
+ if (ntatable != NULL) {
+ dns_ntatable_detach(&ntatable);
+ }
+ return (result);
+}
+
+isc_result_t
+named_server_saventa(named_server_t *server) {
+ dns_view_t *view;
+
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ isc_result_t result = dns_view_saventa(view);
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "error writing NTA file "
+ "for view '%s': %s",
+ view->name, isc_result_totext(result));
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+named_server_loadnta(named_server_t *server) {
+ dns_view_t *view;
+
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ isc_result_t result = dns_view_loadnta(view);
+
+ if ((result != ISC_R_SUCCESS) &&
+ (result != ISC_R_FILENOTFOUND) &&
+ (result != ISC_R_NOTFOUND))
+ {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "error loading NTA file "
+ "for view '%s': %s",
+ view->name, isc_result_totext(result));
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+mkey_refresh(dns_view_t *view, isc_buffer_t **text) {
+ isc_result_t result;
+ char msg[DNS_NAME_FORMATSIZE + 500] = "";
+
+ snprintf(msg, sizeof(msg), "refreshing managed keys for '%s'",
+ view->name);
+ CHECK(putstr(text, msg));
+ CHECK(dns_zone_synckeyzone(view->managed_keys));
+
+cleanup:
+ return (result);
+}
+
+static isc_result_t
+mkey_destroy(named_server_t *server, dns_view_t *view, isc_buffer_t **text) {
+ isc_result_t result;
+ char msg[DNS_NAME_FORMATSIZE + 500] = "";
+ bool exclusive = false;
+ const char *file = NULL;
+ dns_db_t *dbp = NULL;
+ dns_zone_t *mkzone = NULL;
+ bool removed_a_file = false;
+
+ if (view->managed_keys == NULL) {
+ CHECK(ISC_R_NOTFOUND);
+ }
+
+ snprintf(msg, sizeof(msg), "destroying managed-keys database for '%s'",
+ view->name);
+ CHECK(putstr(text, msg));
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ exclusive = true;
+
+ /* Remove and clean up managed keys zone from view */
+ mkzone = view->managed_keys;
+ view->managed_keys = NULL;
+ (void)dns_zone_flush(mkzone);
+
+ /* Unload zone database */
+ if (dns_zone_getdb(mkzone, &dbp) == ISC_R_SUCCESS) {
+ dns_db_detach(&dbp);
+ dns_zone_unload(mkzone);
+ }
+
+ /* Delete files */
+ file = dns_zone_getfile(mkzone);
+ result = isc_file_remove(file);
+ if (result == ISC_R_SUCCESS) {
+ removed_a_file = true;
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "file %s not removed: %s", file,
+ isc_result_totext(result));
+ }
+
+ file = dns_zone_getjournal(mkzone);
+ result = isc_file_remove(file);
+ if (result == ISC_R_SUCCESS) {
+ removed_a_file = true;
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "file %s not removed: %s", file,
+ isc_result_totext(result));
+ }
+
+ if (!removed_a_file) {
+ CHECK(putstr(text, "error: no files could be removed"));
+ CHECK(ISC_R_FAILURE);
+ }
+
+ dns_zone_detach(&mkzone);
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (exclusive) {
+ isc_task_endexclusive(server->task);
+ }
+ return (result);
+}
+
+static isc_result_t
+mkey_dumpzone(dns_view_t *view, isc_buffer_t **text) {
+ isc_result_t result;
+ dns_db_t *db = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_rriterator_t rrit;
+ isc_stdtime_t now;
+ dns_name_t *prevname = NULL;
+
+ isc_stdtime_get(&now);
+
+ CHECK(dns_zone_getdb(view->managed_keys, &db));
+ dns_db_currentversion(db, &ver);
+ dns_rriterator_init(&rrit, db, ver, 0);
+ for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
+ result = dns_rriterator_nextrrset(&rrit))
+ {
+ char buf[DNS_NAME_FORMATSIZE + 500];
+ dns_name_t *name = NULL;
+ dns_rdataset_t *kdset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_keydata_t kd;
+ uint32_t ttl;
+
+ dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
+ if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
+ !dns_rdataset_isassociated(kdset))
+ {
+ continue;
+ }
+
+ if (name != prevname) {
+ char nbuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, nbuf, sizeof(nbuf));
+ snprintf(buf, sizeof(buf), "\n\n name: %s", nbuf);
+ CHECK(putstr(text, buf));
+ }
+
+ for (result = dns_rdataset_first(kdset);
+ result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset))
+ {
+ char alg[DNS_SECALG_FORMATSIZE];
+ char tbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ dns_keytag_t keyid;
+ isc_region_t r;
+ isc_time_t t;
+ bool revoked;
+
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(kdset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &kd, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ dns_rdata_toregion(&rdata, &r);
+ isc_region_consume(&r, 12);
+ keyid = dst_region_computeid(&r);
+
+ snprintf(buf, sizeof(buf), "\n keyid: %u", keyid);
+ CHECK(putstr(text, buf));
+
+ dns_secalg_format(kd.algorithm, alg, sizeof(alg));
+ snprintf(buf, sizeof(buf), "\n\talgorithm: %s", alg);
+ CHECK(putstr(text, buf));
+
+ revoked = ((kd.flags & DNS_KEYFLAG_REVOKE) != 0);
+ snprintf(buf, sizeof(buf), "\n\tflags:%s%s%s",
+ revoked ? " REVOKE" : "",
+ ((kd.flags & DNS_KEYFLAG_KSK) != 0) ? " SEP"
+ : "",
+ (kd.flags == 0) ? " (none)" : "");
+ CHECK(putstr(text, buf));
+
+ isc_time_set(&t, kd.refresh, 0);
+ isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf));
+ snprintf(buf, sizeof(buf), "\n\tnext refresh: %s",
+ tbuf);
+ CHECK(putstr(text, buf));
+
+ if (kd.removehd != 0) {
+ isc_time_set(&t, kd.removehd, 0);
+ isc_time_formathttptimestamp(&t, tbuf,
+ sizeof(tbuf));
+ snprintf(buf, sizeof(buf), "\n\tremove at: %s",
+ tbuf);
+ CHECK(putstr(text, buf));
+ }
+
+ isc_time_set(&t, kd.addhd, 0);
+ isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf));
+ if (kd.addhd == 0) {
+ snprintf(buf, sizeof(buf), "\n\tno trust");
+ } else if (revoked) {
+ snprintf(buf, sizeof(buf), "\n\ttrust revoked");
+ } else if (kd.addhd <= now) {
+ snprintf(buf, sizeof(buf),
+ "\n\ttrusted since: %s", tbuf);
+ } else if (kd.addhd > now) {
+ snprintf(buf, sizeof(buf),
+ "\n\ttrust pending: %s", tbuf);
+ }
+ CHECK(putstr(text, buf));
+ }
+ }
+
+ if (result == ISC_R_NOMORE) {
+ result = ISC_R_SUCCESS;
+ }
+
+cleanup:
+ if (ver != NULL) {
+ dns_rriterator_destroy(&rrit);
+ dns_db_closeversion(db, &ver, false);
+ }
+ if (db != NULL) {
+ dns_db_detach(&db);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+mkey_status(dns_view_t *view, isc_buffer_t **text) {
+ isc_result_t result;
+ char msg[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ isc_time_t t;
+
+ CHECK(putstr(text, "view: "));
+ CHECK(putstr(text, view->name));
+
+ CHECK(putstr(text, "\nnext scheduled event: "));
+
+ dns_zone_getrefreshkeytime(view->managed_keys, &t);
+ if (isc_time_isepoch(&t)) {
+ CHECK(putstr(text, "never"));
+ } else {
+ isc_time_formathttptimestamp(&t, msg, sizeof(msg));
+ CHECK(putstr(text, msg));
+ }
+
+ CHECK(mkey_dumpzone(view, text));
+
+cleanup:
+ return (result);
+}
+
+isc_result_t
+named_server_mkeys(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ char *cmd, *classtxt, *viewtxt = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_view_t *view = NULL;
+ dns_rdataclass_t rdclass;
+ char msg[DNS_NAME_FORMATSIZE + 500] = "";
+ enum { NONE, STATUS, REFRESH, SYNC, DESTROY } opt = NONE;
+ bool found = false;
+ bool first = true;
+
+ REQUIRE(text != NULL);
+
+ /* Skip rndc command name */
+ cmd = next_token(lex, text);
+ if (cmd == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* Get managed-keys subcommand */
+ cmd = next_token(lex, text);
+ if (cmd == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ if (strcasecmp(cmd, "status") == 0) {
+ opt = STATUS;
+ } else if (strcasecmp(cmd, "refresh") == 0) {
+ opt = REFRESH;
+ } else if (strcasecmp(cmd, "sync") == 0) {
+ opt = SYNC;
+ } else if (strcasecmp(cmd, "destroy") == 0) {
+ opt = DESTROY;
+ } else {
+ snprintf(msg, sizeof(msg), "unknown command '%s'", cmd);
+ (void)putstr(text, msg);
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+
+ /* Look for the optional class name. */
+ classtxt = next_token(lex, text);
+ if (classtxt != NULL) {
+ isc_textregion_t r;
+ r.base = classtxt;
+ r.length = strlen(classtxt);
+ result = dns_rdataclass_fromtext(&rdclass, &r);
+ if (result != ISC_R_SUCCESS) {
+ snprintf(msg, sizeof(msg), "unknown class '%s'",
+ classtxt);
+ (void)putstr(text, msg);
+ goto cleanup;
+ }
+ viewtxt = next_token(lex, text);
+ }
+
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (viewtxt != NULL && (rdclass != view->rdclass ||
+ strcmp(view->name, viewtxt) != 0))
+ {
+ continue;
+ }
+
+ if (view->managed_keys == NULL) {
+ if (viewtxt != NULL) {
+ snprintf(msg, sizeof(msg),
+ "view '%s': no managed keys", viewtxt);
+ CHECK(putstr(text, msg));
+ goto cleanup;
+ } else {
+ continue;
+ }
+ }
+
+ found = true;
+
+ switch (opt) {
+ case REFRESH:
+ if (!first) {
+ CHECK(putstr(text, "\n"));
+ }
+ CHECK(mkey_refresh(view, text));
+ break;
+ case STATUS:
+ if (!first) {
+ CHECK(putstr(text, "\n\n"));
+ }
+ CHECK(mkey_status(view, text));
+ break;
+ case SYNC:
+ CHECK(dns_zone_flush(view->managed_keys));
+ break;
+ case DESTROY:
+ if (!first) {
+ CHECK(putstr(text, "\n"));
+ }
+ CHECK(mkey_destroy(server, view, text));
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ if (viewtxt != NULL) {
+ break;
+ }
+ first = false;
+ }
+
+ if (!found) {
+ CHECK(putstr(text, "no views with managed keys"));
+ }
+
+cleanup:
+ if (isc_buffer_usedlength(*text) > 0) {
+ (void)putnull(text);
+ }
+
+ return (result);
+}
+
+isc_result_t
+named_server_dnstap(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+#ifdef HAVE_DNSTAP
+ char *ptr;
+ isc_result_t result;
+ bool reopen = false;
+ int backups = 0;
+
+ REQUIRE(text != NULL);
+
+ if (server->dtenv == NULL) {
+ return (ISC_R_NOTFOUND);
+ }
+
+ /* Check the command name. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /* "dnstap-reopen" was used in 9.11.0b1 */
+ if (strcasecmp(ptr, "dnstap-reopen") == 0) {
+ reopen = true;
+ } else {
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ }
+
+ if (reopen || strcasecmp(ptr, "-reopen") == 0) {
+ backups = ISC_LOG_ROLLNEVER;
+ } else if ((strcasecmp(ptr, "-roll") == 0)) {
+ unsigned int n;
+ ptr = next_token(lex, text);
+ if (ptr != NULL) {
+ unsigned int u;
+ n = sscanf(ptr, "%u", &u);
+ if (n != 1U || u > INT_MAX) {
+ return (ISC_R_BADNUMBER);
+ }
+ backups = u;
+ } else {
+ backups = ISC_LOG_ROLLINFINITE;
+ }
+ } else {
+ return (DNS_R_SYNTAX);
+ }
+
+ result = dns_dt_reopen(server->dtenv, backups);
+ return (result);
+#else /* ifdef HAVE_DNSTAP */
+ UNUSED(server);
+ UNUSED(lex);
+ UNUSED(text);
+ return (ISC_R_NOTIMPLEMENTED);
+#endif /* ifdef HAVE_DNSTAP */
+}
+
+isc_result_t
+named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) {
+ char *ptr;
+ isc_result_t result = ISC_R_SUCCESS;
+ uint32_t initial, idle, keepalive, advertised;
+ char msg[128];
+
+ /* Skip the command name. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ isc_nm_gettimeouts(named_g_netmgr, &initial, &idle, &keepalive,
+ &advertised);
+
+ /* Look for optional arguments. */
+ ptr = next_token(lex, NULL);
+ if (ptr != NULL) {
+ CHECK(isc_parse_uint32(&initial, ptr, 10));
+ initial *= 100;
+ if (initial > MAX_INITIAL_TIMEOUT) {
+ CHECK(ISC_R_RANGE);
+ }
+ if (initial < MIN_INITIAL_TIMEOUT) {
+ CHECK(ISC_R_RANGE);
+ }
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ CHECK(isc_parse_uint32(&idle, ptr, 10));
+ idle *= 100;
+ if (idle > MAX_IDLE_TIMEOUT) {
+ CHECK(ISC_R_RANGE);
+ }
+ if (idle < MIN_IDLE_TIMEOUT) {
+ CHECK(ISC_R_RANGE);
+ }
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ CHECK(isc_parse_uint32(&keepalive, ptr, 10));
+ keepalive *= 100;
+ if (keepalive > MAX_KEEPALIVE_TIMEOUT) {
+ CHECK(ISC_R_RANGE);
+ }
+ if (keepalive < MIN_KEEPALIVE_TIMEOUT) {
+ CHECK(ISC_R_RANGE);
+ }
+
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ CHECK(isc_parse_uint32(&advertised, ptr, 10));
+ advertised *= 100;
+ if (advertised > MAX_ADVERTISED_TIMEOUT) {
+ CHECK(ISC_R_RANGE);
+ }
+
+ result = isc_task_beginexclusive(named_g_server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive,
+ advertised);
+
+ isc_task_endexclusive(named_g_server->task);
+ }
+
+ snprintf(msg, sizeof(msg), "tcp-initial-timeout=%u\n", initial / 100);
+ CHECK(putstr(text, msg));
+ snprintf(msg, sizeof(msg), "tcp-idle-timeout=%u\n", idle / 100);
+ CHECK(putstr(text, msg));
+ snprintf(msg, sizeof(msg), "tcp-keepalive-timeout=%u\n",
+ keepalive / 100);
+ CHECK(putstr(text, msg));
+ snprintf(msg, sizeof(msg), "tcp-advertised-timeout=%u",
+ advertised / 100);
+ CHECK(putstr(text, msg));
+
+cleanup:
+ if (isc_buffer_usedlength(*text) > 0) {
+ (void)putnull(text);
+ }
+
+ return (result);
+}
+
+isc_result_t
+named_server_servestale(named_server_t *server, isc_lex_t *lex,
+ isc_buffer_t **text) {
+ char *ptr, *classtxt, *viewtxt = NULL;
+ char msg[128];
+ dns_rdataclass_t rdclass = dns_rdataclass_in;
+ dns_view_t *view;
+ bool found = false;
+ dns_stale_answer_t staleanswersok = dns_stale_answer_conf;
+ bool wantstatus = false;
+ isc_result_t result = ISC_R_SUCCESS;
+ bool exclusive = false;
+
+ REQUIRE(text != NULL);
+
+ /* Skip the command name. */
+ ptr = next_token(lex, text);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") ||
+ !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true"))
+ {
+ staleanswersok = dns_stale_answer_yes;
+ } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") ||
+ !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false"))
+ {
+ staleanswersok = dns_stale_answer_no;
+ } else if (strcasecmp(ptr, "reset") == 0) {
+ staleanswersok = dns_stale_answer_conf;
+ } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) {
+ wantstatus = true;
+ } else {
+ return (DNS_R_SYNTAX);
+ }
+
+ /* Look for the optional class name. */
+ classtxt = next_token(lex, text);
+ if (classtxt != NULL) {
+ isc_textregion_t r;
+
+ /* Look for the optional view name. */
+ viewtxt = next_token(lex, text);
+
+ /*
+ * If 'classtext' is not a valid class then it us a view name.
+ */
+ r.base = classtxt;
+ r.length = strlen(classtxt);
+ result = dns_rdataclass_fromtext(&rdclass, &r);
+ if (result != ISC_R_SUCCESS) {
+ if (viewtxt != NULL) {
+ snprintf(msg, sizeof(msg), "unknown class '%s'",
+ classtxt);
+ (void)putstr(text, msg);
+ goto cleanup;
+ }
+
+ viewtxt = classtxt;
+ classtxt = NULL;
+ }
+ }
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ exclusive = true;
+
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ dns_ttl_t stale_ttl = 0;
+ uint32_t stale_refresh = 0;
+ dns_db_t *db = NULL;
+
+ if (classtxt != NULL && rdclass != view->rdclass) {
+ continue;
+ }
+
+ if (viewtxt != NULL && strcmp(view->name, viewtxt) != 0) {
+ continue;
+ }
+
+ if (!wantstatus) {
+ view->staleanswersok = staleanswersok;
+ found = true;
+ continue;
+ }
+
+ db = NULL;
+ dns_db_attach(view->cachedb, &db);
+ (void)dns_db_getservestalettl(db, &stale_ttl);
+ (void)dns_db_getservestalerefresh(db, &stale_refresh);
+ dns_db_detach(&db);
+ if (found) {
+ CHECK(putstr(text, "\n"));
+ }
+ CHECK(putstr(text, view->name));
+ CHECK(putstr(text, ": "));
+ switch (view->staleanswersok) {
+ case dns_stale_answer_yes:
+ if (stale_ttl > 0) {
+ CHECK(putstr(text, "stale cache enabled; stale "
+ "answers enabled"));
+ } else {
+ CHECK(putstr(text,
+ "stale cache disabled; stale "
+ "answers unavailable"));
+ }
+ break;
+ case dns_stale_answer_no:
+ if (stale_ttl > 0) {
+ CHECK(putstr(text, "stale cache enabled; stale "
+ "answers disabled"));
+ } else {
+ CHECK(putstr(text,
+ "stale cache disabled; stale "
+ "answers unavailable"));
+ }
+ break;
+ case dns_stale_answer_conf:
+ if (view->staleanswersenable && stale_ttl > 0) {
+ CHECK(putstr(text, "stale cache enabled; stale "
+ "answers enabled"));
+ } else if (stale_ttl > 0) {
+ CHECK(putstr(text, "stale cache enabled; stale "
+ "answers disabled"));
+ } else {
+ CHECK(putstr(text,
+ "stale cache disabled; stale "
+ "answers unavailable"));
+ }
+ break;
+ }
+ if (stale_ttl > 0) {
+ snprintf(msg, sizeof(msg),
+ " (stale-answer-ttl=%u max-stale-ttl=%u "
+ "stale-refresh-time=%u)",
+ view->staleanswerttl, stale_ttl,
+ stale_refresh);
+ CHECK(putstr(text, msg));
+ }
+ found = true;
+ }
+
+ if (!found) {
+ result = ISC_R_NOTFOUND;
+ }
+
+cleanup:
+ if (exclusive) {
+ isc_task_endexclusive(named_g_server->task);
+ }
+
+ if (isc_buffer_usedlength(*text) > 0) {
+ (void)putnull(text);
+ }
+
+ return (result);
+}
diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c
new file mode 100644
index 0000000..2c4760c
--- /dev/null
+++ b/bin/named/statschannel.c
@@ -0,0 +1,4084 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/buffer.h>
+#include <isc/httpd.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/stats.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/cache.h>
+#include <dns/db.h>
+#include <dns/opcode.h>
+#include <dns/rcode.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+#include <dns/resolver.h>
+#include <dns/stats.h>
+#include <dns/view.h>
+#include <dns/zt.h>
+
+#include <ns/stats.h>
+
+#include <named/log.h>
+#include <named/server.h>
+#include <named/statschannel.h>
+
+#if HAVE_JSON_C
+#include <json_object.h>
+#include <linkhash.h>
+#endif /* HAVE_JSON_C */
+
+#if HAVE_LIBXML2
+#include <libxml/xmlwriter.h>
+#define ISC_XMLCHAR (const xmlChar *)
+#endif /* HAVE_LIBXML2 */
+
+#include "xsl_p.h"
+
+#define STATS_XML_VERSION_MAJOR "3"
+#define STATS_XML_VERSION_MINOR "13"
+#define STATS_XML_VERSION STATS_XML_VERSION_MAJOR "." STATS_XML_VERSION_MINOR
+
+#define STATS_JSON_VERSION_MAJOR "1"
+#define STATS_JSON_VERSION_MINOR "7"
+#define STATS_JSON_VERSION STATS_JSON_VERSION_MAJOR "." STATS_JSON_VERSION_MINOR
+
+#define CHECK(m) \
+ do { \
+ result = (m); \
+ if (result != ISC_R_SUCCESS) { \
+ goto cleanup; \
+ } \
+ } while (0)
+
+struct named_statschannel {
+ /* Unlocked */
+ isc_httpdmgr_t *httpdmgr;
+ isc_sockaddr_t address;
+ isc_mem_t *mctx;
+
+ /*
+ * Locked by channel lock: can be referenced and modified by both
+ * the server task and the channel task.
+ */
+ isc_mutex_t lock;
+ dns_acl_t *acl;
+
+ /* Locked by server task */
+ ISC_LINK(struct named_statschannel) link;
+};
+
+typedef struct stats_dumparg {
+ isc_statsformat_t type;
+ void *arg; /* type dependent argument */
+ int ncounters; /* for general statistics */
+ int *counterindices; /* for general statistics */
+ uint64_t *countervalues; /* for general statistics */
+ isc_result_t result;
+} stats_dumparg_t;
+
+static isc_once_t once = ISC_ONCE_INIT;
+
+#if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C)
+#define EXTENDED_STATS
+#else /* if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C) */
+#undef EXTENDED_STATS
+#endif /* if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C) */
+
+#ifdef EXTENDED_STATS
+static const char *
+user_zonetype(dns_zone_t *zone) {
+ dns_zonetype_t ztype;
+ dns_view_t *view;
+ static const struct zt {
+ const dns_zonetype_t type;
+ const char *const string;
+ } typemap[] = { { dns_zone_none, "none" },
+ { dns_zone_primary, "primary" },
+ { dns_zone_secondary, "secondary" },
+ { dns_zone_mirror, "mirror" },
+ { dns_zone_stub, "stub" },
+ { dns_zone_staticstub, "static-stub" },
+ { dns_zone_key, "key" },
+ { dns_zone_dlz, "dlz" },
+ { dns_zone_redirect, "redirect" },
+ { 0, NULL } };
+ const struct zt *tp;
+
+ if ((dns_zone_getoptions(zone) & DNS_ZONEOPT_AUTOEMPTY) != 0) {
+ return ("builtin");
+ }
+
+ view = dns_zone_getview(zone);
+ if (view != NULL && strcmp(view->name, "_bind") == 0) {
+ return ("builtin");
+ }
+
+ ztype = dns_zone_gettype(zone);
+ for (tp = typemap; tp->string != NULL && tp->type != ztype; tp++) {
+ /* empty */
+ }
+ return (tp->string);
+}
+#endif /* ifdef EXTENDED_STATS */
+
+/*%
+ * Statistics descriptions. These could be statistically initialized at
+ * compile time, but we configure them run time in the init_desc() function
+ * below so that they'll be less susceptible to counter name changes.
+ */
+static const char *nsstats_desc[ns_statscounter_max];
+static const char *resstats_desc[dns_resstatscounter_max];
+static const char *adbstats_desc[dns_adbstats_max];
+static const char *zonestats_desc[dns_zonestatscounter_max];
+static const char *sockstats_desc[isc_sockstatscounter_max];
+static const char *dnssecstats_desc[dns_dnssecstats_max];
+static const char *udpinsizestats_desc[dns_sizecounter_in_max];
+static const char *udpoutsizestats_desc[dns_sizecounter_out_max];
+static const char *tcpinsizestats_desc[dns_sizecounter_in_max];
+static const char *tcpoutsizestats_desc[dns_sizecounter_out_max];
+static const char *dnstapstats_desc[dns_dnstapcounter_max];
+static const char *gluecachestats_desc[dns_gluecachestatscounter_max];
+#if defined(EXTENDED_STATS)
+static const char *nsstats_xmldesc[ns_statscounter_max];
+static const char *resstats_xmldesc[dns_resstatscounter_max];
+static const char *adbstats_xmldesc[dns_adbstats_max];
+static const char *zonestats_xmldesc[dns_zonestatscounter_max];
+static const char *sockstats_xmldesc[isc_sockstatscounter_max];
+static const char *dnssecstats_xmldesc[dns_dnssecstats_max];
+static const char *udpinsizestats_xmldesc[dns_sizecounter_in_max];
+static const char *udpoutsizestats_xmldesc[dns_sizecounter_out_max];
+static const char *tcpinsizestats_xmldesc[dns_sizecounter_in_max];
+static const char *tcpoutsizestats_xmldesc[dns_sizecounter_out_max];
+static const char *dnstapstats_xmldesc[dns_dnstapcounter_max];
+static const char *gluecachestats_xmldesc[dns_gluecachestatscounter_max];
+#else /* if defined(EXTENDED_STATS) */
+#define nsstats_xmldesc NULL
+#define resstats_xmldesc NULL
+#define adbstats_xmldesc NULL
+#define zonestats_xmldesc NULL
+#define sockstats_xmldesc NULL
+#define dnssecstats_xmldesc NULL
+#define udpinsizestats_xmldesc NULL
+#define udpoutsizestats_xmldesc NULL
+#define tcpinsizestats_xmldesc NULL
+#define tcpoutsizestats_xmldesc NULL
+#define dnstapstats_xmldesc NULL
+#define gluecachestats_xmldesc NULL
+#endif /* EXTENDED_STATS */
+
+#define TRY0(a) \
+ do { \
+ xmlrc = (a); \
+ if (xmlrc < 0) \
+ goto cleanup; \
+ } while (0)
+
+/*%
+ * Mapping arrays to represent statistics counters in the order of our
+ * preference, regardless of the order of counter indices. For example,
+ * nsstats_desc[nsstats_index[0]] will be the description that is shown first.
+ */
+static int nsstats_index[ns_statscounter_max];
+static int resstats_index[dns_resstatscounter_max];
+static int adbstats_index[dns_adbstats_max];
+static int zonestats_index[dns_zonestatscounter_max];
+static int sockstats_index[isc_sockstatscounter_max];
+static int dnssecstats_index[dns_dnssecstats_max];
+static int udpinsizestats_index[dns_sizecounter_in_max];
+static int udpoutsizestats_index[dns_sizecounter_out_max];
+static int tcpinsizestats_index[dns_sizecounter_in_max];
+static int tcpoutsizestats_index[dns_sizecounter_out_max];
+static int dnstapstats_index[dns_dnstapcounter_max];
+static int gluecachestats_index[dns_gluecachestatscounter_max];
+
+static void
+set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs,
+ const char *xdesc, const char **xdescs) {
+ REQUIRE(counter < maxcounter);
+ REQUIRE(fdescs != NULL && fdescs[counter] == NULL);
+#if defined(EXTENDED_STATS)
+ REQUIRE(xdescs != NULL && xdescs[counter] == NULL);
+#endif /* if defined(EXTENDED_STATS) */
+
+ fdescs[counter] = fdesc;
+#if defined(EXTENDED_STATS)
+ xdescs[counter] = xdesc;
+#else /* if defined(EXTENDED_STATS) */
+ UNUSED(xdesc);
+ UNUSED(xdescs);
+#endif /* if defined(EXTENDED_STATS) */
+}
+
+static void
+init_desc(void) {
+ int i;
+
+ /* Initialize name server statistics */
+ for (i = 0; i < ns_statscounter_max; i++) {
+ nsstats_desc[i] = NULL;
+ }
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < ns_statscounter_max; i++) {
+ nsstats_xmldesc[i] = NULL;
+ }
+#endif /* if defined(EXTENDED_STATS) */
+
+#define SET_NSSTATDESC(counterid, desc, xmldesc) \
+ do { \
+ set_desc(ns_statscounter_##counterid, ns_statscounter_max, \
+ desc, nsstats_desc, xmldesc, nsstats_xmldesc); \
+ nsstats_index[i++] = ns_statscounter_##counterid; \
+ } while (0)
+
+ i = 0;
+ SET_NSSTATDESC(requestv4, "IPv4 requests received", "Requestv4");
+ SET_NSSTATDESC(requestv6, "IPv6 requests received", "Requestv6");
+ SET_NSSTATDESC(edns0in, "requests with EDNS(0) received", "ReqEdns0");
+ SET_NSSTATDESC(badednsver,
+ "requests with unsupported EDNS version received",
+ "ReqBadEDNSVer");
+ SET_NSSTATDESC(tsigin, "requests with TSIG received", "ReqTSIG");
+ SET_NSSTATDESC(sig0in, "requests with SIG(0) received", "ReqSIG0");
+ SET_NSSTATDESC(invalidsig, "requests with invalid signature",
+ "ReqBadSIG");
+ SET_NSSTATDESC(requesttcp, "TCP requests received", "ReqTCP");
+ SET_NSSTATDESC(tcphighwater, "TCP connection high-water",
+ "TCPConnHighWater");
+ SET_NSSTATDESC(authrej, "auth queries rejected", "AuthQryRej");
+ SET_NSSTATDESC(recurserej, "recursive queries rejected", "RecQryRej");
+ SET_NSSTATDESC(xfrrej, "transfer requests rejected", "XfrRej");
+ SET_NSSTATDESC(updaterej, "update requests rejected", "UpdateRej");
+ SET_NSSTATDESC(response, "responses sent", "Response");
+ SET_NSSTATDESC(truncatedresp, "truncated responses sent",
+ "TruncatedResp");
+ SET_NSSTATDESC(edns0out, "responses with EDNS(0) sent", "RespEDNS0");
+ SET_NSSTATDESC(tsigout, "responses with TSIG sent", "RespTSIG");
+ SET_NSSTATDESC(sig0out, "responses with SIG(0) sent", "RespSIG0");
+ SET_NSSTATDESC(success, "queries resulted in successful answer",
+ "QrySuccess");
+ SET_NSSTATDESC(authans, "queries resulted in authoritative answer",
+ "QryAuthAns");
+ SET_NSSTATDESC(nonauthans,
+ "queries resulted in non authoritative answer",
+ "QryNoauthAns");
+ SET_NSSTATDESC(referral, "queries resulted in referral answer",
+ "QryReferral");
+ SET_NSSTATDESC(nxrrset, "queries resulted in nxrrset", "QryNxrrset");
+ SET_NSSTATDESC(servfail, "queries resulted in SERVFAIL", "QrySERVFAIL");
+ SET_NSSTATDESC(formerr, "queries resulted in FORMERR", "QryFORMERR");
+ SET_NSSTATDESC(nxdomain, "queries resulted in NXDOMAIN", "QryNXDOMAIN");
+ SET_NSSTATDESC(recursion, "queries caused recursion", "QryRecursion");
+ SET_NSSTATDESC(duplicate, "duplicate queries received", "QryDuplicate");
+ SET_NSSTATDESC(dropped, "queries dropped", "QryDropped");
+ SET_NSSTATDESC(failure, "other query failures", "QryFailure");
+ SET_NSSTATDESC(xfrdone, "requested transfers completed", "XfrReqDone");
+ SET_NSSTATDESC(updatereqfwd, "update requests forwarded",
+ "UpdateReqFwd");
+ SET_NSSTATDESC(updaterespfwd, "update responses forwarded",
+ "UpdateRespFwd");
+ SET_NSSTATDESC(updatefwdfail, "update forward failed", "UpdateFwdFail");
+ SET_NSSTATDESC(updatedone, "updates completed", "UpdateDone");
+ SET_NSSTATDESC(updatefail, "updates failed", "UpdateFail");
+ SET_NSSTATDESC(updatebadprereq,
+ "updates rejected due to prerequisite failure",
+ "UpdateBadPrereq");
+ SET_NSSTATDESC(recursclients, "recursing clients", "RecursClients");
+ SET_NSSTATDESC(dns64, "queries answered by DNS64", "DNS64");
+ SET_NSSTATDESC(ratedropped, "responses dropped for rate limits",
+ "RateDropped");
+ SET_NSSTATDESC(rateslipped, "responses truncated for rate limits",
+ "RateSlipped");
+ SET_NSSTATDESC(rpz_rewrites, "response policy zone rewrites",
+ "RPZRewrites");
+ SET_NSSTATDESC(udp, "UDP queries received", "QryUDP");
+ SET_NSSTATDESC(tcp, "TCP queries received", "QryTCP");
+ SET_NSSTATDESC(nsidopt, "NSID option received", "NSIDOpt");
+ SET_NSSTATDESC(expireopt, "Expire option received", "ExpireOpt");
+ SET_NSSTATDESC(keepaliveopt, "EDNS TCP keepalive option received",
+ "KeepAliveOpt");
+ SET_NSSTATDESC(padopt, "EDNS padding option received", "PadOpt");
+ SET_NSSTATDESC(otheropt, "Other EDNS option received", "OtherOpt");
+ SET_NSSTATDESC(cookiein, "COOKIE option received", "CookieIn");
+ SET_NSSTATDESC(cookienew, "COOKIE - client only", "CookieNew");
+ SET_NSSTATDESC(cookiebadsize, "COOKIE - bad size", "CookieBadSize");
+ SET_NSSTATDESC(cookiebadtime, "COOKIE - bad time", "CookieBadTime");
+ SET_NSSTATDESC(cookienomatch, "COOKIE - no match", "CookieNoMatch");
+ SET_NSSTATDESC(cookiematch, "COOKIE - match", "CookieMatch");
+ SET_NSSTATDESC(ecsopt, "EDNS client subnet option received", "ECSOpt");
+ SET_NSSTATDESC(nxdomainredirect,
+ "queries resulted in NXDOMAIN that were redirected",
+ "QryNXRedir");
+ SET_NSSTATDESC(nxdomainredirect_rlookup,
+ "queries resulted in NXDOMAIN that were redirected and "
+ "resulted in a successful remote lookup",
+ "QryNXRedirRLookup");
+ SET_NSSTATDESC(badcookie, "sent badcookie response", "QryBADCOOKIE");
+ SET_NSSTATDESC(nxdomainsynth, "synthesized a NXDOMAIN response",
+ "SynthNXDOMAIN");
+ SET_NSSTATDESC(nodatasynth, "synthesized a no-data response",
+ "SynthNODATA");
+ SET_NSSTATDESC(wildcardsynth, "synthesized a wildcard response",
+ "SynthWILDCARD");
+ SET_NSSTATDESC(trystale,
+ "attempts to use stale cache data after lookup failure",
+ "QryTryStale");
+ SET_NSSTATDESC(usedstale,
+ "successful uses of stale cache data after lookup "
+ "failure",
+ "QryUsedStale");
+ SET_NSSTATDESC(prefetch, "queries triggered prefetch", "Prefetch");
+ SET_NSSTATDESC(keytagopt, "Keytag option received", "KeyTagOpt");
+ SET_NSSTATDESC(reclimitdropped,
+ "queries dropped due to recursive client limit",
+ "RecLimitDropped");
+ SET_NSSTATDESC(updatequota, "Update quota exceeded", "UpdateQuota");
+
+ INSIST(i == ns_statscounter_max);
+
+ /* Initialize resolver statistics */
+ for (i = 0; i < dns_resstatscounter_max; i++) {
+ resstats_desc[i] = NULL;
+ }
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < dns_resstatscounter_max; i++) {
+ resstats_xmldesc[i] = NULL;
+ }
+#endif /* if defined(EXTENDED_STATS) */
+
+#define SET_RESSTATDESC(counterid, desc, xmldesc) \
+ do { \
+ set_desc(dns_resstatscounter_##counterid, \
+ dns_resstatscounter_max, desc, resstats_desc, \
+ xmldesc, resstats_xmldesc); \
+ resstats_index[i++] = dns_resstatscounter_##counterid; \
+ } while (0)
+
+ i = 0;
+ SET_RESSTATDESC(queryv4, "IPv4 queries sent", "Queryv4");
+ SET_RESSTATDESC(queryv6, "IPv6 queries sent", "Queryv6");
+ SET_RESSTATDESC(responsev4, "IPv4 responses received", "Responsev4");
+ SET_RESSTATDESC(responsev6, "IPv6 responses received", "Responsev6");
+ SET_RESSTATDESC(nxdomain, "NXDOMAIN received", "NXDOMAIN");
+ SET_RESSTATDESC(servfail, "SERVFAIL received", "SERVFAIL");
+ SET_RESSTATDESC(formerr, "FORMERR received", "FORMERR");
+ SET_RESSTATDESC(othererror, "other errors received", "OtherError");
+ SET_RESSTATDESC(edns0fail, "EDNS(0) query failures", "EDNS0Fail");
+ SET_RESSTATDESC(mismatch, "mismatch responses received", "Mismatch");
+ SET_RESSTATDESC(truncated, "truncated responses received", "Truncated");
+ SET_RESSTATDESC(lame, "lame delegations received", "Lame");
+ SET_RESSTATDESC(retry, "query retries", "Retry");
+ SET_RESSTATDESC(dispabort, "queries aborted due to quota",
+ "QueryAbort");
+ SET_RESSTATDESC(dispsockfail, "failures in opening query sockets",
+ "QuerySockFail");
+ SET_RESSTATDESC(disprequdp, "UDP queries in progress", "QueryCurUDP");
+ SET_RESSTATDESC(dispreqtcp, "TCP queries in progress", "QueryCurTCP");
+ SET_RESSTATDESC(querytimeout, "query timeouts", "QueryTimeout");
+ SET_RESSTATDESC(gluefetchv4, "IPv4 NS address fetches", "GlueFetchv4");
+ SET_RESSTATDESC(gluefetchv6, "IPv6 NS address fetches", "GlueFetchv6");
+ SET_RESSTATDESC(gluefetchv4fail, "IPv4 NS address fetch failed",
+ "GlueFetchv4Fail");
+ SET_RESSTATDESC(gluefetchv6fail, "IPv6 NS address fetch failed",
+ "GlueFetchv6Fail");
+ SET_RESSTATDESC(val, "DNSSEC validation attempted", "ValAttempt");
+ SET_RESSTATDESC(valsuccess, "DNSSEC validation succeeded", "ValOk");
+ SET_RESSTATDESC(valnegsuccess, "DNSSEC NX validation succeeded",
+ "ValNegOk");
+ SET_RESSTATDESC(valfail, "DNSSEC validation failed", "ValFail");
+ SET_RESSTATDESC(queryrtt0,
+ "queries with RTT < " DNS_RESOLVER_QRYRTTCLASS0STR "ms",
+ "QryRTT" DNS_RESOLVER_QRYRTTCLASS0STR);
+ SET_RESSTATDESC(queryrtt1,
+ "queries with RTT " DNS_RESOLVER_QRYRTTCLASS0STR
+ "-" DNS_RESOLVER_QRYRTTCLASS1STR "ms",
+ "QryRTT" DNS_RESOLVER_QRYRTTCLASS1STR);
+ SET_RESSTATDESC(queryrtt2,
+ "queries with RTT " DNS_RESOLVER_QRYRTTCLASS1STR
+ "-" DNS_RESOLVER_QRYRTTCLASS2STR "ms",
+ "QryRTT" DNS_RESOLVER_QRYRTTCLASS2STR);
+ SET_RESSTATDESC(queryrtt3,
+ "queries with RTT " DNS_RESOLVER_QRYRTTCLASS2STR
+ "-" DNS_RESOLVER_QRYRTTCLASS3STR "ms",
+ "QryRTT" DNS_RESOLVER_QRYRTTCLASS3STR);
+ SET_RESSTATDESC(queryrtt4,
+ "queries with RTT " DNS_RESOLVER_QRYRTTCLASS3STR
+ "-" DNS_RESOLVER_QRYRTTCLASS4STR "ms",
+ "QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR);
+ SET_RESSTATDESC(queryrtt5,
+ "queries with RTT > " DNS_RESOLVER_QRYRTTCLASS4STR "ms",
+ "QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR "+");
+ SET_RESSTATDESC(nfetch, "active fetches", "NumFetch");
+ SET_RESSTATDESC(buckets, "bucket size", "BucketSize");
+ SET_RESSTATDESC(refused, "REFUSED received", "REFUSED");
+ SET_RESSTATDESC(cookienew, "COOKIE send with client cookie only",
+ "ClientCookieOut");
+ SET_RESSTATDESC(cookieout, "COOKIE sent with client and server cookie",
+ "ServerCookieOut");
+ SET_RESSTATDESC(cookiein, "COOKIE replies received", "CookieIn");
+ SET_RESSTATDESC(cookieok, "COOKIE client ok", "CookieClientOk");
+ SET_RESSTATDESC(badvers, "bad EDNS version", "BadEDNSVersion");
+ SET_RESSTATDESC(badcookie, "bad cookie rcode", "BadCookieRcode");
+ SET_RESSTATDESC(zonequota, "spilled due to zone quota", "ZoneQuota");
+ SET_RESSTATDESC(serverquota, "spilled due to server quota",
+ "ServerQuota");
+ SET_RESSTATDESC(clientquota, "spilled due to clients per query quota",
+ "ClientQuota");
+ SET_RESSTATDESC(nextitem, "waited for next item", "NextItem");
+ SET_RESSTATDESC(priming, "priming queries", "Priming");
+
+ INSIST(i == dns_resstatscounter_max);
+
+ /* Initialize adb statistics */
+ for (i = 0; i < dns_adbstats_max; i++) {
+ adbstats_desc[i] = NULL;
+ }
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < dns_adbstats_max; i++) {
+ adbstats_xmldesc[i] = NULL;
+ }
+#endif /* if defined(EXTENDED_STATS) */
+
+#define SET_ADBSTATDESC(id, desc, xmldesc) \
+ do { \
+ set_desc(dns_adbstats_##id, dns_adbstats_max, desc, \
+ adbstats_desc, xmldesc, adbstats_xmldesc); \
+ adbstats_index[i++] = dns_adbstats_##id; \
+ } while (0)
+ i = 0;
+ SET_ADBSTATDESC(nentries, "Address hash table size", "nentries");
+ SET_ADBSTATDESC(entriescnt, "Addresses in hash table", "entriescnt");
+ SET_ADBSTATDESC(nnames, "Name hash table size", "nnames");
+ SET_ADBSTATDESC(namescnt, "Names in hash table", "namescnt");
+
+ INSIST(i == dns_adbstats_max);
+
+ /* Initialize zone statistics */
+ for (i = 0; i < dns_zonestatscounter_max; i++) {
+ zonestats_desc[i] = NULL;
+ }
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < dns_zonestatscounter_max; i++) {
+ zonestats_xmldesc[i] = NULL;
+ }
+#endif /* if defined(EXTENDED_STATS) */
+
+#define SET_ZONESTATDESC(counterid, desc, xmldesc) \
+ do { \
+ set_desc(dns_zonestatscounter_##counterid, \
+ dns_zonestatscounter_max, desc, zonestats_desc, \
+ xmldesc, zonestats_xmldesc); \
+ zonestats_index[i++] = dns_zonestatscounter_##counterid; \
+ } while (0)
+
+ i = 0;
+ SET_ZONESTATDESC(notifyoutv4, "IPv4 notifies sent", "NotifyOutv4");
+ SET_ZONESTATDESC(notifyoutv6, "IPv6 notifies sent", "NotifyOutv6");
+ SET_ZONESTATDESC(notifyinv4, "IPv4 notifies received", "NotifyInv4");
+ SET_ZONESTATDESC(notifyinv6, "IPv6 notifies received", "NotifyInv6");
+ SET_ZONESTATDESC(notifyrej, "notifies rejected", "NotifyRej");
+ SET_ZONESTATDESC(soaoutv4, "IPv4 SOA queries sent", "SOAOutv4");
+ SET_ZONESTATDESC(soaoutv6, "IPv6 SOA queries sent", "SOAOutv6");
+ SET_ZONESTATDESC(axfrreqv4, "IPv4 AXFR requested", "AXFRReqv4");
+ SET_ZONESTATDESC(axfrreqv6, "IPv6 AXFR requested", "AXFRReqv6");
+ SET_ZONESTATDESC(ixfrreqv4, "IPv4 IXFR requested", "IXFRReqv4");
+ SET_ZONESTATDESC(ixfrreqv6, "IPv6 IXFR requested", "IXFRReqv6");
+ SET_ZONESTATDESC(xfrsuccess, "transfer requests succeeded",
+ "XfrSuccess");
+ SET_ZONESTATDESC(xfrfail, "transfer requests failed", "XfrFail");
+ INSIST(i == dns_zonestatscounter_max);
+
+ /* Initialize socket statistics */
+ for (i = 0; i < isc_sockstatscounter_max; i++) {
+ sockstats_desc[i] = NULL;
+ }
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < isc_sockstatscounter_max; i++) {
+ sockstats_xmldesc[i] = NULL;
+ }
+#endif /* if defined(EXTENDED_STATS) */
+
+#define SET_SOCKSTATDESC(counterid, desc, xmldesc) \
+ do { \
+ set_desc(isc_sockstatscounter_##counterid, \
+ isc_sockstatscounter_max, desc, sockstats_desc, \
+ xmldesc, sockstats_xmldesc); \
+ sockstats_index[i++] = isc_sockstatscounter_##counterid; \
+ } while (0)
+
+ i = 0;
+ SET_SOCKSTATDESC(udp4open, "UDP/IPv4 sockets opened", "UDP4Open");
+ SET_SOCKSTATDESC(udp6open, "UDP/IPv6 sockets opened", "UDP6Open");
+ SET_SOCKSTATDESC(tcp4open, "TCP/IPv4 sockets opened", "TCP4Open");
+ SET_SOCKSTATDESC(tcp6open, "TCP/IPv6 sockets opened", "TCP6Open");
+ SET_SOCKSTATDESC(unixopen, "Unix domain sockets opened", "UnixOpen");
+ SET_SOCKSTATDESC(rawopen, "Raw sockets opened", "RawOpen");
+ SET_SOCKSTATDESC(udp4openfail, "UDP/IPv4 socket open failures",
+ "UDP4OpenFail");
+ SET_SOCKSTATDESC(udp6openfail, "UDP/IPv6 socket open failures",
+ "UDP6OpenFail");
+ SET_SOCKSTATDESC(tcp4openfail, "TCP/IPv4 socket open failures",
+ "TCP4OpenFail");
+ SET_SOCKSTATDESC(tcp6openfail, "TCP/IPv6 socket open failures",
+ "TCP6OpenFail");
+ SET_SOCKSTATDESC(unixopenfail, "Unix domain socket open failures",
+ "UnixOpenFail");
+ SET_SOCKSTATDESC(rawopenfail, "Raw socket open failures",
+ "RawOpenFail");
+ SET_SOCKSTATDESC(udp4close, "UDP/IPv4 sockets closed", "UDP4Close");
+ SET_SOCKSTATDESC(udp6close, "UDP/IPv6 sockets closed", "UDP6Close");
+ SET_SOCKSTATDESC(tcp4close, "TCP/IPv4 sockets closed", "TCP4Close");
+ SET_SOCKSTATDESC(tcp6close, "TCP/IPv6 sockets closed", "TCP6Close");
+ SET_SOCKSTATDESC(unixclose, "Unix domain sockets closed", "UnixClose");
+ SET_SOCKSTATDESC(fdwatchclose, "FDwatch sockets closed",
+ "FDWatchClose");
+ SET_SOCKSTATDESC(rawclose, "Raw sockets closed", "RawClose");
+ SET_SOCKSTATDESC(udp4bindfail, "UDP/IPv4 socket bind failures",
+ "UDP4BindFail");
+ SET_SOCKSTATDESC(udp6bindfail, "UDP/IPv6 socket bind failures",
+ "UDP6BindFail");
+ SET_SOCKSTATDESC(tcp4bindfail, "TCP/IPv4 socket bind failures",
+ "TCP4BindFail");
+ SET_SOCKSTATDESC(tcp6bindfail, "TCP/IPv6 socket bind failures",
+ "TCP6BindFail");
+ SET_SOCKSTATDESC(unixbindfail, "Unix domain socket bind failures",
+ "UnixBindFail");
+ SET_SOCKSTATDESC(fdwatchbindfail, "FDwatch socket bind failures",
+ "FdwatchBindFail");
+ SET_SOCKSTATDESC(udp4connectfail, "UDP/IPv4 socket connect failures",
+ "UDP4ConnFail");
+ SET_SOCKSTATDESC(udp6connectfail, "UDP/IPv6 socket connect failures",
+ "UDP6ConnFail");
+ SET_SOCKSTATDESC(tcp4connectfail, "TCP/IPv4 socket connect failures",
+ "TCP4ConnFail");
+ SET_SOCKSTATDESC(tcp6connectfail, "TCP/IPv6 socket connect failures",
+ "TCP6ConnFail");
+ SET_SOCKSTATDESC(unixconnectfail, "Unix domain socket connect failures",
+ "UnixConnFail");
+ SET_SOCKSTATDESC(fdwatchconnectfail, "FDwatch socket connect failures",
+ "FDwatchConnFail");
+ SET_SOCKSTATDESC(udp4connect, "UDP/IPv4 connections established",
+ "UDP4Conn");
+ SET_SOCKSTATDESC(udp6connect, "UDP/IPv6 connections established",
+ "UDP6Conn");
+ SET_SOCKSTATDESC(tcp4connect, "TCP/IPv4 connections established",
+ "TCP4Conn");
+ SET_SOCKSTATDESC(tcp6connect, "TCP/IPv6 connections established",
+ "TCP6Conn");
+ SET_SOCKSTATDESC(unixconnect, "Unix domain connections established",
+ "UnixConn");
+ SET_SOCKSTATDESC(fdwatchconnect,
+ "FDwatch domain connections established",
+ "FDwatchConn");
+ SET_SOCKSTATDESC(tcp4acceptfail, "TCP/IPv4 connection accept failures",
+ "TCP4AcceptFail");
+ SET_SOCKSTATDESC(tcp6acceptfail, "TCP/IPv6 connection accept failures",
+ "TCP6AcceptFail");
+ SET_SOCKSTATDESC(unixacceptfail,
+ "Unix domain connection accept failures",
+ "UnixAcceptFail");
+ SET_SOCKSTATDESC(tcp4accept, "TCP/IPv4 connections accepted",
+ "TCP4Accept");
+ SET_SOCKSTATDESC(tcp6accept, "TCP/IPv6 connections accepted",
+ "TCP6Accept");
+ SET_SOCKSTATDESC(unixaccept, "Unix domain connections accepted",
+ "UnixAccept");
+ SET_SOCKSTATDESC(udp4sendfail, "UDP/IPv4 send errors", "UDP4SendErr");
+ SET_SOCKSTATDESC(udp6sendfail, "UDP/IPv6 send errors", "UDP6SendErr");
+ SET_SOCKSTATDESC(tcp4sendfail, "TCP/IPv4 send errors", "TCP4SendErr");
+ SET_SOCKSTATDESC(tcp6sendfail, "TCP/IPv6 send errors", "TCP6SendErr");
+ SET_SOCKSTATDESC(unixsendfail, "Unix domain send errors",
+ "UnixSendErr");
+ SET_SOCKSTATDESC(fdwatchsendfail, "FDwatch send errors",
+ "FDwatchSendErr");
+ SET_SOCKSTATDESC(udp4recvfail, "UDP/IPv4 recv errors", "UDP4RecvErr");
+ SET_SOCKSTATDESC(udp6recvfail, "UDP/IPv6 recv errors", "UDP6RecvErr");
+ SET_SOCKSTATDESC(tcp4recvfail, "TCP/IPv4 recv errors", "TCP4RecvErr");
+ SET_SOCKSTATDESC(tcp6recvfail, "TCP/IPv6 recv errors", "TCP6RecvErr");
+ SET_SOCKSTATDESC(unixrecvfail, "Unix domain recv errors",
+ "UnixRecvErr");
+ SET_SOCKSTATDESC(fdwatchrecvfail, "FDwatch recv errors",
+ "FDwatchRecvErr");
+ SET_SOCKSTATDESC(rawrecvfail, "Raw recv errors", "RawRecvErr");
+ SET_SOCKSTATDESC(udp4active, "UDP/IPv4 sockets active", "UDP4Active");
+ SET_SOCKSTATDESC(udp6active, "UDP/IPv6 sockets active", "UDP6Active");
+ SET_SOCKSTATDESC(tcp4active, "TCP/IPv4 sockets active", "TCP4Active");
+ SET_SOCKSTATDESC(tcp6active, "TCP/IPv6 sockets active", "TCP6Active");
+ SET_SOCKSTATDESC(unixactive, "Unix domain sockets active",
+ "UnixActive");
+ SET_SOCKSTATDESC(rawactive, "Raw sockets active", "RawActive");
+ INSIST(i == isc_sockstatscounter_max);
+
+ /* Initialize DNSSEC statistics */
+ for (i = 0; i < dns_dnssecstats_max; i++) {
+ dnssecstats_desc[i] = NULL;
+ }
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < dns_dnssecstats_max; i++) {
+ dnssecstats_xmldesc[i] = NULL;
+ }
+#endif /* if defined(EXTENDED_STATS) */
+
+#define SET_DNSSECSTATDESC(counterid, desc, xmldesc) \
+ do { \
+ set_desc(dns_dnssecstats_##counterid, dns_dnssecstats_max, \
+ desc, dnssecstats_desc, xmldesc, \
+ dnssecstats_xmldesc); \
+ dnssecstats_index[i++] = dns_dnssecstats_##counterid; \
+ } while (0)
+
+ i = 0;
+ SET_DNSSECSTATDESC(asis,
+ "dnssec validation success with signer "
+ "\"as is\"",
+ "DNSSECasis");
+ SET_DNSSECSTATDESC(downcase,
+ "dnssec validation success with signer "
+ "lower cased",
+ "DNSSECdowncase");
+ SET_DNSSECSTATDESC(wildcard, "dnssec validation of wildcard signature",
+ "DNSSECwild");
+ SET_DNSSECSTATDESC(fail, "dnssec validation failures", "DNSSECfail");
+ INSIST(i == dns_dnssecstats_max);
+
+ /* Initialize dnstap statistics */
+ for (i = 0; i < dns_dnstapcounter_max; i++) {
+ dnstapstats_desc[i] = NULL;
+ }
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < dns_dnstapcounter_max; i++) {
+ dnstapstats_xmldesc[i] = NULL;
+ }
+#endif /* if defined(EXTENDED_STATS) */
+
+#define SET_DNSTAPSTATDESC(counterid, desc, xmldesc) \
+ do { \
+ set_desc(dns_dnstapcounter_##counterid, dns_dnstapcounter_max, \
+ desc, dnstapstats_desc, xmldesc, \
+ dnstapstats_xmldesc); \
+ dnstapstats_index[i++] = dns_dnstapcounter_##counterid; \
+ } while (0)
+ i = 0;
+ SET_DNSTAPSTATDESC(success, "dnstap messages written", "DNSTAPsuccess");
+ SET_DNSTAPSTATDESC(drop, "dnstap messages dropped", "DNSTAPdropped");
+ INSIST(i == dns_dnstapcounter_max);
+
+#define SET_GLUECACHESTATDESC(counterid, desc, xmldesc) \
+ do { \
+ set_desc(dns_gluecachestatscounter_##counterid, \
+ dns_gluecachestatscounter_max, desc, \
+ gluecachestats_desc, xmldesc, \
+ gluecachestats_xmldesc); \
+ gluecachestats_index[i++] = \
+ dns_gluecachestatscounter_##counterid; \
+ } while (0)
+ i = 0;
+ SET_GLUECACHESTATDESC(hits_present, "Hits for present glue (cached)",
+ "GLUECACHEhitspresent");
+ SET_GLUECACHESTATDESC(hits_absent,
+ "Hits for non-existent glue (cached)",
+ "GLUECACHEhitsabsent");
+ SET_GLUECACHESTATDESC(inserts_present,
+ "Miss-plus-cache-inserts for present glue",
+ "GLUECACHEinsertspresent");
+ SET_GLUECACHESTATDESC(inserts_absent,
+ "Miss-plus-cache-inserts for non-existent glue",
+ "GLUECACHEinsertsabsent");
+ INSIST(i == dns_gluecachestatscounter_max);
+
+ /* Sanity check */
+ for (i = 0; i < ns_statscounter_max; i++) {
+ INSIST(nsstats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_resstatscounter_max; i++) {
+ INSIST(resstats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_adbstats_max; i++) {
+ INSIST(adbstats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_zonestatscounter_max; i++) {
+ INSIST(zonestats_desc[i] != NULL);
+ }
+ for (i = 0; i < isc_sockstatscounter_max; i++) {
+ INSIST(sockstats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_dnssecstats_max; i++) {
+ INSIST(dnssecstats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_dnstapcounter_max; i++) {
+ INSIST(dnstapstats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_gluecachestatscounter_max; i++) {
+ INSIST(gluecachestats_desc[i] != NULL);
+ }
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < ns_statscounter_max; i++) {
+ INSIST(nsstats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_resstatscounter_max; i++) {
+ INSIST(resstats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_adbstats_max; i++) {
+ INSIST(adbstats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_zonestatscounter_max; i++) {
+ INSIST(zonestats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < isc_sockstatscounter_max; i++) {
+ INSIST(sockstats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_dnssecstats_max; i++) {
+ INSIST(dnssecstats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_dnstapcounter_max; i++) {
+ INSIST(dnstapstats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_gluecachestatscounter_max; i++) {
+ INSIST(gluecachestats_xmldesc[i] != NULL);
+ }
+#endif /* if defined(EXTENDED_STATS) */
+
+ /* Initialize traffic size statistics */
+ for (i = 0; i < dns_sizecounter_in_max; i++) {
+ udpinsizestats_desc[i] = NULL;
+ tcpinsizestats_desc[i] = NULL;
+#if defined(EXTENDED_STATS)
+ udpinsizestats_xmldesc[i] = NULL;
+ tcpinsizestats_xmldesc[i] = NULL;
+#endif /* if defined(EXTENDED_STATS) */
+ }
+ for (i = 0; i < dns_sizecounter_out_max; i++) {
+ udpoutsizestats_desc[i] = NULL;
+ tcpoutsizestats_desc[i] = NULL;
+#if defined(EXTENDED_STATS)
+ udpoutsizestats_xmldesc[i] = NULL;
+ tcpoutsizestats_xmldesc[i] = NULL;
+#endif /* if defined(EXTENDED_STATS) */
+ }
+
+#define SET_SIZESTATDESC(counterid, desc, xmldesc, inout) \
+ do { \
+ set_desc(dns_sizecounter_##inout##_##counterid, \
+ dns_sizecounter_##inout##_max, desc, \
+ udp##inout##sizestats_desc, xmldesc, \
+ udp##inout##sizestats_xmldesc); \
+ set_desc(dns_sizecounter_##inout##_##counterid, \
+ dns_sizecounter_##inout##_max, desc, \
+ tcp##inout##sizestats_desc, xmldesc, \
+ tcp##inout##sizestats_xmldesc); \
+ udp##inout##sizestats_index[i] = \
+ dns_sizecounter_##inout##_##counterid; \
+ tcp##inout##sizestats_index[i] = \
+ dns_sizecounter_##inout##_##counterid; \
+ i++; \
+ } while (0)
+
+ i = 0;
+ SET_SIZESTATDESC(0, "requests received 0-15 bytes", "0-15", in);
+ SET_SIZESTATDESC(16, "requests received 16-31 bytes", "16-31", in);
+ SET_SIZESTATDESC(32, "requests received 32-47 bytes", "32-47", in);
+ SET_SIZESTATDESC(48, "requests received 48-63 bytes", "48-63", in);
+ SET_SIZESTATDESC(64, "requests received 64-79 bytes", "64-79", in);
+ SET_SIZESTATDESC(80, "requests received 80-95 bytes", "80-95", in);
+ SET_SIZESTATDESC(96, "requests received 96-111 bytes", "96-111", in);
+ SET_SIZESTATDESC(112, "requests received 112-127 bytes", "112-127", in);
+ SET_SIZESTATDESC(128, "requests received 128-143 bytes", "128-143", in);
+ SET_SIZESTATDESC(144, "requests received 144-159 bytes", "144-159", in);
+ SET_SIZESTATDESC(160, "requests received 160-175 bytes", "160-175", in);
+ SET_SIZESTATDESC(176, "requests received 176-191 bytes", "176-191", in);
+ SET_SIZESTATDESC(192, "requests received 192-207 bytes", "192-207", in);
+ SET_SIZESTATDESC(208, "requests received 208-223 bytes", "208-223", in);
+ SET_SIZESTATDESC(224, "requests received 224-239 bytes", "224-239", in);
+ SET_SIZESTATDESC(240, "requests received 240-255 bytes", "240-255", in);
+ SET_SIZESTATDESC(256, "requests received 256-271 bytes", "256-271", in);
+ SET_SIZESTATDESC(272, "requests received 272-287 bytes", "272-287", in);
+ SET_SIZESTATDESC(288, "requests received 288+ bytes", "288+", in);
+ INSIST(i == dns_sizecounter_in_max);
+
+ i = 0;
+ SET_SIZESTATDESC(0, "responses sent 0-15 bytes", "0-15", out);
+ SET_SIZESTATDESC(16, "responses sent 16-31 bytes", "16-31", out);
+ SET_SIZESTATDESC(32, "responses sent 32-47 bytes", "32-47", out);
+ SET_SIZESTATDESC(48, "responses sent 48-63 bytes", "48-63", out);
+ SET_SIZESTATDESC(64, "responses sent 64-79 bytes", "64-79", out);
+ SET_SIZESTATDESC(80, "responses sent 80-95 bytes", "80-95", out);
+ SET_SIZESTATDESC(96, "responses sent 96-111 bytes", "96-111", out);
+ SET_SIZESTATDESC(112, "responses sent 112-127 bytes", "112-127", out);
+ SET_SIZESTATDESC(128, "responses sent 128-143 bytes", "128-143", out);
+ SET_SIZESTATDESC(144, "responses sent 144-159 bytes", "144-159", out);
+ SET_SIZESTATDESC(160, "responses sent 160-175 bytes", "160-175", out);
+ SET_SIZESTATDESC(176, "responses sent 176-191 bytes", "176-191", out);
+ SET_SIZESTATDESC(192, "responses sent 192-207 bytes", "192-207", out);
+ SET_SIZESTATDESC(208, "responses sent 208-223 bytes", "208-223", out);
+ SET_SIZESTATDESC(224, "responses sent 224-239 bytes", "224-239", out);
+ SET_SIZESTATDESC(240, "responses sent 240-255 bytes", "240-255", out);
+ SET_SIZESTATDESC(256, "responses sent 256-271 bytes", "256-271", out);
+ SET_SIZESTATDESC(272, "responses sent 272-287 bytes", "272-287", out);
+ SET_SIZESTATDESC(288, "responses sent 288-303 bytes", "288-303", out);
+ SET_SIZESTATDESC(304, "responses sent 304-319 bytes", "304-319", out);
+ SET_SIZESTATDESC(320, "responses sent 320-335 bytes", "320-335", out);
+ SET_SIZESTATDESC(336, "responses sent 336-351 bytes", "336-351", out);
+ SET_SIZESTATDESC(352, "responses sent 352-367 bytes", "352-367", out);
+ SET_SIZESTATDESC(368, "responses sent 368-383 bytes", "368-383", out);
+ SET_SIZESTATDESC(384, "responses sent 384-399 bytes", "384-399", out);
+ SET_SIZESTATDESC(400, "responses sent 400-415 bytes", "400-415", out);
+ SET_SIZESTATDESC(416, "responses sent 416-431 bytes", "416-431", out);
+ SET_SIZESTATDESC(432, "responses sent 432-447 bytes", "432-447", out);
+ SET_SIZESTATDESC(448, "responses sent 448-463 bytes", "448-463", out);
+ SET_SIZESTATDESC(464, "responses sent 464-479 bytes", "464-479", out);
+ SET_SIZESTATDESC(480, "responses sent 480-495 bytes", "480-495", out);
+ SET_SIZESTATDESC(496, "responses sent 496-511 bytes", "496-511", out);
+ SET_SIZESTATDESC(512, "responses sent 512-527 bytes", "512-527", out);
+ SET_SIZESTATDESC(528, "responses sent 528-543 bytes", "528-543", out);
+ SET_SIZESTATDESC(544, "responses sent 544-559 bytes", "544-559", out);
+ SET_SIZESTATDESC(560, "responses sent 560-575 bytes", "560-575", out);
+ SET_SIZESTATDESC(576, "responses sent 576-591 bytes", "576-591", out);
+ SET_SIZESTATDESC(592, "responses sent 592-607 bytes", "592-607", out);
+ SET_SIZESTATDESC(608, "responses sent 608-623 bytes", "608-623", out);
+ SET_SIZESTATDESC(624, "responses sent 624-639 bytes", "624-639", out);
+ SET_SIZESTATDESC(640, "responses sent 640-655 bytes", "640-655", out);
+ SET_SIZESTATDESC(656, "responses sent 656-671 bytes", "656-671", out);
+ SET_SIZESTATDESC(672, "responses sent 672-687 bytes", "672-687", out);
+ SET_SIZESTATDESC(688, "responses sent 688-703 bytes", "688-703", out);
+ SET_SIZESTATDESC(704, "responses sent 704-719 bytes", "704-719", out);
+ SET_SIZESTATDESC(720, "responses sent 720-735 bytes", "720-735", out);
+ SET_SIZESTATDESC(736, "responses sent 736-751 bytes", "736-751", out);
+ SET_SIZESTATDESC(752, "responses sent 752-767 bytes", "752-767", out);
+ SET_SIZESTATDESC(768, "responses sent 768-783 bytes", "768-783", out);
+ SET_SIZESTATDESC(784, "responses sent 784-799 bytes", "784-799", out);
+ SET_SIZESTATDESC(800, "responses sent 800-815 bytes", "800-815", out);
+ SET_SIZESTATDESC(816, "responses sent 816-831 bytes", "816-831", out);
+ SET_SIZESTATDESC(832, "responses sent 832-847 bytes", "832-847", out);
+ SET_SIZESTATDESC(848, "responses sent 848-863 bytes", "848-863", out);
+ SET_SIZESTATDESC(864, "responses sent 864-879 bytes", "864-879", out);
+ SET_SIZESTATDESC(880, "responses sent 880-895 bytes", "880-895", out);
+ SET_SIZESTATDESC(896, "responses sent 896-911 bytes", "896-911", out);
+ SET_SIZESTATDESC(912, "responses sent 912-927 bytes", "912-927", out);
+ SET_SIZESTATDESC(928, "responses sent 928-943 bytes", "928-943", out);
+ SET_SIZESTATDESC(944, "responses sent 944-959 bytes", "944-959", out);
+ SET_SIZESTATDESC(960, "responses sent 960-975 bytes", "960-975", out);
+ SET_SIZESTATDESC(976, "responses sent 976-991 bytes", "976-991", out);
+ SET_SIZESTATDESC(992, "responses sent 992-1007 bytes", "992-1007", out);
+ SET_SIZESTATDESC(1008, "responses sent 1008-1023 bytes", "1008-1023",
+ out);
+ SET_SIZESTATDESC(1024, "responses sent 1024-1039 bytes", "1024-1039",
+ out);
+ SET_SIZESTATDESC(1040, "responses sent 1040-1055 bytes", "1040-1055",
+ out);
+ SET_SIZESTATDESC(1056, "responses sent 1056-1071 bytes", "1056-1071",
+ out);
+ SET_SIZESTATDESC(1072, "responses sent 1072-1087 bytes", "1072-1087",
+ out);
+ SET_SIZESTATDESC(1088, "responses sent 1088-1103 bytes", "1088-1103",
+ out);
+ SET_SIZESTATDESC(1104, "responses sent 1104-1119 bytes", "1104-1119",
+ out);
+ SET_SIZESTATDESC(1120, "responses sent 1120-1135 bytes", "1120-1135",
+ out);
+ SET_SIZESTATDESC(1136, "responses sent 1136-1151 bytes", "1136-1151",
+ out);
+ SET_SIZESTATDESC(1152, "responses sent 1152-1167 bytes", "1152-1167",
+ out);
+ SET_SIZESTATDESC(1168, "responses sent 1168-1183 bytes", "1168-1183",
+ out);
+ SET_SIZESTATDESC(1184, "responses sent 1184-1199 bytes", "1184-1199",
+ out);
+ SET_SIZESTATDESC(1200, "responses sent 1200-1215 bytes", "1200-1215",
+ out);
+ SET_SIZESTATDESC(1216, "responses sent 1216-1231 bytes", "1216-1231",
+ out);
+ SET_SIZESTATDESC(1232, "responses sent 1232-1247 bytes", "1232-1247",
+ out);
+ SET_SIZESTATDESC(1248, "responses sent 1248-1263 bytes", "1248-1263",
+ out);
+ SET_SIZESTATDESC(1264, "responses sent 1264-1279 bytes", "1264-1279",
+ out);
+ SET_SIZESTATDESC(1280, "responses sent 1280-1295 bytes", "1280-1295",
+ out);
+ SET_SIZESTATDESC(1296, "responses sent 1296-1311 bytes", "1296-1311",
+ out);
+ SET_SIZESTATDESC(1312, "responses sent 1312-1327 bytes", "1312-1327",
+ out);
+ SET_SIZESTATDESC(1328, "responses sent 1328-1343 bytes", "1328-1343",
+ out);
+ SET_SIZESTATDESC(1344, "responses sent 1344-1359 bytes", "1344-1359",
+ out);
+ SET_SIZESTATDESC(1360, "responses sent 1360-1375 bytes", "1360-1375",
+ out);
+ SET_SIZESTATDESC(1376, "responses sent 1376-1391 bytes", "1376-1391",
+ out);
+ SET_SIZESTATDESC(1392, "responses sent 1392-1407 bytes", "1392-1407",
+ out);
+ SET_SIZESTATDESC(1408, "responses sent 1408-1423 bytes", "1408-1423",
+ out);
+ SET_SIZESTATDESC(1424, "responses sent 1424-1439 bytes", "1424-1439",
+ out);
+ SET_SIZESTATDESC(1440, "responses sent 1440-1455 bytes", "1440-1455",
+ out);
+ SET_SIZESTATDESC(1456, "responses sent 1456-1471 bytes", "1456-1471",
+ out);
+ SET_SIZESTATDESC(1472, "responses sent 1472-1487 bytes", "1472-1487",
+ out);
+ SET_SIZESTATDESC(1488, "responses sent 1488-1503 bytes", "1488-1503",
+ out);
+ SET_SIZESTATDESC(1504, "responses sent 1504-1519 bytes", "1504-1519",
+ out);
+ SET_SIZESTATDESC(1520, "responses sent 1520-1535 bytes", "1520-1535",
+ out);
+ SET_SIZESTATDESC(1536, "responses sent 1536-1551 bytes", "1536-1551",
+ out);
+ SET_SIZESTATDESC(1552, "responses sent 1552-1567 bytes", "1552-1567",
+ out);
+ SET_SIZESTATDESC(1568, "responses sent 1568-1583 bytes", "1568-1583",
+ out);
+ SET_SIZESTATDESC(1584, "responses sent 1584-1599 bytes", "1584-1599",
+ out);
+ SET_SIZESTATDESC(1600, "responses sent 1600-1615 bytes", "1600-1615",
+ out);
+ SET_SIZESTATDESC(1616, "responses sent 1616-1631 bytes", "1616-1631",
+ out);
+ SET_SIZESTATDESC(1632, "responses sent 1632-1647 bytes", "1632-1647",
+ out);
+ SET_SIZESTATDESC(1648, "responses sent 1648-1663 bytes", "1648-1663",
+ out);
+ SET_SIZESTATDESC(1664, "responses sent 1664-1679 bytes", "1664-1679",
+ out);
+ SET_SIZESTATDESC(1680, "responses sent 1680-1695 bytes", "1680-1695",
+ out);
+ SET_SIZESTATDESC(1696, "responses sent 1696-1711 bytes", "1696-1711",
+ out);
+ SET_SIZESTATDESC(1712, "responses sent 1712-1727 bytes", "1712-1727",
+ out);
+ SET_SIZESTATDESC(1728, "responses sent 1728-1743 bytes", "1728-1743",
+ out);
+ SET_SIZESTATDESC(1744, "responses sent 1744-1759 bytes", "1744-1759",
+ out);
+ SET_SIZESTATDESC(1760, "responses sent 1760-1775 bytes", "1760-1775",
+ out);
+ SET_SIZESTATDESC(1776, "responses sent 1776-1791 bytes", "1776-1791",
+ out);
+ SET_SIZESTATDESC(1792, "responses sent 1792-1807 bytes", "1792-1807",
+ out);
+ SET_SIZESTATDESC(1808, "responses sent 1808-1823 bytes", "1808-1823",
+ out);
+ SET_SIZESTATDESC(1824, "responses sent 1824-1839 bytes", "1824-1839",
+ out);
+ SET_SIZESTATDESC(1840, "responses sent 1840-1855 bytes", "1840-1855",
+ out);
+ SET_SIZESTATDESC(1856, "responses sent 1856-1871 bytes", "1856-1871",
+ out);
+ SET_SIZESTATDESC(1872, "responses sent 1872-1887 bytes", "1872-1887",
+ out);
+ SET_SIZESTATDESC(1888, "responses sent 1888-1903 bytes", "1888-1903",
+ out);
+ SET_SIZESTATDESC(1904, "responses sent 1904-1919 bytes", "1904-1919",
+ out);
+ SET_SIZESTATDESC(1920, "responses sent 1920-1935 bytes", "1920-1935",
+ out);
+ SET_SIZESTATDESC(1936, "responses sent 1936-1951 bytes", "1936-1951",
+ out);
+ SET_SIZESTATDESC(1952, "responses sent 1952-1967 bytes", "1952-1967",
+ out);
+ SET_SIZESTATDESC(1968, "responses sent 1968-1983 bytes", "1968-1983",
+ out);
+ SET_SIZESTATDESC(1984, "responses sent 1984-1999 bytes", "1984-1999",
+ out);
+ SET_SIZESTATDESC(2000, "responses sent 2000-2015 bytes", "2000-2015",
+ out);
+ SET_SIZESTATDESC(2016, "responses sent 2016-2031 bytes", "2016-2031",
+ out);
+ SET_SIZESTATDESC(2032, "responses sent 2032-2047 bytes", "2032-2047",
+ out);
+ SET_SIZESTATDESC(2048, "responses sent 2048-2063 bytes", "2048-2063",
+ out);
+ SET_SIZESTATDESC(2064, "responses sent 2064-2079 bytes", "2064-2079",
+ out);
+ SET_SIZESTATDESC(2080, "responses sent 2080-2095 bytes", "2080-2095",
+ out);
+ SET_SIZESTATDESC(2096, "responses sent 2096-2111 bytes", "2096-2111",
+ out);
+ SET_SIZESTATDESC(2112, "responses sent 2112-2127 bytes", "2112-2127",
+ out);
+ SET_SIZESTATDESC(2128, "responses sent 2128-2143 bytes", "2128-2143",
+ out);
+ SET_SIZESTATDESC(2144, "responses sent 2144-2159 bytes", "2144-2159",
+ out);
+ SET_SIZESTATDESC(2160, "responses sent 2160-2175 bytes", "2160-2175",
+ out);
+ SET_SIZESTATDESC(2176, "responses sent 2176-2191 bytes", "2176-2191",
+ out);
+ SET_SIZESTATDESC(2192, "responses sent 2192-2207 bytes", "2192-2207",
+ out);
+ SET_SIZESTATDESC(2208, "responses sent 2208-2223 bytes", "2208-2223",
+ out);
+ SET_SIZESTATDESC(2224, "responses sent 2224-2239 bytes", "2224-2239",
+ out);
+ SET_SIZESTATDESC(2240, "responses sent 2240-2255 bytes", "2240-2255",
+ out);
+ SET_SIZESTATDESC(2256, "responses sent 2256-2271 bytes", "2256-2271",
+ out);
+ SET_SIZESTATDESC(2272, "responses sent 2272-2287 bytes", "2272-2287",
+ out);
+ SET_SIZESTATDESC(2288, "responses sent 2288-2303 bytes", "2288-2303",
+ out);
+ SET_SIZESTATDESC(2304, "responses sent 2304-2319 bytes", "2304-2319",
+ out);
+ SET_SIZESTATDESC(2320, "responses sent 2320-2335 bytes", "2320-2335",
+ out);
+ SET_SIZESTATDESC(2336, "responses sent 2336-2351 bytes", "2336-2351",
+ out);
+ SET_SIZESTATDESC(2352, "responses sent 2352-2367 bytes", "2352-2367",
+ out);
+ SET_SIZESTATDESC(2368, "responses sent 2368-2383 bytes", "2368-2383",
+ out);
+ SET_SIZESTATDESC(2384, "responses sent 2384-2399 bytes", "2384-2399",
+ out);
+ SET_SIZESTATDESC(2400, "responses sent 2400-2415 bytes", "2400-2415",
+ out);
+ SET_SIZESTATDESC(2416, "responses sent 2416-2431 bytes", "2416-2431",
+ out);
+ SET_SIZESTATDESC(2432, "responses sent 2432-2447 bytes", "2432-2447",
+ out);
+ SET_SIZESTATDESC(2448, "responses sent 2448-2463 bytes", "2448-2463",
+ out);
+ SET_SIZESTATDESC(2464, "responses sent 2464-2479 bytes", "2464-2479",
+ out);
+ SET_SIZESTATDESC(2480, "responses sent 2480-2495 bytes", "2480-2495",
+ out);
+ SET_SIZESTATDESC(2496, "responses sent 2496-2511 bytes", "2496-2511",
+ out);
+ SET_SIZESTATDESC(2512, "responses sent 2512-2527 bytes", "2512-2527",
+ out);
+ SET_SIZESTATDESC(2528, "responses sent 2528-2543 bytes", "2528-2543",
+ out);
+ SET_SIZESTATDESC(2544, "responses sent 2544-2559 bytes", "2544-2559",
+ out);
+ SET_SIZESTATDESC(2560, "responses sent 2560-2575 bytes", "2560-2575",
+ out);
+ SET_SIZESTATDESC(2576, "responses sent 2576-2591 bytes", "2576-2591",
+ out);
+ SET_SIZESTATDESC(2592, "responses sent 2592-2607 bytes", "2592-2607",
+ out);
+ SET_SIZESTATDESC(2608, "responses sent 2608-2623 bytes", "2608-2623",
+ out);
+ SET_SIZESTATDESC(2624, "responses sent 2624-2639 bytes", "2624-2639",
+ out);
+ SET_SIZESTATDESC(2640, "responses sent 2640-2655 bytes", "2640-2655",
+ out);
+ SET_SIZESTATDESC(2656, "responses sent 2656-2671 bytes", "2656-2671",
+ out);
+ SET_SIZESTATDESC(2672, "responses sent 2672-2687 bytes", "2672-2687",
+ out);
+ SET_SIZESTATDESC(2688, "responses sent 2688-2703 bytes", "2688-2703",
+ out);
+ SET_SIZESTATDESC(2704, "responses sent 2704-2719 bytes", "2704-2719",
+ out);
+ SET_SIZESTATDESC(2720, "responses sent 2720-2735 bytes", "2720-2735",
+ out);
+ SET_SIZESTATDESC(2736, "responses sent 2736-2751 bytes", "2736-2751",
+ out);
+ SET_SIZESTATDESC(2752, "responses sent 2752-2767 bytes", "2752-2767",
+ out);
+ SET_SIZESTATDESC(2768, "responses sent 2768-2783 bytes", "2768-2783",
+ out);
+ SET_SIZESTATDESC(2784, "responses sent 2784-2799 bytes", "2784-2799",
+ out);
+ SET_SIZESTATDESC(2800, "responses sent 2800-2815 bytes", "2800-2815",
+ out);
+ SET_SIZESTATDESC(2816, "responses sent 2816-2831 bytes", "2816-2831",
+ out);
+ SET_SIZESTATDESC(2832, "responses sent 2832-2847 bytes", "2832-2847",
+ out);
+ SET_SIZESTATDESC(2848, "responses sent 2848-2863 bytes", "2848-2863",
+ out);
+ SET_SIZESTATDESC(2864, "responses sent 2864-2879 bytes", "2864-2879",
+ out);
+ SET_SIZESTATDESC(2880, "responses sent 2880-2895 bytes", "2880-2895",
+ out);
+ SET_SIZESTATDESC(2896, "responses sent 2896-2911 bytes", "2896-2911",
+ out);
+ SET_SIZESTATDESC(2912, "responses sent 2912-2927 bytes", "2912-2927",
+ out);
+ SET_SIZESTATDESC(2928, "responses sent 2928-2943 bytes", "2928-2943",
+ out);
+ SET_SIZESTATDESC(2944, "responses sent 2944-2959 bytes", "2944-2959",
+ out);
+ SET_SIZESTATDESC(2960, "responses sent 2960-2975 bytes", "2960-2975",
+ out);
+ SET_SIZESTATDESC(2976, "responses sent 2976-2991 bytes", "2976-2991",
+ out);
+ SET_SIZESTATDESC(2992, "responses sent 2992-3007 bytes", "2992-3007",
+ out);
+ SET_SIZESTATDESC(3008, "responses sent 3008-3023 bytes", "3008-3023",
+ out);
+ SET_SIZESTATDESC(3024, "responses sent 3024-3039 bytes", "3024-3039",
+ out);
+ SET_SIZESTATDESC(3040, "responses sent 3040-3055 bytes", "3040-3055",
+ out);
+ SET_SIZESTATDESC(3056, "responses sent 3056-3071 bytes", "3056-3071",
+ out);
+ SET_SIZESTATDESC(3072, "responses sent 3072-3087 bytes", "3072-3087",
+ out);
+ SET_SIZESTATDESC(3088, "responses sent 3088-3103 bytes", "3088-3103",
+ out);
+ SET_SIZESTATDESC(3104, "responses sent 3104-3119 bytes", "3104-3119",
+ out);
+ SET_SIZESTATDESC(3120, "responses sent 3120-3135 bytes", "3120-3135",
+ out);
+ SET_SIZESTATDESC(3136, "responses sent 3136-3151 bytes", "3136-3151",
+ out);
+ SET_SIZESTATDESC(3152, "responses sent 3152-3167 bytes", "3152-3167",
+ out);
+ SET_SIZESTATDESC(3168, "responses sent 3168-3183 bytes", "3168-3183",
+ out);
+ SET_SIZESTATDESC(3184, "responses sent 3184-3199 bytes", "3184-3199",
+ out);
+ SET_SIZESTATDESC(3200, "responses sent 3200-3215 bytes", "3200-3215",
+ out);
+ SET_SIZESTATDESC(3216, "responses sent 3216-3231 bytes", "3216-3231",
+ out);
+ SET_SIZESTATDESC(3232, "responses sent 3232-3247 bytes", "3232-3247",
+ out);
+ SET_SIZESTATDESC(3248, "responses sent 3248-3263 bytes", "3248-3263",
+ out);
+ SET_SIZESTATDESC(3264, "responses sent 3264-3279 bytes", "3264-3279",
+ out);
+ SET_SIZESTATDESC(3280, "responses sent 3280-3295 bytes", "3280-3295",
+ out);
+ SET_SIZESTATDESC(3296, "responses sent 3296-3311 bytes", "3296-3311",
+ out);
+ SET_SIZESTATDESC(3312, "responses sent 3312-3327 bytes", "3312-3327",
+ out);
+ SET_SIZESTATDESC(3328, "responses sent 3328-3343 bytes", "3328-3343",
+ out);
+ SET_SIZESTATDESC(3344, "responses sent 3344-3359 bytes", "3344-3359",
+ out);
+ SET_SIZESTATDESC(3360, "responses sent 3360-3375 bytes", "3360-3375",
+ out);
+ SET_SIZESTATDESC(3376, "responses sent 3376-3391 bytes", "3376-3391",
+ out);
+ SET_SIZESTATDESC(3392, "responses sent 3392-3407 bytes", "3392-3407",
+ out);
+ SET_SIZESTATDESC(3408, "responses sent 3408-3423 bytes", "3408-3423",
+ out);
+ SET_SIZESTATDESC(3424, "responses sent 3424-3439 bytes", "3424-3439",
+ out);
+ SET_SIZESTATDESC(3440, "responses sent 3440-3455 bytes", "3440-3455",
+ out);
+ SET_SIZESTATDESC(3456, "responses sent 3456-3471 bytes", "3456-3471",
+ out);
+ SET_SIZESTATDESC(3472, "responses sent 3472-3487 bytes", "3472-3487",
+ out);
+ SET_SIZESTATDESC(3488, "responses sent 3488-3503 bytes", "3488-3503",
+ out);
+ SET_SIZESTATDESC(3504, "responses sent 3504-3519 bytes", "3504-3519",
+ out);
+ SET_SIZESTATDESC(3520, "responses sent 3520-3535 bytes", "3520-3535",
+ out);
+ SET_SIZESTATDESC(3536, "responses sent 3536-3551 bytes", "3536-3551",
+ out);
+ SET_SIZESTATDESC(3552, "responses sent 3552-3567 bytes", "3552-3567",
+ out);
+ SET_SIZESTATDESC(3568, "responses sent 3568-3583 bytes", "3568-3583",
+ out);
+ SET_SIZESTATDESC(3584, "responses sent 3584-3599 bytes", "3584-3599",
+ out);
+ SET_SIZESTATDESC(3600, "responses sent 3600-3615 bytes", "3600-3615",
+ out);
+ SET_SIZESTATDESC(3616, "responses sent 3616-3631 bytes", "3616-3631",
+ out);
+ SET_SIZESTATDESC(3632, "responses sent 3632-3647 bytes", "3632-3647",
+ out);
+ SET_SIZESTATDESC(3648, "responses sent 3648-3663 bytes", "3648-3663",
+ out);
+ SET_SIZESTATDESC(3664, "responses sent 3664-3679 bytes", "3664-3679",
+ out);
+ SET_SIZESTATDESC(3680, "responses sent 3680-3695 bytes", "3680-3695",
+ out);
+ SET_SIZESTATDESC(3696, "responses sent 3696-3711 bytes", "3696-3711",
+ out);
+ SET_SIZESTATDESC(3712, "responses sent 3712-3727 bytes", "3712-3727",
+ out);
+ SET_SIZESTATDESC(3728, "responses sent 3728-3743 bytes", "3728-3743",
+ out);
+ SET_SIZESTATDESC(3744, "responses sent 3744-3759 bytes", "3744-3759",
+ out);
+ SET_SIZESTATDESC(3760, "responses sent 3760-3775 bytes", "3760-3775",
+ out);
+ SET_SIZESTATDESC(3776, "responses sent 3776-3791 bytes", "3776-3791",
+ out);
+ SET_SIZESTATDESC(3792, "responses sent 3792-3807 bytes", "3792-3807",
+ out);
+ SET_SIZESTATDESC(3808, "responses sent 3808-3823 bytes", "3808-3823",
+ out);
+ SET_SIZESTATDESC(3824, "responses sent 3824-3839 bytes", "3824-3839",
+ out);
+ SET_SIZESTATDESC(3840, "responses sent 3840-3855 bytes", "3840-3855",
+ out);
+ SET_SIZESTATDESC(3856, "responses sent 3856-3871 bytes", "3856-3871",
+ out);
+ SET_SIZESTATDESC(3872, "responses sent 3872-3887 bytes", "3872-3887",
+ out);
+ SET_SIZESTATDESC(3888, "responses sent 3888-3903 bytes", "3888-3903",
+ out);
+ SET_SIZESTATDESC(3904, "responses sent 3904-3919 bytes", "3904-3919",
+ out);
+ SET_SIZESTATDESC(3920, "responses sent 3920-3935 bytes", "3920-3935",
+ out);
+ SET_SIZESTATDESC(3936, "responses sent 3936-3951 bytes", "3936-3951",
+ out);
+ SET_SIZESTATDESC(3952, "responses sent 3952-3967 bytes", "3952-3967",
+ out);
+ SET_SIZESTATDESC(3968, "responses sent 3968-3983 bytes", "3968-3983",
+ out);
+ SET_SIZESTATDESC(3984, "responses sent 3984-3999 bytes", "3984-3999",
+ out);
+ SET_SIZESTATDESC(4000, "responses sent 4000-4015 bytes", "4000-4015",
+ out);
+ SET_SIZESTATDESC(4016, "responses sent 4016-4031 bytes", "4016-4031",
+ out);
+ SET_SIZESTATDESC(4032, "responses sent 4032-4047 bytes", "4032-4047",
+ out);
+ SET_SIZESTATDESC(4048, "responses sent 4048-4063 bytes", "4048-4063",
+ out);
+ SET_SIZESTATDESC(4064, "responses sent 4064-4079 bytes", "4064-4079",
+ out);
+ SET_SIZESTATDESC(4080, "responses sent 4080-4095 bytes", "4080-4095",
+ out);
+ SET_SIZESTATDESC(4096, "responses sent 4096+ bytes", "4096+", out);
+ INSIST(i == dns_sizecounter_out_max);
+
+ /* Sanity check */
+ for (i = 0; i < ns_statscounter_max; i++) {
+ INSIST(nsstats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_resstatscounter_max; i++) {
+ INSIST(resstats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_adbstats_max; i++) {
+ INSIST(adbstats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_zonestatscounter_max; i++) {
+ INSIST(zonestats_desc[i] != NULL);
+ }
+ for (i = 0; i < isc_sockstatscounter_max; i++) {
+ INSIST(sockstats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_dnssecstats_max; i++) {
+ INSIST(dnssecstats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_sizecounter_in_max; i++) {
+ INSIST(udpinsizestats_desc[i] != NULL);
+ INSIST(tcpinsizestats_desc[i] != NULL);
+ }
+ for (i = 0; i < dns_sizecounter_out_max; i++) {
+ INSIST(udpoutsizestats_desc[i] != NULL);
+ INSIST(tcpoutsizestats_desc[i] != NULL);
+ }
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < ns_statscounter_max; i++) {
+ INSIST(nsstats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_resstatscounter_max; i++) {
+ INSIST(resstats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_adbstats_max; i++) {
+ INSIST(adbstats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_zonestatscounter_max; i++) {
+ INSIST(zonestats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < isc_sockstatscounter_max; i++) {
+ INSIST(sockstats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_dnssecstats_max; i++) {
+ INSIST(dnssecstats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_sizecounter_in_max; i++) {
+ INSIST(udpinsizestats_xmldesc[i] != NULL);
+ INSIST(tcpinsizestats_xmldesc[i] != NULL);
+ }
+ for (i = 0; i < dns_sizecounter_out_max; i++) {
+ INSIST(udpoutsizestats_xmldesc[i] != NULL);
+ INSIST(tcpoutsizestats_xmldesc[i] != NULL);
+ }
+#endif /* if defined(EXTENDED_STATS) */
+}
+
+/*%
+ * Dump callback functions.
+ */
+static void
+generalstat_dump(isc_statscounter_t counter, uint64_t val, void *arg) {
+ stats_dumparg_t *dumparg = arg;
+
+ REQUIRE(counter < dumparg->ncounters);
+ dumparg->countervalues[counter] = val;
+}
+
+static isc_result_t
+dump_counters(isc_stats_t *stats, isc_statsformat_t type, void *arg,
+ const char *category, const char **desc, int ncounters,
+ int *indices, uint64_t *values, int options) {
+ int i, idx;
+ uint64_t value;
+ stats_dumparg_t dumparg;
+ FILE *fp;
+#ifdef HAVE_LIBXML2
+ void *writer;
+ int xmlrc;
+#endif /* ifdef HAVE_LIBXML2 */
+#ifdef HAVE_JSON_C
+ json_object *job, *cat, *counter;
+#endif /* ifdef HAVE_JSON_C */
+
+#if !defined(EXTENDED_STATS)
+ UNUSED(category);
+#endif /* if !defined(EXTENDED_STATS) */
+
+ dumparg.type = type;
+ dumparg.ncounters = ncounters;
+ dumparg.counterindices = indices;
+ dumparg.countervalues = values;
+
+ memset(values, 0, sizeof(values[0]) * ncounters);
+ isc_stats_dump(stats, generalstat_dump, &dumparg, options);
+
+#ifdef HAVE_JSON_C
+ cat = job = (json_object *)arg;
+ if (ncounters > 0 && type == isc_statsformat_json) {
+ if (category != NULL) {
+ cat = json_object_new_object();
+ if (cat == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+ json_object_object_add(job, category, cat);
+ }
+ }
+#endif /* ifdef HAVE_JSON_C */
+
+ for (i = 0; i < ncounters; i++) {
+ idx = indices[i];
+ value = values[idx];
+
+ if (value == 0 && (options & ISC_STATSDUMP_VERBOSE) == 0) {
+ continue;
+ }
+
+ switch (dumparg.type) {
+ case isc_statsformat_file:
+ fp = arg;
+ fprintf(fp, "%20" PRIu64 " %s\n", value, desc[idx]);
+ break;
+ case isc_statsformat_xml:
+#ifdef HAVE_LIBXML2
+ writer = arg;
+
+ if (category != NULL) {
+ /* <NameOfCategory> */
+ TRY0(xmlTextWriterStartElement(
+ writer, ISC_XMLCHAR category));
+
+ /* <name> inside category */
+ TRY0(xmlTextWriterStartElement(
+ writer, ISC_XMLCHAR "name"));
+ TRY0(xmlTextWriterWriteString(
+ writer, ISC_XMLCHAR desc[idx]));
+ TRY0(xmlTextWriterEndElement(writer));
+ /* </name> */
+
+ /* <counter> */
+ TRY0(xmlTextWriterStartElement(
+ writer, ISC_XMLCHAR "counter"));
+ TRY0(xmlTextWriterWriteFormatString(
+ writer, "%" PRIu64, value));
+
+ TRY0(xmlTextWriterEndElement(writer));
+ /* </counter> */
+ TRY0(xmlTextWriterEndElement(writer));
+ /* </NameOfCategory> */
+ } else {
+ TRY0(xmlTextWriterStartElement(
+ writer, ISC_XMLCHAR "counter"));
+ TRY0(xmlTextWriterWriteAttribute(
+ writer, ISC_XMLCHAR "name",
+ ISC_XMLCHAR desc[idx]));
+ TRY0(xmlTextWriterWriteFormatString(
+ writer, "%" PRIu64, value));
+ TRY0(xmlTextWriterEndElement(writer));
+ /* counter */
+ }
+
+#endif /* ifdef HAVE_LIBXML2 */
+ break;
+ case isc_statsformat_json:
+#ifdef HAVE_JSON_C
+ counter = json_object_new_int64(value);
+ if (counter == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+ json_object_object_add(cat, desc[idx], counter);
+#endif /* ifdef HAVE_JSON_C */
+ break;
+ }
+ }
+ return (ISC_R_SUCCESS);
+#ifdef HAVE_LIBXML2
+cleanup:
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed at dump_counters()");
+ return (ISC_R_FAILURE);
+#endif /* ifdef HAVE_LIBXML2 */
+}
+
+static void
+rdtypestat_dump(dns_rdatastatstype_t type, uint64_t val, void *arg) {
+ char typebuf[64];
+ const char *typestr;
+ stats_dumparg_t *dumparg = arg;
+ FILE *fp;
+#ifdef HAVE_LIBXML2
+ void *writer;
+ int xmlrc;
+#endif /* ifdef HAVE_LIBXML2 */
+#ifdef HAVE_JSON_C
+ json_object *zoneobj, *obj;
+#endif /* ifdef HAVE_JSON_C */
+
+ if ((DNS_RDATASTATSTYPE_ATTR(type) &
+ DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) == 0)
+ {
+ dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf,
+ sizeof(typebuf));
+ typestr = typebuf;
+ } else {
+ typestr = "Others";
+ }
+
+ switch (dumparg->type) {
+ case isc_statsformat_file:
+ fp = dumparg->arg;
+ fprintf(fp, "%20" PRIu64 " %s\n", val, typestr);
+ break;
+ case isc_statsformat_xml:
+#ifdef HAVE_LIBXML2
+ writer = dumparg->arg;
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
+ ISC_XMLCHAR typestr));
+
+ TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* type */
+#endif /* ifdef HAVE_LIBXML2 */
+ break;
+ case isc_statsformat_json:
+#ifdef HAVE_JSON_C
+ zoneobj = (json_object *)dumparg->arg;
+ obj = json_object_new_int64(val);
+ if (obj == NULL) {
+ return;
+ }
+ json_object_object_add(zoneobj, typestr, obj);
+#endif /* ifdef HAVE_JSON_C */
+ break;
+ }
+ return;
+#ifdef HAVE_LIBXML2
+cleanup:
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed at rdtypestat_dump()");
+ dumparg->result = ISC_R_FAILURE;
+ return;
+#endif /* ifdef HAVE_LIBXML2 */
+}
+
+static bool
+rdatastatstype_attr(dns_rdatastatstype_t type, unsigned int attr) {
+ return ((DNS_RDATASTATSTYPE_ATTR(type) & attr) != 0);
+}
+
+static void
+rdatasetstats_dump(dns_rdatastatstype_t type, uint64_t val, void *arg) {
+ stats_dumparg_t *dumparg = arg;
+ FILE *fp;
+ char typebuf[64];
+ const char *typestr;
+ bool nxrrset = false;
+ bool stale = false;
+ bool ancient = false;
+#ifdef HAVE_LIBXML2
+ void *writer;
+ int xmlrc;
+#endif /* ifdef HAVE_LIBXML2 */
+#ifdef HAVE_JSON_C
+ json_object *zoneobj, *obj;
+ char buf[1024];
+#endif /* ifdef HAVE_JSON_C */
+
+ if ((DNS_RDATASTATSTYPE_ATTR(type) &
+ DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) != 0)
+ {
+ typestr = "NXDOMAIN";
+ } else if ((DNS_RDATASTATSTYPE_ATTR(type) &
+ DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) != 0)
+ {
+ typestr = "Others";
+ } else {
+ dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf,
+ sizeof(typebuf));
+ typestr = typebuf;
+ }
+
+ nxrrset = rdatastatstype_attr(type, DNS_RDATASTATSTYPE_ATTR_NXRRSET);
+ stale = rdatastatstype_attr(type, DNS_RDATASTATSTYPE_ATTR_STALE);
+ ancient = rdatastatstype_attr(type, DNS_RDATASTATSTYPE_ATTR_ANCIENT);
+
+ switch (dumparg->type) {
+ case isc_statsformat_file:
+ fp = dumparg->arg;
+ fprintf(fp, "%20" PRIu64 " %s%s%s%s\n", val, ancient ? "~" : "",
+ stale ? "#" : "", nxrrset ? "!" : "", typestr);
+ break;
+ case isc_statsformat_xml:
+#ifdef HAVE_LIBXML2
+ writer = dumparg->arg;
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "rrset"));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "name"));
+ TRY0(xmlTextWriterWriteFormatString(
+ writer, "%s%s%s%s", ancient ? "~" : "",
+ stale ? "#" : "", nxrrset ? "!" : "", typestr));
+ TRY0(xmlTextWriterEndElement(writer)); /* name */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter"));
+ TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val));
+ TRY0(xmlTextWriterEndElement(writer)); /* counter */
+
+ TRY0(xmlTextWriterEndElement(writer)); /* rrset */
+#endif /* ifdef HAVE_LIBXML2 */
+ break;
+ case isc_statsformat_json:
+#ifdef HAVE_JSON_C
+ zoneobj = (json_object *)dumparg->arg;
+ snprintf(buf, sizeof(buf), "%s%s%s%s", ancient ? "~" : "",
+ stale ? "#" : "", nxrrset ? "!" : "", typestr);
+ obj = json_object_new_int64(val);
+ if (obj == NULL) {
+ return;
+ }
+ json_object_object_add(zoneobj, buf, obj);
+#endif /* ifdef HAVE_JSON_C */
+ break;
+ }
+ return;
+#ifdef HAVE_LIBXML2
+cleanup:
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed at rdatasetstats_dump()");
+ dumparg->result = ISC_R_FAILURE;
+#endif /* ifdef HAVE_LIBXML2 */
+}
+
+static void
+opcodestat_dump(dns_opcode_t code, uint64_t val, void *arg) {
+ FILE *fp;
+ isc_buffer_t b;
+ char codebuf[64];
+ stats_dumparg_t *dumparg = arg;
+#ifdef HAVE_LIBXML2
+ void *writer;
+ int xmlrc;
+#endif /* ifdef HAVE_LIBXML2 */
+#ifdef HAVE_JSON_C
+ json_object *zoneobj, *obj;
+#endif /* ifdef HAVE_JSON_C */
+
+ isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1);
+ dns_opcode_totext(code, &b);
+ codebuf[isc_buffer_usedlength(&b)] = '\0';
+
+ switch (dumparg->type) {
+ case isc_statsformat_file:
+ fp = dumparg->arg;
+ fprintf(fp, "%20" PRIu64 " %s\n", val, codebuf);
+ break;
+ case isc_statsformat_xml:
+#ifdef HAVE_LIBXML2
+ writer = dumparg->arg;
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
+ ISC_XMLCHAR codebuf));
+ TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val));
+ TRY0(xmlTextWriterEndElement(writer)); /* counter */
+#endif /* ifdef HAVE_LIBXML2 */
+ break;
+ case isc_statsformat_json:
+#ifdef HAVE_JSON_C
+ zoneobj = (json_object *)dumparg->arg;
+ obj = json_object_new_int64(val);
+ if (obj == NULL) {
+ return;
+ }
+ json_object_object_add(zoneobj, codebuf, obj);
+#endif /* ifdef HAVE_JSON_C */
+ break;
+ }
+ return;
+
+#ifdef HAVE_LIBXML2
+cleanup:
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed at opcodestat_dump()");
+ dumparg->result = ISC_R_FAILURE;
+ return;
+#endif /* ifdef HAVE_LIBXML2 */
+}
+
+static void
+rcodestat_dump(dns_rcode_t code, uint64_t val, void *arg) {
+ FILE *fp;
+ isc_buffer_t b;
+ char codebuf[64];
+ stats_dumparg_t *dumparg = arg;
+#ifdef HAVE_LIBXML2
+ void *writer;
+ int xmlrc;
+#endif /* ifdef HAVE_LIBXML2 */
+#ifdef HAVE_JSON_C
+ json_object *zoneobj, *obj;
+#endif /* ifdef HAVE_JSON_C */
+
+ isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1);
+ dns_rcode_totext(code, &b);
+ codebuf[isc_buffer_usedlength(&b)] = '\0';
+
+ switch (dumparg->type) {
+ case isc_statsformat_file:
+ fp = dumparg->arg;
+ fprintf(fp, "%20" PRIu64 " %s\n", val, codebuf);
+ break;
+ case isc_statsformat_xml:
+#ifdef HAVE_LIBXML2
+ writer = dumparg->arg;
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
+ ISC_XMLCHAR codebuf));
+ TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val));
+ TRY0(xmlTextWriterEndElement(writer)); /* counter */
+#endif /* ifdef HAVE_LIBXML2 */
+ break;
+ case isc_statsformat_json:
+#ifdef HAVE_JSON_C
+ zoneobj = (json_object *)dumparg->arg;
+ obj = json_object_new_int64(val);
+ if (obj == NULL) {
+ return;
+ }
+ json_object_object_add(zoneobj, codebuf, obj);
+#endif /* ifdef HAVE_JSON_C */
+ break;
+ }
+ return;
+
+#ifdef HAVE_LIBXML2
+cleanup:
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed at rcodestat_dump()");
+ dumparg->result = ISC_R_FAILURE;
+ return;
+#endif /* ifdef HAVE_LIBXML2 */
+}
+
+#if defined(EXTENDED_STATS)
+static void
+dnssecsignstat_dump(dns_keytag_t tag, uint64_t val, void *arg) {
+ FILE *fp;
+ char tagbuf[64];
+ stats_dumparg_t *dumparg = arg;
+#ifdef HAVE_LIBXML2
+ xmlTextWriterPtr writer;
+ int xmlrc;
+#endif /* ifdef HAVE_LIBXML2 */
+#ifdef HAVE_JSON_C
+ json_object *zoneobj, *obj;
+#endif /* ifdef HAVE_JSON_C */
+
+ snprintf(tagbuf, sizeof(tagbuf), "%u", tag);
+
+ switch (dumparg->type) {
+ case isc_statsformat_file:
+ fp = dumparg->arg;
+ fprintf(fp, "%20" PRIu64 " %s\n", val, tagbuf);
+ break;
+ case isc_statsformat_xml:
+#ifdef HAVE_LIBXML2
+ writer = dumparg->arg;
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
+ ISC_XMLCHAR tagbuf));
+ TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val));
+ TRY0(xmlTextWriterEndElement(writer)); /* counter */
+#endif /* ifdef HAVE_LIBXML2 */
+ break;
+ case isc_statsformat_json:
+#ifdef HAVE_JSON_C
+ zoneobj = (json_object *)dumparg->arg;
+ obj = json_object_new_int64(val);
+ if (obj == NULL) {
+ return;
+ }
+ json_object_object_add(zoneobj, tagbuf, obj);
+#endif /* ifdef HAVE_JSON_C */
+ break;
+ }
+ return;
+#ifdef HAVE_LIBXML2
+cleanup:
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed at dnssecsignstat_dump()");
+ dumparg->result = ISC_R_FAILURE;
+ return;
+#endif /* ifdef HAVE_LIBXML2 */
+}
+#endif /* defined(EXTENDED_STATS) */
+
+#ifdef HAVE_LIBXML2
+/*
+ * Which statistics to include when rendering to XML
+ */
+#define STATS_XML_STATUS 0x00 /* display only common statistics */
+#define STATS_XML_SERVER 0x01
+#define STATS_XML_ZONES 0x02
+#define STATS_XML_TASKS 0x04
+#define STATS_XML_NET 0x08
+#define STATS_XML_MEM 0x10
+#define STATS_XML_TRAFFIC 0x20
+#define STATS_XML_ALL 0xff
+
+static isc_result_t
+zone_xmlrender(dns_zone_t *zone, void *arg) {
+ isc_result_t result;
+ char buf[1024 + 32]; /* sufficiently large for zone name and class */
+ dns_rdataclass_t rdclass;
+ uint32_t serial;
+ xmlTextWriterPtr writer = arg;
+ dns_zonestat_level_t statlevel;
+ int xmlrc;
+ stats_dumparg_t dumparg;
+ const char *ztype;
+ isc_time_t timestamp;
+
+ statlevel = dns_zone_getstatlevel(zone);
+ if (statlevel == dns_zonestat_none) {
+ return (ISC_R_SUCCESS);
+ }
+
+ dumparg.type = isc_statsformat_xml;
+ dumparg.arg = writer;
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zone"));
+
+ dns_zone_nameonly(zone, buf, sizeof(buf));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
+ ISC_XMLCHAR buf));
+
+ rdclass = dns_zone_getclass(zone);
+ dns_rdataclass_format(rdclass, buf, sizeof(buf));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "rdataclass",
+ ISC_XMLCHAR buf));
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "type"));
+ ztype = user_zonetype(zone);
+ if (ztype != NULL) {
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR ztype));
+ } else {
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "unknown"));
+ }
+ TRY0(xmlTextWriterEndElement(writer)); /* type */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial"));
+ if (dns_zone_getserial(zone, &serial) == ISC_R_SUCCESS) {
+ TRY0(xmlTextWriterWriteFormatString(writer, "%u", serial));
+ } else {
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
+ }
+ TRY0(xmlTextWriterEndElement(writer)); /* serial */
+
+ /*
+ * Export zone timers to the statistics channel in XML format. For
+ * primary zones, only include the loaded time. For secondary zones,
+ * also include the expire and refresh times.
+ */
+ CHECK(dns_zone_getloadtime(zone, &timestamp));
+
+ isc_time_formatISO8601(&timestamp, buf, 64);
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "loaded"));
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf));
+ TRY0(xmlTextWriterEndElement(writer));
+
+ if (dns_zone_gettype(zone) == dns_zone_secondary) {
+ CHECK(dns_zone_getexpiretime(zone, &timestamp));
+ isc_time_formatISO8601(&timestamp, buf, 64);
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "expires"));
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf));
+ TRY0(xmlTextWriterEndElement(writer));
+
+ CHECK(dns_zone_getrefreshtime(zone, &timestamp));
+ isc_time_formatISO8601(&timestamp, buf, 64);
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "refresh"));
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf));
+ TRY0(xmlTextWriterEndElement(writer));
+ }
+
+ if (statlevel == dns_zonestat_full) {
+ isc_stats_t *zonestats;
+ isc_stats_t *gluecachestats;
+ dns_stats_t *rcvquerystats;
+ dns_stats_t *dnssecsignstats;
+ uint64_t nsstat_values[ns_statscounter_max];
+ uint64_t gluecachestats_values[dns_gluecachestatscounter_max];
+
+ zonestats = dns_zone_getrequeststats(zone);
+ if (zonestats != NULL) {
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer,
+ ISC_XMLCHAR "type",
+ ISC_XMLCHAR "rcode"));
+
+ CHECK(dump_counters(zonestats, isc_statsformat_xml,
+ writer, NULL, nsstats_xmldesc,
+ ns_statscounter_max, nsstats_index,
+ nsstat_values,
+ ISC_STATSDUMP_VERBOSE));
+ /* counters type="rcode"*/
+ TRY0(xmlTextWriterEndElement(writer));
+ }
+
+ gluecachestats = dns_zone_getgluecachestats(zone);
+ if (gluecachestats != NULL) {
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(
+ writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "gluecache"));
+
+ CHECK(dump_counters(
+ gluecachestats, isc_statsformat_xml, writer,
+ NULL, gluecachestats_xmldesc,
+ dns_gluecachestatscounter_max,
+ gluecachestats_index, gluecachestats_values,
+ ISC_STATSDUMP_VERBOSE));
+ /* counters type="rcode"*/
+ TRY0(xmlTextWriterEndElement(writer));
+ }
+
+ rcvquerystats = dns_zone_getrcvquerystats(zone);
+ if (rcvquerystats != NULL) {
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer,
+ ISC_XMLCHAR "type",
+ ISC_XMLCHAR "qtype"));
+
+ dumparg.result = ISC_R_SUCCESS;
+ dns_rdatatypestats_dump(rcvquerystats, rdtypestat_dump,
+ &dumparg, 0);
+ CHECK(dumparg.result);
+
+ /* counters type="qtype"*/
+ TRY0(xmlTextWriterEndElement(writer));
+ }
+
+ dnssecsignstats = dns_zone_getdnssecsignstats(zone);
+ if (dnssecsignstats != NULL) {
+ /* counters type="dnssec-sign"*/
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(
+ writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "dnssec-sign"));
+
+ dumparg.result = ISC_R_SUCCESS;
+ dns_dnssecsignstats_dump(
+ dnssecsignstats, dns_dnssecsignstats_sign,
+ dnssecsignstat_dump, &dumparg, 0);
+ CHECK(dumparg.result);
+
+ /* counters type="dnssec-sign"*/
+ TRY0(xmlTextWriterEndElement(writer));
+
+ /* counters type="dnssec-refresh"*/
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(
+ writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "dnssec-refresh"));
+
+ dumparg.result = ISC_R_SUCCESS;
+ dns_dnssecsignstats_dump(
+ dnssecsignstats, dns_dnssecsignstats_refresh,
+ dnssecsignstat_dump, &dumparg, 0);
+ CHECK(dumparg.result);
+
+ /* counters type="dnssec-refresh"*/
+ TRY0(xmlTextWriterEndElement(writer));
+ }
+ }
+
+ TRY0(xmlTextWriterEndElement(writer)); /* zone */
+
+ return (ISC_R_SUCCESS);
+cleanup:
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "Failed at zone_xmlrender()");
+ return (ISC_R_FAILURE);
+}
+
+static isc_result_t
+generatexml(named_server_t *server, uint32_t flags, int *buflen,
+ xmlChar **buf) {
+ char boottime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
+ char configtime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
+ char nowstr[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
+ isc_time_t now;
+ xmlTextWriterPtr writer = NULL;
+ xmlDocPtr doc = NULL;
+ int xmlrc;
+ dns_view_t *view;
+ stats_dumparg_t dumparg;
+ dns_stats_t *cacherrstats;
+ uint64_t nsstat_values[ns_statscounter_max];
+ uint64_t resstat_values[dns_resstatscounter_max];
+ uint64_t adbstat_values[dns_adbstats_max];
+ uint64_t zonestat_values[dns_zonestatscounter_max];
+ uint64_t sockstat_values[isc_sockstatscounter_max];
+ uint64_t udpinsizestat_values[dns_sizecounter_in_max];
+ uint64_t udpoutsizestat_values[dns_sizecounter_out_max];
+ uint64_t tcpinsizestat_values[dns_sizecounter_in_max];
+ uint64_t tcpoutsizestat_values[dns_sizecounter_out_max];
+#ifdef HAVE_DNSTAP
+ uint64_t dnstapstat_values[dns_dnstapcounter_max];
+#endif /* ifdef HAVE_DNSTAP */
+ isc_result_t result;
+
+ isc_time_now(&now);
+ isc_time_formatISO8601ms(&named_g_boottime, boottime, sizeof boottime);
+ isc_time_formatISO8601ms(&named_g_configtime, configtime,
+ sizeof configtime);
+ isc_time_formatISO8601ms(&now, nowstr, sizeof nowstr);
+
+ writer = xmlNewTextWriterDoc(&doc, 0);
+ if (writer == NULL) {
+ goto cleanup;
+ }
+ TRY0(xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL));
+ TRY0(xmlTextWriterWritePI(writer, ISC_XMLCHAR "xml-stylesheet",
+ ISC_XMLCHAR "type=\"text/xsl\" "
+ "href=\"/bind9.xsl\""));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
+ ISC_XMLCHAR STATS_XML_VERSION));
+
+ /* Set common fields for statistics dump */
+ dumparg.type = isc_statsformat_xml;
+ dumparg.arg = writer;
+
+ /* Render server information */
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "server"));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "boot-time"));
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR boottime));
+ TRY0(xmlTextWriterEndElement(writer)); /* boot-time */
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "config-time"));
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR configtime));
+ TRY0(xmlTextWriterEndElement(writer)); /* config-time */
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "current-time"));
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR nowstr));
+ TRY0(xmlTextWriterEndElement(writer)); /* current-time */
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "version"));
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR PACKAGE_VERSION));
+ TRY0(xmlTextWriterEndElement(writer)); /* version */
+
+ if ((flags & STATS_XML_SERVER) != 0) {
+ dumparg.result = ISC_R_SUCCESS;
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "opcode"));
+
+ dns_opcodestats_dump(server->sctx->opcodestats, opcodestat_dump,
+ &dumparg, ISC_STATSDUMP_VERBOSE);
+ CHECK(dumparg.result);
+
+ TRY0(xmlTextWriterEndElement(writer));
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "rcode"));
+
+ dns_rcodestats_dump(server->sctx->rcodestats, rcodestat_dump,
+ &dumparg, ISC_STATSDUMP_VERBOSE);
+ CHECK(dumparg.result);
+
+ TRY0(xmlTextWriterEndElement(writer));
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "qtype"));
+
+ dumparg.result = ISC_R_SUCCESS;
+ dns_rdatatypestats_dump(server->sctx->rcvquerystats,
+ rdtypestat_dump, &dumparg, 0);
+ CHECK(dumparg.result);
+
+ TRY0(xmlTextWriterEndElement(writer)); /* counters */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "nsstat"));
+
+ CHECK(dump_counters(ns_stats_get(server->sctx->nsstats),
+ isc_statsformat_xml, writer, NULL,
+ nsstats_xmldesc, ns_statscounter_max,
+ nsstats_index, nsstat_values,
+ ISC_STATSDUMP_VERBOSE));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* /nsstat */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "zonestat"));
+
+ CHECK(dump_counters(server->zonestats, isc_statsformat_xml,
+ writer, NULL, zonestats_xmldesc,
+ dns_zonestatscounter_max, zonestats_index,
+ zonestat_values, ISC_STATSDUMP_VERBOSE));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* /zonestat */
+
+ /*
+ * Most of the common resolver statistics entries are 0, so
+ * we don't use the verbose dump here.
+ */
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "resstat"));
+ CHECK(dump_counters(server->resolverstats, isc_statsformat_xml,
+ writer, NULL, resstats_xmldesc,
+ dns_resstatscounter_max, resstats_index,
+ resstat_values, 0));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* resstat */
+
+#ifdef HAVE_DNSTAP
+ if (server->dtenv != NULL) {
+ isc_stats_t *dnstapstats = NULL;
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer,
+ ISC_XMLCHAR "type",
+ ISC_XMLCHAR "dnstap"));
+ dns_dt_getstats(named_g_server->dtenv, &dnstapstats);
+ result = dump_counters(
+ dnstapstats, isc_statsformat_xml, writer, NULL,
+ dnstapstats_xmldesc, dns_dnstapcounter_max,
+ dnstapstats_index, dnstapstat_values, 0);
+ isc_stats_detach(&dnstapstats);
+ CHECK(result);
+
+ TRY0(xmlTextWriterEndElement(writer)); /* dnstap */
+ }
+#endif /* ifdef HAVE_DNSTAP */
+ }
+
+ if ((flags & STATS_XML_NET) != 0) {
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "sockstat"));
+
+ CHECK(dump_counters(server->sockstats, isc_statsformat_xml,
+ writer, NULL, sockstats_xmldesc,
+ isc_sockstatscounter_max, sockstats_index,
+ sockstat_values, ISC_STATSDUMP_VERBOSE));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* /sockstat */
+ }
+ TRY0(xmlTextWriterEndElement(writer)); /* /server */
+
+ if ((flags & STATS_XML_TRAFFIC) != 0) {
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "traffic"));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ipv4"));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "udp"));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "request-size"));
+
+ CHECK(dump_counters(
+ server->sctx->udpinstats4, isc_statsformat_xml, writer,
+ NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max,
+ udpinsizestats_index, udpinsizestat_values, 0));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "response-size"));
+
+ CHECK(dump_counters(
+ server->sctx->udpoutstats4, isc_statsformat_xml, writer,
+ NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max,
+ udpoutsizestats_index, udpoutsizestat_values, 0));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+ TRY0(xmlTextWriterEndElement(writer)); /* </udp> */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tcp"));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "request-size"));
+
+ CHECK(dump_counters(
+ server->sctx->tcpinstats4, isc_statsformat_xml, writer,
+ NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max,
+ tcpinsizestats_index, tcpinsizestat_values, 0));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "response-size"));
+
+ CHECK(dump_counters(
+ server->sctx->tcpoutstats4, isc_statsformat_xml, writer,
+ NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max,
+ tcpoutsizestats_index, tcpoutsizestat_values, 0));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+ TRY0(xmlTextWriterEndElement(writer)); /* </tcp> */
+ TRY0(xmlTextWriterEndElement(writer)); /* </ipv4> */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ipv6"));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "udp"));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "request-size"));
+
+ CHECK(dump_counters(
+ server->sctx->udpinstats6, isc_statsformat_xml, writer,
+ NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max,
+ udpinsizestats_index, udpinsizestat_values, 0));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "response-size"));
+
+ CHECK(dump_counters(
+ server->sctx->udpoutstats6, isc_statsformat_xml, writer,
+ NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max,
+ udpoutsizestats_index, udpoutsizestat_values, 0));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+ TRY0(xmlTextWriterEndElement(writer)); /* </udp> */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tcp"));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "request-size"));
+
+ CHECK(dump_counters(
+ server->sctx->tcpinstats6, isc_statsformat_xml, writer,
+ NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max,
+ tcpinsizestats_index, tcpinsizestat_values, 0));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "response-size"));
+
+ CHECK(dump_counters(
+ server->sctx->tcpoutstats6, isc_statsformat_xml, writer,
+ NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max,
+ tcpoutsizestats_index, tcpoutsizestat_values, 0));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
+ TRY0(xmlTextWriterEndElement(writer)); /* </tcp> */
+ TRY0(xmlTextWriterEndElement(writer)); /* </ipv6> */
+ TRY0(xmlTextWriterEndElement(writer)); /* </traffic> */
+ }
+
+ /*
+ * Render views. For each view we know of, call its
+ * rendering function.
+ */
+ view = ISC_LIST_HEAD(server->viewlist);
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "views"));
+ while (view != NULL &&
+ ((flags & (STATS_XML_SERVER | STATS_XML_ZONES)) != 0))
+ {
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "view"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
+ ISC_XMLCHAR view->name));
+
+ if ((flags & STATS_XML_ZONES) != 0) {
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "zones"));
+ CHECK(dns_zt_apply(view->zonetable, isc_rwlocktype_read,
+ true, NULL, zone_xmlrender, writer));
+ TRY0(xmlTextWriterEndElement(writer)); /* /zones */
+ }
+
+ if ((flags & STATS_XML_SERVER) == 0) {
+ TRY0(xmlTextWriterEndElement(writer)); /* /view */
+ view = ISC_LIST_NEXT(view, link);
+ continue;
+ }
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "resqtype"));
+
+ if (view->resquerystats != NULL) {
+ dumparg.result = ISC_R_SUCCESS;
+ dns_rdatatypestats_dump(view->resquerystats,
+ rdtypestat_dump, &dumparg, 0);
+ CHECK(dumparg.result);
+ }
+ TRY0(xmlTextWriterEndElement(writer));
+
+ /* <resstats> */
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "resstats"));
+ if (view->resstats != NULL) {
+ CHECK(dump_counters(view->resstats, isc_statsformat_xml,
+ writer, NULL, resstats_xmldesc,
+ dns_resstatscounter_max,
+ resstats_index, resstat_values,
+ ISC_STATSDUMP_VERBOSE));
+ }
+ TRY0(xmlTextWriterEndElement(writer)); /* </resstats> */
+
+ cacherrstats = dns_db_getrrsetstats(view->cachedb);
+ if (cacherrstats != NULL) {
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "cache"));
+ TRY0(xmlTextWriterWriteAttribute(
+ writer, ISC_XMLCHAR "name",
+ ISC_XMLCHAR dns_cache_getname(view->cache)));
+ dumparg.result = ISC_R_SUCCESS;
+ dns_rdatasetstats_dump(cacherrstats, rdatasetstats_dump,
+ &dumparg, 0);
+ CHECK(dumparg.result);
+ TRY0(xmlTextWriterEndElement(writer)); /* cache */
+ }
+
+ /* <adbstats> */
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "adbstat"));
+ if (view->adbstats != NULL) {
+ CHECK(dump_counters(view->adbstats, isc_statsformat_xml,
+ writer, NULL, adbstats_xmldesc,
+ dns_adbstats_max, adbstats_index,
+ adbstat_values,
+ ISC_STATSDUMP_VERBOSE));
+ }
+ TRY0(xmlTextWriterEndElement(writer)); /* </adbstats> */
+
+ /* <cachestats> */
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR "cachestats"));
+ TRY0(dns_cache_renderxml(view->cache, writer));
+ TRY0(xmlTextWriterEndElement(writer)); /* </cachestats> */
+
+ TRY0(xmlTextWriterEndElement(writer)); /* view */
+
+ view = ISC_LIST_NEXT(view, link);
+ }
+ TRY0(xmlTextWriterEndElement(writer)); /* /views */
+
+ if ((flags & STATS_XML_TASKS) != 0) {
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "taskmgr"));
+ TRY0(isc_taskmgr_renderxml(named_g_taskmgr, writer));
+ TRY0(xmlTextWriterEndElement(writer)); /* /taskmgr */
+ }
+
+ if ((flags & STATS_XML_MEM) != 0) {
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "memory"));
+ TRY0(isc_mem_renderxml(writer));
+ TRY0(xmlTextWriterEndElement(writer)); /* /memory */
+ }
+
+ TRY0(xmlTextWriterEndElement(writer)); /* /statistics */
+ TRY0(xmlTextWriterEndDocument(writer));
+
+ xmlDocDumpFormatMemoryEnc(doc, buf, buflen, "UTF-8", 0);
+ if (*buf == NULL) {
+ goto cleanup;
+ }
+
+ xmlFreeTextWriter(writer);
+ xmlFreeDoc(doc);
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed generating XML response");
+ if (writer != NULL) {
+ xmlFreeTextWriter(writer);
+ }
+ if (doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return (ISC_R_FAILURE);
+}
+
+static void
+wrap_xmlfree(isc_buffer_t *buffer, void *arg) {
+ UNUSED(arg);
+
+ xmlFree(isc_buffer_base(buffer));
+}
+
+static isc_result_t
+render_xml(uint32_t flags, void *arg, unsigned int *retcode,
+ const char **retmsg, const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ unsigned char *msg = NULL;
+ int msglen;
+ named_server_t *server = arg;
+ isc_result_t result;
+
+ result = generatexml(server, flags, &msglen, &msg);
+
+ if (result == ISC_R_SUCCESS) {
+ *retcode = 200;
+ *retmsg = "OK";
+ *mimetype = "text/xml";
+ isc_buffer_reinit(b, msg, msglen);
+ isc_buffer_add(b, msglen);
+ *freecb = wrap_xmlfree;
+ *freecb_args = NULL;
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed at rendering XML()");
+ }
+
+ return (result);
+}
+
+static isc_result_t
+render_xml_all(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb,
+ void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_xml(STATS_XML_ALL, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_status(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_xml(STATS_XML_STATUS, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_server(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_xml(STATS_XML_SERVER, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_zones(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_xml(STATS_XML_ZONES, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_net(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb,
+ void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_xml(STATS_XML_NET, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_tasks(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_xml(STATS_XML_TASKS, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_mem(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb,
+ void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_xml(STATS_XML_MEM, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_xml_traffic(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_xml(STATS_XML_TRAFFIC, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+#endif /* HAVE_LIBXML2 */
+
+#ifdef HAVE_JSON_C
+/*
+ * Which statistics to include when rendering to JSON
+ */
+#define STATS_JSON_STATUS 0x00 /* display only common statistics */
+#define STATS_JSON_SERVER 0x01
+#define STATS_JSON_ZONES 0x02
+#define STATS_JSON_TASKS 0x04
+#define STATS_JSON_NET 0x08
+#define STATS_JSON_MEM 0x10
+#define STATS_JSON_TRAFFIC 0x20
+#define STATS_JSON_ALL 0xff
+
+#define CHECKMEM(m) \
+ do { \
+ if (m == NULL) { \
+ result = ISC_R_NOMEMORY; \
+ goto cleanup; \
+ } \
+ } while (0)
+
+static void
+wrap_jsonfree(isc_buffer_t *buffer, void *arg) {
+ json_object_put(isc_buffer_base(buffer));
+ if (arg != NULL) {
+ json_object_put((json_object *)arg);
+ }
+}
+
+static json_object *
+addzone(char *name, char *classname, const char *ztype, uint32_t serial,
+ bool add_serial) {
+ json_object *node = json_object_new_object();
+
+ if (node == NULL) {
+ return (NULL);
+ }
+
+ json_object_object_add(node, "name", json_object_new_string(name));
+ json_object_object_add(node, "class",
+ json_object_new_string(classname));
+ if (add_serial) {
+ json_object_object_add(node, "serial",
+ json_object_new_int64(serial));
+ }
+ if (ztype != NULL) {
+ json_object_object_add(node, "type",
+ json_object_new_string(ztype));
+ }
+ return (node);
+}
+
+static isc_result_t
+zone_jsonrender(dns_zone_t *zone, void *arg) {
+ isc_result_t result = ISC_R_SUCCESS;
+ char buf[1024 + 32]; /* sufficiently large for zone name and class */
+ char classbuf[64]; /* sufficiently large for class */
+ char *zone_name_only = NULL;
+ char *class_only = NULL;
+ dns_rdataclass_t rdclass;
+ uint32_t serial;
+ json_object *zonearray = (json_object *)arg;
+ json_object *zoneobj = NULL;
+ dns_zonestat_level_t statlevel;
+ isc_time_t timestamp;
+
+ statlevel = dns_zone_getstatlevel(zone);
+ if (statlevel == dns_zonestat_none) {
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_zone_nameonly(zone, buf, sizeof(buf));
+ zone_name_only = buf;
+
+ rdclass = dns_zone_getclass(zone);
+ dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
+ class_only = classbuf;
+
+ if (dns_zone_getserial(zone, &serial) != ISC_R_SUCCESS) {
+ zoneobj = addzone(zone_name_only, class_only,
+ user_zonetype(zone), 0, false);
+ } else {
+ zoneobj = addzone(zone_name_only, class_only,
+ user_zonetype(zone), serial, true);
+ }
+
+ if (zoneobj == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ /*
+ * Export zone timers to the statistics channel in JSON format.
+ * For primary zones, only include the loaded time. For secondary
+ * zones, also include the expire and refresh times.
+ */
+
+ CHECK(dns_zone_getloadtime(zone, &timestamp));
+
+ isc_time_formatISO8601(&timestamp, buf, 64);
+ json_object_object_add(zoneobj, "loaded", json_object_new_string(buf));
+
+ if (dns_zone_gettype(zone) == dns_zone_secondary) {
+ CHECK(dns_zone_getexpiretime(zone, &timestamp));
+ isc_time_formatISO8601(&timestamp, buf, 64);
+ json_object_object_add(zoneobj, "expires",
+ json_object_new_string(buf));
+
+ CHECK(dns_zone_getrefreshtime(zone, &timestamp));
+ isc_time_formatISO8601(&timestamp, buf, 64);
+ json_object_object_add(zoneobj, "refresh",
+ json_object_new_string(buf));
+ }
+
+ if (statlevel == dns_zonestat_full) {
+ isc_stats_t *zonestats;
+ isc_stats_t *gluecachestats;
+ dns_stats_t *rcvquerystats;
+ dns_stats_t *dnssecsignstats;
+ uint64_t nsstat_values[ns_statscounter_max];
+ uint64_t gluecachestats_values[dns_gluecachestatscounter_max];
+
+ zonestats = dns_zone_getrequeststats(zone);
+ if (zonestats != NULL) {
+ json_object *counters = json_object_new_object();
+ if (counters == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ result = dump_counters(zonestats, isc_statsformat_json,
+ counters, NULL, nsstats_xmldesc,
+ ns_statscounter_max,
+ nsstats_index, nsstat_values, 0);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(counters)->count != 0) {
+ json_object_object_add(zoneobj, "rcodes",
+ counters);
+ } else {
+ json_object_put(counters);
+ }
+ }
+
+ gluecachestats = dns_zone_getgluecachestats(zone);
+ if (gluecachestats != NULL) {
+ json_object *counters = json_object_new_object();
+ if (counters == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ result = dump_counters(
+ gluecachestats, isc_statsformat_json, counters,
+ NULL, gluecachestats_xmldesc,
+ dns_gluecachestatscounter_max,
+ gluecachestats_index, gluecachestats_values, 0);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(counters)->count != 0) {
+ json_object_object_add(zoneobj, "gluecache",
+ counters);
+ } else {
+ json_object_put(counters);
+ }
+ }
+
+ rcvquerystats = dns_zone_getrcvquerystats(zone);
+ if (rcvquerystats != NULL) {
+ stats_dumparg_t dumparg;
+ json_object *counters = json_object_new_object();
+ CHECKMEM(counters);
+
+ dumparg.type = isc_statsformat_json;
+ dumparg.arg = counters;
+ dumparg.result = ISC_R_SUCCESS;
+ dns_rdatatypestats_dump(rcvquerystats, rdtypestat_dump,
+ &dumparg, 0);
+ if (dumparg.result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(counters)->count != 0) {
+ json_object_object_add(zoneobj, "qtypes",
+ counters);
+ } else {
+ json_object_put(counters);
+ }
+ }
+
+ dnssecsignstats = dns_zone_getdnssecsignstats(zone);
+ if (dnssecsignstats != NULL) {
+ stats_dumparg_t dumparg;
+ json_object *sign_counters = json_object_new_object();
+ CHECKMEM(sign_counters);
+
+ dumparg.type = isc_statsformat_json;
+ dumparg.arg = sign_counters;
+ dumparg.result = ISC_R_SUCCESS;
+ dns_dnssecsignstats_dump(
+ dnssecsignstats, dns_dnssecsignstats_sign,
+ dnssecsignstat_dump, &dumparg, 0);
+ if (dumparg.result != ISC_R_SUCCESS) {
+ json_object_put(sign_counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(sign_counters)->count != 0) {
+ json_object_object_add(zoneobj, "dnssec-sign",
+ sign_counters);
+ } else {
+ json_object_put(sign_counters);
+ }
+
+ json_object *refresh_counters =
+ json_object_new_object();
+ CHECKMEM(refresh_counters);
+
+ dumparg.type = isc_statsformat_json;
+ dumparg.arg = refresh_counters;
+ dumparg.result = ISC_R_SUCCESS;
+ dns_dnssecsignstats_dump(
+ dnssecsignstats, dns_dnssecsignstats_refresh,
+ dnssecsignstat_dump, &dumparg, 0);
+ if (dumparg.result != ISC_R_SUCCESS) {
+ json_object_put(refresh_counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(refresh_counters)->count !=
+ 0)
+ {
+ json_object_object_add(zoneobj,
+ "dnssec-refresh",
+ refresh_counters);
+ } else {
+ json_object_put(refresh_counters);
+ }
+ }
+ }
+
+ json_object_array_add(zonearray, zoneobj);
+ zoneobj = NULL;
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (zoneobj != NULL) {
+ json_object_put(zoneobj);
+ }
+ return (result);
+}
+
+static isc_result_t
+generatejson(named_server_t *server, size_t *msglen, const char **msg,
+ json_object **rootp, uint32_t flags) {
+ dns_view_t *view;
+ isc_result_t result = ISC_R_SUCCESS;
+ json_object *bindstats, *viewlist, *counters, *obj;
+ json_object *traffic = NULL;
+ json_object *udpreq4 = NULL, *udpresp4 = NULL;
+ json_object *tcpreq4 = NULL, *tcpresp4 = NULL;
+ json_object *udpreq6 = NULL, *udpresp6 = NULL;
+ json_object *tcpreq6 = NULL, *tcpresp6 = NULL;
+ uint64_t nsstat_values[ns_statscounter_max];
+ uint64_t resstat_values[dns_resstatscounter_max];
+ uint64_t adbstat_values[dns_adbstats_max];
+ uint64_t zonestat_values[dns_zonestatscounter_max];
+ uint64_t sockstat_values[isc_sockstatscounter_max];
+ uint64_t udpinsizestat_values[dns_sizecounter_in_max];
+ uint64_t udpoutsizestat_values[dns_sizecounter_out_max];
+ uint64_t tcpinsizestat_values[dns_sizecounter_in_max];
+ uint64_t tcpoutsizestat_values[dns_sizecounter_out_max];
+#ifdef HAVE_DNSTAP
+ uint64_t dnstapstat_values[dns_dnstapcounter_max];
+#endif /* ifdef HAVE_DNSTAP */
+ stats_dumparg_t dumparg;
+ char boottime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
+ char configtime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
+ char nowstr[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
+ isc_time_t now;
+
+ REQUIRE(msglen != NULL);
+ REQUIRE(msg != NULL && *msg == NULL);
+ REQUIRE(rootp == NULL || *rootp == NULL);
+
+ bindstats = json_object_new_object();
+ if (bindstats == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ /*
+ * These statistics are included no matter which URL we use.
+ */
+ obj = json_object_new_string(STATS_JSON_VERSION);
+ CHECKMEM(obj);
+ json_object_object_add(bindstats, "json-stats-version", obj);
+
+ isc_time_now(&now);
+ isc_time_formatISO8601ms(&named_g_boottime, boottime, sizeof(boottime));
+ isc_time_formatISO8601ms(&named_g_configtime, configtime,
+ sizeof configtime);
+ isc_time_formatISO8601ms(&now, nowstr, sizeof(nowstr));
+
+ obj = json_object_new_string(boottime);
+ CHECKMEM(obj);
+ json_object_object_add(bindstats, "boot-time", obj);
+
+ obj = json_object_new_string(configtime);
+ CHECKMEM(obj);
+ json_object_object_add(bindstats, "config-time", obj);
+
+ obj = json_object_new_string(nowstr);
+ CHECKMEM(obj);
+ json_object_object_add(bindstats, "current-time", obj);
+ obj = json_object_new_string(PACKAGE_VERSION);
+ CHECKMEM(obj);
+ json_object_object_add(bindstats, "version", obj);
+
+ if ((flags & STATS_JSON_SERVER) != 0) {
+ /* OPCODE counters */
+ counters = json_object_new_object();
+
+ dumparg.result = ISC_R_SUCCESS;
+ dumparg.type = isc_statsformat_json;
+ dumparg.arg = counters;
+
+ dns_opcodestats_dump(server->sctx->opcodestats, opcodestat_dump,
+ &dumparg, ISC_STATSDUMP_VERBOSE);
+ if (dumparg.result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(counters)->count != 0) {
+ json_object_object_add(bindstats, "opcodes", counters);
+ } else {
+ json_object_put(counters);
+ }
+
+ /* OPCODE counters */
+ counters = json_object_new_object();
+
+ dumparg.type = isc_statsformat_json;
+ dumparg.arg = counters;
+
+ dns_rcodestats_dump(server->sctx->rcodestats, rcodestat_dump,
+ &dumparg, ISC_STATSDUMP_VERBOSE);
+ if (dumparg.result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(counters)->count != 0) {
+ json_object_object_add(bindstats, "rcodes", counters);
+ } else {
+ json_object_put(counters);
+ }
+
+ /* QTYPE counters */
+ counters = json_object_new_object();
+
+ dumparg.result = ISC_R_SUCCESS;
+ dumparg.arg = counters;
+
+ dns_rdatatypestats_dump(server->sctx->rcvquerystats,
+ rdtypestat_dump, &dumparg, 0);
+ if (dumparg.result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(counters)->count != 0) {
+ json_object_object_add(bindstats, "qtypes", counters);
+ } else {
+ json_object_put(counters);
+ }
+
+ /* server stat counters */
+ counters = json_object_new_object();
+
+ dumparg.result = ISC_R_SUCCESS;
+ dumparg.arg = counters;
+
+ result = dump_counters(ns_stats_get(server->sctx->nsstats),
+ isc_statsformat_json, counters, NULL,
+ nsstats_xmldesc, ns_statscounter_max,
+ nsstats_index, nsstat_values, 0);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(counters)->count != 0) {
+ json_object_object_add(bindstats, "nsstats", counters);
+ } else {
+ json_object_put(counters);
+ }
+
+ /* zone stat counters */
+ counters = json_object_new_object();
+
+ dumparg.result = ISC_R_SUCCESS;
+ dumparg.arg = counters;
+
+ result = dump_counters(server->zonestats, isc_statsformat_json,
+ counters, NULL, zonestats_xmldesc,
+ dns_zonestatscounter_max,
+ zonestats_index, zonestat_values, 0);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(counters)->count != 0) {
+ json_object_object_add(bindstats, "zonestats",
+ counters);
+ } else {
+ json_object_put(counters);
+ }
+
+ /* resolver stat counters */
+ counters = json_object_new_object();
+
+ dumparg.result = ISC_R_SUCCESS;
+ dumparg.arg = counters;
+
+ result = dump_counters(
+ server->resolverstats, isc_statsformat_json, counters,
+ NULL, resstats_xmldesc, dns_resstatscounter_max,
+ resstats_index, resstat_values, 0);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(counters)->count != 0) {
+ json_object_object_add(bindstats, "resstats", counters);
+ } else {
+ json_object_put(counters);
+ }
+
+#ifdef HAVE_DNSTAP
+ /* dnstap stat counters */
+ if (named_g_server->dtenv != NULL) {
+ isc_stats_t *dnstapstats = NULL;
+ dns_dt_getstats(named_g_server->dtenv, &dnstapstats);
+ counters = json_object_new_object();
+ dumparg.result = ISC_R_SUCCESS;
+ dumparg.arg = counters;
+ result = dump_counters(
+ dnstapstats, isc_statsformat_json, counters,
+ NULL, dnstapstats_xmldesc,
+ dns_dnstapcounter_max, dnstapstats_index,
+ dnstapstat_values, 0);
+ isc_stats_detach(&dnstapstats);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(counters)->count != 0) {
+ json_object_object_add(bindstats, "dnstapstats",
+ counters);
+ } else {
+ json_object_put(counters);
+ }
+ }
+#endif /* ifdef HAVE_DNSTAP */
+ }
+
+ if ((flags & (STATS_JSON_ZONES | STATS_JSON_SERVER)) != 0) {
+ viewlist = json_object_new_object();
+ CHECKMEM(viewlist);
+
+ json_object_object_add(bindstats, "views", viewlist);
+
+ view = ISC_LIST_HEAD(server->viewlist);
+ while (view != NULL) {
+ json_object *za, *v = json_object_new_object();
+
+ CHECKMEM(v);
+ json_object_object_add(viewlist, view->name, v);
+
+ za = json_object_new_array();
+ CHECKMEM(za);
+
+ if ((flags & STATS_JSON_ZONES) != 0) {
+ CHECK(dns_zt_apply(view->zonetable,
+ isc_rwlocktype_read, true,
+ NULL, zone_jsonrender, za));
+ }
+
+ if (json_object_array_length(za) != 0) {
+ json_object_object_add(v, "zones", za);
+ } else {
+ json_object_put(za);
+ }
+
+ if ((flags & STATS_JSON_SERVER) != 0) {
+ json_object *res;
+ dns_stats_t *dstats;
+ isc_stats_t *istats;
+
+ res = json_object_new_object();
+ CHECKMEM(res);
+ json_object_object_add(v, "resolver", res);
+
+ istats = view->resstats;
+ if (istats != NULL) {
+ counters = json_object_new_object();
+ CHECKMEM(counters);
+
+ result = dump_counters(
+ istats, isc_statsformat_json,
+ counters, NULL,
+ resstats_xmldesc,
+ dns_resstatscounter_max,
+ resstats_index, resstat_values,
+ 0);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ result = dumparg.result;
+ goto cleanup;
+ }
+
+ json_object_object_add(res, "stats",
+ counters);
+ }
+
+ dstats = view->resquerystats;
+ if (dstats != NULL) {
+ counters = json_object_new_object();
+ CHECKMEM(counters);
+
+ dumparg.arg = counters;
+ dumparg.result = ISC_R_SUCCESS;
+ dns_rdatatypestats_dump(dstats,
+ rdtypestat_dump,
+ &dumparg, 0);
+ if (dumparg.result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ result = dumparg.result;
+ goto cleanup;
+ }
+
+ json_object_object_add(res, "qtypes",
+ counters);
+ }
+
+ dstats = dns_db_getrrsetstats(view->cachedb);
+ if (dstats != NULL) {
+ counters = json_object_new_object();
+ CHECKMEM(counters);
+
+ dumparg.arg = counters;
+ dumparg.result = ISC_R_SUCCESS;
+ dns_rdatasetstats_dump(
+ dstats, rdatasetstats_dump,
+ &dumparg, 0);
+ if (dumparg.result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ result = dumparg.result;
+ goto cleanup;
+ }
+
+ json_object_object_add(res, "cache",
+ counters);
+ }
+
+ counters = json_object_new_object();
+ CHECKMEM(counters);
+
+ result = dns_cache_renderjson(view->cache,
+ counters);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ json_object_object_add(res, "cachestats",
+ counters);
+
+ istats = view->adbstats;
+ if (istats != NULL) {
+ counters = json_object_new_object();
+ CHECKMEM(counters);
+
+ result = dump_counters(
+ istats, isc_statsformat_json,
+ counters, NULL,
+ adbstats_xmldesc,
+ dns_adbstats_max,
+ adbstats_index, adbstat_values,
+ 0);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ result = dumparg.result;
+ goto cleanup;
+ }
+
+ json_object_object_add(res, "adb",
+ counters);
+ }
+ }
+
+ view = ISC_LIST_NEXT(view, link);
+ }
+ }
+
+ if ((flags & STATS_JSON_NET) != 0) {
+ /* socket stat counters */
+ counters = json_object_new_object();
+
+ dumparg.result = ISC_R_SUCCESS;
+ dumparg.arg = counters;
+
+ result = dump_counters(server->sockstats, isc_statsformat_json,
+ counters, NULL, sockstats_xmldesc,
+ isc_sockstatscounter_max,
+ sockstats_index, sockstat_values, 0);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto cleanup;
+ }
+
+ if (json_object_get_object(counters)->count != 0) {
+ json_object_object_add(bindstats, "sockstats",
+ counters);
+ } else {
+ json_object_put(counters);
+ }
+ }
+
+ if ((flags & STATS_JSON_TASKS) != 0) {
+ json_object *tasks = json_object_new_object();
+ CHECKMEM(tasks);
+
+ result = isc_taskmgr_renderjson(named_g_taskmgr, tasks);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(tasks);
+ goto cleanup;
+ }
+
+ json_object_object_add(bindstats, "taskmgr", tasks);
+ }
+
+ if ((flags & STATS_JSON_MEM) != 0) {
+ json_object *memory = json_object_new_object();
+ CHECKMEM(memory);
+
+ result = isc_mem_renderjson(memory);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(memory);
+ goto cleanup;
+ }
+
+ json_object_object_add(bindstats, "memory", memory);
+ }
+
+ if ((flags & STATS_JSON_TRAFFIC) != 0) {
+ traffic = json_object_new_object();
+ CHECKMEM(traffic);
+
+ udpreq4 = json_object_new_object();
+ CHECKMEM(udpreq4);
+
+ udpresp4 = json_object_new_object();
+ CHECKMEM(udpresp4);
+
+ tcpreq4 = json_object_new_object();
+ CHECKMEM(tcpreq4);
+
+ tcpresp4 = json_object_new_object();
+ CHECKMEM(tcpresp4);
+
+ udpreq6 = json_object_new_object();
+ CHECKMEM(udpreq6);
+
+ udpresp6 = json_object_new_object();
+ CHECKMEM(udpresp6);
+
+ tcpreq6 = json_object_new_object();
+ CHECKMEM(tcpreq6);
+
+ tcpresp6 = json_object_new_object();
+ CHECKMEM(tcpresp6);
+
+ CHECK(dump_counters(
+ server->sctx->udpinstats4, isc_statsformat_json,
+ udpreq4, NULL, udpinsizestats_xmldesc,
+ dns_sizecounter_in_max, udpinsizestats_index,
+ udpinsizestat_values, 0));
+
+ CHECK(dump_counters(
+ server->sctx->udpoutstats4, isc_statsformat_json,
+ udpresp4, NULL, udpoutsizestats_xmldesc,
+ dns_sizecounter_out_max, udpoutsizestats_index,
+ udpoutsizestat_values, 0));
+
+ CHECK(dump_counters(
+ server->sctx->tcpinstats4, isc_statsformat_json,
+ tcpreq4, NULL, tcpinsizestats_xmldesc,
+ dns_sizecounter_in_max, tcpinsizestats_index,
+ tcpinsizestat_values, 0));
+
+ CHECK(dump_counters(
+ server->sctx->tcpoutstats4, isc_statsformat_json,
+ tcpresp4, NULL, tcpoutsizestats_xmldesc,
+ dns_sizecounter_out_max, tcpoutsizestats_index,
+ tcpoutsizestat_values, 0));
+
+ CHECK(dump_counters(
+ server->sctx->udpinstats6, isc_statsformat_json,
+ udpreq6, NULL, udpinsizestats_xmldesc,
+ dns_sizecounter_in_max, udpinsizestats_index,
+ udpinsizestat_values, 0));
+
+ CHECK(dump_counters(
+ server->sctx->udpoutstats6, isc_statsformat_json,
+ udpresp6, NULL, udpoutsizestats_xmldesc,
+ dns_sizecounter_out_max, udpoutsizestats_index,
+ udpoutsizestat_values, 0));
+
+ CHECK(dump_counters(
+ server->sctx->tcpinstats6, isc_statsformat_json,
+ tcpreq6, NULL, tcpinsizestats_xmldesc,
+ dns_sizecounter_in_max, tcpinsizestats_index,
+ tcpinsizestat_values, 0));
+
+ CHECK(dump_counters(
+ server->sctx->tcpoutstats6, isc_statsformat_json,
+ tcpresp6, NULL, tcpoutsizestats_xmldesc,
+ dns_sizecounter_out_max, tcpoutsizestats_index,
+ tcpoutsizestat_values, 0));
+
+ json_object_object_add(traffic,
+ "dns-udp-requests-sizes-received-ipv4",
+ udpreq4);
+ json_object_object_add(
+ traffic, "dns-udp-responses-sizes-sent-ipv4", udpresp4);
+ json_object_object_add(traffic,
+ "dns-tcp-requests-sizes-received-ipv4",
+ tcpreq4);
+ json_object_object_add(
+ traffic, "dns-tcp-responses-sizes-sent-ipv4", tcpresp4);
+ json_object_object_add(traffic,
+ "dns-udp-requests-sizes-received-ipv6",
+ udpreq6);
+ json_object_object_add(
+ traffic, "dns-udp-responses-sizes-sent-ipv6", udpresp6);
+ json_object_object_add(traffic,
+ "dns-tcp-requests-sizes-received-ipv6",
+ tcpreq6);
+ json_object_object_add(
+ traffic, "dns-tcp-responses-sizes-sent-ipv6", tcpresp6);
+ json_object_object_add(bindstats, "traffic", traffic);
+ udpreq4 = NULL;
+ udpresp4 = NULL;
+ tcpreq4 = NULL;
+ tcpresp4 = NULL;
+ udpreq6 = NULL;
+ udpresp6 = NULL;
+ tcpreq6 = NULL;
+ tcpresp6 = NULL;
+ traffic = NULL;
+ }
+
+ *msg = json_object_to_json_string_ext(bindstats,
+ JSON_C_TO_STRING_PRETTY);
+ *msglen = strlen(*msg);
+
+ if (rootp != NULL) {
+ *rootp = bindstats;
+ bindstats = NULL;
+ }
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (udpreq4 != NULL) {
+ json_object_put(udpreq4);
+ }
+ if (udpresp4 != NULL) {
+ json_object_put(udpresp4);
+ }
+ if (tcpreq4 != NULL) {
+ json_object_put(tcpreq4);
+ }
+ if (tcpresp4 != NULL) {
+ json_object_put(tcpresp4);
+ }
+ if (udpreq6 != NULL) {
+ json_object_put(udpreq6);
+ }
+ if (udpresp6 != NULL) {
+ json_object_put(udpresp6);
+ }
+ if (tcpreq6 != NULL) {
+ json_object_put(tcpreq6);
+ }
+ if (tcpresp6 != NULL) {
+ json_object_put(tcpresp6);
+ }
+ if (traffic != NULL) {
+ json_object_put(traffic);
+ }
+ if (bindstats != NULL) {
+ json_object_put(bindstats);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+render_json(uint32_t flags, void *arg, unsigned int *retcode,
+ const char **retmsg, const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ isc_result_t result;
+ json_object *bindstats = NULL;
+ named_server_t *server = arg;
+ const char *msg = NULL;
+ size_t msglen = 0;
+ char *p;
+
+ result = generatejson(server, &msglen, &msg, &bindstats, flags);
+ if (result == ISC_R_SUCCESS) {
+ *retcode = 200;
+ *retmsg = "OK";
+ *mimetype = "application/json";
+ DE_CONST(msg, p);
+ isc_buffer_reinit(b, p, msglen);
+ isc_buffer_add(b, msglen);
+ *freecb = wrap_jsonfree;
+ *freecb_args = bindstats;
+ } else {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed at rendering JSON()");
+ }
+
+ return (result);
+}
+
+static isc_result_t
+render_json_all(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_json(STATS_JSON_ALL, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_status(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_json(STATS_JSON_STATUS, arg, retcode, retmsg, mimetype,
+ b, freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_server(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_json(STATS_JSON_SERVER, arg, retcode, retmsg, mimetype,
+ b, freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_zones(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_json(STATS_JSON_ZONES, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_mem(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_json(STATS_JSON_MEM, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_tasks(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_json(STATS_JSON_TASKS, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_net(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_json(STATS_JSON_NET, arg, retcode, retmsg, mimetype, b,
+ freecb, freecb_args));
+}
+
+static isc_result_t
+render_json_traffic(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
+ void *arg, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args) {
+ UNUSED(httpd);
+ UNUSED(urlinfo);
+ return (render_json(STATS_JSON_TRAFFIC, arg, retcode, retmsg, mimetype,
+ b, freecb, freecb_args));
+}
+
+#endif /* HAVE_JSON_C */
+
+static isc_result_t
+render_xsl(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, void *args,
+ unsigned int *retcode, const char **retmsg, const char **mimetype,
+ isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) {
+ isc_result_t result;
+ char *p = NULL;
+
+ UNUSED(httpd);
+ UNUSED(args);
+
+ *freecb = NULL;
+ *freecb_args = NULL;
+ *mimetype = "text/xslt+xml";
+
+ if (isc_httpdurl_isstatic(urlinfo)) {
+ time_t t1, t2;
+ const isc_time_t *when;
+ const isc_time_t *loadtime;
+
+ when = isc_httpd_if_modified_since(httpd);
+
+ if (isc_time_isepoch(when)) {
+ goto send;
+ }
+
+ result = isc_time_secondsastimet(when, &t1);
+ if (result != ISC_R_SUCCESS) {
+ goto send;
+ }
+
+ loadtime = isc_httpdurl_loadtime(urlinfo);
+
+ result = isc_time_secondsastimet(loadtime, &t2);
+ if (result != ISC_R_SUCCESS) {
+ goto send;
+ }
+
+ if (t1 < t2) {
+ goto send;
+ }
+
+ *retcode = 304;
+ *retmsg = "Not modified";
+ goto end;
+ }
+
+send:
+ *retcode = 200;
+ *retmsg = "OK";
+ DE_CONST(xslmsg, p);
+ isc_buffer_reinit(b, p, strlen(xslmsg));
+ isc_buffer_add(b, strlen(xslmsg));
+end:
+ return (ISC_R_SUCCESS);
+}
+
+static void
+shutdown_listener(named_statschannel_t *listener) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&listener->address, socktext, sizeof(socktext));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE,
+ "stopping statistics channel on %s", socktext);
+
+ isc_httpdmgr_shutdown(&listener->httpdmgr);
+}
+
+static bool
+client_ok(const isc_sockaddr_t *fromaddr, void *arg) {
+ named_statschannel_t *listener = arg;
+ dns_aclenv_t *env =
+ ns_interfacemgr_getaclenv(named_g_server->interfacemgr);
+ isc_netaddr_t netaddr;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ int match;
+
+ REQUIRE(listener != NULL);
+
+ isc_netaddr_fromsockaddr(&netaddr, fromaddr);
+
+ LOCK(&listener->lock);
+ if ((dns_acl_match(&netaddr, NULL, listener->acl, env, &match, NULL) ==
+ ISC_R_SUCCESS) &&
+ match > 0)
+ {
+ UNLOCK(&listener->lock);
+ return (true);
+ }
+ UNLOCK(&listener->lock);
+
+ isc_sockaddr_format(fromaddr, socktext, sizeof(socktext));
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "rejected statistics connection from %s", socktext);
+
+ return (false);
+}
+
+static void
+destroy_listener(void *arg) {
+ named_statschannel_t *listener = (named_statschannel_t *)arg;
+
+ REQUIRE(listener != NULL);
+ REQUIRE(!ISC_LINK_LINKED(listener, link));
+
+ /* We don't have to acquire the lock here since it's already unlinked */
+ dns_acl_detach(&listener->acl);
+
+ isc_mutex_destroy(&listener->lock);
+ isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener));
+}
+
+static isc_result_t
+add_listener(named_server_t *server, named_statschannel_t **listenerp,
+ const cfg_obj_t *listen_params, const cfg_obj_t *config,
+ isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
+ const char *socktext) {
+ isc_result_t result;
+ named_statschannel_t *listener = NULL;
+ const cfg_obj_t *allow = NULL;
+ dns_acl_t *new_acl = NULL;
+ int pf;
+
+ listener = isc_mem_get(server->mctx, sizeof(*listener));
+ *listener = (named_statschannel_t){ .address = *addr };
+ ISC_LINK_INIT(listener, link);
+ isc_mutex_init(&listener->lock);
+ isc_mem_attach(server->mctx, &listener->mctx);
+
+ allow = cfg_tuple_get(listen_params, "allow");
+ if (allow != NULL && cfg_obj_islist(allow)) {
+ result = cfg_acl_fromconfig(allow, config, named_g_lctx,
+ aclconfctx, listener->mctx, 0,
+ &new_acl);
+ } else {
+ result = dns_acl_any(listener->mctx, &new_acl);
+ }
+ CHECK(result);
+
+ dns_acl_attach(new_acl, &listener->acl);
+ dns_acl_detach(&new_acl);
+
+ pf = isc_sockaddr_pf(&listener->address);
+ if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
+ (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
+ {
+ CHECK(ISC_R_FAMILYNOSUPPORT);
+ }
+
+ CHECK(isc_httpdmgr_create(named_g_netmgr, server->mctx, addr, client_ok,
+ destroy_listener, listener,
+ &listener->httpdmgr));
+
+#ifdef HAVE_LIBXML2
+ isc_httpdmgr_addurl(listener->httpdmgr, "/", false, render_xml_all,
+ server);
+ isc_httpdmgr_addurl(listener->httpdmgr, "/xml", false, render_xml_all,
+ server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/xml/v" STATS_XML_VERSION_MAJOR, false,
+ render_xml_all, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/xml/v" STATS_XML_VERSION_MAJOR "/status", false,
+ render_xml_status, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/xml/v" STATS_XML_VERSION_MAJOR "/server", false,
+ render_xml_server, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/xml/v" STATS_XML_VERSION_MAJOR "/zones", false,
+ render_xml_zones, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/xml/v" STATS_XML_VERSION_MAJOR "/net", false,
+ render_xml_net, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/xml/v" STATS_XML_VERSION_MAJOR "/tasks", false,
+ render_xml_tasks, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/xml/v" STATS_XML_VERSION_MAJOR "/mem", false,
+ render_xml_mem, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/xml/v" STATS_XML_VERSION_MAJOR "/traffic", false,
+ render_xml_traffic, server);
+#endif /* ifdef HAVE_LIBXML2 */
+#ifdef HAVE_JSON_C
+ isc_httpdmgr_addurl(listener->httpdmgr, "/json", false, render_json_all,
+ server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/json/v" STATS_JSON_VERSION_MAJOR, false,
+ render_json_all, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/json/v" STATS_JSON_VERSION_MAJOR "/status", false,
+ render_json_status, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/json/v" STATS_JSON_VERSION_MAJOR "/server", false,
+ render_json_server, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/json/v" STATS_JSON_VERSION_MAJOR "/zones", false,
+ render_json_zones, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/json/v" STATS_JSON_VERSION_MAJOR "/tasks", false,
+ render_json_tasks, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/json/v" STATS_JSON_VERSION_MAJOR "/net", false,
+ render_json_net, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/json/v" STATS_JSON_VERSION_MAJOR "/mem", false,
+ render_json_mem, server);
+ isc_httpdmgr_addurl(listener->httpdmgr,
+ "/json/v" STATS_JSON_VERSION_MAJOR "/traffic",
+ false, render_json_traffic, server);
+#endif /* ifdef HAVE_JSON_C */
+ isc_httpdmgr_addurl(listener->httpdmgr, "/bind9.xsl", true, render_xsl,
+ server);
+
+ *listenerp = listener;
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE,
+ "statistics channel listening on %s", socktext);
+
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (listener->acl != NULL) {
+ dns_acl_detach(&listener->acl);
+ }
+ isc_mutex_destroy(&listener->lock);
+ isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener));
+
+ return (result);
+}
+
+static void
+update_listener(named_server_t *server, named_statschannel_t **listenerp,
+ const cfg_obj_t *listen_params, const cfg_obj_t *config,
+ isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
+ const char *socktext) {
+ named_statschannel_t *listener;
+ const cfg_obj_t *allow = NULL;
+ dns_acl_t *new_acl = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ for (listener = ISC_LIST_HEAD(server->statschannels); listener != NULL;
+ listener = ISC_LIST_NEXT(listener, link))
+ {
+ if (isc_sockaddr_equal(addr, &listener->address)) {
+ break;
+ }
+ }
+
+ if (listener == NULL) {
+ *listenerp = NULL;
+ return;
+ }
+
+ /*
+ * Now, keep the old access list unless a new one can be made.
+ */
+ allow = cfg_tuple_get(listen_params, "allow");
+ if (allow != NULL && cfg_obj_islist(allow)) {
+ result = cfg_acl_fromconfig(allow, config, named_g_lctx,
+ aclconfctx, listener->mctx, 0,
+ &new_acl);
+ } else {
+ result = dns_acl_any(listener->mctx, &new_acl);
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ LOCK(&listener->lock);
+
+ dns_acl_detach(&listener->acl);
+ dns_acl_attach(new_acl, &listener->acl);
+ dns_acl_detach(&new_acl);
+
+ UNLOCK(&listener->lock);
+ } else {
+ cfg_obj_log(listen_params, named_g_lctx, ISC_LOG_WARNING,
+ "couldn't install new acl for "
+ "statistics channel %s: %s",
+ socktext, isc_result_totext(result));
+ }
+
+ *listenerp = listener;
+}
+
+isc_result_t
+named_statschannels_configure(named_server_t *server, const cfg_obj_t *config,
+ cfg_aclconfctx_t *aclconfctx) {
+ named_statschannel_t *listener, *listener_next;
+ named_statschannellist_t new_listeners;
+ const cfg_obj_t *statschannellist = NULL;
+ const cfg_listelt_t *element, *element2;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+
+ RUNTIME_CHECK(isc_once_do(&once, init_desc) == ISC_R_SUCCESS);
+
+ ISC_LIST_INIT(new_listeners);
+
+ /*
+ * Get the list of named.conf 'statistics-channels' statements.
+ */
+ (void)cfg_map_get(config, "statistics-channels", &statschannellist);
+
+ /*
+ * Run through the new address/port list, noting sockets that are
+ * already being listened on and moving them to the new list.
+ *
+ * Identifying duplicate addr/port combinations is left to either
+ * the underlying config code, or to the bind attempt getting an
+ * address-in-use error.
+ */
+ if (statschannellist != NULL) {
+#ifndef EXTENDED_STATS
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "statistics-channels specified but not effective "
+ "due to missing XML and/or JSON library");
+#else /* EXTENDED_STATS */
+#ifndef HAVE_LIBXML2
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "statistics-channels: XML library missing, "
+ "only JSON stats will be available");
+#endif /* !HAVE_LIBXML2 */
+#ifndef HAVE_JSON_C
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "statistics-channels: JSON library missing, "
+ "only XML stats will be available");
+#endif /* !HAVE_JSON_C */
+#endif /* EXTENDED_STATS */
+
+ for (element = cfg_list_first(statschannellist);
+ element != NULL; element = cfg_list_next(element))
+ {
+ const cfg_obj_t *statschannel;
+ const cfg_obj_t *listenercfg = NULL;
+
+ statschannel = cfg_listelt_value(element);
+ (void)cfg_map_get(statschannel, "inet", &listenercfg);
+ if (listenercfg == NULL) {
+ continue;
+ }
+
+ for (element2 = cfg_list_first(listenercfg);
+ element2 != NULL;
+ element2 = cfg_list_next(element2))
+ {
+ const cfg_obj_t *listen_params;
+ const cfg_obj_t *obj;
+ isc_sockaddr_t addr;
+
+ listen_params = cfg_listelt_value(element2);
+
+ obj = cfg_tuple_get(listen_params, "address");
+ addr = *cfg_obj_assockaddr(obj);
+ if (isc_sockaddr_getport(&addr) == 0) {
+ isc_sockaddr_setport(
+ &addr,
+ NAMED_STATSCHANNEL_HTTPPORT);
+ }
+
+ isc_sockaddr_format(&addr, socktext,
+ sizeof(socktext));
+
+ isc_log_write(named_g_lctx,
+ NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER,
+ ISC_LOG_DEBUG(9),
+ "processing statistics "
+ "channel %s",
+ socktext);
+
+ update_listener(server, &listener,
+ listen_params, config, &addr,
+ aclconfctx, socktext);
+
+ if (listener != NULL) {
+ /*
+ * Remove the listener from the old
+ * list, so it won't be shut down.
+ */
+ ISC_LIST_UNLINK(server->statschannels,
+ listener, link);
+ } else {
+ /*
+ * This is a new listener.
+ */
+ isc_result_t r;
+
+ r = add_listener(server, &listener,
+ listen_params, config,
+ &addr, aclconfctx,
+ socktext);
+ if (r != ISC_R_SUCCESS) {
+ cfg_obj_log(
+ listen_params,
+ named_g_lctx,
+ ISC_LOG_WARNING,
+ "couldn't allocate "
+ "statistics channel"
+ " %s: %s",
+ socktext,
+ isc_result_totext(r));
+ }
+ }
+
+ if (listener != NULL) {
+ ISC_LIST_APPEND(new_listeners, listener,
+ link);
+ }
+ }
+ }
+ }
+
+ for (listener = ISC_LIST_HEAD(server->statschannels); listener != NULL;
+ listener = listener_next)
+ {
+ listener_next = ISC_LIST_NEXT(listener, link);
+ ISC_LIST_UNLINK(server->statschannels, listener, link);
+ shutdown_listener(listener);
+ }
+
+ ISC_LIST_APPENDLIST(server->statschannels, new_listeners, link);
+ return (ISC_R_SUCCESS);
+}
+
+void
+named_statschannels_shutdown(named_server_t *server) {
+ named_statschannel_t *listener;
+
+ while ((listener = ISC_LIST_HEAD(server->statschannels)) != NULL) {
+ ISC_LIST_UNLINK(server->statschannels, listener, link);
+ shutdown_listener(listener);
+ }
+}
+
+isc_result_t
+named_stats_dump(named_server_t *server, FILE *fp) {
+ isc_stdtime_t now;
+ isc_result_t result;
+ dns_view_t *view;
+ dns_zone_t *zone, *next;
+ stats_dumparg_t dumparg;
+ uint64_t nsstat_values[ns_statscounter_max];
+ uint64_t resstat_values[dns_resstatscounter_max];
+ uint64_t adbstat_values[dns_adbstats_max];
+ uint64_t zonestat_values[dns_zonestatscounter_max];
+ uint64_t sockstat_values[isc_sockstatscounter_max];
+ uint64_t gluecachestats_values[dns_gluecachestatscounter_max];
+
+ RUNTIME_CHECK(isc_once_do(&once, init_desc) == ISC_R_SUCCESS);
+
+ /* Set common fields */
+ dumparg.type = isc_statsformat_file;
+ dumparg.arg = fp;
+
+ isc_stdtime_get(&now);
+ fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now);
+
+ fprintf(fp, "++ Incoming Requests ++\n");
+ dns_opcodestats_dump(server->sctx->opcodestats, opcodestat_dump,
+ &dumparg, 0);
+
+ fprintf(fp, "++ Incoming Queries ++\n");
+ dns_rdatatypestats_dump(server->sctx->rcvquerystats, rdtypestat_dump,
+ &dumparg, 0);
+
+ fprintf(fp, "++ Outgoing Rcodes ++\n");
+ dns_rcodestats_dump(server->sctx->rcodestats, rcodestat_dump, &dumparg,
+ 0);
+
+ fprintf(fp, "++ Outgoing Queries ++\n");
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (view->resquerystats == NULL) {
+ continue;
+ }
+ if (strcmp(view->name, "_default") == 0) {
+ fprintf(fp, "[View: default]\n");
+ } else {
+ fprintf(fp, "[View: %s]\n", view->name);
+ }
+ dns_rdatatypestats_dump(view->resquerystats, rdtypestat_dump,
+ &dumparg, 0);
+ }
+
+ fprintf(fp, "++ Name Server Statistics ++\n");
+ (void)dump_counters(ns_stats_get(server->sctx->nsstats),
+ isc_statsformat_file, fp, NULL, nsstats_desc,
+ ns_statscounter_max, nsstats_index, nsstat_values,
+ 0);
+
+ fprintf(fp, "++ Zone Maintenance Statistics ++\n");
+ (void)dump_counters(server->zonestats, isc_statsformat_file, fp, NULL,
+ zonestats_desc, dns_zonestatscounter_max,
+ zonestats_index, zonestat_values, 0);
+
+ fprintf(fp, "++ Resolver Statistics ++\n");
+ fprintf(fp, "[Common]\n");
+ (void)dump_counters(server->resolverstats, isc_statsformat_file, fp,
+ NULL, resstats_desc, dns_resstatscounter_max,
+ resstats_index, resstat_values, 0);
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (view->resstats == NULL) {
+ continue;
+ }
+ if (strcmp(view->name, "_default") == 0) {
+ fprintf(fp, "[View: default]\n");
+ } else {
+ fprintf(fp, "[View: %s]\n", view->name);
+ }
+ (void)dump_counters(view->resstats, isc_statsformat_file, fp,
+ NULL, resstats_desc,
+ dns_resstatscounter_max, resstats_index,
+ resstat_values, 0);
+ }
+
+ fprintf(fp, "++ Cache Statistics ++\n");
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (strcmp(view->name, "_default") == 0) {
+ fprintf(fp, "[View: default]\n");
+ } else {
+ fprintf(fp, "[View: %s (Cache: %s)]\n", view->name,
+ dns_cache_getname(view->cache));
+ }
+ /*
+ * Avoid dumping redundant statistics when the cache is shared.
+ */
+ if (dns_view_iscacheshared(view)) {
+ continue;
+ }
+ dns_cache_dumpstats(view->cache, fp);
+ }
+
+ fprintf(fp, "++ Cache DB RRsets ++\n");
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ dns_stats_t *cacherrstats;
+
+ cacherrstats = dns_db_getrrsetstats(view->cachedb);
+ if (cacherrstats == NULL) {
+ continue;
+ }
+ if (strcmp(view->name, "_default") == 0) {
+ fprintf(fp, "[View: default]\n");
+ } else {
+ fprintf(fp, "[View: %s (Cache: %s)]\n", view->name,
+ dns_cache_getname(view->cache));
+ }
+ if (dns_view_iscacheshared(view)) {
+ /*
+ * Avoid dumping redundant statistics when the cache is
+ * shared.
+ */
+ continue;
+ }
+ dns_rdatasetstats_dump(cacherrstats, rdatasetstats_dump,
+ &dumparg, 0);
+ }
+
+ fprintf(fp, "++ ADB stats ++\n");
+ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (view->adbstats == NULL) {
+ continue;
+ }
+ if (strcmp(view->name, "_default") == 0) {
+ fprintf(fp, "[View: default]\n");
+ } else {
+ fprintf(fp, "[View: %s]\n", view->name);
+ }
+ (void)dump_counters(view->adbstats, isc_statsformat_file, fp,
+ NULL, adbstats_desc, dns_adbstats_max,
+ adbstats_index, adbstat_values, 0);
+ }
+
+ fprintf(fp, "++ Socket I/O Statistics ++\n");
+ (void)dump_counters(server->sockstats, isc_statsformat_file, fp, NULL,
+ sockstats_desc, isc_sockstatscounter_max,
+ sockstats_index, sockstat_values, 0);
+
+ fprintf(fp, "++ Per Zone Query Statistics ++\n");
+ zone = NULL;
+ for (result = dns_zone_first(server->zonemgr, &zone);
+ result == ISC_R_SUCCESS;
+ next = NULL, result = dns_zone_next(zone, &next), zone = next)
+ {
+ isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
+ if (zonestats != NULL) {
+ char zonename[DNS_NAME_FORMATSIZE];
+
+ view = dns_zone_getview(zone);
+ if (view == NULL) {
+ continue;
+ }
+
+ dns_name_format(dns_zone_getorigin(zone), zonename,
+ sizeof(zonename));
+ fprintf(fp, "[%s", zonename);
+ if (strcmp(view->name, "_default") != 0) {
+ fprintf(fp, " (view: %s)", view->name);
+ }
+ fprintf(fp, "]\n");
+
+ (void)dump_counters(zonestats, isc_statsformat_file, fp,
+ NULL, nsstats_desc,
+ ns_statscounter_max, nsstats_index,
+ nsstat_values, 0);
+ }
+ }
+
+ fprintf(fp, "++ Per Zone Glue Cache Statistics ++\n");
+ zone = NULL;
+ for (result = dns_zone_first(server->zonemgr, &zone);
+ result == ISC_R_SUCCESS;
+ next = NULL, result = dns_zone_next(zone, &next), zone = next)
+ {
+ isc_stats_t *gluecachestats = dns_zone_getgluecachestats(zone);
+ if (gluecachestats != NULL) {
+ char zonename[DNS_NAME_FORMATSIZE];
+
+ view = dns_zone_getview(zone);
+ if (view == NULL) {
+ continue;
+ }
+
+ dns_name_format(dns_zone_getorigin(zone), zonename,
+ sizeof(zonename));
+ fprintf(fp, "[%s", zonename);
+ if (strcmp(view->name, "_default") != 0) {
+ fprintf(fp, " (view: %s)", view->name);
+ }
+ fprintf(fp, "]\n");
+
+ (void)dump_counters(
+ gluecachestats, isc_statsformat_file, fp, NULL,
+ gluecachestats_desc,
+ dns_gluecachestatscounter_max,
+ gluecachestats_index, gluecachestats_values, 0);
+ }
+ }
+
+ fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);
+
+ return (ISC_R_SUCCESS); /* this function currently always succeeds */
+}
diff --git a/bin/named/tkeyconf.c b/bin/named/tkeyconf.c
new file mode 100644
index 0000000..03b198b
--- /dev/null
+++ b/bin/named/tkeyconf.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+#include <dns/tkey.h>
+
+#include <dst/gssapi.h>
+
+#include <isccfg/cfg.h>
+
+#include <named/tkeyconf.h>
+
+#define RETERR(x) \
+ do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto failure; \
+ } while (0)
+
+#include <named/log.h>
+#define LOG(msg) \
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "%s", msg)
+
+isc_result_t
+named_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
+ dns_tkeyctx_t **tctxp) {
+ isc_result_t result;
+ dns_tkeyctx_t *tctx = NULL;
+ const char *s;
+ uint32_t n;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_buffer_t b;
+ const cfg_obj_t *obj;
+ int type;
+
+ result = dns_tkeyctx_create(mctx, &tctx);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ obj = NULL;
+ result = cfg_map_get(options, "tkey-dhkey", &obj);
+ if (result == ISC_R_SUCCESS) {
+ s = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
+ n = cfg_obj_asuint32(cfg_tuple_get(obj, "keyid"));
+ isc_buffer_constinit(&b, s, strlen(s));
+ isc_buffer_add(&b, strlen(s));
+ name = dns_fixedname_initname(&fname);
+ RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+ type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
+ RETERR(dst_key_fromfile(name, (dns_keytag_t)n, DNS_KEYALG_DH,
+ type, NULL, mctx, &tctx->dhkey));
+ }
+
+ obj = NULL;
+ result = cfg_map_get(options, "tkey-domain", &obj);
+ if (result == ISC_R_SUCCESS) {
+ s = cfg_obj_asstring(obj);
+ isc_buffer_constinit(&b, s, strlen(s));
+ isc_buffer_add(&b, strlen(s));
+ name = dns_fixedname_initname(&fname);
+ RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+ tctx->domain = isc_mem_get(mctx, sizeof(dns_name_t));
+ dns_name_init(tctx->domain, NULL);
+ dns_name_dup(name, mctx, tctx->domain);
+ }
+
+ obj = NULL;
+ result = cfg_map_get(options, "tkey-gssapi-credential", &obj);
+ if (result == ISC_R_SUCCESS) {
+ s = cfg_obj_asstring(obj);
+
+ isc_buffer_constinit(&b, s, strlen(s));
+ isc_buffer_add(&b, strlen(s));
+ name = dns_fixedname_initname(&fname);
+ RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+ RETERR(dst_gssapi_acquirecred(name, false, &tctx->gsscred));
+ }
+
+ obj = NULL;
+ result = cfg_map_get(options, "tkey-gssapi-keytab", &obj);
+ if (result == ISC_R_SUCCESS) {
+ s = cfg_obj_asstring(obj);
+ tctx->gssapi_keytab = isc_mem_strdup(mctx, s);
+ }
+
+ *tctxp = tctx;
+ return (ISC_R_SUCCESS);
+
+failure:
+ dns_tkeyctx_destroy(&tctx);
+ return (result);
+}
diff --git a/bin/named/transportconf.c b/bin/named/transportconf.c
new file mode 100644
index 0000000..f24aab1
--- /dev/null
+++ b/bin/named/transportconf.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+
+#include <isc/buffer.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/name.h>
+#include <dns/transport.h>
+
+#include <isccfg/cfg.h>
+
+#include <named/log.h>
+#include <named/transportconf.h>
+
+#define create_name(id, name) \
+ isc_buffer_t namesrc, namebuf; \
+ char namedata[DNS_NAME_FORMATSIZE + 1]; \
+ dns_name_init(name, NULL); \
+ isc_buffer_constinit(&namesrc, id, strlen(id)); \
+ isc_buffer_add(&namesrc, strlen(id)); \
+ isc_buffer_init(&namebuf, namedata, sizeof(namedata)); \
+ result = (dns_name_fromtext(name, &namesrc, dns_rootname, \
+ DNS_NAME_DOWNCASE, &namebuf)); \
+ if (result != ISC_R_SUCCESS) { \
+ goto failure; \
+ }
+
+#define parse_transport_option(map, transport, name, setter) \
+ { \
+ const cfg_obj_t *obj = NULL; \
+ cfg_map_get(map, name, &obj); \
+ if (obj != NULL) { \
+ setter(transport, cfg_obj_asstring(obj)); \
+ } \
+ }
+
+#define parse_transport_tls_versions(map, transport, name, setter) \
+ { \
+ const cfg_obj_t *obj = NULL; \
+ cfg_map_get(map, name, &obj); \
+ if (obj != NULL) { \
+ { \
+ uint32_t tls_protos = 0; \
+ const cfg_listelt_t *proto = NULL; \
+ INSIST(obj != NULL); \
+ for (proto = cfg_list_first(obj); proto != 0; \
+ proto = cfg_list_next(proto)) \
+ { \
+ const cfg_obj_t *tls_proto_obj = \
+ cfg_listelt_value(proto); \
+ const char *tls_sver = \
+ cfg_obj_asstring( \
+ tls_proto_obj); \
+ const isc_tls_protocol_version_t ver = \
+ isc_tls_protocol_name_to_version( \
+ tls_sver); \
+ INSIST(ver != \
+ ISC_TLS_PROTO_VER_UNDEFINED); \
+ INSIST(isc_tls_protocol_supported( \
+ ver)); \
+ tls_protos |= ver; \
+ } \
+ if (tls_protos != 0) { \
+ setter(transport, tls_protos); \
+ } \
+ } \
+ } \
+ }
+
+#define parse_transport_bool_option(map, transport, name, setter) \
+ { \
+ const cfg_obj_t *obj = NULL; \
+ cfg_map_get(map, name, &obj); \
+ if (obj != NULL) { \
+ setter(transport, cfg_obj_asboolean(obj)); \
+ } \
+ }
+
+static isc_result_t
+add_doh_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) {
+ const cfg_obj_t *doh = NULL;
+ const char *dohid = NULL;
+ isc_result_t result;
+
+ for (const cfg_listelt_t *element = cfg_list_first(transportlist);
+ element != NULL; element = cfg_list_next(element))
+ {
+ dns_name_t dohname;
+ dns_transport_t *transport;
+
+ doh = cfg_listelt_value(element);
+ dohid = cfg_obj_asstring(cfg_map_getname(doh));
+
+ create_name(dohid, &dohname);
+
+ transport = dns_transport_new(&dohname, DNS_TRANSPORT_HTTP,
+ list);
+
+ dns_transport_set_tlsname(transport, dohid);
+ parse_transport_option(doh, transport, "key-file",
+ dns_transport_set_keyfile);
+ parse_transport_option(doh, transport, "cert-file",
+ dns_transport_set_certfile);
+ parse_transport_tls_versions(doh, transport, "protocols",
+ dns_transport_set_tls_versions);
+ parse_transport_option(doh, transport, "ciphers",
+ dns_transport_set_ciphers);
+ parse_transport_bool_option(
+ doh, transport, "prefer-server-ciphers",
+ dns_transport_set_prefer_server_ciphers)
+ parse_transport_option(doh, transport, "ca-file",
+ dns_transport_set_cafile);
+ parse_transport_option(doh, transport, "remote-hostname",
+ dns_transport_set_remote_hostname);
+ }
+
+ return (ISC_R_SUCCESS);
+failure:
+ cfg_obj_log(doh, named_g_lctx, ISC_LOG_ERROR,
+ "configuring DoH '%s': %s", dohid,
+ isc_result_totext(result));
+
+ return (result);
+}
+
+static isc_result_t
+add_tls_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) {
+ const cfg_obj_t *tls = NULL;
+ const char *tlsid = NULL;
+ isc_result_t result;
+
+ for (const cfg_listelt_t *element = cfg_list_first(transportlist);
+ element != NULL; element = cfg_list_next(element))
+ {
+ dns_name_t tlsname;
+ dns_transport_t *transport;
+
+ tls = cfg_listelt_value(element);
+ tlsid = cfg_obj_asstring(cfg_map_getname(tls));
+
+ if (!strcmp(tlsid, "ephemeral")) {
+ result = ISC_R_UNEXPECTEDTOKEN;
+ goto failure;
+ }
+
+ create_name(tlsid, &tlsname);
+
+ transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS,
+ list);
+
+ dns_transport_set_tlsname(transport, tlsid);
+ parse_transport_option(tls, transport, "key-file",
+ dns_transport_set_keyfile);
+ parse_transport_option(tls, transport, "cert-file",
+ dns_transport_set_certfile);
+ parse_transport_tls_versions(tls, transport, "protocols",
+ dns_transport_set_tls_versions);
+ parse_transport_option(tls, transport, "ciphers",
+ dns_transport_set_ciphers);
+ parse_transport_bool_option(
+ tls, transport, "prefer-server-ciphers",
+ dns_transport_set_prefer_server_ciphers)
+ parse_transport_option(tls, transport, "ca-file",
+ dns_transport_set_cafile);
+ parse_transport_option(tls, transport, "remote-hostname",
+ dns_transport_set_remote_hostname);
+ }
+
+ return (ISC_R_SUCCESS);
+failure:
+ cfg_obj_log(tls, named_g_lctx, ISC_LOG_ERROR,
+ "configuring tls '%s': %s", tlsid,
+ isc_result_totext(result));
+
+ return (result);
+}
+
+#define CHECK(f) \
+ if ((result = f) != ISC_R_SUCCESS) { \
+ goto failure; \
+ }
+
+static isc_result_t
+transport_list_fromconfig(const cfg_obj_t *config, dns_transport_list_t *list) {
+ const cfg_obj_t *obj = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ if (result == ISC_R_SUCCESS &&
+ cfg_map_get(config, "tls", &obj) == ISC_R_SUCCESS)
+ {
+ result = add_tls_transports(obj, list);
+ obj = NULL;
+ }
+
+ if (result == ISC_R_SUCCESS &&
+ cfg_map_get(config, "doh", &obj) == ISC_R_SUCCESS)
+ {
+ result = add_doh_transports(obj, list);
+ obj = NULL;
+ }
+
+ return (result);
+}
+
+static void
+transport_list_add_ephemeral(dns_transport_list_t *list) {
+ isc_result_t result;
+ dns_name_t tlsname;
+ dns_transport_t *transport;
+
+ create_name("ephemeral", &tlsname);
+
+ transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS, list);
+ dns_transport_set_tlsname(transport, "ephemeral");
+
+ return;
+failure:
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+}
+
+isc_result_t
+named_transports_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ isc_mem_t *mctx, dns_transport_list_t **listp) {
+ isc_result_t result;
+ dns_transport_list_t *list = dns_transport_list_new(mctx);
+
+ REQUIRE(listp != NULL && *listp == NULL);
+
+ transport_list_add_ephemeral(list);
+
+ if (config != NULL) {
+ result = transport_list_fromconfig(config, list);
+ if (result != ISC_R_SUCCESS) {
+ goto failure;
+ }
+ }
+
+ if (vconfig != NULL) {
+ config = cfg_tuple_get(vconfig, "options");
+ transport_list_fromconfig(config, list);
+ }
+
+ *listp = list;
+ return (ISC_R_SUCCESS);
+failure:
+ dns_transport_list_detach(&list);
+ return (result);
+}
diff --git a/bin/named/tsigconf.c b/bin/named/tsigconf.c
new file mode 100644
index 0000000..6d596ab
--- /dev/null
+++ b/bin/named/tsigconf.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/tsig.h>
+
+#include <isccfg/cfg.h>
+
+#include <named/config.h>
+#include <named/log.h>
+#include <named/tsigconf.h>
+
+static isc_result_t
+add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring,
+ isc_mem_t *mctx) {
+ dns_tsigkey_t *tsigkey = NULL;
+ const cfg_listelt_t *element;
+ const cfg_obj_t *key = NULL;
+ const char *keyid = NULL;
+ unsigned char *secret = NULL;
+ int secretalloc = 0;
+ int secretlen = 0;
+ isc_result_t ret;
+ isc_stdtime_t now;
+ uint16_t bits;
+
+ for (element = cfg_list_first(list); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *algobj = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ dns_name_t keyname;
+ const dns_name_t *alg;
+ const char *algstr;
+ char keynamedata[1024];
+ isc_buffer_t keynamesrc, keynamebuf;
+ const char *secretstr;
+ isc_buffer_t secretbuf;
+
+ key = cfg_listelt_value(element);
+ keyid = cfg_obj_asstring(cfg_map_getname(key));
+
+ algobj = NULL;
+ secretobj = NULL;
+ (void)cfg_map_get(key, "algorithm", &algobj);
+ (void)cfg_map_get(key, "secret", &secretobj);
+ INSIST(algobj != NULL && secretobj != NULL);
+
+ /*
+ * Create the key name.
+ */
+ dns_name_init(&keyname, NULL);
+ isc_buffer_constinit(&keynamesrc, keyid, strlen(keyid));
+ isc_buffer_add(&keynamesrc, strlen(keyid));
+ isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata));
+ ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname,
+ DNS_NAME_DOWNCASE, &keynamebuf);
+ if (ret != ISC_R_SUCCESS) {
+ goto failure;
+ }
+
+ /*
+ * Create the algorithm.
+ */
+ algstr = cfg_obj_asstring(algobj);
+ if (named_config_getkeyalgorithm(algstr, &alg, &bits) !=
+ ISC_R_SUCCESS)
+ {
+ cfg_obj_log(algobj, named_g_lctx, ISC_LOG_ERROR,
+ "key '%s': has a "
+ "unsupported algorithm '%s'",
+ keyid, algstr);
+ ret = DNS_R_BADALG;
+ goto failure;
+ }
+
+ secretstr = cfg_obj_asstring(secretobj);
+ secretalloc = secretlen = strlen(secretstr) * 3 / 4;
+ secret = isc_mem_get(mctx, secretlen);
+ isc_buffer_init(&secretbuf, secret, secretlen);
+ ret = isc_base64_decodestring(secretstr, &secretbuf);
+ if (ret != ISC_R_SUCCESS) {
+ goto failure;
+ }
+ secretlen = isc_buffer_usedlength(&secretbuf);
+
+ isc_stdtime_get(&now);
+ ret = dns_tsigkey_create(&keyname, alg, secret, secretlen,
+ false, NULL, now, now, mctx, ring,
+ &tsigkey);
+ isc_mem_put(mctx, secret, secretalloc);
+ secret = NULL;
+ if (ret != ISC_R_SUCCESS) {
+ goto failure;
+ }
+ /*
+ * Set digest bits.
+ */
+ dst_key_setbits(tsigkey->key, bits);
+ dns_tsigkey_detach(&tsigkey);
+ }
+
+ return (ISC_R_SUCCESS);
+
+failure:
+ cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
+ "configuring key '%s': %s", keyid, isc_result_totext(ret));
+
+ if (secret != NULL) {
+ isc_mem_put(mctx, secret, secretalloc);
+ }
+ return (ret);
+}
+
+isc_result_t
+named_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *keylist;
+ dns_tsig_keyring_t *ring = NULL;
+ isc_result_t result;
+ int i;
+
+ REQUIRE(ringp != NULL && *ringp == NULL);
+
+ i = 0;
+ if (config != NULL) {
+ maps[i++] = config;
+ }
+ if (vconfig != NULL) {
+ maps[i++] = cfg_tuple_get(vconfig, "options");
+ }
+ maps[i] = NULL;
+
+ result = dns_tsigkeyring_create(mctx, &ring);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ for (i = 0;; i++) {
+ if (maps[i] == NULL) {
+ break;
+ }
+ keylist = NULL;
+ result = cfg_map_get(maps[i], "key", &keylist);
+ if (result != ISC_R_SUCCESS) {
+ continue;
+ }
+ result = add_initial_keys(keylist, ring, mctx);
+ if (result != ISC_R_SUCCESS) {
+ goto failure;
+ }
+ }
+
+ *ringp = ring;
+ return (ISC_R_SUCCESS);
+
+failure:
+ dns_tsigkeyring_detach(&ring);
+ return (result);
+}
diff --git a/bin/named/xsl_p.h b/bin/named/xsl_p.h
new file mode 100644
index 0000000..5623534
--- /dev/null
+++ b/bin/named/xsl_p.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+extern const char xslmsg[];
diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c
new file mode 100644
index 0000000..44c2242
--- /dev/null
+++ b/bin/named/zoneconf.c
@@ -0,0 +1,2114 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/buffer.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/stats.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/db.h>
+#include <dns/fixedname.h>
+#include <dns/ipkeylist.h>
+#include <dns/journal.h>
+#include <dns/kasp.h>
+#include <dns/log.h>
+#include <dns/masterdump.h>
+#include <dns/name.h>
+#include <dns/nsec3.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/sdlz.h>
+#include <dns/ssu.h>
+#include <dns/stats.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+
+#include <ns/client.h>
+
+#include <named/config.h>
+#include <named/globals.h>
+#include <named/log.h>
+#include <named/server.h>
+#include <named/zoneconf.h>
+
+/* ACLs associated with zone */
+typedef enum {
+ allow_notify,
+ allow_query,
+ allow_query_on,
+ allow_transfer,
+ allow_update,
+ allow_update_forwarding
+} acl_type_t;
+
+#define RETERR(x) \
+ do { \
+ isc_result_t _r = (x); \
+ if (_r != ISC_R_SUCCESS) \
+ return ((_r)); \
+ } while (0)
+
+#define CHECK(x) \
+ do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+/*%
+ * Convenience function for configuring a single zone ACL.
+ */
+static isc_result_t
+configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
+ const cfg_obj_t *config, acl_type_t acltype,
+ cfg_aclconfctx_t *actx, dns_zone_t *zone,
+ void (*setzacl)(dns_zone_t *, dns_acl_t *),
+ void (*clearzacl)(dns_zone_t *)) {
+ isc_result_t result;
+ const cfg_obj_t *maps[5] = { NULL, NULL, NULL, NULL, NULL };
+ const cfg_obj_t *aclobj = NULL;
+ int i = 0;
+ dns_acl_t **aclp = NULL, *acl = NULL;
+ const char *aclname;
+ dns_view_t *view;
+
+ view = dns_zone_getview(zone);
+
+ switch (acltype) {
+ case allow_notify:
+ if (view != NULL) {
+ aclp = &view->notifyacl;
+ }
+ aclname = "allow-notify";
+ break;
+ case allow_query:
+ if (view != NULL) {
+ aclp = &view->queryacl;
+ }
+ aclname = "allow-query";
+ break;
+ case allow_query_on:
+ if (view != NULL) {
+ aclp = &view->queryonacl;
+ }
+ aclname = "allow-query-on";
+ break;
+ case allow_transfer:
+ if (view != NULL) {
+ aclp = &view->transferacl;
+ }
+ aclname = "allow-transfer";
+ break;
+ case allow_update:
+ if (view != NULL) {
+ aclp = &view->updateacl;
+ }
+ aclname = "allow-update";
+ break;
+ case allow_update_forwarding:
+ if (view != NULL) {
+ aclp = &view->upfwdacl;
+ }
+ aclname = "allow-update-forwarding";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ /* First check to see if ACL is defined within the zone */
+ if (zconfig != NULL) {
+ maps[0] = cfg_tuple_get(zconfig, "options");
+ (void)named_config_get(maps, aclname, &aclobj);
+ if (aclobj != NULL) {
+ aclp = NULL;
+ goto parse_acl;
+ }
+ }
+
+ /* Failing that, see if there's a default ACL already in the view */
+ if (aclp != NULL && *aclp != NULL) {
+ (*setzacl)(zone, *aclp);
+ return (ISC_R_SUCCESS);
+ }
+
+ /* Check for default ACLs that haven't been parsed yet */
+ if (vconfig != NULL) {
+ const cfg_obj_t *options = cfg_tuple_get(vconfig, "options");
+ if (options != NULL) {
+ maps[i++] = options;
+ }
+ }
+ if (config != NULL) {
+ const cfg_obj_t *options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL) {
+ maps[i++] = options;
+ }
+ }
+ maps[i++] = named_g_defaults;
+ maps[i] = NULL;
+
+ (void)named_config_get(maps, aclname, &aclobj);
+ if (aclobj == NULL) {
+ (*clearzacl)(zone);
+ return (ISC_R_SUCCESS);
+ }
+
+parse_acl:
+ result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx,
+ named_g_mctx, 0, &acl);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ (*setzacl)(zone, acl);
+
+ /* Set the view default now */
+ if (aclp != NULL) {
+ dns_acl_attach(acl, aclp);
+ }
+
+ dns_acl_detach(&acl);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Parse the zone update-policy statement.
+ */
+static isc_result_t
+configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone,
+ const char *zname) {
+ const cfg_obj_t *updatepolicy = NULL;
+ const cfg_listelt_t *element, *element2;
+ dns_ssutable_t *table = NULL;
+ isc_mem_t *mctx = dns_zone_getmctx(zone);
+ bool autoddns = false;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ (void)cfg_map_get(zconfig, "update-policy", &updatepolicy);
+
+ if (updatepolicy == NULL) {
+ dns_zone_setssutable(zone, NULL);
+ return (ISC_R_SUCCESS);
+ }
+
+ if (cfg_obj_isstring(updatepolicy) &&
+ strcmp("local", cfg_obj_asstring(updatepolicy)) == 0)
+ {
+ autoddns = true;
+ updatepolicy = NULL;
+ }
+
+ dns_ssutable_create(mctx, &table);
+
+ for (element = cfg_list_first(updatepolicy); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *stmt = cfg_listelt_value(element);
+ const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode");
+ const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
+ const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
+ const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
+ const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
+ const char *str;
+ bool grant = false;
+ bool usezone = false;
+ dns_ssumatchtype_t mtype = dns_ssumatchtype_name;
+ dns_fixedname_t fname, fident;
+ isc_buffer_t b;
+ dns_ssuruletype_t *types;
+ unsigned int i, n;
+
+ str = cfg_obj_asstring(mode);
+ if (strcasecmp(str, "grant") == 0) {
+ grant = true;
+ } else if (strcasecmp(str, "deny") == 0) {
+ grant = false;
+ } else {
+ UNREACHABLE();
+ }
+
+ str = cfg_obj_asstring(matchtype);
+ CHECK(dns_ssu_mtypefromstring(str, &mtype));
+ if (mtype == dns_ssumatchtype_subdomain &&
+ strcasecmp(str, "zonesub") == 0)
+ {
+ usezone = true;
+ }
+
+ dns_fixedname_init(&fident);
+ str = cfg_obj_asstring(identity);
+ isc_buffer_constinit(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ result = dns_name_fromtext(dns_fixedname_name(&fident), &b,
+ dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(identity, named_g_lctx, ISC_LOG_ERROR,
+ "'%s' is not a valid name", str);
+ goto cleanup;
+ }
+
+ dns_fixedname_init(&fname);
+ if (usezone) {
+ dns_name_copy(dns_zone_getorigin(zone),
+ dns_fixedname_name(&fname));
+ } else {
+ str = cfg_obj_asstring(dname);
+ isc_buffer_constinit(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ result = dns_name_fromtext(dns_fixedname_name(&fname),
+ &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(identity, named_g_lctx,
+ ISC_LOG_ERROR,
+ "'%s' is not a valid name", str);
+ goto cleanup;
+ }
+ }
+
+ n = named_config_listcount(typelist);
+ if (n == 0) {
+ types = NULL;
+ } else {
+ types = isc_mem_get(mctx, n * sizeof(*types));
+ }
+
+ i = 0;
+ for (element2 = cfg_list_first(typelist); element2 != NULL;
+ element2 = cfg_list_next(element2))
+ {
+ const cfg_obj_t *typeobj;
+ const char *bracket;
+ isc_textregion_t r;
+ unsigned long max = 0;
+
+ INSIST(i < n);
+
+ typeobj = cfg_listelt_value(element2);
+ str = cfg_obj_asstring(typeobj);
+ DE_CONST(str, r.base);
+
+ bracket = strchr(str, '(' /*)*/);
+ if (bracket != NULL) {
+ char *end = NULL;
+ r.length = bracket - str;
+ max = strtoul(bracket + 1, &end, 10);
+ if (max > 0xffff || end[0] != /*(*/ ')' ||
+ end[1] != 0)
+ {
+ cfg_obj_log(identity, named_g_lctx,
+ ISC_LOG_ERROR,
+ "'%s' is not a valid count",
+ bracket);
+ isc_mem_put(mctx, types,
+ n * sizeof(*types));
+ goto cleanup;
+ }
+ } else {
+ r.length = strlen(str);
+ }
+ types[i].max = max;
+
+ result = dns_rdatatype_fromtext(&types[i++].type, &r);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(identity, named_g_lctx,
+ ISC_LOG_ERROR,
+ "'%.*s' is not a valid type",
+ (int)r.length, str);
+ isc_mem_put(mctx, types, n * sizeof(*types));
+ goto cleanup;
+ }
+ }
+ INSIST(i == n);
+
+ dns_ssutable_addrule(table, grant, dns_fixedname_name(&fident),
+ mtype, dns_fixedname_name(&fname), n,
+ types);
+ if (types != NULL) {
+ isc_mem_put(mctx, types, n * sizeof(*types));
+ }
+ }
+
+ /*
+ * If "update-policy local;" and a session key exists,
+ * then use the default policy, which is equivalent to:
+ * update-policy { grant <session-keyname> zonesub any; };
+ */
+ if (autoddns) {
+ dns_ssuruletype_t any = { dns_rdatatype_any, 0 };
+
+ if (named_g_server->session_keyname == NULL) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed to enable auto DDNS policy "
+ "for zone %s: session key not found",
+ zname);
+ result = ISC_R_NOTFOUND;
+ goto cleanup;
+ }
+
+ dns_ssutable_addrule(table, true,
+ named_g_server->session_keyname,
+ dns_ssumatchtype_local,
+ dns_zone_getorigin(zone), 1, &any);
+ }
+
+ dns_zone_setssutable(zone, table);
+
+cleanup:
+ dns_ssutable_detach(&table);
+ return (result);
+}
+
+/*
+ * This is the TTL used for internally generated RRsets for static-stub zones.
+ * The value doesn't matter because the mapping is static, but needs to be
+ * defined for the sake of implementation.
+ */
+#define STATICSTUB_SERVER_TTL 86400
+
+/*%
+ * Configure an apex NS with glues for a static-stub zone.
+ * For example, for the zone named "example.com", the following RRs will be
+ * added to the zone DB:
+ * example.com. NS example.com.
+ * example.com. A 192.0.2.1
+ * example.com. AAAA 2001:db8::1
+ */
+static isc_result_t
+configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone,
+ dns_rdatalist_t *rdatalist_ns,
+ dns_rdatalist_t *rdatalist_a,
+ dns_rdatalist_t *rdatalist_aaaa) {
+ const cfg_listelt_t *element;
+ isc_mem_t *mctx = dns_zone_getmctx(zone);
+ isc_region_t region, sregion;
+ dns_rdata_t *rdata;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ for (element = cfg_list_first(zconfig); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const isc_sockaddr_t *sa;
+ isc_netaddr_t na;
+ const cfg_obj_t *address = cfg_listelt_value(element);
+ dns_rdatalist_t *rdatalist;
+
+ sa = cfg_obj_assockaddr(address);
+ if (isc_sockaddr_getport(sa) != 0) {
+ cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
+ "port is not configurable for "
+ "static stub server-addresses");
+ return (ISC_R_FAILURE);
+ }
+ isc_netaddr_fromsockaddr(&na, sa);
+ if (isc_netaddr_getzone(&na) != 0) {
+ cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
+ "scoped address is not allowed "
+ "for static stub "
+ "server-addresses");
+ return (ISC_R_FAILURE);
+ }
+
+ switch (na.family) {
+ case AF_INET:
+ region.length = sizeof(na.type.in);
+ rdatalist = rdatalist_a;
+ break;
+ default:
+ INSIST(na.family == AF_INET6);
+ region.length = sizeof(na.type.in6);
+ rdatalist = rdatalist_aaaa;
+ break;
+ }
+
+ rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length);
+ region.base = (unsigned char *)(rdata + 1);
+ memmove(region.base, &na.type, region.length);
+ dns_rdata_init(rdata);
+ dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
+ rdatalist->type, &region);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ }
+
+ /*
+ * If no address is specified (unlikely in this context, but possible),
+ * there's nothing to do anymore.
+ */
+ if (ISC_LIST_EMPTY(rdatalist_a->rdata) &&
+ ISC_LIST_EMPTY(rdatalist_aaaa->rdata))
+ {
+ return (ISC_R_SUCCESS);
+ }
+
+ /* Add to the list an apex NS with the ns name being the origin name */
+ dns_name_toregion(dns_zone_getorigin(zone), &sregion);
+ rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
+ region.length = sregion.length;
+ region.base = (unsigned char *)(rdata + 1);
+ memmove(region.base, sregion.base, region.length);
+ dns_rdata_init(rdata);
+ dns_rdata_fromregion(rdata, dns_zone_getclass(zone), dns_rdatatype_ns,
+ &region);
+ ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link);
+
+ return (result);
+}
+
+/*%
+ * Configure an apex NS with an out-of-zone NS names for a static-stub zone.
+ * For example, for the zone named "example.com", something like the following
+ * RRs will be added to the zone DB:
+ * example.com. NS ns.example.net.
+ */
+static isc_result_t
+configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone,
+ dns_rdatalist_t *rdatalist,
+ const char *zname) {
+ const cfg_listelt_t *element;
+ isc_mem_t *mctx = dns_zone_getmctx(zone);
+ dns_rdata_t *rdata;
+ isc_region_t sregion, region;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ for (element = cfg_list_first(zconfig); element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *obj;
+ const char *str;
+ dns_fixedname_t fixed_name;
+ dns_name_t *nsname;
+ isc_buffer_t b;
+
+ obj = cfg_listelt_value(element);
+ str = cfg_obj_asstring(obj);
+
+ nsname = dns_fixedname_initname(&fixed_name);
+
+ isc_buffer_constinit(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
+ "server-name '%s' is not a valid "
+ "name",
+ str);
+ return (result);
+ }
+ if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) {
+ cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
+ "server-name '%s' must not be a "
+ "subdomain of zone name '%s'",
+ str, zname);
+ return (ISC_R_FAILURE);
+ }
+
+ dns_name_toregion(nsname, &sregion);
+ rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
+ region.length = sregion.length;
+ region.base = (unsigned char *)(rdata + 1);
+ memmove(region.base, sregion.base, region.length);
+ dns_rdata_init(rdata);
+ dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
+ dns_rdatatype_ns, &region);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ }
+
+ return (result);
+}
+
+/*%
+ * Configure static-stub zone.
+ */
+static isc_result_t
+configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone,
+ const char *zname, const char *dbtype) {
+ int i = 0;
+ const cfg_obj_t *obj;
+ isc_mem_t *mctx = dns_zone_getmctx(zone);
+ dns_db_t *db = NULL;
+ dns_dbversion_t *dbversion = NULL;
+ dns_dbnode_t *apexnode = NULL;
+ dns_name_t apexname;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa;
+ dns_rdatalist_t *rdatalists[] = { &rdatalist_ns, &rdatalist_a,
+ &rdatalist_aaaa, NULL };
+ dns_rdata_t *rdata;
+ isc_region_t region;
+
+ /* Create the DB beforehand */
+ RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone),
+ dns_dbtype_stub, dns_zone_getclass(zone), 0, NULL,
+ &db));
+
+ dns_rdataset_init(&rdataset);
+
+ dns_rdatalist_init(&rdatalist_ns);
+ rdatalist_ns.rdclass = dns_zone_getclass(zone);
+ rdatalist_ns.type = dns_rdatatype_ns;
+ rdatalist_ns.ttl = STATICSTUB_SERVER_TTL;
+
+ dns_rdatalist_init(&rdatalist_a);
+ rdatalist_a.rdclass = dns_zone_getclass(zone);
+ rdatalist_a.type = dns_rdatatype_a;
+ rdatalist_a.ttl = STATICSTUB_SERVER_TTL;
+
+ dns_rdatalist_init(&rdatalist_aaaa);
+ rdatalist_aaaa.rdclass = dns_zone_getclass(zone);
+ rdatalist_aaaa.type = dns_rdatatype_aaaa;
+ rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL;
+
+ /* Prepare zone RRs from the configuration */
+ obj = NULL;
+ result = cfg_map_get(zconfig, "server-addresses", &obj);
+ if (result == ISC_R_SUCCESS) {
+ INSIST(obj != NULL);
+ CHECK(configure_staticstub_serveraddrs(obj, zone, &rdatalist_ns,
+ &rdatalist_a,
+ &rdatalist_aaaa));
+ }
+
+ obj = NULL;
+ result = cfg_map_get(zconfig, "server-names", &obj);
+ if (result == ISC_R_SUCCESS) {
+ INSIST(obj != NULL);
+ CHECK(configure_staticstub_servernames(obj, zone, &rdatalist_ns,
+ zname));
+ }
+
+ /*
+ * Sanity check: there should be at least one NS RR at the zone apex
+ * to trigger delegation.
+ */
+ if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "No NS record is configured for a "
+ "static-stub zone '%s'",
+ zname);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ /*
+ * Now add NS and glue A/AAAA RRsets to the zone DB.
+ * First open a new version for the add operation and get a pointer
+ * to the apex node (all RRs are of the apex name).
+ */
+ CHECK(dns_db_newversion(db, &dbversion));
+
+ dns_name_init(&apexname, NULL);
+ dns_name_clone(dns_zone_getorigin(zone), &apexname);
+ CHECK(dns_db_findnode(db, &apexname, false, &apexnode));
+
+ /* Add NS RRset */
+ RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset) ==
+ ISC_R_SUCCESS);
+ CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 0,
+ NULL));
+ dns_rdataset_disassociate(&rdataset);
+
+ /* Add glue A RRset, if any */
+ if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) {
+ RUNTIME_CHECK(
+ dns_rdatalist_tordataset(&rdatalist_a, &rdataset) ==
+ ISC_R_SUCCESS);
+ CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset,
+ 0, NULL));
+ dns_rdataset_disassociate(&rdataset);
+ }
+
+ /* Add glue AAAA RRset, if any */
+ if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) {
+ RUNTIME_CHECK(
+ dns_rdatalist_tordataset(&rdatalist_aaaa, &rdataset) ==
+ ISC_R_SUCCESS);
+ CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset,
+ 0, NULL));
+ dns_rdataset_disassociate(&rdataset);
+ }
+
+ dns_db_closeversion(db, &dbversion, true);
+ dns_zone_setdb(zone, db);
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (dns_rdataset_isassociated(&rdataset)) {
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (apexnode != NULL) {
+ dns_db_detachnode(db, &apexnode);
+ }
+ if (dbversion != NULL) {
+ dns_db_closeversion(db, &dbversion, false);
+ }
+ if (db != NULL) {
+ dns_db_detach(&db);
+ }
+ for (i = 0; rdatalists[i] != NULL; i++) {
+ while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) {
+ ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link);
+ dns_rdata_toregion(rdata, &region);
+ isc_mem_put(mctx, rdata,
+ sizeof(*rdata) + region.length);
+ }
+ }
+
+ INSIST(dbversion == NULL);
+
+ return (result);
+}
+
+/*%
+ * Convert a config file zone type into a server zone type.
+ */
+static dns_zonetype_t
+zonetype_fromconfig(const cfg_obj_t *map) {
+ const cfg_obj_t *obj = NULL;
+ isc_result_t result;
+
+ result = cfg_map_get(map, "type", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ return (named_config_getzonetype(obj));
+}
+
+/*%
+ * Helper function for strtoargv(). Pardon the gratuitous recursion.
+ */
+static isc_result_t
+strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp,
+ unsigned int n) {
+ isc_result_t result;
+
+ /* Discard leading whitespace. */
+ while (*s == ' ' || *s == '\t') {
+ s++;
+ }
+
+ if (*s == '\0') {
+ /* We have reached the end of the string. */
+ *argcp = n;
+ *argvp = isc_mem_get(mctx, n * sizeof(char *));
+ } else {
+ char *p = s;
+ while (*p != ' ' && *p != '\t' && *p != '\0') {
+ p++;
+ }
+ if (*p != '\0') {
+ *p++ = '\0';
+ }
+
+ result = strtoargvsub(mctx, p, argcp, argvp, n + 1);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ (*argvp)[n] = s;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Tokenize the string "s" into whitespace-separated words,
+ * return the number of words in '*argcp' and an array
+ * of pointers to the words in '*argvp'. The caller
+ * must free the array using isc_mem_put(). The string
+ * is modified in-place.
+ */
+static isc_result_t
+strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) {
+ return (strtoargvsub(mctx, s, argcp, argvp, 0));
+}
+
+static const char *const primary_synonyms[] = { "primary", "master", NULL };
+
+static const char *const secondary_synonyms[] = { "secondary", "slave", NULL };
+
+static void
+checknames(dns_zonetype_t ztype, const cfg_obj_t **maps,
+ const cfg_obj_t **objp) {
+ isc_result_t result;
+
+ switch (ztype) {
+ case dns_zone_secondary:
+ case dns_zone_mirror:
+ result = named_checknames_get(maps, secondary_synonyms, objp);
+ break;
+ case dns_zone_primary:
+ result = named_checknames_get(maps, primary_synonyms, objp);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ INSIST(result == ISC_R_SUCCESS && objp != NULL && *objp != NULL);
+}
+
+/*
+ * Callback to see if a non-recursive query coming from 'srcaddr' to
+ * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
+ * delivered to 'myview'.
+ *
+ * We run this unlocked as both the view list and the interface list
+ * are updated when the appropriate task has exclusivity.
+ */
+static bool
+isself(dns_view_t *myview, dns_tsigkey_t *mykey, const isc_sockaddr_t *srcaddr,
+ const isc_sockaddr_t *dstaddr, dns_rdataclass_t rdclass, void *arg) {
+ dns_aclenv_t *env = NULL;
+ dns_view_t *view = NULL;
+ dns_tsigkey_t *key = NULL;
+ isc_netaddr_t netsrc;
+ isc_netaddr_t netdst;
+
+ UNUSED(arg);
+
+ /* interfacemgr can be destroyed only in exclusive mode. */
+ if (named_g_server->interfacemgr == NULL) {
+ return (true);
+ }
+
+ if (!ns_interfacemgr_listeningon(named_g_server->interfacemgr, dstaddr))
+ {
+ return (false);
+ }
+
+ isc_netaddr_fromsockaddr(&netsrc, srcaddr);
+ isc_netaddr_fromsockaddr(&netdst, dstaddr);
+ env = ns_interfacemgr_getaclenv(named_g_server->interfacemgr);
+
+ for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ const dns_name_t *tsig = NULL;
+
+ if (view->matchrecursiveonly) {
+ continue;
+ }
+
+ if (rdclass != view->rdclass) {
+ continue;
+ }
+
+ if (mykey != NULL) {
+ bool match;
+ isc_result_t result;
+
+ result = dns_view_gettsig(view, &mykey->name, &key);
+ if (result != ISC_R_SUCCESS) {
+ continue;
+ }
+ match = dst_key_compare(mykey->key, key->key);
+ dns_tsigkey_detach(&key);
+ if (!match) {
+ continue;
+ }
+ tsig = dns_tsigkey_identity(mykey);
+ }
+
+ if (dns_acl_allowed(&netsrc, tsig, view->matchclients, env) &&
+ dns_acl_allowed(&netdst, tsig, view->matchdestinations,
+ env))
+ {
+ break;
+ }
+ }
+ return (view == myview);
+}
+
+/*%
+ * For mirror zones, change "notify yes;" to "notify explicit;", informing the
+ * user only if "notify" was explicitly configured rather than inherited from
+ * default configuration.
+ */
+static dns_notifytype_t
+process_notifytype(dns_notifytype_t ntype, dns_zonetype_t ztype,
+ const char *zname, const cfg_obj_t **maps) {
+ const cfg_obj_t *obj = NULL;
+
+ /*
+ * Return the original setting if this is not a mirror zone or if the
+ * zone is configured with something else than "notify yes;".
+ */
+ if (ztype != dns_zone_mirror || ntype != dns_notifytype_yes) {
+ return (ntype);
+ }
+
+ /*
+ * Only log a message if "notify" was set in the configuration
+ * hierarchy supplied in 'maps'.
+ */
+ if (named_config_get(maps, "notify", &obj) == ISC_R_SUCCESS) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO,
+ "'notify explicit;' will be used for mirror zone "
+ "'%s'",
+ zname);
+ }
+
+ return (dns_notifytype_explicit);
+}
+
+isc_result_t
+named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
+ dns_kasplist_t *kasplist, dns_zone_t *zone,
+ dns_zone_t *raw) {
+ isc_result_t result;
+ const char *zname;
+ dns_rdataclass_t zclass;
+ dns_rdataclass_t vclass;
+ const cfg_obj_t *maps[5];
+ const cfg_obj_t *nodefault[4];
+ const cfg_obj_t *zoptions = NULL;
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *obj;
+ const char *filename = NULL;
+ const char *kaspname = NULL;
+ const char *dupcheck;
+ dns_notifytype_t notifytype = dns_notifytype_yes;
+ uint32_t count;
+ unsigned int dbargc;
+ char **dbargv;
+ static char default_dbtype[] = "rbt";
+ static char dlz_dbtype[] = "dlz";
+ char *cpval = default_dbtype;
+ isc_mem_t *mctx = dns_zone_getmctx(zone);
+ dns_dialuptype_t dialup = dns_dialuptype_no;
+ dns_zonetype_t ztype;
+ int i;
+ int32_t journal_size;
+ bool multi;
+ bool alt;
+ dns_view_t *view = NULL;
+ dns_kasp_t *kasp = NULL;
+ bool check = false, fail = false;
+ bool warn = false, ignore = false;
+ bool ixfrdiff;
+ bool use_kasp = false;
+ dns_masterformat_t masterformat;
+ const dns_master_style_t *masterstyle = &dns_master_style_default;
+ isc_stats_t *zoneqrystats;
+ dns_stats_t *rcvquerystats;
+ dns_stats_t *dnssecsignstats;
+ dns_zonestat_level_t statlevel = dns_zonestat_none;
+ int seconds;
+ dns_ttl_t maxttl = 0; /* unlimited */
+ dns_zone_t *mayberaw = (raw != NULL) ? raw : zone;
+ bool transferinsecs = ns_server_getoption(named_g_server->sctx,
+ NS_SERVER_TRANSFERINSECS);
+
+ i = 0;
+ if (zconfig != NULL) {
+ zoptions = cfg_tuple_get(zconfig, "options");
+ nodefault[i] = maps[i] = zoptions;
+ i++;
+ }
+ if (vconfig != NULL) {
+ nodefault[i] = maps[i] = cfg_tuple_get(vconfig, "options");
+ i++;
+ }
+ if (config != NULL) {
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL) {
+ nodefault[i] = maps[i] = options;
+ i++;
+ }
+ }
+ nodefault[i] = NULL;
+ maps[i++] = named_g_defaults;
+ maps[i] = NULL;
+
+ if (vconfig != NULL) {
+ CHECK(named_config_getclass(cfg_tuple_get(vconfig, "class"),
+ dns_rdataclass_in, &vclass));
+ } else {
+ vclass = dns_rdataclass_in;
+ }
+
+ /*
+ * Configure values common to all zone types.
+ */
+
+ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+
+ CHECK(named_config_getclass(cfg_tuple_get(zconfig, "class"), vclass,
+ &zclass));
+ dns_zone_setclass(zone, zclass);
+ if (raw != NULL) {
+ dns_zone_setclass(raw, zclass);
+ }
+
+ ztype = zonetype_fromconfig(zoptions);
+ if (raw != NULL) {
+ dns_zone_settype(raw, ztype);
+ dns_zone_settype(zone, dns_zone_primary);
+ } else {
+ dns_zone_settype(zone, ztype);
+ }
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "database", &obj);
+ if (result == ISC_R_SUCCESS) {
+ cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
+ }
+ if (cpval == NULL) {
+ CHECK(ISC_R_NOMEMORY);
+ }
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "dlz", &obj);
+ if (result == ISC_R_SUCCESS) {
+ const char *dlzname = cfg_obj_asstring(obj);
+ size_t len;
+
+ if (cpval != default_dbtype) {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "zone '%s': both 'database' and 'dlz' "
+ "specified",
+ zname);
+ CHECK(ISC_R_FAILURE);
+ }
+
+ len = strlen(dlzname) + 5;
+ cpval = isc_mem_allocate(mctx, len);
+ snprintf(cpval, len, "dlz %s", dlzname);
+ }
+
+ result = strtoargv(mctx, cpval, &dbargc, &dbargv);
+ if (result != ISC_R_SUCCESS && cpval != default_dbtype) {
+ isc_mem_free(mctx, cpval);
+ CHECK(result);
+ }
+
+ /*
+ * ANSI C is strange here. There is no logical reason why (char **)
+ * cannot be promoted automatically to (const char * const *) by the
+ * compiler w/o generating a warning.
+ */
+ dns_zone_setdbtype(zone, dbargc, (const char *const *)dbargv);
+ isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv));
+ if (cpval != default_dbtype && cpval != dlz_dbtype) {
+ isc_mem_free(mctx, cpval);
+ }
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "file", &obj);
+ if (result == ISC_R_SUCCESS) {
+ filename = cfg_obj_asstring(obj);
+ }
+
+ /*
+ * Unless we're using some alternative database, a primary zone
+ * will be needing a master file.
+ */
+ if (ztype == dns_zone_primary && cpval == default_dbtype &&
+ filename == NULL)
+ {
+ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "zone '%s': 'file' not specified", zname);
+ CHECK(ISC_R_FAILURE);
+ }
+
+ if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) {
+ masterformat = dns_masterformat_raw;
+ } else {
+ masterformat = dns_masterformat_text;
+ }
+ obj = NULL;
+ result = named_config_get(maps, "masterfile-format", &obj);
+ if (result == ISC_R_SUCCESS) {
+ const char *masterformatstr = cfg_obj_asstring(obj);
+
+ if (strcasecmp(masterformatstr, "text") == 0) {
+ masterformat = dns_masterformat_text;
+ } else if (strcasecmp(masterformatstr, "raw") == 0) {
+ masterformat = dns_masterformat_raw;
+ } else {
+ UNREACHABLE();
+ }
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "masterfile-style", &obj);
+ if (result == ISC_R_SUCCESS) {
+ const char *masterstylestr = cfg_obj_asstring(obj);
+
+ if (masterformat != dns_masterformat_text) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
+ "zone '%s': 'masterfile-style' "
+ "can only be used with "
+ "'masterfile-format text'",
+ zname);
+ CHECK(ISC_R_FAILURE);
+ }
+
+ if (strcasecmp(masterstylestr, "full") == 0) {
+ masterstyle = &dns_master_style_full;
+ } else if (strcasecmp(masterstylestr, "relative") == 0) {
+ masterstyle = &dns_master_style_default;
+ } else {
+ UNREACHABLE();
+ }
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "max-records", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setmaxrecords(mayberaw, cfg_obj_asuint32(obj));
+ if (zone != mayberaw) {
+ dns_zone_setmaxrecords(zone, 0);
+ }
+
+ if (raw != NULL && filename != NULL) {
+#define SIGNED ".signed"
+ size_t signedlen = strlen(filename) + sizeof(SIGNED);
+ char *signedname;
+
+ CHECK(dns_zone_setfile(raw, filename, masterformat,
+ masterstyle));
+ signedname = isc_mem_get(mctx, signedlen);
+
+ (void)snprintf(signedname, signedlen, "%s" SIGNED, filename);
+ result = dns_zone_setfile(zone, signedname,
+ dns_masterformat_raw, NULL);
+ isc_mem_put(mctx, signedname, signedlen);
+ CHECK(result);
+ } else {
+ CHECK(dns_zone_setfile(zone, filename, masterformat,
+ masterstyle));
+ }
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "journal", &obj);
+ if (result == ISC_R_SUCCESS) {
+ CHECK(dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj)));
+ }
+
+ /*
+ * Notify messages are processed by the raw zone if it exists.
+ */
+ if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) {
+ CHECK(configure_zone_acl(zconfig, vconfig, config, allow_notify,
+ ac, mayberaw, dns_zone_setnotifyacl,
+ dns_zone_clearnotifyacl));
+ }
+
+ /*
+ * XXXAG This probably does not make sense for stubs.
+ */
+ CHECK(configure_zone_acl(zconfig, vconfig, config, allow_query, ac,
+ zone, dns_zone_setqueryacl,
+ dns_zone_clearqueryacl));
+
+ CHECK(configure_zone_acl(zconfig, vconfig, config, allow_query_on, ac,
+ zone, dns_zone_setqueryonacl,
+ dns_zone_clearqueryonacl));
+
+ obj = NULL;
+ result = named_config_get(maps, "dialup", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ dialup = dns_dialuptype_yes;
+ } else {
+ dialup = dns_dialuptype_no;
+ }
+ } else {
+ const char *dialupstr = cfg_obj_asstring(obj);
+ if (strcasecmp(dialupstr, "notify") == 0) {
+ dialup = dns_dialuptype_notify;
+ } else if (strcasecmp(dialupstr, "notify-passive") == 0) {
+ dialup = dns_dialuptype_notifypassive;
+ } else if (strcasecmp(dialupstr, "refresh") == 0) {
+ dialup = dns_dialuptype_refresh;
+ } else if (strcasecmp(dialupstr, "passive") == 0) {
+ dialup = dns_dialuptype_passive;
+ } else {
+ UNREACHABLE();
+ }
+ }
+ if (raw != NULL) {
+ dns_zone_setdialup(raw, dialup);
+ }
+ dns_zone_setdialup(zone, dialup);
+
+ obj = NULL;
+ result = named_config_get(maps, "zone-statistics", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ statlevel = dns_zonestat_full;
+ } else {
+ statlevel = dns_zonestat_none;
+ }
+ } else {
+ const char *levelstr = cfg_obj_asstring(obj);
+ if (strcasecmp(levelstr, "full") == 0) {
+ statlevel = dns_zonestat_full;
+ } else if (strcasecmp(levelstr, "terse") == 0) {
+ statlevel = dns_zonestat_terse;
+ } else if (strcasecmp(levelstr, "none") == 0) {
+ statlevel = dns_zonestat_none;
+ } else {
+ UNREACHABLE();
+ }
+ }
+ dns_zone_setstatlevel(zone, statlevel);
+
+ zoneqrystats = NULL;
+ rcvquerystats = NULL;
+ dnssecsignstats = NULL;
+ if (statlevel == dns_zonestat_full) {
+ CHECK(isc_stats_create(mctx, &zoneqrystats,
+ ns_statscounter_max));
+ CHECK(dns_rdatatypestats_create(mctx, &rcvquerystats));
+ CHECK(dns_dnssecsignstats_create(mctx, &dnssecsignstats));
+ }
+ dns_zone_setrequeststats(zone, zoneqrystats);
+ dns_zone_setrcvquerystats(zone, rcvquerystats);
+ dns_zone_setdnssecsignstats(zone, dnssecsignstats);
+
+ if (zoneqrystats != NULL) {
+ isc_stats_detach(&zoneqrystats);
+ }
+
+ if (rcvquerystats != NULL) {
+ dns_stats_detach(&rcvquerystats);
+ }
+
+ if (dnssecsignstats != NULL) {
+ dns_stats_detach(&dnssecsignstats);
+ }
+
+ /*
+ * Configure authoritative zone functionality. This applies
+ * to primary servers (type "primary") and secondaries
+ * acting as primaries (type "secondary"), but not to stubs.
+ */
+ if (ztype != dns_zone_stub && ztype != dns_zone_staticstub &&
+ ztype != dns_zone_redirect)
+ {
+ obj = NULL;
+ result = named_config_get(maps, "dnssec-policy", &obj);
+ if (result == ISC_R_SUCCESS) {
+ kaspname = cfg_obj_asstring(obj);
+ if (strcmp(kaspname, "none") != 0) {
+ result = dns_kasplist_find(kasplist, kaspname,
+ &kasp);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(
+ obj, named_g_lctx,
+ ISC_LOG_ERROR,
+ "dnssec-policy '%s' not found ",
+ kaspname);
+ CHECK(result);
+ }
+ dns_zone_setkasp(zone, kasp);
+ use_kasp = true;
+ }
+ }
+ if (!use_kasp) {
+ dns_zone_setkasp(zone, NULL);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "notify", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ notifytype = dns_notifytype_yes;
+ } else {
+ notifytype = dns_notifytype_no;
+ }
+ } else {
+ const char *str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "explicit") == 0) {
+ notifytype = dns_notifytype_explicit;
+ } else if (strcasecmp(str, "master-only") == 0 ||
+ strcasecmp(str, "primary-only") == 0)
+ {
+ notifytype = dns_notifytype_masteronly;
+ } else {
+ UNREACHABLE();
+ }
+ }
+ notifytype = process_notifytype(notifytype, ztype, zname,
+ nodefault);
+ if (raw != NULL) {
+ dns_zone_setnotifytype(raw, dns_notifytype_no);
+ }
+ dns_zone_setnotifytype(zone, notifytype);
+
+ obj = NULL;
+ result = named_config_get(maps, "also-notify", &obj);
+ if (result == ISC_R_SUCCESS &&
+ (notifytype == dns_notifytype_yes ||
+ notifytype == dns_notifytype_explicit ||
+ (notifytype == dns_notifytype_masteronly &&
+ ztype == dns_zone_primary)))
+ {
+ dns_ipkeylist_t ipkl;
+ dns_ipkeylist_init(&ipkl);
+
+ CHECK(named_config_getipandkeylist(config, "primaries",
+ obj, mctx, &ipkl));
+ dns_zone_setalsonotify(zone, ipkl.addrs, ipkl.keys,
+ ipkl.tlss, ipkl.count);
+ dns_ipkeylist_clear(mctx, &ipkl);
+ } else {
+ dns_zone_setalsonotify(zone, NULL, NULL, NULL, 0);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "parental-source", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+
+ CHECK(dns_zone_setparentalsrc4(zone, cfg_obj_assockaddr(obj)));
+ named_add_reserved_dispatch(named_g_server,
+ cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "parental-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+
+ CHECK(dns_zone_setparentalsrc6(zone, cfg_obj_assockaddr(obj)));
+ named_add_reserved_dispatch(named_g_server,
+ cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "notify-source", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ CHECK(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
+ named_add_reserved_dispatch(named_g_server,
+ cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "notify-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ CHECK(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
+ named_add_reserved_dispatch(named_g_server,
+ cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "notify-to-soa", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA,
+ cfg_obj_asboolean(obj));
+
+ dns_zone_setisself(zone, isself, NULL);
+
+ CHECK(configure_zone_acl(
+ zconfig, vconfig, config, allow_transfer, ac, zone,
+ dns_zone_setxfracl, dns_zone_clearxfracl));
+
+ obj = NULL;
+ result = named_config_get(maps, "max-transfer-time-out", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setmaxxfrout(
+ zone, transferinsecs ? cfg_obj_asuint32(obj)
+ : cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = named_config_get(maps, "max-transfer-idle-out", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setidleout(zone, transferinsecs
+ ? cfg_obj_asuint32(obj)
+ : cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = named_config_get(maps, "max-journal-size", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (raw != NULL) {
+ dns_zone_setjournalsize(raw, -1);
+ }
+ dns_zone_setjournalsize(zone, -1);
+ if (cfg_obj_isstring(obj)) {
+ const char *str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "unlimited") == 0) {
+ journal_size = DNS_JOURNAL_SIZE_MAX;
+ } else {
+ INSIST(strcasecmp(str, "default") == 0);
+ journal_size = -1;
+ }
+ } else {
+ isc_resourcevalue_t value;
+ value = cfg_obj_asuint64(obj);
+ if (value > DNS_JOURNAL_SIZE_MAX) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
+ "'max-journal-size "
+ "%" PRId64 "' "
+ "is too large",
+ value);
+ CHECK(ISC_R_RANGE);
+ }
+ journal_size = (uint32_t)value;
+ }
+ if (raw != NULL) {
+ dns_zone_setjournalsize(raw, journal_size);
+ }
+ dns_zone_setjournalsize(zone, journal_size);
+
+ obj = NULL;
+ result = named_config_get(maps, "ixfr-from-differences", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (cfg_obj_isboolean(obj)) {
+ ixfrdiff = cfg_obj_asboolean(obj);
+ } else if ((strcasecmp(cfg_obj_asstring(obj), "primary") == 0 ||
+ strcasecmp(cfg_obj_asstring(obj), "master") == 0) &&
+ ztype == dns_zone_primary)
+ {
+ ixfrdiff = true;
+ } else if ((strcasecmp(cfg_obj_asstring(obj), "secondary") ==
+ 0 ||
+ strcasecmp(cfg_obj_asstring(obj), "slave") == 0) &&
+ ztype == dns_zone_secondary)
+ {
+ ixfrdiff = true;
+ } else {
+ ixfrdiff = false;
+ }
+ if (raw != NULL) {
+ dns_zone_setoption(raw, DNS_ZONEOPT_IXFRFROMDIFFS,
+ true);
+ dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS,
+ false);
+ } else {
+ dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS,
+ ixfrdiff);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "max-ixfr-ratio", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (cfg_obj_isstring(obj)) {
+ dns_zone_setixfrratio(zone, 0);
+ } else {
+ dns_zone_setixfrratio(zone, cfg_obj_aspercentage(obj));
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "request-expire", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setrequestexpire(zone, cfg_obj_asboolean(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "request-ixfr", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setrequestixfr(zone, cfg_obj_asboolean(obj));
+
+ obj = NULL;
+ checknames(ztype, maps, &obj);
+ INSIST(obj != NULL);
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ fail = false;
+ check = true;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ fail = check = true;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ fail = check = false;
+ } else {
+ UNREACHABLE();
+ }
+ if (raw != NULL) {
+ dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMES, check);
+ dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMESFAIL,
+ fail);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, false);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL,
+ false);
+ } else {
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL,
+ fail);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "notify-delay", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "check-sibling", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING,
+ cfg_obj_asboolean(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "check-spf", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ check = true;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ check = false;
+ } else {
+ UNREACHABLE();
+ }
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check);
+
+ obj = NULL;
+ result = named_config_get(maps, "zero-no-soa-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "nsec3-test-zone", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE,
+ cfg_obj_asboolean(obj));
+ } else if (ztype == dns_zone_redirect) {
+ dns_zone_setnotifytype(zone, dns_notifytype_no);
+
+ obj = NULL;
+ result = named_config_get(maps, "max-journal-size", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setjournalsize(zone, -1);
+ if (cfg_obj_isstring(obj)) {
+ const char *str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "unlimited") == 0) {
+ journal_size = DNS_JOURNAL_SIZE_MAX;
+ } else {
+ INSIST(strcasecmp(str, "default") == 0);
+ journal_size = -1;
+ }
+ } else {
+ isc_resourcevalue_t value;
+ value = cfg_obj_asuint64(obj);
+ if (value > DNS_JOURNAL_SIZE_MAX) {
+ cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
+ "'max-journal-size "
+ "%" PRId64 "' "
+ "is too large",
+ value);
+ CHECK(ISC_R_RANGE);
+ }
+ journal_size = (uint32_t)value;
+ }
+ dns_zone_setjournalsize(zone, journal_size);
+ }
+
+ if (use_kasp) {
+ maxttl = dns_kasp_zonemaxttl(dns_zone_getkasp(zone), false);
+ } else {
+ obj = NULL;
+ result = named_config_get(maps, "max-zone-ttl", &obj);
+ if (result == ISC_R_SUCCESS) {
+ if (cfg_obj_isduration(obj)) {
+ maxttl = cfg_obj_asduration(obj);
+ }
+ }
+ }
+ dns_zone_setmaxttl(zone, maxttl);
+ if (raw != NULL) {
+ dns_zone_setmaxttl(raw, maxttl);
+ }
+
+ /*
+ * Configure update-related options. These apply to
+ * primary servers only.
+ */
+ if (ztype == dns_zone_primary) {
+ dns_acl_t *updateacl;
+
+ CHECK(configure_zone_acl(zconfig, vconfig, config, allow_update,
+ ac, mayberaw, dns_zone_setupdateacl,
+ dns_zone_clearupdateacl));
+
+ updateacl = dns_zone_getupdateacl(mayberaw);
+ if (updateacl != NULL && dns_acl_isinsecure(updateacl)) {
+ isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "zone '%s' allows unsigned updates "
+ "from remote hosts, which is insecure",
+ zname);
+ }
+
+ CHECK(configure_zone_ssutable(zoptions, mayberaw, zname));
+ }
+
+ /*
+ * Configure DNSSEC signing. These apply to primary zones or zones that
+ * use inline-signing (raw != NULL).
+ */
+ if (ztype == dns_zone_primary || raw != NULL) {
+ const cfg_obj_t *validity, *resign;
+ bool allow = false, maint = false;
+ bool sigvalinsecs;
+
+ if (use_kasp) {
+ if (dns_kasp_nsec3(kasp)) {
+ result = dns_zone_setnsec3param(
+ zone, 1, dns_kasp_nsec3flags(kasp),
+ dns_kasp_nsec3iter(kasp),
+ dns_kasp_nsec3saltlen(kasp), NULL, true,
+ false);
+ } else {
+ result = dns_zone_setnsec3param(
+ zone, 0, 0, 0, 0, NULL, true, false);
+ }
+ INSIST(result == ISC_R_SUCCESS);
+ }
+
+ if (use_kasp) {
+ seconds = (uint32_t)dns_kasp_sigvalidity_dnskey(kasp);
+ } else {
+ obj = NULL;
+ result = named_config_get(maps, "dnskey-sig-validity",
+ &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ seconds = cfg_obj_asuint32(obj) * 86400;
+ }
+ dns_zone_setkeyvalidityinterval(zone, seconds);
+
+ if (use_kasp) {
+ seconds = (uint32_t)dns_kasp_sigvalidity(kasp);
+ dns_zone_setsigvalidityinterval(zone, seconds);
+ seconds = (uint32_t)dns_kasp_sigrefresh(kasp);
+ dns_zone_setsigresigninginterval(zone, seconds);
+ } else {
+ obj = NULL;
+ result = named_config_get(maps, "sig-validity-interval",
+ &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+
+ sigvalinsecs = ns_server_getoption(
+ named_g_server->sctx, NS_SERVER_SIGVALINSECS);
+ validity = cfg_tuple_get(obj, "validity");
+ seconds = cfg_obj_asuint32(validity);
+ if (!sigvalinsecs) {
+ seconds *= 86400;
+ }
+ dns_zone_setsigvalidityinterval(zone, seconds);
+
+ resign = cfg_tuple_get(obj, "re-sign");
+ if (cfg_obj_isvoid(resign)) {
+ seconds /= 4;
+ } else if (!sigvalinsecs) {
+ uint32_t r = cfg_obj_asuint32(resign);
+ if (seconds > 7 * 86400) {
+ seconds = r * 86400;
+ } else {
+ seconds = r * 3600;
+ }
+ } else {
+ seconds = cfg_obj_asuint32(resign);
+ }
+ dns_zone_setsigresigninginterval(zone, seconds);
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "key-directory", &obj);
+ if (result == ISC_R_SUCCESS) {
+ filename = cfg_obj_asstring(obj);
+ CHECK(dns_zone_setkeydirectory(zone, filename));
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "sig-signing-signatures", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setsignatures(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "sig-signing-nodes", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setnodes(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "sig-signing-type", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "update-check-ksk", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK,
+ cfg_obj_asboolean(obj));
+ /*
+ * This setting will be ignored if dnssec-policy is used.
+ * named-checkconf will error if both are configured.
+ */
+
+ obj = NULL;
+ result = named_config_get(maps, "dnssec-dnskey-kskonly", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY,
+ cfg_obj_asboolean(obj));
+ /*
+ * This setting will be ignored if dnssec-policy is used.
+ * named-checkconf will error if both are configured.
+ */
+
+ obj = NULL;
+ result = named_config_get(maps, "dnssec-loadkeys-interval",
+ &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ CHECK(dns_zone_setrefreshkeyinterval(zone,
+ cfg_obj_asuint32(obj)));
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "auto-dnssec", &obj);
+ if (kasp != NULL) {
+ bool s2i = (strcmp(dns_kasp_getname(kasp),
+ "insecure") != 0);
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, true);
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, !s2i);
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, true);
+ } else if (result == ISC_R_SUCCESS) {
+ const char *arg = cfg_obj_asstring(obj);
+ if (strcasecmp(arg, "allow") == 0) {
+ allow = true;
+ } else if (strcasecmp(arg, "maintain") == 0) {
+ allow = maint = true;
+ } else if (strcasecmp(arg, "off") == 0) {
+ /* Default */
+ } else {
+ UNREACHABLE();
+ }
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, false);
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
+ }
+ }
+
+ if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) {
+ CHECK(configure_zone_acl(zconfig, vconfig, config,
+ allow_update_forwarding, ac, mayberaw,
+ dns_zone_setforwardacl,
+ dns_zone_clearforwardacl));
+ }
+
+ /*%
+ * Configure parental agents, applies to primary and secondary zones.
+ */
+ if (ztype == dns_zone_primary || ztype == dns_zone_secondary) {
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "parental-agents", &obj);
+ if (obj != NULL) {
+ dns_ipkeylist_t ipkl;
+ dns_ipkeylist_init(&ipkl);
+ CHECK(named_config_getipandkeylist(
+ config, "parental-agents", obj, mctx, &ipkl));
+ dns_zone_setparentals(zone, ipkl.addrs, ipkl.keys,
+ ipkl.tlss, ipkl.count);
+ dns_ipkeylist_clear(mctx, &ipkl);
+ } else {
+ dns_zone_setparentals(zone, NULL, NULL, NULL, 0);
+ }
+ }
+
+ /*%
+ * Configure primary zone functionality.
+ */
+ if (ztype == dns_zone_primary) {
+ obj = NULL;
+ result = named_config_get(maps, "check-wildcard", &obj);
+ if (result == ISC_R_SUCCESS) {
+ check = cfg_obj_asboolean(obj);
+ } else {
+ check = false;
+ }
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKWILDCARD, check);
+
+ obj = NULL;
+ result = named_config_get(maps, "check-dup-records", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dupcheck = cfg_obj_asstring(obj);
+ if (strcasecmp(dupcheck, "warn") == 0) {
+ fail = false;
+ check = true;
+ } else if (strcasecmp(dupcheck, "fail") == 0) {
+ fail = check = true;
+ } else if (strcasecmp(dupcheck, "ignore") == 0) {
+ fail = check = false;
+ } else {
+ UNREACHABLE();
+ }
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRR, check);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRRFAIL, fail);
+
+ obj = NULL;
+ result = named_config_get(maps, "check-mx", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ fail = false;
+ check = true;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ fail = check = true;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ fail = check = false;
+ } else {
+ UNREACHABLE();
+ }
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMX, check);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMXFAIL, fail);
+
+ obj = NULL;
+ result = named_config_get(maps, "check-integrity", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY,
+ cfg_obj_asboolean(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "check-mx-cname", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ warn = true;
+ ignore = false;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ warn = ignore = false;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ warn = ignore = true;
+ } else {
+ UNREACHABLE();
+ }
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNMXCNAME, warn);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNOREMXCNAME, ignore);
+
+ obj = NULL;
+ result = named_config_get(maps, "check-srv-cname", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ warn = true;
+ ignore = false;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ warn = ignore = false;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ warn = ignore = true;
+ } else {
+ UNREACHABLE();
+ }
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNSRVCNAME, warn);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNORESRVCNAME,
+ ignore);
+
+ obj = NULL;
+ result = named_config_get(maps, "dnssec-secure-to-insecure",
+ &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_SECURETOINSECURE,
+ cfg_obj_asboolean(obj));
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "dnssec-update-mode", &obj);
+ if (result == ISC_R_SUCCESS) {
+ const char *arg = cfg_obj_asstring(obj);
+ if (strcasecmp(arg, "no-resign") == 0) {
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_NORESIGN,
+ true);
+ } else if (strcasecmp(arg, "maintain") == 0) {
+ /* Default */
+ } else {
+ UNREACHABLE();
+ }
+ }
+
+ obj = NULL;
+ result = named_config_get(maps, "serial-update-method", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ if (strcasecmp(cfg_obj_asstring(obj), "unixtime") == 0) {
+ dns_zone_setserialupdatemethod(
+ zone, dns_updatemethod_unixtime);
+ } else if (strcasecmp(cfg_obj_asstring(obj), "date") == 0) {
+ dns_zone_setserialupdatemethod(zone,
+ dns_updatemethod_date);
+ } else {
+ dns_zone_setserialupdatemethod(
+ zone, dns_updatemethod_increment);
+ }
+ }
+
+ /*
+ * Configure secondary zone functionality.
+ */
+ switch (ztype) {
+ case dns_zone_mirror:
+ /*
+ * Disable outgoing zone transfers for mirror zones unless they
+ * are explicitly enabled by zone configuration.
+ */
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "allow-transfer", &obj);
+ if (obj == NULL) {
+ dns_acl_t *none;
+ CHECK(dns_acl_none(mctx, &none));
+ dns_zone_setxfracl(zone, none);
+ dns_acl_detach(&none);
+ }
+ FALLTHROUGH;
+ case dns_zone_secondary:
+ case dns_zone_stub:
+ case dns_zone_redirect:
+ count = 0;
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "primaries", &obj);
+ if (obj == NULL) {
+ (void)cfg_map_get(zoptions, "masters", &obj);
+ }
+
+ /*
+ * Use the built-in primary server list if one was not
+ * explicitly specified and this is a root zone mirror.
+ */
+ if (obj == NULL && ztype == dns_zone_mirror &&
+ dns_name_equal(dns_zone_getorigin(zone), dns_rootname))
+ {
+ result = named_config_getremotesdef(
+ named_g_config, "primaries",
+ DEFAULT_IANA_ROOT_ZONE_PRIMARIES, &obj);
+ CHECK(result);
+ }
+ if (obj != NULL) {
+ dns_ipkeylist_t ipkl;
+ dns_ipkeylist_init(&ipkl);
+
+ CHECK(named_config_getipandkeylist(config, "primaries",
+ obj, mctx, &ipkl));
+ dns_zone_setprimaries(mayberaw, ipkl.addrs, ipkl.keys,
+ ipkl.tlss, ipkl.count);
+ count = ipkl.count;
+ dns_ipkeylist_clear(mctx, &ipkl);
+ } else {
+ dns_zone_setprimaries(mayberaw, NULL, NULL, NULL, 0);
+ }
+
+ multi = false;
+ if (count > 1) {
+ obj = NULL;
+ result = named_config_get(maps, "multi-master", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ multi = cfg_obj_asboolean(obj);
+ }
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi);
+
+ obj = NULL;
+ result = named_config_get(maps, "max-transfer-time-in", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setmaxxfrin(
+ mayberaw, transferinsecs ? cfg_obj_asuint32(obj)
+ : cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = named_config_get(maps, "max-transfer-idle-in", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setidlein(mayberaw,
+ transferinsecs ? cfg_obj_asuint32(obj)
+ : cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = named_config_get(maps, "max-refresh-time", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setmaxrefreshtime(mayberaw, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "min-refresh-time", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setminrefreshtime(mayberaw, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "max-retry-time", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setmaxretrytime(mayberaw, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "min-retry-time", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setminretrytime(mayberaw, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "transfer-source", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ CHECK(dns_zone_setxfrsource4(mayberaw,
+ cfg_obj_assockaddr(obj)));
+ named_add_reserved_dispatch(named_g_server,
+ cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "transfer-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ CHECK(dns_zone_setxfrsource6(mayberaw,
+ cfg_obj_assockaddr(obj)));
+ named_add_reserved_dispatch(named_g_server,
+ cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = named_config_get(maps, "alt-transfer-source", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ CHECK(dns_zone_setaltxfrsource4(mayberaw,
+ cfg_obj_assockaddr(obj)));
+ obj = NULL;
+ result = named_config_get(maps, "alt-transfer-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ CHECK(dns_zone_setaltxfrsource6(mayberaw,
+ cfg_obj_assockaddr(obj)));
+ obj = NULL;
+ (void)named_config_get(maps, "use-alt-transfer-source", &obj);
+ if (obj == NULL) {
+ /*
+ * Default off when views are in use otherwise
+ * on for BIND 8 compatibility.
+ */
+ view = dns_zone_getview(zone);
+ if (view != NULL && strcmp(view->name, "_default") == 0)
+ {
+ alt = true;
+ } else {
+ alt = false;
+ }
+ } else {
+ alt = cfg_obj_asboolean(obj);
+ }
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_USEALTXFRSRC, alt);
+
+ obj = NULL;
+ (void)named_config_get(maps, "try-tcp-refresh", &obj);
+ dns_zone_setoption(mayberaw, DNS_ZONEOPT_TRYTCPREFRESH,
+ cfg_obj_asboolean(obj));
+ break;
+
+ case dns_zone_staticstub:
+ CHECK(configure_staticstub(zoptions, zone, zname,
+ default_dbtype));
+ break;
+
+ default:
+ break;
+ }
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (kasp != NULL) {
+ dns_kasp_detach(&kasp);
+ }
+ return (result);
+}
+
+/*
+ * Set up a DLZ zone as writeable
+ */
+isc_result_t
+named_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone,
+ dns_rdataclass_t rdclass, dns_name_t *name) {
+ dns_db_t *db = NULL;
+ isc_time_t now;
+ isc_result_t result;
+
+ TIME_NOW(&now);
+
+ dns_zone_settype(zone, dns_zone_dlz);
+ result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ result = dns_zone_dlzpostload(zone, db);
+ dns_db_detach(&db);
+ return (result);
+}
+
+bool
+named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) {
+ const cfg_obj_t *zoptions = NULL;
+ const cfg_obj_t *obj = NULL;
+ const char *cfilename;
+ const char *zfilename;
+ dns_zone_t *raw = NULL;
+ bool has_raw, inline_signing;
+ dns_zonetype_t ztype;
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+
+ /*
+ * We always reconfigure a static-stub zone for simplicity, assuming
+ * the amount of data to be loaded is small.
+ */
+ if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) {
+ dns_zone_log(zone, ISC_LOG_DEBUG(1),
+ "not reusable: staticstub");
+ return (false);
+ }
+
+ /* If there's a raw zone, use that for filename and type comparison */
+ dns_zone_getraw(zone, &raw);
+ if (raw != NULL) {
+ zfilename = dns_zone_getfile(raw);
+ ztype = dns_zone_gettype(raw);
+ dns_zone_detach(&raw);
+ has_raw = true;
+ } else {
+ zfilename = dns_zone_getfile(zone);
+ ztype = dns_zone_gettype(zone);
+ has_raw = false;
+ }
+
+ inline_signing = named_zone_inlinesigning(zconfig);
+ if (!inline_signing && has_raw) {
+ dns_zone_log(zone, ISC_LOG_DEBUG(1),
+ "not reusable: old zone was inline-signing");
+ return (false);
+ } else if (inline_signing && !has_raw) {
+ dns_zone_log(zone, ISC_LOG_DEBUG(1),
+ "not reusable: old zone was not inline-signing");
+ return (false);
+ }
+
+ if (zonetype_fromconfig(zoptions) != ztype) {
+ dns_zone_log(zone, ISC_LOG_DEBUG(1),
+ "not reusable: type mismatch");
+ return (false);
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "file", &obj);
+ if (obj != NULL) {
+ cfilename = cfg_obj_asstring(obj);
+ } else {
+ cfilename = NULL;
+ }
+ if (!((cfilename == NULL && zfilename == NULL) ||
+ (cfilename != NULL && zfilename != NULL &&
+ strcmp(cfilename, zfilename) == 0)))
+ {
+ dns_zone_log(zone, ISC_LOG_DEBUG(1),
+ "not reusable: filename mismatch");
+ return (false);
+ }
+
+ return (true);
+}
+
+bool
+named_zone_inlinesigning(const cfg_obj_t *zconfig) {
+ const cfg_obj_t *zoptions = NULL;
+ const cfg_obj_t *signing = NULL;
+ bool inline_signing = false;
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+ inline_signing = (cfg_map_get(zoptions, "inline-signing", &signing) ==
+ ISC_R_SUCCESS &&
+ cfg_obj_asboolean(signing));
+
+ return (inline_signing);
+}
diff --git a/bin/nsupdate/Makefile.am b/bin/nsupdate/Makefile.am
new file mode 100644
index 0000000..18c8645
--- /dev/null
+++ b/bin/nsupdate/Makefile.am
@@ -0,0 +1,34 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) \
+ $(LIBISCCFG_CFLAGS) \
+ $(LIBIRS_CFLAGS) \
+ $(LIBBIND9_CFLAGS) \
+ $(GSSAPI_CFLAGS) \
+ $(KRB5_CFLAGS) \
+ $(READLINE_CFLAGS)
+
+AM_CPPFLAGS += \
+ -DSESSION_KEYFILE=\"${localstatedir}/run/named/session.key\"
+
+LDADD += \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS) \
+ $(LIBISCCFG_LIBS) \
+ $(LIBIRS_LIBS) \
+ $(LIBBIND9_LIBS) \
+ $(GSSAPI_LIBS) \
+ $(KRB5_LIBS)
+
+if HAVE_READLINE
+LDADD += \
+ $(READLINE_LIBS)
+endif
+
+bin_PROGRAMS = nsupdate
+
+nsupdate_SOURCES = \
+ nsupdate.c \
+ ../dig/readline.h
diff --git a/bin/nsupdate/Makefile.in b/bin/nsupdate/Makefile.in
new file mode 100644
index 0000000..ce9064d
--- /dev/null
+++ b/bin/nsupdate/Makefile.in
@@ -0,0 +1,828 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+@HAVE_READLINE_TRUE@am__append_2 = \
+@HAVE_READLINE_TRUE@ $(READLINE_LIBS)
+
+bin_PROGRAMS = nsupdate$(EXEEXT)
+subdir = bin/nsupdate
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am_nsupdate_OBJECTS = nsupdate.$(OBJEXT)
+nsupdate_OBJECTS = $(am_nsupdate_OBJECTS)
+nsupdate_LDADD = $(LDADD)
+am__DEPENDENCIES_1 =
+@HAVE_READLINE_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+nsupdate_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS) \
+ $(LIBISCCFG_LIBS) $(LIBIRS_LIBS) $(LIBBIND9_LIBS) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/nsupdate.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(nsupdate_SOURCES)
+DIST_SOURCES = $(nsupdate_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \
+ $(LIBISCCFG_CFLAGS) $(LIBIRS_CFLAGS) $(LIBBIND9_CFLAGS) \
+ $(GSSAPI_CFLAGS) $(KRB5_CFLAGS) $(READLINE_CFLAGS) \
+ -DSESSION_KEYFILE=\"${localstatedir}/run/named/session.key\"
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBISCCFG_LIBS) $(LIBIRS_LIBS) \
+ $(LIBBIND9_LIBS) $(GSSAPI_LIBS) $(KRB5_LIBS) $(am__append_2)
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+nsupdate_SOURCES = \
+ nsupdate.c \
+ ../dig/readline.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/nsupdate/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/nsupdate/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+nsupdate$(EXEEXT): $(nsupdate_OBJECTS) $(nsupdate_DEPENDENCIES) $(EXTRA_nsupdate_DEPENDENCIES)
+ @rm -f nsupdate$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(nsupdate_OBJECTS) $(nsupdate_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nsupdate.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/nsupdate.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/nsupdate.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am: uninstall-binPROGRAMS
+
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir doc-am doc-local dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \
+ uninstall-am uninstall-binPROGRAMS unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c
new file mode 100644
index 0000000..ae759be
--- /dev/null
+++ b/bin/nsupdate/nsupdate.c
@@ -0,0 +1,3463 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/attributes.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/event.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/lex.h>
+#include <isc/log.h>
+#include <isc/managers.h>
+#include <isc/mem.h>
+#include <isc/netmgr.h>
+#include <isc/nonce.h>
+#include <isc/parseint.h>
+#include <isc/portset.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/dispatch.h>
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/nsec3.h>
+#include <dns/rcode.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/request.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+
+#include <dst/dst.h>
+
+#include <isccfg/namedconf.h>
+
+#include <irs/resconf.h>
+
+#if HAVE_GSSAPI
+#include <dst/gssapi.h>
+
+#if HAVE_KRB5_KRB5_H
+#include <krb5/krb5.h>
+#elif HAVE_KRB5_H
+#include <krb5.h>
+#endif
+
+#if HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#elif HAVE_GSSAPI_H
+#include <gssapi.h>
+#endif
+
+#endif /* HAVE_GSSAPI */
+
+#include <bind9/getaddresses.h>
+
+#include "../dig/readline.h"
+
+#define MAXCMD (128 * 1024)
+#define MAXWIRE (64 * 1024)
+#define INITTEXT (2 * 1024)
+#define MAXTEXT (128 * 1024)
+#define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
+
+#define DNSDEFAULTPORT 53
+
+/* Number of addresses to request from bind9_getaddresses() */
+#define MAX_SERVERADDRS 4
+
+static uint16_t dnsport = DNSDEFAULTPORT;
+
+#ifndef RESOLV_CONF
+#define RESOLV_CONF "/etc/resolv.conf"
+#endif /* ifndef RESOLV_CONF */
+
+static bool debugging = false, ddebugging = false;
+static bool memdebugging = false;
+static bool have_ipv4 = false;
+static bool have_ipv6 = false;
+static bool is_dst_up = false;
+static bool usevc = false;
+static bool usegsstsig = false;
+static bool use_win2k_gsstsig = false;
+static bool tried_other_gsstsig = false;
+static bool local_only = false;
+static isc_nm_t *netmgr = NULL;
+static isc_taskmgr_t *taskmgr = NULL;
+static isc_task_t *global_task = NULL;
+static isc_event_t *global_event = NULL;
+static isc_log_t *glctx = NULL;
+static isc_mem_t *gmctx = NULL;
+static dns_dispatchmgr_t *dispatchmgr = NULL;
+static dns_requestmgr_t *requestmgr = NULL;
+static dns_dispatch_t *dispatchv4 = NULL;
+static dns_dispatch_t *dispatchv6 = NULL;
+static dns_message_t *updatemsg = NULL;
+static dns_fixedname_t fuserzone;
+static dns_fixedname_t fzname;
+static dns_name_t *userzone = NULL;
+static dns_name_t *zname = NULL;
+static dns_name_t tmpzonename = DNS_NAME_INITEMPTY;
+static dns_name_t restart_primary = DNS_NAME_INITEMPTY;
+static dns_tsig_keyring_t *gssring = NULL;
+static dns_tsigkey_t *tsigkey = NULL;
+static dst_key_t *sig0key = NULL;
+static isc_sockaddr_t *servers = NULL;
+static isc_sockaddr_t *primary_servers = NULL;
+static bool default_servers = true;
+static int ns_inuse = 0;
+static int primary_inuse = 0;
+static int ns_total = 0;
+static int ns_alloc = 0;
+static int primary_total = 0;
+static int primary_alloc = 0;
+static isc_sockaddr_t *localaddr4 = NULL;
+static isc_sockaddr_t *localaddr6 = NULL;
+static const char *keyfile = NULL;
+static char *keystr = NULL;
+static bool shuttingdown = false;
+static FILE *input;
+static bool interactive = true;
+static bool seenerror = false;
+static const dns_master_style_t *style;
+static int requests = 0;
+static unsigned int logdebuglevel = 0;
+static unsigned int timeout = 300;
+static unsigned int udp_timeout = 3;
+static unsigned int udp_retries = 3;
+static dns_rdataclass_t defaultclass = dns_rdataclass_in;
+static dns_rdataclass_t zoneclass = dns_rdataclass_none;
+static isc_mutex_t answer_lock;
+static dns_message_t *answer = NULL;
+static uint32_t default_ttl = 0;
+static bool default_ttl_set = false;
+static bool checknames = true;
+static const char *resolvconf = RESOLV_CONF;
+
+typedef struct nsu_requestinfo {
+ dns_message_t *msg;
+ isc_sockaddr_t *addr;
+} nsu_requestinfo_t;
+
+static void
+sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
+ dns_request_t **request);
+static void
+send_update(dns_name_t *zonename, isc_sockaddr_t *primary);
+
+noreturn static void
+fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+static void
+debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+static void
+ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+#if HAVE_GSSAPI
+static dns_fixedname_t fkname;
+static isc_sockaddr_t *kserver = NULL;
+static char *realm = NULL;
+static char servicename[DNS_NAME_FORMATSIZE];
+static dns_name_t *keyname;
+typedef struct nsu_gssinfo {
+ dns_message_t *msg;
+ isc_sockaddr_t *addr;
+ gss_ctx_id_t context;
+} nsu_gssinfo_t;
+
+static void
+failed_gssrequest(void);
+static void
+start_gssrequest(dns_name_t *primary);
+static void
+send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
+ dns_request_t **request, gss_ctx_id_t context);
+static void
+recvgss(isc_task_t *task, isc_event_t *event);
+#endif /* HAVE_GSSAPI */
+
+static void
+error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+#define STATUS_MORE (uint16_t)0
+#define STATUS_SEND (uint16_t)1
+#define STATUS_QUIT (uint16_t)2
+#define STATUS_SYNTAX (uint16_t)3
+
+static void
+primary_from_servers(void) {
+ if (primary_servers != NULL && primary_servers != servers) {
+ isc_mem_put(gmctx, primary_servers,
+ primary_alloc * sizeof(isc_sockaddr_t));
+ }
+ primary_servers = servers;
+ primary_total = ns_total;
+ primary_alloc = ns_alloc;
+ primary_inuse = ns_inuse;
+}
+
+static dns_rdataclass_t
+getzoneclass(void) {
+ if (zoneclass == dns_rdataclass_none) {
+ zoneclass = defaultclass;
+ }
+ return (zoneclass);
+}
+
+static bool
+setzoneclass(dns_rdataclass_t rdclass) {
+ if (zoneclass == dns_rdataclass_none || rdclass == dns_rdataclass_none)
+ {
+ zoneclass = rdclass;
+ }
+ if (zoneclass != rdclass) {
+ return (false);
+ }
+ return (true);
+}
+
+static void
+fatal(const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+static void
+error(const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+}
+
+static void
+debug(const char *format, ...) {
+ va_list args;
+
+ if (debugging) {
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+static void
+ddebug(const char *format, ...) {
+ va_list args;
+
+ if (ddebugging) {
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+static void
+check_result(isc_result_t result, const char *msg) {
+ if (result != ISC_R_SUCCESS) {
+ fatal("%s: %s", msg, isc_result_totext(result));
+ }
+}
+
+static char *
+nsu_strsep(char **stringp, const char *delim) {
+ char *string = *stringp;
+ *stringp = NULL;
+ char *s;
+ const char *d;
+ char sc, dc;
+
+ if (string == NULL) {
+ return (NULL);
+ }
+
+ for (; *string != '\0'; string++) {
+ sc = *string;
+ for (d = delim; (dc = *d) != '\0'; d++) {
+ if (sc == dc) {
+ break;
+ }
+ }
+ if (dc == 0) {
+ break;
+ }
+ }
+
+ for (s = string; *s != '\0'; s++) {
+ sc = *s;
+ for (d = delim; (dc = *d) != '\0'; d++) {
+ if (sc == dc) {
+ *s++ = '\0';
+ *stringp = s;
+ return (string);
+ }
+ }
+ }
+ return (string);
+}
+
+static void
+reset_system(void) {
+ ddebug("reset_system()");
+ /* If the update message is still around, destroy it */
+ if (updatemsg != NULL) {
+ dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
+ } else {
+ dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &updatemsg);
+ }
+ updatemsg->opcode = dns_opcode_update;
+ if (usegsstsig) {
+ if (tsigkey != NULL) {
+ dns_tsigkey_detach(&tsigkey);
+ }
+ if (gssring != NULL) {
+ dns_tsigkeyring_detach(&gssring);
+ }
+ tried_other_gsstsig = false;
+ }
+}
+
+static bool
+parse_hmac(const dns_name_t **hmac, const char *hmacstr, size_t len,
+ uint16_t *digestbitsp) {
+ uint16_t digestbits = 0;
+ isc_result_t result;
+ char buf[20];
+
+ REQUIRE(hmac != NULL && *hmac == NULL);
+ REQUIRE(hmacstr != NULL);
+
+ if (len >= sizeof(buf)) {
+ error("unknown key type '%.*s'", (int)(len), hmacstr);
+ return (false);
+ }
+
+ /* Copy len bytes and NUL terminate. */
+ strlcpy(buf, hmacstr, ISC_MIN(len + 1, sizeof(buf)));
+
+ if (strcasecmp(buf, "hmac-md5") == 0) {
+ *hmac = DNS_TSIG_HMACMD5_NAME;
+ } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
+ *hmac = DNS_TSIG_HMACMD5_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[9], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 128) {
+ error("digest-bits out of range [0..128]");
+ return (false);
+ }
+ *digestbitsp = (digestbits + 7) & ~0x7U;
+ } else if (strcasecmp(buf, "hmac-sha1") == 0) {
+ *hmac = DNS_TSIG_HMACSHA1_NAME;
+ } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
+ *hmac = DNS_TSIG_HMACSHA1_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[10], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 160) {
+ error("digest-bits out of range [0..160]");
+ return (false);
+ }
+ *digestbitsp = (digestbits + 7) & ~0x7U;
+ } else if (strcasecmp(buf, "hmac-sha224") == 0) {
+ *hmac = DNS_TSIG_HMACSHA224_NAME;
+ } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
+ *hmac = DNS_TSIG_HMACSHA224_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[12], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 224) {
+ error("digest-bits out of range [0..224]");
+ return (false);
+ }
+ *digestbitsp = (digestbits + 7) & ~0x7U;
+ } else if (strcasecmp(buf, "hmac-sha256") == 0) {
+ *hmac = DNS_TSIG_HMACSHA256_NAME;
+ } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
+ *hmac = DNS_TSIG_HMACSHA256_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[12], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 256) {
+ error("digest-bits out of range [0..256]");
+ return (false);
+ }
+ *digestbitsp = (digestbits + 7) & ~0x7U;
+ } else if (strcasecmp(buf, "hmac-sha384") == 0) {
+ *hmac = DNS_TSIG_HMACSHA384_NAME;
+ } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
+ *hmac = DNS_TSIG_HMACSHA384_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[12], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 384) {
+ error("digest-bits out of range [0..384]");
+ return (false);
+ }
+ *digestbitsp = (digestbits + 7) & ~0x7U;
+ } else if (strcasecmp(buf, "hmac-sha512") == 0) {
+ *hmac = DNS_TSIG_HMACSHA512_NAME;
+ } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
+ *hmac = DNS_TSIG_HMACSHA512_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[12], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 512) {
+ error("digest-bits out of range [0..512]");
+ return (false);
+ }
+ *digestbitsp = (digestbits + 7) & ~0x7U;
+ } else {
+ error("unknown key type '%s'", buf);
+ return (false);
+ }
+ return (true);
+}
+
+static int
+basenamelen(const char *file) {
+ int len = strlen(file);
+
+ if (len > 1 && file[len - 1] == '.') {
+ len -= 1;
+ } else if (len > 8 && strcmp(file + len - 8, ".private") == 0) {
+ len -= 8;
+ } else if (len > 4 && strcmp(file + len - 4, ".key") == 0) {
+ len -= 4;
+ }
+ return (len);
+}
+
+static void
+setup_keystr(void) {
+ unsigned char *secret = NULL;
+ int secretlen;
+ isc_buffer_t secretbuf;
+ isc_result_t result;
+ isc_buffer_t keynamesrc;
+ char *secretstr;
+ char *s, *n;
+ dns_fixedname_t fkeyname;
+ dns_name_t *mykeyname;
+ char *name;
+ const dns_name_t *hmacname = NULL;
+ uint16_t digestbits = 0;
+
+ mykeyname = dns_fixedname_initname(&fkeyname);
+
+ debug("Creating key...");
+
+ s = strchr(keystr, ':');
+ if (s == NULL || s == keystr || s[1] == 0) {
+ fatal("key option must specify [hmac:]keyname:secret");
+ }
+ secretstr = s + 1;
+ n = strchr(secretstr, ':');
+ if (n != NULL) {
+ if (n == secretstr || n[1] == 0) {
+ fatal("key option must specify [hmac:]keyname:secret");
+ }
+ name = secretstr;
+ secretstr = n + 1;
+ if (!parse_hmac(&hmacname, keystr, s - keystr, &digestbits)) {
+ exit(1);
+ }
+ } else {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ name = keystr;
+ n = s;
+ }
+
+ isc_buffer_init(&keynamesrc, name, (unsigned int)(n - name));
+ isc_buffer_add(&keynamesrc, (unsigned int)(n - name));
+
+ debug("namefromtext");
+ result = dns_name_fromtext(mykeyname, &keynamesrc, dns_rootname, 0,
+ NULL);
+ check_result(result, "dns_name_fromtext");
+
+ secretlen = strlen(secretstr) * 3 / 4;
+ secret = isc_mem_allocate(gmctx, secretlen);
+
+ isc_buffer_init(&secretbuf, secret, secretlen);
+ result = isc_base64_decodestring(secretstr, &secretbuf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not create key from %s: %s\n", keystr,
+ isc_result_totext(result));
+ goto failure;
+ }
+
+ secretlen = isc_buffer_usedlength(&secretbuf);
+
+ debug("keycreate");
+ result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen,
+ false, NULL, 0, 0, gmctx, NULL, &tsigkey);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not create key from %s: %s\n", keystr,
+ isc_result_totext(result));
+ } else {
+ dst_key_setbits(tsigkey->key, digestbits);
+ }
+failure:
+ if (secret != NULL) {
+ isc_mem_free(gmctx, secret);
+ }
+}
+
+/*
+ * Get a key from a named.conf format keyfile
+ */
+static isc_result_t
+read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) {
+ cfg_parser_t *pctx = NULL;
+ cfg_obj_t *sessionkey = NULL;
+ const cfg_obj_t *key = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ const cfg_obj_t *algorithmobj = NULL;
+ const char *mykeyname;
+ const char *secretstr;
+ const char *algorithm;
+ isc_result_t result;
+ int len;
+
+ if (!isc_file_exists(keyfile)) {
+ return (ISC_R_FILENOTFOUND);
+ }
+
+ result = cfg_parser_create(mctx, lctx, &pctx);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
+ &sessionkey);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ result = cfg_map_get(sessionkey, "key", &key);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ (void)cfg_map_get(key, "secret", &secretobj);
+ (void)cfg_map_get(key, "algorithm", &algorithmobj);
+ if (secretobj == NULL || algorithmobj == NULL) {
+ fatal("key must have algorithm and secret");
+ }
+
+ mykeyname = cfg_obj_asstring(cfg_map_getname(key));
+ secretstr = cfg_obj_asstring(secretobj);
+ algorithm = cfg_obj_asstring(algorithmobj);
+
+ len = strlen(algorithm) + strlen(mykeyname) + strlen(secretstr) + 3;
+ keystr = isc_mem_allocate(mctx, len);
+ snprintf(keystr, len, "%s:%s:%s", algorithm, mykeyname, secretstr);
+ setup_keystr();
+
+cleanup:
+ if (pctx != NULL) {
+ if (sessionkey != NULL) {
+ cfg_obj_destroy(pctx, &sessionkey);
+ }
+ cfg_parser_destroy(&pctx);
+ }
+
+ if (keystr != NULL) {
+ isc_mem_free(mctx, keystr);
+ }
+
+ return (result);
+}
+
+static void
+setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) {
+ dst_key_t *dstkey = NULL;
+ isc_result_t result;
+ const dns_name_t *hmacname = NULL;
+
+ debug("Creating key...");
+
+ if (sig0key != NULL) {
+ dst_key_free(&sig0key);
+ }
+
+ /* Try reading the key from a K* pair */
+ result = dst_key_fromnamedfile(
+ keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey);
+
+ /* If that didn't work, try reading it as a session.key keyfile */
+ if (result != ISC_R_SUCCESS) {
+ result = read_sessionkey(mctx, lctx);
+ if (result == ISC_R_SUCCESS) {
+ return;
+ }
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "could not read key from %.*s.{private,key}: "
+ "%s\n",
+ basenamelen(keyfile), keyfile,
+ isc_result_totext(result));
+ return;
+ }
+
+ switch (dst_key_alg(dstkey)) {
+ case DST_ALG_HMACMD5:
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ break;
+ case DST_ALG_HMACSHA1:
+ hmacname = DNS_TSIG_HMACSHA1_NAME;
+ break;
+ case DST_ALG_HMACSHA224:
+ hmacname = DNS_TSIG_HMACSHA224_NAME;
+ break;
+ case DST_ALG_HMACSHA256:
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+ break;
+ case DST_ALG_HMACSHA384:
+ hmacname = DNS_TSIG_HMACSHA384_NAME;
+ break;
+ case DST_ALG_HMACSHA512:
+ hmacname = DNS_TSIG_HMACSHA512_NAME;
+ break;
+ }
+ if (hmacname != NULL) {
+ result = dns_tsigkey_createfromkey(
+ dst_key_name(dstkey), hmacname, dstkey, false, NULL, 0,
+ 0, mctx, NULL, &tsigkey);
+ dst_key_free(&dstkey);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not create key from %s: %s\n",
+ keyfile, isc_result_totext(result));
+ return;
+ }
+ } else {
+ dst_key_attach(dstkey, &sig0key);
+ dst_key_free(&dstkey);
+ }
+}
+
+static void
+doshutdown(void) {
+ isc_task_detach(&global_task);
+
+ /*
+ * The isc_mem_put of primary_servers must be before the
+ * isc_mem_put of servers as it sets the servers pointer
+ * to NULL.
+ */
+ if (primary_servers != NULL && primary_servers != servers) {
+ isc_mem_put(gmctx, primary_servers,
+ primary_alloc * sizeof(isc_sockaddr_t));
+ }
+
+ if (servers != NULL) {
+ isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t));
+ }
+
+ if (localaddr4 != NULL) {
+ isc_mem_put(gmctx, localaddr4, sizeof(isc_sockaddr_t));
+ }
+
+ if (localaddr6 != NULL) {
+ isc_mem_put(gmctx, localaddr6, sizeof(isc_sockaddr_t));
+ }
+
+ if (tsigkey != NULL) {
+ ddebug("Freeing TSIG key");
+ dns_tsigkey_detach(&tsigkey);
+ }
+
+ if (sig0key != NULL) {
+ ddebug("Freeing SIG(0) key");
+ dst_key_free(&sig0key);
+ }
+
+ if (updatemsg != NULL) {
+ dns_message_detach(&updatemsg);
+ }
+
+ ddebug("Destroying request manager");
+ dns_requestmgr_detach(&requestmgr);
+
+ ddebug("Freeing the dispatchers");
+ if (have_ipv4) {
+ dns_dispatch_detach(&dispatchv4);
+ }
+ if (have_ipv6) {
+ dns_dispatch_detach(&dispatchv6);
+ }
+
+ ddebug("Shutting down dispatch manager");
+ dns_dispatchmgr_detach(&dispatchmgr);
+}
+
+static void
+maybeshutdown(void) {
+ /* when called from getinput, doshutdown might be already finished */
+ if (requestmgr == NULL) {
+ return;
+ }
+
+ ddebug("Shutting down request manager");
+ dns_requestmgr_shutdown(requestmgr);
+
+ if (requests != 0) {
+ return;
+ }
+
+ doshutdown();
+}
+
+static void
+shutdown_program(isc_task_t *task, isc_event_t *event) {
+ REQUIRE(task == global_task);
+ UNUSED(task);
+
+ ddebug("shutdown_program()");
+ isc_event_free(&event);
+
+ shuttingdown = true;
+ maybeshutdown();
+}
+
+/*
+ * Try honoring the operating system's preferred ephemeral port range.
+ */
+static void
+set_source_ports(dns_dispatchmgr_t *manager) {
+ isc_portset_t *v4portset = NULL, *v6portset = NULL;
+ in_port_t udpport_low, udpport_high;
+ isc_result_t result;
+
+ result = isc_portset_create(gmctx, &v4portset);
+ check_result(result, "isc_portset_create (v4)");
+ result = isc_net_getudpportrange(AF_INET, &udpport_low, &udpport_high);
+ check_result(result, "isc_net_getudpportrange (v4)");
+ isc_portset_addrange(v4portset, udpport_low, udpport_high);
+
+ result = isc_portset_create(gmctx, &v6portset);
+ check_result(result, "isc_portset_create (v6)");
+ result = isc_net_getudpportrange(AF_INET6, &udpport_low, &udpport_high);
+ check_result(result, "isc_net_getudpportrange (v6)");
+ isc_portset_addrange(v6portset, udpport_low, udpport_high);
+
+ result = dns_dispatchmgr_setavailports(manager, v4portset, v6portset);
+ check_result(result, "dns_dispatchmgr_setavailports");
+
+ isc_portset_destroy(gmctx, &v4portset);
+ isc_portset_destroy(gmctx, &v6portset);
+}
+
+static void
+setup_system(void) {
+ isc_result_t result;
+ isc_sockaddr_t bind_any, bind_any6;
+ isc_sockaddrlist_t *nslist;
+ isc_logconfig_t *logconfig = NULL;
+ irs_resconf_t *resconf = NULL;
+
+ ddebug("setup_system()");
+
+ isc_log_create(gmctx, &glctx, &logconfig);
+ isc_log_setcontext(glctx);
+ dns_log_init(glctx);
+ dns_log_setcontext(glctx);
+
+ result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
+ check_result(result, "isc_log_usechannel");
+
+ isc_log_setdebuglevel(glctx, logdebuglevel);
+
+ result = irs_resconf_load(gmctx, resolvconf, &resconf);
+ if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
+ fatal("parse of %s failed", resolvconf);
+ }
+
+ nslist = irs_resconf_getnameservers(resconf);
+
+ if (servers != NULL) {
+ if (primary_servers == servers) {
+ primary_servers = NULL;
+ }
+ isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t));
+ }
+
+ ns_inuse = 0;
+ if (local_only || ISC_LIST_EMPTY(*nslist)) {
+ struct in_addr in;
+ struct in6_addr in6;
+
+ if (local_only && keyfile == NULL) {
+ keyfile = SESSION_KEYFILE;
+ }
+
+ default_servers = !local_only;
+
+ ns_total = ns_alloc = (have_ipv4 ? 1 : 0) + (have_ipv6 ? 1 : 0);
+ servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t));
+
+ if (have_ipv6) {
+ memset(&in6, 0, sizeof(in6));
+ in6.s6_addr[15] = 1;
+ isc_sockaddr_fromin6(&servers[0], &in6, dnsport);
+ }
+ if (have_ipv4) {
+ in.s_addr = htonl(INADDR_LOOPBACK);
+ isc_sockaddr_fromin(&servers[(have_ipv6 ? 1 : 0)], &in,
+ dnsport);
+ }
+ } else {
+ isc_sockaddr_t *sa;
+ int i;
+
+ /*
+ * Count the nameservers (skipping any that we can't use
+ * because of address family restrictions) and allocate
+ * the servers array.
+ */
+ ns_total = 0;
+ for (sa = ISC_LIST_HEAD(*nslist); sa != NULL;
+ sa = ISC_LIST_NEXT(sa, link))
+ {
+ switch (sa->type.sa.sa_family) {
+ case AF_INET:
+ if (have_ipv4) {
+ ns_total++;
+ }
+ break;
+ case AF_INET6:
+ if (have_ipv6) {
+ ns_total++;
+ }
+ break;
+ default:
+ fatal("bad family");
+ }
+ }
+
+ ns_alloc = ns_total;
+ servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t));
+
+ i = 0;
+ for (sa = ISC_LIST_HEAD(*nslist); sa != NULL;
+ sa = ISC_LIST_NEXT(sa, link))
+ {
+ switch (sa->type.sa.sa_family) {
+ case AF_INET:
+ if (have_ipv4) {
+ sa->type.sin.sin_port = htons(dnsport);
+ } else {
+ continue;
+ }
+ break;
+ case AF_INET6:
+ if (have_ipv6) {
+ sa->type.sin6.sin6_port =
+ htons(dnsport);
+ } else {
+ continue;
+ }
+ break;
+ default:
+ fatal("bad family");
+ }
+ INSIST(i < ns_alloc);
+ servers[i++] = *sa;
+ }
+ }
+
+ irs_resconf_destroy(&resconf);
+
+ result = isc_managers_create(gmctx, 1, 0, &netmgr, &taskmgr, NULL);
+ check_result(result, "isc_managers_create");
+
+ result = dns_dispatchmgr_create(gmctx, netmgr, &dispatchmgr);
+ check_result(result, "dns_dispatchmgr_create");
+
+ result = isc_task_create(taskmgr, 0, &global_task);
+ check_result(result, "isc_task_create");
+
+ result = isc_task_onshutdown(global_task, shutdown_program, NULL);
+ check_result(result, "isc_task_onshutdown");
+
+ result = dst_lib_init(gmctx, NULL);
+ check_result(result, "dst_lib_init");
+ is_dst_up = true;
+
+ set_source_ports(dispatchmgr);
+
+ if (have_ipv6) {
+ isc_sockaddr_any6(&bind_any6);
+ result = dns_dispatch_createudp(dispatchmgr, &bind_any6,
+ &dispatchv6);
+ check_result(result, "dns_dispatch_createudp (v6)");
+ }
+
+ if (have_ipv4) {
+ isc_sockaddr_any(&bind_any);
+ result = dns_dispatch_createudp(dispatchmgr, &bind_any,
+ &dispatchv4);
+ check_result(result, "dns_dispatch_createudp (v4)");
+ }
+
+ result = dns_requestmgr_create(gmctx, taskmgr, dispatchmgr, dispatchv4,
+ dispatchv6, &requestmgr);
+ check_result(result, "dns_requestmgr_create");
+
+ if (keystr != NULL) {
+ setup_keystr();
+ } else if (local_only) {
+ result = read_sessionkey(gmctx, glctx);
+ if (result != ISC_R_SUCCESS) {
+ fatal("can't read key from %s: %s\n", keyfile,
+ isc_result_totext(result));
+ }
+ } else if (keyfile != NULL) {
+ setup_keyfile(gmctx, glctx);
+ }
+
+ isc_mutex_init(&answer_lock);
+}
+
+static int
+get_addresses(char *host, in_port_t port, isc_sockaddr_t *sockaddr,
+ int naddrs) {
+ int count = 0;
+ isc_result_t result;
+
+ isc_app_block();
+ result = bind9_getaddresses(host, port, sockaddr, naddrs, &count);
+ isc_app_unblock();
+ if (result != ISC_R_SUCCESS) {
+ error("couldn't get address for '%s': %s", host,
+ isc_result_totext(result));
+ }
+ return (count);
+}
+
+static void
+version(void) {
+ fprintf(stderr, "nsupdate %s\n", PACKAGE_VERSION);
+}
+
+#define PARSE_ARGS_FMT "46C:dDghilL:Mok:p:Pr:R:t:Tu:vVy:"
+
+static void
+pre_parse_args(int argc, char **argv) {
+ dns_rdatatype_t t;
+ int ch;
+ char buf[100];
+ bool doexit = false;
+ bool ipv4only = false, ipv6only = false;
+
+ while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
+ switch (ch) {
+ case 'M': /* was -dm */
+ debugging = true;
+ ddebugging = true;
+ memdebugging = true;
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE |
+ ISC_MEM_DEBUGRECORD;
+ break;
+
+ case '4':
+ if (ipv6only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv4only = true;
+ break;
+
+ case '6':
+ if (ipv4only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv6only = true;
+ break;
+
+ case '?':
+ case 'h':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ argv[0], isc_commandline_option);
+ }
+ fprintf(stderr, "usage: nsupdate [-CdDi] [-L level] "
+ "[-l] [-g | -o | -y keyname:secret "
+ "| -k keyfile] [-p port] "
+ "[-v] [-V] [-P] [-T] [-4 | -6] "
+ "[filename]\n");
+ exit(1);
+
+ case 'P':
+ for (t = 0xff00; t <= 0xfffe; t++) {
+ if (dns_rdatatype_ismeta(t)) {
+ continue;
+ }
+ dns_rdatatype_format(t, buf, sizeof(buf));
+ if (strncmp(buf, "TYPE", 4) != 0) {
+ fprintf(stdout, "%s\n", buf);
+ }
+ }
+ doexit = true;
+ break;
+
+ case 'T':
+ for (t = 1; t <= 0xfeff; t++) {
+ if (dns_rdatatype_ismeta(t)) {
+ continue;
+ }
+ dns_rdatatype_format(t, buf, sizeof(buf));
+ if (strncmp(buf, "TYPE", 4) != 0) {
+ fprintf(stdout, "%s\n", buf);
+ }
+ }
+ doexit = true;
+ break;
+
+ case 'V':
+ version();
+ doexit = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (doexit) {
+ exit(0);
+ }
+ isc_commandline_reset = true;
+ isc_commandline_index = 1;
+}
+
+static void
+parse_args(int argc, char **argv) {
+ int ch;
+ uint32_t i;
+ isc_result_t result;
+ bool force_interactive = false;
+
+ debug("parse_args");
+ while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
+ switch (ch) {
+ case '4':
+ if (have_ipv4) {
+ isc_net_disableipv6();
+ have_ipv6 = false;
+ } else {
+ fatal("can't find IPv4 networking");
+ }
+ break;
+ case '6':
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = false;
+ } else {
+ fatal("can't find IPv6 networking");
+ }
+ break;
+ case 'C':
+ resolvconf = isc_commandline_argument;
+ break;
+ case 'd':
+ debugging = true;
+ break;
+ case 'D': /* was -dd */
+ debugging = true;
+ ddebugging = true;
+ break;
+ case 'M':
+ break;
+ case 'i':
+ force_interactive = true;
+ interactive = true;
+ break;
+ case 'l':
+ local_only = true;
+ break;
+ case 'L':
+ result = isc_parse_uint32(&i, isc_commandline_argument,
+ 10);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "bad library debug value "
+ "'%s'\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ logdebuglevel = i;
+ break;
+ case 'y':
+ keystr = isc_commandline_argument;
+ break;
+ case 'v':
+ usevc = true;
+ break;
+ case 'k':
+ keyfile = isc_commandline_argument;
+ break;
+ case 'g':
+ usegsstsig = true;
+ use_win2k_gsstsig = false;
+ break;
+ case 'o':
+ usegsstsig = true;
+ use_win2k_gsstsig = true;
+ break;
+ case 'p':
+ result = isc_parse_uint16(&dnsport,
+ isc_commandline_argument, 10);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "bad port number "
+ "'%s'\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+ case 't':
+ result = isc_parse_uint32(&timeout,
+ isc_commandline_argument, 10);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "bad timeout '%s'\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ if (timeout == 0) {
+ timeout = UINT_MAX;
+ }
+ break;
+ case 'u':
+ result = isc_parse_uint32(&udp_timeout,
+ isc_commandline_argument, 10);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "bad udp timeout '%s'\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+ case 'r':
+ result = isc_parse_uint32(&udp_retries,
+ isc_commandline_argument, 10);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "bad udp retries '%s'\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'R':
+ fatal("The -R option has been deprecated.");
+ break;
+
+ default:
+ fprintf(stderr, "%s: unhandled option: %c\n", argv[0],
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+ if (keyfile != NULL && keystr != NULL) {
+ fprintf(stderr, "%s: cannot specify both -k and -y\n", argv[0]);
+ exit(1);
+ }
+
+#if HAVE_GSSAPI
+ if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
+ fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
+ argv[0]);
+ exit(1);
+ }
+#else /* HAVE_GSSAPI */
+ if (usegsstsig) {
+ fprintf(stderr,
+ "%s: cannot specify -g or -o, "
+ "program not linked with GSS API Library\n",
+ argv[0]);
+ exit(1);
+ }
+#endif /* HAVE_GSSAPI */
+
+ if (argv[isc_commandline_index] != NULL) {
+ if (strcmp(argv[isc_commandline_index], "-") == 0) {
+ input = stdin;
+ } else {
+ result = isc_stdio_open(argv[isc_commandline_index],
+ "r", &input);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not open '%s': %s\n",
+ argv[isc_commandline_index],
+ isc_result_totext(result));
+ exit(1);
+ }
+ }
+ if (!force_interactive) {
+ interactive = false;
+ }
+ }
+}
+
+static uint16_t
+parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
+ isc_result_t result;
+ char *word;
+ isc_buffer_t source;
+
+ word = nsu_strsep(cmdlinep, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read owner name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ result = dns_message_gettempname(msg, namep);
+ check_result(result, "dns_message_gettempname");
+ isc_buffer_init(&source, word, strlen(word));
+ isc_buffer_add(&source, strlen(word));
+ result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ error("invalid owner name: %s", isc_result_totext(result));
+ isc_buffer_invalidate(&source);
+ dns_message_puttempname(msg, namep);
+ return (STATUS_SYNTAX);
+ }
+ isc_buffer_invalidate(&source);
+ return (STATUS_MORE);
+}
+
+static uint16_t
+parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
+ dns_rdatatype_t rdatatype, dns_message_t *msg, dns_rdata_t *rdata) {
+ char *cmdline = *cmdlinep;
+ isc_buffer_t source, *buf = NULL, *newbuf = NULL;
+ isc_region_t r;
+ isc_lex_t *lex = NULL;
+ dns_rdatacallbacks_t callbacks;
+ isc_result_t result;
+
+ if (cmdline == NULL) {
+ rdata->flags = DNS_RDATA_UPDATE;
+ return (STATUS_MORE);
+ }
+
+ while (*cmdline != 0 && isspace((unsigned char)*cmdline)) {
+ cmdline++;
+ }
+
+ if (*cmdline != 0) {
+ dns_rdatacallbacks_init(&callbacks);
+ result = isc_lex_create(gmctx, strlen(cmdline), &lex);
+ check_result(result, "isc_lex_create");
+ isc_buffer_init(&source, cmdline, strlen(cmdline));
+ isc_buffer_add(&source, strlen(cmdline));
+ result = isc_lex_openbuffer(lex, &source);
+ check_result(result, "isc_lex_openbuffer");
+ isc_buffer_allocate(gmctx, &buf, MAXWIRE);
+ result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
+ dns_rootname, 0, gmctx, buf,
+ &callbacks);
+ isc_lex_destroy(&lex);
+ if (result == ISC_R_SUCCESS) {
+ isc_buffer_usedregion(buf, &r);
+ isc_buffer_allocate(gmctx, &newbuf, r.length);
+ isc_buffer_putmem(newbuf, r.base, r.length);
+ isc_buffer_usedregion(newbuf, &r);
+ dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
+ isc_buffer_free(&buf);
+ dns_message_takebuffer(msg, &newbuf);
+ } else {
+ fprintf(stderr, "invalid rdata format: %s\n",
+ isc_result_totext(result));
+ isc_buffer_free(&buf);
+ return (STATUS_SYNTAX);
+ }
+ } else {
+ rdata->flags = DNS_RDATA_UPDATE;
+ }
+ *cmdlinep = cmdline;
+ return (STATUS_MORE);
+}
+
+static uint16_t
+make_prereq(char *cmdline, bool ispositive, bool isrrset) {
+ isc_result_t result;
+ char *word;
+ dns_name_t *name = NULL;
+ isc_textregion_t region;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdatalist_t *rdatalist = NULL;
+ dns_rdataclass_t rdataclass;
+ dns_rdatatype_t rdatatype;
+ dns_rdata_t *rdata = NULL;
+ uint16_t retval;
+
+ ddebug("make_prereq()");
+
+ /*
+ * Read the owner name
+ */
+ retval = parse_name(&cmdline, updatemsg, &name);
+ if (retval != STATUS_MORE) {
+ return (retval);
+ }
+
+ /*
+ * If this is an rrset prereq, read the class or type.
+ */
+ if (isrrset) {
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read class or type\n");
+ goto failure;
+ }
+ region.base = word;
+ region.length = strlen(word);
+ result = dns_rdataclass_fromtext(&rdataclass, &region);
+ if (result == ISC_R_SUCCESS) {
+ if (!setzoneclass(rdataclass)) {
+ fprintf(stderr, "class mismatch: %s\n", word);
+ goto failure;
+ }
+ /*
+ * Now read the type.
+ */
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read type\n");
+ goto failure;
+ }
+ region.base = word;
+ region.length = strlen(word);
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "invalid type: %s\n", word);
+ goto failure;
+ }
+ } else {
+ rdataclass = getzoneclass();
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "invalid type: %s\n", word);
+ goto failure;
+ }
+ }
+ } else {
+ rdatatype = dns_rdatatype_any;
+ }
+
+ result = dns_message_gettemprdata(updatemsg, &rdata);
+ check_result(result, "dns_message_gettemprdata");
+
+ dns_rdata_init(rdata);
+
+ if (isrrset && ispositive) {
+ retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
+ rdata);
+ if (retval != STATUS_MORE) {
+ goto failure;
+ }
+ } else {
+ rdata->flags = DNS_RDATA_UPDATE;
+ }
+
+ result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
+ check_result(result, "dns_message_gettemprdatalist");
+ result = dns_message_gettemprdataset(updatemsg, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+ rdatalist->type = rdatatype;
+ if (ispositive) {
+ if (isrrset && rdata->data != NULL) {
+ rdatalist->rdclass = rdataclass;
+ } else {
+ rdatalist->rdclass = dns_rdataclass_any;
+ }
+ } else {
+ rdatalist->rdclass = dns_rdataclass_none;
+ }
+ rdata->rdclass = rdatalist->rdclass;
+ rdata->type = rdatatype;
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+ ISC_LIST_INIT(name->list);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
+ return (STATUS_MORE);
+
+failure:
+ if (name != NULL) {
+ dns_message_puttempname(updatemsg, &name);
+ }
+ return (STATUS_SYNTAX);
+}
+
+static uint16_t
+evaluate_prereq(char *cmdline) {
+ char *word;
+ bool ispositive, isrrset;
+
+ ddebug("evaluate_prereq()");
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read operation code\n");
+ return (STATUS_SYNTAX);
+ }
+ if (strcasecmp(word, "nxdomain") == 0) {
+ ispositive = false;
+ isrrset = false;
+ } else if (strcasecmp(word, "yxdomain") == 0) {
+ ispositive = true;
+ isrrset = false;
+ } else if (strcasecmp(word, "nxrrset") == 0) {
+ ispositive = false;
+ isrrset = true;
+ } else if (strcasecmp(word, "yxrrset") == 0) {
+ ispositive = true;
+ isrrset = true;
+ } else {
+ fprintf(stderr, "incorrect operation code: %s\n", word);
+ return (STATUS_SYNTAX);
+ }
+ return (make_prereq(cmdline, ispositive, isrrset));
+}
+
+static uint16_t
+evaluate_server(char *cmdline) {
+ char *word, *server;
+ long port;
+
+ if (local_only) {
+ fprintf(stderr, "cannot reset server in localhost-only mode\n");
+ return (STATUS_SYNTAX);
+ }
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read server name\n");
+ return (STATUS_SYNTAX);
+ }
+ server = word;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ port = dnsport;
+ } else {
+ char *endp;
+ port = strtol(word, &endp, 10);
+ if (*endp != 0) {
+ fprintf(stderr, "port '%s' is not numeric\n", word);
+ return (STATUS_SYNTAX);
+ } else if (port < 1 || port > 65535) {
+ fprintf(stderr,
+ "port '%s' is out of range "
+ "(1 to 65535)\n",
+ word);
+ return (STATUS_SYNTAX);
+ }
+ }
+
+ if (servers != NULL) {
+ if (primary_servers == servers) {
+ primary_servers = NULL;
+ }
+ isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t));
+ }
+
+ default_servers = false;
+
+ ns_alloc = MAX_SERVERADDRS;
+ ns_inuse = 0;
+ servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t));
+
+ memset(servers, 0, ns_alloc * sizeof(isc_sockaddr_t));
+ ns_total = get_addresses(server, (in_port_t)port, servers, ns_alloc);
+ if (ns_total == 0) {
+ return (STATUS_SYNTAX);
+ }
+
+ return (STATUS_MORE);
+}
+
+static uint16_t
+evaluate_local(char *cmdline) {
+ char *word, *local;
+ long port;
+ struct in_addr in4;
+ struct in6_addr in6;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read server name\n");
+ return (STATUS_SYNTAX);
+ }
+ local = word;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ port = 0;
+ } else {
+ char *endp;
+ port = strtol(word, &endp, 10);
+ if (*endp != 0) {
+ fprintf(stderr, "port '%s' is not numeric\n", word);
+ return (STATUS_SYNTAX);
+ } else if (port < 1 || port > 65535) {
+ fprintf(stderr,
+ "port '%s' is out of range "
+ "(1 to 65535)\n",
+ word);
+ return (STATUS_SYNTAX);
+ }
+ }
+
+ if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1) {
+ if (localaddr6 == NULL) {
+ localaddr6 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
+ }
+ isc_sockaddr_fromin6(localaddr6, &in6, (in_port_t)port);
+ } else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1) {
+ if (localaddr4 == NULL) {
+ localaddr4 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
+ }
+ isc_sockaddr_fromin(localaddr4, &in4, (in_port_t)port);
+ } else {
+ fprintf(stderr, "invalid address %s", local);
+ return (STATUS_SYNTAX);
+ }
+
+ return (STATUS_MORE);
+}
+
+static uint16_t
+evaluate_key(char *cmdline) {
+ char *namestr;
+ char *secretstr;
+ isc_buffer_t b;
+ isc_result_t result;
+ dns_fixedname_t fkeyname;
+ dns_name_t *mykeyname;
+ int secretlen;
+ unsigned char *secret = NULL;
+ isc_buffer_t secretbuf;
+ const dns_name_t *hmacname = NULL;
+ uint16_t digestbits = 0;
+ char *n;
+
+ namestr = nsu_strsep(&cmdline, " \t\r\n");
+ if (namestr == NULL || *namestr == 0) {
+ fprintf(stderr, "could not read key name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ mykeyname = dns_fixedname_initname(&fkeyname);
+
+ n = strchr(namestr, ':');
+ if (n != NULL) {
+ if (!parse_hmac(&hmacname, namestr, n - namestr, &digestbits)) {
+ return (STATUS_SYNTAX);
+ }
+ namestr = n + 1;
+ } else {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ }
+
+ isc_buffer_init(&b, namestr, strlen(namestr));
+ isc_buffer_add(&b, strlen(namestr));
+ result = dns_name_fromtext(mykeyname, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not parse key name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ secretstr = nsu_strsep(&cmdline, "\r\n");
+ if (secretstr == NULL || *secretstr == 0) {
+ fprintf(stderr, "could not read key secret\n");
+ return (STATUS_SYNTAX);
+ }
+ secretlen = strlen(secretstr) * 3 / 4;
+ secret = isc_mem_allocate(gmctx, secretlen);
+
+ isc_buffer_init(&secretbuf, secret, secretlen);
+ result = isc_base64_decodestring(secretstr, &secretbuf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not create key from %s: %s\n", secretstr,
+ isc_result_totext(result));
+ isc_mem_free(gmctx, secret);
+ return (STATUS_SYNTAX);
+ }
+ secretlen = isc_buffer_usedlength(&secretbuf);
+
+ if (tsigkey != NULL) {
+ dns_tsigkey_detach(&tsigkey);
+ }
+ result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen,
+ false, NULL, 0, 0, gmctx, NULL, &tsigkey);
+ isc_mem_free(gmctx, secret);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not create key from %s %s: %s\n",
+ namestr, secretstr, isc_result_totext(result));
+ return (STATUS_SYNTAX);
+ }
+ dst_key_setbits(tsigkey->key, digestbits);
+ return (STATUS_MORE);
+}
+
+static uint16_t
+evaluate_zone(char *cmdline) {
+ char *word;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read zone name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ userzone = dns_fixedname_initname(&fuserzone);
+ isc_buffer_init(&b, word, strlen(word));
+ isc_buffer_add(&b, strlen(word));
+ result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ userzone = NULL; /* Lest it point to an invalid name */
+ fprintf(stderr, "could not parse zone name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ return (STATUS_MORE);
+}
+
+static uint16_t
+evaluate_realm(char *cmdline) {
+#if HAVE_GSSAPI
+ char *word;
+ char buf[1024];
+ int n;
+
+ if (realm != NULL) {
+ isc_mem_free(gmctx, realm);
+ realm = NULL;
+ }
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ return (STATUS_MORE);
+ }
+
+ n = snprintf(buf, sizeof(buf), "@%s", word);
+ if (n < 0 || (size_t)n >= sizeof(buf)) {
+ error("realm is too long");
+ return (STATUS_SYNTAX);
+ }
+ realm = isc_mem_strdup(gmctx, buf);
+ return (STATUS_MORE);
+#else /* HAVE_GSSAPI */
+ UNUSED(cmdline);
+ return (STATUS_SYNTAX);
+#endif /* HAVE_GSSAPI */
+}
+
+static uint16_t
+evaluate_ttl(char *cmdline) {
+ char *word;
+ isc_result_t result;
+ uint32_t ttl;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read ttl\n");
+ return (STATUS_SYNTAX);
+ }
+
+ if (!strcasecmp(word, "none")) {
+ default_ttl = 0;
+ default_ttl_set = false;
+ return (STATUS_MORE);
+ }
+
+ result = isc_parse_uint32(&ttl, word, 10);
+ if (result != ISC_R_SUCCESS) {
+ return (STATUS_SYNTAX);
+ }
+
+ if (ttl > TTL_MAX) {
+ fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word,
+ TTL_MAX);
+ return (STATUS_SYNTAX);
+ }
+ default_ttl = ttl;
+ default_ttl_set = true;
+
+ return (STATUS_MORE);
+}
+
+static uint16_t
+evaluate_class(char *cmdline) {
+ char *word;
+ isc_textregion_t r;
+ isc_result_t result;
+ dns_rdataclass_t rdclass;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read class name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ r.base = word;
+ r.length = strlen(word);
+ result = dns_rdataclass_fromtext(&rdclass, &r);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not parse class name: %s\n", word);
+ return (STATUS_SYNTAX);
+ }
+ switch (rdclass) {
+ case dns_rdataclass_none:
+ case dns_rdataclass_any:
+ case dns_rdataclass_reserved0:
+ fprintf(stderr, "bad default class: %s\n", word);
+ return (STATUS_SYNTAX);
+ default:
+ defaultclass = rdclass;
+ }
+
+ return (STATUS_MORE);
+}
+
+static uint16_t
+update_addordelete(char *cmdline, bool isdelete) {
+ isc_result_t result;
+ dns_name_t *name = NULL;
+ uint32_t ttl;
+ char *word;
+ dns_rdataclass_t rdataclass;
+ dns_rdatatype_t rdatatype;
+ dns_rdata_t *rdata = NULL;
+ dns_rdatalist_t *rdatalist = NULL;
+ dns_rdataset_t *rdataset = NULL;
+ isc_textregion_t region;
+ uint16_t retval;
+
+ ddebug("update_addordelete()");
+
+ /*
+ * Read the owner name.
+ */
+ retval = parse_name(&cmdline, updatemsg, &name);
+ if (retval != STATUS_MORE) {
+ return (retval);
+ }
+
+ result = dns_message_gettemprdata(updatemsg, &rdata);
+ check_result(result, "dns_message_gettemprdata");
+
+ dns_rdata_init(rdata);
+
+ /*
+ * If this is an add, read the TTL and verify that it's in range.
+ * If it's a delete, ignore a TTL if present (for compatibility).
+ */
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ if (!isdelete) {
+ fprintf(stderr, "could not read owner ttl\n");
+ goto failure;
+ } else {
+ ttl = 0;
+ rdataclass = dns_rdataclass_any;
+ rdatatype = dns_rdatatype_any;
+ rdata->flags = DNS_RDATA_UPDATE;
+ goto doneparsing;
+ }
+ }
+ result = isc_parse_uint32(&ttl, word, 10);
+ if (result != ISC_R_SUCCESS) {
+ if (isdelete) {
+ ttl = 0;
+ goto parseclass;
+ } else if (default_ttl_set) {
+ ttl = default_ttl;
+ goto parseclass;
+ } else {
+ fprintf(stderr, "ttl '%s': %s\n", word,
+ isc_result_totext(result));
+ goto failure;
+ }
+ }
+
+ if (isdelete) {
+ ttl = 0;
+ } else if (ttl > TTL_MAX) {
+ fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word,
+ TTL_MAX);
+ goto failure;
+ }
+
+ /*
+ * Read the class or type.
+ */
+ word = nsu_strsep(&cmdline, " \t\r\n");
+parseclass:
+ if (word == NULL || *word == 0) {
+ if (isdelete) {
+ rdataclass = dns_rdataclass_any;
+ rdatatype = dns_rdatatype_any;
+ rdata->flags = DNS_RDATA_UPDATE;
+ goto doneparsing;
+ } else {
+ fprintf(stderr, "could not read class or type\n");
+ goto failure;
+ }
+ }
+ region.base = word;
+ region.length = strlen(word);
+ rdataclass = dns_rdataclass_any;
+ result = dns_rdataclass_fromtext(&rdataclass, &region);
+ if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
+ if (!setzoneclass(rdataclass)) {
+ fprintf(stderr, "class mismatch: %s\n", word);
+ goto failure;
+ }
+ /*
+ * Now read the type.
+ */
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ if (isdelete) {
+ rdataclass = dns_rdataclass_any;
+ rdatatype = dns_rdatatype_any;
+ rdata->flags = DNS_RDATA_UPDATE;
+ goto doneparsing;
+ } else {
+ fprintf(stderr, "could not read type\n");
+ goto failure;
+ }
+ }
+ region.base = word;
+ region.length = strlen(word);
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "'%s' is not a valid type: %s\n", word,
+ isc_result_totext(result));
+ goto failure;
+ }
+ } else {
+ rdataclass = getzoneclass();
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "'%s' is not a valid class or type: "
+ "%s\n",
+ word, isc_result_totext(result));
+ goto failure;
+ }
+ }
+
+ retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, rdata);
+ if (retval != STATUS_MORE) {
+ goto failure;
+ }
+
+ if (isdelete) {
+ if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
+ rdataclass = dns_rdataclass_any;
+ } else {
+ rdataclass = dns_rdataclass_none;
+ }
+ } else {
+ if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
+ fprintf(stderr, "could not read rdata\n");
+ goto failure;
+ }
+ }
+
+ if (!isdelete && checknames) {
+ dns_fixedname_t fixed;
+ dns_name_t *bad;
+
+ if (!dns_rdata_checkowner(name, rdata->rdclass, rdata->type,
+ true))
+ {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ fprintf(stderr, "check-names failed: bad owner '%s'\n",
+ namebuf);
+ goto failure;
+ }
+
+ bad = dns_fixedname_initname(&fixed);
+ if (!dns_rdata_checknames(rdata, name, bad)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(bad, namebuf, sizeof(namebuf));
+ fprintf(stderr, "check-names failed: bad name '%s'\n",
+ namebuf);
+ goto failure;
+ }
+ }
+
+ if (!isdelete && rdata->type == dns_rdatatype_nsec3param) {
+ dns_rdata_nsec3param_t nsec3param;
+
+ result = dns_rdata_tostruct(rdata, &nsec3param, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ if (nsec3param.iterations > dns_nsec3_maxiterations()) {
+ fprintf(stderr,
+ "NSEC3PARAM has excessive iterations (> %u)\n",
+ dns_nsec3_maxiterations());
+ goto failure;
+ }
+ }
+
+doneparsing:
+
+ result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
+ check_result(result, "dns_message_gettemprdatalist");
+ result = dns_message_gettemprdataset(updatemsg, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+ rdatalist->type = rdatatype;
+ rdatalist->rdclass = rdataclass;
+ rdatalist->covers = rdatatype;
+ rdatalist->ttl = (dns_ttl_t)ttl;
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+ ISC_LIST_INIT(name->list);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
+ return (STATUS_MORE);
+
+failure:
+ if (name != NULL) {
+ dns_message_puttempname(updatemsg, &name);
+ }
+ dns_message_puttemprdata(updatemsg, &rdata);
+ return (STATUS_SYNTAX);
+}
+
+static uint16_t
+evaluate_update(char *cmdline) {
+ char *word;
+ bool isdelete;
+
+ ddebug("evaluate_update()");
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read operation code\n");
+ return (STATUS_SYNTAX);
+ }
+ if (strcasecmp(word, "delete") == 0) {
+ isdelete = true;
+ } else if (strcasecmp(word, "del") == 0) {
+ isdelete = true;
+ } else if (strcasecmp(word, "add") == 0) {
+ isdelete = false;
+ } else {
+ fprintf(stderr, "incorrect operation code: %s\n", word);
+ return (STATUS_SYNTAX);
+ }
+ return (update_addordelete(cmdline, isdelete));
+}
+
+static uint16_t
+evaluate_checknames(char *cmdline) {
+ char *word;
+
+ ddebug("evaluate_checknames()");
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read check-names directive\n");
+ return (STATUS_SYNTAX);
+ }
+ if (strcasecmp(word, "yes") == 0 || strcasecmp(word, "true") == 0 ||
+ strcasecmp(word, "on") == 0)
+ {
+ checknames = true;
+ } else if (strcasecmp(word, "no") == 0 ||
+ strcasecmp(word, "false") == 0 ||
+ strcasecmp(word, "off") == 0)
+ {
+ checknames = false;
+ } else {
+ fprintf(stderr, "incorrect check-names directive: %s\n", word);
+ return (STATUS_SYNTAX);
+ }
+ return (STATUS_MORE);
+}
+
+static void
+setzone(dns_name_t *zonename) {
+ isc_result_t result;
+ dns_name_t *name = NULL;
+ dns_rdataset_t *rdataset = NULL;
+
+ result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
+ if (result == ISC_R_SUCCESS) {
+ dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
+ dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
+ for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+ rdataset = ISC_LIST_HEAD(name->list))
+ {
+ ISC_LIST_UNLINK(name->list, rdataset, link);
+ dns_rdataset_disassociate(rdataset);
+ dns_message_puttemprdataset(updatemsg, &rdataset);
+ }
+ dns_message_puttempname(updatemsg, &name);
+ }
+
+ if (zonename != NULL) {
+ result = dns_message_gettempname(updatemsg, &name);
+ check_result(result, "dns_message_gettempname");
+ dns_name_clone(zonename, name);
+ result = dns_message_gettemprdataset(updatemsg, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+ dns_rdataset_makequestion(rdataset, getzoneclass(),
+ dns_rdatatype_soa);
+ ISC_LIST_INIT(name->list);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
+ }
+}
+
+static void
+show_message(FILE *stream, dns_message_t *msg, const char *description) {
+ isc_result_t result;
+ isc_buffer_t *buf = NULL;
+ int bufsz;
+
+ ddebug("show_message()");
+
+ setzone(userzone);
+
+ bufsz = INITTEXT;
+ do {
+ if (bufsz > MAXTEXT) {
+ fprintf(stderr, "could not allocate large enough "
+ "buffer to display message\n");
+ exit(1);
+ }
+ if (buf != NULL) {
+ isc_buffer_free(&buf);
+ }
+ isc_buffer_allocate(gmctx, &buf, bufsz);
+ result = dns_message_totext(msg, style, 0, buf);
+ bufsz *= 2;
+ } while (result == ISC_R_NOSPACE);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not convert message to text format.\n");
+ isc_buffer_free(&buf);
+ return;
+ }
+ fprintf(stream, "%s\n%.*s", description,
+ (int)isc_buffer_usedlength(buf), (char *)isc_buffer_base(buf));
+ fflush(stream);
+ isc_buffer_free(&buf);
+}
+
+static uint16_t
+do_next_command(char *cmdline) {
+ char *word;
+
+ ddebug("do_next_command()");
+ word = nsu_strsep(&cmdline, " \t\r\n");
+
+ if (word == NULL || *word == 0) {
+ return (STATUS_SEND);
+ }
+ if (word[0] == ';') {
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "quit") == 0) {
+ return (STATUS_QUIT);
+ }
+ if (strcasecmp(word, "prereq") == 0) {
+ return (evaluate_prereq(cmdline));
+ }
+ if (strcasecmp(word, "nxdomain") == 0) {
+ return (make_prereq(cmdline, false, false));
+ }
+ if (strcasecmp(word, "yxdomain") == 0) {
+ return (make_prereq(cmdline, true, false));
+ }
+ if (strcasecmp(word, "nxrrset") == 0) {
+ return (make_prereq(cmdline, false, true));
+ }
+ if (strcasecmp(word, "yxrrset") == 0) {
+ return (make_prereq(cmdline, true, true));
+ }
+ if (strcasecmp(word, "update") == 0) {
+ return (evaluate_update(cmdline));
+ }
+ if (strcasecmp(word, "delete") == 0) {
+ return (update_addordelete(cmdline, true));
+ }
+ if (strcasecmp(word, "del") == 0) {
+ return (update_addordelete(cmdline, true));
+ }
+ if (strcasecmp(word, "add") == 0) {
+ return (update_addordelete(cmdline, false));
+ }
+ if (strcasecmp(word, "server") == 0) {
+ return (evaluate_server(cmdline));
+ }
+ if (strcasecmp(word, "local") == 0) {
+ return (evaluate_local(cmdline));
+ }
+ if (strcasecmp(word, "zone") == 0) {
+ return (evaluate_zone(cmdline));
+ }
+ if (strcasecmp(word, "class") == 0) {
+ return (evaluate_class(cmdline));
+ }
+ if (strcasecmp(word, "send") == 0) {
+ return (STATUS_SEND);
+ }
+ if (strcasecmp(word, "debug") == 0) {
+ if (debugging) {
+ ddebugging = true;
+ } else {
+ debugging = true;
+ }
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "ttl") == 0) {
+ return (evaluate_ttl(cmdline));
+ }
+ if (strcasecmp(word, "show") == 0) {
+ show_message(stdout, updatemsg, "Outgoing update query:");
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "answer") == 0) {
+ LOCK(&answer_lock);
+ if (answer != NULL) {
+ show_message(stdout, answer, "Answer:");
+ }
+ UNLOCK(&answer_lock);
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "key") == 0) {
+ usegsstsig = false;
+ return (evaluate_key(cmdline));
+ }
+ if (strcasecmp(word, "realm") == 0) {
+ return (evaluate_realm(cmdline));
+ }
+ if (strcasecmp(word, "check-names") == 0 ||
+ strcasecmp(word, "checknames") == 0)
+ {
+ return (evaluate_checknames(cmdline));
+ }
+ if (strcasecmp(word, "gsstsig") == 0) {
+#if HAVE_GSSAPI
+ usegsstsig = true;
+ use_win2k_gsstsig = false;
+#else /* HAVE_GSSAPI */
+ fprintf(stderr, "gsstsig not supported\n");
+#endif /* HAVE_GSSAPI */
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "oldgsstsig") == 0) {
+#if HAVE_GSSAPI
+ usegsstsig = true;
+ use_win2k_gsstsig = true;
+#else /* HAVE_GSSAPI */
+ fprintf(stderr, "gsstsig not supported\n");
+#endif /* HAVE_GSSAPI */
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "help") == 0) {
+ fprintf(stdout, "nsupdate " PACKAGE_VERSION ":\n"
+ "local address [port] (set local "
+ "resolver)\n"
+ "server address [port] (set primary server "
+ "for zone)\n"
+ "send (send the update "
+ "request)\n"
+ "show (show the update "
+ "request)\n"
+ "answer (show the answer to "
+ "the last request)\n"
+ "quit (quit, any pending "
+ "update is not sent)\n"
+ "help (display this "
+ "message)\n"
+ "key [hmac:]keyname secret (use TSIG to sign "
+ "the request)\n"
+ "gsstsig (use GSS_TSIG to "
+ "sign the request)\n"
+ "oldgsstsig (use Microsoft's "
+ "GSS_TSIG to sign the request)\n"
+ "zone name (set the zone to be "
+ "updated)\n"
+ "class CLASS (set the zone's DNS "
+ "class, e.g. IN (default), CH)\n"
+ "check-names { on | off } (enable / disable "
+ "check-names)\n"
+ "[prereq] nxdomain name (require that this "
+ "name does not exist)\n"
+ "[prereq] yxdomain name (require that this "
+ "name exists)\n"
+ "[prereq] nxrrset .... (require that this "
+ "RRset does not exist)\n"
+ "[prereq] yxrrset .... (require that this "
+ "RRset exists)\n"
+ "[update] add .... (add the given "
+ "record to the zone)\n"
+ "[update] del[ete] .... (remove the given "
+ "record(s) from the zone)\n");
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "version") == 0) {
+ fprintf(stdout, "nsupdate " PACKAGE_VERSION "\n");
+ return (STATUS_MORE);
+ }
+ fprintf(stderr, "incorrect section name: %s\n", word);
+ return (STATUS_SYNTAX);
+}
+
+static uint16_t
+get_next_command(void) {
+ uint16_t result = STATUS_QUIT;
+ char cmdlinebuf[MAXCMD];
+ char *cmdline = NULL, *ptr = NULL;
+
+ isc_app_block();
+ if (interactive) {
+ cmdline = ptr = readline("> ");
+ if (ptr != NULL && *ptr != 0) {
+ add_history(ptr);
+ }
+ } else {
+ cmdline = fgets(cmdlinebuf, MAXCMD, input);
+ }
+ isc_app_unblock();
+
+ if (cmdline != NULL) {
+ char *tmp = cmdline;
+
+ /*
+ * Normalize input by removing any eol as readline()
+ * removes eol but fgets doesn't.
+ */
+ (void)nsu_strsep(&tmp, "\r\n");
+ result = do_next_command(cmdline);
+ }
+ if (ptr != NULL) {
+ free(ptr);
+ }
+
+ return (result);
+}
+
+static bool
+user_interaction(void) {
+ uint16_t result = STATUS_MORE;
+
+ ddebug("user_interaction()");
+ while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
+ result = get_next_command();
+ if (!interactive && result == STATUS_SYNTAX) {
+ fatal("syntax error");
+ }
+ }
+ if (result == STATUS_SEND) {
+ return (true);
+ }
+ return (false);
+}
+
+static void
+done_update(void) {
+ isc_event_t *event = global_event;
+ ddebug("done_update()");
+ isc_task_send(global_task, &event);
+}
+
+static void
+check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_any_tsig_t tsig;
+
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "dns_rdataset_first");
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &tsig, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ if (tsig.error != 0) {
+ if (isc_buffer_remaininglength(b) < 1) {
+ check_result(ISC_R_NOSPACE, "isc_buffer_"
+ "remaininglength");
+ }
+ isc_buffer_putstr(b, "(" /*)*/);
+ result = dns_tsigrcode_totext(tsig.error, b);
+ check_result(result, "dns_tsigrcode_totext");
+ if (isc_buffer_remaininglength(b) < 1) {
+ check_result(ISC_R_NOSPACE, "isc_buffer_"
+ "remaininglength");
+ }
+ isc_buffer_putstr(b, /*(*/ ")");
+ }
+}
+
+static bool
+next_primary(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) {
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
+ fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf,
+ isc_result_totext(eresult));
+ if (++primary_inuse >= primary_total) {
+ return (false);
+ }
+ ddebug("%s: trying next server", caller);
+ return (true);
+}
+
+static void
+update_completed(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = NULL;
+ isc_result_t result;
+ dns_request_t *request;
+
+ UNUSED(task);
+
+ ddebug("update_completed()");
+
+ requests--;
+
+ REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
+ reqev = (dns_requestevent_t *)event;
+ request = reqev->request;
+
+ if (shuttingdown) {
+ dns_request_destroy(&request);
+ isc_event_free(&event);
+ maybeshutdown();
+ return;
+ }
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ if (!next_primary("update_completed",
+ &primary_servers[primary_inuse],
+ reqev->result))
+ {
+ seenerror = true;
+ goto done;
+ }
+
+ ddebug("Destroying request [%p]", request);
+ dns_request_destroy(&request);
+ dns_message_renderreset(updatemsg);
+ dns_message_settsigkey(updatemsg, NULL);
+ send_update(zname, &primary_servers[primary_inuse]);
+ isc_event_free(&event);
+ return;
+ }
+
+ LOCK(&answer_lock);
+ dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &answer);
+ result = dns_request_getresponse(request, answer,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ if (answer->verify_attempted) {
+ ddebug("tsig verification successful");
+ }
+ break;
+ case DNS_R_CLOCKSKEW:
+ case DNS_R_EXPECTEDTSIG:
+ case DNS_R_TSIGERRORSET:
+ case DNS_R_TSIGVERIFYFAILURE:
+ case DNS_R_UNEXPECTEDTSIG:
+ case ISC_R_FAILURE:
+#if 0
+ if (usegsstsig && answer->rcode == dns_rcode_noerror) {
+ /*
+ * For MS DNS that violates RFC 2845, section 4.2
+ */
+ break;
+ }
+#endif /* if 0 */
+ fprintf(stderr, "; TSIG error with server: %s\n",
+ isc_result_totext(result));
+ seenerror = true;
+ break;
+ default:
+ check_result(result, "dns_request_getresponse");
+ }
+
+ if (answer->opcode != dns_opcode_update) {
+ fatal("invalid OPCODE in response to UPDATE request");
+ }
+
+ if (answer->rcode != dns_rcode_noerror) {
+ seenerror = true;
+ if (!debugging) {
+ char buf[64];
+ isc_buffer_t b;
+ dns_rdataset_t *rds;
+
+ isc_buffer_init(&b, buf, sizeof(buf) - 1);
+ result = dns_rcode_totext(answer->rcode, &b);
+ check_result(result, "dns_rcode_totext");
+ rds = dns_message_gettsig(answer, NULL);
+ if (rds != NULL) {
+ check_tsig_error(rds, &b);
+ }
+ fprintf(stderr, "update failed: %.*s\n",
+ (int)isc_buffer_usedlength(&b), buf);
+ }
+ }
+ if (debugging) {
+ show_message(stderr, answer, "\nReply from update query:");
+ }
+ UNLOCK(&answer_lock);
+
+done:
+ dns_request_destroy(&request);
+ if (usegsstsig) {
+ dns_name_free(&tmpzonename, gmctx);
+ dns_name_free(&restart_primary, gmctx);
+ dns_name_init(&tmpzonename, 0);
+ dns_name_init(&restart_primary, 0);
+ }
+ isc_event_free(&event);
+ done_update();
+}
+
+static void
+send_update(dns_name_t *zone, isc_sockaddr_t *primary) {
+ isc_result_t result;
+ dns_request_t *request = NULL;
+ unsigned int options = DNS_REQUESTOPT_CASE;
+ isc_sockaddr_t *srcaddr;
+
+ ddebug("send_update()");
+
+ setzone(zone);
+
+ if (usevc) {
+ options |= DNS_REQUESTOPT_TCP;
+ }
+ if (tsigkey == NULL && sig0key != NULL) {
+ result = dns_message_setsig0key(updatemsg, sig0key);
+ check_result(result, "dns_message_setsig0key");
+ }
+ if (debugging) {
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(primary, addrbuf, sizeof(addrbuf));
+ fprintf(stderr, "Sending update to %s\n", addrbuf);
+ }
+
+ if (isc_sockaddr_pf(primary) == AF_INET6) {
+ srcaddr = localaddr6;
+ } else {
+ srcaddr = localaddr4;
+ }
+
+ /* Windows doesn't like the tsig name to be compressed. */
+ if (updatemsg->tsigname) {
+ updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
+ }
+
+ result = dns_request_create(requestmgr, updatemsg, srcaddr, primary,
+ options, tsigkey, timeout, udp_timeout,
+ udp_retries, global_task, update_completed,
+ NULL, &request);
+ check_result(result, "dns_request_create");
+
+ if (debugging) {
+ show_message(stdout, updatemsg, "Outgoing update query:");
+ }
+
+ requests++;
+}
+
+static void
+next_server(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) {
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
+ fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf,
+ isc_result_totext(eresult));
+ if (++ns_inuse >= ns_total) {
+ fatal("could not reach any name server");
+ } else {
+ ddebug("%s: trying next server", caller);
+ }
+}
+
+static void
+recvsoa(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = NULL;
+ dns_request_t *request = NULL;
+ isc_result_t result, eresult;
+ dns_message_t *rcvmsg = NULL;
+ dns_section_t section;
+ dns_name_t *name = NULL;
+ dns_rdataset_t *soaset = NULL;
+ dns_rdata_soa_t soa;
+ dns_rdata_t soarr = DNS_RDATA_INIT;
+ int pass = 0;
+ dns_name_t primary;
+ nsu_requestinfo_t *reqinfo;
+ dns_message_t *soaquery = NULL;
+ isc_sockaddr_t *addr;
+ isc_sockaddr_t *srcaddr;
+ bool seencname = false;
+ dns_name_t tname;
+ unsigned int nlabels;
+
+ UNUSED(task);
+
+ ddebug("recvsoa()");
+
+ requests--;
+
+ REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
+ reqev = (dns_requestevent_t *)event;
+ request = reqev->request;
+ eresult = reqev->result;
+ reqinfo = reqev->ev_arg;
+ soaquery = reqinfo->msg;
+ addr = reqinfo->addr;
+
+ if (shuttingdown) {
+ dns_request_destroy(&request);
+ dns_message_detach(&soaquery);
+ isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
+ isc_event_free(&event);
+ maybeshutdown();
+ return;
+ }
+
+ if (eresult != ISC_R_SUCCESS) {
+ next_server("recvsoa", addr, eresult);
+ ddebug("Destroying request [%p]", request);
+ dns_request_destroy(&request);
+ dns_message_renderreset(soaquery);
+ dns_message_settsigkey(soaquery, NULL);
+ sendrequest(&servers[ns_inuse], soaquery, &request);
+ isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
+ isc_event_free(&event);
+ setzoneclass(dns_rdataclass_none);
+ return;
+ }
+
+ isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
+ reqinfo = NULL;
+ isc_event_free(&event);
+ reqev = NULL;
+
+ ddebug("About to create rcvmsg");
+ dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
+ result = dns_request_getresponse(request, rcvmsg,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ if (result == DNS_R_TSIGERRORSET && servers != NULL) {
+ unsigned int options = 0;
+
+ dns_message_detach(&rcvmsg);
+ ddebug("Destroying request [%p]", request);
+ dns_request_destroy(&request);
+ reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
+ reqinfo->msg = soaquery;
+ reqinfo->addr = addr;
+ dns_message_renderreset(soaquery);
+ ddebug("retrying soa request without TSIG");
+
+ if (!default_servers && usevc) {
+ options |= DNS_REQUESTOPT_TCP;
+ }
+
+ if (isc_sockaddr_pf(addr) == AF_INET6) {
+ srcaddr = localaddr6;
+ } else {
+ srcaddr = localaddr4;
+ }
+
+ result = dns_request_create(requestmgr, soaquery, srcaddr, addr,
+ options, NULL, timeout, udp_timeout,
+ udp_retries, global_task, recvsoa,
+ reqinfo, &request);
+ check_result(result, "dns_request_create");
+ requests++;
+ return;
+ }
+ check_result(result, "dns_request_getresponse");
+
+ if (rcvmsg->rcode == dns_rcode_refused) {
+ next_server("recvsoa", addr, DNS_R_REFUSED);
+ dns_message_detach(&rcvmsg);
+ dns_request_destroy(&request);
+ dns_message_renderreset(soaquery);
+ dns_message_settsigkey(soaquery, NULL);
+ sendrequest(&servers[ns_inuse], soaquery, &request);
+ return;
+ }
+
+ section = DNS_SECTION_ANSWER;
+ POST(section);
+ if (debugging) {
+ show_message(stderr, rcvmsg, "Reply from SOA query:");
+ }
+
+ if (rcvmsg->opcode != dns_opcode_query) {
+ fatal("invalid OPCODE in response to SOA query");
+ }
+
+ if (rcvmsg->rcode != dns_rcode_noerror &&
+ rcvmsg->rcode != dns_rcode_nxdomain)
+ {
+ fatal("response to SOA query was unsuccessful");
+ }
+
+ if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(userzone, namebuf, sizeof(namebuf));
+ error("specified zone '%s' does not exist (NXDOMAIN)", namebuf);
+ dns_message_detach(&rcvmsg);
+ dns_request_destroy(&request);
+ dns_message_detach(&soaquery);
+ ddebug("Out of recvsoa");
+ seenerror = true;
+ done_update();
+ return;
+ }
+
+lookforsoa:
+ if (pass == 0) {
+ section = DNS_SECTION_ANSWER;
+ } else if (pass == 1) {
+ section = DNS_SECTION_AUTHORITY;
+ } else {
+ goto droplabel;
+ }
+
+ result = dns_message_firstname(rcvmsg, section);
+ if (result != ISC_R_SUCCESS) {
+ pass++;
+ goto lookforsoa;
+ }
+ while (result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(rcvmsg, section, &name);
+ soaset = NULL;
+ result = dns_message_findtype(name, dns_rdatatype_soa, 0,
+ &soaset);
+ if (result == ISC_R_SUCCESS) {
+ break;
+ }
+ if (section == DNS_SECTION_ANSWER) {
+ dns_rdataset_t *tset = NULL;
+ if (dns_message_findtype(name, dns_rdatatype_cname, 0,
+ &tset) == ISC_R_SUCCESS ||
+ dns_message_findtype(name, dns_rdatatype_dname, 0,
+ &tset) == ISC_R_SUCCESS)
+ {
+ seencname = true;
+ break;
+ }
+ }
+
+ result = dns_message_nextname(rcvmsg, section);
+ }
+
+ if (soaset == NULL && !seencname) {
+ pass++;
+ goto lookforsoa;
+ }
+
+ if (seencname) {
+ goto droplabel;
+ }
+
+ if (debugging) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ fprintf(stderr, "Found zone name: %s\n", namestr);
+ }
+
+ result = dns_rdataset_first(soaset);
+ check_result(result, "dns_rdataset_first");
+
+ dns_rdata_init(&soarr);
+ dns_rdataset_current(soaset, &soarr);
+ result = dns_rdata_tostruct(&soarr, &soa, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ dns_name_init(&primary, NULL);
+ dns_name_clone(&soa.origin, &primary);
+
+ if (userzone != NULL) {
+ zname = userzone;
+ } else {
+ /*
+ * Save the zone name in case we need to try a second
+ * address.
+ */
+ zname = dns_fixedname_initname(&fzname);
+ dns_name_copy(name, zname);
+ }
+
+ if (debugging) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(&primary, namestr, sizeof(namestr));
+ fprintf(stderr, "The primary is: %s\n", namestr);
+ }
+
+ if (default_servers) {
+ char serverstr[DNS_NAME_MAXTEXT + 1];
+ isc_buffer_t buf;
+ size_t size;
+
+ isc_buffer_init(&buf, serverstr, sizeof(serverstr));
+ result = dns_name_totext(&primary, true, &buf);
+ check_result(result, "dns_name_totext");
+ serverstr[isc_buffer_usedlength(&buf)] = 0;
+
+ if (primary_servers != NULL && primary_servers != servers) {
+ isc_mem_put(gmctx, primary_servers,
+ primary_alloc * sizeof(isc_sockaddr_t));
+ }
+ primary_alloc = MAX_SERVERADDRS;
+ size = primary_alloc * sizeof(isc_sockaddr_t);
+ primary_servers = isc_mem_get(gmctx, size);
+
+ memset(primary_servers, 0, size);
+ primary_total = get_addresses(serverstr, dnsport,
+ primary_servers, primary_alloc);
+ if (primary_total == 0) {
+ seenerror = true;
+ dns_rdata_freestruct(&soa);
+ dns_message_detach(&soaquery);
+ dns_request_destroy(&request);
+ dns_message_detach(&rcvmsg);
+ ddebug("Out of recvsoa");
+ done_update();
+ return;
+ }
+ primary_inuse = 0;
+ } else {
+ primary_from_servers();
+ }
+ dns_rdata_freestruct(&soa);
+
+#if HAVE_GSSAPI
+ if (usegsstsig) {
+ dns_name_init(&tmpzonename, NULL);
+ dns_name_dup(zname, gmctx, &tmpzonename);
+ dns_name_init(&restart_primary, NULL);
+ dns_name_dup(&primary, gmctx, &restart_primary);
+ start_gssrequest(&primary);
+ } else {
+ send_update(zname, &primary_servers[primary_inuse]);
+ setzoneclass(dns_rdataclass_none);
+ }
+#else /* HAVE_GSSAPI */
+ send_update(zname, &primary_servers[primary_inuse]);
+ setzoneclass(dns_rdataclass_none);
+#endif /* HAVE_GSSAPI */
+
+ dns_message_detach(&soaquery);
+ dns_request_destroy(&request);
+
+out:
+ dns_message_detach(&rcvmsg);
+ ddebug("Out of recvsoa");
+ return;
+
+droplabel:
+ result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
+ INSIST(result == ISC_R_SUCCESS);
+ name = NULL;
+ dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
+ nlabels = dns_name_countlabels(name);
+ if (nlabels == 1) {
+ fatal("could not find enclosing zone");
+ }
+ dns_name_init(&tname, NULL);
+ dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
+ dns_name_clone(&tname, name);
+ dns_request_destroy(&request);
+ dns_message_renderreset(soaquery);
+ dns_message_settsigkey(soaquery, NULL);
+ sendrequest(&servers[ns_inuse], soaquery, &request);
+ goto out;
+}
+
+static void
+sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
+ dns_request_t **request) {
+ isc_result_t result;
+ nsu_requestinfo_t *reqinfo;
+ isc_sockaddr_t *srcaddr;
+ unsigned int options = 0;
+
+ if (!default_servers && usevc) {
+ options |= DNS_REQUESTOPT_TCP;
+ }
+
+ reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
+ reqinfo->msg = msg;
+ reqinfo->addr = destaddr;
+
+ if (isc_sockaddr_pf(destaddr) == AF_INET6) {
+ srcaddr = localaddr6;
+ } else {
+ srcaddr = localaddr4;
+ }
+
+ result = dns_request_create(requestmgr, msg, srcaddr, destaddr, options,
+ default_servers ? NULL : tsigkey, timeout,
+ udp_timeout, udp_retries, global_task,
+ recvsoa, reqinfo, request);
+ check_result(result, "dns_request_create");
+ requests++;
+}
+
+#if HAVE_GSSAPI
+
+/*
+ * Get the realm from the users kerberos ticket if possible
+ */
+static void
+get_ticket_realm(isc_mem_t *mctx) {
+ krb5_context ctx;
+ krb5_error_code rc;
+ krb5_ccache ccache;
+ krb5_principal princ;
+ char *name;
+ const char *ticket_realm;
+
+ rc = krb5_init_context(&ctx);
+ if (rc != 0) {
+ return;
+ }
+
+ rc = krb5_cc_default(ctx, &ccache);
+ if (rc != 0) {
+ krb5_free_context(ctx);
+ return;
+ }
+
+ rc = krb5_cc_get_principal(ctx, ccache, &princ);
+ if (rc != 0) {
+ krb5_cc_close(ctx, ccache);
+ krb5_free_context(ctx);
+ return;
+ }
+
+ rc = krb5_unparse_name(ctx, princ, &name);
+ if (rc != 0) {
+ krb5_free_principal(ctx, princ);
+ krb5_cc_close(ctx, ccache);
+ krb5_free_context(ctx);
+ return;
+ }
+
+ ticket_realm = strrchr(name, '@');
+ if (ticket_realm != NULL) {
+ realm = isc_mem_strdup(mctx, ticket_realm);
+ }
+
+ free(name);
+ krb5_free_principal(ctx, princ);
+ krb5_cc_close(ctx, ccache);
+ krb5_free_context(ctx);
+ if (realm != NULL && debugging) {
+ fprintf(stderr, "Found realm from ticket: %s\n", realm + 1);
+ }
+}
+
+static void
+failed_gssrequest(void) {
+ seenerror = true;
+
+ dns_name_free(&tmpzonename, gmctx);
+ dns_name_free(&restart_primary, gmctx);
+ dns_name_init(&tmpzonename, NULL);
+ dns_name_init(&restart_primary, NULL);
+
+ done_update();
+}
+
+static void
+start_gssrequest(dns_name_t *primary) {
+ dns_gss_ctx_id_t context;
+ isc_buffer_t buf;
+ isc_result_t result;
+ uint32_t val = 0;
+ dns_message_t *rmsg = NULL;
+ dns_request_t *request = NULL;
+ dns_name_t *servname;
+ dns_fixedname_t fname;
+ char namestr[DNS_NAME_FORMATSIZE];
+ char mykeystr[DNS_NAME_FORMATSIZE];
+ char *err_message = NULL;
+
+ debug("start_gssrequest");
+ usevc = true;
+
+ if (gssring != NULL) {
+ dns_tsigkeyring_detach(&gssring);
+ }
+ gssring = NULL;
+ result = dns_tsigkeyring_create(gmctx, &gssring);
+
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_tsigkeyring_create failed: %s",
+ isc_result_totext(result));
+ }
+
+ dns_name_format(primary, namestr, sizeof(namestr));
+ if (kserver == NULL) {
+ kserver = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
+ }
+
+ memmove(kserver, &primary_servers[primary_inuse],
+ sizeof(isc_sockaddr_t));
+
+ servname = dns_fixedname_initname(&fname);
+
+ if (realm == NULL) {
+ get_ticket_realm(gmctx);
+ }
+
+ result = snprintf(servicename, sizeof(servicename), "DNS/%s%s", namestr,
+ realm ? realm : "");
+ RUNTIME_CHECK(result < sizeof(servicename));
+ isc_buffer_init(&buf, servicename, strlen(servicename));
+ isc_buffer_add(&buf, strlen(servicename));
+ result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_name_fromtext(servname) failed: %s",
+ isc_result_totext(result));
+ }
+
+ keyname = dns_fixedname_initname(&fkname);
+
+ isc_nonce_buf(&val, sizeof(val));
+
+ result = snprintf(mykeystr, sizeof(mykeystr), "%u.sig-%s", val,
+ namestr);
+ RUNTIME_CHECK(result <= sizeof(mykeystr));
+
+ isc_buffer_init(&buf, mykeystr, strlen(mykeystr));
+ isc_buffer_add(&buf, strlen(mykeystr));
+
+ result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_name_fromtext(keyname) failed: %s",
+ isc_result_totext(result));
+ }
+
+ /* Windows doesn't recognize name compression in the key name. */
+ keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
+
+ rmsg = NULL;
+ dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
+
+ /* Build first request. */
+ context = GSS_C_NO_CONTEXT;
+ result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
+ &context, use_win2k_gsstsig, gmctx,
+ &err_message);
+ if (result == ISC_R_FAILURE) {
+ fprintf(stderr, "tkey query failed: %s\n",
+ err_message != NULL ? err_message : "unknown error");
+ goto failure;
+ }
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_tkey_buildgssquery failed: %s",
+ isc_result_totext(result));
+ }
+
+ send_gssrequest(kserver, rmsg, &request, context);
+ return;
+
+failure:
+ if (rmsg != NULL) {
+ dns_message_detach(&rmsg);
+ }
+ if (err_message != NULL) {
+ isc_mem_free(gmctx, err_message);
+ }
+ failed_gssrequest();
+}
+
+static void
+send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
+ dns_request_t **request, gss_ctx_id_t context) {
+ isc_result_t result;
+ nsu_gssinfo_t *reqinfo;
+ unsigned int options = 0;
+ isc_sockaddr_t *srcaddr;
+
+ debug("send_gssrequest");
+ REQUIRE(destaddr != NULL);
+
+ reqinfo = isc_mem_get(gmctx, sizeof(nsu_gssinfo_t));
+ reqinfo->msg = msg;
+ reqinfo->addr = destaddr;
+ reqinfo->context = context;
+
+ options |= DNS_REQUESTOPT_TCP;
+
+ if (isc_sockaddr_pf(destaddr) == AF_INET6) {
+ srcaddr = localaddr6;
+ } else {
+ srcaddr = localaddr4;
+ }
+
+ result = dns_request_create(requestmgr, msg, srcaddr, destaddr, options,
+ tsigkey, timeout, udp_timeout, udp_retries,
+ global_task, recvgss, reqinfo, request);
+ check_result(result, "dns_request_create");
+ if (debugging) {
+ show_message(stdout, msg, "Outgoing update query:");
+ }
+ requests++;
+}
+
+static void
+recvgss(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = NULL;
+ dns_request_t *request = NULL;
+ isc_result_t result, eresult;
+ dns_message_t *rcvmsg = NULL;
+ nsu_gssinfo_t *reqinfo;
+ dns_message_t *tsigquery = NULL;
+ isc_sockaddr_t *addr;
+ dns_gss_ctx_id_t context;
+ isc_buffer_t buf;
+ dns_name_t *servname;
+ dns_fixedname_t fname;
+ char *err_message = NULL;
+
+ UNUSED(task);
+
+ ddebug("recvgss()");
+
+ requests--;
+
+ REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
+ reqev = (dns_requestevent_t *)event;
+ request = reqev->request;
+ eresult = reqev->result;
+ reqinfo = reqev->ev_arg;
+ tsigquery = reqinfo->msg;
+ context = reqinfo->context;
+ addr = reqinfo->addr;
+
+ if (shuttingdown) {
+ dns_request_destroy(&request);
+ dns_message_detach(&tsigquery);
+ isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
+ isc_event_free(&event);
+ maybeshutdown();
+ return;
+ }
+
+ if (eresult != ISC_R_SUCCESS) {
+ ddebug("Destroying request [%p]", request);
+ dns_request_destroy(&request);
+ if (!next_primary("recvgss", addr, eresult)) {
+ dns_message_detach(&tsigquery);
+ failed_gssrequest();
+ } else {
+ dns_message_renderreset(tsigquery);
+ memmove(kserver, &primary_servers[primary_inuse],
+ sizeof(isc_sockaddr_t));
+ send_gssrequest(kserver, tsigquery, &request, context);
+ }
+ isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
+ isc_event_free(&event);
+ return;
+ }
+ isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
+
+ isc_event_free(&event);
+ reqev = NULL;
+
+ ddebug("recvgss creating rcvmsg");
+ dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
+
+ result = dns_request_getresponse(request, rcvmsg,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ check_result(result, "dns_request_getresponse");
+
+ if (debugging) {
+ show_message(stderr, rcvmsg,
+ "recvmsg reply from GSS-TSIG query");
+ }
+
+ if (rcvmsg->opcode != dns_opcode_query) {
+ fatal("invalid OPCODE in response to GSS-TSIG query");
+ }
+
+ if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
+ ddebug("recvgss trying %s GSS-TSIG",
+ use_win2k_gsstsig ? "Standard" : "Win2k");
+ if (use_win2k_gsstsig) {
+ use_win2k_gsstsig = false;
+ } else {
+ use_win2k_gsstsig = true;
+ }
+ tried_other_gsstsig = true;
+ start_gssrequest(&restart_primary);
+ goto done;
+ }
+
+ if (rcvmsg->rcode != dns_rcode_noerror &&
+ rcvmsg->rcode != dns_rcode_nxdomain)
+ {
+ char rcode[64];
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, rcode, sizeof(rcode) - 1);
+ result = dns_rcode_totext(rcvmsg->rcode, &b);
+ check_result(result, "dns_rcode_totext");
+ rcode[isc_buffer_usedlength(&b)] = 0;
+
+ fatal("response to GSS-TSIG query was unsuccessful (%s)",
+ rcode);
+ }
+
+ servname = dns_fixedname_initname(&fname);
+ isc_buffer_init(&buf, servicename, strlen(servicename));
+ isc_buffer_add(&buf, strlen(servicename));
+ result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
+ check_result(result, "dns_name_fromtext");
+
+ tsigkey = NULL;
+ result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, &context,
+ &tsigkey, gssring, use_win2k_gsstsig,
+ &err_message);
+ switch (result) {
+ case DNS_R_CONTINUE:
+ dns_message_detach(&rcvmsg);
+ dns_request_destroy(&request);
+ send_gssrequest(kserver, tsigquery, &request, context);
+ ddebug("Out of recvgss");
+ return;
+
+ case ISC_R_SUCCESS:
+ /*
+ * XXXSRA Waaay too much fun here. There's no good
+ * reason why we need a TSIG here (the people who put
+ * it into the spec admitted at the time that it was
+ * not a security issue), and Windows clients don't
+ * seem to work if named complies with the spec and
+ * includes the gratuitous TSIG. So we're in the
+ * bizarre situation of having to choose between
+ * complying with a useless requirement in the spec
+ * and interoperating. This is nuts. If we can
+ * confirm this behavior, we should ask the WG to
+ * consider removing the requirement for the
+ * gratuitous TSIG here. For the moment, we ignore
+ * the TSIG -- this too is a spec violation, but it's
+ * the least insane thing to do.
+ */
+#if 0
+ /*
+ * Verify the signature.
+ */
+ rcvmsg->state = DNS_SECTION_ANY;
+ dns_message_setquerytsig(rcvmsg, NULL);
+ result = dns_message_settsigkey(rcvmsg, tsigkey);
+ check_result(result, "dns_message_settsigkey");
+ result = dns_message_checksig(rcvmsg, NULL);
+ ddebug("tsig verification: %s", isc_result_totext(result));
+ check_result(result, "dns_message_checksig");
+#endif /* 0 */
+
+ send_update(&tmpzonename, &primary_servers[primary_inuse]);
+ setzoneclass(dns_rdataclass_none);
+ break;
+
+ default:
+ fatal("dns_tkey_gssnegotiate: %s %s", isc_result_totext(result),
+ err_message != NULL ? err_message : "");
+ }
+
+done:
+ dns_request_destroy(&request);
+ dns_message_detach(&tsigquery);
+
+ dns_message_detach(&rcvmsg);
+ ddebug("Out of recvgss");
+}
+#endif /* HAVE_GSSAPI */
+
+static void
+start_update(void) {
+ isc_result_t result;
+ dns_rdataset_t *rdataset = NULL;
+ dns_name_t *name = NULL;
+ dns_request_t *request = NULL;
+ dns_message_t *soaquery = NULL;
+ dns_name_t *firstname;
+ dns_section_t section = DNS_SECTION_UPDATE;
+
+ ddebug("start_update()");
+
+ LOCK(&answer_lock);
+ if (answer != NULL) {
+ dns_message_detach(&answer);
+ }
+ UNLOCK(&answer_lock);
+
+ /*
+ * If we have both the zone and the servers we have enough information
+ * to send the update straight away otherwise we need to discover
+ * the zone and / or the primary server.
+ */
+ if (userzone != NULL && !default_servers && !usegsstsig) {
+ primary_from_servers();
+ send_update(userzone, &primary_servers[primary_inuse]);
+ setzoneclass(dns_rdataclass_none);
+ return;
+ }
+
+ dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &soaquery);
+
+ if (default_servers) {
+ soaquery->flags |= DNS_MESSAGEFLAG_RD;
+ }
+
+ result = dns_message_gettempname(soaquery, &name);
+ check_result(result, "dns_message_gettempname");
+
+ result = dns_message_gettemprdataset(soaquery, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+
+ dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
+
+ if (userzone != NULL) {
+ dns_name_clone(userzone, name);
+ } else {
+ dns_rdataset_t *tmprdataset;
+ result = dns_message_firstname(updatemsg, section);
+ if (result == ISC_R_NOMORE) {
+ section = DNS_SECTION_PREREQUISITE;
+ result = dns_message_firstname(updatemsg, section);
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(soaquery, &name);
+ dns_rdataset_disassociate(rdataset);
+ dns_message_puttemprdataset(soaquery, &rdataset);
+ dns_message_detach(&soaquery);
+ done_update();
+ return;
+ }
+ firstname = NULL;
+ dns_message_currentname(updatemsg, section, &firstname);
+ dns_name_clone(firstname, name);
+ /*
+ * Looks to see if the first name references a DS record
+ * and if that name is not the root remove a label as DS
+ * records live in the parent zone so we need to start our
+ * search one label up.
+ */
+ tmprdataset = ISC_LIST_HEAD(firstname->list);
+ if (section == DNS_SECTION_UPDATE &&
+ !dns_name_equal(firstname, dns_rootname) &&
+ tmprdataset->type == dns_rdatatype_ds)
+ {
+ unsigned int labels = dns_name_countlabels(name);
+ dns_name_getlabelsequence(name, 1, labels - 1, name);
+ }
+ }
+
+ ISC_LIST_INIT(name->list);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
+
+ ns_inuse = 0;
+ sendrequest(&servers[ns_inuse], soaquery, &request);
+}
+
+static void
+cleanup(void) {
+ ddebug("cleanup()");
+
+ LOCK(&answer_lock);
+ if (answer != NULL) {
+ dns_message_detach(&answer);
+ }
+ UNLOCK(&answer_lock);
+
+ ddebug("Shutting down managers");
+ isc_managers_destroy(&netmgr, &taskmgr, NULL);
+
+#if HAVE_GSSAPI
+ if (tsigkey != NULL) {
+ ddebug("detach tsigkey x%p", tsigkey);
+ dns_tsigkey_detach(&tsigkey);
+ }
+ if (gssring != NULL) {
+ ddebug("Detaching GSS-TSIG keyring");
+ dns_tsigkeyring_detach(&gssring);
+ }
+#endif /* ifdef HAVE_GSSAPI */
+
+ if (sig0key != NULL) {
+ dst_key_free(&sig0key);
+ }
+
+ ddebug("Destroying event");
+ isc_event_free(&global_event);
+
+#ifdef HAVE_GSSAPI
+ /*
+ * Cleanup GSSAPI resources after taskmgr has been destroyed.
+ */
+ if (kserver != NULL) {
+ isc_mem_put(gmctx, kserver, sizeof(isc_sockaddr_t));
+ kserver = NULL;
+ }
+ if (realm != NULL) {
+ isc_mem_free(gmctx, realm);
+ realm = NULL;
+ }
+ if (dns_name_dynamic(&tmpzonename)) {
+ dns_name_free(&tmpzonename, gmctx);
+ }
+ if (dns_name_dynamic(&restart_primary)) {
+ dns_name_free(&restart_primary, gmctx);
+ }
+#endif /* ifdef HAVE_GSSAPI */
+
+ ddebug("Removing log context");
+ isc_log_destroy(&glctx);
+
+ ddebug("Destroying memory context");
+ if (memdebugging) {
+ isc_mem_stats(gmctx, stderr);
+ }
+ isc_mem_destroy(&gmctx);
+
+ isc_mutex_destroy(&answer_lock);
+
+ if (is_dst_up) {
+ ddebug("Destroy DST lib");
+ dst_lib_destroy();
+ is_dst_up = false;
+ }
+}
+
+static void
+getinput(isc_task_t *task, isc_event_t *event) {
+ bool more;
+
+ UNUSED(task);
+
+ if (shuttingdown) {
+ maybeshutdown();
+ return;
+ }
+
+ if (global_event == NULL) {
+ global_event = event;
+ }
+
+ reset_system();
+ more = user_interaction();
+ if (!more) {
+ isc_app_shutdown();
+ return;
+ }
+ start_update();
+ return;
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+ uint32_t timeoutms;
+
+ style = &dns_master_style_debug;
+
+ input = stdin;
+
+ interactive = isatty(0);
+
+ isc_app_start();
+
+ if (isc_net_probeipv4() == ISC_R_SUCCESS) {
+ have_ipv4 = true;
+ }
+ if (isc_net_probeipv6() == ISC_R_SUCCESS) {
+ have_ipv6 = true;
+ }
+ if (!have_ipv4 && !have_ipv6) {
+ fatal("could not find either IPv4 or IPv6");
+ }
+
+ pre_parse_args(argc, argv);
+
+ isc_mem_create(&gmctx);
+
+ parse_args(argc, argv);
+
+ setup_system();
+
+ /* Set the network manager timeouts in milliseconds. */
+ timeoutms = timeout * 1000;
+ isc_nm_settimeouts(netmgr, timeoutms, timeoutms, timeoutms, timeoutms);
+
+ result = isc_app_onrun(gmctx, global_task, getinput, NULL);
+ check_result(result, "isc_app_onrun");
+
+ (void)isc_app_run();
+
+ cleanup();
+
+ isc_app_finish();
+
+ if (seenerror) {
+ return (2);
+ } else {
+ return (0);
+ }
+}
diff --git a/bin/nsupdate/nsupdate.rst b/bin/nsupdate/nsupdate.rst
new file mode 100644
index 0000000..81bb481
--- /dev/null
+++ b/bin/nsupdate/nsupdate.rst
@@ -0,0 +1,391 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. iscman:: nsupdate
+.. program:: nsupdate
+.. _man_nsupdate:
+
+nsupdate - dynamic DNS update utility
+-------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`nsupdate` [**-d**] [**-D**] [**-i**] [**-L** level] [ [**-g**] | [**-o**] | [**-l**] | [**-y** [hmac:]keyname:secret] | [**-k** keyfile] ] [**-t** timeout] [**-u** udptimeout] [**-r** udpretries] [**-v**] [**-T**] [**-P**] [**-V**] [ [**-4**] | [**-6**] ] [filename]
+
+Description
+~~~~~~~~~~~
+
+:program:`nsupdate` is used to submit Dynamic DNS Update requests, as defined in
+:rfc:`2136`, to a name server. This allows resource records to be added or
+removed from a zone without manually editing the zone file. A single
+update request can contain requests to add or remove more than one
+resource record.
+
+Zones that are under dynamic control via :program:`nsupdate` or a DHCP server
+should not be edited by hand. Manual edits could conflict with dynamic
+updates and cause data to be lost.
+
+The resource records that are dynamically added or removed with
+:program:`nsupdate` must be in the same zone. Requests are sent to the
+zone's primary server, which is identified by the MNAME field of the
+zone's SOA record.
+
+Transaction signatures can be used to authenticate the Dynamic DNS
+updates. These use the TSIG resource record type described in :rfc:`2845`,
+the SIG(0) record described in :rfc:`2535` and :rfc:`2931`, or GSS-TSIG as
+described in :rfc:`3645`.
+
+TSIG relies on a shared secret that should only be known to :program:`nsupdate`
+and the name server. For instance, suitable ``key`` and ``server``
+statements are added to |named_conf| so that the name server
+can associate the appropriate secret key and algorithm with the IP
+address of the client application that is using TSIG
+authentication. :iscman:`ddns-confgen` can generate suitable
+configuration fragments. :program:`nsupdate` uses the :option:`-y` or :option:`-k` options
+to provide the TSIG shared secret; these options are mutually exclusive.
+
+SIG(0) uses public key cryptography. To use a SIG(0) key, the public key
+must be stored in a KEY record in a zone served by the name server.
+
+GSS-TSIG uses Kerberos credentials. Standard GSS-TSIG mode is switched
+on with the :option:`-g` flag. A non-standards-compliant variant of GSS-TSIG
+used by Windows 2000 can be switched on with the :option:`-o` flag.
+
+Options
+~~~~~~~
+
+.. option:: -4
+
+ This option sets use of IPv4 only.
+
+.. option:: -6
+
+ This option sets use of IPv6 only.
+
+.. option:: -C
+
+ Overrides the default `resolv.conf` file. This is only intended for testing.
+
+.. option:: -d
+
+ This option sets debug mode, which provides tracing information about the update
+ requests that are made and the replies received from the name server.
+
+.. option:: -D
+
+ This option sets extra debug mode.
+
+.. option:: -g
+
+ This option enables standard GSS-TSIG mode.
+
+.. option:: -i
+
+ This option forces interactive mode, even when standard input is not a terminal.
+
+.. option:: -k keyfile
+
+ This option indicates the file containing the TSIG authentication key. Keyfiles may be in
+ two formats: a single file containing a :iscman:`named.conf`-format ``key``
+ statement, which may be generated automatically by :iscman:`ddns-confgen`;
+ or a pair of files whose names are of the format
+ ``K{name}.+157.+{random}.key`` and
+ ``K{name}.+157.+{random}.private``, which can be generated by
+ :iscman:`dnssec-keygen`. The :option:`-k` option can also be used to specify a SIG(0)
+ key used to authenticate Dynamic DNS update requests. In this case,
+ the key specified is not an HMAC-MD5 key.
+
+.. option:: -l
+
+ This option sets local-host only mode, which sets the server address to localhost
+ (disabling the ``server`` so that the server address cannot be
+ overridden). Connections to the local server use a TSIG key
+ found in |session_key|, which is automatically
+ generated by :iscman:`named` if any local ``primary`` zone has set
+ ``update-policy`` to ``local``. The location of this key file can be
+ overridden with the :option:`-k` option.
+
+.. option:: -L level
+
+ This option sets the logging debug level. If zero, logging is disabled.
+
+.. option:: -o
+
+ This option enables a non-standards-compliant variant of GSS-TSIG
+ used by Windows 2000.
+
+.. option:: -p port
+
+ This option sets the port to use for connections to a name server. The default is
+ 53.
+
+.. option:: -P
+
+ This option prints the list of private BIND-specific resource record types whose
+ format is understood by :program:`nsupdate`. See also the :option:`-T` option.
+
+.. option:: -r udpretries
+
+ This option sets the number of UDP retries. The default is 3. If zero, only one update
+ request is made.
+
+.. option:: -t timeout
+
+ This option sets the maximum time an update request can take before it is aborted. The
+ default is 300 seconds. If zero, the timeout is disabled for TCP mode. For UDP mode,
+ the option :option:`-u` takes precedence over this option, unless the option :option:`-u`
+ is set to zero, in which case the interval is computed from the :option:`-t` timeout interval
+ and the number of UDP retries. For UDP mode, the timeout can not be disabled, and will
+ be rounded up to 1 second in case if both :option:`-t` and :option:`-u` are set to zero.
+
+.. option:: -T
+
+ This option prints the list of IANA standard resource record types whose format is
+ understood by :program:`nsupdate`. :program:`nsupdate` exits after the lists
+ are printed. The :option:`-T` option can be combined with the :option:`-P`
+ option.
+
+ Other types can be entered using ``TYPEXXXXX`` where ``XXXXX`` is the
+ decimal value of the type with no leading zeros. The rdata, if
+ present, is parsed using the UNKNOWN rdata format, (<backslash>
+ <hash> <space> <length> <space> <hexstring>).
+
+.. option:: -u udptimeout
+
+ This option sets the UDP retry interval. The default is 3 seconds. If zero, the
+ interval is computed from the timeout interval and number of UDP
+ retries.
+
+.. option:: -v
+
+ This option specifies that TCP should be used even for small update requests. By default, :program:`nsupdate` uses
+ UDP to send update requests to the name server unless they are too
+ large to fit in a UDP request, in which case TCP is used. TCP may
+ be preferable when a batch of update requests is made.
+
+.. option:: -V
+
+ This option prints the version number and exits.
+
+.. option:: -y [hmac:]keyname:secret
+
+ This option sets the literal TSIG authentication key. ``keyname`` is the name of the key,
+ and ``secret`` is the base64 encoded shared secret. ``hmac`` is the
+ name of the key algorithm; valid choices are ``hmac-md5``,
+ ``hmac-sha1``, ``hmac-sha224``, ``hmac-sha256``, ``hmac-sha384``, or
+ ``hmac-sha512``. If ``hmac`` is not specified, the default is
+ ``hmac-md5``, or if MD5 was disabled, ``hmac-sha256``.
+
+ NOTE: Use of the :option:`-y` option is discouraged because the shared
+ secret is supplied as a command-line argument in clear text. This may
+ be visible in the output from ps1 or in a history file maintained by
+ the user's shell.
+
+Input Format
+~~~~~~~~~~~~
+
+:program:`nsupdate` reads input from ``filename`` or standard input. Each
+command is supplied on exactly one line of input. Some commands are for
+administrative purposes; others are either update instructions or
+prerequisite checks on the contents of the zone. These checks set
+conditions that some name or set of resource records (RRset) either
+exists or is absent from the zone. These conditions must be met if the
+entire update request is to succeed. Updates are rejected if the
+tests for the prerequisite conditions fail.
+
+Every update request consists of zero or more prerequisites and zero or
+more updates. This allows a suitably authenticated update request to
+proceed if some specified resource records are either present or missing from
+the zone. A blank input line (or the ``send`` command) causes the
+accumulated commands to be sent as one Dynamic DNS update request to the
+name server.
+
+The command formats and their meanings are as follows:
+
+``server servername port``
+ This command sends all dynamic update requests to the name server ``servername``.
+ When no server statement is provided, :program:`nsupdate` sends updates
+ to the primary server of the correct zone. The MNAME field of that
+ zone's SOA record identify the primary server for that zone.
+ ``port`` is the port number on ``servername`` where the dynamic
+ update requests are sent. If no port number is specified, the default
+ DNS port number of 53 is used.
+
+ .. note:: This command has no effect when GSS-TSIG is in use.
+
+``local address port``
+ This command sends all dynamic update requests using the local ``address``. When
+ no local statement is provided, :program:`nsupdate` sends updates using
+ an address and port chosen by the system. ``port`` can also
+ be used to force requests to come from a specific port. If no port number
+ is specified, the system assigns one.
+
+``zone zonename``
+ This command specifies that all updates are to be made to the zone ``zonename``.
+ If no ``zone`` statement is provided, :program:`nsupdate` attempts to
+ determine the correct zone to update based on the rest of the input.
+
+``class classname``
+ This command specifies the default class. If no ``class`` is specified, the default
+ class is ``IN``.
+
+``ttl seconds``
+ This command specifies the default time-to-live, in seconds, for records to be added. The value
+ ``none`` clears the default TTL.
+
+``key hmac:keyname secret``
+ This command specifies that all updates are to be TSIG-signed using the
+ ``keyname``-``secret`` pair. If ``hmac`` is specified, it sets
+ the signing algorithm in use. The default is ``hmac-md5``; if MD5
+ was disabled, the default is ``hmac-sha256``. The ``key`` command overrides any key
+ specified on the command line via :option:`-y` or :option:`-k`.
+
+``gsstsig``
+ This command uses GSS-TSIG to sign the updates. This is equivalent to specifying
+ :option:`-g` on the command line.
+
+``oldgsstsig``
+ This command uses the Windows 2000 version of GSS-TSIG to sign the updates. This is
+ equivalent to specifying :option:`-o` on the command line.
+
+``realm [realm_name]``
+ When using GSS-TSIG, this command specifies the use of ``realm_name`` rather than the default realm
+ in ``krb5.conf``. If no realm is specified, the saved realm is
+ cleared.
+
+``check-names [boolean]``
+ This command turns on or off check-names processing on records to be added.
+ Check-names has no effect on prerequisites or records to be deleted.
+ By default check-names processing is on. If check-names processing
+ fails, the record is not added to the UPDATE message.
+
+``prereq nxdomain domain-name``
+ This command requires that no resource record of any type exist with the name
+ ``domain-name``.
+
+``prereq yxdomain domain-name``
+ This command requires that ``domain-name`` exist (as at least one resource
+ record, of any type).
+
+``prereq nxrrset domain-name class type``
+ This command requires that no resource record exist of the specified ``type``,
+ ``class``, and ``domain-name``. If ``class`` is omitted, IN (Internet)
+ is assumed.
+
+``prereq yxrrset domain-name class type``
+ This command requires that a resource record of the specified ``type``,
+ ``class`` and ``domain-name`` exist. If ``class`` is omitted, IN
+ (internet) is assumed.
+
+``prereq yxrrset domain-name class type data``
+ With this command, the ``data`` from each set of prerequisites of this form sharing a
+ common ``type``, ``class``, and ``domain-name`` are combined to form
+ a set of RRs. This set of RRs must exactly match the set of RRs
+ existing in the zone at the given ``type``, ``class``, and
+ ``domain-name``. The ``data`` are written in the standard text
+ representation of the resource record's RDATA.
+
+``update delete domain-name ttl class type data``
+ This command deletes any resource records named ``domain-name``. If ``type`` and
+ ``data`` are provided, only matching resource records are removed.
+ The Internet class is assumed if ``class`` is not supplied. The
+ ``ttl`` is ignored, and is only allowed for compatibility.
+
+``update add domain-name ttl class type data``
+ This command adds a new resource record with the specified ``ttl``, ``class``, and
+ ``data``.
+
+``show``
+ This command displays the current message, containing all of the prerequisites and
+ updates specified since the last send.
+
+``send``
+ This command sends the current message. This is equivalent to entering a blank
+ line.
+
+``answer``
+ This command displays the answer.
+
+``debug``
+ This command turns on debugging.
+
+``version``
+ This command prints the version number.
+
+``help``
+ This command prints a list of commands.
+
+Lines beginning with a semicolon (;) are comments and are ignored.
+
+Examples
+~~~~~~~~
+
+The examples below show how :program:`nsupdate` can be used to insert and
+delete resource records from the ``example.com`` zone. Notice that the
+input in each example contains a trailing blank line, so that a group of
+commands is sent as one dynamic update request to the primary name
+server for ``example.com``.
+
+::
+
+ # nsupdate
+ > update delete oldhost.example.com A
+ > update add newhost.example.com 86400 A 172.16.1.1
+ > send
+
+Any A records for ``oldhost.example.com`` are deleted, and an A record
+for ``newhost.example.com`` with IP address 172.16.1.1 is added. The
+newly added record has a TTL of 1 day (86400 seconds).
+
+::
+
+ # nsupdate
+ > prereq nxdomain nickname.example.com
+ > update add nickname.example.com 86400 CNAME somehost.example.com
+ > send
+
+The prerequisite condition tells the name server to verify that there are
+no resource records of any type for ``nickname.example.com``. If there
+are, the update request fails. If this name does not exist, a CNAME for
+it is added. This ensures that when the CNAME is added, it cannot
+conflict with the long-standing rule in :rfc:`1034` that a name must not
+exist as any other record type if it exists as a CNAME. (The rule has
+been updated for DNSSEC in :rfc:`2535` to allow CNAMEs to have RRSIG,
+DNSKEY, and NSEC records.)
+
+Files
+~~~~~
+
+``/etc/resolv.conf``
+ Used to identify the default name server
+
+|session_key|
+ Sets the default TSIG key for use in local-only mode
+
+``K{name}.+157.+{random}.key``
+ Base-64 encoding of the HMAC-MD5 key created by :iscman:`dnssec-keygen`.
+
+``K{name}.+157.+{random}.private``
+ Base-64 encoding of the HMAC-MD5 key created by :iscman:`dnssec-keygen`.
+
+See Also
+~~~~~~~~
+
+:rfc:`2136`, :rfc:`3007`, :rfc:`2104`, :rfc:`2845`, :rfc:`1034`, :rfc:`2535`, :rfc:`2931`,
+:iscman:`named(8) <named>`, :iscman:`dnssec-keygen(8) <dnssec-keygen>`, :iscman:`tsig-keygen(8) <tsig-keygen>`.
+
+Bugs
+~~~~
+
+The TSIG key is redundantly stored in two separate files. This is a
+consequence of :program:`nsupdate` using the DST library for its cryptographic
+operations, and may change in future releases.
diff --git a/bin/plugins/Makefile.am b/bin/plugins/Makefile.am
new file mode 100644
index 0000000..611dd1b
--- /dev/null
+++ b/bin/plugins/Makefile.am
@@ -0,0 +1,15 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) \
+ $(LIBNS_CFLAGS) \
+ $(LIBISCCFG_CFLAGS)
+
+pkglib_LTLIBRARIES = filter-aaaa.la
+pkglib_LTLIBRARIES += filter-a.la
+
+filter_aaaa_la_SOURCES = filter-aaaa.c
+filter_a_la_SOURCES = filter-a.c
+filter_aaaa_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
+filter_a_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
diff --git a/bin/plugins/Makefile.in b/bin/plugins/Makefile.in
new file mode 100644
index 0000000..b1d1bb8
--- /dev/null
+++ b/bin/plugins/Makefile.in
@@ -0,0 +1,847 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+subdir = bin/plugins
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+filter_a_la_LIBADD =
+am_filter_a_la_OBJECTS = filter-a.lo
+filter_a_la_OBJECTS = $(am_filter_a_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+filter_a_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(filter_a_la_LDFLAGS) $(LDFLAGS) -o $@
+filter_aaaa_la_LIBADD =
+am_filter_aaaa_la_OBJECTS = filter-aaaa.lo
+filter_aaaa_la_OBJECTS = $(am_filter_aaaa_la_OBJECTS)
+filter_aaaa_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(filter_aaaa_la_LDFLAGS) $(LDFLAGS) -o \
+ $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/filter-a.Plo \
+ ./$(DEPDIR)/filter-aaaa.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(filter_a_la_SOURCES) $(filter_aaaa_la_SOURCES)
+DIST_SOURCES = $(filter_a_la_SOURCES) $(filter_aaaa_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \
+ $(LIBNS_CFLAGS) $(LIBISCCFG_CFLAGS)
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD =
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+pkglib_LTLIBRARIES = filter-aaaa.la filter-a.la
+filter_aaaa_la_SOURCES = filter-aaaa.c
+filter_a_la_SOURCES = filter-a.c
+filter_aaaa_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
+filter_a_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/plugins/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/plugins/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \
+ }
+
+uninstall-pkglibLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \
+ done
+
+clean-pkglibLTLIBRARIES:
+ -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
+ @list='$(pkglib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+filter-a.la: $(filter_a_la_OBJECTS) $(filter_a_la_DEPENDENCIES) $(EXTRA_filter_a_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(filter_a_la_LINK) -rpath $(pkglibdir) $(filter_a_la_OBJECTS) $(filter_a_la_LIBADD) $(LIBS)
+
+filter-aaaa.la: $(filter_aaaa_la_OBJECTS) $(filter_aaaa_la_DEPENDENCIES) $(EXTRA_filter_aaaa_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(filter_aaaa_la_LINK) -rpath $(pkglibdir) $(filter_aaaa_la_OBJECTS) $(filter_aaaa_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filter-a.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filter-aaaa.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/filter-a.Plo
+ -rm -f ./$(DEPDIR)/filter-aaaa.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-pkglibLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/filter-a.Plo
+ -rm -f ./$(DEPDIR)/filter-aaaa.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am: uninstall-pkglibLTLIBRARIES
+
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir \
+ doc-am doc-local dvi dvi-am html html-am info info-am install \
+ install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pkglibLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am test-am test-local uninstall uninstall-am \
+ uninstall-pkglibLTLIBRARIES unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/plugins/filter-a.c b/bin/plugins/filter-a.c
new file mode 100644
index 0000000..8556cb7
--- /dev/null
+++ b/bin/plugins/filter-a.c
@@ -0,0 +1,879 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+/* aliases for the exported symbols */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/hash.h>
+#include <isc/ht.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/db.h>
+#include <dns/enumtype.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/rdataset.h>
+#include <dns/types.h>
+#include <dns/view.h>
+
+#include <isccfg/aclconf.h>
+#include <isccfg/cfg.h>
+#include <isccfg/grammar.h>
+
+#include <ns/client.h>
+#include <ns/hooks.h>
+#include <ns/log.h>
+#include <ns/query.h>
+#include <ns/types.h>
+
+#define CHECK(op) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ goto cleanup; \
+ } \
+ } while (0)
+
+/*
+ * Possible values for the settings of filter-a-on-v6 and
+ * filter-a-on-v4: "no" is NONE, "yes" is FILTER, "break-dnssec"
+ * is BREAK_DNSSEC.
+ */
+typedef enum { NONE = 0, FILTER = 1, BREAK_DNSSEC = 2 } filter_a_t;
+
+/*
+ * Persistent data for use by this module. This will be associated
+ * with client object address in the hash table, and will remain
+ * accessible until the client object is detached.
+ */
+typedef struct filter_data {
+ filter_a_t mode;
+ uint32_t flags;
+} filter_data_t;
+
+typedef struct filter_instance {
+ ns_plugin_t *module;
+ isc_mem_t *mctx;
+
+ /*
+ * Hash table associating a client object with its persistent data.
+ */
+ isc_ht_t *ht;
+ isc_mutex_t hlock;
+
+ /*
+ * Values configured when the module is loaded.
+ */
+ filter_a_t v4_a;
+ filter_a_t v6_a;
+ dns_acl_t *a_acl;
+} filter_instance_t;
+
+/*
+ * Per-client flags set by this module
+ */
+#define FILTER_A_RECURSING 0x0001 /* Recursing for AAAA */
+#define FILTER_A_FILTERED 0x0002 /* A was removed from answer */
+
+/*
+ * Client attribute tests.
+ */
+#define WANTDNSSEC(c) (((c)->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
+#define RECURSIONOK(c) (((c)->query.attributes & NS_QUERYATTR_RECURSIONOK) != 0)
+
+/*
+ * Forward declarations of functions referenced in install_hooks().
+ */
+static ns_hookresult_t
+filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp);
+
+/*%
+ * Register the functions to be called at each hook point in 'hooktable', using
+ * memory context 'mctx' for allocating copies of stack-allocated structures
+ * passed to ns_hook_add(). Make sure 'inst' will be passed as the 'cbdata'
+ * argument to every callback.
+ */
+static void
+install_hooks(ns_hooktable_t *hooktable, isc_mem_t *mctx,
+ filter_instance_t *inst) {
+ const ns_hook_t filter_init = {
+ .action = filter_qctx_initialize,
+ .action_data = inst,
+ };
+
+ const ns_hook_t filter_respbegin = {
+ .action = filter_respond_begin,
+ .action_data = inst,
+ };
+
+ const ns_hook_t filter_respanyfound = {
+ .action = filter_respond_any_found,
+ .action_data = inst,
+ };
+
+ const ns_hook_t filter_prepresp = {
+ .action = filter_prep_response_begin,
+ .action_data = inst,
+ };
+
+ const ns_hook_t filter_donesend = {
+ .action = filter_query_done_send,
+ .action_data = inst,
+ };
+
+ const ns_hook_t filter_destroy = {
+ .action = filter_qctx_destroy,
+ .action_data = inst,
+ };
+
+ ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_INITIALIZED, &filter_init);
+ ns_hook_add(hooktable, mctx, NS_QUERY_RESPOND_BEGIN, &filter_respbegin);
+ ns_hook_add(hooktable, mctx, NS_QUERY_RESPOND_ANY_FOUND,
+ &filter_respanyfound);
+ ns_hook_add(hooktable, mctx, NS_QUERY_PREP_RESPONSE_BEGIN,
+ &filter_prepresp);
+ ns_hook_add(hooktable, mctx, NS_QUERY_DONE_SEND, &filter_donesend);
+ ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_DESTROYED, &filter_destroy);
+}
+
+/**
+** Support for parsing of parameters and configuration of the module.
+**/
+
+/*
+ * Support for parsing of parameters.
+ */
+static const char *filter_a_enums[] = { "break-dnssec", NULL };
+
+static isc_result_t
+parse_filter_a(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ return (cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
+}
+
+static void
+doc_filter_a(cfg_printer_t *pctx, const cfg_type_t *type) {
+ cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean);
+}
+
+static cfg_type_t cfg_type_filter_a = {
+ "filter_a", parse_filter_a, cfg_print_ustring,
+ doc_filter_a, &cfg_rep_string, filter_a_enums,
+};
+
+static cfg_clausedef_t param_clauses[] = {
+ { "filter-a", &cfg_type_bracketed_aml, 0 },
+ { "filter-a-on-v6", &cfg_type_filter_a, 0 },
+ { "filter-a-on-v4", &cfg_type_filter_a, 0 },
+};
+
+static cfg_clausedef_t *param_clausesets[] = { param_clauses, NULL };
+
+static cfg_type_t cfg_type_parameters = { "filter-a-params", cfg_parse_mapbody,
+ cfg_print_mapbody, cfg_doc_mapbody,
+ &cfg_rep_map, param_clausesets };
+
+static isc_result_t
+parse_filter_a_on(const cfg_obj_t *param_obj, const char *param_name,
+ filter_a_t *dstp) {
+ const cfg_obj_t *obj = NULL;
+ isc_result_t result;
+
+ result = cfg_map_get(param_obj, param_name, &obj);
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_SUCCESS);
+ }
+
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ *dstp = FILTER;
+ } else {
+ *dstp = NONE;
+ }
+ } else if (strcasecmp(cfg_obj_asstring(obj), "break-dnssec") == 0) {
+ *dstp = BREAK_DNSSEC;
+ } else {
+ result = ISC_R_UNEXPECTED;
+ }
+
+ return (result);
+}
+
+static isc_result_t
+check_syntax(cfg_obj_t *fmap, const void *cfg, isc_mem_t *mctx, isc_log_t *lctx,
+ void *actx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ const cfg_obj_t *aclobj = NULL;
+ dns_acl_t *acl = NULL;
+ filter_a_t f4 = NONE, f6 = NONE;
+
+ cfg_map_get(fmap, "filter-a", &aclobj);
+ if (aclobj == NULL) {
+ return (result);
+ }
+
+ CHECK(cfg_acl_fromconfig(aclobj, (const cfg_obj_t *)cfg, lctx,
+ (cfg_aclconfctx_t *)actx, mctx, 0, &acl));
+
+ CHECK(parse_filter_a_on(fmap, "filter-a-on-v6", &f6));
+ CHECK(parse_filter_a_on(fmap, "filter-a-on-v4", &f4));
+
+ if ((f4 != NONE || f6 != NONE) && dns_acl_isnone(acl)) {
+ cfg_obj_log(aclobj, lctx, ISC_LOG_WARNING,
+ "\"filter-a\" is 'none;' but "
+ "either filter-a-on-v6 or filter-a-on-v4 "
+ "is enabled");
+ result = ISC_R_FAILURE;
+ } else if (f4 == NONE && f6 == NONE && !dns_acl_isnone(acl)) {
+ cfg_obj_log(aclobj, lctx, ISC_LOG_WARNING,
+ "\"filter-a\" is set but "
+ "neither filter-a-on-v6 or filter-a-on-v4 "
+ "is enabled");
+ result = ISC_R_FAILURE;
+ }
+
+cleanup:
+ if (acl != NULL) {
+ dns_acl_detach(&acl);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+parse_parameters(filter_instance_t *inst, const char *parameters,
+ const void *cfg, const char *cfg_file, unsigned long cfg_line,
+ isc_mem_t *mctx, isc_log_t *lctx, void *actx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *param_obj = NULL;
+ const cfg_obj_t *obj = NULL;
+ isc_buffer_t b;
+
+ CHECK(cfg_parser_create(mctx, lctx, &parser));
+
+ isc_buffer_constinit(&b, parameters, strlen(parameters));
+ isc_buffer_add(&b, strlen(parameters));
+ CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line,
+ &cfg_type_parameters, 0, &param_obj));
+
+ CHECK(check_syntax(param_obj, cfg, mctx, lctx, actx));
+
+ CHECK(parse_filter_a_on(param_obj, "filter-a-on-v6", &inst->v6_a));
+ CHECK(parse_filter_a_on(param_obj, "filter-a-on-v4", &inst->v4_a));
+
+ result = cfg_map_get(param_obj, "filter-a", &obj);
+ if (result == ISC_R_SUCCESS) {
+ CHECK(cfg_acl_fromconfig(obj, (const cfg_obj_t *)cfg, lctx,
+ (cfg_aclconfctx_t *)actx, mctx, 0,
+ &inst->a_acl));
+ } else {
+ CHECK(dns_acl_any(mctx, &inst->a_acl));
+ }
+
+cleanup:
+ if (param_obj != NULL) {
+ cfg_obj_destroy(parser, &param_obj);
+ }
+ if (parser != NULL) {
+ cfg_parser_destroy(&parser);
+ }
+ return (result);
+}
+
+/**
+** Mandatory plugin API functions:
+**
+** - plugin_destroy
+** - plugin_register
+** - plugin_version
+** - plugin_check
+**/
+
+/*
+ * Called by ns_plugin_register() to initialize the plugin and
+ * register hook functions into the view hook table.
+ */
+isc_result_t
+plugin_register(const char *parameters, const void *cfg, const char *cfg_file,
+ unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx,
+ void *actx, ns_hooktable_t *hooktable, void **instp) {
+ filter_instance_t *inst = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ isc_log_write(lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS,
+ ISC_LOG_INFO,
+ "registering 'filter-a' "
+ "module from %s:%lu, %s parameters",
+ cfg_file, cfg_line, parameters != NULL ? "with" : "no");
+
+ inst = isc_mem_get(mctx, sizeof(*inst));
+ memset(inst, 0, sizeof(*inst));
+ isc_mem_attach(mctx, &inst->mctx);
+
+ if (parameters != NULL) {
+ CHECK(parse_parameters(inst, parameters, cfg, cfg_file,
+ cfg_line, mctx, lctx, actx));
+ }
+
+ isc_ht_init(&inst->ht, mctx, 16, ISC_HT_CASE_SENSITIVE);
+ isc_mutex_init(&inst->hlock);
+
+ /*
+ * Set hook points in the view's hooktable.
+ */
+ install_hooks(hooktable, mctx, inst);
+
+ *instp = inst;
+
+cleanup:
+ if (result != ISC_R_SUCCESS) {
+ plugin_destroy((void **)&inst);
+ }
+
+ return (result);
+}
+
+isc_result_t
+plugin_check(const char *parameters, const void *cfg, const char *cfg_file,
+ unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx,
+ void *actx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *param_obj = NULL;
+ isc_buffer_t b;
+
+ CHECK(cfg_parser_create(mctx, lctx, &parser));
+
+ isc_buffer_constinit(&b, parameters, strlen(parameters));
+ isc_buffer_add(&b, strlen(parameters));
+ CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line,
+ &cfg_type_parameters, 0, &param_obj));
+
+ CHECK(check_syntax(param_obj, cfg, mctx, lctx, actx));
+
+cleanup:
+ if (param_obj != NULL) {
+ cfg_obj_destroy(parser, &param_obj);
+ }
+ if (parser != NULL) {
+ cfg_parser_destroy(&parser);
+ }
+ return (result);
+}
+
+/*
+ * Called by ns_plugins_free(); frees memory allocated by
+ * the module when it was registered.
+ */
+void
+plugin_destroy(void **instp) {
+ filter_instance_t *inst = (filter_instance_t *)*instp;
+
+ if (inst->ht != NULL) {
+ isc_ht_destroy(&inst->ht);
+ isc_mutex_destroy(&inst->hlock);
+ }
+ if (inst->a_acl != NULL) {
+ dns_acl_detach(&inst->a_acl);
+ }
+
+ isc_mem_putanddetach(&inst->mctx, inst, sizeof(*inst));
+ *instp = NULL;
+
+ return;
+}
+
+/*
+ * Returns plugin API version for compatibility checks.
+ */
+int
+plugin_version(void) {
+ return (NS_PLUGIN_VERSION);
+}
+
+/**
+** "filter-a" feature implementation begins here.
+**/
+
+/*%
+ * Structure describing the filtering to be applied by process_section().
+ */
+typedef struct section_filter {
+ query_ctx_t *qctx;
+ filter_a_t mode;
+ dns_section_t section;
+ const dns_name_t *name;
+ dns_rdatatype_t type;
+ bool only_if_aaaa_exists;
+} section_filter_t;
+
+/*
+ * Check whether this is an IPv4 client.
+ */
+static bool
+is_v4_client(ns_client_t *client) {
+ if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) {
+ return (true);
+ }
+ if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
+ {
+ return (true);
+ }
+ return (false);
+}
+
+/*
+ * Check whether this is an IPv6 client.
+ */
+static bool
+is_v6_client(ns_client_t *client) {
+ if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
+ !IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
+ {
+ return (true);
+ }
+ return (false);
+}
+
+static filter_data_t *
+client_state_get(const query_ctx_t *qctx, filter_instance_t *inst) {
+ filter_data_t *client_state = NULL;
+ isc_result_t result;
+
+ LOCK(&inst->hlock);
+ result = isc_ht_find(inst->ht, (const unsigned char *)&qctx->client,
+ sizeof(qctx->client), (void **)&client_state);
+ UNLOCK(&inst->hlock);
+
+ return (result == ISC_R_SUCCESS ? client_state : NULL);
+}
+
+static void
+client_state_create(const query_ctx_t *qctx, filter_instance_t *inst) {
+ filter_data_t *client_state;
+ isc_result_t result;
+
+ client_state = isc_mem_get(inst->mctx, sizeof(*client_state));
+
+ client_state->mode = NONE;
+ client_state->flags = 0;
+
+ LOCK(&inst->hlock);
+ result = isc_ht_add(inst->ht, (const unsigned char *)&qctx->client,
+ sizeof(qctx->client), client_state);
+ UNLOCK(&inst->hlock);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+}
+
+static void
+client_state_destroy(const query_ctx_t *qctx, filter_instance_t *inst) {
+ filter_data_t *client_state = client_state_get(qctx, inst);
+ isc_result_t result;
+
+ if (client_state == NULL) {
+ return;
+ }
+
+ LOCK(&inst->hlock);
+ result = isc_ht_delete(inst->ht, (const unsigned char *)&qctx->client,
+ sizeof(qctx->client));
+ UNLOCK(&inst->hlock);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ isc_mem_put(inst->mctx, client_state, sizeof(*client_state));
+}
+
+/*%
+ * Mark 'rdataset' and 'sigrdataset' as rendered, gracefully handling NULL
+ * pointers and non-associated rdatasets.
+ */
+static void
+mark_as_rendered(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
+ if (rdataset != NULL && dns_rdataset_isassociated(rdataset)) {
+ rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
+ }
+ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
+ sigrdataset->attributes |= DNS_RDATASETATTR_RENDERED;
+ }
+}
+
+/*%
+ * Check whether an RRset of given 'type' is present at given 'name'. If
+ * it is found and either it is not signed or the combination of query
+ * flags and configured processing 'mode' allows it, mark the RRset and its
+ * associated signatures as already rendered to prevent them from appearing
+ * in the response message stored in 'qctx'. If 'only_if_aaaa_exists' is
+ * true, an RRset of type AAAA must also exist at 'name' in order for the
+ * above processing to happen.
+ */
+static bool
+process_name(query_ctx_t *qctx, filter_a_t mode, const dns_name_t *name,
+ dns_rdatatype_t type, bool only_if_aaaa_exists) {
+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
+ isc_result_t result;
+ bool modified = false;
+
+ if (only_if_aaaa_exists) {
+ CHECK(dns_message_findtype(name, dns_rdatatype_aaaa, 0, NULL));
+ }
+
+ (void)dns_message_findtype(name, type, 0, &rdataset);
+ (void)dns_message_findtype(name, dns_rdatatype_rrsig, type,
+ &sigrdataset);
+
+ if (rdataset != NULL &&
+ (sigrdataset == NULL || !WANTDNSSEC(qctx->client) ||
+ mode == BREAK_DNSSEC))
+ {
+ /*
+ * An RRset of given 'type' was found at 'name' and at least
+ * one of the following is true:
+ *
+ * - the RRset is not signed,
+ * - the client did not set the DO bit in its request,
+ * - configuration allows us to tamper with signed responses.
+ *
+ * This means it is okay to filter out this RRset and its
+ * signatures, if any, from the response.
+ */
+ mark_as_rendered(rdataset, sigrdataset);
+ modified = true;
+ }
+
+cleanup:
+ return (modified);
+}
+
+/*%
+ * Apply the requested section filter, i.e. prevent (when possible, as
+ * determined by process_name()) RRsets of given 'type' from being rendered
+ * in the given 'section' of the response message stored in 'qctx'. Clear
+ * the AD bit if the answer and/or authority section was modified. If
+ * 'name' is NULL, all names in the given 'section' are processed;
+ * otherwise, only 'name' is. 'only_if_aaaa_exists' is passed through to
+ * process_name().
+ */
+static void
+process_section(const section_filter_t *filter) {
+ query_ctx_t *qctx = filter->qctx;
+ filter_a_t mode = filter->mode;
+ dns_section_t section = filter->section;
+ const dns_name_t *name = filter->name;
+ dns_rdatatype_t type = filter->type;
+ bool only_if_aaaa_exists = filter->only_if_aaaa_exists;
+
+ dns_message_t *message = qctx->client->message;
+ isc_result_t result;
+
+ for (result = dns_message_firstname(message, section);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(message, section))
+ {
+ dns_name_t *cur = NULL;
+ dns_message_currentname(message, section, &cur);
+ if (name != NULL && !dns_name_equal(name, cur)) {
+ /*
+ * We only want to process 'name' and this is not it.
+ */
+ continue;
+ }
+
+ if (!process_name(qctx, mode, cur, type, only_if_aaaa_exists)) {
+ /*
+ * Response was not modified, do not touch the AD bit.
+ */
+ continue;
+ }
+
+ if (section == DNS_SECTION_ANSWER ||
+ section == DNS_SECTION_AUTHORITY)
+ {
+ message->flags &= ~DNS_MESSAGEFLAG_AD;
+ }
+ }
+}
+
+/*
+ * Initialize filter state, fetching it from a memory pool and storing it
+ * in a hash table keyed according to the client object; this enables us to
+ * retrieve persistent data related to a client query for as long as the
+ * object persists.
+ */
+static ns_hookresult_t
+filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+ filter_data_t *client_state;
+
+ *resp = ISC_R_UNSET;
+
+ client_state = client_state_get(qctx, inst);
+ if (client_state == NULL) {
+ client_state_create(qctx, inst);
+ }
+
+ return (NS_HOOK_CONTINUE);
+}
+
+/*
+ * Determine whether this client should have A filtered or not, based on
+ * the client address family and the settings of filter-a-on-v6 and
+ * filter-a-on-v4.
+ */
+static ns_hookresult_t
+filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+ filter_data_t *client_state = client_state_get(qctx, inst);
+ isc_result_t result;
+
+ *resp = ISC_R_UNSET;
+
+ if (client_state == NULL) {
+ return (NS_HOOK_CONTINUE);
+ }
+
+ if (inst->v4_a != NONE || inst->v6_a != NONE) {
+ result = ns_client_checkaclsilent(qctx->client, NULL,
+ inst->a_acl, true);
+ if (result == ISC_R_SUCCESS && inst->v4_a != NONE &&
+ is_v4_client(qctx->client))
+ {
+ client_state->mode = inst->v4_a;
+ } else if (result == ISC_R_SUCCESS && inst->v6_a != NONE &&
+ is_v6_client(qctx->client))
+ {
+ client_state->mode = inst->v6_a;
+ }
+ }
+
+ return (NS_HOOK_CONTINUE);
+}
+
+/*
+ * Hide A rrsets if there is a matching AAAA. Trigger recursion if
+ * necessary to find out whether an AAAA exists.
+ *
+ * (This version is for processing answers to explicit A queries; ANY
+ * queries are handled in filter_respond_any_found().)
+ */
+static ns_hookresult_t
+filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+ filter_data_t *client_state = client_state_get(qctx, inst);
+ isc_result_t result = ISC_R_UNSET;
+
+ *resp = ISC_R_UNSET;
+
+ if (client_state == NULL) {
+ return (NS_HOOK_CONTINUE);
+ }
+
+ if (client_state->mode != BREAK_DNSSEC &&
+ (client_state->mode != FILTER ||
+ (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL &&
+ dns_rdataset_isassociated(qctx->sigrdataset))))
+ {
+ return (NS_HOOK_CONTINUE);
+ }
+
+ if (qctx->qtype == dns_rdatatype_a) {
+ dns_rdataset_t *trdataset;
+ trdataset = ns_client_newrdataset(qctx->client);
+ result = dns_db_findrdataset(
+ qctx->db, qctx->node, qctx->version, dns_rdatatype_aaaa,
+ 0, qctx->client->now, trdataset, NULL);
+ if (dns_rdataset_isassociated(trdataset)) {
+ dns_rdataset_disassociate(trdataset);
+ }
+ ns_client_putrdataset(qctx->client, &trdataset);
+
+ /*
+ * We found an A. If we also found an AAAA, then the A
+ * must not be rendered.
+ *
+ * If the AAAA is not in our cache, then any result other than
+ * DNS_R_DELEGATION or ISC_R_NOTFOUND means there is no AAAAA,
+ * and so AAAAs are okay.
+ *
+ * We assume there is no AAAA if we can't recurse for this
+ * client. That might be the wrong answer, but what else
+ * can we do? Besides, the fact that we have the A and
+ * are using this mechanism in the first place suggests
+ * that we care more about AAAAs than As, and would have
+ * cached an AAAA if it existed.
+ */
+ if (result == ISC_R_SUCCESS) {
+ mark_as_rendered(qctx->rdataset, qctx->sigrdataset);
+ qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
+ client_state->flags |= FILTER_A_FILTERED;
+ } else if (!qctx->authoritative && RECURSIONOK(qctx->client) &&
+ (result == DNS_R_DELEGATION ||
+ result == ISC_R_NOTFOUND))
+ {
+ /*
+ * This is an ugly kludge to recurse
+ * for the AAAA and discard the result.???
+ *
+ * Continue to add the A now.
+ * We'll make a note to not render it
+ * if the recursion for the AAAA succeeds.
+ */
+ result = ns_query_recurse(qctx->client,
+ dns_rdatatype_aaaa,
+ qctx->client->query.qname,
+ NULL, NULL, qctx->resuming);
+ if (result == ISC_R_SUCCESS) {
+ client_state->flags |= FILTER_A_RECURSING;
+ qctx->client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ }
+ }
+ } else if (qctx->qtype == dns_rdatatype_aaaa &&
+ (client_state->flags & FILTER_A_RECURSING) != 0)
+ {
+ const section_filter_t filter_answer = {
+ .qctx = qctx,
+ .mode = client_state->mode,
+ .section = DNS_SECTION_ANSWER,
+ .name = qctx->fname,
+ .type = dns_rdatatype_a,
+ };
+ process_section(&filter_answer);
+
+ client_state->flags &= ~FILTER_A_RECURSING;
+
+ result = ns_query_done(qctx);
+
+ *resp = result;
+
+ return (NS_HOOK_RETURN);
+ }
+
+ *resp = result;
+ return (NS_HOOK_CONTINUE);
+}
+
+/*
+ * When answering an ANY query, remove A if AAAA is present.
+ */
+static ns_hookresult_t
+filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+ filter_data_t *client_state = client_state_get(qctx, inst);
+
+ *resp = ISC_R_UNSET;
+
+ if (client_state != NULL && client_state->mode != NONE) {
+ /*
+ * If we are authoritative, require an AAAA record to be
+ * present before filtering out A records; otherwise,
+ * just assume an AAAA record exists even if it was not in the
+ * cache (and therefore is not in the response message),
+ * thus proceeding with filtering out A records.
+ */
+ const section_filter_t filter_answer = {
+ .qctx = qctx,
+ .mode = client_state->mode,
+ .section = DNS_SECTION_ANSWER,
+ .name = qctx->tname,
+ .type = dns_rdatatype_a,
+ .only_if_aaaa_exists = qctx->authoritative,
+ };
+ process_section(&filter_answer);
+ }
+
+ return (NS_HOOK_CONTINUE);
+}
+
+/*
+ * Hide A rrsets in the additional section if there is a matching AAAA, and
+ * hide NS in the authority section if A was filtered in the answer
+ * section.
+ */
+static ns_hookresult_t
+filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+ filter_data_t *client_state = client_state_get(qctx, inst);
+
+ *resp = ISC_R_UNSET;
+
+ if (client_state != NULL && client_state->mode != NONE) {
+ const section_filter_t filter_additional = {
+ .qctx = qctx,
+ .mode = client_state->mode,
+ .section = DNS_SECTION_ADDITIONAL,
+ .type = dns_rdatatype_a,
+ .only_if_aaaa_exists = true,
+ };
+ process_section(&filter_additional);
+
+ if ((client_state->flags & FILTER_A_FILTERED) != 0) {
+ const section_filter_t filter_authority = {
+ .qctx = qctx,
+ .mode = client_state->mode,
+ .section = DNS_SECTION_AUTHORITY,
+ .type = dns_rdatatype_ns,
+ };
+ process_section(&filter_authority);
+ }
+ }
+
+ return (NS_HOOK_CONTINUE);
+}
+
+/*
+ * If the client is being detached, then we can delete our persistent data
+ * from hash table and return it to the memory pool.
+ */
+static ns_hookresult_t
+filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+
+ *resp = ISC_R_UNSET;
+
+ if (!qctx->detach_client) {
+ return (NS_HOOK_CONTINUE);
+ }
+
+ client_state_destroy(qctx, inst);
+
+ return (NS_HOOK_CONTINUE);
+}
diff --git a/bin/plugins/filter-a.rst b/bin/plugins/filter-a.rst
new file mode 100644
index 0000000..16b3dee
--- /dev/null
+++ b/bin/plugins/filter-a.rst
@@ -0,0 +1,86 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: filter-a
+.. _man_filter-a:
+
+filter-a.so - filter A in DNS responses when AAAA is present
+---------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`plugin query` "filter-a.so" [{ parameters }];
+
+Description
+~~~~~~~~~~~
+
+:program:`filter-a.so` is a query plugin module for :iscman:`named`, enabling
+:iscman:`named` to omit some IPv4 addresses when responding to clients.
+
+For example:
+
+::
+
+ plugin query "filter-a.so" {
+ filter-a-on-v6 yes;
+ filter-a-on-v4 yes;
+ filter-a { 192.0.2.1; 2001:db8:2::1; };
+ };
+
+This module is intended to aid transition from IPv4 to IPv6 by
+withholding IPv4 addresses from DNS clients which are not connected to
+the IPv4 Internet, when the name being looked up has an IPv6 address
+available. Use of this module is not recommended unless absolutely
+necessary.
+
+Note: This mechanism can erroneously cause other servers not to give
+A records to their clients. If a recursing server with both IPv6 and
+IPv4 network connections queries an authoritative server using this
+mechanism via IPv6, it is denied A records even if its client is
+using IPv4.
+
+Options
+~~~~~~~
+
+``filter-a``
+ This option specifies a list of client addresses for which A filtering is to
+ be applied. The default is ``any``.
+
+``filter-a-on-v6``
+ If set to ``yes``, this option indicates that the DNS client is at an IPv6 address, in
+ ``filter-a``. If the response does not include DNSSEC
+ signatures, then all A records are deleted from the response. This
+ filtering applies to all responses, not only authoritative
+ ones.
+
+ If set to ``break-dnssec``, then A records are deleted even when
+ DNSSEC is enabled. As suggested by the name, this causes the response
+ to fail to verify, because the DNSSEC protocol is designed to detect
+ deletions.
+
+ This mechanism can erroneously cause other servers not to give A
+ records to their clients. If a recursing server with both IPv6 and IPv4
+ network connections queries an authoritative server using this
+ mechanism via IPv6, it is denied A records even if its client is
+ using IPv4.
+
+``filter-a-on-v4``
+ This option is identical to ``filter-a-on-v6``, except that it filters A responses
+ to queries from IPv4 clients instead of IPv6 clients. To filter all
+ responses, set both options to ``yes``.
+
+See Also
+~~~~~~~~
+
+BIND 9 Administrator Reference Manual.
diff --git a/bin/plugins/filter-aaaa.c b/bin/plugins/filter-aaaa.c
new file mode 100644
index 0000000..1ec1fd8
--- /dev/null
+++ b/bin/plugins/filter-aaaa.c
@@ -0,0 +1,881 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+/* aliases for the exported symbols */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/hash.h>
+#include <isc/ht.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/db.h>
+#include <dns/enumtype.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/rdataset.h>
+#include <dns/types.h>
+#include <dns/view.h>
+
+#include <isccfg/aclconf.h>
+#include <isccfg/cfg.h>
+#include <isccfg/grammar.h>
+
+#include <ns/client.h>
+#include <ns/hooks.h>
+#include <ns/log.h>
+#include <ns/query.h>
+#include <ns/types.h>
+
+#define CHECK(op) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ goto cleanup; \
+ } \
+ } while (0)
+
+/*
+ * Possible values for the settings of filter-aaaa-on-v4 and
+ * filter-aaaa-on-v6: "no" is NONE, "yes" is FILTER, "break-dnssec"
+ * is BREAK_DNSSEC.
+ */
+typedef enum { NONE = 0, FILTER = 1, BREAK_DNSSEC = 2 } filter_aaaa_t;
+
+/*
+ * Persistent data for use by this module. This will be associated
+ * with client object address in the hash table, and will remain
+ * accessible until the client object is detached.
+ */
+typedef struct filter_data {
+ filter_aaaa_t mode;
+ uint32_t flags;
+} filter_data_t;
+
+typedef struct filter_instance {
+ ns_plugin_t *module;
+ isc_mem_t *mctx;
+
+ /*
+ * Hash table associating a client object with its persistent data.
+ */
+ isc_ht_t *ht;
+ isc_mutex_t hlock;
+
+ /*
+ * Values configured when the module is loaded.
+ */
+ filter_aaaa_t v4_aaaa;
+ filter_aaaa_t v6_aaaa;
+ dns_acl_t *aaaa_acl;
+} filter_instance_t;
+
+/*
+ * Per-client flags set by this module
+ */
+#define FILTER_AAAA_RECURSING 0x0001 /* Recursing for A */
+#define FILTER_AAAA_FILTERED 0x0002 /* AAAA was removed from answer */
+
+/*
+ * Client attribute tests.
+ */
+#define WANTDNSSEC(c) (((c)->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
+#define RECURSIONOK(c) (((c)->query.attributes & NS_QUERYATTR_RECURSIONOK) != 0)
+
+/*
+ * Forward declarations of functions referenced in install_hooks().
+ */
+static ns_hookresult_t
+filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp);
+
+/*%
+ * Register the functions to be called at each hook point in 'hooktable', using
+ * memory context 'mctx' for allocating copies of stack-allocated structures
+ * passed to ns_hook_add(). Make sure 'inst' will be passed as the 'cbdata'
+ * argument to every callback.
+ */
+static void
+install_hooks(ns_hooktable_t *hooktable, isc_mem_t *mctx,
+ filter_instance_t *inst) {
+ const ns_hook_t filter_init = {
+ .action = filter_qctx_initialize,
+ .action_data = inst,
+ };
+
+ const ns_hook_t filter_respbegin = {
+ .action = filter_respond_begin,
+ .action_data = inst,
+ };
+
+ const ns_hook_t filter_respanyfound = {
+ .action = filter_respond_any_found,
+ .action_data = inst,
+ };
+
+ const ns_hook_t filter_prepresp = {
+ .action = filter_prep_response_begin,
+ .action_data = inst,
+ };
+
+ const ns_hook_t filter_donesend = {
+ .action = filter_query_done_send,
+ .action_data = inst,
+ };
+
+ const ns_hook_t filter_destroy = {
+ .action = filter_qctx_destroy,
+ .action_data = inst,
+ };
+
+ ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_INITIALIZED, &filter_init);
+ ns_hook_add(hooktable, mctx, NS_QUERY_RESPOND_BEGIN, &filter_respbegin);
+ ns_hook_add(hooktable, mctx, NS_QUERY_RESPOND_ANY_FOUND,
+ &filter_respanyfound);
+ ns_hook_add(hooktable, mctx, NS_QUERY_PREP_RESPONSE_BEGIN,
+ &filter_prepresp);
+ ns_hook_add(hooktable, mctx, NS_QUERY_DONE_SEND, &filter_donesend);
+ ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_DESTROYED, &filter_destroy);
+}
+
+/**
+** Support for parsing of parameters and configuration of the module.
+**/
+
+/*
+ * Support for parsing of parameters.
+ */
+static const char *filter_aaaa_enums[] = { "break-dnssec", NULL };
+
+static isc_result_t
+parse_filter_aaaa(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ return (cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
+}
+
+static void
+doc_filter_aaaa(cfg_printer_t *pctx, const cfg_type_t *type) {
+ cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean);
+}
+
+static cfg_type_t cfg_type_filter_aaaa = {
+ "filter_aaaa", parse_filter_aaaa, cfg_print_ustring,
+ doc_filter_aaaa, &cfg_rep_string, filter_aaaa_enums,
+};
+
+static cfg_clausedef_t param_clauses[] = {
+ { "filter-aaaa", &cfg_type_bracketed_aml, 0 },
+ { "filter-aaaa-on-v4", &cfg_type_filter_aaaa, 0 },
+ { "filter-aaaa-on-v6", &cfg_type_filter_aaaa, 0 },
+};
+
+static cfg_clausedef_t *param_clausesets[] = { param_clauses, NULL };
+
+static cfg_type_t cfg_type_parameters = {
+ "filter-aaaa-params", cfg_parse_mapbody, cfg_print_mapbody,
+ cfg_doc_mapbody, &cfg_rep_map, param_clausesets
+};
+
+static isc_result_t
+parse_filter_aaaa_on(const cfg_obj_t *param_obj, const char *param_name,
+ filter_aaaa_t *dstp) {
+ const cfg_obj_t *obj = NULL;
+ isc_result_t result;
+
+ result = cfg_map_get(param_obj, param_name, &obj);
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_SUCCESS);
+ }
+
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj)) {
+ *dstp = FILTER;
+ } else {
+ *dstp = NONE;
+ }
+ } else if (strcasecmp(cfg_obj_asstring(obj), "break-dnssec") == 0) {
+ *dstp = BREAK_DNSSEC;
+ } else {
+ result = ISC_R_UNEXPECTED;
+ }
+
+ return (result);
+}
+
+static isc_result_t
+check_syntax(cfg_obj_t *fmap, const void *cfg, isc_mem_t *mctx, isc_log_t *lctx,
+ void *actx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ const cfg_obj_t *aclobj = NULL;
+ dns_acl_t *acl = NULL;
+ filter_aaaa_t f4 = NONE, f6 = NONE;
+
+ cfg_map_get(fmap, "filter-aaaa", &aclobj);
+ if (aclobj == NULL) {
+ return (result);
+ }
+
+ CHECK(cfg_acl_fromconfig(aclobj, (const cfg_obj_t *)cfg, lctx,
+ (cfg_aclconfctx_t *)actx, mctx, 0, &acl));
+
+ CHECK(parse_filter_aaaa_on(fmap, "filter-aaaa-on-v4", &f4));
+ CHECK(parse_filter_aaaa_on(fmap, "filter-aaaa-on-v6", &f6));
+
+ if ((f4 != NONE || f6 != NONE) && dns_acl_isnone(acl)) {
+ cfg_obj_log(aclobj, lctx, ISC_LOG_WARNING,
+ "\"filter-aaaa\" is 'none;' but "
+ "either filter-aaaa-on-v4 or filter-aaaa-on-v6 "
+ "is enabled");
+ result = ISC_R_FAILURE;
+ } else if (f4 == NONE && f6 == NONE && !dns_acl_isnone(acl)) {
+ cfg_obj_log(aclobj, lctx, ISC_LOG_WARNING,
+ "\"filter-aaaa\" is set but "
+ "neither filter-aaaa-on-v4 or filter-aaaa-on-v6 "
+ "is enabled");
+ result = ISC_R_FAILURE;
+ }
+
+cleanup:
+ if (acl != NULL) {
+ dns_acl_detach(&acl);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+parse_parameters(filter_instance_t *inst, const char *parameters,
+ const void *cfg, const char *cfg_file, unsigned long cfg_line,
+ isc_mem_t *mctx, isc_log_t *lctx, void *actx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *param_obj = NULL;
+ const cfg_obj_t *obj = NULL;
+ isc_buffer_t b;
+
+ CHECK(cfg_parser_create(mctx, lctx, &parser));
+
+ isc_buffer_constinit(&b, parameters, strlen(parameters));
+ isc_buffer_add(&b, strlen(parameters));
+ CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line,
+ &cfg_type_parameters, 0, &param_obj));
+
+ CHECK(check_syntax(param_obj, cfg, mctx, lctx, actx));
+
+ CHECK(parse_filter_aaaa_on(param_obj, "filter-aaaa-on-v4",
+ &inst->v4_aaaa));
+ CHECK(parse_filter_aaaa_on(param_obj, "filter-aaaa-on-v6",
+ &inst->v6_aaaa));
+
+ result = cfg_map_get(param_obj, "filter-aaaa", &obj);
+ if (result == ISC_R_SUCCESS) {
+ CHECK(cfg_acl_fromconfig(obj, (const cfg_obj_t *)cfg, lctx,
+ (cfg_aclconfctx_t *)actx, mctx, 0,
+ &inst->aaaa_acl));
+ } else {
+ CHECK(dns_acl_any(mctx, &inst->aaaa_acl));
+ }
+
+cleanup:
+ if (param_obj != NULL) {
+ cfg_obj_destroy(parser, &param_obj);
+ }
+ if (parser != NULL) {
+ cfg_parser_destroy(&parser);
+ }
+ return (result);
+}
+
+/**
+** Mandatory plugin API functions:
+**
+** - plugin_destroy
+** - plugin_register
+** - plugin_version
+** - plugin_check
+**/
+
+/*
+ * Called by ns_plugin_register() to initialize the plugin and
+ * register hook functions into the view hook table.
+ */
+isc_result_t
+plugin_register(const char *parameters, const void *cfg, const char *cfg_file,
+ unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx,
+ void *actx, ns_hooktable_t *hooktable, void **instp) {
+ filter_instance_t *inst = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ isc_log_write(lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS,
+ ISC_LOG_INFO,
+ "registering 'filter-aaaa' "
+ "module from %s:%lu, %s parameters",
+ cfg_file, cfg_line, parameters != NULL ? "with" : "no");
+
+ inst = isc_mem_get(mctx, sizeof(*inst));
+ memset(inst, 0, sizeof(*inst));
+ isc_mem_attach(mctx, &inst->mctx);
+
+ if (parameters != NULL) {
+ CHECK(parse_parameters(inst, parameters, cfg, cfg_file,
+ cfg_line, mctx, lctx, actx));
+ }
+
+ isc_ht_init(&inst->ht, mctx, 16, ISC_HT_CASE_SENSITIVE);
+ isc_mutex_init(&inst->hlock);
+
+ /*
+ * Set hook points in the view's hooktable.
+ */
+ install_hooks(hooktable, mctx, inst);
+
+ *instp = inst;
+
+cleanup:
+ if (result != ISC_R_SUCCESS) {
+ plugin_destroy((void **)&inst);
+ }
+
+ return (result);
+}
+
+isc_result_t
+plugin_check(const char *parameters, const void *cfg, const char *cfg_file,
+ unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx,
+ void *actx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *param_obj = NULL;
+ isc_buffer_t b;
+
+ CHECK(cfg_parser_create(mctx, lctx, &parser));
+
+ isc_buffer_constinit(&b, parameters, strlen(parameters));
+ isc_buffer_add(&b, strlen(parameters));
+ CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line,
+ &cfg_type_parameters, 0, &param_obj));
+
+ CHECK(check_syntax(param_obj, cfg, mctx, lctx, actx));
+
+cleanup:
+ if (param_obj != NULL) {
+ cfg_obj_destroy(parser, &param_obj);
+ }
+ if (parser != NULL) {
+ cfg_parser_destroy(&parser);
+ }
+ return (result);
+}
+
+/*
+ * Called by ns_plugins_free(); frees memory allocated by
+ * the module when it was registered.
+ */
+void
+plugin_destroy(void **instp) {
+ filter_instance_t *inst = (filter_instance_t *)*instp;
+
+ if (inst->ht != NULL) {
+ isc_ht_destroy(&inst->ht);
+ isc_mutex_destroy(&inst->hlock);
+ }
+ if (inst->aaaa_acl != NULL) {
+ dns_acl_detach(&inst->aaaa_acl);
+ }
+
+ isc_mem_putanddetach(&inst->mctx, inst, sizeof(*inst));
+ *instp = NULL;
+
+ return;
+}
+
+/*
+ * Returns plugin API version for compatibility checks.
+ */
+int
+plugin_version(void) {
+ return (NS_PLUGIN_VERSION);
+}
+
+/**
+** "filter-aaaa" feature implementation begins here.
+**/
+
+/*%
+ * Structure describing the filtering to be applied by process_section().
+ */
+typedef struct section_filter {
+ query_ctx_t *qctx;
+ filter_aaaa_t mode;
+ dns_section_t section;
+ const dns_name_t *name;
+ dns_rdatatype_t type;
+ bool only_if_a_exists;
+} section_filter_t;
+
+/*
+ * Check whether this is an IPv4 client.
+ */
+static bool
+is_v4_client(ns_client_t *client) {
+ if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) {
+ return (true);
+ }
+ if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
+ {
+ return (true);
+ }
+ return (false);
+}
+
+/*
+ * Check whether this is an IPv6 client.
+ */
+static bool
+is_v6_client(ns_client_t *client) {
+ if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
+ !IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
+ {
+ return (true);
+ }
+ return (false);
+}
+
+static filter_data_t *
+client_state_get(const query_ctx_t *qctx, filter_instance_t *inst) {
+ filter_data_t *client_state = NULL;
+ isc_result_t result;
+
+ LOCK(&inst->hlock);
+ result = isc_ht_find(inst->ht, (const unsigned char *)&qctx->client,
+ sizeof(qctx->client), (void **)&client_state);
+ UNLOCK(&inst->hlock);
+
+ return (result == ISC_R_SUCCESS ? client_state : NULL);
+}
+
+static void
+client_state_create(const query_ctx_t *qctx, filter_instance_t *inst) {
+ filter_data_t *client_state;
+ isc_result_t result;
+
+ client_state = isc_mem_get(inst->mctx, sizeof(*client_state));
+
+ client_state->mode = NONE;
+ client_state->flags = 0;
+
+ LOCK(&inst->hlock);
+ result = isc_ht_add(inst->ht, (const unsigned char *)&qctx->client,
+ sizeof(qctx->client), client_state);
+ UNLOCK(&inst->hlock);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+}
+
+static void
+client_state_destroy(const query_ctx_t *qctx, filter_instance_t *inst) {
+ filter_data_t *client_state = client_state_get(qctx, inst);
+ isc_result_t result;
+
+ if (client_state == NULL) {
+ return;
+ }
+
+ LOCK(&inst->hlock);
+ result = isc_ht_delete(inst->ht, (const unsigned char *)&qctx->client,
+ sizeof(qctx->client));
+ UNLOCK(&inst->hlock);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ isc_mem_put(inst->mctx, client_state, sizeof(*client_state));
+}
+
+/*%
+ * Mark 'rdataset' and 'sigrdataset' as rendered, gracefully handling NULL
+ * pointers and non-associated rdatasets.
+ */
+static void
+mark_as_rendered(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
+ if (rdataset != NULL && dns_rdataset_isassociated(rdataset)) {
+ rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
+ }
+ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
+ sigrdataset->attributes |= DNS_RDATASETATTR_RENDERED;
+ }
+}
+
+/*%
+ * Check whether an RRset of given 'type' is present at given 'name'. If
+ * it is found and either it is not signed or the combination of query
+ * flags and configured processing 'mode' allows it, mark the RRset and its
+ * associated signatures as already rendered to prevent them from appearing
+ * in the response message stored in 'qctx'. If 'only_if_a_exists' is
+ * true, an RRset of type A must also exist at 'name' in order for the
+ * above processing to happen.
+ */
+static bool
+process_name(query_ctx_t *qctx, filter_aaaa_t mode, const dns_name_t *name,
+ dns_rdatatype_t type, bool only_if_a_exists) {
+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
+ isc_result_t result;
+ bool modified = false;
+
+ if (only_if_a_exists) {
+ CHECK(dns_message_findtype(name, dns_rdatatype_a, 0, NULL));
+ }
+
+ (void)dns_message_findtype(name, type, 0, &rdataset);
+ (void)dns_message_findtype(name, dns_rdatatype_rrsig, type,
+ &sigrdataset);
+
+ if (rdataset != NULL &&
+ (sigrdataset == NULL || !WANTDNSSEC(qctx->client) ||
+ mode == BREAK_DNSSEC))
+ {
+ /*
+ * An RRset of given 'type' was found at 'name' and at least
+ * one of the following is true:
+ *
+ * - the RRset is not signed,
+ * - the client did not set the DO bit in its request,
+ * - configuration allows us to tamper with signed responses.
+ *
+ * This means it is okay to filter out this RRset and its
+ * signatures, if any, from the response.
+ */
+ mark_as_rendered(rdataset, sigrdataset);
+ modified = true;
+ }
+
+cleanup:
+ return (modified);
+}
+
+/*%
+ * Apply the requested section filter, i.e. prevent (when possible, as
+ * determined by process_name()) RRsets of given 'type' from being rendered
+ * in the given 'section' of the response message stored in 'qctx'. Clear
+ * the AD bit if the answer and/or authority section was modified. If
+ * 'name' is NULL, all names in the given 'section' are processed;
+ * otherwise, only 'name' is. 'only_if_a_exists' is passed through to
+ * process_name().
+ */
+static void
+process_section(const section_filter_t *filter) {
+ query_ctx_t *qctx = filter->qctx;
+ filter_aaaa_t mode = filter->mode;
+ dns_section_t section = filter->section;
+ const dns_name_t *name = filter->name;
+ dns_rdatatype_t type = filter->type;
+ bool only_if_a_exists = filter->only_if_a_exists;
+
+ dns_message_t *message = qctx->client->message;
+ isc_result_t result;
+
+ for (result = dns_message_firstname(message, section);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(message, section))
+ {
+ dns_name_t *cur = NULL;
+ dns_message_currentname(message, section, &cur);
+ if (name != NULL && !dns_name_equal(name, cur)) {
+ /*
+ * We only want to process 'name' and this is not it.
+ */
+ continue;
+ }
+
+ if (!process_name(qctx, mode, cur, type, only_if_a_exists)) {
+ /*
+ * Response was not modified, do not touch the AD bit.
+ */
+ continue;
+ }
+
+ if (section == DNS_SECTION_ANSWER ||
+ section == DNS_SECTION_AUTHORITY)
+ {
+ message->flags &= ~DNS_MESSAGEFLAG_AD;
+ }
+ }
+}
+
+/*
+ * Initialize filter state, fetching it from a memory pool and storing it
+ * in a hash table keyed according to the client object; this enables us to
+ * retrieve persistent data related to a client query for as long as the
+ * object persists.
+ */
+static ns_hookresult_t
+filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+ filter_data_t *client_state;
+
+ *resp = ISC_R_UNSET;
+
+ client_state = client_state_get(qctx, inst);
+ if (client_state == NULL) {
+ client_state_create(qctx, inst);
+ }
+
+ return (NS_HOOK_CONTINUE);
+}
+
+/*
+ * Determine whether this client should have AAAA filtered or not, based on
+ * the client address family and the settings of filter-aaaa-on-v4 and
+ * filter-aaaa-on-v6.
+ */
+static ns_hookresult_t
+filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+ filter_data_t *client_state = client_state_get(qctx, inst);
+ isc_result_t result;
+
+ *resp = ISC_R_UNSET;
+
+ if (client_state == NULL) {
+ return (NS_HOOK_CONTINUE);
+ }
+
+ if (inst->v4_aaaa != NONE || inst->v6_aaaa != NONE) {
+ result = ns_client_checkaclsilent(qctx->client, NULL,
+ inst->aaaa_acl, true);
+ if (result == ISC_R_SUCCESS && inst->v4_aaaa != NONE &&
+ is_v4_client(qctx->client))
+ {
+ client_state->mode = inst->v4_aaaa;
+ } else if (result == ISC_R_SUCCESS && inst->v6_aaaa != NONE &&
+ is_v6_client(qctx->client))
+ {
+ client_state->mode = inst->v6_aaaa;
+ }
+ }
+
+ return (NS_HOOK_CONTINUE);
+}
+
+/*
+ * Hide AAAA rrsets if there is a matching A. Trigger recursion if
+ * necessary to find out whether an A exists.
+ *
+ * (This version is for processing answers to explicit AAAA queries; ANY
+ * queries are handled in filter_respond_any_found().)
+ */
+static ns_hookresult_t
+filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+ filter_data_t *client_state = client_state_get(qctx, inst);
+ isc_result_t result = ISC_R_UNSET;
+
+ *resp = ISC_R_UNSET;
+
+ if (client_state == NULL) {
+ return (NS_HOOK_CONTINUE);
+ }
+
+ if (client_state->mode != BREAK_DNSSEC &&
+ (client_state->mode != FILTER ||
+ (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL &&
+ dns_rdataset_isassociated(qctx->sigrdataset))))
+ {
+ return (NS_HOOK_CONTINUE);
+ }
+
+ if (qctx->qtype == dns_rdatatype_aaaa) {
+ dns_rdataset_t *trdataset;
+ trdataset = ns_client_newrdataset(qctx->client);
+ result = dns_db_findrdataset(
+ qctx->db, qctx->node, qctx->version, dns_rdatatype_a, 0,
+ qctx->client->now, trdataset, NULL);
+ if (dns_rdataset_isassociated(trdataset)) {
+ dns_rdataset_disassociate(trdataset);
+ }
+ ns_client_putrdataset(qctx->client, &trdataset);
+
+ /*
+ * We found an AAAA. If we also found an A, then the AAAA
+ * must not be rendered.
+ *
+ * If the A is not in our cache, then any result other than
+ * DNS_R_DELEGATION or ISC_R_NOTFOUND means there is no A,
+ * and so AAAAs are okay.
+ *
+ * We assume there is no A if we can't recurse for this
+ * client. That might be the wrong answer, but what else
+ * can we do? Besides, the fact that we have the AAAA and
+ * are using this mechanism in the first place suggests
+ * that we care more about As than AAAAs, and would have
+ * cached an A if it existed.
+ */
+ if (result == ISC_R_SUCCESS) {
+ mark_as_rendered(qctx->rdataset, qctx->sigrdataset);
+ qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
+ client_state->flags |= FILTER_AAAA_FILTERED;
+ } else if (!qctx->authoritative && RECURSIONOK(qctx->client) &&
+ (result == DNS_R_DELEGATION ||
+ result == ISC_R_NOTFOUND))
+ {
+ /*
+ * This is an ugly kludge to recurse
+ * for the A and discard the result.
+ *
+ * Continue to add the AAAA now.
+ * We'll make a note to not render it
+ * if the recursion for the A succeeds.
+ */
+ result = ns_query_recurse(qctx->client, dns_rdatatype_a,
+ qctx->client->query.qname,
+ NULL, NULL, qctx->resuming);
+ if (result == ISC_R_SUCCESS) {
+ client_state->flags |= FILTER_AAAA_RECURSING;
+ qctx->client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ }
+ }
+ } else if (qctx->qtype == dns_rdatatype_a &&
+ (client_state->flags & FILTER_AAAA_RECURSING) != 0)
+ {
+ const section_filter_t filter_answer = {
+ .qctx = qctx,
+ .mode = client_state->mode,
+ .section = DNS_SECTION_ANSWER,
+ .name = qctx->fname,
+ .type = dns_rdatatype_aaaa,
+ };
+ process_section(&filter_answer);
+
+ client_state->flags &= ~FILTER_AAAA_RECURSING;
+
+ result = ns_query_done(qctx);
+
+ *resp = result;
+
+ return (NS_HOOK_RETURN);
+ }
+
+ *resp = result;
+ return (NS_HOOK_CONTINUE);
+}
+
+/*
+ * When answering an ANY query, remove AAAA if A is present.
+ */
+static ns_hookresult_t
+filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+ filter_data_t *client_state = client_state_get(qctx, inst);
+
+ *resp = ISC_R_UNSET;
+
+ if (client_state != NULL && client_state->mode != NONE) {
+ /*
+ * If we are authoritative, require an A record to be
+ * present before filtering out AAAA records; otherwise,
+ * just assume an A record exists even if it was not in the
+ * cache (and therefore is not in the response message),
+ * thus proceeding with filtering out AAAA records.
+ */
+ const section_filter_t filter_answer = {
+ .qctx = qctx,
+ .mode = client_state->mode,
+ .section = DNS_SECTION_ANSWER,
+ .name = qctx->tname,
+ .type = dns_rdatatype_aaaa,
+ .only_if_a_exists = qctx->authoritative,
+ };
+ process_section(&filter_answer);
+ }
+
+ return (NS_HOOK_CONTINUE);
+}
+
+/*
+ * Hide AAAA rrsets in the additional section if there is a matching A, and
+ * hide NS in the authority section if AAAA was filtered in the answer
+ * section.
+ */
+static ns_hookresult_t
+filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+ filter_data_t *client_state = client_state_get(qctx, inst);
+
+ *resp = ISC_R_UNSET;
+
+ if (client_state != NULL && client_state->mode != NONE) {
+ const section_filter_t filter_additional = {
+ .qctx = qctx,
+ .mode = client_state->mode,
+ .section = DNS_SECTION_ADDITIONAL,
+ .type = dns_rdatatype_aaaa,
+ .only_if_a_exists = true,
+ };
+ process_section(&filter_additional);
+
+ if ((client_state->flags & FILTER_AAAA_FILTERED) != 0) {
+ const section_filter_t filter_authority = {
+ .qctx = qctx,
+ .mode = client_state->mode,
+ .section = DNS_SECTION_AUTHORITY,
+ .type = dns_rdatatype_ns,
+ };
+ process_section(&filter_authority);
+ }
+ }
+
+ return (NS_HOOK_CONTINUE);
+}
+
+/*
+ * If the client is being detached, then we can delete our persistent data
+ * from hash table and return it to the memory pool.
+ */
+static ns_hookresult_t
+filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ filter_instance_t *inst = (filter_instance_t *)cbdata;
+
+ *resp = ISC_R_UNSET;
+
+ if (!qctx->detach_client) {
+ return (NS_HOOK_CONTINUE);
+ }
+
+ client_state_destroy(qctx, inst);
+
+ return (NS_HOOK_CONTINUE);
+}
diff --git a/bin/plugins/filter-aaaa.rst b/bin/plugins/filter-aaaa.rst
new file mode 100644
index 0000000..8cd7556
--- /dev/null
+++ b/bin/plugins/filter-aaaa.rst
@@ -0,0 +1,90 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: filter-aaaa
+.. _man_filter-aaaa:
+
+filter-aaaa.so - filter AAAA in DNS responses when A is present
+---------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`plugin query` "filter-aaaa.so" [{ parameters }];
+
+Description
+~~~~~~~~~~~
+
+:program:`filter-aaaa.so` is a query plugin module for :iscman:`named`, enabling
+:iscman:`named` to omit some IPv6 addresses when responding to clients.
+
+Until BIND 9.12, this feature was implemented natively in :iscman:`named` and
+enabled with the ``filter-aaaa`` ACL and the ``filter-aaaa-on-v4`` and
+``filter-aaaa-on-v6`` options. These options are now deprecated in
+:iscman:`named.conf` but can be passed as parameters to the
+``filter-aaaa.so`` plugin, for example:
+
+::
+
+ plugin query "filter-aaaa.so" {
+ filter-aaaa-on-v4 yes;
+ filter-aaaa-on-v6 yes;
+ filter-aaaa { 192.0.2.1; 2001:db8:2::1; };
+ };
+
+This module is intended to aid transition from IPv4 to IPv6 by
+withholding IPv6 addresses from DNS clients which are not connected to
+the IPv6 Internet, when the name being looked up has an IPv4 address
+available. Use of this module is not recommended unless absolutely
+necessary.
+
+Note: This mechanism can erroneously cause other servers not to give
+AAAA records to their clients. If a recursing server with both IPv6 and
+IPv4 network connections queries an authoritative server using this
+mechanism via IPv4, it is denied AAAA records even if its client is
+using IPv6.
+
+Options
+~~~~~~~
+
+``filter-aaaa``
+ This option specifies a list of client addresses for which AAAA filtering is to
+ be applied. The default is ``any``.
+
+``filter-aaaa-on-v4``
+ If set to ``yes``, this option indicates that the DNS client is at an IPv4 address, in
+ ``filter-aaaa``. If the response does not include DNSSEC
+ signatures, then all AAAA records are deleted from the response. This
+ filtering applies to all responses, not only authoritative
+ ones.
+
+ If set to ``break-dnssec``, then AAAA records are deleted even when
+ DNSSEC is enabled. As suggested by the name, this causes the response
+ to fail to verify, because the DNSSEC protocol is designed to detect
+ deletions.
+
+ This mechanism can erroneously cause other servers not to give AAAA
+ records to their clients. If a recursing server with both IPv6 and IPv4
+ network connections queries an authoritative server using this
+ mechanism via IPv4, it is denied AAAA records even if its client is
+ using IPv6.
+
+``filter-aaaa-on-v6``
+ This option is identical to ``filter-aaaa-on-v4``, except that it filters AAAA responses
+ to queries from IPv6 clients instead of IPv4 clients. To filter all
+ responses, set both options to ``yes``.
+
+See Also
+~~~~~~~~
+
+BIND 9 Administrator Reference Manual.
diff --git a/bin/rndc/Makefile.am b/bin/rndc/Makefile.am
new file mode 100644
index 0000000..a668522
--- /dev/null
+++ b/bin/rndc/Makefile.am
@@ -0,0 +1,26 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) \
+ $(LIBISCCFG_CFLAGS) \
+ $(LIBISCCC_CFLAGS) \
+ $(LIBBIND9_CFLAGS)
+
+AM_CPPFLAGS += \
+ -DRNDC_CONFFILE=\"${sysconfdir}/rndc.conf\" \
+ -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\"
+
+sbin_PROGRAMS = rndc
+
+rndc_SOURCES = \
+ rndc.c \
+ util.c \
+ util.h
+
+rndc_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS) \
+ $(LIBISCCC_LIBS) \
+ $(LIBISCCFG_LIBS) \
+ $(LIBBIND9_LIBS)
diff --git a/bin/rndc/Makefile.in b/bin/rndc/Makefile.in
new file mode 100644
index 0000000..7fdcb83
--- /dev/null
+++ b/bin/rndc/Makefile.in
@@ -0,0 +1,831 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+sbin_PROGRAMS = rndc$(EXEEXT)
+subdir = bin/rndc
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)"
+PROGRAMS = $(sbin_PROGRAMS)
+am_rndc_OBJECTS = rndc.$(OBJEXT) util.$(OBJEXT)
+rndc_OBJECTS = $(am_rndc_OBJECTS)
+rndc_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBISCCC_LIBS) \
+ $(LIBISCCFG_LIBS) $(LIBBIND9_LIBS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/rndc.Po ./$(DEPDIR)/util.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(rndc_SOURCES)
+DIST_SOURCES = $(rndc_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \
+ $(LIBISCCFG_CFLAGS) $(LIBISCCC_CFLAGS) $(LIBBIND9_CFLAGS) \
+ -DRNDC_CONFFILE=\"${sysconfdir}/rndc.conf\" \
+ -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\"
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD =
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+rndc_SOURCES = \
+ rndc.c \
+ util.c \
+ util.h
+
+rndc_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS) \
+ $(LIBISCCC_LIBS) \
+ $(LIBISCCFG_LIBS) \
+ $(LIBBIND9_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/rndc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/rndc/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+rndc$(EXEEXT): $(rndc_OBJECTS) $(rndc_DEPENDENCIES) $(EXTRA_rndc_DEPENDENCIES)
+ @rm -f rndc$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(rndc_OBJECTS) $(rndc_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/rndc.Po
+ -rm -f ./$(DEPDIR)/util.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/rndc.Po
+ -rm -f ./$(DEPDIR)/util.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am: uninstall-sbinPROGRAMS
+
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-sbinPROGRAMS cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir doc-am doc-local dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \
+ uninstall-am uninstall-sbinPROGRAMS unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c
new file mode 100644
index 0000000..87c36ba
--- /dev/null
+++ b/bin/rndc/rndc.c
@@ -0,0 +1,1125 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/atomic.h>
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/file.h>
+#include <isc/log.h>
+#include <isc/managers.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/netmgr.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/refcount.h>
+#include <isc/result.h>
+#include <isc/stdtime.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+
+#include <dns/name.h>
+
+#include <isccc/alist.h>
+#include <isccc/base64.h>
+#include <isccc/cc.h>
+#include <isccc/ccmsg.h>
+#include <isccc/sexpr.h>
+#include <isccc/types.h>
+#include <isccc/util.h>
+
+#include <isccfg/namedconf.h>
+
+#include <bind9/getaddresses.h>
+
+#include "util.h"
+
+#define SERVERADDRS 10
+#define RNDC_TIMEOUT 60 * 1000
+
+const char *progname = NULL;
+bool verbose;
+
+static isc_nm_t *netmgr = NULL;
+static isc_taskmgr_t *taskmgr = NULL;
+static isc_task_t *rndc_task = NULL;
+
+static const char *admin_conffile = NULL;
+static const char *admin_keyfile = NULL;
+static const char *version = PACKAGE_VERSION;
+static const char *servername = NULL;
+static isc_sockaddr_t serveraddrs[SERVERADDRS];
+static isc_sockaddr_t local4, local6;
+static bool local4set = false, local6set = false;
+static int nserveraddrs;
+static int currentaddr = 0;
+static unsigned int remoteport = 0;
+static isc_buffer_t *databuf = NULL;
+static isccc_ccmsg_t rndc_ccmsg;
+static uint32_t algorithm;
+static isccc_region_t secret;
+static bool failed = false;
+static bool c_flag = false;
+static isc_mem_t *rndc_mctx = NULL;
+static atomic_uint_fast32_t sends = 0;
+static atomic_uint_fast32_t recvs = 0;
+static atomic_uint_fast32_t connects = 0;
+static char *command = NULL;
+static char *args = NULL;
+static char program[256];
+static uint32_t serial;
+static bool quiet = false;
+static bool showresult = false;
+static bool shuttingdown = false;
+static isc_nmhandle_t *recvdone_handle = NULL;
+static isc_nmhandle_t *recvnonce_handle = NULL;
+
+static void
+rndc_startconnect(isc_sockaddr_t *addr);
+
+noreturn static void
+usage(int status);
+
+static void
+usage(int status) {
+ fprintf(stderr, "\
+Usage: %s [-b address] [-c config] [-s server] [-p port]\n\
+ [-k key-file ] [-y key] [-r] [-V] [-4 | -6] command\n\
+\n\
+command is one of the following:\n\
+\n\
+ addzone zone [class [view]] { zone-options }\n\
+ Add zone to given view. Requires allow-new-zones option.\n\
+ delzone [-clean] zone [class [view]]\n\
+ Removes zone from given view.\n\
+ dnssec -checkds [-key id [-alg algorithm]] [-when time] (published|withdrawn) zone [class [view]]\n\
+ Mark the DS record for the KSK of the given zone as seen\n\
+ in the parent. If the zone has multiple KSKs, select a\n\
+ specific key by providing the keytag with -key id and\n\
+ optionally the key's algorithm with -alg algorithm.\n\
+ Requires the zone to have a dnssec-policy.\n\
+ dnssec -rollover -key id [-alg algorithm] [-when time] zone [class [view]]\n\
+ Rollover key with id of the given zone. Requires the zone\n\
+ to have a dnssec-policy.\n\
+ dnssec -status zone [class [view]]\n\
+ Show the DNSSEC signing state for the specified zone.\n\
+ Requires the zone to have a dnssec-policy.\n\
+ dnstap -reopen\n\
+ Close, truncate and re-open the DNSTAP output file.\n\
+ dnstap -roll [count]\n\
+ Close, rename and re-open the DNSTAP output file(s).\n\
+ dumpdb [-all|-cache|-zones|-adb|-bad|-expired|-fail] [view ...]\n\
+ Dump cache(s) to the dump file (named_dump.db).\n\
+ flush Flushes all of the server's caches.\n\
+ flush [view] Flushes the server's cache for a view.\n\
+ flushname name [view]\n\
+ Flush the given name from the server's cache(s)\n\
+ flushtree name [view]\n\
+ Flush all names under the given name from the server's cache(s)\n\
+ freeze Suspend updates to all dynamic zones.\n\
+ freeze zone [class [view]]\n\
+ Suspend updates to a dynamic zone.\n\
+ halt Stop the server without saving pending updates.\n\
+ halt -p Stop the server without saving pending updates reporting\n\
+ process id.\n\
+ loadkeys zone [class [view]]\n\
+ Update keys without signing immediately.\n\
+ managed-keys refresh [class [view]]\n\
+ Check trust anchor for RFC 5011 key changes\n\
+ managed-keys status [class [view]]\n\
+ Display RFC 5011 managed keys information\n\
+ managed-keys sync [class [view]]\n\
+ Write RFC 5011 managed keys to disk\n\
+ modzone zone [class [view]] { zone-options }\n\
+ Modify a zone's configuration.\n\
+ Requires allow-new-zones option.\n\
+ notify zone [class [view]]\n\
+ Resend NOTIFY messages for the zone.\n\
+ notrace Set debugging level to 0.\n\
+ nta -dump\n\
+ List all negative trust anchors.\n\
+ nta [-lifetime duration] [-force] domain [view]\n\
+ Set a negative trust anchor, disabling DNSSEC validation\n\
+ for the given domain.\n\
+ Using -lifetime specifies the duration of the NTA, up\n\
+ to one week.\n\
+ Using -force prevents the NTA from expiring before its\n\
+ full lifetime, even if the domain can validate sooner.\n\
+ nta -remove domain [view]\n\
+ Remove a negative trust anchor, re-enabling validation\n\
+ for the given domain.\n\
+ querylog [ on | off ]\n\
+ Enable / disable query logging.\n\
+ reconfig Reload configuration file and new zones only.\n\
+ recursing Dump the queries that are currently recursing (named.recursing)\n\
+ refresh zone [class [view]]\n\
+ Schedule immediate maintenance for a zone.\n\
+ reload Reload configuration file and zones.\n\
+ reload zone [class [view]]\n\
+ Reload a single zone.\n\
+ retransfer zone [class [view]]\n\
+ Retransfer a single zone without checking serial number.\n\
+ scan Scan available network interfaces for changes.\n\
+ secroots [view ...]\n\
+ Write security roots to the secroots file.\n\
+ serve-stale [ on | off | reset | status ] [class [view]]\n\
+ Control whether stale answers are returned\n\
+ showzone zone [class [view]]\n\
+ Print a zone's configuration.\n\
+ sign zone [class [view]]\n\
+ Update zone keys, and sign as needed.\n\
+ signing -clear all zone [class [view]]\n\
+ Remove the private records for all keys that have\n\
+ finished signing the given zone.\n\
+ signing -clear <keyid>/<algorithm> zone [class [view]]\n\
+ Remove the private record that indicating the given key\n\
+ has finished signing the given zone.\n\
+ signing -list zone [class [view]]\n\
+ List the private records showing the state of DNSSEC\n\
+ signing in the given zone.\n\
+ signing -nsec3param hash flags iterations salt zone [class [view]]\n\
+ Add NSEC3 chain to zone if already signed.\n\
+ Prime zone with NSEC3 chain if not yet signed.\n\
+ signing -nsec3param none zone [class [view]]\n\
+ Remove NSEC3 chains from zone.\n\
+ signing -serial <value> zone [class [view]]\n\
+ Set the zones's serial to <value>.\n\
+ stats Write server statistics to the statistics file.\n\
+ status Display status of the server.\n\
+ stop Save pending updates to master files and stop the server.\n\
+ stop -p Save pending updates to master files and stop the server\n\
+ reporting process id.\n\
+ sync [-clean] Dump changes to all dynamic zones to disk, and optionally\n\
+ remove their journal files.\n\
+ sync [-clean] zone [class [view]]\n\
+ Dump a single zone's changes to disk, and optionally\n\
+ remove its journal file.\n\
+ tcp-timeouts Display the tcp-*-timeout option values\n\
+ tcp-timeouts initial idle keepalive advertised\n\
+ Update the tcp-*-timeout option values\n\
+ thaw Enable updates to all dynamic zones and reload them.\n\
+ thaw zone [class [view]]\n\
+ Enable updates to a frozen dynamic zone and reload it.\n\
+ trace Increment debugging level by one.\n\
+ trace level Change the debugging level.\n\
+ tsig-delete keyname [view]\n\
+ Delete a TKEY-negotiated TSIG key.\n\
+ tsig-list List all currently active TSIG keys, including both statically\n\
+ configured and TKEY-negotiated keys.\n\
+ validation [ on | off | status ] [view]\n\
+ Enable / disable DNSSEC validation.\n\
+ zonestatus zone [class [view]]\n\
+ Display the current status of a zone.\n\
+\n\
+Version: %s\n",
+ progname, version);
+
+ exit(status);
+}
+
+#define CMDLINE_FLAGS "46b:c:hk:Mmp:qrs:Vy:"
+
+static void
+preparse_args(int argc, char **argv) {
+ bool ipv4only = false, ipv6only = false;
+ int ch;
+
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case '4':
+ if (ipv6only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv4only = true;
+ break;
+ case '6':
+ if (ipv4only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv6only = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ isc_commandline_reset = true;
+ isc_commandline_index = 1;
+}
+
+static void
+get_addresses(const char *host, in_port_t port) {
+ isc_result_t result;
+ int found = 0, count;
+
+ REQUIRE(host != NULL);
+
+ if (*host == '/') {
+ result = isc_sockaddr_frompath(&serveraddrs[nserveraddrs],
+ host);
+ if (result == ISC_R_SUCCESS) {
+ nserveraddrs++;
+ }
+ } else {
+ count = SERVERADDRS - nserveraddrs;
+ result = bind9_getaddresses(
+ host, port, &serveraddrs[nserveraddrs], count, &found);
+ nserveraddrs += found;
+ }
+ if (result != ISC_R_SUCCESS) {
+ fatal("couldn't get address for '%s': %s", host,
+ isc_result_totext(result));
+ }
+ INSIST(nserveraddrs > 0);
+}
+
+static void
+rndc_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
+ isc_nmhandle_t *sendhandle = (isc_nmhandle_t *)arg;
+
+ if (result != ISC_R_SUCCESS) {
+ fatal("send failed: %s", isc_result_totext(result));
+ }
+
+ REQUIRE(sendhandle == handle);
+ isc_nmhandle_detach(&sendhandle);
+
+ if (atomic_fetch_sub_release(&sends, 1) == 1 &&
+ atomic_load_acquire(&recvs) == 0)
+ {
+ shuttingdown = true;
+ isc_task_detach(&rndc_task);
+ isc_app_shutdown();
+ }
+}
+
+static void
+rndc_recvdone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
+ isccc_ccmsg_t *ccmsg = (isccc_ccmsg_t *)arg;
+ isccc_sexpr_t *response = NULL;
+ isccc_sexpr_t *data = NULL;
+ isccc_region_t source;
+ char *errormsg = NULL;
+ char *textmsg = NULL;
+
+ REQUIRE(ccmsg != NULL);
+
+ if (shuttingdown && (result == ISC_R_EOF || result == ISC_R_CANCELED)) {
+ atomic_fetch_sub_release(&recvs, 1);
+ if (handle != NULL) {
+ REQUIRE(recvdone_handle == handle);
+ isc_nmhandle_detach(&recvdone_handle);
+ }
+ return;
+ } else if (result == ISC_R_EOF) {
+ fatal("connection to remote host closed.\n"
+ "* This may indicate that the\n"
+ "* remote server is using an older\n"
+ "* version of the command protocol,\n"
+ "* this host is not authorized to connect,\n"
+ "* the clocks are not synchronized,\n"
+ "* the key signing algorithm is incorrect,\n"
+ "* or the key is invalid.");
+ } else if (result != ISC_R_SUCCESS) {
+ fatal("recv failed: %s", isc_result_totext(result));
+ }
+
+ source.rstart = isc_buffer_base(ccmsg->buffer);
+ source.rend = isc_buffer_used(ccmsg->buffer);
+
+ DO("parse message",
+ isccc_cc_fromwire(&source, &response, algorithm, &secret));
+
+ data = isccc_alist_lookup(response, "_data");
+ if (!isccc_alist_alistp(data)) {
+ fatal("bad or missing data section in response");
+ }
+ result = isccc_cc_lookupstring(data, "err", &errormsg);
+ if (result == ISC_R_SUCCESS) {
+ failed = true;
+ fprintf(stderr, "%s: '%s' failed: %s\n", progname, command,
+ errormsg);
+ } else if (result != ISC_R_NOTFOUND) {
+ fprintf(stderr, "%s: parsing response failed: %s\n", progname,
+ isc_result_totext(result));
+ }
+
+ result = isccc_cc_lookupstring(data, "text", &textmsg);
+ if (result == ISC_R_SUCCESS) {
+ if ((!quiet || failed) && strlen(textmsg) != 0U) {
+ fprintf(failed ? stderr : stdout, "%s\n", textmsg);
+ }
+ } else if (result != ISC_R_NOTFOUND) {
+ fprintf(stderr, "%s: parsing response failed: %s\n", progname,
+ isc_result_totext(result));
+ }
+
+ if (showresult) {
+ isc_result_t eresult;
+
+ result = isccc_cc_lookupuint32(data, "result", &eresult);
+ if (result == ISC_R_SUCCESS) {
+ printf("%s %u\n", isc_result_toid(eresult), eresult);
+ } else {
+ printf("NONE -1\n");
+ }
+ }
+
+ isccc_sexpr_free(&response);
+
+ REQUIRE(recvdone_handle == handle);
+ isc_nmhandle_detach(&recvdone_handle);
+
+ if (atomic_fetch_sub_release(&recvs, 1) == 1 &&
+ atomic_load_acquire(&sends) == 0)
+ {
+ shuttingdown = true;
+ isc_task_detach(&rndc_task);
+ isc_app_shutdown();
+ }
+}
+
+static void
+rndc_recvnonce(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
+ isccc_ccmsg_t *ccmsg = (isccc_ccmsg_t *)arg;
+ isccc_sexpr_t *response = NULL;
+ isc_nmhandle_t *sendhandle = NULL;
+ isccc_sexpr_t *_ctrl = NULL;
+ isccc_region_t source;
+ uint32_t nonce;
+ isccc_sexpr_t *request = NULL;
+ isccc_time_t now;
+ isc_region_t r;
+ isccc_sexpr_t *data = NULL;
+ isc_buffer_t b;
+
+ REQUIRE(ccmsg != NULL);
+
+ if (shuttingdown && (result == ISC_R_EOF || result == ISC_R_CANCELED)) {
+ atomic_fetch_sub_release(&recvs, 1);
+ if (handle != NULL) {
+ REQUIRE(recvnonce_handle == handle);
+ isc_nmhandle_detach(&recvnonce_handle);
+ }
+ return;
+ } else if (result == ISC_R_EOF) {
+ fatal("connection to remote host closed.\n"
+ "* This may indicate that the\n"
+ "* remote server is using an older\n"
+ "* version of the command protocol,\n"
+ "* this host is not authorized to connect,\n"
+ "* the clocks are not synchronized,\n"
+ "* the key signing algorithm is incorrect\n"
+ "* or the key is invalid.");
+ } else if (result != ISC_R_SUCCESS) {
+ fatal("recv failed: %s", isc_result_totext(result));
+ }
+
+ source.rstart = isc_buffer_base(ccmsg->buffer);
+ source.rend = isc_buffer_used(ccmsg->buffer);
+
+ DO("parse message",
+ isccc_cc_fromwire(&source, &response, algorithm, &secret));
+
+ _ctrl = isccc_alist_lookup(response, "_ctrl");
+ if (!isccc_alist_alistp(_ctrl)) {
+ fatal("bad or missing ctrl section in response");
+ }
+ nonce = 0;
+ if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS) {
+ nonce = 0;
+ }
+
+ isc_stdtime_get(&now);
+
+ DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
+ now, now + 60, &request));
+ data = isccc_alist_lookup(request, "_data");
+ if (data == NULL) {
+ fatal("_data section missing");
+ }
+ if (isccc_cc_definestring(data, "type", args) == NULL) {
+ fatal("out of memory");
+ }
+ if (nonce != 0) {
+ _ctrl = isccc_alist_lookup(request, "_ctrl");
+ if (_ctrl == NULL) {
+ fatal("_ctrl section missing");
+ }
+ if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL) {
+ fatal("out of memory");
+ }
+ }
+
+ isc_buffer_clear(databuf);
+ /* Skip the length field (4 bytes) */
+ isc_buffer_add(databuf, 4);
+
+ DO("render message",
+ isccc_cc_towire(request, &databuf, algorithm, &secret));
+
+ isc_buffer_init(&b, databuf->base, 4);
+ isc_buffer_putuint32(&b, databuf->used - 4);
+
+ r.base = databuf->base;
+ r.length = databuf->used;
+
+ isc_nmhandle_attach(handle, &recvdone_handle);
+ atomic_fetch_add_relaxed(&recvs, 1);
+ isccc_ccmsg_readmessage(ccmsg, rndc_recvdone, ccmsg);
+
+ isc_nmhandle_attach(handle, &sendhandle);
+ atomic_fetch_add_relaxed(&sends, 1);
+ isc_nm_send(handle, &r, rndc_senddone, sendhandle);
+
+ REQUIRE(recvnonce_handle == handle);
+ isc_nmhandle_detach(&recvnonce_handle);
+ atomic_fetch_sub_release(&recvs, 1);
+
+ isccc_sexpr_free(&response);
+ isccc_sexpr_free(&request);
+ return;
+}
+
+static void
+rndc_connected(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
+ isccc_ccmsg_t *ccmsg = (isccc_ccmsg_t *)arg;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isccc_sexpr_t *request = NULL;
+ isccc_sexpr_t *data = NULL;
+ isccc_time_t now;
+ isc_region_t r;
+ isc_buffer_t b;
+ isc_nmhandle_t *connhandle = NULL;
+ isc_nmhandle_t *sendhandle = NULL;
+
+ REQUIRE(ccmsg != NULL);
+
+ if (result != ISC_R_SUCCESS) {
+ atomic_fetch_sub_release(&connects, 1);
+ isc_sockaddr_format(&serveraddrs[currentaddr], socktext,
+ sizeof(socktext));
+ if (++currentaddr < nserveraddrs) {
+ notify("connection failed: %s: %s", socktext,
+ isc_result_totext(result));
+ rndc_startconnect(&serveraddrs[currentaddr]);
+ return;
+ }
+
+ fatal("connect failed: %s: %s", socktext,
+ isc_result_totext(result));
+ }
+
+ isc_nmhandle_attach(handle, &connhandle);
+
+ isc_stdtime_get(&now);
+ DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
+ now, now + 60, &request));
+ data = isccc_alist_lookup(request, "_data");
+ if (data == NULL) {
+ fatal("_data section missing");
+ }
+ if (isccc_cc_definestring(data, "type", "null") == NULL) {
+ fatal("out of memory");
+ }
+
+ isc_buffer_clear(databuf);
+ /* Skip the length field (4 bytes) */
+ isc_buffer_add(databuf, 4);
+
+ DO("render message",
+ isccc_cc_towire(request, &databuf, algorithm, &secret));
+
+ isc_buffer_init(&b, databuf->base, 4);
+ isc_buffer_putuint32(&b, databuf->used - 4);
+
+ r.base = databuf->base;
+ r.length = databuf->used;
+
+ isccc_ccmsg_init(rndc_mctx, handle, ccmsg);
+ isccc_ccmsg_setmaxsize(ccmsg, 1024 * 1024);
+
+ isc_nmhandle_attach(handle, &recvnonce_handle);
+ atomic_fetch_add_relaxed(&recvs, 1);
+ isccc_ccmsg_readmessage(ccmsg, rndc_recvnonce, ccmsg);
+
+ isc_nmhandle_attach(handle, &sendhandle);
+ atomic_fetch_add_relaxed(&sends, 1);
+ isc_nm_send(handle, &r, rndc_senddone, sendhandle);
+
+ isc_nmhandle_detach(&connhandle);
+ atomic_fetch_sub_release(&connects, 1);
+
+ isccc_sexpr_free(&request);
+}
+
+static void
+rndc_startconnect(isc_sockaddr_t *addr) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t *local = NULL;
+
+ isc_sockaddr_format(addr, socktext, sizeof(socktext));
+
+ notify("using server %s (%s)", servername, socktext);
+
+ switch (isc_sockaddr_pf(addr)) {
+ case AF_INET:
+ local = &local4;
+ break;
+ case AF_INET6:
+ local = &local6;
+ break;
+ case AF_UNIX:
+ /*
+ * TODO: support UNIX domain sockets in netgmr.
+ */
+ fatal("UNIX domain sockets not currently supported");
+ default:
+ UNREACHABLE();
+ }
+
+ atomic_fetch_add_relaxed(&connects, 1);
+ isc_nm_tcpconnect(netmgr, local, addr, rndc_connected, &rndc_ccmsg,
+ RNDC_TIMEOUT, 0);
+}
+
+static void
+rndc_start(isc_task_t *task, isc_event_t *event) {
+ isc_event_free(&event);
+
+ UNUSED(task);
+
+ currentaddr = 0;
+ rndc_startconnect(&serveraddrs[currentaddr]);
+}
+
+static void
+parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname,
+ cfg_parser_t **pctxp, cfg_obj_t **configp) {
+ isc_result_t result;
+ const char *conffile = admin_conffile;
+ const cfg_obj_t *addresses = NULL;
+ const cfg_obj_t *defkey = NULL;
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *servers = NULL;
+ const cfg_obj_t *server = NULL;
+ const cfg_obj_t *keys = NULL;
+ const cfg_obj_t *key = NULL;
+ const cfg_obj_t *defport = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ const cfg_obj_t *algorithmobj = NULL;
+ cfg_obj_t *config = NULL;
+ const cfg_obj_t *address = NULL;
+ const cfg_listelt_t *elt;
+ const char *secretstr;
+ const char *algorithmstr;
+ static char secretarray[1024];
+ const cfg_type_t *conftype = &cfg_type_rndcconf;
+ bool key_only = false;
+ const cfg_listelt_t *element;
+
+ if (!isc_file_exists(conffile)) {
+ conffile = admin_keyfile;
+ conftype = &cfg_type_rndckey;
+
+ if (c_flag) {
+ fatal("%s does not exist", admin_conffile);
+ }
+
+ if (!isc_file_exists(conffile)) {
+ fatal("neither %s nor %s was found", admin_conffile,
+ admin_keyfile);
+ }
+ key_only = true;
+ } else if (!c_flag && isc_file_exists(admin_keyfile)) {
+ fprintf(stderr,
+ "WARNING: key file (%s) exists, but using "
+ "default configuration file (%s)\n",
+ admin_keyfile, admin_conffile);
+ }
+
+ DO("create parser", cfg_parser_create(mctx, log, pctxp));
+
+ /*
+ * The parser will output its own errors, so DO() is not used.
+ */
+ result = cfg_parse_file(*pctxp, conffile, conftype, &config);
+ if (result != ISC_R_SUCCESS) {
+ fatal("could not load rndc configuration");
+ }
+
+ if (!key_only) {
+ (void)cfg_map_get(config, "options", &options);
+ }
+
+ if (key_only && servername == NULL) {
+ servername = "127.0.0.1";
+ } else if (servername == NULL && options != NULL) {
+ const cfg_obj_t *defserverobj = NULL;
+ (void)cfg_map_get(options, "default-server", &defserverobj);
+ if (defserverobj != NULL) {
+ servername = cfg_obj_asstring(defserverobj);
+ }
+ }
+
+ if (servername == NULL) {
+ fatal("no server specified and no default");
+ }
+
+ if (!key_only) {
+ (void)cfg_map_get(config, "server", &servers);
+ if (servers != NULL) {
+ for (elt = cfg_list_first(servers); elt != NULL;
+ elt = cfg_list_next(elt))
+ {
+ const char *name = NULL;
+ server = cfg_listelt_value(elt);
+ name = cfg_obj_asstring(
+ cfg_map_getname(server));
+ if (strcasecmp(name, servername) == 0) {
+ break;
+ }
+ server = NULL;
+ }
+ }
+ }
+
+ /*
+ * Look for the name of the key to use.
+ */
+ if (keyname != NULL) {
+ /* Was set on command line, do nothing. */
+ } else if (server != NULL) {
+ DO("get key for server", cfg_map_get(server, "key", &defkey));
+ keyname = cfg_obj_asstring(defkey);
+ } else if (options != NULL) {
+ DO("get default key",
+ cfg_map_get(options, "default-key", &defkey));
+ keyname = cfg_obj_asstring(defkey);
+ } else if (!key_only) {
+ fatal("no key for server and no default");
+ }
+
+ /*
+ * Get the key's definition.
+ */
+ if (key_only) {
+ DO("get key", cfg_map_get(config, "key", &key));
+ } else {
+ DO("get config key list", cfg_map_get(config, "key", &keys));
+ for (elt = cfg_list_first(keys); elt != NULL;
+ elt = cfg_list_next(elt))
+ {
+ const char *name = NULL;
+
+ key = cfg_listelt_value(elt);
+ name = cfg_obj_asstring(cfg_map_getname(key));
+ if (strcasecmp(name, keyname) == 0) {
+ break;
+ }
+ }
+ if (elt == NULL) {
+ fatal("no key definition for name %s", keyname);
+ }
+ }
+ (void)cfg_map_get(key, "secret", &secretobj);
+ (void)cfg_map_get(key, "algorithm", &algorithmobj);
+ if (secretobj == NULL || algorithmobj == NULL) {
+ fatal("key must have algorithm and secret");
+ }
+
+ secretstr = cfg_obj_asstring(secretobj);
+ algorithmstr = cfg_obj_asstring(algorithmobj);
+
+ if (strcasecmp(algorithmstr, "hmac-md5") == 0) {
+ algorithm = ISCCC_ALG_HMACMD5;
+ } else if (strcasecmp(algorithmstr, "hmac-sha1") == 0) {
+ algorithm = ISCCC_ALG_HMACSHA1;
+ } else if (strcasecmp(algorithmstr, "hmac-sha224") == 0) {
+ algorithm = ISCCC_ALG_HMACSHA224;
+ } else if (strcasecmp(algorithmstr, "hmac-sha256") == 0) {
+ algorithm = ISCCC_ALG_HMACSHA256;
+ } else if (strcasecmp(algorithmstr, "hmac-sha384") == 0) {
+ algorithm = ISCCC_ALG_HMACSHA384;
+ } else if (strcasecmp(algorithmstr, "hmac-sha512") == 0) {
+ algorithm = ISCCC_ALG_HMACSHA512;
+ } else {
+ fatal("unsupported algorithm: %s", algorithmstr);
+ }
+
+ secret.rstart = (unsigned char *)secretarray;
+ secret.rend = (unsigned char *)secretarray + sizeof(secretarray);
+ DO("decode base64 secret", isccc_base64_decode(secretstr, &secret));
+ secret.rend = secret.rstart;
+ secret.rstart = (unsigned char *)secretarray;
+
+ /*
+ * Find the port to connect to.
+ */
+ if (remoteport != 0) {
+ /* Was set on command line, do nothing. */
+ } else {
+ if (server != NULL) {
+ (void)cfg_map_get(server, "port", &defport);
+ }
+ if (defport == NULL && options != NULL) {
+ (void)cfg_map_get(options, "default-port", &defport);
+ }
+ }
+ if (defport != NULL) {
+ remoteport = cfg_obj_asuint32(defport);
+ if (remoteport > 65535 || remoteport == 0) {
+ fatal("port %u out of range", remoteport);
+ }
+ } else if (remoteport == 0) {
+ remoteport = NS_CONTROL_PORT;
+ }
+
+ if (server != NULL) {
+ result = cfg_map_get(server, "addresses", &addresses);
+ } else {
+ result = ISC_R_NOTFOUND;
+ }
+ if (result == ISC_R_SUCCESS) {
+ for (element = cfg_list_first(addresses); element != NULL;
+ element = cfg_list_next(element))
+ {
+ isc_sockaddr_t sa;
+
+ address = cfg_listelt_value(element);
+ if (!cfg_obj_issockaddr(address)) {
+ unsigned int myport;
+ const char *name;
+ const cfg_obj_t *obj;
+
+ obj = cfg_tuple_get(address, "name");
+ name = cfg_obj_asstring(obj);
+ obj = cfg_tuple_get(address, "port");
+ if (cfg_obj_isuint32(obj)) {
+ myport = cfg_obj_asuint32(obj);
+ if (myport > UINT16_MAX || myport == 0)
+ {
+ fatal("port %u out of range",
+ myport);
+ }
+ } else {
+ myport = remoteport;
+ }
+ if (nserveraddrs < SERVERADDRS) {
+ get_addresses(name, (in_port_t)myport);
+ } else {
+ fprintf(stderr,
+ "too many address: "
+ "%s: dropped\n",
+ name);
+ }
+ continue;
+ }
+ sa = *cfg_obj_assockaddr(address);
+ if (isc_sockaddr_getport(&sa) == 0) {
+ isc_sockaddr_setport(&sa, remoteport);
+ }
+ if (nserveraddrs < SERVERADDRS) {
+ serveraddrs[nserveraddrs++] = sa;
+ } else {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(&sa, socktext,
+ sizeof(socktext));
+ fprintf(stderr,
+ "too many address: %s: dropped\n",
+ socktext);
+ }
+ }
+ }
+
+ if (!local4set && server != NULL) {
+ address = NULL;
+ cfg_map_get(server, "source-address", &address);
+ if (address != NULL) {
+ local4 = *cfg_obj_assockaddr(address);
+ local4set = true;
+ }
+ }
+ if (!local4set && options != NULL) {
+ address = NULL;
+ cfg_map_get(options, "default-source-address", &address);
+ if (address != NULL) {
+ local4 = *cfg_obj_assockaddr(address);
+ local4set = true;
+ }
+ }
+
+ if (!local6set && server != NULL) {
+ address = NULL;
+ cfg_map_get(server, "source-address-v6", &address);
+ if (address != NULL) {
+ local6 = *cfg_obj_assockaddr(address);
+ local6set = true;
+ }
+ }
+ if (!local6set && options != NULL) {
+ address = NULL;
+ cfg_map_get(options, "default-source-address-v6", &address);
+ if (address != NULL) {
+ local6 = *cfg_obj_assockaddr(address);
+ local6set = true;
+ }
+ }
+
+ *configp = config;
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result = ISC_R_SUCCESS;
+ bool show_final_mem = false;
+ isc_log_t *log = NULL;
+ isc_logconfig_t *logconfig = NULL;
+ isc_logdestination_t logdest;
+ cfg_parser_t *pctx = NULL;
+ cfg_obj_t *config = NULL;
+ const char *keyname = NULL;
+ struct in_addr in;
+ struct in6_addr in6;
+ char *p;
+ size_t argslen;
+ int ch;
+ int i;
+
+ result = isc_file_progname(*argv, program, sizeof(program));
+ if (result != ISC_R_SUCCESS) {
+ memmove(program, "rndc", 5);
+ }
+ progname = program;
+
+ admin_conffile = RNDC_CONFFILE;
+ admin_keyfile = RNDC_KEYFILE;
+
+ isc_sockaddr_any(&local4);
+ isc_sockaddr_any6(&local6);
+
+ result = isc_app_start();
+ if (result != ISC_R_SUCCESS) {
+ fatal("isc_app_start() failed: %s", isc_result_totext(result));
+ }
+
+ isc_commandline_errprint = false;
+
+ preparse_args(argc, argv);
+
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case '4':
+ if (isc_net_probeipv4() != ISC_R_SUCCESS) {
+ fatal("can't find IPv4 networking");
+ }
+ isc_net_disableipv6();
+ break;
+ case '6':
+ if (isc_net_probeipv6() != ISC_R_SUCCESS) {
+ fatal("can't find IPv6 networking");
+ }
+ isc_net_disableipv4();
+ break;
+ case 'b':
+ if (inet_pton(AF_INET, isc_commandline_argument, &in) ==
+ 1)
+ {
+ isc_sockaddr_fromin(&local4, &in, 0);
+ local4set = true;
+ } else if (inet_pton(AF_INET6, isc_commandline_argument,
+ &in6) == 1)
+ {
+ isc_sockaddr_fromin6(&local6, &in6, 0);
+ local6set = true;
+ }
+ break;
+
+ case 'c':
+ admin_conffile = isc_commandline_argument;
+ c_flag = true;
+ break;
+
+ case 'k':
+ admin_keyfile = isc_commandline_argument;
+ break;
+
+ case 'M':
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE;
+ break;
+
+ case 'm':
+ show_final_mem = true;
+ break;
+
+ case 'p':
+ remoteport = atoi(isc_commandline_argument);
+ if (remoteport > 65535 || remoteport == 0) {
+ fatal("port '%s' out of range",
+ isc_commandline_argument);
+ }
+ break;
+
+ case 'q':
+ quiet = true;
+ break;
+
+ case 'r':
+ showresult = true;
+ break;
+
+ case 's':
+ servername = isc_commandline_argument;
+ break;
+
+ case 'V':
+ verbose = true;
+ break;
+
+ case 'y':
+ keyname = isc_commandline_argument;
+ break;
+
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ usage(1);
+ }
+ FALLTHROUGH;
+ case 'h':
+ usage(0);
+ break;
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", program,
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argv[0] == NULL) {
+ usage(1);
+ } else {
+ command = argv[0];
+ if (strcmp(command, "restart") == 0) {
+ fatal("'%s' is not implemented", command);
+ }
+ notify("%s", command);
+ }
+
+ serial = isc_random32();
+
+ isc_mem_create(&rndc_mctx);
+ isc_managers_create(rndc_mctx, 1, 0, &netmgr, &taskmgr, NULL);
+ DO("create task", isc_task_create(taskmgr, 0, &rndc_task));
+
+ isc_nm_settimeouts(netmgr, RNDC_TIMEOUT, RNDC_TIMEOUT, RNDC_TIMEOUT, 0);
+
+ isc_log_create(rndc_mctx, &log, &logconfig);
+ isc_log_setcontext(log);
+ isc_log_settag(logconfig, progname);
+ logdest.file.stream = stderr;
+ logdest.file.name = NULL;
+ logdest.file.versions = ISC_LOG_ROLLNEVER;
+ logdest.file.maximum_size = 0;
+ isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC,
+ ISC_LOG_INFO, &logdest,
+ ISC_LOG_PRINTTAG | ISC_LOG_PRINTLEVEL);
+ DO("enabling log channel",
+ isc_log_usechannel(logconfig, "stderr", NULL, NULL));
+
+ parse_config(rndc_mctx, log, keyname, &pctx, &config);
+
+ isc_buffer_allocate(rndc_mctx, &databuf, 2048);
+
+ /*
+ * Convert argc/argv into a space-delimited command string
+ * similar to what the user might enter in interactive mode
+ * (if that were implemented).
+ */
+ argslen = 0;
+ for (i = 0; i < argc; i++) {
+ argslen += strlen(argv[i]) + 1;
+ }
+
+ args = isc_mem_get(rndc_mctx, argslen);
+
+ p = args;
+ for (i = 0; i < argc; i++) {
+ size_t len = strlen(argv[i]);
+ memmove(p, argv[i], len);
+ p += len;
+ *p++ = ' ';
+ }
+
+ p--;
+ *p++ = '\0';
+ INSIST(p == args + argslen);
+
+ if (nserveraddrs == 0 && servername != NULL) {
+ get_addresses(servername, (in_port_t)remoteport);
+ }
+
+ DO("post event", isc_app_onrun(rndc_mctx, rndc_task, rndc_start, NULL));
+
+ result = isc_app_run();
+ if (result != ISC_R_SUCCESS) {
+ fatal("isc_app_run() failed: %s", isc_result_totext(result));
+ }
+
+ isc_managers_destroy(&netmgr, &taskmgr, NULL);
+
+ /*
+ * Note: when TCP connections are shut down, there will be a final
+ * call to the isccc callback routine with &rndc_ccmsg as its
+ * argument. We therefore need to delay invalidating it until
+ * after the netmgr is closed down.
+ */
+ isccc_ccmsg_invalidate(&rndc_ccmsg);
+
+ isc_log_destroy(&log);
+ isc_log_setcontext(NULL);
+
+ cfg_obj_destroy(pctx, &config);
+ cfg_parser_destroy(&pctx);
+
+ isc_mem_put(rndc_mctx, args, argslen);
+
+ isc_buffer_free(&databuf);
+
+ if (show_final_mem) {
+ isc_mem_stats(rndc_mctx, stderr);
+ }
+
+ isc_mem_destroy(&rndc_mctx);
+
+ if (failed) {
+ return (1);
+ }
+
+ return (0);
+}
diff --git a/bin/rndc/rndc.conf.rst b/bin/rndc/rndc.conf.rst
new file mode 100644
index 0000000..20e6bc9
--- /dev/null
+++ b/bin/rndc/rndc.conf.rst
@@ -0,0 +1,158 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: rndc.conf
+.. program:: rndc.conf
+.. _man_rndc.conf:
+
+rndc.conf - rndc configuration file
+-----------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`rndc.conf`
+
+Description
+~~~~~~~~~~~
+
+:program:`rndc.conf` is the configuration file for :iscman:`rndc`, the BIND 9 name
+server control utility. This file has a similar structure and syntax to
+:iscman:`named.conf`. Statements are enclosed in braces and terminated with a
+semi-colon. Clauses in the statements are also semi-colon terminated.
+The usual comment styles are supported:
+
+C style: /\* \*/
+
+C++ style: // to end of line
+
+Unix style: # to end of line
+
+:program:`rndc.conf` is much simpler than :iscman:`named.conf`. The file uses three
+statements: an options statement, a server statement, and a key
+statement.
+
+The ``options`` statement contains five clauses. The ``default-server``
+clause is followed by the name or address of a name server. This host
+is used when no name server is given as an argument to :iscman:`rndc`.
+The ``default-key`` clause is followed by the name of a key, which is
+identified by a ``key`` statement. If no ``keyid`` is provided on the
+rndc command line, and no ``key`` clause is found in a matching
+``server`` statement, this default key is used to authenticate the
+server's commands and responses. The ``default-port`` clause is followed
+by the port to connect to on the remote name server. If no ``port``
+option is provided on the rndc command line, and no ``port`` clause is
+found in a matching ``server`` statement, this default port is used
+to connect. The ``default-source-address`` and
+``default-source-address-v6`` clauses can be used to set the IPv4
+and IPv6 source addresses respectively.
+
+After the ``server`` keyword, the server statement includes a string
+which is the hostname or address for a name server. The statement has
+three possible clauses: ``key``, ``port``, and ``addresses``. The key
+name must match the name of a key statement in the file. The port number
+specifies the port to connect to. If an ``addresses`` clause is supplied,
+these addresses are used instead of the server name. Each address
+can take an optional port. If an ``source-address`` or
+``source-address-v6`` is supplied, it is used to specify the
+IPv4 and IPv6 source address, respectively.
+
+The ``key`` statement begins with an identifying string, the name of the
+key. The statement has two clauses. ``algorithm`` identifies the
+authentication algorithm for :iscman:`rndc` to use; currently only HMAC-MD5
+(for compatibility), HMAC-SHA1, HMAC-SHA224, HMAC-SHA256 (default),
+HMAC-SHA384, and HMAC-SHA512 are supported. This is followed by a secret
+clause which contains the base-64 encoding of the algorithm's
+authentication key. The base-64 string is enclosed in double quotes.
+
+There are two common ways to generate the base-64 string for the secret.
+The BIND 9 program :iscman:`rndc-confgen` can be used to generate a random
+key, or the ``mmencode`` program, also known as ``mimencode``, can be
+used to generate a base-64 string from known input. ``mmencode`` does
+not ship with BIND 9 but is available on many systems. See the Example
+section for sample command lines for each.
+
+Example
+~~~~~~~
+
+::
+
+ options {
+ default-server localhost;
+ default-key samplekey;
+ };
+
+::
+
+ server localhost {
+ key samplekey;
+ };
+
+::
+
+ server testserver {
+ key testkey;
+ addresses { localhost port 5353; };
+ };
+
+::
+
+ key samplekey {
+ algorithm hmac-sha256;
+ secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz";
+ };
+
+::
+
+ key testkey {
+ algorithm hmac-sha256;
+ secret "R3HI8P6BKw9ZwXwN3VZKuQ==";
+ };
+
+
+In the above example, :iscman:`rndc` by default uses the server at
+localhost (127.0.0.1) and the key called "samplekey". Commands to the
+localhost server use the "samplekey" key, which must also be defined
+in the server's configuration file with the same name and secret. The
+key statement indicates that "samplekey" uses the HMAC-SHA256 algorithm
+and its secret clause contains the base-64 encoding of the HMAC-SHA256
+secret enclosed in double quotes.
+
+If :option:`rndc -s testserver <rndc -s>` is used, then :iscman:`rndc` connects to the server
+on localhost port 5353 using the key "testkey".
+
+To generate a random secret with :iscman:`rndc-confgen`:
+
+:iscman:`rndc-confgen`
+
+A complete :program:`rndc.conf` file, including the randomly generated key,
+is written to the standard output. Commented-out ``key`` and
+``controls`` statements for :iscman:`named.conf` are also printed.
+
+To generate a base-64 secret with ``mmencode``:
+
+``echo "known plaintext for a secret" | mmencode``
+
+Name Server Configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The name server must be configured to accept rndc connections and to
+recognize the key specified in the :program:`rndc.conf` file, using the
+controls statement in :iscman:`named.conf`. See the sections on the
+``controls`` statement in the BIND 9 Administrator Reference Manual for
+details.
+
+See Also
+~~~~~~~~
+
+:iscman:`rndc(8) <rndc>`, :iscman:`rndc-confgen(8) <rndc-confgen>`, :manpage:`mmencode(1)`, BIND 9 Administrator Reference Manual.
diff --git a/bin/rndc/rndc.rst b/bin/rndc/rndc.rst
new file mode 100644
index 0000000..35a4f31
--- /dev/null
+++ b/bin/rndc/rndc.rst
@@ -0,0 +1,667 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: rndc
+.. program:: rndc
+.. _man_rndc:
+
+rndc - name server control utility
+----------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`rndc` [**-b** source-address] [**-c** config-file] [**-k** key-file] [**-s** server] [**-p** port] [**-q**] [**-r**] [**-V**] [**-y** server_key] [[**-4**] | [**-6**]] {command}
+
+Description
+~~~~~~~~~~~
+
+:program:`rndc` controls the operation of a name server. If :program:`rndc` is
+invoked with no command line options or arguments, it prints a short
+summary of the supported commands and the available options and their
+arguments.
+
+:program:`rndc` communicates with the name server over a TCP connection,
+sending commands authenticated with digital signatures. In the current
+versions of :program:`rndc` and :iscman:`named`, the only supported authentication
+algorithms are HMAC-MD5 (for compatibility), HMAC-SHA1, HMAC-SHA224,
+HMAC-SHA256 (default), HMAC-SHA384, and HMAC-SHA512. They use a shared
+secret on each end of the connection, which provides TSIG-style
+authentication for the command request and the name server's response.
+All commands sent over the channel must be signed by a server_key known to
+the server.
+
+:program:`rndc` reads a configuration file to determine how to contact the name
+server and decide what algorithm and key it should use.
+
+Options
+~~~~~~~
+
+.. option:: -4
+
+ This option indicates use of IPv4 only.
+
+.. option:: -6
+
+ This option indicates use of IPv6 only.
+
+.. option:: -b source-address
+
+ This option indicates ``source-address`` as the source address for the connection to the
+ server. Multiple instances are permitted, to allow setting of both the
+ IPv4 and IPv6 source addresses.
+
+.. option:: -c config-file
+
+ This option indicates ``config-file`` as the configuration file instead of the default,
+ |rndc_conf|.
+
+.. option:: -k key-file
+
+ This option indicates ``key-file`` as the key file instead of the default,
+ |rndc_key|. The key in |rndc_key| is used to
+ authenticate commands sent to the server if the config-file does not
+ exist.
+
+.. option:: -s server
+
+ ``server`` is the name or address of the server which matches a server
+ statement in the configuration file for :program:`rndc`. If no server is
+ supplied on the command line, the host named by the default-server
+ clause in the options statement of the :program:`rndc` configuration file
+ is used.
+
+.. option:: -p port
+
+ This option instructs BIND 9 to send commands to TCP port ``port`` instead of its default control
+ channel port, 953.
+
+.. option:: -q
+
+ This option sets quiet mode, where message text returned by the server is not printed
+ unless there is an error.
+
+.. option:: -r
+
+ This option instructs :program:`rndc` to print the result code returned by :iscman:`named`
+ after executing the requested command (e.g., ISC_R_SUCCESS,
+ ISC_R_FAILURE, etc.).
+
+.. option:: -V
+
+ This option enables verbose logging.
+
+.. option:: -y server_key
+
+ This option indicates use of the key ``server_key`` from the configuration file. For control message validation to succeed, ``server_key`` must be known
+ by :iscman:`named` with the same algorithm and secret string. If no ``server_key`` is specified,
+ :program:`rndc` first looks for a key clause in the server statement of
+ the server being used, or if no server statement is present for that
+ host, then in the default-key clause of the options statement. Note that
+ the configuration file contains shared secrets which are used to send
+ authenticated control commands to name servers, and should therefore
+ not have general read or write access.
+
+Commands
+~~~~~~~~
+
+A list of commands supported by :program:`rndc` can be seen by running :program:`rndc`
+without arguments.
+
+Currently supported commands are:
+
+.. option:: addzone zone [class [view]] configuration
+
+ This command adds a zone while the server is running. This command requires the
+ ``allow-new-zones`` option to be set to ``yes``. The configuration
+ string specified on the command line is the zone configuration text
+ that would ordinarily be placed in :iscman:`named.conf`.
+
+ The configuration is saved in a file called ``viewname.nzf`` (or, if
+ :iscman:`named` is compiled with liblmdb, an LMDB database file called
+ ``viewname.nzd``). ``viewname`` is the name of the view, unless the view
+ name contains characters that are incompatible with use as a file
+ name, in which case a cryptographic hash of the view name is used
+ instead. When :iscman:`named` is restarted, the file is loaded into
+ the view configuration so that zones that were added can persist
+ after a restart.
+
+ This sample ``addzone`` command adds the zone ``example.com`` to
+ the default view:
+
+ ``rndc addzone example.com '{ type primary; file "example.com.db"; };'``
+
+ (Note the brackets around and semi-colon after the zone configuration
+ text.)
+
+ See also :option:`rndc delzone` and :option:`rndc modzone`.
+
+.. option:: delzone [-clean] zone [class [view]]
+
+ This command deletes a zone while the server is running.
+
+ If the ``-clean`` argument is specified, the zone's master file (and
+ journal file, if any) are deleted along with the zone. Without
+ the ``-clean`` option, zone files must be deleted manually. (If the
+ zone is of type ``secondary`` or ``stub``, the files needing to be removed
+ are reported in the output of the ``rndc delzone`` command.)
+
+ If the zone was originally added via ``rndc addzone``, then it is
+ removed permanently. However, if it was originally configured in
+ :iscman:`named.conf`, then that original configuration remains in place;
+ when the server is restarted or reconfigured, the zone is
+ recreated. To remove it permanently, it must also be removed from
+ :iscman:`named.conf`.
+
+ See also :option:`rndc addzone` and :option:`rndc modzone`.
+
+.. option:: dnssec (-status | -rollover -key id [-alg algorithm] [-when time] | -checkds [-key id [-alg algorithm]] [-when time] published | withdrawn)) zone [class [view]]
+
+ This command allows you to interact with the "dnssec-policy" of a given
+ zone.
+
+ ``rndc dnssec -status`` show the DNSSEC signing state for the specified
+ zone.
+
+ ``rndc dnssec -rollover`` allows you to schedule key rollover for a
+ specific key (overriding the original key lifetime).
+
+ ``rndc dnssec -checkds`` informs :iscman:`named` that the DS for
+ a specified zone's key-signing key has been confirmed to be published
+ in, or withdrawn from, the parent zone. This is required in order to
+ complete a KSK rollover. The ``-key id`` and ``-alg algorithm`` arguments
+ can be used to specify a particular KSK, if necessary; if there is only
+ one key acting as a KSK for the zone, these arguments can be omitted.
+ The time of publication or withdrawal for the DS is set to the current
+ time by default, but can be overridden to a specific time with the
+ argument ``-when time``, where ``time`` is expressed in YYYYMMDDHHMMSS
+ notation.
+
+.. option:: dnstap (-reopen | -roll [number])
+
+ This command closes and re-opens DNSTAP output files.
+
+ ``rndc dnstap -reopen`` allows
+ the output file to be renamed externally, so that :iscman:`named` can
+ truncate and re-open it.
+
+ ``rndc dnstap -roll`` causes the output file
+ to be rolled automatically, similar to log files. The most recent
+ output file has ".0" appended to its name; the previous most recent
+ output file is moved to ".1", and so on. If ``number`` is specified, then
+ the number of backup log files is limited to that number.
+
+.. option:: dumpdb [-all | -cache | -zones | -adb | -bad | -expired | -fail] [view ...]
+
+ This command dumps the server's caches (default) and/or zones to the dump file for
+ the specified views. If no view is specified, all views are dumped.
+ (See the ``dump-file`` option in the BIND 9 Administrator Reference
+ Manual.)
+
+.. option:: flush
+
+ This command flushes the server's cache.
+
+.. option:: flushname name [view]
+
+ This command flushes the given name from the view's DNS cache and, if applicable,
+ from the view's nameserver address database, bad server cache, and
+ SERVFAIL cache.
+
+.. option:: flushtree name [view]
+
+ This command flushes the given name, and all of its subdomains, from the view's
+ DNS cache, address database, bad server cache, and SERVFAIL cache.
+
+.. option:: freeze [zone [class [view]]]
+
+ This command suspends updates to a dynamic zone. If no zone is specified, then all
+ zones are suspended. This allows manual edits to be made to a zone
+ normally updated by dynamic update, and causes changes in the
+ journal file to be synced into the master file. All dynamic update
+ attempts are refused while the zone is frozen.
+
+ See also :option:`rndc thaw`.
+
+.. option:: halt [-p]
+
+ This command stops the server immediately. Recent changes made through dynamic
+ update or IXFR are not saved to the master files, but are rolled
+ forward from the journal files when the server is restarted. If
+ ``-p`` is specified, :iscman:`named`'s process ID is returned. This allows
+ an external process to determine when :iscman:`named` has completed
+ halting.
+
+ See also :option:`rndc stop`.
+
+.. option:: loadkeys [zone [class [view]]]
+
+ This command fetches all DNSSEC keys for the given zone from the key directory. If
+ they are within their publication period, they are merged into the
+ zone's DNSKEY RRset. Unlike :option:`rndc sign`, however, the zone is not
+ immediately re-signed by the new keys, but is allowed to
+ incrementally re-sign over time.
+
+ This command requires that the zone be configured with a ``dnssec-policy``, or
+ that the ``auto-dnssec`` zone option be set to ``maintain``, and also requires the
+ zone to be configured to allow dynamic DNS. (See "Dynamic Update Policies" in
+ the Administrator Reference Manual for more details.)
+
+.. option:: managed-keys (status | refresh | sync | destroy) [class [view]]
+
+ This command inspects and controls the "managed-keys" database which handles
+ :rfc:`5011` DNSSEC trust anchor maintenance. If a view is specified, these
+ commands are applied to that view; otherwise, they are applied to all
+ views.
+
+ - When run with the ``status`` keyword, this prints the current status of
+ the managed-keys database.
+
+ - When run with the ``refresh`` keyword, this forces an immediate refresh
+ query to be sent for all the managed keys, updating the
+ managed-keys database if any new keys are found, without waiting
+ the normal refresh interval.
+
+ - When run with the ``sync`` keyword, this forces an immediate dump of
+ the managed-keys database to disk (in the file
+ ``managed-keys.bind`` or (``viewname.mkeys``). This synchronizes
+ the database with its journal file, so that the database's current
+ contents can be inspected visually.
+
+ - When run with the ``destroy`` keyword, the managed-keys database
+ is shut down and deleted, and all key maintenance is terminated.
+ This command should be used only with extreme caution.
+
+ Existing keys that are already trusted are not deleted from
+ memory; DNSSEC validation can continue after this command is used.
+ However, key maintenance operations cease until :iscman:`named` is
+ restarted or reconfigured, and all existing key maintenance states
+ are deleted.
+
+ Running :option:`rndc reconfig` or restarting :iscman:`named` immediately
+ after this command causes key maintenance to be reinitialized
+ from scratch, just as if the server were being started for the
+ first time. This is primarily intended for testing, but it may
+ also be used, for example, to jumpstart the acquisition of new
+ keys in the event of a trust anchor rollover, or as a brute-force
+ repair for key maintenance problems.
+
+.. option:: modzone zone [class [view]] configuration
+
+ This command modifies the configuration of a zone while the server is running. This
+ command requires the ``allow-new-zones`` option to be set to ``yes``.
+ As with ``addzone``, the configuration string specified on the
+ command line is the zone configuration text that would ordinarily be
+ placed in :iscman:`named.conf`.
+
+ If the zone was originally added via :option:`rndc addzone`, the
+ configuration changes are recorded permanently and are still
+ in effect after the server is restarted or reconfigured. However, if
+ it was originally configured in :iscman:`named.conf`, then that original
+ configuration remains in place; when the server is restarted or
+ reconfigured, the zone reverts to its original configuration. To
+ make the changes permanent, it must also be modified in
+ :iscman:`named.conf`.
+
+ See also :option:`rndc addzone` and :option:`rndc delzone`.
+
+.. option:: notify zone [class [view]]
+
+ This command resends NOTIFY messages for the zone.
+
+.. option:: notrace
+
+ This command sets the server's debugging level to 0.
+
+ See also :option:`rndc trace`.
+
+.. option:: nta [(-class class | -dump | -force | -remove | -lifetime duration)] domain [view]
+
+ This command sets a DNSSEC negative trust anchor (NTA) for ``domain``, with a
+ lifetime of ``duration``. The default lifetime is configured in
+ :iscman:`named.conf` via the ``nta-lifetime`` option, and defaults to one
+ hour. The lifetime cannot exceed one week.
+
+ A negative trust anchor selectively disables DNSSEC validation for
+ zones that are known to be failing because of misconfiguration rather
+ than an attack. When data to be validated is at or below an active
+ NTA (and above any other configured trust anchors), :iscman:`named`
+ aborts the DNSSEC validation process and treats the data as insecure
+ rather than bogus. This continues until the NTA's lifetime has
+ elapsed.
+
+ NTAs persist across restarts of the :iscman:`named` server. The NTAs for a
+ view are saved in a file called ``name.nta``, where ``name`` is the name
+ of the view; if it contains characters that are incompatible with
+ use as a file name, a cryptographic hash is generated from the name of
+ the view.
+
+ An existing NTA can be removed by using the ``-remove`` option.
+
+ An NTA's lifetime can be specified with the ``-lifetime`` option.
+ TTL-style suffixes can be used to specify the lifetime in seconds,
+ minutes, or hours. If the specified NTA already exists, its lifetime
+ is updated to the new value. Setting ``lifetime`` to zero is
+ equivalent to ``-remove``.
+
+ If ``-dump`` is used, any other arguments are ignored and a list
+ of existing NTAs is printed. Note that this may include NTAs that are
+ expired but have not yet been cleaned up.
+
+ Normally, :iscman:`named` periodically tests to see whether data below
+ an NTA can now be validated (see the ``nta-recheck`` option in the
+ Administrator Reference Manual for details). If data can be
+ validated, then the NTA is regarded as no longer necessary and is
+ allowed to expire early. The ``-force`` parameter overrides this behavior
+ and forces an NTA to persist for its entire lifetime, regardless of
+ whether data could be validated if the NTA were not present.
+
+ The view class can be specified with ``-class``. The default is class
+ ``IN``, which is the only class for which DNSSEC is currently
+ supported.
+
+ All of these options can be shortened, i.e., to ``-l``, ``-r``,
+ ``-d``, ``-f``, and ``-c``.
+
+ Unrecognized options are treated as errors. To refer to a domain or
+ view name that begins with a hyphen, use a double-hyphen (--) on the
+ command line to indicate the end of options.
+
+.. option:: querylog [(on | off)]
+
+ This command enables or disables query logging. For backward compatibility, this
+ command can also be used without an argument to toggle query logging
+ on and off.
+
+ Query logging can also be enabled by explicitly directing the
+ ``queries`` ``category`` to a ``channel`` in the ``logging`` section
+ of :iscman:`named.conf`, or by specifying ``querylog yes;`` in the
+ ``options`` section of :iscman:`named.conf`.
+
+.. option:: reconfig
+
+ This command reloads the configuration file and loads new zones, but does not reload
+ existing zone files even if they have changed. This is faster than a
+ full :option:`rndc reload` when there is a large number of zones, because it
+ avoids the need to examine the modification times of the zone files.
+
+.. option:: recursing
+
+ This command dumps the list of queries :iscman:`named` is currently
+ recursing on, and the list of domains to which iterative queries
+ are currently being sent.
+
+ The first list includes all unique clients that are waiting for
+ recursion to complete, including the query that is awaiting a
+ response and the timestamp (seconds since the Unix epoch) of
+ when named started processing this client query.
+
+ The second list comprises of domains for which there are active
+ (or recently active) fetches in progress. It reports the number
+ of active fetches for each domain and the number of queries that
+ have been passed (allowed) or dropped (spilled) as a result of
+ the ``fetches-per-zone`` limit. (Note: these counters are not
+ cumulative over time; whenever the number of active fetches for
+ a domain drops to zero, the counter for that domain is deleted,
+ and the next time a fetch is sent to that domain, it is recreated
+ with the counters set to zero).
+
+.. option:: refresh zone [class [view]]
+
+ This command schedules zone maintenance for the given zone.
+
+.. option:: reload
+
+ This command reloads the configuration file and zones.
+
+ .. program:: rndc reload
+ .. option:: zone [class [view]]
+
+ If a zone is specified, this command reloads only the given zone.
+
+.. program:: rndc
+
+.. option:: retransfer zone [class [view]]
+
+ This command retransfers the given secondary zone from the primary server.
+
+ If the zone is configured to use ``inline-signing``, the signed
+ version of the zone is discarded; after the retransfer of the
+ unsigned version is complete, the signed version is regenerated
+ with new signatures.
+
+.. option:: scan
+
+ This command scans the list of available network interfaces for changes, without
+ performing a full :option:`rndc reconfig` or waiting for the
+ ``interface-interval`` timer.
+
+.. option:: secroots [-] [view ...]
+
+ This command dumps the security roots (i.e., trust anchors configured via
+ ``trust-anchors``, or the ``managed-keys`` or ``trusted-keys`` statements
+ [both deprecated], or ``dnssec-validation auto``) and negative trust anchors
+ for the specified views. If no view is specified, all views are
+ dumped. Security roots indicate whether they are configured as trusted
+ keys, managed keys, or initializing managed keys (managed keys that have not
+ yet been updated by a successful key refresh query).
+
+ If the first argument is ``-``, then the output is returned via the
+ :program:`rndc` response channel and printed to the standard output.
+ Otherwise, it is written to the secroots dump file, which defaults to
+ ``named.secroots``, but can be overridden via the ``secroots-file``
+ option in :iscman:`named.conf`.
+
+ See also :option:`rndc managed-keys`.
+
+.. option:: serve-stale (on | off | reset | status) [class [view]]
+
+ This command enables, disables, resets, or reports the current status of
+ the serving of stale answers as configured in :iscman:`named.conf`.
+
+ If serving of stale answers is disabled by ``rndc-serve-stale off``, then it
+ remains disabled even if :iscman:`named` is reloaded or reconfigured. ``rndc
+ serve-stale reset`` restores the setting as configured in :iscman:`named.conf`.
+
+ ``rndc serve-stale status`` reports whether caching and serving of stale
+ answers is currently enabled or disabled. It also reports the values of
+ ``stale-answer-ttl`` and ``max-stale-ttl``.
+
+.. option:: showzone zone [class [view]]
+
+ This command prints the configuration of a running zone.
+
+ See also :option:`rndc zonestatus`.
+
+.. option:: sign zone [class [view]]
+
+ This command fetches all DNSSEC keys for the given zone from the key directory (see
+ the ``key-directory`` option in the BIND 9 Administrator Reference
+ Manual). If they are within their publication period, they are merged into
+ the zone's DNSKEY RRset. If the DNSKEY RRset is changed, then the
+ zone is automatically re-signed with the new key set.
+
+ This command requires that the zone be configured with a ``dnssec-policy``, or
+ that the ``auto-dnssec`` zone option be set to ``allow`` or ``maintain``,
+ and also requires the zone to be configured to allow dynamic DNS. (See
+ "Dynamic Update Policies" in the BIND 9 Administrator Reference Manual for more
+ details.)
+
+ See also :option:`rndc loadkeys`.
+
+.. option:: signing [(-list | -clear keyid/algorithm | -clear all | -nsec3param (parameters | none) | -serial value) zone [class [view]]
+
+ This command lists, edits, or removes the DNSSEC signing-state records for the
+ specified zone. The status of ongoing DNSSEC operations, such as
+ signing or generating NSEC3 chains, is stored in the zone in the form
+ of DNS resource records of type ``sig-signing-type``.
+ ``rndc signing -list`` converts these records into a human-readable
+ form, indicating which keys are currently signing or have finished
+ signing the zone, and which NSEC3 chains are being created or
+ removed.
+
+ ``rndc signing -clear`` can remove a single key (specified in the
+ same format that ``rndc signing -list`` uses to display it), or all
+ keys. In either case, only completed keys are removed; any record
+ indicating that a key has not yet finished signing the zone is
+ retained.
+
+ ``rndc signing -nsec3param`` sets the NSEC3 parameters for a zone.
+ This is the only supported mechanism for using NSEC3 with
+ ``inline-signing`` zones. Parameters are specified in the same format
+ as an NSEC3PARAM resource record: ``hash algorithm``, ``flags``, ``iterations``,
+ and ``salt``, in that order.
+
+ Currently, the only defined value for ``hash algorithm`` is ``1``,
+ representing SHA-1. The ``flags`` may be set to ``0`` or ``1``,
+ depending on whether the opt-out bit in the NSEC3
+ chain should be set. ``iterations`` defines the number of additional times to apply
+ the algorithm when generating an NSEC3 hash. The ``salt`` is a string
+ of data expressed in hexadecimal, a hyphen (``-``) if no salt is to be
+ used, or the keyword ``auto``, which causes :iscman:`named` to generate a
+ random 64-bit salt.
+
+ The only recommended configuration is ``rndc signing -nsec3param 1 0 0 - zone``,
+ i.e. no salt, no additional iterations, no opt-out.
+
+ .. warning::
+ Do not use extra iterations, salt, or opt-out unless all their implications
+ are fully understood. A higher number of iterations causes interoperability
+ problems and opens servers to CPU-exhausting DoS attacks.
+
+ ``rndc signing -nsec3param none`` removes an existing NSEC3 chain and
+ replaces it with NSEC.
+
+ ``rndc signing -serial value`` sets the serial number of the zone to
+ ``value``. If the value would cause the serial number to go backwards, it
+ is rejected. The primary use of this parameter is to set the serial number on inline
+ signed zones.
+
+.. option:: stats
+
+ This command writes server statistics to the statistics file. (See the
+ ``statistics-file`` option in the BIND 9 Administrator Reference
+ Manual.)
+
+.. option:: status
+
+ This command displays the status of the server. Note that the number of zones includes
+ the internal ``bind/CH`` zone and the default ``./IN`` hint zone, if
+ there is no explicit root zone configured.
+
+.. option:: stop -p
+
+ This command stops the server, making sure any recent changes made through dynamic
+ update or IXFR are first saved to the master files of the updated
+ zones. If ``-p`` is specified, :iscman:`named`'s process ID is returned.
+ This allows an external process to determine when :iscman:`named` has
+ completed stopping.
+
+ See also :option:`rndc halt`.
+
+.. option:: sync -clean [zone [class [view]]]
+
+ This command syncs changes in the journal file for a dynamic zone to the master
+ file. If the "-clean" option is specified, the journal file is also
+ removed. If no zone is specified, then all zones are synced.
+
+.. option:: tcp-timeouts [initial idle keepalive advertised]
+
+ When called without arguments, this command displays the current values of the
+ ``tcp-initial-timeout``, ``tcp-idle-timeout``,
+ ``tcp-keepalive-timeout``, and ``tcp-advertised-timeout`` options.
+ When called with arguments, these values are updated. This allows an
+ administrator to make rapid adjustments when under a
+ denial-of-service (DoS) attack. See the descriptions of these options in the BIND 9
+ Administrator Reference Manual for details of their use.
+
+.. option:: thaw [zone [class [view]]]
+
+ This command enables updates to a frozen dynamic zone. If no zone is specified,
+ then all frozen zones are enabled. This causes the server to reload
+ the zone from disk, and re-enables dynamic updates after the load has
+ completed. After a zone is thawed, dynamic updates are no longer
+ refused. If the zone has changed and the ``ixfr-from-differences``
+ option is in use, the journal file is updated to reflect
+ changes in the zone. Otherwise, if the zone has changed, any existing
+ journal file is removed.
+
+ See also :option:`rndc freeze`.
+
+.. option:: trace [level]
+
+ If no level is specified, this command increments the server's debugging
+ level by one.
+
+ .. program:: rndc trace
+ .. option:: level
+
+ If specified, this command sets the server's debugging level to the
+ provided value.
+
+ See also :option:`rndc notrace`.
+
+.. program:: rndc
+
+.. option:: tsig-delete keyname [view]
+
+ This command deletes a given TKEY-negotiated key from the server. This does not
+ apply to statically configured TSIG keys.
+
+.. option:: tsig-list
+
+ This command lists the names of all TSIG keys currently configured for use by
+ :iscman:`named` in each view. The list includes both statically configured keys and
+ dynamic TKEY-negotiated keys.
+
+.. option:: validation (on | off | status) [view ...]
+
+ This command enables, disables, or checks the current status of DNSSEC validation. By
+ default, validation is enabled.
+
+ The cache is flushed when validation is turned on or off to avoid using data
+ that might differ between states.
+
+.. option:: zonestatus zone [class [view]]
+
+ This command displays the current status of the given zone, including the master
+ file name and any include files from which it was loaded, when it was
+ most recently loaded, the current serial number, the number of nodes,
+ whether the zone supports dynamic updates, whether the zone is DNSSEC
+ signed, whether it uses automatic DNSSEC key management or inline
+ signing, and the scheduled refresh or expiry times for the zone.
+
+ See also :option:`rndc showzone`.
+
+:program:`rndc` commands that specify zone names, such as :option:`reload`
+:option:`retransfer`, or :option:`zonestatus`, can be ambiguous when applied to zones
+of type ``redirect``. Redirect zones are always called ``.``, and can be
+confused with zones of type ``hint`` or with secondary copies of the root
+zone. To specify a redirect zone, use the special zone name
+``-redirect``, without a trailing period. (With a trailing period, this
+would specify a zone called "-redirect".)
+
+Limitations
+~~~~~~~~~~~
+
+There is currently no way to provide the shared secret for a ``server_key``
+without using the configuration file.
+
+Several error messages could be clearer.
+
+See Also
+~~~~~~~~
+
+:iscman:`rndc.conf(5) <rndc.conf>`, :iscman:`rndc-confgen(8) <rndc-confgen>`,
+:iscman:`named(8) <named>`, :iscman:`named.conf(5) <named.conf>`, BIND 9 Administrator
+Reference Manual.
diff --git a/bin/rndc/util.c b/bin/rndc/util.c
new file mode 100644
index 0000000..b0085fe
--- /dev/null
+++ b/bin/rndc/util.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include "util.h"
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/print.h>
+
+extern bool verbose;
+extern const char *progname;
+
+void
+notify(const char *fmt, ...) {
+ va_list ap;
+
+ if (verbose) {
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+ }
+}
+
+void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fprintf(stderr, "%s: ", progname);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
diff --git a/bin/rndc/util.h b/bin/rndc/util.h
new file mode 100644
index 0000000..4ac83e5
--- /dev/null
+++ b/bin/rndc/util.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file */
+
+#include <isc/attributes.h>
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+
+#define NS_CONTROL_PORT 953
+
+#undef DO
+#define DO(name, function) \
+ do { \
+ result = function; \
+ if (result != ISC_R_SUCCESS) \
+ fatal("%s: %s", name, isc_result_totext(result)); \
+ else \
+ notify("%s", name); \
+ } while (0)
+
+ISC_LANG_BEGINDECLS
+
+void
+notify(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2);
+
+noreturn void
+fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+ISC_LANG_ENDDECLS
diff --git a/bin/tests/Makefile.am b/bin/tests/Makefile.am
new file mode 100644
index 0000000..56e81b1
--- /dev/null
+++ b/bin/tests/Makefile.am
@@ -0,0 +1,38 @@
+include $(top_srcdir)/Makefile.top
+
+EXTRA_DIST = convert-trs-to-junit.py
+
+SUBDIRS = system
+
+noinst_PROGRAMS = \
+ test_client \
+ test_server \
+ wire_test
+
+AM_CFLAGS += \
+ $(TEST_CFLAGS)
+
+test_client_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBISC_CFLAGS)
+
+test_client_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+
+test_server_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBISC_CFLAGS)
+
+test_server_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+
+wire_test_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+wire_test_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in
new file mode 100644
index 0000000..d8b1015
--- /dev/null
+++ b/bin/tests/Makefile.in
@@ -0,0 +1,977 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+noinst_PROGRAMS = test_client$(EXEEXT) test_server$(EXEEXT) \
+ wire_test$(EXEEXT)
+subdir = bin/tests
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+test_client_SOURCES = test_client.c
+test_client_OBJECTS = test_client-test_client.$(OBJEXT)
+test_client_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+test_server_SOURCES = test_server.c
+test_server_OBJECTS = test_server-test_server.$(OBJEXT)
+test_server_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS)
+wire_test_SOURCES = wire_test.c
+wire_test_OBJECTS = wire_test-wire_test.$(OBJEXT)
+wire_test_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/test_client-test_client.Po \
+ ./$(DEPDIR)/test_server-test_server.Po \
+ ./$(DEPDIR)/wire_test-wire_test.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = test_client.c test_server.c wire_test.c
+DIST_SOURCES = test_client.c test_server.c wire_test.c
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir distdir-am
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = $(STD_CFLAGS) $(TEST_CFLAGS)
+AM_CPPFLAGS = \
+ $(STD_CPPFLAGS) \
+ -include $(top_builddir)/config.h \
+ -I$(srcdir)/include
+
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD =
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+EXTRA_DIST = convert-trs-to-junit.py
+SUBDIRS = system
+test_client_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBISC_CFLAGS)
+
+test_client_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+
+test_server_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBISC_CFLAGS)
+
+test_server_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+
+wire_test_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+wire_test_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LIBDNS_LIBS)
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/tests/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+test_client$(EXEEXT): $(test_client_OBJECTS) $(test_client_DEPENDENCIES) $(EXTRA_test_client_DEPENDENCIES)
+ @rm -f test_client$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_client_OBJECTS) $(test_client_LDADD) $(LIBS)
+
+test_server$(EXEEXT): $(test_server_OBJECTS) $(test_server_DEPENDENCIES) $(EXTRA_test_server_DEPENDENCIES)
+ @rm -f test_server$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_server_OBJECTS) $(test_server_LDADD) $(LIBS)
+
+wire_test$(EXEEXT): $(wire_test_OBJECTS) $(wire_test_DEPENDENCIES) $(EXTRA_wire_test_DEPENDENCIES)
+ @rm -f wire_test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(wire_test_OBJECTS) $(wire_test_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_client-test_client.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_server-test_server.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wire_test-wire_test.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+test_client-test_client.o: test_client.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_client_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_client-test_client.o -MD -MP -MF $(DEPDIR)/test_client-test_client.Tpo -c -o test_client-test_client.o `test -f 'test_client.c' || echo '$(srcdir)/'`test_client.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_client-test_client.Tpo $(DEPDIR)/test_client-test_client.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_client.c' object='test_client-test_client.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_client_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_client-test_client.o `test -f 'test_client.c' || echo '$(srcdir)/'`test_client.c
+
+test_client-test_client.obj: test_client.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_client_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_client-test_client.obj -MD -MP -MF $(DEPDIR)/test_client-test_client.Tpo -c -o test_client-test_client.obj `if test -f 'test_client.c'; then $(CYGPATH_W) 'test_client.c'; else $(CYGPATH_W) '$(srcdir)/test_client.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_client-test_client.Tpo $(DEPDIR)/test_client-test_client.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_client.c' object='test_client-test_client.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_client_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_client-test_client.obj `if test -f 'test_client.c'; then $(CYGPATH_W) 'test_client.c'; else $(CYGPATH_W) '$(srcdir)/test_client.c'; fi`
+
+test_server-test_server.o: test_server.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_server-test_server.o -MD -MP -MF $(DEPDIR)/test_server-test_server.Tpo -c -o test_server-test_server.o `test -f 'test_server.c' || echo '$(srcdir)/'`test_server.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_server-test_server.Tpo $(DEPDIR)/test_server-test_server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_server.c' object='test_server-test_server.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_server-test_server.o `test -f 'test_server.c' || echo '$(srcdir)/'`test_server.c
+
+test_server-test_server.obj: test_server.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_server-test_server.obj -MD -MP -MF $(DEPDIR)/test_server-test_server.Tpo -c -o test_server-test_server.obj `if test -f 'test_server.c'; then $(CYGPATH_W) 'test_server.c'; else $(CYGPATH_W) '$(srcdir)/test_server.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_server-test_server.Tpo $(DEPDIR)/test_server-test_server.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_server.c' object='test_server-test_server.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_server-test_server.obj `if test -f 'test_server.c'; then $(CYGPATH_W) 'test_server.c'; else $(CYGPATH_W) '$(srcdir)/test_server.c'; fi`
+
+wire_test-wire_test.o: wire_test.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(wire_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT wire_test-wire_test.o -MD -MP -MF $(DEPDIR)/wire_test-wire_test.Tpo -c -o wire_test-wire_test.o `test -f 'wire_test.c' || echo '$(srcdir)/'`wire_test.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wire_test-wire_test.Tpo $(DEPDIR)/wire_test-wire_test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wire_test.c' object='wire_test-wire_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(wire_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o wire_test-wire_test.o `test -f 'wire_test.c' || echo '$(srcdir)/'`wire_test.c
+
+wire_test-wire_test.obj: wire_test.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(wire_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT wire_test-wire_test.obj -MD -MP -MF $(DEPDIR)/wire_test-wire_test.Tpo -c -o wire_test-wire_test.obj `if test -f 'wire_test.c'; then $(CYGPATH_W) 'wire_test.c'; else $(CYGPATH_W) '$(srcdir)/wire_test.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wire_test-wire_test.Tpo $(DEPDIR)/wire_test-wire_test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wire_test.c' object='wire_test-wire_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(wire_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o wire_test-wire_test.obj `if test -f 'wire_test.c'; then $(CYGPATH_W) 'wire_test.c'; else $(CYGPATH_W) '$(srcdir)/wire_test.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f ./$(DEPDIR)/test_client-test_client.Po
+ -rm -f ./$(DEPDIR)/test_server-test_server.Po
+ -rm -f ./$(DEPDIR)/wire_test-wire_test.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-recursive
+
+doc-am: doc-local
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f ./$(DEPDIR)/test_client-test_client.Po
+ -rm -f ./$(DEPDIR)/test_server-test_server.Po
+ -rm -f ./$(DEPDIR)/wire_test-wire_test.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+test: test-recursive
+
+test-am: test-local
+
+uninstall-am:
+
+unit: unit-recursive
+
+unit-am: unit-local
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+ am--depfiles check check-am clean clean-generic clean-libtool \
+ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir doc-am doc-local dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am test-am test-local uninstall uninstall-am unit-am \
+ unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/tests/convert-trs-to-junit.py b/bin/tests/convert-trs-to-junit.py
new file mode 100755
index 0000000..85b37dd
--- /dev/null
+++ b/bin/tests/convert-trs-to-junit.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# Convert automake .trs files into JUnit format suitable for Gitlab
+
+import argparse
+import os
+import sys
+from xml.etree import ElementTree
+from xml.etree.ElementTree import Element
+from xml.etree.ElementTree import SubElement
+
+
+# getting explicit encoding specification right for Python 2/3 would be messy,
+# so let's hope for the best
+def read_whole_text(filename):
+ with open(filename) as inf: # pylint: disable-msg=unspecified-encoding
+ return inf.read().strip()
+
+
+def read_trs_result(filename):
+ result = None
+ with open(filename, "r") as trs: # pylint: disable-msg=unspecified-encoding
+ for line in trs:
+ items = line.split()
+ if len(items) < 2:
+ raise ValueError("unsupported line in trs file", filename, line)
+ if items[0] != (":test-result:"):
+ continue
+ if result is not None:
+ raise NotImplementedError("double :test-result:", filename)
+ result = items[1].upper()
+
+ if result is None:
+ raise ValueError(":test-result: not found", filename)
+
+ return result
+
+
+def find_test_relative_path(source_dir, in_path):
+ """Return {in_path}.c if it exists, with fallback to {in_path}"""
+ candidates_relative = [in_path + ".c", in_path]
+ for relative in candidates_relative:
+ absolute = os.path.join(source_dir, relative)
+ if os.path.exists(absolute):
+ return relative
+ raise KeyError
+
+
+def err_out(exception):
+ raise exception
+
+
+def walk_trss(source_dir):
+ for cur_dir, _dirs, files in os.walk(source_dir, onerror=err_out):
+ for filename in files:
+ if not filename.endswith(".trs"):
+ continue
+
+ filename_prefix = filename[: -len(".trs")]
+ log_name = filename_prefix + ".log"
+ full_trs_path = os.path.join(cur_dir, filename)
+ full_log_path = os.path.join(cur_dir, log_name)
+ sub_dir = os.path.relpath(cur_dir, source_dir)
+ test_name = os.path.join(sub_dir, filename_prefix)
+
+ t = {
+ "name": test_name,
+ "full_log_path": full_log_path,
+ "rel_log_path": os.path.relpath(full_log_path, source_dir),
+ }
+ t["result"] = read_trs_result(full_trs_path)
+
+ # try to find dir/file path for a clickable link
+ try:
+ t["rel_file_path"] = find_test_relative_path(source_dir, test_name)
+ except KeyError:
+ pass # no existing path found
+
+ yield t
+
+
+def append_testcase(testsuite, t):
+ # attributes taken from
+ # https://gitlab.com/gitlab-org/gitlab-foss/-/blob/master/lib/gitlab/ci/parsers/test/junit.rb
+ attrs = {"name": t["name"]}
+ if "rel_file_path" in t:
+ attrs["file"] = t["rel_file_path"]
+
+ testcase = SubElement(testsuite, "testcase", attrs)
+
+ # Gitlab accepts only [[ATTACHMENT| links for system-out, not raw text
+ s = SubElement(testcase, "system-out")
+ s.text = "[[ATTACHMENT|" + t["rel_log_path"] + "]]"
+ if t["result"].lower() == "pass":
+ return
+
+ # Gitlab shows output only for failed or skipped tests
+ if t["result"].lower() == "skip":
+ err = SubElement(testcase, "skipped")
+ else:
+ err = SubElement(testcase, "failure")
+ err.text = read_whole_text(t["full_log_path"])
+
+
+def gen_junit(results):
+ testsuites = Element("testsuites")
+ testsuite = SubElement(testsuites, "testsuite")
+ for test in results:
+ append_testcase(testsuite, test)
+ return testsuites
+
+
+def check_directory(path):
+ try:
+ os.listdir(path)
+ return path
+ except OSError as ex:
+ msg = "Path {} cannot be listed as a directory: {}".format(path, ex)
+ raise argparse.ArgumentTypeError(msg)
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Recursively search for .trs + .log files and compile "
+ "them into JUnit XML suitable for Gitlab. Paths in the "
+ "XML are relative to the specified top directory."
+ )
+ parser.add_argument(
+ "top_directory",
+ type=check_directory,
+ help="root directory where to start scanning for .trs files",
+ )
+ args = parser.parse_args()
+ junit = gen_junit(walk_trss(args.top_directory))
+
+ # encode results into file format, on Python 3 it produces bytes
+ xml = ElementTree.tostring(junit, "utf-8")
+ # use stdout as a binary file object, Python2/3 compatibility
+ output = getattr(sys.stdout, "buffer", sys.stdout)
+ output.write(xml)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/bin/tests/system/Makefile.am b/bin/tests/system/Makefile.am
new file mode 100644
index 0000000..72d464a
--- /dev/null
+++ b/bin/tests/system/Makefile.am
@@ -0,0 +1,258 @@
+include $(top_srcdir)/Makefile.top
+
+EXTRA_DIST = .
+
+# Source tarballs must not contain configure/build artifacts.
+dist-hook:
+ git clean -n -x -d | \
+ grep -v "Makefile.in$$" | \
+ sed -n "s|^Would remove \(.*\)|$(distdir)/\1|p" | \
+ xargs -I{} rm -rf "{}"
+
+SUBDIRS = dyndb/driver dlzexternal/driver hooks/driver
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS)
+
+LDADD += \
+ $(LIBISC_LIBS)
+
+if HAVE_PERL
+
+noinst_PROGRAMS = \
+ feature-test \
+ makejournal \
+ pipelined/pipequeries \
+ resolve \
+ rndc/gencheck \
+ rpz/dnsrps \
+ tkey/keycreate \
+ tkey/keydelete
+
+feature_test_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+makejournal_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+makejournal_LDADD = \
+ $(LDADD) \
+ $(LIBDNS_LIBS)
+
+pipelined_pipequeries_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+pipelined_pipequeries_LDADD = \
+ $(LDADD) \
+ $(LIBDNS_LIBS)
+
+resolve_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) \
+ $(LIBIRS_CFLAGS)
+
+resolve_LDADD = $(LIBISC_LIBS) $(LIBIRS_LIBS) $(LIBDNS_LIBS)
+
+rpz_dnsrps_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+rpz_dnsrps_LDADD = \
+ $(LDADD) \
+ $(LIBDNS_LIBS)
+
+tkey_keycreate_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+tkey_keycreate_LDADD = \
+ $(LDADD) \
+ $(LIBDNS_LIBS)
+
+tkey_keydelete_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+tkey_keydelete_LDADD = \
+ $(LDADD) \
+ $(LIBDNS_LIBS)
+
+TESTS =
+
+if HAVE_PERLMOD_TIME_HIRES
+TESTS += serve-stale
+endif HAVE_PERLMOD_TIME_HIRES
+
+if HAVE_PERLMOD_NET_DNS
+TESTS += \
+ rpzrecurse
+endif HAVE_PERLMOD_NET_DNS
+
+if HAVE_LIBNGHTTP2
+TESTS += \
+ doth
+endif
+
+TESTS += \
+ acl \
+ additional \
+ addzone \
+ allow-query \
+ auth \
+ autosign \
+ builtin \
+ cacheclean \
+ case \
+ catz \
+ cds \
+ checkconf \
+ checknames \
+ checkzone \
+ database \
+ dialup \
+ dlzexternal \
+ dns64 \
+ dsdigest \
+ dupsigs \
+ dyndb \
+ ecdsa \
+ eddsa \
+ ednscompliance \
+ emptyzones \
+ enginepkcs11 \
+ filter-aaaa \
+ formerr \
+ geoip2 \
+ glue \
+ idna \
+ include-multiplecfg \
+ inline \
+ integrity \
+ hooks \
+ host \
+ journal \
+ keepalive \
+ keyfromlabel \
+ legacy \
+ limits \
+ logfileconfig \
+ masterfile \
+ masterformat \
+ metadata \
+ mirror \
+ mkeys \
+ names \
+ notify \
+ nsec3 \
+ nslookup \
+ padding \
+ pending \
+ redirect \
+ rndc \
+ rootkeysentinel \
+ rpz \
+ rrchecker \
+ rrl \
+ rrsetorder \
+ rsabigexponent \
+ runtime \
+ sfcache \
+ smartsign \
+ sortlist \
+ spf \
+ staticstub \
+ stub \
+ synthfromdnssec \
+ tkey \
+ tools \
+ transport-acl \
+ tsig \
+ tsiggss \
+ ttl \
+ unknown \
+ verify \
+ views \
+ wildcard \
+ xferquota \
+ zonechecks
+
+if HAVE_LMDB
+TESTS += nzd2nzf
+endif # HAVE_LMDB
+
+if HAVE_PERLMOD_NET_DNS
+
+TESTS += \
+ fetchlimit \
+ ixfr \
+ nsupdate \
+ resolver \
+ statistics \
+ stress \
+ upforwd \
+ zero
+
+if HAVE_DNSTAP
+TESTS += dnstap
+endif
+
+if HAVE_PERLMOD_FILE_FETCH
+TESTS += statschannel
+endif HAVE_PERLMOD_FILE_FETCH
+
+if HAVE_PERLMOD_DIGEST_HMAC
+TESTS += xfer
+endif HAVE_PERLMOD_DIGEST_HMAC
+
+if HAVE_PERLMOD_NET_DNS_NAMESERVER
+TESTS += reclimit
+endif HAVE_PERLMOD_NET_DNS_NAMESERVER
+
+endif HAVE_PERLMOD_NET_DNS
+
+if HAVE_PYTHON
+TESTS += kasp keymgr2kasp tcp pipelined
+
+if HAVE_PYTEST
+TESTS += checkds dispatch rpzextra shutdown timeouts
+endif
+
+if HAVE_PYMOD_DNS
+TESTS += qmin cookie
+if HAVE_PERLMOD_NET_DNS
+TESTS += digdelv dnssec forward
+if HAVE_PERLMOD_NET_DNS_NAMESERVER
+TESTS += chain
+endif HAVE_PERLMOD_NET_DNS_NAMESERVER
+endif HAVE_PERLMOD_NET_DNS
+endif HAVE_PYMOD_DNS
+
+endif HAVE_PYTHON
+
+else !HAVE_PERL
+check:
+ echo Perl is not available, no tests were ran
+ exit 1
+endif !HAVE_PERL
+
+LOG_DRIVER_V = $(LOG_DRIVER_V_@AM_V@)
+LOG_DRIVER_V_ = $(LOG_DRIVER_V_@AM_DEFAULT_V@)
+LOG_DRIVER_V_0 = --verbose no
+LOG_DRIVER_V_1 = --verbose yes
+
+LOG_DRIVER = $(srcdir)/custom-test-driver
+AM_LOG_DRIVER_FLAGS = $(LOG_DRIVER_V)
+
+LOG_COMPILER = $(builddir)/legacy.run.sh
+AM_LOG_FLAGS = -r
+
+$(TESTS): legacy.run.sh
+
+test-local: check
+
+clean-local::
+ -find $(builddir) -maxdepth 1 -type d -name "*_*" | xargs rm -rf
diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in
new file mode 100644
index 0000000..eb62072
--- /dev/null
+++ b/bin/tests/system/Makefile.in
@@ -0,0 +1,2416 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+@HAVE_PERL_TRUE@noinst_PROGRAMS = feature-test$(EXEEXT) \
+@HAVE_PERL_TRUE@ makejournal$(EXEEXT) \
+@HAVE_PERL_TRUE@ pipelined/pipequeries$(EXEEXT) \
+@HAVE_PERL_TRUE@ resolve$(EXEEXT) rndc/gencheck$(EXEEXT) \
+@HAVE_PERL_TRUE@ rpz/dnsrps$(EXEEXT) tkey/keycreate$(EXEEXT) \
+@HAVE_PERL_TRUE@ tkey/keydelete$(EXEEXT)
+@HAVE_PERLMOD_TIME_HIRES_TRUE@@HAVE_PERL_TRUE@am__append_2 = serve-stale
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@am__append_3 = \
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@ rpzrecurse
+
+@HAVE_LIBNGHTTP2_TRUE@@HAVE_PERL_TRUE@am__append_4 = \
+@HAVE_LIBNGHTTP2_TRUE@@HAVE_PERL_TRUE@ doth
+
+@HAVE_LMDB_TRUE@@HAVE_PERL_TRUE@am__append_5 = nzd2nzf
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@am__append_6 = \
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@ fetchlimit \
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@ ixfr \
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@ nsupdate \
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@ resolver \
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@ statistics \
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@ stress \
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@ upforwd \
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@ zero
+
+@HAVE_DNSTAP_TRUE@@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@am__append_7 = dnstap
+@HAVE_PERLMOD_FILE_FETCH_TRUE@@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@am__append_8 = statschannel
+@HAVE_PERLMOD_DIGEST_HMAC_TRUE@@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@am__append_9 = xfer
+@HAVE_PERLMOD_NET_DNS_NAMESERVER_TRUE@@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@am__append_10 = reclimit
+@HAVE_PERL_TRUE@@HAVE_PYTHON_TRUE@am__append_11 = kasp keymgr2kasp tcp pipelined
+@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@am__append_12 = checkds dispatch rpzextra shutdown timeouts
+@HAVE_PERL_TRUE@@HAVE_PYMOD_DNS_TRUE@@HAVE_PYTHON_TRUE@am__append_13 = qmin cookie
+@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@@HAVE_PYMOD_DNS_TRUE@@HAVE_PYTHON_TRUE@am__append_14 = digdelv dnssec forward
+@HAVE_PERLMOD_NET_DNS_NAMESERVER_TRUE@@HAVE_PERLMOD_NET_DNS_TRUE@@HAVE_PERL_TRUE@@HAVE_PYMOD_DNS_TRUE@@HAVE_PYTHON_TRUE@am__append_15 = chain
+subdir = bin/tests/system
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = conf.sh ifconfig.sh legacy.run.sh start.sh \
+ stop.sh
+CONFIG_CLEAN_VPATH_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+feature_test_SOURCES = feature-test.c
+feature_test_OBJECTS = feature_test-feature-test.$(OBJEXT)
+feature_test_LDADD = $(LDADD)
+feature_test_DEPENDENCIES = $(LIBISC_LIBS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+makejournal_SOURCES = makejournal.c
+makejournal_OBJECTS = makejournal-makejournal.$(OBJEXT)
+@HAVE_PERL_TRUE@makejournal_DEPENDENCIES = $(LDADD) $(LIBDNS_LIBS)
+pipelined_pipequeries_SOURCES = pipelined/pipequeries.c
+am__dirstamp = $(am__leading_dot)dirstamp
+pipelined_pipequeries_OBJECTS = \
+ pipelined/pipequeries-pipequeries.$(OBJEXT)
+@HAVE_PERL_TRUE@pipelined_pipequeries_DEPENDENCIES = $(LDADD) \
+@HAVE_PERL_TRUE@ $(LIBDNS_LIBS)
+resolve_SOURCES = resolve.c
+resolve_OBJECTS = resolve-resolve.$(OBJEXT)
+@HAVE_PERL_TRUE@resolve_DEPENDENCIES = $(LIBISC_LIBS) $(LIBIRS_LIBS) \
+@HAVE_PERL_TRUE@ $(LIBDNS_LIBS)
+rndc_gencheck_SOURCES = rndc/gencheck.c
+rndc_gencheck_OBJECTS = rndc/gencheck.$(OBJEXT)
+rndc_gencheck_LDADD = $(LDADD)
+rndc_gencheck_DEPENDENCIES = $(LIBISC_LIBS)
+rpz_dnsrps_SOURCES = rpz/dnsrps.c
+rpz_dnsrps_OBJECTS = rpz/dnsrps-dnsrps.$(OBJEXT)
+@HAVE_PERL_TRUE@rpz_dnsrps_DEPENDENCIES = $(LDADD) $(LIBDNS_LIBS)
+tkey_keycreate_SOURCES = tkey/keycreate.c
+tkey_keycreate_OBJECTS = tkey/keycreate-keycreate.$(OBJEXT)
+@HAVE_PERL_TRUE@tkey_keycreate_DEPENDENCIES = $(LDADD) $(LIBDNS_LIBS)
+tkey_keydelete_SOURCES = tkey/keydelete.c
+tkey_keydelete_OBJECTS = tkey/keydelete-keydelete.$(OBJEXT)
+@HAVE_PERL_TRUE@tkey_keydelete_DEPENDENCIES = $(LDADD) $(LIBDNS_LIBS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/feature_test-feature-test.Po \
+ ./$(DEPDIR)/makejournal-makejournal.Po \
+ ./$(DEPDIR)/resolve-resolve.Po \
+ pipelined/$(DEPDIR)/pipequeries-pipequeries.Po \
+ rndc/$(DEPDIR)/gencheck.Po rpz/$(DEPDIR)/dnsrps-dnsrps.Po \
+ tkey/$(DEPDIR)/keycreate-keycreate.Po \
+ tkey/$(DEPDIR)/keydelete-keydelete.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = feature-test.c makejournal.c pipelined/pipequeries.c \
+ resolve.c rndc/gencheck.c rpz/dnsrps.c tkey/keycreate.c \
+ tkey/keydelete.c
+DIST_SOURCES = feature-test.c makejournal.c pipelined/pipequeries.c \
+ resolve.c rndc/gencheck.c rpz/dnsrps.c tkey/keycreate.c \
+ tkey/keydelete.c
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ check recheck distdir distdir-am
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)'
+RECHECK_LOGS = $(TEST_LOGS)
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/conf.sh.in \
+ $(srcdir)/ifconfig.sh.in $(srcdir)/legacy.run.sh.in \
+ $(srcdir)/start.sh.in $(srcdir)/stop.sh.in \
+ $(top_srcdir)/Makefile.top $(top_srcdir)/depcomp \
+ $(top_srcdir)/test-driver README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS)
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD = $(LIBISC_LIBS)
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+EXTRA_DIST = .
+SUBDIRS = dyndb/driver dlzexternal/driver hooks/driver
+@HAVE_PERL_TRUE@feature_test_CPPFLAGS = \
+@HAVE_PERL_TRUE@ $(AM_CPPFLAGS) \
+@HAVE_PERL_TRUE@ $(LIBDNS_CFLAGS)
+
+@HAVE_PERL_TRUE@makejournal_CPPFLAGS = \
+@HAVE_PERL_TRUE@ $(AM_CPPFLAGS) \
+@HAVE_PERL_TRUE@ $(LIBDNS_CFLAGS)
+
+@HAVE_PERL_TRUE@makejournal_LDADD = \
+@HAVE_PERL_TRUE@ $(LDADD) \
+@HAVE_PERL_TRUE@ $(LIBDNS_LIBS)
+
+@HAVE_PERL_TRUE@pipelined_pipequeries_CPPFLAGS = \
+@HAVE_PERL_TRUE@ $(AM_CPPFLAGS) \
+@HAVE_PERL_TRUE@ $(LIBDNS_CFLAGS)
+
+@HAVE_PERL_TRUE@pipelined_pipequeries_LDADD = \
+@HAVE_PERL_TRUE@ $(LDADD) \
+@HAVE_PERL_TRUE@ $(LIBDNS_LIBS)
+
+@HAVE_PERL_TRUE@resolve_CPPFLAGS = \
+@HAVE_PERL_TRUE@ $(AM_CPPFLAGS) \
+@HAVE_PERL_TRUE@ $(LIBISC_CFLAGS) \
+@HAVE_PERL_TRUE@ $(LIBDNS_CFLAGS) \
+@HAVE_PERL_TRUE@ $(LIBIRS_CFLAGS)
+
+@HAVE_PERL_TRUE@resolve_LDADD = $(LIBISC_LIBS) $(LIBIRS_LIBS) $(LIBDNS_LIBS)
+@HAVE_PERL_TRUE@rpz_dnsrps_CPPFLAGS = \
+@HAVE_PERL_TRUE@ $(AM_CPPFLAGS) \
+@HAVE_PERL_TRUE@ $(LIBDNS_CFLAGS)
+
+@HAVE_PERL_TRUE@rpz_dnsrps_LDADD = \
+@HAVE_PERL_TRUE@ $(LDADD) \
+@HAVE_PERL_TRUE@ $(LIBDNS_LIBS)
+
+@HAVE_PERL_TRUE@tkey_keycreate_CPPFLAGS = \
+@HAVE_PERL_TRUE@ $(AM_CPPFLAGS) \
+@HAVE_PERL_TRUE@ $(LIBDNS_CFLAGS)
+
+@HAVE_PERL_TRUE@tkey_keycreate_LDADD = \
+@HAVE_PERL_TRUE@ $(LDADD) \
+@HAVE_PERL_TRUE@ $(LIBDNS_LIBS)
+
+@HAVE_PERL_TRUE@tkey_keydelete_CPPFLAGS = \
+@HAVE_PERL_TRUE@ $(AM_CPPFLAGS) \
+@HAVE_PERL_TRUE@ $(LIBDNS_CFLAGS)
+
+@HAVE_PERL_TRUE@tkey_keydelete_LDADD = \
+@HAVE_PERL_TRUE@ $(LDADD) \
+@HAVE_PERL_TRUE@ $(LIBDNS_LIBS)
+
+@HAVE_PERL_TRUE@TESTS = $(am__append_2) $(am__append_3) \
+@HAVE_PERL_TRUE@ $(am__append_4) acl additional addzone \
+@HAVE_PERL_TRUE@ allow-query auth autosign builtin cacheclean \
+@HAVE_PERL_TRUE@ case catz cds checkconf checknames checkzone \
+@HAVE_PERL_TRUE@ database dialup dlzexternal dns64 dsdigest \
+@HAVE_PERL_TRUE@ dupsigs dyndb ecdsa eddsa ednscompliance \
+@HAVE_PERL_TRUE@ emptyzones enginepkcs11 filter-aaaa formerr \
+@HAVE_PERL_TRUE@ geoip2 glue idna include-multiplecfg inline \
+@HAVE_PERL_TRUE@ integrity hooks host journal keepalive \
+@HAVE_PERL_TRUE@ keyfromlabel legacy limits logfileconfig \
+@HAVE_PERL_TRUE@ masterfile masterformat metadata mirror mkeys \
+@HAVE_PERL_TRUE@ names notify nsec3 nslookup padding pending \
+@HAVE_PERL_TRUE@ redirect rndc rootkeysentinel rpz rrchecker \
+@HAVE_PERL_TRUE@ rrl rrsetorder rsabigexponent runtime sfcache \
+@HAVE_PERL_TRUE@ smartsign sortlist spf staticstub stub \
+@HAVE_PERL_TRUE@ synthfromdnssec tkey tools transport-acl tsig \
+@HAVE_PERL_TRUE@ tsiggss ttl unknown verify views wildcard \
+@HAVE_PERL_TRUE@ xferquota zonechecks $(am__append_5) \
+@HAVE_PERL_TRUE@ $(am__append_6) $(am__append_7) \
+@HAVE_PERL_TRUE@ $(am__append_8) $(am__append_9) \
+@HAVE_PERL_TRUE@ $(am__append_10) $(am__append_11) \
+@HAVE_PERL_TRUE@ $(am__append_12) $(am__append_13) \
+@HAVE_PERL_TRUE@ $(am__append_14) $(am__append_15)
+LOG_DRIVER_V = $(LOG_DRIVER_V_@AM_V@)
+LOG_DRIVER_V_ = $(LOG_DRIVER_V_@AM_DEFAULT_V@)
+LOG_DRIVER_V_0 = --verbose no
+LOG_DRIVER_V_1 = --verbose yes
+LOG_DRIVER = $(srcdir)/custom-test-driver
+AM_LOG_DRIVER_FLAGS = $(LOG_DRIVER_V)
+LOG_COMPILER = $(builddir)/legacy.run.sh
+AM_LOG_FLAGS = -r
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tests/system/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/tests/system/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+conf.sh: $(top_builddir)/config.status $(srcdir)/conf.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ifconfig.sh: $(top_builddir)/config.status $(srcdir)/ifconfig.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+legacy.run.sh: $(top_builddir)/config.status $(srcdir)/legacy.run.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+start.sh: $(top_builddir)/config.status $(srcdir)/start.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+stop.sh: $(top_builddir)/config.status $(srcdir)/stop.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+feature-test$(EXEEXT): $(feature_test_OBJECTS) $(feature_test_DEPENDENCIES) $(EXTRA_feature_test_DEPENDENCIES)
+ @rm -f feature-test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(feature_test_OBJECTS) $(feature_test_LDADD) $(LIBS)
+
+makejournal$(EXEEXT): $(makejournal_OBJECTS) $(makejournal_DEPENDENCIES) $(EXTRA_makejournal_DEPENDENCIES)
+ @rm -f makejournal$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(makejournal_OBJECTS) $(makejournal_LDADD) $(LIBS)
+pipelined/$(am__dirstamp):
+ @$(MKDIR_P) pipelined
+ @: > pipelined/$(am__dirstamp)
+pipelined/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) pipelined/$(DEPDIR)
+ @: > pipelined/$(DEPDIR)/$(am__dirstamp)
+pipelined/pipequeries-pipequeries.$(OBJEXT): \
+ pipelined/$(am__dirstamp) pipelined/$(DEPDIR)/$(am__dirstamp)
+
+pipelined/pipequeries$(EXEEXT): $(pipelined_pipequeries_OBJECTS) $(pipelined_pipequeries_DEPENDENCIES) $(EXTRA_pipelined_pipequeries_DEPENDENCIES) pipelined/$(am__dirstamp)
+ @rm -f pipelined/pipequeries$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(pipelined_pipequeries_OBJECTS) $(pipelined_pipequeries_LDADD) $(LIBS)
+
+resolve$(EXEEXT): $(resolve_OBJECTS) $(resolve_DEPENDENCIES) $(EXTRA_resolve_DEPENDENCIES)
+ @rm -f resolve$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(resolve_OBJECTS) $(resolve_LDADD) $(LIBS)
+rndc/$(am__dirstamp):
+ @$(MKDIR_P) rndc
+ @: > rndc/$(am__dirstamp)
+rndc/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) rndc/$(DEPDIR)
+ @: > rndc/$(DEPDIR)/$(am__dirstamp)
+rndc/gencheck.$(OBJEXT): rndc/$(am__dirstamp) \
+ rndc/$(DEPDIR)/$(am__dirstamp)
+
+rndc/gencheck$(EXEEXT): $(rndc_gencheck_OBJECTS) $(rndc_gencheck_DEPENDENCIES) $(EXTRA_rndc_gencheck_DEPENDENCIES) rndc/$(am__dirstamp)
+ @rm -f rndc/gencheck$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(rndc_gencheck_OBJECTS) $(rndc_gencheck_LDADD) $(LIBS)
+rpz/$(am__dirstamp):
+ @$(MKDIR_P) rpz
+ @: > rpz/$(am__dirstamp)
+rpz/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) rpz/$(DEPDIR)
+ @: > rpz/$(DEPDIR)/$(am__dirstamp)
+rpz/dnsrps-dnsrps.$(OBJEXT): rpz/$(am__dirstamp) \
+ rpz/$(DEPDIR)/$(am__dirstamp)
+
+rpz/dnsrps$(EXEEXT): $(rpz_dnsrps_OBJECTS) $(rpz_dnsrps_DEPENDENCIES) $(EXTRA_rpz_dnsrps_DEPENDENCIES) rpz/$(am__dirstamp)
+ @rm -f rpz/dnsrps$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(rpz_dnsrps_OBJECTS) $(rpz_dnsrps_LDADD) $(LIBS)
+tkey/$(am__dirstamp):
+ @$(MKDIR_P) tkey
+ @: > tkey/$(am__dirstamp)
+tkey/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) tkey/$(DEPDIR)
+ @: > tkey/$(DEPDIR)/$(am__dirstamp)
+tkey/keycreate-keycreate.$(OBJEXT): tkey/$(am__dirstamp) \
+ tkey/$(DEPDIR)/$(am__dirstamp)
+
+tkey/keycreate$(EXEEXT): $(tkey_keycreate_OBJECTS) $(tkey_keycreate_DEPENDENCIES) $(EXTRA_tkey_keycreate_DEPENDENCIES) tkey/$(am__dirstamp)
+ @rm -f tkey/keycreate$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(tkey_keycreate_OBJECTS) $(tkey_keycreate_LDADD) $(LIBS)
+tkey/keydelete-keydelete.$(OBJEXT): tkey/$(am__dirstamp) \
+ tkey/$(DEPDIR)/$(am__dirstamp)
+
+tkey/keydelete$(EXEEXT): $(tkey_keydelete_OBJECTS) $(tkey_keydelete_DEPENDENCIES) $(EXTRA_tkey_keydelete_DEPENDENCIES) tkey/$(am__dirstamp)
+ @rm -f tkey/keydelete$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(tkey_keydelete_OBJECTS) $(tkey_keydelete_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f pipelined/*.$(OBJEXT)
+ -rm -f rndc/*.$(OBJEXT)
+ -rm -f rpz/*.$(OBJEXT)
+ -rm -f tkey/*.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/feature_test-feature-test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/makejournal-makejournal.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolve-resolve.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@pipelined/$(DEPDIR)/pipequeries-pipequeries.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@rndc/$(DEPDIR)/gencheck.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@rpz/$(DEPDIR)/dnsrps-dnsrps.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tkey/$(DEPDIR)/keycreate-keycreate.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@tkey/$(DEPDIR)/keydelete-keydelete.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+feature_test-feature-test.o: feature-test.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(feature_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT feature_test-feature-test.o -MD -MP -MF $(DEPDIR)/feature_test-feature-test.Tpo -c -o feature_test-feature-test.o `test -f 'feature-test.c' || echo '$(srcdir)/'`feature-test.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/feature_test-feature-test.Tpo $(DEPDIR)/feature_test-feature-test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='feature-test.c' object='feature_test-feature-test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(feature_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o feature_test-feature-test.o `test -f 'feature-test.c' || echo '$(srcdir)/'`feature-test.c
+
+feature_test-feature-test.obj: feature-test.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(feature_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT feature_test-feature-test.obj -MD -MP -MF $(DEPDIR)/feature_test-feature-test.Tpo -c -o feature_test-feature-test.obj `if test -f 'feature-test.c'; then $(CYGPATH_W) 'feature-test.c'; else $(CYGPATH_W) '$(srcdir)/feature-test.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/feature_test-feature-test.Tpo $(DEPDIR)/feature_test-feature-test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='feature-test.c' object='feature_test-feature-test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(feature_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o feature_test-feature-test.obj `if test -f 'feature-test.c'; then $(CYGPATH_W) 'feature-test.c'; else $(CYGPATH_W) '$(srcdir)/feature-test.c'; fi`
+
+makejournal-makejournal.o: makejournal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(makejournal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT makejournal-makejournal.o -MD -MP -MF $(DEPDIR)/makejournal-makejournal.Tpo -c -o makejournal-makejournal.o `test -f 'makejournal.c' || echo '$(srcdir)/'`makejournal.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/makejournal-makejournal.Tpo $(DEPDIR)/makejournal-makejournal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='makejournal.c' object='makejournal-makejournal.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(makejournal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o makejournal-makejournal.o `test -f 'makejournal.c' || echo '$(srcdir)/'`makejournal.c
+
+makejournal-makejournal.obj: makejournal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(makejournal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT makejournal-makejournal.obj -MD -MP -MF $(DEPDIR)/makejournal-makejournal.Tpo -c -o makejournal-makejournal.obj `if test -f 'makejournal.c'; then $(CYGPATH_W) 'makejournal.c'; else $(CYGPATH_W) '$(srcdir)/makejournal.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/makejournal-makejournal.Tpo $(DEPDIR)/makejournal-makejournal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='makejournal.c' object='makejournal-makejournal.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(makejournal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o makejournal-makejournal.obj `if test -f 'makejournal.c'; then $(CYGPATH_W) 'makejournal.c'; else $(CYGPATH_W) '$(srcdir)/makejournal.c'; fi`
+
+pipelined/pipequeries-pipequeries.o: pipelined/pipequeries.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pipelined_pipequeries_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pipelined/pipequeries-pipequeries.o -MD -MP -MF pipelined/$(DEPDIR)/pipequeries-pipequeries.Tpo -c -o pipelined/pipequeries-pipequeries.o `test -f 'pipelined/pipequeries.c' || echo '$(srcdir)/'`pipelined/pipequeries.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) pipelined/$(DEPDIR)/pipequeries-pipequeries.Tpo pipelined/$(DEPDIR)/pipequeries-pipequeries.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pipelined/pipequeries.c' object='pipelined/pipequeries-pipequeries.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pipelined_pipequeries_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pipelined/pipequeries-pipequeries.o `test -f 'pipelined/pipequeries.c' || echo '$(srcdir)/'`pipelined/pipequeries.c
+
+pipelined/pipequeries-pipequeries.obj: pipelined/pipequeries.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pipelined_pipequeries_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pipelined/pipequeries-pipequeries.obj -MD -MP -MF pipelined/$(DEPDIR)/pipequeries-pipequeries.Tpo -c -o pipelined/pipequeries-pipequeries.obj `if test -f 'pipelined/pipequeries.c'; then $(CYGPATH_W) 'pipelined/pipequeries.c'; else $(CYGPATH_W) '$(srcdir)/pipelined/pipequeries.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) pipelined/$(DEPDIR)/pipequeries-pipequeries.Tpo pipelined/$(DEPDIR)/pipequeries-pipequeries.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pipelined/pipequeries.c' object='pipelined/pipequeries-pipequeries.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pipelined_pipequeries_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pipelined/pipequeries-pipequeries.obj `if test -f 'pipelined/pipequeries.c'; then $(CYGPATH_W) 'pipelined/pipequeries.c'; else $(CYGPATH_W) '$(srcdir)/pipelined/pipequeries.c'; fi`
+
+resolve-resolve.o: resolve.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(resolve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT resolve-resolve.o -MD -MP -MF $(DEPDIR)/resolve-resolve.Tpo -c -o resolve-resolve.o `test -f 'resolve.c' || echo '$(srcdir)/'`resolve.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/resolve-resolve.Tpo $(DEPDIR)/resolve-resolve.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='resolve.c' object='resolve-resolve.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(resolve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o resolve-resolve.o `test -f 'resolve.c' || echo '$(srcdir)/'`resolve.c
+
+resolve-resolve.obj: resolve.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(resolve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT resolve-resolve.obj -MD -MP -MF $(DEPDIR)/resolve-resolve.Tpo -c -o resolve-resolve.obj `if test -f 'resolve.c'; then $(CYGPATH_W) 'resolve.c'; else $(CYGPATH_W) '$(srcdir)/resolve.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/resolve-resolve.Tpo $(DEPDIR)/resolve-resolve.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='resolve.c' object='resolve-resolve.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(resolve_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o resolve-resolve.obj `if test -f 'resolve.c'; then $(CYGPATH_W) 'resolve.c'; else $(CYGPATH_W) '$(srcdir)/resolve.c'; fi`
+
+rpz/dnsrps-dnsrps.o: rpz/dnsrps.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rpz_dnsrps_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rpz/dnsrps-dnsrps.o -MD -MP -MF rpz/$(DEPDIR)/dnsrps-dnsrps.Tpo -c -o rpz/dnsrps-dnsrps.o `test -f 'rpz/dnsrps.c' || echo '$(srcdir)/'`rpz/dnsrps.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rpz/$(DEPDIR)/dnsrps-dnsrps.Tpo rpz/$(DEPDIR)/dnsrps-dnsrps.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rpz/dnsrps.c' object='rpz/dnsrps-dnsrps.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rpz_dnsrps_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rpz/dnsrps-dnsrps.o `test -f 'rpz/dnsrps.c' || echo '$(srcdir)/'`rpz/dnsrps.c
+
+rpz/dnsrps-dnsrps.obj: rpz/dnsrps.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rpz_dnsrps_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rpz/dnsrps-dnsrps.obj -MD -MP -MF rpz/$(DEPDIR)/dnsrps-dnsrps.Tpo -c -o rpz/dnsrps-dnsrps.obj `if test -f 'rpz/dnsrps.c'; then $(CYGPATH_W) 'rpz/dnsrps.c'; else $(CYGPATH_W) '$(srcdir)/rpz/dnsrps.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rpz/$(DEPDIR)/dnsrps-dnsrps.Tpo rpz/$(DEPDIR)/dnsrps-dnsrps.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rpz/dnsrps.c' object='rpz/dnsrps-dnsrps.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rpz_dnsrps_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rpz/dnsrps-dnsrps.obj `if test -f 'rpz/dnsrps.c'; then $(CYGPATH_W) 'rpz/dnsrps.c'; else $(CYGPATH_W) '$(srcdir)/rpz/dnsrps.c'; fi`
+
+tkey/keycreate-keycreate.o: tkey/keycreate.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tkey_keycreate_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tkey/keycreate-keycreate.o -MD -MP -MF tkey/$(DEPDIR)/keycreate-keycreate.Tpo -c -o tkey/keycreate-keycreate.o `test -f 'tkey/keycreate.c' || echo '$(srcdir)/'`tkey/keycreate.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tkey/$(DEPDIR)/keycreate-keycreate.Tpo tkey/$(DEPDIR)/keycreate-keycreate.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tkey/keycreate.c' object='tkey/keycreate-keycreate.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tkey_keycreate_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tkey/keycreate-keycreate.o `test -f 'tkey/keycreate.c' || echo '$(srcdir)/'`tkey/keycreate.c
+
+tkey/keycreate-keycreate.obj: tkey/keycreate.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tkey_keycreate_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tkey/keycreate-keycreate.obj -MD -MP -MF tkey/$(DEPDIR)/keycreate-keycreate.Tpo -c -o tkey/keycreate-keycreate.obj `if test -f 'tkey/keycreate.c'; then $(CYGPATH_W) 'tkey/keycreate.c'; else $(CYGPATH_W) '$(srcdir)/tkey/keycreate.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tkey/$(DEPDIR)/keycreate-keycreate.Tpo tkey/$(DEPDIR)/keycreate-keycreate.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tkey/keycreate.c' object='tkey/keycreate-keycreate.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tkey_keycreate_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tkey/keycreate-keycreate.obj `if test -f 'tkey/keycreate.c'; then $(CYGPATH_W) 'tkey/keycreate.c'; else $(CYGPATH_W) '$(srcdir)/tkey/keycreate.c'; fi`
+
+tkey/keydelete-keydelete.o: tkey/keydelete.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tkey_keydelete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tkey/keydelete-keydelete.o -MD -MP -MF tkey/$(DEPDIR)/keydelete-keydelete.Tpo -c -o tkey/keydelete-keydelete.o `test -f 'tkey/keydelete.c' || echo '$(srcdir)/'`tkey/keydelete.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tkey/$(DEPDIR)/keydelete-keydelete.Tpo tkey/$(DEPDIR)/keydelete-keydelete.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tkey/keydelete.c' object='tkey/keydelete-keydelete.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tkey_keydelete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tkey/keydelete-keydelete.o `test -f 'tkey/keydelete.c' || echo '$(srcdir)/'`tkey/keydelete.c
+
+tkey/keydelete-keydelete.obj: tkey/keydelete.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tkey_keydelete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tkey/keydelete-keydelete.obj -MD -MP -MF tkey/$(DEPDIR)/keydelete-keydelete.Tpo -c -o tkey/keydelete-keydelete.obj `if test -f 'tkey/keydelete.c'; then $(CYGPATH_W) 'tkey/keydelete.c'; else $(CYGPATH_W) '$(srcdir)/tkey/keydelete.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tkey/$(DEPDIR)/keydelete-keydelete.Tpo tkey/$(DEPDIR)/keydelete-keydelete.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tkey/keydelete.c' object='tkey/keydelete-keydelete.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tkey_keydelete_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tkey/keydelete-keydelete.obj `if test -f 'tkey/keydelete.c'; then $(CYGPATH_W) 'tkey/keydelete.c'; else $(CYGPATH_W) '$(srcdir)/tkey/keydelete.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf pipelined/.libs pipelined/_libs
+ -rm -rf rndc/.libs rndc/_libs
+ -rm -rf rpz/.libs rpz/_libs
+ -rm -rf tkey/.libs tkey/_libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS:
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+serve-stale.log: serve-stale
+ @p='serve-stale'; \
+ b='serve-stale'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+rpzrecurse.log: rpzrecurse
+ @p='rpzrecurse'; \
+ b='rpzrecurse'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+doth.log: doth
+ @p='doth'; \
+ b='doth'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+acl.log: acl
+ @p='acl'; \
+ b='acl'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+additional.log: additional
+ @p='additional'; \
+ b='additional'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+addzone.log: addzone
+ @p='addzone'; \
+ b='addzone'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+allow-query.log: allow-query
+ @p='allow-query'; \
+ b='allow-query'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+auth.log: auth
+ @p='auth'; \
+ b='auth'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+autosign.log: autosign
+ @p='autosign'; \
+ b='autosign'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+builtin.log: builtin
+ @p='builtin'; \
+ b='builtin'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+cacheclean.log: cacheclean
+ @p='cacheclean'; \
+ b='cacheclean'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+case.log: case
+ @p='case'; \
+ b='case'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+catz.log: catz
+ @p='catz'; \
+ b='catz'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+cds.log: cds
+ @p='cds'; \
+ b='cds'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+checkconf.log: checkconf
+ @p='checkconf'; \
+ b='checkconf'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+checknames.log: checknames
+ @p='checknames'; \
+ b='checknames'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+checkzone.log: checkzone
+ @p='checkzone'; \
+ b='checkzone'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+database.log: database
+ @p='database'; \
+ b='database'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+dialup.log: dialup
+ @p='dialup'; \
+ b='dialup'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+dlzexternal.log: dlzexternal
+ @p='dlzexternal'; \
+ b='dlzexternal'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+dns64.log: dns64
+ @p='dns64'; \
+ b='dns64'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+dsdigest.log: dsdigest
+ @p='dsdigest'; \
+ b='dsdigest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+dupsigs.log: dupsigs
+ @p='dupsigs'; \
+ b='dupsigs'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+dyndb.log: dyndb
+ @p='dyndb'; \
+ b='dyndb'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+ecdsa.log: ecdsa
+ @p='ecdsa'; \
+ b='ecdsa'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+eddsa.log: eddsa
+ @p='eddsa'; \
+ b='eddsa'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+ednscompliance.log: ednscompliance
+ @p='ednscompliance'; \
+ b='ednscompliance'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+emptyzones.log: emptyzones
+ @p='emptyzones'; \
+ b='emptyzones'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+enginepkcs11.log: enginepkcs11
+ @p='enginepkcs11'; \
+ b='enginepkcs11'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+filter-aaaa.log: filter-aaaa
+ @p='filter-aaaa'; \
+ b='filter-aaaa'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+formerr.log: formerr
+ @p='formerr'; \
+ b='formerr'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+geoip2.log: geoip2
+ @p='geoip2'; \
+ b='geoip2'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+glue.log: glue
+ @p='glue'; \
+ b='glue'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+idna.log: idna
+ @p='idna'; \
+ b='idna'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+include-multiplecfg.log: include-multiplecfg
+ @p='include-multiplecfg'; \
+ b='include-multiplecfg'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+inline.log: inline
+ @p='inline'; \
+ b='inline'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+integrity.log: integrity
+ @p='integrity'; \
+ b='integrity'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+hooks.log: hooks
+ @p='hooks'; \
+ b='hooks'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+host.log: host
+ @p='host'; \
+ b='host'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+journal.log: journal
+ @p='journal'; \
+ b='journal'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+keepalive.log: keepalive
+ @p='keepalive'; \
+ b='keepalive'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+keyfromlabel.log: keyfromlabel
+ @p='keyfromlabel'; \
+ b='keyfromlabel'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+legacy.log: legacy
+ @p='legacy'; \
+ b='legacy'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+limits.log: limits
+ @p='limits'; \
+ b='limits'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+logfileconfig.log: logfileconfig
+ @p='logfileconfig'; \
+ b='logfileconfig'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+masterfile.log: masterfile
+ @p='masterfile'; \
+ b='masterfile'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+masterformat.log: masterformat
+ @p='masterformat'; \
+ b='masterformat'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+metadata.log: metadata
+ @p='metadata'; \
+ b='metadata'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mirror.log: mirror
+ @p='mirror'; \
+ b='mirror'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mkeys.log: mkeys
+ @p='mkeys'; \
+ b='mkeys'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+names.log: names
+ @p='names'; \
+ b='names'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+notify.log: notify
+ @p='notify'; \
+ b='notify'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+nsec3.log: nsec3
+ @p='nsec3'; \
+ b='nsec3'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+nslookup.log: nslookup
+ @p='nslookup'; \
+ b='nslookup'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+padding.log: padding
+ @p='padding'; \
+ b='padding'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+pending.log: pending
+ @p='pending'; \
+ b='pending'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+redirect.log: redirect
+ @p='redirect'; \
+ b='redirect'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+rndc.log: rndc
+ @p='rndc'; \
+ b='rndc'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+rootkeysentinel.log: rootkeysentinel
+ @p='rootkeysentinel'; \
+ b='rootkeysentinel'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+rpz.log: rpz
+ @p='rpz'; \
+ b='rpz'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+rrchecker.log: rrchecker
+ @p='rrchecker'; \
+ b='rrchecker'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+rrl.log: rrl
+ @p='rrl'; \
+ b='rrl'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+rrsetorder.log: rrsetorder
+ @p='rrsetorder'; \
+ b='rrsetorder'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+rsabigexponent.log: rsabigexponent
+ @p='rsabigexponent'; \
+ b='rsabigexponent'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+runtime.log: runtime
+ @p='runtime'; \
+ b='runtime'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+sfcache.log: sfcache
+ @p='sfcache'; \
+ b='sfcache'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+smartsign.log: smartsign
+ @p='smartsign'; \
+ b='smartsign'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+sortlist.log: sortlist
+ @p='sortlist'; \
+ b='sortlist'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+spf.log: spf
+ @p='spf'; \
+ b='spf'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+staticstub.log: staticstub
+ @p='staticstub'; \
+ b='staticstub'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+stub.log: stub
+ @p='stub'; \
+ b='stub'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+synthfromdnssec.log: synthfromdnssec
+ @p='synthfromdnssec'; \
+ b='synthfromdnssec'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+tkey.log: tkey
+ @p='tkey'; \
+ b='tkey'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+tools.log: tools
+ @p='tools'; \
+ b='tools'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+transport-acl.log: transport-acl
+ @p='transport-acl'; \
+ b='transport-acl'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+tsig.log: tsig
+ @p='tsig'; \
+ b='tsig'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+tsiggss.log: tsiggss
+ @p='tsiggss'; \
+ b='tsiggss'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+ttl.log: ttl
+ @p='ttl'; \
+ b='ttl'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+unknown.log: unknown
+ @p='unknown'; \
+ b='unknown'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+verify.log: verify
+ @p='verify'; \
+ b='verify'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+views.log: views
+ @p='views'; \
+ b='views'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+wildcard.log: wildcard
+ @p='wildcard'; \
+ b='wildcard'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+xferquota.log: xferquota
+ @p='xferquota'; \
+ b='xferquota'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+zonechecks.log: zonechecks
+ @p='zonechecks'; \
+ b='zonechecks'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+nzd2nzf.log: nzd2nzf
+ @p='nzd2nzf'; \
+ b='nzd2nzf'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+fetchlimit.log: fetchlimit
+ @p='fetchlimit'; \
+ b='fetchlimit'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+ixfr.log: ixfr
+ @p='ixfr'; \
+ b='ixfr'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+nsupdate.log: nsupdate
+ @p='nsupdate'; \
+ b='nsupdate'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+resolver.log: resolver
+ @p='resolver'; \
+ b='resolver'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+statistics.log: statistics
+ @p='statistics'; \
+ b='statistics'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+stress.log: stress
+ @p='stress'; \
+ b='stress'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+upforwd.log: upforwd
+ @p='upforwd'; \
+ b='upforwd'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+zero.log: zero
+ @p='zero'; \
+ b='zero'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+dnstap.log: dnstap
+ @p='dnstap'; \
+ b='dnstap'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+statschannel.log: statschannel
+ @p='statschannel'; \
+ b='statschannel'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+xfer.log: xfer
+ @p='xfer'; \
+ b='xfer'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+reclimit.log: reclimit
+ @p='reclimit'; \
+ b='reclimit'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+kasp.log: kasp
+ @p='kasp'; \
+ b='kasp'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+keymgr2kasp.log: keymgr2kasp
+ @p='keymgr2kasp'; \
+ b='keymgr2kasp'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+tcp.log: tcp
+ @p='tcp'; \
+ b='tcp'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+pipelined.log: pipelined
+ @p='pipelined'; \
+ b='pipelined'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+checkds.log: checkds
+ @p='checkds'; \
+ b='checkds'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+dispatch.log: dispatch
+ @p='dispatch'; \
+ b='dispatch'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+rpzextra.log: rpzextra
+ @p='rpzextra'; \
+ b='rpzextra'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+shutdown.log: shutdown
+ @p='shutdown'; \
+ b='shutdown'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+timeouts.log: timeouts
+ @p='timeouts'; \
+ b='timeouts'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+qmin.log: qmin
+ @p='qmin'; \
+ b='qmin'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+cookie.log: cookie
+ @p='cookie'; \
+ b='cookie'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+digdelv.log: digdelv
+ @p='digdelv'; \
+ b='digdelv'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+dnssec.log: dnssec
+ @p='dnssec'; \
+ b='dnssec'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+forward.log: forward
+ @p='forward'; \
+ b='forward'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+chain.log: chain
+ @p='chain'; \
+ b='chain'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$(top_distdir)" distdir="$(distdir)" \
+ dist-hook
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-recursive
+all-am: Makefile $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f pipelined/$(DEPDIR)/$(am__dirstamp)
+ -rm -f pipelined/$(am__dirstamp)
+ -rm -f rndc/$(DEPDIR)/$(am__dirstamp)
+ -rm -f rndc/$(am__dirstamp)
+ -rm -f rpz/$(DEPDIR)/$(am__dirstamp)
+ -rm -f rpz/$(am__dirstamp)
+ -rm -f tkey/$(DEPDIR)/$(am__dirstamp)
+ -rm -f tkey/$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f ./$(DEPDIR)/feature_test-feature-test.Po
+ -rm -f ./$(DEPDIR)/makejournal-makejournal.Po
+ -rm -f ./$(DEPDIR)/resolve-resolve.Po
+ -rm -f pipelined/$(DEPDIR)/pipequeries-pipequeries.Po
+ -rm -f rndc/$(DEPDIR)/gencheck.Po
+ -rm -f rpz/$(DEPDIR)/dnsrps-dnsrps.Po
+ -rm -f tkey/$(DEPDIR)/keycreate-keycreate.Po
+ -rm -f tkey/$(DEPDIR)/keydelete-keydelete.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-recursive
+
+doc-am: doc-local
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f ./$(DEPDIR)/feature_test-feature-test.Po
+ -rm -f ./$(DEPDIR)/makejournal-makejournal.Po
+ -rm -f ./$(DEPDIR)/resolve-resolve.Po
+ -rm -f pipelined/$(DEPDIR)/pipequeries-pipequeries.Po
+ -rm -f rndc/$(DEPDIR)/gencheck.Po
+ -rm -f rpz/$(DEPDIR)/dnsrps-dnsrps.Po
+ -rm -f tkey/$(DEPDIR)/keycreate-keycreate.Po
+ -rm -f tkey/$(DEPDIR)/keydelete-keydelete.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+test: test-recursive
+
+test-am: test-local
+
+uninstall-am:
+
+unit: unit-recursive
+
+unit-am: unit-local
+
+.MAKE: $(am__recursive_targets) check-am install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+ am--depfiles check check-TESTS check-am clean clean-generic \
+ clean-libtool clean-local clean-noinstPROGRAMS cscopelist-am \
+ ctags ctags-am dist-hook distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir \
+ doc-am doc-local dvi dvi-am html html-am info info-am install \
+ install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \
+ test-am test-local uninstall uninstall-am unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Source tarballs must not contain configure/build artifacts.
+dist-hook:
+ git clean -n -x -d | \
+ grep -v "Makefile.in$$" | \
+ sed -n "s|^Would remove \(.*\)|$(distdir)/\1|p" | \
+ xargs -I{} rm -rf "{}"
+
+@HAVE_PERL_FALSE@check:
+@HAVE_PERL_FALSE@ echo Perl is not available, no tests were ran
+@HAVE_PERL_FALSE@ exit 1
+
+$(TESTS): legacy.run.sh
+
+test-local: check
+
+clean-local::
+ -find $(builddir) -maxdepth 1 -type d -name "*_*" | xargs rm -rf
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/tests/system/README b/bin/tests/system/README
new file mode 100644
index 0000000..265a9ef
--- /dev/null
+++ b/bin/tests/system/README
@@ -0,0 +1,843 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+Introduction
+===
+This directory holds a simple test environment for running bind9 system tests
+involving multiple name servers.
+
+With the exception of "common" (which holds configuration information common to
+multiple tests), each directory holds a set of scripts and configuration
+files to test different parts of BIND. The directories are named for the
+aspect of BIND they test, for example:
+
+ dnssec/ DNSSEC tests
+ forward/ Forwarding tests
+ glue/ Glue handling tests
+
+etc.
+
+Typically each set of tests sets up 2-5 name servers and then performs one or
+more tests against them. Within the test subdirectory, each name server has a
+separate subdirectory containing its configuration data. These subdirectories
+are named "nsN" or "ansN" (where N is a number between 1 and 8, e.g. ns1, ans2
+etc.)
+
+The tests are completely self-contained and do not require access to the real
+DNS. Generally, one of the test servers (usually ns1) is set up as a root
+nameserver and is listed in the hints file of the others.
+
+
+Preparing to Run the Tests
+===
+To enable all servers to run on the same machine, they bind to separate virtual
+IP addresses on the loopback interface. ns1 runs on 10.53.0.1, ns2 on
+10.53.0.2, etc. Before running any tests, you must set up these addresses by
+running the command
+
+ sh ifconfig.sh up
+
+as root. The interfaces can be removed by executing the command:
+
+ sh ifconfig.sh down
+
+... also as root.
+
+The servers use unprivileged ports (above 1024) instead of the usual port 53,
+so they can be run without root privileges once the interfaces have been set
+up.
+
+
+Note for MacOS Users
+---
+If you wish to make the interfaces survive across reboots, copy
+org.isc.bind.system and org.isc.bind.system.plist to /Library/LaunchDaemons
+then run
+
+ launchctl load /Library/LaunchDaemons/org.isc.bind.system.plist
+
+... as root.
+
+
+Running the System Tests with pytest
+===
+
+The pytest system test runner is currently in development, but it is the
+recommended way to run tests. Please report issues to QA.
+
+Running an Individual Test
+---
+
+pytest -k <test-name>
+
+Note that in comparison to the legacy test runner, some additional tests might
+be picked up when specifying just the system test directory name. To check
+which tests will be executed, you can use the `--collect-only` option. You
+might also be able to find a more specific test name to provide to ensure only
+your desired test is executed. See help for `-k` option in `pytest --help` for
+more info.
+
+It is also possible to run a single individual pytest test case. For example,
+you can use the name test_sslyze_dot to execute just the test_sslyze_dot()
+function from doth/tests_sslyze.py. The entire needed setup and teardown will
+be handled by the framework.
+
+Running All the System Tests
+---
+
+Issuing plain `pytest` command without any argument will execute all tests
+sequenatially. To execute them in parallel, ensure you have pytest-xdist
+installed and run:
+
+pytest -n <number-of-workers>
+
+
+Running the System Tests Using the Legacy Runner
+===
+
+!!! WARNING !!!
+---
+The legacy way to run system tests is currently being reworked into a pytest
+system test runner described in the previous section. The contents of this
+section might be out of date and no longer applicable. Please try and use the
+pytest runner if possible and report issues and missing features.
+
+Running an Individual Test
+---
+The tests can be run individually using the following command:
+
+ sh legacy.run.sh [flags] <test-name> [<test-arguments>]
+
+e.g.
+
+ sh legacy.run.sh [flags] notify
+
+Optional flags are:
+
+ -k Keep servers running after the test completes. Each test
+ usually starts a number of nameservers, either instances
+ of the "named" being tested, or custom servers (written in
+ Python or Perl) that feature test-specific behavior. The
+ servers are automatically started before the test is run
+ and stopped after it ends. This flag leaves them running
+ at the end of the test, so that additional queries can be
+ sent by hand. To stop the servers afterwards, use the
+ command "sh stop.sh <test-name>".
+
+ -n Noclean - do not remove the output files if the test
+ completes successfully. By default, files created by the
+ test are deleted if it passes; they are not deleted if the
+ test fails.
+
+ -p <number> Sets the range of ports used by the test. A block of 100
+ ports is available for each test, the number given to the
+ "-p" switch being the number of the start of that block
+ (e.g. "-p 7900" will mean that the test is able to use
+ ports 7900 through 7999). If not specified, the test will
+ have ports 5000 to 5099 available to it.
+
+Arguments are:
+
+ test-name Mandatory. The name of the test, which is the name of the
+ subdirectory in bin/tests/system holding the test files.
+
+ test-arguments Optional arguments that are passed to each of the test's
+ scripts.
+
+
+Running All The System Tests
+---
+To run all the system tests, enter the command:
+
+ sh runall.sh [-c] [-n] [numproc]
+
+The optional flag "-c" forces colored output (by default system test output is
+not printed in color due to legacy.run.sh being piped through "tee").
+
+The optional flag "-n" has the same effect as it does for "legacy.run.sh" - it
+causes the retention of all output files from all tests.
+
+The optional "numproc" argument specifies the maximum number of tests that can
+run in parallel. The default is 1, which means that all of the tests run
+sequentially. If greater than 1, up to "numproc" tests will run simultaneously,
+new tests being started as tests finish. Each test will get a unique set of
+ports, so there is no danger of tests interfering with one another. Parallel
+running will reduce the total time taken to run the BIND system tests, but will
+mean that the output from all the tests sent to the screen will be mixed up
+with one another. However, the systests.output file produced at the end of the
+run (in the bin/tests/system directory) will contain the output from each test
+in sequential order.
+
+Note that it is not possible to pass arguments to tests though the "runall.sh"
+script.
+
+A run of all the system tests can also be initiated via make:
+
+ make [-j numproc] test
+
+In this case, retention of the output files after a test completes successfully
+is specified by setting the environment variable SYSTEMTEST_NO_CLEAN to 1 prior
+to running make, e.g.
+
+ SYSTEMTEST_NO_CLEAN=1 make [-j numproc] test
+
+while setting environment variable SYSTEMTEST_FORCE_COLOR to 1 forces system
+test output to be printed in color.
+
+
+Running Multiple System Test Suites Simultaneously
+---
+In some cases it may be desirable to have multiple instances of the system test
+suite running simultaneously (e.g. from different terminal windows). To do
+this:
+
+1. Each installation must have its own directory tree. The system tests create
+files in the test directories, so separate directory trees are required to
+avoid interference between the same test running in the different
+installations.
+
+2. For one of the test suites, the starting port number must be specified by
+setting the environment variable STARTPORT before starting the test suite.
+Each test suite comprises about 100 tests, each being allocated a set of 100
+ports. The port ranges for each test are allocated sequentially, so each test
+suite requires about 10,000 ports to itself. By default, the port allocation
+starts at 5,000. So the following set of commands:
+
+ Terminal Window 1:
+ cd <installation-1>/bin/tests/system
+ sh runall.sh 4
+
+ Terminal Window 2:
+ cd <installation-2>/bin/tests/system
+ STARTPORT=20000 sh runall.sh 4
+
+... will start the test suite for installation-1 using the default base port
+of 5,000, so the test suite will use ports 5,000 through 15,000 (or there
+abouts). The use of "STARTPORT=20000" to prefix the run of the test suite for
+installation-2 will mean the test suite uses ports 20,000 through 30,000 or so.
+
+
+Format of Test Output
+---
+All output from the system tests is in the form of lines with the following
+structure:
+
+ <letter>:<test-name>:<message> [(<number>)]
+
+e.g.
+
+ I:catz:checking that dom1.example is not served by primary (1)
+
+The meanings of the fields are as follows:
+
+<letter>
+This indicates the type of message. This is one of:
+
+ S Start of the test
+ A Start of test (retained for backwards compatibility)
+ T Start of test (retained for backwards compatibility)
+ E End of the test
+ I Information. A test will typically output many of these messages
+ during its run, indicating test progress. Note that such a message may
+ be of the form "I:testname:failed", indicating that a sub-test has
+ failed.
+ R Result. Each test will result in one such message, which is of the
+ form:
+
+ R:<test-name>:<result>
+
+ where <result> is one of:
+
+ PASS The test passed
+ FAIL The test failed
+ SKIPPED The test was not run, usually because some
+ prerequisites required to run the test are missing.
+
+<test-name>
+This is the name of the test from which the message emanated, which is also the
+name of the subdirectory holding the test files.
+
+<message>
+This is text output by the test during its execution.
+
+(<number>)
+If present, this will correlate with a file created by the test. The tests
+execute commands and route the output of each command to a file. The name of
+this file depends on the command and the test, but will usually be of the form:
+
+ <command>.out.<suffix><number>
+
+e.g. nsupdate.out.test28, dig.out.q3. This aids diagnosis of problems by
+allowing the output that caused the problem message to be identified.
+
+
+Re-Running the Tests
+---
+If there is a requirement to re-run a test (or the entire test suite), the
+files produced by the tests should be deleted first. Normally, these files are
+deleted if the test succeeds but are retained on error. The legacy.run.sh
+script automatically calls a given test's clean.sh script before invoking its
+setup.sh script.
+
+Deletion of the files produced by the set of tests (e.g. after the execution
+of "runall.sh") can be carried out using the command:
+
+ sh cleanall.sh
+
+or
+
+ make testclean
+
+(Note that the Makefile has two other targets for cleaning up files: "clean"
+will delete all the files produced by the tests, as well as the object and
+executable files used by the tests. "distclean" does all the work of "clean"
+as well as deleting configuration files produced by "configure".)
+
+
+Developer Notes
+===
+This section is intended for developers writing new tests.
+
+
+Overview
+---
+As noted above, each test is in a separate directory. To interact with the
+test framework, the directories contain the following standard files:
+
+prereq.sh Run at the beginning to determine whether the test can be run at
+ all; if not, we see a R:SKIPPED result. This file is optional:
+ if not present, the test is assumed to have all its prerequisites
+ met.
+
+setup.sh Run after prereq.sh, this sets up the preconditions for the tests.
+ Although optional, virtually all tests will require such a file to
+ set up the ports they should use for the test.
+
+tests.sh Runs the actual tests. This file is mandatory.
+
+clean.sh Run at the end to clean up temporary files, but only if the test
+ was completed successfully and its running was not inhibited by the
+ "-n" switch being passed to "legacy.run.sh". Otherwise the
+ temporary files are left in place for inspection.
+
+ns<N> These subdirectories contain test name servers that can be queried
+ or can interact with each other. The value of N indicates the
+ address the server listens on: for example, ns2 listens on
+ 10.53.0.2, and ns4 on 10.53.0.4. All test servers use an
+ unprivileged port, so they don't need to run as root. These
+ servers log at the highest debug level and the log is captured in
+ the file "named.run".
+
+ans<N> Like ns[X], but these are simple mock name servers implemented in
+ Perl or Python. They are generally programmed to misbehave in ways
+ named would not so as to exercise named's ability to interoperate
+ with badly behaved name servers.
+
+
+Port Usage
+---
+In order for the tests to run in parallel, each test requires a unique set of
+ports. These are specified by the "-p" option passed to "legacy.run.sh", which
+sets environment variables that the scripts listed above can reference.
+
+The convention used in the system tests is that the number passed is the start
+of a range of 100 ports. The test is free to use the ports as required,
+although the first ten ports in the block are named and generally tests use the
+named ports for their intended purpose. The names of the environment variables
+are:
+
+ PORT Number to be used for the query port.
+ CONTROLPORT Number to be used as the RNDC control port.
+ EXTRAPORT1 - EXTRAPORT8 Eight port numbers that can be used as needed.
+
+Two other environment variables are defined:
+
+ LOWPORT The lowest port number in the range.
+ HIGHPORT The highest port number in the range.
+
+Since port ranges usually start on a boundary of 10, the variables are set such
+that the last digit of the port number corresponds to the number of the
+EXTRAPORTn variable. For example, if the port range were to start at 5200, the
+port assignments would be:
+
+ PORT = 5200
+ EXTRAPORT1 = 5201
+ :
+ EXTRAPORT8 = 5208
+ CONTROLPORT = 5209
+ LOWPORT = 5200
+ HIGHPORT = 5299
+
+When running tests in parallel (i.e. giving a value of "numproc" greater than 1
+in the "make" or "runall.sh" commands listed above), it is guaranteed that each
+test will get a set of unique port numbers.
+
+
+Writing a Test
+---
+The test framework requires up to four shell scripts (listed above) as well as
+a number of nameserver instances to run. Certain expectations are put on each
+script:
+
+
+General
+---
+1. Each of the four scripts will be invoked with the command
+
+ (cd <test-directory> ; sh <script> [<arguments>] )
+
+... so that working directory when the script starts executing is the test
+directory.
+
+2. Arguments can be only passed to the script if the test is being run as a
+one-off with "legacy.run.sh". In this case, everything on the command line
+after the name of the test is passed to each script. For example, the command:
+
+ sh legacy.run.sh -p 12300 mytest -D xyz
+
+... will run "mytest" with a port range of 12300 to 12399. Each of the
+framework scripts provided by the test will be invoked using the remaining
+arguments, e.g.:
+
+ (cd mytest ; sh prereq.sh -D xyz)
+ (cd mytest ; sh setup.sh -D xyz)
+ (cd mytest ; sh tests.sh -D xyz)
+ (cd mytest ; sh clean.sh -D xyz)
+
+No arguments will be passed to the test scripts if the test is run as part of
+a run of the full test suite (e.g. the tests are started with "runall.sh").
+
+3. Each script should start with the following lines:
+
+ . ../conf.sh
+
+"conf.sh" defines a series of environment variables together with functions
+useful for the test scripts.
+
+
+prereq.sh
+---
+As noted above, this is optional. If present, it should check whether specific
+software needed to run the test is available and/or whether BIND has been
+configured with the appropriate options required.
+
+ * If the software required to run the test is present and the BIND
+ configure options are correct, prereq.sh should return with a status code
+ of 0.
+
+ * If the software required to run the test is not available and/or BIND
+ has not been configured with the appropriate options, prereq.sh should
+ return with a status code of 1.
+
+ * If there is some other problem (e.g. prerequisite software is available
+ but is not properly configured), a status code of 255 should be returned.
+
+
+setup.sh
+---
+This is responsible for setting up the configuration files used in the test.
+
+To cope with the varying port number, ports are not hard-coded into
+configuration files (or, for that matter, scripts that emulate nameservers).
+Instead, setup.sh is responsible for editing the configuration files to set the
+port numbers.
+
+To do this, configuration files should be supplied in the form of templates
+containing tokens identifying ports. The tokens have the same name as the
+environment variables listed above, but are prefixed and suffixed by the "@"
+symbol. For example, a fragment of a configuration file template might look
+like:
+
+ controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+ };
+
+ options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ allow-new-zones yes;
+ };
+
+setup.sh should copy the template to the desired filename using the
+"copy_setports" shell function defined in "conf.sh", i.e.
+
+ copy_setports ns1/named.conf.in ns1/named.conf
+
+This replaces the tokens @PORT@, @CONTROLPORT@, @EXTRAPORT1@ through
+@EXTRAPORT8@ with the contents of the environment variables listed above.
+setup.sh should do this for all configuration files required when the test
+starts.
+
+("setup.sh" should also use this method for replacing the tokens in any Perl or
+Python name servers used in the test.)
+
+
+tests.sh
+---
+This is the main test file and the contents depend on the test. The contents
+are completely up to the developer, although most test scripts have a form
+similar to the following for each sub-test:
+
+ 1. n=$((n + 1))
+ 2. echo_i "prime cache nodata.example ($n)"
+ 3. ret=0
+ 4. $DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$n
+ 5. grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ 6. grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+ 7. if [ $ret != 0 ]; then echo_i "failed"; fi
+ 8. status=$((status + ret))
+
+1. Increment the test number "n" (initialized to zero at the start of the
+ script).
+
+2. Indicate that the sub-test is about to begin. Note that "echo_i" instead
+ of "echo" is used. echo_i is a function defined in "conf.sh" which will
+ prefix the message with "I:<testname>:", so allowing the output from each
+ test to be identified within the output. The test number is included in
+ the message in order to tie the sub-test with its output.
+
+3. Initialize return status.
+
+4 - 6. Carry out the sub-test. In this case, a nameserver is queried (note
+ that the port used is given by the PORT environment variable, which was set
+ by the inclusion of the file "conf.sh" at the start of the script). The
+ output is routed to a file whose suffix includes the test number. The
+ response from the server is examined and, in this case, if the required
+ string is not found, an error is indicated by setting "ret" to 1.
+
+7. If the sub-test failed, a message is printed. "echo_i" is used to print
+ the message to add the prefix "I:<test-name>:" before it is output.
+
+8. "status", used to track how many of the sub-tests have failed, is
+ incremented accordingly. The value of "status" determines the status
+ returned by "tests.sh", which in turn determines whether the framework
+ prints the PASS or FAIL message.
+
+Regardless of this, rules that should be followed are:
+
+a. Use the environment variables set by conf.sh to determine the ports to use
+ for sending and receiving queries.
+
+b. Use a counter to tag messages and to associate the messages with the output
+ files.
+
+c. Store all output produced by queries/commands into files. These files
+ should be named according to the command that produced them, e.g. "dig"
+ output should be stored in a file "dig.out.<suffix>", the suffix being
+ related to the value of the counter.
+
+d. Use "echo_i" to output informational messages.
+
+e. Retain a count of test failures and return this as the exit status from
+ the script.
+
+
+clean.sh
+---
+The inverse of "setup.sh", this is invoked by the framework to clean up the
+test directory. It should delete all files that have been created by the test
+during its run.
+
+
+Starting Nameservers
+---
+As noted earlier, a system test will involve a number of nameservers. These
+will be either instances of named, or special servers written in a language
+such as Perl or Python.
+
+For the former, the version of "named" being run is that in the "bin/named"
+directory in the tree holding the tests (i.e. if "make test" is being run
+immediately after "make", the version of "named" used is that just built). The
+configuration files, zone files etc. for these servers are located in
+subdirectories of the test directory named "nsN", where N is a small integer.
+The latter are special nameservers, mostly used for generating deliberately bad
+responses, located in subdirectories named "ansN" (again, N is an integer).
+In addition to configuration files, these directories should hold the
+appropriate script files as well.
+
+Note that the "N" for a particular test forms a single number space, e.g. if
+there is an "ns2" directory, there cannot be an "ans2" directory as well.
+Ideally, the directory numbers should start at 1 and work upwards.
+
+When running a test, the servers are started using "start.sh" (which is nothing
+more than a wrapper for start.pl). The options for "start.pl" are documented
+in the header for that file, so will not be repeated here. In summary, when
+invoked by "legacy.run.sh", start.pl looks for directories named "nsN" or
+"ansN" in the test directory and starts the servers it finds there.
+
+
+"named" Command-Line Options
+---
+By default, start.pl starts a "named" server with the following options:
+
+ -c named.conf Specifies the configuration file to use (so by implication,
+ each "nsN" nameserver's configuration file must be called
+ named.conf).
+
+ -d 99 Sets the maximum debugging level.
+
+ -D <name> The "-D" option sets a string used to identify the
+ nameserver in a process listing. In this case, the string
+ is the name of the subdirectory.
+
+ -g Runs the server in the foreground and logs everything to
+ stderr.
+
+ -m record
+ Turns on these memory usage debugging flags.
+
+ -U 4 Uses four listeners.
+
+ -X named.lock Acquires a lock on this file in the "nsN" directory, so
+ preventing multiple instances of this named running in this
+ directory (which could possibly interfere with the test).
+
+All output is sent to a file called "named.run" in the nameserver directory.
+
+The options used to start named can be altered. There are three ways of doing
+this. "start.pl" checks the methods in a specific order: if a check succeeds,
+the options are set and any other specification is ignored. In order, these
+are:
+
+1. Specifying options to "start.sh"/"start.pl" after the name of the test
+directory, e.g.
+
+ sh start.sh reclimit ns1 -- "-c n.conf -d 43"
+
+(This is only really useful when running tests interactively.)
+
+2. Including a file called "named.args" in the "nsN" directory. If present,
+the contents of the first non-commented, non-blank line of the file are used as
+the named command-line arguments. The rest of the file is ignored.
+
+3. Tweaking the default command line arguments with "-T" options. This flag is
+used to alter the behavior of BIND for testing and is not documented in the
+ARM. The presence of certain files in the "nsN" directory adds flags to
+the default command line (the content of the files is irrelevant - it
+is only the presence that counts):
+
+ named.noaa Appends "-T noaa" to the command line, which causes
+ "named" to never set the AA bit in an answer.
+
+ named.dropedns Adds "-T dropedns" to the command line, which causes
+ "named" to recognise EDNS options in messages, but drop
+ messages containing them.
+
+ named.maxudp1460 Adds "-T maxudp1460" to the command line, setting the
+ maximum UDP size handled by named to 1460.
+
+ named.maxudp512 Adds "-T maxudp512" to the command line, setting the
+ maximum UDP size handled by named to 512.
+
+ named.noedns Appends "-T noedns" to the command line, which disables
+ recognition of EDNS options in messages.
+
+ named.notcp Adds "-T notcp", which disables TCP in "named".
+
+ named.soa Appends "-T nosoa" to the command line, which disables
+ the addition of SOA records to negative responses (or to
+ the additional section if the response is triggered by RPZ
+ rewriting).
+
+Starting Other Nameservers
+---
+In contrast to "named", nameservers written in Perl or Python (whose script
+file should have the name "ans.pl" or "ans.py" respectively) are started with a
+fixed command line. In essence, the server is given the address and nothing
+else.
+
+(This is not strictly true: Python servers are provided with the number of the
+query port to use. Altering the port used by Perl servers currently requires
+creating a template file containing the "@PORT@" token, and having "setup.sh"
+substitute the actual port being used before the test starts.)
+
+
+Stopping Nameservers
+---
+As might be expected, the test system stops nameservers with the script
+"stop.sh", which is little more than a wrapper for "stop.pl". Like "start.pl",
+the options available are listed in the file's header and will not be repeated
+here.
+
+In summary though, the nameservers for a given test, if left running by
+specifying the "-k" flag to "legacy.run.sh" when the test is started, can be
+stopped by the command:
+
+ sh stop.sh <test-name> [server]
+
+... where if the server (e.g. "ns1", "ans3") is not specified, all servers
+associated with the test are stopped.
+
+
+Adding a Test to the System Test Suite
+---
+Once a test has been created, the following files should be edited:
+
+* conf.sh.in The name of the test should be added to the PARALLELDIRS or
+SEQUENTIALDIRS variables as appropriate. The former is used for tests that
+can run in parallel with other tests, the latter for tests that are unable to
+do so.
+
+* Makefile.in The name of the test should be added to one of the the PARALLEL
+or SEQUENTIAL variables.
+
+(It is likely that a future iteration of the system test suite will remove the
+need to edit multiple files to add a test.)
+
+
+Valgrind
+---
+When running system tests, named can be run under Valgrind. The output from
+Valgrind are sent to per-process files that can be reviewed after the test has
+completed. To enable this, set the USE_VALGRIND environment variable to
+"helgrind" to run the Helgrind tool, or any other value to run the Memcheck
+tool. To use "helgrind" effectively, build BIND with --disable-atomic.
+
+Developer Notes for pytest runner
+===
+
+Test discovery and collection
+---
+There are two distinct types of system tests. The first is a shell script
+tests.sh containing individual test cases executed sequentially and the
+success/failure is determined by return code. The second type is a regular
+pytest file which contains test functions.
+
+Dealing with the regular pytest files doesn't require any special consideration
+as long as the naming conventions are met. Discovering the tests.sh tests is
+more complicated.
+
+The chosen solution is to add a bit of glue for each system test. For every
+tests.sh, there is an accompanying tests_sh_*.py file that contains a test
+function which utilizes a custom run_tests_sh fixture to call the tests.sh
+script. Other solutions were tried and eventually rejected. While this
+introduces a bit of extra glue, it is the most portable, compatible and least
+complex solution.
+
+Module scope
+---
+Pytest fixtures can have a scope. The "module" scope is the most important for
+our use. A module is a python file which contains test functions. Every system
+test directory may contain multiple modules (i.e. tests_*.py files)!
+
+The server setup/teardown is done for a module. Bundling test cases together
+inside a single module may save some resources. However, test cases inside a
+single module can't be executed in parallel.
+
+It is possible to execute different modules defined within a single system test
+directory in parallel. This is possible thanks to executing the tests inside a
+temporary directory and proper port assignment to ensure there won't be any
+conflicts.
+
+Test logging
+---
+Each module has a separate log which will be saved as pytest.log.txt in the
+temporary directory in which the test is executed. This log includes messages
+for this module setup/teardown as well as any logging from the tests using the
+`logger` fixture. Logging level DEBUG and above will be present in this log.
+
+In general, any log messages using INFO or above will also be printed out
+during pytest execution. In CI, the pytest output is also saved to
+pytest.out.txt in the bin/tests/system directory.
+
+Parallel execution
+---
+As mentioned in the previous section, test cases inside a single module can't
+be executed in parallel. To put it differently, all tests cases inside the same
+module must be performed by the same worker/thread. Otherwise, server
+setup/teardown fixtures won't be shared and runtime issues due to port
+collisions are likely to occur.
+
+Pytest-xdist is used for executing pytest test cases in parallel using the `-n
+N_WORKERS` option. By default, xdist will distribute any test case to any
+worker, which would lead to the issue described above. Therefore, conftest.py
+enforces equivalent of `--dist loadscope` option which ensures that test cases
+within the same (module) scope will be handled by the same worker. Parallelism
+is automatically disabled when xdist.scheduler.loadscope library is not
+available.
+
+$ pytest -n auto
+
+Test selection
+---
+It is possible to run just a single pytest test case from any module. Use
+standard pytest facility to select the desired test case(s), i.e. pass a
+sufficiently unique identifier for `-k` parameter. You can also check which
+tests will be executed by using the `--collect-only` flag to debug your `-k`
+expression.
+
+Compatibility with older pytest version
+---
+Keep in mind that the pytest runner must work with ancient versions of pytest.
+When implementing new features, it is advisable to check feature support in
+pytest and pytest-xdist in older distributions first.
+
+As a general rule, any changes to the pytest runner need to keep working on all
+platforms in CI that use the pytest runner. As of 2023-01-13, the oldest
+supported version is whatever is available in EL8.
+
+We may need to add more compat code eventually to handle breaking upstream
+changes. For example, using request.fspath attribute is already deprecatred in
+latest pytest.
+
+Maintenance Notes for legacy runner
+===
+This section is aimed at developers maintaining BIND's system test framework.
+
+Notes on Parallel Execution
+---
+Although execution of an individual test is controlled by "legacy.run.sh",
+which executes the above shell scripts (and starts the relevant servers) for
+each test, the running of all tests in the test suite is controlled by the
+Makefile. ("runall.sh" does little more than invoke "make" on the Makefile.)
+
+All system tests are capable of being run in parallel. For this to work, each
+test needs to use a unique set of ports. To avoid the need to define which
+tests use which ports (and so risk port clashes as further tests are added),
+the ports are assigned when the tests are run. This is achieved by having the
+"test" target in the Makefile depend on "parallel.mk". That file is created
+when "make check" is run, and contains a target for each test of the form:
+
+ <test-name>:
+ @$(SHELL) legacy.run.sh -p <baseport> <test-name>
+
+The <baseport> is unique and the values of <baseport> for each test are
+separated by at least 100 ports.
+
+
+Cleaning Up From Tests
+---
+When a test is run, up to three different types of files are created:
+
+1. Files generated by the test itself, e.g. output from "dig" and "rndc", are
+stored in the test directory.
+
+2. Files produced by named which may not be cleaned up if named exits
+abnormally, e.g. core files, PID files etc., are stored in the test directory.
+
+3. A file "test.output.<test-name>" containing the text written to stdout by the
+test is written to bin/tests/system/. This file is only produced when the test
+is run as part of the entire test suite (e.g. via "runall.sh").
+
+If the test fails, all these files are retained. But if the test succeeds,
+they are cleaned up at different times:
+
+1. Files generated by the test itself are cleaned up by the test's own
+"clean.sh", which is called from "legacy.run.sh".
+
+2. Files that may not be cleaned up if named exits abnormally can be removed
+using the "cleanall.sh" script.
+
+3. "test.output.*" files are deleted when the test suite ends. At this point,
+the file "testsummary.sh" is called which concatenates all the "test.output.*"
+files into a single "systests.output" file before deleting them.
diff --git a/bin/tests/system/acl/clean.sh b/bin/tests/system/acl/clean.sh
new file mode 100644
index 0000000..c8d26cc
--- /dev/null
+++ b/bin/tests/system/acl/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f dig.out.*
+rm -f ns2/example.db ns2/tsigzone.db ns2/example.db.jnl
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f ns*/_default.nzf
+rm -f ns*/_default.nzd*
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
diff --git a/bin/tests/system/acl/ns2/named1.conf.in b/bin/tests/system/acl/ns2/named1.conf.in
new file mode 100644
index 0000000..c3343a3
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named1.conf.in
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+ dnssec-validation no;
+};
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type primary;
+ file "tsigzone.db";
+ allow-transfer { !key one; any; };
+};
diff --git a/bin/tests/system/acl/ns2/named2.conf.in b/bin/tests/system/acl/ns2/named2.conf.in
new file mode 100644
index 0000000..ac9ac84
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named2.conf.in
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+ dnssec-validation no;
+};
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type primary;
+ file "tsigzone.db";
+ /*
+ * 0a00::/8 and 10/8 are the same bits, but different address
+ * families. This should *not* match IPv4 queries from 10.*.
+ */
+ allow-transfer { 0a00::/8; !10/8; key one; };
+};
diff --git a/bin/tests/system/acl/ns2/named3.conf.in b/bin/tests/system/acl/ns2/named3.conf.in
new file mode 100644
index 0000000..efa73fa
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named3.conf.in
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+ dnssec-validation no;
+};
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key three {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+acl reject {
+ !key one; !key two; any;
+};
+
+acl accept {
+ 10.53.0.1; 10.53.0.2;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type primary;
+ file "tsigzone.db";
+ allow-transfer { !reject; accept; };
+};
diff --git a/bin/tests/system/acl/ns2/named4.conf.in b/bin/tests/system/acl/ns2/named4.conf.in
new file mode 100644
index 0000000..54c0da3
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named4.conf.in
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+ dnssec-validation no;
+};
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+acl rejectkeys {
+ !key one; !key two; any;
+};
+
+acl rejectaddrs {
+ !10.53.0.1; !10.53.0.2; any;
+};
+
+acl check1 { !key one; 10.53.0.1; };
+
+acl check2 { !key two; 10.53.0.2; };
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type primary;
+ file "tsigzone.db";
+ allow-transfer { !rejectkeys; !rejectaddrs; !check1; !check2; any; };
+};
diff --git a/bin/tests/system/acl/ns2/named5.conf.in b/bin/tests/system/acl/ns2/named5.conf.in
new file mode 100644
index 0000000..e5b57f0
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named5.conf.in
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+ dnssec-validation no;
+ allow-query-on { 10.53.0.2; };
+ blackhole { 10.53.0.8; };
+};
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type primary;
+ file "tsigzone.db";
+ allow-transfer { !key one; any; };
+};
diff --git a/bin/tests/system/acl/ns3/example.db b/bin/tests/system/acl/ns3/example.db
new file mode 100644
index 0000000..34fe9e5
--- /dev/null
+++ b/bin/tests/system/acl/ns3/example.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
diff --git a/bin/tests/system/acl/ns3/named.conf.in b/bin/tests/system/acl/ns3/named.conf.in
new file mode 100644
index 0000000..31d3526
--- /dev/null
+++ b/bin/tests/system/acl/ns3/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ allow-new-zones yes;
+ allow-transfer { none; };
+ dnssec-validation no;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/acl/ns4/example.db b/bin/tests/system/acl/ns4/example.db
new file mode 100644
index 0000000..91c8702
--- /dev/null
+++ b/bin/tests/system/acl/ns4/example.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.4
diff --git a/bin/tests/system/acl/ns4/existing.db b/bin/tests/system/acl/ns4/existing.db
new file mode 100644
index 0000000..91c8702
--- /dev/null
+++ b/bin/tests/system/acl/ns4/existing.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.4
diff --git a/bin/tests/system/acl/ns4/named.conf.in b/bin/tests/system/acl/ns4/named.conf.in
new file mode 100644
index 0000000..9b769d1
--- /dev/null
+++ b/bin/tests/system/acl/ns4/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ allow-new-zones yes;
+ allow-transfer { none; };
+ dnssec-validation no;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+zone "existing" {
+ type primary;
+ file "existing.db";
+};
diff --git a/bin/tests/system/acl/setup.sh b/bin/tests/system/acl/setup.sh
new file mode 100644
index 0000000..7dcd872
--- /dev/null
+++ b/bin/tests/system/acl/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 3 >ns2/example.db
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 3 >ns2/tsigzone.db
+copy_setports ns2/named1.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
diff --git a/bin/tests/system/acl/tests.sh b/bin/tests/system/acl/tests.sh
new file mode 100644
index 0000000..48536da
--- /dev/null
+++ b/bin/tests/system/acl/tests.sh
@@ -0,0 +1,230 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+t=0
+
+echo_i "testing basic ACL processing"
+# key "one" should fail
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; }
+
+
+# any other key should be fine
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; }
+
+copy_setports ns2/named2.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+sleep 5
+
+# prefix 10/8 should fail
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; }
+
+# any other address should work, as long as it sends key "one"
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 127.0.0.1 axfr -y two:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; }
+
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 127.0.0.1 axfr -y one:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; }
+
+echo_i "testing nested ACL processing"
+# all combinations of 10.53.0.{1|2} with key {one|two}, should succeed
+copy_setports ns2/named3.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+sleep 5
+
+# should succeed
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.2 axfr -y two:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; }
+
+# should succeed
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.2 axfr -y one:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; }
+
+# should succeed
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; }
+
+# should succeed
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; }
+
+# but only one or the other should fail
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 127.0.0.1 axfr -y one:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; }
+
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.2 axfr > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $tt failed" ; status=1; }
+
+# and other values? right out
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 127.0.0.1 axfr -y "${DEFAULT_HMAC}:three:1234abcd8765" > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; }
+
+# now we only allow 10.53.0.1 *and* key one, or 10.53.0.2 *and* key two
+copy_setports ns2/named4.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+sleep 5
+
+# should succeed
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.2 axfr -y two:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; }
+
+# should succeed
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; }
+
+# should fail
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.2 axfr -y one:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; }
+
+# should fail
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; }
+
+# should fail
+t=$((t + 1))
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.3 axfr -y one:1234abcd8765 > dig.out.${t}
+grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; }
+
+echo_i "testing allow-query-on ACL processing"
+copy_setports ns2/named5.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+sleep 5
+t=$((t + 1))
+$DIG -p ${PORT} +tcp soa example. \
+ @10.53.0.2 -b 10.53.0.3 > dig.out.${t}
+grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; }
+
+echo_i "testing blackhole ACL processing"
+t=$((t + 1))
+ret=0
+$DIG -p ${PORT} +tcp soa example. \
+ @10.53.0.2 -b 10.53.0.3 > dig.out.1.${t}
+grep "status: NOERROR" dig.out.1.${t} > /dev/null 2>&1 || ret=1
+$DIG -p ${PORT} +tcp soa example. \
+ @10.53.0.2 -b 10.53.0.8 > dig.out.2.${t} && ret=1
+grep "status: NOERROR" dig.out.2.${t} > /dev/null 2>&1 && ret=1
+grep "communications error" dig.out.2.${t} > /dev/null 2>&1 || ret=1
+$DIG -p ${PORT} soa example. \
+ @10.53.0.2 -b 10.53.0.3 > dig.out.3.${t}
+grep "status: NOERROR" dig.out.3.${t} > /dev/null 2>&1 || ret=1
+$DIG -p ${PORT} soa example. \
+ @10.53.0.2 -b 10.53.0.8 > dig.out.4.${t} && ret=1
+grep "status: NOERROR" dig.out.4.${t} > /dev/null 2>&1 && ret=1
+grep "timed out" dig.out.4.${t} > /dev/null 2>&1 || ret=1
+grep ";; no servers could be reached" dig.out.4.${t} > /dev/null 2>&1 || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+# AXFR tests against ns3
+
+echo_i "testing allow-transfer ACLs against ns3 (no existing zones)"
+
+echo_i "calling addzone example.com on ns3"
+$RNDCCMD 10.53.0.3 addzone 'example.com {type primary; file "example.db"; }; '
+sleep 1
+
+t=$((t + 1))
+ret=0
+echo_i "checking AXFR of example.com from ns3 with ACL allow-transfer { none; }; (${t})"
+$DIG -p ${PORT} @10.53.0.3 example.com axfr > dig.out.${t} 2>&1
+grep "Transfer failed." dig.out.${t} >/dev/null 2>&1 || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+echo_i "calling rndc reconfig"
+rndc_reconfig ns3 10.53.0.3
+
+sleep 1
+
+t=$((t + 1))
+ret=0
+echo_i "re-checking AXFR of example.com from ns3 with ACL allow-transfer { none; }; (${t})"
+$DIG -p ${PORT} @10.53.0.3 example.com axfr > dig.out.${t} 2>&1
+grep "Transfer failed." dig.out.${t} >/dev/null 2>&1 || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+# AXFR tests against ns4
+
+echo_i "testing allow-transfer ACLs against ns4 (1 pre-existing zone)"
+
+echo_i "calling addzone example.com on ns4"
+$RNDCCMD 10.53.0.4 addzone 'example.com {type primary; file "example.db"; }; '
+sleep 1
+
+t=$((t + 1))
+ret=0
+echo_i "checking AXFR of example.com from ns4 with ACL allow-transfer { none; }; (${t})"
+$DIG -p ${PORT} @10.53.0.4 example.com axfr > dig.out.${t} 2>&1
+grep "Transfer failed." dig.out.${t} >/dev/null 2>&1 || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+echo_i "calling rndc reconfig"
+rndc_reconfig ns4 10.53.0.4
+
+sleep 1
+
+t=$((t + 1))
+ret=0
+echo_i "re-checking AXFR of example.com from ns4 with ACL allow-transfer { none; }; (${t})"
+$DIG -p ${PORT} @10.53.0.4 example.com axfr > dig.out.${t} 2>&1
+grep "Transfer failed." dig.out.${t} >/dev/null 2>&1 || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/acl/tests_sh_acl.py b/bin/tests/system/acl/tests_sh_acl.py
new file mode 100644
index 0000000..2c98644
--- /dev/null
+++ b/bin/tests/system/acl/tests_sh_acl.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_acl(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/additional/clean.sh b/bin/tests/system/additional/clean.sh
new file mode 100644
index 0000000..c43c36e
--- /dev/null
+++ b/bin/tests/system/additional/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after tests.
+#
+
+rm -f dig.out.*
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/additional/ns1/mx.db b/bin/tests/system/additional/ns1/mx.db
new file mode 100644
index 0000000..6305e8b
--- /dev/null
+++ b/bin/tests/system/additional/ns1/mx.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ MX 0 mail
+ns1 A 10.53.0.1
+mail A 1.2.3.4
+_25._tcp.mail TLSA 3 0 1 5B30F9602297D558EB719162C225088184FAA32CA45E1ED15DE58A21 D9FCE383
diff --git a/bin/tests/system/additional/ns1/named.args b/bin/tests/system/additional/ns1/named.args
new file mode 100644
index 0000000..45ac93a
--- /dev/null
+++ b/bin/tests/system/additional/ns1/named.args
@@ -0,0 +1,2 @@
+# this server runs named with only one worker thread
+-m record -c named.conf -d 99 -D additional-ns1 -X named.lock -g -n 1 -T maxcachesize=2097152
diff --git a/bin/tests/system/additional/ns1/named1.conf.in b/bin/tests/system/additional/ns1/named1.conf.in
new file mode 100644
index 0000000..d058d1e
--- /dev/null
+++ b/bin/tests/system/additional/ns1/named1.conf.in
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ recursion no;
+ dnssec-validation no;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ notify no;
+ minimal-responses yes;
+};
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "rt.example" {
+ type primary;
+ file "rt.db";
+};
+
+zone "naptr.example" {
+ type primary;
+ file "naptr.db";
+};
+
+zone "rt2.example" {
+ type primary;
+ file "rt2.db";
+};
+
+zone "naptr2.example" {
+ type primary;
+ file "naptr2.db";
+};
+
+zone "nid.example" {
+ type primary;
+ file "nid.db";
+};
diff --git a/bin/tests/system/additional/ns1/named2.conf.in b/bin/tests/system/additional/ns1/named2.conf.in
new file mode 100644
index 0000000..56c6d4b
--- /dev/null
+++ b/bin/tests/system/additional/ns1/named2.conf.in
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ recursion no;
+ dnssec-validation no;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ notify no;
+ minimal-responses no;
+};
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "rt.example" {
+ type primary;
+ file "rt.db";
+};
+
+zone "naptr.example" {
+ type primary;
+ file "naptr.db";
+};
+
+zone "rt2.example" {
+ type primary;
+ file "rt2.db";
+};
+
+zone "naptr2.example" {
+ type primary;
+ file "naptr2.db";
+};
+
+zone "nid.example" {
+ type primary;
+ file "nid.db";
+};
diff --git a/bin/tests/system/additional/ns1/named3.conf.in b/bin/tests/system/additional/ns1/named3.conf.in
new file mode 100644
index 0000000..ad453a3
--- /dev/null
+++ b/bin/tests/system/additional/ns1/named3.conf.in
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ recursion no;
+ dnssec-validation no;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ notify no;
+ minimal-any yes;
+ minimal-responses no-auth;
+};
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "rt.example" {
+ type primary;
+ file "rt.db";
+};
+
+zone "naptr.example" {
+ type primary;
+ file "naptr.db";
+};
+
+zone "rt2.example" {
+ type primary;
+ file "rt2.db";
+};
+
+zone "naptr2.example" {
+ type primary;
+ file "naptr2.db";
+};
+
+zone "nid.example" {
+ type primary;
+ file "nid.db";
+};
diff --git a/bin/tests/system/additional/ns1/named4.conf.in b/bin/tests/system/additional/ns1/named4.conf.in
new file mode 100644
index 0000000..69479b9
--- /dev/null
+++ b/bin/tests/system/additional/ns1/named4.conf.in
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ recursion no;
+ dnssec-validation no;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ notify no;
+ minimal-responses no-auth-recursive;
+};
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "mx.example" {
+ type primary;
+ file "mx.db";
+};
+
+zone "srv.example" {
+ type primary;
+ file "srv.db";
+};
+
+zone "rt.example" {
+ type primary;
+ file "rt.db";
+};
+
+zone "naptr.example" {
+ type primary;
+ file "naptr.db";
+};
+
+zone "rt2.example" {
+ type primary;
+ file "rt2.db";
+};
+
+zone "naptr2.example" {
+ type primary;
+ file "naptr2.db";
+};
+
+zone "nid.example" {
+ type primary;
+ file "nid.db";
+};
diff --git a/bin/tests/system/additional/ns1/naptr.db b/bin/tests/system/additional/ns1/naptr.db
new file mode 100644
index 0000000..51d3c85
--- /dev/null
+++ b/bin/tests/system/additional/ns1/naptr.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ns1 A 10.53.0.1
+
+nap IN NAPTR 50 50 "S" "SIPS+D2T" "" server
+server SRV 0 0 5061 server
+server A 192.168.2.9
+server AAAA 192::9
diff --git a/bin/tests/system/additional/ns1/naptr2.db b/bin/tests/system/additional/ns1/naptr2.db
new file mode 100644
index 0000000..78ca4ad
--- /dev/null
+++ b/bin/tests/system/additional/ns1/naptr2.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ns1 A 10.53.0.1
+
+nap IN NAPTR 50 50 "S" "SIPS+D2T" "" server.hang3a.zone.
+www AAAA 192::99
+www A 192.168.2.99
+www X25 100099
diff --git a/bin/tests/system/additional/ns1/nid.db b/bin/tests/system/additional/ns1/nid.db
new file mode 100644
index 0000000..f76b52e
--- /dev/null
+++ b/bin/tests/system/additional/ns1/nid.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ns1 A 10.53.0.1
+
+ns1 NID 2 0:0:0:0
+ns1 L64 2 0:0:0:0
+ns1 L32 2 0.0.0.0
+nid2 NID 2 0:0:0:1
+nid2 LP 2 ns1
diff --git a/bin/tests/system/additional/ns1/root.db b/bin/tests/system/additional/ns1/root.db
new file mode 100644
index 0000000..94cfdda
--- /dev/null
+++ b/bin/tests/system/additional/ns1/root.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. IN SOA ns2. hostmaster ( 2 8H 2H 4W 1D);
+. NS ns1.rt.example.
+. NS ns2.rt.example.
+ns1.rt.example. A 10.53.0.1
+ns2.rt.example. 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/ns1/rt.db b/bin/tests/system/additional/ns1/rt.db
new file mode 100644
index 0000000..c858f0d
--- /dev/null
+++ b/bin/tests/system/additional/ns1/rt.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ NS ns1.rt2.example.
+ns1 A 10.53.0.1
+
+rt RT 2 www
+www AAAA 192::99
+www A 192.168.2.99
+www X25 100099
diff --git a/bin/tests/system/additional/ns1/rt2.db b/bin/tests/system/additional/ns1/rt2.db
new file mode 100644
index 0000000..b61a198
--- /dev/null
+++ b/bin/tests/system/additional/ns1/rt2.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ns1 A 10.53.0.1
+
+rt RT 2 www.hang3b.zone.
+server SRV 0 0 5061 server
+server A 192.168.2.9
+server AAAA 192::9
diff --git a/bin/tests/system/additional/ns1/srv.db b/bin/tests/system/additional/ns1/srv.db
new file mode 100644
index 0000000..0aee21a
--- /dev/null
+++ b/bin/tests/system/additional/ns1/srv.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ns1 A 10.53.0.1
+_xmpp-client._tcp SRV 1 0 5222 server
+server A 1.2.3.4
+_5222._tcp.server TLSA 3 0 1 5B30F9602297D558EB719162C225088184FAA32CA45E1ED15DE58A21 D9FCE383
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 0000000..ed43ca6
--- /dev/null
+++ b/bin/tests/system/additional/ns2/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ recursion no;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ notify no;
+ minimal-responses yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ 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 0000000..728bdde
--- /dev/null
+++ b/bin/tests/system/additional/ns2/root.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 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/ex.db b/bin/tests/system/additional/ns3/ex.db
new file mode 100644
index 0000000..c893a84
--- /dev/null
+++ b/bin/tests/system/additional/ns3/ex.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ NS ns1.ex2.
+ns1 A 10.53.0.1
diff --git a/bin/tests/system/additional/ns3/ex2.db b/bin/tests/system/additional/ns3/ex2.db
new file mode 100644
index 0000000..f9039cf
--- /dev/null
+++ b/bin/tests/system/additional/ns3/ex2.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+ NS ns1
+ns1 A 10.53.0.1
diff --git a/bin/tests/system/additional/ns3/named.conf.in b/bin/tests/system/additional/ns3/named.conf.in
new file mode 100644
index 0000000..2bd01c9
--- /dev/null
+++ b/bin/tests/system/additional/ns3/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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;
+ dnssec-validation yes;
+ minimal-responses no;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "ex" {
+ type primary;
+ file "ex.db";
+};
+
+zone "ex2" {
+ type primary;
+ file "ex2.db";
+};
diff --git a/bin/tests/system/additional/ns3/root.hint b/bin/tests/system/additional/ns3/root.hint
new file mode 100644
index 0000000..ef6ee6f
--- /dev/null
+++ b/bin/tests/system/additional/ns3/root.hint
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS ns2.
+ns2. A 10.53.0.2
diff --git a/bin/tests/system/additional/setup.sh b/bin/tests/system/additional/setup.sh
new file mode 100644
index 0000000..2cbc08d
--- /dev/null
+++ b/bin/tests/system/additional/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$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/additional/tests.sh b/bin/tests/system/additional/tests.sh
new file mode 100644
index 0000000..a50004c
--- /dev/null
+++ b/bin/tests/system/additional/tests.sh
@@ -0,0 +1,379 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+dotests() {
+ n=$((n + 1))
+ echo_i "test with RT, single zone (+rec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +rec -t RT rt.rt.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with RT, two zones (+rec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +rec -t RT rt.rt2.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with NAPTR, single zone (+rec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +rec -t NAPTR nap.naptr.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with NAPTR, two zones (+rec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +rec -t NAPTR nap.hang3b.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with LP (+rec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +rec -t LP nid2.nid.example @10.53.0.1 > dig.out.$n || ret=1
+ case $minimal in
+ no)
+ grep -w "NS" dig.out.$n > /dev/null || ret=1
+ grep -w "L64" dig.out.$n > /dev/null || ret=1
+ grep -w "L32" dig.out.$n > /dev/null || ret=1
+ ;;
+ yes)
+ grep -w "NS" dig.out.$n > /dev/null && ret=1
+ grep -w "L64" dig.out.$n > /dev/null && ret=1
+ grep -w "L32" dig.out.$n > /dev/null && ret=1
+ ;;
+ no-auth)
+ grep -w "NS" dig.out.$n > /dev/null && ret=1
+ grep -w "L64" dig.out.$n > /dev/null || ret=1
+ grep -w "L32" dig.out.$n > /dev/null || ret=1
+ ;;
+ no-auth-recursive)
+ grep -w "NS" dig.out.$n > /dev/null && ret=1
+ grep -w "L64" dig.out.$n > /dev/null || ret=1
+ grep -w "L32" dig.out.$n > /dev/null || ret=1
+ ;;
+ esac
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with NID (+rec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +rec -t NID ns1.nid.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $minimal = no ] ; then
+ # change && to || when we support NID additional processing
+ grep -w "L64" dig.out.$n > /dev/null && ret=1
+ grep -w "L32" dig.out.$n > /dev/null && ret=1
+ else
+ grep -w "L64" dig.out.$n > /dev/null && ret=1
+ grep -w "L32" dig.out.$n > /dev/null && ret=1
+ fi
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with NID + LP (+rec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +rec -t NID nid2.nid.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $minimal = no ] ; then
+ # change && to || when we support NID additional processing
+ grep -w "LP" dig.out.$n > /dev/null && ret=1
+ grep -w "L64" dig.out.$n > /dev/null && ret=1
+ grep -w "L32" dig.out.$n > /dev/null && ret=1
+ else
+ grep -w "LP" dig.out.$n > /dev/null && ret=1
+ grep -w "L64" dig.out.$n > /dev/null && ret=1
+ grep -w "L32" dig.out.$n > /dev/null && ret=1
+ fi
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with RT, single zone (+norec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +norec -t RT rt.rt.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with RT, two zones (+norec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +norec -t RT rt.rt2.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with NAPTR, single zone (+norec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +norec -t NAPTR nap.naptr.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with NAPTR, two zones (+norec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +norec -t NAPTR nap.hang3b.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with LP (+norec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +norec -t LP nid2.nid.example @10.53.0.1 > dig.out.$n || ret=1
+ case $minimal in
+ no)
+ grep -w "NS" dig.out.$n > /dev/null || ret=1
+ grep -w "L64" dig.out.$n > /dev/null || ret=1
+ grep -w "L32" dig.out.$n > /dev/null || ret=1
+ ;;
+ yes)
+ grep -w "NS" dig.out.$n > /dev/null && ret=1
+ grep -w "L64" dig.out.$n > /dev/null && ret=1
+ grep -w "L32" dig.out.$n > /dev/null && ret=1
+ ;;
+ no-auth)
+ grep -w "NS" dig.out.$n > /dev/null && ret=1
+ grep -w "L64" dig.out.$n > /dev/null || ret=1
+ grep -w "L32" dig.out.$n > /dev/null || ret=1
+ ;;
+ no-auth-recursive)
+ grep -w "NS" dig.out.$n > /dev/null || ret=1
+ grep -w "L64" dig.out.$n > /dev/null || ret=1
+ grep -w "L32" dig.out.$n > /dev/null || ret=1
+ ;;
+ esac
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with NID (+norec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +norec -t NID ns1.nid.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $minimal = no ] ; then
+ # change && to || when we support NID additional processing
+ grep -w "L64" dig.out.$n > /dev/null && ret=1
+ grep -w "L32" dig.out.$n > /dev/null && ret=1
+ else
+ grep -w "L64" dig.out.$n > /dev/null && ret=1
+ grep -w "L32" dig.out.$n > /dev/null && ret=1
+ fi
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with NID + LP (+norec) ($n)"
+ ret=0
+ $DIG $DIGOPTS +norec -t NID nid2.nid.example @10.53.0.1 > dig.out.$n || ret=1
+ if [ $minimal = no ] ; then
+ # change && to || when we support NID additional processing
+ grep -w "LP" dig.out.$n > /dev/null && ret=1
+ grep -w "L64" dig.out.$n > /dev/null && ret=1
+ grep -w "L32" dig.out.$n > /dev/null && ret=1
+ else
+ grep -w "LP" dig.out.$n > /dev/null && ret=1
+ grep -w "L64" dig.out.$n > /dev/null && ret=1
+ grep -w "L32" dig.out.$n > /dev/null && ret=1
+ fi
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with NS, root zone ($n)"
+ ret=0
+ $DIG $DIGOPTS -t NS . @10.53.0.1 > dig.out.$n || ret=1
+ # Always expect glue for root priming queries, regardless $minimal
+ grep 'ADDITIONAL: 3' dig.out.$n > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+
+ n=$((n + 1))
+ echo_i "test with NS, non-root zone ($n)"
+ ret=0
+ $DIG $DIGOPTS -t NS rt.example @10.53.0.1 > dig.out.$n || ret=1
+ case $minimal in
+ yes)
+ grep 'ADDITIONAL: 2' dig.out.$n > /dev/null || ret=1
+ ;;
+ no)
+ grep 'ADDITIONAL: 2' dig.out.$n > /dev/null || ret=1
+ ;;
+ no-auth)
+ grep 'ADDITIONAL: 2' dig.out.$n > /dev/null || ret=1
+ ;;
+ no-auth-recursive)
+ grep 'ADDITIONAL: 2' dig.out.$n > /dev/null || ret=1
+ ;;
+ esac
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+ fi
+}
+
+echo_i "testing with 'minimal-responses yes;'"
+minimal=yes
+dotests
+
+echo_i "reconfiguring server: minimal-responses no"
+copy_setports ns1/named2.conf.in ns1/named.conf
+rndc_reconfig ns1 10.53.0.1
+
+echo_i "testing with 'minimal-responses no;'"
+minimal=no
+dotests
+
+n=$((n + 1))
+echo_i "testing with 'minimal-any no;' ($n)"
+ret=0
+$DIG $DIGOPTS -t ANY www.rt.example @10.53.0.1 > dig.out.$n || ret=1
+grep "ANSWER: 3, AUTHORITY: 2, ADDITIONAL: 2" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+fi
+
+echo_i "reconfiguring server: minimal-any yes"
+copy_setports ns1/named3.conf.in ns1/named.conf
+rndc_reconfig ns1 10.53.0.1
+
+n=$((n + 1))
+echo_i "testing with 'minimal-any yes;' over UDP ($n)"
+ret=0
+$DIG $DIGOPTS -t ANY +notcp www.rt.example @10.53.0.1 > dig.out.$n || ret=1
+grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+fi
+n=$((n + 1))
+
+echo_i "testing with 'minimal-any yes;' over TCP ($n)"
+ret=0
+$DIG $DIGOPTS -t ANY +tcp www.rt.example @10.53.0.1 > dig.out.$n || ret=1
+grep "ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+fi
+
+n=$((n + 1))
+echo_i "testing with 'minimal-any yes;' over UDP ($n)"
+ret=0
+$DIG $DIGOPTS -t ANY +notcp www.rt.example @10.53.0.1 > dig.out.$n || ret=1
+grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+fi
+
+echo_i "testing with 'minimal-responses no-auth;'"
+minimal=no-auth
+dotests
+
+echo_i "reconfiguring server: minimal-responses no-auth-recursive"
+copy_setports ns1/named4.conf.in ns1/named.conf
+rndc_reconfig ns1 10.53.0.1
+
+echo_i "testing with 'minimal-responses no-auth-recursive;'"
+minimal=no-auth-recursive
+dotests
+
+n=$((n + 1))
+echo_i "testing returning TLSA records with MX query ($n)"
+ret=0
+$DIG $DIGOPTS -t mx mx.example @10.53.0.1 > dig.out.$n || ret=1
+grep "mx\.example\..*MX.0 mail\.mx\.example" dig.out.$n > /dev/null || ret=1
+grep "mail\.mx\.example\..*A.1\.2\.3\.4" dig.out.$n > /dev/null || ret=1
+grep "_25\._tcp\.mail\.mx\.example\..*TLSA.3 0 1 5B30F9602297D558EB719162C225088184FAA32CA45E1ED15DE58A21 D9FCE383" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+fi
+
+n=$((n + 1))
+echo_i "testing returning TLSA records with SRV query ($n)"
+ret=0
+$DIG $DIGOPTS -t srv _xmpp-client._tcp.srv.example @10.53.0.1 > dig.out.$n || ret=1
+grep "_xmpp-client\._tcp\.srv\.example\..*SRV.1 0 5222 server\.srv\.example" dig.out.$n > /dev/null || ret=1
+grep "server\.srv\.example\..*A.1\.2\.3\.4" dig.out.$n > /dev/null || ret=1
+grep "_5222\._tcp\.server\.srv\.example\..*TLSA.3 0 1 5B30F9602297D558EB719162C225088184FAA32CA45E1ED15DE58A21 D9FCE383" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+fi
+
+echo_i "reconfiguring server: minimal-responses no"
+copy_setports ns1/named2.conf.in ns1/named.conf
+rndc_reconfig ns1 10.53.0.1
+
+n=$((n + 1))
+echo_i "testing NS handling in ANY responses (authoritative) ($n)"
+ret=0
+$DIG $DIGOPTS -t ANY rt.example @10.53.0.1 > dig.out.$n || ret=1
+grep "AUTHORITY: 0" dig.out.$n > /dev/null || ret=1
+grep "NS[ ]*ns" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+fi
+
+n=$((n + 1))
+echo_i "testing NS handling in ANY responses (recursive) ($n)"
+ret=0
+$DIG $DIGOPTS -t ANY rt.example @10.53.0.3 > dig.out.$n || ret=1
+grep "AUTHORITY: 0" dig.out.$n > /dev/null || ret=1
+grep "NS[ ]*ns" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+fi
+
+n=$((n + 1))
+echo_i "testing out-of-zone additional data from auth zones (authoritative) ($n)"
+ret=0
+$DIG $DIGOPTS -t NS rt.example @10.53.0.1 > dig.out.$n || ret=1
+grep "ADDITIONAL: 2" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+fi
+
+n=$((n + 1))
+echo_i "testing out-of-zone additional data from auth zones (recursive) ($n)"
+ret=0
+$DIG $DIGOPTS -t NS ex @10.53.0.3 > dig.out.$n || ret=1
+grep "ADDITIONAL: 3" dig.out.$n > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=$((status+1))
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/additional/tests_sh_additional.py b/bin/tests/system/additional/tests_sh_additional.py
new file mode 100644
index 0000000..cdc38f4
--- /dev/null
+++ b/bin/tests/system/additional/tests_sh_additional.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_additional(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/addzone/clean.sh b/bin/tests/system/addzone/clean.sh
new file mode 100644
index 0000000..5e94b5c
--- /dev/null
+++ b/bin/tests/system/addzone/clean.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ./dig.out.*
+rm -f ./rndc.out*
+rm -f ./showzone.out*
+rm -f ./zonestatus.out*
+rm -f ./*/named.conf
+rm -f ./*/named.memstats
+rm -f ./ns1/*.nzf ./ns1/*.nzf~
+rm -f ./ns1/*.nzd ./ns1/*.nzd-lock
+rm -f ./ns2/*.nzf ./ns2/*.nzf~
+rm -f ./ns2/*.nzd ./ns2/*.nzd-lock
+rm -f ./ns3/*.nzf ./ns3/*.nzf~
+rm -f ./ns3/*.nzd ./ns3/*.nzd-lock
+rm -f ./ns2/core*
+rm -f ./ns2/inline.db.jbk
+rm -f ./ns2/inline.db.signed
+rm -f ./ns2/inlinesec.bk*
+rm -rf ./ns2/new-zones
+rm -f ./ns*/named.lock
+rm -f ./ns*/named.run ./ns*/named.run.prev
+rm -f ./ns2/nzf-*
+rm -f ./ns3/named.conf
+rm -f ./ns3/*.nzf ./ns3/*.nzf~
+rm -f ./ns3/*.nzd ns3/*.nzd-lock
+rm -f ./ns3/inlinesec.db
+rm -f ./ns1/redirect.db
+rm -f ./ns2/redirect.db
+rm -f ./ns2/redirect.bk
+rm -f ./ns3/redirect.db
+rm -f ./ns*/managed-keys.bind* ns*/*.mkeys*
+rm -f ./nzd2nzf.out.*
+rm -f ./wait_for_message.*
diff --git a/bin/tests/system/addzone/ns1/inlinesec.db b/bin/tests/system/addzone/ns1/inlinesec.db
new file mode 100644
index 0000000..eb9d042
--- /dev/null
+++ b/bin/tests/system/addzone/ns1/inlinesec.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN inlinesec.example.
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ MX 10 mail
+
+a A 10.0.0.1
+mail A 10.0.0.2
diff --git a/bin/tests/system/addzone/ns1/named.conf.in b/bin/tests/system/addzone/ns1/named.conf.in
new file mode 100644
index 0000000..9015e1b
--- /dev/null
+++ b/bin/tests/system/addzone/ns1/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ allow-query { any; };
+ allow-new-zones yes;
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "inlinesec.example" {
+ type primary;
+ file "inlinesec.db";
+};
+
+zone "." {
+ type redirect;
+ file "redirect.db";
+};
diff --git a/bin/tests/system/addzone/ns1/redirect.db.1 b/bin/tests/system/addzone/ns1/redirect.db.1
new file mode 100644
index 0000000..5dcdd1b
--- /dev/null
+++ b/bin/tests/system/addzone/ns1/redirect.db.1
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 0 0 0 0 0
+@ 0 NS .
diff --git a/bin/tests/system/addzone/ns1/redirect.db.2 b/bin/tests/system/addzone/ns1/redirect.db.2
new file mode 100644
index 0000000..4dcbdbc
--- /dev/null
+++ b/bin/tests/system/addzone/ns1/redirect.db.2
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 1 0 0 0 0
+@ 0 NS .
diff --git a/bin/tests/system/addzone/ns2/added.db b/bin/tests/system/addzone/ns2/added.db
new file mode 100644
index 0000000..286e717
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/added.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+;$ORIGIN added.example.
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ MX 10 mail
+
+a A 10.0.0.1
+mail A 10.0.0.2
diff --git a/bin/tests/system/addzone/ns2/default.nzf.in b/bin/tests/system/addzone/ns2/default.nzf.in
new file mode 100644
index 0000000..d9740f5
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/default.nzf.in
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone previous.example { type primary; file "previous.db"; };
diff --git a/bin/tests/system/addzone/ns2/hints.db b/bin/tests/system/addzone/ns2/hints.db
new file mode 100644
index 0000000..e0f186c
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/hints.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.1
diff --git a/bin/tests/system/addzone/ns2/inline.db b/bin/tests/system/addzone/ns2/inline.db
new file mode 100644
index 0000000..c968104
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/inline.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN inline.example.
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ MX 10 mail
+
+a A 10.0.0.1
+mail A 10.0.0.2
diff --git a/bin/tests/system/addzone/ns2/named1.conf.in b/bin/tests/system/addzone/ns2/named1.conf.in
new file mode 100644
index 0000000..23be60e
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/named1.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ allow-query { any; };
+ recursion no;
+ allow-new-zones yes;
+ dnssec-validation no;
+};
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "normal.db";
+};
+
+zone "finaldot.example." {
+ type primary;
+ file "normal.db";
+};
diff --git a/bin/tests/system/addzone/ns2/named2.conf.in b/bin/tests/system/addzone/ns2/named2.conf.in
new file mode 100644
index 0000000..8b0f23d
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/named2.conf.in
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+view internal {
+ match-clients { 10.53.0.2; };
+ allow-new-zones no;
+ recursion yes;
+
+ response-policy { zone "policy"; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "policy" {
+ type primary;
+ file "normal.db";
+ };
+};
+
+view external {
+ match-clients { any; };
+ allow-new-zones yes;
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+};
+
+# This view is only here to test that configuration context is cleaned
+# up correctly when using multiple named ACLs (regression test for RT #22739)
+acl match { none; };
+acl nobody { none; };
+view extra {
+ match-clients { match; };
+ allow-new-zones yes;
+ allow-transfer { nobody; };
+ allow-query { nobody; };
+ allow-recursion { nobody; };
+};
diff --git a/bin/tests/system/addzone/ns2/named3.conf.in b/bin/tests/system/addzone/ns2/named3.conf.in
new file mode 100644
index 0000000..7078ce9
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/named3.conf.in
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; 10.53.0.4; 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion no;
+ new-zones-directory "new-zones";
+ dnssec-validation no;
+};
+
+view internal {
+ match-clients { 10.53.0.2; };
+ allow-new-zones no;
+ recursion yes;
+
+ response-policy { zone "policy"; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "policy" {
+ type primary;
+ file "normal.db";
+ };
+};
+
+view directory {
+ match-clients { 10.53.0.5; };
+ allow-new-zones yes;
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+};
+
+view external {
+ match-clients { any; };
+ allow-new-zones yes;
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+};
+
+# This view is only here to test that configuration context is cleaned
+# up correctly when using multiple named ACLs (regression test for RT #22739)
+acl match { none; };
+acl nobody { none; };
+view extra {
+ match-clients { match; };
+ allow-new-zones yes;
+ allow-transfer { nobody; };
+ allow-query { nobody; };
+ allow-recursion { nobody; };
+};
diff --git a/bin/tests/system/addzone/ns2/normal.db b/bin/tests/system/addzone/ns2/normal.db
new file mode 100644
index 0000000..fa05638
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/normal.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN normal.example.
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ MX 10 mail
+
+a A 10.0.0.1
+mail A 10.0.0.2
diff --git a/bin/tests/system/addzone/ns2/previous.db b/bin/tests/system/addzone/ns2/previous.db
new file mode 100644
index 0000000..6d2e495
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/previous.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN previous.example.
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ MX 10 mail
+
+a A 10.0.0.1
+mail A 10.0.0.2
diff --git a/bin/tests/system/addzone/ns2/redirect.db.1 b/bin/tests/system/addzone/ns2/redirect.db.1
new file mode 100644
index 0000000..5dcdd1b
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/redirect.db.1
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 0 0 0 0 0
+@ 0 NS .
diff --git a/bin/tests/system/addzone/ns2/redirect.db.2 b/bin/tests/system/addzone/ns2/redirect.db.2
new file mode 100644
index 0000000..4dcbdbc
--- /dev/null
+++ b/bin/tests/system/addzone/ns2/redirect.db.2
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 1 0 0 0 0
+@ 0 NS .
diff --git a/bin/tests/system/addzone/ns3/e.db b/bin/tests/system/addzone/ns3/e.db
new file mode 100644
index 0000000..7f74f0a
--- /dev/null
+++ b/bin/tests/system/addzone/ns3/e.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA ns3 hostmaster 0 0 0 0 0
+@ NS ns3
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/addzone/ns3/example.db b/bin/tests/system/addzone/ns3/example.db
new file mode 100644
index 0000000..2bf4f8d
--- /dev/null
+++ b/bin/tests/system/addzone/ns3/example.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ IN SOA localhost. localhost.localhost. 1 10800 3600 605800 86400
+@ IN NS localhost.
diff --git a/bin/tests/system/addzone/ns3/named1.conf.in b/bin/tests/system/addzone/ns3/named1.conf.in
new file mode 100644
index 0000000..6c512a6
--- /dev/null
+++ b/bin/tests/system/addzone/ns3/named1.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ allow-query { any; };
+ recursion no;
+ allow-new-zones yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "redirect.db";
+};
+
+primaries "test" {
+ 192.5.5.241;
+};
diff --git a/bin/tests/system/addzone/ns3/named2.conf.in b/bin/tests/system/addzone/ns3/named2.conf.in
new file mode 100644
index 0000000..6ca25f1
--- /dev/null
+++ b/bin/tests/system/addzone/ns3/named2.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ allow-query { any; };
+ recursion no;
+ allow-new-zones yes;
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/addzone/ns3/redirect.db.1 b/bin/tests/system/addzone/ns3/redirect.db.1
new file mode 100644
index 0000000..60a2622
--- /dev/null
+++ b/bin/tests/system/addzone/ns3/redirect.db.1
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 0 0 0 0 0
+@ 0 NS .
+@ 0 A 127.0.0.1
diff --git a/bin/tests/system/addzone/ns3/redirect.db.2 b/bin/tests/system/addzone/ns3/redirect.db.2
new file mode 100644
index 0000000..3804fef
--- /dev/null
+++ b/bin/tests/system/addzone/ns3/redirect.db.2
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 1 0 0 0 0
+@ 0 NS .
+@ 0 A 127.0.0.1
diff --git a/bin/tests/system/addzone/setup.sh b/bin/tests/system/addzone/setup.sh
new file mode 100644
index 0000000..b2227c1
--- /dev/null
+++ b/bin/tests/system/addzone/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+cp -f ns1/redirect.db.1 ns1/redirect.db
+cp -f ns2/redirect.db.1 ns2/redirect.db
+cp -f ns3/redirect.db.1 ns3/redirect.db
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named1.conf.in ns2/named.conf
+copy_setports ns3/named1.conf.in ns3/named.conf
+
+cp -f ns2/default.nzf.in ns2/3bf305731dd26307.nzf
+mkdir ns2/new-zones
diff --git a/bin/tests/system/addzone/tests.sh b/bin/tests/system/addzone/tests.sh
new file mode 100755
index 0000000..2937e79
--- /dev/null
+++ b/bin/tests/system/addzone/tests.sh
@@ -0,0 +1,756 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +nosea +nostat +nocmd +norec +noques +noauth +noadd +nostats +dnssec -p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+check_zonestatus() (
+ $RNDCCMD "10.53.0.$1" zonestatus -redirect > "zonestatus.out.ns$1.$n" &&
+ grep "type: redirect" "zonestatus.out.ns$1.$n" > /dev/null &&
+ grep "serial: 1" "zonestatus.out.ns$1.$n" > /dev/null
+)
+
+status=0
+n=0
+
+echo_i "checking normally loaded zone ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# When LMDB support is compiled in, this tests that migration from
+# NZF to NZD occurs during named startup
+echo_i "checking previously added zone ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 a.previous.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.previous.example' dig.out.ns2.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if $FEATURETEST --with-lmdb; then
+ echo_i "checking that existing NZF file was renamed after migration ($n)"
+ [ -e ns2/3bf305731dd26307.nzf~ ] || ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+echo_i "adding new zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'added.example { type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /'
+_check_adding_new_zone () (
+ $DIG $DIGOPTS @10.53.0.2 a.added.example a > dig.out.ns2.$n &&
+ grep 'status: NOERROR' dig.out.ns2.$n > /dev/null &&
+ grep '^a.added.example' dig.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_adding_new_zone || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+nextpart ns2/named.run >/dev/null
+echo_i "checking addzone errors are logged correctly"
+ret=0
+$RNDCCMD 10.53.0.2 addzone bad.example '{ type mister; };' 2>&1 | grep 'unexpected token' > /dev/null 2>&1 || ret=1
+wait_for_log_peek 20 "addzone: 'mister' unexpected" ns2/named.run || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+nextpart ns2/named.run >/dev/null
+echo_i "checking modzone errors are logged correctly"
+ret=0
+$RNDCCMD 10.53.0.2 modzone added.example '{ type mister; };' 2>&1 | grep 'unexpected token' > /dev/null 2>&1 || ret=1
+wait_for_log_peek 20 "modzone: 'mister' unexpected" ns2/named.run || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "adding a zone that requires quotes ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone '"32/1.0.0.127-in-addr.added.example" {
+check-names ignore; type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /'
+_check_zone_that_requires_quotes() (
+ $DIG $DIGOPTS @10.53.0.2 "a.32/1.0.0.127-in-addr.added.example" a > dig.out.ns2.$n &&
+ grep 'status: NOERROR' dig.out.ns2.$n > /dev/null &&
+ grep '^a.32/1.0.0.127-in-addr.added.example' dig.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_zone_that_requires_quotes || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "adding a zone with a quote in the name ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone '"foo\"bar.example" { check-names ignore; type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /'
+_check_zone_with_a_quote() (
+ $DIG $DIGOPTS @10.53.0.2 "a.foo\"bar.example" a > dig.out.ns2.$n &&
+ grep 'status: NOERROR' dig.out.ns2.$n > /dev/null &&
+ grep '^a.foo\\"bar.example' dig.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_zone_with_a_quote || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "adding new zone with missing file ($n)"
+ret=0
+$DIG $DIGOPTS +all @10.53.0.2 a.missing.example a > dig.out.ns2.pre.$n || ret=1
+grep "status: REFUSED" dig.out.ns2.pre.$n > /dev/null || ret=1
+$RNDCCMD 10.53.0.2 addzone 'missing.example { type primary; file "missing.db"; };' 2> rndc.out.ns2.$n && ret=1
+grep "file not found" rndc.out.ns2.$n > /dev/null || ret=1
+$DIG $DIGOPTS +all @10.53.0.2 a.missing.example a > dig.out.ns2.post.$n || ret=1
+grep "status: REFUSED" dig.out.ns2.post.$n > /dev/null || ret=1
+digcomp dig.out.ns2.pre.$n dig.out.ns2.post.$n || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if ! $FEATURETEST --with-lmdb; then
+ echo_i "verifying no comments in NZF file ($n)"
+ ret=0
+ hcount=$(grep "^# New zone file for view: _default" ns2/3bf305731dd26307.nzf | wc -l)
+ [ $hcount -eq 0 ] || ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+echo_i "checking rndc showzone with previously added zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 showzone previous.example > rndc.out.ns2.$n
+expected='zone "previous.example" { type primary; file "previous.db"; };'
+[ "$(cat rndc.out.ns2.$n)" = "$expected" ] || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if $FEATURETEST --with-lmdb; then
+ echo_i "checking zone is present in NZD ($n)"
+ ret=0
+ $NZD2NZF ns2/_default.nzd | grep previous.example > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+echo_i "deleting previously added zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 delzone previous.example 2>&1 | sed 's/^/I:ns2 /'
+_check_deleting_previously_added_zone() (
+ $DIG $DIGOPTS @10.53.0.2 a.previous.example a > dig.out.ns2.$n &&
+ grep 'status: REFUSED' dig.out.ns2.$n > /dev/null &&
+ ! grep '^a.previous.example' dig.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_deleting_previously_added_zone || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+check_nzd2nzf() (
+ $NZD2NZF ns2/_default.nzd > nzd2nzf.out.$n &&
+ ! grep previous.example nzd2nzf.out.$n > /dev/null
+)
+
+if $FEATURETEST --with-lmdb; then
+ echo_i "checking zone was deleted from NZD ($n)"
+ retry_quiet 10 check_nzd2nzf || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+if ! $FEATURETEST --with-lmdb; then
+ echo_i "checking NZF file now has comment ($n)"
+ ret=0
+ hcount=$(grep "^# New zone file for view: _default" ns2/3bf305731dd26307.nzf | wc -l)
+ [ $hcount -eq 1 ] || ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+echo_i "deleting newly added zone added.example ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 delzone added.example 2>&1 | sed 's/^/I:ns2 /'
+_check_deleting_newly_added_zone() (
+ $DIG $DIGOPTS @10.53.0.2 a.added.example a > dig.out.ns2.$n &&
+ grep 'status: REFUSED' dig.out.ns2.$n > /dev/null &&
+ ! grep '^a.added.example' dig.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_deleting_newly_added_zone || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "deleting newly added zone with escaped quote ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 delzone "foo\\\"bar.example" 2>&1 | sed 's/^/I:ns2 /'
+_check_deleting_newly_added_zone_quote() (
+ $DIG $DIGOPTS @10.53.0.2 "a.foo\"bar.example" a > dig.out.ns2.$n &&
+ grep 'status: REFUSED' dig.out.ns2.$n > /dev/null &&
+ ! grep "^a.foo\"bar.example" dig.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_deleting_newly_added_zone_quote || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking rndc showzone with a normally-loaded zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 showzone normal.example > rndc.out.ns2.$n
+expected='zone "normal.example" { type primary; file "normal.db"; };'
+[ "$(cat rndc.out.ns2.$n)" = "$expected" ] || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking rndc showzone with a normally-loaded zone with trailing dot ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 showzone finaldot.example > rndc.out.ns2.$n
+expected='zone "finaldot.example." { type primary; file "normal.db"; };'
+[ "$(cat rndc.out.ns2.$n)" = "$expected" ] || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking rndc showzone with a normally-loaded redirect zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 showzone -redirect > rndc.out.ns1.$n
+expected='zone "." { type redirect; file "redirect.db"; };'
+[ "$(cat rndc.out.ns1.$n)" = "$expected" ] || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking rndc zonestatus with a normally-loaded redirect zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 zonestatus -redirect > rndc.out.ns1.$n
+grep "type: redirect" rndc.out.ns1.$n > /dev/null || ret=1
+grep "serial: 0" rndc.out.ns1.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking rndc reload with a normally-loaded redirect zone ($n)"
+ret=0
+sleep 1
+cp -f ns1/redirect.db.2 ns1/redirect.db
+$RNDCCMD 10.53.0.1 reload -redirect > rndc.out.ns1.$n
+retry_quiet 5 check_zonestatus 1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "delete a normally-loaded zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 delzone normal.example > rndc.out.ns2.$n 2>&1
+grep "is no longer active and will be deleted" rndc.out.ns2.$n > /dev/null || ret=11
+grep "To keep it from returning when the server is restarted" rndc.out.ns2.$n > /dev/null || ret=1
+grep "must also be removed from named.conf." rndc.out.ns2.$n > /dev/null || ret=1
+_check_delete_normally_loaded_zone() (
+ $DIG $DIGOPTS @10.53.0.2 a.normal.example a > dig.out.ns2.$n &&
+ grep 'status: REFUSED' dig.out.ns2.$n > /dev/null
+)
+retry_quiet 5 _check_delete_normally_loaded_zone || ret=1
+
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "attempting to add primary zone with inline signing ($n)"
+$RNDCCMD 10.53.0.2 addzone 'inline.example { type primary; file "inline.db"; inline-signing yes; };' 2>&1 | sed 's/^/I:ns2 /'
+_check_add_primary_zone_with_inline() (
+ $DIG $DIGOPTS @10.53.0.2 a.inline.example a > dig.out.ns2.$n &&
+ grep 'status: NOERROR' dig.out.ns2.$n > /dev/null &&
+ grep '^a.inline.example' dig.out.ns2.$n > /dev/null
+)
+retry_quiet 5 _check_add_primary_zone_with_inline || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "attempting to add primary zone with inline signing and missing file ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'inlinemissing.example { type primary; file "missing.db"; inline-signing yes; };' 2> rndc.out.ns2.$n && ret=1
+grep "file not found" rndc.out.ns2.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "attempting to add secondary zone with inline signing ($n)"
+$RNDCCMD 10.53.0.2 addzone 'inlinesec.example { type secondary; primaries { 10.53.0.1; }; file "inlinesec.bk"; inline-signing yes; };' 2>&1 | sed 's/^/I:ns2 /'
+_check_add_secondary_with_inline() (
+ $DIG $DIGOPTS @10.53.0.2 a.inlinesec.example a > dig.out.ns2.$n &&
+ grep 'status: NOERROR' dig.out.ns2.$n > /dev/null &&
+ grep '^a.inlinesec.example' dig.out.ns2.$n > /dev/null
+)
+retry_quiet 5 _check_add_secondary_with_inline || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "attempting to delete secondary zone with inline signing ($n)"
+ret=0
+retry_quiet 10 test -f ns2/inlinesec.bk.signed -a -f ns2/inlinesec.bk || ret=1
+$RNDCCMD 10.53.0.2 delzone inlinesec.example > rndc.out2.test$n 2>&1 || ret=1
+test -f inlinesec.bk ||
+grep '^inlinesec.bk$' rndc.out2.test$n > /dev/null || {
+ echo_i "failed to report inlinesec.bk"; ret=1;
+}
+test ! -f inlinesec.bk.signed ||
+grep '^inlinesec.bk.signed$' rndc.out2.test$n > /dev/null || {
+ echo_i "failed to report inlinesec.bk.signed"; ret=1;
+}
+n=$((n + 1))
+status=$((status + ret))
+
+echo_i "restoring secondary zone with inline signing ($n)"
+$RNDCCMD 10.53.0.2 addzone 'inlinesec.example { type secondary; primaries { 10.53.0.1; }; file "inlinesec.bk"; inline-signing yes; };' 2>&1 | sed 's/^/I:ns2 /'
+_check_restoring_secondary_with_inline() (
+ $DIG $DIGOPTS @10.53.0.2 a.inlinesec.example a > dig.out.ns2.$n &&
+ grep 'status: NOERROR' dig.out.ns2.$n > /dev/null &&
+ grep '^a.inlinesec.example' dig.out.ns2.$n > /dev/null
+)
+retry_quiet 5 _check_restoring_secondary_with_inline || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "deleting secondary zone with automatic zone file removal ($n)"
+ret=0
+retry_quiet 10 test -f ns2/inlinesec.bk.signed -a -f ns2/inlinesec.bk || ret=1
+$RNDCCMD 10.53.0.2 delzone -clean inlinesec.example > /dev/null 2>&1
+retry_quiet 10 test ! -f ns2/inlinesec.bk.signed -a ! -f ns2/inlinesec.bk
+n=$((n + 1))
+status=$((status + ret))
+
+echo_i "modifying zone configuration ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'mod.example { type primary; file "added.db"; };' 2>&1 | sed 's/^/ns2 /' | cat_i
+$DIG +norec $DIGOPTS @10.53.0.2 mod.example ns > dig.out.ns2.1.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.1.$n > /dev/null || ret=1
+$RNDCCMD 10.53.0.2 modzone 'mod.example { type primary; file "added.db"; allow-query { none; }; };' 2>&1 | sed 's/^/ns2 /' | cat_i
+$DIG +norec $DIGOPTS @10.53.0.2 mod.example ns > dig.out.ns2.2.$n || ret=1
+$RNDCCMD 10.53.0.2 showzone mod.example | grep 'allow-query { "none"; };' > /dev/null 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that adding a 'stub' zone works ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'stub.example { type stub; primaries { 1.2.3.4; }; file "stub.example.bk"; };' > rndc.out.ns2.$n 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that adding a 'static-stub' zone works ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'static-stub.example { type static-stub; server-addresses { 1.2.3.4; }; };' > rndc.out.ns2.$n 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that adding a 'primary redirect' zone works ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone '"." { type redirect; file "redirect.db"; };' > rndc.out.ns2.$n 2>&1 || ret=1
+_check_add_primary_redirect() (
+ $RNDCCMD 10.53.0.2 showzone -redirect > showzone.out.ns2.$n 2>&1 &&
+ grep "type redirect;" showzone.out.ns2.$n > /dev/null &&
+ $RNDCCMD 10.53.0.2 zonestatus -redirect > zonestatus.out.ns2.$n 2>&1 &&
+ grep "type: redirect" zonestatus.out.ns2.$n > /dev/null &&
+ grep "serial: 0" zonestatus.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_add_primary_redirect || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that reloading a added 'primary redirect' zone works ($n)"
+ret=0
+sleep 1
+cp -f ns2/redirect.db.2 ns2/redirect.db
+$RNDCCMD 10.53.0.2 reload -redirect > rndc.out.ns2.$n
+retry_quiet 10 check_zonestatus 2 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that retransfer of a added 'primary redirect' zone fails ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 retransfer -redirect > rndc.out.ns2.$n 2>&1 && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that deleting a 'primary redirect' zone works ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 delzone -redirect > rndc.out.ns2.$n 2>&1 || ret=1
+_check_deleting_primary_redirect() (
+ $RNDCCMD 10.53.0.2 showzone -redirect > showzone.out.ns2.$n 2>&1 || true
+ grep 'not found' showzone.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_deleting_primary_redirect || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that adding a 'secondary redirect' zone works ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone '"." { type redirect; primaries { 10.53.0.3;}; file "redirect.bk"; };' > rndc.out.ns2.$n 2>&1 || ret=1
+_check_adding_secondary_redirect() (
+ $RNDCCMD 10.53.0.2 showzone -redirect > showzone.out.ns2.$n 2>&1 &&
+ grep "type redirect;" showzone.out.ns2.$n > /dev/null &&
+ $RNDCCMD 10.53.0.2 zonestatus -redirect > zonestatus.out.ns2.$n 2>&1 &&
+ grep "type: redirect" zonestatus.out.ns2.$n > /dev/null &&
+ grep "serial: 0" zonestatus.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_adding_secondary_redirect || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that retransfering a added 'secondary redirect' zone works ($n)"
+ret=0
+cp -f ns3/redirect.db.2 ns3/redirect.db
+$RNDCCMD 10.53.0.3 reload . > showzone.out.ns3.$n 2>&1 || ret=1
+_check_retransfering_secondary_redirect() (
+ $RNDCCMD 10.53.0.2 retransfer -redirect > rndc.out.ns2.$n 2>&1 &&
+ $RNDCCMD 10.53.0.2 zonestatus -redirect > zonestatus.out.ns2.$n 2>&1 &&
+ grep "type: redirect" zonestatus.out.ns2.$n > /dev/null &&
+ grep "serial: 1" zonestatus.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_retransfering_secondary_redirect || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that deleting a 'secondary redirect' zone works ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 delzone -redirect > rndc.out.ns2.$n 2>&1 || ret=1
+_check_deleting_secondary_redirect() (
+ $RNDCCMD 10.53.0.2 showzone -redirect > showzone.out.ns2.$n 2>&1 || true
+ grep 'not found' showzone.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_deleting_secondary_redirect || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that zone type 'hint' is properly rejected ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone '"." { type hint; file "hints.db"; };' > rndc.out.ns2.$n 2>&1 && ret=1
+grep "zones not supported by addzone" rndc.out.ns2.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that zone type 'forward' is properly rejected ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'forward.example { type forward; forwarders { 1.2.3.4; }; forward only; };' > rndc.out.ns2.$n 2>&1 && ret=1
+grep "zones not supported by addzone" rndc.out.ns2.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that zone type 'delegation-only' is properly rejected ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'delegation-only.example { type delegation-only; };' > rndc.out.ns2.$n 2>&1 && ret=1
+grep "zones not supported by addzone" rndc.out.ns2.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'in-view' zones are properly rejected ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'in-view.example { in-view "_default"; };' > rndc.out.ns2.$n 2>&1 && ret=1
+grep "zones not supported by addzone" rndc.out.ns2.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "reconfiguring server with multiple views"
+rm -f ns2/named.conf
+copy_setports ns2/named2.conf.in ns2/named.conf
+rndc_reconfig ns2 10.53.0.2
+
+echo_i "adding new zone to external view ($n)"
+# NOTE: The internal view has "recursion yes" set, and so queries for
+# nonexistent zones should return NOERROR. The external view is
+# "recursion no", so queries for nonexistent zones should return
+# REFUSED. This behavior should be the same regardless of whether
+# the zone does not exist because a) it has not yet been loaded, b)
+# it failed to load, or c) it has been deleted.
+ret=0
+$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.intpre.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.intpre.$n > /dev/null || ret=1
+$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.extpre.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.extpre.$n > /dev/null || ret=1
+$RNDCCMD 10.53.0.2 addzone 'added.example in external { type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /'
+$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.int.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.int.$n > /dev/null || ret=1
+$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.ext.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.ext.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.ext.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if ! $FEATURETEST --with-lmdb; then
+ echo_i "checking new NZF file has comment ($n)"
+ ret=0
+ hcount=$(grep "^# New zone file for view: external" ns2/external.nzf | wc -l)
+ [ $hcount -eq 1 ] || ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+if $FEATURETEST --with-lmdb; then
+ echo_i "verifying added.example in external view created an external.nzd DB ($n)"
+ ret=0
+ [ -e ns2/external.nzd ] || ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+echo_i "checking rndc reload causes named to reload the external view's new zone config ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i
+_check_rndc_reload_external_view_config() (
+ $DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.int.$n &&
+ grep 'status: NOERROR' dig.out.ns2.int.$n > /dev/null &&
+ $DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.ext.$n &&
+ grep 'status: NOERROR' dig.out.ns2.ext.$n > /dev/null &&
+ grep '^a.added.example' dig.out.ns2.ext.$n > /dev/null
+)
+retry_quiet 10 _check_rndc_reload_external_view_config || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking rndc showzone with newly added zone ($n)"
+_check_rndc_showzone_newly_added() (
+ if ! $FEATURETEST --with-lmdb; then
+ expected='zone "added.example" in external { type primary; file "added.db"; };'
+ else
+ expected='zone "added.example" { type primary; file "added.db"; };'
+ fi
+ $RNDCCMD 10.53.0.2 showzone added.example in external > rndc.out.ns2.$n 2>/dev/null &&
+ [ "$(cat rndc.out.ns2.$n)" = "$expected" ]
+)
+retry_quiet 10 _check_rndc_showzone_newly_added || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "deleting newly added zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 delzone 'added.example in external' 2>&1 | sed 's/^/I:ns2 /'
+_check_deleting_newly_added_zone() (
+ $DIG $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.$n &&
+ grep 'status: REFUSED' dig.out.ns2.$n > /dev/null &&
+ ! grep '^a.added.example' dig.out.ns2.$n > /dev/null
+)
+retry_quiet 10 _check_deleting_newly_added_zone || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "attempting to add zone to internal view ($n)"
+ret=0
+$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.pre.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.pre.$n > /dev/null || ret=1
+$RNDCCMD 10.53.0.2 addzone 'added.example in internal { type primary; file "added.db"; };' 2> rndc.out.ns2.$n && ret=1
+grep "permission denied" rndc.out.ns2.$n > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.int.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.int.$n > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.ext.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.ext.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "attempting to delete a policy zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 delzone 'policy in internal' 2> rndc.out.ns2.$n >&1 && ret=1
+grep 'cannot be deleted' rndc.out.ns2.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "adding new zone again to external view ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 addzone 'added.example in external { type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /'
+_check_adding_new_zone_again_external() (
+ $DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.int.$n &&
+ grep 'status: NOERROR' dig.out.ns2.int.$n > /dev/null &&
+ $DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.ext.$n &&
+ grep 'status: NOERROR' dig.out.ns2.ext.$n > /dev/null &&
+ grep '^a.added.example' dig.out.ns2.ext.$n > /dev/null
+)
+retry_quiet 10 _check_adding_new_zone_again_external || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "reconfiguring server with multiple views and new-zones-directory"
+rm -f ns2/named.conf
+copy_setports ns2/named3.conf.in ns2/named.conf
+rndc_reconfig ns2 10.53.0.2
+
+echo_i "checking new zone is still loaded after dir change ($n)"
+ret=0
+$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.ext.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.ext.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.ext.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "deleting newly added zone from external ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 delzone 'added.example in external' 2>&1 | sed 's/^/I:ns2 /'
+$DIG $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "adding new zone to directory view ($n)"
+ret=0
+$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.intpre.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.intpre.$n > /dev/null || ret=1
+$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.extpre.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.extpre.$n > /dev/null || ret=1
+$DIG +norec $DIGOPTS @10.53.0.5 -b 10.53.0.5 a.added.example a > dig.out.ns2.dirpre.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.dirpre.$n > /dev/null || ret=1
+$RNDCCMD 10.53.0.2 addzone 'added.example in directory { type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /'
+$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.int.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.int.$n > /dev/null || ret=1
+$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.ext.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.ext.$n > /dev/null || ret=1
+$DIG +norec $DIGOPTS @10.53.0.5 -b 10.53.0.5 a.added.example a > dig.out.ns2.dir.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.dir.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.dir.$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if $FEATURETEST --with-lmdb; then
+ echo_i "checking NZD file was created in new-zones-directory ($n)"
+ expect=ns2/new-zones/directory.nzd
+else
+ echo_i "checking NZF file was created in new-zones-directory ($n)"
+ expect=ns2/new-zones/directory.nzf
+fi
+$RNDCCMD 10.53.0.2 sync 'added.example IN directory' 2>&1 | sed 's/^/I:ns2 /'
+sleep 2
+[ -e "$expect" ] || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "deleting newly added zone from directory ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 delzone 'added.example in directory' 2>&1 | sed 's/^/I:ns2 /'
+$DIG $DIGOPTS @10.53.0.5 -b 10.53.0.5 a.added.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.added.example' dig.out.ns2.$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "ensure the configuration context is cleaned up correctly ($n)"
+ret=0
+rndc_reconfig ns2 10.53.0.2
+$RNDCCMD 10.53.0.2 status > /dev/null 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check delzone after reconfig failure ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 addzone 'inlinesec.example. IN { type secondary; file "inlinesec.db"; masterfile-format text; primaries { test; }; };' > /dev/null 2>&1 || ret=1
+copy_setports ns3/named2.conf.in ns3/named.conf
+rndc_reconfig ns3 10.53.0.3
+$RNDCCMD 10.53.0.3 delzone inlinesec.example > /dev/null 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if ! $FEATURETEST --with-lmdb
+then
+ echo_i "check that addzone is fully reversed on failure (--with-lmdb=no) ($n)"
+ ret=0
+ $RNDCCMD 10.53.0.3 addzone "test1.baz" '{ type primary; file "e.db"; };' > /dev/null 2>&1 || ret=1
+ $RNDCCMD 10.53.0.3 addzone "test2.baz" '{ type primary; file "dne.db"; };' > /dev/null 2>&1 && ret=1
+ $RNDCCMD 10.53.0.3 addzone "test3.baz" '{ type primary; file "e.db"; };' > /dev/null 2>&1 || ret=1
+ $RNDCCMD 10.53.0.3 delzone "test3.baz" > /dev/null 2>&1 || ret=1
+ grep test2.baz ns3/_default.nzf > /dev/null && ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+_check_version_bind() (
+ $DIG $DIGOPTS @10.53.0.3 version.bind txt ch > dig.out.test$n &&
+ grep "status: NOERROR" dig.out.test$n > /dev/null
+)
+
+echo_i "check that named restarts with multiple added zones ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 addzone "test4.baz" '{ type primary; file "e.db"; };' > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.3 addzone "test5.baz" '{ type primary; file "e.db"; };' > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.3 addzone '"test/.baz"' '{ type primary; check-names ignore; file "e.db"; };' > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.3 addzone '"test\".baz"' '{ type primary; check-names ignore; file "e.db"; };' > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.3 addzone '"test\\.baz"' '{ type primary; check-names ignore; file "e.db"; };' > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.3 addzone '"test\032.baz"' '{ type primary; check-names ignore; file "e.db"; };' > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.3 addzone '"test\010.baz"' '{ type primary; check-names ignore; file "e.db"; };' > /dev/null 2>&1 || ret=1
+stop_server ns3
+start_server --noclean --restart --port ${PORT} ns3 || ret=1
+retry_quiet 10 _check_version_bind || ret=1
+$DIG $DIGOPTS @10.53.0.3 SOA "test4.baz" > dig.out.1.test$n || ret=1
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 SOA "test5.baz" > dig.out.2.test$n || ret=1
+grep "status: NOERROR" dig.out.2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.2.test$n > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 SOA 'test/.baz' > dig.out.3.test$n || ret=1
+grep "status: NOERROR" dig.out.3.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.3.test$n > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 SOA 'test\\.baz' > dig.out.4.test$n || ret=1
+grep "status: NOERROR" dig.out.4.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.4.test$n > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 SOA 'test\032.baz' > dig.out.5.test$n || ret=1
+grep "status: NOERROR" dig.out.5.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.5.test$n > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 SOA 'test\010.baz' > dig.out.6.test$n || ret=1
+grep "status: NOERROR" dig.out.6.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.6.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/addzone/tests_rndc_deadlock.py b/bin/tests/system/addzone/tests_rndc_deadlock.py
new file mode 100755
index 0000000..bd21d62
--- /dev/null
+++ b/bin/tests/system/addzone/tests_rndc_deadlock.py
@@ -0,0 +1,92 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import concurrent.futures
+import os
+import subprocess
+import time
+
+
+def run_rndc(server, rndc_command):
+ """
+ Send the specified 'rndc_command' to 'server' with a timeout of 10 seconds
+ """
+ rndc = os.getenv("RNDC")
+ port = os.getenv("CONTROLPORT")
+
+ cmdline = [rndc, "-c", "../common/rndc.conf", "-p", port, "-s", server]
+ cmdline.extend(rndc_command)
+
+ subprocess.check_output(cmdline, stderr=subprocess.STDOUT, timeout=10)
+
+
+def rndc_loop(test_state, domain):
+ """
+ Run "rndc addzone", "rndc modzone", and "rndc delzone" in a tight loop
+ until the test is considered finished, ignoring errors
+ """
+ rndc_commands = [
+ ["addzone", domain, '{ type primary; file "example.db"; };'],
+ [
+ "modzone",
+ domain,
+ '{ type primary; file "example.db"; allow-transfer { any; }; };',
+ ],
+ ["delzone", domain],
+ ]
+
+ while not test_state["finished"]:
+ for command in rndc_commands:
+ try:
+ run_rndc("10.53.0.3", command)
+ except subprocess.SubprocessError:
+ pass
+
+
+def check_if_server_is_responsive():
+ """
+ Check if server status can be successfully retrieved using "rndc status"
+ """
+ try:
+ run_rndc("10.53.0.3", ["status"])
+ return True
+ except subprocess.SubprocessError:
+ return False
+
+
+def test_rndc_deadlock():
+ """
+ Test whether running "rndc addzone", "rndc modzone", and "rndc delzone"
+ commands concurrently does not trigger a deadlock
+ """
+ test_state = {"finished": False}
+
+ # Create 4 worker threads running "rndc" commands in a loop.
+ with concurrent.futures.ThreadPoolExecutor() as executor:
+ for i in range(1, 5):
+ domain = "example%d" % i
+ executor.submit(rndc_loop, test_state, domain)
+
+ # Run "rndc status" 10 times, with 1-second pauses between attempts.
+ # Each "rndc status" invocation has a timeout of 10 seconds. If any of
+ # them fails, the loop will be interrupted.
+ server_is_responsive = True
+ attempts = 10
+ while server_is_responsive and attempts > 0:
+ server_is_responsive = check_if_server_is_responsive()
+ attempts -= 1
+ time.sleep(1)
+
+ # Signal worker threads that the test is finished.
+ test_state["finished"] = True
+
+ # Check whether all "rndc status" commands succeeded.
+ assert server_is_responsive
diff --git a/bin/tests/system/addzone/tests_sh_addzone.py b/bin/tests/system/addzone/tests_sh_addzone.py
new file mode 100644
index 0000000..dca8e74
--- /dev/null
+++ b/bin/tests/system/addzone/tests_sh_addzone.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_addzone(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/allow-query/clean.sh b/bin/tests/system/allow-query/clean.sh
new file mode 100644
index 0000000..9914de7
--- /dev/null
+++ b/bin/tests/system/allow-query/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after allow query tests.
+#
+
+rm -f dig.out.*
+rm -f ns*/named.conf
+rm -f ns2/controls.conf
+rm -f */named.memstats
+rm -f ns*/named.lock
+rm -f ns*/named.run ns*/named.run.prev
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
diff --git a/bin/tests/system/allow-query/ns1/named.conf.in b/bin/tests/system/allow-query/ns1/named.conf.in
new file mode 100644
index 0000000..dd786e2
--- /dev/null
+++ b/bin/tests/system/allow-query/ns1/named.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/allow-query/ns1/root.db b/bin/tests/system/allow-query/ns1/root.db
new file mode 100644
index 0000000..456198e
--- /dev/null
+++ b/bin/tests/system/allow-query/ns1/root.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA a.root-servers.nil. hostmaster.localhost. 1 3600 1200 604800 3600
+ NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+normal.example. NS ns2.normal.example.
+ns2.normal.example. A 10.53.0.2
diff --git a/bin/tests/system/allow-query/ns2/generic.db b/bin/tests/system/allow-query/ns2/generic.db
new file mode 100644
index 0000000..83e66f9
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/generic.db
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN @
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ MX 10 mail
+
+a A 10.0.7.1
+mail A 10.0.7.2
+b A 10.0.7.3
+c A 10.0.7.4
+d A 10.0.7.5
+e A 10.0.7.6
+f A 10.0.7.7
+g A 10.0.7.8
+h A 10.0.7.9
diff --git a/bin/tests/system/allow-query/ns2/named01.conf.in b/bin/tests/system/allow-query/ns2/named01.conf.in
new file mode 100644
index 0000000..3069010
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named01.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named02.conf.in b/bin/tests/system/allow-query/ns2/named02.conf.in
new file mode 100644
index 0000000..678c417
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named02.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { any; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named03.conf.in b/bin/tests/system/allow-query/ns2/named03.conf.in
new file mode 100644
index 0000000..cdc64ff
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named03.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { none; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named04.conf.in b/bin/tests/system/allow-query/ns2/named04.conf.in
new file mode 100644
index 0000000..0544662
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named04.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { 10.53.0.2; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named05.conf.in b/bin/tests/system/allow-query/ns2/named05.conf.in
new file mode 100644
index 0000000..6f92049
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named05.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { 10.53.0.1; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named06.conf.in b/bin/tests/system/allow-query/ns2/named06.conf.in
new file mode 100644
index 0000000..261c75b
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named06.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query {! 10.53.0.2; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named07.conf.in b/bin/tests/system/allow-query/ns2/named07.conf.in
new file mode 100644
index 0000000..8050fa2
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named07.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl accept { 10.53.0.2; };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { accept; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named08.conf.in b/bin/tests/system/allow-query/ns2/named08.conf.in
new file mode 100644
index 0000000..ffa4cdc
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named08.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl accept { 10.53.0.1; };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { accept; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named09.conf.in b/bin/tests/system/allow-query/ns2/named09.conf.in
new file mode 100644
index 0000000..49166e6
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named09.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl accept { 10.53.0.2; };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query {! accept; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named10.conf.in b/bin/tests/system/allow-query/ns2/named10.conf.in
new file mode 100644
index 0000000..d684c2d
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named10.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { key one; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named11.conf.in b/bin/tests/system/allow-query/ns2/named11.conf.in
new file mode 100644
index 0000000..59b9e0e
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named11.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234efgh8765";
+};
+
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { key one; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named12.conf.in b/bin/tests/system/allow-query/ns2/named12.conf.in
new file mode 100644
index 0000000..a8e9107
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named12.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query {! key one; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
diff --git a/bin/tests/system/allow-query/ns2/named21.conf.in b/bin/tests/system/allow-query/ns2/named21.conf.in
new file mode 100644
index 0000000..c6204a3
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named21.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named22.conf.in b/bin/tests/system/allow-query/ns2/named22.conf.in
new file mode 100644
index 0000000..454f24a
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named22.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { any; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+
+};
diff --git a/bin/tests/system/allow-query/ns2/named23.conf.in b/bin/tests/system/allow-query/ns2/named23.conf.in
new file mode 100644
index 0000000..f62337b
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named23.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { none; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named24.conf.in b/bin/tests/system/allow-query/ns2/named24.conf.in
new file mode 100644
index 0000000..1e277a9
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named24.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { 10.53.0.2; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named25.conf.in b/bin/tests/system/allow-query/ns2/named25.conf.in
new file mode 100644
index 0000000..0548af2
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named25.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { 10.53.0.1; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named26.conf.in b/bin/tests/system/allow-query/ns2/named26.conf.in
new file mode 100644
index 0000000..40e5dfd
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named26.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query {! 10.53.0.2; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named27.conf.in b/bin/tests/system/allow-query/ns2/named27.conf.in
new file mode 100644
index 0000000..92fa1f8
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named27.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl accept { 10.53.0.2; };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { accept; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+
+};
diff --git a/bin/tests/system/allow-query/ns2/named28.conf.in b/bin/tests/system/allow-query/ns2/named28.conf.in
new file mode 100644
index 0000000..2ecac7c
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named28.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl accept { 10.53.0.1; };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { accept; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named29.conf.in b/bin/tests/system/allow-query/ns2/named29.conf.in
new file mode 100644
index 0000000..9a6c9e5
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named29.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl accept { 10.53.0.2; };
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query {! accept; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named30.conf.in b/bin/tests/system/allow-query/ns2/named30.conf.in
new file mode 100644
index 0000000..f7084c8
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named30.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { key one; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named31.conf.in b/bin/tests/system/allow-query/ns2/named31.conf.in
new file mode 100644
index 0000000..d6a7af5
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named31.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234efgh8765";
+};
+
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { key one; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { key one; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named32.conf.in b/bin/tests/system/allow-query/ns2/named32.conf.in
new file mode 100644
index 0000000..b7d7ee4
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named32.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query {! key one; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named33.conf.in b/bin/tests/system/allow-query/ns2/named33.conf.in
new file mode 100644
index 0000000..be31b72
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named33.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { none; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { any; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+
+};
diff --git a/bin/tests/system/allow-query/ns2/named34.conf.in b/bin/tests/system/allow-query/ns2/named34.conf.in
new file mode 100644
index 0000000..165ff06
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named34.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { any; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { none; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named40.conf.in b/bin/tests/system/allow-query/ns2/named40.conf.in
new file mode 100644
index 0000000..b7a8746
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named40.conf.in
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl accept { 10.53.0.2; };
+
+acl badaccept { 10.53.0.1; };
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234efgh8765";
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+};
+
+zone "any.example" {
+ type primary;
+ file "generic.db";
+ allow-query { any; };
+};
+
+zone "none.example" {
+ type primary;
+ file "generic.db";
+ allow-query { none; };
+};
+
+zone "addrallow.example" {
+ type primary;
+ file "generic.db";
+ allow-query { 10.53.0.2; };
+};
+
+zone "addrnotallow.example" {
+ type primary;
+ file "generic.db";
+ allow-query { 10.53.0.1; };
+};
+
+zone "addrdisallow.example" {
+ type primary;
+ file "generic.db";
+ allow-query { ! 10.53.0.2; };
+};
+
+zone "aclallow.example" {
+ type primary;
+ file "generic.db";
+ allow-query { accept; };
+};
+
+zone "aclnotallow.example" {
+ type primary;
+ file "generic.db";
+ allow-query { badaccept; };
+};
+
+zone "acldisallow.example" {
+ type primary;
+ file "generic.db";
+ allow-query { ! accept; };
+};
+
+/* Also usable for testing key not allowed */
+zone "keyallow.example" {
+ type primary;
+ file "generic.db";
+ allow-query { key one; };
+};
+
+zone "keydisallow.example" {
+ type primary;
+ file "generic.db";
+ allow-query { ! key one; };
+};
diff --git a/bin/tests/system/allow-query/ns2/named53.conf.in b/bin/tests/system/allow-query/ns2/named53.conf.in
new file mode 100644
index 0000000..bd0af28
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named53.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { none; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+ allow-query { any; };
+};
diff --git a/bin/tests/system/allow-query/ns2/named54.conf.in b/bin/tests/system/allow-query/ns2/named54.conf.in
new file mode 100644
index 0000000..a6ca424
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named54.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ allow-query { any; };
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "normal.example" {
+ type primary;
+ file "generic.db";
+ allow-query { none; };
+};
diff --git a/bin/tests/system/allow-query/ns2/named55.conf.in b/bin/tests/system/allow-query/ns2/named55.conf.in
new file mode 100644
index 0000000..6bcba07
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named55.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { none; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ allow-query { any; };
+ };
+
+};
diff --git a/bin/tests/system/allow-query/ns2/named56.conf.in b/bin/tests/system/allow-query/ns2/named56.conf.in
new file mode 100644
index 0000000..d89a5fb
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named56.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+
+ allow-query { any; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ allow-query { none; };
+ };
+};
diff --git a/bin/tests/system/allow-query/ns2/named57.conf.in b/bin/tests/system/allow-query/ns2/named57.conf.in
new file mode 100644
index 0000000..bcc3a85
--- /dev/null
+++ b/bin/tests/system/allow-query/ns2/named57.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+include "controls.conf";
+
+view "internal" {
+ allow-query-on { any; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "normal.example" {
+ type primary;
+ file "generic.db";
+ };
+
+ zone "aclnotallow.example" {
+ type primary;
+ file "generic.db";
+ allow-query-on { none; };
+ };
+};
diff --git a/bin/tests/system/allow-query/ns3/named.args b/bin/tests/system/allow-query/ns3/named.args
new file mode 100644
index 0000000..e875a57
--- /dev/null
+++ b/bin/tests/system/allow-query/ns3/named.args
@@ -0,0 +1,2 @@
+# this server only has 127.0.0.1 in its localhost/localnets ACLs
+-m record -c named.conf -d 99 -D allow-query-ns3 -X named.lock -g -T maxcachesize=2097152 -T fixedlocal
diff --git a/bin/tests/system/allow-query/ns3/named1.conf.in b/bin/tests/system/allow-query/ns3/named1.conf.in
new file mode 100644
index 0000000..74b9885
--- /dev/null
+++ b/bin/tests/system/allow-query/ns3/named1.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/allow-query/ns3/named2.conf.in b/bin/tests/system/allow-query/ns3/named2.conf.in
new file mode 100644
index 0000000..c4a4e8f
--- /dev/null
+++ b/bin/tests/system/allow-query/ns3/named2.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ allow-recursion { any; };
+ allow-recursion-on { none; };
+ allow-query-cache-on { 10.53.0.3; };
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/allow-query/ns3/named3.conf.in b/bin/tests/system/allow-query/ns3/named3.conf.in
new file mode 100644
index 0000000..0e1f7b0
--- /dev/null
+++ b/bin/tests/system/allow-query/ns3/named3.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; 10.53.1.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ allow-recursion { any; };
+ allow-query-cache { any; };
+ allow-query-cache-on { 10.53.0.3; }; # allow-recursion-on inherits
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/allow-query/ns3/named4.conf.in b/bin/tests/system/allow-query/ns3/named4.conf.in
new file mode 100644
index 0000000..36ff911
--- /dev/null
+++ b/bin/tests/system/allow-query/ns3/named4.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; 10.53.1.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ allow-recursion { any; };
+ allow-query-cache { any; };
+ allow-recursion-on { 10.53.0.3; }; # allow-query-cache-on inherits
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/allow-query/setup.sh b/bin/tests/system/allow-query/setup.sh
new file mode 100644
index 0000000..c85676e
--- /dev/null
+++ b/bin/tests/system/allow-query/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ../common/controls.conf.in ns2/controls.conf
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named01.conf.in ns2/named.conf
+copy_setports ns3/named1.conf.in ns3/named.conf
diff --git a/bin/tests/system/allow-query/tests.sh b/bin/tests/system/allow-query/tests.sh
new file mode 100644
index 0000000..3a1b8b4
--- /dev/null
+++ b/bin/tests/system/allow-query/tests.sh
@@ -0,0 +1,739 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Test of allow-query statement.
+# allow-query takes an address match list and can be included in either the
+# options statement or in the zone statement. This test assumes that the
+# acl tests cover the details of the address match list and uses a limited
+# number of address match test cases to ensure that allow-query finds the
+# expected match.
+# Test list:
+# In options:
+# default (any), any, none, [localhost, localnets],
+# allowed address, not allowed address, denied address,
+# allowed key, not allowed key, denied key
+# allowed acl, not allowed acl, denied acl (acls pointing to addresses)
+#
+# Each of these tests requires changing to a new configuration
+# file and using rndc to update the server
+#
+# In view, with nothing in options (default to any)
+# default (any), any, none, [localhost, localnets],
+# allowed address, not allowed address, denied address,
+# allowed key, not allowed key, denied key
+# allowed acl, not allowed acl, denied acl (acls pointing to addresses)
+#
+# In view, with options set to none, view set to any
+# In view, with options set to any, view set to none
+#
+# In zone, with nothing in options (default to any)
+# any, none, [localhost, localnets],
+# allowed address, denied address,
+# allowed key, not allowed key, denied key
+# allowed acl, not allowed acl, denied acl (acls pointing to addresses),
+#
+# In zone, with options set to none, zone set to any
+# In zone, with options set to any, zone set to none
+# In zone, with view set to none, zone set to any
+# In zone, with view set to any, zone set to none
+#
+# zone types of primary, secondary and stub can be tested in parallel by
+# using multiple instances (ns2 as primary, ns3 as secondary, ns4 as stub)
+# and querying as necessary.
+#
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +nosea +nostat +nocmd +norec +noques +noauth +noadd +nostats +dnssec -p ${PORT}"
+
+status=0
+n=0
+
+nextpart ns2/named.run > /dev/null
+
+# Test 1 - default, query allowed
+n=$((n + 1))
+echo_i "test $n: default - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 2 - explicit any, query allowed
+n=$((n + 1))
+copy_setports ns2/named02.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: explicit any - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 3 - none, query refused
+n=$((n + 1))
+copy_setports ns2/named03.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: none - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+nextpart ns2/named.run | grep 'recursion not enabled for view' > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+DIGNOEDNS="+tcp +nosea +nostat +nocmd +norec +noques +noauth +noadd +nostats +noedns -p ${PORT}"
+
+echo_i "test $n: none - query refused (no edns)"
+ret=0
+$DIG $DIGNOEDNS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null && ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 4 - address allowed, query allowed
+n=$((n + 1))
+copy_setports ns2/named04.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: address allowed - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 5 - address not allowed, query refused
+n=$((n + 1))
+copy_setports ns2/named05.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: address not allowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 6 - address disallowed, query refused
+n=$((n + 1))
+copy_setports ns2/named06.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: address disallowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 7 - acl allowed, query allowed
+n=$((n + 1))
+copy_setports ns2/named07.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: acl allowed - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 8 - acl not allowed, query refused
+n=$((n + 1))
+copy_setports ns2/named08.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: acl not allowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+
+# Test 9 - acl disallowed, query refused
+n=$((n + 1))
+copy_setports ns2/named09.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: acl disallowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 10 - key allowed, query allowed
+n=$((n + 1))
+copy_setports ns2/named10.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: key allowed - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 11 - key not allowed, query refused
+n=$((n + 1))
+copy_setports ns2/named11.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: key not allowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y two:1234efgh8765 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 12 - key disallowed, query refused
+n=$((n + 1))
+copy_setports ns2/named12.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: key disallowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# The next set of tests check if allow-query works in a view
+
+n=20
+# Test 21 - views default, query allowed
+n=$((n + 1))
+copy_setports ns2/named21.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views default - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 22 - views explicit any, query allowed
+n=$((n + 1))
+copy_setports ns2/named22.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views explicit any - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 23 - views none, query refused
+n=$((n + 1))
+copy_setports ns2/named23.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views none - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 24 - views address allowed, query allowed
+n=$((n + 1))
+copy_setports ns2/named24.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views address allowed - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 25 - views address not allowed, query refused
+n=$((n + 1))
+copy_setports ns2/named25.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views address not allowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 26 - views address disallowed, query refused
+n=$((n + 1))
+copy_setports ns2/named26.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views address disallowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 27 - views acl allowed, query allowed
+n=$((n + 1))
+copy_setports ns2/named27.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views acl allowed - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 28 - views acl not allowed, query refused
+n=$((n + 1))
+copy_setports ns2/named28.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views acl not allowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 29 - views acl disallowed, query refused
+n=$((n + 1))
+copy_setports ns2/named29.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views acl disallowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 30 - views key allowed, query allowed
+n=$((n + 1))
+copy_setports ns2/named30.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views key allowed - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 31 - views key not allowed, query refused
+n=$((n + 1))
+copy_setports ns2/named31.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views key not allowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y two:1234efgh8765 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 32 - views key disallowed, query refused
+n=$((n + 1))
+copy_setports ns2/named32.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views key disallowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 33 - views over options, views allow, query allowed
+n=$((n + 1))
+copy_setports ns2/named33.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views over options, views allow - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 34 - views over options, views disallow, query refused
+n=$((n + 1))
+copy_setports ns2/named34.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views over options, views disallow - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Tests for allow-query in the zone statements
+
+n=40
+
+# Test 41 - zone default, query allowed
+n=$((n + 1))
+copy_setports ns2/named40.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: zone default - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 42 - zone explicit any, query allowed
+n=$((n + 1))
+echo_i "test $n: zone explicit any - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.any.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.any.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 43 - zone none, query refused
+n=$((n + 1))
+echo_i "test $n: zone none - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.none.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.none.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 44 - zone address allowed, query allowed
+n=$((n + 1))
+echo_i "test $n: zone address allowed - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.addrallow.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.addrallow.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 45 - zone address not allowed, query refused
+n=$((n + 1))
+echo_i "test $n: zone address not allowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.addrnotallow.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.addrnotallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 46 - zone address disallowed, query refused
+n=$((n + 1))
+echo_i "test $n: zone address disallowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.addrdisallow.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.addrdisallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 47 - zone acl allowed, query allowed
+n=$((n + 1))
+echo_i "test $n: zone acl allowed - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.aclallow.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.aclallow.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 48 - zone acl not allowed, query refused
+n=$((n + 1))
+echo_i "test $n: zone acl not allowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.aclnotallow.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.aclnotallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 49 - zone acl disallowed, query refused
+n=$((n + 1))
+echo_i "test $n: zone acl disallowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.acldisallow.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.acldisallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 50 - zone key allowed, query allowed
+n=$((n + 1))
+echo_i "test $n: zone key allowed - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.keyallow.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.keyallow.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 51 - zone key not allowed, query refused
+n=$((n + 1))
+echo_i "test $n: zone key not allowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y two:1234efgh8765 a.keyallow.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.keyallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 52 - zone key disallowed, query refused
+n=$((n + 1))
+echo_i "test $n: zone key disallowed - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.keydisallow.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.keydisallow.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 53 - zones over options, zones allow, query allowed
+n=$((n + 1))
+copy_setports ns2/named53.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views over options, views allow - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 54 - zones over options, zones disallow, query refused
+n=$((n + 1))
+copy_setports ns2/named54.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: views over options, views disallow - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 55 - zones over views, zones allow, query allowed
+n=$((n + 1))
+copy_setports ns2/named55.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: zones over views, views allow - query allowed"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 56 - zones over views, zones disallow, query refused
+n=$((n + 1))
+copy_setports ns2/named56.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: zones over views, views disallow - query refused"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 57 - zones over views, zones disallow, query refused (allow-query-on)
+n=$((n + 1))
+copy_setports ns2/named57.conf.in ns2/named.conf
+rndc_reload ns2 10.53.0.2
+
+echo_i "test $n: zones over views, allow-query-on"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a > dig.out.ns2.1.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.1.$n > /dev/null || ret=1
+grep '^a.normal.example' dig.out.ns2.1.$n > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.aclnotallow.example a > dig.out.ns2.2.$n || ret=1
+grep 'status: REFUSED' dig.out.ns2.2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns2.2.$n > /dev/null || ret=1
+grep '^a.aclnotallow.example' dig.out.ns2.2.$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 58 - allow-recursion default
+n=$((n + 1))
+echo_i "test $n: default allow-recursion configuration"
+ret=0
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 -b 127.0.0.1 a.normal.example a > dig.out.ns3.1.$n
+grep 'status: NOERROR' dig.out.ns3.1.$n > /dev/null || ret=1
+$DIG -p ${PORT} @10.53.0.3 -b 10.53.0.1 a.normal.example a > dig.out.ns3.2.$n
+grep 'status: REFUSED' dig.out.ns3.2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns3.2.$n > /dev/null || ret=1
+nextpart ns3/named.run | grep 'allow-recursion did not match' > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 59 - allow-query-cache default
+n=$((n + 1))
+echo_i "test $n: default allow-query-cache configuration"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 -b 127.0.0.1 ns . > dig.out.ns3.1.$n
+grep 'status: NOERROR' dig.out.ns3.1.$n > /dev/null || ret=1
+$DIG -p ${PORT} @10.53.0.3 -b 10.53.0.1 ns . > dig.out.ns3.2.$n
+grep 'status: REFUSED' dig.out.ns3.2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns3.2.$n > /dev/null || ret=1
+nextpart ns3/named.run | grep 'allow-recursion did not match' > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 60 - block recursion-on, allow query-cache-on
+n=$((n + 1))
+copy_setports ns3/named2.conf.in ns3/named.conf
+rndc_reload ns3 10.53.0.3
+
+echo_i "test $n: block recursion-on, allow query-cache-on"
+ret=0
+# this should query the cache, and an answer should already be there
+$DIG -p ${PORT} @10.53.0.3 a.normal.example a > dig.out.ns3.1.$n
+grep 'recursion requested but not available' dig.out.ns3.1.$n > /dev/null || ret=1
+grep 'ANSWER: 1' dig.out.ns3.1.$n > /dev/null || ret=1
+# this should require recursion and therefore can't get an answer
+$DIG -p ${PORT} @10.53.0.3 b.normal.example a > dig.out.ns3.2.$n
+grep 'recursion requested but not available' dig.out.ns3.2.$n > /dev/null || ret=1
+grep 'ANSWER: 0' dig.out.ns3.2.$n > /dev/null || ret=1
+nextpart ns3/named.run | grep 'allow-recursion-on did not match' > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 61 - inheritance of allow-query-cache-on from allow-recursion-on
+n=$((n + 1))
+copy_setports ns3/named3.conf.in ns3/named.conf
+rndc_reload ns3 10.53.0.3
+
+echo_i "test $n: inheritance of allow-query-cache-on"
+ret=0
+# this should query the cache, an answer should already be there
+$DIG -p ${PORT} @10.53.0.3 a.normal.example a > dig.out.ns3.1.$n
+grep 'ANSWER: 1' dig.out.ns3.1.$n > /dev/null || ret=1
+# this should be refused due to allow-recursion-on/allow-query-cache-on
+$DIG -p ${PORT} @10.53.1.2 a.normal.example a > dig.out.ns3.2.$n
+grep 'recursion requested but not available' dig.out.ns3.2.$n > /dev/null || ret=1
+grep 'status: REFUSED' dig.out.ns3.2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns3.2.$n > /dev/null || ret=1
+# this should require recursion and should be allowed
+$DIG -p ${PORT} @10.53.0.3 c.normal.example a > dig.out.ns3.3.$n
+grep 'ANSWER: 1' dig.out.ns3.3.$n > /dev/null || ret=1
+# this should require recursion and be refused
+$DIG -p ${PORT} @10.53.1.2 d.normal.example a > dig.out.ns3.4.$n
+grep 'recursion requested but not available' dig.out.ns3.4.$n > /dev/null || ret=1
+grep 'status: REFUSED' dig.out.ns3.4.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns3.4.$n > /dev/null || ret=1
+nextpart ns3/named.run | grep 'allow-recursion-on did not match' > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 62 - inheritance of allow-recursion-on from allow-query-cache-on
+n=$((n + 1))
+copy_setports ns3/named4.conf.in ns3/named.conf
+rndc_reload ns3 10.53.0.3
+
+echo_i "test $n: inheritance of allow-recursion-on"
+ret=0
+# this should query the cache, an answer should already be there
+$DIG -p ${PORT} @10.53.0.3 a.normal.example a > dig.out.ns3.1.$n
+grep 'ANSWER: 1' dig.out.ns3.1.$n > /dev/null || ret=1
+# this should be refused due to allow-recursion-on/allow-query-cache-on
+$DIG -p ${PORT} @10.53.1.2 a.normal.example a > dig.out.ns3.2.$n
+grep 'recursion requested but not available' dig.out.ns3.2.$n > /dev/null || ret=1
+grep 'status: REFUSED' dig.out.ns3.2.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns3.2.$n > /dev/null || ret=1
+# this should require recursion and should be allowed
+$DIG -p ${PORT} @10.53.0.3 e.normal.example a > dig.out.ns3.3.$n
+grep 'ANSWER: 1' dig.out.ns3.3.$n > /dev/null || ret=1
+# this should require recursion and be refused
+$DIG -p ${PORT} @10.53.1.2 f.normal.example a > dig.out.ns3.4.$n
+grep 'recursion requested but not available' dig.out.ns3.4.$n > /dev/null || ret=1
+grep 'status: REFUSED' dig.out.ns3.4.$n > /dev/null || ret=1
+grep 'EDE: 18 (Prohibited)' dig.out.ns3.4.$n > /dev/null || ret=1
+nextpart ns3/named.run | grep 'allow-recursion-on did not match' > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/allow-query/tests_sh_allowquery.py b/bin/tests/system/allow-query/tests_sh_allowquery.py
new file mode 100644
index 0000000..ce20d79
--- /dev/null
+++ b/bin/tests/system/allow-query/tests_sh_allowquery.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_allowquery(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/ans.pl b/bin/tests/system/ans.pl
new file mode 100644
index 0000000..d42372d
--- /dev/null
+++ b/bin/tests/system/ans.pl
@@ -0,0 +1,534 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# This is the name server from hell. It provides canned
+# responses based on pattern matching the queries, and
+# can be reprogrammed on-the-fly over a TCP connection.
+#
+# The server listens for queries on port 5300 (or PORT).
+#
+# The server listens for control connections on port 5301 (or EXTRAPORT1).
+#
+# A control connection is a TCP stream of lines like
+#
+# /pattern/
+# name ttl type rdata
+# name ttl type rdata
+# ...
+# /pattern/
+# name ttl type rdata
+# name ttl type rdata
+# ...
+#
+# There can be any number of patterns, each associated
+# with any number of response RRs. Each pattern is a
+# Perl regular expression. If an empty pattern ("//") is
+# received, the server will ignore all incoming queries (TCP
+# connections will still be accepted, but both UDP queries
+# and TCP queries will not be responded to). If a non-empty
+# pattern is then received over the same control connection,
+# default behavior is restored.
+#
+# Each incoming query is converted into a string of the form
+# "qname qtype" (the printable query domain name, space,
+# printable query type) and matched against each pattern.
+#
+# The first pattern matching the query is selected, and
+# the RR following the pattern line are sent in the
+# answer section of the response.
+#
+# Each new control connection causes the current set of
+# patterns and responses to be cleared before adding new
+# ones.
+#
+# The server handles UDP and TCP queries. Zone transfer
+# responses work, but must fit in a single 64 k message.
+#
+# Now you can add TSIG, just specify key/key data with:
+#
+# /pattern <key> <key_data>/
+# name ttl type rdata
+# name ttl type rdata
+#
+# Note that this data will still be sent with any request for
+# pattern, only this data will be signed. Currently, this is only
+# done for TCP.
+#
+# /pattern bad-id <key> <key_data>/
+# /pattern bad-id/
+#
+# will add 50 to the message id of the response.
+
+
+use IO::File;
+use IO::Socket;
+use Data::Dumper;
+use Net::DNS;
+use Net::DNS::Packet;
+use strict;
+
+# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early
+local $SIG{PIPE} = 'IGNORE';
+
+# Flush logged output after every line
+local $| = 1;
+
+# We default to listening on 10.53.0.2 for historical reasons
+# XXX: we should also be able to specify IPv6
+my $server_addr = "10.53.0.2";
+if (@ARGV > 0) {
+ $server_addr = @ARGV[0];
+}
+
+my $mainport = int($ENV{'PORT'});
+if (!$mainport) { $mainport = 5300; }
+my $ctrlport = int($ENV{'EXTRAPORT1'});
+if (!$ctrlport) { $ctrlport = 5301; }
+
+# XXX: we should also be able to set the port numbers to listen on.
+my $ctlsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $ctrlport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $mainport, Proto => "udp", Reuse => 1) or die "$!";
+
+my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $mainport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+print "listening on $server_addr:$mainport,$ctrlport.\n";
+print "Using Net::DNS $Net::DNS::VERSION\n";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";;
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+#my @answers = ();
+my @rules;
+my $udphandler;
+my $tcphandler;
+
+sub handleUDP {
+ my ($buf) = @_;
+ my $request;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($request, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ my @questions = $request->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+ my $qclass = $questions[0]->qclass;
+ my $id = $request->header->id;
+
+ my $packet = new Net::DNS::Packet($qname, $qtype, $qclass);
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ $packet->header->id($id);
+
+ # get the existing signature if any, and clear the additional section
+ my $prev_tsig;
+ while (my $rr = $request->pop("additional")) {
+ $prev_tsig = $rr if ($rr->type eq "TSIG");
+ }
+
+ my $r;
+ foreach $r (@rules) {
+ my $pattern = $r->{pattern};
+ my($dbtype, $key_name, $key_data) = split(/ /,$pattern);
+ print "[handleUDP] $dbtype, $key_name, $key_data\n";
+ if ("$qname $qtype" =~ /$dbtype/) {
+ my $a;
+ foreach $a (@{$r->{answer}}) {
+ $packet->push("answer", $a);
+ }
+ if (defined($key_name) && defined($key_data)) {
+ my $tsig;
+ # Sign the packet
+ print " Signing the response with " .
+ "$key_name/$key_data\n";
+
+ if ($Net::DNS::VERSION < 0.69) {
+ $tsig = Net::DNS::RR->new(
+ "$key_name TSIG $key_data");
+ } else {
+ $tsig = Net::DNS::RR->new(
+ name => $key_name,
+ type => 'TSIG',
+ key => $key_data);
+ }
+
+ # These kluges are necessary because Net::DNS
+ # doesn't know how to sign responses. We
+ # clear compnames so that the TSIG key and
+ # algorithm name won't be compressed, and
+ # add one to arcount because the signing
+ # function will attempt to decrement it,
+ # which is incorrect in a response. Finally
+ # we set request_mac to the previous digest.
+ $packet->{"compnames"} = {}
+ if ($Net::DNS::VERSION < 0.70);
+ $packet->{"header"}{"arcount"} += 1
+ if ($Net::DNS::VERSION < 0.70);
+ if (defined($prev_tsig)) {
+ if ($Net::DNS::VERSION < 0.73) {
+ my $rmac = pack('n H*',
+ length($prev_tsig->mac)/2,
+ $prev_tsig->mac);
+ $tsig->{"request_mac"} =
+ unpack("H*", $rmac);
+ } else {
+ $tsig->request_mac(
+ $prev_tsig->mac);
+ }
+ }
+
+ $packet->sign_tsig($tsig);
+ }
+ last;
+ }
+ }
+ #$packet->print;
+
+ return $packet->data;
+}
+
+# namelen:
+# given a stream of data, reads a DNS-formatted name and returns its
+# total length, thus making it possible to skip past it.
+sub namelen {
+ my ($data) = @_;
+ my $len = 0;
+ my $label_len = 0;
+ do {
+ $label_len = unpack("c", $data);
+ $data = substr($data, $label_len + 1);
+ $len += $label_len + 1;
+ } while ($label_len != 0);
+ return ($len);
+}
+
+# packetlen:
+# given a stream of data, reads a DNS wire-format packet and returns
+# its total length, making it possible to skip past it.
+sub packetlen {
+ my ($data) = @_;
+ my $q;
+ my $rr;
+ my $header;
+ my $offset;
+
+ #
+ # decode/encode were introduced in Net::DNS 0.68
+ # parse is no longer a method and calling it here makes perl croak.
+ #
+ my $decode = 0;
+ $decode = 1 if ($Net::DNS::VERSION >= 0.68);
+
+ if ($decode) {
+ ($header, $offset) = Net::DNS::Header->decode(\$data);
+ } else {
+ ($header, $offset) = Net::DNS::Header->parse(\$data);
+ }
+
+ for (1 .. $header->qdcount) {
+ if ($decode) {
+ ($q, $offset) =
+ Net::DNS::Question->decode(\$data, $offset);
+ } else {
+ ($q, $offset) =
+ Net::DNS::Question->parse(\$data, $offset);
+ }
+ }
+ for (1 .. $header->ancount) {
+ if ($decode) {
+ ($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
+ } else {
+ ($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ }
+ for (1 .. $header->nscount) {
+ if ($decode) {
+ ($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
+ } else {
+ ($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ }
+ for (1 .. $header->arcount) {
+ if ($decode) {
+ ($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
+ } else {
+ ($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ }
+ return $offset;
+}
+
+# sign_tcp_continuation:
+# This is a hack to correct the problem that Net::DNS has no idea how
+# to sign multiple-message TCP responses. Several data that are included
+# in the digest when signing a query or the first message of a response are
+# omitted when signing subsequent messages in a TCP stream.
+#
+# Net::DNS::Packet->sign_tsig() has the ability to use a custom signing
+# function (specified by calling Packet->sign_func()). We use this
+# function as the signing function for TCP continuations, and it removes
+# the unwanted data from the digest before calling the default sign_hmac
+# function.
+sub sign_tcp_continuation {
+ my ($key, $data) = @_;
+
+ # copy out first two bytes: size of the previous MAC
+ my $rmacsize = unpack("n", $data);
+ $data = substr($data, 2);
+
+ # copy out previous MAC
+ my $rmac = substr($data, 0, $rmacsize);
+ $data = substr($data, $rmacsize);
+
+ # try parsing out the packet information
+ my $plen = packetlen($data);
+ my $pdata = substr($data, 0, $plen);
+ $data = substr($data, $plen);
+
+ # remove the keyname, ttl, class, and algorithm name
+ $data = substr($data, namelen($data));
+ $data = substr($data, 6);
+ $data = substr($data, namelen($data));
+
+ # preserve the TSIG data
+ my $tdata = substr($data, 0, 8);
+
+ # prepare a new digest and sign with it
+ $data = pack("n", $rmacsize) . $rmac . $pdata . $tdata;
+ return Net::DNS::RR::TSIG::sign_hmac($key, $data);
+}
+
+sub handleTCP {
+ my ($buf) = @_;
+ my $request;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($request, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ my @questions = $request->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+ my $qclass = $questions[0]->qclass;
+ my $id = $request->header->id;
+
+ my $opaque;
+
+ my $packet = new Net::DNS::Packet($qname, $qtype, $qclass);
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ $packet->header->id($id);
+
+ # get the existing signature if any, and clear the additional section
+ my $prev_tsig;
+ my $signer;
+ my $continuation = 0;
+ if ($Net::DNS::VERSION < 0.81) {
+ while (my $rr = $request->pop("additional")) {
+ if ($rr->type eq "TSIG") {
+ $prev_tsig = $rr;
+ }
+ }
+ }
+
+ my @results = ();
+ my $count_these = 0;
+
+ my $r;
+ foreach $r (@rules) {
+ my $pattern = $r->{pattern};
+ my($dbtype, $key_name, $key_data, $tname) = split(/ /,$pattern);
+ print "[handleTCP] $dbtype, $key_name, $key_data, $tname \n";
+ if ("$qname $qtype" =~ /$dbtype/) {
+ $count_these++;
+ my $a;
+ foreach $a (@{$r->{answer}}) {
+ $packet->push("answer", $a);
+ }
+ if (defined($key_name) && $key_name eq "bad-id") {
+ $packet->header->id(($id+50)%0xffff);
+ $key_name = $key_data;
+ ($key_data, $tname) = split(/ /,$tname)
+ }
+ if (defined($key_name) && defined($key_data)) {
+ my $tsig;
+ # sign the packet
+ print " Signing the data with " .
+ "$key_name/$key_data\n";
+
+ if ($Net::DNS::VERSION < 0.69) {
+ $tsig = Net::DNS::RR->new(
+ "$key_name TSIG $key_data");
+ } elsif ($Net::DNS::VERSION >= 0.81 &&
+ $continuation) {
+ } elsif ($Net::DNS::VERSION >= 0.75 &&
+ $continuation) {
+ $tsig = $prev_tsig;
+ } else {
+ $tsig = Net::DNS::RR->new(
+ name => $key_name,
+ type => 'TSIG',
+ key => $key_data);
+ }
+
+ # These kluges are necessary because Net::DNS
+ # doesn't know how to sign responses. We
+ # clear compnames so that the TSIG key and
+ # algorithm name won't be compressed, and
+ # add one to arcount because the signing
+ # function will attempt to decrement it,
+ # which is incorrect in a response. Finally
+ # we set request_mac to the previous digest.
+ $packet->{"compnames"} = {}
+ if ($Net::DNS::VERSION < 0.70);
+ $packet->{"header"}{"arcount"} += 1
+ if ($Net::DNS::VERSION < 0.70);
+ if (defined($prev_tsig)) {
+ if ($Net::DNS::VERSION < 0.73) {
+ my $rmac = pack('n H*',
+ length($prev_tsig->mac)/2,
+ $prev_tsig->mac);
+ $tsig->{"request_mac"} =
+ unpack("H*", $rmac);
+ } elsif ($Net::DNS::VERSION < 0.81) {
+ $tsig->request_mac(
+ $prev_tsig->mac);
+ }
+ }
+
+ $tsig->sign_func($signer) if defined($signer);
+ $tsig->continuation($continuation) if
+ ($Net::DNS::VERSION >= 0.71 &&
+ $Net::DNS::VERSION <= 0.74 );
+ if ($Net::DNS::VERSION < 0.81) {
+ $packet->sign_tsig($tsig);
+ } elsif ($continuation) {
+ $opaque = $packet->sign_tsig($opaque);
+ } else {
+ $opaque = $packet->sign_tsig($request);
+ }
+ $signer = \&sign_tcp_continuation
+ if ($Net::DNS::VERSION < 0.70);
+ $continuation = 1;
+
+ my $copy =
+ Net::DNS::Packet->new(\($packet->data));
+ $prev_tsig = $copy->pop("additional");
+ }
+ #$packet->print;
+ push(@results,$packet->data);
+ if ($tname eq "") {
+ $tname = $qname;
+ }
+ $packet = new Net::DNS::Packet($tname, $qtype, $qclass);
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ $packet->header->id($id);
+ }
+ }
+ print " A total of $count_these patterns matched\n";
+ return \@results;
+}
+
+# Main
+my $rin;
+my $rout;
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($ctlsock), 1) = 1;
+ vec($rin, fileno($tcpsock), 1) = 1;
+ vec($rin, fileno($udpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($ctlsock), 1)) {
+ warn "ctl conn";
+ my $conn = $ctlsock->accept;
+ my $rule = ();
+ @rules = ();
+ while (my $line = $conn->getline) {
+ chomp $line;
+ if ($line =~ m!^/(.*)/$!) {
+ if (length($1) == 0) {
+ $udphandler = sub { return; };
+ $tcphandler = sub { return; };
+ } else {
+ $udphandler = \&handleUDP;
+ $tcphandler = \&handleTCP;
+ $rule = { pattern => $1, answer => [] };
+ push(@rules, $rule);
+ }
+ } else {
+ push(@{$rule->{answer}},
+ new Net::DNS::RR($line));
+ }
+ }
+ $conn->close;
+ #print Dumper(@rules);
+ #print "+=+=+ $rules[0]->{'pattern'}\n";
+ #print "+=+=+ $rules[0]->{'answer'}->[0]->{'rname'}\n";
+ #print "+=+=+ $rules[0]->{'answer'}->[0]\n";
+ } elsif (vec($rout, fileno($udpsock), 1)) {
+ printf "UDP request\n";
+ my $buf;
+ $udpsock->recv($buf, 512);
+ my $result = &$udphandler($buf);
+ if (defined($result)) {
+ my $num_chars = $udpsock->send($result);
+ print " Sent $num_chars bytes via UDP\n";
+ }
+ } elsif (vec($rout, fileno($tcpsock), 1)) {
+ my $conn = $tcpsock->accept;
+ my $buf;
+ for (;;) {
+ my $lenbuf;
+ my $n = $conn->sysread($lenbuf, 2);
+ last unless $n == 2;
+ my $len = unpack("n", $lenbuf);
+ $n = $conn->sysread($buf, $len);
+ last unless $n == $len;
+ print "TCP request\n";
+ my $result = &$tcphandler($buf);
+ if (defined($result)) {
+ foreach my $response (@$result) {
+ $len = length($response);
+ $n = $conn->syswrite(pack("n", $len), 2);
+ $n = $conn->syswrite($response, $len);
+ print " Sent: $n chars via TCP\n";
+ }
+ }
+ }
+ $conn->close;
+ }
+}
diff --git a/bin/tests/system/auth/clean.sh b/bin/tests/system/auth/clean.sh
new file mode 100644
index 0000000..5fb37ac
--- /dev/null
+++ b/bin/tests/system/auth/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f dig.out.test*
+rm -f ns2/example.com.bk
+rm -f ns2/example.net.bk
+rm -f ns*/managed-keys.bind* ns*/*mkeys*
diff --git a/bin/tests/system/auth/ns1/chaos.db b/bin/tests/system/auth/ns1/chaos.db
new file mode 100644
index 0000000..bbd489a
--- /dev/null
+++ b/bin/tests/system/auth/ns1/chaos.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ CH SOA ns root (
+ 2018010100 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A ch-addr.example. 1001
+test A ch-addr.example. 1002
+ A ch-addr.example. 1003
diff --git a/bin/tests/system/auth/ns1/example.com.db b/bin/tests/system/auth/ns1/example.com.db
new file mode 100644
index 0000000..6768895
--- /dev/null
+++ b/bin/tests/system/auth/ns1/example.com.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2018010100 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+www CNAME server.example.net.
+inzone CNAME a.example.com.
+a A 10.53.0.1
+dname DNAME @
diff --git a/bin/tests/system/auth/ns1/example.net.db b/bin/tests/system/auth/ns1/example.net.db
new file mode 100644
index 0000000..29885ca
--- /dev/null
+++ b/bin/tests/system/auth/ns1/example.net.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2018010100 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+server A 10.53.0.100
diff --git a/bin/tests/system/auth/ns1/named.conf.in b/bin/tests/system/auth/ns1/named.conf.in
new file mode 100644
index 0000000..9d0a517
--- /dev/null
+++ b/bin/tests/system/auth/ns1/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+view main in {
+ zone example.net {
+ type primary;
+ file "example.net.db";
+ };
+
+ zone example.com {
+ type primary;
+ file "example.com.db";
+ };
+};
+
+view alt chaos {
+ zone example.chaos chaos {
+ type primary;
+ file "chaos.db";
+ };
+};
diff --git a/bin/tests/system/auth/ns2/named.conf.in b/bin/tests/system/auth/ns2/named.conf.in
new file mode 100644
index 0000000..9b82c50
--- /dev/null
+++ b/bin/tests/system/auth/ns2/named.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+ dnssec-validation no;
+};
+
+zone example.net {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "example.net.bk";
+};
+
+zone example.com {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "example.com.bk";
+};
diff --git a/bin/tests/system/auth/setup.sh b/bin/tests/system/auth/setup.sh
new file mode 100644
index 0000000..6929ec5
--- /dev/null
+++ b/bin/tests/system/auth/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
diff --git a/bin/tests/system/auth/tests.sh b/bin/tests/system/auth/tests.sh
new file mode 100644
index 0000000..6cd4a27
--- /dev/null
+++ b/bin/tests/system/auth/tests.sh
@@ -0,0 +1,192 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp -p ${PORT}"
+
+status=0
+n=0
+
+n=$((n + 1))
+echo_i "wait for zones to finish transferring to ns2 ($n)"
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ for zone in example.com example.net
+ do
+ $DIG $DIGOPTS @10.53.0.2 soa $zone > dig.out.test$n || ret=1
+ grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+ done
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+#
+# If recursion is unrequested or unavailable, then cross-zone CNAME records
+# should not be followed. If both requested and available, they should be.
+#
+n=$((n + 1))
+echo_i "check that cross-zone CNAME record does not return target data (rd=0/ra=0) ($n)"
+ret=0
+$DIG $DIGOPTS +norec @10.53.0.1 www.example.com > dig.out.test$n || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "flags: qr aa;" dig.out.test$n > /dev/null || ret=1
+grep "www.example.com.*CNAME.*server.example.net" dig.out.test$n > /dev/null || ret=1
+grep "server.example.net.*A.*10.53.0.100" dig.out.test$n > /dev/null && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that cross-zone CNAME record does not return target data (rd=1/ra=0) ($n)"
+ret=0
+$DIG $DIGOPTS +rec @10.53.0.1 www.example.com > dig.out.test$n || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "flags: qr aa rd;" dig.out.test$n > /dev/null || ret=1
+grep "www.example.com.*CNAME.*server.example.net" dig.out.test$n > /dev/null || ret=1
+grep "server.example.net.*A.*10.53.0.100" dig.out.test$n > /dev/null && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that cross-zone CNAME record does not return target data (rd=0/ra=1) ($n)"
+ret=0
+$DIG $DIGOPTS +norec @10.53.0.2 www.example.com > dig.out.test$n || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "flags: qr aa ra;" dig.out.test$n > /dev/null || ret=1
+grep "www.example.com.*CNAME.*server.example.net" dig.out.test$n > /dev/null || ret=1
+grep "server.example.net.*A.*10.53.0.100" dig.out.test$n > /dev/null && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that cross-zone CNAME records return target data (rd=1/ra=1) ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 www.example.com > dig.out.test$n || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "flags: qr aa rd ra;" dig.out.test$n > /dev/null || ret=1
+grep "www.example.com.*CNAME.*server.example.net" dig.out.test$n > /dev/null || ret=1
+grep "server.example.net.*A.*10.53.0.100" dig.out.test$n > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+#
+# In-zone CNAME records should always be followed regardless of RD and RA.
+#
+n=$((n + 1))
+echo_i "check that in-zone CNAME records return target data (rd=0/ra=0) ($n)"
+ret=0
+$DIG $DIGOPTS +norec @10.53.0.1 inzone.example.com > dig.out.test$n || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "flags: qr aa;" dig.out.test$n > /dev/null || ret=1
+grep "inzone.example.com.*CNAME.*a.example.com" dig.out.test$n > /dev/null || ret=1
+grep "a.example.com.*A.*10.53.0.1" dig.out.test$n > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that in-zone CNAME records returns target data (rd=1/ra=0) ($n)"
+ret=0
+$DIG $DIGOPTS +rec @10.53.0.1 inzone.example.com > dig.out.test$n || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "flags: qr aa rd;" dig.out.test$n > /dev/null || ret=1
+grep "inzone.example.com.*CNAME.*a.example.com" dig.out.test$n > /dev/null || ret=1
+grep "a.example.com.*A.*10.53.0.1" dig.out.test$n > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that in-zone CNAME records return target data (rd=0/ra=1) ($n)"
+ret=0
+$DIG $DIGOPTS +norec @10.53.0.2 inzone.example.com > dig.out.test$n || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "flags: qr aa ra;" dig.out.test$n > /dev/null || ret=1
+grep "inzone.example.com.*CNAME.*a.example.com" dig.out.test$n > /dev/null || ret=1
+grep "a.example.com.*A.*10.53.0.1" dig.out.test$n > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that in-zone CNAME records return target data (rd=1/ra=1) ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 inzone.example.com > dig.out.test$n || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "flags: qr aa rd ra;" dig.out.test$n > /dev/null || ret=1
+grep "inzone.example.com.*CNAME.*a.example.com" dig.out.test$n > /dev/null || ret=1
+grep "a.example.com.*A.*10.53.0.1" dig.out.test$n > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that in-zone CNAME records does not return target data when QTYPE is CNAME (rd=1/ra=1) ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -t cname inzone.example.com > dig.out.test$n || ret=1
+grep 'ANSWER: 1,' dig.out.test$n > /dev/null || ret=1
+grep 'flags: qr aa rd ra;' dig.out.test$n > /dev/null || ret=1
+grep 'inzone\.example\.com\..*CNAME.a\.example\.com\.' dig.out.test$n > /dev/null || ret=1
+grep 'a\.example\.com\..*A.10\.53\.0\.1' dig.out.test$n > /dev/null && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that in-zone CNAME records does not return target data when QTYPE is ANY (rd=1/ra=1) ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -t any inzone.example.com > dig.out.test$n || ret=1
+grep 'ANSWER: 1,' dig.out.test$n > /dev/null || ret=1
+grep 'flags: qr aa rd ra;' dig.out.test$n > /dev/null || ret=1
+grep 'inzone\.example\.com\..*CNAME.a\.example\.com\.' dig.out.test$n > /dev/null || ret=1
+grep 'a\.example\.com\..*A.10\.53\.0\.1' dig.out.test$n > /dev/null && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that in-zone DNAME records does not return target data when QTYPE is CNAME (rd=1/ra=1) ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -t cname inzone.dname.example.com > dig.out.test$n || ret=1
+grep 'ANSWER: 2,' dig.out.test$n > /dev/null || ret=1
+grep 'flags: qr aa rd ra;' dig.out.test$n > /dev/null || ret=1
+grep 'dname\.example\.com\..*DNAME.example\.com\.' dig.out.test$n > /dev/null || ret=1
+grep 'inzone\.dname\.example\.com\..*CNAME.inzone\.example\.com\.' dig.out.test$n > /dev/null || ret=1
+grep 'inzone\.example\.com\..*CNAME.a\.example\.com\.' dig.out.test$n > /dev/null && ret=1
+grep 'a\.example\.com\..*A.10\.53\.0\.1' dig.out.test$n > /dev/null && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that in-zone DNAME records does not return target data when QTYPE is ANY (rd=1/ra=1) ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -t any inzone.dname.example.com > dig.out.test$n || ret=1
+grep 'ANSWER: 2,' dig.out.test$n > /dev/null || ret=1
+grep 'flags: qr aa rd ra;' dig.out.test$n > /dev/null || ret=1
+grep 'dname\.example\.com\..*DNAME.example\.com\.' dig.out.test$n > /dev/null || ret=1
+grep 'inzone\.dname\.example\.com\..*CNAME.inzone\.example\.com\.' dig.out.test$n > /dev/null || ret=1
+grep 'inzone\.example\.com.*CNAME.a\.example\.com\.' dig.out.test$n > /dev/null && ret=1
+grep 'a\.example\.com.*A.10\.53\.0\.1' dig.out.test$n > /dev/null && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that CHAOS addresses are compared correctly ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 +noall +answer ch test.example.chaos > dig.out.test$n
+lines=$(wc -l < dig.out.test$n)
+[ ${lines:-0} -eq 2 ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/auth/tests_sh_auth.py b/bin/tests/system/auth/tests_sh_auth.py
new file mode 100644
index 0000000..97233fa
--- /dev/null
+++ b/bin/tests/system/auth/tests_sh_auth.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_auth(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/autosign/clean.sh b/bin/tests/system/autosign/clean.sh
new file mode 100644
index 0000000..ef67677
--- /dev/null
+++ b/bin/tests/system/autosign/clean.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */K* */dsset-* */*.signed */tmp* */*.jnl */*.bk
+rm -f */core
+rm -f */example.bk
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run*
+rm -f */trusted.conf */private.conf
+rm -f activate-now-publish-1day.key
+rm -f active.key inact.key del.key delzsk.key unpub.key standby.key rev.key
+rm -f delayksk.key delayzsk.key autoksk.key autozsk.key
+rm -f dig.out.*
+rm -f digcomp.out.test*
+rm -f noksk-ksk.key nozsk-ksk.key nozsk-zsk.key inaczsk-zsk.key inaczsk-ksk.key
+rm -f nopriv.key vanishing.key del1.key del2.key
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.lock
+rm -f ns1/root.db
+rm -f ns2/example.db
+rm -f ns2/optout-with-ent.db
+rm -f ns2/private.secure.example.db ns2/bar.db
+rm -f ns3/*.nzd ns3/*.nzd-lock ns3/*.nzf
+rm -f ns3/*.nzf
+rm -f ns3/autonsec3.example.db
+rm -f ns3/cdnskey-delete.example.db
+rm -f ns3/cds-delete.example.db
+rm -f ns3/delzsk.example.db
+rm -f ns3/dname-at-apex-nsec3.example.db
+rm -f ns3/inacksk2.example.db
+rm -f ns3/inacksk3.example.db
+rm -f ns3/inaczsk2.example.db
+rm -f ns3/inaczsk3.example.db
+rm -f ns3/jitter.nsec3.example.db
+rm -f ns3/kg.out ns3/s.out ns3/st.out
+rm -f ns3/kskonly.example.db
+rm -f ns3/named.ns3.prev
+rm -f ns3/noksk.example.db
+rm -f ns3/nozsk.example.db ns3/inaczsk.example.db
+rm -f ns3/nsec-only.example.db
+rm -f ns3/nsec3-to-nsec.example.db
+rm -f ns3/nsec3.example.db
+rm -f ns3/nsec3.nsec3.example.db
+rm -f ns3/nsec3.optout.example.db
+rm -f ns3/oldsigs.example.db
+rm -f ns3/optout.example.db
+rm -f ns3/optout.nsec3.example.db
+rm -f ns3/optout.optout.example.db
+rm -f ns3/prepub.example.db
+rm -f ns3/prepub.example.db.in
+rm -f ns3/reconf.example.db
+rm -f ns3/rsasha256.example.db ns3/rsasha512.example.db
+rm -f ns3/secure-to-insecure.example.db
+rm -f ns3/secure-to-insecure2.example.db
+rm -f ns3/secure.example.db
+rm -f ns3/secure.nsec3.example.db
+rm -f ns3/secure.optout.example.db
+rm -f ns3/settime.out.*
+rm -f ns3/sync.example.db
+rm -f ns3/ttl*.db
+rm -f nsupdate.out
+rm -f settime.out.*
+rm -f signing.out.*
+rm -f sync.key
diff --git a/bin/tests/system/autosign/ns1/keygen.sh b/bin/tests/system/autosign/ns1/keygen.sh
new file mode 100644
index 0000000..6b969c3
--- /dev/null
+++ b/bin/tests/system/autosign/ns1/keygen.sh
@@ -0,0 +1,53 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=.
+zonefile=root.db
+infile=root.db.in
+
+(cd ../ns2 && $SHELL keygen.sh )
+
+cat $infile ../ns2/dsset-example. ../ns2/dsset-bar. > $zonefile
+
+zskact=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q $zone)
+zskvanish=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q $zone)
+zskdel=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -D now $zone)
+zskinact=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -I now $zone)
+zskunpub=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -G $zone)
+zsksby=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -A none $zone)
+zskactnowpub1d=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -A now -P +1d $zone)
+zsknopriv=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q $zone)
+rm $zsknopriv.private
+
+ksksby=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -P now -A now+15s -fk $zone)
+kskrev=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -R now+15s -fk $zone)
+
+keyfile_to_static_ds $ksksby > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+cp trusted.conf ../ns3/trusted.conf
+cp trusted.conf ../ns4/trusted.conf
+
+keyfile_to_static_ds $kskrev > trusted.conf
+cp trusted.conf ../ns5/trusted.conf
+
+echo $zskact > ../active.key
+echo $zskvanish > ../vanishing.key
+echo $zskdel > ../del.key
+echo $zskinact > ../inact.key
+echo $zskunpub > ../unpub.key
+echo $zsknopriv > ../nopriv.key
+echo $zsksby > ../standby.key
+echo $zskactnowpub1d > ../activate-now-publish-1day.key
+$REVOKE -R $kskrev > ../rev.key
diff --git a/bin/tests/system/autosign/ns1/named.conf.in b/bin/tests/system/autosign/ns1/named.conf.in
new file mode 100644
index 0000000..2a55483
--- /dev/null
+++ b/bin/tests/system/autosign/ns1/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+ allow-transfer { any; };
+ allow-query { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+ dnssec-dnskey-kskonly no;
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/autosign/ns1/root.db.in b/bin/tests/system/autosign/ns1/root.db.in
new file mode 100644
index 0000000..6715a02
--- /dev/null
+++ b/bin/tests/system/autosign/ns1/root.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 30
+. IN SOA a.root.servers.nil. each.isc.org. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+. TXT "root zone"
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+bar. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/autosign/ns2/Xbar.+013+59973.key b/bin/tests/system/autosign/ns2/Xbar.+013+59973.key
new file mode 100644
index 0000000..1f4d1f4
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/Xbar.+013+59973.key
@@ -0,0 +1,5 @@
+; This is a key-signing key, keyid 59973, for bar.
+; Created: 20220623022335 (Thu Jun 23 12:23:35 2022)
+; Publish: 20220623022335 (Thu Jun 23 12:23:35 2022)
+; Activate: 20220623022335 (Thu Jun 23 12:23:35 2022)
+bar. IN DNSKEY 257 3 13 QT6CpMaV4BT072+NaKLY5H01Mj2r1MOgsxgoiTAq1Fbf6rrkEWpnbktu Dh9Ol9kuzcUrefxDuxNwsXJu3iDPxw==
diff --git a/bin/tests/system/autosign/ns2/Xbar.+013+59973.private b/bin/tests/system/autosign/ns2/Xbar.+013+59973.private
new file mode 100644
index 0000000..708d242
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/Xbar.+013+59973.private
@@ -0,0 +1,6 @@
+Private-key-format: v1.3
+Algorithm: 13 (ECDSAP256SHA256)
+PrivateKey: joFZ8vCdyqkgMb6rZ0zanrdrzOSCg1GyEJV6tp5F+Bw=
+Created: 20220623022335
+Publish: 20220623022335
+Activate: 20220623022335
diff --git a/bin/tests/system/autosign/ns2/Xbar.+013+60101.key b/bin/tests/system/autosign/ns2/Xbar.+013+60101.key
new file mode 100644
index 0000000..0c47840
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/Xbar.+013+60101.key
@@ -0,0 +1,5 @@
+; This is a key-signing key, keyid 60101, for bar.
+; Created: 20220623022331 (Thu Jun 23 12:23:31 2022)
+; Publish: 20220623022331 (Thu Jun 23 12:23:31 2022)
+; Activate: 20220623022331 (Thu Jun 23 12:23:31 2022)
+bar. IN DNSKEY 257 3 13 dLGGOAE5uJd53Gci9MdymaRTMwsXVn13j05IfGJoVt9ucpeXpoIKVViX JNVE/uO4eJvkHycdEAvdVUWcslEmMQ==
diff --git a/bin/tests/system/autosign/ns2/Xbar.+013+60101.private b/bin/tests/system/autosign/ns2/Xbar.+013+60101.private
new file mode 100644
index 0000000..6ca8370
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/Xbar.+013+60101.private
@@ -0,0 +1,6 @@
+Private-key-format: v1.3
+Algorithm: 13 (ECDSAP256SHA256)
+PrivateKey: pTTXxZUTzeVBXHMUJxTMxjh9yU4oxDtEhEvpkj+olf0=
+Created: 20220623022331
+Publish: 20220623022331
+Activate: 20220623022331
diff --git a/bin/tests/system/autosign/ns2/bar.db.in b/bin/tests/system/autosign/ns2/bar.db.in
new file mode 100644
index 0000000..8a9fa98
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/bar.db.in
@@ -0,0 +1,80 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+
+; Used for testing ANY queries
+foo TXT "testing"
+foo A 10.0.1.0
+
+; Used for testing CNAME queries
+cname1 CNAME cname1-target
+cname1-target TXT "testing cname"
+
+cname2 CNAME cname2-target
+cname2-target TXT "testing cname"
+
+; Used for testing DNAME queries
+dname1 DNAME dname1-target
+foo.dname1-target TXT "testing dname"
+
+dname2 DNAME dname2-target
+foo.dname2-target TXT "testing dname"
+
+; A secure subdomain
+secure NS ns.secure
+ns.secure A 10.53.0.3
+
+; An insecure subdomain
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+
+; A insecure subdomain
+mustbesecure NS ns.mustbesecure
+ns.mustbesecure A 10.53.0.3
+
+z A 10.0.0.26
+
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+
+optout NS ns.optout
+ns.optout A 10.53.0.3
+
+nsec3-unknown NS ns.nsec3-unknown
+ns.nsec3-unknown A 10.53.0.3
+
+optout-unknown NS ns.optout-unknown
+ns.optout-unknown A 10.53.0.3
+
+multiple NS ns.multiple
+ns.multiple A 10.53.0.3
+
+rsasha256 NS ns.rsasha256
+ns.rsasha256 A 10.53.0.3
+
+rsasha512 NS ns.rsasha512
+ns.rsasha512 A 10.53.0.3
diff --git a/bin/tests/system/autosign/ns2/child.nsec3.example.db b/bin/tests/system/autosign/ns2/child.nsec3.example.db
new file mode 100644
index 0000000..8fc3bc8
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/child.nsec3.example.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2006081400 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ IN NS ns2.example.
diff --git a/bin/tests/system/autosign/ns2/child.optout.example.db b/bin/tests/system/autosign/ns2/child.optout.example.db
new file mode 100644
index 0000000..8fc3bc8
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/child.optout.example.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2006081400 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ IN NS ns2.example.
diff --git a/bin/tests/system/autosign/ns2/dst.example.db.in b/bin/tests/system/autosign/ns2/dst.example.db.in
new file mode 100644
index 0000000..0039484
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/dst.example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2.example.
+a A 10.0.0.1
diff --git a/bin/tests/system/autosign/ns2/example.db.in b/bin/tests/system/autosign/ns2/example.db.in
new file mode 100644
index 0000000..a970074
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/example.db.in
@@ -0,0 +1,88 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+
+; Used for testing ANY queries
+foo TXT "testing"
+foo A 10.0.1.0
+
+; Used for testing CNAME queries
+cname1 CNAME cname1-target
+cname1-target TXT "testing cname"
+
+cname2 CNAME cname2-target
+cname2-target TXT "testing cname"
+
+; Used for testing DNAME queries
+dname1 DNAME dname1-target
+foo.dname1-target TXT "testing dname"
+
+dname2 DNAME dname2-target
+foo.dname2-target TXT "testing dname"
+
+; A secure subdomain
+secure NS ns.secure
+ns.secure A 10.53.0.3
+
+; An insecure subdomain
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+
+; A insecure subdomain
+mustbesecure NS ns.mustbesecure
+ns.mustbesecure A 10.53.0.3
+
+z A 10.0.0.26
+
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+
+optout NS ns.optout
+ns.optout A 10.53.0.3
+
+nsec3-unknown NS ns.nsec3-unknown
+ns.nsec3-unknown A 10.53.0.3
+
+optout-unknown NS ns.optout-unknown
+ns.optout-unknown A 10.53.0.3
+
+multiple NS ns.multiple
+ns.multiple A 10.53.0.3
+
+rsasha256 NS ns.rsasha256
+ns.rsasha256 A 10.53.0.3
+
+rsasha512 NS ns.rsasha512
+ns.rsasha512 A 10.53.0.3
+
+nsec3-to-nsec NS ns.nsec3-to-nsec
+ns.nsec3-to-nsec A 10.53.0.3
+
+oldsigs NS ns.oldsigs
+ns.oldsigs A 10.53.0.3
+
+dname-at-apex-nsec3 NS ns3
diff --git a/bin/tests/system/autosign/ns2/insecure.secure.example.db b/bin/tests/system/autosign/ns2/insecure.secure.example.db
new file mode 100644
index 0000000..14971bd
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/insecure.secure.example.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/autosign/ns2/keygen.sh b/bin/tests/system/autosign/ns2/keygen.sh
new file mode 100644
index 0000000..9b7c31d
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/keygen.sh
@@ -0,0 +1,65 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+# Have the child generate subdomain keys and pass DS sets to us.
+( cd ../ns3 && $SHELL keygen.sh )
+
+for subdomain in secure nsec3 autonsec3 optout rsasha256 rsasha512 \
+ nsec3-to-nsec oldsigs sync dname-at-apex-nsec3 cds-delete \
+ cdnskey-delete
+do
+ cp ../ns3/dsset-$subdomain.example. .
+done
+
+# Create keys and pass the DS to the parent.
+zone=example
+zonefile="${zone}.db"
+infile="${zonefile}.in"
+cat $infile dsset-*.example. > $zonefile
+
+kskname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q -fk $zone)
+$KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q $zone > /dev/null
+$DSFROMKEY $kskname.key > dsset-${zone}.
+
+# Create keys for a private secure zone.
+zone=private.secure.example
+zonefile="${zone}.db"
+infile="${zonefile}.in"
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q -fk $zone)
+$KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q $zone > /dev/null
+keyfile_to_static_ds $ksk > private.conf
+cp private.conf ../ns4/private.conf
+$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile > /dev/null
+
+# Extract saved keys for the revoke-to-duplicate-key test
+zone=bar
+zonefile="${zone}.db"
+infile="${zonefile}.in"
+cat $infile > $zonefile
+for i in Xbar.+013+59973.key Xbar.+013+59973.private \
+ Xbar.+013+60101.key Xbar.+013+60101.private
+do
+ cp $i $(echo $i | sed s/X/K/)
+done
+$KEYGEN -a ECDSAP256SHA256 -q $zone > /dev/null
+$DSFROMKEY Kbar.+013+60101.key > dsset-bar.
+
+# a zone with empty non-terminals.
+zone=optout-with-ent
+zonefile=optout-with-ent.db
+infile=optout-with-ent.db.in
+cat $infile > $zonefile
+kskname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q -fk $zone)
+$KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q $zone > /dev/null
diff --git a/bin/tests/system/autosign/ns2/named.conf.in b/bin/tests/system/autosign/ns2/named.conf.in
new file mode 100644
index 0000000..c155a3b
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/named.conf.in
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+ dnssec-loadkeys-interval 30;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+ sig-signing-type 65280;
+};
+
+zone "bar" {
+ type primary;
+ file "bar.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+ dnssec-dnskey-kskonly yes;
+};
+
+zone "private.secure.example" {
+ type primary;
+ file "private.secure.example.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "insecure.secure.example" {
+ type primary;
+ file "insecure.secure.example.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "child.nsec3.example" {
+ type primary;
+ file "child.nsec3.example.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "child.optout.example" {
+ type primary;
+ file "child.optout.example.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "optout-with-ent" {
+ type primary;
+ file "optout-with-ent.db";
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/autosign/ns2/optout-with-ent.db.in b/bin/tests/system/autosign/ns2/optout-with-ent.db.in
new file mode 100644
index 0000000..5a3e207
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/optout-with-ent.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns2.example. . (
+ 2010042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2.example.
+sub1.ent NS .
+sub2.ent NS .
diff --git a/bin/tests/system/autosign/ns2/private.secure.example.db.in b/bin/tests/system/autosign/ns2/private.secure.example.db.in
new file mode 100644
index 0000000..29fcddf
--- /dev/null
+++ b/bin/tests/system/autosign/ns2/private.secure.example.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.2
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+private2secure-nxdomain CNAME r.example.
diff --git a/bin/tests/system/autosign/ns3/autonsec3.example.db.in b/bin/tests/system/autosign/ns3/autonsec3.example.db.in
new file mode 100644
index 0000000..17964e8
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/autonsec3.example.db.in
@@ -0,0 +1,37 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+child NS ns2.example.
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17
diff --git a/bin/tests/system/autosign/ns3/cdnskey-delete.example.db.in b/bin/tests/system/autosign/ns3/cdnskey-delete.example.db.in
new file mode 100644
index 0000000..3083a79
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/cdnskey-delete.example.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/cds-delete.example.db.in b/bin/tests/system/autosign/ns3/cds-delete.example.db.in
new file mode 100644
index 0000000..3083a79
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/cds-delete.example.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/delay.example.db b/bin/tests/system/autosign/ns3/delay.example.db
new file mode 100644
index 0000000..0b11a00
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/delay.example.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/delzsk.example.db.in b/bin/tests/system/autosign/ns3/delzsk.example.db.in
new file mode 100644
index 0000000..14fef54
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/delzsk.example.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000010101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+sub NS ns.sub
+ DS 12345 8 1 0000000000000000000000000000000000000000
+ns.sub A 10.53.0.3
diff --git a/bin/tests/system/autosign/ns3/dname-at-apex-nsec3.example.db.in b/bin/tests/system/autosign/ns3/dname-at-apex-nsec3.example.db.in
new file mode 100644
index 0000000..080d111
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/dname-at-apex-nsec3.example.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns3.example. . 1 1200 1200 1814400 3600
+@ NS ns3.example.
+@ DNAME example.
+@ NSEC3PARAM 1 0 0 -
diff --git a/bin/tests/system/autosign/ns3/inacksk2.example.db.in b/bin/tests/system/autosign/ns3/inacksk2.example.db.in
new file mode 100644
index 0000000..1376922
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/inacksk2.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/inacksk3.example.db.in b/bin/tests/system/autosign/ns3/inacksk3.example.db.in
new file mode 100644
index 0000000..1376922
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/inacksk3.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/inaczsk.example.db.in b/bin/tests/system/autosign/ns3/inaczsk.example.db.in
new file mode 100644
index 0000000..1376922
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/inaczsk.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/inaczsk2.example.db.in b/bin/tests/system/autosign/ns3/inaczsk2.example.db.in
new file mode 100644
index 0000000..1376922
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/inaczsk2.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/inaczsk3.example.db.in b/bin/tests/system/autosign/ns3/inaczsk3.example.db.in
new file mode 100644
index 0000000..1376922
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/inaczsk3.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/insecure.example.db b/bin/tests/system/autosign/ns3/insecure.example.db
new file mode 100644
index 0000000..14971bd
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/insecure.example.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/autosign/ns3/jitter.nsec3.example.db.in b/bin/tests/system/autosign/ns3/jitter.nsec3.example.db.in
new file mode 100644
index 0000000..8a96023
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/jitter.nsec3.example.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
diff --git a/bin/tests/system/autosign/ns3/keygen.sh b/bin/tests/system/autosign/ns3/keygen.sh
new file mode 100644
index 0000000..96158b3
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/keygen.sh
@@ -0,0 +1,398 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+SYSTESTDIR=autosign
+
+dumpit () {
+ echo_d "${debug}: dumping ${1}"
+ cat "${1}" | cat_d
+}
+
+setup () {
+ echo_i "setting up zone: $1"
+ debug="$1"
+ zone="$1"
+ zonefile="${zone}.db"
+ infile="${zonefile}.in"
+ n=$((${n:-0} + 1))
+}
+
+setup secure.example
+cp $infile $zonefile
+ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# NSEC3/NSEC test zone
+#
+setup secure.nsec3.example
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# NSEC3/NSEC3 test zone
+#
+setup nsec3.nsec3.example
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# Jitter/NSEC3 test zone
+#
+setup jitter.nsec3.example
+cp $infile $zonefile
+count=1
+while [ $count -le 1000 ]
+do
+ echo "label${count} IN TXT label${count}" >> $zonefile
+ count=$((count + 1))
+done
+# Don't create keys just yet, because the scenario we want to test
+# is an unsigned zone that has a NSEC3PARAM record added with
+# dynamic update before the keys are generated.
+
+#
+# OPTOUT/NSEC3 test zone
+#
+setup optout.nsec3.example
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# A nsec3 zone (non-optout).
+#
+setup nsec3.example
+cat $infile dsset-*.${zone}. > $zonefile
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# An NSEC3 zone, with NSEC3 parameters set prior to signing
+#
+setup autonsec3.example
+cat $infile > $zonefile
+ksk=$($KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+echo $ksk > ../autoksk.key
+zsk=$($KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out) || dumpit kg.out
+echo $zsk > ../autozsk.key
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# OPTOUT/NSEC test zone
+#
+setup secure.optout.example
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# OPTOUT/NSEC3 test zone
+#
+setup nsec3.optout.example
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# OPTOUT/OPTOUT test zone
+#
+setup optout.optout.example
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# A optout nsec3 zone.
+#
+setup optout.example
+cat $infile dsset-*.${zone}. > $zonefile
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# A RSASHA256 zone.
+#
+setup rsasha256.example
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a RSASHA256 -b 2048 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a RSASHA256 -b 2048 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# A RSASHA512 zone.
+#
+setup rsasha512.example
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a RSASHA512 -b 2048 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a RSASHA512 -b 2048 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# NSEC-only zone. A zone using NSEC-only DNSSEC algorithms.
+# None of these algorithms are supported for signing in FIPS mode
+# as they are MD5 and SHA1 based.
+#
+if (cd ..; $SHELL ../testcrypto.sh -q RSASHA1)
+then
+ setup nsec-only.example
+ cp $infile $zonefile
+ ksk=$($KEYGEN -q -a RSASHA1 -fk $zone 2> kg.out) || dumpit kg.out
+ $KEYGEN -q -a RSASHA1 $zone > kg.out 2>&1 || dumpit kg.out
+ $DSFROMKEY $ksk.key > dsset-${zone}.
+else
+ echo_i "skip: nsec-only.example - signing with RSASHA1 not supported"
+fi
+
+#
+# Signature refresh test zone. Signatures are set to expire long
+# in the past; they should be updated by autosign.
+#
+setup oldsigs.example
+cp $infile $zonefile
+count=1
+while [ $count -le 1000 ]
+do
+ echo "label${count} IN TXT label${count}" >> $zonefile
+ count=$((count + 1))
+done
+$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM $zone > kg.out 2>&1 || dumpit kg.out
+$SIGNER -PS -s now-1y -e now-6mo -o $zone -f $zonefile.signed $zonefile > s.out || dumpit s.out
+mv $zonefile.signed $zonefile
+
+#
+# NSEC3->NSEC transition test zone.
+#
+setup nsec3-to-nsec.example
+$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM $zone > kg.out 2>&1 || dumpit kg.out
+$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile > s.out || dumpit s.out
+
+#
+# secure-to-insecure transition test zone; used to test removal of
+# keys via nsupdate
+#
+setup secure-to-insecure.example
+$KEYGEN -a $DEFAULT_ALGORITHM -q -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -q $zone > kg.out 2>&1 || dumpit kg.out
+$SIGNER -S -o $zone -f $zonefile $infile > s.out || dumpit s.out
+
+#
+# another secure-to-insecure transition test zone; used to test
+# removal of keys on schedule.
+#
+setup secure-to-insecure2.example
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+echo $ksk > ../del1.key
+zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out) || dumpit kg.out
+echo $zsk > ../del2.key
+$SIGNER -S -3 beef -o $zone -f $zonefile $infile > s.out || dumpit s.out
+
+#
+# Introducing a pre-published key test.
+#
+setup prepub.example
+infile="secure-to-insecure2.example.db.in"
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out
+$SIGNER -S -3 beef -o $zone -f $zonefile $infile > s.out || dumpit s.out
+
+#
+# Key TTL tests.
+#
+
+# no default key TTL; DNSKEY should get SOA TTL
+setup ttl1.example
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out
+cp $infile $zonefile
+
+# default key TTL should be used
+setup ttl2.example
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -L 60 $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 60 $zone > kg.out 2>&1 || dumpit kg.out
+cp $infile $zonefile
+
+# mismatched key TTLs, should use shortest
+setup ttl3.example
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -L 30 $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 60 $zone > kg.out 2>&1 || dumpit kg.out
+cp $infile $zonefile
+
+# existing DNSKEY RRset, should retain TTL
+setup ttl4.example
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 30 -fk $zone > kg.out 2>&1 || dumpit kg.out
+cat ${infile} K${zone}.+*.key > $zonefile
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 180 $zone > kg.out 2>&1 || dumpit kg.out
+
+#
+# A zone with a DNSKEY RRset that is published before it's activated
+#
+setup delay.example
+ksk=$($KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+echo $ksk > ../delayksk.key
+zsk=$($KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out) || dumpit kg.out
+echo $zsk > ../delayzsk.key
+
+#
+# A zone with signatures that are already expired, and the private KSK
+# is missing.
+#
+setup noksk.example
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out) || dumpit kg.out
+$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out || dumpit s.out
+echo $ksk > ../noksk-ksk.key
+rm -f ${ksk}.private
+
+#
+# A zone with signatures that are already expired, and the private ZSK
+# is missing.
+#
+setup nozsk.example
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out) || dumpit kg.out
+$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out || dumpit s.out
+echo $ksk > ../nozsk-ksk.key
+echo $zsk > ../nozsk-zsk.key
+rm -f ${zsk}.private
+
+#
+# A zone with signatures that are already expired, and the private ZSK
+# is inactive.
+#
+setup inaczsk.example
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2> kg.out) || dumpit kg.out
+$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out || dumpit s.out
+echo $ksk > ../inaczsk-ksk.key
+echo $zsk > ../inaczsk-zsk.key
+$SETTIME -I now $zsk > st.out 2>&1 || dumpit st.out
+
+#
+# A zone that is set to 'auto-dnssec maintain' during a reconfig
+#
+setup reconf.example
+cp secure.example.db.in $zonefile
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+
+#
+# A zone which generates CDS and CDNSEY RRsets automatically
+#
+setup sync.example
+cp $infile $zonefile
+ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -P sync now $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+echo ns3/$ksk > ../sync.key
+
+#
+# A zone that generates CDS and CDNSKEY and uses dnssec-dnskey-kskonly
+#
+setup kskonly.example
+cp $infile $zonefile
+ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -P sync now $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# A zone that has a published inactive key that is autosigned.
+#
+setup inacksk2.example
+cp $infile $zonefile
+ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -Pnow -A now+3600 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# A zone that has a published inactive key that is autosigned.
+#
+setup inaczsk2.example
+cp $infile $zonefile
+ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -P now -A now+3600 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# A zone that starts with a active KSK + ZSK and a inactive ZSK.
+#
+setup inacksk3.example
+cp $infile $zonefile
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -P now -A now+3600 -fk $zone > kg.out 2>&1 || dumpit kg.out
+ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# A zone that starts with a active KSK + ZSK and a inactive ZSK.
+#
+setup inaczsk3.example
+cp $infile $zonefile
+ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -P now -A now+3600 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# A zone that starts with an active KSK + ZSK and an inactive ZSK, with the
+# latter getting deleted during the test.
+#
+setup delzsk.example
+cp $infile $zonefile
+ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone > kg.out 2>&1 || dumpit kg.out
+zsk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -I now-1w $zone 2>kg.out) || dumpit kg.out
+echo $zsk > ../delzsk.key
+
+#
+# Check that NSEC3 are correctly signed and returned from below a DNAME
+#
+setup dname-at-apex-nsec3.example
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# Check that dynamically added CDS (DELETE) is kept in the zone after signing.
+#
+setup cds-delete.example
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
+
+#
+# Check that dynamically added CDNSKEY (DELETE) is kept in the zone after
+# signing.
+#
+setup cdnskey-delete.example
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2> kg.out) || dumpit kg.out
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}.
diff --git a/bin/tests/system/autosign/ns3/kskonly.example.db.in b/bin/tests/system/autosign/ns3/kskonly.example.db.in
new file mode 100644
index 0000000..c6c7f88
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/kskonly.example.db.in
@@ -0,0 +1,34 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
diff --git a/bin/tests/system/autosign/ns3/named.conf.in b/bin/tests/system/autosign/ns3/named.conf.in
new file mode 100644
index 0000000..64196a1
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/named.conf.in
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+ dnssec-loadkeys-interval 10;
+ allow-new-zones yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "example.bk";
+};
+
+zone "bar" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "bar.bk";
+};
+
+zone "secure.example" {
+ type primary;
+ file "secure.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "insecure.example" {
+ type primary;
+ file "insecure.example.db";
+};
+
+zone "nsec3.example" {
+ type primary;
+ file "nsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "autonsec3.example" {
+ type primary;
+ file "autonsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "optout.nsec3.example" {
+ type primary;
+ file "optout.nsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "nsec3.nsec3.example" {
+ type primary;
+ file "nsec3.nsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "jitter.nsec3.example" {
+ type primary;
+ file "jitter.nsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+ sig-validity-interval 10 2;
+ sig-signing-nodes 1000;
+ sig-signing-signatures 100;
+};
+
+zone "secure.nsec3.example" {
+ type primary;
+ file "secure.nsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "optout.example" {
+ type primary;
+ file "optout.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "secure.optout.example" {
+ type primary;
+ file "secure.optout.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "nsec3.optout.example" {
+ type primary;
+ file "nsec3.optout.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "optout.optout.example" {
+ type primary;
+ file "optout.optout.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "rsasha256.example" {
+ type primary;
+ file "rsasha256.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "rsasha512.example" {
+ type primary;
+ file "rsasha512.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "nsec-only.example" {
+ type primary;
+ file "nsec-only.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "nsec3-to-nsec.example" {
+ type primary;
+ file "nsec3-to-nsec.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "secure-to-insecure.example" {
+ type primary;
+ file "secure-to-insecure.example.db";
+ allow-update { any; };
+ dnssec-secure-to-insecure yes;
+};
+
+zone "secure-to-insecure2.example" {
+ type primary;
+ file "secure-to-insecure2.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+ dnssec-secure-to-insecure yes;
+};
+
+zone "oldsigs.example" {
+ type primary;
+ file "oldsigs.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+ sig-validity-interval 10 2;
+ sig-signing-nodes 1000;
+ sig-signing-signatures 100;
+};
+
+zone "prepub.example" {
+ type primary;
+ file "prepub.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "ttl1.example" {
+ type primary;
+ file "ttl1.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "ttl2.example" {
+ type primary;
+ file "ttl2.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "ttl3.example" {
+ type primary;
+ file "ttl3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "ttl4.example" {
+ type primary;
+ file "ttl4.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "delay.example" {
+ type primary;
+ file "delay.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "nozsk.example" {
+ type primary;
+ file "nozsk.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "inaczsk.example" {
+ type primary;
+ file "inaczsk.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "noksk.example" {
+ type primary;
+ file "noksk.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "sync.example" {
+ type primary;
+ file "sync.example.db";
+ allow-update { any; };
+ dnssec-dnskey-kskonly no;
+ auto-dnssec maintain;
+};
+
+zone "kskonly.example" {
+ type primary;
+ file "kskonly.example.db";
+ allow-update { any; };
+ dnssec-dnskey-kskonly yes;
+ auto-dnssec maintain;
+};
+
+zone "inacksk2.example" {
+ type primary;
+ file "inacksk2.example.db";
+ allow-update { any; };
+ dnssec-dnskey-kskonly yes;
+ auto-dnssec maintain;
+};
+
+zone "inacksk3.example" {
+ type primary;
+ file "inacksk3.example.db";
+ allow-update { any; };
+ dnssec-dnskey-kskonly yes;
+ auto-dnssec maintain;
+};
+
+zone "inaczsk2.example" {
+ type primary;
+ file "inaczsk2.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "inaczsk3.example" {
+ type primary;
+ file "inaczsk3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "delzsk.example." {
+ type primary;
+ file "delzsk.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "dname-at-apex-nsec3.example" {
+ type primary;
+ file "dname-at-apex-nsec3.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "cds-delete.example" {
+ type primary;
+ file "cds-delete.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "cdnskey-delete.example" {
+ type primary;
+ file "cdnskey-delete.example.db";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/autosign/ns3/noksk.example.db.in b/bin/tests/system/autosign/ns3/noksk.example.db.in
new file mode 100644
index 0000000..1376922
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/noksk.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/nozsk.example.db.in b/bin/tests/system/autosign/ns3/nozsk.example.db.in
new file mode 100644
index 0000000..1376922
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nozsk.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/nsec-only.example.db.in b/bin/tests/system/autosign/ns3/nsec-only.example.db.in
new file mode 100644
index 0000000..0b11a00
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nsec-only.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/nsec3-to-nsec.example.db.in b/bin/tests/system/autosign/ns3/nsec3-to-nsec.example.db.in
new file mode 100644
index 0000000..0b11a00
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nsec3-to-nsec.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/nsec3.example.db.in b/bin/tests/system/autosign/ns3/nsec3.example.db.in
new file mode 100644
index 0000000..17964e8
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nsec3.example.db.in
@@ -0,0 +1,37 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+child NS ns2.example.
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17
diff --git a/bin/tests/system/autosign/ns3/nsec3.nsec3.example.db.in b/bin/tests/system/autosign/ns3/nsec3.nsec3.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nsec3.nsec3.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/autosign/ns3/nsec3.optout.example.db.in b/bin/tests/system/autosign/ns3/nsec3.optout.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/nsec3.optout.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/autosign/ns3/oldsigs.example.db.in b/bin/tests/system/autosign/ns3/oldsigs.example.db.in
new file mode 100644
index 0000000..0b11a00
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/oldsigs.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/optout.example.db.in b/bin/tests/system/autosign/ns3/optout.example.db.in
new file mode 100644
index 0000000..fbb05af
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/optout.example.db.in
@@ -0,0 +1,38 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+child NS ns2.example.
+insecure.empty NS ns.insecure.empty
+ns.insecure.empty A 10.53.0.3
diff --git a/bin/tests/system/autosign/ns3/optout.nsec3.example.db.in b/bin/tests/system/autosign/ns3/optout.nsec3.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/optout.nsec3.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/autosign/ns3/optout.optout.example.db.in b/bin/tests/system/autosign/ns3/optout.optout.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/optout.optout.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/autosign/ns3/rsasha256.example.db.in b/bin/tests/system/autosign/ns3/rsasha256.example.db.in
new file mode 100644
index 0000000..f6c4fab
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/rsasha256.example.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/rsasha512.example.db.in b/bin/tests/system/autosign/ns3/rsasha512.example.db.in
new file mode 100644
index 0000000..f6c4fab
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/rsasha512.example.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/secure-to-insecure.example.db.in b/bin/tests/system/autosign/ns3/secure-to-insecure.example.db.in
new file mode 100644
index 0000000..14971bd
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/secure-to-insecure.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/autosign/ns3/secure-to-insecure2.example.db.in b/bin/tests/system/autosign/ns3/secure-to-insecure2.example.db.in
new file mode 100644
index 0000000..14971bd
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/secure-to-insecure2.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/autosign/ns3/secure.example.db.in b/bin/tests/system/autosign/ns3/secure.example.db.in
new file mode 100644
index 0000000..9855ec0
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/secure.example.db.in
@@ -0,0 +1,37 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
+dname-and-txt DNAME @
+ TXT "DNAME and TXT"
diff --git a/bin/tests/system/autosign/ns3/secure.nsec3.example.db.in b/bin/tests/system/autosign/ns3/secure.nsec3.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/secure.nsec3.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/autosign/ns3/secure.optout.example.db.in b/bin/tests/system/autosign/ns3/secure.optout.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/secure.optout.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/autosign/ns3/sync.example.db.in b/bin/tests/system/autosign/ns3/sync.example.db.in
new file mode 100644
index 0000000..c6c7f88
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/sync.example.db.in
@@ -0,0 +1,34 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
diff --git a/bin/tests/system/autosign/ns3/ttl1.example.db.in b/bin/tests/system/autosign/ns3/ttl1.example.db.in
new file mode 100644
index 0000000..0b11a00
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/ttl1.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/ttl2.example.db.in b/bin/tests/system/autosign/ns3/ttl2.example.db.in
new file mode 100644
index 0000000..0b11a00
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/ttl2.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/ttl3.example.db.in b/bin/tests/system/autosign/ns3/ttl3.example.db.in
new file mode 100644
index 0000000..0b11a00
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/ttl3.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns3/ttl4.example.db.in b/bin/tests/system/autosign/ns3/ttl4.example.db.in
new file mode 100644
index 0000000..0b11a00
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/ttl4.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/autosign/ns4/named.conf.in b/bin/tests/system/autosign/ns4/named.conf.in
new file mode 100644
index 0000000..b46ce91
--- /dev/null
+++ b/bin/tests/system/autosign/ns4/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+ dnssec-must-be-secure mustbesecure.example yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
+include "private.conf";
diff --git a/bin/tests/system/autosign/ns5/named.conf.in b/bin/tests/system/autosign/ns5/named.conf.in
new file mode 100644
index 0000000..710dfa8
--- /dev/null
+++ b/bin/tests/system/autosign/ns5/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/autosign/setup.sh b/bin/tests/system/autosign/setup.sh
new file mode 100644
index 0000000..e029fdf
--- /dev/null
+++ b/bin/tests/system/autosign/setup.sh
@@ -0,0 +1,23 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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
+
+echo_i "generating keys and preparing zones"
+cd ns1 && $SHELL keygen.sh
diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh
new file mode 100755
index 0000000..ad23c22
--- /dev/null
+++ b/bin/tests/system/autosign/tests.sh
@@ -0,0 +1,1800 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+# convert private-type records to readable form
+# $1 is the zone
+# $2 is the server
+# $3 is ignored
+# $4 is the alternate type
+showprivate () {
+ echo "-- $@ --"
+ $DIG $DIGOPTS +nodnssec +short @$2 -t ${4:-type65534} $1 | cut -f3 -d' ' |
+ while read record; do
+ $PERL -e 'my $rdata = pack("H*", @ARGV[0]);
+ die "invalid record" unless length($rdata) == 5;
+ my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata);
+ my $action = "signing";
+ $action = "removing" if $remove;
+ my $state = " (incomplete)";
+ $state = " (complete)" if $complete;
+ print ("$action: alg: $alg, key: $key$state\n");' $record
+ done
+}
+
+# check that signing records are marked as complete
+# if $3 is 1 then we are expecting "(incomplete)"
+# if $3 is 2 then we are not expecting either "(complete)" or "(incomplete)"
+# if $4 is present then that specifies any alternate type to check
+checkprivate () {
+ _ret=0
+ expected="${3:-0}"
+ x=$(showprivate "$@")
+ echo $x | grep "(complete)" > /dev/null || _ret=2
+ echo $x | grep "(incomplete)" > /dev/null && _ret=1
+
+ if [ $_ret = $expected ]; then
+ return 0
+ fi
+
+ echo "$x"
+ echo_i "failed"
+ return 1
+}
+
+# wait until notifies for zone $1 are sent by server $2. This is an indication
+# that the zone is signed with the active keys, and the changes have been
+# committed.
+wait_for_notifies () {
+ wait_for_log 10 "zone ${1}/IN: sending notifies" "${2}/named.run" || return 1
+}
+
+freq() {
+ _file=$1
+ # remove first and last line that has incomplete set and skews the distribution
+ awk '$4 == "RRSIG" {print substr($9,1,8)}' < "$_file" | sort | uniq -c | sed '1d;$d'
+}
+# Check the signatures expiration times. First check how many signatures
+# there are in total ($rrsigs). Then see what the distribution of signature
+# expiration times is ($expiretimes). Ignore the time part for a better
+# modelled distribution.
+checkjitter () {
+ _file=$1
+ _ret=0
+
+ if ! command -v bc >/dev/null 2>&1; then
+ echo_i "skip: bc not available"
+ return 0
+ fi
+
+ freq "$_file" | cat_i
+ _expiretimes=$(freq "$_file" | awk '{print $1}')
+
+ _count=0
+ # Check if we have at least 4 days
+ # This number has been tuned for `sig-validity-interval 10 2`, as
+ # 1 signature expiration dates should be spread out across at most 8 (10-2) days
+ # 2. we remove first and last day to remove frequency outlier, we are left with 6 (8-2) days
+ # 3. we subtract two more days to allow test pass on day boundaries, etc. leaving us with 4 (6-2)
+ for _num in $_expiretimes
+ do
+ _count=$((_count+1))
+ done
+ if [ "$_count" -lt 4 ]; then
+ echo_i "error: not enough categories"
+ return 1
+ fi
+
+ # Calculate mean
+ _total=0
+ for _num in $_expiretimes
+ do
+ _total=$((_total+_num))
+ done
+ _mean=$(($_total / $_count))
+
+ # Calculate stddev
+ _stddev=0
+ for _num in $_expiretimes
+ do
+ _stddev=$(echo "$_stddev + (($_num - $_mean) * ($_num - $_mean))" | bc)
+ done
+ _stddev=$(echo "sqrt($_stddev/$_count)" | bc)
+
+ # We expect the number of signatures not to exceed the mean +- 3 * stddev.
+ _limit=$((_stddev*3))
+ _low=$((_mean-_limit))
+ _high=$((_mean+_limit))
+ # Find outliers.
+ echo_i "checking whether all frequencies fall into <$_low;$_high> range"
+ for _num in $_expiretimes
+ do
+ if [ $_num -gt $_high ]; then
+ echo_i "error: too many RRSIG records ($_num) in expiration bucket"
+ _ret=1
+ fi
+ if [ $_num -lt $_low ]; then
+ echo_i "error: too few RRSIG records ($_num) in expiration bucket"
+ _ret=1
+ fi
+ done
+
+ return $_ret
+}
+
+#
+# The NSEC record at the apex of the zone and its RRSIG records are
+# added as part of the last step in signing a zone. We wait for the
+# NSEC records to appear before proceeding with a counter to prevent
+# infinite loops if there is a error.
+#
+echo_i "waiting for autosign changes to take effect"
+i=0
+while [ $i -lt 30 ]
+do
+ ret=0
+ #
+ # Wait for the root DNSKEY RRset to be fully signed.
+ #
+ $DIG $DIGOPTS . @10.53.0.1 dnskey > dig.out.ns1.test$n || ret=1
+ grep "ANSWER: 10," dig.out.ns1.test$n > /dev/null || ret=1
+ for z in .
+ do
+ $DIG $DIGOPTS $z @10.53.0.1 nsec > dig.out.ns1.test$n || ret=1
+ grep "NS SOA" dig.out.ns1.test$n > /dev/null || ret=1
+ done
+ for z in bar. example. private.secure.example. optout-with-ent.
+ do
+ $DIG $DIGOPTS $z @10.53.0.2 nsec > dig.out.ns2.test$n || ret=1
+ grep "NS SOA" dig.out.ns2.test$n > /dev/null || ret=1
+ done
+ for z in bar. example. inacksk2.example. inacksk3.example \
+ inaczsk2.example. inaczsk3.example noksk.example nozsk.example
+ do
+ $DIG $DIGOPTS $z @10.53.0.3 nsec > dig.out.ns3.test$n || ret=1
+ grep "NS SOA" dig.out.ns3.test$n > /dev/null || ret=1
+ done
+ i=$((i + 1))
+ if [ $ret = 0 ]; then break; fi
+ echo_i "waiting ... ($i)"
+ sleep 2
+done
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "done"; fi
+status=$((status + ret))
+
+echo_i "Convert optout-with-ent from nsec to nsec3"
+($RNDCCMD 10.53.0.2 signing -nsec3param 1 1 1 - optout-with-ent 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1
+
+echo_i "Initial counts of RRSIG expiry fields values for auto signed zones"
+for z in .
+do
+ echo_i zone $z
+ $DIG $DIGOPTS $z @10.53.0.1 axfr | awk '$4 == "RRSIG" {print $9}' | sort | uniq -c | cat_i
+done
+for z in bar. example. private.secure.example.
+do
+ echo_i zone $z
+ $DIG $DIGOPTS $z @10.53.0.2 axfr | awk '$4 == "RRSIG" {print $9}' | sort | uniq -c | cat_i
+done
+for z in inacksk2.example. inacksk3.example inaczsk2.example. inaczsk3.example
+do
+ echo_i zone $z
+ $DIG $DIGOPTS $z @10.53.0.3 axfr | awk '$4 == "RRSIG" {print $9}' | sort | uniq -c | cat_i
+done
+
+# Set logfile offset for wait_for_log usage.
+nextpartreset ns3/named.run
+
+#
+# Check that DNSKEY is initially signed with a KSK and not a ZSK.
+#
+echo_i "check that zone with active and inactive KSK and active ZSK is properly"
+echo_ic "resigned after the active KSK is deleted - stage 1: Verify that DNSKEY"
+echo_ic "is initially signed with a KSK and not a ZSK. ($n)"
+ret=0
+
+$DIG $DIGOPTS @10.53.0.3 axfr inacksk3.example > dig.out.ns3.test$n
+
+zskid=$(awk '$4 == "DNSKEY" && $5 == 256 { print }' dig.out.ns3.test$n |
+ $DSFROMKEY -A -2 -f - inacksk3.example | awk '{ print $4}')
+grep "DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 2 " dig.out.ns3.test$n > /dev/null || ret=1
+
+pattern="DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 2 [0-9]* [0-9]* [0-9]* ${zskid} "
+grep "${pattern}" dig.out.ns3.test$n > /dev/null && ret=1
+
+count=$(awk 'BEGIN { count = 0 }
+ $4 == "RRSIG" && $5 == "DNSKEY" { count++ }
+ END {print count}' dig.out.ns3.test$n)
+test $count -eq 1 || ret=1
+
+count=$(awk 'BEGIN { count = 0 }
+ $4 == "DNSKEY" { count++ }
+ END {print count}' dig.out.ns3.test$n)
+test $count -eq 3 || ret=1
+
+awk='$4 == "RRSIG" && $5 == "DNSKEY" { printf "%05u\n", $11 }'
+id=$(awk "${awk}" dig.out.ns3.test$n)
+
+keyfile=$(printf "ns3/Kinacksk3.example.+%03u+%s" "${DEFAULT_ALGORITHM_NUMBER}" "${id}")
+$SETTIME -D now+5 "${keyfile}" > settime.out.test$n || ret=1
+($RNDCCMD 10.53.0.3 loadkeys inacksk3.example 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1
+
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#
+# Check that zone is initially signed with a ZSK and not a KSK.
+#
+echo_i "check that zone with active and inactive ZSK and active KSK is properly"
+echo_ic "resigned after the active ZSK is deleted - stage 1: Verify that zone"
+echo_ic "is initially signed with a ZSK and not a KSK. ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 axfr inaczsk3.example > dig.out.ns3.test$n
+kskid=$(awk '$4 == "DNSKEY" && $5 == 257 { print }' dig.out.ns3.test$n |
+ $DSFROMKEY -2 -f - inaczsk3.example | awk '{ print $4}' )
+grep "CNAME ${DEFAULT_ALGORITHM_NUMBER} 3 " dig.out.ns3.test$n > /dev/null || ret=1
+grep "CNAME ${DEFAULT_ALGORITHM_NUMBER} 3 [0-9]* [0-9]* [0-9]* ${kskid} " dig.out.ns3.test$n > /dev/null && ret=1
+count=$(awk 'BEGIN { count = 0 }
+ $4 == "RRSIG" && $5 == "CNAME" { count++ }
+ END {print count}' dig.out.ns3.test$n)
+test $count -eq 1 || ret=1
+count=$(awk 'BEGIN { count = 0 }
+ $4 == "DNSKEY" { count++ }
+ END {print count}' dig.out.ns3.test$n)
+test $count -eq 3 || ret=1
+id=$(awk '$4 == "RRSIG" && $5 == "CNAME" { printf "%05u\n", $11 }' dig.out.ns3.test$n)
+
+keyfile=$(printf "ns3/Kinaczsk3.example.+%03u+%s" "${DEFAULT_ALGORITHM_NUMBER}" "${id}")
+$SETTIME -D now+5 "${keyfile}" > settime.out.test$n || ret=1
+($RNDCCMD 10.53.0.3 loadkeys inaczsk3.example 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NSEC->NSEC3 conversion prerequisites ($n)"
+ret=0
+# these commands should result in an empty file:
+$DIG $DIGOPTS +noall +answer nsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.1.test$n || ret=1
+grep "NSEC3PARAM" dig.out.ns3.1.test$n > /dev/null && ret=1
+$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.2.test$n || ret=1
+grep "NSEC3PARAM" dig.out.ns3.2.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NSEC3->NSEC conversion prerequisites ($n)"
+ret=0
+$DIG $DIGOPTS +noall +answer nsec3-to-nsec.example. nsec3param @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "NSEC3PARAM" dig.out.ns3.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "converting zones from nsec to nsec3"
+$NSUPDATE > /dev/null 2>&1 <<END || status=1
+server 10.53.0.3 ${PORT}
+zone nsec3.nsec3.example.
+update add nsec3.nsec3.example. 3600 NSEC3PARAM 1 0 10 BEEF
+send
+zone optout.nsec3.example.
+update add optout.nsec3.example. 3600 NSEC3PARAM 1 1 10 BEEF
+send
+zone nsec3.example.
+update add nsec3.example. 3600 NSEC3PARAM 1 0 10 BEEF
+send
+zone autonsec3.example.
+update add autonsec3.example. 3600 NSEC3PARAM 1 0 20 DEAF
+send
+zone nsec3.optout.example.
+update add nsec3.optout.example. 3600 NSEC3PARAM 1 0 10 BEEF
+send
+zone optout.optout.example.
+update add optout.optout.example. 3600 NSEC3PARAM 1 1 10 BEEF
+send
+zone optout.example.
+update add optout.example. 3600 NSEC3PARAM 1 1 10 BEEF
+send
+END
+
+if $SHELL ../testcrypto.sh -q RSASHA1
+then
+ # try to convert nsec-only.example; this should fail due to
+ # non-NSEC3 compatible keys
+ echo_i "preset nsec3param in unsigned zone via nsupdate ($n)"
+ ret=0
+ $NSUPDATE > nsupdate.out 2>&1 <<END && ret=1
+server 10.53.0.3 ${PORT}
+zone nsec-only.example.
+update add nsec-only.example. 3600 NSEC3PARAM 1 0 10 BEEF
+send
+END
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+echo_i "checking for nsec3param in unsigned zone ($n)"
+ret=0
+$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "NSEC3PARAM" dig.out.ns3.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking for nsec3param signing record ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 signing -list autonsec3.example. > signing.out.test$n 2>&1
+grep "Pending NSEC3 chain 1 0 20 DEAF" signing.out.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "resetting nsec3param via rndc signing ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 signing -clear all autonsec3.example. > /dev/null 2>&1
+$RNDCCMD 10.53.0.3 signing -nsec3param 1 1 10 beef autonsec3.example. > /dev/null 2>&1
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ ret=0
+ $RNDCCMD 10.53.0.3 signing -list autonsec3.example. > signing.out.test$n 2>&1
+ grep "Pending NSEC3 chain 1 1 10 BEEF" signing.out.test$n > /dev/null || ret=1
+ num=$(grep "Pending " signing.out.test$n | wc -l)
+ [ $num -eq 1 ] || ret=1
+ [ $ret -eq 0 ] && break
+ echo_i "waiting ... ($i)"
+ sleep 2
+done
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "signing preset nsec3 zone"
+zsk=$(cat autozsk.key)
+ksk=$(cat autoksk.key)
+$SETTIME -K ns3 -P now -A now $zsk > settime.out.test$n.zsk || ret=1
+$SETTIME -K ns3 -P now -A now $ksk > settime.out.test$n.ksk || ret=1
+($RNDCCMD 10.53.0.3 loadkeys autonsec3.example. 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1
+
+echo_i "waiting for changes to take effect"
+sleep 3
+
+echo_i "converting zone from nsec3 to nsec"
+$NSUPDATE > /dev/null 2>&1 << END || status=1
+server 10.53.0.3 ${PORT}
+zone nsec3-to-nsec.example.
+update delete nsec3-to-nsec.example. NSEC3PARAM
+send
+END
+
+echo_i "waiting for change to take effect"
+sleep 3
+
+missing=$(keyfile_to_key_id "$(cat noksk-ksk.key)")
+echo_i "checking that expired RRSIGs from missing KSK $missing are not deleted ($n)"
+ret=0
+$JOURNALPRINT ns3/noksk.example.db.jnl | \
+ awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {error=1}} END {exit error}' id=$missing || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+missing=$(keyfile_to_key_id "$(cat nozsk-zsk.key)")
+ksk=$(keyfile_to_key_id "$(cat nozsk-ksk.key)")
+echo_i "checking that expired RRSIGs from missing ZSK $missing are replaced ($n)"
+ret=0
+$JOURNALPRINT ns3/nozsk.example.db.jnl | \
+ awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$missing || ret=1
+$JOURNALPRINT ns3/nozsk.example.db.jnl | \
+ awk '{if ($1 == "add" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$ksk || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+inactive=$(keyfile_to_key_id "$(cat inaczsk-zsk.key)")
+ksk=$(keyfile_to_key_id "$(cat inaczsk-ksk.key)")
+echo_i "checking that expired RRSIGs from inactive ZSK $inactive are replaced ($n)"
+ret=0
+$JOURNALPRINT ns3/inaczsk.example.db.jnl | \
+ awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$inactive || ret=1
+$JOURNALPRINT ns3/inaczsk.example.db.jnl | \
+ awk '{if ($1 == "add" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$ksk || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that replaced RRSIGs are not logged (missing ZSK private key) ($n)"
+ret=0
+loglines=$(grep "Key nozsk.example/$DEFAULT_ALGORITHM/$missing .* retaining signatures" ns3/named.run | wc -l)
+[ "$loglines" -eq 0 ] || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that replaced RRSIGs are not logged (inactive ZSK private key) ($n)"
+ret=0
+loglines=$(grep "Key inaczsk.example/$DEFAULT_ALGORITHM/$inactive .* retaining signatures" ns3/named.run | wc -l)
+[ "$loglines" -eq 0 ] || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Send rndc sync command to ns1, ns2 and ns3, to force the dynamically
+# signed zones to be dumped to their zone files
+echo_i "dumping zone files"
+($RNDCCMD 10.53.0.1 sync 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1
+($RNDCCMD 10.53.0.2 sync 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1
+($RNDCCMD 10.53.0.3 sync 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1
+
+now="$(TZ=UTC date +%Y%m%d%H%M%S)"
+check_expiry() (
+ $DIG $DIGOPTS AXFR oldsigs.example @10.53.0.3 > dig.out.test$n
+ nearest_expiration="$(awk '$4 == "RRSIG" { print $9 }' < dig.out.test$n | sort -n | head -1)"
+ if [ "$nearest_expiration" -le "$now" ]; then
+ echo_i "failed: $nearest_expiration <= $now"
+ return 1
+ fi
+)
+
+echo_i "checking expired signatures were updated ($n)"
+retry 10 check_expiry || ret=1
+$DIG $DIGOPTS +noauth a.oldsigs.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.oldsigs.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check jitter distribution.
+echo_i "checking expired signatures were jittered correctly ($n)"
+ret=0
+$DIG $DIGOPTS axfr oldsigs.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
+checkjitter dig.out.ns3.test$n || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NSEC->NSEC3 conversion succeeded ($n)"
+ret=0
+$DIG $DIGOPTS nsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.ok.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.ok.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +noauth q.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth q.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking direct NSEC3 autosigning succeeded ($n)"
+ret=0
+$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.ok.test$n || ret=1
+[ -s dig.out.ns3.ok.test$n ] || ret=1
+grep "NSEC3PARAM" dig.out.ns3.ok.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NSEC->NSEC3 conversion failed with NSEC-only key ($n)"
+ret=0
+if $SHELL ../testcrypto.sh -q RSASHA1
+then
+ grep "failed: REFUSED" nsupdate.out > /dev/null || ret=1
+else
+ echo_i "skip: RSASHA1 not supported"
+fi
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NSEC3->NSEC conversion succeeded ($n)"
+ret=0
+# this command should result in an empty file:
+$DIG $DIGOPTS +noall +answer nsec3-to-nsec.example. nsec3param @10.53.0.3 > dig.out.ns3.nx.test$n || ret=1
+grep "NSEC3PARAM" dig.out.ns3.nx.test$n > /dev/null && ret=1
+$DIG $DIGOPTS +noauth q.nsec3-to-nsec.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth q.nsec3-to-nsec.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NSEC3->NSEC conversion with 'rndc signing -nsec3param none' ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 signing -nsec3param none autonsec3.example. > /dev/null 2>&1
+# this command should result in an empty file:
+no_nsec3param() (
+ $DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.nx.test$n || return 1
+ grep "NSEC3PARAM" dig.out.ns3.nx.test$n > /dev/null && return 1
+ return 0
+)
+retry_quiet 10 no_nsec3param || ret=1
+$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTLs of imported DNSKEYs (no default) ($n)"
+ret=0
+$DIG $DIGOPTS +tcp +noall +answer dnskey ttl1.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
+[ -s dig.out.ns3.test$n ] || ret=1
+(awk 'BEGIN {r=0} $2 != 300 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTLs of imported DNSKEYs (with default) ($n)"
+ret=0
+$DIG $DIGOPTS +tcp +noall +answer dnskey ttl2.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
+[ -s dig.out.ns3.test$n ] || ret=1
+(awk 'BEGIN {r=0} $2 != 60 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTLs of imported DNSKEYs (mismatched) ($n)"
+ret=0
+$DIG $DIGOPTS +tcp +noall +answer dnskey ttl3.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
+[ -s dig.out.ns3.test$n ] || ret=1
+(awk 'BEGIN {r=0} $2 != 30 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTLs of imported DNSKEYs (existing RRset) ($n)"
+ret=0
+$DIG $DIGOPTS +tcp +noall +answer dnskey ttl4.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
+[ -s dig.out.ns3.test$n ] || ret=1
+(awk 'BEGIN {r=0} $2 != 30 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking positive validation NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking positive validation NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking positive validation OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking negative validation NXDOMAIN NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth q.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth q.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking negative validation NXDOMAIN NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth q.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth q.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking negative validation NXDOMAIN OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth q.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth q.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking negative validation NODATA NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth a.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking negative validation NODATA NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking negative validation NODATA OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check the insecure.example domain
+
+echo_i "checking 1-server insecurity proof NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking 1-server negative insecurity proof NSEC ($n)"
+ret=0
+$DIG $DIGOPTS q.insecure.example. a @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS q.insecure.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check the secure.example domain
+
+echo_i "checking multi-stage positive validation NSEC/NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.secure.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.secure.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking multi-stage positive validation NSEC/NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking multi-stage positive validation NSEC/OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking multi-stage positive validation NSEC3/NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.secure.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.secure.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking multi-stage positive validation NSEC3/NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking multi-stage positive validation NSEC3/OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.optout.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.optout.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking multi-stage positive validation OPTOUT/NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.secure.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.secure.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking multi-stage positive validation OPTOUT/NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.nsec3.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.nsec3.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking multi-stage positive validation OPTOUT/OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.optout.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.optout.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking empty NODATA OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth empty.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth empty.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+#grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check the insecure.secure.example domain (insecurity proof)
+
+echo_i "checking 2-server insecurity proof ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.2 a \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.4 a \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check a negative response in insecure.secure.example
+
+echo_i "checking 2-server insecurity proof with a negative answer ($n)"
+ret=0
+$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.2 a > dig.out.ns2.test$n \
+ || ret=1
+$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.4 a > dig.out.ns4.test$n \
+ || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking security root query ($n)"
+ret=0
+$DIG $DIGOPTS . @10.53.0.4 key > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking positive validation RSASHA256 NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.rsasha256.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.rsasha256.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking positive validation RSASHA512 NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.rsasha512.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.rsasha512.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that positive validation in a privately secure zone works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that negative validation in a privately secure zone works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking privately secure to nxdomain works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Try validating with a revoked trusted key.
+# This should fail.
+
+echo_i "checking that validation returns insecure due to revoked trusted key ($n)"
+ret=0
+$DIG $DIGOPTS example. soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "flags:.*; QUERY" dig.out.ns5.test$n > /dev/null || ret=1
+grep "flags:.* ad.*; QUERY" dig.out.ns5.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that revoked key is present ($n)"
+ret=0
+id=$(cat rev.key)
+$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that revoked key self-signs ($n)"
+ret=0
+id=$(cat rev.key)
+$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking for unpublished key ($n)"
+ret=0
+id=$(keyfile_to_key_id "$(cat unpub.key)")
+$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking for activated but unpublished key ($n)"
+ret=0
+id=$(keyfile_to_key_id "$(cat activate-now-publish-1day.key)")
+$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that standby key does not sign records ($n)"
+ret=0
+id=$(keyfile_to_key_id "$(cat standby.key)")
+$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that deactivated key does not sign records ($n)"
+ret=0
+id=$(keyfile_to_key_id "$(cat inact.key)")
+$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking insertion of public-only key ($n)"
+ret=0
+id=$(keyfile_to_key_id "$(cat nopriv.key)")
+file="ns1/$(cat nopriv.key).key"
+keydata=$(grep DNSKEY $file)
+$NSUPDATE > /dev/null 2>&1 <<END || status=1
+server 10.53.0.1 ${PORT}
+zone .
+ttl 3600
+update add $keydata
+send
+END
+sleep 1
+$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking key deletion ($n)"
+ret=0
+id=$(keyfile_to_key_id "$(cat del.key)")
+$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking secure-to-insecure transition, nsupdate ($n)"
+ret=0
+$NSUPDATE > /dev/null 2>&1 <<END || status=1
+server 10.53.0.3 ${PORT}
+zone secure-to-insecure.example
+update delete secure-to-insecure.example dnskey
+send
+END
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ ret=0
+ $DIG $DIGOPTS axfr secure-to-insecure.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
+ grep -E '(RRSIG|DNSKEY|NSEC)' dig.out.ns3.test$n > /dev/null && ret=1
+ [ $ret -eq 0 ] && break
+ echo_i "waiting ... ($i)"
+ sleep 2
+done
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking secure-to-insecure transition, scheduled ($n)"
+ret=0
+file="ns3/$(cat del1.key).key"
+$SETTIME -I now -D now $file > settime.out.test$n.1 || ret=1
+file="ns3/$(cat del2.key).key"
+$SETTIME -I now -D now $file > settime.out.test$n.2 || ret=1
+($RNDCCMD 10.53.0.3 sign secure-to-insecure2.example. 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ ret=0
+ $DIG $DIGOPTS axfr secure-to-insecure2.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
+ grep -E '(RRSIG|DNSKEY|NSEC3)' dig.out.ns3.test$n > /dev/null && ret=1
+ [ $ret -eq 0 ] && break
+ echo_i "waiting ... ($i)"
+ sleep 2
+done
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking jitter in a newly signed NSEC3 zone ($n)"
+ret=0
+# Use DNS UPDATE to add an NSEC3PARAM record into the zone.
+$NSUPDATE > nsupdate.out.test$n 2>&1 <<END || ret=1
+server 10.53.0.3 ${PORT}
+zone jitter.nsec3.example.
+update add jitter.nsec3.example. 3600 NSEC3PARAM 1 0 10 BEEF
+send
+END
+[ $ret != 0 ] && echo_i "error: dynamic update add NSEC3PARAM failed"
+# Create DNSSEC keys in the zone directory.
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -K ns3 jitter.nsec3.example > /dev/null
+# Trigger zone signing.
+($RNDCCMD 10.53.0.3 sign jitter.nsec3.example. 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1
+# Wait until zone has been signed.
+check_if_nsec3param_exists() {
+ $DIG $DIGOPTS NSEC3PARAM jitter.nsec3.example @10.53.0.3 > dig.out.ns3.1.test$n || return 1
+ grep -q "^jitter\.nsec3\.example\..*NSEC3PARAM" dig.out.ns3.1.test$n || return 1
+}
+retry_quiet 40 check_if_nsec3param_exists || {
+ echo_i "error: NSEC3PARAM not present yet"
+ ret=1
+}
+$DIG $DIGOPTS AXFR jitter.nsec3.example @10.53.0.3 > dig.out.ns3.2.test$n || ret=1
+# Check jitter distribution.
+checkjitter dig.out.ns3.2.test$n || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that serial number and RRSIGs are both updated (rt21045) ($n)"
+ret=0
+oldserial=$($DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '$0 !~ /SOA/ {print $3}')
+oldinception=$($DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '/SOA/ {print $6}' | sort -u)
+
+$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -K ns3 -P 0 -A +6d -I +38d -D +45d prepub.example > /dev/null
+
+($RNDCCMD 10.53.0.3 sign prepub.example 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1
+newserial=$oldserial
+try=0
+while [ $oldserial -eq $newserial -a $try -lt 42 ]
+do
+ newserial=$($DIG $DIGOPTS +short soa prepub.example @10.53.0.3 |
+ awk '$0 !~ /SOA/ {print $3}')
+ sleep 1
+ try=$((try + 1))
+done
+newinception=$($DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '/SOA/ {print $6}' | sort -u)
+#echo "$oldserial : $newserial"
+#echo "$oldinception : $newinception"
+
+[ "$oldserial" = "$newserial" ] && ret=1
+[ "$oldinception" = "$newinception" ] && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "preparing to test key change corner cases"
+echo_i "removing a private key file"
+file="ns1/$(cat vanishing.key).private"
+rm -f $file
+
+echo_i "preparing ZSK roll"
+starttime=$($PERL -e 'print time(), "\n";')
+oldfile=$(cat active.key)
+oldid=$(keyfile_to_key_id "$(cat active.key)")
+newfile=$(cat standby.key)
+newid=$(keyfile_to_key_id "$(cat standby.key)")
+$SETTIME -K ns1 -I now+2s -D now+25 $oldfile > settime.out.test$n.1 || ret=1
+$SETTIME -K ns1 -i 0 -S $oldfile $newfile > settime.out.test$n.2 || ret=1
+
+# note previous zone serial number
+oldserial=$($DIG $DIGOPTS +short soa . @10.53.0.1 | awk '{print $3}')
+
+($RNDCCMD 10.53.0.1 loadkeys . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1
+sleep 4
+
+echo_i "revoking key to duplicated key ID"
+$SETTIME -R now -K ns2 Kbar.+013+59973.key > settime.out.test$n.3 || ret=1
+
+($RNDCCMD 10.53.0.2 loadkeys bar. 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1
+
+echo_i "waiting for changes to take effect"
+sleep 5
+
+echo_i "checking former standby key $newid is now active ($n)"
+ret=0
+$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking former standby key has only signed incrementally ($n)"
+ret=0
+$DIG $DIGOPTS txt . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
+grep 'RRSIG.*'" $oldid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that signing records have been marked as complete ($n)"
+ret=0
+checkprivate . 10.53.0.1 || ret=1
+checkprivate bar 10.53.0.2 || ret=1
+checkprivate example 10.53.0.2 0 type65280 || ret=1 # sig-signing-type 65280
+checkprivate private.secure.example 10.53.0.3 2 || ret=1 # pre-signed
+checkprivate nsec3.example 10.53.0.3 || ret=1
+checkprivate nsec3.nsec3.example 10.53.0.3 || ret=1
+checkprivate nsec3.optout.example 10.53.0.3 || ret=1
+checkprivate nsec3-to-nsec.example 10.53.0.3 2 || ret=1 # automatically removed
+if $SHELL ../testcrypto.sh -q RSASHA1
+then
+ checkprivate nsec-only.example 10.53.0.3 || ret=1
+fi
+checkprivate oldsigs.example 10.53.0.3 2 || ret=1 # pre-signed
+checkprivate optout.example 10.53.0.3 || ret=1
+checkprivate optout.nsec3.example 10.53.0.3 || ret=1
+checkprivate optout.optout.example 10.53.0.3 || ret=1
+checkprivate prepub.example 10.53.0.3 1 || ret=1 # expecting incomplete
+checkprivate rsasha256.example 10.53.0.3 || ret=1
+checkprivate rsasha512.example 10.53.0.3 || ret=1
+checkprivate secure.example 10.53.0.3 || ret=1
+checkprivate secure.nsec3.example 10.53.0.3 || ret=1
+checkprivate secure.optout.example 10.53.0.3 || ret=1
+checkprivate secure-to-insecure2.example 10.53.0.3 2|| ret=1 # automatically removed
+checkprivate secure-to-insecure.example 10.53.0.3 2 || ret=1 # automatically removed
+checkprivate ttl1.example 10.53.0.3 || ret=1
+checkprivate ttl2.example 10.53.0.3 || ret=1
+checkprivate ttl3.example 10.53.0.3 || ret=1
+checkprivate ttl4.example 10.53.0.3 || ret=1
+n=$((n + 1))
+status=$((status + ret))
+
+echo_i "forcing full sign"
+($RNDCCMD 10.53.0.1 sign . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1
+
+echo_i "waiting for change to take effect"
+sleep 5
+
+echo_i "checking former standby key has now signed fully ($n)"
+ret=0
+$DIG $DIGOPTS txt . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking SOA serial number has been incremented ($n)"
+ret=0
+newserial=$($DIG $DIGOPTS +short soa . @10.53.0.1 | awk '{print $3}')
+[ "$newserial" != "$oldserial" ] || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking delayed key publication/activation ($n)"
+ret=0
+zsk=$(cat delayzsk.key)
+ksk=$(cat delayksk.key)
+# publication and activation times should be unset
+$SETTIME -K ns3 -pA -pP $zsk > settime.out.test$n.zsk || ret=1
+grep -v UNSET settime.out.test$n.zsk >/dev/null && ret=1
+$SETTIME -K ns3 -pA -pP $ksk > settime.out.test$n.ksk || ret=1
+grep -v UNSET settime.out.test$n.ksk >/dev/null && ret=1
+$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
+# DNSKEY not expected:
+awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.test$n && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking scheduled key publication, not activation ($n)"
+ret=0
+# Ensure initial zone is loaded.
+wait_for_notifies "delay.example" "ns3" || ret=1
+$SETTIME -K ns3 -P now+3s -A none $zsk > settime.out.test$n.zsk || ret=1
+$SETTIME -K ns3 -P now+3s -A none $ksk > settime.out.test$n.ksk || ret=1
+($RNDCCMD 10.53.0.3 loadkeys delay.example. 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1
+echo_i "waiting for changes to take effect"
+sleep 3
+wait_for_notifies "delay.example" "ns3" || ret=1
+
+$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
+# DNSKEY expected:
+awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.test$n || ret=1
+# RRSIG not expected:
+awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.test$n && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking scheduled key activation ($n)"
+ret=0
+$SETTIME -K ns3 -A now+3s $zsk > settime.out.test$n.zsk || ret=1
+$SETTIME -K ns3 -A now+3s $ksk > settime.out.test$n.ksk || ret=1
+($RNDCCMD 10.53.0.3 loadkeys delay.example. 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1
+echo_i "waiting for changes to take effect"
+sleep 3
+wait_for_log_re 10 "add delay\.example\..*NSEC.a\.delay\.example\. NS SOA RRSIG NSEC DNSKEY" ns3/named.run
+check_is_signed() {
+ $DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.1.test$n || return 1
+ # DNSKEY expected:
+ awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.1.test$n || return 1
+ # RRSIG expected:
+ awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.1.test$n || return 1
+ $DIG $DIGOPTS +noall +answer a a.delay.example. @10.53.0.3 > dig.out.ns3.2.test$n || return 1
+ # A expected:
+ awk 'BEGIN {r=1} $4=="A" {r=0} END {exit r}' dig.out.ns3.2.test$n || return 1
+ # RRSIG expected:
+ awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.2.test$n || return 1
+ return 0
+}
+retry_quiet 5 check_is_signed || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking former active key was removed ($n)"
+#
+# Work out how long we need to sleep. Allow 4 seconds for the records
+# to be removed.
+#
+now=$($PERL -e 'print time(), "\n";')
+sleep=$((starttime + 29 - now))
+case $sleep in
+-*|0);;
+*) echo_i "waiting for timer to have activated"; sleep $sleep;;
+esac
+ret=0
+$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep '; key id = '"$oldid"'$' dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking private key file removal caused no immediate harm ($n)"
+ret=0
+id=$(keyfile_to_key_id "$(cat vanishing.key)")
+$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking revoked key with duplicate key ID ($n)"
+ret=0
+id=59973
+rid=60101
+$DIG $DIGOPTS +multi dnskey bar @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep '; key id = '"$id"'$' dig.out.ns2.test$n > /dev/null && ret=1
+keys=$(grep '; key id = '"$rid"'$' dig.out.ns2.test$n | wc -l)
+test $keys -eq 2 || ret=1
+$DIG $DIGOPTS dnskey bar @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking key event timers are always set ($n)"
+ret=0
+# this is a regression test for a bug in which the next key event could
+# be scheduled for the present moment, and then never fire. check for
+# visible evidence of this error in the logs:
+awk '/next key event/ {if ($1 == $8 && $2 == $9) exit 1}' */named.run || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# this confirms that key events are never scheduled more than
+# 'dnssec-loadkeys-interval' minutes in the future, and that the
+# event scheduled is within 10 seconds of expected interval.
+check_interval () {
+ awk '/next key event/ {print $2 ":" $9}' $1/named.run |
+ sed -e 's/\.//g' -e 's/:0\{1,4\}/:/g' |
+ awk -F: '
+ {
+ x = ($6+ $5*60000 + $4*3600000) - ($3+ $2*60000 + $1*3600000);
+ # abs(x) < 1000 ms treat as 'now'
+ if (x < 1000 && x > -1000)
+ x = 0;
+ # convert to seconds
+ x = x/1000;
+ # handle end of day roll over
+ if (x < 0)
+ x = x + 24*3600;
+ # handle log timestamp being a few milliseconds later
+ if (x != int(x))
+ x = int(x + 1);
+ if (int(x) > int(interval))
+ exit (1);
+ }
+ END { if (int(x) > int(interval) || int(x) < int(interval-10)) exit(1) }' interval=$2 || return $?
+ return 0
+}
+
+echo_i "checking automatic key reloading interval ($n)"
+ret=0
+check_interval ns1 3600 || ret=1
+check_interval ns2 1800 || ret=1
+check_interval ns3 600 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking for key reloading loops ($n)"
+ret=0
+# every key event should schedule a successor, so these should be equal
+rekey_calls=$(grep "reconfiguring zone keys" ns*/named.run | wc -l)
+rekey_events=$(grep "next key event" ns*/named.run | wc -l)
+[ "$rekey_calls" = "$rekey_events" ] || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "forcing full sign with unreadable keys ($n)"
+ret=0
+chmod 0 ns1/K.+*+*.key ns1/K.+*+*.private || ret=1
+($RNDCCMD 10.53.0.1 sign . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1
+$DIG $DIGOPTS . @10.53.0.1 dnskey > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "test turning on auto-dnssec during reconfig ($n)"
+ret=0
+# first create a zone that doesn't have auto-dnssec
+($RNDCCMD 10.53.0.3 addzone reconf.example '{ type primary; file "reconf.example.db"; };' 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1
+rekey_calls=$(grep "zone reconf.example.*next key event" ns3/named.run | wc -l)
+[ "$rekey_calls" -eq 0 ] || ret=1
+# ...then we add auto-dnssec and reconfigure
+($RNDCCMD 10.53.0.3 modzone reconf.example '{ type primary; file "reconf.example.db"; allow-update { any; }; auto-dnssec maintain; };' 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1
+rndc_reconfig ns3 10.53.0.3
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ lret=0
+ rekey_calls=$(grep "zone reconf.example.*next key event" ns3/named.run | wc -l)
+ [ "$rekey_calls" -gt 0 ] || lret=1
+ if [ "$lret" -eq 0 ]; then break; fi
+ echo_i "waiting ... ($i)"
+ sleep 1
+done
+n=$((n + 1))
+if [ "$lret" != 0 ]; then ret=$lret; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "test CDS and CDNSKEY auto generation ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 sync.example cds > dig.out.ns3.cdstest$n
+$DIG $DIGOPTS @10.53.0.3 sync.example cdnskey > dig.out.ns3.cdnskeytest$n
+grep -i "sync.example.*in.cds.*[1-9][0-9]* " dig.out.ns3.cdstest$n > /dev/null || ret=1
+grep -i "sync.example.*in.cdnskey.*257 " dig.out.ns3.cdnskeytest$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "test 'dnssec-dnskey-kskonly no' affects DNSKEY/CDS/CDNSKEY ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 sync.example dnskey > dig.out.ns3.dnskeytest$n
+$DIG $DIGOPTS @10.53.0.3 sync.example cdnskey > dig.out.ns3.cdnskeytest$n
+$DIG $DIGOPTS @10.53.0.3 sync.example cds > dig.out.ns3.cdstest$n
+lines=$(awk '$4 == "RRSIG" && $5 == "DNSKEY" {print}' dig.out.ns3.dnskeytest$n | wc -l)
+test ${lines:-0} -eq 2 || ret=1
+lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.ns3.cdnskeytest$n | wc -l)
+test ${lines:-0} -eq 2 || ret=1
+lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.ns3.cdstest$n | wc -l)
+test ${lines:-0} -eq 2 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "test 'dnssec-dnskey-kskonly yes' affects DNSKEY/CDS/CDNSKEY ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 kskonly.example dnskey > dig.out.ns3.dnskeytest$n
+$DIG $DIGOPTS @10.53.0.3 kskonly.example cdnskey > dig.out.ns3.cdnskeytest$n
+$DIG $DIGOPTS @10.53.0.3 kskonly.example cds > dig.out.ns3.cdstest$n
+lines=$(awk '$4 == "RRSIG" && $5 == "DNSKEY" {print}' dig.out.ns3.dnskeytest$n | wc -l)
+test ${lines:-0} -eq 1 || ret=1
+lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.ns3.cdnskeytest$n | wc -l)
+test ${lines:-0} -eq 1 || ret=1
+lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.ns3.cdstest$n | wc -l)
+test ${lines:-0} -eq 1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "setting CDS and CDNSKEY deletion times and calling 'rndc loadkeys'"
+$SETTIME -D sync now $(cat sync.key) > settime.out.test$n || ret=1
+($RNDCCMD 10.53.0.3 loadkeys sync.example | sed 's/^/ns3 /' | cat_i) || ret=1
+
+echo_i "checking that the CDS and CDNSKEY are deleted ($n)"
+ret=0
+ensure_cds_and_cdnskey_are_deleted() {
+ $DIG $DIGOPTS @10.53.0.3 sync.example. CDS > dig.out.ns3.cdstest$n || return 1
+ awk '$1 == "sync.example." && $4 == "CDS" { exit 1; }' dig.out.ns3.cdstest$n || return 1
+ $DIG $DIGOPTS @10.53.0.3 sync.example. CDNSKEY > dig.out.ns3.cdnskeytest$n || return 1
+ awk '$1 == "sync.example." && $4 == "CDNSKEY" { exit 1; }' dig.out.ns3.cdnskeytest$n || return 1
+}
+retry 10 ensure_cds_and_cdnskey_are_deleted || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that dnssec-settime -p Dsync works ($n)"
+ret=0
+$SETTIME -p Dsync $(cat sync.key) > settime.out.test$n || ret=1
+grep "SYNC Delete:" settime.out.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that dnssec-settime -p Psync works ($n)"
+ret=0
+$SETTIME -p Psync $(cat sync.key) > settime.out.test$n || ret=1
+grep "SYNC Publish:" settime.out.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that zone with inactive KSK and active ZSK is properly autosigned ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 axfr inacksk2.example > dig.out.ns3.test$n
+
+zskid=$(awk '$4 == "DNSKEY" && $5 == 256 { print }' dig.out.ns3.test$n |
+ $DSFROMKEY -A -2 -f - inacksk2.example | awk '{ print $4}' )
+pattern="DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 2 [0-9]* [0-9]* [0-9]* ${zskid} "
+grep "${pattern}" dig.out.ns3.test$n > /dev/null || ret=1
+
+kskid=$(awk '$4 == "DNSKEY" && $5 == 257 { print }' dig.out.ns3.test$n |
+ $DSFROMKEY -2 -f - inacksk2.example | awk '{ print $4}' )
+pattern="DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 2 [0-9]* [0-9]* [0-9]* ${kskid} "
+grep "${pattern}" dig.out.ns3.test$n > /dev/null && ret=1
+
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that zone with inactive ZSK and active KSK is properly autosigned ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 axfr inaczsk2.example > dig.out.ns3.test$n
+grep "SOA ${DEFAULT_ALGORITHM_NUMBER} 2" dig.out.ns3.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#
+# Check that DNSKEY is now signed with the ZSK.
+#
+echo_i "check that zone with active and inactive KSK and active ZSK is properly"
+echo_ic "resigned after the active KSK is deleted - stage 2: Verify that DNSKEY"
+echo_ic "is now signed with the ZSK. ($n)"
+ret=0
+
+$DIG $DIGOPTS @10.53.0.3 axfr inacksk3.example > dig.out.ns3.test$n
+
+zskid=$(awk '$4 == "DNSKEY" && $5 == 256 { print }' dig.out.ns3.test$n |
+ $DSFROMKEY -A -2 -f - inacksk3.example | awk '{ print $4}' )
+pattern="DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 2 [0-9]* [0-9]* [0-9]* ${zskid} "
+grep "${pattern}" dig.out.ns3.test$n > /dev/null || ret=1
+
+count=$(awk 'BEGIN { count = 0 }
+ $4 == "RRSIG" && $5 == "DNSKEY" { count++ }
+ END {print count}' dig.out.ns3.test$n)
+test $count -eq 1 || ret=1
+
+count=$(awk 'BEGIN { count = 0 }
+ $4 == "DNSKEY" { count++ }
+ END {print count}' dig.out.ns3.test$n)
+test $count -eq 2 || ret=1
+
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#
+# Check that zone is now signed with the KSK.
+#
+echo_i "check that zone with active and inactive ZSK and active KSK is properly"
+echo_ic "resigned after the active ZSK is deleted - stage 2: Verify that zone"
+echo_ic "is now signed with the KSK. ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 axfr inaczsk3.example > dig.out.ns3.test$n
+kskid=$(awk '$4 == "DNSKEY" && $5 == 257 { print }' dig.out.ns3.test$n |
+ $DSFROMKEY -2 -f - inaczsk3.example | awk '{ print $4}' )
+grep "CNAME ${DEFAULT_ALGORITHM_NUMBER} 3 [0-9]* [0-9]* [0-9]* ${kskid} " dig.out.ns3.test$n > /dev/null || ret=1
+count=$(awk 'BEGIN { count = 0 }
+ $4 == "RRSIG" && $5 == "CNAME" { count++ }
+ END {print count}' dig.out.ns3.test$n)
+test $count -eq 1 || ret=1
+count=$(awk 'BEGIN { count = 0 }
+ $4 == "DNSKEY" { count++ }
+ END {print count}' dig.out.ns3.test$n)
+test $count -eq 2 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking for out-of-zone NSEC3 records after ZSK removal ($n)"
+ret=0
+# Switch the zone over to NSEC3 and wait until the transition is complete.
+$RNDCCMD 10.53.0.3 signing -nsec3param 1 1 10 12345678 delzsk.example. > signing.out.1.test$n 2>&1 || ret=1
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ _ret=1
+ $DIG $DIGOPTS delzsk.example NSEC3PARAM @10.53.0.3 > dig.out.ns3.1.test$n 2>&1 || ret=1
+ { grep "NSEC3PARAM.*12345678" dig.out.ns3.1.test$n > /dev/null 2>&1; rc=$?; } || true
+ if [ $rc -eq 0 ]; then
+ $RNDCCMD 10.53.0.3 signing -list delzsk.example > signing.out.2.test$n 2>&1
+ { grep "Creating NSEC3 chain " signing.out.2.test$n > /dev/null 2>&1; rc=$?; } || true
+ if [ $rc -ne 0 ]; then
+ _ret=0
+ break
+ fi
+ fi
+ sleep 1
+done
+if [ $_ret -ne 0 ]; then
+ echo_i "timed out waiting for NSEC3 chain creation"
+ ret=1
+fi
+# Mark the inactive ZSK as pending removal.
+file="ns3/$(cat delzsk.key).key"
+$SETTIME -D now-1h $file > settime.out.test$n || ret=1
+# Trigger removal of the inactive ZSK and wait until its completion.
+($RNDCCMD 10.53.0.3 loadkeys delzsk.example 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ _ret=1
+ $RNDCCMD 10.53.0.3 signing -list delzsk.example > signing.out.3.test$n 2>&1
+ { grep "Signing " signing.out.3.test$n > /dev/null 2>&1; rc=$?; } || true
+ if [ $rc -ne 0 ]; then
+ if [ $(grep "Done signing " signing.out.3.test$n | wc -l) -eq 2 ]; then
+ _ret=0
+ break
+ fi
+ fi
+ sleep 1
+done
+if [ $_ret -ne 0 ]; then
+ echo_i "timed out waiting for key removal"
+ ret=1
+fi
+# Check whether key removal caused NSEC3 records to be erroneously created for
+# glue records due to a secure delegation already being signed by the active key
+# (i.e. a key other than the one being removed but using the same algorithm).
+#
+# For reference:
+#
+# $ nsec3hash 12345678 1 10 ns.sub.delzsk.example.
+# 589R358VSPJUFVAJU949JPVF74D9PTGH (salt=12345678, hash=1, iterations=10)
+#
+$DIG $DIGOPTS delzsk.example AXFR @10.53.0.3 > dig.out.ns3.3.test$n || ret=1
+grep "589R358VSPJUFVAJU949JPVF74D9PTGH" dig.out.ns3.3.test$n > /dev/null 2>&1 && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that DNAME at apex with NSEC3 is correctly signed (auto-dnssec maintain) ($n)"
+ret=0
+$DIG $DIGOPTS txt dname-at-apex-nsec3.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "RRSIG NSEC3 ${DEFAULT_ALGORITHM_NUMBER} 3 600" dig.out.ns3.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that DNAME is not treated as a delegation when signing ($n)"
+ret=0
+$DIG $DIGOPTS dname-and-txt.secure.example. DNAME @10.53.0.3 > dig.out.ns3.1.test$n || ret=1
+grep "dname-and-txt.secure.example.*RRSIG.*DNAME" dig.out.ns3.1.test$n > /dev/null 2>&1 || ret=1
+$DIG $DIGOPTS dname-and-txt.secure.example. TXT @10.53.0.3 > dig.out.ns3.2.test$n || ret=1
+grep "dname-and-txt.secure.example.*RRSIG.*TXT" dig.out.ns3.2.test$n > /dev/null 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking key maintenance events were logged correctly ($n)"
+ret=0
+pub=$(grep "DNSKEY .* is now published" ns1/named.run | wc -l)
+[ "$pub" -eq 6 ] || ret=1
+act=$(grep "DNSKEY .* is now active" ns1/named.run | wc -l)
+[ "$act" -eq 5 ] || ret=1
+rev=$(grep "DNSKEY .* is now revoked" ns1/named.run | wc -l)
+[ "$rev" -eq 1 ] || ret=1
+inac=$(grep "DNSKEY .* is now inactive" ns1/named.run | wc -l)
+[ "$inac" -eq 1 ] || ret=1
+del=$(grep "DNSKEY .* is now deleted" ns1/named.run | wc -l)
+[ "$del" -eq 1 ] || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that CDS (DELETE) persists after zone sign ($n)"
+echo_i "update add cds-delete.example. CDS 0 0 00"
+ret=0
+$NSUPDATE > nsupdate.out 2>&1 <<END
+server 10.53.0.3 ${PORT}
+zone cds-delete.example.
+update add cds-delete.example. 3600 CDS 0 0 0 00
+send
+END
+
+_cds_delete() (
+ $DIG $DIGOPTS +noall +answer $1 cds @10.53.0.3 > dig.out.ns3.test$n || return 1
+ grep "CDS.*0.*0.*0.*00" dig.out.ns3.test$n > /dev/null 2>&1 || return 1
+ return 0
+)
+_cdnskey_delete_nx() {
+ $DIG $DIGOPTS +noall +answer $1 cdnskey @10.53.0.3 > dig.out.ns3.test$n || return 1
+ grep "CDNSKEY.*0.*3.*0.*AA==" dig.out.ns3.test$n > /dev/null 2>&1 && return 1
+ return 0
+}
+
+echo_i "query cds-delete.example. CDS"
+retry_quiet 10 _cds_delete cds-delete.example. || ret=1
+echo_i "query cds-delete.example. CDNSKEY"
+retry_quiet 1 _cdnskey_delete_nx cds-delete.example. || ret=1
+
+echo_i "sign cds-delete.example."
+nextpart ns3/named.run >/dev/null
+$RNDCCMD 10.53.0.3 sign cds-delete.example > /dev/null 2>&1 || ret=1
+wait_for_log 10 "zone cds-delete.example/IN: next key event" ns3/named.run
+# The CDS (DELETE) record should still be here.
+echo_i "query cds-delete.example. CDS"
+retry_quiet 1 _cds_delete cds-delete.example. || ret=1
+# The CDNSKEY (DELETE) record should still not be added.
+echo_i "query cds-delete.example. CDNSKEY"
+retry_quiet 1 _cdnskey_delete_nx cds-delete.example. || ret=1
+
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that CDNSKEY (DELETE) persists after zone sign ($n)"
+echo_i "update add cdnskey-delete.example. CDNSKEY 0 3 0 AA=="
+ret=0
+$NSUPDATE > nsupdate.out 2>&1 <<END
+server 10.53.0.3 ${PORT}
+zone cdnskey-delete.example.
+update add cdnskey-delete.example. 3600 CDNSKEY 0 3 0 AA==
+send
+END
+
+_cds_delete_nx() (
+ $DIG $DIGOPTS +noall +answer $1 cds @10.53.0.3 > dig.out.ns3.test$n || return 1
+ grep "CDS.*0.*0.*0.*00" dig.out.ns3.test$n > /dev/null 2>&1 && return 1
+ return 0
+)
+_cdnskey_delete() {
+ $DIG $DIGOPTS +noall +answer $1 cdnskey @10.53.0.3 > dig.out.ns3.test$n || return 1
+ grep "CDNSKEY.*0.*3.*0.*AA==" dig.out.ns3.test$n > /dev/null 2>&1 || return 1
+ return 0
+}
+
+echo_i "query cdnskey-delete.example. CDNSKEY"
+retry_quiet 10 _cdnskey_delete cdnskey-delete.example. || ret=1
+echo_i "query cdnskey-delete.example. CDS"
+retry_quiet 1 _cds_delete_nx cdnskey-delete.example. || ret=1
+
+echo_i "sign cdsnskey-delete.example."
+nextpart ns3/named.run >/dev/null
+$RNDCCMD 10.53.0.3 sign cdnskey-delete.example > /dev/null 2>&1 || ret=1
+wait_for_log 10 "zone cdnskey-delete.example/IN: next key event" ns3/named.run
+# The CDNSKEY (DELETE) record should still be here.
+echo_i "query cdnskey-delete.example. CDNSKEY"
+retry_quiet 1 _cdnskey_delete cdnskey-delete.example. || ret=1
+# The CDS (DELETE) record should still not be added.
+echo_i "query cdnskey-delete.example. CDS"
+retry_quiet 1 _cds_delete_nx cdnskey-delete.example. || ret=1
+
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check removal of ENT NSEC3 records when opt out delegations are removed ($n)"
+ret=0
+zone=optout-with-ent
+hash=JTR8R6AVFULU0DQH9I6HNN2KUK5956EL
+# check that NSEC3 for ENT is present
+$DIG $DIGOPTS @10.53.0.2 a "ent.${zone}" > dig.out.pre.ns2.test$n
+grep "status: NOERROR" dig.out.pre.ns2.test$n >/dev/null || ret=1
+grep "ANSWER: 0, AUTHORITY: 4, " dig.out.pre.ns2.test$n > /dev/null || ret=1
+grep "^${hash}.${zone}." dig.out.pre.ns2.test$n > /dev/null || ret=1
+# remove first delegation of two delegations, NSEC3 for ENT should remain.
+(
+echo zone $zone
+echo server 10.53.0.2 "$PORT"
+echo update del sub1.ent.$zone NS
+echo send
+) | $NSUPDATE
+# check that NSEC3 for ENT is still present
+$DIG $DIGOPTS @10.53.0.2 a "ent.${zone}" > dig.out.pre.ns2.test$n
+$DIG $DIGOPTS @10.53.0.2 a "ent.${zone}" > dig.out.mid.ns2.test$n
+grep "status: NOERROR" dig.out.mid.ns2.test$n >/dev/null || ret=1
+grep "ANSWER: 0, AUTHORITY: 4, " dig.out.mid.ns2.test$n > /dev/null || ret=1
+grep "^${hash}.${zone}." dig.out.mid.ns2.test$n > /dev/null || ret=1
+# remove second delegation of two delegations, NSEC3 for ENT should be deleted.
+(
+echo zone $zone
+echo server 10.53.0.2 "$PORT"
+echo update del sub2.ent.$zone NS
+echo send
+) | $NSUPDATE
+# check that NSEC3 for ENT is gone present
+$DIG $DIGOPTS @10.53.0.2 a "ent.${zone}" > dig.out.post.ns2.test$n
+grep "status: NXDOMAIN" dig.out.post.ns2.test$n >/dev/null || ret=1
+grep "ANSWER: 0, AUTHORITY: 4, " dig.out.post.ns2.test$n > /dev/null || ret=1
+grep "^${hash}.${zone}." dig.out.post.ns2.test$n > /dev/null && ret=1
+$DIG $DIGOPTS @10.53.0.2 axfr "${zone}" > dig.out.axfr.ns2.test$n
+grep "^${hash}.${zone}." dig.out.axfr.ns2.test$n > /dev/null && ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/autosign/tests_sh_autosign.py b/bin/tests/system/autosign/tests_sh_autosign.py
new file mode 100644
index 0000000..16dfc29
--- /dev/null
+++ b/bin/tests/system/autosign/tests_sh_autosign.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_autosign(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/builtin/clean.sh b/bin/tests/system/builtin/clean.sh
new file mode 100644
index 0000000..1ad33dc
--- /dev/null
+++ b/bin/tests/system/builtin/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns?/named.run
+rm -f ns?/named.memstats
+rm -f ns?/named.conf
+rm -f rndc.status.ns*
+rm -f dig.out.ns*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/builtin/ns1/named.conf.in b/bin/tests/system/builtin/ns1/named.conf.in
new file mode 100644
index 0000000..723e6b2
--- /dev/null
+++ b/bin/tests/system/builtin/ns1/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 yes;
+ notify no;
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/builtin/ns2/named.conf.in b/bin/tests/system/builtin/ns2/named.conf.in
new file mode 100644
index 0000000..38b95f0
--- /dev/null
+++ b/bin/tests/system/builtin/ns2/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+ server-id hostname;
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/builtin/ns3/named.conf.in b/bin/tests/system/builtin/ns3/named.conf.in
new file mode 100644
index 0000000..df538db
--- /dev/null
+++ b/bin/tests/system/builtin/ns3/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ notify no;
+ hostname "this.is.a.test.of.hostname";
+ server-id "this.is.a.test.of.server-id";
+ version "this is a test of version";
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/builtin/setup.sh b/bin/tests/system/builtin/setup.sh
new file mode 100644
index 0000000..7ffda55
--- /dev/null
+++ b/bin/tests/system/builtin/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
diff --git a/bin/tests/system/builtin/tests.sh b/bin/tests/system/builtin/tests.sh
new file mode 100644
index 0000000..9151fc3
--- /dev/null
+++ b/bin/tests/system/builtin/tests.sh
@@ -0,0 +1,248 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+emptyzones="
+10.IN-ADDR.ARPA
+16.172.IN-ADDR.ARPA
+17.172.IN-ADDR.ARPA
+18.172.IN-ADDR.ARPA
+19.172.IN-ADDR.ARPA
+20.172.IN-ADDR.ARPA
+21.172.IN-ADDR.ARPA
+22.172.IN-ADDR.ARPA
+23.172.IN-ADDR.ARPA
+24.172.IN-ADDR.ARPA
+25.172.IN-ADDR.ARPA
+26.172.IN-ADDR.ARPA
+27.172.IN-ADDR.ARPA
+28.172.IN-ADDR.ARPA
+29.172.IN-ADDR.ARPA
+30.172.IN-ADDR.ARPA
+31.172.IN-ADDR.ARPA
+168.192.IN-ADDR.ARPA
+64.100.IN-ADDR.ARPA
+65.100.IN-ADDR.ARPA
+66.100.IN-ADDR.ARPA
+67.100.IN-ADDR.ARPA
+68.100.IN-ADDR.ARPA
+69.100.IN-ADDR.ARPA
+70.100.IN-ADDR.ARPA
+71.100.IN-ADDR.ARPA
+72.100.IN-ADDR.ARPA
+73.100.IN-ADDR.ARPA
+74.100.IN-ADDR.ARPA
+75.100.IN-ADDR.ARPA
+76.100.IN-ADDR.ARPA
+77.100.IN-ADDR.ARPA
+78.100.IN-ADDR.ARPA
+79.100.IN-ADDR.ARPA
+80.100.IN-ADDR.ARPA
+81.100.IN-ADDR.ARPA
+82.100.IN-ADDR.ARPA
+83.100.IN-ADDR.ARPA
+84.100.IN-ADDR.ARPA
+85.100.IN-ADDR.ARPA
+86.100.IN-ADDR.ARPA
+87.100.IN-ADDR.ARPA
+88.100.IN-ADDR.ARPA
+89.100.IN-ADDR.ARPA
+90.100.IN-ADDR.ARPA
+91.100.IN-ADDR.ARPA
+92.100.IN-ADDR.ARPA
+93.100.IN-ADDR.ARPA
+94.100.IN-ADDR.ARPA
+95.100.IN-ADDR.ARPA
+96.100.IN-ADDR.ARPA
+97.100.IN-ADDR.ARPA
+98.100.IN-ADDR.ARPA
+99.100.IN-ADDR.ARPA
+100.100.IN-ADDR.ARPA
+101.100.IN-ADDR.ARPA
+102.100.IN-ADDR.ARPA
+103.100.IN-ADDR.ARPA
+104.100.IN-ADDR.ARPA
+105.100.IN-ADDR.ARPA
+106.100.IN-ADDR.ARPA
+107.100.IN-ADDR.ARPA
+108.100.IN-ADDR.ARPA
+109.100.IN-ADDR.ARPA
+110.100.IN-ADDR.ARPA
+111.100.IN-ADDR.ARPA
+112.100.IN-ADDR.ARPA
+113.100.IN-ADDR.ARPA
+114.100.IN-ADDR.ARPA
+115.100.IN-ADDR.ARPA
+116.100.IN-ADDR.ARPA
+117.100.IN-ADDR.ARPA
+118.100.IN-ADDR.ARPA
+119.100.IN-ADDR.ARPA
+120.100.IN-ADDR.ARPA
+121.100.IN-ADDR.ARPA
+122.100.IN-ADDR.ARPA
+123.100.IN-ADDR.ARPA
+124.100.IN-ADDR.ARPA
+125.100.IN-ADDR.ARPA
+126.100.IN-ADDR.ARPA
+127.100.IN-ADDR.ARPA
+0.IN-ADDR.ARPA
+127.IN-ADDR.ARPA
+254.169.IN-ADDR.ARPA
+2.0.192.IN-ADDR.ARPA
+100.51.198.IN-ADDR.ARPA
+113.0.203.IN-ADDR.ARPA
+255.255.255.255.IN-ADDR.ARPA
+0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA
+1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA
+D.F.IP6.ARPA
+8.E.F.IP6.ARPA
+9.E.F.IP6.ARPA
+A.E.F.IP6.ARPA
+B.E.F.IP6.ARPA
+8.B.D.0.1.0.0.2.IP6.ARPA
+EMPTY.AS112.ARPA
+HOME.ARPA"
+
+n=$((n + 1))
+ret=0
+count=0
+echo_i "Checking expected empty zones were configured ($n)"
+for zone in ${emptyzones}
+do
+ grep "automatic empty zone: $zone" ns1/named.run > /dev/null || {
+ echo_i "failed (empty zone $zone missing)"
+ ret=1
+ }
+ count=$((count + 1))
+done
+lines=$(grep "automatic empty zone: " ns1/named.run | wc -l)
+test $count -eq $lines -a $count -eq 99 || {
+ ret=1; echo_i "failed (count mismatch)";
+}
+if [ $ret != 0 ] ; then status=$((status + ret)); fi
+
+n=$((n + 1))
+echo_i "Checking that reconfiguring empty zones is silent ($n)"
+$RNDCCMD 10.53.0.1 reconfig
+ret=0
+grep "automatic empty zone" ns1/named.run > /dev/null || ret=1
+grep "received control channel command 'reconfig'" ns1/named.run > /dev/null || ret=1
+grep "reloading configuration succeeded" ns1/named.run > /dev/null || ret=1
+sleep 1
+grep "zone serial (0) unchanged." ns1/named.run > /dev/null && ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+n=$((n + 1))
+echo_i "Checking that reloading empty zones is silent ($n)"
+rndc_reload ns1 10.53.0.1
+ret=0
+grep "automatic empty zone" ns1/named.run > /dev/null || ret=1
+grep "received control channel command 'reload'" ns1/named.run > /dev/null || ret=1
+grep "reloading configuration succeeded" ns1/named.run > /dev/null || ret=1
+sleep 1
+grep "zone serial (0) unchanged." ns1/named.run > /dev/null && ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+HOST_NAME=$($FEATURETEST --gethostname)
+BIND_VERSION_STRING=$($NAMED -V | head -1)
+BIND_VERSION=$($NAMED -V | sed -ne 's/^BIND \([^ ]*\).*/\1/p')
+
+n=$((n + 1))
+ret=0
+echo_i "Checking that default version works for rndc ($n)"
+$RNDCCMD 10.53.0.1 status > rndc.status.ns1.$n 2>&1
+grep -F "version: $BIND_VERSION_STRING" rndc.status.ns1.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+n=$((n + 1))
+ret=0
+echo_i "Checking that custom version works for rndc ($n)"
+$RNDCCMD 10.53.0.3 status > rndc.status.ns3.$n 2>&1
+grep -F "version: $BIND_VERSION_STRING (this is a test of version)" rndc.status.ns3.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+n=$((n + 1))
+ret=0
+echo_i "Checking that default version works for query ($n)"
+$DIG $DIGOPTS +short version.bind txt ch @10.53.0.1 > dig.out.ns1.$n || ret=1
+grep "^\"$BIND_VERSION\"$" dig.out.ns1.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+n=$((n + 1))
+ret=0
+echo_i "Checking that custom version works for query ($n)"
+$DIG $DIGOPTS +short version.bind txt ch @10.53.0.3 > dig.out.ns3.$n || ret=1
+grep "^\"this is a test of version\"$" dig.out.ns3.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+n=$((n + 1))
+ret=0
+echo_i "Checking that default hostname works for query ($n)"
+$DIG $DIGOPTS +short hostname.bind txt ch @10.53.0.1 > dig.out.ns1.$n || ret=1
+grep "^\"$HOST_NAME\"$" dig.out.ns1.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+n=$((n + 1))
+ret=0
+echo_i "Checking that custom hostname works for query ($n)"
+$DIG $DIGOPTS +short hostname.bind txt ch @10.53.0.3 > dig.out.ns3.$n || ret=1
+grep "^\"this.is.a.test.of.hostname\"$" dig.out.ns3.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+n=$((n + 1))
+ret=0
+echo_i "Checking that default server-id is none for query ($n)"
+$DIG $DIGOPTS id.server txt ch @10.53.0.1 > dig.out.ns1.$n || ret=1
+grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns1.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+n=$((n + 1))
+ret=0
+echo_i "Checking that server-id hostname works for query ($n)"
+$DIG $DIGOPTS +short id.server txt ch @10.53.0.2 > dig.out.ns2.$n || ret=1
+grep "^\"$HOST_NAME\"$" dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+n=$((n + 1))
+ret=0
+echo_i "Checking that server-id hostname works for EDNS name server ID request ($n)"
+$DIG $DIGOPTS +norec +nsid foo @10.53.0.2 > dig.out.ns2.$n || ret=1
+grep "^; NSID: .* (\"$HOST_NAME\")$" dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+n=$((n + 1))
+ret=0
+echo_i "Checking that custom server-id works for query ($n)"
+$DIG $DIGOPTS +short id.server txt ch @10.53.0.3 > dig.out.ns3.$n || ret=1
+grep "^\"this.is.a.test.of.server-id\"$" dig.out.ns3.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+n=$((n + 1))
+ret=0
+echo_i "Checking that custom server-id works for EDNS name server ID request ($n)"
+$DIG $DIGOPTS +norec +nsid foo @10.53.0.3 > dig.out.ns3.$n || ret=1
+grep "^; NSID: .* (\"this.is.a.test.of.server-id\")$" dig.out.ns3.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/builtin/tests_sh_builtin.py b/bin/tests/system/builtin/tests_sh_builtin.py
new file mode 100644
index 0000000..2246cb4
--- /dev/null
+++ b/bin/tests/system/builtin/tests_sh_builtin.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_builtin(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/cacheclean/clean.sh b/bin/tests/system/cacheclean/clean.sh
new file mode 100644
index 0000000..b346e65
--- /dev/null
+++ b/bin/tests/system/cacheclean/clean.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after cache cleaner tests.
+#
+
+rm -f dig.out.ns2
+rm -f dig.out.expire
+rm -f rndc.out.*
+rm -f sed.out.*
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f ns2/named_dump.db.*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/cacheclean/dig.batch b/bin/tests/system/cacheclean/dig.batch
new file mode 100644
index 0000000..d185204
--- /dev/null
+++ b/bin/tests/system/cacheclean/dig.batch
@@ -0,0 +1,924 @@
+YA.AKAMAI.com. IN A
+UPR1.UPR.CLU.EDU. IN A
+integra.s-integra.co.JP. IN A
+avalon.iks-jena.de. IN A
+NS1.GLOBALDNS.com. IN A
+NS.RDU.BELLSOUTH.net. IN A
+ns.space.net. IN A
+SUN.MHS-RELAY.AC.UK. IN A
+AYAX.UNIANDES.EDU.CO. IN A
+DNS.NIC.CD. IN A
+NS.DNS.PT. IN A
+NS1.INTERNETSHARE.com. IN A
+MASTER.DNS.BE. IN A
+CATAMOUNT.middlebury.EDU. IN A
+FM03.FM. IN A
+NAAMAK.NCST.ERNET.IN. IN A
+gateway2.BFG.com. IN A
+NS3.NS.ESAT.net. IN A
+DNS1.INTUIT.com. IN A
+DEN-NS2.FWIDCSERVICES.net. IN A
+SOL.UNDPBI.TELEPAC.net. IN A
+NS2.tridog.com. IN A
+DNS2.KW. IN A
+NS2.MAIL.com. IN A
+NS.FIRSTCOM.CL. IN A
+DNS4.QUICKEN.com. IN A
+bofh.cid.net. IN A
+NS1.KRNIC.net. IN A
+NS2.SR.net. IN A
+NS1.TELSTRA.net. IN A
+ns.cafax.SE. IN A
+NS1.DNS.NET.NZ. IN A
+NS.CONCOURSE.com. IN A
+35.32/27.110.16.12.IN-ADDR.ARPA. IN PTR
+CCC.champcable.com. IN A
+NS.RIPE.net. IN A
+NS.NIC.NU. IN A
+KIM.CAMNET.CM. IN A
+DOGON.SOTELMA.net. IN A
+DNS02.FLAME.org. IN A
+NS.MIA.BELLSOUTH.net. IN A
+mail.ok.RU. IN A
+NS.NIC.MX. IN A
+NS2.BERKELEY.EDU. IN A
+SHIKHAR.MOS.COM.NP. IN A
+noc.rrz.Uni-Koeln.de. IN A
+NS.KORNET.net. IN A
+keith.gazpacho.org. IN A
+NS2.appliedtheory.com. IN A
+NS.CERNET.net. IN A
+smtp.ELISTX.com. IN A
+NS-AIT.THNIC.net. IN A
+from.PL. IN A
+mailhub.icann.org. IN A
+SEC1.DNS.UK.PSI.net. IN A
+isrv3-i.isc.org. IN A
+PHLOEM.UOREGON.EDU. IN A
+CTINA.AR. IN A
+DNS2.IAM.NET.MA. IN A
+10.126.39.137.IN-ADDR.ARPA. IN PTR
+DNS.PRINCETON.EDU. IN A
+NS.BELLSOUTH.net. IN A
+NS1.SNS-FELB.DEBIS.com. IN A
+localhost. IN A
+hm6.vt.highmeadow.com. IN A
+SYRUP.hill.com. IN A
+NS99.WAIKATO.AC.NZ. IN A
+NS4.CW.net. IN A
+NS2.SLOWMOE.com. IN A
+ns2.hypa.net. IN A
+ns.sxtyptt.NET.CN. IN A
+NS2.MERCHANTWARE.com. IN A
+uunymdgds1.DOUBLECLICK.net. IN A
+e34.co.us.IBM.com. IN A
+kista.dns.swip.net. IN A
+ZEBRA.UEM.MZ. IN A
+NET2.GENDYN.com. IN A
+NS0.UTK.EDU. IN A
+NS.RELCOM.EU.net. IN A
+DNS0.AXION.BT.CO.UK. IN A
+mail.vhv.com. IN A
+DNS4.UK.MSFT.net. IN A
+NS2.ADNS.net. IN A
+NS1.SEATTLE.US.NETDNS.com. IN A
+NS2.UNIVIE.AC.at. IN A
+NS15B.BOCA15-VERIO.com. IN A
+www.BAYAREA.com. IN CNAME
+ns4.onemain.com. IN A
+NS2.EDIGITALS.com. IN A
+MICHAEL.VATICAN.VA. IN A
+AUSTIN.GH.com. IN A
+sld-ns2.CNNIC.NET.CN. IN A
+NS2.CDC.GOV. IN A
+NS.WATSON.IBM.com. IN A
+NS.NIC.SH. IN A
+NS2.BAHNHOF.net. IN A
+NS-AUTH2.cmates.com. IN A
+ISDMNL.WR.USGS.GOV. IN A
+NS2.COBEX.net. IN A
+MERLE.CIRA.CA. IN A
+NS.UVG.EDU.GT. IN A
+NS1.CWVA.DOUBLECLICK.net. IN A
+eliot.diebold.com. IN A
+NS.ALMADEN.IBM.com. IN A
+NS2.INTERNETSQUARE.com. IN A
+mail.QUEST-NET.com. IN A
+Z1.NS.LHR1.GLOBIX.net. IN A
+DNS1.AVANTEL.NET.MX. IN A
+vh80040.vh8.INFI.net. IN A
+NS.LEB.net. IN A
+NS.DCC.UCHILE.CL. IN A
+CLOUSO.RISQ.QC.CA. IN A
+muenster.westfalen.de. IN A
+us.a1.YIMG.com. IN CNAME
+NS.DEMOS.SU. IN A
+south.NAVPOINT.com. IN A
+netconsult.netconx.de. IN A
+DNS2.btinternet.com. IN A
+NS2.CINE.net. IN A
+castor.cmc.ec.gc.CA. IN A
+EX2-DNS0.AVENUEA.com. IN A
+firewall3.glaxowellcome.com. IN A
+MACU.MA.MT.NP.ELS-GMS.att.net. IN A
+NS.PA. IN A
+TGSERV.TELE.GL. IN A
+KYNSE02.MESSAGESECURE.com. IN A
+GORGON.XTRA.CO.NZ. IN A
+DNS.NIC.IT. IN A
+pop.VERMONTEL.net. IN CNAME
+NS2.REGISTRY.HM. IN A
+NAMESERVER1.CONCENTRIC.net. IN A
+47.131.127.204.IN-ADDR.ARPA. IN PTR
+mailhost.tfm.com. IN A
+NS1.MRC.GM. IN A
+NS.WIDE.AD.JP. IN A
+NS.BTA.NET.CN. IN A
+NS2.ISPC.org. IN A
+BOW.RAIN.FR. IN A
+srs.srs.state.vt.us. IN A
+NS4.WEB2010.com. IN A
+NS.TELECOM.NET.ET. IN A
+NS1.DNS.NET.KH. IN A
+GATEN.JARING.MY. IN A
+shell.nominum.com. IN A
+CHEOPS.ANU.EDU.AU. IN A
+VANGOGH.CS.BERKELEY.EDU. IN A
+NS2.NOC.NULLUS.net. IN A
+NIC.LTH.SE. IN A
+ns.farm.net. IN A
+NS.USEC.SUN.com. IN A
+NS2.YOUR-DOMAIN.com. IN A
+DNS-EAST.PREP.net. IN A
+ns.hcr.net. IN A
+NS-RCH.nortelnetworks.com. IN A
+crl.DEC.com. IN A
+NS.PIXAR.ES. IN A
+MEX1-M-213.UNINET.NET.MX. IN A
+NS.ITU.CH. IN A
+matrix.uwm.EDU.PL. IN A
+gateway1.gmcr.com. IN A
+NS2.DNS.BR. IN A
+foxharp.boston.MA.us. IN MX
+Quest-7.symquest.com. IN A
+NS2.VERIO.net. IN A
+NAME.IAD.GBLX.net. IN A
+NS2.EMIRATES.NET.AE. IN A
+supai.oit.UMASS.EDU. IN A
+QUERN.EPILOGUE.com. IN A
+NS3.TOPICA.com. IN A
+NS1.JERKY.net. IN A
+JTB.BRUNET.BN. IN A
+AUTH100.NS.UU.net. IN A
+BOW.INTNET.DJ. IN A
+OSI2.GUA.net. IN A
+AZMODAN.ULA.VE. IN A
+THUMPER.RPSLMC.EDU. IN A
+ICHU.RCP.NET.PE. IN A
+NS.NIC.AC. IN A
+DNS.NETFLIGHT.com. IN A
+ns2.UTORONTO.CA. IN A
+mail.giffordmed.org. IN A
+RATA.VUW.AC.NZ. IN A
+NS-2.ADMONITOR.net. IN A
+NCC.MOC.KW. IN A
+NS.EUNET.ES. IN A
+NS3.best.com. IN A
+zip.MAIL-LIST.com. IN MX
+JATZ.AARNET.EDU.AU. IN A
+DNS2.MAN.LODZ.PL. IN A
+NS.VERITAS.com. IN A
+218.241.103.199.IN-ADDR.ARPA. IN PTR
+BOW.SNPT.KM. IN A
+Z1.NS.SJC1.GLOBIX.net. IN A
+DNS.NIC.TT. IN A
+MAKISIG.IPHIL.net. IN A
+NS.DK.net. IN A
+NS.NI. IN A
+CIUP1.NCC.UP.PT. IN A
+ns2.verisign-grs.com. IN A
+NS1.UMASS.EDU. IN A
+NS.NEWACCOUNT.net. IN A
+UDNS2.ULTRADNS.net. IN A
+NS2.LATNET.LV. IN A
+info-server.surrey.AC.UK. IN A
+NS2.SQUONK.net. IN A
+NS2.DSO.net. IN A
+www.energyenhancement.org. IN A
+DNS1.BD. IN A
+nl.COMPUWARE.com. IN MX
+NS.DHIRAAGU.MV. IN A
+TRANTOR.UMD.EDU. IN A
+NS.ALCANET.NO. IN A
+Z6.MSFT.AKADNS.com. IN A
+NS4.ync.net. IN A
+CMTU.MT.NS.ELS-GMS.att.net. IN A
+vh40099.vh4.INFI.net. IN A
+ns2.secondary.nl. IN A
+abyssinian.sleepycat.com. IN A
+APHEX.MENTOR.BE. IN A
+webmail.fiberia.com. IN A
+localhost.moonmothers.com. IN A
+NS2.DNS.LU. IN A
+NS.VISUALCOM.ES. IN A
+TONIC.TO. IN A
+NS1.CRSNIC.net. IN A
+trurl.ispid.com.PL. IN A
+datingagentur.de. IN A
+NS2.NSIREGISTRY.net. IN A
+ICE.VIA-NET-WORKS.IE. IN A
+sgi1.map.com. IN A
+NS0.HS0.U-NET.net. IN A
+candle.pha.pa.us. IN A
+NS1.PACIFIC.NET.SG. IN A
+NS.CENIAI.NET.CU. IN A
+NS2.UUCP.NE.JP. IN A
+za.akamaitech.net. IN A
+NS.UCR.AC.CR. IN A
+DNS-02.NS.cs.com. IN A
+dns2.primary.net. IN A
+PAPPSRV.PAPP.UNDP.org. IN A
+NS1.REGME.com. IN A
+DNS.CS.KULEUVEN.AC.BE. IN A
+NS1.VERMONTLAW.net. IN A
+mail.garmontusa.com. IN A
+NS2.SAIPAN.com. IN A
+NS.ARICATRA.com. IN A
+ns2.reedmedia.net. IN A
+NS.NETLAB.SK. IN A
+RELAY.GW.tislabs.com. IN A
+b.ns.tmcs.net. IN A
+NS1.IBL.BM. IN A
+ok.RU. IN A
+NS.RICC.ALMA-ATA.SU. IN A
+KITKA.MARNET.MK. IN A
+dasher.dartmouth.EDU. IN A
+NS0.PLANET-THREE.com. IN A
+KNOCK.SER.BBNPLANET.net. IN A
+tornado.webtech.elk.PL. IN A
+AUTH2.NS.IDT.net. IN A
+host3.VTLEGALAID.org. IN A
+NS.EUNET.SK. IN A
+TULKU.NIC.AR. IN A
+RELAY.CDNNET.CA. IN A
+DNS2.TPSA.PL. IN A
+enterprise.wirbel.com. IN A
+ECNET.EC. IN A
+ENGINE1.UNA.net. IN A
+WYCU.WY.BR.NP.ELS-GMS.att.net. IN A
+ARWENA.NASK.WAW.PL. IN A
+PAC2.NIPR.MIL. IN A
+DAISY.EE.UND.AC.ZA. IN A
+odin.ietf.org. IN A
+dns.kaben-net.de. IN A
+NS2.ALTAVISTA.com. IN A
+CASTOR.TELEGLOBE.net. IN A
+CIR.RED.SV. IN A
+PIJIN.COM.SB. IN A
+NS4.CTCCOM.net. IN A
+NS1.SOL.NO. IN A
+DNS2.TK.MSFT.net. IN A
+NS.BSDI.com. IN A
+NS.SVIANED.nl. IN A
+NS.NOVELL.com. IN A
+NS.LUCKY.net. IN A
+SJC-NS2.SJC.LYCOS.com. IN A
+NS1.OP.net. IN A
+worldnet.att.net. IN A
+APIES.FRD.AC.ZA. IN A
+mail.skiinsurance.com. IN A
+NS.BELNET.BE. IN A
+KOMO.INET.GA. IN A
+EARTH.THEPLANET.net. IN A
+VASCO.USMA.AC.PA. IN A
+GODFEVER.DCCSERVER.com. IN A
+BOS-NS2.BOS.LYCOS.com. IN A
+NS2.GOTO.com. IN A
+NS1.overstock.com. IN A
+NS1-PUBLIC.ZMA.COMPAQ.com. IN A
+ns.ilovedomain.com. IN A
+ns1.anycast.net. IN A
+PASCAL.UPRR.PR. IN A
+NS3-AUTH.SPRINTLINK.net. IN A
+NS1-Y.DNS.PIPEX.net. IN A
+prue.eim.surrey.AC.UK. IN A
+TROLL-GW.GATECH.EDU. IN A
+NS.SIERRATEL.SL. IN A
+ns2.PSHIFT.com. IN A
+NS.ERS.IBM.com. IN A
+ASLAN.OPEN-RSC.org. IN A
+NS2.DOMAIN-REGISTRY.nl. IN A
+uranus.lan-ks.de. IN A
+mail.unlisys.net. IN A
+NS.AUSTRIA.EU.net. IN A
+AUTH01.CONNECT.IE. IN A
+SUN.SCSI.GOV.BY. IN A
+NS1.SIGMAHOSTING.com. IN A
+NS.CAST.EDU.JM. IN A
+DS.NIC.NET.SG. IN A
+PRADES.CESCA.ES. IN A
+ns.sta.NET.CN. IN A
+NSE00.excite.com. IN A
+NS3.ABOVE.net. IN A
+CASBAH.ELDJAZAIR.NET.DZ. IN A
+ASKIA.SOTELMA.ML. IN A
+NS.IDT.net. IN A
+FXCLPR02.IS.CHRYSLER.com. IN A
+SVC00.APNIC.net. IN A
+NS5.DCX.YAHOO.com. IN A
+ns1.ray.net. IN A
+NS.NIC.MC. IN A
+ns.runway.CN.net. IN A
+benoni.uit.NO. IN A
+SCRATCHY.MINDSPRING.net. IN A
+ns1.pcode.com. IN A
+ns1.aha.RU. IN A
+ns2.uwaterloo.CA. IN A
+ns2.NIC.AD.JP. IN A
+a.ns.foxharp.boston.MA.us. IN A
+NS.NIC.IO. IN A
+A-GTLD-SERVERS.dot-god.com. IN A
+SMTP.slac.stanford.EDU. IN A
+52.87.198.209.IN-ADDR.ARPA. IN PTR
+BARNEY.ADVSYS.CO.UK. IN A
+NS1.TELEPAC.PT. IN A
+NICOSIA.CCS.UCY.AC.CY. IN A
+NS.PUNCHDOWN.org. IN A
+SYNAESTHESIA.COGNOSCENTI.org. IN A
+NS2.PLANET-THREE.net. IN A
+DNS.CIT.CORNELL.EDU. IN A
+MODOR.VERISIGN.net. IN A
+SUNSTROKE.IS.RPSLMC.EDU. IN A
+NS2.SEG.net. IN A
+NEMUNAS.SC-UNI.KTU.LT. IN A
+MULGA.CS.MU.OZ.AU. IN A
+NS1.NPLUS.GF. IN A
+ns2.centralinfo.net. IN A
+K.GTLD-SERVERS.net. IN A
+ns1.codelocal.com. IN A
+NS2.IPNS.com. IN A
+NS0.DE.NIC.NU. IN A
+NS.USSR.EU.net. IN A
+NS.INTERNET.SK. IN A
+CORREOS.SEKER.ES. IN A
+mx1.buf.ADELPHIA.net. IN A
+aun.UNINETT.NO. IN A
+NS0.NETANET.com. IN A
+www.MANY-PATHS-ENERGY-ENHANCEMENT.com. IN A
+NS2.STARFIRE.DOUGLAS.MA.us. IN A
+NS3.IKP.PL. IN A
+pns.dtag.de. IN A
+NZ.NS.NIC.NU. IN A
+DAVER.bungi.com. IN A
+gutenberg.bucksnet.com. IN A
+DNS2.IT.net. IN A
+NS2.SNS-UT.DEBIS.com. IN A
+ISI.EDU. IN A
+amethyst.xaos.org. IN A
+PAPPILLOMA.WWEBSVS.com. IN A
+NS2.bock.com. IN A
+NS2.OAR.net. IN A
+MINION.NETPOLICY.com. IN A
+Mail.catic1.com. IN A
+NS4.DNS.space.net. IN A
+b.gtld-servers.ORSC. IN A
+bend.madriver.com. IN A
+NS4.IS-FUN.net. IN A
+NS2.JPS.net. IN A
+NS1.IP-PLUS.net. IN A
+rush.cc1.RPSLMC.EDU. IN A
+NS2.GBMTECH.net. IN A
+DNS.MSEN.com. IN A
+DNSSEC2.SINGNET.COM.SG. IN A
+NS2.HOME.net. IN A
+ACCESS.MBNET.MB.CA. IN A
+DNS0.SPIN.AD.JP. IN A
+Filer.PHOTOTRUST.com. IN A
+jpl.NASA.GOV. IN A
+NS2.TECHNOLOGIA.net. IN A
+bparker.CONNACTIVITY.com. IN A
+NS1.uvm.EDU. IN A
+NS.SENET.net. IN A
+DNS2.UTCC.UTORONTO.CA. IN A
+localhost.costorf.com. IN A
+DNS2.AD. IN A
+HYDRA.HELSINKI.FI. IN A
+NAME.PHX.GBLX.net. IN A
+NS2.FOOL.com. IN A
+NS01-SERVER.CURINFO.AN. IN A
+NS.CR. IN A
+mail.pshift.net. IN A
+NS.IRD.FR. IN A
+NS.UZ. IN A
+DNS.INTELCOM.SM. IN A
+DNS2.UNIV-NKC.MR. IN A
+HNS3.hns.com. IN A
+bay.cs.UTORONTO.CA. IN A
+NS0.BT.net. IN A
+BAYONET.SJMERCURY.com. IN A
+PAN.BIJT.net. IN A
+NAVI.SUBTEND.net. IN A
+NS.CIX.CX. IN A
+waldorf.Informatik.Uni-Dortmund.de. IN A
+NS2.ivillage.com. IN A
+DNS.NIC.XLINK.net. IN A
+NS1.MERCHANTWARE.CON. IN A
+NS.TO.GD-ES.com. IN A
+NS-A.RNC.RO. IN A
+REGGAE.NCREN.net. IN A
+SSS-NL.DENIC.de. IN A
+NS1.TDC.TO. IN A
+NS.NIC.HU. IN A
+JOANNA.WILLIAM.org. IN A
+NS0.IIJ.AD.JP. IN A
+maus.spack.org. IN A
+B.NS.VERIO.net. IN A
+SECDNS.EUNET.BE. IN A
+NS3.EUROPE.YAHOO.com. IN A
+A.ROOT-SERVERS.net. IN A
+sherickpm.com. IN MX
+NS2.MEDIASERVICES.net. IN A
+YARDBIRD.CNS.vt.EDU. IN A
+SUNIC.SUNET.SE. IN A
+NS.MT. IN A
+CNDVG001.usa.net. IN A
+NS1.CX.ESCROW.IOCOMM.NET.CX. IN A
+DNS-02.NS.AOL.com. IN A
+ns2.tesserae.com. IN A
+SV10.BATELCO.COM.BH. IN A
+dec.anr.state.vt.us. IN MX
+3.133.188.192.IN-ADDR.ARPA. IN PTR
+NS1.LONDON.UK.NETDNS.com. IN A
+NS.NIC.MG. IN A
+DNS1.VN. IN A
+DENS20.DEN.nps.GOV. IN A
+z.ip6.INT. IN A
+NS3.TRIVALLEY.com. IN A
+isis.imag.FR. IN A
+NS.SOVAM.com. IN A
+NS-SOA.DARENET.DK. IN A
+NS4.NIC.TV. IN A
+DNSSRV1X.mitre.org. IN A
+GATEKEEPER.NYTIMES.com. IN A
+D.I-DNS.net. IN A
+NS.KOLO.net. IN A
+NS4.FIRSTWORLD.net. IN A
+DECST.CERIST.DZ. IN A
+NS4.DNS.WS. IN A
+NS0.GDGSC.com. IN A
+UCTHPX.UCT.AC.ZA. IN A
+NS2.HOTWIRED.com. IN A
+ns02.ca.us.ibm.net. IN A
+NS2.SPEAKEASY.net. IN A
+TELCOM.ZPTC.CO.ZW. IN A
+NS.DK-HOSTMASTER.DK. IN A
+NS.NIC.LK. IN A
+NS2.zama.net. IN A
+CZ.EUNET.CZ. IN A
+NS.AC.ID. IN A
+NS1.CUBE.de. IN A
+NS1.QUASAR.net. IN A
+NS1.OFFSHORE.AI. IN A
+NS5.NRSITE.com. IN A
+NS.AIC.net. IN A
+OWL.NCC.nps.GOV. IN A
+MAXIM.gbch.net. IN A
+BOW.INTNET.TD. IN A
+ns1.cacheware.com. IN A
+NS2.SPEEDHOST.com. IN A
+NS1.COMMIT.GM. IN A
+NAME.ROC.GBLX.net. IN A
+90.198.245.204.IN-ADDR.ARPA. IN PTR
+BOLOGNA.NETTUNO.IT. IN A
+NIC.IBD.com. IN A
+NS.WESTOL.com. IN A
+time.SOVER.net. IN CNAME
+UNIX1.CS.UMASS.EDU. IN A
+AARDVARK.WR.UMIST.AC.UK. IN A
+NS1.NIC.YU. IN A
+mail.velco.com. IN A
+DNSAUTH2.SYS.GTEI.net. IN A
+NS.TELE.FI. IN A
+state.vt.us. IN MX
+NS.NYC.juno.com. IN A
+NS1.g-world.com. IN A
+AUTH2.AMERICA.net. IN A
+KIRA.ECS.UMASS.EDU. IN A
+CONACYT.GOB.SV. IN A
+DNS.SRCE.HR. IN A
+NS00.ns0.com. IN A
+NS2.CL.BELLSOUTH.net. IN A
+jenner.med.HARVARD.EDU. IN A
+p2.cavebear.com. IN A
+NS1.NIC.JE. IN A
+ORCU.OR.BR.NP.ELS-GMS.att.net. IN A
+NS.XBILL.org. IN A
+WRAITH.CS.UOW.EDU.AU. IN A
+12.159.145.204.IN-ADDR.ARPA. IN PTR
+ns1.pr.SUN.com. IN A
+NS.SPIN.OMNES.net. IN A
+smtp.188.net. IN A
+TERMINAL.2GLOBE.net. IN A
+NS2.HARVARD.EDU. IN A
+NAMESERVER.CNR.IT. IN A
+EARTH.SY. IN A
+DNS2.REACCIUN.VE. IN A
+NS.TMX.COM.NI. IN A
+freefour.acs.rpi.EDU. IN A
+242.84.198.209.IN-ADDR.ARPA. IN PTR
+CORREU.STA.AD. IN A
+NS.DRUKNET.NET.BT. IN A
+NS4.US.PRSERV.net. IN A
+KAASASSUK.GH.GL. IN A
+ECUA.NET.EC. IN A
+NS.CONCYT.GOB.GT. IN A
+NS2.NAP.net. IN A
+DNS2.CN.net. IN A
+MX.NSI.NASA.GOV. IN A
+NS.TDS.net. IN A
+tdns-me1.NETSCAPE.com. IN A
+NS2.METU.EDU.TR. IN A
+NS2.SETARNET.AW. IN A
+87.184.152.204.IN-ADDR.ARPA. IN PTR
+DNS.OMNIWAY.SM. IN A
+NS0.U-NET.net. IN A
+elektro.CMHNET.org. IN A
+ns2.HIGGS.net. IN A
+NS2.SKYNETWEB.com. IN A
+MAGIC.MN. IN A
+NS1.YAHOO.com. IN A
+mx1.cdp.ADELPHIA.net. IN A
+SANTO.VANUATU.COM.VU. IN A
+www.mmuuf.org. IN MX
+ns1.timeheart.net. IN A
+NS2.TOGETHER.net. IN A
+NS.AMNIC.net. IN A
+NS.EENET.EE. IN A
+www.ONLINEPHOTOCONTEST.com. IN A
+VIC20.BLIPP.com. IN A
+DNS.FROGHOUSE.org. IN A
+NS2.ELI.net. IN A
+NS.CAIS.com. IN A
+BAABEN.AFRIQ.net. IN A
+NS2.NJ.EXODUS.net. IN A
+DOMREG.NIC.CH. IN A
+NS.EU.net. IN A
+NS1.DIEBOLD.net. IN A
+NS3.CP.net. IN A
+DNS.FUW.EDU.PL. IN A
+www.retro.com. IN A
+NS2.UNI2.net. IN A
+ns1.alcatrazmedia.com. IN A
+dns6.CP.MSFT.net. IN A
+NS1.SEYCHELLES.net. IN A
+NS2.INTERNIC.net. IN A
+front.macrosoft.WAW.PL. IN A
+NISC.JVNC.net. IN A
+AUTH03.NS.DE.UU.net. IN A
+BURDELL.CC.GATECH.EDU. IN A
+NS4.AH.net. IN A
+ns1.sgh-net.de. IN A
+Leland2.stanford.EDU. IN A
+CBRU.BR.NS.ELS-GMS.att.net. IN A
+DENEB.DOMAINNT.net. IN A
+ns1.ivm.net. IN A
+NS0.CWCI.net. IN A
+35.110.16.12.IN-ADDR.ARPA. IN CNAME
+f.trns. IN A
+ODISEJ.TELEKOM.YU. IN A
+FRCU.EUN.EG. IN A
+NS.HHS.net. IN A
+FOO.GRNET.GR. IN A
+mail.WonderWorks.com. IN A
+NS1.IAFRICA.com. IN A
+NS.KACST.EDU.SA. IN A
+srs.state.vt.us. IN A
+OM4.OMANTEL.NET.OM. IN A
+Yeshua.Christ.com. IN A
+NS1.SIMORGH.com. IN A
+OLKETA.SOLOMON.COM.SB. IN A
+BANBA.DOMAINREGISTRY.IE. IN A
+NOC.IOS.com. IN A
+ns.schnism.net. IN A
+e4.ny.us.IBM.com. IN A
+DNS2.SEANET.com. IN A
+doubt.dd.org. IN A
+AMBER.ELEKTRON.PL. IN A
+gw.rge.com. IN A
+NS2.ZTNET.com. IN A
+NS3.INFI.net. IN A
+ZA.AKADNS.net. IN A
+ESTIA.CSI.FORTH.GR. IN A
+vtagr04.agr.state.vt.us. IN A
+NS1-PUBLIC.ZTX.COMPAQ.com. IN A
+ADMII.ARL.MIL. IN A
+NS.NIXU.FI. IN A
+DNS2.PIONEERNET.net. IN A
+NS.NIC.CL. IN A
+NS2.UTZ. IN A
+NS4.LUXNOC.com. IN A
+NS2.PBI.net. IN A
+annwfn.erfurt.thur.de. IN A
+NS1.MW.mediaone.net. IN A
+NS1.ISU.NET.SA. IN A
+pop.SHOREHAM.net. IN CNAME
+DNS2.GUERNSEY.net. IN A
+NS1.BEACHSHORE.net. IN A
+HKUXB.HKU.HK. IN A
+NS.DOLEH.com. IN A
+NS.hactrn.net. IN A
+MALAKULA.BONDY.IRD.FR. IN A
+NS1.mediaone.net. IN A
+NS2.GPG.com. IN A
+noc.BelWue.de. IN A
+NS2.GIP.net. IN A
+RS.ISLES.net. IN A
+BOW.INTNET.GQ. IN A
+A.OPEN.BY. IN A
+us.i1.YIMG.com. IN CNAME
+athome.wetlogic.net. IN CNAME
+NS1.NIST.GOV. IN A
+mail.jerusalem-mail.com. IN A
+ISDSUN.cr.USGS.GOV. IN A
+NS.BOSTON.juno.com. IN A
+NS2.CADABRA.com. IN A
+nps.GOV. IN MX
+RELAY.HUJI.AC.IL. IN A
+styx.tahina.priv.at. IN A
+ISGATE.IS. IN A
+ns0.lux.dot-eu.org. IN A
+BILBO.NASK.ORG.PL. IN A
+MAIL.TARSUS.com. IN A
+SUN.REDIRIS.ES. IN A
+NS2.NEASE.net. IN A
+OHCU.OH.MT.NP.ELS-GMS.att.net. IN A
+NS2.NF. IN A
+MIRAF-SERVER3.HONDUTEL.HN. IN A
+ns3.worldnet.att.net. IN A
+NS2.NETNAMES.net. IN A
+ITGBOX.IAT.CNR.IT. IN A
+NS2.ADELPHIA.net. IN A
+NS2.RIPN.net. IN A
+NS1.cinenet.net. IN A
+jengate.thur.de. IN A
+NOC.ULCC.JA.net. IN A
+NS.NOC.UZ. IN A
+NS0.JA.net. IN A
+NS2.INR.net. IN A
+netsage.org. IN A
+TERI.USP.AC.FJ. IN A
+NS2.NETSOL.com. IN A
+NS2.ABAC.com. IN A
+NS2.NIC.FR. IN A
+KANIN.ARNES.SI. IN A
+NS.EDU.GU. IN A
+DNS.INRIA.FR. IN A
+HEDNS1.GOOGLE.com. IN A
+asylum.sf.ca.us. IN A
+ACT2.ACT2000.net. IN A
+ICM1.ICP.net. IN A
+202.192.103.198.209.IN-ADDR.ARPA. IN PTR
+ECSEL.jhuapl.EDU. IN A
+NS2.DCNY.DOUBLECLICK.net. IN A
+keith.netsage.org. IN A
+MANTA.OUTREMER.com. IN A
+NS2.globalnetisp.net. IN A
+NS2.CCSRS.net. IN A
+NS1.NL.CONCENTRIC.com. IN A
+NS2.VI.net. IN A
+NS2.NEO.net. IN A
+cgi.MERCURYCENTER.com. IN CNAME
+ORSTOM.RIO.net. IN A
+NS2.CONRADPROMOTIONS.com. IN A
+YARRINA.CONNECT.COM.AU. IN A
+dns03.OPS.usa.net. IN A
+APPSRV.HAITIWORLD.com. IN A
+NS.RELCOM.KZ. IN A
+NS1.MAGIC-MOMENTS.com. IN A
+NS.ALCATEL.com. IN A
+ns2.terra.net. IN A
+NS3.hotmail.com. IN A
+vtc.VSC.EDU. IN MX
+www.vmba.org. IN MX
+NAHOURI.ONATEL.BF. IN A
+SERVER2.INFN.IT. IN A
+NS2.AI-R.com. IN A
+NS1.FREE.net. IN A
+vcmr-54.server.rpi.EDU. IN A
+haig.CS.UCL.AC.UK. IN A
+mail.nova-data.com. IN A
+MOEVAX.EDU.TW. IN A
+NS2.LTWCC.org. IN A
+NS.BA. IN A
+noc.HRZ.uni-bielefeld.de. IN A
+VANILLA.WRO.nps.GOV. IN A
+NS2.SZTAKI.HU. IN A
+SECIU.EDU.UY. IN A
+COL2.CARIBSURF.com. IN A
+NS2.QATAR.NET.QA. IN A
+NS2.E-SYNC.net. IN A
+ns1.eu.SUN.com. IN A
+NS1.UUSJ.DOUBLECLICK.net. IN A
+NS2.CUHK.EDU.HK. IN A
+NS1.MEITCA.com. IN A
+NS2.DSL.net. IN A
+techfac.techfak.uni-bielefeld.de. IN A
+listserv.performancediver.com. IN A
+foolusmf.D4P.net. IN CNAME
+pedic-med.vrx.net. IN A
+GRUMPY.NET.NA. IN A
+BK.tifosi.com. IN A
+ns3.PAIR.com. IN A
+ns2.ar.com. IN A
+MASSIRA.ONPT.NET.MA. IN A
+NS.KBFI.EE. IN A
+ns3.Algebra.com. IN A
+faerber.muc.de. IN MX
+9.206.203.192.IN-ADDR.ARPA. IN PTR
+PUKU.UNZA.ZM. IN A
+ATLNET.ATLONLINE.com. IN A
+Z1.NS.NYC1.GLOBIX.net. IN A
+www.hometownbands.com. IN A
+SIMON.CS.CORNELL.EDU. IN A
+EKEKO.RCPIP.net. IN A
+emerald.itnet.com.PL. IN A
+DNS1.ICS.FORTH.GR. IN A
+NS.ATL.BELLSOUTH.net. IN A
+ntp.ctr.COLUMBIA.EDU. IN CNAME
+NS2.GLOBECOMM.net. IN A
+UUNS1DNS1.FLONETWORK.com. IN A
+GRIN.GNOSH.net. IN A
+NS.DIGSYS.BG. IN A
+uunet.UU.net. IN MX
+ns1.vermontel.com. IN A
+NS2.GREENMOUNTAINACCESS.net. IN A
+38.241.5.198.IN-ADDR.ARPA. IN PTR
+NS1.NIC.UK. IN A
+DNS.FCCN.PT. IN A
+NS2.NIC.TJ. IN A
+NS4.NEWACCOUNT.com. IN A
+NS2.IHUG.NET.NZ. IN A
+NS.SIGNALZ.com. IN A
+DNS.NIC.AD. IN A
+3.2.39.137.IN-ADDR.ARPA. IN PTR
+UUCP-GW-2.PA.DEC.com. IN A
+NS.LANDLORDS.com. IN A
+NS2.EXODUS.net. IN A
+NS2.SCRUZ.net. IN A
+NS.PIPEX-SZ.net. IN A
+saturn.SUN.com. IN A
+e24.nc.us.IBM.com. IN A
+NMS.CYFRONET.KRAKOW.PL. IN A
+NS.TWNIC.net. IN A
+ns2.alcatel.NO. IN A
+INPAKSODNS.AKSO.nps.GOV. IN A
+mail.reptiles.org. IN A
+59.187.152.204.IN-ADDR.ARPA. IN PTR
+ns1.mobydark.com. IN A
+NS.KG. IN A
+NS.SPB.SU. IN A
+PENDRAGON.CS.PURDUE.EDU. IN A
+NS1.IGC.APC.org. IN A
+USDNS.NIC.us. IN A
+NS2.WEBTRENDS.com. IN A
+URANUS.DAIMI.AAU.DK. IN A
+ANTANA.IRD.MG. IN A
+NS.JERSEY.juno.com. IN A
+NS2.INTERNET-TOOLS.com. IN A
+ns-tk012.ocn.AD.JP. IN A
+bvt-ext.gdarm.com. IN A
+NS1.ID. IN A
+NS2.MAHNET.net. IN A
+NS.ALCANET.COM.AU. IN A
+UTAMA.BOLNET.BO. IN A
+NS.CNC.AC.CN. IN A
+NS.KREN.NE.KR. IN A
+NS1.REDHAT.com. IN A
+db.rc.VIX.com. IN A
+198.103.198.209.IN-ADDR.ARPA. IN CNAME
+alf.pbks.PL. IN A
+FLAG.EP.net. IN A
+DNS2.IUNET.IT. IN A
+NS2.QUANTIFIED.net. IN A
+INTERNET-SERVER.ZURICH.IBM.com. IN A
+seaipsvcs.idx.com. IN A
+lebanon.valley.net. IN A
+SERVER.NORDU.net. IN A
+NS.NIC.DO. IN A
+isc-01.iscvt.org. IN A
+NAC.NO. IN A
+SAVA.UTIC.NET.BA. IN A
+NS1.TOKYO.JP.NETDNS.com. IN A
+NETSERV2.ITS.rpi.EDU. IN A
+IFI.UIO.NO. IN A
+www.TOAPLAN.com. IN A
+ns2.the-frontier.org. IN A
+NS.UNAM.MX. IN A
+ARISTO.TAU.AC.IL. IN A
+DNS.CS.WISC.EDU. IN A
+NS1.NIC.IR. IN A
+NS1.RETINA.AR. IN A
+mailer.connriver.net. IN A
+NS.ATI.TN. IN A
+NS2.CLEAR.NET.NZ. IN A
+NS4.EARTHLINK.net. IN A
+mejac.palo-alto.ca.us. IN A
+New-York4.NY.ALTER.net. IN A
+falcon.tallship.net. IN A
+ZEUS.CC.UCY.AC.CY. IN A
+NS2.SECURE.net. IN A
+NS0.FLIRBLE.org. IN A
+dns.zenon.net. IN A
+SERVIDOR.MICROASTUR.ES. IN A
+DOWNSTAGE.MCS.VUW.AC.NZ. IN A
+ns2.GNAC.com. IN A
+PRIFI.EUNET.FI. IN A
+ns2.k12.vt.us. IN A
+ns2.nic.mnet. IN A
+NS0.PIPEX.net. IN A
+NS1.SANFRANCISCO.US.NETDNS.com. IN A
+AMRA.NIC.GOV.JO. IN A
+kw.com.CN. IN MX
+SHNS.163.net. IN A
+NS.ER.USGS.GOV. IN A
+FAITH.MYNET.net. IN A
+mail.smuggs.com. IN A
+MIMOS.MY. IN A
+NS.GU. IN A
+mx00.schlund.de. IN A
+CADDSYS.IPTEK.net. IN A
+NS0.TELIA.NIC.NU. IN A
+NS2.GRANITECANYON.com. IN A
+GATEKEEPER.corning.com. IN A
+NS2.2DAY.com. IN A
+1.0.0.127.IN-ADDR.ARPA. IN PTR
+RAIN.PSG.com. IN A
+STRAWB.MIT.EDU. IN A
+NS2.DIGISERVE.com. IN A
+UMACSN2.UMAC.MO. IN A
+NS.JM. IN A
+12.153.66.206.IN-ADDR.ARPA. IN PTR
+EAST.ISI.EDU. IN A
+NS2.UUNET.CA. IN A
+SUNNY.STAT-USA.GOV. IN A
+BOW.INTNET.CF. IN A
+NS4.TELE.DK. IN A
+NS2.sodak.net. IN A
+NS1.NEWYORK.US.NETDNS.com. IN A
+NS2.PSI.net. IN A
+NS.KREONET.RE.KR. IN A
+GIANT.MINDLINK.net. IN A
+NS0.SECTOR001.org. IN A
+DNS.SEABONE.net. IN A
+NS2.MANA.PF. IN A
+NRWEB.CENPAC.NET.NR. IN A
+www.TRAVELPHOTOCONTESTS.com. IN A
+NS1.REGEX.com. IN A
+BIGBIRD.ITD.nps.GOV. IN A
+CUNIXD.CC.COLUMBIA.EDU. IN A
+NS1.CLASSIFIEDMONSTER.com. IN A
+SERVER1.SANS.org. IN A
+BRONZE.COIL.com. IN A
+SCSNMS.SWITCH.CH. IN A
+SCE.CNC.UNA.PY. IN A
+RELAY.LA.TIS.com. IN A
+NS.AUSTIN.IBM.com. IN A
+SERVICE.robert-morris.EDU. IN A
+MERCURY.ML.org. IN A
+proxy.pccf.net. IN A
+DUB-NAME-SVC-1.compuserve.com. IN A
+NS.CNRI.reston.va.us. IN A
+NS.UCAD.SN. IN A
+ns01.ny.us.ibm.net. IN A
+NS4-AUTH.ALASKA.net. IN A
+BOW.INTNET.NE. IN A
+NS-JP.SINET.AD.JP. IN A
+ns.musin.de. IN A
+ip1.romkey.SEG.net. IN A
+DNS2.ITD.UMICH.EDU. IN A
+mail.rpi.EDU. IN A
+INECO.NIC.ES. IN A
+DNS2.FIREHOUSE.net. IN A
+BOW.INTNET.BJ. IN A
+sundown.vtc.VSC.EDU. IN A
+NIC.AIX.GR. IN A
+NIC.AD.JP. IN A
+NS.DC.IGC.org. IN A
+LHR.NS.GDNS.net. IN A
+NS2.WEBMAGIC.net. IN A
+MUNNARI.OZ.AU. IN A
+HIPPO.RU.AC.ZA. IN A
+PEBBLES.IOM.com. IN A
+penpal.dmz.RPSLMC.EDU. IN A
+netnews.HINET.net. IN A
+INS2.TOSA.TWTELECOM.net. IN A
+proxy6.cisco.com. IN A
+NS2.HOST4U.net. IN A
+POIPARAU.OYSTER.NET.CK. IN A
+NS-EXT.VIX.com. IN A
+NS2.NURSAT.net. IN A
+mail2.kw.com.CN. IN A
+NS-02B.ANS.net. IN A
+DNS.RCCN.net. IN A
+B.ROOT-SERVERS.ORSC. IN A
+FIREHOUSE.net. IN A
diff --git a/bin/tests/system/cacheclean/knowngood.dig.out b/bin/tests/system/cacheclean/knowngood.dig.out
new file mode 100644
index 0000000..a0f087e
--- /dev/null
+++ b/bin/tests/system/cacheclean/knowngood.dig.out
@@ -0,0 +1,953 @@
+YA.AKAMAI.com. 604800 IN A 204.178.118.68
+UPR1.UPR.CLU.EDU. 604800 IN A 136.145.1.4
+integra.s-integra.co.JP. 604800 IN A 210.162.202.34
+avalon.iks-jena.de. 604800 IN A 194.221.90.34
+NS1.GLOBALDNS.com. 604800 IN A 206.253.214.11
+NS.RDU.BELLSOUTH.net. 604800 IN A 205.152.32.20
+ns.space.net. 604800 IN A 195.30.0.1
+SUN.MHS-RELAY.AC.UK. 604800 IN A 128.86.8.25
+AYAX.UNIANDES.EDU.CO. 604800 IN A 157.253.50.30
+DNS.NIC.CD. 604800 IN A 194.38.74.11
+NS.DNS.PT. 604800 IN A 193.136.0.1
+NS1.INTERNETSHARE.com. 604800 IN A 63.207.108.53
+MASTER.DNS.BE. 604800 IN A 194.7.171.243
+CATAMOUNT.middlebury.EDU. 604800 IN A 140.233.2.204
+FM03.FM. 604800 IN A 206.49.89.4
+NAAMAK.NCST.ERNET.IN. 604800 IN A 202.41.110.66
+gateway2.BFG.com. 604800 IN A 166.102.214.66
+NS3.NS.ESAT.net. 604800 IN A 192.111.39.100
+DNS1.INTUIT.com. 604800 IN A 208.157.255.4
+DEN-NS2.FWIDCSERVICES.net. 604800 IN A 216.7.160.32
+SOL.UNDPBI.TELEPAC.net. 604800 IN A 194.65.87.2
+NS2.tridog.com. 604800 IN A 206.168.112.51
+DNS2.KW. 604800 IN A 161.252.48.150
+NS2.MAIL.com. 604800 IN A 165.251.1.3
+NS.FIRSTCOM.CL. 604800 IN A 200.27.2.2
+DNS4.QUICKEN.com. 604800 IN A 198.3.99.252
+bofh.cid.net. 604800 IN A 212.172.21.254
+NS1.KRNIC.net. 604800 IN A 202.30.50.51
+NS2.SR.net. 604800 IN A 200.1.156.11
+NS1.TELSTRA.net. 604800 IN A 139.130.4.5
+ns.cafax.SE. 604800 IN A 192.71.228.17
+NS1.DNS.NET.NZ. 604800 IN A 202.46.161.3
+NS.CONCOURSE.com. 604800 IN A 199.218.113.2
+35.32/27.110.16.12.IN-ADDR.ARPA. 604800 IN PTR mail.nova-data.com.
+CCC.champcable.com. 604800 IN A 207.41.53.11
+NS.RIPE.net. 604800 IN A 193.0.0.193
+NS.NIC.NU. 604800 IN A 128.11.47.50
+KIM.CAMNET.CM. 604800 IN A 195.24.192.35
+DOGON.SOTELMA.net. 604800 IN A 208.144.230.1
+DNS02.FLAME.org. 604800 IN A 204.152.184.97
+NS.MIA.BELLSOUTH.net. 604800 IN A 205.152.16.20
+mail.ok.RU. 604800 IN A 195.2.83.162
+NS.NIC.MX. 604800 IN A 200.23.1.1
+NS2.BERKELEY.EDU. 604800 IN A 128.32.136.12
+NS2.BERKELEY.EDU. 604800 IN A 128.32.206.12
+SHIKHAR.MOS.COM.NP. 604800 IN A 202.52.255.5
+noc.rrz.Uni-Koeln.de. 604800 IN A 134.95.100.209
+NS.KORNET.net. 604800 IN A 168.126.63.1
+keith.gazpacho.org. 604800 IN A 209.67.235.37
+NS2.appliedtheory.com. 604800 IN A 168.75.17.11
+NS.CERNET.net. 604800 IN A 202.112.0.44
+smtp.ELISTX.com. 604800 IN A 209.116.252.130
+NS-AIT.THNIC.net. 604800 IN A 192.41.170.219
+from.PL. 604800 IN A 212.160.132.114
+mailhub.icann.org. 604800 IN A 192.0.34.33
+SEC1.DNS.UK.PSI.net. 604800 IN A 154.32.105.34
+isrv3-i.isc.org. 604800 IN A 204.152.184.87
+PHLOEM.UOREGON.EDU. 604800 IN A 128.223.32.35
+CTINA.AR. 604800 IN A 200.16.97.17
+DNS2.IAM.NET.MA. 604800 IN A 212.217.0.12
+10.126.39.137.IN-ADDR.ARPA. 604800 IN PTR Fddi0-0.New-York4.NY.ALTER.NET.
+DNS.PRINCETON.EDU. 604800 IN A 128.112.129.15
+NS.BELLSOUTH.net. 604800 IN A 205.152.0.5
+NS1.SNS-FELB.DEBIS.com. 604800 IN A 53.122.1.10
+localhost. 604800 IN A 127.0.0.1
+hm6.vt.highmeadow.com. 604800 IN A 207.136.209.6
+SYRUP.hill.com. 604800 IN A 208.162.106.3
+NS99.WAIKATO.AC.NZ. 604800 IN A 130.217.76.27
+NS4.CW.net. 604800 IN A 204.70.49.234
+NS2.SLOWMOE.com. 604800 IN A 137.118.8.50
+ns2.hypa.net. 604800 IN A 63.160.181.11
+ns.sxtyptt.NET.CN. 604800 IN A 202.99.192.68
+NS2.MERCHANTWARE.com. 604800 IN A 209.170.142.35
+uunymdgds1.DOUBLECLICK.net. 604800 IN A 206.65.183.21
+e34.co.us.IBM.com. 604800 IN A 32.97.110.132
+kista.dns.swip.net. 604800 IN A 192.71.220.9
+ZEBRA.UEM.MZ. 604800 IN A 196.3.96.67
+NET2.GENDYN.com. 604800 IN A 204.60.171.9
+NS0.UTK.EDU. 604800 IN A 160.36.0.66
+NS.RELCOM.EU.net. 604800 IN A 193.124.23.3
+DNS0.AXION.BT.CO.UK. 604800 IN A 132.146.5.1
+mail.vhv.com. 604800 IN A 208.5.161.11
+DNS4.UK.MSFT.net. 604800 IN A 213.199.144.152
+NS2.ADNS.net. 604800 IN A 199.5.157.3
+NS1.SEATTLE.US.NETDNS.com. 604800 IN A 206.253.214.13
+NS2.UNIVIE.AC.at. 604800 IN A 193.171.255.66
+NS15B.BOCA15-VERIO.com. 604800 IN A 208.55.91.51
+www.BAYAREA.com. 604800 IN CNAME vh80040.vh8.infi.net.
+ns4.onemain.com. 604800 IN A 63.208.210.11
+NS2.EDIGITALS.com. 604800 IN A 211.39.139.36
+MICHAEL.VATICAN.VA. 604800 IN A 212.77.0.2
+AUSTIN.GH.com. 604800 IN A 196.3.64.1
+sld-ns2.CNNIC.NET.CN. 604800 IN A 202.97.16.197
+NS2.CDC.GOV. 604800 IN A 198.246.96.92
+NS.WATSON.IBM.com. 604800 IN A 198.81.209.2
+NS.NIC.SH. 604800 IN A 194.205.62.60
+NS2.BAHNHOF.net. 604800 IN A 212.85.64.4
+NS-AUTH2.cmates.com. 604800 IN A 208.23.213.3
+ISDMNL.WR.USGS.GOV. 604800 IN A 130.118.4.2
+NS2.COBEX.net. 604800 IN A 207.102.129.72
+MERLE.CIRA.CA. 604800 IN A 64.26.149.98
+NS.UVG.EDU.GT. 604800 IN A 168.234.68.2
+NS1.CWVA.DOUBLECLICK.net. 604800 IN A 205.138.3.20
+eliot.diebold.com. 604800 IN A 204.151.249.21
+NS.ALMADEN.IBM.com. 604800 IN A 198.4.83.35
+NS2.INTERNETSQUARE.com. 604800 IN A 205.227.232.9
+mail.QUEST-NET.com. 604800 IN A 207.140.30.11
+Z1.NS.LHR1.GLOBIX.net. 604800 IN A 212.111.32.38
+DNS1.AVANTEL.NET.MX. 604800 IN A 200.33.213.66
+vh80040.vh8.INFI.net. 604800 IN A 209.97.59.245
+NS.LEB.net. 604800 IN A 206.127.55.2
+NS.DCC.UCHILE.CL. 604800 IN A 146.83.5.204
+CLOUSO.RISQ.QC.CA. 604800 IN A 192.26.210.1
+muenster.westfalen.de. 604800 IN A 193.174.5.2
+us.a1.YIMG.com. 604800 IN CNAME a32.g.a.YIMG.com.
+NS.DEMOS.SU. 604800 IN A 194.87.0.8
+NS.DEMOS.SU. 604800 IN A 194.87.0.9
+south.NAVPOINT.com. 604800 IN A 207.106.42.12
+netconsult.netconx.de. 604800 IN A 193.141.75.1
+DNS2.btinternet.com. 604800 IN A 194.73.73.94
+NS2.CINE.net. 604800 IN A 207.168.250.12
+castor.cmc.ec.gc.CA. 604800 IN A 142.135.4.14
+EX2-DNS0.AVENUEA.com. 604800 IN A 216.34.88.20
+firewall3.glaxowellcome.com. 604800 IN A 192.58.204.207
+MACU.MA.MT.NP.ELS-GMS.att.net. 604800 IN A 199.191.145.136
+NS.PA. 604800 IN A 168.77.8.2
+TGSERV.TELE.GL. 604800 IN A 194.177.224.7
+KYNSE02.MESSAGESECURE.com. 604800 IN A 216.142.252.201
+GORGON.XTRA.CO.NZ. 604800 IN A 202.27.158.34
+DNS.NIC.IT. 604800 IN A 193.205.245.5
+pop.VERMONTEL.net. 604800 IN CNAME loomis.VERMONTEL.net.
+NS2.REGISTRY.HM. 604800 IN A 209.54.168.55
+NAMESERVER1.CONCENTRIC.net. 604800 IN A 207.155.183.73
+47.131.127.204.IN-ADDR.ARPA. 604800 IN PTR mtiwmhc22.worldnet.att.net.
+mailhost.tfm.com. 604800 IN A 192.231.224.11
+NS1.MRC.GM. 604800 IN A 212.60.69.1
+NS.WIDE.AD.JP. 604800 IN A 203.178.136.63
+NS.BTA.NET.CN. 604800 IN A 202.96.0.133
+NS2.ISPC.org. 604800 IN A 209.124.64.11
+BOW.RAIN.FR. 604800 IN A 194.51.3.49
+srs.srs.state.vt.us. 604800 IN A 159.105.101.150
+NS4.WEB2010.com. 604800 IN A 216.157.55.6
+NS.TELECOM.NET.ET. 604800 IN A 196.27.22.43
+NS1.DNS.NET.KH. 604800 IN A 203.127.100.21
+GATEN.JARING.MY. 604800 IN A 161.142.227.17
+shell.nominum.com. 604800 IN A 204.152.187.59
+CHEOPS.ANU.EDU.AU. 604800 IN A 150.203.224.24
+VANGOGH.CS.BERKELEY.EDU. 604800 IN A 128.32.33.5
+NS2.NOC.NULLUS.net. 604800 IN A 63.119.253.254
+NIC.LTH.SE. 604800 IN A 130.235.20.3
+ns.farm.net. 604800 IN A 216.112.179.160
+NS.USEC.SUN.com. 604800 IN A 192.9.48.3
+NS2.YOUR-DOMAIN.com. 604800 IN A 216.167.31.177
+DNS-EAST.PREP.net. 604800 IN A 129.250.252.10
+ns.hcr.net. 604800 IN A 208.240.246.4
+NS-RCH.nortelnetworks.com. 604800 IN A 192.135.215.2
+crl.DEC.com. 604800 IN A 192.58.206.2
+NS.PIXAR.ES. 604800 IN A 194.143.196.3
+MEX1-M-213.UNINET.NET.MX. 604800 IN A 200.33.146.213
+NS.ITU.CH. 604800 IN A 156.106.192.121
+matrix.uwm.EDU.PL. 604800 IN A 213.184.3.136
+gateway1.gmcr.com. 604800 IN A 12.34.108.130
+NS2.DNS.BR. 604800 IN A 200.19.119.99
+foxharp.boston.MA.us. 604800 IN MX 10 bparker.connactivity.com.
+Quest-7.symquest.com. 604800 IN A 64.69.102.131
+NS2.VERIO.net. 604800 IN A 129.250.31.190
+NAME.IAD.GBLX.net. 604800 IN A 204.152.166.155
+NS2.EMIRATES.NET.AE. 604800 IN A 194.170.1.7
+supai.oit.UMASS.EDU. 604800 IN A 128.119.175.6
+QUERN.EPILOGUE.com. 604800 IN A 128.224.1.136
+NS3.TOPICA.com. 604800 IN A 206.111.131.72
+NS1.JERKY.net. 604800 IN A 204.57.55.100
+JTB.BRUNET.BN. 604800 IN A 202.160.8.2
+AUTH100.NS.UU.net. 604800 IN A 198.6.1.202
+BOW.INTNET.DJ. 604800 IN A 193.251.143.253
+OSI2.GUA.net. 604800 IN A 205.161.188.3
+AZMODAN.ULA.VE. 604800 IN A 150.185.130.16
+THUMPER.RPSLMC.EDU. 604800 IN A 144.74.22.8
+ICHU.RCP.NET.PE. 604800 IN A 161.132.5.14
+NS.NIC.AC. 604800 IN A 194.205.62.120
+DNS.NETFLIGHT.com. 604800 IN A 207.88.32.2
+ns2.UTORONTO.CA. 604800 IN A 128.100.102.202
+mail.giffordmed.org. 604800 IN A 130.189.100.51
+RATA.VUW.AC.NZ. 604800 IN A 130.195.2.11
+NS-2.ADMONITOR.net. 604800 IN A 216.35.185.40
+NCC.MOC.KW. 604800 IN A 196.1.69.98
+NS.EUNET.ES. 604800 IN A 193.127.1.11
+NS3.best.com. 604800 IN A 209.24.149.42
+zip.MAIL-LIST.com. 604800 IN MX 5 zip.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 20 sluice.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 20 pipeline.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 20 transport.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 50 brisk.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 50 swifty.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 50 velocity.MAIL-LIST.com.
+JATZ.AARNET.EDU.AU. 604800 IN A 139.130.204.4
+DNS2.MAN.LODZ.PL. 604800 IN A 212.51.192.5
+NS.VERITAS.com. 604800 IN A 204.177.156.38
+218.241.103.199.IN-ADDR.ARPA. 604800 IN PTR abyssinian.sleepycat.com.
+BOW.SNPT.KM. 604800 IN A 195.101.19.253
+Z1.NS.SJC1.GLOBIX.net. 604800 IN A 209.10.34.55
+DNS.NIC.TT. 604800 IN A 24.3.198.194
+MAKISIG.IPHIL.net. 604800 IN A 203.176.28.135
+NS.DK.net. 604800 IN A 193.88.44.42
+NS.NI. 604800 IN A 200.30.36.8
+NS.NI. 604800 IN A 165.98.1.2
+CIUP1.NCC.UP.PT. 604800 IN A 193.136.51.52
+ns2.verisign-grs.com. 604800 IN A 198.41.3.108
+NS1.UMASS.EDU. 604800 IN A 128.119.166.14
+NS.NEWACCOUNT.net. 604800 IN A 216.121.96.26
+UDNS2.ULTRADNS.net. 604800 IN A 204.74.101.1
+NS2.LATNET.LV. 604800 IN A 159.148.108.1
+info-server.surrey.AC.UK. 604800 IN A 131.227.102.6
+NS2.SQUONK.net. 604800 IN A 63.84.12.135
+NS2.DSO.net. 604800 IN A 206.16.77.11
+www.energyenhancement.org. 604800 IN A 216.121.175.228
+DNS1.BD. 604800 IN A 209.58.24.5
+nl.COMPUWARE.com. 604800 IN MX 150 uucp.nl.net.
+nl.COMPUWARE.com. 604800 IN MX 50 bitbucket.extern.uniface.nl.
+nl.COMPUWARE.com. 604800 IN MX 100 smtp.nl.net.
+NS.DHIRAAGU.MV. 604800 IN A 202.1.192.196
+TRANTOR.UMD.EDU. 604800 IN A 128.8.10.14
+NS.ALCANET.NO. 604800 IN A 193.213.238.10
+Z6.MSFT.AKADNS.com. 604800 IN A 207.229.152.20
+NS4.ync.net. 604800 IN A 206.185.20.9
+CMTU.MT.NS.ELS-GMS.att.net. 604800 IN A 12.127.16.69
+vh40099.vh4.INFI.net. 604800 IN A 209.97.59.121
+ns2.secondary.nl. 604800 IN A 194.229.138.6
+abyssinian.sleepycat.com. 604800 IN A 199.103.241.218
+APHEX.MENTOR.BE. 604800 IN A 193.121.64.5
+webmail.fiberia.com. 604800 IN A 216.55.147.2
+localhost.moonmothers.com. 604800 IN A 127.0.0.1
+NS2.DNS.LU. 604800 IN A 158.64.229.3
+NS.VISUALCOM.ES. 604800 IN A 194.143.202.202
+TONIC.TO. 604800 IN A 206.184.59.10
+NS1.CRSNIC.net. 604800 IN A 198.41.3.39
+trurl.ispid.com.PL. 604800 IN A 195.150.99.3
+datingagentur.de. 604800 IN A 212.227.216.57
+NS2.NSIREGISTRY.net. 604800 IN A 198.41.3.108
+ICE.VIA-NET-WORKS.IE. 604800 IN A 212.17.32.2
+sgi1.map.com. 604800 IN A 204.71.19.20
+NS0.HS0.U-NET.net. 604800 IN A 194.119.128.70
+candle.pha.pa.us. 604800 IN A 162.33.245.46
+NS1.PACIFIC.NET.SG. 604800 IN A 192.169.33.3
+NS.CENIAI.NET.CU. 604800 IN A 169.158.128.136
+NS2.UUCP.NE.JP. 604800 IN A 210.141.111.69
+za.akamaitech.net. 604800 IN A 204.178.107.226
+NS.UCR.AC.CR. 604800 IN A 163.178.88.2
+DNS-02.NS.cs.com. 604800 IN A 205.188.157.235
+dns2.primary.net. 604800 IN A 205.242.187.235
+PAPPSRV.PAPP.UNDP.org. 604800 IN A 192.115.229.1
+NS1.REGME.com. 604800 IN A 207.153.57.14
+DNS.CS.KULEUVEN.AC.BE. 604800 IN A 134.58.40.4
+NS1.VERMONTLAW.net. 604800 IN A 63.89.26.15
+mail.garmontusa.com. 604800 IN A 64.30.8.178
+NS2.SAIPAN.com. 604800 IN A 202.128.28.2
+NS.ARICATRA.com. 604800 IN A 206.64.112.114
+ns2.reedmedia.net. 604800 IN A 209.241.86.6
+NS.NETLAB.SK. 604800 IN A 195.168.1.4
+RELAY.GW.tislabs.com. 604800 IN A 192.94.214.100
+b.ns.tmcs.net. 604800 IN A 209.104.33.252
+NS1.IBL.BM. 604800 IN A 199.172.192.1
+ok.RU. 604800 IN A 195.2.83.162
+NS.RICC.ALMA-ATA.SU. 604800 IN A 194.87.112.4
+KITKA.MARNET.MK. 604800 IN A 194.149.131.2
+dasher.dartmouth.EDU. 604800 IN A 129.170.208.6
+NS0.PLANET-THREE.com. 604800 IN A 212.49.219.164
+KNOCK.SER.BBNPLANET.net. 604800 IN A 192.239.16.129
+tornado.webtech.elk.PL. 604800 IN A 212.244.162.100
+AUTH2.NS.IDT.net. 604800 IN A 169.132.133.1
+host3.VTLEGALAID.org. 604800 IN A 207.136.208.115
+NS.EUNET.SK. 604800 IN A 192.108.130.33
+TULKU.NIC.AR. 604800 IN A 200.16.97.77
+RELAY.CDNNET.CA. 604800 IN A 192.73.5.1
+DNS2.TPSA.PL. 604800 IN A 194.204.152.34
+enterprise.wirbel.com. 604800 IN A 194.231.54.2
+ECNET.EC. 604800 IN A 157.100.45.2
+ENGINE1.UNA.net. 604800 IN A 208.136.52.74
+WYCU.WY.BR.NP.ELS-GMS.att.net. 604800 IN A 199.191.128.43
+ARWENA.NASK.WAW.PL. 604800 IN A 193.59.201.28
+PAC2.NIPR.MIL. 604800 IN A 199.252.155.234
+DAISY.EE.UND.AC.ZA. 604800 IN A 146.230.192.18
+odin.ietf.org. 604800 IN A 132.151.1.176
+dns.kaben-net.de. 604800 IN A 195.179.28.17
+NS2.ALTAVISTA.com. 604800 IN A 209.73.164.7
+CASTOR.TELEGLOBE.net. 604800 IN A 199.202.55.2
+CIR.RED.SV. 604800 IN A 168.243.254.1
+PIJIN.COM.SB. 604800 IN A 202.139.42.10
+NS4.CTCCOM.net. 604800 IN A 64.69.100.35
+NS1.SOL.NO. 604800 IN A 195.225.2.10
+DNS2.TK.MSFT.net. 604800 IN A 207.46.232.38
+NS.BSDI.com. 604800 IN A 207.174.116.8
+NS.SVIANED.nl. 604800 IN A 143.177.1.3
+NS.NOVELL.com. 604800 IN A 137.65.1.1
+NS.LUCKY.net. 604800 IN A 193.193.193.100
+SJC-NS2.SJC.LYCOS.com. 604800 IN A 206.79.171.40
+NS1.OP.net. 604800 IN A 209.152.193.4
+worldnet.att.net. 604800 IN A 199.70.151.234
+APIES.FRD.AC.ZA. 604800 IN A 137.214.80.1
+mail.skiinsurance.com. 604800 IN A 207.136.205.152
+NS.BELNET.BE. 604800 IN A 193.190.198.2
+NS.BELNET.BE. 604800 IN A 193.190.198.10
+KOMO.INET.GA. 604800 IN A 208.148.44.1
+EARTH.THEPLANET.net. 604800 IN A 195.92.195.222
+VASCO.USMA.AC.PA. 604800 IN A 208.141.92.2
+GODFEVER.DCCSERVER.com. 604800 IN A 208.137.22.6
+BOS-NS2.BOS.LYCOS.com. 604800 IN A 209.67.228.40
+NS2.GOTO.com. 604800 IN A 204.71.128.137
+NS1.overstock.com. 604800 IN A 207.225.194.13
+NS1-PUBLIC.ZMA.COMPAQ.com. 604800 IN A 161.114.64.24
+ns.ilovedomain.com. 604800 IN A 211.175.164.170
+ns1.anycast.net. 604800 IN A 216.196.51.4
+PASCAL.UPRR.PR. 604800 IN A 134.202.1.120
+NS3-AUTH.SPRINTLINK.net. 604800 IN A 144.228.255.10
+NS1-Y.DNS.PIPEX.net. 604800 IN A 158.43.193.89
+prue.eim.surrey.AC.UK. 604800 IN A 131.227.76.5
+TROLL-GW.GATECH.EDU. 604800 IN A 130.207.244.251
+NS.SIERRATEL.SL. 604800 IN A 194.133.124.5
+ns2.PSHIFT.com. 604800 IN A 208.153.85.21
+NS.ERS.IBM.com. 604800 IN A 204.146.173.35
+ASLAN.OPEN-RSC.org. 604800 IN A 199.5.157.128
+NS2.DOMAIN-REGISTRY.nl. 604800 IN A 193.176.144.130
+uranus.lan-ks.de. 604800 IN A 194.45.71.1
+mail.unlisys.net. 604800 IN A 195.21.255.252
+NS.AUSTRIA.EU.net. 604800 IN A 192.92.138.35
+AUTH01.CONNECT.IE. 604800 IN A 194.106.128.50
+SUN.SCSI.GOV.BY. 604800 IN A 195.50.5.103
+NS1.SIGMAHOSTING.com. 604800 IN A 209.241.86.6
+NS.CAST.EDU.JM. 604800 IN A 200.9.115.2
+DS.NIC.NET.SG. 604800 IN A 202.42.194.205
+PRADES.CESCA.ES. 604800 IN A 192.94.163.152
+ns.sta.NET.CN. 604800 IN A 202.96.199.133
+NSE00.excite.com. 604800 IN A 198.3.102.250
+NS3.ABOVE.net. 604800 IN A 207.126.105.146
+CASBAH.ELDJAZAIR.NET.DZ. 604800 IN A 193.194.81.45
+ASKIA.SOTELMA.ML. 604800 IN A 208.144.230.3
+NS.IDT.net. 604800 IN A 198.4.75.100
+FXCLPR02.IS.CHRYSLER.com. 604800 IN A 204.189.94.37
+SVC00.APNIC.net. 604800 IN A 202.12.28.131
+NS5.DCX.YAHOO.com. 604800 IN A 216.32.74.10
+ns1.ray.net. 604800 IN A 195.238.228.131
+NS.NIC.MC. 604800 IN A 195.78.6.131
+ns.runway.CN.net. 604800 IN A 211.101.132.8
+benoni.uit.NO. 604800 IN A 129.242.4.254
+SCRATCHY.MINDSPRING.net. 604800 IN A 207.69.200.211
+ns1.pcode.com. 604800 IN A 216.15.192.135
+ns1.aha.RU. 604800 IN A 195.2.80.142
+ns2.uwaterloo.CA. 604800 IN A 129.97.128.100
+ns2.NIC.AD.JP. 604800 IN A 202.12.30.133
+a.ns.foxharp.boston.MA.us. 604800 IN A 24.147.209.205
+NS.NIC.IO. 604800 IN A 194.205.62.100
+A-GTLD-SERVERS.dot-god.com. 604800 IN A 205.189.73.123
+SMTP.slac.stanford.EDU. 604800 IN A 134.79.18.80
+52.87.198.209.IN-ADDR.ARPA. 604800 IN PTR mqueue0.sover.net.
+BARNEY.ADVSYS.CO.UK. 604800 IN A 194.72.124.2
+NS1.TELEPAC.PT. 604800 IN A 194.65.3.20
+NICOSIA.CCS.UCY.AC.CY. 604800 IN A 194.42.6.97
+NS.PUNCHDOWN.org. 604800 IN A 140.174.131.100
+SYNAESTHESIA.COGNOSCENTI.org. 604800 IN A 207.208.112.4
+NS2.PLANET-THREE.net. 604800 IN A 212.49.219.190
+DNS.CIT.CORNELL.EDU. 604800 IN A 192.35.82.50
+MODOR.VERISIGN.net. 604800 IN A 205.139.94.55
+SUNSTROKE.IS.RPSLMC.EDU. 604800 IN A 144.74.21.8
+NS2.SEG.net. 604800 IN A 206.34.181.16
+NEMUNAS.SC-UNI.KTU.LT. 604800 IN A 193.219.32.13
+MULGA.CS.MU.OZ.AU. 604800 IN A 128.250.1.22
+MULGA.CS.MU.OZ.AU. 604800 IN A 128.250.37.150
+NS1.NPLUS.GF. 604800 IN A 195.6.144.3
+ns2.centralinfo.net. 604800 IN A 63.102.204.130
+K.GTLD-SERVERS.net. 604800 IN A 213.177.194.5
+ns1.codelocal.com. 604800 IN A 216.15.192.130
+NS2.IPNS.com. 604800 IN A 63.230.183.1
+NS0.DE.NIC.NU. 604800 IN A 216.200.116.40
+NS.USSR.EU.net. 604800 IN A 193.124.22.65
+NS.INTERNET.SK. 604800 IN A 192.108.130.91
+CORREOS.SEKER.ES. 604800 IN A 194.179.87.1
+mx1.buf.ADELPHIA.net. 604800 IN A 24.48.36.10
+aun.UNINETT.NO. 604800 IN A 129.241.1.99
+NS0.NETANET.com. 604800 IN A 195.172.127.72
+NS0.NETANET.com. 604800 IN A 194.6.96.218
+www.MANY-PATHS-ENERGY-ENHANCEMENT.com. 604800 IN A 66.33.4.50
+NS2.STARFIRE.DOUGLAS.MA.us. 604800 IN A 216.129.136.9
+NS3.IKP.PL. 604800 IN A 157.25.5.30
+pns.dtag.de. 604800 IN A 194.25.0.125
+NZ.NS.NIC.NU. 604800 IN A 203.97.132.66
+DAVER.bungi.com. 604800 IN A 207.126.97.2
+DAVER.bungi.com. 604800 IN A 206.14.228.2
+gutenberg.bucksnet.com. 604800 IN A 207.113.15.5
+DNS2.IT.net. 604800 IN A 151.1.2.1
+NS2.SNS-UT.DEBIS.com. 604800 IN A 53.122.2.10
+ISI.EDU. 604800 IN A 128.9.176.32
+amethyst.xaos.org. 604800 IN A 204.145.159.12
+PAPPILLOMA.WWEBSVS.com. 604800 IN A 209.233.37.10
+NS2.bock.com. 604800 IN A 64.30.29.4
+NS2.OAR.net. 604800 IN A 192.88.195.10
+MINION.NETPOLICY.com. 604800 IN A 207.87.121.66
+Mail.catic1.com. 604800 IN A 207.190.204.103
+NS4.DNS.space.net. 604800 IN A 195.222.210.93
+b.gtld-servers.ORSC. 604800 IN A 216.13.126.116
+bend.madriver.com. 604800 IN A 207.136.232.15
+NS4.IS-FUN.net. 604800 IN A 212.162.54.34
+NS2.JPS.net. 604800 IN A 216.224.156.252
+NS1.IP-PLUS.net. 604800 IN A 164.128.36.34
+rush.cc1.RPSLMC.EDU. 604800 IN A 144.74.150.23
+NS2.GBMTECH.net. 604800 IN A 208.243.164.3
+DNS.MSEN.com. 604800 IN A 148.59.19.11
+DNSSEC2.SINGNET.COM.SG. 604800 IN A 195.13.10.226
+NS2.HOME.net. 604800 IN A 24.2.0.27
+ACCESS.MBNET.MB.CA. 604800 IN A 130.179.16.143
+DNS0.SPIN.AD.JP. 604800 IN A 165.76.0.98
+Filer.PHOTOTRUST.com. 604800 IN A 64.85.86.172
+jpl.NASA.GOV. 604800 IN A 137.78.160.180
+NS2.TECHNOLOGIA.net. 604800 IN A 207.253.59.4
+bparker.CONNACTIVITY.com. 604800 IN A 206.34.200.200
+NS1.uvm.EDU. 604800 IN A 132.198.201.10
+NS.SENET.net. 604800 IN A 206.155.163.195
+DNS2.UTCC.UTORONTO.CA. 604800 IN A 128.100.102.201
+localhost.costorf.com. 604800 IN A 127.0.0.1
+DNS2.AD. 604800 IN A 194.158.64.8
+HYDRA.HELSINKI.FI. 604800 IN A 128.214.4.29
+NAME.PHX.GBLX.net. 604800 IN A 206.165.6.10
+NS2.FOOL.com. 604800 IN A 208.51.76.222
+NS01-SERVER.CURINFO.AN. 604800 IN A 200.44.117.129
+NS.CR. 604800 IN A 163.178.8.2
+mail.pshift.net. 604800 IN A 208.153.85.30
+NS.IRD.FR. 604800 IN A 195.83.14.1
+NS.UZ. 604800 IN A 213.68.88.11
+DNS.INTELCOM.SM. 604800 IN A 194.183.64.11
+DNS2.UNIV-NKC.MR. 604800 IN A 193.251.145.154
+HNS3.hns.com. 604800 IN A 208.236.67.3
+bay.cs.UTORONTO.CA. 604800 IN A 128.100.1.1
+NS0.BT.net. 604800 IN A 194.72.6.51
+BAYONET.SJMERCURY.com. 604800 IN A 207.1.134.34
+PAN.BIJT.net. 604800 IN A 213.196.2.97
+NAVI.SUBTEND.net. 604800 IN A 208.186.117.224
+NS.CIX.CX. 604800 IN A 195.222.235.216
+waldorf.Informatik.Uni-Dortmund.de. 604800 IN A 129.217.4.42
+NS2.ivillage.com. 604800 IN A 209.185.162.16
+DNS.NIC.XLINK.net. 604800 IN A 193.141.40.42
+NS1.MERCHANTWARE.CON. 604800 IN A 209.170.142.34
+NS.TO.GD-ES.com. 604800 IN A 199.107.240.66
+NS-A.RNC.RO. 604800 IN A 192.162.16.31
+REGGAE.NCREN.net. 604800 IN A 128.109.131.3
+SSS-NL.DENIC.de. 604800 IN A 193.0.0.237
+NS1.TDC.TO. 604800 IN A 206.86.247.250
+NS.NIC.HU. 604800 IN A 193.6.27.62
+JOANNA.WILLIAM.org. 604800 IN A 195.153.6.2
+NS0.IIJ.AD.JP. 604800 IN A 202.232.2.34
+maus.spack.org. 604800 IN A 204.245.198.90
+B.NS.VERIO.net. 604800 IN A 129.250.35.32
+SECDNS.EUNET.BE. 604800 IN A 193.74.208.139
+NS3.EUROPE.YAHOO.com. 604800 IN A 217.12.4.71
+A.ROOT-SERVERS.net. 604800 IN A 198.41.0.4
+sherickpm.com. 604800 IN MX 10 inbound.sherickpm.com.criticalpath.net.
+NS2.MEDIASERVICES.net. 604800 IN A 64.65.16.237
+YARDBIRD.CNS.vt.EDU. 604800 IN A 198.82.247.34
+SUNIC.SUNET.SE. 604800 IN A 192.36.125.2
+NS.MT. 604800 IN A 193.188.47.252
+CNDVG001.usa.net. 604800 IN A 165.212.12.1
+NS1.CX.ESCROW.IOCOMM.NET.CX. 604800 IN A 203.132.96.2
+DNS-02.NS.AOL.com. 604800 IN A 205.188.157.232
+ns2.tesserae.com. 604800 IN A 209.157.194.3
+SV10.BATELCO.COM.BH. 604800 IN A 193.188.124.227
+dec.anr.state.vt.us. 604800 IN MX 0 dec.anr.state.vt.us.
+dec.anr.state.vt.us. 604800 IN MX 10 mx1.state.vt.us.
+dec.anr.state.vt.us. 604800 IN MX 10 mx2.state.vt.us.
+3.133.188.192.IN-ADDR.ARPA. 604800 IN PTR elektro.com.
+NS1.LONDON.UK.NETDNS.com. 604800 IN A 212.62.6.38
+NS.NIC.MG. 604800 IN A 194.214.107.253
+DNS1.VN. 604800 IN A 203.162.3.235
+DENS20.DEN.nps.GOV. 604800 IN A 165.83.24.20
+z.ip6.INT. 604800 IN A 198.32.2.66
+NS3.TRIVALLEY.com. 604800 IN A 206.25.132.30
+isis.imag.FR. 604800 IN A 129.88.32.24
+NS.SOVAM.com. 604800 IN A 194.67.2.97
+NS-SOA.DARENET.DK. 604800 IN A 130.226.1.4
+NS4.NIC.TV. 604800 IN A 207.151.24.23
+DNSSRV1X.mitre.org. 604800 IN A 199.94.97.51
+GATEKEEPER.NYTIMES.com. 604800 IN A 199.181.175.201
+D.I-DNS.net. 604800 IN A 211.169.245.170
+NS.KOLO.net. 604800 IN A 209.66.103.20
+NS4.FIRSTWORLD.net. 604800 IN A 216.7.160.162
+DECST.CERIST.DZ. 604800 IN A 193.194.64.11
+NS4.DNS.WS. 604800 IN A 216.52.234.102
+NS0.GDGSC.com. 604800 IN A 192.160.62.66
+UCTHPX.UCT.AC.ZA. 604800 IN A 137.158.128.1
+NS2.HOTWIRED.com. 604800 IN A 209.185.151.6
+ns02.ca.us.ibm.net. 604800 IN A 165.87.201.243
+NS2.SPEAKEASY.net. 604800 IN A 216.231.41.22
+TELCOM.ZPTC.CO.ZW. 604800 IN A 194.133.122.47
+NS.DK-HOSTMASTER.DK. 604800 IN A 193.163.102.2
+NS.NIC.LK. 604800 IN A 192.248.1.65
+NS2.zama.net. 604800 IN A 203.142.130.5
+CZ.EUNET.CZ. 604800 IN A 193.85.3.130
+NS.AC.ID. 604800 IN A 202.159.124.34
+NS1.CUBE.de. 604800 IN A 212.162.54.243
+NS1.QUASAR.net. 604800 IN A 199.166.31.3
+NS1.OFFSHORE.AI. 604800 IN A 209.88.68.34
+NS5.NRSITE.com. 604800 IN A 208.178.169.4
+NS.AIC.net. 604800 IN A 195.250.64.65
+OWL.NCC.nps.GOV. 604800 IN A 165.83.34.60
+MAXIM.gbch.net. 604800 IN A 203.9.155.249
+BOW.INTNET.TD. 604800 IN A 193.251.147.253
+ns1.cacheware.com. 604800 IN A 64.221.210.242
+NS2.SPEEDHOST.com. 604800 IN A 216.42.31.169
+NS1.COMMIT.GM. 604800 IN A 63.77.152.177
+NAME.ROC.GBLX.net. 604800 IN A 209.130.187.10
+90.198.245.204.IN-ADDR.ARPA. 604800 IN PTR maus.spack.org.
+BOLOGNA.NETTUNO.IT. 604800 IN A 193.43.2.5
+NIC.IBD.com. 604800 IN A 209.249.61.18
+NS.WESTOL.com. 604800 IN A 63.93.137.4
+time.SOVER.net. 604800 IN CNAME garnet.SOVER.net.
+UNIX1.CS.UMASS.EDU. 604800 IN A 128.119.40.12
+AARDVARK.WR.UMIST.AC.UK. 604800 IN A 130.88.146.3
+AARDVARK.WR.UMIST.AC.UK. 604800 IN A 128.16.5.31
+NS1.NIC.YU. 604800 IN A 147.91.8.6
+mail.velco.com. 604800 IN A 198.136.217.106
+DNSAUTH2.SYS.GTEI.net. 604800 IN A 4.2.49.3
+NS.TELE.FI. 604800 IN A 193.210.19.19
+state.vt.us. 604800 IN MX 10 mx1.state.vt.us.
+state.vt.us. 604800 IN MX 10 mx2.state.vt.us.
+NS.NYC.juno.com. 604800 IN A 205.231.108.1
+NS1.g-world.com. 604800 IN A 216.26.39.10
+AUTH2.AMERICA.net. 604800 IN A 209.17.197.18
+KIRA.ECS.UMASS.EDU. 604800 IN A 128.119.91.10
+CONACYT.GOB.SV. 604800 IN A 168.243.64.2
+DNS.SRCE.HR. 604800 IN A 161.53.3.7
+NS00.ns0.com. 604800 IN A 216.92.60.60
+NS2.CL.BELLSOUTH.net. 604800 IN A 205.152.16.8
+jenner.med.HARVARD.EDU. 604800 IN A 134.174.141.2
+p2.cavebear.com. 604800 IN A 199.184.128.35
+NS1.NIC.JE. 604800 IN A 216.110.45.224
+ORCU.OR.BR.NP.ELS-GMS.att.net. 604800 IN A 199.191.129.139
+NS.XBILL.org. 604800 IN A 204.152.186.163
+WRAITH.CS.UOW.EDU.AU. 604800 IN A 130.130.64.1
+12.159.145.204.IN-ADDR.ARPA. 604800 IN PTR amethyst.xaos.org.
+ns1.pr.SUN.com. 604800 IN A 192.18.16.2
+NS.SPIN.OMNES.net. 604800 IN A 192.23.90.196
+smtp.188.net. 604800 IN A 202.96.125.104
+TERMINAL.2GLOBE.net. 604800 IN A 195.178.183.230
+NS2.HARVARD.EDU. 604800 IN A 128.103.1.1
+NAMESERVER.CNR.IT. 604800 IN A 194.119.192.34
+EARTH.SY. 604800 IN A 195.22.198.6
+DNS2.REACCIUN.VE. 604800 IN A 150.188.4.212
+NS.TMX.COM.NI. 604800 IN A 205.218.253.2
+freefour.acs.rpi.EDU. 604800 IN A 128.113.24.91
+242.84.198.209.IN-ADDR.ARPA. 604800 IN PTR dlawren-gw.burl.sover.net.
+CORREU.STA.AD. 604800 IN A 194.158.67.1
+NS.DRUKNET.NET.BT. 604800 IN A 202.144.128.200
+NS4.US.PRSERV.net. 604800 IN A 165.87.201.244
+KAASASSUK.GH.GL. 604800 IN A 194.177.232.3
+ECUA.NET.EC. 604800 IN A 157.100.1.2
+NS.CONCYT.GOB.GT. 604800 IN A 168.234.106.2
+NS2.NAP.net. 604800 IN A 206.54.224.1
+DNS2.CN.net. 604800 IN A 202.97.18.61
+MX.NSI.NASA.GOV. 604800 IN A 128.102.18.31
+NS.TDS.net. 604800 IN A 204.246.1.20
+tdns-me1.NETSCAPE.com. 604800 IN A 205.188.247.67
+NS2.METU.EDU.TR. 604800 IN A 144.122.199.93
+NS2.SETARNET.AW. 604800 IN A 206.48.100.11
+87.184.152.204.IN-ADDR.ARPA. 604800 IN PTR isrv3-i.isc.org.
+DNS.OMNIWAY.SM. 604800 IN A 194.183.64.10
+NS0.U-NET.net. 604800 IN A 194.119.128.65
+elektro.CMHNET.org. 604800 IN A 192.188.133.3
+ns2.HIGGS.net. 604800 IN A 204.80.125.145
+NS2.SKYNETWEB.com. 604800 IN A 208.231.1.35
+MAGIC.MN. 604800 IN A 202.131.0.10
+NS1.YAHOO.com. 604800 IN A 204.71.200.33
+mx1.cdp.ADELPHIA.net. 604800 IN A 24.48.58.221
+SANTO.VANUATU.COM.VU. 604800 IN A 202.139.40.7
+www.mmuuf.org. 604800 IN MX 10 gro.dd.org.
+ns1.timeheart.net. 604800 IN A 63.197.231.203
+NS2.TOGETHER.net. 604800 IN A 204.97.120.31
+NS.AMNIC.net. 604800 IN A 195.250.64.90
+NS.EENET.EE. 604800 IN A 193.40.56.245
+www.ONLINEPHOTOCONTEST.com. 604800 IN A 64.85.86.152
+VIC20.BLIPP.com. 604800 IN A 195.163.165.35
+DNS.FROGHOUSE.org. 604800 IN A 207.121.69.243
+NS2.ELI.net. 604800 IN A 207.173.86.2
+NS.CAIS.com. 604800 IN A 205.177.10.10
+BAABEN.AFRIQ.net. 604800 IN A 165.231.1.3
+NS2.NJ.EXODUS.net. 604800 IN A 209.1.10.234
+DOMREG.NIC.CH. 604800 IN A 130.59.1.80
+NS.EU.net. 604800 IN A 192.16.202.11
+NS1.DIEBOLD.net. 604800 IN A 65.196.80.10
+NS3.CP.net. 604800 IN A 209.228.14.4
+DNS.FUW.EDU.PL. 604800 IN A 193.0.80.11
+www.retro.com. 604800 IN A 205.179.181.195
+NS2.UNI2.net. 604800 IN A 195.82.195.99
+ns1.alcatrazmedia.com. 604800 IN A 167.160.132.2
+dns6.CP.MSFT.net. 604800 IN A 207.46.138.20
+NS1.SEYCHELLES.net. 604800 IN A 202.84.235.33
+NS2.INTERNIC.net. 604800 IN A 198.41.0.11
+front.macrosoft.WAW.PL. 604800 IN A 194.196.86.66
+NISC.JVNC.net. 604800 IN A 128.121.50.7
+AUTH03.NS.DE.UU.net. 604800 IN A 192.76.144.16
+BURDELL.CC.GATECH.EDU. 604800 IN A 130.207.3.207
+NS4.AH.net. 604800 IN A 203.21.205.20
+ns1.sgh-net.de. 604800 IN A 212.86.129.142
+Leland2.stanford.EDU. 604800 IN A 171.64.14.58
+CBRU.BR.NS.ELS-GMS.att.net. 604800 IN A 199.191.128.105
+DENEB.DOMAINNT.net. 604800 IN A 207.211.220.90
+ns1.ivm.net. 604800 IN A 62.204.1.1
+NS0.CWCI.net. 604800 IN A 194.6.79.162
+35.110.16.12.IN-ADDR.ARPA. 604800 IN CNAME 35.32/27.110.16.12.IN-ADDR.ARPA.
+f.trns. 604800 IN A 209.133.38.16
+ODISEJ.TELEKOM.YU. 604800 IN A 195.178.32.2
+FRCU.EUN.EG. 604800 IN A 193.227.1.1
+NS.HHS.net. 604800 IN A 63.93.136.29
+FOO.GRNET.GR. 604800 IN A 194.177.210.211
+mail.WonderWorks.com. 604800 IN A 192.203.206.67
+NS1.IAFRICA.com. 604800 IN A 196.7.0.139
+NS.KACST.EDU.SA. 604800 IN A 212.26.44.3
+srs.state.vt.us. 604800 IN A 159.105.101.150
+OM4.OMANTEL.NET.OM. 604800 IN A 206.49.101.5
+Yeshua.Christ.com. 604800 IN A 207.54.4.5
+NS1.SIMORGH.com. 604800 IN A 209.1.163.10
+OLKETA.SOLOMON.COM.SB. 604800 IN A 202.139.42.4
+BANBA.DOMAINREGISTRY.IE. 604800 IN A 193.1.142.2
+NOC.IOS.com. 604800 IN A 198.4.75.69
+ns.schnism.net. 604800 IN A 195.88.150.3
+e4.ny.us.IBM.com. 604800 IN A 32.97.182.104
+DNS2.SEANET.com. 604800 IN A 199.181.164.2
+doubt.dd.org. 604800 IN A 209.198.103.193
+AMBER.ELEKTRON.PL. 604800 IN A 195.117.6.10
+gw.rge.com. 604800 IN A 157.225.178.11
+NS2.ZTNET.com. 604800 IN A 63.211.17.252
+NS3.INFI.net. 604800 IN A 205.219.239.5
+ZA.AKADNS.net. 604800 IN A 209.185.188.39
+ESTIA.CSI.FORTH.GR. 604800 IN A 139.91.191.3
+vtagr04.agr.state.vt.us. 604800 IN A 159.105.50.4
+NS1-PUBLIC.ZTX.COMPAQ.com. 604800 IN A 161.114.1.204
+ADMII.ARL.MIL. 604800 IN A 128.63.31.4
+ADMII.ARL.MIL. 604800 IN A 128.63.5.4
+NS.NIXU.FI. 604800 IN A 193.209.237.29
+DNS2.PIONEERNET.net. 604800 IN A 208.240.196.10
+NS.NIC.CL. 604800 IN A 146.83.4.11
+NS2.UTZ. 604800 IN A 160.124.112.10
+NS4.LUXNOC.com. 604800 IN A 195.206.104.201
+NS2.PBI.net. 604800 IN A 206.13.29.11
+annwfn.erfurt.thur.de. 604800 IN A 194.122.210.3
+NS1.MW.mediaone.net. 604800 IN A 24.131.1.8
+NS1.ISU.NET.SA. 604800 IN A 212.26.18.3
+pop.SHOREHAM.net. 604800 IN CNAME SHOREHAM.net.
+DNS2.GUERNSEY.net. 604800 IN A 195.226.128.3
+NS1.BEACHSHORE.net. 604800 IN A 199.166.31.250
+HKUXB.HKU.HK. 604800 IN A 147.8.16.15
+NS.DOLEH.com. 604800 IN A 204.255.25.63
+NS.hactrn.net. 604800 IN A 216.254.68.12
+MALAKULA.BONDY.IRD.FR. 604800 IN A 193.50.53.1
+NS1.mediaone.net. 604800 IN A 24.128.1.80
+NS2.GPG.com. 604800 IN A 209.1.163.50
+noc.BelWue.de. 604800 IN A 129.143.2.1
+NS2.GIP.net. 604800 IN A 204.59.1.222
+RS.ISLES.net. 604800 IN A 212.100.224.90
+BOW.INTNET.GQ. 604800 IN A 195.101.152.253
+A.OPEN.BY. 604800 IN A 194.226.121.36
+us.i1.YIMG.com. 604800 IN CNAME a1.g.a.YIMG.com.
+athome.wetlogic.net. 604800 IN CNAME c1059495-a.snvl1.sfba.home.com.
+NS1.NIST.GOV. 604800 IN A 129.6.13.2
+mail.jerusalem-mail.com. 604800 IN A 216.251.232.93
+ISDSUN.cr.USGS.GOV. 604800 IN A 136.177.16.3
+NS.BOSTON.juno.com. 604800 IN A 64.136.25.53
+NS2.CADABRA.com. 604800 IN A 209.157.194.109
+nps.GOV. 604800 IN MX 10 ccmail2.itd.nps.GOV.
+nps.GOV. 604800 IN MX 5 ccmail.itd.nps.GOV.
+RELAY.HUJI.AC.IL. 604800 IN A 128.139.6.1
+styx.tahina.priv.at. 604800 IN A 194.152.163.253
+ISGATE.IS. 604800 IN A 193.4.58.51
+ns0.lux.dot-eu.org. 604800 IN A 195.206.105.102
+BILBO.NASK.ORG.PL. 604800 IN A 195.187.245.51
+BILBO.NASK.ORG.PL. 604800 IN A 148.81.16.51
+MAIL.TARSUS.com. 604800 IN A 208.130.9.252
+SUN.REDIRIS.ES. 604800 IN A 130.206.1.2
+NS2.NEASE.net. 604800 IN A 202.103.134.4
+OHCU.OH.MT.NP.ELS-GMS.att.net. 604800 IN A 199.191.144.75
+NS2.NF. 604800 IN A 203.12.249.101
+MIRAF-SERVER3.HONDUTEL.HN. 604800 IN A 206.48.104.142
+ns3.worldnet.att.net. 604800 IN A 204.127.160.1
+NS2.NETNAMES.net. 604800 IN A 212.53.77.28
+ITGBOX.IAT.CNR.IT. 604800 IN A 146.48.65.46
+NS2.ADELPHIA.net. 604800 IN A 24.48.62.35
+NS2.RIPN.net. 604800 IN A 195.209.0.6
+NS1.cinenet.net. 604800 IN A 198.147.76.65
+jengate.thur.de. 604800 IN A 193.174.15.34
+NOC.ULCC.JA.net. 604800 IN A 193.63.94.25
+NS.NOC.UZ. 604800 IN A 194.67.52.42
+NS0.JA.net. 604800 IN A 128.86.1.20
+NS0.JA.net. 604800 IN A 193.63.94.20
+NS2.INR.net. 604800 IN A 198.77.208.3
+netsage.org. 604800 IN A 209.67.235.38
+TERI.USP.AC.FJ. 604800 IN A 144.120.8.1
+NS2.NETSOL.com. 604800 IN A 198.17.208.71
+NS2.ABAC.com. 604800 IN A 216.55.144.4
+NS2.NIC.FR. 604800 IN A 192.93.0.4
+KANIN.ARNES.SI. 604800 IN A 193.2.1.66
+NS.EDU.GU. 604800 IN A 168.123.2.50
+DNS.INRIA.FR. 604800 IN A 193.51.208.13
+HEDNS1.GOOGLE.com. 604800 IN A 64.209.200.10
+asylum.sf.ca.us. 604800 IN A 192.48.232.17
+ACT2.ACT2000.net. 604800 IN A 207.42.132.227
+ICM1.ICP.net. 604800 IN A 192.94.207.66
+202.192.103.198.209.IN-ADDR.ARPA. 604800 IN PTR fraud.dd.org.
+ECSEL.jhuapl.EDU. 604800 IN A 128.244.65.29
+NS2.DCNY.DOUBLECLICK.net. 604800 IN A 204.253.104.10
+keith.netsage.org. 604800 IN A 209.67.235.37
+MANTA.OUTREMER.com. 604800 IN A 213.16.1.106
+NS2.globalnetisp.net. 604800 IN A 207.136.213.2
+NS2.CCSRS.net. 604800 IN A 206.253.214.73
+NS1.NL.CONCENTRIC.com. 604800 IN A 195.18.114.5
+NS2.VI.net. 604800 IN A 212.78.64.10
+NS2.NEO.net. 604800 IN A 206.109.7.65
+cgi.MERCURYCENTER.com. 604800 IN CNAME vh80167.vh8.infi.net.
+ORSTOM.RIO.net. 604800 IN A 192.33.151.1
+NS2.CONRADPROMOTIONS.com. 604800 IN A 208.24.118.203
+YARRINA.CONNECT.COM.AU. 604800 IN A 192.189.54.17
+dns03.OPS.usa.net. 604800 IN A 204.68.24.136
+APPSRV.HAITIWORLD.com. 604800 IN A 206.152.15.34
+NS.RELCOM.KZ. 604800 IN A 212.110.240.65
+NS1.MAGIC-MOMENTS.com. 604800 IN A 195.224.53.80
+NS.ALCATEL.com. 604800 IN A 192.160.6.91
+ns2.terra.net. 604800 IN A 199.103.128.2
+NS3.hotmail.com. 604800 IN A 209.185.130.68
+vtc.VSC.EDU. 604800 IN MX 0 eve.vtc.VSC.EDU.
+www.vmba.org. 604800 IN MX 10 gro.dd.org.
+NAHOURI.ONATEL.BF. 604800 IN A 206.82.130.195
+SERVER2.INFN.IT. 604800 IN A 131.154.1.3
+NS2.AI-R.com. 604800 IN A 66.33.4.51
+NS1.FREE.net. 604800 IN A 147.45.15.34
+vcmr-54.server.rpi.EDU. 604800 IN A 128.113.113.44
+haig.CS.UCL.AC.UK. 604800 IN A 128.16.6.8
+mail.nova-data.com. 604800 IN A 12.16.110.35
+MOEVAX.EDU.TW. 604800 IN A 140.111.1.2
+NS2.LTWCC.org. 604800 IN A 12.33.66.62
+NS.BA. 604800 IN A 195.130.35.5
+noc.HRZ.uni-bielefeld.de. 604800 IN A 129.70.5.16
+VANILLA.WRO.nps.GOV. 604800 IN A 165.83.71.3
+NS2.SZTAKI.HU. 604800 IN A 193.225.86.1
+SECIU.EDU.UY. 604800 IN A 164.73.128.5
+COL2.CARIBSURF.com. 604800 IN A 205.214.192.202
+NS2.QATAR.NET.QA. 604800 IN A 212.77.192.13
+NS2.E-SYNC.net. 604800 IN A 192.206.57.128
+ns1.eu.SUN.com. 604800 IN A 192.18.240.8
+NS1.UUSJ.DOUBLECLICK.net. 604800 IN A 204.176.177.10
+NS2.CUHK.EDU.HK. 604800 IN A 137.189.6.21
+NS1.MEITCA.com. 604800 IN A 137.203.5.1
+NS2.DSL.net. 604800 IN A 209.87.79.232
+techfac.techfak.uni-bielefeld.de. 604800 IN A 129.70.132.100
+listserv.performancediver.com. 604800 IN A 216.34.185.155
+foolusmf.D4P.net. 604800 IN CNAME a100.g.akamai.net.
+pedic-med.vrx.net. 604800 IN A 199.166.24.2
+GRUMPY.NET.NA. 604800 IN A 196.20.23.1
+BK.tifosi.com. 604800 IN A 208.58.189.13
+ns3.PAIR.com. 604800 IN A 209.68.1.15
+ns2.ar.com. 604800 IN A 64.124.80.42
+MASSIRA.ONPT.NET.MA. 604800 IN A 206.103.26.1
+NS.KBFI.EE. 604800 IN A 192.121.251.13
+ns3.Algebra.com. 604800 IN A 216.254.54.22
+faerber.muc.de. 604800 IN MX 10 slarti.muc.de.
+9.206.203.192.IN-ADDR.ARPA. 604800 IN PTR ice.WonderWorks.COM.
+PUKU.UNZA.ZM. 604800 IN A 196.7.240.1
+ATLNET.ATLONLINE.com. 604800 IN A 207.153.72.193
+Z1.NS.NYC1.GLOBIX.net. 604800 IN A 209.10.66.55
+www.hometownbands.com. 604800 IN A 209.67.235.38
+SIMON.CS.CORNELL.EDU. 604800 IN A 128.84.154.10
+EKEKO.RCPIP.net. 604800 IN A 209.45.127.2
+emerald.itnet.com.PL. 604800 IN A 195.116.64.3
+DNS1.ICS.FORTH.GR. 604800 IN A 139.91.151.70
+NS.ATL.BELLSOUTH.net. 604800 IN A 205.152.0.20
+ntp.ctr.COLUMBIA.EDU. 604800 IN CNAME sirius.ctr.COLUMBIA.EDU.
+NS2.GLOBECOMM.net. 604800 IN A 165.251.1.3
+UUNS1DNS1.FLONETWORK.com. 604800 IN A 209.167.79.5
+GRIN.GNOSH.net. 604800 IN A 216.15.87.207
+NS.DIGSYS.BG. 604800 IN A 192.92.129.1
+uunet.UU.net. 604800 IN MX 10 Mail.UU.net.
+ns1.vermontel.com. 604800 IN A 204.164.106.2
+NS2.GREENMOUNTAINACCESS.net. 604800 IN A 208.144.252.31
+38.241.5.198.IN-ADDR.ARPA. 604800 IN PTR cmr0.ash.ops.us.uu.net.
+NS1.NIC.UK. 604800 IN A 195.66.240.130
+DNS.FCCN.PT. 604800 IN A 193.136.192.10
+NS2.NIC.TJ. 604800 IN A 209.77.224.1
+NS4.NEWACCOUNT.com. 604800 IN A 209.78.16.6
+NS2.IHUG.NET.NZ. 604800 IN A 203.29.160.2
+NS.SIGNALZ.com. 604800 IN A 209.67.230.71
+DNS.NIC.AD. 604800 IN A 194.158.67.251
+3.2.39.137.IN-ADDR.ARPA. 604800 IN PTR New-York4.NY.ALTER.NET.
+UUCP-GW-2.PA.DEC.com. 604800 IN A 16.1.0.19
+NS.LANDLORDS.com. 604800 IN A 63.64.164.68
+NS2.EXODUS.net. 604800 IN A 207.82.198.150
+NS2.SCRUZ.net. 604800 IN A 165.227.2.10
+NS.PIPEX-SZ.net. 604800 IN A 196.15.232.19
+saturn.SUN.com. 604800 IN A 192.9.25.2
+e24.nc.us.IBM.com. 604800 IN A 32.97.136.230
+NMS.CYFRONET.KRAKOW.PL. 604800 IN A 149.156.1.3
+NS.TWNIC.net. 604800 IN A 192.83.166.11
+ns2.alcatel.NO. 604800 IN A 193.213.238.2
+INPAKSODNS.AKSO.nps.GOV. 604800 IN A 165.83.49.9
+mail.reptiles.org. 604800 IN A 198.96.117.157
+59.187.152.204.IN-ADDR.ARPA. 604800 IN PTR shell.nominum.com.
+ns1.mobydark.com. 604800 IN A 216.13.76.21
+NS.KG. 604800 IN A 195.38.160.36
+NS.SPB.SU. 604800 IN A 193.124.83.69
+PENDRAGON.CS.PURDUE.EDU. 604800 IN A 128.10.2.5
+NS1.IGC.APC.org. 604800 IN A 192.82.108.38
+USDNS.NIC.us. 604800 IN A 198.41.3.87
+NS2.WEBTRENDS.com. 604800 IN A 63.88.212.11
+URANUS.DAIMI.AAU.DK. 604800 IN A 130.225.16.40
+ANTANA.IRD.MG. 604800 IN A 194.214.107.1
+NS.JERSEY.juno.com. 604800 IN A 64.136.17.178
+NS2.INTERNET-TOOLS.com. 604800 IN A 206.109.113.140
+ns-tk012.ocn.AD.JP. 604800 IN A 203.139.160.74
+bvt-ext.gdarm.com. 604800 IN A 166.19.32.42
+NS1.ID. 604800 IN A 202.155.30.227
+NS2.MAHNET.net. 604800 IN A 207.219.173.132
+NS.ALCANET.COM.AU. 604800 IN A 203.62.196.10
+UTAMA.BOLNET.BO. 604800 IN A 166.114.1.40
+NS.CNC.AC.CN. 604800 IN A 159.226.1.1
+NS.KREN.NE.KR. 604800 IN A 147.47.1.1
+NS1.REDHAT.com. 604800 IN A 216.148.218.250
+db.rc.VIX.com. 604800 IN A 204.152.187.21
+198.103.198.209.IN-ADDR.ARPA. 604800 IN CNAME 198.192.103.198.209.IN-ADDR.ARPA.
+alf.pbks.PL. 604800 IN A 195.205.33.200
+FLAG.EP.net. 604800 IN A 198.32.4.13
+DNS2.IUNET.IT. 604800 IN A 192.106.1.31
+NS2.QUANTIFIED.net. 604800 IN A 63.212.171.3
+INTERNET-SERVER.ZURICH.IBM.com. 604800 IN A 195.212.119.252
+seaipsvcs.idx.com. 604800 IN A 172.22.64.42
+lebanon.valley.net. 604800 IN A 198.115.160.16
+SERVER.NORDU.net. 604800 IN A 193.10.252.19
+NS.NIC.DO. 604800 IN A 207.176.16.50
+isc-01.iscvt.org. 604800 IN A 207.136.209.131
+NAC.NO. 604800 IN A 129.240.2.40
+SAVA.UTIC.NET.BA. 604800 IN A 195.130.35.3
+NS1.TOKYO.JP.NETDNS.com. 604800 IN A 64.56.164.118
+NETSERV2.ITS.rpi.EDU. 604800 IN A 128.113.1.3
+IFI.UIO.NO. 604800 IN A 129.240.64.2
+www.TOAPLAN.com. 604800 IN A 216.42.31.169
+ns2.the-frontier.org. 604800 IN A 216.86.199.115
+NS.UNAM.MX. 604800 IN A 132.248.253.1
+ARISTO.TAU.AC.IL. 604800 IN A 132.66.32.10
+DNS.CS.WISC.EDU. 604800 IN A 128.105.2.10
+NS1.NIC.IR. 604800 IN A 194.225.70.83
+NS1.RETINA.AR. 604800 IN A 200.10.202.3
+mailer.connriver.net. 604800 IN A 63.93.137.13
+NS.ATI.TN. 604800 IN A 193.95.66.10
+NS2.CLEAR.NET.NZ. 604800 IN A 203.97.37.14
+NS4.EARTHLINK.net. 604800 IN A 209.179.179.19
+mejac.palo-alto.ca.us. 604800 IN A 192.147.236.1
+New-York4.NY.ALTER.net. 604800 IN A 137.39.2.3
+New-York4.NY.ALTER.net. 604800 IN A 137.39.126.10
+falcon.tallship.net. 604800 IN A 208.179.112.2
+ZEUS.CC.UCY.AC.CY. 604800 IN A 194.42.1.1
+NS2.SECURE.net. 604800 IN A 161.58.9.10
+NS0.FLIRBLE.org. 604800 IN A 195.40.6.20
+dns.zenon.net. 604800 IN A 195.2.83.107
+SERVIDOR.MICROASTUR.ES. 604800 IN A 195.76.178.5
+DOWNSTAGE.MCS.VUW.AC.NZ. 604800 IN A 130.195.6.10
+ns2.GNAC.com. 604800 IN A 209.182.195.77
+PRIFI.EUNET.FI. 604800 IN A 193.66.1.146
+ns2.k12.vt.us. 604800 IN A 170.222.64.130
+ns2.nic.mnet. 604800 IN A 208.109.83.110
+NS0.PIPEX.net. 604800 IN A 158.43.128.8
+NS1.SANFRANCISCO.US.NETDNS.com. 604800 IN A 207.82.50.166
+AMRA.NIC.GOV.JO. 604800 IN A 193.188.66.103
+kw.com.CN. 604800 IN MX 15 mail2.kw.com.CN.
+SHNS.163.net. 604800 IN A 61.129.65.108
+NS.ER.USGS.GOV. 604800 IN A 130.11.48.2
+FAITH.MYNET.net. 604800 IN A 207.13.11.2
+mail.smuggs.com. 604800 IN A 209.67.230.71
+MIMOS.MY. 604800 IN A 192.228.128.18
+NS.GU. 604800 IN A 168.123.4.10
+mx00.schlund.de. 604800 IN A 195.20.224.67
+mx00.schlund.de. 604800 IN A 195.20.224.68
+mx00.schlund.de. 604800 IN A 195.20.224.130
+mx00.schlund.de. 604800 IN A 195.20.224.152
+mx00.schlund.de. 604800 IN A 195.20.224.198
+CADDSYS.IPTEK.net. 604800 IN A 202.46.1.2
+NS0.TELIA.NIC.NU. 604800 IN A 212.181.91.4
+NS2.GRANITECANYON.com. 604800 IN A 204.1.217.148
+GATEKEEPER.corning.com. 604800 IN A 149.42.1.2
+NS2.2DAY.com. 604800 IN A 202.89.128.74
+1.0.0.127.IN-ADDR.ARPA. 604800 IN PTR localhost.
+RAIN.PSG.com. 604800 IN A 147.28.0.34
+STRAWB.MIT.EDU. 604800 IN A 18.71.0.151
+NS2.DIGISERVE.com. 604800 IN A 204.91.84.216
+UMACSN2.UMAC.MO. 604800 IN A 161.64.3.2
+NS.JM. 604800 IN A 196.2.1.6
+12.153.66.206.IN-ADDR.ARPA. 604800 IN PTR d.dd.org.
+EAST.ISI.EDU. 604800 IN A 38.245.76.2
+NS2.UUNET.CA. 604800 IN A 142.77.1.5
+SUNNY.STAT-USA.GOV. 604800 IN A 192.239.70.8
+BOW.INTNET.CF. 604800 IN A 194.206.73.253
+NS4.TELE.DK. 604800 IN A 194.239.134.84
+NS2.sodak.net. 604800 IN A 63.65.239.225
+NS1.NEWYORK.US.NETDNS.com. 604800 IN A 216.32.212.86
+NS2.PSI.net. 604800 IN A 38.8.50.2
+NS.KREONET.RE.KR. 604800 IN A 134.75.30.1
+GIANT.MINDLINK.net. 604800 IN A 204.174.18.2
+NS0.SECTOR001.org. 604800 IN A 24.4.49.117
+DNS.SEABONE.net. 604800 IN A 195.22.205.163
+NS2.MANA.PF. 604800 IN A 202.3.225.20
+NRWEB.CENPAC.NET.NR. 604800 IN A 203.98.224.66
+www.TRAVELPHOTOCONTESTS.com. 604800 IN A 64.85.86.156
+NS1.REGEX.com. 604800 IN A 202.152.12.227
+BIGBIRD.ITD.nps.GOV. 604800 IN A 165.83.208.5
+CUNIXD.CC.COLUMBIA.EDU. 604800 IN A 128.59.35.142
+NS1.CLASSIFIEDMONSTER.com. 604800 IN A 216.254.54.22
+SERVER1.SANS.org. 604800 IN A 167.216.133.33
+BRONZE.COIL.com. 604800 IN A 198.4.94.1
+SCSNMS.SWITCH.CH. 604800 IN A 130.59.1.30
+SCSNMS.SWITCH.CH. 604800 IN A 130.59.10.30
+SCE.CNC.UNA.PY. 604800 IN A 200.10.228.133
+RELAY.LA.TIS.com. 604800 IN A 198.51.22.11
+NS.AUSTIN.IBM.com. 604800 IN A 192.35.232.34
+SERVICE.robert-morris.EDU. 604800 IN A 205.146.48.22
+MERCURY.ML.org. 604800 IN A 209.68.0.85
+proxy.pccf.net. 604800 IN A 205.189.73.123
+DUB-NAME-SVC-1.compuserve.com. 604800 IN A 149.174.213.5
+NS.CNRI.reston.va.us. 604800 IN A 132.151.1.1
+NS.UCAD.SN. 604800 IN A 196.1.95.1
+ns01.ny.us.ibm.net. 604800 IN A 165.87.194.244
+NS4-AUTH.ALASKA.net. 604800 IN A 209.112.130.4
+BOW.INTNET.NE. 604800 IN A 194.51.164.253
+NS-JP.SINET.AD.JP. 604800 IN A 150.100.2.3
+ns.musin.de. 604800 IN A 194.113.40.45
+ip1.romkey.SEG.net. 604800 IN A 207.121.69.234
+DNS2.ITD.UMICH.EDU. 604800 IN A 141.211.125.15
+mail.rpi.EDU. 604800 IN A 128.113.100.7
+INECO.NIC.ES. 604800 IN A 194.69.254.2
+DNS2.FIREHOUSE.net. 604800 IN A 63.160.175.18
+BOW.INTNET.BJ. 604800 IN A 194.51.163.253
+sundown.vtc.VSC.EDU. 604800 IN A 155.42.12.12
+NIC.AIX.GR. 604800 IN A 195.130.89.210
+NIC.AD.JP. 604800 IN A 202.12.30.33
+NS.DC.IGC.org. 604800 IN A 199.75.208.10
+LHR.NS.GDNS.net. 604800 IN A 212.250.25.101
+NS2.WEBMAGIC.net. 604800 IN A 64.168.49.66
+MUNNARI.OZ.AU. 604800 IN A 128.250.1.21
+HIPPO.RU.AC.ZA. 604800 IN A 146.231.128.1
+PEBBLES.IOM.com. 604800 IN A 194.72.124.1
+penpal.dmz.RPSLMC.EDU. 604800 IN A 144.74.60.151
+netnews.HINET.net. 604800 IN A 168.95.195.16
+INS2.TOSA.TWTELECOM.net. 604800 IN A 204.95.160.4
+proxy6.cisco.com. 604800 IN A 203.41.198.245
+NS2.HOST4U.net. 604800 IN A 209.150.129.3
+POIPARAU.OYSTER.NET.CK. 604800 IN A 202.65.32.127
+NS-EXT.VIX.com. 604800 IN A 204.152.184.64
+NS2.NURSAT.net. 604800 IN A 212.13.167.1
+mail2.kw.com.CN. 604800 IN A 159.226.25.8
+NS-02B.ANS.net. 604800 IN A 207.24.245.178
+DNS.RCCN.net. 604800 IN A 193.136.7.17
+B.ROOT-SERVERS.ORSC. 604800 IN A 216.13.126.116
+FIREHOUSE.net. 604800 IN A 63.160.175.19
diff --git a/bin/tests/system/cacheclean/ns1/example.db b/bin/tests/system/cacheclean/ns1/example.db
new file mode 100644
index 0000000..7262109
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns1/example.db
@@ -0,0 +1,2942 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+$ORIGIN .
+. IN SOA hostmaster.nominum.com. a.root-servers.nil. (
+ 2000042100
+ 600
+ 600
+ 1200
+ 600
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil IN A 10.53.0.1
+localhost IN A 127.0.0.1
+$ORIGIN NIC.AC.
+NS IN A 194.205.62.120
+$ORIGIN AD.
+DNS2 IN A 194.158.64.8
+DINIS IN A 194.158.64.7
+$ORIGIN NIC.AD.
+DNS IN A 194.158.67.251
+$ORIGIN STA.AD.
+CORREU IN A 194.158.67.1
+$ORIGIN EMIRATES.NET.AE.
+NS2 IN A 194.170.1.7
+NS1 IN A 194.170.1.6
+$ORIGIN BA.
+NS IN A 195.130.35.5
+$ORIGIN UTIC.NET.BA.
+SAVA IN A 195.130.35.3
+$ORIGIN OFFSHORE.AI.
+NS1 IN A 209.88.68.34
+$ORIGIN BD.
+DNS1 IN A 209.58.24.5
+DNS IN A 209.58.24.3
+$ORIGIN MENTOR.BE.
+APHEX IN A 193.121.64.5
+$ORIGIN EUNET.BE.
+SECDNS IN A 193.74.208.139
+$ORIGIN BELNET.BE.
+NS IN A 193.190.198.10
+ IN A 193.190.198.2
+$ORIGIN DNS.BE.
+MASTER IN A 194.7.171.243
+$ORIGIN CS.KULEUVEN.AC.BE.
+DNS IN A 134.58.40.4
+$ORIGIN CURINFO.AN.
+NS01-SERVER IN A 200.44.117.129
+KADUSHI IN A 200.44.117.130
+$ORIGIN ONATEL.BF.
+NAHOURI IN A 206.82.130.195
+$ORIGIN DIGSYS.BG.
+NS IN A 192.92.129.1
+$ORIGIN BATELCO.COM.BH.
+SV10 IN A 193.188.124.227
+NS2 IN A 193.188.97.212
+NS IN A 193.188.97.197
+$ORIGIN UTORONTO.CA.
+ns2 IN A 128.100.102.202
+ns1 IN A 128.100.100.129
+chime IN A 128.100.102.201
+$ORIGIN cs.UTORONTO.CA.
+bay IN A 128.100.1.1
+$ORIGIN UTCC.UTORONTO.CA.
+DNS2 IN A 128.100.102.201
+$ORIGIN UUNET.CA.
+NS2 IN A 142.77.1.5
+NS IN A 142.77.1.1
+$ORIGIN CIRA.CA.
+MERLE IN A 64.26.149.98
+$ORIGIN cmc.ec.gc.CA.
+castor IN A 142.135.4.14
+$ORIGIN RISQ.QC.CA.
+CLOUSO IN A 192.26.210.1
+$ORIGIN MBNET.MB.CA.
+ACCESS IN A 130.179.16.143
+$ORIGIN CDNNET.CA.
+RELAY IN A 192.73.5.1
+$ORIGIN uwaterloo.CA.
+ns2 IN A 129.97.128.100
+math IN A 129.97.140.144
+ IN A 129.97.216.42
+ IN MX 0 math.uwaterloo.ca.
+ns1 IN A 129.97.128.10
+$ORIGIN AR.
+CTINA IN A 200.16.97.17
+ATHEA IN A 200.16.98.2
+$ORIGIN NIC.AR.
+TULKU IN A 200.16.97.77
+$ORIGIN RETINA.AR.
+NS1 IN A 200.10.202.3
+$ORIGIN INTNET.BJ.
+BOW IN A 194.51.163.253
+$ORIGIN NIC.CD.
+DNS IN A 194.38.74.11
+$ORIGIN tahina.priv.at.
+styx IN A 194.152.163.253
+$ORIGIN UNIVIE.AC.at.
+NS2 IN A 193.171.255.66
+NS7 IN A 194.246.96.192
+NS1 IN A 193.171.255.2
+$ORIGIN OZ.AU.
+MUNNARI IN A 128.250.1.21
+$ORIGIN CS.MU.OZ.AU.
+MULGA IN A 128.250.1.22
+ IN A 128.250.37.150
+$ORIGIN AARNET.EDU.AU.
+JATZ IN A 139.130.204.4
+$ORIGIN ANU.EDU.AU.
+CHEOPS IN A 150.203.224.24
+$ORIGIN CS.UOW.EDU.AU.
+WRAITH IN A 130.130.64.1
+$ORIGIN ALCANET.COM.AU.
+NS IN A 203.62.196.10
+$ORIGIN CONNECT.COM.AU.
+YARRINA IN A 192.189.54.17
+$ORIGIN IBL.BM.
+NS1 IN A 199.172.192.1
+$ORIGIN BRUNET.BN.
+JTB IN A 202.160.8.2
+$ORIGIN INTNET.CF.
+BOW IN A 194.206.73.253
+$ORIGIN SETARNET.AW.
+NS2 IN A 206.48.100.11
+NS1 IN A 206.48.100.5
+$ORIGIN BOLNET.BO.
+UTAMA IN A 166.114.1.40
+$ORIGIN SWITCH.CH.
+SCSNMS IN A 130.59.1.30
+ IN A 130.59.10.30
+MERAPI IN A 130.59.211.10
+$ORIGIN ITU.CH.
+NS IN A 156.106.192.121
+$ORIGIN NIC.CH.
+DOMREG IN A 130.59.1.80
+$ORIGIN ip6.INT.
+z IN A 198.32.2.66
+ IN AAAA 3ffe:0:1::c60:242
+$ORIGIN DNS.BR.
+NS2 IN A 200.19.119.99
+NS1 IN A 200.255.253.234
+NS IN A 143.108.23.2
+$ORIGIN OYSTER.NET.CK.
+POIPARAU IN A 202.65.32.127
+PARAU IN A 202.65.32.128
+$ORIGIN DRUKNET.NET.BT.
+NS IN A 202.144.128.200
+$ORIGIN DCC.UCHILE.CL.
+NS IN A 146.83.5.204
+$ORIGIN NIC.CL.
+NS IN A 146.83.4.11
+$ORIGIN FIRSTCOM.CL.
+NS IN A 200.27.2.2
+$ORIGIN EDU.
+ISI IN A 128.9.176.32
+UMASS IN MX 20 vcmr-54.server.rpi.edu.
+ IN MX 1 mail.rpi.edu.
+dartmouth IN A 129.170.16.6
+ IN MX 10 donner.dartmouth.edu.
+ IN MX 10 prancer.dartmouth.edu.
+ IN MX 10 vixen.dartmouth.edu.
+ IN MX 10 blitzen.dartmouth.edu.
+ IN MX 0 mailhub.dartmouth.edu.
+ IN MX 10 dasher.dartmouth.edu.
+rush IN MX 30 penpal.dmz.rpslmc.edu.
+ IN MX 10 detox.cc1.rpslmc.edu.
+ IN MX 20 rush.cc1.rpslmc.edu.
+NYU IN A 128.122.253.92
+GATECH IN A 130.207.244.244
+ARIZONA IN A 128.196.128.233
+stanford IN A 171.64.14.120
+ IN MX 20 Leland.stanford.edu.
+ IN MX 20 Leland2.stanford.edu.
+ IN MX 20 Leland3.stanford.edu.
+$ORIGIN jhuapl.EDU.
+ECSEL IN A 128.244.65.29
+APLDNS2 IN A 128.244.194.100
+ABACUS IN A 128.244.197.32
+$ORIGIN MIT.EDU.
+STRAWB IN A 18.71.0.151
+W20NS IN A 18.70.0.160
+BITSY IN A 18.72.0.3
+$ORIGIN ITD.UMICH.EDU.
+DNS2 IN A 141.211.125.15
+$ORIGIN ISI.EDU.
+EAST IN A 38.245.76.2
+VENERA IN A 128.9.176.32
+NS IN A 128.9.128.127
+$ORIGIN CS.PURDUE.EDU.
+PENDRAGON IN A 128.10.2.5
+$ORIGIN CS.WISC.EDU.
+DNS IN A 128.105.2.10
+$ORIGIN UMD.EDU.
+TRANTOR IN A 128.8.10.14
+$ORIGIN RPSLMC.EDU.
+THUMPER IN A 144.74.22.8
+$ORIGIN dmz.RPSLMC.EDU.
+penpal IN A 144.74.60.151
+$ORIGIN cc1.RPSLMC.EDU.
+rush IN A 144.74.150.23
+detox IN A 144.74.150.44
+$ORIGIN IS.RPSLMC.EDU.
+SUNSTROKE IN A 144.74.21.8
+$ORIGIN VSC.EDU.
+vtc IN MX 0 eve.vtc.vsc.edu.
+MAZE IN A 155.42.1.89
+ENIGMA IN A 155.42.1.7
+$ORIGIN vtc.VSC.EDU.
+sundown IN A 155.42.12.12
+eve IN A 155.42.12.102
+$ORIGIN UMASS.EDU.
+NS1 IN A 128.119.166.14
+NIC IN A 128.119.175.14
+$ORIGIN oit.UMASS.EDU.
+supai IN A 128.119.175.6
+ponzi IN A 128.119.166.18
+$ORIGIN ECS.UMASS.EDU.
+KIRA IN A 128.119.91.10
+$ORIGIN CS.UMASS.EDU.
+UNIX1 IN A 128.119.40.12
+$ORIGIN UPR.CLU.EDU.
+UPR1 IN A 136.145.1.4
+$ORIGIN PRINCETON.EDU.
+DNS IN A 128.112.129.15
+$ORIGIN rpi.EDU.
+mail IN A 128.113.100.7
+$ORIGIN server.rpi.EDU.
+vcmr-54 IN A 128.113.113.44
+$ORIGIN acs.rpi.EDU.
+freefour IN A 128.113.24.91
+$ORIGIN ITS.rpi.EDU.
+NETSERV2 IN A 128.113.1.3
+NETSERV1 IN A 128.113.1.5
+$ORIGIN uvm.EDU.
+NS1 IN A 132.198.201.10
+NS2 IN A 132.198.202.10
+$ORIGIN dartmouth.EDU.
+dasher IN A 129.170.208.6
+mailhub IN A 129.170.16.6
+donner IN A 129.170.208.3
+prancer IN A 129.170.208.2
+vixen IN A 129.170.208.15
+NS1 IN A 129.170.17.4
+blitzen IN A 129.170.208.4
+NS2 IN A 129.170.16.4
+$ORIGIN middlebury.EDU.
+CATAMOUNT IN A 140.233.2.204
+LION IN A 140.233.1.4
+$ORIGIN CIT.CORNELL.EDU.
+DNS IN A 192.35.82.50
+$ORIGIN CS.CORNELL.EDU.
+SIMON IN A 128.84.154.10
+$ORIGIN BERKELEY.EDU.
+NS2 IN A 128.32.136.12
+ IN A 128.32.206.12
+NS1 IN A 128.32.136.9
+ IN A 128.32.206.9
+$ORIGIN CS.BERKELEY.EDU.
+VANGOGH IN A 128.32.33.5
+$ORIGIN ctr.COLUMBIA.EDU.
+ntp IN CNAME sirius.ctr.columbia.edu.
+sirius IN A 128.59.64.60
+$ORIGIN CC.COLUMBIA.EDU.
+CUNIXD IN A 128.59.35.142
+$ORIGIN UOREGON.EDU.
+PHLOEM IN A 128.223.32.35
+$ORIGIN GATECH.EDU.
+TROLL-GW IN A 130.207.244.251
+$ORIGIN CC.GATECH.EDU.
+BURDELL IN A 130.207.3.207
+$ORIGIN UTK.EDU.
+NS0 IN A 160.36.0.66
+NS1 IN A 160.36.128.66
+$ORIGIN robert-morris.EDU.
+SERVICE IN A 205.146.48.22
+COLONIAL-SERVER IN A 205.146.48.25
+$ORIGIN CNS.vt.EDU.
+YARDBIRD IN A 198.82.247.34
+MILO IN A 198.82.247.98
+$ORIGIN stanford.EDU.
+Leland2 IN A 171.64.14.58
+AVALLONE IN A 171.64.2.210
+ATALANTE IN A 171.64.2.220
+ARGUS IN A 171.64.2.230
+$ORIGIN slac.stanford.EDU.
+SMTP IN A 134.79.18.80
+NS2 IN A 134.79.16.10
+NS1 IN A 134.79.16.9
+$ORIGIN HARVARD.EDU.
+NS2 IN A 128.103.1.1
+ns IN A 128.103.201.100
+NS1 IN A 128.103.200.101
+$ORIGIN med.HARVARD.EDU.
+jenner IN A 134.174.141.2
+knight IN A 134.174.141.46
+eno IN A 134.174.141.50
+heckle IN A 134.174.146.152
+$ORIGIN de.
+datingagentur IN A 212.227.216.57
+ IN MX 10 mx01.schlund.de.
+ IN MX 10 mx00.schlund.de.
+$ORIGIN schlund.de.
+mx00 IN A 195.20.224.130
+ IN A 195.20.224.198
+ IN A 195.20.224.67
+ IN A 195.20.224.68
+ IN A 195.20.224.152
+ns4 IN A 195.20.225.36
+mx01 IN A 195.20.224.131
+ IN A 195.20.224.236
+ IN A 195.20.224.237
+ IN A 195.20.224.238
+ns3 IN A 195.20.224.95
+$ORIGIN Informatik.Uni-Dortmund.de.
+waldorf IN A 129.217.4.42
+$ORIGIN muc.de.
+faerber IN MX 10 slarti.muc.de.
+ IN A 193.149.49.70
+ns2 IN A 193.149.48.2
+slarti IN A 193.149.48.10
+ns1 IN A 193.149.48.11
+$ORIGIN westfalen.de.
+muenster IN A 193.174.5.2
+$ORIGIN lan-ks.de.
+uranus IN A 194.45.71.1
+$ORIGIN kaben-net.de.
+dns IN A 195.179.28.17
+$ORIGIN thur.de.
+jengate IN A 193.174.15.34
+$ORIGIN erfurt.thur.de.
+annwfn IN A 194.122.210.3
+$ORIGIN sgh-net.de.
+ns1 IN A 212.86.129.142
+$ORIGIN DENIC.de.
+SSS-NL IN A 193.0.0.237
+SSS-AT IN A 193.171.255.34
+DNS IN A 194.246.96.79
+$ORIGIN iks-jena.de.
+avalon IN A 194.221.90.34
+$ORIGIN musin.de.
+ns IN A 194.113.40.45
+$ORIGIN rrz.Uni-Koeln.de.
+noc IN A 134.95.100.209
+$ORIGIN BelWue.de.
+noc IN A 129.143.2.1
+$ORIGIN HRZ.uni-bielefeld.de.
+noc IN A 129.70.5.16
+$ORIGIN techfak.uni-bielefeld.de.
+techfac IN A 129.70.132.100
+$ORIGIN CUBE.de.
+NS1 IN A 212.162.54.243
+$ORIGIN dtag.de.
+pns IN A 194.25.0.125
+$ORIGIN netconx.de.
+netconsult IN A 193.141.75.1
+$ORIGIN CAMNET.CM.
+KIM IN A 195.24.192.35
+LOM IN A 195.24.192.34
+SANAGA IN A 195.24.192.17
+$ORIGIN sxtyptt.NET.CN.
+ns IN A 202.99.192.68
+$ORIGIN sta.NET.CN.
+ns IN A 202.96.199.133
+$ORIGIN BTA.NET.CN.
+NS IN A 202.96.0.133
+$ORIGIN CNNIC.NET.CN.
+sld-ns2 IN A 202.97.16.197
+DNS2 IN A 202.97.16.196
+sld-ns1 IN A 159.226.1.3
+$ORIGIN com.CN.
+kw IN MX 15 mail2.kw.com.cn.
+$ORIGIN kw.com.CN.
+mail2 IN A 159.226.25.8
+ns IN A 159.226.25.8
+$ORIGIN CNC.AC.CN.
+NS IN A 159.226.1.1
+$ORIGIN UNIANDES.EDU.CO.
+AYAX IN A 157.253.50.30
+CDCNET IN A 157.253.1.13
+$ORIGIN SCSI.GOV.BY.
+SUN IN A 195.50.5.103
+NS2 IN A 194.67.193.130
+$ORIGIN OPEN.BY.
+A IN A 194.226.121.36
+$ORIGIN CR.
+NS IN A 163.178.8.2
+$ORIGIN UCR.AC.CR.
+NS IN A 163.178.88.2
+$ORIGIN INTNET.DJ.
+BOW IN A 193.251.143.253
+$ORIGIN DARENET.DK.
+NS-SOA IN A 130.226.1.4
+$ORIGIN TELE.DK.
+NS4 IN A 194.239.134.84
+$ORIGIN DAIMI.AAU.DK.
+URANUS IN A 130.225.16.40
+$ORIGIN DK-HOSTMASTER.DK.
+NS IN A 193.163.102.2
+$ORIGIN EC.
+ECNET IN A 157.100.45.2
+$ORIGIN NET.EC.
+ECUA IN A 157.100.1.2
+$ORIGIN CENIAI.NET.CU.
+NS IN A 169.158.128.136
+$ORIGIN EENET.EE.
+NS IN A 193.40.56.245
+$ORIGIN KBFI.EE.
+NS IN A 192.121.251.13
+$ORIGIN NIC.DO.
+NS IN A 207.176.16.50
+$ORIGIN EUN.EG.
+FRCU IN A 193.227.1.1
+$ORIGIN CIX.CX.
+NS IN A 195.222.235.216
+$ORIGIN CX.ESCROW.IOCOMM.NET.CX.
+NS1 IN A 203.132.96.2
+$ORIGIN CCS.UCY.AC.CY.
+NICOSIA IN A 194.42.6.97
+$ORIGIN CC.UCY.AC.CY.
+ZEUS IN A 194.42.1.1
+$ORIGIN EUNET.CZ.
+CZ IN A 193.85.3.130
+$ORIGIN EUNET.FI.
+PRIFI IN A 193.66.1.146
+$ORIGIN NIXU.FI.
+NS IN A 193.209.237.29
+$ORIGIN TELE.FI.
+NS IN A 193.210.19.19
+$ORIGIN HELSINKI.FI.
+HYDRA IN A 128.214.4.29
+$ORIGIN INET.GA.
+KOMO IN A 208.148.44.1
+$ORIGIN CERIST.DZ.
+DECST IN A 193.194.64.11
+$ORIGIN ELDJAZAIR.NET.DZ.
+CASBAH IN A 193.194.81.45
+$ORIGIN USP.AC.FJ.
+TERI IN A 144.120.8.1
+$ORIGIN EUNET.ES.
+NS IN A 193.127.1.11
+$ORIGIN NIC.ES.
+INECO IN A 194.69.254.2
+NS1 IN A 194.69.254.1
+$ORIGIN VISUALCOM.ES.
+NS IN A 194.143.202.202
+$ORIGIN MICROASTUR.ES.
+SERVIDOR IN A 195.76.178.5
+$ORIGIN CESCA.ES.
+PRADES IN A 192.94.163.152
+$ORIGIN PIXAR.ES.
+NS IN A 194.143.196.3
+$ORIGIN REDIRIS.ES.
+SUN IN A 130.206.1.2
+$ORIGIN SEKER.ES.
+CORREOS IN A 194.179.87.1
+$ORIGIN TELECOM.NET.ET.
+NS IN A 196.27.22.43
+$ORIGIN FM.
+FM03 IN A 206.49.89.4
+FM01 IN A 206.49.89.2
+$ORIGIN NPLUS.GF.
+NS1 IN A 195.6.144.3
+$ORIGIN trns.
+f IN A 209.133.38.16
+d IN A 207.112.147.14
+e IN A 145.89.234.7
+c IN A 212.172.21.254
+a IN A 64.6.65.10
+$ORIGIN IRD.FR.
+NS IN A 195.83.14.1
+$ORIGIN BONDY.IRD.FR.
+MALAKULA IN A 193.50.53.1
+$ORIGIN RAIN.FR.
+BOW IN A 194.51.3.49
+$ORIGIN imag.FR.
+isis IN A 129.88.32.24
+imag IN A 129.88.30.1
+$ORIGIN INRIA.FR.
+DNS IN A 193.51.208.13
+$ORIGIN NIC.FR.
+NS2 IN A 192.93.0.4
+NS1 IN A 192.93.0.1
+NS3 IN A 192.134.0.49
+$ORIGIN GH.GL.
+KAASASSUK IN A 194.177.232.3
+$ORIGIN TELE.GL.
+TGSERV IN A 194.177.224.7
+$ORIGIN COMMIT.GM.
+NS1 IN A 63.77.152.177
+$ORIGIN MRC.GM.
+NS1 IN A 212.60.69.1
+$ORIGIN INTNET.GQ.
+BOW IN A 195.101.152.253
+$ORIGIN AIX.GR.
+NIC IN A 195.130.89.210
+$ORIGIN GRNET.GR.
+FOO IN A 194.177.210.211
+NIC IN A 194.177.210.210
+$ORIGIN CSI.FORTH.GR.
+ESTIA IN A 139.91.191.3
+$ORIGIN ICS.FORTH.GR.
+DNS1 IN A 139.91.151.70
+GRDNS IN A 139.91.1.1
+$ORIGIN HKU.HK.
+HKUXB IN A 147.8.16.15
+$ORIGIN CUHK.EDU.HK.
+NS2 IN A 137.189.6.21
+NS1 IN A 137.189.6.1
+$ORIGIN CONCYT.GOB.GT.
+NS IN A 168.234.106.2
+$ORIGIN UVG.EDU.GT.
+NS IN A 168.234.68.2
+$ORIGIN ID.
+NS1 IN A 202.155.30.227
+$ORIGIN AC.ID.
+NS IN A 202.159.124.34
+$ORIGIN GU.
+NS IN A 168.123.4.10
+$ORIGIN EDU.GU.
+NS IN A 168.123.2.50
+$ORIGIN REGISTRY.HM.
+NS2 IN A 209.54.168.55
+NS3 IN A 202.169.102.24
+NS1 IN A 204.144.183.78
+$ORIGIN CONNECT.IE.
+AUTH01 IN A 194.106.128.50
+$ORIGIN DOMAINREGISTRY.IE.
+BANBA IN A 193.1.142.2
+$ORIGIN VIA-NET-WORKS.IE.
+ICE IN A 212.17.32.2
+$ORIGIN HONDUTEL.HN.
+MIRAF-SERVER3 IN A 206.48.104.142
+$ORIGIN SRCE.HR.
+DNS IN A 161.53.3.7
+$ORIGIN HUJI.AC.IL.
+RELAY IN A 128.139.6.1
+$ORIGIN TAU.AC.IL.
+ARISTO IN A 132.66.32.10
+$ORIGIN NIC.JE.
+NS1 IN A 216.110.45.224
+$ORIGIN SZTAKI.HU.
+NS2 IN A 193.225.86.1
+$ORIGIN NIC.HU.
+NS IN A 193.6.27.62
+$ORIGIN NCST.ERNET.IN.
+NAAMAK IN A 202.41.110.66
+SS585 IN A 202.141.150.18
+$ORIGIN NIC.IO.
+NS IN A 194.205.62.100
+$ORIGIN NIC.IR.
+NS1 IN A 194.225.70.83
+$ORIGIN IS.
+ISGATE IN A 193.4.58.51
+$ORIGIN IUNET.IT.
+DNS2 IN A 192.106.1.31
+NS IN A 192.106.1.1
+$ORIGIN INFN.IT.
+SERVER2 IN A 131.154.1.3
+$ORIGIN CNR.IT.
+NAMESERVER IN A 194.119.192.34
+$ORIGIN IAT.CNR.IT.
+ITGBOX IN A 146.48.65.46
+$ORIGIN NETTUNO.IT.
+BOLOGNA IN A 193.43.2.5
+$ORIGIN NIC.IT.
+DNS IN A 193.205.245.5
+$ORIGIN JM.
+NS IN A 196.2.1.6
+$ORIGIN CAST.EDU.JM.
+NS IN A 200.9.115.2
+$ORIGIN NIC.GOV.JO.
+AMRA IN A 193.188.66.103
+PETRA IN A 193.188.66.2
+$ORIGIN KG.
+NS IN A 195.38.160.36
+$ORIGIN AD.JP.
+NIC IN A 202.12.30.33
+$ORIGIN ocn.AD.JP.
+ns-tk012 IN A 203.139.160.74
+$ORIGIN IIJ.AD.JP.
+NS0 IN A 202.232.2.34
+$ORIGIN SINET.AD.JP.
+NS-JP IN A 150.100.2.3
+$ORIGIN SPIN.AD.JP.
+DNS0 IN A 165.76.0.98
+$ORIGIN NIC.AD.JP.
+ns2 IN A 202.12.30.133
+TRF IN A 192.41.192.2
+NS-JP IN A 61.120.151.100
+NS0 IN A 202.12.30.131
+ns1 IN A 202.12.30.33
+$ORIGIN WIDE.AD.JP.
+NS IN A 203.178.136.63
+ IN MX 10 integra.s-integra.co.jp.
+$ORIGIN s-integra.co.JP.
+integra IN A 210.162.202.34
+$ORIGIN UUCP.NE.JP.
+NS2 IN A 210.141.111.69
+$ORIGIN DNS.NET.KH.
+NS1 IN A 203.127.100.21
+$ORIGIN org.
+netsage IN A 209.67.235.38
+ietf IN A 132.151.1.19
+ IN MX 10 odin.ietf.org.
+vmba IN MX 10 gro.dd.org.
+bnfinfo IN MX 10 mail.sover.net.
+ IN MX 20 mqueue.sover.net.
+dd IN MX 10 gro.dd.org.
+ IN MX 50 mqueue.sover.net.
+ IN MX 100 mail.uu.net.
+vtvast IN A 207.217.96.38
+ IN A 207.217.96.39
+ IN A 207.217.96.40
+ IN A 207.217.96.41
+ IN A 207.217.96.42
+ IN A 207.217.96.43
+ IN A 207.217.96.44
+ IN A 207.217.96.45
+ IN A 207.217.96.28
+ IN A 207.217.96.29
+ IN A 207.217.96.30
+ IN A 207.217.96.31
+ IN A 207.217.96.32
+ IN A 207.217.96.33
+ IN A 207.217.96.34
+ IN A 207.217.96.35
+ IN A 207.217.96.36
+ IN A 207.217.96.37
+ IN MX 10 vipmailgate.earthlink.net.
+gazpacho IN A 209.67.235.38
+bikeclub IN MX 20 pop.shoreham.net.
+ IN MX 50 smtp.america.net.
+giffordmed IN A 130.189.100.57
+ IN MX 20 quest-net.com.
+ IN MX 10 mail.giffordmed.org.
+isc IN A 204.152.184.101
+icann IN MX 100 mail.icann.org.
+ IN MX 95 mailhub.icann.org.
+xaos IN A 24.93.15.22
+ IN TXT "XAOS Associates Online Services"
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+ IN LOC 43 02 20.000 N 77 43 12.000 W 170.00m 1.00m 30.00m 10.00m
+mmuuf IN MX 10 gro.dd.org.
+reptiles IN A 198.96.117.142
+ IN MX 10 mail2.reptiles.org.
+ IN MX 20 mail.vex.net.
+ IN MX 5 mail.reptiles.org.
+iscvt IN A 207.136.209.132
+ IN MX 10 isc-01.iscvt.org.
+ IN MX 20 mqueue.sover.net.
+mailinglists IN A 63.160.175.18
+lawlinevt IN MX 20 mqueue.sover.net.
+ IN MX 10 host3.vtlegalaid.org.
+mail-abuse IN A 204.152.184.74
+$ORIGIN SECTOR001.org.
+NS0 IN A 24.4.49.117
+NS1 IN A 24.4.49.246
+$ORIGIN ML.org.
+MERCURY IN A 209.68.0.85
+$ORIGIN XBILL.org.
+NS IN A 204.152.186.163
+$ORIGIN spack.org.
+maus IN A 204.245.198.90
+$ORIGIN netsage.org.
+keith IN A 209.67.235.37
+www IN CNAME netsage.org.
+sure IN A 209.67.235.38
+$ORIGIN ietf.org.
+odin IN A 132.151.1.176
+www2 IN A 4.17.168.6
+www IN CNAME www2.ietf.org.
+$ORIGIN lux.dot-eu.org.
+ns0 IN A 195.206.105.102
+$ORIGIN the-frontier.org.
+ns2 IN A 216.86.199.115
+ns1 IN A 216.86.199.114
+$ORIGIN vmba.org.
+www IN MX 10 gro.dd.org.
+ IN A 209.198.103.206
+$ORIGIN WILLIAM.org.
+JOANNA IN A 195.153.6.2
+$ORIGIN FROGHOUSE.org.
+DNS IN A 207.121.69.243
+$ORIGIN VTLEGALAID.org.
+host3 IN A 207.136.208.115
+$ORIGIN dd.org.
+doubt IN A 209.198.103.193
+news IN CNAME gro.dd.org.
+gro IN A 209.198.103.200
+d IN A 209.198.103.199
+workgroup IN A 209.198.103.201
+dhcp1 IN A 209.198.103.194
+go IN A 209.198.103.198
+mail IN CNAME gro.dd.org.
+localhost IN A 127.0.0.1
+dhcp2 IN A 209.198.103.195
+www IN CNAME gro.dd.org.
+dhcp3 IN A 209.198.103.196
+dhcp4 IN A 209.198.103.197
+moderators IN CNAME moderators.isc.org.
+ns IN CNAME gro.dd.org.
+$ORIGIN gazpacho.org.
+keith IN A 209.67.235.37
+sure IN A 209.67.235.38
+$ORIGIN FLAME.org.
+DNS02 IN A 204.152.184.97
+www IN A 204.152.184.97
+DNS01 IN A 204.152.184.80
+$ORIGIN giffordmed.org.
+mail IN A 130.189.100.51
+$ORIGIN isc.org.
+isrv3-i IN A 204.152.184.87
+$ORIGIN energyenhancement.org.
+www IN A 216.121.175.228
+$ORIGIN icann.org.
+mailhub IN A 192.0.34.33
+mail IN A 198.32.1.99
+$ORIGIN PAPP.UNDP.org.
+PAPPSRV IN A 192.115.229.1
+$ORIGIN xaos.org.
+amethyst IN A 204.145.159.12
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+sure IN A 209.67.235.38
+taiyoo IN A 204.145.159.13
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+gw IN A 24.93.15.22
+reimei IN A 204.145.159.17
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+gwi IN A 204.145.159.2
+ IN HINFO "Firewall" "Gateway"
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+keith IN A 209.67.235.37
+axis IN A 204.145.159.20
+mail IN CNAME furii.xaos.org.
+all IN A 24.95.203.33
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+www IN CNAME gw.xaos.org.
+kadou IN A 204.145.159.14
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+furii IN A 204.145.159.11
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+ftp IN CNAME gw.xaos.org.
+gwe IN CNAME gw.xaos.org.
+$ORIGIN PUNCHDOWN.org.
+NS IN A 140.174.131.100
+$ORIGIN mmuuf.org.
+www IN MX 10 gro.dd.org.
+ IN A 209.198.103.205
+$ORIGIN OPEN-RSC.org.
+ASLAN IN A 199.5.157.128
+UNICORN IN A 207.126.103.16
+$ORIGIN COGNOSCENTI.org.
+SYNAESTHESIA IN A 207.208.112.4
+ANAESTHESIA IN A 207.208.112.3
+$ORIGIN DC.IGC.org.
+NS IN A 199.75.208.10
+$ORIGIN mitre.org.
+DNSSRV1X IN A 199.94.97.51
+mbunix IN A 199.94.97.52
+DNSSRV3X IN A 198.76.173.100
+smtpproxy1 IN A 129.83.20.90
+linus IN A 129.83.10.1
+ IN MX 1 linus.mitre.org.
+ IN MX 5 smtpproxy1.mitre.org.
+ IN MX 10 smtpproxy2.mitre.org.
+smtpproxy2 IN A 128.29.154.90
+mwunix IN A 198.76.173.52
+$ORIGIN reptiles.org.
+mail IN A 198.96.117.157
+NS2 IN A 192.75.253.138
+NS IN A 198.96.117.136
+$ORIGIN ISPC.org.
+NS2 IN A 209.124.64.11
+NS3 IN A 207.230.32.23
+NS1 IN A 207.106.7.7
+$ORIGIN IGC.APC.org.
+NS1 IN A 192.82.108.38
+$ORIGIN iscvt.org.
+isc-01 IN A 207.136.209.131
+$ORIGIN FLIRBLE.org.
+NS0 IN A 195.40.6.20
+$ORIGIN SANS.org.
+SERVER1 IN A 167.216.133.33
+$ORIGIN LTWCC.org.
+NS2 IN A 12.33.66.62
+NS1 IN A 12.33.66.61
+$ORIGIN CMHNET.org.
+elektro IN A 192.188.133.3
+$ORIGIN SNPT.KM.
+BOW IN A 195.101.19.253
+$ORIGIN ONPT.NET.MA.
+MASSIRA IN A 206.103.26.1
+$ORIGIN IAM.NET.MA.
+DNS2 IN A 212.217.0.12
+DNS3 IN A 212.217.1.1
+DNS1 IN A 212.217.0.1
+$ORIGIN KREONET.RE.KR.
+NS IN A 134.75.30.1
+$ORIGIN KREN.NE.KR.
+NS IN A 147.47.1.1
+$ORIGIN NIC.LK.
+NS IN A 192.248.1.65
+$ORIGIN NIC.MC.
+NS IN A 195.78.6.131
+$ORIGIN 110.16.12.IN-ADDR.ARPA.
+35 IN CNAME 35.32/27.110.16.12.in-addr.arpa.
+$ORIGIN 32/27.110.16.12.IN-ADDR.ARPA.
+35 IN PTR mail.nova-data.com.
+$ORIGIN 0.0.127.IN-ADDR.ARPA.
+1 IN PTR localhost.
+$ORIGIN 184.152.204.IN-ADDR.ARPA.
+87 IN PTR isrv3-i.isc.org.
+$ORIGIN 187.152.204.IN-ADDR.ARPA.
+59 IN PTR shell.nominum.com.
+$ORIGIN 131.127.204.IN-ADDR.ARPA.
+47 IN PTR mtiwmhc22.worldnet.att.net.
+$ORIGIN 198.245.204.IN-ADDR.ARPA.
+90 IN PTR maus.spack.org.
+$ORIGIN 159.145.204.IN-ADDR.ARPA.
+12 IN PTR amethyst.xaos.org.
+13 IN PTR taiyoo.xaos.org.
+14 IN PTR kadou.xaos.org.
+17 IN PTR reimei.xaos.org.
+20 IN PTR axis.xaos.org.
+2 IN PTR gwi.xaos.org.
+11 IN PTR furii.xaos.org.
+$ORIGIN 241.5.198.IN-ADDR.ARPA.
+38 IN PTR cmr0.ash.ops.us.uu.net.
+39 IN PTR cmr1.ash.ops.us.uu.net.
+$ORIGIN 241.103.199.IN-ADDR.ARPA.
+218 IN PTR abyssinian.sleepycat.com.
+$ORIGIN 153.66.206.IN-ADDR.ARPA.
+12 IN PTR d.dd.org.
+102 IN PTR gro.dd.org.
+128 IN PTR www.vmba.org.
+1 IN PTR workgroup.dd.org.
+2 IN PTR doubt.dd.org.
+136 IN PTR www.mmuuf.org.
+4 IN PTR nila.dd.org.
+10 IN PTR go.dd.org.
+$ORIGIN 84.198.209.IN-ADDR.ARPA.
+242 IN PTR dlawren-gw.burl.sover.net.
+$ORIGIN 87.198.209.IN-ADDR.ARPA.
+52 IN PTR mqueue0.sover.net.
+$ORIGIN 103.198.209.IN-ADDR.ARPA.
+198 IN CNAME 198.192.103.198.209.in-addr.arpa.
+205 IN CNAME 205.192.103.198.209.in-addr.arpa.
+199 IN CNAME 199.192.103.198.209.in-addr.arpa.
+206 IN CNAME 206.192.103.198.209.in-addr.arpa.
+193 IN CNAME 193.192.103.198.209.in-addr.arpa.
+200 IN CNAME 200.192.103.198.209.in-addr.arpa.
+201 IN CNAME 201.192.103.198.209.in-addr.arpa.
+$ORIGIN 192.103.198.209.IN-ADDR.ARPA.
+202 IN PTR fraud.dd.org.
+195 IN PTR dhcp2.dd.org.
+203 IN PTR fraud.dd.org.
+196 IN PTR dhcp3.dd.org.
+204 IN PTR ppp.dd.org.
+197 IN PTR dhcp4.dd.org.
+205 IN PTR www.mmuuf.org.
+198 IN PTR go.dd.org.
+206 IN PTR www.vmba.org.
+199 IN PTR d.dd.org.
+207 IN PTR broadcast.dd.org.
+200 IN PTR gro.dd.org.
+193 IN PTR doubt.dd.org.
+201 IN PTR workgroup.dd.org.
+194 IN PTR dhcp1.dd.org.
+$ORIGIN 133.188.192.IN-ADDR.ARPA.
+3 IN PTR elektro.com.
+$ORIGIN 206.203.192.IN-ADDR.ARPA.
+9 IN PTR ice.WonderWorks.COM.
+$ORIGIN 2.39.137.IN-ADDR.ARPA.
+3 IN PTR New-York4.NY.ALTER.NET.
+$ORIGIN 126.39.137.IN-ADDR.ARPA.
+10 IN PTR Fddi0-0.New-York4.NY.ALTER.NET.
+$ORIGIN IRD.MG.
+ANTANA IN A 194.214.107.1
+$ORIGIN NIC.MG.
+NS IN A 194.214.107.253
+$ORIGIN KW.
+DNS2 IN A 161.252.48.150
+DNS1 IN A 161.252.48.140
+$ORIGIN MOC.KW.
+NCC IN A 196.1.69.98
+$ORIGIN NET.NA.
+GRUMPY IN A 196.20.23.1
+$ORIGIN RELCOM.KZ.
+NS IN A 212.110.240.65
+$ORIGIN MARNET.MK.
+KITKA IN A 194.149.131.2
+$ORIGIN SC-UNI.KTU.LT.
+NEMUNAS IN A 193.219.32.13
+$ORIGIN SOTELMA.ML.
+ASKIA IN A 208.144.230.3
+$ORIGIN DNS.LU.
+NS2 IN A 158.64.229.3
+NS5 IN A 194.246.96.193
+NS1 IN A 158.64.229.2
+$ORIGIN INTNET.NE.
+BOW IN A 194.51.164.253
+$ORIGIN MN.
+MAGIC IN A 202.131.0.10
+$ORIGIN NF.
+NS2 IN A 203.12.249.101
+NS1 IN A 203.12.249.100
+$ORIGIN LATNET.LV.
+NS2 IN A 159.148.108.1
+NS IN A 159.148.60.2
+$ORIGIN UMAC.MO.
+UMACSN2 IN A 161.64.3.2
+NS2 IN A 161.64.7.2
+UMACSN1 IN A 161.64.3.1
+NS1 IN A 161.64.7.1
+$ORIGIN NI.
+NS IN A 165.98.1.2
+ IN A 200.30.36.8
+$ORIGIN TMX.COM.NI.
+NS IN A 205.218.253.2
+$ORIGIN UNIV-NKC.MR.
+DNS2 IN A 193.251.145.154
+DNS1 IN A 193.251.145.155
+$ORIGIN SVIANED.nl.
+NS IN A 143.177.1.3
+$ORIGIN secondary.nl.
+ns2 IN A 194.229.138.6
+$ORIGIN DOMAIN-REGISTRY.nl.
+NS2 IN A 193.176.144.130
+NS IN A 193.176.144.2
+$ORIGIN MT.
+NS IN A 193.188.47.252
+$ORIGIN DHIRAAGU.MV.
+NS IN A 202.1.192.196
+$ORIGIN NO.
+NAC IN A 129.240.2.40
+ALCANET IN MX 15 tyholt.uninett.no.
+ IN MX 20 nac.no.
+ IN A 158.39.5.5
+$ORIGIN UIO.NO.
+IFI IN A 129.240.64.2
+$ORIGIN SOL.NO.
+NS1 IN A 195.225.2.10
+$ORIGIN uit.NO.
+benoni IN A 129.242.4.254
+$ORIGIN ALCANET.NO.
+NS IN A 193.213.238.10
+$ORIGIN UNINETT.NO.
+aun IN A 129.241.1.99
+tyholt IN A 158.38.60.10
+NN IN A 158.38.0.181
+$ORIGIN alcatel.NO.
+ns2 IN A 193.213.238.2
+$ORIGIN UNINET.NET.MX.
+MEX1-M-213 IN A 200.33.146.213
+$ORIGIN AVANTEL.NET.MX.
+DNS1 IN A 200.33.213.66
+$ORIGIN UNAM.MX.
+NS IN A 132.248.253.1
+$ORIGIN NIC.MX.
+NS IN A 200.23.1.1
+$ORIGIN MOS.COM.NP.
+SHIKHAR IN A 202.52.255.5
+$ORIGIN MY.
+MIMOS IN A 192.228.128.18
+JARING IN A 192.228.128.20
+$ORIGIN JARING.MY.
+GATEN IN A 161.142.227.17
+GATE1 IN A 161.142.2.17
+$ORIGIN PA.
+NS IN A 168.77.8.2
+$ORIGIN USMA.AC.PA.
+VASCO IN A 208.141.92.2
+$ORIGIN UEM.MZ.
+ZEBRA IN A 196.3.96.67
+OCEANO IN A 196.3.96.69
+DZOWO IN A 196.3.96.66
+$ORIGIN CENPAC.NET.NR.
+NRWEB IN A 203.98.224.66
+$ORIGIN NIC.NU.
+NS IN A 128.11.47.50
+$ORIGIN DE.NIC.NU.
+NS0 IN A 216.200.116.40
+$ORIGIN TELIA.NIC.NU.
+NS0 IN A 212.181.91.4
+$ORIGIN NS.NIC.NU.
+NZ IN A 203.97.132.66
+$ORIGIN OMANTEL.NET.OM.
+OM4 IN A 206.49.101.5
+OM10 IN A 206.49.101.6
+$ORIGIN RCP.NET.PE.
+ICHU IN A 161.132.5.14
+$ORIGIN MANA.PF.
+NS2 IN A 202.3.225.20
+NS1 IN A 202.3.225.10
+$ORIGIN QATAR.NET.QA.
+NS2 IN A 212.77.192.13
+NS3 IN A 212.77.192.15
+NS1 IN A 212.77.192.10
+$ORIGIN CLEAR.NET.NZ.
+NS2 IN A 203.97.37.14
+NS1 IN A 203.97.33.14
+$ORIGIN DNS.NET.NZ.
+NS1 IN A 202.46.161.3
+$ORIGIN IHUG.NET.NZ.
+NS2 IN A 203.29.160.2
+$ORIGIN XTRA.CO.NZ.
+GORGON IN A 202.27.158.34
+$ORIGIN WAIKATO.AC.NZ.
+NS99 IN A 130.217.76.27
+$ORIGIN VUW.AC.NZ.
+RATA IN A 130.195.2.11
+$ORIGIN MCS.VUW.AC.NZ.
+DOWNSTAGE IN A 130.195.6.10
+CIRCA IN A 130.195.5.12
+$ORIGIN PL.
+from IN A 212.160.132.114
+$ORIGIN NASK.ORG.PL.
+BILBO IN A 148.81.16.51
+ IN A 195.187.245.51
+$ORIGIN pbks.PL.
+alf IN A 195.205.33.200
+$ORIGIN CYFRONET.KRAKOW.PL.
+NMS IN A 149.156.1.3
+$ORIGIN MAN.LODZ.PL.
+DNS2 IN A 212.51.192.5
+$ORIGIN ispid.com.PL.
+trurl IN A 195.150.99.3
+$ORIGIN itnet.com.PL.
+emerald IN A 195.116.64.3
+$ORIGIN ELEKTRON.PL.
+AMBER IN A 195.117.6.10
+$ORIGIN macrosoft.WAW.PL.
+front IN A 194.196.86.66
+$ORIGIN NASK.WAW.PL.
+ARWENA IN A 193.59.201.28
+$ORIGIN webtech.elk.PL.
+tornado IN A 212.244.162.100
+$ORIGIN IKP.PL.
+NS3 IN A 157.25.5.30
+$ORIGIN TPSA.PL.
+DNS2 IN A 194.204.152.34
+$ORIGIN uwm.EDU.PL.
+matrix IN A 213.184.3.136
+$ORIGIN FUW.EDU.PL.
+DNS IN A 193.0.80.11
+$ORIGIN UPRR.PR.
+PASCAL IN A 134.202.1.120
+DESCARTES IN A 134.202.1.125
+$ORIGIN NCC.UP.PT.
+CIUP1 IN A 193.136.51.52
+$ORIGIN FCCN.PT.
+DNS IN A 193.136.192.10
+$ORIGIN DNS.PT.
+NS IN A 193.136.0.1
+$ORIGIN TELEPAC.PT.
+NS1 IN A 194.65.3.20
+VIVALDI IN A 194.65.3.21
+$ORIGIN CNC.UNA.PY.
+SCE IN A 200.10.228.133
+NS IN A 200.10.228.132
+$ORIGIN ISU.NET.SA.
+NS1 IN A 212.26.18.3
+$ORIGIN KACST.EDU.SA.
+NS IN A 212.26.44.3
+$ORIGIN COM.SB.
+PIJIN IN A 202.139.42.10
+$ORIGIN SOLOMON.COM.SB.
+OLKETA IN A 202.139.42.4
+$ORIGIN cafax.SE.
+ns IN A 192.71.228.17
+$ORIGIN LTH.SE.
+NIC IN A 130.235.20.3
+$ORIGIN SUNET.SE.
+SUNIC IN A 192.36.125.2
+$ORIGIN PACIFIC.NET.SG.
+NS1 IN A 192.169.33.3
+$ORIGIN NIC.NET.SG.
+DS IN A 202.42.194.205
+$ORIGIN SINGNET.COM.SG.
+DNSSEC2 IN A 195.13.10.226
+DNSSEC3 IN A 165.21.100.11
+DNSSEC1 IN A 165.21.83.11
+$ORIGIN RNC.RO.
+NS-A IN A 192.162.16.31
+NS IN A 192.162.16.21
+$ORIGIN NIC.SH.
+NS IN A 194.205.62.60
+$ORIGIN ARNES.SI.
+KANIN IN A 193.2.1.66
+SREBRNJAK IN A 193.2.1.91
+$ORIGIN INTERNET.SK.
+NS IN A 192.108.130.91
+$ORIGIN EUNET.SK.
+NS IN A 192.108.130.33
+$ORIGIN NETLAB.SK.
+NS IN A 195.168.1.4
+$ORIGIN SIERRATEL.SL.
+NS IN A 194.133.124.5
+$ORIGIN INTNET.TD.
+BOW IN A 193.251.147.253
+$ORIGIN RU.
+ok IN A 195.2.83.162
+ IN MX 50 mail.ok.ru.
+ IN MX 100 relay1.aha.ru.
+ IN MX 300 relay3.aha.ru.
+$ORIGIN aha.RU.
+ns1 IN A 195.2.80.142
+$ORIGIN ok.RU.
+mail IN A 195.2.83.162
+ns IN A 195.2.64.36
+$ORIGIN INTELCOM.SM.
+DNS IN A 194.183.64.11
+$ORIGIN OMNIWAY.SM.
+DNS IN A 194.183.64.10
+$ORIGIN UCAD.SN.
+NS IN A 196.1.95.1
+$ORIGIN NIC.TJ.
+NS2 IN A 209.77.224.1
+NS1 IN A 209.77.250.1
+$ORIGIN SPB.SU.
+NS IN A 193.124.83.69
+$ORIGIN RICC.ALMA-ATA.SU.
+NS IN A 194.87.112.4
+$ORIGIN DEMOS.SU.
+NS IN A 194.87.0.8
+ IN A 194.87.0.9
+$ORIGIN RED.SV.
+CIR IN A 168.243.254.1
+$ORIGIN GOB.SV.
+CONACYT IN A 168.243.64.2
+ANTEL IN A 168.243.65.1
+$ORIGIN ATI.TN.
+NS IN A 193.95.66.10
+$ORIGIN TO.
+TONIC IN A 206.184.59.10
+COLO IN A 206.86.247.253
+$ORIGIN TDC.TO.
+NS1 IN A 206.86.247.250
+$ORIGIN SY.
+EARTH IN A 195.22.198.6
+$ORIGIN VATICAN.VA.
+MICHAEL IN A 212.77.0.2
+$ORIGIN METU.EDU.TR.
+NS2 IN A 144.122.199.93
+NS1 IN A 144.122.199.90
+$ORIGIN NIC.UK.
+NS1 IN A 195.66.240.130
+$ORIGIN AXION.BT.CO.UK.
+DNS0 IN A 132.146.5.1
+$ORIGIN ADVSYS.CO.UK.
+BARNEY IN A 194.72.124.2
+$ORIGIN WR.UMIST.AC.UK.
+AARDVARK IN A 130.88.146.3
+ IN A 128.16.5.31
+ IN MX 10 bells.cs.ucl.ac.uk.
+ IN MX 11 haig.cs.ucl.ac.uk.
+$ORIGIN CS.UCL.AC.UK.
+haig IN A 128.16.6.8
+bells IN A 128.16.5.31
+NS1 IN A 128.16.5.32
+$ORIGIN surrey.AC.UK.
+info-server IN A 131.227.102.6
+eim IN MX 6 phoebe.eim.surrey.ac.uk.
+ IN MX 6 prue.eim.surrey.ac.uk.
+$ORIGIN eim.surrey.AC.UK.
+prue IN A 131.227.76.5
+phoebe IN A 131.227.74.4
+$ORIGIN MHS-RELAY.AC.UK.
+SUN IN A 128.86.8.25
+$ORIGIN NIC.TT.
+DNS IN A 24.3.198.194
+$ORIGIN REACCIUN.VE.
+DNS2 IN A 150.188.4.212
+DNS IN A 150.188.4.210
+$ORIGIN ULA.VE.
+AZMODAN IN A 150.185.130.16
+$ORIGIN UTZ.
+NS2 IN A 160.124.112.10
+NS3 IN A 160.124.147.1
+NS1 IN A 160.124.48.4
+$ORIGIN NIC.TV.
+NS4 IN A 207.151.24.23
+NS2 IN A 208.184.1.167
+NS6 IN A 64.56.165.153
+NS7 IN A 64.69.172.153
+NS1 IN A 209.143.242.138
+$ORIGIN EDU.TW.
+MOEVAX IN A 140.111.1.2
+$ORIGIN vt.us.
+state IN MX 10 mx1.state.vt.us.
+ IN MX 10 mx2.state.vt.us.
+$ORIGIN k12.vt.us.
+ns2 IN A 170.222.64.130
+morristown IN MX 0 mail.k12.vt.us.
+ns1 IN A 170.222.64.130
+jericho IN MX 0 mail.k12.vt.us.
+founders IN MX 0 mail.k12.vt.us.
+$ORIGIN state.vt.us.
+srs IN A 159.105.101.150
+ IN MX 0 srs.srs.state.vt.us.
+ IN MX 10 mx1.state.vt.us.
+ IN MX 10 mx2.state.vt.us.
+defgen IN MX 0 mail.state.vt.us.
+ IN MX 10 mx1.state.vt.us.
+ IN MX 10 mx2.state.vt.us.
+ IN MX 5 vtagr02.agr.state.vt.us.
+ IN MX 15 mx1.state.vt.us.
+ IN MX 20 mx2.state.vt.us.
+mail IN A 170.222.64.134
+ns1 IN A 159.105.23.130
+ns2 IN A 170.222.64.130
+$ORIGIN srs.state.vt.us.
+srs IN A 159.105.101.150
+$ORIGIN agr.state.vt.us.
+vtagr04 IN A 159.105.50.4
+vtagr02 IN A 159.105.50.2
+$ORIGIN anr.state.vt.us.
+dec IN MX 10 mx1.state.vt.us.
+ IN MX 10 mx2.state.vt.us.
+ IN MX 0 dec.anr.state.vt.us.
+ IN A 159.105.46.4
+$ORIGIN pha.pa.us.
+candle IN A 162.33.245.46
+$ORIGIN CNRI.reston.va.us.
+NS IN A 132.151.1.1
+$ORIGIN boston.MA.us.
+foxharp IN MX 10 bparker.connactivity.com.
+$ORIGIN ns.foxharp.boston.MA.us.
+a IN A 24.147.209.205
+$ORIGIN STARFIRE.DOUGLAS.MA.us.
+NS2 IN A 216.129.136.9
+DNS IN A 206.225.44.40
+NS1 IN A 216.129.136.9
+$ORIGIN NIC.us.
+USDNS IN A 198.41.3.87
+$ORIGIN sf.ca.us.
+asylum IN A 192.48.232.17
+$ORIGIN palo-alto.ca.us.
+mejac IN A 192.147.236.1
+$ORIGIN VN.
+DNS1 IN A 203.162.3.235
+$ORIGIN EDU.UY.
+SECIU IN A 164.73.128.5
+$ORIGIN UZ.
+NS IN A 213.68.88.11
+$ORIGIN NOC.UZ.
+NS IN A 194.67.52.42
+$ORIGIN VANUATU.COM.VU.
+SANTO IN A 202.139.40.7
+FUTUNA IN A 202.139.40.3
+EFATE IN A 202.139.40.5
+$ORIGIN nic.mnet.
+ns2 IN A 208.109.83.110
+ns1 IN A 216.61.39.172
+$ORIGIN DNS.WS.
+NS4 IN A 216.52.234.102
+NS2 IN A 216.35.187.250
+NS1 IN A 202.4.48.217
+NS5 IN A 216.35.188.8
+NS3 IN A 216.52.234.99
+$ORIGIN UCT.AC.ZA.
+UCTHPX IN A 137.158.128.1
+$ORIGIN FRD.AC.ZA.
+APIES IN A 137.214.80.1
+$ORIGIN EE.UND.AC.ZA.
+DAISY IN A 146.230.192.18
+$ORIGIN RU.AC.ZA.
+HIPPO IN A 146.231.128.1
+$ORIGIN UNZA.ZM.
+PUKU IN A 196.7.240.1
+$ORIGIN NIC.YU.
+NS1 IN A 147.91.8.6
+$ORIGIN TELEKOM.YU.
+ODISEJ IN A 195.178.32.2
+$ORIGIN gtld-servers.ORSC.
+b IN A 216.13.126.116
+$ORIGIN ROOT-SERVERS.ORSC.
+B IN A 216.13.126.116
+C IN A 65.196.80.102
+A IN A 199.166.24.1
+$ORIGIN ZPTC.CO.ZW.
+TELCOM IN A 194.133.122.47
+$ORIGIN NIPR.MIL.
+PAC2 IN A 199.252.155.234
+EUR2 IN A 199.252.143.234
+CON2 IN A 199.252.173.234
+PAC1 IN A 199.252.180.234
+EUR1 IN A 199.252.154.234
+CON1 IN A 199.252.175.234
+$ORIGIN ARL.MIL.
+ADMII IN A 128.63.31.4
+ IN A 128.63.5.4
+$ORIGIN GOV.
+nps IN MX 5 ccmail.itd.nps.gov.
+ IN MX 10 ccmail2.itd.nps.gov.
+$ORIGIN STAT-USA.GOV.
+SUNNY IN A 192.239.70.8
+$ORIGIN NASA.GOV.
+jpl IN A 137.78.160.180
+NASANS4 IN A 198.116.144.33
+NASANS3 IN A 198.116.144.49
+NASANS1 IN A 192.77.84.32
+$ORIGIN NSI.NASA.GOV.
+MX IN A 128.102.18.31
+$ORIGIN CDC.GOV.
+NS2 IN A 198.246.96.92
+NS1 IN A 198.246.96.61
+$ORIGIN NIST.GOV.
+NS1 IN A 129.6.13.2
+$ORIGIN cr.USGS.GOV.
+ISDSUN IN A 136.177.16.3
+ns IN A 136.177.16.3
+rgfsparc IN A 136.177.164.192
+$ORIGIN ER.USGS.GOV.
+NS IN A 130.11.48.2
+$ORIGIN WR.USGS.GOV.
+ISDMNL IN A 130.118.4.2
+$ORIGIN DEN.nps.GOV.
+DENS20 IN A 165.83.24.20
+$ORIGIN ITD.nps.GOV.
+BIGBIRD IN A 165.83.208.5
+$ORIGIN AKSO.nps.GOV.
+INPAKSODNS IN A 165.83.49.9
+$ORIGIN WRO.nps.GOV.
+VANILLA IN A 165.83.71.3
+$ORIGIN NCC.nps.GOV.
+OWL IN A 165.83.34.60
+$ORIGIN net.
+FIREHOUSE IN A 63.160.175.19
+gbch IN MX 0 maxim.gbch.net.
+VERMONTEL IN A 63.167.45.2
+ IN MX 0 pop.vermontel.net.
+reedmedia IN A 63.145.197.178
+goldstats IN A 66.33.12.17
+zama IN A 203.142.132.46
+helicon IN A 63.93.137.2
+wetlogic IN MX 10 athome.wetlogic.net.
+188 IN A 202.96.125.100
+ IN A 202.96.125.101
+ IN MX 10 mx2.188.net.
+ IN MX 20 smtp.188.net.
+ IN MX 10 mx1.188.net.
+valley IN MX 0 lebanon.valley.net.
+primary IN A 216.87.34.253
+SOVER IN A 209.198.87.53
+ IN A 209.198.87.34
+ IN MX 10 mail.sover.net.
+ IN MX 20 mqueue.sover.net.
+UU IN MX 10 external-mail-router.UU.NET.
+connriver IN A 63.93.137.13
+ IN MX 10 ns.hcr.net.
+ IN MX 1 mailer.connriver.net.
+SHOREHAM IN A 199.170.121.2
+$ORIGIN cinenet.net.
+NS1 IN A 198.147.76.65
+$ORIGIN TOGETHER.net.
+NS2 IN A 204.97.120.31
+NS1 IN A 204.97.120.30
+$ORIGIN IPHIL.net.
+MAKISIG IN A 203.176.28.135
+$ORIGIN PLANET-THREE.net.
+NS2 IN A 212.49.219.190
+$ORIGIN FIREHOUSE.net.
+DNS2 IN A 63.160.175.18
+DNS1 IN A 63.160.175.19
+$ORIGIN space.net.
+ns IN A 195.30.0.1
+$ORIGIN DNS.space.net.
+NS4 IN A 195.222.210.93
+NS3 IN A 193.149.44.49
+$ORIGIN ALASKA.net.
+NS4-AUTH IN A 209.112.130.4
+NS1-AUTH IN A 209.112.160.4
+$ORIGIN FWIDCSERVICES.net.
+DEN-NS2 IN A 216.7.160.32
+IRV-NS1 IN A 216.23.160.51
+DEN-NS1 IN A 216.7.160.31
+NS1 IN A 64.78.224.58
+$ORIGIN BIJT.net.
+PAN IN A 213.196.2.97
+$ORIGIN SEABONE.net.
+DNS IN A 195.22.205.163
+$ORIGIN SPIN.OMNES.net.
+NS IN A 192.23.90.196
+$ORIGIN VERIO.net.
+NS2 IN A 129.250.31.190
+NS0 IN A 129.250.15.61
+NS1 IN A 204.91.99.140
+$ORIGIN NS.VERIO.net.
+B IN A 129.250.35.32
+T IN A 192.67.14.16
+$ORIGIN GNOSH.net.
+GRIN IN A 216.15.87.207
+$ORIGIN NEASE.net.
+NS2 IN A 202.103.134.4
+$ORIGIN CRSNIC.net.
+NS1 IN A 198.41.3.39
+$ORIGIN VERISIGN.net.
+MODOR IN A 205.139.94.55
+CITADEL IN A 205.139.94.15
+PAGOSA IN A 205.139.94.16
+KAOS IN A 208.202.137.126
+$ORIGIN terra.net.
+ns2 IN A 199.103.128.2
+ns1 IN A 199.103.128.1
+$ORIGIN ADMONITOR.net.
+NS-2 IN A 216.35.185.40
+ads IN A 216.35.185.145
+SC-NS1 IN A 64.70.20.85
+$ORIGIN NORDU.net.
+SERVER IN A 193.10.252.19
+$ORIGIN TELEGLOBE.net.
+CASTOR IN A 199.202.55.2
+$ORIGIN sodak.net.
+NS2 IN A 63.65.239.225
+RINGNECK IN A 63.65.238.65
+$ORIGIN gbch.net.
+MAXIM IN A 203.9.155.249
+$ORIGIN VERMONTEL.net.
+pop IN CNAME loomis.vermontel.net.
+NS2 IN A 204.164.106.8
+loomis IN A 204.164.106.19
+NS1 IN A 204.164.106.2
+$ORIGIN farm.net.
+ns IN A 216.112.179.160
+$ORIGIN NAP.net.
+NS2 IN A 206.54.224.1
+$ORIGIN AH.net.
+NS4 IN A 203.21.205.20
+NS2 IN A 203.21.205.1
+$ORIGIN NS.GDNS.net.
+LHR IN A 212.250.25.101
+DCA IN A 209.207.221.1
+$ORIGIN CONCENTRIC.net.
+NAMESERVER1 IN A 207.155.183.73
+NAMESERVER3 IN A 206.173.119.72
+NAMESERVER IN A 207.155.183.72
+NIC2 IN A 207.88.60.5
+NAMESERVER2 IN A 207.155.184.72
+$ORIGIN att.net.
+worldnet IN A 199.70.151.234
+$ORIGIN worldnet.att.net.
+ns3 IN A 204.127.160.1
+ns4 IN A 204.127.160.2
+mtiwmhc22 IN A 204.127.131.47
+ns1 IN A 204.127.129.1
+ns IN A 204.127.160.2
+ IN A 12.102.240.1
+ IN A 12.102.240.2
+ IN A 12.102.244.1
+ IN A 12.102.244.2
+ IN A 204.127.129.1
+ IN A 204.127.129.2
+ IN A 204.127.160.1
+ns2 IN A 204.127.129.2
+$ORIGIN OR.BR.NP.ELS-GMS.att.net.
+ORCU IN A 199.191.129.139
+$ORIGIN WY.BR.NP.ELS-GMS.att.net.
+WYCU IN A 199.191.128.43
+$ORIGIN OH.MT.NP.ELS-GMS.att.net.
+OHCU IN A 199.191.144.75
+$ORIGIN MA.MT.NP.ELS-GMS.att.net.
+MACU IN A 199.191.145.136
+$ORIGIN MT.NS.ELS-GMS.att.net.
+CMTU IN A 12.127.16.69
+DMTU IN A 12.127.16.70
+$ORIGIN BR.NS.ELS-GMS.att.net.
+CBRU IN A 199.191.128.105
+DBRU IN A 199.191.128.106
+$ORIGIN LEB.net.
+NS IN A 206.127.55.2
+$ORIGIN SEG.net.
+NS2 IN A 206.34.181.16
+NS1 IN A 206.34.181.15
+$ORIGIN romkey.SEG.net.
+ip1 IN A 207.121.69.234
+$ORIGIN ync.net.
+NS4 IN A 206.185.20.9
+NS2 IN A 216.34.185.21
+NS5 IN A 206.185.20.10
+NS3 IN A 206.185.20.8
+ns1 IN A 216.34.185.20
+$ORIGIN GLOBECOMM.net.
+NS2 IN A 165.251.1.3
+NS1 IN A 165.251.1.2
+$ORIGIN PREP.net.
+DNS-EAST IN A 129.250.252.10
+$ORIGIN EARTHLINK.net.
+NS4 IN A 209.179.179.19
+DNS2 IN A 207.217.77.12
+DNS3 IN A 207.217.120.13
+DNS4 IN A 209.179.179.18
+NS1 IN A 207.217.126.41
+NS2 IN A 207.217.77.42
+$ORIGIN SPRINTLINK.net.
+NS3-AUTH IN A 144.228.255.10
+NS2-AUTH IN A 144.228.254.10
+NS1-AUTH IN A 206.228.179.10
+$ORIGIN OP.net.
+NS1 IN A 209.152.193.4
+$ORIGIN CERNET.net.
+NS IN A 202.112.0.44
+$ORIGIN zenon.net.
+dns IN A 195.2.83.107
+$ORIGIN INFI.net.
+NS3 IN A 205.219.239.5
+NS4 IN A 216.33.106.19
+NS001 IN A 208.131.160.201
+NS1 IN A 198.22.1.107
+NS2 IN A 198.22.1.108
+$ORIGIN vh8.INFI.net.
+vh80040 IN A 209.97.59.245
+vh80167 IN A 209.97.57.116
+$ORIGIN vh4.INFI.net.
+vh40099 IN A 209.97.59.121
+$ORIGIN SCRUZ.net.
+NS2 IN A 165.227.2.10
+NS IN A 165.227.1.1
+$ORIGIN HINET.net.
+netnews IN A 168.95.195.16
+ IN MX 0 netnews.hinet.net.
+HNTP1 IN A 168.95.192.1
+HNTP3 IN A 168.95.192.2
+DNS IN A 168.95.1.1
+$ORIGIN reedmedia.net.
+ns2 IN A 209.241.86.6
+NS1 IN A 63.145.197.178
+$ORIGIN schnism.net.
+ns IN A 195.88.150.3
+$ORIGIN unlisys.net.
+mail IN A 195.21.255.252
+$ORIGIN AIC.net.
+NS IN A 195.250.64.65
+$ORIGIN PIPEX-SZ.net.
+NS IN A 196.15.232.19
+$ORIGIN DOMAINNT.net.
+DENEB IN A 207.211.220.90
+RIGEL IN A 212.0.205.5
+VEGA IN A 209.26.120.5
+POLARIS IN A 209.26.120.2
+ANTARES IN A 209.26.120.3
+$ORIGIN GUERNSEY.net.
+DNS2 IN A 195.226.128.3
+$ORIGIN usa.net.
+CNDVG001 IN A 165.212.12.1
+$ORIGIN OPS.usa.net.
+dns03 IN A 204.68.24.136
+DNS01 IN A 204.68.24.137
+$ORIGIN INR.net.
+NS2 IN A 198.77.208.3
+NS1 IN A 198.77.208.2
+$ORIGIN CP.MSFT.net.
+dns6 IN A 207.46.138.20
+DNS4 IN A 207.46.138.11
+dns7 IN A 207.46.138.21
+dns IN A 207.46.138.10
+DNS5 IN A 207.46.138.12
+$ORIGIN UK.MSFT.net.
+DNS4 IN A 213.199.144.152
+DNS3 IN A 213.199.144.151
+$ORIGIN TK.MSFT.net.
+DNS2 IN A 207.46.232.38
+DNS1 IN A 207.46.232.37
+$ORIGIN HHS.net.
+NS IN A 63.93.136.29
+$ORIGIN NEWACCOUNT.net.
+NS IN A 216.121.96.26
+$ORIGIN PBI.net.
+NS2 IN A 206.13.29.11
+NS1 IN A 206.13.28.11
+$ORIGIN timeheart.net.
+ns1 IN A 63.197.231.203
+$ORIGIN TOSA.TWTELECOM.net.
+INS2 IN A 204.95.160.4
+INS1 IN A 204.95.160.2
+$ORIGIN zama.net.
+NS2 IN A 203.142.130.5
+NS1 IN A 203.142.130.4
+$ORIGIN MINDLINK.net.
+GIANT IN A 204.174.18.2
+DEEP IN A 204.174.16.4
+$ORIGIN SER.BBNPLANET.net.
+KNOCK IN A 192.239.16.129
+$ORIGIN MEDIASERVICES.net.
+NS2 IN A 64.65.16.237
+NS IN A 64.65.15.147
+$ORIGIN KOLO.net.
+NS IN A 209.66.103.20
+$ORIGIN SEYCHELLES.net.
+NS1 IN A 202.84.235.33
+$ORIGIN BT.net.
+NS0 IN A 194.72.6.51
+$ORIGIN JERKY.net.
+NS1 IN A 204.57.55.100
+$ORIGIN CN.net.
+DNS2 IN A 202.97.18.61
+NS1 IN A 202.97.7.17
+NS IN A 202.97.16.195
+$ORIGIN runway.CN.net.
+ns IN A 211.101.132.8
+$ORIGIN APNIC.net.
+SVC00 IN A 202.12.28.131
+TECKLA IN A 202.12.28.129
+NS IN A 203.37.255.97
+$ORIGIN BELLSOUTH.net.
+NS IN A 205.152.0.5
+$ORIGIN ATL.BELLSOUTH.net.
+NS IN A 205.152.0.20
+$ORIGIN CL.BELLSOUTH.net.
+NS2 IN A 205.152.16.8
+NS3 IN A 205.152.32.8
+$ORIGIN MIA.BELLSOUTH.net.
+NS IN A 205.152.16.20
+$ORIGIN RDU.BELLSOUTH.net.
+NS IN A 205.152.32.20
+$ORIGIN 163.net.
+SHNS IN A 61.129.65.108
+BJNS IN A 202.108.255.202
+NS IN A 202.108.255.201
+$ORIGIN ca.us.ibm.net.
+ns02 IN A 165.87.201.243
+ns01 IN A 165.87.201.244
+$ORIGIN ny.us.ibm.net.
+ns01 IN A 165.87.194.244
+$ORIGIN CP.net.
+NS3 IN A 209.228.14.4
+NS1 IN A 209.228.15.4
+$ORIGIN tallship.net.
+falcon IN A 208.179.112.2
+condor IN A 12.28.140.20
+nomad IN A 204.107.129.2
+satan IN A 204.107.129.3
+rectum IN A 204.107.129.10
+$ORIGIN ns.tmcs.net.
+b IN A 209.104.33.252
+c IN A 209.104.39.252
+a IN A 209.104.63.252
+$ORIGIN pshift.net.
+mail IN A 208.153.85.30
+$ORIGIN CTCCOM.net.
+NS4 IN A 64.69.100.35
+NS3 IN A 64.69.100.67
+$ORIGIN cid.net.
+bofh IN A 212.172.21.254
+$ORIGIN PIPEX.net.
+NS0 IN A 158.43.128.8
+NS1 IN A 158.43.192.7
+$ORIGIN DNS.PIPEX.net.
+NS1-Y IN A 158.43.193.89
+NS0-Y IN A 158.43.129.89
+$ORIGIN SOTELMA.net.
+DOGON IN A 208.144.230.1
+CIWARA IN A 208.144.230.2
+$ORIGIN DK.net.
+NS IN A 193.88.44.42
+$ORIGIN HIGGS.net.
+ns2 IN A 204.80.125.145
+ns3 IN A 204.80.101.94
+ns IN A 204.80.101.90
+ns1 IN A 204.80.125.130
+PINE IN A 204.80.125.130
+$ORIGIN E-SYNC.net.
+NS2 IN A 192.206.57.128
+NS1 IN A 192.206.57.127
+$ORIGIN ABOVE.net.
+NS3 IN A 207.126.105.146
+NS IN A 207.126.96.162
+$ORIGIN COBEX.net.
+NS2 IN A 207.102.129.72
+NS1 IN A 207.102.129.71
+$ORIGIN NEO.net.
+NS2 IN A 206.109.7.65
+NS IN A 206.109.1.1
+$ORIGIN AFRIQ.net.
+BAABEN IN A 165.231.1.3
+NEENE IN A 165.231.1.2
+$ORIGIN CW.net.
+NS4 IN A 204.70.49.234
+NS2 IN A 204.70.57.242
+NS3 IN A 204.70.25.234
+NS IN A 204.70.128.1
+$ORIGIN hactrn.net.
+NS IN A 216.254.68.12
+$ORIGIN QUASAR.net.
+NS1 IN A 199.166.31.3
+$ORIGIN VERMONTLAW.net.
+NS1 IN A 63.89.26.15
+NS IN A 63.89.26.16
+$ORIGIN ICP.net.
+ICM1 IN A 192.94.207.66
+$ORIGIN wetlogic.net.
+athome IN CNAME c1059495-a.snvl1.sfba.home.com.
+$ORIGIN NY.ALTER.net.
+New-York4 IN A 137.39.126.10
+ IN A 137.39.2.3
+$ORIGIN pccf.net.
+proxy IN A 205.189.73.123
+$ORIGIN IS-FUN.net.
+NS4 IN A 212.162.54.34
+$ORIGIN GUA.net.
+OSI2 IN A 205.161.188.3
+$ORIGIN 2GLOBE.net.
+TERMINAL IN A 195.178.183.230
+NS IN A 195.178.183.200
+$ORIGIN SYS.GTEI.net.
+DNSAUTH2 IN A 4.2.49.3
+DNSAUTH3 IN A 4.2.49.4
+DNSAUTH1 IN A 4.2.49.2
+$ORIGIN SPEAKEASY.net.
+NS2 IN A 216.231.41.22
+NS1 IN A 216.254.0.9
+$ORIGIN PSI.net.
+NS2 IN A 38.8.50.2
+$ORIGIN DNS.UK.PSI.net.
+SEC1 IN A 154.32.105.34
+$ORIGIN ray.net.
+ns1 IN A 195.238.228.131
+$ORIGIN anycast.net.
+ns1 IN A 216.196.51.4
+$ORIGIN EP.net.
+FLAG IN A 198.32.4.13
+$ORIGIN SR.net.
+NS2 IN A 200.1.156.11
+NS1 IN A 200.1.157.10
+$ORIGIN IPTEK.net.
+CADDSYS IN A 202.46.1.2
+$ORIGIN NIC.XLINK.net.
+DNS IN A 193.141.40.42
+$ORIGIN NURSAT.net.
+NS2 IN A 212.13.167.1
+NS IN A 194.226.128.1
+$ORIGIN 188.net.
+smtp IN A 202.96.125.104
+mx2 IN A 202.96.125.101
+ns2 IN A 202.103.134.4
+mx1 IN A 202.96.125.100
+NS IN A 202.96.125.106
+$ORIGIN KORNET.net.
+NS IN A 168.126.63.1
+$ORIGIN CCSRS.net.
+NS2 IN A 206.253.214.73
+NS1 IN A 209.237.73.73
+$ORIGIN EU.net.
+NS IN A 192.16.202.11
+$ORIGIN USSR.EU.net.
+NS IN A 193.124.22.65
+$ORIGIN RELCOM.EU.net.
+NS IN A 193.124.23.3
+$ORIGIN AUSTRIA.EU.net.
+NS IN A 192.92.138.35
+NS3 IN A 193.154.160.110
+$ORIGIN hypa.net.
+ns2 IN A 63.160.181.11
+ns1 IN A 63.160.181.10
+ IN A 209.166.167.208
+$ORIGIN IDT.net.
+NS IN A 198.4.75.100
+$ORIGIN NS.IDT.net.
+AUTH2 IN A 169.132.133.1
+$ORIGIN ROOT-SERVERS.net.
+A IN A 198.41.0.4
+B IN A 128.9.0.107
+C IN A 192.33.4.12
+D IN A 128.8.10.90
+E IN A 192.203.230.10
+F IN A 192.5.5.241
+G IN A 192.112.36.4
+H IN A 128.63.2.53
+I IN A 192.36.148.17
+$ORIGIN I-DNS.net.
+D IN A 211.169.245.170
+B IN A 208.184.25.199
+F IN A 216.200.119.128
+E IN A 202.160.253.152
+C IN A 210.189.254.50
+A IN A 208.184.174.7
+$ORIGIN US.PRSERV.net.
+NS4 IN A 165.87.201.244
+NS1 IN A 165.87.194.244
+NS3 IN A 165.87.201.243
+$ORIGIN U-NET.net.
+NS0 IN A 194.119.128.65
+NS1 IN A 194.119.128.66
+$ORIGIN HS0.U-NET.net.
+NS0 IN A 194.119.128.70
+NS1 IN A 194.119.128.71
+$ORIGIN ULTRADNS.net.
+UDNS2 IN A 204.74.101.1
+UDNS1 IN A 204.69.234.1
+$ORIGIN WEBMAGIC.net.
+NS2 IN A 64.168.49.66
+NS1 IN A 209.119.182.2
+$ORIGIN HOST4U.net.
+NS2 IN A 209.150.129.3
+NS IN A 209.150.128.30
+$ORIGIN RCCN.net.
+DNS IN A 193.136.7.17
+$ORIGIN valley.net.
+lebanon IN A 198.115.160.16
+NS2 IN A 198.115.160.16
+DNS IN A 198.115.160.10
+$ORIGIN primary.net.
+dns2 IN A 205.242.187.235
+NS2 IN A 205.242.176.103
+dns1 IN A 205.242.187.234
+NS1 IN A 205.242.92.2
+$ORIGIN SQUONK.net.
+NS2 IN A 63.84.12.135
+NS1 IN A 63.84.12.133
+$ORIGIN IP-PLUS.net.
+NS1 IN A 164.128.36.34
+$ORIGIN TECHNOLOGIA.net.
+NS2 IN A 207.253.59.4
+NS1 IN A 207.253.214.199
+NS3 IN A 195.115.180.67
+$ORIGIN VI.net.
+NS2 IN A 212.78.64.10
+NS1 IN A 194.88.77.1
+$ORIGIN ISLES.net.
+RS IN A 212.100.224.90
+$ORIGIN SOVER.net.
+time IN CNAME garnet.sover.net.
+mqueue IN A 209.198.87.52
+etrn IN A 209.198.87.58
+garnet IN A 209.198.87.53
+MAPLE IN A 209.198.87.41
+CLOVER IN A 209.198.87.40
+mail IN A 209.198.87.53
+ IN A 209.198.87.34
+mqueue0 IN A 209.198.87.52
+$ORIGIN ACT2000.net.
+ACT2 IN A 207.42.132.227
+ACT1 IN A 207.42.132.226
+$ORIGIN AKADNS.net.
+ZA IN A 209.185.188.39
+ZB IN A 216.32.65.105
+ZC IN A 204.178.107.227
+ZD IN A 204.178.110.67
+ZE IN A 216.200.14.118
+ZF IN A 208.5.85.132
+ZG IN A 206.132.160.36
+ZH IN A 63.208.48.42
+$ORIGIN NS.ESAT.net.
+NS3 IN A 192.111.39.100
+$ORIGIN THEPLANET.net.
+EARTH IN A 195.92.195.222
+PLUTO IN A 194.207.6.30
+VENUS IN A 194.152.65.222
+$ORIGIN UU.net.
+uunet IN MX 10 Mail.uu.net.
+external-mail-router IN A 198.5.241.39
+ IN A 198.5.241.38
+ IN A 198.5.241.40
+NS IN A 137.39.1.3
+$ORIGIN NS.DE.UU.net.
+AUTH03 IN A 192.76.144.16
+$ORIGIN NS.UU.net.
+AUTH100 IN A 198.6.1.202
+AUTH00 IN A 198.6.1.65
+AUTH02 IN A 198.6.1.82
+AUTH03 IN A 198.6.1.83
+AUTH60 IN A 198.6.1.181
+AUTH61 IN A 198.6.1.182
+AUTH110 IN A 198.6.1.114
+AUTH50 IN A 198.6.1.161
+AUTH51 IN A 198.6.1.162
+$ORIGIN PIONEERNET.net.
+DNS2 IN A 208.240.196.10
+DNS1 IN A 208.240.196.9
+$ORIGIN HOME.net.
+NS2 IN A 24.2.0.27
+NS1 IN A 24.0.0.27
+$ORIGIN QUANTIFIED.net.
+NS2 IN A 63.212.171.3
+NS1 IN A 63.212.171.2
+$ORIGIN SECURE.net.
+NS2 IN A 161.58.9.10
+NS1 IN A 192.41.1.10
+$ORIGIN DSL.net.
+NS2 IN A 209.87.79.232
+NS1 IN A 209.87.64.70
+$ORIGIN JA.net.
+NS0 IN A 128.86.1.20
+ IN A 193.63.94.20
+$ORIGIN ULCC.JA.net.
+NOC IN A 193.63.94.25
+$ORIGIN CINE.net.
+NS2 IN A 207.168.250.12
+$ORIGIN ANS.net.
+NS-02B IN A 207.24.245.178
+NS-01B IN A 199.221.47.8
+NS-02A IN A 207.24.245.179
+NS-01A IN A 199.221.47.7
+$ORIGIN OAR.net.
+NS2 IN A 192.88.195.10
+NS1 IN A 192.88.193.144
+$ORIGIN MAHNET.net.
+NS2 IN A 207.219.173.132
+NS1 IN A 24.69.168.121
+$ORIGIN NCREN.net.
+REGGAE IN A 128.109.131.3
+NCNOC IN A 192.101.21.1
+$ORIGIN AMERICA.net.
+AUTH2 IN A 209.17.197.18
+AUTH1 IN A 209.17.197.2
+$ORIGIN EXODUS.net.
+NS2 IN A 207.82.198.150
+NS IN A 206.79.230.10
+NS3 IN A 206.79.240.13
+$ORIGIN NJ.EXODUS.net.
+NS2 IN A 209.1.10.234
+NS IN A 206.79.7.50
+$ORIGIN DOUBLECLICK.net.
+uunymdgds1 IN A 206.65.183.21
+dcnymdgds1 IN A 204.253.104.202
+exnjmdgds1 IN A 209.67.38.22
+dcnyadgds1 IN A 204.253.104.11
+bbvamdgds1 IN A 128.11.60.75
+exnjadgds1 IN A 209.67.38.48
+annyadgds1 IN A 208.184.29.250
+annyadgds2 IN A 208.184.29.252
+cwvamdgds1 IN A 205.138.3.240
+uucamdgds1 IN A 204.178.112.124
+cwvaadgds1 IN A 205.138.3.242
+spnjadgds1 IN A 208.32.211.70
+cwvaadgds2 IN A 205.138.3.243
+ctukadgds1 IN A 213.86.246.20
+tlseadgds1 IN A 194.237.107.6
+uusjmdgds1 IN A 204.176.177.20
+uuvamdgds1 IN A 204.178.112.168
+$ORIGIN DCNY.DOUBLECLICK.net.
+NS2 IN A 204.253.104.10
+NS1 IN A 208.211.225.10
+$ORIGIN UUSJ.DOUBLECLICK.net.
+NS1 IN A 204.176.177.10
+$ORIGIN CWVA.DOUBLECLICK.net.
+NS1 IN A 205.138.3.20
+$ORIGIN DSO.net.
+NS2 IN A 206.16.77.11
+NS1 IN A 206.16.77.10
+$ORIGIN GIP.net.
+NS2 IN A 204.59.1.222
+NS1 IN A 204.59.144.222
+NS3 IN A 204.59.64.222
+$ORIGIN AMNIC.net.
+NS IN A 195.250.64.90
+$ORIGIN TELSTRA.net.
+NS1 IN A 139.130.4.5
+$ORIGIN ELI.net.
+NS2 IN A 207.173.86.2
+NS IN A 209.63.0.2
+$ORIGIN TWNIC.net.
+NS IN A 192.83.166.11
+$ORIGIN BAHNHOF.net.
+NS2 IN A 212.85.64.4
+NS1 IN A 195.178.160.2
+$ORIGIN ivm.net.
+ns1 IN A 62.204.1.1
+$ORIGIN BEACHSHORE.net.
+NS1 IN A 199.166.31.250
+$ORIGIN TDS.net.
+NS IN A 204.246.1.20
+$ORIGIN FIRSTWORLD.net.
+NS4 IN A 216.7.160.162
+NS2 IN A 216.127.92.78
+NS1 IN A 216.7.160.75
+NS3 IN A 216.7.160.161
+$ORIGIN centralinfo.net.
+ns2 IN A 63.102.204.130
+ns1 IN A 63.102.200.2
+$ORIGIN NOC.NULLUS.net.
+NS2 IN A 63.119.253.254
+NS3 IN A 63.168.101.254
+NS1 IN A 209.136.161.254
+$ORIGIN FREE.net.
+NS1 IN A 147.45.15.34
+$ORIGIN mediaone.net.
+NS1 IN A 24.128.1.80
+NS2 IN A 24.128.1.81
+$ORIGIN MW.mediaone.net.
+NS1 IN A 24.131.1.8
+$ORIGIN JVNC.net.
+NISC IN A 128.121.50.7
+$ORIGIN NS.NYC1.GLOBIX.net.
+Z1 IN A 209.10.66.55
+$ORIGIN NS.LHR1.GLOBIX.net.
+Z1 IN A 212.111.32.38
+$ORIGIN NS.SJC1.GLOBIX.net.
+Z1 IN A 209.10.34.55
+$ORIGIN akamaitech.net.
+za IN A 204.178.107.226
+n6g IN A 216.52.121.175
+ZB IN A 128.11.47.240
+n2g IN A 216.52.56.47
+ZC IN A 216.32.65.14
+ZD IN A 38.144.120.147
+n5g IN A 216.52.56.33
+ZE IN A 216.200.14.134
+n1g IN A 216.52.56.36
+ZF IN A 204.178.110.73
+n8g IN A 216.52.56.33
+ZG IN A 209.185.188.14
+n4g IN A 216.52.56.33
+ZH IN A 213.161.66.165
+n0g IN A 216.52.56.33
+n7g IN A 216.52.196.5
+n3g IN A 216.52.56.48
+$ORIGIN THNIC.net.
+NS-AIT IN A 192.41.170.219
+NS IN A 202.28.0.1
+$ORIGIN connriver.net.
+mailer IN A 63.93.137.13
+ns2 IN A 208.240.246.5
+netserver IN A 204.249.74.100
+$ORIGIN IT.net.
+DNS2 IN A 151.1.2.1
+DNS IN A 151.1.1.1
+$ORIGIN D4P.net.
+foolusmf IN CNAME a100.g.akamai.net.
+$ORIGIN LUCKY.net.
+NS IN A 193.193.193.100
+$ORIGIN SENET.net.
+NS IN A 206.155.163.195
+$ORIGIN RIPE.net.
+NS IN A 193.0.0.193
+$ORIGIN ADELPHIA.net.
+NS2 IN A 24.48.62.35
+NS3 IN A 208.239.78.134
+NS1 IN A 24.48.43.3
+$ORIGIN cdp.ADELPHIA.net.
+mx1 IN A 24.48.58.221
+$ORIGIN buf.ADELPHIA.net.
+mx1 IN A 24.48.36.10
+$ORIGIN INTERNIC.net.
+NS2 IN A 198.41.0.11
+$ORIGIN UNDPBI.TELEPAC.net.
+SOL IN A 194.65.87.2
+$ORIGIN KRNIC.net.
+NS1 IN A 202.30.50.51
+NS IN A 202.30.50.50
+$ORIGIN UNI2.net.
+NS2 IN A 195.82.195.99
+NS IN A 129.142.7.99
+$ORIGIN GTLD-SERVERS.net.
+K IN A 213.177.194.5
+A IN A 198.41.3.38
+B IN A 203.181.106.5
+M IN A 202.153.114.101
+C IN A 205.188.185.18
+D IN A 208.206.240.5
+E IN A 207.200.81.69
+F IN A 198.17.208.67
+G IN A 198.41.3.101
+I IN A 192.36.144.133
+J IN A 210.132.100.101
+$ORIGIN dns.swip.net.
+kista IN A 192.71.220.9
+$ORIGIN RCPIP.net.
+EKEKO IN A 209.45.127.2
+$ORIGIN UNA.net.
+ENGINE1 IN A 208.136.52.74
+$ORIGIN hcr.net.
+ns IN A 208.240.246.4
+$ORIGIN NSIREGISTRY.net.
+NS2 IN A 198.41.3.108
+$ORIGIN SUBTEND.net.
+NAVI IN A 208.186.117.224
+NS1 IN A 208.186.117.71
+$ORIGIN IAD.GBLX.net.
+NAME IN A 204.152.166.155
+$ORIGIN PHX.GBLX.net.
+NAME IN A 206.165.6.10
+$ORIGIN ROC.GBLX.net.
+NAME IN A 209.130.187.10
+$ORIGIN SHOREHAM.net.
+pop IN CNAME shoreham.net.
+$ORIGIN GREENMOUNTAINACCESS.net.
+NS2 IN A 208.144.252.31
+NS1 IN A 208.144.252.30
+$ORIGIN MINDSPRING.net.
+SCRATCHY IN A 207.69.200.211
+ITCHY IN A 207.69.200.210
+$ORIGIN RIPN.net.
+NS2 IN A 195.209.0.6
+NS IN A 194.85.119.1
+$ORIGIN CWCI.net.
+NS0 IN A 194.6.79.162
+$ORIGIN GBMTECH.net.
+NS2 IN A 208.243.164.3
+NS1 IN A 208.243.164.2
+$ORIGIN vrx.net.
+pedic-med IN A 199.166.24.2
+ns2 IN A 65.196.80.102
+ns3 IN A 199.166.24.3
+ns1 IN A 199.166.24.1
+ IN A 216.13.76.2
+$ORIGIN globalnetisp.net.
+NS2 IN A 207.136.213.2
+NS1 IN A 207.136.213.1
+$ORIGIN MYNET.net.
+FAITH IN A 207.13.11.2
+$ORIGIN ADNS.net.
+NS2 IN A 199.5.157.3
+KOVU IN A 199.5.157.52
+NS1 IN A 199.5.157.2
+$ORIGIN DIEBOLD.net.
+NS1 IN A 65.196.80.10
+$ORIGIN JPS.net.
+NS2 IN A 216.224.156.252
+NS1 IN A 216.119.0.192
+$ORIGIN NETNAMES.net.
+NS2 IN A 212.53.77.28
+NS1 IN A 212.53.64.60
+$ORIGIN RIO.net.
+ORSTOM IN A 192.33.151.1
+$ORIGIN com.
+sherickpm IN MX 10 inbound.sherickpm.com.criticalpath.net.
+ultradevices IN A 209.249.61.20
+verisign IN A 205.139.94.60
+vermontel IN A 204.164.106.2
+ IN MX 0 pop.vermontel.net.
+TOPICA IN A 206.132.75.196
+unknown IN A 168.143.148.168
+vietmercury IN A 207.1.134.34
+moonmothers IN A 24.218.253.157
+ IN MX 10 costorf.ne.mediaone.net.
+vhv IN MX 0 mail.vhv.com.
+BURSTNET IN MX 15 mail.ar.com.
+ IN MX 5 ibd.ar.com.
+velco IN A 207.217.96.41
+ IN A 207.217.96.42
+ IN A 207.217.96.43
+ IN A 207.217.96.44
+ IN A 207.217.96.45
+ IN A 207.217.96.28
+ IN A 207.217.96.29
+ IN A 207.217.96.30
+ IN A 207.217.96.31
+ IN A 207.217.96.32
+ IN A 207.217.96.33
+ IN A 207.217.96.34
+ IN A 207.217.96.35
+ IN A 207.217.96.36
+ IN A 207.217.96.37
+ IN A 207.217.96.38
+ IN A 207.217.96.39
+ IN A 207.217.96.40
+ IN MX 10 mail.velco.com.
+ffic IN A 64.84.58.128
+ IN MX 5 mail.mailconnect.com.
+overstock IN A 64.78.130.251
+madriver IN MX 10 bend.madriver.com.
+catic1 IN MX 10 Mail.catic1.com.
+ IN MX 20 smtp-Relay.CTCCom.net.
+goldstats IN A 66.33.12.17
+nominum IN A 204.152.184.170
+hill IN A 208.162.106.6
+ IN MX 20 mail.hill.com.
+garmontusa IN MX 20 mail.garmontusa.com.
+bt IN A 62.7.244.127
+xraylitho IN MX 10 mail.sover.net.
+ IN MX 20 mqueue.sover.net.
+glaxowellcome IN MX 10 firewall1.glaxowellcome.com.
+ IN MX 10 firewall3.glaxowellcome.com.
+nova-data IN A 64.70.144.14
+ IN MX 10 mail.nova-data.com.
+AVENUEA IN MX 100 mail2.louisdreyfus.co.uk.
+ IN MX 10 ldfwsvr2.l-dreyfus.com.
+ IN MX 50 ldfwsvr02-hme1.l-dreyfus.com.
+ IN MX 75 mail.louisdreyfus.co.uk.
+best IN MX 10 mail1.best.com.
+ IN MX 10 mail2.best.com.
+ IN MX 20 mail3.best.com.
+ IN MX 20 mail4.best.com.
+biketrack IN MX 20 mqueue.sover.net.
+ IN MX 10 mail.sover.net.
+ilovedomain IN A 211.175.164.170
+symquest IN A 64.69.102.131
+ IN MX 10 Quest-7.symquest.com.
+QUEST-NET IN A 207.140.30.11
+ IN MX 5 mail.quest-net.com.
+cacheware IN A 209.128.82.20
+Algebra IN A 208.233.99.160
+gmcr IN A 12.34.108.130
+ IN MX 10 gateway1.gmcr.com.
+YAHOO IN A 216.115.108.243
+ IN A 216.115.108.245
+ogud IN MX 90 smtp.elistx.com.
+ IN MX 10 mail.dc.ogud.com.
+costorf IN A 24.218.253.157
+ IN MX 10 costorf.ne.mediaone.net.
+highmeadow IN A 207.136.209.6
+ IN MX 10 hm6.vt.highmeadow.com.
+ IN MX 20 mqueue.sover.net.
+broadsoft IN A 208.39.36.48
+cmates IN MX 10 popmail.u-net.com.
+mt-mansfield IN A 208.153.85.16
+ IN MX 10 mail.pshift.net.
+ IN MX 30 pomail.pshift.com.
+skiinsurance IN MX 10 mail.skiinsurance.com.
+ IN MX 20 etrn.sover.net.
+map IN A 206.98.40.150
+idx IN MX 30 isdev.idx.com.
+ IN MX 50 drawbridge.idx.com.
+ IN MX 10 idx.idx.com.
+ IN MX 20 bvtsweeper.idx.com.
+msgbox IN A 216.71.82.42
+sleepycat IN A 192.41.61.122
+cisco IN A 198.133.219.25
+ IN MX 10 proxy2.cisco.com.
+ IN MX 10 proxy3.cisco.com.
+ IN MX 20 proxy6.cisco.com.
+ IN MX 20 proxy9.cisco.com.
+ IN MX 10 proxy1.cisco.com.
+TOAPLAN IN A 216.42.31.169
+hometownbands IN A 209.67.235.38
+smuggs IN MX 10 mail.smuggs.com.
+clothncanvas IN A 208.153.85.16
+ IN MX 10 mail.pshift.net.
+ IN MX 30 mail.pshift.com.
+quantified IN A 63.212.171.4
+arabia IN A 216.251.232.40
+bostic IN A 199.103.241.218
+verisign-grs IN A 198.41.3.55
+gdarm IN MX 10 bvt-ext.gdarm.com.
+retro IN A 205.179.181.194
+ IN MX 10 gw.retro.com.
+ IN MX 20 www.retro.com.
+ IN MX 50 mail.scruznet.com.
+vssg IN A 216.157.26.252
+jerusalem-mail IN A 216.251.232.93
+ IN MX 10 mail.jerusalem-mail.com.
+tfm IN MX 50 mtbaker.tfm.com.
+ IN MX 20 mailhost.tfm.com.
+fratfunz IN A 216.226.16.150
+elektro IN A 192.188.133.3
+WonderWorks IN A 192.203.206.65
+ IN MX 50 mail.wonderworks.com.
+fiberia IN MX 10 webmail.fiberia.com.
+tifosi IN MX 10 gutenberg.bucksnet.com.
+ivillage IN A 209.185.162.150
+pwshift IN A 208.153.85.36
+goputney IN MX 10 mail.sover.net.
+ IN MX 20 mqueue.sover.net.
+$ORIGIN IPNS.com.
+NS2 IN A 63.230.183.1
+NS IN A 208.187.190.2
+$ORIGIN appliedtheory.com.
+NS2 IN A 168.75.17.11
+NS1 IN A 204.168.28.9
+ns3 IN A 207.127.101.8
+$ORIGIN COMPUWARE.com.
+nl IN MX 150 uucp.nl.net.
+ IN MX 50 bitbucket.extern.uniface.nl.
+ IN MX 100 smtp.nl.net.
+$ORIGIN YOUR-DOMAIN.com.
+NS2 IN A 216.167.31.177
+NS1 IN A 216.167.31.176
+$ORIGIN nortelnetworks.com.
+NS-RCH IN A 192.135.215.2
+NS-OTT IN A 192.58.194.71
+ns-har IN A 192.100.101.3
+$ORIGIN SJMERCURY.com.
+BAYONET IN A 207.1.134.34
+$ORIGIN excite.com.
+NSE00 IN A 198.3.102.250
+NS00 IN A 198.3.98.250
+NSE01 IN A 198.3.102.251
+NS01 IN A 198.3.98.251
+$ORIGIN PLANET-THREE.com.
+NS0 IN A 212.49.219.164
+$ORIGIN TOKYO.JP.NETDNS.com.
+NS1 IN A 64.56.164.118
+$ORIGIN LONDON.UK.NETDNS.com.
+NS1 IN A 212.62.6.38
+$ORIGIN SANFRANCISCO.US.NETDNS.com.
+NS1 IN A 207.82.50.166
+$ORIGIN NEWYORK.US.NETDNS.com.
+NS1 IN A 216.32.212.86
+$ORIGIN SEATTLE.US.NETDNS.com.
+NS1 IN A 206.253.214.13
+$ORIGIN ARICATRA.com.
+NS IN A 206.64.112.114
+$ORIGIN REGME.com.
+NS1 IN A 207.153.57.14
+$ORIGIN ELISTX.com.
+smtp IN A 209.116.252.130
+NS IN A 209.116.252.130
+$ORIGIN SIGMAHOSTING.com.
+NS1 IN A 209.241.86.6
+$ORIGIN champcable.com.
+CCC IN A 207.41.53.11
+$ORIGIN IAFRICA.com.
+NS1 IN A 196.7.0.139
+NS3 IN A 196.7.0.137
+$ORIGIN dot-god.com.
+A-GTLD-SERVERS IN A 205.189.73.123
+B-GTLD-SERVERS IN A 205.189.71.10
+$ORIGIN CONRADPROMOTIONS.com.
+NS2 IN A 208.24.118.203
+NS1 IN A 208.158.96.118
+$ORIGIN onemain.com.
+ns4 IN A 63.208.210.11
+NS2 IN A 166.90.148.68
+NS1 IN A 166.90.148.67
+ns3 IN A 63.208.210.10
+$ORIGIN SIMORGH.com.
+NS1 IN A 209.1.163.10
+$ORIGIN Christ.com.
+Yeshua IN A 207.54.4.5
+Abba IN A 63.229.15.59
+$ORIGIN TRAVELPHOTOCONTESTS.com.
+www IN A 64.85.86.156
+$ORIGIN WEB2010.com.
+NS4 IN A 216.157.55.6
+NS2 IN A 216.157.79.246
+NS3 IN A 216.157.47.6
+NS IN A 209.235.31.149
+$ORIGIN 2DAY.com.
+NS2 IN A 202.89.128.74
+NS1 IN A 202.37.240.13
+NS3 IN A 209.240.128.25
+$ORIGIN NETSCAPE.com.
+tdns-me1 IN A 205.188.247.67
+tdns-me2 IN A 205.188.247.68
+tdns2 IN A 207.200.77.53
+tdns3 IN A 207.200.73.72
+NS IN A 198.95.251.10
+NS2 IN A 207.200.73.80
+$ORIGIN WWEBSVS.com.
+PAPPILLOMA IN A 209.233.37.10
+$ORIGIN vermontel.com.
+ns1 IN A 204.164.106.2
+$ORIGIN LA.TIS.com.
+RELAY IN A 198.51.22.11
+$ORIGIN MSEN.com.
+DNS IN A 148.59.19.11
+$ORIGIN bungi.com.
+DAVER IN A 206.14.228.2
+ IN A 207.126.97.2
+max IN A 206.14.228.7
+ IN A 207.126.97.7
+$ORIGIN SPEEDHOST.com.
+NS2 IN A 216.42.31.169
+NS3 IN A 216.42.31.130
+$ORIGIN GPG.com.
+NS2 IN A 209.1.163.50
+NS1 IN A 209.1.163.30
+$ORIGIN NL.CONCENTRIC.com.
+NS1 IN A 195.18.114.5
+$ORIGIN SJC.LYCOS.com.
+SJC-NS2 IN A 206.79.171.40
+SJC-NS1 IN A 206.79.171.39
+$ORIGIN BOS.LYCOS.com.
+BOS-NS2 IN A 209.67.228.40
+BOS-NS1 IN A 209.67.228.39
+$ORIGIN TOPICA.com.
+NS3 IN A 206.111.131.72
+ns-ext IN A 206.132.75.195
+inmta011 IN A 206.132.75.197
+inmta009 IN A 206.132.75.226
+dns IN A 206.111.131.72
+outmta004 IN A 206.132.75.201
+inmta001 IN A 206.132.75.197
+ IN A 206.111.131.79
+inmta003 IN A 206.132.75.213
+outmta010 IN A 206.132.75.222
+inmta005 IN A 206.132.75.217
+NS1 IN A 206.132.75.195
+NS2 IN A 208.184.76.200
+$ORIGIN DOLEH.com.
+NS IN A 204.255.25.63
+$ORIGIN BSDI.com.
+NS IN A 207.174.116.8
+$ORIGIN NYTIMES.com.
+GATEKEEPER IN A 199.181.175.201
+$ORIGIN GDGSC.com.
+NS0 IN A 192.160.62.66
+NS2 IN A 204.162.124.66
+$ORIGIN EDIGITALS.com.
+NS2 IN A 211.39.139.36
+NS3 IN A 211.175.164.170
+NS1 IN A 211.39.139.35
+$ORIGIN INTERNETSQUARE.com.
+NS2 IN A 205.227.232.9
+NS1 IN A 216.226.16.146
+$ORIGIN MAIL.com.
+NS2 IN A 165.251.1.3
+GTLD IN A 165.251.1.239
+NS1 IN A 165.251.1.2
+$ORIGIN moonmothers.com.
+localhost IN A 127.0.0.1
+www IN CNAME moonmothers.com.
+$ORIGIN vhv.com.
+mail IN A 208.5.161.11
+$ORIGIN BOCA15-VERIO.com.
+NS15B IN A 208.55.91.51
+NS15A IN A 208.55.91.50
+$ORIGIN ar.com.
+ns2 IN A 64.124.80.42
+ibd IN A 63.194.205.75
+mail IN A 63.194.205.74
+NS1 IN A 63.194.205.74
+$ORIGIN BLIPP.com.
+VIC20 IN A 195.163.165.35
+$ORIGIN CONCOURSE.com.
+NS IN A 199.218.113.2
+$ORIGIN velco.com.
+mail IN A 198.136.217.106
+$ORIGIN FLONETWORK.com.
+UUNS1DNS1 IN A 209.167.79.5
+UUNS1DNS2 IN A 209.167.79.6
+$ORIGIN overstock.com.
+NS1 IN A 207.225.194.13
+$ORIGIN NEWACCOUNT.com.
+NS4 IN A 209.78.16.6
+NS2 IN A 209.78.16.5
+NS3 IN A 216.121.32.205
+NS IN A 216.121.32.10
+$ORIGIN tridog.com.
+NS2 IN A 206.168.112.51
+TRIDOG1 IN A 206.168.112.71
+$ORIGIN madriver.com.
+bend IN A 207.136.232.15
+FUSION IN A 207.136.232.11
+PRIMUS IN A 207.136.232.12
+$ORIGIN catic1.com.
+Mail IN A 207.190.204.103
+$ORIGIN IBD.com.
+NIC IN A 209.249.61.18
+$ORIGIN IOM.com.
+PEBBLES IN A 194.72.124.1
+$ORIGIN nominum.com.
+shell IN A 204.152.187.59
+GNS2 IN A 198.133.199.2
+gns1 IN A 198.133.199.1
+$ORIGIN ATLONLINE.com.
+ATLNET IN A 207.153.72.193
+ATLWEB1 IN A 207.153.72.194
+$ORIGIN hill.com.
+SYRUP IN A 208.162.106.3
+$ORIGIN garmontusa.com.
+mail IN A 64.30.8.178
+$ORIGIN VIX.com.
+NS-EXT IN A 204.152.184.64
+ns-int IN A 204.152.184.65
+$ORIGIN rc.VIX.com.
+db IN A 204.152.187.21
+$ORIGIN SOVAM.com.
+NS IN A 194.67.2.97
+$ORIGIN IOS.com.
+NOC IN A 198.4.75.69
+$ORIGIN BOSTON.juno.com.
+NS IN A 64.136.25.53
+$ORIGIN JERSEY.juno.com.
+NS IN A 64.136.17.178
+$ORIGIN NYC.juno.com.
+NS IN A 205.231.108.1
+$ORIGIN MEITCA.com.
+NS1 IN A 137.203.5.1
+$ORIGIN glaxowellcome.com.
+firewall3 IN A 192.58.204.207
+firewall1 IN A 192.58.204.204
+NS IN A 192.58.204.113
+$ORIGIN EPILOGUE.com.
+QUERN IN A 128.224.1.136
+$ORIGIN CLASSIFIEDMONSTER.com.
+NS1 IN A 216.254.54.22
+$ORIGIN nova-data.com.
+mail IN A 12.16.110.35
+$ORIGIN corning.com.
+GATEKEEPER IN A 149.42.1.2
+$ORIGIN a1.YIMG.com.
+us IN CNAME a32.g.a.yimg.com.
+$ORIGIN i1.YIMG.com.
+us IN CNAME a1.g.a.yimg.com.
+$ORIGIN nc.us.IBM.com.
+e24 IN A 32.97.136.230
+e22 IN A 32.97.136.228
+e23 IN A 32.97.136.229
+e21 IN A 32.97.136.227
+$ORIGIN co.us.IBM.com.
+e34 IN A 32.97.110.132
+e32 IN A 32.97.110.130
+e33 IN A 32.97.110.131
+e31 IN A 32.97.110.129
+$ORIGIN ny.us.IBM.com.
+e4 IN A 32.97.182.104
+e2 IN A 32.97.182.102
+e3 IN A 32.97.182.103
+e1 IN A 32.97.182.101
+$ORIGIN AUSTIN.IBM.com.
+NS IN A 192.35.232.34
+$ORIGIN ZURICH.IBM.com.
+INTERNET-SERVER IN A 195.212.119.252
+$ORIGIN ALMADEN.IBM.com.
+NS IN A 198.4.83.35
+$ORIGIN ERS.IBM.com.
+NS IN A 204.146.173.35
+$ORIGIN WATSON.IBM.com.
+NS IN A 198.81.209.2
+$ORIGIN DCCSERVER.com.
+GODFEVER IN A 208.137.22.6
+$ORIGIN SUN.com.
+saturn IN A 192.9.25.2
+venus IN A 192.9.25.5
+east IN MX 40 mars.sun.com.
+ IN MX 40 mondzo.sun.com.
+ IN MX 5 venus.sun.com.
+ IN MX 5 lukla.sun.com.
+ IN MX 5 saturn.sun.com.
+ IN MX 5 patan.sun.com.
+ IN MX 15 mercury.sun.com.
+mondzo IN A 192.18.100.1
+lukla IN A 192.18.98.31
+NS-BRM IN A 192.18.99.5
+ns-os IN A 192.9.9.6
+patan IN A 192.18.98.43
+mars IN A 192.9.22.1
+mercury IN A 192.9.25.1
+NS IN A 192.9.9.3
+$ORIGIN pr.SUN.com.
+ns1 IN A 192.18.16.2
+$ORIGIN eu.SUN.com.
+ns1 IN A 192.18.240.8
+$ORIGIN USEC.SUN.com.
+NS IN A 192.9.48.3
+$ORIGIN PSHIFT.com.
+ns2 IN A 208.153.85.21
+NS1 IN A 208.153.85.20
+$ORIGIN mobydark.com.
+ns1 IN A 216.13.76.21
+$ORIGIN compuserve.com.
+DUB-NAME-SVC-1 IN A 149.174.213.5
+ARL-NAME-SVC-1 IN A 149.174.211.5
+$ORIGIN NS.cs.com.
+DNS-02 IN A 205.188.157.235
+DNS-01 IN A 152.163.159.235
+$ORIGIN pcode.com.
+ns1 IN A 216.15.192.135
+$ORIGIN AVENUEA.com.
+EX2-DNS0 IN A 216.34.88.20
+SEA2DNS IN A 63.251.8.150
+$ORIGIN PHOTOTRUST.com.
+Filer IN A 64.85.86.172
+NS02 IN A 64.85.86.142
+www IN A 64.85.86.151
+NS01 IN A 64.85.86.141
+$ORIGIN GOOGLE.com.
+HEDNS1 IN A 64.209.200.10
+helbdns IN A 64.209.200.252
+valbdns IN A 216.239.37.252
+exlbdns IN A 64.208.34.252
+sulbdns IN A 64.208.32.252
+NS IN A 209.185.108.134
+sjlbdns IN A 216.239.35.252
+NS2 IN A 209.185.108.135
+$ORIGIN ns0.com.
+NS00 IN A 216.92.60.60
+ns0 IN A 209.197.64.1
+$ORIGIN best.com.
+NS3 IN A 209.24.149.42
+mail2 IN A 206.184.139.12
+ IN A 206.184.139.13
+ IN A 206.184.139.16
+ IN A 206.184.139.18
+mail3 IN A 206.184.139.12
+ IN A 206.184.139.13
+ IN A 206.184.139.16
+ IN A 206.184.139.18
+mail4 IN A 206.184.139.12
+ IN A 206.184.139.13
+ IN A 206.184.139.16
+ IN A 206.184.139.18
+NS1 IN A 209.24.149.41
+mail1 IN A 206.184.139.12
+ IN A 206.184.139.13
+ IN A 206.184.139.16
+ IN A 206.184.139.18
+NS2 IN A 209.157.102.11
+$ORIGIN WESTOL.com.
+NS IN A 63.93.137.4
+$ORIGIN ilovedomain.com.
+ns IN A 211.175.164.170
+$ORIGIN symquest.com.
+Quest-7 IN A 64.69.102.131
+$ORIGIN QUEST-NET.com.
+mail IN A 207.140.30.11
+NS2 IN A 207.140.30.13
+NS1 IN A 207.140.30.11
+$ORIGIN cavebear.com.
+p2 IN A 199.184.128.35
+npax IN A 192.203.17.71
+$ORIGIN cacheware.com.
+ns1 IN A 64.221.210.242
+$ORIGIN Algebra.com.
+ns3 IN A 216.254.54.22
+ns1 IN A 160.79.196.177
+NS5 IN A 208.233.99.161
+$ORIGIN gmcr.com.
+gateway1 IN A 12.34.108.130
+$ORIGIN YAHOO.com.
+NS1 IN A 204.71.200.33
+$ORIGIN EUROPE.YAHOO.com.
+NS3 IN A 217.12.4.71
+$ORIGIN DCX.YAHOO.com.
+NS5 IN A 216.32.74.10
+$ORIGIN GRANITECANYON.com.
+NS2 IN A 204.1.217.148
+NS1 IN A 205.166.226.38
+$ORIGIN costorf.com.
+localhost IN A 127.0.0.1
+www IN CNAME costorf.com.
+$ORIGIN PSG.com.
+RAIN IN A 147.28.0.34
+RIP IN A 147.28.0.39
+$ORIGIN vt.highmeadow.com.
+hm6 IN A 207.136.209.6
+$ORIGIN btinternet.com.
+DNS2 IN A 194.73.73.94
+DNS1 IN A 194.73.73.95
+$ORIGIN INTERNET-TOOLS.com.
+NS2 IN A 206.109.113.140
+NS IN A 208.239.1.2
+NS3 IN A 38.153.179.2
+$ORIGIN CADABRA.com.
+NS2 IN A 209.157.194.109
+NS IN A 209.143.240.148
+$ORIGIN SLOWMOE.com.
+NS2 IN A 137.118.8.50
+NS1 IN A 137.118.8.49
+$ORIGIN ZTNET.com.
+NS2 IN A 63.211.17.252
+NS1 IN A 63.211.17.251
+$ORIGIN HOTWIRED.com.
+NS2 IN A 209.185.151.6
+NS4 IN A 209.185.151.4
+NS1 IN A 216.32.228.8
+NS3 IN A 216.32.228.9
+$ORIGIN g-world.com.
+NS1 IN A 216.26.39.10
+$ORIGIN alcatrazmedia.com.
+ns1 IN A 167.160.132.2
+$ORIGIN MESSAGESECURE.com.
+KYNSE02 IN A 216.142.252.201
+KYNSE01 IN A 216.142.252.199
+$ORIGIN HAITIWORLD.com.
+APPSRV IN A 206.152.15.34
+NS IN A 206.152.15.33
+$ORIGIN NETSOL.com.
+NS2 IN A 198.17.208.71
+RS0 IN A 216.168.224.206
+NS3 IN A 216.168.224.201
+NS1 IN A 216.168.224.200
+$ORIGIN cmates.com.
+NS-AUTH2 IN A 208.23.213.3
+ns-auth1 IN A 208.23.213.2
+$ORIGIN skiinsurance.com.
+mail IN A 207.136.205.152
+$ORIGIN GH.com.
+AUSTIN IN A 196.3.64.1
+$ORIGIN DIGISERVE.com.
+NS2 IN A 204.91.84.216
+NS1 IN A 151.196.69.5
+$ORIGIN map.com.
+sgi1 IN A 204.71.19.20
+WORMHOLE IN A 204.71.19.10
+$ORIGIN SNS-UT.DEBIS.com.
+NS2 IN A 53.122.2.10
+$ORIGIN SNS-FELB.DEBIS.com.
+NS1 IN A 53.122.1.10
+$ORIGIN idx.com.
+seaipsvcs IN A 172.22.64.42
+BOSDOC IN A 198.114.171.109
+drawbridge IN A 204.165.241.2
+IDXNMS IN A 204.165.242.7
+idx IN A 198.114.171.160
+isdev IN A 198.181.234.9
+bvtipsvcs IN A 198.114.172.50
+bosdns IN A 198.114.171.109
+bvtsweeper IN A 198.181.234.69
+$ORIGIN VERITAS.com.
+NS IN A 204.177.156.38
+$ORIGIN BFG.com.
+gateway2 IN A 166.102.214.66
+aisvt IN MX 0 gateway2.bfg.com.
+GATEWAY IN A 131.187.253.2
+$ORIGIN sleepycat.com.
+abyssinian IN A 199.103.241.218
+$ORIGIN cisco.com.
+proxy6 IN A 203.41.198.245
+proxy9 IN A 192.135.250.71
+proxy1 IN A 192.31.7.88
+proxy2 IN A 192.31.7.89
+proxy3 IN A 192.31.7.90
+ns1 IN A 128.107.241.185
+NS2 IN A 192.135.250.69
+$ORIGIN TOAPLAN.com.
+www IN A 216.42.31.169
+$ORIGIN INTUIT.com.
+DNS1 IN A 208.157.255.4
+$ORIGIN REGEX.com.
+NS1 IN A 202.152.12.227
+$ORIGIN DEC.com.
+crl IN A 192.58.206.2
+ns IN A 204.123.2.42
+$ORIGIN PA.DEC.com.
+UUCP-GW-2 IN A 16.1.0.19
+UUCP-GW-1 IN A 16.1.0.18
+ IN A 204.123.2.18
+$ORIGIN LANDLORDS.com.
+NS IN A 63.64.164.68
+$ORIGIN hometownbands.com.
+www IN A 209.67.235.38
+$ORIGIN MSFT.AKADNS.com.
+Z6 IN A 207.229.152.20
+Z2 IN A 32.96.80.17
+Z4 IN A 208.148.96.220
+Z7 IN A 213.161.66.158
+Z3 IN A 63.215.198.67
+Z1 IN A 216.32.118.104
+$ORIGIN smuggs.com.
+mail IN A 209.67.230.71
+$ORIGIN OUTREMER.com.
+MANTA IN A 213.16.1.106
+$ORIGIN hns.com.
+HNS3 IN A 208.236.67.3
+$ORIGIN TRIVALLEY.com.
+NS3 IN A 206.25.132.30
+$ORIGIN AI-R.com.
+NS2 IN A 66.33.4.51
+NS1 IN A 66.33.0.143
+$ORIGIN ALCATEL.com.
+NS IN A 192.160.6.91
+PRIMARY IN A 192.160.6.90
+$ORIGIN GENDYN.com.
+NET2 IN A 204.60.171.9
+NET1 IN A 204.60.171.8
+$ORIGIN ONLINEPHOTOCONTEST.com.
+www IN A 64.85.86.152
+$ORIGIN performancediver.com.
+listserv IN A 216.34.185.155
+$ORIGIN rge.com.
+gw IN A 157.225.178.11
+$ORIGIN NS.AOL.com.
+DNS-02 IN A 205.188.157.232
+DNS-01 IN A 152.163.159.232
+$ORIGIN MANY-PATHS-ENERGY-ENHANCEMENT.com.
+www IN A 66.33.4.50
+$ORIGIN IS.CHRYSLER.com.
+FXCLPR02 IN A 204.189.94.37
+FXIOD01 IN A 204.189.94.70
+$ORIGIN TO.GD-ES.com.
+NS IN A 199.107.240.66
+$ORIGIN GNAC.com.
+ns2 IN A 209.182.195.77
+NS1 IN A 209.182.195.77
+$ORIGIN AKAMAI.com.
+YA IN A 204.178.118.68
+ACCESS IN A 4.17.143.9
+YB IN A 204.212.232.16
+YC IN A 209.246.46.48
+YD IN A 209.189.112.39
+YE IN A 192.215.168.18
+YF IN A 216.32.118.14
+YG IN A 204.178.110.35
+YH IN A 128.11.61.225
+$ORIGIN QUICKEN.com.
+DNS4 IN A 198.3.99.252
+DNS2 IN A 206.154.105.67
+news IN MX 10 mail1.emailpub.com.
+ IN MX 10 mail2.emailpub.com.
+ IN MX 10 mail3.emailpub.com.
+ IN MX 10 mail4.emailpub.com.
+ IN MX 10 mail5.emailpub.com.
+ IN MX 10 mail6.emailpub.com.
+ IN A 207.211.106.100
+DNS3 IN A 198.3.96.252
+DNS1 IN A 206.154.105.66
+$ORIGIN LUXNOC.com.
+NS4 IN A 195.206.104.201
+NS2 IN A 195.206.105.102
+NS0 IN A 195.206.105.1
+NS5 IN A 195.206.104.211
+NS3 IN A 195.206.104.1
+NS1 IN A 195.206.105.101
+$ORIGIN MAGIC-MOMENTS.com.
+NS1 IN A 195.224.53.80
+$ORIGIN ABAC.com.
+NS2 IN A 216.55.144.4
+NS1 IN A 216.55.128.4
+$ORIGIN GOTO.com.
+NS2 IN A 204.71.128.137
+NS1 IN A 206.132.152.241
+$ORIGIN WEBTRENDS.com.
+NS2 IN A 63.88.212.11
+NS1 IN A 63.88.212.10
+$ORIGIN hotmail.com.
+NS3 IN A 209.185.130.68
+NS1 IN A 216.200.206.140
+$ORIGIN MERCHANTWARE.com.
+NS2 IN A 209.170.142.35
+$ORIGIN MERCURYCENTER.com.
+cgi IN CNAME vh80167.vh8.infi.net.
+$ORIGIN CARIBSURF.com.
+COL2 IN A 205.214.192.202
+COL1 IN A 205.214.192.201
+$ORIGIN MAIL-LIST.com.
+zip IN MX 20 sluice.mail-list.com.
+ IN MX 20 pipeline.mail-list.com.
+ IN MX 20 transport.mail-list.com.
+ IN MX 50 swifty.mail-list.com.
+ IN MX 50 velocity.mail-list.com.
+ IN MX 50 brisk.mail-list.com.
+ IN MX 5 zip.mail-list.com.
+$ORIGIN NAVPOINT.com.
+south IN A 207.106.42.12
+north IN A 207.106.42.10
+NS2 IN A 207.106.42.12
+NS IN A 207.106.42.10
+$ORIGIN verisign-grs.com.
+ns2 IN A 198.41.3.108
+ns1 IN A 198.41.3.39
+$ORIGIN gdarm.com.
+bvt-ext IN A 166.19.32.42
+$ORIGIN REDHAT.com.
+NS1 IN A 216.148.218.250
+$ORIGIN SKYNETWEB.com.
+NS2 IN A 208.231.1.35
+NS1 IN A 208.231.1.34
+$ORIGIN COIL.com.
+BRONZE IN A 198.4.94.1
+$ORIGIN ZTX.COMPAQ.com.
+NS1-PUBLIC IN A 161.114.1.204
+$ORIGIN ZMA.COMPAQ.com.
+NS1-PUBLIC IN A 161.114.64.24
+$ORIGIN FOOL.com.
+NS2 IN A 208.51.76.222
+NS1 IN A 208.241.66.222
+$ORIGIN retro.com.
+www IN A 205.179.181.195
+gw IN A 205.179.181.194
+$ORIGIN NRSITE.com.
+NS5 IN A 208.178.169.4
+NS7 IN A 206.41.20.3
+NS3 IN A 199.172.144.20
+$ORIGIN jerusalem-mail.com.
+mail IN A 216.251.232.93
+$ORIGIN PAIR.com.
+ns3 IN A 209.68.1.15
+NS1 IN A 209.68.1.11
+$ORIGIN GLOBALDNS.com.
+NS1 IN A 206.253.214.11
+$ORIGIN tfm.com.
+mailhost IN A 192.231.224.11
+mtbaker IN A 192.231.224.2
+NS2 IN A 208.236.160.42
+NS1 IN A 209.83.142.82
+NS IN A 192.231.224.1
+$ORIGIN bock.com.
+NS2 IN A 64.30.29.4
+NS1 IN A 64.30.29.3
+$ORIGIN TARSUS.com.
+MAIL IN A 208.130.9.252
+BEAR IN A 208.130.9.248
+$ORIGIN NETANET.com.
+NS0 IN A 194.6.96.218
+ IN A 195.172.127.72
+NS1 IN A 194.6.96.218
+$ORIGIN SEANET.com.
+DNS2 IN A 199.181.164.2
+DNS3 IN A 199.181.164.3
+DNS1 IN A 199.181.164.1
+$ORIGIN INTERNETSHARE.com.
+NS1 IN A 63.207.108.53
+$ORIGIN ALTAVISTA.com.
+NS2 IN A 209.73.164.7
+NS3 IN A 209.73.176.204
+NS1 IN A 209.73.164.76
+$ORIGIN NOVELL.com.
+NS IN A 137.65.1.1
+$ORIGIN SAIPAN.com.
+NS2 IN A 202.128.28.2
+NS IN A 202.128.27.2
+$ORIGIN diebold.com.
+eliot IN A 204.151.249.21
+ness IN A 208.228.181.21
+$ORIGIN WonderWorks.com.
+mail IN A 192.203.206.67
+ice IN A 192.203.206.9
+$ORIGIN SIGNALZ.com.
+NS IN A 209.67.230.71
+$ORIGIN GW.tislabs.com.
+RELAY IN A 192.94.214.100
+$ORIGIN CAIS.com.
+NS IN A 205.177.10.10
+$ORIGIN tesserae.com.
+ns2 IN A 209.157.194.3
+NS IN A 209.157.194.2
+$ORIGIN NETPOLICY.com.
+MINION IN A 207.87.121.66
+$ORIGIN wirbel.com.
+enterprise IN A 194.231.54.2
+$ORIGIN fiberia.com.
+webmail IN A 216.55.147.2
+$ORIGIN BAYAREA.com.
+www IN CNAME vh80040.vh8.infi.net.
+$ORIGIN CONNACTIVITY.com.
+bparker IN A 206.34.200.200
+NS2 IN A 206.34.200.3
+CONNACTIVITY IN A 206.34.200.2
+$ORIGIN tifosi.com.
+BK IN A 208.58.189.13
+daytona IN A 192.104.156.3
+$ORIGIN bucksnet.com.
+gutenberg IN A 207.113.15.5
+$ORIGIN ivillage.com.
+NS2 IN A 209.185.162.16
+NS1 IN A 209.185.162.15
+$ORIGIN codelocal.com.
+ns1 IN A 216.15.192.130
+$ORIGIN NETFLIGHT.com.
+DNS IN A 207.88.32.2
+$ORIGIN MERCHANTWARE.CON.
+NS1 IN A 209.170.142.34
diff --git a/bin/tests/system/cacheclean/ns1/expire-test.db b/bin/tests/system/cacheclean/ns1/expire-test.db
new file mode 100644
index 0000000..8085543
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns1/expire-test.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA hostmaster.ns ns (
+ 2011072900
+ 600
+ 600
+ 1200
+ 3600
+ )
+ NS ns
+ns IN A 10.53.0.1
diff --git a/bin/tests/system/cacheclean/ns1/flushtest.db b/bin/tests/system/cacheclean/ns1/flushtest.db
new file mode 100644
index 0000000..ac6b408
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns1/flushtest.db
@@ -0,0 +1,44 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+$ORIGIN flushtest.example.
+@ IN SOA flushtest.example. ns.flushtest.example. (
+ 2011072900
+ 600
+ 600
+ 1200
+ 3600
+ )
+ NS ns
+ns IN A 10.53.0.1
+
+top1 IN TXT "text"
+second1.top1 IN TXT "text"
+third1.second1.top1 IN TXT "text"
+third2.second1.top1 IN TXT "text"
+second2.top1 IN TXT "text"
+second3.top1 IN TXT "text"
+
+; top2 node is omitted for testing with an empty nonterminal
+second1.top2 IN TXT "text"
+second2.top2 IN TXT "text"
+second3.top2 IN TXT "text"
+
+top3 IN TXT "text"
+second1.top3 IN TXT "text"
+third1.second1.top3 IN TXT "text"
+third2.second1.top3 IN TXT "text"
+; second2.top3 is omitted for testing with an empty nontermianl
+third1.second2.top3 IN TXT "text"
+third2.second2.top3 IN TXT "text"
+second3.top3 IN TXT "text"
+
diff --git a/bin/tests/system/cacheclean/ns1/named.args b/bin/tests/system/cacheclean/ns1/named.args
new file mode 100644
index 0000000..b7ce00d
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns1/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 1 -D cacheclean-ns1 -X named.lock -g -T maxcachesize=2097152
diff --git a/bin/tests/system/cacheclean/ns1/named.conf.in b/bin/tests/system/cacheclean/ns1/named.conf.in
new file mode 100644
index 0000000..98d2b28
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns1/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ dnssec-validation no;
+ notify yes;
+ check-integrity no;
+ minimal-responses no;
+};
+
+zone "." {
+ type primary;
+ file "example.db";
+};
+
+zone "flushtest.example" {
+ type primary;
+ file "flushtest.db";
+};
+
+zone "expire-test" {
+ type primary;
+ file "expire-test.db";
+};
diff --git a/bin/tests/system/cacheclean/ns2/named.args b/bin/tests/system/cacheclean/ns2/named.args
new file mode 100644
index 0000000..071016c
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns2/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 3 -D cacheclean-ns2 -X named.lock -g -T maxcachesize=2097152
diff --git a/bin/tests/system/cacheclean/ns2/named.conf.in b/bin/tests/system/cacheclean/ns2/named.conf.in
new file mode 100644
index 0000000..0b5cd29
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns2/named.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ notify yes;
+ disable-empty-zone 127.IN-ADDR.ARPA;
+ recursion yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "flushtest.example" {
+ type forward;
+ forwarders { 10.53.0.1; };
+};
+
+zone "expire-test" {
+ type secondary;
+ primaries { 10.53.0.1; };
+};
diff --git a/bin/tests/system/cacheclean/setup.sh b/bin/tests/system/cacheclean/setup.sh
new file mode 100644
index 0000000..6929ec5
--- /dev/null
+++ b/bin/tests/system/cacheclean/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
diff --git a/bin/tests/system/cacheclean/tests.sh b/bin/tests/system/cacheclean/tests.sh
new file mode 100755
index 0000000..387ce86
--- /dev/null
+++ b/bin/tests/system/cacheclean/tests.sh
@@ -0,0 +1,269 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+RNDCOPTS="-c ../common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT}"
+DIGOPTS="+nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm \
+ +nostat @10.53.0.2 -p ${PORT}"
+
+# fill the cache with nodes from flushtest.example zone
+load_cache () {
+ # empty all existing cache data
+ $RNDC $RNDCOPTS flush
+
+ # load the positive cache entries
+ $DIG $DIGOPTS -f - << EOF > /dev/null 2>&1
+txt top1.flushtest.example
+txt second1.top1.flushtest.example
+txt third1.second1.top1.flushtest.example
+txt third2.second1.top1.flushtest.example
+txt second2.top1.flushtest.example
+txt second3.top1.flushtest.example
+txt second1.top2.flushtest.example
+txt second2.top2.flushtest.example
+txt second3.top2.flushtest.example
+txt top3.flushtest.example
+txt second1.top3.flushtest.example
+txt third1.second1.top3.flushtest.example
+txt third2.second1.top3.flushtest.example
+txt third1.second2.top3.flushtest.example
+txt third2.second2.top3.flushtest.example
+txt second3.top3.flushtest.example
+EOF
+
+ # load the negative cache entries
+ # nxrrset:
+ $DIG $DIGOPTS a third1.second1.top1.flushtest.example > /dev/null
+ # nxdomain:
+ $DIG $DIGOPTS txt top4.flushtest.example > /dev/null
+ # empty nonterminal:
+ $DIG $DIGOPTS txt second2.top3.flushtest.example > /dev/null
+
+ # sleep 2 seconds ensure the TTLs will be lower on cached data
+ sleep 2
+}
+
+dump_cache () {
+ rndc_dumpdb ns2 -cache _default
+}
+
+clear_cache () {
+ $RNDC $RNDCOPTS flush
+}
+
+in_cache () {
+ ttl=$($DIG $DIGOPTS "$@" | awk '{print $2}')
+ [ -z "$ttl" ] && {
+ ttl=$($DIG $DIGOPTS +noanswer +auth "$@" | awk '{print $2}')
+ [ "$ttl" -ge 3599 ] && return 1
+ return 0
+ }
+ [ "$ttl" -ge 3599 ] && return 1
+ return 0
+}
+
+# Extract records at and below name "$1" from the cache dump in file "$2".
+filter_tree () {
+ tree="$1"
+ file="$2"
+ perl -n -e '
+ next if /^;/;
+ if (/'"$tree"'/ || (/^\t/ && $print)) {
+ $print = 1;
+ } else {
+ $print = 0;
+ }
+ print if $print;
+ ' "$file"
+}
+
+n=$((n + 1))
+echo_i "check correctness of routine cache cleaning ($n)"
+$DIG $DIGOPTS +tcp +keepopen -b 10.53.0.7 -f dig.batch > dig.out.ns2 || status=1
+
+digcomp --lc dig.out.ns2 knowngood.dig.out || status=1
+
+n=$((n + 1))
+echo_i "only one tcp socket was used ($n)"
+tcpclients=$(awk '$3 == "client" && $5 ~ /10.53.0.7#[0-9]*:/ {print $5}' ns2/named.run | sort | uniq -c | wc -l)
+
+test $tcpclients -eq 1 || { status=1; echo_i "failed"; }
+
+n=$((n + 1))
+echo_i "reset and check that records are correctly cached initially ($n)"
+ret=0
+load_cache
+dump_cache
+nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | grep -E '(TXT|ANY)' | wc -l)
+[ $nrecords -eq 18 ] || { ret=1; echo_i "found $nrecords records expected 18"; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check flushing of the full cache ($n)"
+ret=0
+clear_cache
+dump_cache
+nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | wc -l)
+[ $nrecords -eq 0 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check flushing of individual nodes (interior node) ($n)"
+ret=0
+clear_cache
+load_cache
+# interior node
+in_cache txt top1.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushname top1.flushtest.example
+in_cache txt top1.flushtest.example && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check flushing of individual nodes (leaf node, under the interior node) ($n)"
+ret=0
+# leaf node, under the interior node (should still exist)
+in_cache txt third2.second1.top1.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushname third2.second1.top1.flushtest.example
+in_cache txt third2.second1.top1.flushtest.example && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check flushing of individual nodes (another leaf node, with both positive and negative cache entries) ($n)"
+ret=0
+# another leaf node, with both positive and negative cache entries
+in_cache a third1.second1.top1.flushtest.example || ret=1
+in_cache txt third1.second1.top1.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushname third1.second1.top1.flushtest.example
+in_cache a third1.second1.top1.flushtest.example && ret=1
+in_cache txt third1.second1.top1.flushtest.example && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check flushing a nonexistent name ($n)"
+ret=0
+$RNDC $RNDCOPTS flushname fake.flushtest.example || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check flushing of namespaces ($n)"
+ret=0
+clear_cache
+load_cache
+# flushing leaf node should leave the interior node:
+in_cache txt third1.second1.top1.flushtest.example || ret=1
+in_cache txt top1.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushtree third1.second1.top1.flushtest.example
+in_cache txt third1.second1.top1.flushtest.example && ret=1
+in_cache txt top1.flushtest.example || ret=1
+in_cache txt second1.top1.flushtest.example || ret=1
+in_cache txt third2.second1.top1.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushtree second1.top1.flushtest.example
+in_cache txt top1.flushtest.example || ret=1
+in_cache txt second1.top1.flushtest.example && ret=1
+in_cache txt third2.second1.top1.flushtest.example && ret=1
+
+# flushing from an empty node should still remove all its children
+in_cache txt second1.top2.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushtree top2.flushtest.example
+in_cache txt second1.top2.flushtest.example && ret=1
+in_cache txt second2.top2.flushtest.example && ret=1
+in_cache txt second3.top2.flushtest.example && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check flushing a nonexistent namespace ($n)"
+ret=0
+$RNDC $RNDCOPTS flushtree fake.flushtest.example || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check the number of cached records remaining ($n)"
+ret=0
+dump_cache
+nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | grep -v '^;' | grep -E '(TXT|ANY)' | wc -l)
+[ $nrecords -eq 17 ] || { ret=1; echo_i "found $nrecords records expected 17"; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check the check that flushname of a partial match works ($n)"
+ret=0
+in_cache txt second2.top1.flushtest.example || ret=1
+$RNDC $RNDCOPTS flushtree example
+in_cache txt second2.top1.flushtest.example && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check the number of cached records remaining ($n)"
+ret=0
+dump_cache
+nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | grep -E '(TXT|ANY)' | wc -l)
+[ $nrecords -eq 1 ] || { ret=1; echo_i "found $nrecords records expected 1"; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check flushtree clears adb correctly ($n)"
+ret=0
+load_cache
+dump_cache
+mv ns2/named_dump.db.test$n ns2/named_dump.db.test$n.a
+sed -n '/plain success\/timeout/,/Unassociated entries/p' \
+ ns2/named_dump.db.test$n.a > sed.out.$n.a
+grep 'plain success/timeout' sed.out.$n.a > /dev/null 2>&1 || ret=1
+grep 'Unassociated entries' sed.out.$n.a > /dev/null 2>&1 || ret=1
+grep 'ns.flushtest.example' sed.out.$n.a > /dev/null 2>&1 || ret=1
+$RNDC $RNDCOPTS flushtree flushtest.example || ret=1
+dump_cache
+mv ns2/named_dump.db.test$n ns2/named_dump.db.test$n.b
+sed -n '/plain success\/timeout/,/Unassociated entries/p' \
+ ns2/named_dump.db.test$n.b > sed.out.$n.b
+grep 'plain success/timeout' sed.out.$n.b > /dev/null 2>&1 || ret=1
+grep 'Unassociated entries' sed.out.$n.b > /dev/null 2>&1 || ret=1
+grep 'ns.flushtest.example' sed.out.$n.b > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check expire option returned from primary zone ($n)"
+ret=0
+$DIG @10.53.0.1 -p ${PORT} +expire soa expire-test > dig.out.expire || ret=1
+grep EXPIRE: dig.out.expire > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check expire option returned from secondary zone ($n)"
+ret=0
+$DIG @10.53.0.2 -p ${PORT} +expire soa expire-test > dig.out.expire || ret=1
+grep EXPIRE: dig.out.expire > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/cacheclean/tests_sh_cacheclean.py b/bin/tests/system/cacheclean/tests_sh_cacheclean.py
new file mode 100644
index 0000000..e47157e
--- /dev/null
+++ b/bin/tests/system/cacheclean/tests_sh_cacheclean.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_cacheclean(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/case/clean.sh b/bin/tests/system/case/clean.sh
new file mode 100644
index 0000000..2c7bf97
--- /dev/null
+++ b/bin/tests/system/case/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.ns*.test*
+rm -f ns*/named.conf
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns1/dynamic.db
+rm -f ns1/dynamic.db.jnl
+rm -f ns2/dynamic.bk
+rm -f ns2/dynamic.bk.jnl
+rm -f ns2/example.bk
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/case/dynamic.good b/bin/tests/system/case/dynamic.good
new file mode 100644
index 0000000..66f8afd
--- /dev/null
+++ b/bin/tests/system/case/dynamic.good
@@ -0,0 +1,6 @@
+DyNaMiC. 300 IN SOA mname1. . 2000042407 20 20 1814400 3600
+DyNaMiC. 300 IN NS ns1.DYNAMIC.
+DynamiC. 300 IN MX 0 mail.eXaMpLe.
+mAiL.DynamiC. 300 IN A 10.53.0.1
+ns1.DYNAMIC. 300 IN A 10.53.0.1
+DyNaMiC. 300 IN SOA mname1. . 2000042407 20 20 1814400 3600
diff --git a/bin/tests/system/case/ns1/dynamic.db.in b/bin/tests/system/case/ns1/dynamic.db.in
new file mode 100644
index 0000000..b39b519
--- /dev/null
+++ b/bin/tests/system/case/ns1/dynamic.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+$ORIGIN DyNaMiC.
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+$ORIGIN DYNAMIC.
+ NS ns1
+ns1 A 10.53.0.1
+$ORIGIN DynamiC.
+@ MX 0 mail.eXaMpLe.
+mAiL A 10.53.0.1
diff --git a/bin/tests/system/case/ns1/example.db b/bin/tests/system/case/ns1/example.db
new file mode 100644
index 0000000..b58414c
--- /dev/null
+++ b/bin/tests/system/case/ns1/example.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns1
+ns1 A 10.53.0.1
+@ MX 0 mail.eXaMpLe.
+mAiL A 10.53.0.1
diff --git a/bin/tests/system/case/ns1/named.conf.in b/bin/tests/system/case/ns1/named.conf.in
new file mode 100644
index 0000000..fa0d808
--- /dev/null
+++ b/bin/tests/system/case/ns1/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+ minimal-responses no;
+ dnssec-validation no;
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ also-notify { 10.53.0.2; };
+};
+
+zone "dynamic" {
+ type primary;
+ file "dynamic.db";
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+};
diff --git a/bin/tests/system/case/ns2/named.conf.in b/bin/tests/system/case/ns2/named.conf.in
new file mode 100644
index 0000000..fe0b52c
--- /dev/null
+++ b/bin/tests/system/case/ns2/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+ no-case-compress { 10.53.0.2; };
+ minimal-responses no;
+ dnssec-validation no;
+};
+
+zone "example" {
+ type secondary;
+ file "example.bk";
+ primaries { 10.53.0.1; };
+};
+
+zone "dynamic" {
+ type secondary;
+ file "dynamic.bk";
+ primaries { 10.53.0.1; };
+};
diff --git a/bin/tests/system/case/postns1.good b/bin/tests/system/case/postns1.good
new file mode 100644
index 0000000..fcb3f9c
--- /dev/null
+++ b/bin/tests/system/case/postns1.good
@@ -0,0 +1,6 @@
+dYNAMIc. 300 IN SOA mname1. . 2000042409 20 20 1814400 3600
+DyNaMiC. 300 IN NS ns1.DYNAMIC.
+DynamiC. 300 IN MX 0 mail.eXaMpLe.
+mAiL.DynamiC. 300 IN A 10.53.0.1
+Ns1.DyNaMIC. 300 IN A 10.53.0.1
+dYNAMIc. 300 IN SOA mname1. . 2000042409 20 20 1814400 3600
diff --git a/bin/tests/system/case/postupdate.good b/bin/tests/system/case/postupdate.good
new file mode 100644
index 0000000..7755928
--- /dev/null
+++ b/bin/tests/system/case/postupdate.good
@@ -0,0 +1,6 @@
+dYNAMIc. 300 IN SOA mname1. . 2000042408 20 20 1814400 3600
+DyNaMiC. 300 IN NS ns1.DYNAMIC.
+DynamiC. 300 IN MX 0 mail.eXaMpLe.
+mAiL.DynamiC. 300 IN A 10.53.0.1
+ns1.DYNAMIC. 300 IN A 10.53.0.1
+dYNAMIc. 300 IN SOA mname1. . 2000042408 20 20 1814400 3600
diff --git a/bin/tests/system/case/setup.sh b/bin/tests/system/case/setup.sh
new file mode 100644
index 0000000..c9de4ee
--- /dev/null
+++ b/bin/tests/system/case/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+cp -f ns1/dynamic.db.in ns1/dynamic.db
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
diff --git a/bin/tests/system/case/tests.sh b/bin/tests/system/case/tests.sh
new file mode 100644
index 0000000..6b40574
--- /dev/null
+++ b/bin/tests/system/case/tests.sh
@@ -0,0 +1,151 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+
+wait_for_serial() (
+ $DIG $DIGOPTS "@$1" "$2" SOA > "$4"
+ serial=$(awk '$4 == "SOA" { print $7 }' "$4")
+ [ "$3" -eq "${serial:--1}" ]
+)
+
+status=0
+n=0
+
+n=$((n + 1))
+echo_i "waiting for zone transfer to complete ($n)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS soa example. @10.53.0.2 > dig.ns2.test$n || true
+ grep SOA dig.ns2.test$n > /dev/null && break
+ sleep 1
+done
+for i in 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS soa dynamic. @10.53.0.2 > dig.ns2.test$n || true
+ grep SOA dig.ns2.test$n > /dev/null && break
+ sleep 1
+done
+
+n=$((n + 1))
+echo_i "testing case preserving responses - no acl ($n)"
+ret=0
+$DIG $DIGOPTS mx example. @10.53.0.1 > dig.ns1.test$n || ret=1
+grep "0.mail.eXaMpLe" dig.ns1.test$n > /dev/null || ret=1
+grep "mAiL.example" dig.ns1.test$n > /dev/null || ret=1
+test $ret -eq 0 || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing no-case-compress acl '{ 10.53.0.2; }' ($n)"
+ret=0
+
+# check that we preserve zone case for non-matching query (10.53.0.1)
+$DIG $DIGOPTS mx example. -b 10.53.0.1 @10.53.0.1 > dig.ns1.test$n || ret=1
+grep "0.mail.eXaMpLe" dig.ns1.test$n > /dev/null || ret=1
+grep "mAiL.example" dig.ns1.test$n > /dev/null || ret=1
+
+# check that we don't preserve zone case for match (10.53.0.2)
+$DIG $DIGOPTS mx example. -b 10.53.0.2 @10.53.0.2 > dig.ns2.test$n || ret=1
+grep "0.mail.example" dig.ns2.test$n > /dev/null || ret=1
+grep "mail.example" dig.ns2.test$n > /dev/null || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing load of dynamic zone with various \$ORIGIN values ($n)"
+ret=0
+$DIG $DIGOPTS axfr dynamic @10.53.0.1 > dig.ns1.test$n || ret=1
+digcomp dig.ns1.test$n dynamic.good || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "transfer of dynamic zone with various \$ORIGIN values ($n)"
+ret=0
+$DIG $DIGOPTS axfr dynamic @10.53.0.2 > dig.ns2.test$n || ret=1
+digcomp dig.ns2.test$n dynamic.good || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "change SOA owner case via update ($n)"
+$NSUPDATE << EOF
+server 10.53.0.1 ${PORT}
+zone dynamic
+update add dYNAMIc 0 SOA mname1. . 2000042408 20 20 1814400 3600
+send
+EOF
+$DIG $DIGOPTS axfr dynamic @10.53.0.1 > dig.ns1.test$n || ret=1
+digcomp dig.ns1.test$n postupdate.good || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+ret=0
+echo_i "wait for zone to transfer ($n)"
+retry_quiet 20 wait_for_serial 10.53.0.2 dynamic 2000042408 dig.ns2.test$n || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check SOA owner case is transferred to secondary ($n)"
+ret=0
+$DIG $DIGOPTS axfr dynamic @10.53.0.2 > dig.ns2.test$n || ret=1
+digcomp dig.ns2.test$n postupdate.good || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=$((status + ret))
+
+#update delete Ns1.DyNaMIC. 300 IN A 10.53.0.1
+n=$((n + 1))
+echo_i "change A record owner case via update ($n)"
+$NSUPDATE << EOF
+server 10.53.0.1 ${PORT}
+zone dynamic
+update add Ns1.DyNaMIC. 300 IN A 10.53.0.1
+send
+EOF
+$DIG $DIGOPTS axfr dynamic @10.53.0.1 > dig.ns1.test$n || ret=1
+digcomp dig.ns1.test$n postns1.good || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+ret=0
+echo_i "wait for zone to transfer ($n)"
+retry_quiet 20 wait_for_serial 10.53.0.2 dynamic 2000042409 dig.ns2.test$n || ret=1
+
+test $ret -eq 0 || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check A owner case is transferred to secondary ($n)"
+ret=0
+$DIG $DIGOPTS axfr dynamic @10.53.0.2 > dig.ns2.test$n || ret=1
+digcomp dig.ns2.test$n postns1.good || ret=1
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/case/tests_sh_case.py b/bin/tests/system/case/tests_sh_case.py
new file mode 100644
index 0000000..bbe94d3
--- /dev/null
+++ b/bin/tests/system/case/tests_sh_case.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_case(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/catz/clean.sh b/bin/tests/system/catz/clean.sh
new file mode 100644
index 0000000..21dbc75
--- /dev/null
+++ b/bin/tests/system/catz/clean.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.*
+rm -f ns*/*.jnl
+rm -f ns*/*.mkeys
+rm -f ns*/*.nzd ns*/*.nzd-lock
+rm -f ns*/*.nzf
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.conf
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/named.run.prev
+rm -f ns1/*dom*example.db
+rm -f ns1/tls1.example.db
+rm -f ns2/__catz__*db
+rm -f ns2/catalog-bad*.db
+rm -f ns2/named.conf.tmp
+rm -f ns3/dom2.example.db ns3/dom13.example.db ns3/dom14.example.db ns3/dom17.example.db ns3/dom18.example.db
+rm -f ns4/__catz__*db
+rm -f ns4/catalog-self.example.db
+rm -f ns[123]/catalog[1234].example.db
+rm -f ns[14]/catalog-tls.example.db
+rm -f nsupdate.out.*
+rm -f wait_for_message.*
+rm -rf ns2/zonedir
diff --git a/bin/tests/system/catz/ns1/catalog-bad1.example.db b/bin/tests/system/catz/ns1/catalog-bad1.example.db
new file mode 100644
index 0000000..b8402de
--- /dev/null
+++ b/bin/tests/system/catz/ns1/catalog-bad1.example.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 IN NS invalid.
diff --git a/bin/tests/system/catz/ns1/catalog-bad2.example.db b/bin/tests/system/catz/ns1/catalog-bad2.example.db
new file mode 100644
index 0000000..06b9121
--- /dev/null
+++ b/bin/tests/system/catz/ns1/catalog-bad2.example.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 IN NS invalid.
+version IN TXT "99"
diff --git a/bin/tests/system/catz/ns1/catalog-bad3.example.db b/bin/tests/system/catz/ns1/catalog-bad3.example.db
new file mode 100644
index 0000000..0116697
--- /dev/null
+++ b/bin/tests/system/catz/ns1/catalog-bad3.example.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 IN NS invalid.
+version IN TXT "1"
+version IN TXT "2"
diff --git a/bin/tests/system/catz/ns1/catalog-bad4.example.db b/bin/tests/system/catz/ns1/catalog-bad4.example.db
new file mode 100644
index 0000000..d04bab3
--- /dev/null
+++ b/bin/tests/system/catz/ns1/catalog-bad4.example.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 IN NS invalid.
+version IN A 10.53.0.1
diff --git a/bin/tests/system/catz/ns1/catalog-bad5.example.db b/bin/tests/system/catz/ns1/catalog-bad5.example.db
new file mode 100644
index 0000000..b014d0a
--- /dev/null
+++ b/bin/tests/system/catz/ns1/catalog-bad5.example.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 CH NS invalid.
+version CH TXT "2"
diff --git a/bin/tests/system/catz/ns1/catalog.example.db.in b/bin/tests/system/catz/ns1/catalog.example.db.in
new file mode 100644
index 0000000..6b52947
--- /dev/null
+++ b/bin/tests/system/catz/ns1/catalog.example.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 IN NS invalid.
+version IN TXT "2"
diff --git a/bin/tests/system/catz/ns1/named.conf.in b/bin/tests/system/catz/ns1/named.conf.in
new file mode 100644
index 0000000..bcfc68a
--- /dev/null
+++ b/bin/tests/system/catz/ns1/named.conf.in
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ tls-port @TLSPORT@;
+ allow-new-zones yes;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on port @EXTRAPORT1@ { 10.53.0.1; };
+ listen-on tls ephemeral { 10.53.0.1; };
+ listen-on-v6 { none; };
+ notify no;
+ recursion no;
+ allow-transfer { any; };
+ dnssec-validation no;
+};
+
+view "default" {
+
+ zone "catalog1.example" {
+ type primary;
+ file "catalog1.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+ };
+
+ /* catalog2 is provided by the ns3 primary */
+
+ zone "catalog3.example" {
+ type primary;
+ file "catalog3.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+ };
+
+ zone "catalog4.example" {
+ type primary;
+ file "catalog4.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+ };
+
+ /* catalog5 is missing on purpose */
+
+ # No "version" property
+ zone "catalog-bad1.example" {
+ type primary;
+ file "catalog-bad1.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+ };
+
+ # Unsupported "version" property
+ zone "catalog-bad2.example" {
+ type primary;
+ file "catalog-bad2.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+ };
+
+ # Two RRs in TXT RRset for the "version" property
+ zone "catalog-bad3.example" {
+ type primary;
+ file "catalog-bad3.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+ };
+
+ # Type A "version" property
+ zone "catalog-bad4.example" {
+ type primary;
+ file "catalog-bad4.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+ };
+
+ # A catalog zone that requires TLS to be used
+ zone "catalog-tls.example" {
+ type primary;
+ file "catalog-tls.example.db";
+ allow-transfer transport tls { key tsig_key; };
+ allow-update { any; };
+ also-notify { 10.53.0.4; };
+ notify explicit;
+ };
+};
+
+view "ch" ch {
+
+ # Non-IN class catalog zone
+ zone "catalog-bad5.example" ch {
+ type primary;
+ file "catalog-bad5.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+ };
+
+};
+
+key tsig_key. {
+ secret "LSAnCU+Z";
+ algorithm @DEFAULT_HMAC@;
+};
+
+key next_key. {
+ secret "LaAnCU+Z";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/catz/ns2/dom-existing.example.db b/bin/tests/system/catz/ns2/dom-existing.example.db
new file mode 100644
index 0000000..b8402de
--- /dev/null
+++ b/bin/tests/system/catz/ns2/dom-existing.example.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 IN NS invalid.
diff --git a/bin/tests/system/catz/ns2/named1.conf.in b/bin/tests/system/catz/ns2/named1.conf.in
new file mode 100644
index 0000000..3169abb
--- /dev/null
+++ b/bin/tests/system/catz/ns2/named1.conf.in
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ notify no;
+ recursion no;
+ serial-query-rate 100;
+ dnssec-validation no;
+};
+
+/*
+ * The comment lines starting with "#Tn" markers below are designed to be
+ * uncommented by "tests.sh" when running the tests to perform some of required
+ * tests which need ns2 reconfgiuration.
+ */
+
+view "default" {
+
+ catalog-zones {
+ zone "catalog1.example"
+ default-masters { 10.53.0.1; }
+ in-memory no
+ zone-directory "zonedir";
+ zone "catalog2.example"
+ default-primaries { 10.53.0.1 port @EXTRAPORT1@; }
+ in-memory yes;
+ zone "catalog3.example"
+ default-masters { 10.53.0.1; }
+ zone-directory "nonexistent";
+#T1 zone "catalog4.example"
+#T1 default-masters { 10.53.0.1; };
+#T2 zone "catalog5.example"
+#T2 default-primaries { 10.53.0.1; };
+ zone "catalog-bad1.example"
+ default-masters { 10.53.0.1; }
+ in-memory yes;
+ zone "catalog-bad2.example"
+ default-masters { 10.53.0.1; }
+ in-memory yes;
+ zone "catalog-bad3.example"
+ default-masters { 10.53.0.1; }
+ in-memory yes;
+ zone "catalog-bad4.example"
+ default-masters { 10.53.0.1; }
+ in-memory yes;
+ };
+
+ # A faulty dlz configuration to check if named and catz survive a certain class
+ # of failed configuration attempts (see GL #3060).
+ # We use "dlz" because the dlz processing code is located in an ideal place in
+ # the view configuration function for the test to cover the view reverting code.
+#T3 dlz "bad-dlz" {
+#T3 database "dlopen bad-dlz.so example.org";
+#T3 };
+
+ zone "dom-existing.example" {
+ type primary;
+ file "dom-existing.example.db";
+ };
+
+ zone "dom-existing-forward.example" {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.1; };
+ };
+
+ zone "dom-existing-forward-off.example" {
+ type forward;
+ forward only;
+ forwarders { };
+ };
+
+ zone "catalog1.example" {
+ type secondary;
+ file "catalog1.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ zone "catalog2.example" {
+ type secondary;
+ file "catalog2.example.db";
+ primaries { 10.53.0.3; };
+ };
+
+ zone "catalog3.example" {
+ type secondary;
+ file "catalog3.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ zone "catalog4.example" {
+ type secondary;
+ file "catalog4.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ # When the following zone configuration is enabled, "dom3.example" should
+ # already exist as a member of "catalog1.example", and named should be able
+ # to deal with that situation (see GL #3911). Make sure that this duplicate
+ # zone comes after the the "catalog1.example" zone in the configuration file.
+#T4 zone "dom3.example" {
+#T4 type secondary;
+#T4 file "dom2.example.db";
+#T4 };
+
+ # No "version" property
+ zone "catalog-bad1.example" {
+ type secondary;
+ file "catalog-bad1.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ # Unsupported "version" property
+ zone "catalog-bad2.example" {
+ type secondary;
+ file "catalog-bad2.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ # Two RRs in TXT RRset for the "version" property
+ zone "catalog-bad3.example" {
+ type secondary;
+ file "catalog-bad3.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ # Type A "version" property
+ zone "catalog-bad4.example" {
+ type secondary;
+ file "catalog-bad4.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+};
+
+view "ch" ch {
+
+ catalog-zones {
+ zone "catalog-bad5.example"
+ default-masters { 10.53.0.1; }
+ in-memory yes;
+ };
+
+ # Non-IN class catalog zone
+ zone "catalog-bad5.example" ch {
+ type secondary;
+ file "catalog-bad5.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+};
+
+key tsig_key. {
+ secret "LSAnCU+Z";
+ algorithm @DEFAULT_HMAC@;
+};
+
+key next_key. {
+ secret "LaAnCU+Z";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/catz/ns2/named2.conf.in b/bin/tests/system/catz/ns2/named2.conf.in
new file mode 100644
index 0000000..b5be974
--- /dev/null
+++ b/bin/tests/system/catz/ns2/named2.conf.in
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ notify no;
+ recursion no;
+ serial-query-rate 100;
+ dnssec-validation no;
+};
+
+view "default" {
+
+ # Removed catalog-zone option, otherwise this is
+ # identical to named1.conf.in
+
+ zone "dom-existing.example" {
+ type primary;
+ file "dom-existing.example.db";
+ };
+
+ zone "dom-existing-forward.example" {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.1; };
+ };
+
+ zone "dom-existing-forward-off.example" {
+ type forward;
+ forward only;
+ forwarders { };
+ };
+
+ zone "catalog1.example" {
+ type secondary;
+ file "catalog1.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ zone "catalog2.example" {
+ type secondary;
+ file "catalog2.example.db";
+ primaries { 10.53.0.3; };
+ };
+
+ zone "catalog3.example" {
+ type secondary;
+ file "catalog3.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ zone "catalog4.example" {
+ type secondary;
+ file "catalog4.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ # No "version" property
+ zone "catalog-bad1.example" {
+ type secondary;
+ file "catalog-bad1.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ # Unsupported "version" property
+ zone "catalog-bad2.example" {
+ type secondary;
+ file "catalog-bad2.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ # Two RRs in TXT RRset for the "version" property
+ zone "catalog-bad3.example" {
+ type secondary;
+ file "catalog-bad3.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+ # Type A "version" property
+ zone "catalog-bad4.example" {
+ type secondary;
+ file "catalog-bad4.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+};
+
+view "ch" ch {
+
+ # Removed catalog-zone option, otherwise this is
+ # identical to named1.conf.in
+
+ # Non-IN class catalog zone
+ zone "catalog-bad5.example" ch {
+ type secondary;
+ file "catalog-bad5.example.db";
+ primaries { 10.53.0.1; };
+ };
+
+};
+
+key tsig_key. {
+ secret "LSAnCU+Z";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/catz/ns3/catalog.example.db.in b/bin/tests/system/catz/ns3/catalog.example.db.in
new file mode 100644
index 0000000..eccb4f1
--- /dev/null
+++ b/bin/tests/system/catz/ns3/catalog.example.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA . . 2670950424 86400 3600 86400 3600
+@ 3600 IN NS invalid.
+version IN TXT "1"
diff --git a/bin/tests/system/catz/ns3/dom5.example.db b/bin/tests/system/catz/ns3/dom5.example.db
new file mode 100644
index 0000000..5779aaf
--- /dev/null
+++ b/bin/tests/system/catz/ns3/dom5.example.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 IN SOA . . 1 3600 3600 3600 3600
+@ IN NS invalid.
diff --git a/bin/tests/system/catz/ns3/dom6.example.db b/bin/tests/system/catz/ns3/dom6.example.db
new file mode 100644
index 0000000..5779aaf
--- /dev/null
+++ b/bin/tests/system/catz/ns3/dom6.example.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 IN SOA . . 1 3600 3600 3600 3600
+@ IN NS invalid.
diff --git a/bin/tests/system/catz/ns3/named.conf.in b/bin/tests/system/catz/ns3/named.conf.in
new file mode 100644
index 0000000..fb82379
--- /dev/null
+++ b/bin/tests/system/catz/ns3/named.conf.in
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ allow-new-zones yes;
+ pid-file "named.pid";
+ provide-ixfr no;
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::3; };
+ notify no;
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "catalog2.example" {
+ type primary;
+ file "catalog2.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+};
+
+zone "dom5.example" {
+ type primary;
+ file "dom5.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ notify explicit;
+};
+
+zone "dom6.example" {
+ type primary;
+ file "dom6.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ notify explicit;
+};
diff --git a/bin/tests/system/catz/ns4/catalog.example.db.in b/bin/tests/system/catz/ns4/catalog.example.db.in
new file mode 100644
index 0000000..a0bab0d
--- /dev/null
+++ b/bin/tests/system/catz/ns4/catalog.example.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 IN NS invalid.
+version IN TXT "1"
diff --git a/bin/tests/system/catz/ns4/named.conf.in b/bin/tests/system/catz/ns4/named.conf.in
new file mode 100644
index 0000000..2f43c25
--- /dev/null
+++ b/bin/tests/system/catz/ns4/named.conf.in
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ tls-port @TLSPORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { fd92:7065:b8e:ffff::4; };
+ notify no;
+ notify-delay 0;
+ recursion no;
+ serial-query-rate 100;
+ ixfr-from-differences yes; // GL #3777
+ dnssec-validation no;
+
+ catalog-zones {
+ zone "catalog-tls.example"
+ min-update-interval 1s
+ default-primaries { 10.53.0.1 key tsig_key tls ephemeral; };
+ zone "catalog-self.example"
+ min-update-interval 1s
+ default-primaries { 10.53.0.4; };
+ };
+};
+
+zone "catalog-tls.example" {
+ type secondary;
+ file "catalog-tls.example.db";
+ primaries { 10.53.0.1 key tsig_key tls ephemeral; };
+};
+
+zone "catalog-self.example" {
+ type primary;
+ file "catalog-self.example.db";
+ notify explicit;
+};
+
+key tsig_key. {
+ secret "LSAnCU+Z";
+ algorithm @DEFAULT_HMAC@;
+};
+
+key next_key. {
+ secret "LaAnCU+Z";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/catz/setup.sh b/bin/tests/system/catz/setup.sh
new file mode 100644
index 0000000..eb2e53b
--- /dev/null
+++ b/bin/tests/system/catz/setup.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named1.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
+
+cp -f ns1/catalog.example.db.in ns1/catalog1.example.db
+cp -f ns3/catalog.example.db.in ns3/catalog2.example.db
+cp -f ns1/catalog.example.db.in ns1/catalog3.example.db
+cp -f ns1/catalog.example.db.in ns1/catalog4.example.db
+cp -f ns1/catalog.example.db.in ns1/catalog-tls.example.db
+cp -f ns4/catalog.example.db.in ns4/catalog-self.example.db
+
+mkdir -p ns2/zonedir
diff --git a/bin/tests/system/catz/tests.sh b/bin/tests/system/catz/tests.sh
new file mode 100644
index 0000000..4965e20
--- /dev/null
+++ b/bin/tests/system/catz/tests.sh
@@ -0,0 +1,2658 @@
+#!/bin/sh -x
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+dig_with_opts() {
+ "$DIG" -p "${PORT}" "$@"
+}
+
+rndccmd() (
+ "$RNDC" -c ../common/rndc.conf -p "${CONTROLPORT}" -s "$@"
+)
+
+_wait_for_message() (
+ nextpartpeek "$1" > wait_for_message.$n
+ grep -F "$2" wait_for_message.$n >/dev/null
+)
+
+wait_for_message() (
+ retry_quiet 20 _wait_for_message "$@"
+)
+
+_wait_for_rcode() (
+ rcode="$1"
+ qtype="$2"
+ ns="$3"
+ qname="$4"
+ file="$5"
+ shift 5
+ dig_with_opts "$ns" "$qtype" "$qname" "$@" >"$file" || return 1
+ grep "status: $rcode" "$file" >/dev/null
+)
+
+wait_for_rcode() (
+ retry_quiet 10 _wait_for_rcode "$@"
+)
+
+wait_for_soa() (
+ wait_for_rcode NOERROR SOA "$@"
+)
+
+wait_for_a() (
+ wait_for_rcode NOERROR A "$@"
+)
+
+wait_for_no_soa() {
+ wait_for_rcode REFUSED SOA "$@"
+}
+
+_wait_for_zonefile() (
+ # shellcheck disable=SC2234
+ [ -f "$1" ]
+)
+
+wait_for_zonefile() (
+ retry_quiet 10 _wait_for_zonefile "$@"
+)
+
+_wait_for_no_zonefile() (
+ # shellcheck disable=SC2234
+ [ ! -f "$1" ]
+)
+
+wait_for_no_zonefile() (
+ retry_quiet 10 _wait_for_no_zonefile "$@"
+)
+
+status=0
+n=0
+
+##########################################################################
+n=$((n+1))
+echo_i "checking that catalog-bad1.example (with no version) has failed to load ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: zone 'catalog-bad1.example' has no 'version' record" &&
+wait_for_message ns2/named.run "catz: new catalog zone 'catalog-bad1.example' is broken and will not be processed" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that catalog-bad2.example (with unsupported version) has failed to load ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: zone 'catalog-bad2.example' unsupported version '99'" &&
+wait_for_message ns2/named.run "catz: new catalog zone 'catalog-bad2.example' is broken and will not be processed" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that catalog-bad3.example (with two supported version records) has failed to load ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: 'version' property TXT RRset contains more than one record, which is invalid" &&
+wait_for_message ns2/named.run "catz: invalid record in catalog zone - version.catalog-bad3.example IN TXT (failure) - ignoring" &&
+wait_for_message ns2/named.run "catz: zone 'catalog-bad3.example' version is not set" &&
+wait_for_message ns2/named.run "catz: new catalog zone 'catalog-bad3.example' is broken and will not be processed" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that catalog-bad4.example (with only spurious type A version record) has failed to load ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: invalid record in catalog zone - version.catalog-bad4.example IN A (failure) - ignoring" &&
+wait_for_message ns2/named.run "catz: zone 'catalog-bad4.example' version is not set" &&
+wait_for_message ns2/named.run "catz: new catalog zone 'catalog-bad4.example' is broken and will not be processed" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that catalog-bad5.example (non-IN class) has failed to load ($n)"
+ret=0
+wait_for_message ns2/named.run "'catalog-zones' option is only supported for views with class IN" &&
+wait_for_message ns2/named.run "all zones loaded" || ret=1
+grep -F "catz: dns_catz_add_zone catalog-bad5.example" ns2/named.run && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+##########################################################################
+echo_i "Testing adding/removing of domain in catalog zone"
+n=$((n+1))
+echo_i "checking that dom1.example. is not served by primary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.1 dom1.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding a domain dom1.example. to primary via RNDC ($n)"
+ret=0
+# enough initial content for IXFR response when TXT record is added below
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom1.example.db
+echo "@ 3600 IN NS invalid." >> ns1/dom1.example.db
+echo "foo 3600 IN TXT some content here" >> ns1/dom1.example.db
+echo "bar 3600 IN TXT some content here" >> ns1/dom1.example.db
+echo "xxx 3600 IN TXT some content here" >> ns1/dom1.example.db
+echo "yyy 3600 IN TXT some content here" >> ns1/dom1.example.db
+rndccmd 10.53.0.1 addzone dom1.example. in default '{ type primary; file "dom1.example.db"; allow-update { any; }; notify explicit; also-notify { 10.53.0.2; }; };' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom1.example. is now served by primary ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom1.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Adding domain dom1.example. to catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog1.example. 3600 IN PTR dom1.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom1.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom1.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom1.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom1.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that zone-directory is populated ($n)"
+ret=0
+wait_for_zonefile "ns2/zonedir/__catz__default_catalog1.example_dom1.example.db" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "update dom1.example. ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add dom1.example 0 IN TXT added record
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "wait for secondary to be updated ($n)"
+ret=0
+wait_for_txt() {
+ dig_with_opts @10.53.0.2 TXT dom1.example. > dig.out.test$n || return 1
+ grep "ANSWER: 1," dig.out.test$n > /dev/null || return 1
+ grep "status: NOERROR" dig.out.test$n > /dev/null || return 1
+ grep "IN.TXT." dig.out.test$n > /dev/null || return 1
+}
+retry_quiet 10 wait_for_txt || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check that journal was created for cleanup test ($n)"
+ret=0
+test -f ns2/zonedir/__catz__default_catalog1.example_dom1.example.db.jnl || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "update catalog zone serial ($n)"
+ret=0
+# default minimum update rate is once / 5 seconds
+sleep 5
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add catalog1.example 3600 SOA . . 20 86400 3600 86400 3600
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "wait for catalog zone to transfer ($n)"
+ret=0
+wait_for_soa_equal_20() {
+ dig_with_opts @10.53.0.2 SOA catalog1.example. > dig.out.test$n || return 1
+ grep "ANSWER: 1," dig.out.test$n > /dev/null || return 1
+ grep "status: NOERROR" dig.out.test$n > /dev/null || return 1
+ grep 'IN.SOA.\. \. 20 ' dig.out.test$n > /dev/null || return 1
+}
+retry_quiet 10 wait_for_soa_equal_20 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "update dom1.example. again ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add foo.dom1.example 0 IN TXT added record
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "wait for secondary to be updated again ($n)"
+ret=0
+wait_for_txt() {
+ dig_with_opts @10.53.0.2 TXT foo.dom1.example. > dig.out.test$n || return 1
+ grep "ANSWER: 2," dig.out.test$n > /dev/null || return 1
+ grep "status: NOERROR" dig.out.test$n > /dev/null || return 1
+ grep "IN.TXT." dig.out.test$n > /dev/null || return 1
+}
+retry_quiet 10 wait_for_txt || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "removing domain dom1.example. from catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog1.example
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "zone_shutdown: zone dom1.example/IN/default: shutting down" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom1.example. is not served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom1.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that zone-directory is emptied ($n)"
+ret=0
+wait_for_no_zonefile "ns2/zonedir/__catz__default_catalog1.example_dom1.example.db" || ret=1
+wait_for_no_zonefile "ns2/zonedir/__catz__default_catalog1.example_dom1.example.db.jnl" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+##########################################################################
+echo_i "Testing various simple operations on domains, including using multiple catalog zones and garbage in zone"
+n=$((n+1))
+echo_i "adding domain dom2.example. to primary via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom2.example.db
+echo "@ IN NS invalid." >> ns1/dom2.example.db
+echo "@ IN A 192.0.2.1" >> ns1/dom2.example.db
+rndccmd 10.53.0.1 addzone dom2.example. in default '{type primary; file "dom2.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "adding domain dom2.example. to primary ns3 via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns3/dom2.example.db
+echo "@ IN NS invalid." >> ns3/dom2.example.db
+echo "@ IN A 192.0.2.2" >> ns3/dom2.example.db
+rndccmd 10.53.0.3 addzone dom2.example. '{type primary; file "dom2.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "adding domain dom4.example. to primary via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom4.example.db
+echo "@ IN NS invalid." >> ns1/dom4.example.db
+rndccmd 10.53.0.1 addzone dom4.example. in default '{type primary; file "dom4.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "adding domains dom2.example, dom3.example. and some garbage to catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add 636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example.
+ update add coo.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN TXT "catalog2.example."
+ update add b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN PTR dom3.example.
+ update add e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog1.example. 3600 IN NS foo.bar.
+ update add trash.catalog1.example. 3600 IN A 1.2.3.4
+ update add trash2.foo.catalog1.example. 3600 IN A 1.2.3.4
+ update add trash3.zones.catalog1.example. 3600 IN NS a.dom2.example.
+ update add foobarbaz.b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN PTR dom3.example.
+ update add blahblah.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example.
+ update add foobarbaz.b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN APL 1:1.2.3.4/30
+ update add blahblah.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN TXT "blah blah"
+ update add version.catalog1.example. 3600 IN A 1.2.3.4
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "adding domain dom4.example. to catalog2 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update add de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example. 3600 IN PTR dom4.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: updating catalog zone 'catalog2.example' with serial 2670950425" &&
+wait_for_message ns2/named.run "catz: adding zone 'dom2.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "catz: adding zone 'dom3.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "catz: adding zone 'dom4.example' from catalog 'catalog2.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom4.example/IN/default' from 10.53.0.1#${EXTRAPORT1}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom4.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom4.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom3.example. is not served by primary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.1 dom3.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "adding a domain dom3.example. to primary via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom3.example.db
+echo "@ IN NS invalid." >> ns1/dom3.example.db
+rndccmd 10.53.0.1 addzone dom3.example. in default '{type primary; file "dom3.example.db"; also-notify { 10.53.0.2; }; notify explicit; };' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom3.example. is served by primary ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom3.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "transfer of 'dom2.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" &&
+wait_for_message ns2/named.run "transfer of 'dom3.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom3.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom3.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+# The member zone's PTR RRset must have only one record in it.
+# Check that adding a second record to the RRset is caught and such a
+# catalog zone is not processed.
+n=$((n+1))
+echo_i "adding domain dom4-reused-label.example. to catalog2 zone, reusing a label ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update add de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example. 3600 IN PTR dom4-reused-label.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up, and checking that the reused label has been caught ($n)"
+ret=0
+wait_for_message ns2/named.run "de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example IN PTR (failure)" &&
+wait_for_message ns2/named.run "catz: new catalog zone 'catalog2.example' is broken and will not be processed" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "deleting domain dom4-reused-label.example. from catalog2 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update delete de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example. 3600 IN PTR dom4-reused-label.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+# Test zone associated state reset.
+n=$((n+1))
+echo_i "renaming the label of domain dom4.example. in catalog2 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update delete de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example. 3600 IN PTR dom4.example.
+ update add dom4-renamed-label.zones.catalog2.example. 3600 IN PTR dom4.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up, and checking that the zone has been reset ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: zone 'dom4.example' unique label has changed, reset state" &&
+wait_for_message ns2/named.run "catz: deleting zone 'dom4.example' from catalog 'catalog2.example' - success" &&
+wait_for_message ns2/named.run "catz: adding zone 'dom4.example' from catalog 'catalog2.example' - success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding domain dom2.example. to catalog2 zone to test change of ownership ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update add dom2-without-coo.zones.catalog2.example. 3600 IN PTR dom2.example.
+ update add primaries.dom2-without-coo.zones.catalog2.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom2.example' from catalog 'catalog2.example'" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that unpermitted change of ownership did not happen ($n)"
+ret=0
+wait_for_message ns2/named.run "catz_addmodzone_taskaction: zone 'dom2.example' will not be added because another catalog zone already contains an entry with that zone" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom2.example. is served by secondary and that it's the one from ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom2.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding change of ownership permission record for dom2.example. into catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add coo.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR catalog2.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: updating catalog zone 'catalog1.example'" &&
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "updating catalog2 zone to initiate a zone transfer ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update delete dom2-without-coo.zones.catalog2.example. 3600 IN PTR dom2.example.
+ update delete primaries.dom2-without-coo.zones.catalog2.example. 3600 IN A 10.53.0.3
+ update add dom2-with-coo.zones.catalog2.example. 3600 IN PTR dom2.example.
+ update add primaries.dom2-with-coo.zones.catalog2.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up and checking that the change of ownership was successful ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: zone 'dom2.example' change of ownership from 'catalog1.example' to 'catalog2.example'" &&
+wait_for_message ns2/named.run "catz: deleting zone 'dom2.example' from catalog 'catalog1.example' - success" &&
+wait_for_message ns2/named.run "catz: adding zone 'dom2.example' from catalog 'catalog2.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom2.example/IN/default' from 10.53.0.3#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom2.example. is served by secondary and that it's now the one from ns3 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom2.example. dig.out.test$n || ret=1
+grep "192.0.2.2" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "removing dom2.example. and its change of ownership permission record from catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete 636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example.
+ update delete coo.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR catalog2.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: iteration finished" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding change of ownership permission record for dom2.example. into catalog2 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update add coo.dom2-with-coo.zones.catalog2.example. 3600 IN PTR catalog1.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: iteration finished" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding back dom2.example. into catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add 636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that the change of ownership did not happen because version '1' catalog2 zone does not support the 'coo' property ($n)"
+ret=0
+wait_for_message ns2/named.run "catz_addmodzone_taskaction: zone 'dom2.example' will not be added because another catalog zone already contains an entry with that zone" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom2.example. is still served by secondary and that it's still the one from ns3 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom2.example. dig.out.test$n || ret=1
+grep "192.0.2.2" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+# GL #3060
+n=$((n+1))
+echo_i "reconfiguring secondary - checking if catz survives a certain class of failed reconfiguration attempts ($n)"
+ret=0
+sed -e "s/^#T3//" < ns2/named1.conf.in > ns2/named.conf.tmp
+copy_setports ns2/named.conf.tmp ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p "${CONTROLPORT}" reconfig > /dev/null 2>&1 && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking again that dom3.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom3.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "reconfiguring secondary - reverting the bad configuration ($n)"
+ret=0
+copy_setports ns2/named1.conf.in ns2/named.conf
+rndccmd 10.53.0.2 reconfig || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+# GL #3911
+n=$((n+1))
+echo_i "reconfiguring secondary - checking if catz survives another type of failed reconfiguration attempts ($n)"
+ret=0
+sed -e "s/^#T4//" < ns2/named1.conf.in > ns2/named.conf.tmp
+copy_setports ns2/named.conf.tmp ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p "${CONTROLPORT}" reconfig > /dev/null 2>&1 && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# catalog zone update can be deferred
+sleep 2
+
+n=$((n+1))
+echo_i "checking again that dom3.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom3.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "reconfiguring secondary - reverting the bad configuration ($n)"
+ret=0
+copy_setports ns2/named1.conf.in ns2/named.conf
+rndccmd 10.53.0.2 reconfig || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding a domain dom-existing.example. to primary via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom-existing.example.db
+echo "@ IN NS invalid." >> ns1/dom-existing.example.db
+echo "@ IN A 192.0.2.1" >> ns1/dom-existing.example.db
+rndccmd 10.53.0.1 addzone dom-existing.example. in default '{type primary; file "dom-existing.example.db"; also-notify { 10.53.0.2; }; notify explicit; };' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom-existing.example. is served by primary ($n)"
+ret=0
+wait_for_a @10.53.0.1 dom-existing.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "adding domain dom-existing.example. to catalog1 zone to test that existing zones don't get overwritten ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add dom-existing.zones.catalog1.example. 3600 IN PTR dom-existing.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom-existing.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "catz_addmodzone_taskaction: zone 'dom-existing.example' will not be added because it is an explicitly configured zone" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom-existing.example. is served by secondary and that it's not the one from the primary ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom-existing.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding a domain dom-existing-forward.example. to primary via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom-existing-forward.example.db
+echo "@ IN NS invalid." >> ns1/dom-existing-forward.example.db
+echo "@ IN A 192.0.2.1" >> ns1/dom-existing-forward.example.db
+rndccmd 10.53.0.1 addzone dom-existing-forward.example. in default '{type primary; file "dom-existing-forward.example.db"; also-notify { 10.53.0.2; }; notify explicit; };' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom-existing-forward.example. is served by primary ($n)"
+ret=0
+wait_for_a @10.53.0.1 dom-existing-forward.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "adding domain dom-existing-forward.example. to catalog1 zone to test that existing forward zones don't get overwritten ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add dom-existing-forward.zones.catalog1.example. 3600 IN PTR dom-existing-forward.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom-existing-forward.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "catz_addmodzone_taskaction: zone 'dom-existing-forward.example' will not be processed because of the explicitly configured forwarding for that zone" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom-existing-forward.example. is not served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom-existing-forward.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding a domain dom-existing-forward-off.example. to primary via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom-existing-forward-off.example.db
+echo "@ IN NS invalid." >> ns1/dom-existing-forward-off.example.db
+echo "@ IN A 192.0.2.1" >> ns1/dom-existing-forward-off.example.db
+rndccmd 10.53.0.1 addzone dom-existing-forward-off.example. in default '{type primary; file "dom-existing-forward-off.example.db"; also-notify { 10.53.0.2; }; notify explicit; };' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom-existing-forward-off.example. is served by primary ($n)"
+ret=0
+wait_for_a @10.53.0.1 dom-existing-forward-off.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "adding domain dom-existing-forward-off.example. to catalog1 zone to test that a zone with turned off forwarding can be used in a catalog zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add dom-existing-forward-off.zones.catalog1.example. 3600 IN PTR dom-existing-forward-off.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom-existing-forward-off.example' from catalog 'catalog1.example'" &&
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom-existing-forward-off.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom-existing-forward-off.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "removing all records from catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete 636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example.
+ update delete coo.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN TXT "catalog2.example."
+ update delete b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN PTR dom3.example.
+ update delete e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog1.example. 3600 IN NS foo.bar.
+ update delete trash.catalog1.example. 3600 IN A 1.2.3.4
+ update delete trash2.foo.catalog1.example. 3600 IN A 1.2.3.4
+ update delete trash3.zones.catalog1.example. 3600 IN NS a.dom2.example.
+ update delete foobarbaz.b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN PTR dom3.example.
+ update delete blahblah.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example.
+ update delete foobarbaz.b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN APL 1:1.2.3.4/30
+ update delete blahblah.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN TXT "blah blah"
+ update delete version.catalog1.example. 3600 IN A 1.2.3.4
+ update delete dom-existing.zones.catalog1.example. 3600 IN PTR dom-existing.example.
+ update delete dom-existing-forward.zones.catalog1.example. 3600 IN PTR dom-existing-forward.example.
+ update delete dom-existing-forward-off.zones.catalog1.example. 3600 IN PTR dom-existing-forward.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "removing all records from catalog2 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update delete dom2-with-coo.zones.catalog2.example. 3600 IN PTR dom2.example.
+ update delete primaries.dom2-with-coo.zones.catalog2.example. 3600 IN A 10.53.0.3
+ update delete coo.dom2-with-coo.zones.catalog2.example. 3600 IN PTR catalog1.example.
+ update delete dom4-renamed-label.zones.catalog2.example. 3600 IN PTR dom4.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+echo_i "Testing primaries suboption and random labels"
+n=$((n+1))
+echo_i "adding dom5.example. with a valid primaries suboption (IP without TSIG) and a random label ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add somerandomlabel.zones.catalog1.example. 3600 IN PTR dom5.example.
+ update add primaries.ext.somerandomlabel.zones.catalog1.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom5.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom5.example/IN/default' from 10.53.0.3#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom5.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom5.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "removing dom5.example. ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete somerandomlabel.zones.catalog1.example. 3600 IN PTR dom5.example.
+ update delete primaries.somerandomlabel.zones.catalog1.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "zone_shutdown: zone dom5.example/IN/default: shutting down" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom5.example. is no longer served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom5.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+
+##########################################################################
+echo_i "Testing primaries global option"
+n=$((n+1))
+echo_i "adding dom6.example. and a valid global primaries option (IP without TSIG) ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add primaries.ext.catalog1.example. 3600 IN A 10.53.0.3
+ update add primaries.ext.catalog1.example. 3600 IN AAAA fd92:7065:b8e:ffff::3
+ update add 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example. 3600 IN PTR dom6.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom6.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom6.example/IN/default' from " > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom6.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom6.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "removing dom6.example. ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete primaries.ext.catalog1.example. 3600 IN A 10.53.0.3
+ update delete primaries.ext.catalog1.example. 3600 IN AAAA fd92:7065:b8e:ffff::3
+ update delete 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example. 3600 IN PTR dom6.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "zone_shutdown: zone dom6.example/IN/default: shutting down" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom6.example. is no longer served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom6.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding dom6.example. and an invalid global primaries option (TSIG without IP) ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add label1.primaries.ext.catalog1.example. 3600 IN TXT "tsig_key"
+ update add 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example. 3600 IN PTR dom6.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom6.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "error \"failure\" while trying to generate config for zone 'dom6.example'" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "removing dom6.example. ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete label1.primaries.ext.catalog1.example. 3600 IN TXT "tsig_key"
+ update delete 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example. 3600 IN PTR dom6.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: deleting zone 'dom6.example' from catalog 'catalog1.example' - success" > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+n=$((n+1))
+echo_i "Checking that a missing zone directory forces in-memory ($n)"
+ret=0
+grep "'nonexistent' not found; zone files will not be saved" ns2/named.run > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+echo_i "Testing allow-query and allow-transfer ACLs"
+n=$((n+1))
+echo_i "adding domains dom7.example. and dom8.example. to primary via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom7.example.db
+echo "@ IN NS invalid." >> ns1/dom7.example.db
+rndccmd 10.53.0.1 addzone dom7.example. in default '{type primary; file "dom7.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom8.example.db
+echo "@ IN NS invalid." >> ns1/dom8.example.db
+rndccmd 10.53.0.1 addzone dom8.example. in default '{type primary; file "dom8.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom7.example. is now served by primary ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom7.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding domain dom7.example. to catalog1 zone with an allow-query statement ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add 78833ec3c0059fd4540fee81c7eaddce088e7cd7.zones.catalog1.example. 3600 IN PTR dom7.example.
+ update add allow-query.ext.78833ec3c0059fd4540fee81c7eaddce088e7cd7.zones.catalog1.example. 3600 IN APL 1:10.53.0.1/32 !1:10.53.0.0/30 1:0.0.0.0/0
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom7.example' from catalog 'catalog1.example'" > /dev/null &&
+wait_for_message ns2/named.run "transfer of 'dom7.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom7.example. is accessible from 10.53.0.1 ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom7.example. dig.out.test$n -b 10.53.0.1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom7.example. is not accessible from 10.53.0.2 ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom7.example. dig.out.test$n -b 10.53.0.2 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom7.example. is accessible from 10.53.0.5 ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom7.example. dig.out.test$n -b 10.53.0.5 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+n=$((n+1))
+echo_i "adding dom8.example. domain and global allow-query and allow-transfer ACLs ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add cba95222e308baba42417be6021026fdf20827b6.zones.catalog1.example. 3600 IN PTR dom8.example
+ update add allow-query.ext.catalog1.example. 3600 IN APL 1:10.53.0.1/32
+ update add allow-transfer.ext.catalog1.example. 3600 IN APL 1:10.53.0.2/32
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" &&
+wait_for_message ns2/named.run "transfer of 'dom8.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom8.example. is accessible from 10.53.0.1 ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom8.example. dig.out.test$n -b 10.53.0.1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom8.example. is not accessible from 10.53.0.2 ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom8.example. dig.out.test$n -b 10.53.0.2 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom8.example. is not AXFR accessible from 10.53.0.1 ($n)"
+ret=0
+dig_with_opts @10.53.0.2 axfr dom8.example. -b 10.53.0.1 > dig.out.test$n || ret=1
+grep "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom8.example. is AXFR accessible from 10.53.0.2 ($n)"
+ret=0
+dig_with_opts @10.53.0.2 axfr dom8.example. -b 10.53.0.2 > dig.out.test$n || ret=1
+grep -v "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+n=$((n+1))
+echo_i "deleting global allow-query and allow-domain ACLs ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete allow-query.ext.catalog1.example. 3600 IN APL 1:10.53.0.1/32
+ update delete allow-transfer.ext.catalog1.example. 3600 IN APL 1:10.53.0.2/32
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom8.example. is accessible from 10.53.0.1 ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom8.example. dig.out.test$n -b 10.53.0.1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom8.example. is accessible from 10.53.0.2 ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom8.example. dig.out.test$n -b 10.53.0.2 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom8.example. is AXFR accessible from 10.53.0.1 ($n)"
+ret=0
+dig_with_opts @10.53.0.2 axfr dom8.example. -b 10.53.0.1 > dig.out.test$n || ret=1
+grep -v "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom8.example. is AXFR accessible from 10.53.0.2 ($n)"
+ret=0
+dig_with_opts @10.53.0.2 axfr dom8.example. -b 10.53.0.2 > dig.out.test$n || ret=1
+grep -v "Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+
+##########################################################################
+echo_i "Testing TSIG keys for primaries set per-domain"
+n=$((n+1))
+echo_i "adding a domain dom9.example. to primary via RNDC, with transfers allowed only with TSIG key ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom9.example.db
+echo "@ IN NS invalid." >> ns1/dom9.example.db
+rndccmd 10.53.0.1 addzone dom9.example. in default '{type primary; file "dom9.example.db"; allow-transfer { key tsig_key; }; };' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom9.example. is now served by primary ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom9.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding domain dom9.example. to catalog1 zone with a valid primaries suboption (IP with TSIG) ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN PTR dom9.example.
+ update add label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN A 10.53.0.1
+ update add label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "tsig_key"
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom9.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom9.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom9.example. is accessible on secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom9.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "change TSIG key name on primary ($n)"
+ret=0
+rndccmd 10.53.0.1 modzone dom9.example. in default '{type primary; notify yes; file "dom9.example.db"; allow-transfer { key next_key; }; };' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "update TSIG key name in catalog zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update del label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "tsig_key"
+ update add label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "next_key"
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: modifying zone 'dom9.example' from catalog 'catalog1.example'" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "update zone contents and reload ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 2 3600 3600 3600 3600" > ns1/dom9.example.db
+echo "@ IN NS ns2" >> ns1/dom9.example.db
+echo "ns2 IN A 10.53.0.2" >> ns1/dom9.example.db
+rndccmd 10.53.0.1 reload dom9.example. || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "wait for primary to update zone ($n)"
+ret=0
+wait_for_a @10.53.0.1 ns2.dom9.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "wait for secondary to update zone ($n)"
+ret=0
+wait_for_a @10.53.0.2 ns2.dom9.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "deleting domain dom9.example. from catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN PTR dom9.example.
+ update delete label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN A 10.53.0.1
+ update delete label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "next_key"
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: deleting zone 'dom9.example' from catalog 'catalog1.example' - success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom9.example. is no longer accessible on secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom9.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding domain dom9.example. to catalog1 zone with an invalid primaries suboption (TSIG without IP) ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN PTR dom9.example.
+ update add label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "tsig_key"
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom9.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "error \"failure\" while trying to generate config for zone 'dom9.example'" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "deleting domain dom9.example. from catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN PTR dom9.example.
+ update delete label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "tsig_key"
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: deleting zone 'dom9.example' from catalog 'catalog1.example'" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+echo_i "Testing catalog entries that can't be represented as filenames"
+# note: we need 4 backslashes in the shell to get 2 backslashes in DNS
+# presentation format, which is 1 backslash on the wire.
+for special in \
+ this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example \
+ this.zone/domain.has.a.slash.dom10.example \
+ this.zone\\\\domain.has.backslash.dom10.example \
+ this.zone:domain.has.a.colon.dom.10.example
+do
+ # hashes below are generated by:
+ # python ${TOP}/contrib/scripts/catzhash.py "${special}"
+
+ case "$special" in
+ this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example)
+ hash=825f48b1ce1b4cf5a041d20255a0c8e98d114858
+ db=__catz__a35e0a044ff9f37436068e1e83e9b99fb9da51b0fe7b699bdb404f7755d68276.db
+ ;;
+ this.zone/domain.has.a.slash.dom10.example)
+ hash=e64cc64c99bf52d0a77fb16dd7ed57cf925a36aa
+ db=__catz__765197c8050c794f4ec5bbf5dbdf64d0551459c08a91a4217768fcd16cd3b7ce.db
+ ;;
+ this.zone\\\\domain.has.backslash.dom10.example)
+ hash=91e27e02153d38cf656a9b376d7747fbcd19f985
+ db=__catz__0f2f3beaf2ef70e0086063ae28a69444cdf3847cb85e668bfe52c89f7f756b29.db
+ ;;
+ this.zone:domain.has.a.colon.dom.10.example)
+ hash=8b7238bf4c34045834c573ba4116557ebb24d33c
+ db=__catz__ba75ab860533508a62b0937c5c6b8537e4186e4d5e7685161287260d07418251.db
+ ;;
+ esac
+
+ n=$((n+1))
+ echo_i "checking that ${special}. is not served by primary ($n)"
+ ret=0
+ wait_for_no_soa @10.53.0.1 "${special}" dig.out.test$n || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "Adding a domain ${special}. to primary via RNDC ($n)"
+ ret=0
+ echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom10.example.db
+ echo "@ IN NS invalid." >> ns1/dom10.example.db
+ rndccmd 10.53.0.1 addzone '"'"${special}"'"' in default '{type primary; file "dom10.example.db";};' || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking that ${special}. is now served by primary ($n)"
+ ret=0
+ wait_for_soa @10.53.0.1 "${special}." dig.out.test$n || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ nextpart ns2/named.run >/dev/null
+
+ n=$((n+1))
+ echo_i "Adding domain ${special}. to catalog1 zone ($n)"
+ ret=0
+ $NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add ${hash}.zones.catalog1.example 3600 IN PTR ${special}.
+ send
+END
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "waiting for secondary to sync up ($n)"
+ ret=0
+ wait_for_message ns2/named.run "catz: adding zone '$special' from catalog 'catalog1.example'" &&
+ wait_for_message ns2/named.run "transfer of '$special/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking that ${special}. is served by secondary ($n)"
+ ret=0
+ wait_for_soa @10.53.0.2 "${special}." dig.out.test$n || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking that zone-directory is populated with a hashed filename ($n)"
+ ret=0
+ wait_for_zonefile "ns2/zonedir/$db" || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "removing domain ${special}. from catalog1 zone ($n)"
+ ret=0
+ $NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete ${hash}.zones.catalog1.example
+ send
+END
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "waiting for secondary to sync up ($n)"
+ ret=0
+ wait_for_message ns2/named.run "zone_shutdown: zone ${special}/IN/default: shutting down" || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking that ${special}. is not served by secondary ($n)"
+ ret=0
+ wait_for_no_soa @10.53.0.2 "${special}." dig.out.test$n || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking that zone-directory is emptied ($n)"
+ ret=0
+ wait_for_no_zonefile "ns2/zonedir/$db" || ret=1
+ wait_for_no_zonefile "ns2/zonedir/$db.jnl" || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+done
+
+##########################################################################
+echo_i "Testing adding a domain and a subdomain of it"
+n=$((n+1))
+echo_i "checking that dom11.example. is not served by primary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.1 dom11.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding a domain dom11.example. to primary via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom11.example.db
+echo "@ IN NS invalid." >> ns1/dom11.example.db
+rndccmd 10.53.0.1 addzone dom11.example. in default '{type primary; file "dom11.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom11.example. is now served by primary ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom11.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Adding domain dom11.example. to catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add 0580d70e769c86c8b951a488d8b776627f427d7a.zones.catalog1.example. 3600 IN PTR dom11.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom11.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom11.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom11.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom11.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that subdomain.of.dom11.example. is not served by primary ($n)"
+ret=0
+wait_for_rcode NXDOMAIN SOA @10.53.0.1 subdomain.of.dom11.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding a domain subdomain.of.dom11.example. to primary via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/subdomain.of.dom11.example.db
+echo "@ IN NS invalid." >> ns1/subdomain.of.dom11.example.db
+rndccmd 10.53.0.1 addzone subdomain.of.dom11.example. in default '{type primary; file "subdomain.of.dom11.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that subdomain.of.dom11.example. is now served by primary ($n)"
+ret=0
+wait_for_soa @10.53.0.1 subdomain.of.dom11.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Adding domain subdomain.of.dom11.example. to catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add 25557e0bdd10cb3710199bb421b776df160f241e.zones.catalog1.example. 3600 IN PTR subdomain.of.dom11.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'subdomain.of.dom11.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "transfer of 'subdomain.of.dom11.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that subdomain.of.dom11.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 subdomain.of.dom11.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "removing domain dom11.example. from catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete 0580d70e769c86c8b951a488d8b776627f427d7a.zones.catalog1.example
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "zone_shutdown: zone dom11.example/IN/default: shutting down" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom11.example. is not served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom11.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that subdomain.of.dom11.example. is still served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 subdomain.of.dom11.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "removing domain subdomain.of.dom11.example. from catalog1 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete 25557e0bdd10cb3710199bb421b776df160f241e.zones.catalog1.example
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "zone_shutdown: zone subdomain.of.dom11.example/IN/default: shutting down" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that subdomain.of.dom11.example. is not served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 subdomain.of.d11.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+echo_i "Testing adding a catalog zone at runtime with rndc reconfig"
+n=$((n+1))
+echo_i "checking that dom12.example. is not served by primary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.1 dom12.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding a domain dom12.example. to primary via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom12.example.db
+echo "@ IN NS invalid." >> ns1/dom12.example.db
+rndccmd 10.53.0.1 addzone dom12.example. in default '{type primary; file "dom12.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom12.example. is now served by primary ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom12.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Adding domain dom12.example. to catalog4 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add 871d51e5433543c0f6fb263c40f359fbc152c8ae.zones.catalog4.example. 3600 IN PTR dom12.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom12.example. is not served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom12.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+
+n=$((n+1))
+echo_i "reconfiguring secondary - adding catalog4 catalog zone ($n)"
+ret=0
+sed -e "s/^#T1//g" < ns2/named1.conf.in > ns2/named.conf.tmp
+copy_setports ns2/named.conf.tmp ns2/named.conf
+rndccmd 10.53.0.2 reconfig || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom12.example' from catalog 'catalog4.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom12.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom7.example. is still served by secondary after reconfiguration ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom7.example. dig.out.test$n -b 10.53.0.1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+n=$((n+1))
+
+echo_i "checking that dom12.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom12.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "reconfiguring secondary - removing catalog4 catalog zone, adding non-existent catalog5 catalog zone ($n)"
+ret=0
+sed -e "s/^#T2//" < ns2/named1.conf.in > ns2/named.conf.tmp
+copy_setports ns2/named.conf.tmp ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p "${CONTROLPORT}" reconfig > /dev/null 2>&1 && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "reconfiguring secondary - removing non-existent catalog5 catalog zone ($n)"
+ret=0
+copy_setports ns2/named1.conf.in ns2/named.conf
+rndccmd 10.53.0.2 reconfig || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom12.example. is not served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom12.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "removing domain dom12.example. from catalog4 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete 871d51e5433543c0f6fb263c40f359fbc152c8ae.zones.catalog4.example. 3600 IN PTR dom12.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+echo_i "Testing having a zone in two different catalogs"
+n=$((n+1))
+echo_i "checking that dom13.example. is not served by primary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.1 dom13.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding a domain dom13.example. to primary ns1 via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom13.example.db
+echo "@ IN NS invalid." >> ns1/dom13.example.db
+echo "@ IN A 192.0.2.1" >> ns1/dom13.example.db
+rndccmd 10.53.0.1 addzone dom13.example. in default '{type primary; file "dom13.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom13.example. is now served by primary ns1 ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom13.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding a domain dom13.example. to primary ns3 via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns3/dom13.example.db
+echo "@ IN NS invalid." >> ns3/dom13.example.db
+echo "@ IN A 192.0.2.2" >> ns3/dom13.example.db
+rndccmd 10.53.0.3 addzone dom13.example. '{type primary; file "dom13.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom13.example. is now served by primary ns3 ($n)"
+ret=0
+wait_for_soa @10.53.0.3 dom13.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Adding domain dom13.example. to catalog1 zone with ns1 as primary ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add 8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog1.example. 3600 IN PTR dom13.example.
+ update add primaries.ext.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog1.example. 3600 IN A 10.53.0.1
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom13.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom13.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "checking that dom13.example. is served by secondary and that it's the one from ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom13.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding domain dom13.example. to catalog2 zone with ns3 as primary ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update add 8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog2.example. 3600 IN PTR dom13.example.
+ update add primaries.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog2.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom13.example. is served by secondary and that it's still the one from ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom13.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Deleting domain dom13.example. from catalog2 ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update delete 8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog2.example. 3600 IN PTR dom13.example.
+ update delete primaries.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog2.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom13.example. is served by secondary and that it's still the one from ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom13.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Deleting domain dom13.example. from catalog1 ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete 8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog1.example. 3600 IN PTR dom13.example.
+ update delete primaries.ext.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog1.example. 3600 IN A 10.53.0.2
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom13.example. is no longer served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom13.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+echo_i "Testing recreation of a manually deleted zone after a reload"
+n=$((n+1))
+echo_i "checking that dom16.example. is not served by primary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.1 dom16.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding a domain dom16.example. to primary ns1 via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom16.example.db
+echo "@ IN NS invalid." >> ns1/dom16.example.db
+echo "@ IN A 192.0.2.1" >> ns1/dom16.example.db
+rndccmd 10.53.0.1 addzone dom16.example. in default '{type primary; file "dom16.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom16.example. is now served by primary ns1 ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom16.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Adding domain dom16.example. to catalog1 zone with ns1 as primary ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN PTR dom16.example.
+ update add masters.efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN A 10.53.0.1
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom16.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom16.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "checking that dom16.example. is served by secondary and that it's the one from ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom16.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+echo_i "Deleting dom16.example. from secondary ns2 via RNDC ($n)"
+ret=0
+rndccmd 10.53.0.2 delzone dom16.example. in default >/dev/null 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom16.example. is no longer served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom16.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+echo_i "Reloading secondary ns2 via RNDC ($n)"
+ret=0
+rndccmd 10.53.0.2 reload >/dev/null 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom16.example. is served by secondary and that it's the one from ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom16.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Deleting domain dom16.example. from catalog1 ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN PTR dom16.example.
+ update delete masters.efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN A 10.53.0.1
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom16.example. is no longer served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom16.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+echo_i "Testing having a regular zone and a zone in catalog zone of the same name"
+n=$((n+1))
+echo_i "checking that dom14.example. is not served by primary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.1 dom14.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding a domain dom14.example. to primary ns1 via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom14.example.db
+echo "@ IN NS invalid." >> ns1/dom14.example.db
+echo "@ IN A 192.0.2.1" >> ns1/dom14.example.db
+rndccmd 10.53.0.1 addzone dom14.example. in default '{type primary; file "dom14.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom14.example. is now served by primary ns1 ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom14.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding a domain dom14.example. to primary ns3 via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns3/dom14.example.db
+echo "@ IN NS invalid." >> ns3/dom14.example.db
+echo "@ IN A 192.0.2.2" >> ns3/dom14.example.db
+rndccmd 10.53.0.3 addzone dom14.example. '{type primary; file "dom14.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom14.example. is now served by primary ns3 ($n)"
+ret=0
+wait_for_soa @10.53.0.3 dom14.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Adding domain dom14.example. with rndc with ns1 as primary ($n)"
+ret=0
+rndccmd 10.53.0.2 addzone dom14.example. in default '{type secondary; primaries {10.53.0.1;};};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "transfer of 'dom14.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "checking that dom14.example. is served by secondary and that it's the one from ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom14.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding domain dom14.example. to catalog2 zone with ns3 as primary ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update add 45e3d45ea5f7bd01c395ccbde6ae2e750a3ee8ab.zones.catalog2.example. 3600 IN PTR dom14.example.
+ update add primaries.45e3d45ea5f7bd01c395ccbde6ae2e750a3ee8ab.zones.catalog2.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom14.example. is served by secondary and that it's still the one from ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom14.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Deleting domain dom14.example. from catalog2 ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update delete 45e3d45ea5f7bd01c395ccbde6ae2e750a3ee8ab.zones.catalog2.example. 3600 IN PTR dom14.example.
+ update delete primaries.45e3d45ea5f7bd01c395ccbde6ae2e750a3ee8ab.zones.catalog2.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom14.example. is served by secondary and that it's still the one from ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom14.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+echo_i "Testing changing label for a member zone"
+n=$((n+1))
+echo_i "checking that dom15.example. is not served by primary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.1 dom15.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Adding a domain dom15.example. to primary ns1 via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom15.example.db
+echo "@ IN NS invalid." >> ns1/dom15.example.db
+rndccmd 10.53.0.1 addzone dom15.example. in default '{type primary; file "dom15.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom15.example. is now served by primary ns1 ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom15.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+echo_i "Adding domain dom15.example. to catalog1 zone with 'dom15label1' label ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add dom15label1.zones.catalog1.example. 3600 IN PTR dom15.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+sleep 3
+
+n=$((n+1))
+echo_i "checking that dom15.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom15.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Changing label of domain dom15.example. from 'dom15label1' to 'dom15label2' ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete dom15label1.zones.catalog1.example. 3600 IN PTR dom15.example.
+ update add dom15label2.zones.catalog1.example. 3600 IN PTR dom15.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom15.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom15.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+echo_i "Testing custom properties version '1' and version '2' syntaxes"
+n=$((n+1))
+echo_i "checking that dom17.example. is not served by primary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.1 dom17.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom18.example. is not served by primary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.1 dom18.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "adding domains dom17.example. and dom18.example. to primary ns1 via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom17.example.db
+echo "@ IN NS invalid." >> ns1/dom17.example.db
+echo "@ IN A 192.0.2.1" >> ns1/dom17.example.db
+rndccmd 10.53.0.1 addzone dom17.example. in default '{type primary; file "dom17.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom18.example.db
+echo "@ IN NS invalid." >> ns1/dom18.example.db
+echo "@ IN A 192.0.2.1" >> ns1/dom18.example.db
+rndccmd 10.53.0.1 addzone dom18.example. in default '{type primary; file "dom18.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom17.example. is now served by primary ns1 ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom17.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom18.example. is now served by primary ns1 ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom18.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom17.example. is not served by primary ns3 ($n)"
+ret=0
+wait_for_no_soa @10.53.0.3 dom17.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom18.example. is not served by primary ns3 ($n)"
+ret=0
+wait_for_no_soa @10.53.0.3 dom18.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "adding domains dom17.example. and dom18.example. to primary ns3 via RNDC ($n)"
+ret=0
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns3/dom17.example.db
+echo "@ IN NS invalid." >> ns3/dom17.example.db
+echo "@ IN A 192.0.2.2" >> ns3/dom17.example.db
+rndccmd 10.53.0.3 addzone dom17.example. '{type primary; file "dom17.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns3/dom18.example.db
+echo "@ IN NS invalid." >> ns3/dom18.example.db
+echo "@ IN A 192.0.2.2" >> ns3/dom18.example.db
+rndccmd 10.53.0.3 addzone dom18.example. '{type primary; file "dom18.example.db";};' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom17.example. is now served by primary ns3 ($n)"
+ret=0
+wait_for_soa @10.53.0.3 dom17.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom18.example. is now served by primary ns3 ($n)"
+ret=0
+wait_for_soa @10.53.0.3 dom17.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding domains dom17.example. and dom18.example. to catalog1 zone with ns3 as custom primary using different custom properties syntax ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add dom17.zones.catalog1.example. 3600 IN PTR dom17.example.
+ update add dom18.zones.catalog1.example. 3600 IN PTR dom18.example.
+ update add primaries.dom17.zones.catalog1.example. 3600 IN A 10.53.0.3
+ update add primaries.ext.dom18.zones.catalog1.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: invalid record in catalog zone - primaries.dom17.zones.catalog1.example IN A (failure) - ignoring" &&
+wait_for_message ns2/named.run "catz: adding zone 'dom17.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "catz: adding zone 'dom18.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom17.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" &&
+wait_for_message ns2/named.run "transfer of 'dom18.example/IN/default' from 10.53.0.3#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# The "primaries" custom property for dom17.example. was added using the legacy
+# syntax into a version 2 catalog1 zone, so we expect that it was ignored, no
+# override of the default setting happened, and dom17.example. was transferred
+# from the ns1 primary (the default).
+n=$((n+1))
+echo_i "checking that dom17.example. is served by secondary and that it's the one from ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom17.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# The "primaries" custom property for dom18.example. was added using a supported
+# syntax into a version 2 catalog1 zone, so we expect that it was processed,
+# will override the default setting, and dom18.example. was transferred
+# from the ns3 primary.
+n=$((n+1))
+echo_i "checking that dom18.example. is served by secondary and that it's the one from ns3 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom18.example. dig.out.test$n || ret=1
+grep "192.0.2.2" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "deleting domain dom17.example. and dom18.example. from catalog1 ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update delete dom17.zones.catalog1.example. 3600 IN PTR dom17.example.
+ update delete dom18.zones.catalog1.example. 3600 IN PTR dom18.example.
+ update delete primaries.dom17.zones.catalog1.example. 3600 IN A 10.53.0.3
+ update delete primaries.ext.dom18.zones.catalog1.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: deleting zone 'dom17.example' from catalog 'catalog1.example' - success" &&
+wait_for_message ns2/named.run "catz: deleting zone 'dom18.example' from catalog 'catalog1.example' - success" &&
+wait_for_message ns2/named.run "zone_shutdown: zone dom17.example/IN/default: shutting down" &&
+wait_for_message ns2/named.run "zone_shutdown: zone dom18.example/IN/default: shutting down" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom17.example. is not served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom17.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom18.example. is not served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom18.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "adding domains dom17.example. and dom18.example. to catalog2 zone with ns3 as custom primary using different custom properties syntax ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update add dom17.zones.catalog2.example. 3600 IN PTR dom17.example.
+ update add dom18.zones.catalog2.example. 3600 IN PTR dom18.example.
+ update add primaries.dom17.zones.catalog2.example. 3600 IN A 10.53.0.3
+ update add primaries.ext.dom18.zones.catalog2.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: invalid record in catalog zone - primaries.ext.dom18.zones.catalog2.example IN A (failure) - ignoring" &&
+wait_for_message ns2/named.run "catz: adding zone 'dom17.example' from catalog 'catalog2.example'" &&
+wait_for_message ns2/named.run "catz: adding zone 'dom18.example' from catalog 'catalog2.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom17.example/IN/default' from 10.53.0.3#${PORT}: Transfer status: success" &&
+wait_for_message ns2/named.run "transfer of 'dom18.example/IN/default' from 10.53.0.1#${EXTRAPORT1}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# The "primaries" custom property for dom17.example. was added using a supported
+# syntax into a version 1 catalog1 zone, so we expect that it was processed,
+# will override the default setting, and dom17.example. was transferred
+# from the ns3 primary.
+n=$((n+1))
+echo_i "checking that dom17.example. is served by secondary and that it's the one from ns3 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom17.example. dig.out.test$n || ret=1
+grep "192.0.2.2" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# The "primaries" custom property for dom18.example. was added using the new
+# syntax into a version 1 catalog1 zone, so we expect that it was ignored, no
+# override of the default setting happened, and dom18.example. was transferred
+# from the ns1 primary (the default).
+n=$((n+1))
+echo_i "checking that dom18.example. is served by secondary and that it's the one from ns1 ($n)"
+ret=0
+wait_for_a @10.53.0.2 dom18.example. dig.out.test$n || ret=1
+grep "192.0.2.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "deleting domain dom17.example. and dom18.example. from catalog2 ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update delete dom17.zones.catalog2.example. 3600 IN PTR dom17.example.
+ update delete dom18.zones.catalog2.example. 3600 IN PTR dom18.example.
+ update delete primaries.dom17.zones.catalog2.example. 3600 IN A 10.53.0.3
+ update delete primaries.ext.dom18.zones.catalog2.example. 3600 IN A 10.53.0.3
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: deleting zone 'dom17.example' from catalog 'catalog2.example' - success" &&
+wait_for_message ns2/named.run "catz: deleting zone 'dom18.example' from catalog 'catalog2.example' - success" &&
+wait_for_message ns2/named.run "zone_shutdown: zone dom17.example/IN/default: shutting down" &&
+wait_for_message ns2/named.run "zone_shutdown: zone dom18.example/IN/default: shutting down" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom17.example. is not served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom17.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that dom18.example. is not served by secondary ($n)"
+ret=0
+wait_for_no_soa @10.53.0.2 dom18.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+n=$((n+1))
+echo_i "checking that reconfig can delete and restore catalog zone configuration ($n)"
+ret=0
+copy_setports ns2/named2.conf.in ns2/named.conf
+rndccmd 10.53.0.2 reconfig || ret=1
+copy_setports ns2/named1.conf.in ns2/named.conf
+rndccmd 10.53.0.2 reconfig || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#########################################################################
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Adding a dom19.example. to primary via RNDC ($n)"
+ret=0
+# enough initial content for IXFR response when TXT record is added below
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom19.example.db
+echo "@ 3600 IN NS invalid." >> ns1/dom19.example.db
+echo "foo 3600 IN TXT some content here" >> ns1/dom19.example.db
+echo "bar 3600 IN TXT some content here" >> ns1/dom19.example.db
+echo "xxx 3600 IN TXT some content here" >> ns1/dom19.example.db
+echo "yyy 3600 IN TXT some content here" >> ns1/dom19.example.db
+rndccmd 10.53.0.1 addzone dom19.example. in default '{ type primary; file "dom19.example.db"; allow-transfer { key tsig_key; }; allow-update { any; }; notify explicit; also-notify { 10.53.0.2; }; };' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "add an entry to the restored catalog zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add 09da0a318e5333a9a7f6c14c385d69f6933e8b72.zones.catalog1.example. 3600 IN PTR dom19.example.
+ update add label1.primaries.ext.09da0a318e5333a9a7f6c14c385d69f6933e8b72.zones.catalog1.example. 3600 IN A 10.53.0.1
+ update add label1.primaries.ext.09da0a318e5333a9a7f6c14c385d69f6933e8b72.zones.catalog1.example. 3600 IN TXT "tsig_key"
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom19.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "transfer of 'dom19.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+n=$((n+1))
+echo_i "Adding a domain tls1.example. to primary via RNDC ($n)"
+ret=0
+# enough initial content for IXFR response when TXT record is added below
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/tls1.example.db
+echo "@ 3600 IN NS invalid." >> ns1/tls1.example.db
+echo "foo 3600 IN TXT some content here" >> ns1/tls1.example.db
+echo "bar 3600 IN TXT some content here" >> ns1/tls1.example.db
+echo "xxx 3600 IN TXT some content here" >> ns1/tls1.example.db
+echo "yyy 3600 IN TXT some content here" >> ns1/tls1.example.db
+rndccmd 10.53.0.1 addzone tls1.example. in default '{ type primary; file "tls1.example.db"; allow-transfer transport tls { key tsig_key; }; allow-update { any; }; notify explicit; also-notify { 10.53.0.4; }; };' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that tls1.example. is now served by primary ($n)"
+ret=0
+wait_for_soa @10.53.0.1 tls1.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns4/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Adding domain tls1.example. to catalog-tls zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add 1ba056ba375209a66a2c9a0617b1df714b998112.zones.catalog-tls.example. 3600 IN PTR tls1.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+wait_for_message ns4/named.run "catz: adding zone 'tls1.example' from catalog 'catalog-tls.example'" &&
+wait_for_message ns4/named.run "transfer of 'tls1.example/IN' from 10.53.0.1#${TLSPORT}: Transfer status: success" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that tls1.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.4 tls1.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+# GL #3777
+nextpart ns4/named.run >/dev/null
+
+n=$((n+1))
+echo_i "Adding domain self.example. to catalog-self zone without updating the serial ($n)"
+ret=0
+echo "self.zones.catalog-self.example. 3600 IN PTR self.example." >> ns4/catalog-self.example.db
+rndccmd 10.53.0.4 reload || ret=1
+
+n=$((n+1))
+echo_i "Issuing another rndc reload command after 1 second ($n)"
+sleep 1
+rndccmd 10.53.0.4 reload || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##########################################################################
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/catz/tests_sh_catz.py b/bin/tests/system/catz/tests_sh_catz.py
new file mode 100644
index 0000000..eae546f
--- /dev/null
+++ b/bin/tests/system/catz/tests_sh_catz.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_catz(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/cds/checkmtime.pl b/bin/tests/system/cds/checkmtime.pl
new file mode 100644
index 0000000..be53584
--- /dev/null
+++ b/bin/tests/system/cds/checkmtime.pl
@@ -0,0 +1,18 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+my $target = shift;
+my $file = shift;
+my $mtime = time - (stat $file)[9];
+die "bad mtime $mtime"
+ unless ($mtime - $target >= 0 && $mtime - $target < 60);
diff --git a/bin/tests/system/cds/checktime.pl b/bin/tests/system/cds/checktime.pl
new file mode 100644
index 0000000..d85fd91
--- /dev/null
+++ b/bin/tests/system/cds/checktime.pl
@@ -0,0 +1,27 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+use warnings;
+
+my $target = shift;
+my $notbefore;
+my $inception;
+while (<>) {
+ $notbefore = $1 if m{^.* must not be signed before \d+ [(](\d+)[)]};
+ $inception = $1 if m{^.* inception time \d+ [(](\d+)[)]};
+}
+die "missing notbefore time" unless $notbefore;
+die "missing inception time" unless $inception;
+my $delta = $inception - $notbefore;
+die "bad inception time $delta" unless abs($delta - $target) <= 10;
diff --git a/bin/tests/system/cds/clean.sh b/bin/tests/system/cds/clean.sh
new file mode 100644
index 0000000..b9743a5
--- /dev/null
+++ b/bin/tests/system/cds/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f CDNSKEY* CDS* DS*
+rm -f K*
+rm -f UP*
+rm -f brk.*
+rm -f db.*
+rm -f dsset-*
+rm -f empty
+rm -f sig.*
+rm -f vars.sh
+rm -f err* out* xerr xout
diff --git a/bin/tests/system/cds/mangle.pl b/bin/tests/system/cds/mangle.pl
new file mode 100644
index 0000000..9268cc0
--- /dev/null
+++ b/bin/tests/system/cds/mangle.pl
@@ -0,0 +1,19 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+my $re = $ARGV[0];
+shift;
+while (<>) {
+ s{($re)........}{${1}00000000};
+ print;
+}
diff --git a/bin/tests/system/cds/setup.sh b/bin/tests/system/cds/setup.sh
new file mode 100644
index 0000000..6de5de5
--- /dev/null
+++ b/bin/tests/system/cds/setup.sh
@@ -0,0 +1,138 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+set -u
+
+touch empty
+
+Z=cds.test
+
+keyz=$($KEYGEN -q -a $DEFAULT_ALGORITHM $Z)
+key1=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK $Z)
+key2=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK $Z)
+
+idz=$(keyfile_to_key_id $keyz)
+id1=$(keyfile_to_key_id $key1)
+id2=$(keyfile_to_key_id $key2)
+
+cat <<EOF >vars.sh
+Z=$Z
+key1=$key1
+key2=$key2
+idz=$idz
+id1=$id1
+id2=$id2
+EOF
+
+tac() {
+ $PERL -e 'print reverse <>'
+}
+
+convert() {
+ key=$1
+ n=$2
+ $DSFROMKEY -12 $key >DS.$n
+ grep " ${DEFAULT_ALGORITHM_NUMBER} 1 " DS.$n >DS.$n-1
+ grep " ${DEFAULT_ALGORITHM_NUMBER} 2 " DS.$n >DS.$n-2
+ sed 's/ IN DS / IN CDS /' <DS.$n >>CDS.$n
+ sed 's/ IN DS / IN CDS /' <DS.$n-1 >>CDS.$n-1
+ sed 's/ IN DS / IN CDS /' <DS.$n-2 >>CDS.$n-2
+ sed 's/ IN DNSKEY / IN CDNSKEY /' <$key.key >CDNSKEY.$n
+ sed 's/ IN DS / 3600 IN DS /' <DS.$n >DS.ttl$n
+ sed 's/ IN DS / 7200 IN DS /' <DS.$n >DS.ttlong$n
+ tac <DS.$n >DS.rev$n
+}
+convert $key1 1
+convert $key2 2
+
+# consistent order wrt IDs
+sort DS.1 DS.2 >DS.both
+
+cp DS.1 DS.inplace
+$PERL -we 'utime time, time - 7200, "DS.inplace" or die'
+
+mangle="$PERL mangle.pl"
+
+$mangle " IN DS $id1 ${DEFAULT_ALGORITHM_NUMBER} 1 " <DS.1 >DS.broke1
+$mangle " IN DS $id1 ${DEFAULT_ALGORITHM_NUMBER} 2 " <DS.1 >DS.broke2
+$mangle " IN DS $id1 ${DEFAULT_ALGORITHM_NUMBER} [12] " <DS.1 >DS.broke12
+
+sed 's/^/update add /
+$a\
+send
+' <DS.2 >UP.add2
+
+sed 's/^/update del /
+$a\
+send
+' <DS.1 >UP.del1
+
+cat UP.add2 UP.del1 | sed 3d >UP.swap
+
+sed 's/ add \(.*\) IN DS / add \1 3600 IN DS /' <UP.swap >UP.swapttl
+
+sign() {
+ cat >db.$1
+ $SIGNER >/dev/null \
+ -S -O full -o $Z -f sig.$1 db.$1
+}
+
+sign null <<EOF
+\$TTL 1h
+@ SOA localhost. root.localhost. (
+ 1 ; serial
+ 1h ; refresh
+ 1h ; retry
+ 1w ; expiry
+ 1h ; minimum
+ )
+;
+ NS localhost.
+;
+EOF
+
+cat sig.null CDS.1 >brk.unsigned-cds
+
+cat db.null CDS.1 | sign cds.1
+cat db.null CDS.2 | sign cds.2
+cat db.null CDS.1 CDS.2 | sign cds.both
+
+tac <sig.cds.1 >sig.cds.rev1
+
+cat db.null CDNSKEY.2 | sign cdnskey.2
+cat db.null CDS.2 CDNSKEY.2 | sign cds.cdnskey.2
+cat db.null CDS.1 CDNSKEY.2 | sign cds1.cdnskey2
+
+cat db.null CDS.2-1 | sign cds.2.sha1
+cat db.null CDS.2-1 CDNSKEY.2 | sign cds.cdnskey.2.sha1
+
+$mangle '\s+IN\s+RRSIG\s+CDS .* '$idz' '$Z'\. ' \
+ <sig.cds.1 >brk.rrsig.cds.zsk
+$mangle '\s+IN\s+RRSIG\s+CDS .* '$id1' '$Z'\. ' \
+ <sig.cds.1 >brk.rrsig.cds.ksk
+
+$mangle " IN CDS $id1 ${DEFAULT_ALGORITHM_NUMBER} 1 " <db.cds.1 |
+sign cds-mangled
+
+bad=$($PERL -le "print ($id1 ^ 255);")
+sed "s/IN CDS $id1 ${DEFAULT_ALGORITHM_NUMBER} 1 /IN CDS $bad ${DEFAULT_ALGORITHM_NUMBER} 1 /" <db.cds.1 |
+sign bad-digests
+
+sed "/IN CDS $id1 ${DEFAULT_ALGORITHM_NUMBER} /p;s//IN CDS $bad $ALTERNATIVE_ALGORITHM_NUMBER /" <db.cds.1 |
+sign bad-algos
+
+rm -f dsset-*
diff --git a/bin/tests/system/cds/tests.sh b/bin/tests/system/cds/tests.sh
new file mode 100644
index 0000000..2eb092f
--- /dev/null
+++ b/bin/tests/system/cds/tests.sh
@@ -0,0 +1,260 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+fail() {
+ echo_i "failed"
+ status=$((status + 1))
+}
+
+runcmd() {
+ ("$@" 1> out.$n 2> err.$n; echo $?) || true
+}
+
+testcase() {
+ n=$((n + 1))
+ echo_i "$name ($n)"
+ expect=$1
+ shift
+ result=$(runcmd "$@")
+ check_stdout
+ check_stderr
+ if [ "$expect" -ne "$result" ]; then
+ echo_d "exit status does not match $expect"
+ fail
+ fi
+ unset name err out
+}
+
+check_stderr() {
+ if [ -n "${err:=}" ]; then
+ grep -E "$err" err.$n >/dev/null && return 0
+ echo_d "stderr did not match '$err'"
+ else
+ [ -s err.$n ] || return 0
+ fi
+ cat err.$n | cat_d
+ fail
+}
+
+check_stdout() {
+ diff out.$n "${out:-empty}" >/dev/null && return
+ echo_d "stdout did not match '$out'"
+ ( echo "wanted"
+ cat "$out"
+ echo "got"
+ cat out.$n
+ ) | cat_d
+ fail
+}
+
+Z=cds.test
+
+name='usage'
+err='Usage'
+testcase 1 $CDS
+
+name='need a DS file'
+err='DS pathname'
+testcase 1 $CDS $Z
+
+name='name of dsset in directory'
+err="./dsset-$Z.: file not found"
+testcase 1 $CDS -d . $Z
+
+name='load a file'
+err='could not find DS records'
+testcase 1 $CDS -d empty $Z
+
+name='load DS records'
+err='path to file containing child data must be specified'
+testcase 1 $CDS -d DS.1 $Z
+
+name='missing DNSKEY'
+err='could not find signed DNSKEY RRset'
+testcase 1 $CDS -f db.null -d DS.1 $Z
+
+name='sigs too old'
+err='could not validate child DNSKEY RRset'
+testcase 1 $CDS -f sig.null -d DS.1 $Z
+
+name='sigs too old, verbosely'
+err='skip RRSIG by key [0-9]+: too old'
+testcase 1 $CDS -v1 -f sig.null -d DS.1 $Z
+
+name='old sigs are allowed'
+err='found RRSIG by key'
+out=DS.1
+testcase 0 $CDS -v1 -s -7200 -f sig.null -d DS.1 $Z
+
+name='no CDS/CDNSKEY records'
+out=DS.1
+testcase 0 $CDS -s -7200 -f sig.null -d DS.1 $Z
+
+name='no child records, verbosely'
+err='has neither CDS nor CDNSKEY records'
+out=DS.1
+testcase 0 $CDS -v1 -s -7200 -f sig.null -d DS.1 $Z
+
+name='unsigned CDS'
+err='missing RRSIG CDS records'
+testcase 1 $CDS -f brk.unsigned-cds -d DS.1 $Z
+
+name='correct signature inception time'
+$CDS -v3 -s -7200 -f sig.cds.1 -d DS.1 $Z 1>xout 2>xerr
+testcase 0 $PERL checktime.pl 3600 xerr
+
+name='in-place reads modification time'
+testcase 0 $CDS -a1 -a2 -f sig.cds.1 -i.bak -d DS.inplace $Z
+
+name='in-place output correct modification time'
+testcase 0 $PERL checkmtime.pl 3600 DS.inplace
+
+name='in-place backup correct modification time'
+testcase 0 $PERL checkmtime.pl 7200 DS.inplace.bak
+
+name='in-place correct output'
+testcase 0 diff DS.1 DS.inplace
+
+name='in-place backup unmodified'
+testcase 0 diff DS.1 DS.inplace.bak
+
+name='one mangled DS'
+err='found RRSIG by key'
+out=DS.1
+testcase 0 $CDS -v1 -a1 -a2 -s -7200 -f sig.cds.1 -d DS.broke1 $Z
+
+name='other mangled DS'
+err='found RRSIG by key'
+out=DS.1
+testcase 0 $CDS -v1 -a1 -a2 -s -7200 -f sig.cds.1 -d DS.broke2 $Z
+
+name='both mangled DS'
+err='could not validate child DNSKEY RRset'
+testcase 1 $CDS -v1 -a1 -a2 -s -7200 -f sig.cds.1 -d DS.broke12 $Z
+
+name='mangle RRSIG CDS by ZSK'
+err='found RRSIG by key'
+out=DS.1
+testcase 0 $CDS -v1 -a1 -a2 -s -7200 -f brk.rrsig.cds.zsk -d DS.1 $Z
+
+name='mangle RRSIG CDS by KSK'
+err='could not validate child CDS RRset'
+testcase 1 $CDS -v1 -s -7200 -f brk.rrsig.cds.ksk -d DS.1 $Z
+
+name='mangle CDS 1'
+err='could not validate child DNSKEY RRset with new DS records'
+testcase 1 $CDS -a1 -a2 -s -7200 -f sig.cds-mangled -d DS.1 $Z
+
+name='inconsistent digests'
+err='do not cover each key with the same set of digest types'
+testcase 1 $CDS -a1 -a2 -s -7200 -f sig.bad-digests -d DS.1 $Z
+
+name='inconsistent algorithms'
+err='missing signature for algorithm'
+testcase 1 $CDS -s -7200 -f sig.bad-algos -d DS.1 $Z
+
+name='add DS records'
+out=DS.both
+$CDS -a1 -a2 -s -7200 -f sig.cds.both -d DS.1 $Z >DS.out
+# sort to allow for numerical vs lexical order of key tags
+testcase 0 sort DS.out
+
+name='update add'
+out=UP.add2
+testcase 0 $CDS -a1 -a2 -u -s -7200 -f sig.cds.both -d DS.1 $Z
+
+name='remove DS records'
+out=DS.2
+testcase 0 $CDS -a1 -a2 -s -7200 -f sig.cds.2 -d DS.both $Z
+
+name='update del'
+out=UP.del1
+testcase 0 $CDS -a1 -a2 -u -s -7200 -f sig.cds.2 -d DS.both $Z
+
+name='swap DS records'
+out=DS.2
+testcase 0 $CDS -a1 -a2 -s -7200 -f sig.cds.2 -d DS.1 $Z
+
+name='update swap'
+out=UP.swap
+testcase 0 $CDS -a1 -a2 -u -s -7200 -f sig.cds.2 -d DS.1 $Z
+
+name='TTL from -T'
+out=DS.ttl2
+testcase 0 $CDS -a1 -a2 -T 3600 -s -7200 -f sig.cds.2 -d DS.1 $Z
+
+name='update TTL from -T'
+out=UP.swapttl
+testcase 0 $CDS -a1 -a2 -u -T 3600 -s -7200 -f sig.cds.2 -d DS.1 $Z
+
+name='update TTL from dsset'
+out=UP.swapttl
+testcase 0 $CDS -a1 -a2 -u -s -7200 -f sig.cds.2 -d DS.ttl1 $Z
+
+name='TTL from -T overrides dsset'
+out=DS.ttlong2
+testcase 0 $CDS -a1 -a2 -T 7200 -s -7200 -f sig.cds.2 -d DS.ttl1 $Z
+
+name='stable DS record order (changes)'
+out=DS.1
+testcase 0 $CDS -a1 -a2 -s -7200 -f sig.cds.rev1 -d DS.2 $Z
+
+name='CDNSKEY default algorithm'
+out=DS.2-2
+testcase 0 $CDS -s -7200 -f sig.cdnskey.2 -d DS.1 $Z
+
+name='CDNSKEY SHA1'
+out=DS.2-1
+testcase 0 $CDS -a SHA1 -s -7200 -f sig.cdnskey.2 -d DS.1 $Z
+
+name='CDNSKEY two algorithms'
+out=DS.2
+testcase 0 $CDS -a SHA1 -a SHA256 -s -7200 -f sig.cdnskey.2 -d DS.1 $Z
+
+name='CDNSKEY two algorithms, reversed'
+out=DS.2
+testcase 0 $CDS -a SHA256 -a SHA1 -s -7200 -f sig.cdnskey.2 -d DS.1 $Z
+
+name='CDNSKEY and CDS'
+out=DS.2
+testcase 0 $CDS -a1 -a2 -s -7200 -f sig.cds.cdnskey.2 -d DS.1 $Z
+
+name='prefer CDNSKEY'
+out=DS.2-2
+testcase 0 $CDS -D -s -7200 -f sig.cds1.cdnskey2 -d DS.1 $Z
+
+name='CDS subset default (SHA-256)'
+out=DS.2-2
+testcase 0 $CDS -s -7200 -f sig.cds.2 -d DS.1 $Z
+
+name='CDS subset replace SHA1 with SHA2'
+out=DS.2-2
+testcase 0 $CDS -s -7200 -f sig.cds.cdnskey.2.sha1 -d DS.1 $Z
+
+name='CDS subset mismatch'
+err='do not match any -a digest types'
+testcase 1 $CDS -s -7200 -f sig.cds.2.sha1 -d DS.1 $Z
+
+name='CDS algorithm unavailable, use CDNSKEY'
+err='using CDNSKEY instead'
+out=DS.2-2
+testcase 0 $CDS -v1 -a SHA256 -s -7200 -f sig.cds.cdnskey.2.sha1 -d DS.1 $Z
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/cds/tests_sh_cds.py b/bin/tests/system/cds/tests_sh_cds.py
new file mode 100644
index 0000000..d00a8ae
--- /dev/null
+++ b/bin/tests/system/cds/tests_sh_cds.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_cds(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/chain/README b/bin/tests/system/chain/README
new file mode 100644
index 0000000..649142e
--- /dev/null
+++ b/bin/tests/system/chain/README
@@ -0,0 +1,22 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+ns1 is the root server.
+
+ns2 and ns5 are both authoritative servers.
+
+ans3 is a mock authoritative server that can return various broken
+responses.
+
+ans4 is a mock authoritative server that can return CNAME or DNAME
+responses of arbitrary size in arbitrary order.
+
+ns7 is the resolver under test.
diff --git a/bin/tests/system/chain/ans3/ans.pl b/bin/tests/system/chain/ans3/ans.pl
new file mode 100644
index 0000000..271b2a4
--- /dev/null
+++ b/bin/tests/system/chain/ans3/ans.pl
@@ -0,0 +1,131 @@
+#!/usr/bin/env perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+use warnings;
+
+use IO::File;
+use Getopt::Long;
+use Net::DNS::Nameserver;
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+my $localaddr = "10.53.0.3";
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $verbose = 0;
+my $ttl = 60;
+my $zone = "example.broken";
+my $nsname = "ns3.$zone";
+my $synth = "synth-then-dname.$zone";
+my $synth2 = "synth2-then-dname.$zone";
+
+sub reply_handler {
+ my ($qname, $qclass, $qtype, $peerhost, $query, $conn) = @_;
+ my ($rcode, @ans, @auth, @add);
+
+ print ("request: $qname/$qtype\n");
+ STDOUT->flush();
+
+ if ($qname eq "example.broken") {
+ if ($qtype eq "SOA") {
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass SOA . . 0 0 0 0 0");
+ push @ans, $rr;
+ } elsif ($qtype eq "NS") {
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass NS $nsname");
+ push @ans, $rr;
+ $rr = new Net::DNS::RR("$nsname $ttl $qclass A $localaddr");
+ push @add, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "cname-to-$synth2") {
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name.$synth2");
+ push @ans, $rr;
+ $rr = new Net::DNS::RR("name.$synth2 $ttl $qclass CNAME name");
+ push @ans, $rr;
+ $rr = new Net::DNS::RR("$synth2 $ttl $qclass DNAME .");
+ push @ans, $rr;
+ $rcode = "NOERROR";
+ } elsif ($qname eq "$synth" || $qname eq "$synth2") {
+ if ($qtype eq "DNAME") {
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass DNAME .");
+ push @ans, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "name.$synth") {
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name.");
+ push @ans, $rr;
+ $rr = new Net::DNS::RR("$synth $ttl $qclass DNAME .");
+ push @ans, $rr;
+ $rcode = "NOERROR";
+ } elsif ($qname eq "name.$synth2") {
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name.");
+ push @ans, $rr;
+ $rr = new Net::DNS::RR("$synth2 $ttl $qclass DNAME .");
+ push @ans, $rr;
+ $rcode = "NOERROR";
+ # The following three code branches referring to the "example.dname"
+ # zone are necessary for the resolver variant of the CVE-2021-25215
+ # regression test to work. A named instance cannot be used for
+ # serving the DNAME records below as a version of BIND vulnerable to
+ # CVE-2021-25215 would crash while answering the queries asked by
+ # the tested resolver.
+ } elsif ($qname eq "ns3.example.dname") {
+ if ($qtype eq "A") {
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass A 10.53.0.3");
+ push @ans, $rr;
+ }
+ if ($qtype eq "AAAA") {
+ my $rr = new Net::DNS::RR("example.dname. $ttl $qclass SOA . . 0 0 0 0 $ttl");
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "self.example.self.example.dname") {
+ my $rr = new Net::DNS::RR("self.example.dname. $ttl $qclass DNAME dname.");
+ push @ans, $rr;
+ $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME self.example.dname.");
+ push @ans, $rr;
+ $rcode = "NOERROR";
+ } elsif ($qname eq "self.example.dname") {
+ if ($qtype eq "DNAME") {
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass DNAME dname.");
+ push @ans, $rr;
+ }
+ $rcode = "NOERROR";
+ } else {
+ $rcode = "REFUSED";
+ }
+ return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
+}
+
+GetOptions(
+ 'port=i' => \$localport,
+ 'verbose!' => \$verbose,
+);
+
+my $ns = Net::DNS::Nameserver->new(
+ LocalAddr => $localaddr,
+ LocalPort => $localport,
+ ReplyHandler => \&reply_handler,
+ Verbose => $verbose,
+);
+
+$ns->main_loop;
diff --git a/bin/tests/system/chain/ans4/README.anspy b/bin/tests/system/chain/ans4/README.anspy
new file mode 100644
index 0000000..7cb0bf0
--- /dev/null
+++ b/bin/tests/system/chain/ans4/README.anspy
@@ -0,0 +1,24 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+REQUIREMENTS
+ans.py requires at least dnspython 1.12.0.
+
+"ans.py" is a fairly simple Python script that will respond as an
+authoritative server to DNS queries. It opens a UDP socket on 10.53.0.4
+and fd92:7065:b8e:ffff::8, port 5300 (or PORT) (these are for DNS queries)
+and a TCP socket addresses on 10.53.0.4 at port 5301 (or EXTRAPORT1)
+(this is the control channel).
+
+Please note that all functionality and formatting are subject to change as
+we determine what features the tool will need.
+
+"ans.py" will respond to queries as follows: TBD
diff --git a/bin/tests/system/chain/ans4/ans.py b/bin/tests/system/chain/ans4/ans.py
new file mode 100755
index 0000000..839067f
--- /dev/null
+++ b/bin/tests/system/chain/ans4/ans.py
@@ -0,0 +1,386 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+############################################################################
+# ans.py: See README.anspy for details.
+############################################################################
+
+from __future__ import print_function
+import os
+import sys
+import signal
+import socket
+import select
+from datetime import datetime, timedelta
+import functools
+
+import dns, dns.message, dns.query
+from dns.rdatatype import *
+from dns.rdataclass import *
+from dns.rcode import *
+from dns.name import *
+
+############################################################################
+# set up the RRs to be returned in the next answer
+#
+# the message contains up to two pipe-separated ('|') fields.
+#
+# the first field of the message is a comma-separated list
+# of actions indicating what to put into the answer set
+# (e.g., a dname, a cname, another cname, etc)
+#
+# supported actions:
+# - cname (cname from the current name to a new one in the same domain)
+# - dname (dname to a new domain, plus a synthesized cname)
+# - xname ("external" cname, to a new name in a new domain)
+#
+# example: xname, dname, cname represents a CNAME to an external
+# domain which is then answered by a DNAME and synthesized
+# CNAME pointing to yet another domain, which is then answered
+# by a CNAME within the same domain, and finally an answer
+# to the query. each RR in the answer set has a corresponding
+# RRSIG. these signatures are not valid, but will exercise the
+# response parser.
+#
+# the second field is a comma-separated list of which RRs in the
+# answer set to include in the answer, in which order. if prepended
+# with 's', the number indicates which signature to include.
+#
+# examples: for the answer set "cname, cname, cname", an rr set
+# '1, s1, 2, s2, 3, s3, 4, s4' indicates that all four RRs should
+# be included in the answer, with siagntures, in the original
+# order, while 4, s4, 3, s3, 2, s2, 1, s1' indicates the order
+# should be reversed, 's3, s3, s3, s3' indicates that the third
+# RRSIG should be repeated four times and everything else should
+# be omitted, and so on.
+#
+# if there is no second field (i.e., no pipe symbol appears in
+# the line) , the default is to send all answers and signatures.
+# if a pipe symbol exists but the second field is empty, then
+# nothing is sent at all.
+############################################################################
+actions = []
+rrs = []
+
+
+def ctl_channel(msg):
+ global actions, rrs
+
+ msg = msg.splitlines().pop(0)
+ print("received control message: %s" % msg)
+
+ msg = msg.split(b"|")
+ if len(msg) == 0:
+ return
+
+ actions = [x.strip() for x in msg[0].split(b",")]
+ n = functools.reduce(
+ lambda n, act: (n + (2 if act == b"dname" else 1)), [0] + actions
+ )
+
+ if len(msg) == 1:
+ rrs = []
+ for i in range(n):
+ for b in [False, True]:
+ rrs.append((i, b))
+ return
+
+ rlist = [x.strip() for x in msg[1].split(b",")]
+ rrs = []
+ for item in rlist:
+ if item[0] == b"s"[0]:
+ i = int(item[1:].strip()) - 1
+ if i > n:
+ print("invalid index %d" + (i + 1))
+ continue
+ rrs.append((int(item[1:]) - 1, True))
+ else:
+ i = int(item) - 1
+ if i > n:
+ print("invalid index %d" % (i + 1))
+ continue
+ rrs.append((i, False))
+
+
+############################################################################
+# Respond to a DNS query.
+############################################################################
+def create_response(msg):
+ m = dns.message.from_wire(msg)
+ qname = m.question[0].name.to_text()
+ labels = qname.lower().split(".")
+ wantsigs = True if m.ednsflags & dns.flags.DO else False
+
+ # get qtype
+ rrtype = m.question[0].rdtype
+ typename = dns.rdatatype.to_text(rrtype)
+
+ # for 'www.example.com.'...
+ # - name is 'www'
+ # - domain is 'example.com.'
+ # - sld is 'example'
+ # - tld is 'com.'
+ name = labels.pop(0)
+ domain = ".".join(labels)
+ sld = labels.pop(0)
+ tld = ".".join(labels)
+
+ print("query: " + qname + "/" + typename)
+ print("domain: " + domain)
+
+ # default answers, depending on QTYPE.
+ # currently only A, AAAA, TXT and NS are supported.
+ ttl = 86400
+ additionalA = "10.53.0.4"
+ additionalAAAA = "fd92:7065:b8e:ffff::4"
+ if typename == "A":
+ final = "10.53.0.4"
+ elif typename == "AAAA":
+ final = "fd92:7065:b8e:ffff::4"
+ elif typename == "TXT":
+ final = "Some\ text\ here"
+ elif typename == "NS":
+ domain = qname
+ final = "ns1.%s" % domain
+ else:
+ final = None
+
+ # RRSIG rdata - won't validate but will exercise response parsing
+ t = datetime.now()
+ delta = timedelta(30)
+ t1 = t - delta
+ t2 = t + delta
+ inception = t1.strftime("%Y%m%d000000")
+ expiry = t2.strftime("%Y%m%d000000")
+ sigdata = "OCXH2De0yE4NMTl9UykvOsJ4IBGs/ZIpff2rpaVJrVG7jQfmj50otBAp A0Zo7dpBU4ofv0N/F2Ar6LznCncIojkWptEJIAKA5tHegf/jY39arEpO cevbGp6DKxFhlkLXNcw7k9o7DSw14OaRmgAjXdTFbrl4AiAa0zAttFko Tso="
+
+ # construct answer set.
+ answers = []
+ sigs = []
+ curdom = domain
+ curname = name
+ i = 0
+
+ for action in actions:
+ if name != "test":
+ continue
+ if action == b"xname":
+ owner = curname + "." + curdom
+ newname = "cname%d" % i
+ i += 1
+ newdom = "domain%d.%s" % (i, tld)
+ i += 1
+ target = newname + "." + newdom
+ print("add external CNAME %s to %s" % (owner, target))
+ answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target))
+ rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % (
+ ttl,
+ expiry,
+ inception,
+ domain,
+ sigdata,
+ )
+ print("add external RRISG(CNAME) %s to %s" % (owner, target))
+ sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
+ curname = newname
+ curdom = newdom
+ continue
+
+ if action == b"cname":
+ owner = curname + "." + curdom
+ newname = "cname%d" % i
+ target = newname + "." + curdom
+ i += 1
+ print("add CNAME %s to %s" % (owner, target))
+ answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target))
+ rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % (
+ ttl,
+ expiry,
+ inception,
+ domain,
+ sigdata,
+ )
+ print("add RRSIG(CNAME) %s to %s" % (owner, target))
+ sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
+ curname = newname
+ continue
+
+ if action == b"dname":
+ owner = curdom
+ newdom = "domain%d.%s" % (i, tld)
+ i += 1
+ print("add DNAME %s to %s" % (owner, newdom))
+ answers.append(dns.rrset.from_text(owner, ttl, IN, DNAME, newdom))
+ rrsig = "DNAME 5 3 %d %s %s 12345 %s %s" % (
+ ttl,
+ expiry,
+ inception,
+ domain,
+ sigdata,
+ )
+ print("add RRSIG(DNAME) %s to %s" % (owner, newdom))
+ sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
+ owner = curname + "." + curdom
+ target = curname + "." + newdom
+ print("add synthesized CNAME %s to %s" % (owner, target))
+ answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target))
+ rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % (
+ ttl,
+ expiry,
+ inception,
+ domain,
+ sigdata,
+ )
+ print("add synthesized RRSIG(CNAME) %s to %s" % (owner, target))
+ sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
+ curdom = newdom
+ continue
+
+ # now add the final answer
+ owner = curname + "." + curdom
+ answers.append(dns.rrset.from_text(owner, ttl, IN, rrtype, final))
+ rrsig = "%s 5 3 %d %s %s 12345 %s %s" % (
+ typename,
+ ttl,
+ expiry,
+ inception,
+ domain,
+ sigdata,
+ )
+ sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
+
+ # prepare the response and convert to wire format
+ r = dns.message.make_response(m)
+
+ if name != "test":
+ r.answer.append(answers[-1])
+ if wantsigs:
+ r.answer.append(sigs[-1])
+ else:
+ for i, sig in rrs:
+ if sig and not wantsigs:
+ continue
+ elif sig:
+ r.answer.append(sigs[i])
+ else:
+ r.answer.append(answers[i])
+
+ if typename != "NS":
+ r.authority.append(
+ dns.rrset.from_text(domain, ttl, IN, "NS", ("ns1.%s" % domain))
+ )
+ r.additional.append(
+ dns.rrset.from_text(("ns1.%s" % domain), 86400, IN, A, additionalA)
+ )
+ r.additional.append(
+ dns.rrset.from_text(("ns1.%s" % domain), 86400, IN, AAAA, additionalAAAA)
+ )
+
+ r.flags |= dns.flags.AA
+ r.use_edns()
+ return r.to_wire()
+
+
+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
+
+try:
+ ctrlport = int(os.environ["EXTRAPORT1"])
+except:
+ ctrlport = 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
+
+ctrl_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ctrl_socket.bind((ip4, ctrlport))
+ctrl_socket.listen(5)
+
+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("Control channel on %s port %d" % (ip4, ctrlport))
+print("Ctrl-c to quit")
+
+if havev6:
+ input = [query4_socket, query6_socket, ctrl_socket]
+else:
+ input = [query4_socket, ctrl_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 == ctrl_socket:
+ # Handle control channel input
+ conn, addr = s.accept()
+ print("Control channel connected")
+ while True:
+ msg = conn.recv(65535)
+ if not msg:
+ break
+ ctl_channel(msg)
+ conn.close()
+ if s == query4_socket or s == query6_socket:
+ print("Query received on %s" % (ip4 if s == query4_socket else ip6))
+ # Handle incoming queries
+ msg = s.recvfrom(65535)
+ rsp = create_response(msg[0])
+ if rsp:
+ s.sendto(rsp, msg[1])
+ if not running:
+ break
diff --git a/bin/tests/system/chain/clean.sh b/bin/tests/system/chain/clean.sh
new file mode 100755
index 0000000..57b05a7
--- /dev/null
+++ b/bin/tests/system/chain/clean.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.* named*.pid
+rm -f ns*/named.conf
+rm -f */named.memstats */named.recursing */named.lock */named.run */ans.run
+rm -f ns2/K* ns2/dsset-* ns2/*.db.signed
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/chain/ns1/named.conf.in b/bin/tests/system/chain/ns1/named.conf.in
new file mode 100644
index 0000000..5504261
--- /dev/null
+++ b/bin/tests/system/chain/ns1/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation yes;
+ notify yes;
+};
+
+zone "." { type primary; file "root.db"; };
diff --git a/bin/tests/system/chain/ns1/root.db b/bin/tests/system/chain/ns1/root.db
new file mode 100644
index 0000000..3469fb5
--- /dev/null
+++ b/bin/tests/system/chain/ns1/root.db
@@ -0,0 +1,51 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA root.domain.nil a.root.servers.nil. (
+ 2016012800 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+example.broken. NS ns3.example.broken.
+ns3.example.broken. A 10.53.0.3
+
+; for the resolver variant of the CVE-2021-25215 regression test
+example.dname. NS ns3.example.dname.
+ns3.example.dname. A 10.53.0.3
+
+domain0.nil. NS ns2.domain0.nil
+domain1.nil. NS ns2.domain0.nil
+domain2.nil. NS ns2.domain0.nil
+domain3.nil. NS ns2.domain0.nil
+domain4.nil. NS ns2.domain0.nil
+domain5.nil. NS ns2.domain0.nil
+domain6.nil. NS ns2.domain0.nil
+domain7.nil. NS ns2.domain0.nil
+domain8.nil. NS ns2.domain0.nil
+domain9.nil. NS ns2.domain0.nil
+ns2.domain0.nil. A 10.53.0.2
+ns2.domain0.nil. AAAA fd92:7065:b8e:ffff::2
+
+domain.nil. NS ns4.domain.nil
+ns4.domain.nil. A 10.53.0.4
+ns4.domain.nil. AAAA fd92:7065:b8e:ffff::4
+
+domain. NS ns4.domain.
+ns4.domain. A 10.53.0.4
diff --git a/bin/tests/system/chain/ns2/example.db b/bin/tests/system/chain/ns2/example.db
new file mode 100644
index 0000000..c13f2d2
--- /dev/null
+++ b/bin/tests/system/chain/ns2/example.db
@@ -0,0 +1,69 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+
+a.short A 10.0.0.1
+short-dname DNAME short
+a.longlonglonglonglonglonglonglonglonglonglonglonglong A 10.0.0.2
+long-dname DNAME longlonglonglonglonglonglonglonglonglonglonglonglong
+toolong-dname DNAME longlonglonglonglonglonglonglonglonglonglonglonglong
+cname CNAME a.cnamedname
+cnamedname DNAME target
+a.target A 10.0.0.3
+
+; CNAME to delegation
+; (unsigned delegations, external and internal)
+sub5 NS ns5.sub5
+ns5.sub5 A 10.53.0.5
+a CNAME a.sub5
+sub2 NS ns2.sub2
+ns2.sub2 A 10.53.0.2
+b CNAME b.sub2
+
+; (signed delegation, external and internal)
+; note: these DS records are fake and will not validate; we're only
+; testing that the resolver handles their presence in a reply correctly
+signed-sub5 NS ns5.sub5
+signed-sub5 DS 44137 8 2 1CB4F54E0B4F4F85109143113A3C679716A2377D86EB0907846A03FB 0C0A3927
+c CNAME c.signed-sub5
+signed-sub2 NS ns2.sub2
+signed-sub2 DS 44137 8 2 1CB4F54E0B4F4F85109143113A3C679716A2377D86EB0907846A03FB 0C0A3927
+d CNAME d.signed-sub2
+
+; long CNAME loop
+loop CNAME goop
+goop CNAME boop
+boop CNAME soup
+soup CNAME gump
+gump CNAME bump
+bump CNAME lump
+lump CNAME rump
+rump CNAME romp
+romp CNAME bomp
+bomp CNAME stomp
+stomp CNAME clomp
+clomp CNAME clump
+clump CNAME hunk
+hunk CNAME hank
+hank CNAME bank
+bank CNAME wank
+wank CNAME woop
+woop CNAME loop
diff --git a/bin/tests/system/chain/ns2/generic.db b/bin/tests/system/chain/ns2/generic.db
new file mode 100644
index 0000000..9d59378
--- /dev/null
+++ b/bin/tests/system/chain/ns2/generic.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 86400 SOA ns2.domain0.nil. hostmaster.ns2.nil. 0 1 1 1 1
+@ 86400 NS ns2.domain0.nil.
+ns2 86400 A 10.53.0.2
+ns2 86400 AAAA fd92:7065:b8e:ffff::2
+
+@ 86400 A 1.2.3.4
+@ 86400 AAAA 1:2:3::4
+* 86400 A 1.2.3.4
+* 86400 AAAA 1:2:3::4
+; CVE-2021-25215 regression test data
+self 86400 DNAME nil.
diff --git a/bin/tests/system/chain/ns2/named.conf.in b/bin/tests/system/chain/ns2/named.conf.in
new file mode 100644
index 0000000..922d2fa
--- /dev/null
+++ b/bin/tests/system/chain/ns2/named.conf.in
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "example" {
+ type primary;
+ file "example.db.signed";
+ allow-update { any; };
+};
+
+zone "sub2.example" {
+ type primary;
+ file "sub.db";
+};
+
+zone "signed-sub2.example" {
+ type primary;
+ file "sub.db";
+};
+
+zone "wildcard-secure.example" {
+ type primary;
+ file "wildcard-secure.example.db.signed";
+};
+
+zone "wildcard-nsec.example" {
+ type primary;
+ file "wildcard-nsec.example.db.signed";
+};
+
+zone "wildcard-nsec3.example" {
+ type primary;
+ file "wildcard-nsec3.example.db.signed";
+};
+
+zone "wildcard-nsec3-optout.example" {
+ type primary;
+ file "wildcard-nsec3-optout.example.db.signed";
+};
+
+zone "domain0.nil" { type primary; file "generic.db"; };
+zone "domain1.nil" { type primary; file "generic.db"; };
+zone "domain2.nil" { type primary; file "generic.db"; };
+zone "domain3.nil" { type primary; file "generic.db"; };
+zone "domain4.nil" { type primary; file "generic.db"; };
+zone "domain5.nil" { type primary; file "generic.db"; };
+zone "domain6.nil" { type primary; file "generic.db"; };
+zone "domain7.nil" { type primary; file "generic.db"; };
+zone "domain8.nil" { type primary; file "generic.db"; };
+zone "domain9.nil" { type primary; file "generic.db"; };
diff --git a/bin/tests/system/chain/ns2/sign.sh b/bin/tests/system/chain/ns2/sign.sh
new file mode 100644
index 0000000..90d1912
--- /dev/null
+++ b/bin/tests/system/chain/ns2/sign.sh
@@ -0,0 +1,54 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=example.
+zonefile=example.db
+signedfile=example.db.signed
+
+ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} -fk $zone)
+zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} $zone)
+$SIGNER -S -o $zone -f $signedfile $zonefile > /dev/null
+
+zone=wildcard-secure.example.
+zonefile=wildcard-secure.db
+signedfile=wildcard-secure.example.db.signed
+
+ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} -fk $zone)
+zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} $zone)
+$SIGNER -S -o $zone -f $signedfile $zonefile > /dev/null
+
+zone=wildcard-nsec.example.
+zonefile=wildcard.db
+signedfile=wildcard-nsec.example.db.signed
+
+ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} -fk $zone)
+zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} $zone)
+$SIGNER -S -o $zone -f $signedfile $zonefile > /dev/null
+
+zone=wildcard-nsec3.example.
+zonefile=wildcard.db
+signedfile=wildcard-nsec3.example.db.signed
+
+ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} -fk $zone)
+zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} $zone)
+$SIGNER -S -3 - -H 0 -o $zone -f $signedfile $zonefile > /dev/null
+
+zone=wildcard-nsec3-optout.example.
+zonefile=wildcard.db
+signedfile=wildcard-nsec3-optout.example.db.signed
+
+ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} -fk $zone)
+zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} $zone)
+$SIGNER -S -3 - -H 0 -A -o $zone -f $signedfile $zonefile > /dev/null
diff --git a/bin/tests/system/chain/ns2/sub.db b/bin/tests/system/chain/ns2/sub.db
new file mode 100644
index 0000000..ad03165
--- /dev/null
+++ b/bin/tests/system/chain/ns2/sub.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2017031001 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+d A 10.0.0.4
diff --git a/bin/tests/system/chain/ns2/wildcard-secure.db b/bin/tests/system/chain/ns2/wildcard-secure.db
new file mode 100644
index 0000000..e39237a
--- /dev/null
+++ b/bin/tests/system/chain/ns2/wildcard-secure.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2021051901 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS localhost.
+
+delegation NS localhost.
+ DS 12345 13 2 0000000000000000000000000000000000000000000000000000000000000000
+
+; CNAME pointing into a child zone
+cname CNAME delegation
+
+; wildcard CNAME pointing at a CNAME pointing into a child zone
+* CNAME cname
diff --git a/bin/tests/system/chain/ns2/wildcard.db b/bin/tests/system/chain/ns2/wildcard.db
new file mode 100644
index 0000000..cc39e9c
--- /dev/null
+++ b/bin/tests/system/chain/ns2/wildcard.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2021051901 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS localhost.
+
+delegation NS localhost.
+
+; CNAME pointing into a child zone
+cname CNAME delegation
+
+; wildcard CNAME pointing at a CNAME pointing into a child zone
+* CNAME cname
diff --git a/bin/tests/system/chain/ns5/named.conf.in b/bin/tests/system/chain/ns5/named.conf.in
new file mode 100644
index 0000000..86bbf26
--- /dev/null
+++ b/bin/tests/system/chain/ns5/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+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 no;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "sub5.example" {
+ type primary;
+ file "sub.db";
+};
+
+zone "signed-sub5.example" {
+ type primary;
+ file "sub.db";
+};
diff --git a/bin/tests/system/chain/ns5/sub.db b/bin/tests/system/chain/ns5/sub.db
new file mode 100644
index 0000000..df571fb
--- /dev/null
+++ b/bin/tests/system/chain/ns5/sub.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2017031001 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns5
+ns5 A 10.53.0.5
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+d A 10.0.0.4
diff --git a/bin/tests/system/chain/ns7/named.conf.in b/bin/tests/system/chain/ns7/named.conf.in
new file mode 100644
index 0000000..32c9b5f
--- /dev/null
+++ b/bin/tests/system/chain/ns7/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory ".";
+ 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.7; };
+ listen-on-v6 { fd92:7065:b8e:ffff::7; };
+ recursion yes;
+ allow-recursion { any; };
+ dnssec-validation yes;
+ deny-answer-aliases {
+ "example";
+ } except-from {
+ "example";
+ };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/chain/ns7/root.hint b/bin/tests/system/chain/ns7/root.hint
new file mode 100644
index 0000000..4f3f48b
--- /dev/null
+++ b/bin/tests/system/chain/ns7/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.1
diff --git a/bin/tests/system/chain/setup.sh b/bin/tests/system/chain/setup.sh
new file mode 100644
index 0000000..6f52e65
--- /dev/null
+++ b/bin/tests/system/chain/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns5/named.conf.in ns5/named.conf
+copy_setports ns7/named.conf.in ns7/named.conf
+
+cd ns2
+$SHELL sign.sh
diff --git a/bin/tests/system/chain/tests.sh b/bin/tests/system/chain/tests.sh
new file mode 100644
index 0000000..3ad8e31
--- /dev/null
+++ b/bin/tests/system/chain/tests.sh
@@ -0,0 +1,630 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+sendcmd() {
+ send 10.53.0.4 "${EXTRAPORT1}"
+}
+
+status=0
+n=0
+
+n=$((n + 1))
+echo_i "checking short DNAME from authoritative ($n)"
+ret=0
+$DIG $DIGOPTS a.short-dname.example @10.53.0.2 a > dig.out.ns2.short || ret=1
+grep "status: NOERROR" dig.out.ns2.short > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking short DNAME from recursive ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS a.short-dname.example @10.53.0.7 a > dig.out.ns4.short || ret=1
+grep "status: NOERROR" dig.out.ns4.short > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking long DNAME from authoritative ($n)"
+ret=0
+$DIG $DIGOPTS a.long-dname.example @10.53.0.2 a > dig.out.ns2.long || ret=1
+grep "status: NOERROR" dig.out.ns2.long > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking long DNAME from recursive ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS a.long-dname.example @10.53.0.7 a > dig.out.ns4.long || ret=1
+grep "status: NOERROR" dig.out.ns4.long > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking (too) long DNAME from authoritative ($n)"
+ret=0
+$DIG $DIGOPTS 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.long-dname.example @10.53.0.2 a > dig.out.ns2.toolong || ret=1
+grep "status: YXDOMAIN" dig.out.ns2.toolong > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking (too) long DNAME from recursive with cached DNAME ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.long-dname.example @10.53.0.7 a > dig.out.ns4.cachedtoolong || ret=1
+grep "status: YXDOMAIN" dig.out.ns4.cachedtoolong > /dev/null || ret=1
+grep '^long-dname\.example\..*DNAME.*long' dig.out.ns4.cachedtoolong > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking (too) long DNAME from recursive without cached DNAME ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglong.toolong-dname.example @10.53.0.7 a > dig.out.ns4.uncachedtoolong || ret=1
+grep "status: YXDOMAIN" dig.out.ns4.uncachedtoolong > /dev/null || ret=1
+grep '^toolong-dname\.example\..*DNAME.*long' dig.out.ns4.uncachedtoolong > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+find_records() {
+ owner_name="$1"
+ rr_type="$2"
+ file="$3"
+ awk '$1 == "'"$owner_name"'" && $4 == "'"$rr_type"'" { print }' < "$file"
+}
+
+count_records() {
+ owner_name="$1"
+ rr_type="$2"
+ file="$3"
+ find_records "$owner_name" "$rr_type" "$file" | wc -l
+}
+
+exactly_one_record_exists_for() {
+ owner_name="$1"
+ rr_type="$2"
+ file="$3"
+ test "$(count_records "$owner_name" "$rr_type" "$file")" -eq 1
+}
+
+no_records_exist_for() {
+ owner_name="$1"
+ rr_type="$2"
+ file="$3"
+ test "$(count_records "$owner_name" "$rr_type" "$file")" -eq 0
+}
+
+ensure_no_ds_in_bitmap() {
+ owner_name="$1"
+ rr_type="$2"
+ file="$3"
+ case "$rr_type" in
+ NSEC) start_index=6 ;;
+ NSEC3) start_index=10 ;;
+ *) exit 1 ;;
+ esac
+ find_records "$owner_name" "$rr_type" "$file" | awk '{ for (i='"$start_index"'; i<=NF; i++) if ($i == "DS") exit 1 }'
+}
+
+n=$((n + 1))
+echo_i "checking secure delegation prepared using CNAME chaining ($n)"
+ret=0
+# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a
+# DS RRset.
+$DIG $DIGOPTS @10.53.0.2 cname.wildcard-secure.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
+# Ensure that the AUTHORITY section contains the expected NS and DS RRsets.
+exactly_one_record_exists_for "delegation.wildcard-secure.example." NS dig.out.2.$n || ret=1
+exactly_one_record_exists_for "delegation.wildcard-secure.example." DS dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking secure delegation prepared using wildcard expansion + CNAME chaining ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset, an
+# NSEC record proving nonexistence of QNAME, and a DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 a-nonexistent-name.wildcard-secure.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
+# Ensure that the AUTHORITY section contains the expected NS and DS RRsets.
+exactly_one_record_exists_for "delegation.wildcard-secure.example." NS dig.out.2.$n || ret=1
+exactly_one_record_exists_for "delegation.wildcard-secure.example." DS dig.out.2.$n || ret=1
+# Check NSEC records in the AUTHORITY section.
+no_records_exist_for "wildcard-secure.example." NSEC dig.out.2.$n || ret=1
+exactly_one_record_exists_for "*.wildcard-secure.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "cname.wildcard-secure.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "delegation.wildcard-secure.example." NSEC dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking insecure delegation prepared using CNAME chaining, NSEC ($n)"
+ret=0
+# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a
+# single NSEC record proving nonexistence of a DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
+# Ensure that the AUTHORITY section contains an NS RRset without an associated
+# DS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1
+no_records_exist_for "delegation.wildcard-nsec.example." DS dig.out.2.$n || ret=1
+# Check NSEC records in the AUTHORITY section.
+no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+# Ensure the NSEC record for the zone cut does not have the DS bit set in the
+# type bit map.
+ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC, QNAME #1 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, these two NSEC records are different.
+$DIG $DIGOPTS @10.53.0.2 a-nonexistent-name.wildcard-nsec.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
+# Ensure that the AUTHORITY section contains an NS RRset without an associated
+# DS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1
+no_records_exist_for "delegation.wildcard-nsec.example." DS dig.out.2.$n || ret=1
+# Check NSEC records in the AUTHORITY section.
+no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+exactly_one_record_exists_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+# Ensure the NSEC record for the zone cut does not have the DS bit set in the
+# type bit map.
+ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC, QNAME #2 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, the same NSEC record proves nonexistence of both the
+# QNAME and the DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
+# Ensure that the AUTHORITY section contains an NS RRset without an associated
+# DS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1
+no_records_exist_for "delegation.wildcard-nsec.example." DS dig.out.2.$n || ret=1
+# Check NSEC records in the AUTHORITY section.
+no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+# Ensure the NSEC record for the zone cut does not have the DS bit set in the
+# type bit map.
+ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Relevant NSEC3 hashes:
+#
+# - existing names:
+#
+# $ nsec3hash - 1 0 wildcard-nsec3.example.
+# 38IVP9CN0LBISO6H3V5REQCKMTHLI5AN (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 cname.wildcard-nsec3.example.
+# 3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 delegation.wildcard-nsec3.example.
+# AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 *.wildcard-nsec3.example.
+# Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2 (salt=-, hash=1, iterations=0)
+#
+# - nonexistent names:
+#
+# $ nsec3hash - 1 0 a-nonexistent-name.wildcard-nsec3.example.
+# PST9IH6M0DG3M139CO3G12NUP4ER88SH (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 z-nonexistent-name.wildcard-nsec3.example.
+# SG2DEHEAOGCKP7FTNQAUVC3I3TIPJH0J (salt=-, hash=1, iterations=0)
+
+n=$((n + 1))
+echo_i "checking insecure delegation prepared using CNAME chaining, NSEC3 ($n)"
+ret=0
+# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a
+# single NSEC3 record proving nonexistence of a DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec3.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
+# Ensure that the AUTHORITY section contains an NS RRset without an associated
+# DS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1
+no_records_exist_for "delegation.wildcard-nsec3.example." DS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3, QNAME #1 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, these two NSEC3 records are different.
+$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec3.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
+# Ensure that the AUTHORITY section contains an NS RRset without an associated
+# DS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1
+no_records_exist_for "delegation.wildcard-nsec3.example." DS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3, QNAME #2 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, the same NSEC3 record proves nonexistence of both the
+# QNAME and the DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 a-nonexistent-name.wildcard-nsec3.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
+# Ensure that the AUTHORITY section contains an NS RRset without an associated
+# DS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1
+no_records_exist_for "delegation.wildcard-nsec3.example." DS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Relevant NSEC3 hashes:
+#
+# - existing names with corresponding NSEC3 records:
+#
+# $ nsec3hash - 1 0 *.wildcard-nsec3-optout.example.
+# 2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 cname.wildcard-nsec3-optout.example.
+# OKRFKC9SS1O60E8U2980UD62MUSMKGUG (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 wildcard-nsec3-optout.example.
+# SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI (salt=-, hash=1, iterations=0)
+#
+# - existing name with no corresponding NSEC3 record due to opt-out:
+#
+# $ nsec3hash - 1 0 delegation.wildcard-nsec3-optout.example.
+# UFP8PVECFTD57HU5PUD2HE0ES37QEOAP (salt=-, hash=1, iterations=0)
+#
+# - nonexistent names:
+#
+# $ nsec3hash - 1 0 b-nonexistent-name.wildcard-nsec3-optout.example.
+# 3J38JE2OU0O7B4CE2ADMBBKJ5HT994S5 (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 z-nonexistent-name.wildcard-nsec3-optout.example.
+# V7OTS4791T9SU0HKVL93EVNAJ9JH2CH3 (salt=-, hash=1, iterations=0)
+
+n=$((n + 1))
+echo_i "checking insecure delegation prepared using CNAME chaining, NSEC3 with opt-out ($n)"
+ret=0
+# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a
+# single NSEC3 record proving nonexistence of a DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec3-optout.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
+# Ensure that the AUTHORITY section contains an NS RRset without an associated
+# DS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1
+no_records_exist_for "delegation.wildcard-nsec3-optout.example." DS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+no_records_exist_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3 with opt-out, QNAME #1 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, these two NSEC3 records are different.
+$DIG $DIGOPTS @10.53.0.2 b-nonexistent-name.wildcard-nsec3-optout.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
+# Ensure that the AUTHORITY section contains an NS RRset without an associated
+# DS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1
+no_records_exist_for "delegation.wildcard-nsec3-optout.example." DS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+exactly_one_record_exists_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3 with opt-out, QNAME #2 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, the same NSEC3 record proves nonexistence of both the
+# QNAME and the DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec3-optout.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
+# Ensure that the AUTHORITY section contains an NS RRset without an associated
+# DS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1
+no_records_exist_for "delegation.wildcard-nsec3-optout.example." DS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+no_records_exist_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking CNAME to DNAME from authoritative ($n)"
+ret=0
+$DIG $DIGOPTS cname.example @10.53.0.2 a > dig.out.ns2.cname
+grep "status: NOERROR" dig.out.ns2.cname > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking CNAME to DNAME from recursive"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS cname.example @10.53.0.7 a > dig.out.ns4.cname
+grep "status: NOERROR" dig.out.ns4.cname > /dev/null || ret=1
+grep '^cname.example.' dig.out.ns4.cname > /dev/null || ret=1
+grep '^cnamedname.example.' dig.out.ns4.cname > /dev/null || ret=1
+grep '^a.cnamedname.example.' dig.out.ns4.cname > /dev/null || ret=1
+grep '^a.target.example.' dig.out.ns4.cname > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DNAME is returned with synthesized CNAME before DNAME ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS @10.53.0.7 name.synth-then-dname.example.broken A > dig.out.test$n
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
+grep '^name.synth-then-dname\.example\.broken\..*CNAME.*name.$' dig.out.test$n > /dev/null || ret=1
+grep '^synth-then-dname\.example\.broken\..*DNAME.*\.$' dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DNAME is returned with CNAME to synthesized CNAME before DNAME ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS @10.53.0.7 cname-to-synth2-then-dname.example.broken A > dig.out.test$n
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
+grep '^cname-to-synth2-then-dname\.example\.broken\..*CNAME.*name\.synth2-then-dname\.example\.broken.$' dig.out.test$n > /dev/null || ret=1
+grep '^name\.synth2-then-dname\.example\.broken\..*CNAME.*name.$' dig.out.test$n > /dev/null || ret=1
+grep '^synth2-then-dname\.example\.broken\..*DNAME.*\.$' dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking CNAME loops are detected ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS @10.53.0.7 loop.example > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 17" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking CNAME to external delegated zones is handled ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS @10.53.0.7 a.example > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking CNAME to internal delegated zones is handled ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS @10.53.0.7 b.example > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking CNAME to signed external delegation is handled ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS @10.53.0.7 c.example > dig.out.$n
+grep "status: NOERROR" dig.out.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking CNAME to signed internal delegation is handled ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS @10.53.0.7 d.example > dig.out.$n
+grep "status: NOERROR" dig.out.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking CNAME chains in various orders ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n - step 1 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "cname,cname,cname|1,2,3,4,s1,s2,s3,s4" | sendcmd
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.1.$n 2>&1
+grep 'status: NOERROR' dig.out.1.$n > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 2' dig.out.1.$n > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.7 null --- start test$n - step 2 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "cname,cname,cname|1,1,2,2,3,4,s4,s3,s1" | sendcmd
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.2.$n 2>&1
+grep 'status: NOERROR' dig.out.2.$n > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 2' dig.out.2.$n > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.7 null --- start test$n - step 3 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "cname,cname,cname|2,1,3,4,s3,s1,s2,s4" | sendcmd
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.3.$n 2>&1
+grep 'status: NOERROR' dig.out.3.$n > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 2' dig.out.3.$n > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.7 null --- start test$n - step 4 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "cname,cname,cname|4,3,2,1,s4,s3,s2,s1" | sendcmd
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.4.$n 2>&1
+grep 'status: NOERROR' dig.out.4.$n > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 2' dig.out.4.$n > /dev/null 2>&1 || ret=1
+echo "cname,cname,cname|4,3,2,1,s4,s3,s2,s1" | sendcmd
+$RNDCCMD 10.53.0.7 null --- start test$n - step 5 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.5.$n 2>&1
+grep 'status: NOERROR' dig.out.5.$n > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 2' dig.out.5.$n > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.7 null --- start test$n - step 6 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "cname,cname,cname|4,3,3,3,s1,s1,1,3,4" | sendcmd
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.6.$n 2>&1
+grep 'status: NOERROR' dig.out.6.$n > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 2' dig.out.6.$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that only the initial CNAME is cached ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "cname,cname,cname|1,2,3,4,s1,s2,s3,s4" | sendcmd
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.1.$n 2>&1
+sleep 1
+$DIG $DIGOPTS +noall +answer @10.53.0.7 cname1.domain.nil > dig.out.2.$n 2>&1
+ttl=$(awk '{print $2}' dig.out.2.$n)
+[ "$ttl" -eq 86400 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DNAME chains in various orders ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n - step 1 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "dname,dname|5,4,3,2,1,s5,s4,s3,s2,s1" | sendcmd
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.1.$n 2>&1
+grep 'status: NOERROR' dig.out.1.$n > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 3' dig.out.1.$n > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.7 null --- start test$n - step 2 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "dname,dname|5,4,3,2,1,s5,s4,s3,s2,s1" | sendcmd
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.2.$n 2>&1
+grep 'status: NOERROR' dig.out.2.$n > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 3' dig.out.2.$n > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.7 null --- start test$n - step 3 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "dname,dname|2,3,s1,s2,s3,s4,1" | sendcmd
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.3.$n 2>&1
+grep 'status: NOERROR' dig.out.3.$n > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 3' dig.out.3.$n > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking external CNAME/DNAME chains in various orders ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n - step 1 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "xname,dname|1,2,3,4,s1,s2,s3,s4" | sendcmd
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.1.$n 2>&1
+grep 'status: NOERROR' dig.out.1.$n > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 2' dig.out.1.$n > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.7 null --- start test$n - step 2 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "xname,dname|s2,2,s1,1,4,s4,3" | sendcmd
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.2.$n 2>&1
+grep 'status: NOERROR' dig.out.2.$n > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 2' dig.out.2.$n > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.7 null --- start test$n - step 3 --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+echo "xname,dname|s2,2,2,2" | sendcmd
+$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.3.$n 2>&1
+grep 'status: SERVFAIL' dig.out.3.$n > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking explicit DNAME query ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS @10.53.0.7 dname short-dname.example > dig.out.7.$n 2>&1
+grep 'status: NOERROR' dig.out.7.$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DNAME via ANY query ($n)"
+ret=0
+$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
+$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
+$DIG $DIGOPTS @10.53.0.7 any short-dname.example > dig.out.7.$n 2>&1
+grep 'status: NOERROR' dig.out.7.$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Regression test for CVE-2021-25215 (authoritative server).
+n=$((n + 1))
+echo_i "checking DNAME resolution via itself (authoritative) ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 DNAME self.domain0.self.domain0.nil. > dig.out.2.$n 2>&1
+grep 'status: NOERROR' dig.out.2.$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Regression test for CVE-2021-25215 (recursive resolver).
+n=$((n + 1))
+echo_i "checking DNAME resolution via itself (recursive) ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.7 DNAME self.example.self.example.dname. > dig.out.7.$n 2>&1
+grep 'status: NOERROR' dig.out.7.$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/chain/tests_sh_chain.py b/bin/tests/system/chain/tests_sh_chain.py
new file mode 100644
index 0000000..ca3c057
--- /dev/null
+++ b/bin/tests/system/chain/tests_sh_chain.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_chain(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/checkconf/altdb.conf b/bin/tests/system/checkconf/altdb.conf
new file mode 100644
index 0000000..1d8aded
--- /dev/null
+++ b/bin/tests/system/checkconf/altdb.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view override_bind chaos {
+ zone "version.bind" chaos {
+ type primary;
+ database "_builtin version";
+ };
+};
diff --git a/bin/tests/system/checkconf/altdlz.conf b/bin/tests/system/checkconf/altdlz.conf
new file mode 100644
index 0000000..db8eecc
--- /dev/null
+++ b/bin/tests/system/checkconf/altdlz.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dlz external {
+ database "dlopen driver.so";
+ search no;
+};
+
+zone "example.com" {
+ type primary;
+ dlz external;
+};
+
+zone "." {
+ type redirect;
+ dlz external;
+};
diff --git a/bin/tests/system/checkconf/ancient.conf b/bin/tests/system/checkconf/ancient.conf
new file mode 100644
index 0000000..98189cc
--- /dev/null
+++ b/bin/tests/system/checkconf/ancient.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Ancient options are fatal.
+ */
+options {
+ fake-iquery yes;
+};
diff --git a/bin/tests/system/checkconf/bad-acl.conf b/bin/tests/system/checkconf/bad-acl.conf
new file mode 100644
index 0000000..5095059
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-acl.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl a {
+ { "none"; };
+ { !19.0.0.0/7; };
+};
+
+options {
+ allow-query { a; };
+};
diff --git a/bin/tests/system/checkconf/bad-also-notify.conf b/bin/tests/system/checkconf/bad-also-notify.conf
new file mode 100644
index 0000000..2ab8896
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-also-notify.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Missing primary in also-notify clause.
+ */
+
+zone dummy {
+ type primary;
+ file "xxxx";
+ also-notify { xxxx; };
+};
diff --git a/bin/tests/system/checkconf/bad-catz-zone-dup.conf b/bin/tests/system/checkconf/bad-catz-zone-dup.conf
new file mode 100644
index 0000000..08fae42
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-catz-zone-dup.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ catalog-zones { zone example.com; zone example.com; };
+};
+
+zone example.com {
+ type primary;
+ file "example.com";
+};
diff --git a/bin/tests/system/checkconf/bad-catz-zone-primary-dup.conf b/bin/tests/system/checkconf/bad-catz-zone-primary-dup.conf
new file mode 100644
index 0000000..55a2d78
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-catz-zone-primary-dup.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ catalog-zones {
+ zone "catalog.example"
+ default-masters { 10.53.0.1; }
+ default-primaries { 10.53.0.1 port 5304; }
+ in-memory yes;
+ };
+};
+
+zone "catalog.example" {
+ type secondary;
+ file "catalog.example.db";
+ primaries { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-catz-zone.conf b/bin/tests/system/checkconf/bad-catz-zone.conf
new file mode 100644
index 0000000..6f0677a
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-catz-zone.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ catalog-zones {
+ zone "nonexistent";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-checknames-primary-dup-2.conf b/bin/tests/system/checkconf/bad-checknames-primary-dup-2.conf
new file mode 100644
index 0000000..24e6ef9
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-checknames-primary-dup-2.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-names primary warn;
+ check-names primary fail;
+};
diff --git a/bin/tests/system/checkconf/bad-checknames-primary-dup.conf b/bin/tests/system/checkconf/bad-checknames-primary-dup.conf
new file mode 100644
index 0000000..e746e84
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-checknames-primary-dup.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-names master warn;
+ check-names primary fail;
+};
diff --git a/bin/tests/system/checkconf/bad-checknames-secondary-dup.conf b/bin/tests/system/checkconf/bad-checknames-secondary-dup.conf
new file mode 100644
index 0000000..ea83d7e
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-checknames-secondary-dup.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-names slave ignore;
+ check-names secondary warn;
+};
diff --git a/bin/tests/system/checkconf/bad-dnskey-validity.conf b/bin/tests/system/checkconf/bad-dnskey-validity.conf
new file mode 100644
index 0000000..8c28ac5
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dnskey-validity.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnskey-sig-validity 5000; /* maximum value 10 years, this is 14 */
+};
diff --git a/bin/tests/system/checkconf/bad-dnssec.conf b/bin/tests/system/checkconf/bad-dnssec.conf
new file mode 100644
index 0000000..3dbd0f3
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dnssec.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone not-inline {
+ type secondary;
+ primaries { 127.0.0.1; };
+ inline-signing no;
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+ dnssec-loadkeys-interval 10;
+
+};
+
+zone inline {
+ type secondary;
+ primaries { 127.0.0.1; };
+ inline-signing yes;
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+ dnssec-loadkeys-interval 10;
+};
diff --git a/bin/tests/system/checkconf/bad-doh-1.conf b/bin/tests/system/checkconf/bad-doh-1.conf
new file mode 100644
index 0000000..a10a236
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-doh-1.conf
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+http local-http-server {
+ endpoints { "/dns-query"; };
+};
+
+# undefined 'tls' specification
+options {
+ listen-on port 8080 http local-http-server tls unknown { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-doh-2.conf b/bin/tests/system/checkconf/bad-doh-2.conf
new file mode 100644
index 0000000..c797eee
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-doh-2.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+# undefined 'http' specification
+options {
+ listen-on port 8080 http unknown tls local-tls { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-doh-3.conf b/bin/tests/system/checkconf/bad-doh-3.conf
new file mode 100644
index 0000000..7447a01
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-doh-3.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+http local-http-server {
+ endpoints { "/dns-query"; };
+};
+
+# no 'tls' specification
+options {
+ listen-on port 8080 http unknown { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-doh-badpath-1.conf b/bin/tests/system/checkconf/bad-doh-badpath-1.conf
new file mode 100644
index 0000000..9a0f449
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-doh-badpath-1.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# bad HTTP location
+http local-http-server {
+ endpoints { "dns-query"; };
+};
+
+options {
+ listen-on port 8080 tls none http local-http-server { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-doh-badpath-2.conf b/bin/tests/system/checkconf/bad-doh-badpath-2.conf
new file mode 100644
index 0000000..e8013ee
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-doh-badpath-2.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# bad HTTP location
+http local-http-server {
+ endpoints { "//"; };
+};
+
+options {
+ listen-on port 8080 tls none http local-http-server { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-doh-badpath-3.conf b/bin/tests/system/checkconf/bad-doh-badpath-3.conf
new file mode 100644
index 0000000..fc5464c
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-doh-badpath-3.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# bad HTTP location
+http local-http-server {
+ endpoints { "/dns-query?dns="; };
+};
+
+options {
+ listen-on port 8080 tls none http local-http-server { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-doh-default.conf b/bin/tests/system/checkconf/bad-doh-default.conf
new file mode 100644
index 0000000..dce7fe6
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-doh-default.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# 'default' is a built-in configuration intended to be used in
+# 'listen-on' statements
+http default {
+ endpoints { "/dns-query"; };
+ listener-clients 100;
+ streams-per-connection 100;
+};
diff --git a/bin/tests/system/checkconf/bad-doh-duplicates.conf b/bin/tests/system/checkconf/bad-doh-duplicates.conf
new file mode 100644
index 0000000..a598d07
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-doh-duplicates.conf
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+http local-http-server {
+ endpoints { "/dns-query"; };
+ listener-clients 100;
+ streams-per-connection 100;
+};
+
+# duplicated HTTP configuration
+http local-http-server {
+ endpoints { "/dns-query"; };
+ listener-clients 100;
+ streams-per-connection 100;
+};
+
+options {
+ listen-on { 10.53.0.1; };
+ http-port 80;
+ https-port 443;
+ http-listener-clients 100;
+ http-streams-per-connection 100;
+ listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; };
+ listen-on port 8080 tls none http local-http-server { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-1.conf b/bin/tests/system/checkconf/bad-dot-1.conf
new file mode 100644
index 0000000..436a269
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-1.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# undefined 'tls' specification
+options {
+ listen-on port 853 tls local-tls { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-port.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-port.conf
new file mode 100644
index 0000000..7d807fd
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-port.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example1" {
+ type primary;
+ file "example1.db";
+ allow-transfer port 99999 { any; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-1.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-1.conf
new file mode 100644
index 0000000..cba5557
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-1.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example1" {
+ type primary;
+ file "example1.db";
+ allow-transfer port 44344 transport blah { any; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-2.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-2.conf
new file mode 100644
index 0000000..e772592
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-2.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example1" {
+ type primary;
+ file "example1.db";
+ allow-transfer port 44344 transport udp { any; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-3.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-3.conf
new file mode 100644
index 0000000..22956d2
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-3.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example1" {
+ type primary;
+ file "example1.db";
+ allow-transfer port 44344 transport http { any; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-4.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-4.conf
new file mode 100644
index 0000000..dfc7794
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-4.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example1" {
+ type primary;
+ file "example1.db";
+ allow-transfer port 44344 transport http-plain { any; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-badciphers.conf b/bin/tests/system/checkconf/bad-dot-badciphers.conf
new file mode 100644
index 0000000..42a9f64
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-badciphers.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+ ciphers "$bad:ciphers";
+};
+
+options {
+ listen-on port 853 tls local-tls { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-badprotocol.conf b/bin/tests/system/checkconf/bad-dot-badprotocol.conf
new file mode 100644
index 0000000..f1cc15a
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-badprotocol.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+ protocols { unknown; TLSv1.2; }; # bad TLS protocol version name
+};
+
+options {
+ listen-on port 853 tls local-tls { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-duplicatetls.conf b/bin/tests/system/checkconf/bad-dot-duplicatetls.conf
new file mode 100644
index 0000000..508290f
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-duplicatetls.conf
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+options {
+ listen-on port 853 tls local-tls { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-ephemeral.conf b/bin/tests/system/checkconf/bad-dot-ephemeral.conf
new file mode 100644
index 0000000..c9581f2
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-ephemeral.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# ephemeral is reserved for internal use
+tls ephemeral {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+options {
+ listen-on port 853 tls ephemeral { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-nocert.conf b/bin/tests/system/checkconf/bad-dot-nocert.conf
new file mode 100644
index 0000000..db02e9f
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-nocert.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+};
+
+http local-http-server {
+ endpoints { "/dns-query"; };
+ listener-clients 100;
+ streams-per-connection 100;
+};
+
+options {
+ listen-on { 10.53.0.1; };
+ http-port 80;
+ https-port 443;
+ http-listener-clients 100;
+ http-streams-per-connection 100;
+ listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; };
+ listen-on port 8080 tls none http local-http-server { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-nokey.conf b/bin/tests/system/checkconf/bad-dot-nokey.conf
new file mode 100644
index 0000000..1d5c3c5
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-nokey.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ cert-file "cert.pem";
+};
+
+http local-http-server {
+ endpoints { "/dns-query"; };
+ listener-clients 100;
+ streams-per-connection 100;
+};
+
+options {
+ listen-on { 10.53.0.1; };
+ http-port 80;
+ https-port 443;
+ http-listener-clients 100;
+ http-streams-per-connection 100;
+ listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; };
+ listen-on port 8080 tls none http local-http-server { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-none.conf b/bin/tests/system/checkconf/bad-dot-none.conf
new file mode 100644
index 0000000..fa26ab1
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-none.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# none is reserved for internal use
+tls none {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+options {
+ listen-on port 853 tls none { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-dot-primaries.conf b/bin/tests/system/checkconf/bad-dot-primaries.conf
new file mode 100644
index 0000000..8958cbe
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-dot-primaries.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.1 tls undefined; };
+ file "example.db";
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/checkconf/bad-duplicate-key.conf b/bin/tests/system/checkconf/bad-duplicate-key.conf
new file mode 100644
index 0000000..17f2237
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-duplicate-key.conf
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnssec-validation yes;
+};
+
+trust-anchors {
+ example. initial-key 257 3 8 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl
+ 25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafG
+ tURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJY
+ kYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJ
+ fpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaS
+ WG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjI
+ NQyrszHhWUU=";
+};
+
+trust-anchors {
+ example. static-key 257 3 8 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbod
+ y0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQ
+ YfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX
+ 2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuw
+ E60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/
+ Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn
+ 6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/bad-duplicate-primaries-1.conf b/bin/tests/system/checkconf/bad-duplicate-primaries-1.conf
new file mode 100644
index 0000000..3bbabde
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-duplicate-primaries-1.conf
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+primaries duplicate { 1.2.3.4; };
+primaries duplicate { 4.3.2.1; };
diff --git a/bin/tests/system/checkconf/bad-duplicate-primaries-2.conf b/bin/tests/system/checkconf/bad-duplicate-primaries-2.conf
new file mode 100644
index 0000000..1d1c6f0
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-duplicate-primaries-2.conf
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+masters duplicate { 1.2.3.4; };
+primaries duplicate { 4.3.2.1; };
diff --git a/bin/tests/system/checkconf/bad-duplicate-root-key.conf b/bin/tests/system/checkconf/bad-duplicate-root-key.conf
new file mode 100644
index 0000000..1cbc7d4
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-duplicate-root-key.conf
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnssec-validation yes;
+};
+
+trust-anchors {
+ . initial-key 257 3 8 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl
+ 25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafG
+ tURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJY
+ kYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJ
+ fpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaS
+ WG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjI
+ NQyrszHhWUU=";
+};
+
+trusted-keys {
+ . 257 3 8 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbod
+ y0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQ
+ YfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX
+ 2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuw
+ E60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/
+ Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn
+ 6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/bad-duration.conf b/bin/tests/system/checkconf/bad-duration.conf
new file mode 100644
index 0000000..1fbecc7
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-duration.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "test" {
+ dnskey-ttl xPT1H;
+};
diff --git a/bin/tests/system/checkconf/bad-glue-cache-bogus.conf b/bin/tests/system/checkconf/bad-glue-cache-bogus.conf
new file mode 100644
index 0000000..c264b26
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-glue-cache-bogus.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ glue-cache bogusvalue;
+};
diff --git a/bin/tests/system/checkconf/bad-hint.conf b/bin/tests/system/checkconf/bad-hint.conf
new file mode 100644
index 0000000..7214a00
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-hint.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type hint;
+ masterfile-format raw;
+ file "hint";
+};
diff --git a/bin/tests/system/checkconf/bad-in-view-dup.conf b/bin/tests/system/checkconf/bad-in-view-dup.conf
new file mode 100644
index 0000000..1d8bd17
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-in-view-dup.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view a {
+ zone x { type primary; file "x"; };
+};
+
+view b {
+ zone x { type primary; file "x"; };
+ zone x { in-view a; };
+};
diff --git a/bin/tests/system/checkconf/bad-inline-options.conf b/bin/tests/system/checkconf/bad-inline-options.conf
new file mode 100644
index 0000000..f7c62dd
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-inline-options.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * inline-signing not allowed at options level.
+ */
+options {
+ inline-signing yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/checkconf/bad-inline-secondary.conf b/bin/tests/system/checkconf/bad-inline-secondary.conf
new file mode 100644
index 0000000..3646216
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-inline-secondary.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+ /*
+ * An inline-signing secondary should be forced to have a file option
+ */
+
+ zone "." {
+ type secondary;
+ inline-signing yes;
+ primaries { 10.53.0.1; };
+ };
diff --git a/bin/tests/system/checkconf/bad-inline-view.conf b/bin/tests/system/checkconf/bad-inline-view.conf
new file mode 100644
index 0000000..e46bd0b
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-inline-view.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * inline-signing not allowed at view level.
+ */
+view "a" {
+ inline-signing yes;
+
+ zone "." {
+ type primary;
+ file "root.db.signed";
+ };
+};
+
+view "b" {
+ zone "." {
+ type primary;
+ file "root.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-interface-interval.conf b/bin/tests/system/checkconf/bad-interface-interval.conf
new file mode 100644
index 0000000..ba8341a
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-interface-interval.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ interface-interval 1x;
+};
diff --git a/bin/tests/system/checkconf/bad-ipv4-prefix-dotted1.conf b/bin/tests/system/checkconf/bad-ipv4-prefix-dotted1.conf
new file mode 100644
index 0000000..d7604eb
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-ipv4-prefix-dotted1.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl myacl {
+ 127.1; /* Incomplete dotted IPv4 address / prefix */
+};
diff --git a/bin/tests/system/checkconf/bad-ipv4-prefix-dotted2.conf b/bin/tests/system/checkconf/bad-ipv4-prefix-dotted2.conf
new file mode 100644
index 0000000..cb53741
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-ipv4-prefix-dotted2.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl myacl {
+ 127.1/8; /* No-zero bits */
+};
diff --git a/bin/tests/system/checkconf/bad-ipv4-prefix2.conf b/bin/tests/system/checkconf/bad-ipv4-prefix2.conf
new file mode 100644
index 0000000..98e724a
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-ipv4-prefix2.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl myacl {
+ 127; /* Non-dotted quad IPv4 address (0.0.0.127) / prefix without length. */
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-define-default.conf b/bin/tests/system/checkconf/bad-kasp-define-default.conf
new file mode 100644
index 0000000..73c90ef
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-define-default.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 'default' is a built-in policy, redefinition not allowed.
+dnssec-policy "default" {
+ signatures-refresh P5D;
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "default";
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-define-insecure.conf b/bin/tests/system/checkconf/bad-kasp-define-insecure.conf
new file mode 100644
index 0000000..b2d22d3
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-define-insecure.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 'insecure' is a built-in policy, redefinition not allowed.
+dnssec-policy "insecure" {
+ signatures-refresh P5D;
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "insecure";
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-define-none.conf b/bin/tests/system/checkconf/bad-kasp-define-none.conf
new file mode 100644
index 0000000..cea9988
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-define-none.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 'none' is a built-in policy, redefinition not allowed.
+dnssec-policy "none" {
+ signatures-refresh P5D;
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "none";
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-duplicate.conf b/bin/tests/system/checkconf/bad-kasp-duplicate.conf
new file mode 100644
index 0000000..7f3ade6
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-duplicate.conf
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy a { };
+dnssec-policy a { };
diff --git a/bin/tests/system/checkconf/bad-kasp-key1.conf b/bin/tests/system/checkconf/bad-kasp-key1.conf
new file mode 100644
index 0000000..0bf80de
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-key1.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "badalg" {
+ keys {
+ csk lifetime unlimited algorithm ceasarscipher;
+ };
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "badalg";
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-key2.conf b/bin/tests/system/checkconf/bad-kasp-key2.conf
new file mode 100644
index 0000000..8e97e2a
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-key2.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "badalg" {
+ keys {
+ csk lifetime unlimited algorithm 8 4097;
+ };
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "badalg";
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-key3.conf b/bin/tests/system/checkconf/bad-kasp-key3.conf
new file mode 100644
index 0000000..85e4e48
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-key3.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "badalg" {
+ keys {
+ csk lifetime unlimited algorithm rsasha512 1023;
+ };
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "badalg";
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-key4.conf b/bin/tests/system/checkconf/bad-kasp-key4.conf
new file mode 100644
index 0000000..ca142a3
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-key4.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "badalg" {
+ keys {
+ csk lifetime unlimited algorithm 5 511;
+ };
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "badalg";
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-keydir1.conf.in b/bin/tests/system/checkconf/bad-kasp-keydir1.conf.in
new file mode 100644
index 0000000..b0deaea
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-keydir1.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * The same zone in different views is using different DNSSEC policies, so it
+ * may not have the same key-directory.
+ */
+
+
+key "keyforview1" {
+ algorithm @DEFAULT_HMAC@;
+ secret "YPfMoAk6h+3iN8MDRQC004iSNHY=";
+};
+
+key "keyforview2" {
+ algorithm @DEFAULT_HMAC@;
+ secret "4xILSZQnuO1UKubXHkYUsvBRPu8=";
+};
+
+view "example1" {
+ match-clients { key "keyforview1"; };
+
+ zone "example.net" {
+ type primary;
+ dnssec-policy "default";
+ key-directory ".";
+ file "example1.db";
+ };
+};
+
+view "example2" {
+ match-clients { key "keyforview2"; };
+
+ zone "example.net" {
+ type primary;
+ dnssec-policy "insecure";
+ key-directory ".";
+ file "example2.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-keydir2.conf.in b/bin/tests/system/checkconf/bad-kasp-keydir2.conf.in
new file mode 100644
index 0000000..699c193
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-keydir2.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * No key-directory is set, so the default is used.
+ * Should fail because the same zone in different views is using different
+ * DNSSEC policies.
+ */
+
+key "keyforview1" {
+ algorithm @DEFAULT_HMAC@;
+ secret "YPfMoAk6h+3iN8MDRQC004iSNHY=";
+};
+
+key "keyforview2" {
+ algorithm @DEFAULT_HMAC@;
+ secret "4xILSZQnuO1UKubXHkYUsvBRPu8=";
+};
+
+view "example1" {
+ match-clients { key "keyforview1"; };
+
+ zone "example.net" {
+ type primary;
+ dnssec-policy "default";
+ file "example1.db";
+ };
+};
+
+view "example2" {
+ match-clients { key "keyforview2"; };
+
+ zone "example.net" {
+ type primary;
+ dnssec-policy "insecure";
+ file "example2.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-keydir3.conf.in b/bin/tests/system/checkconf/bad-kasp-keydir3.conf.in
new file mode 100644
index 0000000..0dbd7e2
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-keydir3.conf.in
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * The zone in view "example1" inherits the key directory value from "options",
+ * but in view "example2" sets the key directory to the same value. This should
+ * be detected as an error because the zone is using different DNSSEC policies
+ * and should thus use different key directories.
+ */
+
+key "keyforview1" {
+ algorithm @DEFAULT_HMAC@;
+ secret "YPfMoAk6h+3iN8MDRQC004iSNHY=";
+};
+
+key "keyforview2" {
+ algorithm @DEFAULT_HMAC@;
+ secret "4xILSZQnuO1UKubXHkYUsvBRPu8=";
+};
+
+options {
+ key-directory "keys";
+};
+
+view "example1" {
+ match-clients { key "keyforview1"; };
+
+ zone "example.net" {
+ type primary;
+ /* key-directory inherited from options. */
+ dnssec-policy "default";
+ file "example1.db";
+ };
+};
+
+view "example2" {
+ match-clients { key "keyforview2"; };
+
+ zone "example.net" {
+ type primary;
+ dnssec-policy "insecure";
+ key-directory "keys";
+ file "example2.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-keydir4.conf.in b/bin/tests/system/checkconf/bad-kasp-keydir4.conf.in
new file mode 100644
index 0000000..af4a8f9
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-keydir4.conf.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * The zone inherits the key-directory from the "view" level. Both views use the
+ * same key-directory, but the zone uses a different DNSSEC policy per view.
+ * This is a configuration error.
+ */
+
+key "keyforview1" {
+ algorithm @DEFAULT_HMAC@;
+ secret "YPfMoAk6h+3iN8MDRQC004iSNHY=";
+};
+
+key "keyforview2" {
+ algorithm @DEFAULT_HMAC@;
+ secret "4xILSZQnuO1UKubXHkYUsvBRPu8=";
+};
+
+view "example1" {
+ match-clients { key "keyforview1"; };
+
+ key-directory "keys";
+
+ zone "example.net" {
+ type primary;
+ dnssec-policy "default";
+ file "example1.db";
+ };
+};
+
+view "example2" {
+ match-clients { key "keyforview2"; };
+
+ key-directory "keys";
+
+ zone "example.net" {
+ type primary;
+ dnssec-policy "insecure";
+ file "example2.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-keydir5.conf.in b/bin/tests/system/checkconf/bad-kasp-keydir5.conf.in
new file mode 100644
index 0000000..1cca608
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-keydir5.conf.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * In one view, the zone inherits the key-directory from the "view" level, while
+ * in the other it is set explicitly at the "zone" level. In both cases, the
+ * same key-directory is used, but the zone uses a different DNSSEC policy per
+ * view. This is a configuration error.
+ */
+
+key "keyforview1" {
+ algorithm @DEFAULT_HMAC@;
+ secret "YPfMoAk6h+3iN8MDRQC004iSNHY=";
+};
+
+key "keyforview2" {
+ algorithm @DEFAULT_HMAC@;
+ secret "4xILSZQnuO1UKubXHkYUsvBRPu8=";
+};
+
+view "example1" {
+ match-clients { key "keyforview1"; };
+
+ key-directory "keys";
+
+ zone "example.net" {
+ type primary;
+ dnssec-policy "default";
+ file "example1.db";
+ };
+};
+
+view "example2" {
+ match-clients { key "keyforview2"; };
+
+ zone "example.net" {
+ type primary;
+ dnssec-policy "insecure";
+ key-directory "keys";
+ file "example2.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-nsec3-alg.conf b/bin/tests/system/checkconf/bad-kasp-nsec3-alg.conf
new file mode 100644
index 0000000..ff25ece
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-nsec3-alg.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "badnsec3alg" {
+ keys {
+ csk lifetime unlimited algorithm rsasha1;
+ };
+ nsec3param iterations 0 optout 0 salt-length 0;
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "badnsec3alg";
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited-view.conf b/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited-view.conf
new file mode 100644
index 0000000..12a26d3
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited-view.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * The dnssec-policy is not defined. Should also be caught if it is inherited.
+ */
+
+view "test" {
+ dnssec-policy "notdefined";
+
+ zone "example.net" {
+ type primary;
+ file "example.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited.conf b/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited.conf
new file mode 100644
index 0000000..48514ac
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * The dnssec-policy is not defined. Should also be caught if it is inherited.
+ */
+
+options {
+ dnssec-policy "notdefined";
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/checkconf/bad-kasp10.conf b/bin/tests/system/checkconf/bad-kasp10.conf
new file mode 100644
index 0000000..8253fae
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp10.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// One zone with dnssec-policy 'none', one zone with dnssec-policy 'insecure',
+// both using the same zone file.
+
+zone "example1.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "none";
+};
+
+zone "example2.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "insecure";
+};
+
diff --git a/bin/tests/system/checkconf/bad-kasp11.conf b/bin/tests/system/checkconf/bad-kasp11.conf
new file mode 100644
index 0000000..68177c2
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp11.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// One zone with a dnssec-policy, the other with allow-update,
+// with the same zone file.
+
+zone "example1.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "default";
+};
+
+zone "example2.net" {
+ type primary;
+ file "example.db";
+ allow-update { any; };
+};
+
diff --git a/bin/tests/system/checkconf/bad-kasp12.conf b/bin/tests/system/checkconf/bad-kasp12.conf
new file mode 100644
index 0000000..0ae8c1e
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp12.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// One zone with a dnssec-policy, the other with update-policy,
+// with the same zone file.
+
+zone "example1.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "default";
+};
+
+zone "example2.net" {
+ type primary;
+ file "example.db";
+ update-policy {
+ grant * self * TXT;
+ };
+};
+
diff --git a/bin/tests/system/checkconf/bad-kasp13.conf b/bin/tests/system/checkconf/bad-kasp13.conf
new file mode 100644
index 0000000..c74a5d7
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp13.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// One zone transitioning to insecure, the other with allow-update,
+// with the same zone file.
+
+zone "example1.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "insecure";
+};
+
+zone "example2.net" {
+ type primary;
+ file "example.db";
+ allow-update { any; };
+};
+
diff --git a/bin/tests/system/checkconf/bad-kasp2.conf b/bin/tests/system/checkconf/bad-kasp2.conf
new file mode 100644
index 0000000..2e88964
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp2.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "good-kasp.conf";
+
+// Bad zone configuration because this has dnssec-policy and other DNSSEC sign
+// configuration options (auto-dnssec).
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "test";
+ auto-dnssec maintain;
+ allow-update { any; };
+};
diff --git a/bin/tests/system/checkconf/bad-kasp3.conf b/bin/tests/system/checkconf/bad-kasp3.conf
new file mode 100644
index 0000000..8c6d7b4
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp3.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "good-kasp.conf";
+
+// Bad zone configuration because this has dnssec-policy with no matching
+// dnssec-policy configuration (good-kasp.conf has "test", zone refers to
+// "nosuchpolicy".
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "nosuchpolicy";
+};
+
diff --git a/bin/tests/system/checkconf/bad-kasp4.conf b/bin/tests/system/checkconf/bad-kasp4.conf
new file mode 100644
index 0000000..d35d12f
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp4.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// Bad kasp configuration because this has an invalid duration for
+// signatures-refresh.
+dnssec-policy "badduration" {
+ signatures-refresh PT20Sabcd;
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "badduration";
+};
+
diff --git a/bin/tests/system/checkconf/bad-kasp6.conf b/bin/tests/system/checkconf/bad-kasp6.conf
new file mode 100644
index 0000000..3304038
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp6.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// Two zones with dnssec-policy with the same zone file.
+
+zone "example1.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "default";
+};
+
+zone "example2.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "default";
+};
+
diff --git a/bin/tests/system/checkconf/bad-kasp7.conf b/bin/tests/system/checkconf/bad-kasp7.conf
new file mode 100644
index 0000000..c5dfbe8
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp7.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// Two zones with dnssec-policy 'insecure' (transitioning to insecure)
+// with the same zone file.
+
+zone "example1.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "insecure";
+};
+
+zone "example2.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "insecure";
+};
+
diff --git a/bin/tests/system/checkconf/bad-kasp8.conf b/bin/tests/system/checkconf/bad-kasp8.conf
new file mode 100644
index 0000000..1712fd0
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp8.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// One zone with dnssec-policy, the other zone has 'dnssec-policy none',
+// both with the same zone file.
+
+zone "example1.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "default";
+};
+
+zone "example2.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "none";
+};
+
diff --git a/bin/tests/system/checkconf/bad-kasp9.conf b/bin/tests/system/checkconf/bad-kasp9.conf
new file mode 100644
index 0000000..3bb5448
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-kasp9.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// One zone with dnssec-policy, the other zone has 'dnssec-policy insecure'
+// (transitioning to inseure), both with the same zone file.
+
+zone "example1.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "default";
+};
+
+zone "example2.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "insecure";
+};
+
diff --git a/bin/tests/system/checkconf/bad-keep-response-order.conf b/bin/tests/system/checkconf/bad-keep-response-order.conf
new file mode 100644
index 0000000..a3685d7
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-keep-response-order.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ keep-response-order {
+ does_not_exist;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-ksk-without-zsk.conf b/bin/tests/system/checkconf/bad-ksk-without-zsk.conf
new file mode 100644
index 0000000..66e1b7f
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-ksk-without-zsk.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy ksk-without-zsk {
+ keys {
+ ksk lifetime 30d algorithm 13;
+ };
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ dnssec-policy ksk-without-zsk;
+};
diff --git a/bin/tests/system/checkconf/bad-lifetime.conf b/bin/tests/system/checkconf/bad-lifetime.conf
new file mode 100644
index 0000000..f268076
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-lifetime.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ nta-lifetime 8d;
+};
diff --git a/bin/tests/system/checkconf/bad-lmdb-mapsize-bogus.conf b/bin/tests/system/checkconf/bad-lmdb-mapsize-bogus.conf
new file mode 100644
index 0000000..5655a16
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-bogus.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ lmdb-mapsize bogusvalue;
+};
diff --git a/bin/tests/system/checkconf/bad-lmdb-mapsize-toolarge.conf b/bin/tests/system/checkconf/bad-lmdb-mapsize-toolarge.conf
new file mode 100644
index 0000000..006ca7d
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-toolarge.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ lmdb-mapsize 2048G;
+};
diff --git a/bin/tests/system/checkconf/bad-lmdb-mapsize-toosmall.conf b/bin/tests/system/checkconf/bad-lmdb-mapsize-toosmall.conf
new file mode 100644
index 0000000..5dd1720
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-toosmall.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ lmdb-mapsize 1;
+};
diff --git a/bin/tests/system/checkconf/bad-lmdb-mapsize-unlimited.conf b/bin/tests/system/checkconf/bad-lmdb-mapsize-unlimited.conf
new file mode 100644
index 0000000..f1e7b88
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-unlimited.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ lmdb-mapsize unlimited;
+};
diff --git a/bin/tests/system/checkconf/bad-master-request-ixfr.conf b/bin/tests/system/checkconf/bad-master-request-ixfr.conf
new file mode 100644
index 0000000..770afb3
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-master-request-ixfr.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * request-ixfr clause is not allowed in zone of type primary.
+ */
+
+zone dummy {
+ type primary;
+ request-ixfr no;
+ file "xxxx";
+};
diff --git a/bin/tests/system/checkconf/bad-masterfile-format-map.conf b/bin/tests/system/checkconf/bad-masterfile-format-map.conf
new file mode 100644
index 0000000..634ca14
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-masterfile-format-map.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { ::1; };
+ masterfile-format map;
+};
diff --git a/bin/tests/system/checkconf/bad-maxcachettl.conf b/bin/tests/system/checkconf/bad-maxcachettl.conf
new file mode 100644
index 0000000..47f0643
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-maxcachettl.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ max-cache-ttl 1x;
+};
diff --git a/bin/tests/system/checkconf/bad-maxncachettl-1.conf b/bin/tests/system/checkconf/bad-maxncachettl-1.conf
new file mode 100644
index 0000000..ad852c3
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-maxncachettl-1.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ max-ncache-ttl 1x;
+};
diff --git a/bin/tests/system/checkconf/bad-maxncachettl-2.conf b/bin/tests/system/checkconf/bad-maxncachettl-2.conf
new file mode 100644
index 0000000..ada5c83
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-maxncachettl-2.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view two {
+ max-ncache-ttl 604801;
+};
diff --git a/bin/tests/system/checkconf/bad-maxncachettl-3.conf b/bin/tests/system/checkconf/bad-maxncachettl-3.conf
new file mode 100644
index 0000000..771a0f3
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-maxncachettl-3.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view three {
+ max-ncache-ttl 4000000000;
+};
+view four {
+ max-ncache-ttl -1;
+};
diff --git a/bin/tests/system/checkconf/bad-maxncachettl-4.conf b/bin/tests/system/checkconf/bad-maxncachettl-4.conf
new file mode 100644
index 0000000..d9cd939
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-maxncachettl-4.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view four {
+ max-ncache-ttl -1;
+};
diff --git a/bin/tests/system/checkconf/bad-maxratio1.conf b/bin/tests/system/checkconf/bad-maxratio1.conf
new file mode 100644
index 0000000..ade4de1
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-maxratio1.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone example {
+ type primary;
+ masterfile-format raw;
+ file "example.db";
+ max-ixfr-ratio 0.9;
+};
diff --git a/bin/tests/system/checkconf/bad-maxratio2.conf b/bin/tests/system/checkconf/bad-maxratio2.conf
new file mode 100644
index 0000000..adb63f3
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-maxratio2.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone example {
+ type primary;
+ masterfile-format raw;
+ file "example.db";
+ max-ixfr-ratio 0%;
+};
diff --git a/bin/tests/system/checkconf/bad-mincachettl.conf b/bin/tests/system/checkconf/bad-mincachettl.conf
new file mode 100644
index 0000000..cd02c66
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-mincachettl.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ min-cache-ttl 1x;
+};
diff --git a/bin/tests/system/checkconf/bad-minncachettl.conf b/bin/tests/system/checkconf/bad-minncachettl.conf
new file mode 100644
index 0000000..1148bcc
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-minncachettl.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ min-ncache-ttl 1x;
+};
diff --git a/bin/tests/system/checkconf/bad-mirror-allow-recursion-none.conf b/bin/tests/system/checkconf/bad-mirror-allow-recursion-none.conf
new file mode 100644
index 0000000..1f4c8fe
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-mirror-allow-recursion-none.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ recursion yes;
+ allow-recursion { none; };
+};
+
+zone "." {
+ type mirror;
+ primaries { 127.0.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-mirror-explicit-notify-yes.conf b/bin/tests/system/checkconf/bad-mirror-explicit-notify-yes.conf
new file mode 100644
index 0000000..27ad850
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-mirror-explicit-notify-yes.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type mirror;
+ notify yes;
+};
diff --git a/bin/tests/system/checkconf/bad-mirror-non-root-zone-without-masters.conf b/bin/tests/system/checkconf/bad-mirror-non-root-zone-without-masters.conf
new file mode 100644
index 0000000..c9c8b03
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-mirror-non-root-zone-without-masters.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "foo." {
+ type mirror;
+};
diff --git a/bin/tests/system/checkconf/bad-mirror-recursion-no.conf b/bin/tests/system/checkconf/bad-mirror-recursion-no.conf
new file mode 100644
index 0000000..f5536ac
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-mirror-recursion-no.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ recursion no;
+};
+
+zone "." {
+ type mirror;
+};
diff --git a/bin/tests/system/checkconf/bad-mirror-zonename.conf b/bin/tests/system/checkconf/bad-mirror-zonename.conf
new file mode 100644
index 0000000..6fc11c1
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-mirror-zonename.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "\0example" {
+ type mirror;
+ file "example.db";
+};
diff --git a/bin/tests/system/checkconf/bad-noddns.conf b/bin/tests/system/checkconf/bad-noddns.conf
new file mode 100644
index 0000000..f7859d1
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-noddns.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone example {
+ type primary;
+ file "example.db";
+ auto-dnssec maintain;
+ allow-update { none; };
+};
diff --git a/bin/tests/system/checkconf/bad-notify-source-v6.conf b/bin/tests/system/checkconf/bad-notify-source-v6.conf
new file mode 100644
index 0000000..ef53c96
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-notify-source-v6.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ notify-source-v6 fd92:7065:b8e:ffff::1 port 5300;
+};
diff --git a/bin/tests/system/checkconf/bad-notify-source.conf b/bin/tests/system/checkconf/bad-notify-source.conf
new file mode 100644
index 0000000..b950784
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-notify-source.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ notify-source 10.53.0.1 port 5300;
+};
diff --git a/bin/tests/system/checkconf/bad-options-also-notify.conf b/bin/tests/system/checkconf/bad-options-also-notify.conf
new file mode 100644
index 0000000..889a88f
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-options-also-notify.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ also-notify { missing; };
+};
+
+zone "example.net" {
+ type secondary;
+ primaries { 192.168.1.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-parental-agents-def-options.conf b/bin/tests/system/checkconf/bad-parental-agents-def-options.conf
new file mode 100644
index 0000000..2091155
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-agents-def-options.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ parental-agents { 192.168.1.2; };
+};
+
+zone "example.net" {
+ type primary;
+ file "example.net.db";
+};
diff --git a/bin/tests/system/checkconf/bad-parental-agents-def-view.conf b/bin/tests/system/checkconf/bad-parental-agents-def-view.conf
new file mode 100644
index 0000000..47c062a
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-agents-def-view.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "test" {
+ parental-agents { 192.168.1.2; };
+ zone "example.net" {
+ type primary;
+ file "example.net.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-parental-agents-def-view2.conf b/bin/tests/system/checkconf/bad-parental-agents-def-view2.conf
new file mode 100644
index 0000000..aa65a4d
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-agents-def-view2.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "test" {
+ parental-agents "net" {
+ 192.168.1.2;
+ };
+ zone "example.net" {
+ type primary;
+ file "example.net.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-parental-agents-def-zone.conf b/bin/tests/system/checkconf/bad-parental-agents-def-zone.conf
new file mode 100644
index 0000000..e2a8389
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-agents-def-zone.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.net" {
+ type primary;
+ file "example.net.db";
+ parental-agents "net" { 192.168.1.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-parental-agents-dup.conf b/bin/tests/system/checkconf/bad-parental-agents-dup.conf
new file mode 100644
index 0000000..cb5ac44
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-agents-dup.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.net" {
+ type primary;
+ file "example.net.db";
+ parental-agents { 192.168.1.1; };
+ parental-agents { 192.168.1.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-parental-agents-dupdef.conf b/bin/tests/system/checkconf/bad-parental-agents-dupdef.conf
new file mode 100644
index 0000000..7ca88f7
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-agents-dupdef.conf
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+parental-agents "net" {
+ 192.168.1.1;
+};
+
+parental-agents "net" {
+ 192.168.1.2;
+};
+
+zone "example.net" {
+ type primary;
+ file "example.net.db";
+ parental-agents { "net"; };
+};
diff --git a/bin/tests/system/checkconf/bad-parental-agents-empty.conf b/bin/tests/system/checkconf/bad-parental-agents-empty.conf
new file mode 100644
index 0000000..f61de06
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-agents-empty.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+parental-agents "net" { };
+
+zone "example.net" {
+ type primary;
+ file "example.net.db";
+ parental-agents { "net"; };
+};
diff --git a/bin/tests/system/checkconf/bad-parental-agents-empty2.conf b/bin/tests/system/checkconf/bad-parental-agents-empty2.conf
new file mode 100644
index 0000000..93b8f7b
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-agents-empty2.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.net" {
+ type primary;
+ file "example.net.db";
+ parental-agents { };
+};
diff --git a/bin/tests/system/checkconf/bad-parental-agents-mirror.conf b/bin/tests/system/checkconf/bad-parental-agents-mirror.conf
new file mode 100644
index 0000000..62926e2
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-agents-mirror.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type mirror;
+ file "root.mirror";
+ parental-agents { 192.168.1.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-parental-agents-notfound.conf b/bin/tests/system/checkconf/bad-parental-agents-notfound.conf
new file mode 100644
index 0000000..98075c4
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-agents-notfound.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+parental-agents "com" {
+ 192.168.1.2;
+};
+
+zone "example.net" {
+ type primary;
+ file "example.net.db";
+ parental-agents { "net"; };
+};
diff --git a/bin/tests/system/checkconf/bad-parental-source-v6.conf b/bin/tests/system/checkconf/bad-parental-source-v6.conf
new file mode 100644
index 0000000..1b053d0
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-source-v6.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ parental-source-v6 fd92:7065:b8e:ffff::1 port 5300;
+};
diff --git a/bin/tests/system/checkconf/bad-parental-source.conf b/bin/tests/system/checkconf/bad-parental-source.conf
new file mode 100644
index 0000000..9587b3e
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-parental-source.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ parental-source 10.53.0.1 port 5300;
+};
diff --git a/bin/tests/system/checkconf/bad-port.conf b/bin/tests/system/checkconf/bad-port.conf
new file mode 100644
index 0000000..9650c8f
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-port.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 99999;
+};
diff --git a/bin/tests/system/checkconf/bad-primaries-dup.conf b/bin/tests/system/checkconf/bad-primaries-dup.conf
new file mode 100644
index 0000000..ed761c9
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-primaries-dup.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.net" {
+ type secondary;
+ primaries { 192.168.1.1; };
+ masters { 192.168.1.2; };
+};
diff --git a/bin/tests/system/checkconf/bad-primaries-key.conf b/bin/tests/system/checkconf/bad-primaries-key.conf
new file mode 100644
index 0000000..f592293
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-primaries-key.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4 key a..b; };
+};
diff --git a/bin/tests/system/checkconf/bad-primaries-notfound.conf b/bin/tests/system/checkconf/bad-primaries-notfound.conf
new file mode 100644
index 0000000..4640098
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-primaries-notfound.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+primaries "net" {
+ 192.168.1.2;
+};
+
+zone "example.net" {
+ type secondary;
+ primaries { "foo"; };
+};
diff --git a/bin/tests/system/checkconf/bad-primaries-tls.conf b/bin/tests/system/checkconf/bad-primaries-tls.conf
new file mode 100644
index 0000000..7858d1d
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-primaries-tls.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4 tls a..b; };
+};
diff --git a/bin/tests/system/checkconf/bad-printtime.conf b/bin/tests/system/checkconf/bad-printtime.conf
new file mode 100644
index 0000000..80a53cb
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-printtime.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+logging {
+ channel one {
+ file "one.out";
+ print-time bogus;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-acl.conf b/bin/tests/system/checkconf/bad-rate-limit-acl.conf
new file mode 100644
index 0000000..06543fb
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-acl.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ responses-per-second 10;
+ exempt-clients { localhost; localnets; unknownacl; };
+ log-only yes;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-all-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-all-per-second.conf
new file mode 100644
index 0000000..aae353e
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-all-per-second.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ all-per-second 1001; // greater than DNS_RRL_MAX_RATE
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-errors-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-errors-per-second.conf
new file mode 100644
index 0000000..b2c6097
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-errors-per-second.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ errors-per-second 1001; // greater than DNS_RRL_MAX_RATE
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-ipv4-prefix-length.conf b/bin/tests/system/checkconf/bad-rate-limit-ipv4-prefix-length.conf
new file mode 100644
index 0000000..b728575
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-ipv4-prefix-length.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ ipv4-prefix-length 33; // greater than bits in address
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-ipv6-prefix-length.conf b/bin/tests/system/checkconf/bad-rate-limit-ipv6-prefix-length.conf
new file mode 100644
index 0000000..6b5fda5
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-ipv6-prefix-length.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ ipv6-prefix-length 65; // max 64
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-max-table-size.conf b/bin/tests/system/checkconf/bad-rate-limit-max-table-size.conf
new file mode 100644
index 0000000..95309db
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-max-table-size.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ max-table-size 30; // less than min-table-size default of 500
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-nodata-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-nodata-per-second.conf
new file mode 100644
index 0000000..ecfb5f8
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-nodata-per-second.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ nodata-per-second 1001; // greater than DNS_RRL_MAX_RATE
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-nxdomains-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-nxdomains-per-second.conf
new file mode 100644
index 0000000..77c5749
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-nxdomains-per-second.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ nxdomains-per-second 1001; // greater than DNS_RRL_MAX_RATE
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-qps-scale.conf b/bin/tests/system/checkconf/bad-rate-limit-qps-scale.conf
new file mode 100644
index 0000000..0dc4532
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-qps-scale.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ qps-scale 0; // must be greater than zero
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-referrals-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-referrals-per-second.conf
new file mode 100644
index 0000000..0ea4836
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-referrals-per-second.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ referrals-per-second 1001; // greater than DNS_RRL_MAX_RATE
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-responses-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-responses-per-second.conf
new file mode 100644
index 0000000..8187244
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-responses-per-second.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ responses-per-second 1001; // greater than DNS_RRL_MAX_RATE
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-slip.conf b/bin/tests/system/checkconf/bad-rate-limit-slip.conf
new file mode 100644
index 0000000..15d270c
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-slip.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ slip 11; // greater than default of 10
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rate-limit-window.conf b/bin/tests/system/checkconf/bad-rate-limit-window.conf
new file mode 100644
index 0000000..7ded786
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rate-limit-window.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rate-limit {
+ window 3601; // greater than default of 3600
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-root-mixed-key.conf b/bin/tests/system/checkconf/bad-root-mixed-key.conf
new file mode 100644
index 0000000..7035066
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-root-mixed-key.conf
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ # This key (19036) is to be phased out starting in 2017. It will
+ # remain in the root zone for some time after its successor key
+ # has been added. It will remain this file until it is removed from
+ # the root zone.
+ . static-key 257 3 8 "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF
+ FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX
+ bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD
+ X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz
+ W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS
+ Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq
+ QxA+Uk1ihz0=";
+
+ # This key (20326) was published in the root zone in 2017.
+ # Servers which were already using the old key (19036) should
+ # roll seamlessly to this new one via RFC 5011 rollover. Servers
+ # being set up for the first time can use the contents of this
+ # file as initializing keys; thereafter, the keys in the
+ # managed key database will be trusted and maintained
+ # automatically.
+ . initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3
+ +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv
+ ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF
+ 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e
+ oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd
+ RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN
+ R1AkUTV74bU=";
+};
diff --git a/bin/tests/system/checkconf/bad-rpz-too-many-zones.conf b/bin/tests/system/checkconf/bad-rpz-too-many-zones.conf
new file mode 100644
index 0000000..0eb9ef3
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rpz-too-many-zones.conf
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ response-policy {
+ zone "max1";
+ zone "max2";
+ zone "max3";
+ zone "max4";
+ zone "max5";
+ zone "max6";
+ zone "max7";
+ zone "max8";
+ zone "max9";
+ zone "max10";
+ zone "max11";
+ zone "max12";
+ zone "max13";
+ zone "max14";
+ zone "max15";
+ zone "max16";
+ zone "max17";
+ zone "max18";
+ zone "max19";
+ zone "max20";
+ zone "max21";
+ zone "max22";
+ zone "max23";
+ zone "max24";
+ zone "max25";
+ zone "max26";
+ zone "max27";
+ zone "max28";
+ zone "max29";
+ zone "max30";
+ zone "max31";
+ zone "max32";
+ zone "max33";
+ zone "max34";
+ zone "max35";
+ zone "max36";
+ zone "max37";
+ zone "max38";
+ zone "max39";
+ zone "max40";
+ zone "max41";
+ zone "max42";
+ zone "max43";
+ zone "max44";
+ zone "max45";
+ zone "max46";
+ zone "max47";
+ zone "max48";
+ zone "max49";
+ zone "max50";
+ zone "max51";
+ zone "max52";
+ zone "max53";
+ zone "max54";
+ zone "max55";
+ zone "max56";
+ zone "max57";
+ zone "max58";
+ zone "max59";
+ zone "max60";
+ zone "max61";
+ zone "max62";
+ zone "max63";
+ zone "max64";
+ zone "max65";
+ };
+};
+
+zone "max1" { type primary; file "rpz.db"; };
+zone "max2" { type primary; file "rpz.db"; };
+zone "max3" { type primary; file "rpz.db"; };
+zone "max4" { type primary; file "rpz.db"; };
+zone "max5" { type primary; file "rpz.db"; };
+zone "max6" { type primary; file "rpz.db"; };
+zone "max7" { type primary; file "rpz.db"; };
+zone "max8" { type primary; file "rpz.db"; };
+zone "max9" { type primary; file "rpz.db"; };
+zone "max10" { type primary; file "rpz.db"; };
+zone "max11" { type primary; file "rpz.db"; };
+zone "max12" { type primary; file "rpz.db"; };
+zone "max13" { type primary; file "rpz.db"; };
+zone "max14" { type primary; file "rpz.db"; };
+zone "max15" { type primary; file "rpz.db"; };
+zone "max16" { type primary; file "rpz.db"; };
+zone "max17" { type primary; file "rpz.db"; };
+zone "max18" { type primary; file "rpz.db"; };
+zone "max19" { type primary; file "rpz.db"; };
+zone "max20" { type primary; file "rpz.db"; };
+zone "max21" { type primary; file "rpz.db"; };
+zone "max22" { type primary; file "rpz.db"; };
+zone "max23" { type primary; file "rpz.db"; };
+zone "max24" { type primary; file "rpz.db"; };
+zone "max25" { type primary; file "rpz.db"; };
+zone "max26" { type primary; file "rpz.db"; };
+zone "max27" { type primary; file "rpz.db"; };
+zone "max28" { type primary; file "rpz.db"; };
+zone "max29" { type primary; file "rpz.db"; };
+zone "max30" { type primary; file "rpz.db"; };
+zone "max31" { type primary; file "rpz.db"; };
+zone "max32" { type primary; file "rpz.db"; };
+zone "max33" { type primary; file "rpz.db"; };
+zone "max34" { type primary; file "rpz.db"; };
+zone "max35" { type primary; file "rpz.db"; };
+zone "max36" { type primary; file "rpz.db"; };
+zone "max37" { type primary; file "rpz.db"; };
+zone "max38" { type primary; file "rpz.db"; };
+zone "max39" { type primary; file "rpz.db"; };
+zone "max40" { type primary; file "rpz.db"; };
+zone "max41" { type primary; file "rpz.db"; };
+zone "max42" { type primary; file "rpz.db"; };
+zone "max43" { type primary; file "rpz.db"; };
+zone "max44" { type primary; file "rpz.db"; };
+zone "max45" { type primary; file "rpz.db"; };
+zone "max46" { type primary; file "rpz.db"; };
+zone "max47" { type primary; file "rpz.db"; };
+zone "max48" { type primary; file "rpz.db"; };
+zone "max49" { type primary; file "rpz.db"; };
+zone "max50" { type primary; file "rpz.db"; };
+zone "max51" { type primary; file "rpz.db"; };
+zone "max52" { type primary; file "rpz.db"; };
+zone "max53" { type primary; file "rpz.db"; };
+zone "max54" { type primary; file "rpz.db"; };
+zone "max55" { type primary; file "rpz.db"; };
+zone "max56" { type primary; file "rpz.db"; };
+zone "max57" { type primary; file "rpz.db"; };
+zone "max58" { type primary; file "rpz.db"; };
+zone "max59" { type primary; file "rpz.db"; };
+zone "max60" { type primary; file "rpz.db"; };
+zone "max61" { type primary; file "rpz.db"; };
+zone "max62" { type primary; file "rpz.db"; };
+zone "max63" { type primary; file "rpz.db"; };
+zone "max64" { type primary; file "rpz.db"; };
+zone "max65" { type primary; file "rpz.db"; };
diff --git a/bin/tests/system/checkconf/bad-rpz-ttl.conf b/bin/tests/system/checkconf/bad-rpz-ttl.conf
new file mode 100644
index 0000000..7b3a6ef
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rpz-ttl.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com." {
+ type primary;
+ file "example.com.zone";
+};
+
+options {
+ response-policy {
+ zone "example.com." policy given;
+ }
+ max-policy-ttl 1x;
+};
diff --git a/bin/tests/system/checkconf/bad-rpz-update.conf b/bin/tests/system/checkconf/bad-rpz-update.conf
new file mode 100644
index 0000000..a03f179
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rpz-update.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com." {
+ type primary;
+ file "example.com.zone";
+};
+
+options {
+ response-policy {
+ zone "example.com."
+ policy given
+ min-update-interval 5x;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-rpz-zone.conf b/bin/tests/system/checkconf/bad-rpz-zone.conf
new file mode 100644
index 0000000..4aadc61
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-rpz-zone.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ response-policy {
+ zone "nonexistent";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-sharedwritable1.conf b/bin/tests/system/checkconf/bad-sharedwritable1.conf
new file mode 100644
index 0000000..3fcb1af
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-sharedwritable1.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone a {
+ type primary;
+ file "shared.db";
+};
+zone b {
+ type secondary;
+ file "shared.db";
+ primaries { 1.2.3.4; };
+};
diff --git a/bin/tests/system/checkconf/bad-sharedwritable2.conf b/bin/tests/system/checkconf/bad-sharedwritable2.conf
new file mode 100644
index 0000000..e8c940c
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-sharedwritable2.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone a {
+ type secondary;
+ file "shared.db";
+ primaries { 1.2.3.4; };
+};
+zone b {
+ type secondary;
+ file "shared.db";
+ primaries { 1.2.3.4; };
+};
diff --git a/bin/tests/system/checkconf/bad-sharedzone1.conf b/bin/tests/system/checkconf/bad-sharedzone1.conf
new file mode 100644
index 0000000..fccffe9
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-sharedzone1.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "first" {
+ match-clients {
+ "none";
+ };
+ zone "clone" {
+ type primary;
+ file "xxx";
+ };
+};
+view "second" {
+ match-clients {
+ "any";
+ };
+ zone "clone" {
+ in-view "first";
+ type secondary;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-sharedzone2.conf b/bin/tests/system/checkconf/bad-sharedzone2.conf
new file mode 100644
index 0000000..76032e3
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-sharedzone2.conf
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "first" {
+ match-clients {
+ "none";
+ };
+ zone "clone" {
+ type primary;
+ file "xxx";
+ };
+};
+view "second" {
+ match-clients {
+ "any";
+ };
+ zone "clone" {
+ in-view "first";
+ forward only;
+ forwarders { 10.0.0.100; };
+ type secondary;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-sharedzone3.conf b/bin/tests/system/checkconf/bad-sharedzone3.conf
new file mode 100644
index 0000000..07e92bd
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-sharedzone3.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view first {
+ zone shared.example {
+ in-view second;
+ };
+};
+
+view second {
+ zone shared.example {
+ type primary;
+ file "shared.example.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-sig-validity.conf b/bin/tests/system/checkconf/bad-sig-validity.conf
new file mode 100644
index 0000000..1744eba
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-sig-validity.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ sig-validity-interval 5000;
+};
diff --git a/bin/tests/system/checkconf/bad-static-initial-1.conf b/bin/tests/system/checkconf/bad-static-initial-1.conf
new file mode 100644
index 0000000..91a5c10
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-static-initial-1.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ example. initial-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
+ example. static-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6";
+};
diff --git a/bin/tests/system/checkconf/bad-static-initial-2.conf b/bin/tests/system/checkconf/bad-static-initial-2.conf
new file mode 100644
index 0000000..3b4754d
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-static-initial-2.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ example. initial-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
+ example. static-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/bad-static-initial-3.conf b/bin/tests/system/checkconf/bad-static-initial-3.conf
new file mode 100644
index 0000000..c396d9c
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-static-initial-3.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ example. static-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
+ example. initial-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/bad-static-initial-4.conf b/bin/tests/system/checkconf/bad-static-initial-4.conf
new file mode 100644
index 0000000..2170d52
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-static-initial-4.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ example. initial-key 257 3 5 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafGtURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJYkYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJfpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaSWG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjINQyrszHhWUU=";
+ example. static-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/bad-stub-masters-dialup.conf b/bin/tests/system/checkconf/bad-stub-masters-dialup.conf
new file mode 100644
index 0000000..a30236c
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-stub-masters-dialup.conf
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ heartbeat-interval 2;
+ recursion no;
+};
+zone "." {
+ type hint;
+ file "hint";
+};
+zone "example." {
+ type stub;
+ dialup notify;
+ notify no;
+ file "example.bk";
+ // primaries { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/bad-transfer-source-v6.conf b/bin/tests/system/checkconf/bad-transfer-source-v6.conf
new file mode 100644
index 0000000..da182ff
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-transfer-source-v6.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ transfer-source-v6 fd92:7065:b8e:ffff::1 port 5300;
+};
diff --git a/bin/tests/system/checkconf/bad-transfer-source.conf b/bin/tests/system/checkconf/bad-transfer-source.conf
new file mode 100644
index 0000000..315c410
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-transfer-source.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ transfer-source 10.53.0.1 port 5300;
+};
diff --git a/bin/tests/system/checkconf/bad-tsig.conf b/bin/tests/system/checkconf/bad-tsig.conf
new file mode 100644
index 0000000..4af25b0
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-tsig.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* Bad secret */
+key "badtsig" {
+ algorithm hmac-md5;
+ secret "jEdD+BPKg==";
+};
+
diff --git a/bin/tests/system/checkconf/bad-unpaired-keys.conf b/bin/tests/system/checkconf/bad-unpaired-keys.conf
new file mode 100644
index 0000000..63b6dc2
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-unpaired-keys.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy unpaired-keys {
+ keys {
+ /* zsk without ksk */
+ zsk lifetime 30d algorithm 13;
+ /* ksk without zsk */
+ ksk lifetime 30d algorithm 7;
+ };
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ dnssec-policy unpaired-keys;
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy1.conf b/bin/tests/system/checkconf/bad-update-policy1.conf
new file mode 100644
index 0000000..fa1330c
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy1.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * self TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy10.conf b/bin/tests/system/checkconf/bad-update-policy10.conf
new file mode 100644
index 0000000..39ac656
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy10.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * krb5-selfsub TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy11.conf b/bin/tests/system/checkconf/bad-update-policy11.conf
new file mode 100644
index 0000000..d148b58
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy11.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * ms-selfsub TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy12.conf b/bin/tests/system/checkconf/bad-update-policy12.conf
new file mode 100644
index 0000000..dc79db3
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy12.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * external TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy13.conf b/bin/tests/system/checkconf/bad-update-policy13.conf
new file mode 100644
index 0000000..694c73b
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy13.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant a-key-name name TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy14.conf b/bin/tests/system/checkconf/bad-update-policy14.conf
new file mode 100644
index 0000000..af02ef2
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy14.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant a-key-name subdomain TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy15.conf b/bin/tests/system/checkconf/bad-update-policy15.conf
new file mode 100644
index 0000000..f8f7d13
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy15.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant a-key-name wildcard TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy16.conf b/bin/tests/system/checkconf/bad-update-policy16.conf
new file mode 100644
index 0000000..747c381
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy16.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * tcp-self . "ptr(10 )";
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy17.conf b/bin/tests/system/checkconf/bad-update-policy17.conf
new file mode 100644
index 0000000..a2955f2
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy17.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant realm krb5-subdomain-self-rhs PTR;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy18.conf b/bin/tests/system/checkconf/bad-update-policy18.conf
new file mode 100644
index 0000000..090f621
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy18.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant realm krb5-subdomain-self-rhs SRV;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy19.conf b/bin/tests/system/checkconf/bad-update-policy19.conf
new file mode 100644
index 0000000..b8c636b
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy19.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant realm ms-subdomain-self-rhs PTR;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy2.conf b/bin/tests/system/checkconf/bad-update-policy2.conf
new file mode 100644
index 0000000..0d5adf6
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy2.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * selfsub TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy20.conf b/bin/tests/system/checkconf/bad-update-policy20.conf
new file mode 100644
index 0000000..9775e2c
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy20.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant realm ms-subdomain-self-rhs SRV;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy3.conf b/bin/tests/system/checkconf/bad-update-policy3.conf
new file mode 100644
index 0000000..4583ede
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy3.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * selfwild TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy4.conf b/bin/tests/system/checkconf/bad-update-policy4.conf
new file mode 100644
index 0000000..52a074d
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy4.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * ms-self TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy5.conf b/bin/tests/system/checkconf/bad-update-policy5.conf
new file mode 100644
index 0000000..38a6d4f
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy5.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * krb5-self TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy6.conf b/bin/tests/system/checkconf/bad-update-policy6.conf
new file mode 100644
index 0000000..acca627
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy6.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * ms-subdomain TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy7.conf b/bin/tests/system/checkconf/bad-update-policy7.conf
new file mode 100644
index 0000000..95541d4
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy7.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * krb5-subdomain TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy8.conf b/bin/tests/system/checkconf/bad-update-policy8.conf
new file mode 100644
index 0000000..d0534c4
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy8.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * tcp-self TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-update-policy9.conf b/bin/tests/system/checkconf/bad-update-policy9.conf
new file mode 100644
index 0000000..96d201c
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-update-policy9.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * 6to4-self TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-validation-auto-key.conf b/bin/tests/system/checkconf/bad-validation-auto-key.conf
new file mode 100644
index 0000000..bd6f547
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-validation-auto-key.conf
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnssec-validation auto;
+};
+
+trust-anchors {
+ . static-key 257 3 8 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbod
+ y0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQ
+ YfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX
+ 2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuw
+ E60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/
+ Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn
+ 6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/bad-view-also-notify.conf b/bin/tests/system/checkconf/bad-view-also-notify.conf
new file mode 100644
index 0000000..071a621
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-view-also-notify.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view example {
+ also-notify { missing; };
+ zone "example.net" {
+ type secondary;
+ primaries { 192.168.1.1; };
+ };
+};
diff --git a/bin/tests/system/checkconf/bad-zsk-without-ksk.conf b/bin/tests/system/checkconf/bad-zsk-without-ksk.conf
new file mode 100644
index 0000000..31b031c
--- /dev/null
+++ b/bin/tests/system/checkconf/bad-zsk-without-ksk.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy zsk-without-ksk {
+ keys {
+ zsk lifetime 30d algorithm 13;
+ };
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ dnssec-policy zsk-without-ksk;
+};
diff --git a/bin/tests/system/checkconf/check-dup-records-fail.conf b/bin/tests/system/checkconf/check-dup-records-fail.conf
new file mode 100644
index 0000000..04880b6
--- /dev/null
+++ b/bin/tests/system/checkconf/check-dup-records-fail.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-integrity yes; // default is yes
+};
+
+zone "check-dup-records" {
+ type primary;
+ file "check-dup-records.db";
+ check-dup-records fail;
+};
+
diff --git a/bin/tests/system/checkconf/check-dup-records.db b/bin/tests/system/checkconf/check-dup-records.db
new file mode 100644
index 0000000..558686c
--- /dev/null
+++ b/bin/tests/system/checkconf/check-dup-records.db
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600 ; 10 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ MX 10 mail
+
+mail A 10.0.0.1
+ns2 A 10.53.0.2
+
+; following records are not de-duplicated
+; and will be matched by check-dup-records
+duplicate HIP ( 2 200100107B1A74DF365639CC39F1D578
+ AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
+ rvs.example.com. )
+duplicate HIP ( 2 200100107B1A74DF365639CC39F1D578
+ AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
+ RVS.example.com. )
diff --git a/bin/tests/system/checkconf/check-missing-zone.conf b/bin/tests/system/checkconf/check-missing-zone.conf
new file mode 100644
index 0000000..daf2cf7
--- /dev/null
+++ b/bin/tests/system/checkconf/check-missing-zone.conf
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view missing {
+ zone missing.example {
+ type primary;
+ file "missing.example.db";
+ };
+};
+
+view good {
+ zone shared.example {
+ type primary;
+ file "shared.example.db";
+ };
+};
diff --git a/bin/tests/system/checkconf/check-mixed-keys.conf b/bin/tests/system/checkconf/check-mixed-keys.conf
new file mode 100644
index 0000000..1dd018d
--- /dev/null
+++ b/bin/tests/system/checkconf/check-mixed-keys.conf
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ # This key (19036) is to be phased out starting in 2017. It will
+ # remain in the root zone for some time after its successor key
+ # has been added. It will remain this file until it is removed from
+ # the root zone.
+ . static-key 257 3 8 "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF
+ FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX
+ bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD
+ X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz
+ W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS
+ Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq
+ QxA+Uk1ihz0=";
+};
+
+managed-keys {
+ # This key (20326) was published in the root zone in 2017.
+ # Servers which were already using the old key (19036) should
+ # roll seamlessly to this new one via RFC 5011 rollover. Servers
+ # being set up for the first time can use the contents of this
+ # file as initializing keys; thereafter, the keys in the
+ # managed key database will be trusted and maintained
+ # automatically.
+ . initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3
+ +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv
+ ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF
+ 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e
+ oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd
+ RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN
+ R1AkUTV74bU=";
+};
diff --git a/bin/tests/system/checkconf/check-mx-cname-fail.conf b/bin/tests/system/checkconf/check-mx-cname-fail.conf
new file mode 100644
index 0000000..ac52ec0
--- /dev/null
+++ b/bin/tests/system/checkconf/check-mx-cname-fail.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-integrity yes; // default is yes
+};
+
+zone "check-mx-cname" {
+ type primary;
+ file "check-mx-cname.db";
+ check-mx-cname fail;
+};
diff --git a/bin/tests/system/checkconf/check-mx-cname.db b/bin/tests/system/checkconf/check-mx-cname.db
new file mode 100644
index 0000000..dc30f08
--- /dev/null
+++ b/bin/tests/system/checkconf/check-mx-cname.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600 ; 10 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ MX 10 mail
+
+; MX points to a CNAME which is detected by check-mx-cname
+mail CNAME ns2
+
+ns2 A 10.53.0.2
diff --git a/bin/tests/system/checkconf/check-mx-fail.conf b/bin/tests/system/checkconf/check-mx-fail.conf
new file mode 100644
index 0000000..aa7a666
--- /dev/null
+++ b/bin/tests/system/checkconf/check-mx-fail.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-integrity yes; // default is yes
+};
+
+zone "check-mx" {
+ type primary;
+ file "check-mx.db";
+ check-mx fail;
+};
diff --git a/bin/tests/system/checkconf/check-mx.db b/bin/tests/system/checkconf/check-mx.db
new file mode 100644
index 0000000..dced644
--- /dev/null
+++ b/bin/tests/system/checkconf/check-mx.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600 ; 10 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+; MX appears to be an address and will be detected by check-mx
+ MX 10 10.0.0.1
+
+ns2 A 10.53.0.2
diff --git a/bin/tests/system/checkconf/check-names-fail.conf b/bin/tests/system/checkconf/check-names-fail.conf
new file mode 100644
index 0000000..86be82d
--- /dev/null
+++ b/bin/tests/system/checkconf/check-names-fail.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-integrity yes; // default is yes
+};
+
+zone "check-names" {
+ type primary;
+ file "check-names.db";
+ check-names fail;
+};
diff --git a/bin/tests/system/checkconf/check-names.db b/bin/tests/system/checkconf/check-names.db
new file mode 100644
index 0000000..0274ec9
--- /dev/null
+++ b/bin/tests/system/checkconf/check-names.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600 ; 10 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ MX 10 mail
+
+mail A 10.0.0.1
+ns2 A 10.53.0.2
+
+; the RDATA of this record contains a name that may be considered
+; invalid and will be detected by check-names configuration.
+check-names SRV 1 2 3 _underscore
diff --git a/bin/tests/system/checkconf/check-root-ksk-2010.conf b/bin/tests/system/checkconf/check-root-ksk-2010.conf
new file mode 100644
index 0000000..d422635
--- /dev/null
+++ b/bin/tests/system/checkconf/check-root-ksk-2010.conf
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ # This key (19036) is to be phased out starting in 2017. It will
+ # remain in the root zone for some time after its successor key
+ # has been added. It will remain this file until it is removed from
+ # the root zone.
+ . initial-key 257 3 8 "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF
+ FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX
+ bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD
+ X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz
+ W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS
+ Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq
+ QxA+Uk1ihz0=";
+};
diff --git a/bin/tests/system/checkconf/check-root-ksk-2017.conf b/bin/tests/system/checkconf/check-root-ksk-2017.conf
new file mode 100644
index 0000000..72f6fb4
--- /dev/null
+++ b/bin/tests/system/checkconf/check-root-ksk-2017.conf
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ # This key (20326) was published in the root zone in 2017.
+ # Servers which were already using the old key (19036) should
+ # roll seamlessly to this new one via RFC 5011 rollover. Servers
+ # being set up for the first time can use the contents of this
+ # file as initializing keys; thereafter, the keys in the
+ # managed key database will be trusted and maintained
+ # automatically.
+ . initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3
+ +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv
+ ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF
+ 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e
+ oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd
+ RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN
+ R1AkUTV74bU=";
+};
diff --git a/bin/tests/system/checkconf/check-root-ksk-both.conf b/bin/tests/system/checkconf/check-root-ksk-both.conf
new file mode 100644
index 0000000..88c308f
--- /dev/null
+++ b/bin/tests/system/checkconf/check-root-ksk-both.conf
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ # This key (19036) is to be phased out starting in 2017. It will
+ # remain in the root zone for some time after its successor key
+ # has been added. It will remain this file until it is removed from
+ # the root zone.
+ . initial-key 257 3 8 "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF
+ FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX
+ bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD
+ X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz
+ W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS
+ Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq
+ QxA+Uk1ihz0=";
+
+ # This key (20326) was published in the root zone in 2017.
+ # Servers which were already using the old key (19036) should
+ # roll seamlessly to this new one via RFC 5011 rollover. Servers
+ # being set up for the first time can use the contents of this
+ # file as initializing keys; thereafter, the keys in the
+ # managed key database will be trusted and maintained
+ # automatically.
+ . initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3
+ +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv
+ ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF
+ 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e
+ oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd
+ RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN
+ R1AkUTV74bU=";
+};
diff --git a/bin/tests/system/checkconf/check-root-static-ds.conf b/bin/tests/system/checkconf/check-root-static-ds.conf
new file mode 100644
index 0000000..eb37b85
--- /dev/null
+++ b/bin/tests/system/checkconf/check-root-static-ds.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ . static-ds 20326 8 2 "E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D";
+};
diff --git a/bin/tests/system/checkconf/check-root-static-key.conf b/bin/tests/system/checkconf/check-root-static-key.conf
new file mode 100644
index 0000000..7be5304
--- /dev/null
+++ b/bin/tests/system/checkconf/check-root-static-key.conf
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ # This key (20326) was published in the root zone in 2017.
+ # Servers which were already using the old key (19036) should
+ # roll seamlessly to this new one via RFC 5011 rollover. Servers
+ # being set up for the first time can use the contents of this
+ # file as initializing keys; thereafter, the keys in the
+ # managed key database will be trusted and maintained
+ # automatically.
+ . static-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3
+ +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv
+ ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF
+ 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e
+ oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd
+ RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN
+ R1AkUTV74bU=";
+};
diff --git a/bin/tests/system/checkconf/check-root-trusted-key.conf b/bin/tests/system/checkconf/check-root-trusted-key.conf
new file mode 100644
index 0000000..65261a8
--- /dev/null
+++ b/bin/tests/system/checkconf/check-root-trusted-key.conf
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trusted-keys {
+ # This key (20326) was published in the root zone in 2017.
+ # Servers which were already using the old key (19036) should
+ # roll seamlessly to this new one via RFC 5011 rollover. Servers
+ # being set up for the first time can use the contents of this
+ # file as initializing keys; thereafter, the keys in the
+ # managed key database will be trusted and maintained
+ # automatically.
+ . 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3
+ +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv
+ ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF
+ 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e
+ oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd
+ RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN
+ R1AkUTV74bU=";
+};
diff --git a/bin/tests/system/checkconf/check-srv-cname-fail.conf b/bin/tests/system/checkconf/check-srv-cname-fail.conf
new file mode 100644
index 0000000..3897bf8
--- /dev/null
+++ b/bin/tests/system/checkconf/check-srv-cname-fail.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ check-integrity yes; // default is yes
+};
+
+zone "check-srv-cname" {
+ type primary;
+ file "check-srv-cname.db";
+ check-srv-cname fail;
+};
diff --git a/bin/tests/system/checkconf/check-srv-cname.db b/bin/tests/system/checkconf/check-srv-cname.db
new file mode 100644
index 0000000..0671ab1
--- /dev/null
+++ b/bin/tests/system/checkconf/check-srv-cname.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600 ; 10 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ MX 10 mail
+
+mail A 10.0.0.1
+ns2 A 10.53.0.2
+
+check-srv-cname SRV 1 2 3 target
+; SRV points to a CNAME which is detected by check-srv-cname configuration
+target CNAME mail
diff --git a/bin/tests/system/checkconf/check-wildcard-no.conf b/bin/tests/system/checkconf/check-wildcard-no.conf
new file mode 100644
index 0000000..beb641a
--- /dev/null
+++ b/bin/tests/system/checkconf/check-wildcard-no.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "check-wildcard" {
+ type primary;
+ file "check-wildcard.db";
+ check-wildcard no;
+};
diff --git a/bin/tests/system/checkconf/check-wildcard.conf b/bin/tests/system/checkconf/check-wildcard.conf
new file mode 100644
index 0000000..263f8b4
--- /dev/null
+++ b/bin/tests/system/checkconf/check-wildcard.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "check-wildcard" {
+ type primary;
+ file "check-wildcard.db";
+ check-wildcard yes;
+};
diff --git a/bin/tests/system/checkconf/check-wildcard.db b/bin/tests/system/checkconf/check-wildcard.db
new file mode 100644
index 0000000..1db5af0
--- /dev/null
+++ b/bin/tests/system/checkconf/check-wildcard.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600 ; 10 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+; an interior wildcard name
+foo.* TXT The owner name contains an interior wildcard
diff --git a/bin/tests/system/checkconf/clean.sh b/bin/tests/system/checkconf/clean.sh
new file mode 100644
index 0000000..8981c45
--- /dev/null
+++ b/bin/tests/system/checkconf/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f bad-kasp-keydir1.conf
+rm -f bad-kasp-keydir2.conf
+rm -f bad-kasp-keydir3.conf
+rm -f bad-kasp-keydir4.conf
+rm -f bad-kasp-keydir5.conf
+rm -f checkconf.out*
+rm -f diff.out*
+rm -f good-kasp.conf.in
+rm -f good-server-christmas-tree.conf
+rm -f good.conf.in good.conf.out badzero.conf *.out
+rm -rf keys
+rm -f ns*/named.lock
+rm -rf test.keydir
diff --git a/bin/tests/system/checkconf/deprecated.conf b/bin/tests/system/checkconf/deprecated.conf
new file mode 100644
index 0000000..bd6e0c2
--- /dev/null
+++ b/bin/tests/system/checkconf/deprecated.conf
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+server 1.2.3.4 {
+ query-source 10.10.10.10 port 5353;
+};
+
+options {
+ dnssec-validation yes;
+
+ dialup yes;
+ heartbeat-interval 60;
+
+ dnssec-must-be-secure mustbesecure.example yes;
+
+ use-v4-udp-ports { range 1024 65535; };
+ use-v6-udp-ports { range 1024 65535; };
+ avoid-v4-udp-ports { range 1 1023; };
+ avoid-v6-udp-ports { range 1 1023; };
+
+ tkey-dhkey "server" 12345;
+
+ root-delegation-only exclude { "them"; };
+};
+
+trusted-keys {
+ fake.trusted. 257 3 8
+ "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF
+ FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX
+ bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD
+ X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz
+ W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS
+ Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq
+ QxA+Uk1ihz0=";
+};
+
+managed-keys {
+ fake.managed. initial-key 257 3 8
+ "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3
+ +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv
+ ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF
+ 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e
+ oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd
+ RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN
+ R1AkUTV74bU=";
+};
+
+zone "." {
+ type hint;
+ file "shared.example.db";
+ delegation-only yes;
+};
+
+zone com {
+ type delegation-only;
+};
diff --git a/bin/tests/system/checkconf/dlz-bad.conf b/bin/tests/system/checkconf/dlz-bad.conf
new file mode 100644
index 0000000..7332112
--- /dev/null
+++ b/bin/tests/system/checkconf/dlz-bad.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dlz one {
+ database "one";
+};
+
+dlz two {
+ database "two";
+ search no;
+};
+
+zone primary {
+ type primary;
+ database "none";
+ dlz two;
+};
diff --git a/bin/tests/system/checkconf/dnssec.1 b/bin/tests/system/checkconf/dnssec.1
new file mode 100644
index 0000000..a466ac4
--- /dev/null
+++ b/bin/tests/system/checkconf/dnssec.1
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view view1 {
+ match-clients { any; };
+ dnssec-validation yes;
+};
+
+view view2 {
+ match-clients { none; };
+ dnssec-validation auto;
+};
+
+view view3 {
+ match-clients { none; };
+ auto-dnssec maintain;
+};
diff --git a/bin/tests/system/checkconf/dnssec.2 b/bin/tests/system/checkconf/dnssec.2
new file mode 100644
index 0000000..0f6a8af
--- /dev/null
+++ b/bin/tests/system/checkconf/dnssec.2
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view view1 {
+ match-clients { any; };
+};
+
+view view2 {
+ match-clients { none; };
+};
+
+view view3 {
+ match-clients { none; };
+ dnssec-validation auto;
+};
+
+view view4 {
+ match-clients { none; };
+};
+
+view view5 {
+ match-clients { none; };
+ auto-dnssec off;
+};
diff --git a/bin/tests/system/checkconf/dnssec.3 b/bin/tests/system/checkconf/dnssec.3
new file mode 100644
index 0000000..53e5d91
--- /dev/null
+++ b/bin/tests/system/checkconf/dnssec.3
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "test" {
+ type primary;
+ file "test.db";
+ auto-dnssec maintain;
+};
diff --git a/bin/tests/system/checkconf/good-acl.conf b/bin/tests/system/checkconf/good-acl.conf
new file mode 100644
index 0000000..be32923
--- /dev/null
+++ b/bin/tests/system/checkconf/good-acl.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl a {
+ { "none"; };
+ { !19.0.0.0/8; };
+};
+
+options {
+ allow-query { a; };
+};
diff --git a/bin/tests/system/checkconf/good-allow-update-forwarding-view.conf b/bin/tests/system/checkconf/good-allow-update-forwarding-view.conf
new file mode 100644
index 0000000..5bc9232
--- /dev/null
+++ b/bin/tests/system/checkconf/good-allow-update-forwarding-view.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ allow-update-forwarding { any; };
+};
diff --git a/bin/tests/system/checkconf/good-allow-update-forwarding.conf b/bin/tests/system/checkconf/good-allow-update-forwarding.conf
new file mode 100644
index 0000000..d7e89be
--- /dev/null
+++ b/bin/tests/system/checkconf/good-allow-update-forwarding.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ allow-update-forwarding { any; };
+};
diff --git a/bin/tests/system/checkconf/good-allow-update-view.conf b/bin/tests/system/checkconf/good-allow-update-view.conf
new file mode 100644
index 0000000..da799a2
--- /dev/null
+++ b/bin/tests/system/checkconf/good-allow-update-view.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ allow-update { any; };
+};
diff --git a/bin/tests/system/checkconf/good-allow-update.conf b/bin/tests/system/checkconf/good-allow-update.conf
new file mode 100644
index 0000000..6b7a67e
--- /dev/null
+++ b/bin/tests/system/checkconf/good-allow-update.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ allow-update { any; };
+};
diff --git a/bin/tests/system/checkconf/good-class.conf b/bin/tests/system/checkconf/good-class.conf
new file mode 100644
index 0000000..2f8c321
--- /dev/null
+++ b/bin/tests/system/checkconf/good-class.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "example" class00 { };
diff --git a/bin/tests/system/checkconf/good-dnskey-validity-3660.conf b/bin/tests/system/checkconf/good-dnskey-validity-3660.conf
new file mode 100644
index 0000000..4e0a7ee
--- /dev/null
+++ b/bin/tests/system/checkconf/good-dnskey-validity-3660.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnskey-sig-validity 3660; /* maximum value 10 years */
+};
diff --git a/bin/tests/system/checkconf/good-dnskey-validity-zero.conf b/bin/tests/system/checkconf/good-dnskey-validity-zero.conf
new file mode 100644
index 0000000..5da41b8
--- /dev/null
+++ b/bin/tests/system/checkconf/good-dnskey-validity-zero.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnskey-sig-validity 0; /* 0 is disabled */
+};
diff --git a/bin/tests/system/checkconf/good-doh-1.conf b/bin/tests/system/checkconf/good-doh-1.conf
new file mode 100644
index 0000000..0c642ec
--- /dev/null
+++ b/bin/tests/system/checkconf/good-doh-1.conf
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+http local-http-server {
+ endpoints { "/dns-query"; };
+ listener-clients 100;
+ streams-per-connection 100;
+};
+
+options {
+ listen-on { 10.53.0.1; };
+ http-port 80;
+ https-port 443;
+ http-listener-clients 100;
+ http-streams-per-connection 100;
+ listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; };
+ listen-on port 8080 tls none http local-http-server { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/good-doh-2.conf b/bin/tests/system/checkconf/good-doh-2.conf
new file mode 100644
index 0000000..1bbe9e0
--- /dev/null
+++ b/bin/tests/system/checkconf/good-doh-2.conf
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+http local-http-server {
+ endpoints { "/dns-query"; };
+};
+
+options {
+ listen-on { 10.53.0.1; };
+ http-port 80;
+ https-port 443;
+ listen-on port 443 http local-http-server tls local-tls { 10.53.0.1; };
+ listen-on port 8080 tls none http local-http-server { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/good-doh-3.conf b/bin/tests/system/checkconf/good-doh-3.conf
new file mode 100644
index 0000000..cd410b9
--- /dev/null
+++ b/bin/tests/system/checkconf/good-doh-3.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ listen-on { 10.53.0.1; };
+ http-port 80;
+ https-port 443;
+ listen-on port 8080 tls none http default { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/good-doh-4.conf b/bin/tests/system/checkconf/good-doh-4.conf
new file mode 100644
index 0000000..d191347
--- /dev/null
+++ b/bin/tests/system/checkconf/good-doh-4.conf
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+# Use the default values only - just to make sure that we could
+# override only values which we need and there is no required ones.
+http empty-http-server {
+};
+
+options {
+ listen-on { 10.53.0.1; };
+ http-port 80;
+ https-port 443;
+ http-listener-clients 100;
+ listen-on port 443 tls local-tls http empty-http-server { 10.53.0.1; };
+ listen-on port 8080 tls none http empty-http-server { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/good-doh-tlsopts.conf b/bin/tests/system/checkconf/good-doh-tlsopts.conf
new file mode 100644
index 0000000..7ba4bdb
--- /dev/null
+++ b/bin/tests/system/checkconf/good-doh-tlsopts.conf
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ protocols { TLSv1.2; };
+ key-file "key.pem";
+ cert-file "cert.pem";
+ dhparam-file "dhparam.pem";
+ ciphers "HIGH:!aNULL:!MD5:!RC4";
+ prefer-server-ciphers yes;
+ session-tickets no;
+};
+
+http local-http-server {
+ endpoints { "/dns-query"; };
+ listener-clients 100;
+ streams-per-connection 100;
+};
+
+options {
+ listen-on { 10.53.0.1; };
+ http-port 80;
+ https-port 443;
+ http-listener-clients 100;
+ http-streams-per-connection 100;
+ listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; };
+ listen-on port 8080 tls none http local-http-server { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/good-dot-1.conf b/bin/tests/system/checkconf/good-dot-1.conf
new file mode 100644
index 0000000..d94616a
--- /dev/null
+++ b/bin/tests/system/checkconf/good-dot-1.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+options {
+ listen-on port 853 tls local-tls { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/good-dot-allow-transfer-encrypted.conf b/bin/tests/system/checkconf/good-dot-allow-transfer-encrypted.conf
new file mode 100644
index 0000000..74c7969
--- /dev/null
+++ b/bin/tests/system/checkconf/good-dot-allow-transfer-encrypted.conf
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example1" {
+ type primary;
+ file "example1.db";
+ allow-transfer port 44344 transport tls { any; };
+};
+
+zone "example2" {
+ type primary;
+ file "example2.db";
+ allow-transfer port 44344 transport tcp { any; };
+};
+
+zone "example3" {
+ type primary;
+ file "example3.db";
+ allow-transfer transport tls { any; };
+};
+
+zone "example4" {
+ type primary;
+ file "example4.db";
+ allow-transfer transport tcp { any; };
+};
+
+
+zone "example5" {
+ type primary;
+ file "example5.db";
+ allow-transfer port 53 { any; };
+};
+
+zone "example6" {
+ type primary;
+ file "example6.db";
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/checkconf/good-dot-doh-tls-nokeycert.conf b/bin/tests/system/checkconf/good-dot-doh-tls-nokeycert.conf
new file mode 100644
index 0000000..d541d15
--- /dev/null
+++ b/bin/tests/system/checkconf/good-dot-doh-tls-nokeycert.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# In some cases a "tls" statement may omit key-file and cert-file.
+tls local-tls {
+ protocols {TLSv1.2;};
+ remote-hostname "fqdn.example.com";
+};
diff --git a/bin/tests/system/checkconf/good-dot-primaries-ephemeral.conf b/bin/tests/system/checkconf/good-dot-primaries-ephemeral.conf
new file mode 100644
index 0000000..2b33cf3
--- /dev/null
+++ b/bin/tests/system/checkconf/good-dot-primaries-ephemeral.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.1 tls ephemeral; };
+ file "example.db";
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/checkconf/good-dot-primaries.conf b/bin/tests/system/checkconf/good-dot-primaries.conf
new file mode 100644
index 0000000..592a94c
--- /dev/null
+++ b/bin/tests/system/checkconf/good-dot-primaries.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ protocols { TLSv1.2; };
+ ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+ prefer-server-ciphers no;
+};
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.1 tls local-tls; };
+ file "example.db";
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/checkconf/good-dot-tlsopts.conf b/bin/tests/system/checkconf/good-dot-tlsopts.conf
new file mode 100644
index 0000000..fc7e248
--- /dev/null
+++ b/bin/tests/system/checkconf/good-dot-tlsopts.conf
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ protocols { TLSv1.2; };
+ key-file "key.pem";
+ cert-file "cert.pem";
+ dhparam-file "dhparam.pem";
+ ciphers "HIGH:!aNULL:!MD5:!RC4";
+ prefer-server-ciphers yes;
+ session-tickets no;
+};
+
+options {
+ listen-on port 853 tls local-tls { 10.53.0.1; };
+};
diff --git a/bin/tests/system/checkconf/good-ds-key-1.conf b/bin/tests/system/checkconf/good-ds-key-1.conf
new file mode 100644
index 0000000..de7de84
--- /dev/null
+++ b/bin/tests/system/checkconf/good-ds-key-1.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ example. initial-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
+ example. initial-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/good-ds-key-2.conf b/bin/tests/system/checkconf/good-ds-key-2.conf
new file mode 100644
index 0000000..060fb2f
--- /dev/null
+++ b/bin/tests/system/checkconf/good-ds-key-2.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ example. static-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
+ example. static-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/good-dup-managed-key.conf b/bin/tests/system/checkconf/good-dup-managed-key.conf
new file mode 100644
index 0000000..2f91247
--- /dev/null
+++ b/bin/tests/system/checkconf/good-dup-managed-key.conf
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnssec-validation yes;
+};
+
+trust-anchors {
+ example. initial-key 257 3 8 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl
+ 25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafG
+ tURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJY
+ kYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJ
+ fpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaS
+ WG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjI
+ NQyrszHhWUU=";
+ example. initial-key 257 3 8 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbod
+ y0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQ
+ YfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX
+ 2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuw
+ E60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/
+ Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn
+ 6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/good-dup-trusted-key.conf b/bin/tests/system/checkconf/good-dup-trusted-key.conf
new file mode 100644
index 0000000..46089c4
--- /dev/null
+++ b/bin/tests/system/checkconf/good-dup-trusted-key.conf
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnssec-validation yes;
+};
+
+trusted-keys {
+ example. 257 3 8 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl
+ 25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafG
+ tURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJY
+ kYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJ
+ fpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaS
+ WG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjI
+ NQyrszHhWUU=";
+ example. 257 3 8 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbod
+ y0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQ
+ YfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX
+ 2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuw
+ E60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/
+ Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn
+ 6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/good-glue-cache.conf b/bin/tests/system/checkconf/good-glue-cache.conf
new file mode 100644
index 0000000..fd5524b
--- /dev/null
+++ b/bin/tests/system/checkconf/good-glue-cache.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ glue-cache yes;
+};
diff --git a/bin/tests/system/checkconf/good-initial-ds.conf b/bin/tests/system/checkconf/good-initial-ds.conf
new file mode 100644
index 0000000..b54a2b3
--- /dev/null
+++ b/bin/tests/system/checkconf/good-initial-ds.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ example. initial-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6";
+};
diff --git a/bin/tests/system/checkconf/good-interface-interval.conf b/bin/tests/system/checkconf/good-interface-interval.conf
new file mode 100644
index 0000000..60c50b3
--- /dev/null
+++ b/bin/tests/system/checkconf/good-interface-interval.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ interface-interval 1h;
+};
diff --git a/bin/tests/system/checkconf/good-kasp.conf b/bin/tests/system/checkconf/good-kasp.conf
new file mode 100644
index 0000000..17309e5
--- /dev/null
+++ b/bin/tests/system/checkconf/good-kasp.conf
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * This is just a random selection of DNSSEC configuration options.
+ */
+
+/* cut here */
+dnssec-policy "test" {
+ dnskey-ttl 3600;
+ keys {
+ ksk key-directory lifetime P1Y algorithm ecdsa256;
+ zsk lifetime P30D algorithm 13;
+ csk key-directory lifetime unlimited algorithm rsasha256 2048;
+ };
+ max-zone-ttl 86400;
+ nsec3param iterations 5 optout no salt-length 8;
+ parent-ds-ttl 7200;
+ parent-propagation-delay PT1H;
+ publish-safety PT3600S;
+ retire-safety PT3600S;
+ signatures-refresh P3D;
+ signatures-validity P2W;
+ signatures-validity-dnskey P14D;
+ zone-propagation-delay PT5M;
+};
+options {
+ dnssec-policy "default";
+};
+zone "example1" {
+ type primary;
+ file "example1.db";
+ inline-signing yes;
+};
+zone "example2" {
+ type primary;
+ file "example2.db";
+ allow-update {
+ "any";
+ };
+ dnssec-policy "test";
+};
+zone "example3" {
+ type primary;
+ file "example3.db";
+ inline-signing yes;
+ dnssec-policy "default";
+};
+zone "dnssec-policy-none-shared-zonefile1" {
+ type primary;
+ file "shared.db";
+ dnssec-policy "none";
+};
+zone "dnssec-policy-none-shared-zonefile2" {
+ type primary;
+ file "shared.db";
+ dnssec-policy "none";
+};
diff --git a/bin/tests/system/checkconf/good-key-directory.conf b/bin/tests/system/checkconf/good-key-directory.conf
new file mode 100644
index 0000000..45befff
--- /dev/null
+++ b/bin/tests/system/checkconf/good-key-directory.conf
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "internet" {
+ keys {
+ ksk key-directory lifetime unlimited algorithm ecdsa256;
+ zsk key-directory lifetime P90D algorithm ecdsa256;
+ };
+
+ nsec3param iterations 15 optout no salt-length 8;
+};
+
+dnssec-policy "intranet" {
+ keys {
+ ksk key-directory lifetime unlimited algorithm ecdsa256;
+ zsk key-directory lifetime P30D algorithm ecdsa256;
+ };
+ nsec3param iterations 15 optout no salt-length 8;
+};
+
+dnssec-policy "localhost" {
+ keys {
+ ksk key-directory lifetime unlimited algorithm ecdsa256;
+ zsk key-directory lifetime P30D algorithm ecdsa256;
+ };
+ nsec3param iterations 15 optout no salt-length 8;
+};
+
+options {
+ key-directory "global/keys";
+};
+
+view "localhost" {
+ match-clients { 127.0.0.1; ::1; };
+ zone "example.com" IN {
+ type primary;
+ file "localhost/example.com.zone";
+ dnssec-policy "localhost";
+ inline-signing yes;
+ };
+};
+
+view "external" {
+ match-clients { 0/0; };
+ key-directory "external/keys";
+ zone "example.com" IN {
+ type primary;
+ file "external/example.com.zone";
+ dnssec-policy "internet";
+ inline-signing yes;
+ };
+};
+
+view "internal" {
+ match-clients { ::/0; };
+ key-directory "internal/keys";
+ zone "example.com" IN {
+ type primary;
+ file "internal/example.com.zone";
+ dnssec-policy "intranet";
+ inline-signing yes;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-masterfile-format-raw.conf b/bin/tests/system/checkconf/good-masterfile-format-raw.conf
new file mode 100644
index 0000000..b6f3cbf
--- /dev/null
+++ b/bin/tests/system/checkconf/good-masterfile-format-raw.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { ::1; };
+ masterfile-format raw;
+};
diff --git a/bin/tests/system/checkconf/good-masterfile-format-text.conf b/bin/tests/system/checkconf/good-masterfile-format-text.conf
new file mode 100644
index 0000000..8138058
--- /dev/null
+++ b/bin/tests/system/checkconf/good-masterfile-format-text.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { ::1; };
+ masterfile-format text;
+};
diff --git a/bin/tests/system/checkconf/good-masters-and-primaries.conf b/bin/tests/system/checkconf/good-masters-and-primaries.conf
new file mode 100644
index 0000000..d84657f
--- /dev/null
+++ b/bin/tests/system/checkconf/good-masters-and-primaries.conf
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+masters a { 1.2.3.4; };
+primaries b { 1.2.3.4; };
diff --git a/bin/tests/system/checkconf/good-maxcachettl.conf b/bin/tests/system/checkconf/good-maxcachettl.conf
new file mode 100644
index 0000000..58f6901
--- /dev/null
+++ b/bin/tests/system/checkconf/good-maxcachettl.conf
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ max-cache-ttl 0;
+};
+view two {
+ max-cache-ttl 86400;
+};
+view three {
+ max-cache-ttl 4000000000;
+};
+view four {
+ max-cache-ttl 3600s;
+};
+view five {
+ max-cache-ttl 1h;
+};
+view six {
+ max-cache-ttl 1d;
+};
+view seven {
+ max-cache-ttl 1w;
+};
diff --git a/bin/tests/system/checkconf/good-maxncachettl.conf b/bin/tests/system/checkconf/good-maxncachettl.conf
new file mode 100644
index 0000000..80dc753
--- /dev/null
+++ b/bin/tests/system/checkconf/good-maxncachettl.conf
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ max-ncache-ttl 0;
+};
+view two {
+ max-ncache-ttl 86400;
+};
+view three {
+ max-ncache-ttl 604800;
+};
+view four {
+ max-ncache-ttl 3600s;
+};
+view five {
+ max-ncache-ttl 1h;
+};
+view six {
+ max-ncache-ttl 1d;
+};
+view seven {
+ max-ncache-ttl 1w;
+};
diff --git a/bin/tests/system/checkconf/good-maxratio1.conf b/bin/tests/system/checkconf/good-maxratio1.conf
new file mode 100644
index 0000000..4161a24
--- /dev/null
+++ b/bin/tests/system/checkconf/good-maxratio1.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone example {
+ type primary;
+ masterfile-format raw;
+ file "example.db";
+ max-ixfr-ratio 50%;
+};
diff --git a/bin/tests/system/checkconf/good-maxratio2.conf b/bin/tests/system/checkconf/good-maxratio2.conf
new file mode 100644
index 0000000..0ef2f3c
--- /dev/null
+++ b/bin/tests/system/checkconf/good-maxratio2.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone example {
+ type primary;
+ masterfile-format raw;
+ file "example.db";
+ max-ixfr-ratio unlimited;
+};
diff --git a/bin/tests/system/checkconf/good-mincachettl.conf b/bin/tests/system/checkconf/good-mincachettl.conf
new file mode 100644
index 0000000..b619a73
--- /dev/null
+++ b/bin/tests/system/checkconf/good-mincachettl.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ min-cache-ttl 0;
+};
+view two {
+ min-cache-ttl 30;
+};
+view three {
+ min-cache-ttl 60;
+};
+view four {
+ min-cache-ttl 90s;
+};
+view five {
+ min-cache-ttl 1m;
+};
diff --git a/bin/tests/system/checkconf/good-minncachettl.conf b/bin/tests/system/checkconf/good-minncachettl.conf
new file mode 100644
index 0000000..3e4101b
--- /dev/null
+++ b/bin/tests/system/checkconf/good-minncachettl.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ min-ncache-ttl 0;
+};
+view two {
+ min-ncache-ttl 30;
+};
+view three {
+ min-ncache-ttl 60;
+};
+view four {
+ min-ncache-ttl 90s;
+};
+view five {
+ min-ncache-ttl 1m;
+};
diff --git a/bin/tests/system/checkconf/good-mirror-inherited-notify-yes.conf b/bin/tests/system/checkconf/good-mirror-inherited-notify-yes.conf
new file mode 100644
index 0000000..09bbf94
--- /dev/null
+++ b/bin/tests/system/checkconf/good-mirror-inherited-notify-yes.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ notify yes;
+};
+
+zone "." {
+ type mirror;
+};
diff --git a/bin/tests/system/checkconf/good-mirror-root-zone-without-masters.conf b/bin/tests/system/checkconf/good-mirror-root-zone-without-masters.conf
new file mode 100644
index 0000000..9723b7a
--- /dev/null
+++ b/bin/tests/system/checkconf/good-mirror-root-zone-without-masters.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type mirror;
+};
diff --git a/bin/tests/system/checkconf/good-nested.conf b/bin/tests/system/checkconf/good-nested.conf
new file mode 100644
index 0000000..12a027c
--- /dev/null
+++ b/bin/tests/system/checkconf/good-nested.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl a { 127.0.0.1; ::1; };
+acl b { a; };
+acl c { !b; };
+
+options {
+ allow-query { c; };
+};
diff --git a/bin/tests/system/checkconf/good-notify-source-v6.conf b/bin/tests/system/checkconf/good-notify-source-v6.conf
new file mode 100644
index 0000000..797f966
--- /dev/null
+++ b/bin/tests/system/checkconf/good-notify-source-v6.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ notify-source-v6 fd92:7065:b8e:ffff::1;
+};
diff --git a/bin/tests/system/checkconf/good-notify-source.conf b/bin/tests/system/checkconf/good-notify-source.conf
new file mode 100644
index 0000000..6b97314
--- /dev/null
+++ b/bin/tests/system/checkconf/good-notify-source.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ notify-source 10.53.0.1;
+};
diff --git a/bin/tests/system/checkconf/good-options-also-notify.conf b/bin/tests/system/checkconf/good-options-also-notify.conf
new file mode 100644
index 0000000..e10403d
--- /dev/null
+++ b/bin/tests/system/checkconf/good-options-also-notify.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ also-notify { missing; };
+};
+
+zone "example.net" {
+ type secondary;
+ notify no;
+ primaries { 192.168.1.1; };
+};
diff --git a/bin/tests/system/checkconf/good-parental-source-v6.conf b/bin/tests/system/checkconf/good-parental-source-v6.conf
new file mode 100644
index 0000000..fe998f1
--- /dev/null
+++ b/bin/tests/system/checkconf/good-parental-source-v6.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ parental-source-v6 fd92:7065:b8e:ffff::1;
+};
diff --git a/bin/tests/system/checkconf/good-parental-source.conf b/bin/tests/system/checkconf/good-parental-source.conf
new file mode 100644
index 0000000..e45856a
--- /dev/null
+++ b/bin/tests/system/checkconf/good-parental-source.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ parental-source 10.53.0.1;
+};
diff --git a/bin/tests/system/checkconf/good-printtime.conf b/bin/tests/system/checkconf/good-printtime.conf
new file mode 100644
index 0000000..06bb7be
--- /dev/null
+++ b/bin/tests/system/checkconf/good-printtime.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+logging {
+ channel one {
+ file "one.out";
+ print-time no;
+ };
+ channel two {
+ file "two.out";
+ print-time yes;
+ };
+ channel three {
+ file "three.out";
+ print-time local;
+ };
+ channel four {
+ file "four.out";
+ print-time iso8601;
+ };
+ channel five {
+ file "five.out";
+ print-time iso8601-utc;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-response-dot.conf b/bin/tests/system/checkconf/good-response-dot.conf
new file mode 100644
index 0000000..f21daeb
--- /dev/null
+++ b/bin/tests/system/checkconf/good-response-dot.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com." {
+ type primary;
+ file "example.com.zone";
+};
+
+options {
+ response-policy {
+ zone "example.com." policy given;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-rpz-ttl.conf b/bin/tests/system/checkconf/good-rpz-ttl.conf
new file mode 100644
index 0000000..26d41bb
--- /dev/null
+++ b/bin/tests/system/checkconf/good-rpz-ttl.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com." {
+ type primary;
+ file "example.com.zone";
+};
+
+options {
+ response-policy {
+ zone "example.com." policy given;
+ }
+ max-policy-ttl 1h;
+};
diff --git a/bin/tests/system/checkconf/good-rpz-update.conf b/bin/tests/system/checkconf/good-rpz-update.conf
new file mode 100644
index 0000000..34b3ec5
--- /dev/null
+++ b/bin/tests/system/checkconf/good-rpz-update.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com." {
+ type primary;
+ file "example.com.zone";
+};
+
+options {
+ response-policy {
+ zone "example.com."
+ policy given
+ min-update-interval 5m;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-rrset-order-none.conf b/bin/tests/system/checkconf/good-rrset-order-none.conf
new file mode 100644
index 0000000..f0818ca
--- /dev/null
+++ b/bin/tests/system/checkconf/good-rrset-order-none.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ rrset-order {
+ order none;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-server-christmas-tree.conf.in b/bin/tests/system/checkconf/good-server-christmas-tree.conf.in
new file mode 100644
index 0000000..a786a11
--- /dev/null
+++ b/bin/tests/system/checkconf/good-server-christmas-tree.conf.in
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key example {
+ algorithm hmac-sha256;
+ secret "aaaaaaaaaaaaaaaaaaaaaaaa";
+};
+
+server 0.0.0.0 {
+ bogus no;
+ edns no;
+ edns-udp-size 512;
+ edns-version 0;
+ keys example;
+ max-udp-size 512;
+ notify-source 0.0.0.0;
+ padding 512;
+ provide-ixfr no;
+ query-source 0.0.0.0;
+ request-expire no;
+ request-ixfr no;
+ request-nsid no;
+ send-cookie no;
+ tcp-keepalive no;
+ tcp-only no;
+ transfer-format one-answer;
+ transfer-source 0.0.0.0;
+ transfers 1;
+};
+
+server :: {
+ bogus no;
+ edns no;
+ edns-udp-size 512;
+ edns-version 0;
+ keys example;
+ max-udp-size 512;
+ notify-source-v6 ::;
+ padding 512;
+ provide-ixfr no;
+ query-source-v6 ::;
+ request-expire no;
+ request-ixfr no;
+ request-nsid no;
+ send-cookie no;
+ tcp-keepalive no;
+ tcp-only no;
+ transfer-format one-answer;
+ transfer-source-v6 ::;
+ transfers 1;
+};
diff --git a/bin/tests/system/checkconf/good-sig-signing-type.conf b/bin/tests/system/checkconf/good-sig-signing-type.conf
new file mode 100644
index 0000000..dda1b73
--- /dev/null
+++ b/bin/tests/system/checkconf/good-sig-signing-type.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone example {
+ type primary;
+ file "example.db";
+ sig-signing-type 65280;
+};
diff --git a/bin/tests/system/checkconf/good-static-ds.conf b/bin/tests/system/checkconf/good-static-ds.conf
new file mode 100644
index 0000000..be7412a
--- /dev/null
+++ b/bin/tests/system/checkconf/good-static-ds.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ example. static-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6";
+};
diff --git a/bin/tests/system/checkconf/good-transfer-source-v6.conf b/bin/tests/system/checkconf/good-transfer-source-v6.conf
new file mode 100644
index 0000000..0527b85
--- /dev/null
+++ b/bin/tests/system/checkconf/good-transfer-source-v6.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ transfer-source-v6 fd92:7065:b8e:ffff::1;
+};
diff --git a/bin/tests/system/checkconf/good-transfer-source.conf b/bin/tests/system/checkconf/good-transfer-source.conf
new file mode 100644
index 0000000..df23d1c
--- /dev/null
+++ b/bin/tests/system/checkconf/good-transfer-source.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ transfer-source 10.53.0.1;
+};
diff --git a/bin/tests/system/checkconf/good-update-policy1.conf b/bin/tests/system/checkconf/good-update-policy1.conf
new file mode 100644
index 0000000..b312590
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy1.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * self * TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy10.conf b/bin/tests/system/checkconf/good-update-policy10.conf
new file mode 100644
index 0000000..3605834
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy10.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * krb5-subdomain . TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy11.conf b/bin/tests/system/checkconf/good-update-policy11.conf
new file mode 100644
index 0000000..92be340
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy11.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * tcp-self . TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy12.conf b/bin/tests/system/checkconf/good-update-policy12.conf
new file mode 100644
index 0000000..b76e583
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy12.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * 6to4-self . TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy13.conf b/bin/tests/system/checkconf/good-update-policy13.conf
new file mode 100644
index 0000000..e0030e8
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy13.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * tcp-self . ptr(1);
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy2.conf b/bin/tests/system/checkconf/good-update-policy2.conf
new file mode 100644
index 0000000..9af4d8a
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy2.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * self . TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy3.conf b/bin/tests/system/checkconf/good-update-policy3.conf
new file mode 100644
index 0000000..2d4f8ee
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy3.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * selfsub . TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy4.conf b/bin/tests/system/checkconf/good-update-policy4.conf
new file mode 100644
index 0000000..480ec5e
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy4.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * selfsub * TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy5.conf b/bin/tests/system/checkconf/good-update-policy5.conf
new file mode 100644
index 0000000..5619188
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy5.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * selfwild * TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy6.conf b/bin/tests/system/checkconf/good-update-policy6.conf
new file mode 100644
index 0000000..7e9d8c0
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy6.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * selfwild . TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy7.conf b/bin/tests/system/checkconf/good-update-policy7.conf
new file mode 100644
index 0000000..8b0b821
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy7.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * krb5-self . TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy8.conf b/bin/tests/system/checkconf/good-update-policy8.conf
new file mode 100644
index 0000000..b00e8c4
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy8.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * ms-self . TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-update-policy9.conf b/bin/tests/system/checkconf/good-update-policy9.conf
new file mode 100644
index 0000000..491e07c
--- /dev/null
+++ b/bin/tests/system/checkconf/good-update-policy9.conf
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant * ms-subdomain . TXT;
+ };
+};
diff --git a/bin/tests/system/checkconf/good-view-also-notify.conf b/bin/tests/system/checkconf/good-view-also-notify.conf
new file mode 100644
index 0000000..54d90ba
--- /dev/null
+++ b/bin/tests/system/checkconf/good-view-also-notify.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view example {
+ also-notify { missing; };
+ zone "example.net" {
+ type secondary;
+ notify no;
+ primaries { 192.168.1.1; };
+ };
+};
diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf
new file mode 100644
index 0000000..f8d0408
--- /dev/null
+++ b/bin/tests/system/checkconf/good.conf
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * This is just a random selection of configuration options.
+ */
+
+/* cut here */
+dnssec-policy "test" {
+ dnskey-ttl 3600;
+ keys {
+ ksk key-directory lifetime P1Y algorithm 13 256;
+ zsk key-directory lifetime P30D algorithm 13;
+ csk key-directory lifetime P30D algorithm 8 2048;
+ };
+ max-zone-ttl 86400;
+ nsec3param ;
+ parent-ds-ttl 7200;
+ parent-propagation-delay PT1H;
+ publish-safety PT3600S;
+ purge-keys P90D;
+ retire-safety PT3600S;
+ signatures-refresh P3D;
+ signatures-validity P2W;
+ signatures-validity-dnskey P14D;
+ zone-propagation-delay PT5M;
+};
+options {
+ avoid-v4-udp-ports {
+ 100;
+ };
+ avoid-v6-udp-ports {
+ 100;
+ };
+ blackhole {
+ 10.0.0.0/8;
+ };
+ directory ".";
+ dscp 41;
+ dump-file "named_dumpdb";
+ heartbeat-interval 30;
+ hostname none;
+ interface-interval 30;
+ keep-response-order {
+ 10.0.10.0/24;
+ };
+ listen-on port 90 {
+ "any";
+ };
+ listen-on port 100 dscp 33 {
+ 127.0.0.1/32;
+ };
+ listen-on-v6 port 53 dscp 57 {
+ "none";
+ };
+ match-mapped-addresses yes;
+ memstatistics-file "named.memstats";
+ pid-file none;
+ port 5300;
+ querylog yes;
+ recursing-file "named.recursing";
+ recursive-clients 3000;
+ serial-query-rate 100;
+ server-id none;
+ update-quota 200;
+ check-names primary warn;
+ check-names secondary ignore;
+ max-cache-size 20000000000000;
+ nta-lifetime 604800;
+ nta-recheck 604800;
+ validate-except {
+ "corp";
+ };
+ dnssec-policy "test";
+ max-ixfr-ratio 90%;
+ transfer-source 0.0.0.0 dscp 63;
+ zone-statistics none;
+};
+parental-agents "parents" {
+ 10.10.10.11;
+ 10.10.10.12;
+};
+view "first" {
+ match-clients {
+ "none";
+ };
+ zone "example1" {
+ type primary;
+ file "xxx";
+ update-policy local;
+ max-ixfr-ratio 20%;
+ notify-source 10.10.10.10 port 53 dscp 55;
+ };
+ zone "clone" {
+ type primary;
+ file "yyy";
+ inline-signing yes;
+ max-ixfr-ratio unlimited;
+ };
+ dnssec-validation auto;
+ zone-statistics terse;
+};
+view "second" {
+ match-clients {
+ "any";
+ };
+ zone "example1" {
+ type primary;
+ file "zzz";
+ update-policy local;
+ zone-statistics yes;
+ };
+ zone "example2" {
+ type static-stub;
+ forward only;
+ forwarders {
+ 10.53.0.4;
+ };
+ zone-statistics no;
+ };
+ zone "example3" {
+ type static-stub;
+ server-addresses {
+ 1.2.3.4;
+ };
+ };
+ zone "clone" {
+ in-view "first";
+ };
+ zone "." {
+ type redirect;
+ primaries {
+ 1.2.3.4;
+ };
+ };
+ dnssec-validation auto;
+ zone-statistics full;
+};
+view "third" {
+ match-clients {
+ "none";
+ };
+ zone "clone" {
+ in-view "first";
+ forward only;
+ forwarders {
+ 10.0.0.100;
+ };
+ };
+ zone "dnssec" {
+ type primary;
+ file "file";
+ allow-update {
+ "any";
+ };
+ dnssec-policy "default";
+ };
+ zone "p" {
+ type primary;
+ file "pfile";
+ inline-signing yes;
+ };
+ zone "s" {
+ type secondary;
+ file "sfile";
+ inline-signing yes;
+ primaries {
+ 1.2.3.4;
+ };
+ notify primary-only;
+ };
+};
+view "fourth" {
+ zone "dnssec-test" {
+ type primary;
+ file "dnssec-test.db";
+ inline-signing yes;
+ parental-agents {
+ 1.2.3.4;
+ 1.2.3.5;
+ };
+ dnssec-policy "test";
+ parental-source 10.10.10.10 port 53 dscp 55;
+ };
+ zone "dnssec-default" {
+ type primary;
+ file "dnssec-default.db";
+ inline-signing yes;
+ parental-agents {
+ "parents";
+ };
+ dnssec-policy "default";
+ };
+ zone "dnssec-inherit" {
+ type primary;
+ file "dnssec-inherit.db";
+ inline-signing yes;
+ };
+ zone "dnssec-none" {
+ type primary;
+ file "dnssec-none.db";
+ dnssec-policy "none";
+ };
+ zone "dnssec-view1" {
+ type primary;
+ file "dnssec-view41.db";
+ inline-signing yes;
+ dnssec-policy "test";
+ };
+ zone "dnssec-view2" {
+ type primary;
+ file "dnssec-view42.db";
+ inline-signing yes;
+ };
+ zone "dnssec-view3" {
+ type primary;
+ file "dnssec-view43.db";
+ dnssec-policy "none";
+ key-directory "keys";
+ };
+ zone "dnssec-view4" {
+ type primary;
+ file "dnssec-view44.db";
+ dnssec-policy "none";
+ };
+ dnssec-policy "default";
+ key-directory ".";
+};
+view "fifth" {
+ zone "dnssec-view1" {
+ type primary;
+ file "dnssec-view51.db";
+ inline-signing yes;
+ dnssec-policy "test";
+ };
+ zone "dnssec-view2" {
+ type primary;
+ file "dnssec-view52.db";
+ inline-signing yes;
+ dnssec-policy "test";
+ key-directory "keys";
+ };
+ zone "dnssec-view3" {
+ type primary;
+ file "dnssec-view53.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ key-directory "keys";
+ };
+ zone "dnssec-view4" {
+ type primary;
+ file "dnssec-view54.db";
+ dnssec-policy "none";
+ };
+ key-directory ".";
+};
+view "chaos" chaos {
+ zone "hostname.bind" chaos {
+ type primary;
+ database "_builtin hostname";
+ inline-signing yes;
+ };
+};
+dyndb "name" "library.so" {
+ this;
+ \};
+ is a {
+ "test" { \{ of; the; };
+ } bracketed;
+ "text \"";
+ system;
+};
+key "mykey" {
+ algorithm "hmac-md5";
+ secret "qwertyuiopasdfgh";
+};
diff --git a/bin/tests/system/checkconf/good.zonelist b/bin/tests/system/checkconf/good.zonelist
new file mode 100644
index 0000000..a5fbfda
--- /dev/null
+++ b/bin/tests/system/checkconf/good.zonelist
@@ -0,0 +1,24 @@
+example1 IN first primary
+clone IN first primary
+example1 IN second primary
+example2 IN second static-stub
+example3 IN second static-stub
+clone IN second in-view first
+. IN second redirect
+clone IN third in-view first
+dnssec IN third primary
+p IN third primary
+s IN third secondary
+dnssec-test IN fourth primary
+dnssec-default IN fourth primary
+dnssec-inherit IN fourth primary
+dnssec-none IN fourth primary
+dnssec-view1 IN fourth primary
+dnssec-view2 IN fourth primary
+dnssec-view3 IN fourth primary
+dnssec-view4 IN fourth primary
+dnssec-view1 IN fifth primary
+dnssec-view2 IN fifth primary
+dnssec-view3 IN fifth primary
+dnssec-view4 IN fifth primary
+hostname.bind chaos chaos primary
diff --git a/bin/tests/system/checkconf/hint-nofile.conf b/bin/tests/system/checkconf/hint-nofile.conf
new file mode 100644
index 0000000..1d1dee2
--- /dev/null
+++ b/bin/tests/system/checkconf/hint-nofile.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type hint;
+ file "nonexistent.db";
+};
diff --git a/bin/tests/system/checkconf/in-view-good.conf b/bin/tests/system/checkconf/in-view-good.conf
new file mode 100644
index 0000000..e5e860d
--- /dev/null
+++ b/bin/tests/system/checkconf/in-view-good.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view internal {
+ zone shared.example {
+ type primary;
+ file "shared.example.db";
+ };
+};
+
+view external {
+ zone shared.example {
+ in-view internal;
+ };
+};
diff --git a/bin/tests/system/checkconf/inline-bad.conf b/bin/tests/system/checkconf/inline-bad.conf
new file mode 100644
index 0000000..17dcb6b
--- /dev/null
+++ b/bin/tests/system/checkconf/inline-bad.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl "transferees" {};
+primaries "stealthPrimaries" {127.0.0.1;};
+primaries "publicSecondaries" {127.0.0.1;};
+zone "example.net" {
+ type secondary;
+ key-directory "/var/lib/bind/example.net";
+ auto-dnssec maintain;
+ inline-signing yes;
+ primaries { stealthPrimaries; };
+ notify explicit;
+ also-notify { publicSecondaries; };
+ allow-transfer { localhost; transferees; };
+};
+
diff --git a/bin/tests/system/checkconf/inline-good.conf b/bin/tests/system/checkconf/inline-good.conf
new file mode 100644
index 0000000..f588bcd
--- /dev/null
+++ b/bin/tests/system/checkconf/inline-good.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl "transferees" {};
+primaries "stealthPrimaries" {127.0.0.1;};
+primaries "publicSecondaries" {127.0.0.1;};
+zone "example.net" {
+ type secondary;
+ file "/var/cache/bind/example.net.db";
+ key-directory "/var/lib/bind/example.net";
+ auto-dnssec maintain;
+ inline-signing yes;
+ primaries { stealthPrimaries; };
+ notify explicit;
+ also-notify { publicSecondaries; };
+ allow-transfer { localhost; transferees; };
+};
+
diff --git a/bin/tests/system/checkconf/inline-no.conf b/bin/tests/system/checkconf/inline-no.conf
new file mode 100644
index 0000000..f6dbc5a
--- /dev/null
+++ b/bin/tests/system/checkconf/inline-no.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl "transferees" {};
+primaries "stealthPrimaries" {127.0.0.1;};
+primaries "publicSecondaries" {127.0.0.1;};
+zone "example.net" {
+ type secondary;
+ key-directory "/var/lib/bind/example.net";
+ auto-dnssec maintain;
+ inline-signing no;
+ primaries { stealthPrimaries; };
+ notify explicit;
+ also-notify { publicSecondaries; };
+ allow-transfer { localhost; transferees; };
+};
+
diff --git a/bin/tests/system/checkconf/kasp-and-other-dnssec-options.conf b/bin/tests/system/checkconf/kasp-and-other-dnssec-options.conf
new file mode 100644
index 0000000..b67a0e1
--- /dev/null
+++ b/bin/tests/system/checkconf/kasp-and-other-dnssec-options.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "good-kasp.conf";
+
+zone "nsec3.net" {
+ type primary;
+ file "nsec3.db";
+ dnssec-policy "test";
+ auto-dnssec maintain;
+ dnskey-sig-validity 3600;
+ dnssec-dnskey-kskonly yes;
+ dnssec-secure-to-insecure yes;
+ dnssec-update-mode maintain;
+ inline-signing no;
+ sig-validity-interval 3600;
+ update-check-ksk yes;
+};
diff --git a/bin/tests/system/checkconf/kasp-bad-keylen.conf b/bin/tests/system/checkconf/kasp-bad-keylen.conf
new file mode 100644
index 0000000..5ca4c34
--- /dev/null
+++ b/bin/tests/system/checkconf/kasp-bad-keylen.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "bad-keylen" {
+ keys {
+ csk lifetime P10Y algorithm rsasha1 511;
+ };
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "bad-keylen";
+};
diff --git a/bin/tests/system/checkconf/kasp-bad-lifetime.conf b/bin/tests/system/checkconf/kasp-bad-lifetime.conf
new file mode 100644
index 0000000..225b386
--- /dev/null
+++ b/bin/tests/system/checkconf/kasp-bad-lifetime.conf
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "bad-lifetime-ksk" {
+ /*
+ * The KSK lifetime is too short.
+ * The ZSK lifetime is good enough but should trigger a warning.
+ */
+ keys {
+ ksk lifetime PT3H algorithm 13;
+ zsk lifetime P8DT2H1S algorithm 13;
+ };
+
+ dnskey-ttl PT1H;
+ publish-safety PT1H;
+ retire-safety PT1H;
+ zone-propagation-delay PT1H;
+ max-zone-ttl P1D;
+ signatures-validity P10D;
+ signatures-refresh P3D;
+ parent-ds-ttl PT1H;
+ parent-propagation-delay PT5M;
+};
+
+dnssec-policy "bad-lifetime-zsk" {
+ /*
+ * The ZSK lifetime is too short.
+ * The KSK lifetime is good enough but should trigger a warning.
+ */
+ keys {
+ ksk lifetime PT3H1S algorithm 13;
+ zsk lifetime P8DT2H algorithm 13;
+ };
+
+ dnskey-ttl PT1H;
+ publish-safety PT1H;
+ retire-safety PT1H;
+ zone-propagation-delay PT1H;
+ max-zone-ttl P1D;
+ signatures-validity P10D;
+ signatures-refresh P3D;
+ parent-ds-ttl PT1H;
+ parent-propagation-delay PT5M;
+};
+
+dnssec-policy "bad-lifetime-csk" {
+ /*
+ * The CSK lifetime is too short.
+ */
+ keys {
+ csk lifetime PT3H algorithm 13;
+ };
+
+ dnskey-ttl PT1H;
+ publish-safety PT1H;
+ retire-safety PT1H;
+ zone-propagation-delay PT1H;
+ max-zone-ttl P1D;
+ signatures-validity P10D;
+ signatures-refresh P3D;
+ parent-ds-ttl PT1H;
+ parent-propagation-delay PT5M;
+};
+
+zone "bad-lifetime-ksk.example.net" {
+ type primary;
+ file "bad-lifetime-ksk.example.db";
+ dnssec-policy "bad-lifetime-ksk";
+};
+
+zone "bad-lifetime-zsk.example.net" {
+ type primary;
+ file "bad-lifetime-zsk.example.db";
+ dnssec-policy "bad-lifetime-zsk";
+};
+
+zone "bad-lifetime-csk.example.net" {
+ type primary;
+ file "bad-lifetime-csk.example.db";
+ dnssec-policy "bad-lifetime-csk";
+};
diff --git a/bin/tests/system/checkconf/kasp-bad-nsec3-alg.conf b/bin/tests/system/checkconf/kasp-bad-nsec3-alg.conf
new file mode 100644
index 0000000..8691b6c
--- /dev/null
+++ b/bin/tests/system/checkconf/kasp-bad-nsec3-alg.conf
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "bad-salt" {
+ keys {
+ csk lifetime unlimited algorithm rsasha1;
+ };
+ nsec3param ;
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "bad-salt";
+};
+
diff --git a/bin/tests/system/checkconf/kasp-bad-nsec3-iter.conf b/bin/tests/system/checkconf/kasp-bad-nsec3-iter.conf
new file mode 100644
index 0000000..a5a71d3
--- /dev/null
+++ b/bin/tests/system/checkconf/kasp-bad-nsec3-iter.conf
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "rsasha1" {
+ keys {
+ csk lifetime P10Y algorithm nsec3rsasha1 1024;
+ };
+ nsec3param iterations 150;
+};
+
+dnssec-policy "rsasha1-bad" {
+ keys {
+ csk lifetime P10Y algorithm nsec3rsasha1 1024;
+ };
+ nsec3param iterations 151;
+};
+
+dnssec-policy "rsasha256" {
+ keys {
+ csk lifetime P10Y algorithm rsasha256 2048;
+ };
+ nsec3param iterations 150;
+};
+
+dnssec-policy "rsasha256-bad" {
+ keys {
+ csk lifetime P10Y algorithm rsasha256 2048;
+ };
+ nsec3param iterations 151;
+};
+
+dnssec-policy "rsasha512" {
+ keys {
+ csk lifetime P10Y algorithm rsasha512 4096;
+ };
+ nsec3param iterations 150;
+};
+
+dnssec-policy "rsasha512-bad" {
+ keys {
+ csk lifetime P10Y algorithm rsasha512 4096;
+ };
+ nsec3param iterations 151;
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "default";
+ inline-signing yes;
+};
diff --git a/bin/tests/system/checkconf/kasp-bad-nsec3-salt.conf b/bin/tests/system/checkconf/kasp-bad-nsec3-salt.conf
new file mode 100644
index 0000000..708e580
--- /dev/null
+++ b/bin/tests/system/checkconf/kasp-bad-nsec3-salt.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "bad-salt" {
+ nsec3param salt "pepper";
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "bad-salt";
+};
+
diff --git a/bin/tests/system/checkconf/kasp-bad-signatures-refresh.conf b/bin/tests/system/checkconf/kasp-bad-signatures-refresh.conf
new file mode 100644
index 0000000..197ff17
--- /dev/null
+++ b/bin/tests/system/checkconf/kasp-bad-signatures-refresh.conf
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "bad-sigrefresh" {
+ keys {
+ csk lifetime unlimited algorithm 13;
+ };
+
+ signatures-validity P10D;
+ signatures-validity-dnskey P20D;
+ signatures-refresh P9DT1S;
+};
+
+dnssec-policy "bad-sigrefresh-dnskey" {
+ keys {
+ csk lifetime unlimited algorithm 13;
+ };
+
+ signatures-validity P20D;
+ signatures-validity-dnskey P10D;
+ signatures-refresh P9DT1S;
+};
+
+zone "sigrefresh.example.net" {
+ type primary;
+ file "sigrefresh.example.db";
+ inline-signing yes;
+ dnssec-policy "bad-sigrefresh";
+};
+
+zone "dnskey.example.net" {
+ type primary;
+ file "dnskey.example.db";
+ inline-signing yes;
+ dnssec-policy "bad-sigrefresh-dnskey";
+};
diff --git a/bin/tests/system/checkconf/kasp-ignore-keylen.conf b/bin/tests/system/checkconf/kasp-ignore-keylen.conf
new file mode 100644
index 0000000..c9787d4
--- /dev/null
+++ b/bin/tests/system/checkconf/kasp-ignore-keylen.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "warn-length" {
+ keys {
+ // Algorithm 13 has predefined length, warn about length param.
+ csk lifetime unlimited algorithm ecdsa256 2048;
+ };
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ dnssec-policy "warn-length";
+ inline-signing yes;
+};
+
diff --git a/bin/tests/system/checkconf/kasp-warning.conf b/bin/tests/system/checkconf/kasp-warning.conf
new file mode 100644
index 0000000..41b6d6f
--- /dev/null
+++ b/bin/tests/system/checkconf/kasp-warning.conf
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "warn1" {
+ keys {
+ // This policy has keys in the same algorithm with the same
+ // role, this should trigger a warning.
+ ksk lifetime unlimited algorithm ecdsa256;
+ zsk lifetime unlimited algorithm ecdsa256;
+ zsk lifetime unlimited algorithm ecdsa256;
+ ksk lifetime unlimited algorithm ecdsa256;
+ };
+};
+
+dnssec-policy "warn2" {
+ keys {
+ // This policy has keys in the same algorithm with the same
+ // role, this should trigger a warning.
+ csk lifetime unlimited algorithm rsasha256;
+ ksk lifetime unlimited algorithm rsasha256;
+ zsk lifetime unlimited algorithm rsasha256;
+ };
+};
+
+dnssec-policy "warn3" {
+ keys {
+ // This policy has a key with a very short lifetime.
+ csk lifetime PT2591999S algorithm rsasha256;
+ };
+};
+
+zone "warn1.example.net" {
+ type primary;
+ file "warn1.example.db";
+ inline-signing yes;
+ dnssec-policy "warn1";
+};
+
+zone "warn2.example.net" {
+ type primary;
+ file "warn2.example.db";
+ inline-signing yes;
+ dnssec-policy "warn2";
+};
+
+zone "warn3.example.net" {
+ type primary;
+ file "warn3.example.db";
+ inline-signing yes;
+ dnssec-policy "warn3";
+};
+
diff --git a/bin/tests/system/checkconf/lmdb-mapsize-largest.conf b/bin/tests/system/checkconf/lmdb-mapsize-largest.conf
new file mode 100644
index 0000000..a55b835
--- /dev/null
+++ b/bin/tests/system/checkconf/lmdb-mapsize-largest.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ lmdb-mapsize 1024G;
+};
diff --git a/bin/tests/system/checkconf/lmdb-mapsize-smallest.conf b/bin/tests/system/checkconf/lmdb-mapsize-smallest.conf
new file mode 100644
index 0000000..4478706
--- /dev/null
+++ b/bin/tests/system/checkconf/lmdb-mapsize-smallest.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ lmdb-mapsize 1M;
+};
diff --git a/bin/tests/system/checkconf/max-cache-size-good.conf b/bin/tests/system/checkconf/max-cache-size-good.conf
new file mode 100644
index 0000000..bb12775
--- /dev/null
+++ b/bin/tests/system/checkconf/max-cache-size-good.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ max-cache-size 60%;
+};
diff --git a/bin/tests/system/checkconf/max-ttl.conf b/bin/tests/system/checkconf/max-ttl.conf
new file mode 100644
index 0000000..b91a5fd
--- /dev/null
+++ b/bin/tests/system/checkconf/max-ttl.conf
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory ".";
+ max-zone-ttl 600;
+};
+
+zone "maxttl1.example" {
+ type primary;
+ file "maxttl-bad.db";
+};
+
+zone "maxttl2.example" {
+ type primary;
+ file "maxttl-bad.db";
+ max-zone-ttl 300;
+};
+
+zone "maxttl3.example" {
+ type primary;
+ file "maxttl-bad.db";
+ max-zone-ttl 120;
+};
diff --git a/bin/tests/system/checkconf/maxttl-bad.conf b/bin/tests/system/checkconf/maxttl-bad.conf
new file mode 100644
index 0000000..66bbebd
--- /dev/null
+++ b/bin/tests/system/checkconf/maxttl-bad.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory ".";
+ max-zone-ttl 8000w;
+};
+
+zone "maxttl.example" {
+ type primary;
+ file "maxttl-bad.db";
+};
+
+
diff --git a/bin/tests/system/checkconf/maxttl-bad.db b/bin/tests/system/checkconf/maxttl-bad.db
new file mode 100644
index 0000000..978f0ec
--- /dev/null
+++ b/bin/tests/system/checkconf/maxttl-bad.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ MX 10 mail
+
+a 600 A 10.0.0.1
+mail 900 A 10.0.0.2
diff --git a/bin/tests/system/checkconf/maxttl.db b/bin/tests/system/checkconf/maxttl.db
new file mode 100644
index 0000000..3ad695e
--- /dev/null
+++ b/bin/tests/system/checkconf/maxttl.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600 ; 10 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ MX 10 mail
+
+a A 10.0.0.1
+mail A 10.0.0.2
diff --git a/bin/tests/system/checkconf/notify.conf b/bin/tests/system/checkconf/notify.conf
new file mode 100644
index 0000000..2978118
--- /dev/null
+++ b/bin/tests/system/checkconf/notify.conf
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view one {
+ notify primary-only;
+
+ # also-notify inconsistent with primary-only notify option
+ zone "secondary" {
+ type secondary;
+ primaries { 1.2.3.4; };
+ also-notify { 5.6.7.8; };
+ };
+
+ # OK
+ zone "primary" {
+ type primary;
+ file "filename";
+ also-notify { 5.6.7.8; };
+ };
+};
+
+view two {
+ notify no;
+
+ # also-notify inconsistent with notify option at the view level
+ zone "secondary" {
+ type secondary;
+ primaries { 1.2.3.4; };
+ also-notify { 5.6.7.8; };
+ };
+
+ # OK
+ zone "primary" {
+ type primary;
+ file "filename";
+ notify yes;
+ also-notify { 5.6.7.8; };
+ };
+};
+
+view three {
+ # also-notify inconsistent with notify option at the zone level
+ zone "secondary" {
+ type secondary;
+ primaries { 1.2.3.4; };
+ notify no;
+ also-notify { 5.6.7.8; };
+ };
+
+ # OK
+ zone "primary" {
+ type primary;
+ file "filename";
+ also-notify { 5.6.7.8; };
+ };
+};
+
+view four {
+ also-notify { 5.6.7.8; };
+
+ # OK
+ zone "secondary" {
+ type secondary;
+ primaries { 1.2.3.4; };
+ notify primary-only;
+ };
+
+ # OK
+ zone "primary" {
+ type primary;
+ file "filename";
+ notify no;
+ };
+};
diff --git a/bin/tests/system/checkconf/portrange-good.conf b/bin/tests/system/checkconf/portrange-good.conf
new file mode 100644
index 0000000..c4eb582
--- /dev/null
+++ b/bin/tests/system/checkconf/portrange-good.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ avoid-v4-udp-ports {
+ 1935;
+ 2605;
+ 4321;
+ 6514;
+ range 8610 8614;
+ };
+};
diff --git a/bin/tests/system/checkconf/range.conf b/bin/tests/system/checkconf/range.conf
new file mode 100644
index 0000000..c254f5c
--- /dev/null
+++ b/bin/tests/system/checkconf/range.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 999999;
+};
diff --git a/bin/tests/system/checkconf/servestale.stale-refresh-time.0.conf b/bin/tests/system/checkconf/servestale.stale-refresh-time.0.conf
new file mode 100644
index 0000000..3ff6b0d
--- /dev/null
+++ b/bin/tests/system/checkconf/servestale.stale-refresh-time.0.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ stale-refresh-time 0;
+};
diff --git a/bin/tests/system/checkconf/servestale.stale-refresh-time.29.conf b/bin/tests/system/checkconf/servestale.stale-refresh-time.29.conf
new file mode 100644
index 0000000..9e0669c
--- /dev/null
+++ b/bin/tests/system/checkconf/servestale.stale-refresh-time.29.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ stale-refresh-time 29;
+};
diff --git a/bin/tests/system/checkconf/setup.sh b/bin/tests/system/checkconf/setup.sh
new file mode 100644
index 0000000..7d83eb5
--- /dev/null
+++ b/bin/tests/system/checkconf/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports bad-kasp-keydir1.conf.in bad-kasp-keydir1.conf
+copy_setports bad-kasp-keydir2.conf.in bad-kasp-keydir2.conf
+copy_setports bad-kasp-keydir3.conf.in bad-kasp-keydir3.conf
+copy_setports bad-kasp-keydir4.conf.in bad-kasp-keydir4.conf
+copy_setports bad-kasp-keydir5.conf.in bad-kasp-keydir5.conf
+cp -f good-server-christmas-tree.conf.in good-server-christmas-tree.conf
diff --git a/bin/tests/system/checkconf/shared.example.db b/bin/tests/system/checkconf/shared.example.db
new file mode 100644
index 0000000..5dcdd1b
--- /dev/null
+++ b/bin/tests/system/checkconf/shared.example.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 0 0 0 0 0
+@ 0 NS .
diff --git a/bin/tests/system/checkconf/tests.sh b/bin/tests/system/checkconf/tests.sh
new file mode 100644
index 0000000..8d82f92
--- /dev/null
+++ b/bin/tests/system/checkconf/tests.sh
@@ -0,0 +1,664 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+mkdir -p keys
+
+n=$((n + 1))
+echo_i "checking that named-checkconf handles a known good config ($n)"
+ret=0
+$CHECKCONF good.conf > checkconf.out$n 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf prints a known good config ($n)"
+ret=0
+awk 'BEGIN { ok = 0; } /cut here/ { ok = 1; getline } ok == 1 { print }' good.conf > good.conf.in
+[ -s good.conf.in ] || ret=1
+$CHECKCONF -p good.conf.in > checkconf.out$n || ret=1
+grep -v '^good.conf.in:' < checkconf.out$n > good.conf.out 2>&1 || ret=1
+cmp good.conf.in good.conf.out || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf -x removes secrets ($n)"
+ret=0
+# ensure there is a secret and that it is not the check string.
+grep 'secret "' good.conf.in > /dev/null || ret=1
+grep 'secret "????????????????"' good.conf.in > /dev/null 2>&1 && ret=1
+$CHECKCONF -p -x good.conf.in > checkconf.out$n || ret=1
+grep -v '^good.conf.in:' < checkconf.out$n > good.conf.out 2>&1 || ret=1
+grep 'secret "????????????????"' good.conf.out > /dev/null 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+for bad in bad-*.conf
+do
+ n=$((n + 1))
+ echo_i "checking that named-checkconf detects error in $bad ($n)"
+ ret=0
+ { $CHECKCONF $bad > checkconf.out$n 2>&1; rc=$?; } || true
+ if [ $rc -ne 1 ]; then ret=1; fi
+ grep "^$bad:[0-9]*: " < checkconf.out$n > /dev/null || ret=1
+ case $bad in
+ bad-update-policy[123].conf)
+ pat="identity and name fields are not the same"
+ grep "$pat" < checkconf.out$n > /dev/null || ret=1
+ ;;
+ bad-update-policy[4589].conf|bad-update-policy1[01].conf)
+ pat="name field not set to placeholder value"
+ grep "$pat" < checkconf.out$n > /dev/null || ret=1
+ ;;
+ bad-update-policy[67].conf|bad-update-policy1[2345789].conf|bad-update-policy20.conf)
+ pat="missing name field type '.*' found"
+ grep "$pat" < checkconf.out$n > /dev/null || ret=1
+ ;;
+ esac
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+for good in good-*.conf
+do
+ n=$((n + 1))
+ echo_i "checking that named-checkconf detects no error in $good ($n)"
+ ret=0
+ if ! $FEATURETEST --with-libnghttp2
+ then
+ case $good in
+ good-doh-*.conf) continue;;
+ good-dot-*.conf) continue;;
+ esac
+ fi
+ { $CHECKCONF $good > checkconf.out$n 2>&1; rc=$?; } || true
+ if [ $rc -ne 0 ]; then echo_i "failed"; ret=1; fi
+ status=$((status + ret))
+done
+
+for lmdb in lmdb-*.conf
+do
+ n=$((n + 1))
+ ret=0
+
+ if $FEATURETEST --with-lmdb; then
+ echo_i "checking that named-checkconf detects no error in $lmdb ($n)"
+ { $CHECKCONF $lmdb > checkconf.out$n 2>&1; rc=$?; } || true
+ if [ $rc -ne 0 ]; then echo_i "failed"; ret=1; fi
+ else
+ echo_i "checking that named-checkconf detects error in $lmdb ($n)"
+ { $CHECKCONF $lmdb > checkconf.out$n 2>&1; rc=$?; } || true
+ if [ $rc -eq 0 ]; then echo_i "failed"; ret=1; fi
+ fi
+ status=$((status + ret))
+done
+
+n=$((n + 1))
+echo_i "checking that ancient options report a fatal error ($n)"
+ret=0
+$CHECKCONF ancient.conf > ancient.out 2>&1 && ret=1
+grep "no longer exists" ancient.out > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf -z catches missing hint file ($n)"
+ret=0
+$CHECKCONF -z hint-nofile.conf > hint-nofile.out 2>&1 && ret=1
+grep "could not configure root hints from 'nonexistent.db': file not found" hint-nofile.out > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf catches range errors ($n)"
+ret=0
+$CHECKCONF range.conf > checkconf.out$n 2>&1 && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf warns of notify inconsistencies ($n)"
+ret=0
+$CHECKCONF notify.conf > checkconf.out$n 2>&1
+warnings=$(grep "'notify' is disabled" < checkconf.out$n | wc -l)
+[ $warnings -eq 3 ] || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf dnssec warnings ($n)"
+ret=0
+# dnssec.1: auto-dnssec warning
+$CHECKCONF dnssec.1 > checkconf.out$n.1 2>&1 && ret=1
+grep 'auto-dnssec may only be ' < checkconf.out$n.1 > /dev/null || ret=1
+# dnssec.2: should have no warnings (other than deprecation warning)
+$CHECKCONF dnssec.2 > checkconf.out$n.2 2>&1 || ret=1
+grep "option 'auto-dnssec' is deprecated" < checkconf.out$n.2 > /dev/null || ret=1
+lines=$(wc -l < "checkconf.out$n.2")
+if [ $lines != 1 ]; then ret=1; fi
+# dnssec.3: should have specific deprecation warning
+$CHECKCONF dnssec.3 > checkconf.out$n.3 2>&1 && ret=1
+grep "'auto-dnssec' option is deprecated and will be removed in BIND 9\.19" < checkconf.out$n.3 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf deprecate warnings ($n)"
+ret=0
+$CHECKCONF deprecated.conf > checkconf.out$n.1 2>&1
+grep "option 'managed-keys' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "option 'trusted-keys' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "option 'use-v4-udp-ports' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "option 'use-v6-udp-ports' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "option 'avoid-v4-udp-ports' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "option 'avoid-v6-udp-ports' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "option 'delegation-only' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "option 'tkey-dhkey' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "option 'root-delegation-only' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "'type delegation-only' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "option 'dialup' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "option 'heartbeat-interval' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "option 'dnssec-must-be-secure' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+grep "token 'port' is deprecated" < checkconf.out$n.1 > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+# set -i to ignore deprecate warnings
+$CHECKCONF -i deprecated.conf > checkconf.out$n.2 2>&1
+grep '.*' < checkconf.out$n.2 > /dev/null && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf servestale warnings ($n)"
+ret=0
+$CHECKCONF servestale.stale-refresh-time.0.conf > checkconf.out$n.1 2>&1
+grep "'stale-refresh-time' should either be 0 or otherwise 30 seconds or higher" < checkconf.out$n.1 > /dev/null && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+ret=0
+$CHECKCONF servestale.stale-refresh-time.29.conf > checkconf.out$n.1 2>&1
+grep "'stale-refresh-time' should either be 0 or otherwise 30 seconds or higher" < checkconf.out$n.1 > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "range checking fields that do not allow zero ($n)"
+ret=0
+for field in max-retry-time min-retry-time max-refresh-time min-refresh-time; do
+ cat > badzero.conf << EOF
+options {
+ $field 0;
+};
+EOF
+ { $CHECKCONF badzero.conf > checkconf.out$n.1 2>&1; rc=$?; } || true
+ [ $rc -eq 1 ] || { echo_i "options $field failed" ; ret=1; }
+ cat > badzero.conf << EOF
+view dummy {
+ $field 0;
+};
+EOF
+ { $CHECKCONF badzero.conf > checkconf.out$n.2 2>&1; rc=$?; } || true
+ [ $rc -eq 1 ] || { echo_i "view $field failed" ; ret=1; }
+ cat > badzero.conf << EOF
+options {
+ $field 0;
+};
+view dummy {
+};
+EOF
+ { $CHECKCONF badzero.conf > checkconf.out$n.3 2>&1; rc=$?; } || true
+ [ $rc -eq 1 ] || { echo_i "options + view $field failed" ; ret=1; }
+ cat > badzero.conf << EOF
+zone dummy {
+ type secondary;
+ primaries { 0.0.0.0; };
+ $field 0;
+};
+EOF
+ { $CHECKCONF badzero.conf > checkconf.out$n.4 2>&1; rc=$?; } || true
+ [ $rc -eq 1 ] || { echo_i "zone $field failed" ; ret=1; }
+done
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking options allowed in inline-signing secondaries ($n)"
+ret=0
+$CHECKCONF bad-dnssec.conf > checkconf.out$n.1 2>&1 && ret=1
+l=$(grep "dnssec-dnskey-kskonly.*requires inline" < checkconf.out$n.1 | wc -l)
+[ $l -eq 1 ] || ret=1
+$CHECKCONF bad-dnssec.conf > checkconf.out$n.2 2>&1 && ret=1
+l=$(grep "dnssec-loadkeys-interval.*requires inline" < checkconf.out$n.2 | wc -l)
+[ $l -eq 1 ] || ret=1
+$CHECKCONF bad-dnssec.conf > checkconf.out$n.3 2>&1 && ret=1
+l=$(grep "update-check-ksk.*requires inline" < checkconf.out$n.3 | wc -l)
+[ $l -eq 1 ] || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check file + inline-signing for secondary zones ($n)"
+$CHECKCONF inline-no.conf > checkconf.out$n.1 2>&1 && ret=1
+l=$(grep "missing 'file' entry" < checkconf.out$n.1 | wc -l)
+[ $l -eq 0 ] || ret=1
+$CHECKCONF inline-good.conf > checkconf.out$n.2 2>&1 || ret=1
+l=$(grep "missing 'file' entry" < checkconf.out$n.2 | wc -l)
+[ $l -eq 0 ] || ret=1
+$CHECKCONF inline-bad.conf > checkconf.out$n.3 2>&1 && ret=1
+l=$(grep "missing 'file' entry" < checkconf.out$n.3 | wc -l)
+[ $l -eq 1 ] || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf DLZ warnings ($n)"
+ret=0
+$CHECKCONF dlz-bad.conf > checkconf.out$n 2>&1 && ret=1
+grep "'dlz' and 'database'" < checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking for missing key directory warning ($n)"
+ret=0
+rm -rf test.keydir
+$CHECKCONF warn-keydir.conf > checkconf.out$n.1 2>&1
+l=$(grep "'test.keydir' does not exist" < checkconf.out$n.1 | wc -l)
+[ $l -eq 1 ] || ret=1
+touch test.keydir
+$CHECKCONF warn-keydir.conf > checkconf.out$n.2 2>&1
+l=$(grep "'test.keydir' is not a directory" < checkconf.out$n.2 | wc -l)
+[ $l -eq 1 ] || ret=1
+rm -f test.keydir
+mkdir test.keydir
+$CHECKCONF warn-keydir.conf > checkconf.out$n.3 2>&1
+l=$(grep "key-directory" < checkconf.out$n.3 | wc -l)
+[ $l -eq 0 ] || ret=1
+rm -rf test.keydir
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+
+n=$((n + 1))
+echo_i "checking that named-checkconf -z catches conflicting ttl with max-ttl ($n)"
+ret=0
+$CHECKCONF -z max-ttl.conf > check.out 2>&1 && ret=1
+grep 'TTL 900 exceeds configured max-zone-ttl 600' check.out > /dev/null 2>&1 || ret=1
+grep 'TTL 900 exceeds configured max-zone-ttl 600' check.out > /dev/null 2>&1 || ret=1
+grep 'TTL 900 exceeds configured max-zone-ttl 600' check.out > /dev/null 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf -z catches invalid max-ttl ($n)"
+ret=0
+$CHECKCONF -z max-ttl-bad.conf > checkconf.out$n 2>&1 && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf -z skips zone check with alternate databases ($n)"
+ret=0
+$CHECKCONF -z altdb.conf > checkconf.out$n 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf -z skips zone check with DLZ ($n)"
+ret=0
+$CHECKCONF -z altdlz.conf > checkconf.out$n 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf -z fails on view with ANY class ($n)"
+ret=0
+$CHECKCONF -z view-class-any1.conf > checkconf.out$n 2>&1 && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf -z fails on view with CLASS255 class ($n)"
+ret=0
+$CHECKCONF -z view-class-any2.conf > checkconf.out$n 2>&1 && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf -z passes on view with IN class ($n)"
+ret=0
+$CHECKCONF -z view-class-in1.conf > checkconf.out$n 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf -z passes on view with CLASS1 class ($n)"
+ret=0
+$CHECKCONF -z view-class-in2.conf > checkconf.out$n 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that check-names fails as configured ($n)"
+ret=0
+$CHECKCONF -z check-names-fail.conf > checkconf.out$n 2>&1 && ret=1
+grep "near '_underscore': bad name (check-names)" < checkconf.out$n > /dev/null || ret=1
+grep "zone check-names/IN: loaded serial" < checkconf.out$n > /dev/null && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that check-mx fails as configured ($n)"
+ret=0
+$CHECKCONF -z check-mx-fail.conf > checkconf.out$n 2>&1 && ret=1
+grep "near '10.0.0.1': MX is an address" < checkconf.out$n > /dev/null || ret=1
+grep "zone check-mx/IN: loaded serial" < checkconf.out$n > /dev/null && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that check-dup-records fails as configured ($n)"
+ret=0
+$CHECKCONF -z check-dup-records-fail.conf > checkconf.out$n 2>&1 && ret=1
+grep "has semantically identical records" < checkconf.out$n > /dev/null || ret=1
+grep "zone check-dup-records/IN: loaded serial" < checkconf.out$n > /dev/null && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that check-mx fails as configured ($n)"
+ret=0
+$CHECKCONF -z check-mx-fail.conf > checkconf.out$n 2>&1 && ret=1
+grep "failed: MX is an address" < checkconf.out$n > /dev/null || ret=1
+grep "zone check-mx/IN: loaded serial" < checkconf.out$n > /dev/null && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that check-mx-cname fails as configured ($n)"
+ret=0
+$CHECKCONF -z check-mx-cname-fail.conf > checkconf.out$n 2>&1 && ret=1
+grep "MX.* is a CNAME (illegal)" < checkconf.out$n > /dev/null || ret=1
+grep "zone check-mx-cname/IN: loaded serial" < checkconf.out$n > /dev/null && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that check-srv-cname fails as configured ($n)"
+ret=0
+$CHECKCONF -z check-srv-cname-fail.conf > checkconf.out$n 2>&1 && ret=1
+grep "SRV.* is a CNAME (illegal)" < checkconf.out$n > /dev/null || ret=1
+grep "zone check-mx-cname/IN: loaded serial" < checkconf.out$n > /dev/null && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that named-checkconf -p properly print a port range ($n)"
+ret=0
+$CHECKCONF -p portrange-good.conf > checkconf.out$n 2>&1 || ret=1
+grep "range 8610 8614;" < checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that named-checkconf -z handles in-view ($n)"
+ret=0
+$CHECKCONF -z in-view-good.conf > checkconf.out$n 2>&1 || ret=1
+grep "zone shared.example/IN: loaded serial" < checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that named-checkconf -z returns error when a later view is okay ($n)"
+ret=0
+$CHECKCONF -z check-missing-zone.conf > checkconf.out$n 2>&1 && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that named-checkconf prints max-cache-size <percentage> correctly ($n)"
+ret=0
+$CHECKCONF -p max-cache-size-good.conf > checkconf.out$n 2>&1 || ret=1
+grep "max-cache-size 60%;" < checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that named-checkconf -l prints out the zone list ($n)"
+ret=0
+$CHECKCONF -l good.conf |
+grep -v "is deprecated" |
+grep -v "is not implemented" |
+grep -v "is not recommended" |
+grep -v "no longer exists" |
+grep -v "is obsolete" > checkconf.out$n || ret=1
+diff good.zonelist checkconf.out$n > diff.out$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that the 2010 ICANN ROOT KSK without the 2017 ICANN ROOT KSK generates a warning ($n)"
+ret=0
+$CHECKCONF check-root-ksk-2010.conf > checkconf.out$n 2>/dev/null || ret=1
+[ -s checkconf.out$n ] || ret=1
+grep "key without the updated" < checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that the 2010 ICANN ROOT KSK with the 2017 ICANN ROOT KSK does not generate a warning ($n)"
+ret=0
+$CHECKCONF check-root-ksk-both.conf > checkconf.out$n 2>/dev/null || ret=1
+[ -s checkconf.out$n ] && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that the 2017 ICANN ROOT KSK alone does not generate a warning ($n)"
+ret=0
+$CHECKCONF check-root-ksk-2017.conf > checkconf.out$n 2>/dev/null || ret=1
+[ -s checkconf.out$n ] && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that a static root key generates a warning ($n)"
+ret=0
+$CHECKCONF check-root-static-key.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "static entry for the root zone WILL FAIL" checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that a static root DS trust anchor generates a warning ($n)"
+ret=0
+$CHECKCONF check-root-static-ds.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "static entry for the root zone WILL FAIL" checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that a trusted-keys entry for root generates a warning ($n)"
+ret=0
+$CHECKCONF check-root-trusted-key.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "trusted-keys entry for the root zone WILL FAIL" checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that using trust-anchors and managed-keys generates an error ($n)"
+ret=0
+$CHECKCONF check-mixed-keys.conf > checkconf.out$n 2>/dev/null && ret=1
+grep "use of managed-keys is not allowed" checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf kasp errors ($n)"
+ret=0
+$CHECKCONF kasp-and-other-dnssec-options.conf > checkconf.out$n 2>&1 && ret=1
+grep "'inline-signing yes;' must also be configured explicitly for zones using dnssec-policy without a configured 'allow-update' or 'update-policy'" < checkconf.out$n > /dev/null || ret=1
+grep "'auto-dnssec maintain;' cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
+grep "dnskey-sig-validity: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
+grep "dnssec-dnskey-kskonly: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
+grep "dnssec-secure-to-insecure: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
+grep "dnssec-update-mode: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
+grep "sig-validity-interval: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
+grep "update-check-ksk: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf kasp nsec3 iterations errors ($n)"
+ret=0
+$CHECKCONF kasp-bad-nsec3-iter.conf > checkconf.out$n 2>&1 && ret=1
+grep "dnssec-policy: nsec3 iterations value 151 out of range" < checkconf.out$n > /dev/null || ret=1
+lines=$(wc -l < "checkconf.out$n")
+if [ $lines -ne 3 ]; then ret=1; fi
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf kasp nsec3 algorithm errors ($n)"
+ret=0
+$CHECKCONF kasp-bad-nsec3-alg.conf > checkconf.out$n 2>&1 && ret=1
+grep "dnssec-policy: cannot use nsec3 with algorithm 'RSASHA1'" < checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf kasp key errors ($n)"
+ret=0
+$CHECKCONF kasp-bad-keylen.conf > checkconf.out$n 2>&1 && ret=1
+grep "dnssec-policy: key with algorithm rsasha1 has invalid key length 511" < checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf kasp signatures refresh errors ($n)"
+ret=0
+$CHECKCONF kasp-bad-signatures-refresh.conf > checkconf.out$n 2>&1 && ret=1
+grep "dnssec-policy: policy 'bad-sigrefresh' signatures-refresh must be at most 90% of the signatures-validity" < checkconf.out$n > /dev/null || ret=1
+grep "dnssec-policy: policy 'bad-sigrefresh-dnskey' signatures-refresh must be at most 90% of the signatures-validity-dnskey" < checkconf.out$n > /dev/null || ret=1
+lines=$(wc -l < "checkconf.out$n")
+if [ $lines -ne 2 ]; then ret=1; fi
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf kasp key lifetime errors ($n)"
+ret=0
+$CHECKCONF kasp-bad-lifetime.conf > checkconf.out$n 2>&1 && ret=1
+lines=$(grep "dnssec-policy: key lifetime is shorter than the time it takes to do a rollover" < checkconf.out$n | wc -l) || ret=1
+if [ $lines -ne 3 ]; then ret=1; fi
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf kasp predefined key length ($n)"
+ret=0
+$CHECKCONF kasp-ignore-keylen.conf > checkconf.out$n 2>&1 || ret=1
+grep "dnssec-policy: key algorithm ecdsa256 has predefined length; ignoring length value 2048" < checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking named-checkconf kasp warns about weird policies ($n)"
+ret=0
+$CHECKCONF kasp-warning.conf > checkconf.out$n 2>&1 || ret=1
+grep "dnssec-policy: algorithm 8 has multiple keys with ZSK role" < checkconf.out$n > /dev/null || ret=1
+grep "dnssec-policy: algorithm 8 has multiple keys with ZSK role" < checkconf.out$n > /dev/null || ret=1
+grep "dnssec-policy: algorithm 13 has multiple keys with KSK role" < checkconf.out$n > /dev/null || ret=1
+grep "dnssec-policy: algorithm 13 has multiple keys with ZSK role" < checkconf.out$n > /dev/null || ret=1
+grep "dnssec-policy: key lifetime is shorter than 30 days" < checkconf.out$n > /dev/null || ret=1
+lines=$(wc -l < "checkconf.out$n")
+if [ $lines -ne 5 ]; then ret=1; fi
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that a good 'kasp' configuration is accepted ($n)"
+ret=0
+$CHECKCONF good-kasp.conf > checkconf.out$n 2>/dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that named-checkconf prints a known good kasp config ($n)"
+ret=0
+awk 'BEGIN { ok = 0; } /cut here/ { ok = 1; getline } ok == 1 { print }' good-kasp.conf > good-kasp.conf.in
+[ -s good-kasp.conf.in ] || ret=1
+$CHECKCONF -p good-kasp.conf.in | grep -v '^good-kasp.conf.in:' > good-kasp.conf.out 2>&1 || ret=1
+cmp good-kasp.conf.in good-kasp.conf.out || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that max-ixfr-ratio 100% generates a warning ($n)"
+ret=0
+$CHECKCONF warn-maxratio1.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "exceeds 100%" < checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that *-source options with specified port generate warnings ($n)"
+ret=0
+$CHECKCONF warn-transfer-source.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "not recommended" < checkconf.out$n > /dev/null || ret=1
+$CHECKCONF warn-notify-source.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "not recommended" < checkconf.out$n > /dev/null || ret=1
+$CHECKCONF warn-parental-source.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "not recommended" < checkconf.out$n > /dev/null || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that using both max-zone-ttl and dnssec-policy generates a warning ($n)"
+ret=0
+$CHECKCONF warn-kasp-max-zone-ttl.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "option 'max-zone-ttl' is ignored when used together with 'dnssec-policy'" < checkconf.out$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check obsolete options generate warnings ($n)"
+ret=0
+$CHECKCONF warn-random-device.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "option 'random-device' is obsolete and should be removed" < checkconf.out$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that 'check-wildcard no;' succeeds as configured ($n)"
+ret=0
+$CHECKCONF -z check-wildcard-no.conf > checkconf.out$n 2>&1 || ret=1
+grep -F "warning: ownername 'foo.*.check-wildcard' contains an non-terminal wildcard" checkconf.out$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that 'check-wildcard yes;' warns as configured ($n)"
+ret=0
+$CHECKCONF -z check-wildcard.conf > checkconf.out$n 2>&1 || ret=1
+grep -F "warning: ownername 'foo.*.check-wildcard' contains an non-terminal wildcard" checkconf.out$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/checkconf/tests_sh_checkconf.py b/bin/tests/system/checkconf/tests_sh_checkconf.py
new file mode 100644
index 0000000..3a348ba
--- /dev/null
+++ b/bin/tests/system/checkconf/tests_sh_checkconf.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_checkconf(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/checkconf/view-class-any1.conf b/bin/tests/system/checkconf/view-class-any1.conf
new file mode 100644
index 0000000..8b39456
--- /dev/null
+++ b/bin/tests/system/checkconf/view-class-any1.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "example" any { };
diff --git a/bin/tests/system/checkconf/view-class-any2.conf b/bin/tests/system/checkconf/view-class-any2.conf
new file mode 100644
index 0000000..049ccf6
--- /dev/null
+++ b/bin/tests/system/checkconf/view-class-any2.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "example" class255 { };
diff --git a/bin/tests/system/checkconf/view-class-in1.conf b/bin/tests/system/checkconf/view-class-in1.conf
new file mode 100644
index 0000000..1d203e6
--- /dev/null
+++ b/bin/tests/system/checkconf/view-class-in1.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "example" in { };
diff --git a/bin/tests/system/checkconf/view-class-in2.conf b/bin/tests/system/checkconf/view-class-in2.conf
new file mode 100644
index 0000000..38b356e
--- /dev/null
+++ b/bin/tests/system/checkconf/view-class-in2.conf
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "example" class1 { };
diff --git a/bin/tests/system/checkconf/warn-kasp-max-zone-ttl.conf b/bin/tests/system/checkconf/warn-kasp-max-zone-ttl.conf
new file mode 100644
index 0000000..0d3139d
--- /dev/null
+++ b/bin/tests/system/checkconf/warn-kasp-max-zone-ttl.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * The dnssec-policy is not defined. Should also be caught if it is inherited.
+ */
+
+options {
+ dnssec-policy default;
+};
+
+zone "example.net" {
+ type primary;
+ file "example.db";
+ inline-signing yes;
+ max-zone-ttl 600;
+};
diff --git a/bin/tests/system/checkconf/warn-keydir.conf b/bin/tests/system/checkconf/warn-keydir.conf
new file mode 100644
index 0000000..9600071
--- /dev/null
+++ b/bin/tests/system/checkconf/warn-keydir.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * key-directory defined but doesn't exist.
+ */
+options {
+ directory ".";
+};
+
+zone dummy {
+ type primary;
+ file "xxxx";
+ key-directory "test.keydir";
+};
diff --git a/bin/tests/system/checkconf/warn-maxratio1.conf b/bin/tests/system/checkconf/warn-maxratio1.conf
new file mode 100644
index 0000000..eedf263
--- /dev/null
+++ b/bin/tests/system/checkconf/warn-maxratio1.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone example {
+ type primary;
+ masterfile-format raw;
+ file "example.db";
+ max-ixfr-ratio 101%;
+};
diff --git a/bin/tests/system/checkconf/warn-notify-source.conf b/bin/tests/system/checkconf/warn-notify-source.conf
new file mode 100644
index 0000000..4d840cc
--- /dev/null
+++ b/bin/tests/system/checkconf/warn-notify-source.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ notify-source 10.53.0.1 port 100;
+};
diff --git a/bin/tests/system/checkconf/warn-parental-source.conf b/bin/tests/system/checkconf/warn-parental-source.conf
new file mode 100644
index 0000000..2bbb34b
--- /dev/null
+++ b/bin/tests/system/checkconf/warn-parental-source.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ parental-source 10.53.0.1 port 100;
+};
diff --git a/bin/tests/system/checkconf/warn-random-device.conf b/bin/tests/system/checkconf/warn-random-device.conf
new file mode 100644
index 0000000..bc1451d
--- /dev/null
+++ b/bin/tests/system/checkconf/warn-random-device.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ random-device "/dev/urandom";
+};
diff --git a/bin/tests/system/checkconf/warn-transfer-source.conf b/bin/tests/system/checkconf/warn-transfer-source.conf
new file mode 100644
index 0000000..eb31041
--- /dev/null
+++ b/bin/tests/system/checkconf/warn-transfer-source.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port 5300;
+};
+
+zone example {
+ type secondary;
+ primaries { 1.2.3.4; };
+ transfer-source 10.53.0.1 port 100;
+};
diff --git a/bin/tests/system/checkds/README b/bin/tests/system/checkds/README
new file mode 100644
index 0000000..759c4bd
--- /dev/null
+++ b/bin/tests/system/checkds/README
@@ -0,0 +1,26 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+The test setup for the checkds tests.
+
+These servers are parent servers:
+- ns2 is a primary authoritative server that serves the parent zone for zones
+ configured in ns9.
+- ns4 is the secondary server for ns2.
+- ns5 is a primary authoritative server that serves the parent zone for zones
+ configured in ns9, but this one does not publish DS records (to test cases
+ where the DS is missing).
+- ns6 is an authoritative server for a different zone, to test badly configured
+ parental agents.
+- ns7 is the secondary server for ns5.
+
+Finally, ns9 is the authoritative server for the various DNSSEC enabled test
+domains.
diff --git a/bin/tests/system/checkds/clean.sh b/bin/tests/system/checkds/clean.sh
new file mode 100644
index 0000000..c73067f
--- /dev/null
+++ b/bin/tests/system/checkds/clean.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f dig.out*
+rm -f ns*/named.conf ns*/named.memstats ns*/named.run*
+rm -f ns*/*.jnl ns*/*.jbk
+rm -f ns*/K*.private ns*/K*.key ns*/K*.state
+rm -f ns*/dsset-*
+rm -f ns*/*.db ns*/*.jnl ns*/*.jbk ns*/*.db.signed ns*/*.db.infile
+rm -f ns*/keygen.out.* ns*/settime.out.* ns*/signer.out.*
+rm -f ns*/managed-keys.bind*
+rm -f ns*/trusted.conf
+rm -f ns*/*.mkeys
+rm -f ns*/zones
+rm -f *.checkds.out
diff --git a/bin/tests/system/checkds/ns1/named.conf.in b/bin/tests/system/checkds/ns1/named.conf.in
new file mode 100644
index 0000000..5b1c9fe
--- /dev/null
+++ b/bin/tests/system/checkds/ns1/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
diff --git a/bin/tests/system/checkds/ns1/root.db.in b/bin/tests/system/checkds/ns1/root.db.in
new file mode 100644
index 0000000..b2b9924
--- /dev/null
+++ b/bin/tests/system/checkds/ns1/root.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+checkds. NS ns2.checkds.
+ns2.checkds. A 10.53.0.2
diff --git a/bin/tests/system/checkds/ns1/setup.sh b/bin/tests/system/checkds/ns1/setup.sh
new file mode 100644
index 0000000..537fb42
--- /dev/null
+++ b/bin/tests/system/checkds/ns1/setup.sh
@@ -0,0 +1,46 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+echo_i "ns1/setup.sh"
+
+cp "../ns2/dsset-checkds." .
+
+ksk=$("$KEYGEN" -q -fk -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+cp "$ksk.key" "../ns10/"
+cp "$zsk.key" "../ns10/"
+cp "$ksk.private" "../ns10/"
+cp "$zsk.private" "../ns10/"
+
+cat "$infile" "$ksk.key" "$zsk.key" > "$zonefile"
+"$SIGNER" -g -o "$zone" "$zonefile" > /dev/null 2>&1
+
+(
+ cd ../ns10
+ cat "$infile" "$ksk.key" "$zsk.key" > "$zonefile"
+ "$SIGNER" -g -o "$zone" "$zonefile" > /dev/null 2>&1
+)
+
+# Configure the resolving server with a static key.
+keyfile_to_static_ds "$ksk" > trusted.conf
+cp trusted.conf ../ns3/trusted.conf
+cp trusted.conf ../ns8/trusted.conf
diff --git a/bin/tests/system/checkds/ns10/named.conf.in b/bin/tests/system/checkds/ns10/named.conf.in
new file mode 100644
index 0000000..e7e5f0c
--- /dev/null
+++ b/bin/tests/system/checkds/ns10/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS10
+
+options {
+ query-source address 10.53.0.10;
+ notify-source 10.53.0.10;
+ transfer-source 10.53.0.10;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.10; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
diff --git a/bin/tests/system/checkds/ns10/root.db.in b/bin/tests/system/checkds/ns10/root.db.in
new file mode 100644
index 0000000..988d7d1
--- /dev/null
+++ b/bin/tests/system/checkds/ns10/root.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.10
+
+checkds. NS ns5.checkds.
+ns5.checkds. A 10.53.0.5
diff --git a/bin/tests/system/checkds/ns2/named.conf.in b/bin/tests/system/checkds/ns2/named.conf.in
new file mode 100644
index 0000000..48e675c
--- /dev/null
+++ b/bin/tests/system/checkds/ns2/named.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ allow-transfer { any; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "checkds" {
+ type primary;
+ file "checkds.db";
+};
diff --git a/bin/tests/system/checkds/ns2/setup.sh b/bin/tests/system/checkds/ns2/setup.sh
new file mode 100644
index 0000000..3701948
--- /dev/null
+++ b/bin/tests/system/checkds/ns2/setup.sh
@@ -0,0 +1,36 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns2/setup.sh"
+
+for subdomain in dspublished reference missing-dspublished bad-dspublished \
+ multiple-dspublished incomplete-dspublished bad2-dspublished \
+ resolver-dspublished \
+ dswithdrawn missing-dswithdrawn bad-dswithdrawn \
+ multiple-dswithdrawn incomplete-dswithdrawn bad2-dswithdrawn \
+ resolver-dswithdrawn
+do
+ cp "../ns9/dsset-$subdomain.checkds." .
+done
+
+zone="checkds"
+infile="checkds.db.infile"
+zonefile="checkds.db"
+
+CSK=$($KEYGEN -k default $zone 2> keygen.out.$zone)
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+$SIGNER -S -g -z -x -s now-1h -e now+30d -o $zone -O full -f $zonefile $infile > signer.out.$zone 2>&1
diff --git a/bin/tests/system/checkds/ns2/template.db.in b/bin/tests/system/checkds/ns2/template.db.in
new file mode 100644
index 0000000..13d814f
--- /dev/null
+++ b/bin/tests/system/checkds/ns2/template.db.in
@@ -0,0 +1,39 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA secondary.example. hostmaster.example. (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns2
+ns2 A 10.53.0.2
+
+dspublished NS ns9.dspublished
+reference NS ns9.reference
+missing-dspublished NS ns9.missing-dspublished
+bad-dspublished NS ns9.bad-dspublished
+multiple-dspublished NS ns9.multiple-dspublished
+incomplete-dspublished NS ns9.incomplete-dspublished
+bad2-dspublished NS ns9.bad2-dspublished
+resolver-dspublished NS ns9.resolver-dspublished
+
+dswithdrawn NS ns9.dswithdrawn
+missing-dswithdrawn NS ns9.missing-dswithdrawn
+bad-dswithdrawn NS ns9.bad-dswithdrawn
+multiple-dswithdrawn NS ns9.multiple-dswithdrawn
+incomplete-dswithdrawn NS ns9.incomplete-dswithdrawn
+bad2-dswithdrawn NS ns9.bad2-dswithdrawn
+resolver-dswithdrawn NS ns9.resolver-dswithdrawn
diff --git a/bin/tests/system/checkds/ns3/named.conf.in b/bin/tests/system/checkds/ns3/named.conf.in
new file mode 100644
index 0000000..54bfc99
--- /dev/null
+++ b/bin/tests/system/checkds/ns3/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+options {
+ query-source address 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ session-keyfile "session.key";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/checkds/ns4/named.conf.in b/bin/tests/system/checkds/ns4/named.conf.in
new file mode 100644
index 0000000..0ca46d4
--- /dev/null
+++ b/bin/tests/system/checkds/ns4/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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; };
+ allow-transfer { any; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "checkds" {
+ type secondary;
+ file "checkds.db";
+ primaries { 10.53.0.2 port @PORT@; };
+};
diff --git a/bin/tests/system/checkds/ns5/named.conf.in b/bin/tests/system/checkds/ns5/named.conf.in
new file mode 100644
index 0000000..b7226fe
--- /dev/null
+++ b/bin/tests/system/checkds/ns5/named.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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; };
+ allow-transfer { any; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "checkds" {
+ type primary;
+ file "checkds.db";
+};
diff --git a/bin/tests/system/checkds/ns5/setup.sh b/bin/tests/system/checkds/ns5/setup.sh
new file mode 100644
index 0000000..79d7b71
--- /dev/null
+++ b/bin/tests/system/checkds/ns5/setup.sh
@@ -0,0 +1,26 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns5/setup.sh"
+
+zone="checkds"
+infile="checkds.db.infile"
+zonefile="checkds.db"
+
+CSK=$($KEYGEN -k default $zone 2> keygen.out.$zone)
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+$SIGNER -S -g -z -x -s now-1h -e now+30d -o $zone -O full -f $zonefile $infile > signer.out.$zone 2>&1
diff --git a/bin/tests/system/checkds/ns5/template.db.in b/bin/tests/system/checkds/ns5/template.db.in
new file mode 100644
index 0000000..54e4881
--- /dev/null
+++ b/bin/tests/system/checkds/ns5/template.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA secondary.example. hostmaster.example. (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns5
+ns5 A 10.53.0.5
+
+dspublished NS ns9.dspublished
+reference NS ns9.reference
+missing-dspublished NS ns9.missing-dspublished
+bad-dspublished NS ns9.bad-dspublished
+multiple-dspublished NS ns9.multiple-dspublished
+incomplete-dspublished NS ns9.incomplete-dspublished
+bad2-dspublished NS ns9.bad2-dspublished
+resolver-dspublished NS ns9.resolver-dspublished
+
+dswithdrawn NS ns9.dswithdrawn
+missing-dswithdrawn NS ns9.missing-dswithdrawn
+bad-dswithdrawn NS ns9.bad-dswithdrawn
+multiple-dswithdrawn NS ns9.multiple-dswithdrawn
+incomplete-dswithdrawn NS ns9.incomplete-dswithdrawn
+bad2-dswithdrawn NS ns9.bad2-dswithdrawn
+resolver-dswithdrawn NS ns9.resolver-dswithdrawn
+
diff --git a/bin/tests/system/checkds/ns6/named.conf.in b/bin/tests/system/checkds/ns6/named.conf.in
new file mode 100644
index 0000000..cc226fb
--- /dev/null
+++ b/bin/tests/system/checkds/ns6/named.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ 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.6; };
+ listen-on-v6 { none; };
+ allow-transfer { any; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "foo" {
+ type primary;
+ file "foo.db";
+};
diff --git a/bin/tests/system/checkds/ns7/named.conf.in b/bin/tests/system/checkds/ns7/named.conf.in
new file mode 100644
index 0000000..57460c8
--- /dev/null
+++ b/bin/tests/system/checkds/ns7/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS7
+
+options {
+ 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.7; };
+ listen-on-v6 { none; };
+ allow-transfer { any; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "checkds" {
+ type secondary;
+ file "checkds.db";
+ primaries { 10.53.0.5 port @PORT@; };
+};
diff --git a/bin/tests/system/checkds/ns8/named.conf.in b/bin/tests/system/checkds/ns8/named.conf.in
new file mode 100644
index 0000000..5fc52aa
--- /dev/null
+++ b/bin/tests/system/checkds/ns8/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS8
+
+options {
+ query-source address 10.53.0.8;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.8; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ session-keyfile "session.key";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/checkds/ns8/root.hint b/bin/tests/system/checkds/ns8/root.hint
new file mode 100644
index 0000000..3d54373
--- /dev/null
+++ b/bin/tests/system/checkds/ns8/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.10
diff --git a/bin/tests/system/checkds/ns9/named.conf.in b/bin/tests/system/checkds/ns9/named.conf.in
new file mode 100644
index 0000000..74a5130
--- /dev/null
+++ b/bin/tests/system/checkds/ns9/named.conf.in
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS9
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ allow-transfer { any; };
+ recursion no;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+parental-agents "ns2" port @PORT@ {
+ 10.53.0.2;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+/*
+ * Zone with parental agent configured, due for DS checking.
+ */
+zone "dspublished.checkds" {
+ type primary;
+ file "dspublished.checkds.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ parental-agents { 10.53.0.2 port @PORT@; };
+};
+
+/*
+ * Zone with parental agent configured, due for DS checking.
+ * Same as above, but now with a reference to parental-agents.
+ */
+zone "reference.checkds" {
+ type primary;
+ file "reference.checkds.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ parental-agents { "ns2"; };
+};
+
+/*
+ * Zone with parental agent configured, due for DS checking.
+ * The parental agent does not have the DS yet.
+ */
+zone "missing-dspublished.checkds" {
+ type primary;
+ file "missing-dspublished.checkds.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ parental-agents {
+ 10.53.0.5 port @PORT@; // missing
+ };
+};
+
+
+/*
+ * Zone with parental agent configured, due for DS checking.
+ * This case, the server is badly configured.
+ */
+zone "bad-dspublished.checkds" {
+ type primary;
+ file "bad-dspublished.checkds.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ parental-agents {
+ 10.53.0.6 port @PORT@; // bad
+ };
+};
+
+/*
+ * Zone with multiple parental agents configured, due for DS checking.
+ * All need to have the DS before the rollover may continue.
+ */
+zone "multiple-dspublished.checkds" {
+ type primary;
+ file "multiple-dspublished.checkds.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ parental-agents {
+ 10.53.0.2 port @PORT@;
+ 10.53.0.4 port @PORT@;
+ };
+};
+
+/*
+ * Zone with multiple parental agents configured, due for DS checking.
+ * All need to have the DS before the rollover may continue.
+ * This case, one server is still missing the DS.
+ */
+zone "incomplete-dspublished.checkds" {
+ type primary;
+ file "incomplete-dspublished.checkds.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ parental-agents {
+ 10.53.0.2 port @PORT@;
+ 10.53.0.4 port @PORT@;
+ 10.53.0.5 port @PORT@; // missing
+ };
+};
+
+
+/*
+ * Zone with multiple parental agents configured, due for DS checking.
+ * All need to have the DS before the rollover may continue.
+ * This case, one server is badly configured.
+ */
+zone "bad2-dspublished.checkds" {
+ type primary;
+ file "bad2-dspublished.checkds.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ parental-agents {
+ 10.53.0.2 port @PORT@;
+ 10.53.0.4 port @PORT@;
+ 10.53.0.6 port @PORT@; // bad
+ };
+};
+
+/*
+ * Zone with resolver parental agent configured, due for DS checking.
+ */
+zone "resolver-dspublished.checkds" {
+ type primary;
+ file "resolver-dspublished.checkds.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ parental-agents {
+ 10.53.0.3 port @PORT@;
+ };
+};
+
+// TODO: Other test cases:
+// - Test with bogus response
+// - check with TSIG
+// - check with TLS
+
+
+/*
+ * Zones that are going insecure (test DS withdrawn polling).
+ */
+zone "dswithdrawn.checkds" {
+ type primary;
+ file "dswithdrawn.checkds.db";
+ inline-signing yes;
+ dnssec-policy "insecure";
+ parental-agents { 10.53.0.5 port @PORT@; };
+};
+
+zone "missing-dswithdrawn.checkds" {
+ type primary;
+ file "missing-dswithdrawn.checkds.db";
+ inline-signing yes;
+ dnssec-policy "insecure";
+ parental-agents {
+ 10.53.0.2 port @PORT@; // still published
+ };
+};
+
+zone "bad-dswithdrawn.checkds" {
+ type primary;
+ file "bad-dswithdrawn.checkds.db";
+ inline-signing yes;
+ dnssec-policy "insecure";
+ parental-agents {
+ 10.53.0.6 port @PORT@; // bad
+ };
+};
+
+zone "multiple-dswithdrawn.checkds" {
+ type primary;
+ file "multiple-dswithdrawn.checkds.db";
+ inline-signing yes;
+ dnssec-policy "insecure";
+ parental-agents {
+ 10.53.0.5 port @PORT@;
+ 10.53.0.7 port @PORT@;
+ };
+};
+
+zone "incomplete-dswithdrawn.checkds" {
+ type primary;
+ file "incomplete-dswithdrawn.checkds.db";
+ inline-signing yes;
+ dnssec-policy "insecure";
+ parental-agents {
+ 10.53.0.2 port @PORT@; // still published
+ 10.53.0.5 port @PORT@;
+ 10.53.0.7 port @PORT@;
+ };
+};
+
+zone "bad2-dswithdrawn.checkds" {
+ type primary;
+ file "bad2-dswithdrawn.checkds.db";
+ inline-signing yes;
+ dnssec-policy "insecure";
+ parental-agents {
+ 10.53.0.5 port @PORT@;
+ 10.53.0.7 port @PORT@;
+ 10.53.0.6 port @PORT@; // bad
+ };
+};
+
+zone "resolver-dswithdrawn.checkds" {
+ type primary;
+ file "resolver-dswithdrawn.checkds.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ parental-agents {
+ 10.53.0.8 port @PORT@;
+ };
+};
diff --git a/bin/tests/system/checkds/ns9/setup.sh b/bin/tests/system/checkds/ns9/setup.sh
new file mode 100644
index 0000000..e4d1586
--- /dev/null
+++ b/bin/tests/system/checkds/ns9/setup.sh
@@ -0,0 +1,63 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns9/setup.sh"
+
+setup() {
+ zone="$1"
+ echo_i "setting up zone: $zone"
+ zonefile="${zone}.db"
+ infile="${zone}.db.infile"
+ echo "$zone" >> zones
+}
+
+# Short environment variable names for key states and times.
+H="HIDDEN"
+R="RUMOURED"
+O="OMNIPRESENT"
+U="UNRETENTIVE"
+T="now-30d"
+Y="now-1y"
+
+# DS Publication.
+for zn in dspublished reference missing-dspublished bad-dspublished \
+ multiple-dspublished incomplete-dspublished bad2-dspublished resolver-dspublished
+do
+ setup "${zn}.checkds"
+ cp template.db.in "$zonefile"
+ keytimes="-P $T -P sync $T -A $T"
+ CSK=$($KEYGEN -k default $keytimes $zone 2> keygen.out.$zone)
+ $SETTIME -s -g $O -k $O $T -r $O $T -z $O $T -d $R $T "$CSK" > settime.out.$zone 2>&1
+ cat template.db.in "${CSK}.key" > "$infile"
+ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+ cp $infile $zonefile
+ $SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+done
+
+# DS Withdrawal.
+for zn in dswithdrawn missing-dswithdrawn bad-dswithdrawn multiple-dswithdrawn \
+ incomplete-dswithdrawn bad2-dswithdrawn resolver-dswithdrawn
+do
+ setup "${zn}.checkds"
+ cp template.db.in "$zonefile"
+ keytimes="-P $Y -P sync $Y -A $Y"
+ CSK=$($KEYGEN -k default $keytimes $zone 2> keygen.out.$zone)
+ $SETTIME -s -g $H -k $O $T -r $O $T -z $O $T -d $U $T "$CSK" > settime.out.$zone 2>&1
+ cat template.db.in "${CSK}.key" > "$infile"
+ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+ cp $infile $zonefile
+ $SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+done
diff --git a/bin/tests/system/checkds/ns9/template.db.in b/bin/tests/system/checkds/ns9/template.db.in
new file mode 100644
index 0000000..cf06015
--- /dev/null
+++ b/bin/tests/system/checkds/ns9/template.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns9
+ns9 A 10.53.0.9
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+
diff --git a/bin/tests/system/checkds/setup.sh b/bin/tests/system/checkds/setup.sh
new file mode 100644
index 0000000..828b2e6
--- /dev/null
+++ b/bin/tests/system/checkds/setup.sh
@@ -0,0 +1,48 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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
+copy_setports ns8/named.conf.in ns8/named.conf
+copy_setports ns9/named.conf.in ns9/named.conf
+copy_setports ns10/named.conf.in ns10/named.conf
+
+# Setup zones
+(
+ cd ns9
+ $SHELL setup.sh
+)
+(
+ cd ns5
+ $SHELL setup.sh
+)
+(
+ cd ns2
+ $SHELL setup.sh
+)
+(
+ cd ns1
+ $SHELL setup.sh
+)
diff --git a/bin/tests/system/checkds/tests_checkds.py b/bin/tests/system/checkds/tests_checkds.py
new file mode 100755
index 0000000..5f9ae73
--- /dev/null
+++ b/bin/tests/system/checkds/tests_checkds.py
@@ -0,0 +1,470 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import mmap
+import os
+import subprocess
+import sys
+import time
+
+import pytest
+
+pytest.importorskip("dns", minversion="2.0.0")
+import dns.exception
+import dns.message
+import dns.name
+import dns.query
+import dns.rcode
+import dns.rdataclass
+import dns.rdatatype
+import dns.resolver
+
+
+pytestmark = pytest.mark.skipif(
+ sys.version_info < (3, 7), reason="Python >= 3.7 required [GL #3001]"
+)
+
+
+def has_signed_apex_nsec(zone, response):
+ has_nsec = False
+ has_rrsig = False
+
+ ttl = 300
+ nextname = "a."
+ types = "NS SOA RRSIG NSEC DNSKEY"
+ match = "{0} {1} IN NSEC {2}{0} {3}".format(zone, ttl, nextname, types)
+ sig = "{0} {1} IN RRSIG NSEC 13 2 300".format(zone, ttl)
+
+ for rr in response.answer:
+ if match in rr.to_text():
+ has_nsec = True
+ if sig in rr.to_text():
+ has_rrsig = True
+
+ if not has_nsec:
+ print("error: missing apex NSEC record in response")
+ if not has_rrsig:
+ print("error: missing NSEC signature in response")
+
+ return has_nsec and has_rrsig
+
+
+def do_query(server, qname, qtype, tcp=False):
+ query = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True)
+ try:
+ if tcp:
+ response = dns.query.tcp(
+ query, server.nameservers[0], timeout=3, port=server.port
+ )
+ else:
+ response = dns.query.udp(
+ query, server.nameservers[0], timeout=3, port=server.port
+ )
+ except dns.exception.Timeout:
+ print(
+ "error: query timeout for query {} {} to {}".format(
+ qname, qtype, server.nameservers[0]
+ )
+ )
+ return None
+
+ return response
+
+
+def verify_zone(zone, transfer):
+ verify = os.getenv("VERIFY")
+ assert verify is not None
+
+ filename = "{}out".format(zone)
+ with open(filename, "w", encoding="utf-8") as file:
+ for rr in transfer.answer:
+ file.write(rr.to_text())
+ file.write("\n")
+
+ # dnssec-verify command with default arguments.
+ verify_cmd = [verify, "-z", "-o", zone, filename]
+
+ verifier = subprocess.run(verify_cmd, capture_output=True, check=True)
+
+ if verifier.returncode != 0:
+ print("error: dnssec-verify {} failed".format(zone))
+ sys.stderr.buffer.write(verifier.stderr)
+
+ return verifier.returncode == 0
+
+
+def read_statefile(server, zone):
+ addr = server.nameservers[0]
+ count = 0
+ keyid = 0
+ state = {}
+
+ response = do_query(server, zone, "DS", tcp=True)
+ if not isinstance(response, dns.message.Message):
+ print("error: no response for {} DS from {}".format(zone, addr))
+ return {}
+
+ if response.rcode() == dns.rcode.NOERROR:
+ # fetch key id from response.
+ for rr in response.answer:
+ if rr.match(
+ dns.name.from_text(zone),
+ dns.rdataclass.IN,
+ dns.rdatatype.DS,
+ dns.rdatatype.NONE,
+ ):
+ if count == 0:
+ keyid = list(dict(rr.items).items())[0][0].key_tag
+ count += 1
+
+ if count != 1:
+ print(
+ "error: expected a single DS in response for {} from {},"
+ "got {}".format(zone, addr, count)
+ )
+ return {}
+ else:
+ print(
+ "error: {} response for {} DNSKEY from {}".format(
+ dns.rcode.to_text(response.rcode()), zone, addr
+ )
+ )
+ return {}
+
+ filename = "ns9/K{}+013+{:05d}.state".format(zone, keyid)
+ print("read state file {}".format(filename))
+
+ try:
+ with open(filename, "r", encoding="utf-8") as file:
+ for line in file:
+ if line.startswith(";"):
+ continue
+ key, val = line.strip().split(":", 1)
+ state[key.strip()] = val.strip()
+
+ except FileNotFoundError:
+ # file may not be written just yet.
+ return {}
+
+ return state
+
+
+def zone_check(server, zone):
+ addr = server.nameservers[0]
+
+ # wait until zone is fully signed.
+ signed = False
+ for _ in range(10):
+ response = do_query(server, zone, "NSEC")
+ if not isinstance(response, dns.message.Message):
+ print("error: no response for {} NSEC from {}".format(zone, addr))
+ elif response.rcode() == dns.rcode.NOERROR:
+ signed = has_signed_apex_nsec(zone, response)
+ else:
+ print(
+ "error: {} response for {} NSEC from {}".format(
+ dns.rcode.to_text(response.rcode()), zone, addr
+ )
+ )
+
+ if signed:
+ break
+
+ time.sleep(1)
+
+ assert signed
+
+ # check if zone if DNSSEC valid.
+ verified = False
+ transfer = do_query(server, zone, "AXFR", tcp=True)
+ if not isinstance(transfer, dns.message.Message):
+ print("error: no response for {} AXFR from {}".format(zone, addr))
+ elif transfer.rcode() == dns.rcode.NOERROR:
+ verified = verify_zone(zone, transfer)
+ else:
+ print(
+ "error: {} response for {} AXFR from {}".format(
+ dns.rcode.to_text(transfer.rcode()), zone, addr
+ )
+ )
+
+ assert verified
+
+
+def keystate_check(server, zone, key):
+ val = 0
+ deny = False
+
+ search = key
+ if key.startswith("!"):
+ deny = True
+ search = key[1:]
+
+ for _ in range(10):
+ state = read_statefile(server, zone)
+ try:
+ val = state[search]
+ except KeyError:
+ pass
+
+ if not deny and val != 0:
+ break
+ if deny and val == 0:
+ break
+
+ time.sleep(1)
+
+ if deny:
+ assert val == 0
+ else:
+ assert val != 0
+
+
+def wait_for_log(filename, log):
+ found = False
+
+ for _ in range(10):
+ print("read log file {}".format(filename))
+
+ try:
+ with open(filename, "r", encoding="utf-8") as file:
+ s = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ)
+ if s.find(bytes(log, "ascii")) != -1:
+ found = True
+ except FileNotFoundError:
+ print("file not found {}".format(filename))
+
+ if found:
+ break
+
+ print("sleep")
+ time.sleep(1)
+
+ assert found
+
+
+def test_checkds_dspublished(named_port):
+ # We create resolver instances that will be used to send queries.
+ server = dns.resolver.Resolver()
+ server.nameservers = ["10.53.0.9"]
+ server.port = named_port
+
+ parent = dns.resolver.Resolver()
+ parent.nameservers = ["10.53.0.2"]
+ parent.port = named_port
+
+ # DS correctly published in parent.
+ zone_check(server, "dspublished.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone dspublished.checkds/IN (signed): checkds: DS response from 10.53.0.2",
+ )
+ keystate_check(parent, "dspublished.checkds.", "DSPublish")
+
+ # DS correctly published in parent (reference to parental-agent).
+ zone_check(server, "reference.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone reference.checkds/IN (signed): checkds: DS response from 10.53.0.2",
+ )
+ keystate_check(parent, "reference.checkds.", "DSPublish")
+
+ # DS not published in parent.
+ zone_check(server, "missing-dspublished.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone missing-dspublished.checkds/IN (signed): checkds: "
+ "empty DS response from 10.53.0.5",
+ )
+ keystate_check(parent, "missing-dspublished.checkds.", "!DSPublish")
+
+ # Badly configured parent.
+ zone_check(server, "bad-dspublished.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone bad-dspublished.checkds/IN (signed): checkds: "
+ "bad DS response from 10.53.0.6",
+ )
+ keystate_check(parent, "bad-dspublished.checkds.", "!DSPublish")
+
+ # TBD: DS published in parent, but bogus signature.
+
+ # DS correctly published in all parents.
+ zone_check(server, "multiple-dspublished.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone multiple-dspublished.checkds/IN (signed): checkds: "
+ "DS response from 10.53.0.2",
+ )
+ wait_for_log(
+ "ns9/named.run",
+ "zone multiple-dspublished.checkds/IN (signed): checkds: "
+ "DS response from 10.53.0.4",
+ )
+ keystate_check(parent, "multiple-dspublished.checkds.", "DSPublish")
+
+ # DS published in only one of multiple parents.
+ zone_check(server, "incomplete-dspublished.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone incomplete-dspublished.checkds/IN (signed): checkds: "
+ "DS response from 10.53.0.2",
+ )
+ wait_for_log(
+ "ns9/named.run",
+ "zone incomplete-dspublished.checkds/IN (signed): checkds: "
+ "DS response from 10.53.0.4",
+ )
+ wait_for_log(
+ "ns9/named.run",
+ "zone incomplete-dspublished.checkds/IN (signed): checkds: "
+ "empty DS response from 10.53.0.5",
+ )
+ keystate_check(parent, "incomplete-dspublished.checkds.", "!DSPublish")
+
+ # One of the parents is badly configured.
+ zone_check(server, "bad2-dswithdrawn.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone bad2-dspublished.checkds/IN (signed): checkds: "
+ "DS response from 10.53.0.2",
+ )
+ wait_for_log(
+ "ns9/named.run",
+ "zone bad2-dspublished.checkds/IN (signed): checkds: "
+ "DS response from 10.53.0.4",
+ )
+ wait_for_log(
+ "ns9/named.run",
+ "zone bad2-dspublished.checkds/IN (signed): checkds: "
+ "bad DS response from 10.53.0.6",
+ )
+ keystate_check(parent, "bad2-dspublished.checkds.", "!DSPublish")
+
+ # Check with resolver parental-agent.
+ zone_check(server, "resolver-dspublished.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone resolver-dspublished.checkds/IN (signed): checkds: "
+ "DS response from 10.53.0.3",
+ )
+ keystate_check(parent, "resolver-dspublished.checkds.", "DSPublish")
+
+ # TBD: DS published in all parents, but one has bogus signature.
+
+ # TBD: Check with TSIG
+
+ # TBD: Check with TLS
+
+
+def test_checkds_dswithdrawn(named_port):
+ # We create resolver instances that will be used to send queries.
+ server = dns.resolver.Resolver()
+ server.nameservers = ["10.53.0.9"]
+ server.port = named_port
+
+ parent = dns.resolver.Resolver()
+ parent.nameservers = ["10.53.0.2"]
+ parent.port = named_port
+
+ # DS correctly published in single parent.
+ zone_check(server, "dswithdrawn.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone dswithdrawn.checkds/IN (signed): checkds: "
+ "empty DS response from 10.53.0.5",
+ )
+ keystate_check(parent, "dswithdrawn.checkds.", "DSRemoved")
+
+ # DS not withdrawn from parent.
+ zone_check(server, "missing-dswithdrawn.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone missing-dswithdrawn.checkds/IN (signed): checkds: "
+ "DS response from 10.53.0.2",
+ )
+ keystate_check(parent, "missing-dswithdrawn.checkds.", "!DSRemoved")
+
+ # Badly configured parent.
+ zone_check(server, "bad-dswithdrawn.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone bad-dswithdrawn.checkds/IN (signed): checkds: "
+ "bad DS response from 10.53.0.6",
+ )
+ keystate_check(parent, "bad-dswithdrawn.checkds.", "!DSRemoved")
+
+ # TBD: DS published in parent, but bogus signature.
+
+ # DS correctly withdrawn from all parents.
+ zone_check(server, "multiple-dswithdrawn.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone multiple-dswithdrawn.checkds/IN (signed): checkds: "
+ "empty DS response from 10.53.0.5",
+ )
+ wait_for_log(
+ "ns9/named.run",
+ "zone multiple-dswithdrawn.checkds/IN (signed): checkds: "
+ "empty DS response from 10.53.0.7",
+ )
+ keystate_check(parent, "multiple-dswithdrawn.checkds.", "DSRemoved")
+
+ # DS withdrawn from only one of multiple parents.
+ zone_check(server, "incomplete-dswithdrawn.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: "
+ "DS response from 10.53.0.2",
+ )
+ wait_for_log(
+ "ns9/named.run",
+ "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: "
+ "empty DS response from 10.53.0.5",
+ )
+ wait_for_log(
+ "ns9/named.run",
+ "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: "
+ "empty DS response from 10.53.0.7",
+ )
+ keystate_check(parent, "incomplete-dswithdrawn.checkds.", "!DSRemoved")
+
+ # One of the parents is badly configured.
+ zone_check(server, "bad2-dswithdrawn.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone bad2-dswithdrawn.checkds/IN (signed): checkds: "
+ "empty DS response from 10.53.0.5",
+ )
+ wait_for_log(
+ "ns9/named.run",
+ "zone bad2-dswithdrawn.checkds/IN (signed): checkds: "
+ "empty DS response from 10.53.0.7",
+ )
+ wait_for_log(
+ "ns9/named.run",
+ "zone bad2-dswithdrawn.checkds/IN (signed): checkds: "
+ "bad DS response from 10.53.0.6",
+ )
+ keystate_check(parent, "bad2-dswithdrawn.checkds.", "!DSRemoved")
+
+ # Check with resolver parental-agent.
+ zone_check(server, "resolver-dswithdrawn.checkds.")
+ wait_for_log(
+ "ns9/named.run",
+ "zone resolver-dswithdrawn.checkds/IN (signed): checkds: "
+ "empty DS response from 10.53.0.8",
+ )
+ keystate_check(parent, "resolver-dswithdrawn.checkds.", "DSRemoved")
+
+ # TBD: DS withdrawn from all parents, but one has bogus signature.
diff --git a/bin/tests/system/checknames/clean.sh b/bin/tests/system/checknames/clean.sh
new file mode 100644
index 0000000..fcbd504
--- /dev/null
+++ b/bin/tests/system/checknames/clean.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.conf
+rm -f dig.out.ns?.test*
+rm -f nsupdate.out.test*
+rm -f ns1/*.example.db
+rm -f ns1/*.update.db
+rm -f ns1/*.update.db.jnl
+rm -f ns4/*.update.db
+rm -f ns4/*.update.db.jnl
+rm -f ns5/*.update.db
+rm -f ns5/*.update.db.jnl
+rm -f */named.memstats
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/checknames/ns1/fail.example.db.in b/bin/tests/system/checknames/ns1/fail.example.db.in
new file mode 100644
index 0000000..c4c06c3
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/fail.example.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA ns1.fail.example. hostmaster.fail.example. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.fail.example.
+ns1.fail.example. A 10.53.0.1
+xx_xx.fail.example. A 127.0.0.1
diff --git a/bin/tests/system/checknames/ns1/fail.update.db.in b/bin/tests/system/checknames/ns1/fail.update.db.in
new file mode 100644
index 0000000..a360cfd
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/fail.update.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA ns1.fail.update. hostmaster.fail.update. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.fail.update.
+ns1.fail.update. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns1/ignore.example.db.in b/bin/tests/system/checknames/ns1/ignore.example.db.in
new file mode 100644
index 0000000..148fa6a
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/ignore.example.db.in
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA ns1.ignore.example. hostmaster.ignore.example. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.ignore.example.
+ns1.ignore.example. A 10.53.0.1
+yy_yy.ignore.example. A 10.53.0.1
+mx.ignore.example. MX 10 zz_zz.ignore.example.
diff --git a/bin/tests/system/checknames/ns1/ignore.update.db.in b/bin/tests/system/checknames/ns1/ignore.update.db.in
new file mode 100644
index 0000000..0925cef
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/ignore.update.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA ns1.ignore.update. hostmaster.ignore.update. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.ignore.update.
+ns1.ignore.update. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns1/named.conf.in b/bin/tests/system/checknames/ns1/named.conf.in
new file mode 100644
index 0000000..a6a3a66
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/named.conf.in
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ check-integrity no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "ignore.example" {
+ type primary;
+ file "ignore.example.db";
+ check-names ignore;
+};
+
+zone "warn.example" {
+ type primary;
+ file "warn.example.db";
+ check-names warn;
+};
+
+zone "fail.example" {
+ type primary;
+ file "fail.example.db";
+ check-names fail;
+};
+
+zone "ignore.update" {
+ type primary;
+ file "ignore.update.db";
+ allow-update { any; };
+ check-names ignore;
+};
+
+zone "warn.update" {
+ type primary;
+ file "warn.update.db";
+ allow-update { any; };
+ check-names warn;
+};
+
+zone "fail.update" {
+ type primary;
+ file "fail.update.db";
+ allow-update { any; };
+ check-names fail;
+};
diff --git a/bin/tests/system/checknames/ns1/root.db b/bin/tests/system/checknames/ns1/root.db
new file mode 100644
index 0000000..bc026a5
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA ns1. hostmaster.warn.example. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.
+ns1. A 10.53.0.1
+;
+ignore.example. NS ns1.ignore.example.
+ns1.ignore.example. A 10.53.0.1
+warn.example. NS ns1.warn.example.
+ns1.warn.example. A 10.53.0.1
+fail.example. NS ns1.fail.example.
+ns1.fail.example. A 10.53.0.1
+;
+ignore.update. NS ns1.ignore.update.
+ns1.ignore.update. A 10.53.0.1
+warn.update. NS ns1.warn.update.
+ns1.warn.update. A 10.53.0.1
+fail.update. NS ns1.fail.update.
+ns1.fail.update. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns1/warn.example.db.in b/bin/tests/system/checknames/ns1/warn.example.db.in
new file mode 100644
index 0000000..7b636fd
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/warn.example.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA ns1.warn.example. hostmaster.warn.example. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.warn.example.
+ns1.warn.example. A 10.53.0.1
+xx_xx.warn.example. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns1/warn.update.db.in b/bin/tests/system/checknames/ns1/warn.update.db.in
new file mode 100644
index 0000000..9a9af97
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/warn.update.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA ns1.warn.update. hostmaster.warn.update. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.warn.update.
+ns1.warn.update. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns2/named.conf.in b/bin/tests/system/checknames/ns2/named.conf.in
new file mode 100644
index 0000000..3ba62e1
--- /dev/null
+++ b/bin/tests/system/checknames/ns2/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ check-names response warn;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
diff --git a/bin/tests/system/checknames/ns2/root.hints b/bin/tests/system/checknames/ns2/root.hints
new file mode 100644
index 0000000..5e89d74
--- /dev/null
+++ b/bin/tests/system/checknames/ns2/root.hints
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. NS ns1.
+ns1. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns3/named.conf.in b/bin/tests/system/checknames/ns3/named.conf.in
new file mode 100644
index 0000000..7c0cacb
--- /dev/null
+++ b/bin/tests/system/checknames/ns3/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ check-names response fail;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
diff --git a/bin/tests/system/checknames/ns3/root.hints b/bin/tests/system/checknames/ns3/root.hints
new file mode 100644
index 0000000..5e89d74
--- /dev/null
+++ b/bin/tests/system/checknames/ns3/root.hints
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. NS ns1.
+ns1. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns4/named.conf.in b/bin/tests/system/checknames/ns4/named.conf.in
new file mode 100644
index 0000000..f0cb870
--- /dev/null
+++ b/bin/tests/system/checknames/ns4/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ check-names primary ignore;
+ check-names secondary ignore;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
+
+zone "primary-ignore.update" {
+ type primary;
+ file "primary-ignore.update.db";
+ allow-update { any; };
+};
+
+zone "master-ignore.update" {
+ type secondary;
+ primaries { 10.53.0.5; };
+ file "secondary-ignore.update.db";
+};
diff --git a/bin/tests/system/checknames/ns4/primary-ignore.update.db.in b/bin/tests/system/checknames/ns4/primary-ignore.update.db.in
new file mode 100644
index 0000000..b343cb1
--- /dev/null
+++ b/bin/tests/system/checknames/ns4/primary-ignore.update.db.in
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA ns4 hostmaster.ignore.update. (
+ 1 3600 1200 604800 3600 )
+ NS ns4
+ NS ns5
+ns4 A 10.53.0.4
+ns5 A 10.53.0.5
diff --git a/bin/tests/system/checknames/ns4/root.hints b/bin/tests/system/checknames/ns4/root.hints
new file mode 100644
index 0000000..5e89d74
--- /dev/null
+++ b/bin/tests/system/checknames/ns4/root.hints
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. NS ns1.
+ns1. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns5/master-ignore.update.db.in b/bin/tests/system/checknames/ns5/master-ignore.update.db.in
new file mode 100644
index 0000000..1057248
--- /dev/null
+++ b/bin/tests/system/checknames/ns5/master-ignore.update.db.in
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA ns5. hostmaster.ignore.update. (
+ 1 3600 1200 604800 3600 )
+ NS ns4
+ NS ns5
+ns4 A 10.53.0.4
+ns5 A 10.53.0.5
diff --git a/bin/tests/system/checknames/ns5/named.conf.in b/bin/tests/system/checknames/ns5/named.conf.in
new file mode 100644
index 0000000..1797aa1
--- /dev/null
+++ b/bin/tests/system/checknames/ns5/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ dnssec-validation yes;
+ check-names master ignore;
+ check-names slave ignore;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
+
+zone "master-ignore.update" {
+ type primary;
+ file "master-ignore.update.db";
+ allow-update { any; };
+};
+
+zone "primary-ignore.update" {
+ type secondary;
+ primaries { 10.53.0.4; };
+ file "primary-ignore.update.db";
+};
diff --git a/bin/tests/system/checknames/ns5/root.hints b/bin/tests/system/checknames/ns5/root.hints
new file mode 100644
index 0000000..5e89d74
--- /dev/null
+++ b/bin/tests/system/checknames/ns5/root.hints
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. NS ns1.
+ns1. A 10.53.0.1
diff --git a/bin/tests/system/checknames/setup.sh b/bin/tests/system/checknames/setup.sh
new file mode 100644
index 0000000..d80e746
--- /dev/null
+++ b/bin/tests/system/checknames/setup.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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
+
+cp ns1/ignore.example.db.in ns1/ignore.example.db
+cp ns1/warn.example.db.in ns1/warn.example.db
+cp ns1/fail.example.db.in ns1/fail.example.db
+
+cp ns1/ignore.update.db.in ns1/ignore.update.db
+cp ns1/warn.update.db.in ns1/warn.update.db
+cp ns1/fail.update.db.in ns1/fail.update.db
+
+cp ns4/primary-ignore.update.db.in ns4/primary-ignore.update.db
+
+cp ns5/master-ignore.update.db.in ns5/master-ignore.update.db
diff --git a/bin/tests/system/checknames/tests.sh b/bin/tests/system/checknames/tests.sh
new file mode 100644
index 0000000..47ba801
--- /dev/null
+++ b/bin/tests/system/checknames/tests.sh
@@ -0,0 +1,192 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=1
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}"
+
+wait_for_record () {
+ $DIG $DIGOPTS "$1" "$2" "$3" > "$4" || return 1
+ grep NOERROR "$4" > /dev/null || return 1
+ return 0
+}
+
+# Entry should exist.
+echo_i "check for failure from on zone load for 'check-names fail;' ($n)"
+ret=0
+$DIG $DIGOPTS fail.example. @10.53.0.1 a > dig.out.ns1.test$n || ret=1
+grep SERVFAIL dig.out.ns1.test$n > /dev/null || ret=1
+grep 'xx_xx.fail.example: bad owner name (check-names)' ns1/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# Entry should exist.
+echo_i "check for warnings from on zone load for 'check-names warn;' ($n)"
+ret=0
+grep 'xx_xx.warn.example: bad owner name (check-names)' ns1/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# Entry should not exist.
+echo_i "check for warnings from on zone load for 'check-names ignore;' ($n)"
+ret=1
+grep 'yy_yy.ignore.example: bad owner name (check-names)' ns1/named.run || ret=0
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# Entry should exist
+echo_i "check that 'check-names response warn;' works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth yy_yy.ignore.example. @10.53.0.1 a > dig.out.ns1.test$n || ret=1
+$DIG $DIGOPTS +noauth yy_yy.ignore.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+digcomp dig.out.ns1.test$n dig.out.ns2.test$n || ret=1
+grep "check-names warning yy_yy.ignore.example/A/IN" ns2/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# Entry should exist
+echo_i "check that 'check-names response (owner) fails;' works ($n)"
+ret=0
+$DIG $DIGOPTS yy_yy.ignore.example. @10.53.0.1 a > dig.out.ns1.test$n || ret=1
+$DIG $DIGOPTS yy_yy.ignore.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+grep NOERROR dig.out.ns1.test$n > /dev/null || ret=1
+grep REFUSED dig.out.ns3.test$n > /dev/null || ret=1
+grep "check-names failure yy_yy.ignore.example/A/IN" ns3/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# Entry should exist
+echo_i "check that 'check-names response (rdata) fails;' works ($n)"
+ret=0
+$DIG $DIGOPTS mx.ignore.example. @10.53.0.1 MX > dig.out.ns1.test$n || ret=1
+$DIG $DIGOPTS mx.ignore.example. @10.53.0.3 MX > dig.out.ns3.test$n || ret=1
+grep NOERROR dig.out.ns1.test$n > /dev/null || ret=1
+grep SERVFAIL dig.out.ns3.test$n > /dev/null || ret=1
+grep "check-names failure mx.ignore.example/MX/IN" ns3/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "check that updates to 'check-names fail;' are rejected ($n)"
+ret=0
+not=1
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 || not=0
+check-names off
+server 10.53.0.1 ${PORT}
+update add xxx_xxx.fail.update. 600 A 10.10.10.1
+send
+END
+if [ $not != 0 ]; then ret=1; fi
+$DIG $DIGOPTS xxx_xxx.fail.update @10.53.0.1 A > dig.out.ns1.test$n || ret=1
+grep "xxx_xxx.fail.update/A: bad owner name (check-names)" ns1/named.run > /dev/null || ret=1
+grep NXDOMAIN dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "check that updates to 'check-names warn;' succeed and are logged ($n)"
+ret=0
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1|| ret=1
+check-names off
+server 10.53.0.1 ${PORT}
+update add xxx_xxx.warn.update. 600 A 10.10.10.1
+send
+END
+$DIG $DIGOPTS xxx_xxx.warn.update @10.53.0.1 A > dig.out.ns1.test$n || ret=1
+grep "xxx_xxx.warn.update/A: bad owner name (check-names)" ns1/named.run > /dev/null || ret=1
+grep NOERROR dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "check that updates to 'check-names ignore;' succeed and are not logged ($n)"
+ret=0
+not=1
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 || ret=1
+check-names off
+server 10.53.0.1 ${PORT}
+update add xxx_xxx.ignore.update. 600 A 10.10.10.1
+send
+END
+grep "xxx_xxx.ignore.update/A.*(check-names)" ns1/named.run > /dev/null || not=0
+if [ $not != 0 ]; then ret=1; fi
+$DIG $DIGOPTS xxx_xxx.ignore.update @10.53.0.1 A > dig.out.ns1.test$n || ret=1
+grep NOERROR dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "check that updates to 'check-names primary ignore;' succeed and are not logged ($n)"
+ret=0
+not=1
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 || ret=1
+check-names off
+server 10.53.0.4 ${PORT}
+update add xxx_xxx.primary-ignore.update. 600 A 10.10.10.1
+send
+END
+grep "xxx_xxx.primary-ignore.update/A.*(check-names)" ns4/named.run > /dev/null || not=0
+if [ $not != 0 ]; then ret=1; fi
+$DIG $DIGOPTS xxx_xxx.primary-ignore.update @10.53.0.4 A > dig.out.ns4.test$n || ret=1
+grep NOERROR dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "check that updates to 'check-names master ignore;' succeed and are not logged ($n)"
+ret=0
+not=1
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 || ret=1
+check-names off
+server 10.53.0.5 ${PORT}
+update add xxx_xxx.master-ignore.update. 600 A 10.10.10.1
+send
+END
+grep "xxx_xxx.master-ignore.update/A.*(check-names)" ns5/named.run > /dev/null || not=0
+if [ $not != 0 ]; then ret=1; fi
+$DIG $DIGOPTS xxx_xxx.master-ignore.update @10.53.0.5 A > dig.out.ns5.test$n || ret=1
+grep NOERROR dig.out.ns5.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+n=$((n+1))
+
+echo_i "check that updates to 'check-names secondary ignore;' succeed and are not logged ($n)"
+ret=0
+# takes a while for the transfer to succeed as ns5 (primary) is started after ns4 (secondary)
+# and the zone is still loading when we get to this point.
+retry_quiet 35 wait_for_record xxx_xxx.master-ignore.update @10.53.0.4 A dig.out.ns4.test$n || ret=1
+grep "xxx_xxx.master-ignore.update/A.*(check-names)" ns4/named.run > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "check that updates to 'check-names master ignore;' succeed and are not logged ($n)"
+ret=0
+retry_quiet 35 wait_for_record xxx_xxx.primary-ignore.update @10.53.0.5 A dig.out.ns5.test$n || ret=1
+grep "xxx_xxx.primary-ignore.update/A.*(check-names)" ns5/named.run > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+n=$((n+1))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/checknames/tests_sh_checknames.py b/bin/tests/system/checknames/tests_sh_checknames.py
new file mode 100644
index 0000000..e0e035b
--- /dev/null
+++ b/bin/tests/system/checknames/tests_sh_checknames.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_checknames(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/checkzone/clean.sh b/bin/tests/system/checkzone/clean.sh
new file mode 100644
index 0000000..cb189a3
--- /dev/null
+++ b/bin/tests/system/checkzone/clean.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f test.* good1.db.raw named-compilezone
+rm -f ns*/named.lock
+rm -f zones/bad-tsig.db
+rm -f zones/zone1_*.txt
diff --git a/bin/tests/system/checkzone/setup.sh b/bin/tests/system/checkzone/setup.sh
new file mode 100644
index 0000000..4518c56
--- /dev/null
+++ b/bin/tests/system/checkzone/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+ln -s $CHECKZONE named-compilezone
+
+./named-compilezone -D -F raw -o good1.db.raw example \
+ zones/good1.db > /dev/null 2>&1
+
+copy_setports zones/bad-tsig.db.in zones/bad-tsig.db
diff --git a/bin/tests/system/checkzone/tests.sh b/bin/tests/system/checkzone/tests.sh
new file mode 100644
index 0000000..169e411
--- /dev/null
+++ b/bin/tests/system/checkzone/tests.sh
@@ -0,0 +1,214 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=1
+
+for db in zones/good*.db
+do
+ echo_i "checking $db ($n)"
+ ret=0
+ case $db in
+ zones/good-gc-msdcs.db|zones/good-spf-exception.db)
+ $CHECKZONE -k fail -i local example $db > test.out.$n 2>&1 || ret=1
+ ;;
+ zones/good-dns-sd-reverse.db)
+ $CHECKZONE -k fail -i local 0.0.0.0.in-addr.arpa $db > test.out.$n 2>&1 || ret=1
+ ;;
+ *)
+ $CHECKZONE -i local example $db > test.out.$n 2>&1 || ret=1
+ ;;
+ esac
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+done
+
+for db in zones/bad*.db
+do
+ echo_i "checking $db ($n)"
+ ret=0 v=0
+ case $db in
+ zones/bad-dns-sd-reverse.db|zones/bad-svcb-servername.db)
+ $CHECKZONE -k fail -i local 0.0.0.0.in-addr.arpa $db > test.out.$n 2>&1 || v=$?
+ ;;
+ *)
+ $CHECKZONE -i local example $db > test.out.$n 2>&1 || v=$?
+ ;;
+ esac
+ test $v = 1 || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+done
+
+echo_i "checking with journal file ($n)"
+ret=0
+$CHECKZONE -D -o test.orig.db test zones/test1.db > /dev/null 2>&1 || ret=1
+$CHECKZONE -D -o test.changed.db test zones/test2.db > /dev/null 2>&1 || ret=1
+$MAKEJOURNAL test test.orig.db test.changed.db test.orig.db.jnl 2>&1 || ret=1
+jlines=$($JOURNALPRINT test.orig.db.jnl | wc -l)
+[ $jlines = 3 ] || ret=1
+$CHECKZONE -D -j -o test.out1.db test test.orig.db > /dev/null 2>&1 || ret=1
+cmp -s test.changed.db test.out1.db || ret=1
+mv -f test.orig.db.jnl test.journal
+$CHECKZONE -D -J test.journal -o test.out2.db test test.orig.db > /dev/null 2>&1 || ret=1
+cmp -s test.changed.db test.out2.db || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking with spf warnings ($n)"
+ret=0
+$CHECKZONE example zones/spf.db > test.out1.$n 2>&1 || ret=1
+$CHECKZONE -T ignore example zones/spf.db > test.out2.$n 2>&1 || ret=1
+grep "'x.example' found type SPF" test.out1.$n > /dev/null && ret=1
+grep "'y.example' found type SPF" test.out1.$n > /dev/null || ret=1
+grep "'example' found type SPF" test.out1.$n > /dev/null && ret=1
+grep "'x.example' found type SPF" test.out2.$n > /dev/null && ret=1
+grep "'y.example' found type SPF" test.out2.$n > /dev/null && ret=1
+grep "'example' found type SPF" test.out2.$n > /dev/null && ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking with max ttl (text) ($n)"
+ret=0
+$CHECKZONE -l 300 example zones/good1.db > test.out1.$n 2>&1 && ret=1
+$CHECKZONE -l 600 example zones/good1.db > test.out2.$n 2>&1 || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking with max ttl (raw) ($n)"
+ret=0
+$CHECKZONE -f raw -l 300 example good1.db.raw > test.out1.$n 2>&1 && ret=1
+$CHECKZONE -f raw -l 600 example good1.db.raw > test.out2.$n 2>&1 || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking for no 'inherited owner' warning on '\$INCLUDE file' with no new \$ORIGIN ($n)"
+ret=0
+$CHECKZONE example zones/nowarn.inherited.owner.db > test.out1.$n 2>&1 || ret=1
+grep "inherited.owner" test.out1.$n > /dev/null && ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking for 'inherited owner' warning on '\$ORIGIN + \$INCLUDE file' ($n)"
+ret=0
+$CHECKZONE example zones/warn.inherit.origin.db > test.out1.$n 2>&1 || ret=1
+grep "inherited.owner" test.out1.$n > /dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking for 'inherited owner' warning on '\$INCLUDE file origin' ($n)"
+ret=0
+$CHECKZONE example zones/warn.inherited.owner.db > test.out1.$n 2>&1 || ret=1
+grep "inherited.owner" test.out1.$n > /dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking that raw zone with bad class is handled ($n)"
+ret=0
+$CHECKZONE -f raw example zones/bad-badclass.raw > test.out.$n 2>&1 && ret=1
+grep "failed: bad class" test.out.$n >/dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking that expirations that loop using serial arithmetic are handled ($n)"
+ret=0
+q=-q
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking that nameserver below DNAME is reported even with occulted address record present ($n)"
+ret=0
+$CHECKZONE example.com zones/ns-address-below-dname.db > test.out.$n 2>&1 && ret=1
+grep "is below a DNAME" test.out.$n >/dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking that delegating nameserver below DNAME is reported even with occulted address record present ($n)"
+ret=0
+$CHECKZONE example.com zones/delegating-ns-address-below-dname.db > test.out.$n 2>&1 || ret=1
+grep "is below a DNAME" test.out.$n >/dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that named-compilezone works when reading input from stdin ($n)"
+ret=0
+# Step 1: take raw input from stdin and convert it to text/relative format.
+# Last argument "-" is optional, but it says more explicitly that we're reading from stdin.
+cat zones/zone1.db | ./named-compilezone -f text -F text -s relative \
+ -o zones/zone1_stdin.txt zone1.com - > /dev/null || ret=1
+status=$((status+ret))
+
+ret=0
+# Step 2: take raw input from file and convert it to text format.
+./named-compilezone -f text -F text -s relative -o zones/zone1_file.txt \
+ zone1.com zones/zone1.db > /dev/null || ret=1
+status=$((status+ret))
+
+ret=0
+# Step 3: Ensure that output conversion from stdin is the same as the output conversion from a file.
+diff zones/zone1_file.txt zones/zone1_stdin.txt >/dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "checking integer overflow is prevented in \$GENERATE ($n)"
+$CHECKZONE -D example.com zones/generate-overflow.db > test.out.$n 2>&1 || ret=1
+lines=$(grep -c CNAME test.out.$n)
+echo $lines
+[ "$lines" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/checkzone/tests_sh_checkzone.py b/bin/tests/system/checkzone/tests_sh_checkzone.py
new file mode 100644
index 0000000..87613cb
--- /dev/null
+++ b/bin/tests/system/checkzone/tests_sh_checkzone.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_checkzone(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/checkzone/zones/.gitattributes b/bin/tests/system/checkzone/zones/.gitattributes
new file mode 100644
index 0000000..a1b3cec
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/.gitattributes
@@ -0,0 +1 @@
+*.raw -text
diff --git a/bin/tests/system/checkzone/zones/bad-badclass.raw b/bin/tests/system/checkzone/zones/bad-badclass.raw
new file mode 100644
index 0000000..d8f1bf7
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-badclass.raw
Binary files differ
diff --git a/bin/tests/system/checkzone/zones/bad-caa-rr.db b/bin/tests/system/checkzone/zones/bad-caa-rr.db
new file mode 100644
index 0000000..fb7b861
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-caa-rr.db
Binary files differ
diff --git a/bin/tests/system/checkzone/zones/bad-cdnskey.db b/bin/tests/system/checkzone/zones/bad-cdnskey.db
new file mode 100644
index 0000000..d109423
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-cdnskey.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+example. 0 SOA . . 0 0 0 0 0
+example. 0 NS .
+example. 0 DNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc=
+example. 0 CDNSKEY 257 3 14 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTXXXX WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc=
diff --git a/bin/tests/system/checkzone/zones/bad-cds.db b/bin/tests/system/checkzone/zones/bad-cds.db
new file mode 100644
index 0000000..2ce4a0d
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-cds.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+example. 0 SOA . . 0 0 0 0 0
+example. 0 NS .
+example. 0 DNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc=
+example. 0 CDS 14364 14 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0B
diff --git a/bin/tests/system/checkzone/zones/bad-dhcid.db b/bin/tests/system/checkzone/zones/bad-dhcid.db
new file mode 100644
index 0000000..df36eb7
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-dhcid.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 DHCID
+@ 3600 DHCID
diff --git a/bin/tests/system/checkzone/zones/bad-dns-sd-reverse.db b/bin/tests/system/checkzone/zones/bad-dns-sd-reverse.db
new file mode 100644
index 0000000..c766c8f
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-dns-sd-reverse.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA . . 0 0 0 0 0
+@ IN NS .
+;
+; The following are *not* Service Discovery Prefixes from RFC 6763 and the
+; PTR check-names rules for IN-ADDR.ARPA and IP6.ARPA do still apply.
+;
+b._fail._udp IN PTR !@#3.
+db._wrong._udp IN PTR !@#3.
+lb._dns-sd._tcp IN PTR !@#3.
diff --git a/bin/tests/system/checkzone/zones/bad-ds.db b/bin/tests/system/checkzone/zones/bad-ds.db
new file mode 100644
index 0000000..9363cb0
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-ds.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+example. 0 SOA . . 0 0 0 0 0
+example. 0 NS .
+example. 0 DNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc=
+example. 0 DS 14364 10 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C
diff --git a/bin/tests/system/checkzone/zones/bad-eid.db b/bin/tests/system/checkzone/zones/bad-eid.db
new file mode 100644
index 0000000..ba568ef
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-eid.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ EID
+@ EID
diff --git a/bin/tests/system/checkzone/zones/bad-generate-garbage.db b/bin/tests/system/checkzone/zones/bad-generate-garbage.db
new file mode 100644
index 0000000..0d66e75
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-generate-garbage.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+$GENERATE 0-7 host$ A 1.2.3.${1,0,dgarbagegarbage}
diff --git a/bin/tests/system/checkzone/zones/bad-generate-missing-brace.db b/bin/tests/system/checkzone/zones/bad-generate-missing-brace.db
new file mode 100644
index 0000000..314583e
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-generate-missing-brace.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+$GENERATE 0-7 host$ A 1.2.3.${1000
diff --git a/bin/tests/system/checkzone/zones/bad-generate-range.db b/bin/tests/system/checkzone/zones/bad-generate-range.db
new file mode 100644
index 0000000..62a9e15
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-generate-range.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+; 2147483647 + 1 overflows what can be represented in an 'int'
+$GENERATE 1-1 host$ TXT foo${2147483647}
diff --git a/bin/tests/system/checkzone/zones/bad-generate-tkey.db b/bin/tests/system/checkzone/zones/bad-generate-tkey.db
new file mode 100644
index 0000000..8c05e51
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-generate-tkey.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+$GENERATE 0-7 tkey$ TKEY "invalid.algorithm. 1516055980 1516140801 1 0 16 gRof8D2BFKvl/vrr9Lmnjw== 16 gRof8D2BFKvl/vrr9Lmnjw=="
diff --git a/bin/tests/system/checkzone/zones/bad-nimloc.db b/bin/tests/system/checkzone/zones/bad-nimloc.db
new file mode 100644
index 0000000..56d04c6
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-nimloc.db
@@ -0,0 +1,10 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership. \ No newline at end of file
diff --git a/bin/tests/system/checkzone/zones/bad-nsap-empty.db b/bin/tests/system/checkzone/zones/bad-nsap-empty.db
new file mode 100644
index 0000000..fb8fdd0
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-nsap-empty.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+; NSAP with an odd number of hex digits
+example NSAP 0x47000580005a0000000001e133ffffff000161000
diff --git a/bin/tests/system/checkzone/zones/bad-nsap-odd-nibble.db b/bin/tests/system/checkzone/zones/bad-nsap-odd-nibble.db
new file mode 100644
index 0000000..d287648
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-nsap-odd-nibble.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+; empty NSAP address
+example NSAP 0x
diff --git a/bin/tests/system/checkzone/zones/bad-nsec3-padded.db b/bin/tests/system/checkzone/zones/bad-nsec3-padded.db
new file mode 100644
index 0000000..8212bc4
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-nsec3-padded.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+; The following NSEC3 RR is invalid as the Next Hashed Owner Name field
+; is padded. See RFC 5155.
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom NSEC3 1 1 12 aabbccdd (
+ CPNMU=== MX DNSKEY NS
+ SOA NSEC3PARAM RRSIG )
diff --git a/bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db b/bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db
new file mode 100644
index 0000000..bf3c5ab
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+; The following NSEC3 RR owner is invalid as the owner name is padded.
+CPNMU=== NSEC3 2 1 12 aabbccdd ( CPNMU MX DNSKEY NS
+ SOA NSEC3PARAM RRSIG )
diff --git a/bin/tests/system/checkzone/zones/bad-svcb-mandatory.db b/bin/tests/system/checkzone/zones/bad-svcb-mandatory.db
new file mode 100644
index 0000000..368f0ca
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-svcb-mandatory.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+svcb SVCB 0 . mandatory=alpn
diff --git a/bin/tests/system/checkzone/zones/bad-svcb-servername.db b/bin/tests/system/checkzone/zones/bad-svcb-servername.db
new file mode 100644
index 0000000..61751a0
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-svcb-servername.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+svcb SVCB 1 _underscore.example. port=60 alpn=h3 ech="ZWFzdGVyIGVnZyE="
diff --git a/bin/tests/system/checkzone/zones/bad-svcb.db b/bin/tests/system/checkzone/zones/bad-svcb.db
new file mode 100644
index 0000000..ad710bf
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-svcb.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+svcb SVCB 0 . unknown=wha
diff --git a/bin/tests/system/checkzone/zones/bad-tkey.db b/bin/tests/system/checkzone/zones/bad-tkey.db
new file mode 100644
index 0000000..a030074
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-tkey.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+tkey TKEY invalid.algorithm. 1516055980 1516140801 1 0 16 gRof8D2BFKvl/vrr9Lmnjw== 16 gRof8D2BFKvl/vrr9Lmnjw==
diff --git a/bin/tests/system/checkzone/zones/bad-tsig.db.in b/bin/tests/system/checkzone/zones/bad-tsig.db.in
new file mode 100644
index 0000000..daef06c
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-tsig.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+tsig TSIG @DEFAULT_HMAC@ 1516135665 300 20 thBt8DheAD7qpqSFTiGK999sxGg= 54994 NOERROR 0
diff --git a/bin/tests/system/checkzone/zones/bad-unspec.db b/bin/tests/system/checkzone/zones/bad-unspec.db
new file mode 100644
index 0000000..e5abefe
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad-unspec.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+example IN TYPE103 ^# 1 00
diff --git a/bin/tests/system/checkzone/zones/bad1.db b/bin/tests/system/checkzone/zones/bad1.db
new file mode 100644
index 0000000..05ab829
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad1.db
Binary files differ
diff --git a/bin/tests/system/checkzone/zones/bad2.db b/bin/tests/system/checkzone/zones/bad2.db
new file mode 100644
index 0000000..38e82e6
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad2.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+; The following GENERATE directive contains two dashes in the range
+; which is a syntax error.
+$GENERATE 9--10 host$ 3600 A 192.0.2.$
diff --git a/bin/tests/system/checkzone/zones/bad3.db b/bin/tests/system/checkzone/zones/bad3.db
new file mode 100644
index 0000000..1391afe
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad3.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+;
+; A trailing '/' is not permitted.
+;
+$GENERATE 1-3/ $ A 1.2.3.$
diff --git a/bin/tests/system/checkzone/zones/bad4.db b/bin/tests/system/checkzone/zones/bad4.db
new file mode 100644
index 0000000..99def7a
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/bad4.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+;
+; A step of zero is not permitted.
+;
+$GENERATE 1-3/0 $ A 1.2.3.$
diff --git a/bin/tests/system/checkzone/zones/badttl.db b/bin/tests/system/checkzone/zones/badttl.db
new file mode 100644
index 0000000..95cd422
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/badttl.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+ns-and-dname NS ns.ns-and-dname
+ DNAME example.com.
+ns.ns-and-dname A 203.178.141.207
diff --git a/bin/tests/system/checkzone/zones/crashzone.db b/bin/tests/system/checkzone/zones/crashzone.db
new file mode 100644
index 0000000..2a62e2a
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/crashzone.db
@@ -0,0 +1,62 @@
+; 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 https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+dyn.example.net. 7200 IN SOA ns1.example.net. hostmaster.example.net. (
+ 6 ; serial
+ 43200 ; refresh (12 hours)
+ 1800 ; retry (30 minutes)
+ 1209600 ; expire (2 weeks)
+ 7200 ; minimum (2 hours)
+ )
+ 7200 RRSIG SOA 7 3 7200 2010 20100225214229 30323 dyn.example.net. MuyI
+ 7200 NS ns1.example.net.
+ 7200 NS ns2.example.net.
+ 3600 RRSIG DNSKEY 7 3 3600 20100227180048 (
+ 20100221180048 52935 dyn.example.net.
+ MuyIUCa3XlttWuSnaQegQnRgTrTsx0Mj4EGI
+ fwtZs2H3L079Y/brqMvtlIGxtlr9meLg43oo
+ jX1w48ilerzf1PwYhtVpFefZTgmClK0h2ej4
+ Ho9Qh4/6snesVj06kWsQDkhuVs58zHmhRtEy
+ P4YlqP/R1CAk166RhwSmGuSx1O8= )
+ 0 NSEC3PARAM 1 0 10 76931F
+ns1.dyn.example.net. 7200 IN A 1.0.0.5
+ 7200 AAAA 2001:db8::53
+ 7200 RRSIG AAAA 7 4 7200 20100227180048 (
+ 20100221180048 30323 dyn.example.net.
+ dk1DfG0y9qjCi3VD4e9B1NGKWEig7q8hFdaR
+ 3hElCIzGlflvgHRiE7iTJxDMB+kTA0by4BMZ
+ yssUuXP2FMlB2g== )
+ns2.dyn.example.net. 7200 IN A 1.2.0.6
+y.dyn.example.net. 7200 IN A 1.2.3.5
+z.dyn.example.net. 7200 IN A 1.2.3.6
+A54T6DKFVU4QCKFFNJ0KEU0FH0I4OJSN.dyn.example.net. 7200 IN NSEC3 1 0 10 76931F AJHVGTICN6K0VDA53GCHFMT219SRRQLM A RRSIG
+ò 7200 RRSIG NSEC3 7 4 7200 00100227180048 (
+ 20100221180048 30323 dyn.example.net.
+ 9BhZcQdLwRPU/Dz38uMis/nCcddyhKEm0Zb+
+ Mhh3V3OsGI202cebTaxbwVEbQQOeowpUmf8l
+ AmK/cNX7+IS2rw== )
+AJHVGTICN6K0VDA53GCHFMT219SRRQLM.dyn.example.net. 7200 IN NSEC3 1 0 10 76931F FQ7RBG86KRMACA1NAAKP2KQRQALBA0C7 A RRSIG
+FQ7RBG86KRMACA1NAAKP2KQRQALBA0C7.dyn.example.net. 7200 RRSIG NSEC3 7 4 7200 20100227180048 (
+ 20100221180048 30323 dyn.example.net.
+ 577WZnTQemStx+diON9rEGXAGnU7C0KLjrFL
+ VyhocnBnNtxJS8eRMSWvb9XuYCMNhYKOurtt
+ Ar4qh4VW1+unmA== )
+I7A7A184GGMI35K1E3IR650LKO7NOB5R.dyn.example.net. 7200 IN NSEC3 1 0 10 76931F IMQ912BREQP1POLAH3RMONG;UED541AS A RRSIG
+IMQ912BREQP1POLAH3RMONG3UED541AS.dyn.example.net. 7200 IN NSEC3 1 0 10 76931F S3USV4M1HLVJ8F88EDSG8N9PVQRQ20N7 A RRSIG
+ 7200 RRSIG NSEC3 7 4 7200 20100227180048 (
+ 20100221180048 30323 dyn.example.net.
+ smsg35snQ9PpeG2r8ZGxBl44pwSReh/1rIil
+ u/n8aa5nKbBpkqtbcc7q1OpUgb1Q7+Tl/wes
+ kB6bJA== )
+S3USV4M1HLVJ8F88EDSG8N9PVQRQ20N7.dyn.example.net. 7200 RRSIG NSEC3 7 4 7200 20100227180048 (
+ 20100221180048 30323 dyn.example.net.
+ XalRIESpdeVK1aNbwu9ym2SpK981Y127rKua
+ xsoals0Zn2tTjF9wpOYVGVOto3FcWBbyKD1g
+ 69BTRlv634UIOw== )
+T320G5LC07QE1BLR074KORIJTG9DPTI9.dyn.example.net. 7200 IN NSEC3 1 0 10 76931F A54T6DKFVU4QCAFFNJ0KEU0FH0I4OJSN NS SOA RRSIG DNSKEY NSEC3PARAM
diff --git a/bin/tests/system/checkzone/zones/delegating-ns-address-below-dname.db b/bin/tests/system/checkzone/zones/delegating-ns-address-below-dname.db
new file mode 100644
index 0000000..78c1029
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/delegating-ns-address-below-dname.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+example.com. SOA marka.isc.org. a.root.servers.nil. (
+ 2026 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+example.com. NS ns.example.com.
+ns.example.com. A 192.168.0.2
+sub.example.com. NS ns.sub2.example.com.
+sub2.example.com. DNAME example.net.
+ns.sub2.example.com. A 192.168.0.2
diff --git a/bin/tests/system/checkzone/zones/generate-overflow.db b/bin/tests/system/checkzone/zones/generate-overflow.db
new file mode 100644
index 0000000..c16b517
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/generate-overflow.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+$GENERATE 19-28/2147483645 $ CNAME x
diff --git a/bin/tests/system/checkzone/zones/good-cdnskey.db b/bin/tests/system/checkzone/zones/good-cdnskey.db
new file mode 100644
index 0000000..7892f13
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-cdnskey.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+example. 0 SOA . . 0 0 0 0 0
+example. 0 NS .
+example. 0 DNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc=
+example. 0 CDNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc=
diff --git a/bin/tests/system/checkzone/zones/good-cds-unsigned.db b/bin/tests/system/checkzone/zones/good-cds-unsigned.db
new file mode 100644
index 0000000..9b1737d
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-cds-unsigned.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+example. 0 SOA . . 0 0 0 0 0
+example. 0 NS .
+example. 0 CDS 0 0 0 00
+example. 0 CDNSKEY 0 3 0 AA==
+
diff --git a/bin/tests/system/checkzone/zones/good-cds.db b/bin/tests/system/checkzone/zones/good-cds.db
new file mode 100644
index 0000000..9200657
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-cds.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+example. 0 SOA . . 0 0 0 0 0
+example. 0 NS .
+example. 0 DNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc=
+example. 0 CDS 14364 10 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C
diff --git a/bin/tests/system/checkzone/zones/good-dns-sd-reverse.db b/bin/tests/system/checkzone/zones/good-dns-sd-reverse.db
new file mode 100644
index 0000000..fffd27b
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-dns-sd-reverse.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA . . 0 0 0 0 0
+@ IN NS .
+;
+; The following are Service Discovery Prefixes from RFC 6763 and the
+; PTR check-names rules for IN-ADDR.ARPA and IP6.ARPA do not apply.
+;
+b._dns-sd._udp IN PTR !@#3.
+db._dns-sd._udp IN PTR !@#3.
+r._dns-sd._udp IN PTR !@#3.
+dr._dns-sd._udp IN PTR !@#3.
+lb._dns-sd._udp IN PTR !@#3.
diff --git a/bin/tests/system/checkzone/zones/good-gc-msdcs.db b/bin/tests/system/checkzone/zones/good-gc-msdcs.db
new file mode 100644
index 0000000..defd550
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-gc-msdcs.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+gc._msdcs A 192.0.2.2
diff --git a/bin/tests/system/checkzone/zones/good-generate-modifier.db b/bin/tests/system/checkzone/zones/good-generate-modifier.db
new file mode 100644
index 0000000..3c811d6
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-generate-modifier.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+$GENERATE 0-7 host$ A 1.2.3.${1,0,d}
+$GENERATE 8-9 host$ A 1.2.3.${1,0}
+$GENERATE 10-11 host$ A 1.2.3.${1}
+$GENERATE 1024-1026 ${0,3,n} AAAA 2001:db8::${0,4,x}
diff --git a/bin/tests/system/checkzone/zones/good-nsap.db b/bin/tests/system/checkzone/zones/good-nsap.db
new file mode 100644
index 0000000..8ad9ee0
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-nsap.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+; empty NSAP address
+example NSAP 0x47.0005.80.005a00.0000....0001.e133.ffffff000162.00
diff --git a/bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db b/bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db
new file mode 100644
index 0000000..5bd378c
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+; a hash that isn't a multiple of 8 characters
+CPNMU NSEC3 2 1 12 aabbccdd ( CPNMU MX DNSKEY NS
+ SOA NSEC3PARAM RRSIG )
diff --git a/bin/tests/system/checkzone/zones/good-occulted-ns-by-dname.db b/bin/tests/system/checkzone/zones/good-occulted-ns-by-dname.db
new file mode 100644
index 0000000..80fc4a6
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-occulted-ns-by-dname.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+example. SOA marka.isc.org. a.root.servers.nil. (
+ 2026 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+example. DNAME example.net. ; only the apex record exist
+example. NS ns.example.net. ; out of zone
+foo.example. NS exavider.example. ; no "address" records
diff --git a/bin/tests/system/checkzone/zones/good-occulted-ns-by-ns.db b/bin/tests/system/checkzone/zones/good-occulted-ns-by-ns.db
new file mode 100644
index 0000000..38913b9
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-occulted-ns-by-ns.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+example. SOA marka.isc.org. a.root.servers.nil. (
+ 2026 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+example. NS ns.example.net. ; out of zone
+foo.example. NS ns.example.net. ; out of zone
+bar.foo.example. NS x.foo.example. ; no address records
diff --git a/bin/tests/system/checkzone/zones/good-spf-exception.db b/bin/tests/system/checkzone/zones/good-spf-exception.db
new file mode 100644
index 0000000..212bfbc
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-spf-exception.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+a._spf A 192.0.2.2
+a._spf_rate A 192.0.2.2
+a._spf_verify A 192.0.2.2
diff --git a/bin/tests/system/checkzone/zones/good-svcb.db b/bin/tests/system/checkzone/zones/good-svcb.db
new file mode 100644
index 0000000..df868f3
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good-svcb.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+svcb0 SVCB 0 example.net.
+svcb1 SVCB 1 . port=60 alpn=h3 ech="ZWFzdGVyIGVnZyE="
+svcb2 SVCB 2 . no-default-alpn alpn=alpn
+svcb3 SVCB 3 . ipv4hint="10.10.10.10"
+svcb4 SVCB 4 . ipv6hint="feed:a::bee"
+svcb5 SVCB 5 . key9999="something"
+svcb6 SVCB 6 . mandatory=port,alpn port=60 alpn=h3
+svcb7 SVCB 7 . mandatory=port,alpn port=60 alpn=h1,h3
+svcb8 SVCB 8 . mandatory=port,alpn port=60 alpn="h1\\,h2,h3"
+svcb9 SVCB 0 44._svbc.example.net.
+svcb10 SVCB 7 . alpn="h2,h3" dohpath=/{?dns}
diff --git a/bin/tests/system/checkzone/zones/good1.db b/bin/tests/system/checkzone/zones/good1.db
new file mode 100644
index 0000000..59eaa54
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/good1.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2011012708 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+ns-and-dname NS ns.ns-and-dname
+ DNAME example.com.
+ns.ns-and-dname A 203.178.141.207
diff --git a/bin/tests/system/checkzone/zones/inherit.db b/bin/tests/system/checkzone/zones/inherit.db
new file mode 100644
index 0000000..e075d41
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/inherit.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+ NS .
diff --git a/bin/tests/system/checkzone/zones/nowarn.inherited.owner.db b/bin/tests/system/checkzone/zones/nowarn.inherited.owner.db
new file mode 100644
index 0000000..db26217
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/nowarn.inherited.owner.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 IN SOA . . 0 0 0 0 0
+$INCLUDE "zones/inherit.db"
diff --git a/bin/tests/system/checkzone/zones/ns-address-below-dname.db b/bin/tests/system/checkzone/zones/ns-address-below-dname.db
new file mode 100644
index 0000000..e15ad5c
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/ns-address-below-dname.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+example.com. SOA marka.isc.org. a.root.servers.nil. (
+ 2026 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+example.com. DNAME example.net.
+example.com. NS ns.example.com
+ns.example.com. A 192.168.0.2
diff --git a/bin/tests/system/checkzone/zones/spf.db b/bin/tests/system/checkzone/zones/spf.db
new file mode 100644
index 0000000..9527b1b
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/spf.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 IN SOA . . 0 0 0 0 0
+@ 0 IN NS .
+@ 0 IN TXT "v=spf1 -all"
+@ 0 IN SPF "v=spf1 -all"
+x 0 IN TXT "v=spf1"
+y 0 IN SPF "v=spf1"
+y 0 IN TXT "a non spf record"
diff --git a/bin/tests/system/checkzone/zones/test1.db b/bin/tests/system/checkzone/zones/test1.db
new file mode 100644
index 0000000..55669d7
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/test1.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2012010901 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+addr1 A 10.53.0.1
diff --git a/bin/tests/system/checkzone/zones/test2.db b/bin/tests/system/checkzone/zones/test2.db
new file mode 100644
index 0000000..0cb1184
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/test2.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2012010902 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+addr1 A 10.53.0.1
+addr2 A 10.53.0.2
diff --git a/bin/tests/system/checkzone/zones/warn.inherit.origin.db b/bin/tests/system/checkzone/zones/warn.inherit.origin.db
new file mode 100644
index 0000000..a348a8f
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/warn.inherit.origin.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 IN SOA . . 0 0 0 0 0
+$ORIGIN @
+$INCLUDE "zones/inherit.db"
diff --git a/bin/tests/system/checkzone/zones/warn.inherited.owner.db b/bin/tests/system/checkzone/zones/warn.inherited.owner.db
new file mode 100644
index 0000000..dbbd9d1
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/warn.inherited.owner.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 IN SOA . . 0 0 0 0 0
+$INCLUDE "zones/inherit.db" @
diff --git a/bin/tests/system/checkzone/zones/zone1.db b/bin/tests/system/checkzone/zones/zone1.db
new file mode 100644
index 0000000..c2f395d
--- /dev/null
+++ b/bin/tests/system/checkzone/zones/zone1.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+zone1.com. 86400 IN SOA dns1.zone1.com. hostmaster.zone1.com. 2001062501 21600 3600 604800 86400
+zone1.com. 86400 IN NS dns1.zone1.com.
+zone1.com. 86400 IN NS dns2.zone1.com.
+zone1.com. 86400 IN A 10.53.0.1
+zone1.com. 86400 IN MX 10 mail1.zone1.com.
+zone1.com. 86400 IN MX 20 mail2.zone1.com.
+dns1.zone1.com. 86400 IN A 10.53.0.1
+dns2.zone1.com. 86400 IN A 10.53.0.2
+mail1.zone1.com. 86400 IN A 10.53.0.1
+mail2.zone1.com. 86400 IN A 10.53.0.2
diff --git a/bin/tests/system/ckdnsrps.sh b/bin/tests/system/ckdnsrps.sh
new file mode 100644
index 0000000..afc405d
--- /dev/null
+++ b/bin/tests/system/ckdnsrps.sh
@@ -0,0 +1,167 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# Say on stdout whether to test DNSRPS
+# and create dnsrps.conf and dnsrps-secondary.conf
+# Note that dnsrps.conf and dnsrps-secondary.conf are included in named.conf
+# and differ from dnsrpz.conf which is used by dnsrpzd.
+
+
+. ../conf.sh
+
+DNSRPS_CMD=../rpz/dnsrps
+
+AS_NS=
+TEST_DNSRPS=
+MCONF=dnsrps.conf
+SCONF=dnsrps-secondary.conf
+USAGE="$0: [-xAD] [-M dnsrps.conf] [-S dnsrps-secondary.conf]"
+while getopts "xADM:S:" c; do
+ case $c in
+ x) set -x; DEBUG=-x;;
+ A) AS_NS=yes;;
+ D) TEST_DNSRPS=yes;;
+ M) MCONF="$OPTARG";;
+ S) SCONF="$OPTARG";;
+ *) echo "$USAGE" 1>&2; exit 1;;
+ esac
+done
+shift $(expr $OPTIND - 1 || true)
+if [ "$#" -ne 0 ]; then
+ echo "$USAGE" 1>&2
+ exit 1
+fi
+
+# erase any existing conf files
+cat /dev/null > $MCONF
+cat /dev/null > $SCONF
+
+add_conf () {
+ echo "$*" >>$MCONF
+ echo "$*" >>$SCONF
+}
+
+if ! $FEATURETEST --enable-dnsrps; then
+ if [ -n "$TEST_DNSRPS" ]; then
+ add_conf "## DNSRPS disabled at compile time"
+ fi
+ add_conf "#skip"
+ exit 0
+fi
+
+if [ -z "$TEST_DNSRPS" ]; then
+ add_conf "## testing with native RPZ"
+ add_conf '#skip'
+ exit 0
+else
+ add_conf "## testing with DNSRPS"
+fi
+
+if [ ! -x "$DNSRPS_CMD" ]; then
+ add_conf "## make $DNSRPS_CMD to test DNSRPS"
+ add_conf '#skip'
+ exit 0
+fi
+
+if $DNSRPS_CMD -a >/dev/null; then :
+else
+ add_conf "## DNSRPS provider library is not available"
+ add_conf '#skip'
+ exit 0
+fi
+
+CMN=" dnsrps-options { dnsrpzd-conf ../dnsrpzd.conf
+ dnsrpzd-sock ../dnsrpzd.sock
+ dnsrpzd-rpzf ../dnsrpzd.rpzf
+ dnsrpzd-args '-dddd -L stdout'
+ log-level 3"
+
+PRIMARY="$CMN"
+if [ -n "$AS_NS" ]; then
+ PRIMARY="$PRIMARY
+ qname-as-ns yes
+ ip-as-ns yes"
+fi
+
+# write dnsrps settings for primary resolver
+cat <<EOF >>$MCONF
+$PRIMARY };
+EOF
+
+# write dnsrps settings for resolvers that should not start dnsrpzd
+cat <<EOF >>$SCONF
+$CMN
+ dnsrpzd '' }; # do not start dnsrpzd
+EOF
+
+
+# DNSRPS is available.
+# The test should fail if the license is bad.
+add_conf "dnsrps-enable yes;"
+
+# Use alt-dnsrpzd-license.conf if it exists
+CUR_L=dnsrpzd-license-cur.conf
+ALT_L=alt-dnsrpzd-license.conf
+# try ../rpz/alt-dnsrpzd-license.conf if alt-dnsrpzd-license.conf does not exist
+[ -s $ALT_L ] || ALT_L=../rpz/alt-dnsrpzd-license.conf
+if [ -s $ALT_L ]; then
+ SRC_L=$ALT_L
+ USE_ALT=
+else
+ SRC_L=../rpz/dnsrpzd-license.conf
+ USE_ALT="## consider installing alt-dnsrpzd-license.conf"
+fi
+cp $SRC_L $CUR_L
+
+# parse $CUR_L for the license zone name, primary IP addresses, and optional
+# transfer-source IP addresses
+eval `sed -n -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'\
+ -e 's/.*zone *\([-a-z0-9]*.license.fastrpz.com\).*/NAME=\1/p' \
+ -e 's/.*farsight_fastrpz_license *\([0-9.]*\);.*/IPV4=\1/p' \
+ -e 's/.*farsight_fastrpz_license *\([0-9a-f:]*\);.*/IPV6=\1/p' \
+ -e 's/.*transfer-source *\([0-9.]*\);.*/TS4=-b\1/p' \
+ -e 's/.*transfer-source *\([0-9a-f:]*\);.*/TS6=-b\1/p' \
+ -e 's/.*transfer-source-v6 *\([0-9a-f:]*\);.*/TS6=-b\1/p' \
+ $CUR_L`
+if [ -z "$NAME" ]; then
+ add_conf "## no DNSRPS tests; no license domain name in $SRC_L"
+ add_conf '#fail'
+ exit 0
+fi
+if [ -z "$IPV4" ]; then
+ IPV4=license1.fastrpz.com
+ TS4=
+fi
+if [ -z "$IPV6" ]; then
+ IPV6=license1.fastrpz.com
+ TS6=
+fi
+
+# This TSIG key is common and NOT a secret
+KEY='hmac-sha256:farsight_fastrpz_license:f405d02b4c8af54855fcebc1'
+
+# Try IPv4 and then IPv6 to deal with IPv6 tunnel and connectivity problems
+if `$DIG -4 -t axfr -y$KEY $TS4 $NAME @$IPV4 \
+ | grep -i "^$NAME.*TXT" >/dev/null`; then
+ exit 0
+fi
+if `$DIG -6 -t axfr -y$KEY $TS6 $NAME @$IPV6 \
+ | grep -i "^$NAME.*TXT" >/dev/null`; then
+ exit 0
+fi
+
+add_conf "## DNSRPS lacks a valid license via $SRC_L"
+[ -z "$USE_ALT" ] || add_conf "$USE_ALT"
+add_conf '#fail'
diff --git a/bin/tests/system/cleanall.sh b/bin/tests/system/cleanall.sh
new file mode 100644
index 0000000..79a8434
--- /dev/null
+++ b/bin/tests/system/cleanall.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after system tests.
+#
+
+. ./conf.sh
+
+
+find . -type f \( \
+ -name '*~' -o -name 'core' -o -name '*.core' \
+ -o -name '*.log' -o -name '*.pid' -o -name '*.keyset' \
+ -o -name named.run -o -name ans.run \
+ -o -name '*-valgrind-*.log' \) -print | xargs rm -f
+
+status=0
+
+rm -f ../random.data
+
+for d in $SUBDIRS
+do
+ test ! -f $d/clean.sh || ( cd $d && $SHELL clean.sh )
+ rm -f test.output.$d
+ test -d $d && find $d -type d -exec rmdir '{}' \; 2> /dev/null
+done
diff --git a/bin/tests/system/common/controls.conf.in b/bin/tests/system/common/controls.conf.in
new file mode 100644
index 0000000..1db9286
--- /dev/null
+++ b/bin/tests/system/common/controls.conf.in
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
diff --git a/bin/tests/system/common/rndc.conf b/bin/tests/system/common/rndc.conf
new file mode 100644
index 0000000..b887ec3
--- /dev/null
+++ b/bin/tests/system/common/rndc.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ default-key "rndc_key";
+};
+
+key rndc_key {
+ algorithm hmac-sha256;
+ secret "1234abcd8765";
+};
diff --git a/bin/tests/system/common/rndc.key b/bin/tests/system/common/rndc.key
new file mode 100644
index 0000000..3ef41c3
--- /dev/null
+++ b/bin/tests/system/common/rndc.key
@@ -0,0 +1,15 @@
+/*
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
diff --git a/bin/tests/system/common/root.hint b/bin/tests/system/common/root.hint
new file mode 100644
index 0000000..e0f186c
--- /dev/null
+++ b/bin/tests/system/common/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.1
diff --git a/bin/tests/system/conf.sh.common b/bin/tests/system/conf.sh.common
new file mode 100644
index 0000000..90059dd
--- /dev/null
+++ b/bin/tests/system/conf.sh.common
@@ -0,0 +1,738 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+testsock6() {
+ if test -n "$PERL" && $PERL -e "use IO::Socket::INET6;" 2> /dev/null
+ then
+ $PERL "$TOP_SRCDIR/bin/tests/system/testsock6.pl" "$@"
+ else
+ false
+ fi
+}
+
+export LANG=C
+
+
+#
+# Common lists of system tests to run.
+#
+# The following tests are hard-coded to use ports 5300 and 9953. For
+# this reason, these must be run sequentially.
+#
+# Sequential tests that only run on unix/linux should be added to
+# SEQUENTIAL_UNIX in conf.sh.in
+#
+SEQUENTIAL_COMMON=""
+
+#
+# These tests can use ports assigned by the caller (other than 5300
+# and 9953). Because separate blocks of ports can be used for teach
+# test, these tests can be run in parallel.
+#
+# Parallel tests that only run on unix/linux should be added to
+# PARALLEL_UNIX in conf.sh.in;
+#
+# Note: some of the longer-running tests such as serve-stale and
+# rpzrecurse are scheduled first, in order to get more benefit from
+# parallelism.
+#
+PARALLEL_COMMON="
+rpzrecurse
+serve-stale
+dupsigs
+acl
+additional
+addzone
+allow-query
+auth
+autosign
+builtin
+cacheclean
+case
+catz
+cds
+checkconf
+checknames
+checkzone
+database
+digdelv
+dlz
+dns64
+dsdigest
+ecdsa
+eddsa
+ednscompliance
+emptyzones
+fetchlimit
+formerr
+forward
+geoip2
+glue
+idna
+include-multiplecfg
+inline
+integrity
+ixfr
+journal
+keepalive
+limits
+masterfile
+masterformat
+metadata
+mirror
+mkeys
+names
+notify
+nsec3
+nslookup
+nsupdate
+padding
+pending
+reclimit
+redirect
+resolver
+rndc
+rootkeysentinel
+rpz
+rrchecker
+rrl
+rrsetorder
+rsabigexponent
+runtime
+sfcache
+smartsign
+sortlist
+spf
+staticstub
+statistics
+statschannel
+stub
+synthfromdnssec
+tkey
+tools
+tsig
+tsiggss
+ttl
+unknown
+upforwd
+verify
+views
+wildcard
+xfer
+xferquota
+zero
+zonechecks"
+
+#
+# Set up color-coded test output
+#
+if [ ${SYSTEMTEST_FORCE_COLOR:-0} -eq 1 ] || test -t 1 && type tput > /dev/null 2>&1 && tput setaf 7 > /dev/null 2>&1 ; then
+ export COLOR_END=$(tput setaf 4) # blue
+ export COLOR_FAIL=$(tput setaf 1) # red
+ export COLOR_INFO=$(tput bold) # bold
+ export COLOR_NONE=$(tput sgr0)
+ export COLOR_PASS=$(tput setaf 2) # green
+ export COLOR_START=$(tput setaf 4) # blue
+ export COLOR_WARN=$(tput setaf 3) # yellow
+else
+ # set to empty strings so printf succeeds
+ export COLOR_END=''
+ export COLOR_FAIL=''
+ export COLOR_INFO=''
+ export COLOR_NONE=''
+ export COLOR_PASS=''
+ export COLOR_START=''
+ export COLOR_WARN=''
+fi
+
+export SYSTESTDIR="$(basename $PWD)"
+
+if type printf > /dev/null 2>&1
+then
+ echofail () {
+ printf "${COLOR_FAIL}%s${COLOR_NONE}\n" "$*"
+ }
+ echowarn () {
+ printf "${COLOR_WARN}%s${COLOR_NONE}\n" "$*"
+ }
+ echopass () {
+ printf "${COLOR_PASS}%s${COLOR_NONE}\n" "$*"
+ }
+ echoinfo () {
+ printf "${COLOR_INFO}%s${COLOR_NONE}\n" "$*"
+ }
+ echostart () {
+ printf "${COLOR_START}%s${COLOR_NONE}\n" "$*"
+ }
+ echoend () {
+ printf "${COLOR_END}%s${COLOR_NONE}\n" "$*"
+ }
+ echo_i() {
+ printf '%s\n' "$*" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR:$__LINE"
+ done
+ }
+
+ echo_ic() {
+ printf '%s\n' "$*" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR: $__LINE"
+ done
+ }
+
+ echo_d() {
+ printf '%s\n' "$*" | while IFS= read -r __LINE ; do
+ echoinfo "D:$SYSTESTDIR:$__LINE"
+ done
+ }
+else
+ echofail () {
+ echo "$*"
+ }
+ echowarn () {
+ echo "$*"
+ }
+ echopass () {
+ echo "$*"
+ }
+ echoinfo () {
+ echo "$*"
+ }
+ echostart () {
+ echo "$*"
+ }
+ echoend () {
+ echo "$*"
+ }
+
+ echo_i() {
+ echo "$@" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR:$__LINE"
+ done
+ }
+
+ echo_ic() {
+ echo "$@" | while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR: $__LINE"
+ done
+ }
+
+ echo_d() {
+ echo "$@" | while IFS= read -r __LINE ; do
+ echoinfo "D:$SYSTESTDIR:$__LINE"
+ done
+ }
+fi
+
+cat_i() {
+ while IFS= read -r __LINE ; do
+ echoinfo "I:$SYSTESTDIR:$__LINE"
+ done
+}
+
+cat_d() {
+ while IFS= read -r __LINE ; do
+ echoinfo "D:$SYSTESTDIR:$__LINE"
+ done
+}
+
+digcomp() {
+ { output=$($PERL $TOP_SRCDIR/bin/tests/system/digcomp.pl "$@"); result=$?; } || true
+ [ -n "$output" ] && { echo "digcomp failed:"; echo "$output"; } | cat_i
+ return $result
+}
+
+start_server() {
+ $PERL "$TOP_SRCDIR/bin/tests/system/start.pl" "$SYSTESTDIR" "$@"
+}
+
+stop_server() {
+ $PERL "$TOP_SRCDIR/bin/tests/system/stop.pl" "$SYSTESTDIR" "$@"
+}
+
+send() {
+ $PERL "$TOP_SRCDIR/bin/tests/system/send.pl" "$@"
+}
+
+#
+# Useful variables in test scripts
+#
+
+# The following script sets the following algorithm-related variables. These
+# are selected randomly at runtime from a list of supported algorithms. The
+# randomization is deterministic and remains stable for a period of time for a
+# given platform.
+#
+# Default algorithm for testing.
+# DEFAULT_ALGORITHM
+# DEFAULT_ALGORITHM_NUMBER
+# DEFAULT_BITS
+#
+# This is an alternative algorithm for test cases that require more than one
+# algorithm (for example algorithm rollover). Must be different from
+# DEFAULT_ALGORITHM.
+# ALTERNATIVE_ALGORITHM
+# ALTERNATIVE_ALGORITHM_NUMBER
+# ALTERNATIVE_BITS
+#
+# This is an algorithm that is used for tests against the "disable-algorithms"
+# configuration option. Must be different from above algorithms.
+# DISABLED_ALGORITHM
+# DISABLED_ALGORITHM_NUMBER
+# DISABLED_BITS
+#
+# There are multiple algoritms sets to choose from (see get_algorithms.py). To
+# override the default choice, set the ALGORITHM_SET env var (see mkeys system
+# test for example).
+eval "$($PYTHON "$TOP_SRCDIR/bin/tests/system/get_algorithms.py")"
+
+# Default HMAC algorithm.
+# also update common/rndc.conf and common/rndc.key when updating DEFAULT_HMAC
+export DEFAULT_HMAC=hmac-sha256
+
+#
+# Useful functions in test scripts
+#
+
+# assert_int_equal: compare two integer variables, $1 and $2
+#
+# If $1 and $2 are equal, return 0; if $1 and $2 are not equal, report
+# the error using the description of the tested variable provided in $3
+# and return 1.
+assert_int_equal() {
+ found="$1"
+ expected="$2"
+ description="$3"
+
+ if [ "${expected}" -ne "${found}" ]; then
+ echo_i "incorrect ${description}: got ${found}, expected ${expected}"
+ return 1
+ fi
+
+ return 0
+}
+
+# keyfile_to_keys_section: helper function for keyfile_to_*_keys() which
+# converts keyfile data into a key-style trust anchor configuration
+# section using the supplied parameters
+keyfile_to_keys() {
+ section_name=$1
+ key_prefix=$2
+ shift
+ shift
+ echo "$section_name {"
+ for keyname in $*; do
+ awk '!/^; /{
+ printf "\t\""$1"\" "
+ printf "'"$key_prefix "'"
+ printf $4 " " $5 " " $6 " \""
+ for (i=7; i<=NF; i++) printf $i
+ printf "\";\n"
+ }' $keyname.key
+ done
+ echo "};"
+}
+
+# keyfile_to_dskeys_section: helper function for keyfile_to_*_dskeys()
+# converts keyfile data into a DS-style trust anchor configuration
+# section using the supplied parameters
+keyfile_to_dskeys() {
+ section_name=$1
+ key_prefix=$2
+ shift
+ shift
+ echo "$section_name {"
+ for keyname in $*; do
+ $DSFROMKEY $keyname.key | \
+ awk '!/^; /{
+ printf "\t\""$1"\" "
+ printf "'"$key_prefix "'"
+ printf $4 " " $5 " " $6 " \""
+ for (i=7; i<=NF; i++) printf $i
+ printf "\";\n"
+ }'
+ done
+ echo "};"
+}
+
+# keyfile_to_trusted_keys: convert key data contained in the keyfile(s)
+# provided to a "trust-keys" section suitable for including in a
+# resolver's configuration file
+keyfile_to_trusted_keys() {
+ keyfile_to_keys "trusted-keys" "" $*
+}
+
+# keyfile_to_static_keys: convert key data contained in the keyfile(s)
+# provided to a *static-key* "trust-anchors" section suitable for including in
+# a resolver's configuration file
+keyfile_to_static_keys() {
+ keyfile_to_keys "trust-anchors" "static-key" $*
+}
+
+# keyfile_to_initial_keys: convert key data contained in the keyfile(s)
+# provided to an *initial-key* "trust-anchors" section suitable for including
+# in a resolver's configuration file
+keyfile_to_initial_keys() {
+ keyfile_to_keys "trust-anchors" "initial-key" $*
+}
+
+# keyfile_to_static_ds_keys: convert key data contained in the keyfile(s)
+# provided to a *static-ds* "trust-anchors" section suitable for including in a
+# resolver's configuration file
+keyfile_to_static_ds() {
+ keyfile_to_dskeys "trust-anchors" "static-ds" $*
+}
+
+# keyfile_to_initial_ds_keys: convert key data contained in the keyfile(s)
+# provided to an *initial-ds* "trust-anchors" section suitable for including
+# in a resolver's configuration file
+keyfile_to_initial_ds() {
+ keyfile_to_dskeys "trust-anchors" "initial-ds" $*
+}
+
+# keyfile_to_key_id: convert a key file name to a key ID
+#
+# For a given key file name (e.g. "Kexample.+013+06160") provided as $1,
+# print the key ID with leading zeros stripped ("6160" for the
+# aforementioned example).
+keyfile_to_key_id() {
+ echo "$1" | sed "s/.*+0\{0,4\}//"
+}
+
+# private_type_record: write a private type record recording the state of the
+# signing process
+#
+# For a given zone ($1), algorithm number ($2) and key file ($3), print the
+# private type record with default type value of 65534, indicating that the
+# signing process for this key is completed.
+private_type_record() {
+ _zone=$1
+ _algorithm=$2
+ _keyfile=$3
+
+ _id=$(keyfile_to_key_id "$_keyfile")
+
+ printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id"
+}
+
+# nextpart*() - functions for reading files incrementally
+#
+# These functions aim to facilitate looking for (or waiting for)
+# messages which may be logged more than once throughout the lifetime of
+# a given named instance by outputting just the part of the file which
+# has been appended since the last time we read it.
+#
+# Calling some of these functions causes temporary *.prev files to be
+# created that need to be cleaned up manually (usually by a given system
+# test's clean.sh script).
+#
+# Note that unlike other nextpart*() functions, nextpartread() is not
+# meant to be directly used in system tests; its sole purpose is to
+# reduce code duplication below.
+#
+# A quick usage example:
+#
+# $ echo line1 > named.log
+# $ echo line2 >> named.log
+# $ nextpart named.log
+# line1
+# line2
+# $ echo line3 >> named.log
+# $ nextpart named.log
+# line3
+# $ nextpart named.log
+# $ echo line4 >> named.log
+# $ nextpartpeek named.log
+# line4
+# $ nextpartpeek named.log
+# line4
+# $ nextpartreset named.log
+# $ nextpartpeek named.log
+# line1
+# line2
+# line3
+# line4
+# $ nextpart named.log
+# line1
+# line2
+# line3
+# line4
+# $ nextpart named.log
+# $
+
+# nextpartreset: reset the marker used by nextpart() and nextpartpeek()
+# so that it points to the start of the given file
+nextpartreset() {
+ echo "0" > $1.prev
+}
+
+# nextpartread: read everything that's been appended to a file since the
+# last time nextpart() was called and print it to stdout, print the
+# total number of lines read from that file so far to file descriptor 3
+nextpartread() {
+ [ -f $1.prev ] || nextpartreset $1
+ prev=$(cat $1.prev)
+ awk "NR > $prev "'{ print }
+ END { print NR > "/dev/stderr" }' $1 2>&3
+}
+
+# nextpart: read everything that's been appended to a file since the
+# last time nextpart() was called
+nextpart() {
+ nextpartread $1 3> $1.prev.tmp
+ mv $1.prev.tmp $1.prev
+}
+
+# nextpartpeek: read everything that's been appended to a file since the
+# last time nextpart() was called
+nextpartpeek() {
+ nextpartread $1 3> /dev/null
+}
+
+# _search_log: look for message $1 in file $2 with nextpart().
+_search_log() (
+ msg="$1"
+ file="$2"
+ nextpart "$file" | grep -F -e "$msg" > /dev/null
+)
+
+# _search_log_re: same as _search_log but the message is an grep -E regex
+_search_log_re() (
+ msg="$1"
+ file="$2"
+ nextpart "$file" | grep -E -e "$msg" > /dev/null
+)
+
+# _search_log_peek: look for message $1 in file $2 with nextpartpeek().
+_search_log_peek() (
+ msg="$1"
+ file="$2"
+ nextpartpeek "$file" | grep -F -e "$msg" > /dev/null
+)
+
+# wait_for_log: wait until message $2 in file $3 appears. Bail out after
+# $1 seconds. This needs to be used in conjunction with a prior call to
+# nextpart() or nextpartreset() on the same file to guarantee the offset is
+# set correctly. Tests using wait_for_log() are responsible for cleaning up
+# the created <file>.prev files.
+wait_for_log() (
+ timeout="$1"
+ msg="$2"
+ file="$3"
+ retry_quiet "$timeout" _search_log "$msg" "$file" && return 0
+ echo_i "exceeded time limit waiting for literal '$msg' in $file"
+ return 1
+)
+
+# wait_for_log_re: same as wait_for_log, but the message is an grep -E regex
+wait_for_log_re() (
+ timeout="$1"
+ msg="$2"
+ file="$3"
+ retry_quiet "$timeout" _search_log_re "$msg" "$file" && return 0
+ echo_i "exceeded time limit waiting for regex '$msg' in $file"
+ return 1
+)
+
+# wait_for_log_peek: similar to wait_for_log() but peeking, so the file offset
+# does not change.
+wait_for_log_peek() (
+ timeout="$1"
+ msg="$2"
+ file="$3"
+ retry_quiet "$timeout" _search_log_peek "$msg" "$file" && return 0
+ echo_i "exceeded time limit waiting for literal '$msg' in $file"
+ return 1
+)
+
+# _retry: keep running a command until it succeeds, up to $1 times, with
+# one-second intervals, optionally printing a message upon every attempt
+_retry() {
+ __retries="${1}"
+ shift
+
+ while :; do
+ if "$@"; then
+ return 0
+ fi
+ __retries=$((__retries-1))
+ if [ "${__retries}" -gt 0 ]; then
+ if [ "${__retry_quiet}" -ne 1 ]; then
+ echo_i "retrying"
+ fi
+ sleep 1
+ else
+ return 1
+ fi
+ done
+}
+
+# retry: call _retry() in verbose mode
+retry() {
+ __retry_quiet=0
+ _retry "$@"
+}
+
+# retry_quiet: call _retry() in silent mode
+retry_quiet() {
+ __retry_quiet=1
+ _retry "$@"
+}
+
+# _repeat: keep running command up to $1 times, unless it fails
+_repeat() (
+ __retries="${1}"
+ shift
+ while :; do
+ if ! "$@"; then
+ return 1
+ fi
+ __retries=$((__retries-1))
+ if [ "${__retries}" -le 0 ]; then
+ break
+ fi
+ done
+ return 0
+)
+
+_times() {
+ awk "BEGIN{ for(i = 1; i <= $1; i++) print i}";
+}
+
+rndc_reload() {
+ $RNDC -c ../common/rndc.conf -s $2 -p ${CONTROLPORT} reload $3 2>&1 | sed 's/^/'"I:$SYSTESTDIR:$1"' /'
+ # reloading single zone is synchronous, if we're reloading whole server
+ # we need to wait for reload to finish
+ if [ -z "$3" ]; then
+ for _ in $(_times 10); do
+ $RNDC -c ../common/rndc.conf -s $2 -p ${CONTROLPORT} status | grep "reload/reconfig in progress" > /dev/null || break
+ sleep 1
+ done
+ fi
+}
+
+rndc_reconfig() {
+ seconds=${3:-10}
+ $RNDC -c ../common/rndc.conf -s "$2" -p "${CONTROLPORT}" reconfig 2>&1 | sed 's/^/'"I:$SYSTESTDIR:$1"' /'
+ for _ in $(_times "$seconds"); do
+ "$RNDC" -c ../common/rndc.conf -s "$2" -p "${CONTROLPORT}" status | grep "reload/reconfig in progress" > /dev/null || break
+ sleep 1
+ done
+}
+
+# rndc_dumpdb: call "rndc dumpdb [...]" and wait until it completes
+#
+# The first argument is the name server instance to send the command to, in the
+# form of "nsX" (where "X" is the instance number), e.g. "ns5". The remaining
+# arguments, if any, are appended to the rndc command line after "dumpdb".
+#
+# Control channel configuration for the name server instance to send the
+# command to must match the contents of bin/tests/system/common/rndc.conf.
+#
+# rndc output is stored in a file called rndc.out.test${n}; the "n" variable is
+# required to be set by the calling tests.sh script.
+#
+# Return 0 if the dump completes successfully; return 1 if rndc returns an exit
+# code other than 0 or if the "; Dump complete" string does not appear in the
+# dump within 10 seconds.
+rndc_dumpdb() {
+ __ret=0
+ __dump_complete=0
+ __server="${1}"
+ __ip="10.53.0.$(echo "${__server}" | tr -c -d "0-9")"
+
+ shift
+ ${RNDC} -c ../common/rndc.conf -p "${CONTROLPORT}" -s "${__ip}" dumpdb "$@" > "rndc.out.test${n}" 2>&1 || __ret=1
+
+ for _ in 0 1 2 3 4 5 6 7 8 9
+ do
+ if grep '^; Dump complete$' "${__server}/named_dump.db" > /dev/null; then
+ mv "${__server}/named_dump.db" "${__server}/named_dump.db.test${n}"
+ __dump_complete=1
+ break
+ fi
+ sleep 1
+ done
+
+ if [ ${__dump_complete} -eq 0 ]; then
+ echo_i "timed out waiting for 'rndc dumpdb' to finish"
+ __ret=1
+ fi
+
+ return ${__ret}
+}
+
+# get_dig_xfer_stats: extract transfer statistics from dig output stored
+# in $1, converting them to a format used by some system tests.
+get_dig_xfer_stats() {
+ LOGFILE="$1"
+ sed -n "s/^;; XFR size: .*messages \([0-9][0-9]*\).*/messages=\1/p" "${LOGFILE}"
+ sed -n "s/^;; XFR size: \([0-9][0-9]*\) records.*/records=\1/p" "${LOGFILE}"
+ sed -n "s/^;; XFR size: .*bytes \([0-9][0-9]*\).*/bytes=\1/p" "${LOGFILE}"
+}
+
+# get_named_xfer_stats: from named log file $1, extract transfer
+# statistics for the last transfer for peer $2 and zone $3 (from a log
+# message which has to contain the string provided in $4), converting
+# them to a format used by some system tests.
+get_named_xfer_stats() {
+ LOGFILE="$1"
+ PEER="$(echo $2 | sed 's/\./\\./g')"
+ ZONE="$(echo $3 | sed 's/\./\\./g')"
+ MESSAGE="$4"
+ grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
+ sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) messages.*/messages=\1/p" | tail -1
+ grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
+ sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) records.*/records=\1/p" | tail -1
+ grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
+ sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) bytes.*/bytes=\1/p" | tail -1
+}
+
+# copy_setports - Copy Configuration File and Replace Ports
+#
+# Convenience function to copy a configuration file, replacing the tokens
+# QUERYPORT, CONTROLPORT and EXTRAPORT[1-8] with the values of the equivalent
+# environment variables. (These values are set by test runner, which calls the
+# scripts invoking this function.)
+#
+# Usage:
+# copy_setports infile outfile
+#
+copy_setports() {
+ dir=$(echo "$TMPDIR" | sed 's/\//\\\//g')
+
+ sed -e "s/@TMPDIR@/${dir}/g" \
+ -e "s/@PORT@/${PORT}/g" \
+ -e "s/@TLSPORT@/${TLSPORT}/g" \
+ -e "s/@HTTPPORT@/${HTTPPORT}/g" \
+ -e "s/@HTTPSPORT@/${HTTPSPORT}/g" \
+ -e "s/@EXTRAPORT1@/${EXTRAPORT1}/g" \
+ -e "s/@EXTRAPORT2@/${EXTRAPORT2}/g" \
+ -e "s/@EXTRAPORT3@/${EXTRAPORT3}/g" \
+ -e "s/@EXTRAPORT4@/${EXTRAPORT4}/g" \
+ -e "s/@EXTRAPORT5@/${EXTRAPORT5}/g" \
+ -e "s/@EXTRAPORT6@/${EXTRAPORT6}/g" \
+ -e "s/@EXTRAPORT7@/${EXTRAPORT7}/g" \
+ -e "s/@EXTRAPORT8@/${EXTRAPORT8}/g" \
+ -e "s/@CONTROLPORT@/${CONTROLPORT}/g" \
+ -e "s/@DEFAULT_ALGORITHM@/${DEFAULT_ALGORITHM}/g" \
+ -e "s/@DEFAULT_ALGORITHM_NUMBER@/${DEFAULT_ALGORITHM_NUMBER}/g" \
+ -e "s/@DEFAULT_BITS@/${DEFAULT_BITS}/g" \
+ -e "s/@ALTERNATIVE_ALGORITHM@/${ALTERNATIVE_ALGORITHM}/g" \
+ -e "s/@ALTERNATIVE_ALGORITHM_NUMBER@/${ALTERNATIVE_ALGORITHM_NUMBER}/g" \
+ -e "s/@ALTERNATIVE_BITS@/${ALTERNATIVE_BITS}/g" \
+ -e "s/@DEFAULT_HMAC@/${DEFAULT_HMAC}/g" \
+ -e "s/@DISABLED_ALGORITHM@/${DISABLED_ALGORITHM}/g" \
+ -e "s/@DISABLED_ALGORITHM_NUMBER@/${DISABLED_ALGORITHM_NUMBER}/g" \
+ -e "s/@DISABLED_BITS@/${DISABLED_BITS}/g" \
+ $1 > $2
+}
diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in
new file mode 100644
index 0000000..1a2fe73
--- /dev/null
+++ b/bin/tests/system/conf.sh.in
@@ -0,0 +1,130 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Common configuration data for system tests, to be sourced into
+# other shell scripts.
+#
+
+# Find the top of the BIND9 tree.
+export TOP_BUILDDIR=@abs_top_builddir@
+export TOP_SRCDIR=@abs_top_srcdir@
+
+# Provide TMPDIR variable for tests that need it.
+export TMPDIR=${TMPDIR:-/tmp}
+
+export ARPANAME=$TOP_BUILDDIR/bin/tools/arpaname
+export CDS=$TOP_BUILDDIR/bin/dnssec/dnssec-cds
+export CHECKCONF=$TOP_BUILDDIR/bin/check/named-checkconf
+export CHECKZONE=$TOP_BUILDDIR/bin/check/named-checkzone
+if [ -z "$TSAN_OPTIONS" ]; then # workaround for GL#4119
+ export DELV=$TOP_BUILDDIR/bin/delv/delv
+ export RESOLVE=$TOP_BUILDDIR/bin/tests/system/resolve
+else
+ export DELV=:
+ export RESOLVE=:
+fi
+export DIG=$TOP_BUILDDIR/bin/dig/dig
+export DNSTAPREAD=$TOP_BUILDDIR/bin/tools/dnstap-read
+export DSFROMKEY=$TOP_BUILDDIR/bin/dnssec/dnssec-dsfromkey
+export FEATURETEST=$TOP_BUILDDIR/bin/tests/system/feature-test
+export FSTRM_CAPTURE=@FSTRM_CAPTURE@
+export HOST=$TOP_BUILDDIR/bin/dig/host
+export IMPORTKEY=$TOP_BUILDDIR/bin/dnssec/dnssec-importkey
+export JOURNALPRINT=$TOP_BUILDDIR/bin/tools/named-journalprint
+export KEYFRLAB=$TOP_BUILDDIR/bin/dnssec/dnssec-keyfromlabel
+export KEYGEN=$TOP_BUILDDIR/bin/dnssec/dnssec-keygen
+export MDIG=$TOP_BUILDDIR/bin/tools/mdig
+export NAMED=$TOP_BUILDDIR/bin/named/named
+export NSEC3HASH=$TOP_BUILDDIR/bin/tools/nsec3hash
+export NSLOOKUP=$TOP_BUILDDIR/bin/dig/nslookup
+export NSUPDATE=$TOP_BUILDDIR/bin/nsupdate/nsupdate
+export NZD2NZF=$TOP_BUILDDIR/bin/tools/named-nzd2nzf
+export REVOKE=$TOP_BUILDDIR/bin/dnssec/dnssec-revoke
+export RNDC=$TOP_BUILDDIR/bin/rndc/rndc
+export RNDCCONFGEN=$TOP_BUILDDIR/bin/confgen/rndc-confgen
+export RRCHECKER=$TOP_BUILDDIR/bin/tools/named-rrchecker
+export SETTIME=$TOP_BUILDDIR/bin/dnssec/dnssec-settime
+export SIGNER=$TOP_BUILDDIR/bin/dnssec/dnssec-signzone
+export TSIGKEYGEN=$TOP_BUILDDIR/bin/confgen/tsig-keygen
+export VERIFY=$TOP_BUILDDIR/bin/dnssec/dnssec-verify
+export WIRETEST=$TOP_BUILDDIR/bin/tests/wire_test
+
+export BIGKEY=$TOP_BUILDDIR/bin/tests/system/rsabigexponent/bigkey
+export GENCHECK=$TOP_BUILDDIR/bin/tests/system/rndc/gencheck
+export KEYCREATE=$TOP_BUILDDIR/bin/tests/system/tkey/keycreate
+export KEYDELETE=$TOP_BUILDDIR/bin/tests/system/tkey/keydelete
+export MAKEJOURNAL=$TOP_BUILDDIR/bin/tests/system/makejournal
+export PIPEQUERIES=$TOP_BUILDDIR/bin/tests/system/pipelined/pipequeries
+
+# we don't want a KRB5_CONFIG setting breaking the tests
+export KRB5_CONFIG=/dev/null
+# use local keytab instead of default /etc/krb5.keytab
+export KRB5_KTNAME=dns.keytab
+
+#
+# Programs detected by configure
+# Variables will be empty if no program was found by configure
+#
+export SHELL=@SHELL@
+export CURL=@CURL@
+export NC=@NC@
+export XMLLINT=@XMLLINT@
+export XSLTPROC=@XSLTPROC@
+export PYTEST=@PYTEST@
+
+#
+# Interpreters for system tests detected by configure
+#
+export PERL=$(command -v "@PERL@" || true)
+if ! test -x "$PERL"; then
+ echo "Perl interpreter is required for system tests."
+ exit 77
+fi
+export PYTHON=$(command -v "@PYTHON@" || true)
+if ! test -x "$PYTHON"; then
+ echo "Python interpreter is required for system tests."
+ exit 77
+fi
+
+# Load common values
+. $TOP_SRCDIR/bin/tests/system/conf.sh.common
+
+#
+# Construct the lists of tests to run
+#
+SEQUENTIAL_UNIX=""
+SEQUENTIALDIRS="$SEQUENTIAL_COMMON $SEQUENTIAL_UNIX"
+
+PARALLEL_UNIX="@DNSTAP@
+chain
+checkds
+cookie
+dlzexternal
+dnssec
+dyndb
+enginepkcs11
+filter-aaaa
+kasp
+keyfromlabel
+keymgr2kasp
+legacy
+logfileconfig
+nzd2nzf
+pipelined
+qmin
+shutdown
+tcp"
+PARALLELDIRS="$PARALLEL_COMMON $PARALLEL_UNIX"
+
+SUBDIRS="$SEQUENTIALDIRS $PARALLELDIRS"
diff --git a/bin/tests/system/conftest.py b/bin/tests/system/conftest.py
new file mode 100644
index 0000000..50510a0
--- /dev/null
+++ b/bin/tests/system/conftest.py
@@ -0,0 +1,639 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import logging
+import os
+import pytest
+
+
+# ======================= LEGACY=COMPATIBLE FIXTURES =========================
+# The following fixtures are designed to work with both pytest system test
+# runner and the legacy system test framework.
+#
+# FUTURE: Rewrite the individual port fixtures to re-use the `ports` fixture.
+
+
+@pytest.fixture(scope="module")
+def named_port():
+ return int(os.environ.get("PORT", default=5300))
+
+
+@pytest.fixture(scope="module")
+def named_tlsport():
+ return int(os.environ.get("TLSPORT", default=8853))
+
+
+@pytest.fixture(scope="module")
+def named_httpsport():
+ return int(os.environ.get("HTTPSPORT", default=4443))
+
+
+@pytest.fixture(scope="module")
+def control_port():
+ return int(os.environ.get("CONTROLPORT", default=9953))
+
+
+if os.getenv("LEGACY_TEST_RUNNER", "0") != "0":
+
+ @pytest.fixture
+ def logger(request):
+ """Logging facility specific to a particular test."""
+ return logging.getLogger(request.node.name)
+
+else:
+ # ======================= PYTEST SYSTEM TEST RUNNER ==========================
+ # From this point onward, any setting, fixtures or functions only apply to the
+ # new pytest runner. Ideally, these would be in a separate file. However, due
+ # to how pytest works and how it's used by the legacy runner, the best approach
+ # is to have everything in this file to avoid duplication and set the
+ # LEGACY_TEST_RUNNER if pytest is executed from the legacy framework.
+ #
+ # FUTURE: Once legacy runner is no longer supported, remove the env var and
+ # don't branch the code.
+
+ from functools import partial
+ from pathlib import Path
+ import re
+ import shutil
+ import subprocess
+ import tempfile
+ import time
+ from typing import Any, Dict, List, Optional
+
+ # Silence warnings caused by passing a pytest fixture to another fixture.
+ # pylint: disable=redefined-outer-name
+
+ # ----------------- Older pytest / xdist compatibility -------------------
+ # As of 2023-01-11, the minimal supported pytest / xdist versions are
+ # determined by what is available in EL8/EPEL8:
+ # - pytest 3.4.2
+ # - pytest-xdist 1.24.1
+ _pytest_ver = pytest.__version__.split(".")
+ _pytest_major_ver = int(_pytest_ver[0])
+ if _pytest_major_ver < 7:
+ # pytest.Stash/pytest.StashKey mechanism has been added in 7.0.0
+ # for older versions, use regular dictionary with string keys instead
+ FIXTURE_OK = "fixture_ok" # type: Any
+ else:
+ FIXTURE_OK = pytest.StashKey[bool]() # pylint: disable=no-member
+
+ # ----------------------- Globals definition -----------------------------
+
+ LOG_FORMAT = "%(asctime)s %(levelname)7s:%(name)s %(message)s"
+ XDIST_WORKER = os.environ.get("PYTEST_XDIST_WORKER", "")
+ FILE_DIR = os.path.abspath(Path(__file__).parent)
+ ENV_RE = re.compile(b"([^=]+)=(.*)")
+ PORT_MIN = 5001
+ PORT_MAX = 32767
+ PORTS_PER_TEST = 20
+ PRIORITY_TESTS = [
+ # Tests that are scheduled first. Speeds up parallel execution.
+ "dupsigs/",
+ "rpz/",
+ "rpzrecurse/",
+ "serve-stale/",
+ "timeouts/",
+ "upforwd/",
+ ]
+ PRIORITY_TESTS_RE = re.compile("|".join(PRIORITY_TESTS))
+ CONFTEST_LOGGER = logging.getLogger("conftest")
+ SYSTEM_TEST_DIR_GIT_PATH = "bin/tests/system"
+ SYSTEM_TEST_NAME_RE = re.compile(f"{SYSTEM_TEST_DIR_GIT_PATH}" + r"/([^/]+)")
+ SYMLINK_REPLACEMENT_RE = re.compile(r"/tests(_sh(?=_))?(.*)\.py")
+
+ # ---------------------- Module initialization ---------------------------
+
+ def init_pytest_conftest_logger(conftest_logger):
+ """
+ This initializes the conftest logger which is used for pytest setup
+ and configuration before tests are executed -- aka any logging in this
+ file that is _not_ module-specific.
+ """
+ conftest_logger.setLevel(logging.DEBUG)
+ file_handler = logging.FileHandler("pytest.conftest.log.txt")
+ file_handler.setLevel(logging.DEBUG)
+ file_handler.setFormatter(logging.Formatter(LOG_FORMAT))
+ conftest_logger.addHandler(file_handler)
+
+ init_pytest_conftest_logger(CONFTEST_LOGGER)
+
+ def avoid_duplicated_logs():
+ """
+ Remove direct root logger output to file descriptors.
+ This default is causing duplicates because all our messages go through
+ regular logging as well and are thus displayed twice.
+ """
+ todel = []
+ for handler in logging.root.handlers:
+ if handler.__class__ == logging.StreamHandler:
+ # Beware: As for pytest 7.2.2, LiveLogging and LogCapture
+ # handlers inherit from logging.StreamHandler
+ todel.append(handler)
+ for handler in todel:
+ logging.root.handlers.remove(handler)
+
+ def parse_env(env_bytes):
+ """Parse the POSIX env format into Python dictionary."""
+ out = {}
+ for line in env_bytes.splitlines():
+ match = ENV_RE.match(line)
+ if match:
+ # EL8+ workaround for https://access.redhat.com/solutions/6994985
+ # FUTURE: can be removed when we no longer need to parse env vars
+ if match.groups()[0] in [b"which_declare", b"BASH_FUNC_which%%"]:
+ continue
+ out[match.groups()[0]] = match.groups()[1]
+ return out
+
+ def get_env_bytes(cmd):
+ try:
+ proc = subprocess.run(
+ [cmd],
+ shell=True,
+ check=True,
+ cwd=FILE_DIR,
+ stdout=subprocess.PIPE,
+ )
+ except subprocess.CalledProcessError as exc:
+ CONFTEST_LOGGER.error("failed to get shell env: %s", exc)
+ raise exc
+ env_bytes = proc.stdout
+ return parse_env(env_bytes)
+
+ # Read common environment variables for running tests from conf.sh.
+ # FUTURE: Remove conf.sh entirely and define all variables in pytest only.
+ CONF_ENV = get_env_bytes(". ./conf.sh && env")
+ os.environb.update(CONF_ENV)
+ CONFTEST_LOGGER.debug(
+ "variables in env: %s", ", ".join([str(key) for key in CONF_ENV])
+ )
+
+ # --------------------------- pytest hooks -------------------------------
+
+ def pytest_addoption(parser):
+ parser.addoption(
+ "--noclean",
+ action="store_true",
+ default=False,
+ help="don't remove the temporary test directories with artifacts",
+ )
+
+ def pytest_configure(config):
+ # Ensure this hook only runs on the main pytest instance if xdist is
+ # used to spawn other workers.
+ if not XDIST_WORKER:
+ if config.pluginmanager.has_plugin("xdist") and config.option.numprocesses:
+ # system tests depend on module scope for setup & teardown
+ # enforce use "loadscope" scheduler or disable paralelism
+ try:
+ import xdist.scheduler.loadscope # pylint: disable=unused-import
+ except ImportError:
+ CONFTEST_LOGGER.debug(
+ "xdist is too old and does not have "
+ "scheduler.loadscope, disabling parallelism"
+ )
+ config.option.dist = "no"
+ else:
+ config.option.dist = "loadscope"
+
+ def pytest_ignore_collect(path):
+ # System tests are executed in temporary directories inside
+ # bin/tests/system. These temporary directories contain all files
+ # needed for the system tests - including tests_*.py files. Make sure to
+ # ignore these during test collection phase. Otherwise, test artifacts
+ # from previous runs could mess with the runner. Also ignore the
+ # convenience symlinks to those test directories. In both of those
+ # cases, the system test name (directory) contains an underscore, which
+ # is otherwise and invalid character for a system test name.
+ match = SYSTEM_TEST_NAME_RE.search(str(path))
+ if match is None:
+ CONFTEST_LOGGER.warning("unexpected test path: %s (ignored)", path)
+ return True
+ system_test_name = match.groups()[0]
+ return "_" in system_test_name
+
+ def pytest_collection_modifyitems(items):
+ """Schedule long-running tests first to get more benefit from parallelism."""
+ priority = []
+ other = []
+ for item in items:
+ if PRIORITY_TESTS_RE.search(item.nodeid):
+ priority.append(item)
+ else:
+ other.append(item)
+ items[:] = priority + other
+
+ class NodeResult:
+ def __init__(self, report=None):
+ self.outcome = None
+ self.messages = []
+ if report is not None:
+ self.update(report)
+
+ def update(self, report):
+ if self.outcome is None or report.outcome != "passed":
+ self.outcome = report.outcome
+ if report.longreprtext:
+ self.messages.append(report.longreprtext)
+
+ @pytest.hookimpl(tryfirst=True, hookwrapper=True)
+ def pytest_runtest_makereport(item):
+ """Hook that is used to expose test results to session (for use in fixtures)."""
+ # execute all other hooks to obtain the report object
+ outcome = yield
+ report = outcome.get_result()
+
+ # Set the test outcome in session, so we can access it from module-level
+ # fixture using nodeid. Note that this hook is called three times: for
+ # setup, call and teardown. We only care about the overall result so we
+ # merge the results together and preserve the information whether a test
+ # passed.
+ test_results = {}
+ try:
+ test_results = getattr(item.session, "test_results")
+ except AttributeError:
+ setattr(item.session, "test_results", test_results)
+ node_result = test_results.setdefault(item.nodeid, NodeResult())
+ node_result.update(report)
+
+ # --------------------------- Fixtures -----------------------------------
+
+ @pytest.fixture(scope="session")
+ def modules():
+ """Sorted list of all modules. Used to determine port distribution."""
+ mods = []
+ for dirpath, _dirs, files in os.walk(os.getcwd()):
+ for file in files:
+ if file.startswith("tests_") and file.endswith(".py"):
+ mod = f"{dirpath}/{file}"
+ mods.append(mod)
+ return sorted(mods)
+
+ @pytest.fixture(scope="session")
+ def module_base_ports(modules):
+ """
+ Dictionary containing assigned base port for every module.
+
+ Note that this is a session-wide fixture. The port numbers are
+ deterministically assigned before any testing starts. This fixture MUST
+ return the same value when called again during the same test session.
+ When running tests in parallel, this is exactly what happens - every
+ worker thread will call this fixture to determine test ports.
+ """
+ port_min = PORT_MIN
+ port_max = PORT_MAX - len(modules) * PORTS_PER_TEST
+ if port_max < port_min:
+ raise RuntimeError(
+ "not enough ports to assign unique port set to each module"
+ )
+
+ # Rotate the base port value over time to detect possible test issues
+ # with using random ports. This introduces a very slight race condition
+ # risk. If this value changes between pytest invocation and spawning
+ # worker threads, multiple tests may have same port values assigned. If
+ # these tests are then executed simultaneously, the test results will
+ # be misleading.
+ base_port = int(time.time() // 3600) % (port_max - port_min) + port_min
+
+ return {mod: base_port + i * PORTS_PER_TEST for i, mod in enumerate(modules)}
+
+ @pytest.fixture(scope="module")
+ def base_port(request, module_base_ports):
+ """Start of the port range assigned to a particular test module."""
+ port = module_base_ports[request.fspath]
+ return port
+
+ @pytest.fixture(scope="module")
+ def ports(base_port):
+ """Dictionary containing port names and their assigned values."""
+ return {
+ "PORT": str(base_port),
+ "TLSPORT": str(base_port + 1),
+ "HTTPPORT": str(base_port + 2),
+ "HTTPSPORT": str(base_port + 3),
+ "EXTRAPORT1": str(base_port + 4),
+ "EXTRAPORT2": str(base_port + 5),
+ "EXTRAPORT3": str(base_port + 6),
+ "EXTRAPORT4": str(base_port + 7),
+ "EXTRAPORT5": str(base_port + 8),
+ "EXTRAPORT6": str(base_port + 9),
+ "EXTRAPORT7": str(base_port + 10),
+ "EXTRAPORT8": str(base_port + 11),
+ "CONTROLPORT": str(base_port + 12),
+ }
+
+ @pytest.fixture(scope="module")
+ def env(ports):
+ """Dictionary containing environment variables for the test."""
+ env = os.environ.copy()
+ env.update(ports)
+ env["builddir"] = f"{env['TOP_BUILDDIR']}/{SYSTEM_TEST_DIR_GIT_PATH}"
+ env["srcdir"] = f"{env['TOP_SRCDIR']}/{SYSTEM_TEST_DIR_GIT_PATH}"
+ return env
+
+ @pytest.fixture(scope="module")
+ def system_test_name(request):
+ """Name of the system test directory."""
+ path = Path(request.fspath)
+ return path.parent.name
+
+ @pytest.fixture(scope="module")
+ def mlogger(system_test_name):
+ """Logging facility specific to this test module."""
+ avoid_duplicated_logs()
+ return logging.getLogger(system_test_name)
+
+ @pytest.fixture
+ def logger(request, system_test_name):
+ """Logging facility specific to a particular test."""
+ return logging.getLogger(f"{system_test_name}.{request.node.name}")
+
+ @pytest.fixture(scope="module")
+ def system_test_dir(
+ request, env, system_test_name, mlogger
+ ): # pylint: disable=too-many-statements,too-many-locals
+ """
+ Temporary directory for executing the test.
+
+ This fixture is responsible for creating (and potentially removing) a
+ copy of the system test directory which is used as a temporary
+ directory for the test execution.
+
+ FUTURE: This removes the need to have clean.sh scripts.
+ """
+
+ def get_test_result():
+ """Aggregate test results from all individual tests from this module
+ into a single result: failed > skipped > passed."""
+ try:
+ all_test_results = request.session.test_results
+ except AttributeError:
+ # This may happen if pytest execution is interrupted and
+ # pytest_runtest_makereport() is never called.
+ mlogger.debug("can't obtain test results, test run was interrupted")
+ return "error"
+ test_results = {
+ node.nodeid: all_test_results[node.nodeid]
+ for node in request.node.collect()
+ if node.nodeid in all_test_results
+ }
+ assert len(test_results)
+ messages = []
+ for node, result in test_results.items():
+ mlogger.debug("%s %s", result.outcome.upper(), node)
+ messages.extend(result.messages)
+ for message in messages:
+ mlogger.debug("\n" + message)
+ failed = any(res.outcome == "failed" for res in test_results.values())
+ skipped = any(res.outcome == "skipped" for res in test_results.values())
+ if failed:
+ return "failed"
+ if skipped:
+ return "skipped"
+ assert all(res.outcome == "passed" for res in test_results.values())
+ return "passed"
+
+ def unlink(path):
+ try:
+ path.unlink() # missing_ok=True isn't available on Python 3.6
+ except FileNotFoundError:
+ pass
+
+ # Create a temporary directory with a copy of the original system test dir contents
+ system_test_root = Path(f"{env['TOP_BUILDDIR']}/{SYSTEM_TEST_DIR_GIT_PATH}")
+ testdir = Path(
+ tempfile.mkdtemp(prefix=f"{system_test_name}_tmp_", dir=system_test_root)
+ )
+ shutil.rmtree(testdir)
+ shutil.copytree(system_test_root / system_test_name, testdir)
+
+ # Create a convenience symlink with a stable and predictable name
+ module_name = SYMLINK_REPLACEMENT_RE.sub(r"\2", request.node.name)
+ symlink_dst = system_test_root / module_name
+ unlink(symlink_dst)
+ symlink_dst.symlink_to(os.path.relpath(testdir, start=system_test_root))
+
+ # Configure logger to write to a file inside the temporary test directory
+ mlogger.handlers.clear()
+ mlogger.setLevel(logging.DEBUG)
+ handler = logging.FileHandler(testdir / "pytest.log.txt", mode="w")
+ formatter = logging.Formatter(LOG_FORMAT)
+ handler.setFormatter(formatter)
+ mlogger.addHandler(handler)
+
+ # System tests are meant to be executed from their directory - switch to it.
+ old_cwd = os.getcwd()
+ os.chdir(testdir)
+ mlogger.debug("switching to tmpdir: %s", testdir)
+ try:
+ yield testdir # other fixtures / tests will execute here
+ finally:
+ os.chdir(old_cwd)
+ mlogger.debug("changed workdir to: %s", old_cwd)
+
+ result = get_test_result()
+
+ # Clean temporary dir unless it should be kept
+ keep = False
+ if request.config.getoption("--noclean"):
+ mlogger.debug(
+ "--noclean requested, keeping temporary directory %s", testdir
+ )
+ keep = True
+ elif result == "failed":
+ mlogger.debug(
+ "test failure detected, keeping temporary directory %s", testdir
+ )
+ keep = True
+ elif not request.node.stash[FIXTURE_OK]:
+ mlogger.debug(
+ "test setup/teardown issue detected, keeping temporary directory %s",
+ testdir,
+ )
+ keep = True
+
+ if keep:
+ mlogger.info(
+ "test artifacts in: %s", symlink_dst.relative_to(system_test_root)
+ )
+ else:
+ mlogger.debug("deleting temporary directory")
+ handler.flush()
+ handler.close()
+ shutil.rmtree(testdir)
+ unlink(symlink_dst)
+
+ def _run_script( # pylint: disable=too-many-arguments
+ env,
+ mlogger,
+ system_test_dir: Path,
+ interpreter: str,
+ script: str,
+ args: Optional[List[str]] = None,
+ ):
+ """Helper function for the shell / perl script invocations (through fixtures below)."""
+ if args is None:
+ args = []
+ path = Path(script)
+ if not path.is_absolute():
+ # make sure relative paths are always relative to system_dir
+ path = system_test_dir.parent / path
+ script = str(path)
+ cwd = os.getcwd()
+ if not path.exists():
+ raise FileNotFoundError(f"script {script} not found in {cwd}")
+ mlogger.debug("running script: %s %s %s", interpreter, script, " ".join(args))
+ mlogger.debug(" workdir: %s", cwd)
+ returncode = 1
+
+ cmd = [interpreter, script] + args
+ with subprocess.Popen(
+ cmd,
+ env=env,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ bufsize=1,
+ universal_newlines=True,
+ errors="backslashreplace",
+ ) as proc:
+ if proc.stdout:
+ for line in proc.stdout:
+ mlogger.info(" %s", line.rstrip("\n"))
+ proc.communicate()
+ returncode = proc.returncode
+ if returncode:
+ raise subprocess.CalledProcessError(returncode, cmd)
+ mlogger.debug(" exited with %d", returncode)
+
+ @pytest.fixture(scope="module")
+ def shell(env, system_test_dir, mlogger):
+ """Function to call a shell script with arguments."""
+ return partial(_run_script, env, mlogger, system_test_dir, env["SHELL"])
+
+ @pytest.fixture(scope="module")
+ def perl(env, system_test_dir, mlogger):
+ """Function to call a perl script with arguments."""
+ return partial(_run_script, env, mlogger, system_test_dir, env["PERL"])
+
+ @pytest.fixture(scope="module")
+ def run_tests_sh(system_test_dir, shell):
+ """Utility function to execute tests.sh as a python test."""
+
+ def run_tests():
+ shell(f"{system_test_dir}/tests.sh")
+
+ return run_tests
+
+ @pytest.fixture(scope="module", autouse=True)
+ def system_test( # pylint: disable=too-many-arguments,too-many-statements
+ request,
+ env: Dict[str, str],
+ mlogger,
+ system_test_dir,
+ shell,
+ perl,
+ ):
+ """
+ Driver of the test setup/teardown process. Used automatically for every test module.
+
+ This is the most important one-fixture-to-rule-them-all. Note the
+ autouse=True which causes this fixture to be loaded by every test
+ module without the need to explicitly specify it.
+
+ When this fixture is used, it utilizes other fixtures, such as
+ system_test_dir, which handles the creation of the temporary test
+ directory.
+
+ Afterwards, it checks the test environment and takes care of starting
+ the servers. When everything is ready, that's when the actual tests are
+ executed. Once that is done, this fixture stops the servers and checks
+ for any artifacts indicating an issue (e.g. coredumps).
+
+ Finally, when this fixture reaches an end (or encounters an exception,
+ which may be caused by fail/skip invocations), any fixtures which is
+ used by this one are finalized - e.g. system_test_dir performs final
+ checks and cleans up the temporary test directory.
+ """
+
+ def check_net_interfaces():
+ try:
+ perl("testsock.pl", ["-p", env["PORT"]])
+ except subprocess.CalledProcessError as exc:
+ mlogger.error("testsock.pl: exited with code %d", exc.returncode)
+ pytest.skip("Network interface aliases not set up.")
+
+ def check_prerequisites():
+ try:
+ shell(f"{system_test_dir}/prereq.sh")
+ except FileNotFoundError:
+ pass # prereq.sh is optional
+ except subprocess.CalledProcessError:
+ pytest.skip("Prerequisites missing.")
+
+ def setup_test():
+ try:
+ shell(f"{system_test_dir}/setup.sh")
+ except FileNotFoundError:
+ pass # setup.sh is optional
+ except subprocess.CalledProcessError as exc:
+ mlogger.error("Failed to run test setup")
+ pytest.fail(f"setup.sh exited with {exc.returncode}")
+
+ def start_servers():
+ try:
+ perl("start.pl", ["--port", env["PORT"], system_test_dir.name])
+ except subprocess.CalledProcessError as exc:
+ mlogger.error("Failed to start servers")
+ pytest.fail(f"start.pl exited with {exc.returncode}")
+
+ def stop_servers():
+ try:
+ perl("stop.pl", [system_test_dir.name])
+ except subprocess.CalledProcessError as exc:
+ mlogger.error("Failed to stop servers")
+ get_core_dumps()
+ pytest.fail(f"stop.pl exited with {exc.returncode}")
+
+ def get_core_dumps():
+ try:
+ shell("get_core_dumps.sh", [system_test_dir.name])
+ except subprocess.CalledProcessError as exc:
+ mlogger.error("Found core dumps or sanitizer reports")
+ pytest.fail(f"get_core_dumps.sh exited with {exc.returncode}")
+
+ os.environ.update(env) # Ensure pytests have the same env vars as shell tests.
+ mlogger.info(f"test started: {request.node.name}")
+ port = int(env["PORT"])
+ mlogger.info("using port range: <%d, %d>", port, port + PORTS_PER_TEST - 1)
+
+ if not hasattr(request.node, "stash"): # compatibility with pytest<7.0.0
+ request.node.stash = {} # use regular dict instead of pytest.Stash
+ request.node.stash[FIXTURE_OK] = True
+
+ # Perform checks which may skip this test.
+ check_net_interfaces()
+ check_prerequisites()
+
+ # Store the fact that this fixture hasn't successfully finished yet.
+ # This is checked before temporary directory teardown to decide whether
+ # it's okay to remove the directory.
+ request.node.stash[FIXTURE_OK] = False
+
+ setup_test()
+ try:
+ start_servers()
+ mlogger.debug("executing test(s)")
+ yield
+ finally:
+ mlogger.debug("test(s) finished")
+ stop_servers()
+ get_core_dumps()
+ request.node.stash[FIXTURE_OK] = True
diff --git a/bin/tests/system/cookie/ans9/ans.py b/bin/tests/system/cookie/ans9/ans.py
new file mode 100644
index 0000000..6f90797
--- /dev/null
+++ b/bin/tests/system/cookie/ans9/ans.py
@@ -0,0 +1,308 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from __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
+import dns.edns
+import dns.flags
+import dns.message
+import dns.query
+import dns.tsig
+import dns.tsigkeyring
+import dns.version
+
+from dns.edns import *
+from dns.name import *
+from dns.rcode import *
+from dns.rdataclass import *
+from dns.rdatatype import *
+from dns.tsig import *
+
+
+# Log query to file
+def logquery(type, qname):
+ with open("qlog", "a") as f:
+ f.write("%s %s\n", type, qname)
+
+
+# DNS 2.0 keyring specifies the algorithm
+try:
+ keyring = dns.tsigkeyring.from_text(
+ {
+ "foo": {"hmac-sha256", "aaaaaaaaaaaa"},
+ "fake": {"hmac-sha256", "aaaaaaaaaaaa"},
+ }
+ )
+except:
+ keyring = dns.tsigkeyring.from_text({"foo": "aaaaaaaaaaaa", "fake": "aaaaaaaaaaaa"})
+
+dopass2 = False
+
+
+############################################################################
+#
+# This server will serve valid and spoofed answers. A spoofed answer will
+# have the address 10.53.0.10 included.
+#
+# When receiving a query over UDP:
+#
+# A query to "nocookie"/A will result in a spoofed answer with no cookie set.
+# A query to "tcponly"/A will result in a spoofed answer with no cookie set.
+# A query to "withtsig"/A will result in two responses, the first is a spoofed
+# answer that is TSIG signed, the second is a valid answer with a cookie set.
+# A query to anything else will result in a valid answer with a cookie set.
+#
+# When receiving a query over TCP:
+#
+# A query to "nocookie"/A will result in a valid answer with no cookie set.
+# A query to anything else will result in a valid answer with a cookie set.
+#
+############################################################################
+def create_response(msg, tcp, first, ns10):
+ global dopass2
+ m = dns.message.from_wire(msg, keyring=keyring)
+ qname = m.question[0].name.to_text()
+ lqname = qname.lower()
+ labels = lqname.split(".")
+ rrtype = m.question[0].rdtype
+ typename = dns.rdatatype.to_text(rrtype)
+
+ with open("query.log", "a") as f:
+ f.write("%s %s\n" % (typename, qname))
+ print("%s %s" % (typename, qname), end=" ")
+
+ r = dns.message.make_response(m)
+ r.set_rcode(NOERROR)
+ if rrtype == A:
+ # exempt potential nameserver A records.
+ if labels[0] == "ns" and ns10:
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10"))
+ else:
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.9"))
+ if not tcp and labels[0] == "nocookie":
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10"))
+ if not tcp and labels[0] == "tcponly":
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10"))
+ if first and not tcp and labels[0] == "withtsig":
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10"))
+ dopass2 = True
+ elif rrtype == NS:
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, NS, "."))
+ elif rrtype == SOA:
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, SOA, ". . 0 0 0 0 0"))
+ else:
+ r.authority.append(dns.rrset.from_text(qname, 1, IN, SOA, ". . 0 0 0 0 0"))
+ # Add a server cookie to the response
+ if labels[0] != "nocookie":
+ for o in m.options:
+ if o.otype == 10: # Use 10 instead of COOKIE
+ if first and labels[0] == "withtsig" and not tcp:
+ r.use_tsig(
+ keyring=keyring,
+ keyname=dns.name.from_text("fake"),
+ algorithm=HMAC_SHA256,
+ )
+ elif labels[0] != "tcponly" or tcp:
+ cookie = o
+ if len(o.data) == 8:
+ cookie.data = o.data + o.data
+ else:
+ cookie.data = o.data
+ r.use_edns(options=[cookie])
+ r.flags |= dns.flags.AA
+ 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_addr1 = "10.53.0.9"
+ip4_addr2 = "10.53.0.10"
+ip6_addr1 = "fd92:7065:b8e:ffff::9"
+ip6_addr2 = "fd92:7065:b8e:ffff::10"
+
+try:
+ port = int(os.environ["PORT"])
+except:
+ port = 5300
+
+query4_udp1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+query4_udp1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+query4_udp1.bind((ip4_addr1, port))
+query4_tcp1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+query4_tcp1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+query4_tcp1.bind((ip4_addr1, port))
+query4_tcp1.listen(1)
+query4_tcp1.settimeout(1)
+
+query4_udp2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+query4_udp2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+query4_udp2.bind((ip4_addr2, port))
+query4_tcp2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+query4_tcp2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+query4_tcp2.bind((ip4_addr2, port))
+query4_tcp2.listen(1)
+query4_tcp2.settimeout(1)
+
+havev6 = True
+query6_udp1 = None
+query6_udp2 = None
+query6_tcp1 = None
+query6_tcp2 = None
+try:
+ query6_udp1 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
+ query6_udp1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ query6_udp1.bind((ip6_addr1, port))
+ query6_tcp1 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+ query6_tcp1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ query6_tcp1.bind((ip6_addr1, port))
+ query6_tcp1.listen(1)
+ query6_tcp1.settimeout(1)
+
+ query6_udp2 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
+ query6_udp2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ query6_udp2.bind((ip6_addr2, port))
+ query6_tcp2 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+ query6_tcp2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ query6_tcp2.bind((ip6_addr2, port))
+ query6_tcp2.listen(1)
+ query6_tcp2.settimeout(1)
+except:
+ if query6_udp1 != None:
+ query6_udp1.close()
+ if query6_tcp1 != None:
+ query6_tcp1.close()
+ if query6_udp2 != None:
+ query6_udp2.close()
+ if query6_tcp2 != None:
+ query6_tcp2.close()
+ havev6 = False
+
+signal.signal(signal.SIGTERM, sigterm)
+
+f = open("ans.pid", "w")
+pid = os.getpid()
+print(pid, file=f)
+f.close()
+
+running = True
+
+print("Using DNS version %s" % dns.version.version)
+print("Listening on %s port %d" % (ip4_addr1, port))
+print("Listening on %s port %d" % (ip4_addr2, port))
+if havev6:
+ print("Listening on %s port %d" % (ip6_addr1, port))
+ print("Listening on %s port %d" % (ip6_addr2, port))
+print("Ctrl-c to quit")
+
+if havev6:
+ input = [
+ query4_udp1,
+ query6_udp1,
+ query4_tcp1,
+ query6_tcp1,
+ query4_udp2,
+ query6_udp2,
+ query4_tcp2,
+ query6_tcp2,
+ ]
+else:
+ input = [query4_udp1, query4_tcp1, query4_udp2, query4_tcp2]
+
+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:
+ ns10 = False
+ if s == query4_udp1 or s == query6_udp1 or s == query4_udp2 or s == query6_udp2:
+ if s == query4_udp1 or s == query6_udp1:
+ print(
+ "UDP Query received on %s"
+ % (ip4_addr1 if s == query4_udp1 else ip6_addr1),
+ end=" ",
+ )
+ if s == query4_udp2 or s == query6_udp2:
+ print(
+ "UDP Query received on %s"
+ % (ip4_addr2 if s == query4_udp2 else ip6_addr2),
+ end=" ",
+ )
+ ns10 = True
+ # Handle incoming queries
+ msg = s.recvfrom(65535)
+ dopass2 = False
+ rsp = create_response(msg[0], False, True, ns10)
+ print(dns.rcode.to_text(rsp.rcode()))
+ s.sendto(rsp.to_wire(), msg[1])
+ if dopass2:
+ print("Sending second UDP response without TSIG", end=" ")
+ rsp = create_response(msg[0], False, False, ns10)
+ s.sendto(rsp.to_wire(), msg[1])
+ print(dns.rcode.to_text(rsp.rcode()))
+
+ if s == query4_tcp1 or s == query6_tcp1 or s == query4_tcp2 or s == query6_tcp2:
+ try:
+ (cs, _) = s.accept()
+ if s == query4_tcp1 or s == query6_tcp1:
+ print(
+ "TCP Query received on %s"
+ % (ip4_addr1 if s == query4_tcp1 else ip6_addr1),
+ end=" ",
+ )
+ if s == query4_tcp2 or s == query6_tcp2:
+ print(
+ "TCP Query received on %s"
+ % (ip4_addr2 if s == query4_tcp2 else ip6_addr2),
+ end=" ",
+ )
+ ns10 = True
+ # get TCP message length
+ buf = cs.recv(2)
+ length = struct.unpack(">H", buf[:2])[0]
+ # grep DNS message
+ msg = cs.recv(length)
+ rsp = create_response(msg, True, True, ns10)
+ print(dns.rcode.to_text(rsp.rcode()))
+ wire = rsp.to_wire()
+ cs.send(struct.pack(">H", len(wire)))
+ cs.send(wire)
+ cs.close()
+ except s.timeout:
+ pass
+ if not running:
+ break
diff --git a/bin/tests/system/cookie/bad-cookie-badaes.conf b/bin/tests/system/cookie/bad-cookie-badaes.conf
new file mode 100644
index 0000000..7d8cfe3
--- /dev/null
+++ b/bin/tests/system/cookie/bad-cookie-badaes.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ cookie-algorithm aes;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733faaa"; // 136 bits
+};
diff --git a/bin/tests/system/cookie/bad-cookie-badhex.conf b/bin/tests/system/cookie/bad-cookie-badhex.conf
new file mode 100644
index 0000000..43c11ad
--- /dev/null
+++ b/bin/tests/system/cookie/bad-cookie-badhex.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ cookie-secret "012345678901234567890123456789012345678901234567890123456789012";
+};
diff --git a/bin/tests/system/cookie/bad-cookie-badsiphash24.conf b/bin/tests/system/cookie/bad-cookie-badsiphash24.conf
new file mode 100644
index 0000000..25ff78f
--- /dev/null
+++ b/bin/tests/system/cookie/bad-cookie-badsiphash24.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ cookie-algorithm siphash24;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733faaabbccdd"; // 160 bits
+};
diff --git a/bin/tests/system/cookie/bad-cookie-toolong.conf b/bin/tests/system/cookie/bad-cookie-toolong.conf
new file mode 100644
index 0000000..5ea67b9
--- /dev/null
+++ b/bin/tests/system/cookie/bad-cookie-toolong.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ cookie-secret "01234567890123456789012345678901234567890123456789012345678901234567890";
+};
diff --git a/bin/tests/system/cookie/clean.sh b/bin/tests/system/cookie/clean.sh
new file mode 100644
index 0000000..d0675aa
--- /dev/null
+++ b/bin/tests/system/cookie/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.conf
+rm -f dig.out.*
+rm -f named.run.*
+rm -f rndc.out.*
+rm -f ns1/named_dump.db*
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.run.prev
+rm -f ans*/ans.run ans*/ans.log
diff --git a/bin/tests/system/cookie/good-cookie-aes.conf b/bin/tests/system/cookie/good-cookie-aes.conf
new file mode 100644
index 0000000..97a6f67
--- /dev/null
+++ b/bin/tests/system/cookie/good-cookie-aes.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ cookie-algorithm aes;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733fa"; // 128 bits
+};
diff --git a/bin/tests/system/cookie/good-cookie-siphash24.conf b/bin/tests/system/cookie/good-cookie-siphash24.conf
new file mode 100644
index 0000000..c937d71
--- /dev/null
+++ b/bin/tests/system/cookie/good-cookie-siphash24.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ cookie-algorithm siphash24;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733fa"; // 128 bits
+};
diff --git a/bin/tests/system/cookie/ns1/example.db b/bin/tests/system/cookie/ns1/example.db
new file mode 100644
index 0000000..75a6d3c
--- /dev/null
+++ b/bin/tests/system/cookie/ns1/example.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA ns1 hostmaster.isc.org. 1 600 600 1200 600
+@ NS ns1
+ns1 A 10.53.0.1
+large TXT ( large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large )
diff --git a/bin/tests/system/cookie/ns1/named.conf.in b/bin/tests/system/cookie/ns1/named.conf.in
new file mode 100644
index 0000000..025f8d0
--- /dev/null
+++ b/bin/tests/system/cookie/ns1/named.conf.in
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+key foo {
+ secret "aaaaaaaaaaaa";
+ algorithm hmac-sha256;
+};
+
+server 10.53.0.10 {
+ keys foo;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 yes;
+ dnssec-validation yes;
+ deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; }
+ except-from { "example.org"; };
+ deny-answer-aliases { "example.org"; }
+ except-from { "goodcname.example.net";
+ "gooddname.example.net"; };
+ allow-query {!10.53.0.8; any; };
+ send-cookie yes;
+ nocookie-udp-size 512;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/cookie/ns1/root.hint b/bin/tests/system/cookie/ns1/root.hint
new file mode 100644
index 0000000..993227d
--- /dev/null
+++ b/bin/tests/system/cookie/ns1/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.2
diff --git a/bin/tests/system/cookie/ns2/named.conf.in b/bin/tests/system/cookie/ns2/named.conf.in
new file mode 100644
index 0000000..cd74d8a
--- /dev/null
+++ b/bin/tests/system/cookie/ns2/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ send-cookie yes;
+ nocookie-udp-size 512;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/cookie/ns2/root.db b/bin/tests/system/cookie/ns2/root.db
new file mode 100644
index 0000000..533ab88
--- /dev/null
+++ b/bin/tests/system/cookie/ns2/root.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA a.root-servers.nil. hostmaster.isc.org. 1 600 600 1200 600
+@ NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.2
+large.xxx TXT ( large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large )
+tld. NS ns.tld.
+ns.tld A 10.53.0.9
+tsig. NS ns.tsig.
+ns.tsig A 10.53.0.10
diff --git a/bin/tests/system/cookie/ns3/named.conf.in b/bin/tests/system/cookie/ns3/named.conf.in
new file mode 100644
index 0000000..090d528
--- /dev/null
+++ b/bin/tests/system/cookie/ns3/named.conf.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation yes;
+ deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; }
+ except-from { "example.org"; };
+ deny-answer-aliases { "example.org"; }
+ except-from { "goodcname.example.net";
+ "gooddname.example.net"; };
+ allow-query {!10.53.0.8; any; };
+ send-cookie yes;
+ nocookie-udp-size 512;
+ require-server-cookie yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/cookie/ns3/root.hint b/bin/tests/system/cookie/ns3/root.hint
new file mode 100644
index 0000000..993227d
--- /dev/null
+++ b/bin/tests/system/cookie/ns3/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.2
diff --git a/bin/tests/system/cookie/ns4/named.conf.in b/bin/tests/system/cookie/ns4/named.conf.in
new file mode 100644
index 0000000..c49b87e
--- /dev/null
+++ b/bin/tests/system/cookie/ns4/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation yes;
+ cookie-algorithm siphash24;
+ cookie-secret "569d36a6cc27d6bf55502183302ba352";
+ require-server-cookie yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/cookie/ns4/root.hint b/bin/tests/system/cookie/ns4/root.hint
new file mode 100644
index 0000000..993227d
--- /dev/null
+++ b/bin/tests/system/cookie/ns4/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.2
diff --git a/bin/tests/system/cookie/ns5/named.conf.in b/bin/tests/system/cookie/ns5/named.conf.in
new file mode 100644
index 0000000..87210ad
--- /dev/null
+++ b/bin/tests/system/cookie/ns5/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation yes;
+ cookie-algorithm siphash24;
+ cookie-secret "569d36a6cc27d6bf55502183302ba352";
+ cookie-secret "6b300e27a0db46d4b046e4189790fa7d";
+ require-server-cookie yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/cookie/ns5/root.hint b/bin/tests/system/cookie/ns5/root.hint
new file mode 100644
index 0000000..993227d
--- /dev/null
+++ b/bin/tests/system/cookie/ns5/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.2
diff --git a/bin/tests/system/cookie/ns6/named.conf.in b/bin/tests/system/cookie/ns6/named.conf.in
new file mode 100644
index 0000000..158d898
--- /dev/null
+++ b/bin/tests/system/cookie/ns6/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ 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.6; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ cookie-algorithm siphash24;
+ cookie-secret "6b300e27a0db46d4b046e4189790fa7d";
+ require-server-cookie yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/cookie/ns6/root.hint b/bin/tests/system/cookie/ns6/root.hint
new file mode 100644
index 0000000..993227d
--- /dev/null
+++ b/bin/tests/system/cookie/ns6/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.2
diff --git a/bin/tests/system/cookie/ns7/named.conf.in b/bin/tests/system/cookie/ns7/named.conf.in
new file mode 100644
index 0000000..45f19b8
--- /dev/null
+++ b/bin/tests/system/cookie/ns7/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.7;
+ notify-source 10.53.0.7;
+ transfer-source 10.53.0.7;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.7; };
+ listen-on-v6 { none; };
+ recursion no;
+ answer-cookie no;
+ send-cookie yes;
+ nocookie-udp-size 512;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/cookie/ns7/root.db b/bin/tests/system/cookie/ns7/root.db
new file mode 100644
index 0000000..39a63da
--- /dev/null
+++ b/bin/tests/system/cookie/ns7/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA a.root-servers.nil. hostmaster.isc.org. 1 600 600 1200 600
+@ NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.2
+large.xxx TXT ( large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large
+ large large large large large large large large )
diff --git a/bin/tests/system/cookie/ns8/example.db b/bin/tests/system/cookie/ns8/example.db
new file mode 100644
index 0000000..7fa64d6
--- /dev/null
+++ b/bin/tests/system/cookie/ns8/example.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA . . 0 0 0 0 0
+@ 3600 NS .
diff --git a/bin/tests/system/cookie/ns8/named.conf.in b/bin/tests/system/cookie/ns8/named.conf.in
new file mode 100644
index 0000000..99ff66b
--- /dev/null
+++ b/bin/tests/system/cookie/ns8/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.8;
+ notify-source 10.53.0.8;
+ transfer-source 10.53.0.8;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.8; };
+ listen-on-v6 { none; };
+ dnssec-validation yes;
+ rate-limit {};
+ require-server-cookie yes;
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/cookie/setup.sh b/bin/tests/system/cookie/setup.sh
new file mode 100644
index 0000000..88c7518
--- /dev/null
+++ b/bin/tests/system/cookie/setup.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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
+copy_setports ns8/named.conf.in ns8/named.conf
diff --git a/bin/tests/system/cookie/tests.sh b/bin/tests/system/cookie/tests.sh
new file mode 100755
index 0000000..489a248
--- /dev/null
+++ b/bin/tests/system/cookie/tests.sh
@@ -0,0 +1,550 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+getcookie() {
+ awk '$2 == "COOKIE:" {
+ print $3;
+ }' < $1
+}
+
+fullcookie() {
+ awk 'BEGIN { n = 0 }
+ // { v[n++] = length(); }
+ END { print (v[1] == v[2]); }'
+}
+
+havetc() {
+ grep 'flags:.* tc[^;]*;' $1 > /dev/null
+}
+
+for bad in bad*.conf
+do
+ n=$((n + 1))
+ echo_i "checking that named-checkconf detects error in $bad ($n)"
+ ret=0
+ $CHECKCONF $bad > /dev/null 2>&1 && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+for good in good*.conf
+do
+ n=$((n + 1))
+ echo_i "checking that named-checkconf detects accepts $good ($n)"
+ ret=0
+ $CHECKCONF $good > /dev/null 2>&1 || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+n=$((n + 1))
+echo_i "checking RCODE=FORMERR to query without question section and without COOKIE option ($n)"
+ret=0
+$DIG $DIGOPTS +qr +header-only +nocookie version.bind txt ch @10.53.0.1 > dig.out.test$n || ret=1
+grep COOKIE: dig.out.test$n > /dev/null && ret=1
+grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking RCODE=NOERROR to query without question section and with COOKIE option ($n)"
+ret=0
+$DIG $DIGOPTS +qr +header-only +cookie version.bind txt ch @10.53.0.1 > dig.out.test$n || ret=1
+grep COOKIE: dig.out.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking COOKIE token is returned to empty COOKIE option ($n)"
+ret=0
+$DIG $DIGOPTS +cookie version.bind txt ch @10.53.0.1 > dig.out.test$n || ret=1
+grep COOKIE: dig.out.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking COOKIE is not returned when answer-cookie is false ($n)"
+ret=0
+$DIG $DIGOPTS +cookie version.bind txt ch @10.53.0.7 > dig.out.test$n || ret=1
+grep COOKIE: dig.out.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking response size without COOKIE ($n)"
+ret=0
+$DIG $DIGOPTS large.example txt @10.53.0.1 +ignore > dig.out.test$n || ret=1
+havetc dig.out.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking response size without valid COOKIE ($n)"
+ret=0
+$DIG $DIGOPTS +cookie large.example txt @10.53.0.1 +ignore > dig.out.test$n || ret=1
+havetc dig.out.test$n || ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking response size with COOKIE ($n)"
+ret=0
+$DIG $DIGOPTS +cookie large.example txt @10.53.0.1 > dig.out.test$n.l || ret=1
+cookie=$(getcookie dig.out.test$n.l)
+$DIG $DIGOPTS +qr +cookie=$cookie large.example txt @10.53.0.1 +ignore > dig.out.test$n || ret=1
+havetc dig.out.test$n && ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking response size with COOKIE recursive ($n)"
+ret=0
+$DIG $DIGOPTS +qr +cookie=$cookie large.xxx txt @10.53.0.1 +ignore > dig.out.test$n || ret=1
+havetc dig.out.test$n && ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking COOKIE is learnt for TCP retry ($n)"
+ret=0
+$DIG $DIGOPTS +qr +cookie large.example txt @10.53.0.1 > dig.out.test$n || ret=1
+linecount=$(getcookie dig.out.test$n | wc -l)
+if [ $linecount != 3 ]; then ret=1; fi
+checkfull=$(getcookie dig.out.test$n | fullcookie)
+if [ $checkfull != 1 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking for COOKIE value in adb ($n)"
+ret=0
+rndc_dumpdb ns1
+grep "10.53.0.2.*\[cookie=" ns1/named_dump.db.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking require-server-cookie default (no) ($n)"
+ret=0
+$DIG $DIGOPTS +qr +cookie +nobadcookie soa @10.53.0.1 > dig.out.test$n || ret=1
+grep BADCOOKIE dig.out.test$n > /dev/null && ret=1
+linecount=$(getcookie dig.out.test$n | wc -l)
+if [ $linecount != 2 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking require-server-cookie yes ($n)"
+ret=0
+$DIG $DIGOPTS +qr +cookie +nobadcookie soa @10.53.0.3 > dig.out.test$n || ret=1
+grep "flags: qr[^;]* aa[ ;]" dig.out.test$n > /dev/null && ret=1
+grep "flags: qr[^;]* ad[ ;]" dig.out.test$n > /dev/null && ret=1
+grep BADCOOKIE dig.out.test$n > /dev/null || ret=1
+linecount=$(getcookie dig.out.test$n | wc -l)
+if [ $linecount != 2 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking +qr +showbadcookie ($n)"
+ret=0
+$DIG $DIGOPTS +qr +cookie +showbadcookie soa @10.53.0.3 > dig.out.test$n || ret=1
+noerror=$(grep "status: NOERROR" dig.out.test$n | wc -l)
+badcookie=$(grep "status: BADCOOKIE" dig.out.test$n | wc -l)
+server=$(grep "COOKIE: ................................................" dig.out.test$n | wc -l)
+good=$(grep "COOKIE: ................................................ (good)" dig.out.test$n | wc -l)
+linecount=$(getcookie dig.out.test$n | wc -l)
+if [ $noerror != 3 ]; then ret=1; fi
+if [ $badcookie != 1 ]; then ret=1; fi
+if [ $server != 3 ]; then ret=1; fi
+if [ $good != 2 ]; then ret=1; fi
+if [ $linecount != 4 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking +showbadcookie ($n)"
+ret=0
+$DIG $DIGOPTS +cookie +showbadcookie soa @10.53.0.3 > dig.out.test$n || ret=1
+noerror=$(grep "status: NOERROR" dig.out.test$n | wc -l)
+badcookie=$(grep "status: BADCOOKIE" dig.out.test$n | wc -l)
+server=$(grep "COOKIE: ................................................" dig.out.test$n | wc -l)
+good=$(grep "COOKIE: ................................................ (good)" dig.out.test$n | wc -l)
+linecount=$(getcookie dig.out.test$n | wc -l)
+if [ $noerror != 1 ]; then ret=1; fi
+if [ $badcookie != 1 ]; then ret=1; fi
+if [ $server != 2 ]; then ret=1; fi
+if [ $good != 2 ]; then ret=1; fi
+if [ $linecount != 2 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking require-server-cookie yes with rate-limit ($n)"
+ret=0
+$DIG $DIGOPTS +qr +cookie +nobadcookie soa example @10.53.0.8 > dig.out.test$n || ret=1
+grep "flags: qr[^;]* ad[ ;]" dig.out.test$n > /dev/null && ret=1
+grep BADCOOKIE dig.out.test$n > /dev/null || ret=1
+linecount=$(getcookie dig.out.test$n | wc -l)
+if [ $linecount != 2 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "send undersized cookie ($n)"
+ret=0
+$DIG $DIGOPTS +qr +cookie=000000 soa @10.53.0.1 > dig.out.test$n || ret=1
+grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "send oversized for named cookie ($n)"
+ret=0
+$DIG $DIGOPTS +qr +cookie=${cookie}00 soa @10.53.0.1 > dig.out.test$n || ret=1
+grep "COOKIE: [a-f0-9]* (good)" dig.out.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "send oversized for named cookie with server requiring a good cookie ($n)"
+ret=0
+$DIG $DIGOPTS +qr +cookie=${cookie}00 soa @10.53.0.3 > dig.out.test$n || ret=1
+grep "COOKIE: [a-f0-9]* (good)" dig.out.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#
+# Test shared cookie-secret support.
+#
+# NS4 has cookie-secret "569d36a6cc27d6bf55502183302ba352";
+#
+# NS5 has cookie-secret "569d36a6cc27d6bf55502183302ba352";
+# NS5 has cookie-secret "6b300e27a0db46d4b046e4189790fa7d"; (alternate)
+#
+# NS6 has cookie-secret "6b300e27a0db46d4b046e4189790fa7d";
+#
+# Server cookies from NS4 are accepted by NS5 and not NS6
+# Server cookies from NS5 are accepted by NS4 and not NS6
+# Server cookies from NS6 are accepted by NS5 and not NS4
+#
+# Force local address so that the client's address is the same to all servers.
+#
+
+n=$((n + 1))
+echo_i "get NS4 cookie for cross server checking ($n)"
+ret=0
+$DIG $DIGOPTS +cookie -b 10.53.0.4 soa . @10.53.0.4 > dig.out.test$n || ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+ns4cookie=$(getcookie dig.out.test$n)
+test -n "$ns4cookie" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "get NS5 cookie for cross server checking ($n)"
+ret=0
+$DIG $DIGOPTS +cookie -b 10.53.0.4 soa . @10.53.0.5 > dig.out.test$n || ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+ns5cookie=$(getcookie dig.out.test$n)
+test -n "$ns5cookie" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "get NS6 cookie for cross server checking ($n)"
+ret=0
+$DIG $DIGOPTS +cookie -b 10.53.0.4 soa . @10.53.0.6 > dig.out.test$n || ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+ns6cookie=$(getcookie dig.out.test$n)
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "test NS4 cookie on NS5 (expect success) ($n)"
+ret=0
+$DIG $DIGOPTS +cookie=$ns4cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.5 > dig.out.test$n || ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "test NS4 cookie on NS6 (expect badcookie) ($n)"
+ret=0
+$DIG $DIGOPTS +cookie=$ns4cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.6 > dig.out.test$n || ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+grep "status: BADCOOKIE," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "test NS5 cookie on NS4 (expect success) ($n)"
+ret=0
+$DIG $DIGOPTS +cookie=$ns5cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.4 > dig.out.test$n || ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "test NS5 cookie on NS6 (expect badcookie) ($n)"
+ret=0
+$DIG $DIGOPTS +cookie=$ns5cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.6 > dig.out.test$n || ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+grep "status: BADCOOKIE," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "test NS6 cookie on NS4 (expect badcookie) ($n)"
+ret=0
+$DIG $DIGOPTS +cookie=$ns6cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.4 > dig.out.test$n || ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+grep "status: BADCOOKIE," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "test NS6 cookie on NS5 (expect success) ($n)"
+ret=0
+$DIG $DIGOPTS +cookie=$ns6cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.5 > dig.out.test$n || ret=1
+grep "; COOKIE:.*(good)" dig.out.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that test server is correctly configured ($n)"
+ret=0
+pat="; COOKIE: ................................ (good)"
+#UDP
+$DIG $DIGOPTS @10.53.0.9 +notcp tld > dig.out.test$n.1 || ret=1
+grep "status: NOERROR" dig.out.test$n.1 > /dev/null || ret=1
+grep "$pat" dig.out.test$n.1 > /dev/null || ret=1
+grep 'A.10\.53\.0\.9' dig.out.test$n.1 > /dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.test$n.1 > /dev/null && ret=1
+grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 > /dev/null && ret=1
+
+$DIG $DIGOPTS @10.53.0.9 +notcp tcponly.tld > dig.out.test$n.2 || ret=1
+grep "status: NOERROR" dig.out.test$n.2 > /dev/null || ret=1
+grep "; COOKIE:" dig.out.test$n.2 > /dev/null && ret=1
+grep 'A.10\.53\.0\.9' dig.out.test$n.2 > /dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.test$n.2 > /dev/null || ret=1
+grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 > /dev/null && ret=1
+
+$DIG $DIGOPTS @10.53.0.9 +notcp nocookie.tld > dig.out.test$n.3 || ret=1
+grep "status: NOERROR" dig.out.test$n.3 > /dev/null || ret=1
+grep "; COOKIE:" dig.out.test$n.3 > /dev/null && ret=1
+grep 'A.10\.53\.0\.9' dig.out.test$n.3 > /dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.test$n.3 > /dev/null || ret=1
+grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 > /dev/null && ret=1
+
+$DIG $DIGOPTS @10.53.0.9 +notcp withtsig.tld > dig.out.test$n.4 || ret=1
+grep "status: NOERROR" dig.out.test$n.4 > /dev/null || ret=1
+grep "; COOKIE:" dig.out.test$n.4 > /dev/null && ret=1
+grep 'A.10\.53\.0\.9' dig.out.test$n.4 > /dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.test$n.4 > /dev/null || ret=1
+grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.4 > /dev/null || ret=1
+
+#TCP
+$DIG $DIGOPTS @10.53.0.9 +tcp tld > dig.out.test$n.5 || ret=1
+grep "status: NOERROR" dig.out.test$n.5 > /dev/null || ret=1
+grep "$pat" dig.out.test$n.5 > /dev/null || ret=1
+grep 'A.10\.53\.0\.9' dig.out.test$n.5 > /dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.test$n.5 > /dev/null && ret=1
+grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 > /dev/null && ret=1
+
+$DIG $DIGOPTS @10.53.0.9 +tcp tcponly.tld > dig.out.test$n.6
+grep "status: NOERROR" dig.out.test$n.6 > /dev/null || ret=1
+grep "$pat" dig.out.test$n.6 > /dev/null || ret=1
+grep 'A.10\.53\.0\.9' dig.out.test$n.6 > /dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.test$n.6 > /dev/null && ret=1
+grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 > /dev/null && ret=1
+
+$DIG $DIGOPTS @10.53.0.9 +tcp nocookie.tld > dig.out.test$n.7
+grep "status: NOERROR" dig.out.test$n.7 > /dev/null || ret=1
+grep "; COOKIE:" dig.out.test$n.7 > /dev/null && ret=1
+grep 'A.10\.53\.0\.9' dig.out.test$n.7 > /dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.test$n.7 > /dev/null && ret=1
+grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 > /dev/null && ret=1
+
+$DIG $DIGOPTS @10.53.0.9 +tcp withtsig.tld > dig.out.test$n.8
+grep "status: NOERROR" dig.out.test$n.8 > /dev/null || ret=1
+grep "$pat" dig.out.test$n.8 > /dev/null || ret=1
+grep 'A.10\.53\.0\.9' dig.out.test$n.8 > /dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.test$n.8 > /dev/null && ret=1
+grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.8 > /dev/null && ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that spoofed response is dropped when we have a server cookie ($n)"
+ret=0
+msg="missing expected cookie from"
+pat='10\.53\.0\.9 .*\[cookie=................................\] \[ttl'
+# prime EDNS COOKIE state
+$DIG $DIGOPTS @10.53.0.1 tld > dig.out.test$n.1 || ret=1
+grep "status: NOERROR" dig.out.test$n.1 > /dev/null || ret=1
+rndc_dumpdb ns1
+grep "$pat" ns1/named_dump.db.test$n > /dev/null || ret=1
+# spoofed response contains 10.53.0.10
+nextpart ns1/named.run >/dev/null
+$DIG $DIGOPTS @10.53.0.1 tcponly.tld > dig.out.test$n.2 || ret=1
+wait_for_log 5 "$msg" ns1/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n.2 > /dev/null || ret=1
+grep 'A.10\.53\.0\.9' dig.out.test$n.2 > /dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.test$n.2 > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that gracefully handle server disabling DNS COOKIE we have a server cookie ($n)"
+ret=0
+msg="missing expected cookie from"
+pat='10\.53\.0\.9 .*\[cookie=................................\] \[ttl'
+# prime EDNS COOKIE state
+$DIG $DIGOPTS @10.53.0.1 tld > dig.out.test$n.1 || ret=1
+grep "status: NOERROR" dig.out.test$n.1 > /dev/null || ret=1
+rndc_dumpdb ns1
+grep "$pat" ns1/named_dump.db.test$n > /dev/null || ret=1
+# check the disabled server response
+nextpart ns1/named.run >/dev/null
+$DIG $DIGOPTS @10.53.0.1 nocookie.tld > dig.out.test$n.2
+wait_for_log 5 "$msg" ns1/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n.2 > /dev/null || ret=1
+grep 'A.10\.53\.0\.9' dig.out.test$n.2 > /dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.test$n.2 > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that spoofed response with a TSIG is dropped when we have a server cookie ($n)"
+ret=0
+pat='10\.53\.0\.9 .*\[cookie=................................\] \[ttl'
+# prime EDNS COOKIE state
+$DIG $DIGOPTS @10.53.0.1 tld > dig.out.test$n.1 || ret=1
+grep "status: NOERROR" dig.out.test$n.1 > /dev/null || ret=1
+rndc_dumpdb ns1
+grep "$pat" ns1/named_dump.db.test$n > /dev/null || ret=1
+# spoofed response contains 10.53.0.10
+nextpart ns1/named.run >/dev/null
+$DIG $DIGOPTS @10.53.0.1 withtsig.tld > dig.out.test$n.2 || ret=1
+grep "status: NOERROR" dig.out.test$n.2 > /dev/null || ret=1
+grep 'A.10\.53\.0\.9' dig.out.test$n.2 > /dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.test$n.2 > /dev/null && ret=1
+nextpart ns1/named.run > named.run.test$n
+count=$(grep -c ') [0-9][0-9]* NOERROR 0' named.run.test$n)
+test $count -eq 1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if $PYTHON -c '
+import dns.version, sys;
+if dns.version.MAJOR > 1: sys.exit(0);
+if dns.version.MAJOR == 1 and dns.version.MINOR >= 16: sys.exit(0);
+sys.exit(1)'
+then
+ n=$((n + 1))
+ echo_i "check that TSIG test server is correctly configured ($n)"
+ ret=0
+ pat="; COOKIE: ................................ (good)"
+ key=hmac-sha256:foo:aaaaaaaaaaaa
+ #UDP
+ $DIG $DIGOPTS @10.53.0.10 -y $key +notcp tsig. > dig.out.test$n.1 || ret=1
+ grep "status: NOERROR" dig.out.test$n.1 > /dev/null || ret=1
+ grep "$pat" dig.out.test$n.1 > /dev/null || ret=1
+ grep 'A.10\.53\.0\.9' dig.out.test$n.1 > /dev/null || ret=1
+ grep 'A.10\.53\.0\.10' dig.out.test$n.1 > /dev/null && ret=1
+ grep 'TSIG.*NOERROR' dig.out.test$n.1 > /dev/null || ret=1
+
+ $DIG $DIGOPTS @10.53.0.10 -y $key +notcp tcponly.tsig > dig.out.test$n.2 || ret=1
+ grep "status: NOERROR" dig.out.test$n.2 > /dev/null || ret=1
+ grep "; COOKIE:" dig.out.test$n.2 > /dev/null && ret=1
+ grep 'A.10\.53\.0\.9' dig.out.test$n.2 > /dev/null || ret=1
+ grep 'A.10\.53\.0\.10' dig.out.test$n.2 > /dev/null || ret=1
+ grep 'TSIG.*NOERROR' dig.out.test$n.1 > /dev/null || ret=1
+
+ $DIG $DIGOPTS @10.53.0.10 -y $key +notcp nocookie.tsig > dig.out.test$n.3 || ret=1
+ grep "status: NOERROR" dig.out.test$n.3 > /dev/null || ret=1
+ grep "; COOKIE:" dig.out.test$n.3 > /dev/null && ret=1
+ grep 'A.10\.53\.0\.9' dig.out.test$n.3 > /dev/null || ret=1
+ grep 'A.10\.53\.0\.10' dig.out.test$n.3 > /dev/null || ret=1
+ grep 'TSIG.*NOERROR' dig.out.test$n.1 > /dev/null || ret=1
+
+ #TCP
+ $DIG $DIGOPTS @10.53.0.10 -y $key +tcp tsig. > dig.out.test$n.5 || ret=1
+ grep "status: NOERROR" dig.out.test$n.5 > /dev/null || ret=1
+ grep "$pat" dig.out.test$n.5 > /dev/null || ret=1
+ grep 'A.10\.53\.0\.9' dig.out.test$n.5 > /dev/null || ret=1
+ grep 'A.10\.53\.0\.10' dig.out.test$n.5 > /dev/null && ret=1
+ grep 'TSIG.*NOERROR' dig.out.test$n.1 > /dev/null || ret=1
+
+ $DIG $DIGOPTS @10.53.0.10 -y $key +tcp tcponly.tsig > dig.out.test$n.6 || ret=1
+ grep "status: NOERROR" dig.out.test$n.6 > /dev/null || ret=1
+ grep "$pat" dig.out.test$n.6 > /dev/null || ret=1
+ grep 'A.10\.53\.0\.9' dig.out.test$n.6 > /dev/null || ret=1
+ grep 'A.10\.53\.0\.10' dig.out.test$n.6 > /dev/null && ret=1
+ grep 'TSIG.*NOERROR' dig.out.test$n.1 > /dev/null || ret=1
+
+ $DIG $DIGOPTS @10.53.0.10 -y $key +tcp nocookie.tsig > dig.out.test$n.7 || ret=1
+ grep "status: NOERROR" dig.out.test$n.7 > /dev/null || ret=1
+ grep "; COOKIE:" dig.out.test$n.7 > /dev/null && ret=1
+ grep 'A.10\.53\.0\.9' dig.out.test$n.7 > /dev/null || ret=1
+ grep 'A.10\.53\.0\.10' dig.out.test$n.7 > /dev/null && ret=1
+ grep 'TSIG.*NOERROR' dig.out.test$n.1 > /dev/null || ret=1
+
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ n=$((n + 1))
+ echo_i "check that missing COOKIE with a valid TSIG signed response does not trigger TCP fallback ($n)"
+ ret=0
+ pat='10\.53\.0\.10 .*\[cookie=................................\] \[ttl'
+ # prime EDNS COOKIE state
+ $DIG $DIGOPTS @10.53.0.1 tsig. > dig.out.test$n.1
+ grep "status: NOERROR" dig.out.test$n.1 > /dev/null || ret=1
+ rndc_dumpdb ns1
+ grep "$pat" ns1/named_dump.db.test$n > /dev/null || ret=1
+ # check the disabled server response
+ nextpart ns1/named.run >/dev/null
+ $DIG $DIGOPTS @10.53.0.1 nocookie.tsig > dig.out.test$n.2
+ grep "status: NOERROR" dig.out.test$n.2 > /dev/null || ret=1
+ grep 'A.10\.53\.0\.9' dig.out.test$n.2 > /dev/null || ret=1
+ grep 'A.10\.53\.0\.10' dig.out.test$n.2 > /dev/null || ret=1
+ nextpart ns1/named.run > named.run.test$n
+ count=$(grep -c ') [0-9][0-9]* NOERROR 0' named.run.test$n)
+ test $count -eq 2 || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/cookie/tests_sh_cookie.py b/bin/tests/system/cookie/tests_sh_cookie.py
new file mode 100644
index 0000000..2f1d029
--- /dev/null
+++ b/bin/tests/system/cookie/tests_sh_cookie.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_cookie(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/custom-test-driver b/bin/tests/system/custom-test-driver
new file mode 100755
index 0000000..7499aa0
--- /dev/null
+++ b/bin/tests/system/custom-test-driver
@@ -0,0 +1,162 @@
+#!/bin/sh
+
+# test-driver - basic testsuite driver script.
+
+scriptversion=2021-09-20.08; # UTC
+
+# Copyright (C) 2011-2020 Free Software Foundation, Inc.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later WITH LicenseRef-Automake-exception-2.0
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+# Make unconditional expansion of undefined variables an error. This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+ echo "$0: $*" >&2
+ print_usage >&2
+ exit 2
+}
+
+print_usage ()
+{
+ cat <<END
+Usage:
+ test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+ [--expect-failure={yes|no}] [--color-tests={yes|no}]
+ [--enable-hard-errors={yes|no}] [--]
+ TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+test_name= # Used for reporting.
+log_file= # Where to save the output of the test script.
+trs_file= # Where to save the metadata of the test run.
+status_file= # Where to save the status of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+verbose=no
+while test $# -gt 0; do
+ case $1 in
+ --help) print_usage; exit $?;;
+ --version) echo "test-driver $scriptversion"; exit $?;;
+ --test-name) test_name=$2; shift;;
+ --log-file) log_file=$2; shift;;
+ --trs-file) trs_file=$2; shift;;
+ --status-file) status_file=$2; shift;;
+ --color-tests) color_tests=$2; shift;;
+ --expect-failure) expect_failure=$2; shift;;
+ --enable-hard-errors) enable_hard_errors=$2; shift;;
+ --verbose) verbose=$2; shift;;
+ --) shift; break;;
+ -*) usage_error "invalid option: '$1'";;
+ *) break;;
+ esac
+ shift
+done
+
+missing_opts=
+test x"$test_name" = x && missing_opts="$missing_opts --test-name"
+test x"$log_file" = x && missing_opts="$missing_opts --log-file"
+test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
+if test x"$missing_opts" != x; then
+ usage_error "the following mandatory options are missing:$missing_opts"
+fi
+
+if test $# -eq 0; then
+ usage_error "missing argument"
+fi
+
+if test $color_tests = yes; then
+ # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+ red='' # Red.
+ grn='' # Green.
+ lgn='' # Light green.
+ blu='' # Blue.
+ mgn='' # Magenta.
+ std='' # No color.
+else
+ red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file $status_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Set default
+test x"$status_file" = x && status_file=$(mktemp ./custom-test-runner.XXXXXX)
+# Test script is run here.
+if test $verbose = yes; then
+ ("$@" 2>&1; echo $? > "$status_file") | tee $log_file
+else
+ "$@" >$log_file 2>&1; echo $? > "$status_file"
+fi
+read -r estatus < "$status_file"
+rm "$status_file"
+
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+ tweaked_estatus=1
+else
+ tweaked_estatus=$estatus
+fi
+
+case $tweaked_estatus:$expect_failure in
+ 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+ 0:*) col=$grn res=PASS recheck=no gcopy=no;;
+ 77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
+ 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
+ *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
+ *:*) col=$red res=FAIL recheck=yes gcopy=yes;;
+esac
+
+# Report the test outcome and exit status in the logs, so that one can
+# know whether the test passed or failed simply by looking at the '.log'
+# file, without the need of also peaking into the corresponding '.trs'
+# file (automake bug#11814).
+echo "$res $test_name (exit status: $estatus)" >>$log_file
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/bin/tests/system/database/clean.sh b/bin/tests/system/database/clean.sh
new file mode 100644
index 0000000..f86404c
--- /dev/null
+++ b/bin/tests/system/database/clean.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns1/named.conf ns1/named.run ns1/named.memstats
+rm -f dig.out.*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/database/ns1/named1.conf.in b/bin/tests/system/database/ns1/named1.conf.in
new file mode 100644
index 0000000..5fa7ce5
--- /dev/null
+++ b/bin/tests/system/database/ns1/named1.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation yes;
+};
+
+zone "database" {
+ type primary;
+ database "_builtin empty localhost. hostmaster.isc.org.";
+};
diff --git a/bin/tests/system/database/ns1/named2.conf.in b/bin/tests/system/database/ns1/named2.conf.in
new file mode 100644
index 0000000..80cfab2
--- /dev/null
+++ b/bin/tests/system/database/ns1/named2.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation yes;
+};
+
+zone "database" {
+ type primary;
+ database "_builtin empty localhost. marka.isc.org.";
+};
diff --git a/bin/tests/system/database/setup.sh b/bin/tests/system/database/setup.sh
new file mode 100644
index 0000000..f3f0088
--- /dev/null
+++ b/bin/tests/system/database/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named1.conf.in ns1/named.conf
diff --git a/bin/tests/system/database/tests.sh b/bin/tests/system/database/tests.sh
new file mode 100644
index 0000000..408b094
--- /dev/null
+++ b/bin/tests/system/database/tests.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+RNDCCMD="$RNDC -s 10.53.0.1 -p ${CONTROLPORT} -c ../common/rndc.conf"
+
+# Check the example. domain
+
+echo_i "checking pre reload zone ($n)"
+ret=0
+$DIG $DIGOPTS soa database. @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "hostmaster\.isc\.org" dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+copy_setports ns1/named2.conf.in ns1/named.conf
+$RNDCCMD reload 2>&1 >/dev/null
+
+echo_i "checking post reload zone ($n)"
+ret=1
+try=0
+while test $try -lt 6
+do
+ sleep 1
+ ret=0
+ $DIG $DIGOPTS soa database. @10.53.0.1 > dig.out.ns1.test$n || ret=1
+ grep "marka\.isc\.org" dig.out.ns1.test$n > /dev/null || ret=1
+ try=$((try + 1))
+ test $ret -eq 0 && break
+done
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/database/tests_sh_database.py b/bin/tests/system/database/tests_sh_database.py
new file mode 100644
index 0000000..b48469e
--- /dev/null
+++ b/bin/tests/system/database/tests_sh_database.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_database(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/dialup/clean.sh b/bin/tests/system/dialup/clean.sh
new file mode 100644
index 0000000..9318255
--- /dev/null
+++ b/bin/tests/system/dialup/clean.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns2/example.bk
+rm -f ns3/example.bk
+rm -f */named.memstats */named.run
+rm -f ns*/named.conf
+rm -f ns*/named.lock
diff --git a/bin/tests/system/dialup/ns1/example.db b/bin/tests/system/dialup/ns1/example.db
new file mode 100644
index 0000000..3ce33f9
--- /dev/null
+++ b/bin/tests/system/dialup/ns1/example.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA hostmaster.ns1 ns1 (
+ 1 3600 1200 3600000 1200 )
+ NS ns1.example.
+ NS ns2.example.
+ NS ns3.example.
+ns1 A 10.53.0.1
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/dialup/ns1/named.conf.in b/bin/tests/system/dialup/ns1/named.conf.in
new file mode 100644
index 0000000..4b8302b
--- /dev/null
+++ b/bin/tests/system/dialup/ns1/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+ heartbeat-interval 2;
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example." {
+ type primary;
+ notify explicit;
+ also-notify { 10.53.0.2; };
+ dialup yes;
+ file "example.db";
+};
diff --git a/bin/tests/system/dialup/ns1/root.db b/bin/tests/system/dialup/ns1/root.db
new file mode 100644
index 0000000..882da96
--- /dev/null
+++ b/bin/tests/system/dialup/ns1/root.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA hostmaster.ns1.example ns1.example (
+ 1 3600 1200 3600000 1200 )
+ NS ns1.example
+example NS ns1.example
+ NS ns2.example
+ NS ns3.example
+ns1.example A 10.53.0.1
+ns2.example A 10.53.0.2
+ns3.example A 10.53.0.3
diff --git a/bin/tests/system/dialup/ns2/hint.db b/bin/tests/system/dialup/ns2/hint.db
new file mode 100644
index 0000000..0198f25
--- /dev/null
+++ b/bin/tests/system/dialup/ns2/hint.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 1200 NS ns1.example
+ns1.example A 10.53.0.1
diff --git a/bin/tests/system/dialup/ns2/named.conf.in b/bin/tests/system/dialup/ns2/named.conf.in
new file mode 100644
index 0000000..382f5ce
--- /dev/null
+++ b/bin/tests/system/dialup/ns2/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ heartbeat-interval 2;
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+zone "example." {
+ type secondary;
+ dialup passive;
+ notify no;
+ file "example.bk";
+ primaries { 10.53.0.1; };
+};
diff --git a/bin/tests/system/dialup/ns3/hint.db b/bin/tests/system/dialup/ns3/hint.db
new file mode 100644
index 0000000..0198f25
--- /dev/null
+++ b/bin/tests/system/dialup/ns3/hint.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 1200 NS ns1.example
+ns1.example A 10.53.0.1
diff --git a/bin/tests/system/dialup/ns3/named.conf.in b/bin/tests/system/dialup/ns3/named.conf.in
new file mode 100644
index 0000000..054a658
--- /dev/null
+++ b/bin/tests/system/dialup/ns3/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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; };
+ heartbeat-interval 2;
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+zone "example." {
+ type secondary;
+ dialup refresh;
+ notify no;
+ file "example.bk";
+ primaries { 10.53.0.2; };
+};
diff --git a/bin/tests/system/dialup/setup.sh b/bin/tests/system/dialup/setup.sh
new file mode 100644
index 0000000..dad3589
--- /dev/null
+++ b/bin/tests/system/dialup/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+copy_setports ns1/named.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/dialup/tests.sh b/bin/tests/system/dialup/tests.sh
new file mode 100644
index 0000000..b68c71e
--- /dev/null
+++ b/bin/tests/system/dialup/tests.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+
+rm -f dig.out.*
+
+DIGOPTS="+norec +tcp +noadd +nosea +nostat +noquest +nocmd -p ${PORT}"
+
+# Check the example. domain
+
+$DIG $DIGOPTS example. @10.53.0.1 soa > dig.out.ns1.test || ret=1
+echo_i "checking that first zone transfer worked"
+ret=0
+try=0
+while test $try -lt 120
+do
+ $DIG $DIGOPTS example. @10.53.0.2 soa > dig.out.ns2.test || ret=1
+ if grep SERVFAIL dig.out.ns2.test > /dev/null
+ then
+ try=$((try + 1))
+ sleep 1
+ else
+ digcomp dig.out.ns1.test dig.out.ns2.test || ret=1
+ break;
+ fi
+done
+echo_i "try $try"
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that second zone transfer worked"
+ret=0
+try=0
+while test $try -lt 120
+do
+ $DIG $DIGOPTS example. @10.53.0.3 soa > dig.out.ns3.test || ret=1
+ if grep SERVFAIL dig.out.ns3.test > /dev/null
+ then
+ try=$((try + 1))
+ sleep 1
+ else
+ digcomp dig.out.ns1.test dig.out.ns3.test || ret=1
+ break;
+ fi
+done
+echo_i "try $try"
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dialup/tests_sh_dialup.py b/bin/tests/system/dialup/tests_sh_dialup.py
new file mode 100644
index 0000000..fa28e86
--- /dev/null
+++ b/bin/tests/system/dialup/tests_sh_dialup.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_dialup(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/digcomp.pl b/bin/tests/system/digcomp.pl
new file mode 100644
index 0000000..8024dea
--- /dev/null
+++ b/bin/tests/system/digcomp.pl
@@ -0,0 +1,164 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Compare two files, each with the output from dig, for differences.
+# Ignore "unimportant" differences, like ordering of NS lines, TTL's,
+# etc...
+
+$lc = 0;
+if ($ARGV[0] eq "--lc") {
+ $lc = 1;
+ shift;
+}
+$file1 = $ARGV[0];
+$file2 = $ARGV[1];
+
+$count = 0;
+$firstname = "";
+$status = 0;
+$rcode1 = "none";
+$rcode2 = "none";
+
+open(FILE1, $file1) || die("open: $file1: $!\n");
+while (<FILE1>) {
+ ~ s/\r\n//g;
+ ~ s/\n//g;
+ if (/^;.+status:\s+(\S+).+$/) {
+ $rcode1 = $1;
+ }
+ next if (/^;/);
+ if (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+(.+)$/) {
+ $name = $1;
+ $class = $2;
+ $type = $3;
+ $value = $4;
+ if ($lc) {
+ $name = lc($name);
+ $value = lc($value);
+ }
+ if ($type eq "SOA") {
+ $firstname = $name if ($firstname eq "");
+ if ($name eq $firstname) {
+ $name = "$name$count";
+ $count++;
+ }
+ }
+ if ($entry{"$name ; $class.$type ; $value"} ne "") {
+ $line = $entry{"$name ; $class.$type ; $value"};
+ print("Duplicate entry in $file1:\n> $_\n< $line\n");
+ } else {
+ $entry{"$name ; $class.$type ; $value"} = $_;
+ }
+ } elsif (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s*$/) {
+ $name = $1;
+ $class = $2;
+ $type = $3;
+ $value = "";
+ if ($lc) {
+ $name = lc($name);
+ $value = lc($value);
+ }
+ if ($type eq "SOA") {
+ $firstname = $name if ($firstname eq "");
+ if ($name eq $firstname) {
+ $name = "$name$count";
+ $count++;
+ }
+ }
+ if ($entry{"$name ; $class.$type ; $value"} ne "") {
+ $line = $entry{"$name ; $class.$type ; $value"};
+ print("Duplicate entry in $file1:\n> $_\n< $line\n");
+ } else {
+ $entry{"$name ; $class.$type ; $value"} = $_;
+ }
+ }
+}
+close(FILE1);
+
+$printed = 0;
+
+open(FILE2, $file2) || die("open: $file2: $!\n");
+while (<FILE2>) {
+ ~ s/\r\n//g;
+ ~ s/\n//g;
+ if (/^;.+status:\s+(\S+).+$/) {
+ $rcode2 = $1;
+ }
+ next if (/^;/);
+ if (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+(.+)$/) {
+ $name = $1;
+ $class = $2;
+ $type = $3;
+ $value = $4;
+ if ($lc) {
+ $name = lc($name);
+ $value = lc($value);
+ }
+ if (($name eq $firstname) && ($type eq "SOA")) {
+ $count--;
+ $name = "$name$count";
+ }
+ if ($entry{"$name ; $class.$type ; $value"} ne "") {
+ $entry{"$name ; $class.$type ; $value"} = "";
+ } else {
+ print("Only in $file2 (missing from $file1):\n")
+ if ($printed == 0);
+ print("> $_\n");
+ $printed++;
+ $status = 1;
+ }
+ } elsif (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s*$/) {
+ $name = $1;
+ $class = $2;
+ $type = $3;
+ $value = "";
+ if ($lc) {
+ $name = lc($name);
+ $value = lc($value);
+ }
+ if (($name eq $firstname) && ($type eq "SOA")) {
+ $count--;
+ $name = "$name$count";
+ }
+ if ($entry{"$name ; $class.$type ; $value"} ne "") {
+ $entry{"$name ; $class.$type ; $value"} = "";
+ } else {
+ print("Only in $file2 (missing from $file1):\n")
+ if ($printed == 0);
+ print("> $_\n");
+ $printed++;
+ $status = 1;
+ }
+ }
+}
+close(FILE2);
+
+$printed = 0;
+
+foreach $key (keys(%entry)) {
+ if ($entry{$key} ne "") {
+ print("Only in $file1 (missing from $file2):\n")
+ if ($printed == 0);
+ print("< $entry{$key}\n");
+ $status = 1;
+ $printed++;
+ }
+}
+
+if ($rcode1 ne $rcode2) {
+ print("< status: $rcode1\n");
+ print("> status: $rcode2\n");
+ $status = 1;
+}
+
+exit($status);
diff --git a/bin/tests/system/digdelv/ans4/startme b/bin/tests/system/digdelv/ans4/startme
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/bin/tests/system/digdelv/ans4/startme
@@ -0,0 +1 @@
+
diff --git a/bin/tests/system/digdelv/ans5/ans.pl b/bin/tests/system/digdelv/ans5/ans.pl
new file mode 100644
index 0000000..6396406
--- /dev/null
+++ b/bin/tests/system/digdelv/ans5/ans.pl
@@ -0,0 +1,176 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# This is a TCP-only DNS server whose aim is to facilitate testing how dig
+# copes with prematurely closed TCP connections.
+#
+# This server can be configured (through a separate control socket) with a
+# series of responses to send for subsequent incoming TCP DNS queries. Only
+# one query is handled before closing each connection. In order to keep things
+# simple, the server is not equipped with any mechanism for handling malformed
+# queries.
+#
+# Available response types are defined in the %response_types hash in the
+# getAnswerSection() function below. Each RR returned is generated dynamically
+# based on the QNAME found in the incoming query.
+
+use IO::File;
+use Net::DNS;
+use Net::DNS::Packet;
+
+use strict;
+
+# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early
+local $SIG{PIPE} = 'IGNORE';
+
+# Flush logged output after every line
+local $| = 1;
+
+my $server_addr = "10.53.0.5";
+if (@ARGV > 0) {
+ $server_addr = @ARGV[0];
+}
+
+my $mainport = int($ENV{'PORT'});
+if (!$mainport) { $mainport = 5300; }
+my $ctrlport = int($ENV{'EXTRAPORT1'});
+if (!$ctrlport) { $ctrlport = 5301; }
+
+my $ctlsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $ctrlport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $mainport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";;
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+my @response_sequence = ("complete_axfr");
+my $connection_counter = 0;
+
+# Return the next answer type to send, incrementing the connection counter and
+# making sure the latter does not exceed the size of the array holding the
+# configured response sequence.
+sub getNextResponseType {
+ my $response_type = $response_sequence[$connection_counter];
+
+ $connection_counter++;
+ $connection_counter %= scalar(@response_sequence);
+
+ return $response_type;
+}
+
+# Return an array of resource records comprising the answer section of a given
+# response type.
+sub getAnswerSection {
+ my ($response_type, $qname) = @_;
+
+ my %response_types = (
+ no_response => [],
+
+ partial_axfr => [
+ Net::DNS::RR->new("$qname 300 IN SOA . . 0 0 0 0 300"),
+ Net::DNS::RR->new("$qname NS ."),
+ ],
+
+ complete_axfr => [
+ Net::DNS::RR->new("$qname 300 IN SOA . . 0 0 0 0 300"),
+ Net::DNS::RR->new("$qname NS ."),
+ Net::DNS::RR->new("$qname 300 IN SOA . . 0 0 0 0 300"),
+ ],
+ );
+
+ return $response_types{$response_type};
+}
+
+
+# Generate a Net::DNS::Packet containing the response to send on the current
+# TCP connection. If the answer section of the response is determined to be
+# empty, no data will be sent on the connection at all (immediate EOF).
+sub generateResponse {
+ my ($buf) = @_;
+ my $request;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($request, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ my @questions = $request->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+ my $qclass = $questions[0]->qclass;
+ my $id = $request->header->id;
+
+ my $packet = new Net::DNS::Packet($qname, $qtype, $qclass);
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ $packet->header->id($id);
+
+ my $response_type = getNextResponseType();
+ my $answers = getAnswerSection($response_type, $qname);
+ for my $rr (@$answers) {
+ $packet->push("answer", $rr);
+ }
+
+ print " Sending \"$response_type\" response\n";
+
+ return $packet->data if @$answers;
+}
+
+my $rin;
+my $rout;
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($ctlsock), 1) = 1;
+ vec($rin, fileno($tcpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($ctlsock), 1)) {
+ my $conn = $ctlsock->accept;
+ @response_sequence = split(' ', $conn->getline);
+ $connection_counter = 0;
+ print "Response sequence set to: @response_sequence\n";
+ $conn->close;
+ } elsif (vec($rout, fileno($tcpsock), 1)) {
+ my $buf;
+ my $lenbuf;
+ my $conn = $tcpsock->accept;
+ my $n = $conn->sysread($lenbuf, 2);
+ die unless $n == 2;
+ my $len = unpack("n", $lenbuf);
+ $n = $conn->sysread($buf, $len);
+ die unless $n == $len;
+ print "TCP request\n";
+ my $response = generateResponse($buf);
+ if ($response) {
+ $len = length($response);
+ $n = $conn->syswrite(pack("n", $len), 2);
+ $n = $conn->syswrite($response, $len);
+ print " Sent: $n chars via TCP\n";
+ } else {
+ print " No response sent\n";
+ }
+ $conn->close;
+ }
+}
diff --git a/bin/tests/system/digdelv/ans6/ans.pl b/bin/tests/system/digdelv/ans6/ans.pl
new file mode 100755
index 0000000..39d02b2
--- /dev/null
+++ b/bin/tests/system/digdelv/ans6/ans.pl
@@ -0,0 +1,84 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.6",
+ LocalPort => $localport, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+for (;;) {
+ $sock->recv($buf, 512);
+
+ print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
+
+ my $packet;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ print "REQUEST:\n";
+ $packet->print;
+
+ $packet->header->qr(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+
+ my $donotrespond = 0;
+
+ $packet->header->aa(1);
+ if ($qtype eq "A") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname . " 300 A 10.53.0.5"));
+ } else {
+ $donotrespond = 1;
+ }
+
+ if ($donotrespond == 0) {
+ my $sendsock =
+ IO::Socket::INET->new(LocalAddr => "10.53.1.2",
+ PeerAddr => $sock->peerhost,
+ PeerPort => $sock->peerport,
+ Proto => "udp") or die "$!";
+ print "**** response from ", $sendsock->sockhost, " to " ,
+ $sendsock->peerhost, " port ", $sendsock->peerport, "\n";
+ $sendsock->send($packet->data);
+ $sendsock->close;
+ print "RESPONSE:\n";
+ $packet->print;
+ print "\n";
+ } else {
+ print "DROP:\n";
+ }
+}
diff --git a/bin/tests/system/digdelv/ans7/ans.pl b/bin/tests/system/digdelv/ans7/ans.pl
new file mode 100755
index 0000000..a7aa60e
--- /dev/null
+++ b/bin/tests/system/digdelv/ans7/ans.pl
@@ -0,0 +1,68 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.7",
+ LocalPort => $localport, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+STDOUT->autoflush(1);
+
+print "Net::DNS::VERSION => $Net::DNS::VERSION\n";
+
+for (;;) {
+ $sock->recv($buf, 512);
+
+ print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
+
+ my $packet;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ print "REQUEST:\n";
+ $packet->print;
+
+ $packet->header->qr(1);
+ $packet->header->opcode(5);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+ $packet->push("update", rr_del("$qname SOA"));
+
+ print "RESPONSE:\n";
+ $packet->print;
+
+ $sock->send($packet->data);
+}
diff --git a/bin/tests/system/digdelv/ans8/ans.py b/bin/tests/system/digdelv/ans8/ans.py
new file mode 100644
index 0000000..3e18edc
--- /dev/null
+++ b/bin/tests/system/digdelv/ans8/ans.py
@@ -0,0 +1,202 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from __future__ import print_function
+import os
+import sys
+import signal
+import socket
+import select
+import struct
+
+import dns, dns.message
+from dns.rcode import *
+
+modes = [
+ b"silent", # Do not respond
+ b"close", # UDP: same as silent; TCP: also close the connection
+ b"servfail", # Always respond with SERVFAIL
+ b"unstable", # Constantly switch between "silent" and "servfail"
+]
+mode = modes[0]
+n = 0
+
+
+def ctrl_channel(msg):
+ global modes, mode, n
+
+ msg = msg.splitlines().pop(0)
+ print("Received control message: %s" % msg)
+
+ if msg in modes:
+ mode = msg
+ n = 0
+ print("New mode: %s" % str(mode))
+
+
+def create_servfail(msg):
+ m = dns.message.from_wire(msg)
+ qname = m.question[0].name.to_text()
+ rrtype = m.question[0].rdtype
+ typename = dns.rdatatype.to_text(rrtype)
+
+ with open("query.log", "a") as f:
+ f.write("%s %s\n" % (typename, qname))
+ print("%s %s" % (typename, qname), end=" ")
+
+ r = dns.message.make_response(m)
+ r.set_rcode(SERVFAIL)
+ return r
+
+
+def sigterm(signum, frame):
+ print("Shutting down now...")
+ os.remove("ans.pid")
+ running = False
+ sys.exit(0)
+
+
+ip4 = "10.53.0.8"
+
+try:
+ port = int(os.environ["PORT"])
+except:
+ port = 5300
+
+try:
+ ctrlport = int(os.environ["EXTRAPORT1"])
+except:
+ ctrlport = 5300
+
+query4_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+query4_udp.bind((ip4, port))
+
+query4_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+query4_tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+query4_tcp.bind((ip4, port))
+query4_tcp.listen(100)
+
+ctrl4_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ctrl4_tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ctrl4_tcp.bind((ip4, ctrlport))
+ctrl4_tcp.listen(100)
+
+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))
+print("Listening on %s port %d" % (ip4, ctrlport))
+print("Ctrl-c to quit")
+
+input = [query4_udp, query4_tcp, ctrl4_tcp]
+
+hung_conns = []
+
+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_udp:
+ n = n + 1
+ print("UDP query received on %s" % ip4, end=" ")
+ msg = s.recvfrom(65535)
+ if (
+ mode == b"silent"
+ or mode == b"close"
+ or (mode == b"unstable" and n % 2 == 1)
+ ):
+ # Do not respond.
+ print("NO RESPONSE (%s)" % str(mode))
+ continue
+ elif mode == b"servfail" or (mode == b"unstable" and n % 2 == 0):
+ rsp = create_servfail(msg[0])
+ if rsp:
+ print(dns.rcode.to_text(rsp.rcode()))
+ s.sendto(rsp.to_wire(), msg[1])
+ else:
+ print("NO RESPONSE (can not create a response)")
+ else:
+ raise (Exception("unsupported mode: %s" % mode))
+ elif s == query4_tcp:
+ n = n + 1
+ print("TCP query received on %s" % ip4, end=" ")
+ conn = None
+ try:
+ if mode == b"silent" or (mode == b"unstable" and n % 2 == 1):
+ conn, addr = s.accept()
+ # Do not respond and hang the connection.
+ print("NO RESPONSE (%s)" % str(mode))
+ hung_conns.append(conn)
+ continue
+ elif mode == b"close":
+ conn, addr = s.accept()
+ # Do not respond and close the connection.
+ print("NO RESPONSE (%s)" % str(mode))
+ conn.close()
+ continue
+ elif mode == b"servfail" or (mode == b"unstable" and n % 2 == 0):
+ conn, addr = s.accept()
+ # get TCP message length
+ msg = conn.recv(2)
+ if len(msg) != 2:
+ print("NO RESPONSE (can not read the message length)")
+ conn.close()
+ continue
+ length = struct.unpack(">H", msg[:2])[0]
+ msg = conn.recv(length)
+ if len(msg) != length:
+ print("NO RESPONSE (can not read the message)")
+ conn.close()
+ continue
+ rsp = create_servfail(msg)
+ if rsp:
+ print(dns.rcode.to_text(rsp.rcode()))
+ wire = rsp.to_wire()
+ conn.send(struct.pack(">H", len(wire)))
+ conn.send(wire)
+ else:
+ print("NO RESPONSE (can not create a response)")
+ else:
+ raise (Exception("unsupported mode: %s" % mode))
+ except socket.error as e:
+ print("NO RESPONSE (error: %s)" % str(e))
+ if conn:
+ conn.close()
+ elif s == ctrl4_tcp:
+ print("Control channel connected")
+ conn = None
+ try:
+ # Handle control channel input
+ conn, addr = s.accept()
+ msg = conn.recv(1024)
+ if msg:
+ ctrl_channel(msg)
+ conn.close()
+ except s.timeout:
+ pass
+ if conn:
+ conn.close()
+
+ if not running:
+ break
diff --git a/bin/tests/system/digdelv/clean.sh b/bin/tests/system/digdelv/clean.sh
new file mode 100644
index 0000000..ed9ad87
--- /dev/null
+++ b/bin/tests/system/digdelv/clean.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f ./*/anchor.*
+rm -f ./*/named.conf
+rm -f ./*/named.memstats
+rm -f ./*/named.run
+rm -f ./ans*/ans.run
+rm -f ./ans*/query.log
+rm -f ./delv.out.test*
+rm -f ./dig.out.*test*
+rm -f ./dig.out.mm.*
+rm -f ./dig.out.mn.*
+rm -f ./dig.out.nm.*
+rm -f ./dig.out.nn.*
+rm -f ./host.out.test*
+rm -f ./ns*/managed-keys.bind*
+rm -f ./ns*/named.lock
+rm -f ./ns2/dsset-example.
+rm -f ./ns2/example.db ./ns2/K* ./ns2/keyid ./ns2/keydata
+rm -f ./nslookup.out.test*
+rm -f ./yamlget.out.*
+rm -f ./nsupdate.out.test*
diff --git a/bin/tests/system/digdelv/ns1/named.conf.in b/bin/tests/system/digdelv/ns1/named.conf.in
new file mode 100644
index 0000000..df552bd
--- /dev/null
+++ b/bin/tests/system/digdelv/ns1/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ query-source address 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { fd92:7065:b8e:ffff::1; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/digdelv/ns1/root.db b/bin/tests/system/digdelv/ns1/root.db
new file mode 100644
index 0000000..b43cc40
--- /dev/null
+++ b/bin/tests/system/digdelv/ns1/root.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+a.root-servers.nil. AAAA fd92:7065:b8e:ffff::1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+ns2.example. AAAA fd92:7065:b8e:ffff::2
diff --git a/bin/tests/system/digdelv/ns2/example.db.in b/bin/tests/system/digdelv/ns2/example.db.in
new file mode 100644
index 0000000..c711049
--- /dev/null
+++ b/bin/tests/system/digdelv/ns2/example.db.in
@@ -0,0 +1,51 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns2 AAAA fd92:7065:b8e:ffff::2
+ns3 A 10.53.0.3
+ns3 AAAA fd92:7065:b8e:ffff::3
+
+a A 10.0.0.1
+a AAAA fd92:7065:b8e:ffff::1
+b A 10.0.0.2
+b AAAA fd92:7065:b8e:ffff::2
+c A 10.0.0.3
+c AAAA fd92:7065:b8e:ffff::3
+d A 10.0.0.0
+d AAAA fd92:7065:b8e:ffff::
+
+xn--caf-dma A 10.1.2.3
+
+foo TXT "testing"
+foo A 10.0.1.0
+foo SSHFP 2 1 123456789abcdef67890123456789abcdef67890
+
+; TTL of 3 weeks
+weeks 1814400 A 10.53.0.2
+; TTL of 3 days
+days 259200 A 10.53.0.2
+; TTL of 3 hours
+hours 10800 A 10.53.0.2
+;TTL of 45 minutes
+minutes 2700 A 10.53.0.2
+;TTL of 45 seconds
+seconds 45 A 10.53.0.2
diff --git a/bin/tests/system/digdelv/ns2/named.conf.in b/bin/tests/system/digdelv/ns2/named.conf.in
new file mode 100644
index 0000000..1391b73
--- /dev/null
+++ b/bin/tests/system/digdelv/ns2/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/digdelv/ns2/sign.sh b/bin/tests/system/digdelv/ns2/sign.sh
new file mode 100644
index 0000000..c8564b2
--- /dev/null
+++ b/bin/tests/system/digdelv/ns2/sign.sh
@@ -0,0 +1,29 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone example.)
+
+cp example.db.in example.db
+
+"$SIGNER" -Sz -f example.db -o example example.db.in > /dev/null 2>&1
+
+keyfile_to_key_id "$ksk" > keyid
+grep -Ev '^;' < "$ksk.key" | cut -f 7- -d ' ' > keydata
+
+keyfile_to_initial_keys "$ksk" > ../ns3/anchor.dnskey
+keyfile_to_initial_ds "$ksk" > ../ns3/anchor.ds
diff --git a/bin/tests/system/digdelv/ns3/named.conf.in b/bin/tests/system/digdelv/ns3/named.conf.in
new file mode 100644
index 0000000..66bb748
--- /dev/null
+++ b/bin/tests/system/digdelv/ns3/named.conf.in
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::3; };
+ recursion yes;
+ dnssec-validation no;
+ server-id "ns3";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/digdelv/setup.sh b/bin/tests/system/digdelv/setup.sh
new file mode 100644
index 0000000..ca63977
--- /dev/null
+++ b/bin/tests/system/digdelv/setup.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+
+cd ns2 && $SHELL sign.sh
diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh
new file mode 100644
index 0000000..dceced6
--- /dev/null
+++ b/bin/tests/system/digdelv/tests.sh
@@ -0,0 +1,1403 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+status=0
+n=0
+
+sendcmd() {
+ send "${1}" "$EXTRAPORT1"
+}
+
+dig_with_opts() {
+ "$DIG" -p "$PORT" "$@"
+}
+
+mdig_with_opts() {
+ "$MDIG" -p "$PORT" "$@"
+}
+
+# Check if response in file $1 has the correct TTL range.
+# The response record must have RRtype $2 and class IN (CLASS1).
+# Maximum TTL is given by $3. This works in most cases where TTL is
+# the second word on the line. TTL position can be adjusted with
+# setting the position $4, but that requires updating this function.
+check_ttl_range() {
+ file=$1
+ pos=$4
+
+ case "$pos" in
+ "3")
+ { awk -v rrtype="$2" -v ttl="$3" '($4 == "IN" || $4 == "CLASS1" ) && $5 == rrtype { if ($3 <= ttl) { ok=1 } } END { exit(ok?0:1) }' < $file; result=$?; } || true
+ ;;
+ *)
+ { awk -v rrtype="$2" -v ttl="$3" '($3 == "IN" || $3 == "CLASS1" ) && $4 == rrtype { if ($2 <= ttl) { ok=1 } } END { exit(ok?0:1) }' < $file; result=$?; } || true
+ ;;
+ esac
+
+ [ $result -eq 0 ] || echo_i "ttl check failed"
+ return $result
+}
+
+# using delv insecure mode as not testing dnssec here
+delv_with_opts() {
+ "$DELV" +noroot -p "$PORT" "$@"
+}
+
+KEYID="$(cat ns2/keyid)"
+KEYDATA="$(< ns2/keydata sed -e 's/+/[+]/g')"
+NOSPLIT="$(< ns2/keydata sed -e 's/+/[+]/g' -e 's/ //g')"
+
+HAS_PYYAML=0
+if [ -x "$PYTHON" ] ; then
+ $PYTHON -c "import yaml" 2> /dev/null && HAS_PYYAML=1
+fi
+
+#
+# test whether ans7/ans.pl will be able to send a UPDATE response.
+# if it can't, we will log that below.
+#
+if "$PERL" -e 'use Net::DNS; use Net::DNS::Packet; my $p = new Net::DNS::Packet; $p->header->opcode(5);' > /dev/null 2>&1
+then
+ checkupdate=1
+else
+ checkupdate=0
+fi
+
+if [ -x "$NSLOOKUP" -a $checkupdate -eq 1 ] ; then
+
+ n=$((n+1))
+ echo_i "check nslookup handles UPDATE response ($n)"
+ ret=0
+ "$NSLOOKUP" -q=CNAME -timeout=1 "-port=$PORT" foo.bar 10.53.0.7 > nslookup.out.test$n 2>&1 && ret=1
+ grep "Opcode mismatch" nslookup.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+fi
+
+if [ -x "$HOST" -a $checkupdate -eq 1 ] ; then
+
+ n=$((n+1))
+ echo_i "check host handles UPDATE response ($n)"
+ ret=0
+ "$HOST" -W 1 -t CNAME -p $PORT foo.bar 10.53.0.7 > host.out.test$n 2>&1 && ret=1
+ grep "Opcode mismatch" host.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+fi
+
+if [ -x "$NSUPDATE" -a $checkupdate -eq 1 ] ; then
+
+ n=$((n+1))
+ echo_i "check nsupdate handles UPDATE response to QUERY ($n)"
+ ret=0
+ res=0
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || res=$?
+server 10.53.0.7 ${PORT}
+add x.example.com 300 in a 1.2.3.4
+send
+EOF
+ test $res -eq 1 || ret=1
+ grep "invalid OPCODE in response to SOA query" nsupdate.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+fi
+
+if [ -x "$DIG" ] ; then
+
+ if [ $checkupdate -eq 1 ] ; then
+
+ n=$((n+1))
+ echo_i "check dig handles UPDATE response ($n)"
+ ret=0
+ dig_with_opts @10.53.0.7 +tries=1 +timeout=1 cname foo.bar > dig.out.test$n 2>&1 && ret=1
+ grep "Opcode mismatch" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ else
+ echo_i "Skipped UPDATE handling test"
+ fi
+
+ n=$((n+1))
+ echo_i "checking dig short form works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +short a a.example > dig.out.test$n || ret=1
+ test "$(wc -l < dig.out.test$n)" -eq 1 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig split width works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +split=4 -t sshfp foo.example > dig.out.test$n || ret=1
+ grep " 9ABC DEF6 7890 " < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "SSHFP" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +unknownformat works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +unknownformat a a.example > dig.out.test$n || ret=1
+ grep "CLASS1[ ][ ]*TYPE1[ ][ ]*\\\\# 4 0A000001" < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "TYPE1" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig with reverse lookup works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 -x 127.0.0.1 > dig.out.test$n 2>&1 || ret=1
+ # doesn't matter if has answer
+ grep -i "127\\.in-addr\\.arpa\\." < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "SOA" 86400 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig over TCP works ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 a a.example > dig.out.test$n || ret=1
+ grep "10\\.0\\.0\\.1$" < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t DNSKEY example > dig.out.test$n || ret=1
+ grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" dig.out.test$n > /dev/null && ret=1
+ check_ttl_range dig.out.test$n "DNSKEY" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +multi +norrcomments works for SOA (when default is rrcomments)($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t SOA example > dig.out.test$n || ret=1
+ grep "; serial" dig.out.test$n > /dev/null && ret=1
+ check_ttl_range dig.out.test$n "SOA" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +rrcomments works for DNSKEY($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +rrcomments DNSKEY example > dig.out.test$n || ret=1
+ grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "DNSKEY" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +short +rrcomments works for DNSKEY ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example > dig.out.test$n || ret=1
+ grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +short +nosplit works($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +short +nosplit DNSKEY example > dig.out.test$n || ret=1
+ grep "$NOSPLIT" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +short +rrcomments works($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example > dig.out.test$n || ret=1
+ grep -q "$KEYDATA ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID\$" < dig.out.test$n || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig multi flag is local($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +nomulti example +nomulti > dig.out.nn.$n || ret=1
+ dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +multi example +nomulti > dig.out.mn.$n || ret=1
+ dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +nomulti example +multi > dig.out.nm.$n || ret=1
+ dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +multi example +multi > dig.out.mm.$n || ret=1
+ lcnn=$(wc -l < dig.out.nn.$n)
+ lcmn=$(wc -l < dig.out.mn.$n)
+ lcnm=$(wc -l < dig.out.nm.$n)
+ lcmm=$(wc -l < dig.out.mm.$n)
+ test "$lcmm" -ge "$lcnm" || ret=1
+ test "$lcmm" -ge "$lcmn" || ret=1
+ test "$lcnm" -ge "$lcnn" || ret=1
+ test "$lcmn" -ge "$lcnn" || ret=1
+ check_ttl_range dig.out.nn.$n "DNSKEY" 300 || ret=1
+ check_ttl_range dig.out.mn.$n "DNSKEY" 300 || ret=1
+ check_ttl_range dig.out.nm.$n "DNSKEY" 300 || ret=1
+ check_ttl_range dig.out.mm.$n "DNSKEY" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +noheader-only works ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +noheader-only A example > dig.out.test$n || ret=1
+ grep "Got answer:" < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "SOA" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +short +rrcomments works($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example > dig.out.test$n || ret=1
+ grep -q "$KEYDATA ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID\$" < dig.out.test$n || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +header-only works ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +header-only example > dig.out.test$n || ret=1
+ grep "^;; flags: qr rd; QUERY: 0, ANSWER: 0," < dig.out.test$n > /dev/null || ret=1
+ grep "^;; QUESTION SECTION:" < dig.out.test$n > /dev/null && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +raflag works ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +raflag +qr example > dig.out.test$n || ret=1
+ grep "^;; flags: rd ra ad; QUERY: 1, ANSWER: 0," < dig.out.test$n > /dev/null || ret=1
+ grep "^;; flags: qr rd ra; QUERY: 1, ANSWER: 0," < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "SOA" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +tcflag works ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +tcflag +qr example > dig.out.test$n || ret=1
+ grep "^;; flags: tc rd ad; QUERY: 1, ANSWER: 0" < dig.out.test$n > /dev/null || ret=1
+ grep "^;; flags: qr rd ra; QUERY: 1, ANSWER: 0," < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "SOA" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +header-only works (with class and type set) ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +header-only -c IN -t A example > dig.out.test$n || ret=1
+ grep "^;; flags: qr rd; QUERY: 0, ANSWER: 0," < dig.out.test$n > /dev/null || ret=1
+ grep "^;; QUESTION SECTION:" < dig.out.test$n > /dev/null && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +zflag works, and that BIND properly ignores it ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.3 +zflag +qr A example > dig.out.test$n || ret=1
+ sed -n '/Sending:/,/Got answer:/p' dig.out.test$n | grep "^;; flags: rd ad; MBZ: 0x4;" > /dev/null || ret=1
+ sed -n '/Got answer:/,/AUTHORITY SECTION:/p' dig.out.test$n | grep "^;; flags: qr rd ra; QUERY: 1" > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "SOA" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +qr +ednsopt=08 does not cause an INSIST failure ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=08 +qr a a.example > dig.out.test$n || ret=1
+ grep "INSIST" < dig.out.test$n > /dev/null && ret=1
+ grep "FORMERR" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +ttlunits works ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.2 +ttlunits A weeks.example > dig.out.test$n || ret=1
+ grep "^weeks.example. 3w" < dig.out.test$n > /dev/null || ret=1
+ dig_with_opts +tcp @10.53.0.2 +ttlunits A days.example > dig.out.test$n || ret=1
+ grep "^days.example. 3d" < dig.out.test$n > /dev/null || ret=1
+ dig_with_opts +tcp @10.53.0.2 +ttlunits A hours.example > dig.out.test$n || ret=1
+ grep "^hours.example. 3h" < dig.out.test$n > /dev/null || ret=1
+ dig_with_opts +tcp @10.53.0.2 +ttlunits A minutes.example > dig.out.test$n || ret=1
+ grep "^minutes.example. 45m" < dig.out.test$n > /dev/null || ret=1
+ dig_with_opts +tcp @10.53.0.2 +ttlunits A seconds.example > dig.out.test$n || ret=1
+ grep "^seconds.example. 45s" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig respects precedence of options with +ttlunits ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.2 +ttlunits +nottlid A weeks.example > dig.out.test$n || ret=1
+ grep "^weeks.example. IN" < dig.out.test$n > /dev/null || ret=1
+ dig_with_opts +tcp @10.53.0.2 +nottlid +ttlunits A weeks.example > dig.out.test$n || ret=1
+ grep "^weeks.example. 3w" < dig.out.test$n > /dev/null || ret=1
+ dig_with_opts +tcp @10.53.0.2 +nottlid +nottlunits A weeks.example > dig.out.test$n || ret=1
+ grep "^weeks.example. 1814400" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig preserves origin on TCP retries ($n)"
+ ret=0
+ # Ask ans4 to still accept TCP connections, but not respond to queries
+ echo "//" | sendcmd 10.53.0.4
+ dig_with_opts -d +tcp @10.53.0.4 +retry=1 +time=1 +domain=bar foo > dig.out.test$n 2>&1 && ret=1
+ test "$(grep -c "trying origin bar" dig.out.test$n)" -eq 2 || ret=1
+ grep "using root origin" < dig.out.test$n > /dev/null && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig -6 -4 ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.2 -4 -6 A a.example > dig.out.test$n 2>&1 && ret=1
+ grep "only one of -4 and -6 allowed" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig @IPv6addr -4 A a.example ($n)"
+ if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null
+ then
+ ret=0
+ dig_with_opts +tcp @fd92:7065:b8e:ffff::2 -4 A a.example > dig.out.test$n 2>&1 && ret=1
+ grep "address family not supported" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ else
+ echo_i "IPv6 unavailable; skipping"
+ fi
+
+ n=$((n+1))
+ echo_i "checking dig +tcp @IPv4addr -6 A a.example ($n)"
+ if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null
+ then
+ ret=0
+ dig_with_opts +tcp @10.53.0.2 -6 A a.example > dig.out.test$n 2>&1 || ret=1
+ grep "SERVER: ::ffff:10.53.0.2#$PORT" < dig.out.test$n > /dev/null && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ else
+ echo_i "IPv6 unavailable; skipping"
+ fi
+ n=$((n+1))
+
+ echo_i "checking dig +notcp @IPv4addr -6 A a.example ($n)"
+ if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null
+ then
+ ret=0
+ dig_with_opts +notcp @10.53.0.2 -6 A a.example > dig.out.test$n 2>&1 || ret=1
+ grep "SERVER: ::ffff:10.53.0.2#$PORT" < dig.out.test$n > /dev/null && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ else
+ echo_i "IPv6 unavailable; skipping"
+ fi
+
+ n=$((n+1))
+ echo_i "checking dig +subnet ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.2 +subnet=127.0.0.1 A a.example > dig.out.test$n 2>&1 || ret=1
+ grep "CLIENT-SUBNET: 127.0.0.1/32/0" < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +subnet +subnet ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.2 +subnet=127.0.0.0 +subnet=127.0.0.1 A a.example > dig.out.test$n 2>&1 || ret=1
+ grep "CLIENT-SUBNET: 127.0.0.1/32/0" < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +subnet with various prefix lengths ($n)"
+ ret=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24; do
+ dig_with_opts +tcp @10.53.0.2 +subnet=255.255.255.255/$i A a.example > dig.out.$i.test$n 2>&1 || ret=1
+ case $i in
+ 1|9|17) octet=128 ;;
+ 2|10|18) octet=192 ;;
+ 3|11|19) octet=224 ;;
+ 4|12|20) octet=240 ;;
+ 5|13|21) octet=248 ;;
+ 6|14|22) octet=252 ;;
+ 7|15|23) octet=254 ;;
+ 8|16|24) octet=255 ;;
+ esac
+ case $i in
+ 1|2|3|4|5|6|7|8) addr="${octet}.0.0.0";;
+ 9|10|11|12|13|14|15|16) addr="255.${octet}.0.0";;
+ 17|18|19|20|21|22|23|24) addr="255.255.${octet}.0" ;;
+ esac
+ grep "FORMERR" < dig.out.$i.test$n > /dev/null && ret=1
+ grep "CLIENT-SUBNET: $addr/$i/0" < dig.out.$i.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.$i.test$n "A" 300 || ret=1
+ done
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +subnet=0/0 ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.2 +subnet=0/0 A a.example > dig.out.test$n 2>&1 || ret=1
+ grep "status: NOERROR" < dig.out.test$n > /dev/null || ret=1
+ grep "CLIENT-SUBNET: 0.0.0.0/0/0" < dig.out.test$n > /dev/null || ret=1
+ grep "10.0.0.1" < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +subnet=0 ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.2 +subnet=0 A a.example > dig.out.test$n 2>&1 || ret=1
+ grep "status: NOERROR" < dig.out.test$n > /dev/null || ret=1
+ grep "CLIENT-SUBNET: 0.0.0.0/0/0" < dig.out.test$n > /dev/null || ret=1
+ grep "10.0.0.1" < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +subnet=::/0 ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.2 +subnet=::/0 A a.example > dig.out.test$n 2>&1 || ret=1
+ grep "status: NOERROR" < dig.out.test$n > /dev/null || ret=1
+ grep "CLIENT-SUBNET: ::/0/0" < dig.out.test$n > /dev/null || ret=1
+ grep "10.0.0.1" < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +ednsopt=8:00000000 (family=0, source=0, scope=0) ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.2 +ednsopt=8:00000000 A a.example > dig.out.test$n 2>&1 || ret=1
+ grep "status: NOERROR" < dig.out.test$n > /dev/null || ret=1
+ grep "CLIENT-SUBNET: 0/0/0" < dig.out.test$n > /dev/null || ret=1
+ grep "10.0.0.1" < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +ednsopt=8:00030000 (family=3, source=0, scope=0) ($n)"
+ ret=0
+ dig_with_opts +qr +tcp @10.53.0.2 +ednsopt=8:00030000 A a.example > dig.out.test$n 2>&1 || ret=1
+ grep "status: FORMERR" < dig.out.test$n > /dev/null || ret=1
+ grep "CLIENT-SUBNET: 00 03 00 00" < dig.out.test$n > /dev/null || ret=1
+ test "$(grep -c "CLIENT-SUBNET: 00 03 00 00" dig.out.test$n)" -eq 1 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +subnet with prefix lengths between byte boundaries ($n)"
+ ret=0
+ for p in 9 10 11 12 13 14 15; do
+ dig_with_opts +tcp @10.53.0.2 +subnet=10.53/$p A a.example > dig.out.test.$p.$n 2>&1 || ret=1
+ grep "FORMERR" < dig.out.test.$p.$n > /dev/null && ret=1
+ grep "CLIENT-SUBNET.*/$p/0" < dig.out.test.$p.$n > /dev/null || ret=1
+ check_ttl_range dig.out.test.$p.$n "A" 300 || ret=1
+ done
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +sp works as an abbreviated form of split ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +sp=4 -t sshfp foo.example > dig.out.test$n || ret=1
+ grep " 9ABC DEF6 7890 " < dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "SSHFP" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig -c works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 -c CHAOS -t txt version.bind > dig.out.test$n || ret=1
+ grep "version.bind. 0 CH TXT" < dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +ednsopt with option number ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=3 a.example > dig.out.test$n 2>&1 || ret=1
+ grep 'NSID: .* ("ns3")' dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking dig +ednsopt with option name ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=nsid a.example > dig.out.test$n 2>&1 || ret=1
+ grep 'NSID: .* ("ns3")' dig.out.test$n > /dev/null || ret=1
+ check_ttl_range dig.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking ednsopt LLQ prints as expected ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=llq:0001000200001234567812345678fefefefe +qr a.example > dig.out.test$n 2>&1 || ret=1
+ pat='LLQ: Version: 1, Opcode: 2, Error: 0, Identifier: 1311768465173141112, Lifetime: 4278124286$'
+ grep "$pat" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking that dig warns about .local queries ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 local soa > dig.out.test$n 2>&1 || ret=1
+ grep ";; WARNING: .local is reserved for Multicast DNS" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig processes +ednsopt=key-tag and FORMERR is returned ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=key-tag a.example +qr > dig.out.test$n 2>&1 || ret=1
+ grep "; KEY-TAG: *$" dig.out.test$n > /dev/null || ret=1
+ grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig processes +ednsopt=key-tag:<value-list> ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=key-tag:00010002 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ grep "; KEY-TAG: 1, 2$" dig.out.test$n > /dev/null || ret=1
+ grep "status: FORMERR" dig.out.test$n > /dev/null && ret=1
+ check_ttl_range dig.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig processes +ednsopt=key-tag:<malformed-value-list> and FORMERR is returned ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=key-tag:0001000201 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ grep "; KEY-TAG: 00 01 00 02 01" dig.out.test$n > /dev/null || ret=1
+ grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig processes +ednsopt=client-tag:value ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=client-tag:0001 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ grep "; CLIENT-TAG: 1$" dig.out.test$n > /dev/null || ret=1
+ grep "status: FORMERR" dig.out.test$n > /dev/null && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that FORMERR is returned for a too short client-tag ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=client-tag:01 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ grep "; CLIENT-TAG" dig.out.test$n > /dev/null || ret=1
+ grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that FORMERR is returned for a too long client-tag ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=client-tag:000001 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ grep "; CLIENT-TAG" dig.out.test$n > /dev/null || ret=1
+ grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig processes +ednsopt=server-tag:value ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=server-tag:0001 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ grep "; SERVER-TAG: 1$" dig.out.test$n > /dev/null || ret=1
+ grep "status: FORMERR" dig.out.test$n > /dev/null && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that FORMERR is returned for a too short server-tag ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=server-tag:01 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ grep "; SERVER-TAG" dig.out.test$n > /dev/null || ret=1
+ grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that FORMERR is returned for a too long server-tag ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=server-tag:000001 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ grep "; SERVER-TAG" dig.out.test$n > /dev/null || ret=1
+ grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that Extended DNS Error 0 is printed correctly ($n)"
+ # First defined EDE code, additional text "foo".
+ dig_with_opts @10.53.0.3 +ednsopt=ede:0000666f6f a.example +qr > dig.out.test$n 2>&1 || ret=1
+ pat='^; EDE: 0 (Other): (foo)$'
+ grep "$pat" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that Extended DNS Error 24 is printed correctly ($n)"
+ # Last defined EDE code, no additional text.
+ dig_with_opts @10.53.0.3 +ednsopt=ede:0018 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ pat='^; EDE: 24 (Invalid Data)$'
+ grep "$pat" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that Extended DNS Error 25 is printed correctly ($n)"
+ # First undefined EDE code, additional text "foo".
+ dig_with_opts @10.53.0.3 +ednsopt=ede:0019666f6f a.example +qr > dig.out.test$n 2>&1 || ret=1
+ pat='^; EDE: 25: (foo)$'
+ grep "$pat" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that invalid Extended DNS Error (length 0) is printed ($n)"
+ # EDE payload is too short
+ dig_with_opts @10.53.0.3 +ednsopt=ede a.example +qr > dig.out.test$n 2>&1 || ret=1
+ pat='^; EDE:$'
+ grep "$pat" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that invalid Extended DNS Error (length 1) is printed ($n)"
+ # EDE payload is too short
+ dig_with_opts @10.53.0.3 +ednsopt=ede:00 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ pat='^; EDE: 00 (".")$'
+ grep "$pat" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ if [ $HAS_PYYAML -ne 0 ] ; then
+ n=$((n+1))
+ echo_i "check that +yaml Extended DNS Error 0 is printed correctly ($n)"
+ # First defined EDE code, additional text "foo".
+ dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0000666f6f a.example +qr > dig.out.test$n 2>&1 || ret=1
+ $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE INFO-CODE > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "0 (Other)" ] || ret=1
+ $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE EXTRA-TEXT > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "foo" ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that +yaml Extended DNS Error 24 is printed correctly ($n)"
+ # Last defined EDE code, no additional text.
+ dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0018 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE INFO-CODE > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "24 (Invalid Data)" ] || ret=1
+ $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE EXTRA-TEXT > yamlget.out.test$n 2>&1 && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that +yaml Extended DNS Error 25 is printed correctly ($n)"
+ # First undefined EDE code, additional text "foo".
+ dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0019666f6f a.example +qr > dig.out.test$n 2>&1 || ret=1
+ $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE INFO-CODE > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "25" ] || ret=1
+ $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE EXTRA-TEXT > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "foo" ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that invalid Extended DNS Error (length 0) is printed ($n)"
+ # EDE payload is too short
+ dig_with_opts @10.53.0.3 +yaml +ednsopt=ede a.example +qr > dig.out.test$n 2>&1 || ret=1
+ $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "None" ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that invalid +yaml Extended DNS Error (length 1) is printed ($n)"
+ # EDE payload is too short
+ dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:00 a.example +qr > dig.out.test$n 2>&1 || ret=1
+ $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = '00 (".")' ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ fi
+
+ n=$((n+1))
+ echo_i "check that dig handles malformed option '+ednsopt=:' gracefully ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +ednsopt=: a.example > dig.out.test$n 2>&1 && ret=1
+ grep "ednsopt no code point specified" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig gracefully handles bad escape in domain name ($n)"
+ ret=0
+ digstatus=0
+ dig_with_opts @10.53.0.3 '\0.' > dig.out.test$n 2>&1 || digstatus=$?
+ echo digstatus=$digstatus >> dig.out.test$n
+ test $digstatus -eq 10 || ret=1
+ grep REQUIRE dig.out.test$n > /dev/null && ret=1
+ grep "is not a legal name (bad escape)" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig -q -m works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 -q -m > dig.out.test$n 2>&1
+ pat='^;-m\..*IN.*A$'
+ grep "$pat" dig.out.test$n > /dev/null || ret=1
+ grep "Dump of all outstanding memory allocations" dig.out.test$n > /dev/null && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking exit code for a retry upon TCP EOF (immediate -> immediate) ($n)"
+ ret=0
+ echo "no_response no_response" | sendcmd 10.53.0.5
+ dig_with_opts @10.53.0.5 example AXFR +tries=2 > dig.out.test$n 2>&1 && ret=1
+ # Sanity check: ensure ans5 behaves as expected.
+ [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> partial AXFR) ($n)"
+ ret=0
+ echo "partial_axfr partial_axfr" | sendcmd 10.53.0.5
+ dig_with_opts @10.53.0.5 example AXFR +tries=2 > dig.out.test$n 2>&1 && ret=1
+ # Sanity check: ensure ans5 behaves as expected.
+ [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking exit code for a retry upon TCP EOF (immediate -> partial AXFR) ($n)"
+ ret=0
+ echo "no_response partial_axfr" | sendcmd 10.53.0.5
+ dig_with_opts @10.53.0.5 example AXFR +tries=2 > dig.out.test$n 2>&1 && ret=1
+ # Sanity check: ensure ans5 behaves as expected.
+ [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> immediate) ($n)"
+ ret=0
+ echo "partial_axfr no_response" | sendcmd 10.53.0.5
+ dig_with_opts @10.53.0.5 example AXFR +tries=2 > dig.out.test$n 2>&1 && ret=1
+ # Sanity check: ensure ans5 behaves as expected.
+ [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking exit code for a retry upon TCP EOF (immediate -> complete AXFR) ($n)"
+ ret=0
+ echo "no_response complete_axfr" | sendcmd 10.53.0.5
+ dig_with_opts @10.53.0.5 example AXFR +tries=2 > dig.out.test$n 2>&1 || ret=1
+ # Sanity check: ensure ans5 behaves as expected.
+ [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> complete AXFR) ($n)"
+ ret=0
+ echo "partial_axfr complete_axfr" | sendcmd 10.53.0.5
+ dig_with_opts @10.53.0.5 example AXFR +tries=2 > dig.out.test$n 2>&1 || ret=1
+ # Sanity check: ensure ans5 behaves as expected.
+ [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking +tries=1 won't retry twice upon TCP EOF ($n)"
+ ret=0
+ echo "no_response no_response" | sendcmd 10.53.0.5
+ dig_with_opts @10.53.0.5 example AXFR +tries=1 > dig.out.test$n 2>&1 && ret=1
+ # Sanity check: ensure ans5 behaves as expected.
+ [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking +retry=0 won't retry twice upon TCP EOF ($n)"
+ ret=0
+ dig_with_opts @10.53.0.5 example AXFR +retry=0 > dig.out.test$n 2>&1 && ret=1
+ # Sanity check: ensure ans5 behaves as expected.
+ [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig +expandaaaa works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +expandaaaa AAAA ns2.example > dig.out.test$n 2>&1 || ret=1
+ grep "ns2.example.*fd92:7065:0b8e:ffff:0000:0000:0000:0002" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig +noexpandaaaa works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +noexpandaaaa AAAA ns2.example > dig.out.test$n 2>&1 || ret=1
+ grep "ns2.example.*fd92:7065:b8e:ffff::2" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig default for +[no]expandaaa (+noexpandaaaa) works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 AAAA ns2.example > dig.out.test$n 2>&1 || ret=1
+ grep "ns2.example.*fd92:7065:b8e:ffff::2" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+
+ echo_i "check that dig +short +expandaaaa works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 +short +expandaaaa AAAA ns2.example > dig.out.test$n 2>&1 || ret=1
+ pat='^fd92:7065:0b8e:ffff:0000:0000:0000:0002$'
+ grep "$pat" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ if [ $HAS_PYYAML -ne 0 ] ; then
+ n=$((n+1))
+ echo_i "check dig +yaml output ($n)"
+ ret=0
+ dig_with_opts +qr +yaml @10.53.0.3 any ns2.example > dig.out.test$n 2>&1 || ret=1
+ $PYTHON yamlget.py dig.out.test$n 0 message query_message_data status > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "NOERROR" ] || ret=1
+ $PYTHON yamlget.py dig.out.test$n 1 message response_message_data status > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "NOERROR" ] || ret=1
+ $PYTHON yamlget.py dig.out.test$n 1 message response_message_data QUESTION_SECTION 0 > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "ns2.example. IN ANY" ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check dig +yaml output of an IPv6 address ending in zeroes ($n)"
+ ret=0
+ dig_with_opts +qr +yaml @10.53.0.3 aaaa d.example > dig.out.test$n 2>&1 || ret=1
+ $PYTHON yamlget.py dig.out.test$n 1 message response_message_data ANSWER_SECTION 0 > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "d.example. 300 IN AAAA fd92:7065:b8e:ffff::0" ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ fi
+
+ n=$((n+1))
+ echo_i "check that dig +bufsize=0 just sets the buffer size to 0 ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 a.example +bufsize=0 +qr > dig.out.test$n 2>&1 || ret=1
+ grep "EDNS:" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig +bufsize restores default bufsize ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 a.example +bufsize=0 +bufsize +qr > dig.out.test$n 2>&1 || ret=1
+ lines=$(grep "EDNS:.* udp:" dig.out.test$n | wc -l)
+ lines1232=$(grep "EDNS:.* udp: 1232" dig.out.test$n | wc -l)
+ test $lines -eq 2 || ret=1
+ test $lines1232 -eq 2 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig without -u displays 'Query time' in millseconds ($n)"
+ ret=0
+ dig_with_opts @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ grep ';; Query time: [0-9][0-9]* msec' dig.out.test$n >/dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig -u displays 'Query time' in microseconds ($n)"
+ ret=0
+ dig_with_opts -u @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ grep ';; Query time: [0-9][0-9]* usec' dig.out.test$n >/dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig +yaml without -u displays timestamps in milliseconds ($n)"
+ ret=0
+ dig_with_opts +yaml @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ grep 'query_time: !!timestamp ....-..-..T..:..:..\....Z' dig.out.test$n >/dev/null || ret=1
+ grep 'response_time: !!timestamp ....-..-..T..:..:..\....Z' dig.out.test$n >/dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig -u +yaml displays timestamps in microseconds ($n)"
+ ret=0
+ dig_with_opts -u +yaml @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ grep 'query_time: !!timestamp ....-..-..T..:..:..\.......Z' dig.out.test$n >/dev/null || ret=1
+ grep 'response_time: !!timestamp ....-..-..T..:..:..\.......Z' dig.out.test$n >/dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ # See [GL #3020] for more information
+ n=$((n+1))
+ echo_i "check that dig handles UDP timeout followed by a SERVFAIL correctly ($n)"
+ # Ask ans8 to be in "unstable" mode (switching between "silent" and "servfail" modes)
+ echo "unstable" | sendcmd 10.53.0.8
+ ret=0
+ dig_with_opts +timeout=1 +nofail @10.53.0.8 a.example > dig.out.test$n 2>&1 || ret=1
+ grep -F "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig handles TCP timeout followed by a SERVFAIL correctly ($n)"
+ # Ask ans8 to be in "unstable" mode (switching between "silent" and "servfail" modes)
+ echo "unstable" | sendcmd 10.53.0.8
+ ret=0
+ dig_with_opts +timeout=1 +nofail +tcp @10.53.0.8 a.example > dig.out.test$n 2>&1 || ret=1
+ grep -F "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig tries the next server after a UDP socket network unreachable error ($n)"
+ ret=0
+ dig_with_opts @192.0.2.128 @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ test $(grep -F -e "connection refused" -e "timed out" -e "network unreachable" -e "host unreachable" dig.out.test$n | wc -l) -eq 3 || ret=1
+ grep -F "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig tries the next server after a TCP socket network unreachable error ($n)"
+ ret=0
+ dig_with_opts +tcp @192.0.2.128 @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ test $(grep -F -e "connection refused" -e "timed out" -e "network unreachable" -e "host unreachable" dig.out.test$n | wc -l) -eq 3 || ret=1
+ grep -F "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig tries the next server after a UDP socket read error ($n)"
+ ret=0
+ dig_with_opts @10.53.0.99 @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ grep -F "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig tries the next server after a TCP socket read error ($n)"
+ # Ask ans8 to be in "close" mode, which closes the connection after accepting it
+ echo "close" | sendcmd 10.53.0.8
+ ret=0
+ dig_with_opts +tcp @10.53.0.8 @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ grep -F "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ # Note that we combine TCP socket "connection error" and "timeout" cases in
+ # one, because it is not trivial to simulate the timeout case in a system test
+ # in Linux without a firewall, but the code which handles error cases during
+ # the connection establishment time does not differentiate between timeout and
+ # other types of errors (unlike during reading), so this one check should be
+ # sufficient for both cases.
+ n=$((n+1))
+ echo_i "check that dig tries the next server after a TCP socket connection error/timeout ($n)"
+ ret=0
+ dig_with_opts +tcp @10.53.0.99 @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ test $(grep -F -e "connection refused" -e "timed out" -e "network unreachable" dig.out.test$n | wc -l) -eq 3 || ret=1
+ grep -F "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig tries the next server after UDP socket read timeouts ($n)"
+ # Ask ans8 to be in "silent" mode
+ echo "silent" | sendcmd 10.53.0.8
+ ret=0
+ dig_with_opts +timeout=1 @10.53.0.8 @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ grep -F "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig tries the next server after TCP socket read timeouts ($n)"
+ # Ask ans8 to be in "silent" mode
+ echo "silent" | sendcmd 10.53.0.8
+ ret=0
+ dig_with_opts +timeout=1 +tcp @10.53.0.8 @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ grep -F "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ # See [GL #3248] for more information
+ n=$((n+1))
+ echo_i "check that dig correctly refuses to use a server with a IPv4 mapped IPv6 address after failing with a regular IP address ($n)"
+ ret=0
+ dig_with_opts @10.53.0.8 @::ffff:10.53.0.8 a.example > dig.out.test$n 2>&1 || ret=1
+ grep -F ";; Skipping mapped address" dig.out.test$n > /dev/null || ret=1
+ grep -F ";; No acceptable nameservers" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ # See [GL #3244] for more information
+ n=$((n+1))
+ echo_i "check that dig handles printing query information with +qr and +y when multiple queries are involved (including a failed query) ($n)"
+ ret=0
+ dig_with_opts +timeout=1 +qr +y @127.0.0.1 @10.53.0.3 a.example > dig.out.test$n 2>&1 || ret=1
+ grep -F "IN A 10.0.0.1" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+else
+ echo_i "$DIG is needed, so skipping these dig tests"
+fi
+
+if [ -x "$MDIG" ] ; then
+ n=$((n+1))
+ echo_i "check that mdig handles malformed option '+ednsopt=:' gracefully ($n)"
+ ret=0
+ mdig_with_opts @10.53.0.3 +ednsopt=: a.example > dig.out.test$n 2>&1 && ret=1
+ grep "ednsopt no code point specified" dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking mdig +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)"
+ ret=0
+ mdig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t DNSKEY example > dig.out.test$n || ret=1
+ grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" dig.out.test$n && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking mdig +multi +norrcomments works for SOA (when default is rrcomments)($n)"
+ ret=0
+ mdig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t SOA example > dig.out.test$n || ret=1
+ grep "; serial" < dig.out.test$n > /dev/null && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ if [ $HAS_PYYAML -ne 0 ] ; then
+ n=$((n+1))
+ echo_i "check mdig +yaml output ($n)"
+ ret=0
+ mdig_with_opts +yaml @10.53.0.3 -t any ns2.example > dig.out.test$n 2>&1 || ret=1
+ $PYTHON yamlget.py dig.out.test$n 0 message response_message_data status > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "NOERROR" ] || ret=1
+ $PYTHON yamlget.py dig.out.test$n 0 message response_message_data QUESTION_SECTION 0 > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "ns2.example. IN ANY" ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ fi
+else
+ echo_i "$MDIG is needed, so skipping these mdig tests"
+fi
+
+if [ -x "$DELV" ] ; then
+ n=$((n+1))
+ echo_i "checking delv short form works ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 +short a a.example > delv.out.test$n || ret=1
+ test "$(wc -l < delv.out.test$n)" -eq 1 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv split width works ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 +split=4 -t sshfp foo.example > delv.out.test$n || ret=1
+ grep " 9ABC DEF6 7890 " < delv.out.test$n > /dev/null || ret=1
+ check_ttl_range delv.out.test$n "SSHFP" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv +unknownformat works ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 +unknownformat a a.example > delv.out.test$n || ret=1
+ grep "CLASS1[ ][ ]*TYPE1[ ][ ]*\\\\# 4 0A000001" < delv.out.test$n > /dev/null || ret=1
+ check_ttl_range delv.out.test$n "TYPE1" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv -4 -6 ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 -4 -6 A a.example > delv.out.test$n 2>&1 && ret=1
+ grep "only one of -4 and -6 allowed" < delv.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv with IPv6 on IPv4 does not work ($n)"
+ if testsock6 fd92:7065:b8e:ffff::3 2>/dev/null
+ then
+ ret=0
+ # following should fail because @IPv4 overrides earlier @IPv6 above
+ # and -6 forces IPv6 so this should fail, with a message
+ # "Use of IPv4 disabled by -6"
+ delv_with_opts @fd92:7065:b8e:ffff::3 @10.53.0.3 -6 -t txt foo.example > delv.out.test$n 2>&1 && ret=1
+ # it should have no results but error output
+ grep "testing" < delv.out.test$n > /dev/null && ret=1
+ grep "Use of IPv4 disabled by -6" delv.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ else
+ echo_i "IPv6 unavailable; skipping"
+ fi
+
+ n=$((n+1))
+ echo_i "checking delv with IPv4 on IPv6 does not work ($n)"
+ if testsock6 fd92:7065:b8e:ffff::3 2>/dev/null
+ then
+ ret=0
+ # following should fail because @IPv6 overrides earlier @IPv4 above
+ # and -4 forces IPv4 so this should fail, with a message
+ # "Use of IPv6 disabled by -4"
+ delv_with_opts @10.53.0.3 @fd92:7065:b8e:ffff::3 -4 -t txt foo.example > delv.out.test$n 2>&1 && ret=1
+ # it should have no results but error output
+ grep "testing" delv.out.test$n > /dev/null && ret=1
+ grep "Use of IPv6 disabled by -4" delv.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ else
+ echo_i "IPv6 unavailable; skipping"
+ fi
+
+ n=$((n+1))
+ echo_i "checking delv with reverse lookup works ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 -x 127.0.0.1 > delv.out.test$n 2>&1 || ret=1
+ # doesn't matter if has answer
+ grep -i "127\\.in-addr\\.arpa\\." < delv.out.test$n > /dev/null || ret=1
+ check_ttl_range delv.out.test$n '\\-ANY' 10800 3 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv over TCP works ($n)"
+ ret=0
+ delv_with_opts +tcp @10.53.0.3 a a.example > delv.out.test$n || ret=1
+ grep "10\\.0\\.0\\.1$" < delv.out.test$n > /dev/null || ret=1
+ check_ttl_range delv.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)"
+ ret=0
+ delv_with_opts +tcp @10.53.0.3 +multi +norrcomments DNSKEY example > delv.out.test$n || ret=1
+ grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < delv.out.test$n > /dev/null && ret=1
+ check_ttl_range delv.out.test$n "DNSKEY" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv +multi +norrcomments works for SOA (when default is rrcomments)($n)"
+ ret=0
+ delv_with_opts +tcp @10.53.0.3 +multi +norrcomments SOA example > delv.out.test$n || ret=1
+ grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < delv.out.test$n > /dev/null && ret=1
+ check_ttl_range delv.out.test$n "SOA" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv +rrcomments works for DNSKEY($n)"
+ ret=0
+ delv_with_opts +tcp @10.53.0.3 +rrcomments DNSKEY example > delv.out.test$n || ret=1
+ grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < delv.out.test$n > /dev/null || ret=1
+ check_ttl_range delv.out.test$n "DNSKEY" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv +short +rrcomments works for DNSKEY ($n)"
+ ret=0
+ delv_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example > delv.out.test$n || ret=1
+ grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < delv.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv +short +rrcomments works ($n)"
+ ret=0
+ delv_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example > delv.out.test$n || ret=1
+ grep -q "$KEYDATA ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < delv.out.test$n || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv +short +nosplit works ($n)"
+ ret=0
+ delv_with_opts +tcp @10.53.0.3 +short +nosplit DNSKEY example > delv.out.test$n || ret=1
+ grep -q "$NOSPLIT" < delv.out.test$n || ret=1
+ test "$(wc -l < delv.out.test$n)" -eq 1 || ret=1
+ test "$(awk '{print NF}' < delv.out.test$n)" -eq 14 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv +short +nosplit +norrcomments works ($n)"
+ ret=0
+ delv_with_opts +tcp @10.53.0.3 +short +nosplit +norrcomments DNSKEY example > delv.out.test$n || ret=1
+ grep -q "$NOSPLIT\$" < delv.out.test$n || ret=1
+ test "$(wc -l < delv.out.test$n)" -eq 1 || ret=1
+ test "$(awk '{print NF}' < delv.out.test$n)" -eq 4 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv +sp works as an abbriviated form of split ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 +sp=4 -t sshfp foo.example > delv.out.test$n || ret=1
+ grep " 9ABC DEF6 7890 " < delv.out.test$n > /dev/null || ret=1
+ check_ttl_range delv.out.test$n "SSHFP" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv +sh works as an abbriviated form of short ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 +sh a a.example > delv.out.test$n || ret=1
+ test "$(wc -l < delv.out.test$n)" -eq 1 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv -c IN works ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 -c IN -t a a.example > delv.out.test$n || ret=1
+ grep "a.example." < delv.out.test$n > /dev/null || ret=1
+ check_ttl_range delv.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv -c CH is ignored, and treated like IN ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 -c CH -t a a.example > delv.out.test$n || ret=1
+ grep "a.example." < delv.out.test$n > /dev/null || ret=1
+ check_ttl_range delv.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking delv H is ignored, and treated like IN ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 -c CH -t a a.example > delv.out.test$n || ret=1
+ grep "a.example." < delv.out.test$n > /dev/null || ret=1
+ check_ttl_range delv.out.test$n "A" 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that delv -q -m works ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 -q -m > delv.out.test$n 2>&1 || ret=1
+ grep '^; -m\..*[0-9]*.*IN.*ANY.*;' delv.out.test$n > /dev/null || ret=1
+ grep "^add " delv.out.test$n > /dev/null && ret=1
+ grep "^del " delv.out.test$n > /dev/null && ret=1
+ check_ttl_range delv.out.test$n '\\-ANY' 300 3 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that delv -t ANY works ($n)"
+ ret=0
+ delv_with_opts @10.53.0.3 -t ANY example > delv.out.test$n 2>&1 || ret=1
+ grep "^example." < delv.out.test$n > /dev/null || ret=1
+ check_ttl_range delv.out.test$n NS 300 || ret=1
+ check_ttl_range delv.out.test$n SOA 300 || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that delv loads key-style trust anchors ($n)"
+ ret=0
+ delv_with_opts -a ns3/anchor.dnskey +root=example @10.53.0.3 -t DNSKEY example > delv.out.test$n 2>&1 || ret=1
+ grep "fully validated" delv.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that delv loads DS-style trust anchors ($n)"
+ ret=0
+ delv_with_opts -a ns3/anchor.ds +root=example @10.53.0.3 -t DNSKEY example > delv.out.test$n 2>&1 || ret=1
+ grep "fully validated" delv.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ if [ $HAS_PYYAML -ne 0 ] ; then
+ n=$((n+1))
+ echo_i "check delv +yaml output ($n)"
+ ret=0
+ delv_with_opts +yaml @10.53.0.3 any ns2.example > delv.out.test$n || ret=1
+ $PYTHON yamlget.py delv.out.test$n status > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "success" ] || ret=1
+ $PYTHON yamlget.py delv.out.test$n query_name > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ [ "$value" = "ns2.example" ] || ret=1
+ $PYTHON yamlget.py delv.out.test$n records 0 answer_not_validated 0 > yamlget.out.test$n 2>&1 || ret=1
+ read -r value < yamlget.out.test$n
+ count=$(echo $value | wc -w )
+ [ ${count:-0} -eq 5 ] || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ fi
+else
+ echo_i "$DELV is needed, so skipping these delv tests"
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/digdelv/tests_sh_digdelv.py b/bin/tests/system/digdelv/tests_sh_digdelv.py
new file mode 100644
index 0000000..2973c26
--- /dev/null
+++ b/bin/tests/system/digdelv/tests_sh_digdelv.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_digdelv(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/digdelv/yamlget.py b/bin/tests/system/digdelv/yamlget.py
new file mode 100644
index 0000000..afa582d
--- /dev/null
+++ b/bin/tests/system/digdelv/yamlget.py
@@ -0,0 +1,35 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import sys
+
+try:
+ import yaml
+# pylint: disable=bare-except
+except:
+ print("No python yaml module, skipping")
+ sys.exit(1)
+
+with open(sys.argv[1], "r", encoding="utf-8") as f:
+ for item in yaml.safe_load_all(f):
+ for key in sys.argv[2:]:
+ try:
+ key = int(key)
+ except ValueError:
+ pass
+
+ try:
+ item = item[key]
+ except KeyError:
+ print('Key "' + key + '" not found.')
+ sys.exit(1)
+
+ print(item)
diff --git a/bin/tests/system/dispatch/ans3/ans.py b/bin/tests/system/dispatch/ans3/ans.py
new file mode 100644
index 0000000..4e4ebac
--- /dev/null
+++ b/bin/tests/system/dispatch/ans3/ans.py
@@ -0,0 +1,99 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import os
+import select
+import signal
+import socket
+import sys
+import time
+
+import dns.flags
+import dns.message
+
+
+def port():
+ env_port = os.getenv("PORT")
+ if env_port is None:
+ env_port = 5300
+ else:
+ env_port = int(env_port)
+
+ return env_port
+
+
+def udp_listen(port):
+ udp = socket.socket(type=socket.SOCK_DGRAM)
+ udp.bind(("10.53.0.3", port))
+
+ return udp
+
+
+def tcp_listen(port):
+ tcp = socket.socket(type=socket.SOCK_STREAM)
+ tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ tcp.bind(("10.53.0.3", port))
+ tcp.listen(100)
+
+ return tcp
+
+
+def udp_tc_once(udp):
+ qrybytes, clientaddr = udp.recvfrom(65535)
+ qry = dns.message.from_wire(qrybytes)
+ answ = dns.message.make_response(qry)
+ answ.flags |= dns.flags.TC
+ answbytes = answ.to_wire()
+ udp.sendto(answbytes, clientaddr)
+
+
+def tcp_once(tcp):
+ csock, _clientaddr = tcp.accept()
+ time.sleep(5)
+ csock.close()
+
+
+def sigterm(signum, frame):
+ os.remove("ans.pid")
+ sys.exit(0)
+
+
+def write_pid():
+ with open("ans.pid", "w") as f:
+ pid = os.getpid()
+ f.write("{}".format(pid))
+
+
+signal.signal(signal.SIGTERM, sigterm)
+write_pid()
+
+udp = udp_listen(port())
+tcp = tcp_listen(port())
+
+input = [udp, tcp]
+
+while True:
+ try:
+ inputready, outputready, exceptready = select.select(input, [], [])
+ except select.error:
+ break
+ except socket.error:
+ break
+ except KeyboardInterrupt:
+ break
+
+ for s in inputready:
+ if s == udp:
+ udp_tc_once(udp)
+ if s == tcp:
+ tcp_once(tcp)
+
+sigterm(signal.SIGTERM, 0)
diff --git a/bin/tests/system/dispatch/clean.sh b/bin/tests/system/dispatch/clean.sh
new file mode 100644
index 0000000..608ec5c
--- /dev/null
+++ b/bin/tests/system/dispatch/clean.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.run ns*/named.conf ns*/named.pid ns*/managed-keys.bind*
+rm -f ans*/ans.run ans*/ans.pid
+rm -f ns*/named.memstats
diff --git a/bin/tests/system/dispatch/ns1/named.conf.in b/bin/tests/system/dispatch/ns1/named.conf.in
new file mode 100644
index 0000000..d3337a5
--- /dev/null
+++ b/bin/tests/system/dispatch/ns1/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+
+ listen-on { 10.53.0.1; };
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+
+ listen-on-v6 { fd92:7065:b8e:ffff::1; };
+ query-source-v6 address fd92:7065:b8e:ffff::1;
+ notify-source-v6 fd92:7065:b8e:ffff::1;
+ transfer-source-v6 fd92:7065:b8e:ffff::1;
+
+ recursion no;
+ servfail-ttl 0;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/dispatch/ns1/root.db b/bin/tests/system/dispatch/ns1/root.db
new file mode 100644
index 0000000..b6b7367
--- /dev/null
+++ b/bin/tests/system/dispatch/ns1/root.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 300 SOA . . 0 0 0 0 0
+. 300 NS ns.nil.
+ns.nil. 300 A 10.53.0.1
+example. 300 NS ns.example.
+ns.example. 300 A 10.53.0.2
diff --git a/bin/tests/system/dispatch/ns2/example.db b/bin/tests/system/dispatch/ns2/example.db
new file mode 100644
index 0000000..f60a47e
--- /dev/null
+++ b/bin/tests/system/dispatch/ns2/example.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+example. 86400 IN SOA ns.example. root.example. 43 10800 900 604800 86400
+example. 86400 IN NS ns.example.
+ns.example. A 10.53.0.2
+
+ns.sub.example. A 10.53.0.3
+sub.example. NS ns.sub.example.
diff --git a/bin/tests/system/dispatch/ns2/named.conf.in b/bin/tests/system/dispatch/ns2/named.conf.in
new file mode 100644
index 0000000..50f2c34
--- /dev/null
+++ b/bin/tests/system/dispatch/ns2/named.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+
+ listen-on { 10.53.0.2; };
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ query-source-v6 address fd92:7065:b8e:ffff::2;
+ notify-source-v6 fd92:7065:b8e:ffff::2;
+ transfer-source-v6 fd92:7065:b8e:ffff::2;
+
+ recursion yes;
+ servfail-ttl 0;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/dispatch/setup.sh b/bin/tests/system/dispatch/setup.sh
new file mode 100644
index 0000000..6929ec5
--- /dev/null
+++ b/bin/tests/system/dispatch/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
diff --git a/bin/tests/system/dispatch/tests_connreset.py b/bin/tests/system/dispatch/tests_connreset.py
new file mode 100644
index 0000000..f74bfd7
--- /dev/null
+++ b/bin/tests/system/dispatch/tests_connreset.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import pytest
+
+pytest.importorskip("dns")
+import dns.message
+import dns.query
+import dns.rcode
+
+
+def test_connreset(named_port):
+ msg = dns.message.make_query(
+ "sub.example.", "A", want_dnssec=True, use_edns=0, payload=1232
+ )
+ ans = dns.query.udp(msg, "10.53.0.2", timeout=10, port=named_port)
+ assert ans.rcode() == dns.rcode.SERVFAIL
diff --git a/bin/tests/system/ditch.pl b/bin/tests/system/ditch.pl
new file mode 100644
index 0000000..e208250
--- /dev/null
+++ b/bin/tests/system/ditch.pl
@@ -0,0 +1,87 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# This is a tool for sending queries via UDP to specified address and
+# port, then exiting without waiting for a response.
+#
+# Usage: ditch.pl [-s <address>] [-p <port>] [filename]
+#
+# Input (in filename, if specified, otherwise stdin) is a series of one
+# or more DNS names and types to send as queries, e.g.:
+#
+# www.example.com A
+# www.example.org MX
+#
+# If not specified, address defaults to 127.0.0.1, port to 53.
+
+require 5.006.001;
+
+use strict;
+use Getopt::Std;
+use Net::DNS;
+use Net::DNS::Packet;
+use IO::File;
+use IO::Socket;
+
+sub usage {
+ print ("Usage: ditch.pl [-s address] [-p port] [file]\n");
+ exit 1;
+}
+
+my %options={};
+getopts("s:p:t:", \%options);
+
+my $addr = "127.0.0.1";
+$addr = $options{s} if defined $options{s};
+
+my $port = 53;
+$port = $options{p} if defined $options{p};
+
+my $file = "STDIN";
+if (@ARGV >= 1) {
+ my $filename = shift @ARGV;
+ open FH, "<$filename" or die "$filename: $!";
+ $file = "FH";
+}
+
+my $input = "";
+while (defined(my $line = <$file>) ) {
+ chomp $line;
+ next if ($line =~ m/^ *#/);
+ my @tokens = split (' ', $line);
+
+ my $packet;
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet();
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet();
+ $err and die $err;
+ }
+
+ my $q = new Net::DNS::Question($tokens[0], $tokens[1], "IN");
+ $packet->header->rd(1);
+ $packet->push(question => $q);
+
+ my $sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port,
+ Proto => "udp",) or die "$!";
+
+ my $bytes = $sock->send($packet->data);
+ #print ("sent $bytes bytes to $addr:$port:\n");
+ #print (" ", unpack("H* ", $packet->data), "\n");
+
+ $sock->close;
+}
+
+close $file;
diff --git a/bin/tests/system/dlzexternal/clean.sh b/bin/tests/system/dlzexternal/clean.sh
new file mode 100644
index 0000000..2bbf75b
--- /dev/null
+++ b/bin/tests/system/dlzexternal/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after dlzexternal tests.
+#
+
+rm -f ns1/update.txt
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns1/ddns.key
+rm -f dig.out*
+rm -f ns*/named.lock
+rm -f ns1/session.key
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/dlzexternal/driver/Makefile.am b/bin/tests/system/dlzexternal/driver/Makefile.am
new file mode 100644
index 0000000..0028edb
--- /dev/null
+++ b/bin/tests/system/dlzexternal/driver/Makefile.am
@@ -0,0 +1,13 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+noinst_LTLIBRARIES = dlzexternal.la
+
+dlzexternal_la_SOURCES = \
+ driver.c \
+ driver.h
+
+dlzexternal_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir)
diff --git a/bin/tests/system/dlzexternal/driver/Makefile.in b/bin/tests/system/dlzexternal/driver/Makefile.in
new file mode 100644
index 0000000..8a26cb9
--- /dev/null
+++ b/bin/tests/system/dlzexternal/driver/Makefile.in
@@ -0,0 +1,778 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+subdir = bin/tests/system/dlzexternal/driver
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+dlzexternal_la_LIBADD =
+am_dlzexternal_la_OBJECTS = driver.lo
+dlzexternal_la_OBJECTS = $(am_dlzexternal_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+dlzexternal_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(dlzexternal_la_LDFLAGS) $(LDFLAGS) -o \
+ $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/driver.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(dlzexternal_la_SOURCES)
+DIST_SOURCES = $(dlzexternal_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS)
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD =
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+noinst_LTLIBRARIES = dlzexternal.la
+dlzexternal_la_SOURCES = \
+ driver.c \
+ driver.h
+
+dlzexternal_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tests/system/dlzexternal/driver/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/tests/system/dlzexternal/driver/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+dlzexternal.la: $(dlzexternal_la_OBJECTS) $(dlzexternal_la_DEPENDENCIES) $(EXTRA_dlzexternal_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(dlzexternal_la_LINK) $(dlzexternal_la_OBJECTS) $(dlzexternal_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/driver.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/driver.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/driver.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am:
+
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir \
+ doc-am doc-local dvi dvi-am html html-am info info-am install \
+ install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \
+ uninstall-am unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/tests/system/dlzexternal/driver/driver.c b/bin/tests/system/dlzexternal/driver/driver.c
new file mode 100644
index 0000000..20edfd0
--- /dev/null
+++ b/bin/tests/system/dlzexternal/driver/driver.c
@@ -0,0 +1,862 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * This provides a very simple example of an external loadable DLZ
+ * driver, with update support.
+ */
+
+#include "driver.h"
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/log.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/dlz_dlopen.h>
+#include <dns/types.h>
+
+/* aliases for exported symbols */
+
+dlz_dlopen_version_t dlz_version;
+dlz_dlopen_create_t dlz_create;
+dlz_dlopen_destroy_t dlz_destroy;
+dlz_dlopen_findzonedb_t dlz_findzonedb;
+dlz_dlopen_lookup_t dlz_lookup;
+dlz_dlopen_allowzonexfr_t dlz_allowzonexfr;
+dlz_dlopen_allnodes_t dlz_allnodes;
+dlz_dlopen_newversion_t dlz_newversion;
+dlz_dlopen_closeversion_t dlz_closeversion;
+dlz_dlopen_configure_t dlz_configure;
+dlz_dlopen_ssumatch_t dlz_ssumatch;
+dlz_dlopen_addrdataset_t dlz_addrdataset;
+dlz_dlopen_subrdataset_t dlz_subrdataset;
+dlz_dlopen_delrdataset_t dlz_delrdataset;
+
+#define CHECK(x) \
+ do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto failure; \
+ } while (0)
+
+#define loginfo(...) \
+ ({ \
+ if ((state != NULL) && (state->log != NULL)) \
+ state->log(ISC_LOG_INFO, __VA_ARGS__); \
+ })
+#define logerr(...) \
+ ({ \
+ if ((state != NULL) && (state->log != NULL)) \
+ state->log(ISC_LOG_ERROR, __VA_ARGS__); \
+ })
+
+/* For this simple example, use fixed sized strings */
+struct record {
+ char name[100];
+ char type[10];
+ char data[200];
+ dns_ttl_t ttl;
+};
+
+#define MAX_RECORDS 100
+
+typedef void
+log_t(int level, const char *fmt, ...);
+
+struct dlz_example_data {
+ char *zone_name;
+
+ /* An example driver doesn't need good memory management :-) */
+ struct record current[MAX_RECORDS];
+ struct record adds[MAX_RECORDS];
+ struct record deletes[MAX_RECORDS];
+
+ bool transaction_started;
+
+ /* Helper functions from the dlz_dlopen driver */
+ log_t *log;
+ dns_sdlz_putrr_t *putrr;
+ dns_sdlz_putnamedrr_t *putnamedrr;
+ dns_dlz_writeablezone_t *writeable_zone;
+};
+
+static bool
+single_valued(const char *type) {
+ const char *single[] = { "soa", "cname", NULL };
+ int i;
+
+ for (i = 0; single[i]; i++) {
+ if (strcasecmp(single[i], type) == 0) {
+ return (true);
+ }
+ }
+ return (false);
+}
+
+/*
+ * Add a record to a list
+ */
+static isc_result_t
+add_name(struct dlz_example_data *state, struct record *list, const char *name,
+ const char *type, dns_ttl_t ttl, const char *data) {
+ int i;
+ bool single = single_valued(type);
+ int first_empty = -1;
+
+ for (i = 0; i < MAX_RECORDS; i++) {
+ INSIST(list[i].name != NULL);
+ if (first_empty == -1 && strlen(list[i].name) == 0U) {
+ first_empty = i;
+ }
+ if (strcasecmp(list[i].name, name) != 0) {
+ continue;
+ }
+ if (strcasecmp(list[i].type, type) != 0) {
+ continue;
+ }
+ if (!single && strcasecmp(list[i].data, data) != 0) {
+ continue;
+ }
+ break;
+ }
+ if (i == MAX_RECORDS && first_empty != -1) {
+ i = first_empty;
+ }
+ if (i == MAX_RECORDS) {
+ logerr("dlz_example: out of record space");
+ return (ISC_R_FAILURE);
+ }
+
+ if (strlen(name) >= sizeof(list[i].name) ||
+ strlen(type) >= sizeof(list[i].type) ||
+ strlen(data) >= sizeof(list[i].data))
+ {
+ return (ISC_R_NOSPACE);
+ }
+
+ strncpy(list[i].name, name, sizeof(list[i].name) - 1);
+ list[i].name[sizeof(list[i].name) - 1] = '\0';
+
+ strncpy(list[i].type, type, sizeof(list[i].type) - 1);
+ list[i].type[sizeof(list[i].type) - 1] = '\0';
+
+ strncpy(list[i].data, data, sizeof(list[i].data) - 1);
+ list[i].data[sizeof(list[i].data) - 1] = '\0';
+
+ list[i].ttl = ttl;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Delete a record from a list
+ */
+static isc_result_t
+del_name(struct dlz_example_data *state, struct record *list, const char *name,
+ const char *type, dns_ttl_t ttl, const char *data) {
+ int i;
+
+ UNUSED(state);
+
+ for (i = 0; i < MAX_RECORDS; i++) {
+ if (strcasecmp(name, list[i].name) == 0 &&
+ strcasecmp(type, list[i].type) == 0 &&
+ strcasecmp(data, list[i].data) == 0 && ttl == list[i].ttl)
+ {
+ break;
+ }
+ }
+ if (i == MAX_RECORDS) {
+ return (ISC_R_NOTFOUND);
+ }
+ memset(&list[i], 0, sizeof(struct record));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fmt_address(isc_sockaddr_t *addr, char *buffer, size_t size) {
+ char addr_buf[INET6_ADDRSTRLEN];
+ const char *ret;
+ uint16_t port = 0;
+
+ switch (addr->type.sa.sa_family) {
+ case AF_INET:
+ port = ntohs(addr->type.sin.sin_port);
+ ret = inet_ntop(AF_INET, &addr->type.sin.sin_addr, addr_buf,
+ sizeof(addr_buf));
+ break;
+ case AF_INET6:
+ port = ntohs(addr->type.sin6.sin6_port);
+ ret = inet_ntop(AF_INET6, &addr->type.sin6.sin6_addr, addr_buf,
+ sizeof(addr_buf));
+ break;
+ default:
+ return (ISC_R_FAILURE);
+ }
+
+ if (ret == NULL) {
+ return (ISC_R_FAILURE);
+ }
+
+ snprintf(buffer, size, "%s#%u", addr_buf, port);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Return the version of the API
+ */
+int
+dlz_version(unsigned int *flags) {
+ UNUSED(flags);
+ return (DLZ_DLOPEN_VERSION);
+}
+
+/*
+ * Remember a helper function from the bind9 dlz_dlopen driver
+ */
+static void
+b9_add_helper(struct dlz_example_data *state, const char *helper_name,
+ void *ptr) {
+ if (strcmp(helper_name, "log") == 0) {
+ state->log = (log_t *)ptr;
+ }
+ if (strcmp(helper_name, "putrr") == 0) {
+ state->putrr = (dns_sdlz_putrr_t *)ptr;
+ }
+ if (strcmp(helper_name, "putnamedrr") == 0) {
+ state->putnamedrr = (dns_sdlz_putnamedrr_t *)ptr;
+ }
+ if (strcmp(helper_name, "writeable_zone") == 0) {
+ state->writeable_zone = (dns_dlz_writeablezone_t *)ptr;
+ }
+}
+
+/*
+ * Called to initialize the driver
+ */
+isc_result_t
+dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata,
+ ...) {
+ struct dlz_example_data *state;
+ const char *helper_name;
+ va_list ap;
+ char soa_data[sizeof("@ hostmaster.root 123 900 600 86400 3600")];
+ isc_result_t result;
+ size_t n;
+
+ UNUSED(dlzname);
+
+ state = calloc(1, sizeof(struct dlz_example_data));
+ if (state == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ /* Fill in the helper functions */
+ va_start(ap, dbdata);
+ while ((helper_name = va_arg(ap, const char *)) != NULL) {
+ b9_add_helper(state, helper_name, va_arg(ap, void *));
+ }
+ va_end(ap);
+
+ if (argc < 2 || argv[1][0] == '\0') {
+ logerr("dlz_example: please specify a zone name");
+ dlz_destroy(state);
+ return (ISC_R_FAILURE);
+ }
+
+ /* Ensure zone name is absolute */
+ state->zone_name = malloc(strlen(argv[1]) + 2);
+ if (state->zone_name == NULL) {
+ free(state);
+ return (ISC_R_NOMEMORY);
+ }
+ if (argv[1][strlen(argv[1]) - 1] == '.') {
+ strcpy(state->zone_name, argv[1]);
+ } else {
+ sprintf(state->zone_name, "%s.", argv[1]);
+ }
+
+ /*
+ * Use relative names to trigger ISC_R_NOSPACE in dns_sdlz_putrr.
+ */
+ if (strcmp(state->zone_name, ".") == 0) {
+ n = strlcpy(soa_data,
+ "@ hostmaster.root 123 900 600 86400 3600",
+ sizeof(soa_data));
+ } else {
+ n = strlcpy(soa_data, "@ hostmaster 123 900 600 86400 3600",
+ sizeof(soa_data));
+ }
+
+ if (n >= sizeof(soa_data)) {
+ CHECK(ISC_R_NOSPACE);
+ }
+
+ add_name(state, &state->current[0], state->zone_name, "soa", 3600,
+ soa_data);
+ add_name(state, &state->current[0], state->zone_name, "ns", 3600,
+ state->zone_name);
+ add_name(state, &state->current[0], state->zone_name, "a", 1800,
+ "10.53.0.1");
+
+ loginfo("dlz_example: started for zone %s", state->zone_name);
+
+ *dbdata = state;
+ return (ISC_R_SUCCESS);
+
+failure:
+ free(state);
+ return (result);
+}
+
+/*
+ * Shut down the backend
+ */
+void
+dlz_destroy(void *dbdata) {
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+
+ loginfo("dlz_example: shutting down zone %s", state->zone_name);
+ free(state->zone_name);
+ free(state);
+}
+
+/*
+ * See if we handle a given zone
+ */
+isc_result_t
+dlz_findzonedb(void *dbdata, const char *name, dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo) {
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+ isc_sockaddr_t *src;
+ char addrbuf[100];
+ char absolute[1024];
+
+ strcpy(addrbuf, "unknown");
+ if (methods != NULL && methods->sourceip != NULL &&
+ methods->version - methods->age <= DNS_CLIENTINFOMETHODS_VERSION &&
+ DNS_CLIENTINFOMETHODS_VERSION <= methods->version)
+ {
+ methods->sourceip(clientinfo, &src);
+ fmt_address(src, addrbuf, sizeof(addrbuf));
+ }
+
+ loginfo("dlz_example: dlz_findzonedb called with name '%s' "
+ "in zone DB '%s' from %s",
+ name, state->zone_name, addrbuf);
+
+ /*
+ * Returning ISC_R_NOTFOUND will cause the query logic to
+ * check the database for parent names, looking for zone cuts.
+ *
+ * Returning ISC_R_NOMORE prevents the query logic from doing
+ * this; it will move onto the next database after a single query.
+ */
+ if (strcasecmp(name, "test.example.com") == 0) {
+ return (ISC_R_NOMORE);
+ }
+
+ /*
+ * For example.net, only return ISC_R_NOMORE when queried
+ * from 10.53.0.1.
+ */
+ if (strcasecmp(name, "test.example.net") == 0 &&
+ strncmp(addrbuf, "10.53.0.1", 9) == 0)
+ {
+ return (ISC_R_NOMORE);
+ }
+
+ /*
+ * For bigcname.domain, return success so it appears to be
+ * the zone origin; this regression tests a bug in which
+ * zone origin nodes could fail to return SERVFAIL to the client.
+ */
+ if (strcasecmp(name, "bigcname.domain") == 0) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Return success if we have an exact match between the
+ * zone name and the qname
+ */
+ if (strcasecmp(state->zone_name, name) == 0) {
+ return (ISC_R_SUCCESS);
+ }
+
+ snprintf(absolute, sizeof(absolute), "%s.", name);
+ if (strcasecmp(state->zone_name, absolute) == 0) {
+ return (ISC_R_SUCCESS);
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+/*
+ * Look up one record in the sample database.
+ *
+ * If the queryname is "source-addr", send back a TXT record containing
+ * the address of the client, to test the use of 'methods' and 'clientinfo'
+ *
+ * If the queryname is "too-long", send back a TXT record that's too long
+ * to process; this should result in a SERVFAIL when queried.
+ */
+isc_result_t
+dlz_lookup(const char *zone, const char *name, void *dbdata,
+ dns_sdlzlookup_t *lookup, dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo) {
+ isc_result_t result;
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+ bool found = false;
+ void *dbversion = NULL;
+ isc_sockaddr_t *src;
+ char full_name[256];
+ char buf[512];
+ static char last[256];
+ static int count = 0;
+ int i, size;
+
+ UNUSED(zone);
+
+ if (state->putrr == NULL) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ if (strcmp(name, "@") == 0) {
+ size = snprintf(full_name, sizeof(full_name), "%s",
+ state->zone_name);
+ } else if (strcmp(state->zone_name, ".") == 0) {
+ size = snprintf(full_name, sizeof(full_name), "%s.", name);
+ } else {
+ size = snprintf(full_name, sizeof(full_name), "%s.%s", name,
+ state->zone_name);
+ }
+
+ if (size < 0 || (size_t)size >= sizeof(full_name) ||
+ (size_t)size >= sizeof(last))
+ {
+ return (ISC_R_NOSPACE);
+ }
+
+ /*
+ * For test purposes, log all calls to dlz_lookup()
+ */
+ if (strcasecmp(full_name, last) == 0) {
+ count++;
+ } else {
+ count = 1;
+ memcpy(last, full_name, size + 1);
+ }
+ loginfo("lookup #%d for %s", count, full_name);
+
+ /*
+ * If we need to know the database version (as set in
+ * the 'newversion' dlz function) we can pick it up from the
+ * clientinfo.
+ *
+ * This allows a lookup to query the correct version of the DNS
+ * data, if the DLZ can differentiate between versions.
+ *
+ * For example, if a new database transaction is created by
+ * 'newversion', the lookup should query within the same
+ * transaction scope if it can.
+ *
+ * If the DLZ only operates on 'live' data, then version
+ * wouldn't necessarily be needed.
+ */
+ if (clientinfo != NULL && clientinfo->version >= 2) {
+ dbversion = clientinfo->dbversion;
+ if (dbversion != NULL && *(bool *)dbversion) {
+ loginfo("dlz_example: lookup against live transaction");
+ }
+ }
+
+ if (strcmp(name, "source-addr") == 0) {
+ char ecsbuf[DNS_ECS_FORMATSIZE] = "not supported";
+ strncpy(buf, "unknown", sizeof(buf));
+ if (methods != NULL && methods->sourceip != NULL &&
+ (methods->version - methods->age <=
+ DNS_CLIENTINFOMETHODS_VERSION) &&
+ DNS_CLIENTINFOMETHODS_VERSION <= methods->version)
+ {
+ methods->sourceip(clientinfo, &src);
+ fmt_address(src, buf, sizeof(buf));
+ }
+ if (clientinfo != NULL && clientinfo->version >= 3) {
+ if (clientinfo->ecs.addr.family != AF_UNSPEC) {
+ dns_ecs_format(&clientinfo->ecs, ecsbuf,
+ sizeof(ecsbuf));
+ } else {
+ snprintf(ecsbuf, sizeof(ecsbuf), "%s",
+ "not present");
+ }
+ }
+ i = strlen(buf);
+ snprintf(buf + i, sizeof(buf) - i - 1, " ECS %s", ecsbuf);
+
+ loginfo("dlz_example: lookup connection from %s", buf);
+
+ found = true;
+ result = state->putrr(lookup, "TXT", 0, buf);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ if (strcmp(name, "too-long") == 0 ||
+ strcmp(zone, "bigcname.domain") == 0)
+ {
+ for (i = 0; i < 511; i++) {
+ buf[i] = 'x';
+ }
+ buf[i] = '\0';
+ found = true;
+ result = state->putrr(lookup, "TXT", 0, buf);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ /* Tests for DLZ redirection zones */
+ if (strcmp(name, "*") == 0 && strcmp(zone, ".") == 0) {
+ result = state->putrr(lookup, "A", 0, "100.100.100.2");
+ found = true;
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ if (strcmp(name, "long.name.is.not.there") == 0 &&
+ strcmp(zone, ".") == 0)
+ {
+ result = state->putrr(lookup, "A", 0, "100.100.100.3");
+ found = true;
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ /* Answer from current records */
+ for (i = 0; i < MAX_RECORDS; i++) {
+ if (strcasecmp(state->current[i].name, full_name) == 0) {
+ found = true;
+ result = state->putrr(lookup, state->current[i].type,
+ state->current[i].ttl,
+ state->current[i].data);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ }
+
+ if (!found) {
+ return (ISC_R_NOTFOUND);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * See if a zone transfer is allowed
+ */
+isc_result_t
+dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+ isc_result_t result;
+
+ loginfo("dlz_example: dlz_allowzonexfr called for %s", name);
+
+ result = dlz_findzonedb(dbdata, name, NULL, NULL);
+ if (result != ISC_R_SUCCESS) {
+ loginfo("dlz_example: findzonedb returned %s",
+ isc_result_totext(result));
+ return (result);
+ }
+
+ /*
+ * Exception for "example.org" so we can test the use of
+ * the view ACL.
+ */
+ if (strcmp(name, "example.org") == 0) {
+ loginfo("dlz_example: use view ACL for example.org");
+ return (ISC_R_DEFAULT);
+ }
+
+ /*
+ * Exception for 10.53.0.5 so we can test that allow-transfer
+ * is effective.
+ */
+ if (strcmp(client, "10.53.0.5") == 0) {
+ loginfo("dlz_example: disallow transfer to 10.53.0.5");
+ return (ISC_R_NOPERM);
+ }
+
+ loginfo("dlz_example: transfer allowed for %s", name);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Perform a zone transfer
+ */
+isc_result_t
+dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) {
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+ int i;
+
+ UNUSED(zone);
+
+ if (state->putnamedrr == NULL) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ for (i = 0; i < MAX_RECORDS; i++) {
+ isc_result_t result;
+ if (strlen(state->current[i].name) == 0U) {
+ continue;
+ }
+ result = state->putnamedrr(allnodes, state->current[i].name,
+ state->current[i].type,
+ state->current[i].ttl,
+ state->current[i].data);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Start a transaction
+ */
+isc_result_t
+dlz_newversion(const char *zone, void *dbdata, void **versionp) {
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+
+ if (state->transaction_started) {
+ loginfo("dlz_example: transaction already started for zone %s",
+ zone);
+ return (ISC_R_FAILURE);
+ }
+
+ state->transaction_started = true;
+ *versionp = (void *)&state->transaction_started;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * End a transaction
+ */
+void
+dlz_closeversion(const char *zone, bool commit, void *dbdata, void **versionp) {
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+
+ if (!state->transaction_started) {
+ loginfo("dlz_example: transaction not started for zone %s",
+ zone);
+ *versionp = NULL;
+ return;
+ }
+
+ state->transaction_started = false;
+
+ *versionp = NULL;
+
+ if (commit) {
+ int i;
+ loginfo("dlz_example: committing transaction on zone %s", zone);
+ for (i = 0; i < MAX_RECORDS; i++) {
+ if (strlen(state->deletes[i].name) > 0U) {
+ (void)del_name(state, &state->current[0],
+ state->deletes[i].name,
+ state->deletes[i].type,
+ state->deletes[i].ttl,
+ state->deletes[i].data);
+ }
+ }
+ for (i = 0; i < MAX_RECORDS; i++) {
+ if (strlen(state->adds[i].name) > 0U) {
+ (void)add_name(state, &state->current[0],
+ state->adds[i].name,
+ state->adds[i].type,
+ state->adds[i].ttl,
+ state->adds[i].data);
+ }
+ }
+ } else {
+ loginfo("dlz_example: cancelling transaction on zone %s", zone);
+ }
+ memset(state->adds, 0, sizeof(state->adds));
+ memset(state->deletes, 0, sizeof(state->deletes));
+}
+
+/*
+ * Configure a writeable zone
+ */
+isc_result_t
+dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *dbdata) {
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+ isc_result_t result;
+
+ loginfo("dlz_example: starting configure");
+
+ if (state->writeable_zone == NULL) {
+ loginfo("dlz_example: no writeable_zone method available");
+ return (ISC_R_FAILURE);
+ }
+
+ result = state->writeable_zone(view, dlzdb, state->zone_name);
+ if (result != ISC_R_SUCCESS) {
+ loginfo("dlz_example: failed to configure zone %s",
+ state->zone_name);
+ return (result);
+ }
+
+ loginfo("dlz_example: configured writeable zone %s", state->zone_name);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Authorize a zone update
+ */
+bool
+dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
+ const char *type, const char *key, uint32_t keydatalen,
+ unsigned char *keydata, void *dbdata) {
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+
+ UNUSED(tcpaddr);
+ UNUSED(type);
+ UNUSED(key);
+ UNUSED(keydatalen);
+ UNUSED(keydata);
+
+ if (strncmp(name, "deny.", 5) == 0) {
+ loginfo("dlz_example: denying update of name=%s by %s", name,
+ signer);
+ return (false);
+ }
+ loginfo("dlz_example: allowing update of name=%s by %s", name, signer);
+ return (true);
+}
+
+static isc_result_t
+modrdataset(struct dlz_example_data *state, const char *name,
+ const char *rdatastr, struct record *list) {
+ char *full_name, *dclass, *type, *data, *ttlstr, *buf;
+ char absolute[1024];
+ isc_result_t result;
+ char *saveptr = NULL;
+
+ buf = strdup(rdatastr);
+ if (buf == NULL) {
+ return (ISC_R_FAILURE);
+ }
+
+ /*
+ * The format is:
+ * FULLNAME\tTTL\tDCLASS\tTYPE\tDATA
+ *
+ * The DATA field is space separated, and is in the data format
+ * for the type used by dig
+ */
+
+ full_name = strtok_r(buf, "\t", &saveptr);
+ if (full_name == NULL) {
+ goto error;
+ }
+
+ ttlstr = strtok_r(NULL, "\t", &saveptr);
+ if (ttlstr == NULL) {
+ goto error;
+ }
+
+ dclass = strtok_r(NULL, "\t", &saveptr);
+ if (dclass == NULL) {
+ goto error;
+ }
+
+ type = strtok_r(NULL, "\t", &saveptr);
+ if (type == NULL) {
+ goto error;
+ }
+
+ data = strtok_r(NULL, "\t", &saveptr);
+ if (data == NULL) {
+ goto error;
+ }
+
+ if (name[strlen(name) - 1] != '.') {
+ snprintf(absolute, sizeof(absolute), "%s.", name);
+ name = absolute;
+ }
+
+ result = add_name(state, list, name, type, strtoul(ttlstr, NULL, 10),
+ data);
+ free(buf);
+ return (result);
+
+error:
+ free(buf);
+ return (ISC_R_FAILURE);
+}
+
+isc_result_t
+dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata,
+ void *version) {
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+
+ if (version != (void *)&state->transaction_started) {
+ return (ISC_R_FAILURE);
+ }
+
+ loginfo("dlz_example: adding rdataset %s '%s'", name, rdatastr);
+
+ return (modrdataset(state, name, rdatastr, &state->adds[0]));
+}
+
+isc_result_t
+dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata,
+ void *version) {
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+
+ if (version != (void *)&state->transaction_started) {
+ return (ISC_R_FAILURE);
+ }
+
+ loginfo("dlz_example: subtracting rdataset %s '%s'", name, rdatastr);
+
+ return (modrdataset(state, name, rdatastr, &state->deletes[0]));
+}
+
+isc_result_t
+dlz_delrdataset(const char *name, const char *type, void *dbdata,
+ void *version) {
+ struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+
+ if (version != (void *)&state->transaction_started) {
+ return (ISC_R_FAILURE);
+ }
+
+ loginfo("dlz_example: deleting rdataset %s of type %s", name, type);
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/bin/tests/system/dlzexternal/driver/driver.h b/bin/tests/system/dlzexternal/driver/driver.h
new file mode 100644
index 0000000..2c1a594
--- /dev/null
+++ b/bin/tests/system/dlzexternal/driver/driver.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <dns/dlz_dlopen.h>
+
+/*
+ * This header includes the declarations of entry points.
+ */
+
+dlz_dlopen_version_t dlz_version;
+dlz_dlopen_create_t dlz_create;
+dlz_dlopen_destroy_t dlz_destroy;
+dlz_dlopen_findzonedb_t dlz_findzonedb;
+dlz_dlopen_lookup_t dlz_lookup;
+dlz_dlopen_allowzonexfr_t dlz_allowzonexfr;
+dlz_dlopen_allnodes_t dlz_allnodes;
+dlz_dlopen_newversion_t dlz_newversion;
+dlz_dlopen_closeversion_t dlz_closeversion;
+dlz_dlopen_configure_t dlz_configure;
+dlz_dlopen_ssumatch_t dlz_ssumatch;
+dlz_dlopen_addrdataset_t dlz_addrdataset;
+dlz_dlopen_subrdataset_t dlz_subrdataset;
+dlz_dlopen_delrdataset_t dlz_delrdataset;
diff --git a/bin/tests/system/dlzexternal/ns1/named.conf.in b/bin/tests/system/dlzexternal/ns1/named.conf.in
new file mode 100644
index 0000000..f8b36e9
--- /dev/null
+++ b/bin/tests/system/dlzexternal/ns1/named.conf.in
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.1; 127.0.0.1; };
+ listen-on-v6 { none; };
+ allow-transfer { !10.53.0.1; any; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+include "ddns.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+dlz "example one" {
+ database "dlopen ../driver/.libs/dlzexternal.so example.nil";
+};
+
+dlz "example two" {
+ database "dlopen ../driver/.libs/dlzexternal.so alternate.nil";
+};
+
+dlz "example three" {
+ database "dlopen ../driver/.libs/dlzexternal.so example.org";
+};
+
+dlz "example four" {
+ // Long zone name to trigger ISC_R_NOSPACE in dns_sdlz_putrr.
+ database "dlopen ../driver/.libs/dlzexternal.so 123456789.123456789.123456789.123456789.123456789.example.foo";
+};
+
+dlz "unsearched1" {
+ database "dlopen ../driver/.libs/dlzexternal.so other.nil";
+ search no;
+};
+
+dlz "unsearched2" {
+ database "dlopen ../driver/.libs/dlzexternal.so zone.nil";
+ search no;
+};
+
+dlz redzone {
+ database "dlopen ../driver/.libs/dlzexternal.so .";
+ search no;
+};
+
+zone zone.nil {
+ type primary;
+ dlz unsearched2;
+};
+
+zone "." {
+ type redirect;
+ dlz redzone;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/dlzexternal/ns1/root.db b/bin/tests/system/dlzexternal/ns1/root.db
new file mode 100644
index 0000000..6cbe579
--- /dev/null
+++ b/bin/tests/system/dlzexternal/ns1/root.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns1.example.
+ns1.example. A 10.53.0.1
+
+exists. A 10.10.10.10
diff --git a/bin/tests/system/dlzexternal/prereq.sh b/bin/tests/system/dlzexternal/prereq.sh
new file mode 100644
index 0000000..066a74e
--- /dev/null
+++ b/bin/tests/system/dlzexternal/prereq.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$FEATURETEST --tsan && {
+ echo_i "TSAN - skipping dlzexternal test"
+ exit 255
+}
+
+exit 0
diff --git a/bin/tests/system/dlzexternal/setup.sh b/bin/tests/system/dlzexternal/setup.sh
new file mode 100644
index 0000000..dda16df
--- /dev/null
+++ b/bin/tests/system/dlzexternal/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$TSIGKEYGEN ddns-key.example.nil > ns1/ddns.key
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/dlzexternal/tests.sh b/bin/tests/system/dlzexternal/tests.sh
new file mode 100644
index 0000000..a86ea7e
--- /dev/null
+++ b/bin/tests/system/dlzexternal/tests.sh
@@ -0,0 +1,231 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+DIGOPTS="@10.53.0.1 -p ${PORT} +nocookie"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+newtest() {
+ n=$((n + 1))
+ echo_i "${1} (${n})"
+ ret=0
+}
+
+test_update() {
+ host="$1"
+ type="$2"
+ cmd="$3"
+ digout="$4"
+ should_fail="$5"
+
+ cat <<EOF > ns1/update.txt
+server 10.53.0.1 ${PORT}
+update add $host $cmd
+send
+EOF
+
+ newtest "testing update for $host $type $cmd${comment:+ }$comment"
+ $NSUPDATE -k ns1/ddns.key ns1/update.txt > /dev/null 2>&1 || {
+ [ "$should_fail" ] || \
+ echo_i "update failed for $host $type $cmd"
+ return 1
+ }
+
+ out=$($DIG $DIGOPTS -t $type -q $host | grep -E "^$host")
+ lines=$(echo "$out" | grep "$digout" | wc -l)
+ [ $lines -eq 1 ] || {
+ [ "$should_fail" ] || \
+ echo_i "dig output incorrect for $host $type $cmd: $out"
+ return 1
+ }
+ return 0
+}
+
+test_update testdc1.example.nil. A "86400 A 10.53.0.10" "10.53.0.10" || ret=1
+status=$((status + ret))
+
+test_update testdc2.example.nil. A "86400 A 10.53.0.11" "10.53.0.11" || ret=1
+status=$((status + ret))
+
+test_update testdc3.example.nil. A "86400 A 10.53.0.10" "10.53.0.10" || ret=1
+status=$((status + ret))
+
+test_update deny.example.nil. TXT "86400 TXT helloworld" "helloworld" should_fail && ret=1
+status=$((status + ret))
+
+newtest "testing nxrrset"
+$DIG $DIGOPTS testdc1.example.nil AAAA > dig.out.$n || ret=1
+grep "status: NOERROR" dig.out.$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.$n > /dev/null || ret=1
+status=$((status + ret))
+
+newtest "testing prerequisites are checked correctly"
+cat > ns1/update.txt << EOF
+server 10.53.0.1 ${PORT}
+prereq nxdomain testdc3.example.nil
+update add testdc3.example.nil 86500 in a 10.53.0.12
+send
+EOF
+$NSUPDATE -k ns1/ddns.key ns1/update.txt > /dev/null 2>&1 && ret=1
+out=$($DIG $DIGOPTS +short a testdc3.example.nil)
+[ "$out" = "10.53.0.12" ] && ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing passing client info into DLZ driver"
+out=$($DIG $DIGOPTS +short -t txt -q source-addr.example.nil | grep -v '^;')
+addr=$(eval echo "$out" | cut -f1 -d'#')
+[ "$addr" = "10.53.0.1" ] || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing DLZ driver is cleaned up on reload"
+rndc_reload ns1 10.53.0.1
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ ret=0
+ grep 'dlz_example: shutting down zone example.nil' ns1/named.run > /dev/null 2>&1 || ret=1
+ [ "$ret" -eq 0 ] && break
+ sleep 1
+done
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing multiple DLZ drivers"
+test_update testdc1.alternate.nil. A "86400 A 10.53.0.10" "10.53.0.10" || ret=1
+status=$((status + ret))
+
+newtest "testing AXFR from DLZ drivers"
+$DIG $DIGOPTS +noall +answer axfr example.nil > dig.out.example.ns1.test$n || ret=1
+lines=$(cat dig.out.example.ns1.test$n | wc -l)
+[ ${lines:-0} -eq 4 ] || ret=1
+$DIG $DIGOPTS +noall +answer axfr alternate.nil > dig.out.alternate.ns1.test$n || ret=1
+lines=$(cat dig.out.alternate.ns1.test$n | wc -l)
+[ ${lines:-0} -eq 5 ] || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing AXFR denied from DLZ drivers"
+$DIG $DIGOPTS -b 10.53.0.5 +noall +answer axfr example.nil > dig.out.example.ns1.test$n || ret=1
+grep "; Transfer failed" dig.out.example.ns1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS -b 10.53.0.5 +noall +answer axfr alternate.nil > dig.out.alternate.ns1.test$n || ret=1
+grep "; Transfer failed" dig.out.alternate.ns1.test$n > /dev/null || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing AXFR denied based on view ACL"
+# 10.53.0.1 should be disallowed
+$DIG $DIGOPTS -b 10.53.0.1 +noall +answer axfr example.org > dig.out.example.ns1.test$n.1 || ret=1
+grep "; Transfer failed" dig.out.example.ns1.test$n.1 > /dev/null || ret=1
+# 10.53.0.2 should be allowed
+$DIG $DIGOPTS -b 10.53.0.2 +noall +answer axfr example.org > dig.out.example.ns1.test$n.2 || ret=1
+grep "; Transfer failed" dig.out.example.ns1.test$n.2 > /dev/null && ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing unsearched/unregistered DLZ zone is not found"
+$DIG $DIGOPTS +noall +answer ns other.nil > dig.out.ns1.test$n || ret=1
+grep "3600.IN.NS.other.nil." dig.out.ns1.test$n > /dev/null && ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing unsearched/registered DLZ zone is found"
+$DIG $DIGOPTS +noall +answer ns zone.nil > dig.out.ns1.test$n || ret=1
+grep "3600.IN.NS.zone.nil." dig.out.ns1.test$n > /dev/null || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing unsearched/registered DLZ zone is found"
+$DIG $DIGOPTS +noall +answer ns zone.nil > dig.out.ns1.test$n || ret=1
+grep "3600.IN.NS.zone.nil." dig.out.ns1.test$n > /dev/null || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing correct behavior with findzone returning ISC_R_NOMORE"
+$DIG $DIGOPTS +noall a test.example.com > /dev/null 2>&1 || ret=1
+# we should only find one logged lookup per searched DLZ database
+lines=$(grep "dlz_findzonedb.*test\.example\.com.*example.nil" ns1/named.run | wc -l)
+[ $lines -eq 1 ] || ret=1
+lines=$(grep "dlz_findzonedb.*test\.example\.com.*alternate.nil" ns1/named.run | wc -l)
+[ $lines -eq 1 ] || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing findzone can return different results per client"
+$DIG $DIGOPTS -b 10.53.0.1 +noall a test.example.net > /dev/null 2>&1 || ret=1
+# we should only find one logged lookup per searched DLZ database
+lines=$(grep "dlz_findzonedb.*example\.net.*example.nil" ns1/named.run | wc -l)
+[ $lines -eq 1 ] || ret=1
+lines=$(grep "dlz_findzonedb.*example\.net.*alternate.nil" ns1/named.run | wc -l)
+[ $lines -eq 1 ] || ret=1
+$DIG $DIGOPTS -b 10.53.0.2 +noall a test.example.net > /dev/null 2>&1 || ret=1
+# we should find several logged lookups this time
+lines=$(grep "dlz_findzonedb.*example\.net.*example.nil" ns1/named.run | wc -l)
+[ $lines -gt 2 ] || ret=1
+lines=$(grep "dlz_findzonedb.*example\.net.*alternate.nil" ns1/named.run | wc -l)
+[ $lines -gt 2 ] || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing zone returning oversized data"
+$DIG $DIGOPTS txt too-long.example.nil > dig.out.ns1.test$n 2>&1 || ret=1
+grep "status: SERVFAIL" dig.out.ns1.test$n > /dev/null || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "testing zone returning oversized data at zone origin"
+$DIG $DIGOPTS txt bigcname.domain > dig.out.ns1.test$n 2>&1 || ret=1
+grep "status: SERVFAIL" dig.out.ns1.test$n > /dev/null || ret=1
+[ "$ret" -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+newtest "checking redirected lookup for nonexistent name"
+$DIG $DIGOPTS @10.53.0.1 unexists a > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "^unexists.*A.*100.100.100.2" dig.out.ns1.test$n > /dev/null || ret=1
+grep "flags:[^;]* aa[ ;]" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "checking no redirected lookup for nonexistent type"
+$DIG $DIGOPTS @10.53.0.1 exists aaaa > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "checking redirected lookup for a long nonexistent name"
+$DIG $DIGOPTS @10.53.0.1 long.name.is.not.there a > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "^long.name.*A.*100.100.100.3" dig.out.ns1.test$n > /dev/null || ret=1
+grep "flags:[^;]* aa[ ;]" dig.out.ns1.test$n > /dev/null || ret=1
+lookups=$(grep "lookup #.*\.not\.there" ns1/named.run | wc -l)
+[ "$lookups" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "checking ECS data is passed to driver in clientinfo"
+$DIG $DIGOPTS +short +subnet=192.0/16 source-addr.example.nil txt > dig.out.ns1.test$n.1 || ret=1
+grep "192.0.0.0/16/0" dig.out.ns1.test$n.1 > /dev/null || ret=1
+$DIG $DIGOPTS +short source-addr.example.nil txt > dig.out.ns1.test$n.2 || ret=1
+grep "not.*present" dig.out.ns1.test$n.2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dlzexternal/tests_sh_dlzexternal.py b/bin/tests/system/dlzexternal/tests_sh_dlzexternal.py
new file mode 100644
index 0000000..1c0f7e5
--- /dev/null
+++ b/bin/tests/system/dlzexternal/tests_sh_dlzexternal.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_dlzexternal(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/dns64/clean.sh b/bin/tests/system/dns64/clean.sh
new file mode 100644
index 0000000..b773e2d
--- /dev/null
+++ b/bin/tests/system/dns64/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.conf
+rm -f ns1/K*
+rm -f ns1/signed.db*
+rm -f ns1/dsset-signed.
+rm -f */named.memstats
+rm -f */named.run
+rm -f dig.out.*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/dns64/conf/bad1.conf b/bin/tests/system/dns64/conf/bad1.conf
new file mode 100644
index 0000000..a4b7e7f
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad1.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 ::/0 { };
+};
diff --git a/bin/tests/system/dns64/conf/bad10.conf b/bin/tests/system/dns64/conf/bad10.conf
new file mode 100644
index 0000000..21855f6
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad10.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 0000:0000:0000:0000:0100:000f::/96 { }; /* bits [64..71] MBZ */
+};
diff --git a/bin/tests/system/dns64/conf/bad11.conf b/bin/tests/system/dns64/conf/bad11.conf
new file mode 100644
index 0000000..c3bdd92
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad11.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 0000:0000:0000:0000:0200:000f::/96 { }; /* bits [64..71] MBZ */
+};
diff --git a/bin/tests/system/dns64/conf/bad12.conf b/bin/tests/system/dns64/conf/bad12.conf
new file mode 100644
index 0000000..6ffe720
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad12.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 0000:0000:0000:0000:0400:000f::/96 { }; /* bits [64..71] MBZ */
+};
diff --git a/bin/tests/system/dns64/conf/bad13.conf b/bin/tests/system/dns64/conf/bad13.conf
new file mode 100644
index 0000000..dc6c064
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad13.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 0000:0000:0000:0000:0800:000f::/96 { }; /* bits [64..71] MBZ */
+};
diff --git a/bin/tests/system/dns64/conf/bad14.conf b/bin/tests/system/dns64/conf/bad14.conf
new file mode 100644
index 0000000..985101a
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad14.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 0000:0000:0000:0000:1000:000f::/96 { }; /* bits [64..71] MBZ */
+};
diff --git a/bin/tests/system/dns64/conf/bad15.conf b/bin/tests/system/dns64/conf/bad15.conf
new file mode 100644
index 0000000..0931a55
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad15.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 0000:0000:0000:0000:2000:000f::/96 { }; /* bits [64..71] MBZ */
+};
diff --git a/bin/tests/system/dns64/conf/bad16.conf b/bin/tests/system/dns64/conf/bad16.conf
new file mode 100644
index 0000000..3a8b962
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad16.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 0000:0000:0000:0000:4000:000f::/96 { }; /* bits [64..71] MBZ */
+};
diff --git a/bin/tests/system/dns64/conf/bad17.conf b/bin/tests/system/dns64/conf/bad17.conf
new file mode 100644
index 0000000..6c9079b
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad17.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 0000:0000:0000:0000:8000:000f::/96 { }; /* bits [64..71] MBZ */
+};
diff --git a/bin/tests/system/dns64/conf/bad18.conf b/bin/tests/system/dns64/conf/bad18.conf
new file mode 100644
index 0000000..566e177
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad18.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 ::/32 { suffix ::8000:0000:0000:0000; }; /* bits [64..71] MBZ */
+};
diff --git a/bin/tests/system/dns64/conf/bad19.conf b/bin/tests/system/dns64/conf/bad19.conf
new file mode 100644
index 0000000..8a9fb76
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad19.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 ::/32 { suffix ::0100:0000:0000:0000; }; /* bits [64..71] MBZ */
+};
diff --git a/bin/tests/system/dns64/conf/bad2.conf b/bin/tests/system/dns64/conf/bad2.conf
new file mode 100644
index 0000000..d275998
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad2.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 ::/96 { suffix ::1; };
+};
diff --git a/bin/tests/system/dns64/conf/bad3.conf b/bin/tests/system/dns64/conf/bad3.conf
new file mode 100644
index 0000000..24971b3
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad3.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 ::/96 { suffix 127.0.0.1; };
+};
diff --git a/bin/tests/system/dns64/conf/bad4.conf b/bin/tests/system/dns64/conf/bad4.conf
new file mode 100644
index 0000000..bc73ca5
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad4.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 ::/129 { };
+};
diff --git a/bin/tests/system/dns64/conf/bad5.conf b/bin/tests/system/dns64/conf/bad5.conf
new file mode 100644
index 0000000..bc73ca5
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad5.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 ::/129 { };
+};
diff --git a/bin/tests/system/dns64/conf/bad6.conf b/bin/tests/system/dns64/conf/bad6.conf
new file mode 100644
index 0000000..1d85ab9
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad6.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 :: { };
+};
diff --git a/bin/tests/system/dns64/conf/bad7.conf b/bin/tests/system/dns64/conf/bad7.conf
new file mode 100644
index 0000000..afbf437
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad7.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 FC36:EAFE:F993::/64 {
+ exclude { bogusacl; };
+ };
+};
diff --git a/bin/tests/system/dns64/conf/bad8.conf b/bin/tests/system/dns64/conf/bad8.conf
new file mode 100644
index 0000000..9aa423f
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad8.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 FC36:EAFE:F993::/64 {
+ clients { bogusacl; };
+ };
+};
diff --git a/bin/tests/system/dns64/conf/bad9.conf b/bin/tests/system/dns64/conf/bad9.conf
new file mode 100644
index 0000000..b74204c
--- /dev/null
+++ b/bin/tests/system/dns64/conf/bad9.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dns64 FC36:EAFE:F993::/64 {
+ mapped { bogusacl; };
+ };
+};
diff --git a/bin/tests/system/dns64/conf/good1.conf b/bin/tests/system/dns64/conf/good1.conf
new file mode 100644
index 0000000..d84733e
--- /dev/null
+++ b/bin/tests/system/dns64/conf/good1.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+options {
+ /* Well Known Prefix */
+ dns64 64:FF9B::/96 {
+ clients { any; };
+ mapped { !rfc1918; any; };
+ exclude { ::ffff:0:0/96; };
+ };
+};
diff --git a/bin/tests/system/dns64/conf/good2.conf b/bin/tests/system/dns64/conf/good2.conf
new file mode 100644
index 0000000..41b5730
--- /dev/null
+++ b/bin/tests/system/dns64/conf/good2.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+options {
+ /* Well Known Prefix */
+ dns64 64:FF9B::/96 {
+ mapped { !rfc1918; any; };
+ exclude { ::ffff:0:0/96; };
+ };
+};
diff --git a/bin/tests/system/dns64/conf/good3.conf b/bin/tests/system/dns64/conf/good3.conf
new file mode 100644
index 0000000..450b2e0
--- /dev/null
+++ b/bin/tests/system/dns64/conf/good3.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+options {
+ /* Well Known Prefix */
+ dns64 64:FF9B::/96 {
+ clients { any; };
+ exclude { ::ffff:0:0/96; };
+ };
+};
diff --git a/bin/tests/system/dns64/conf/good4.conf b/bin/tests/system/dns64/conf/good4.conf
new file mode 100644
index 0000000..2c57f23
--- /dev/null
+++ b/bin/tests/system/dns64/conf/good4.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+options {
+ /* Well Known Prefix */
+ dns64 64:FF9B::/96 {
+ clients { any; };
+ mapped { !rfc1918; any; };
+ };
+};
diff --git a/bin/tests/system/dns64/conf/good5.conf b/bin/tests/system/dns64/conf/good5.conf
new file mode 100644
index 0000000..f6027a4
--- /dev/null
+++ b/bin/tests/system/dns64/conf/good5.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+options {
+ /* Well Known Prefix */
+ dns64 64:FF9B::/96 { };
+};
diff --git a/bin/tests/system/dns64/ns1/example.db b/bin/tests/system/dns64/ns1/example.db
new file mode 100644
index 0000000..8253f1d
--- /dev/null
+++ b/bin/tests/system/dns64/ns1/example.db
@@ -0,0 +1,56 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns1 marka.isc.org. 0 0 0 0 1200
+@ NS ns1
+ns1 A 10.53.0.1
+excluded-good-a AAAA 2001:eeee::1
+ A 1.2.3.4
+excluded-bad-a AAAA 2001:eeee::2
+ A 10.0.0.1
+excluded-only AAAA 2001:eeee::3
+partially-excluded-good-a AAAA 2001:eeee::1
+ AAAA 2001::1
+ A 1.2.3.4
+partially-excluded-bad-a AAAA 2001:eeee::2
+ AAAA 2001::2
+ A 10.0.0.1
+partially-excluded-only AAAA 2001:eeee::3
+ AAAA 2001::3
+a-only A 1.2.3.5
+a-and-aaaa AAAA 2001::1
+ A 1.2.3.6
+aaaa-only AAAA 2001::2
+a-not-mapped A 10.0.0.2
+a-and-mapped AAAA ::ffff:1.2.3.4
+ A 1.2.3.5
+a-and-aaaa-and-mapped AAAA 2001:eeee::4
+a-and-aaaa-and-mapped AAAA ::ffff:1.2.3.4
+a-and-aaaa-and-mapped A 1.2.3.5
+mx-only MX 10 ns.example.
+cname-excluded-good-a CNAME excluded-good-a
+cname-excluded-bad-a CNAME excluded-bad-a
+cname-excluded-only CNAME excluded-only
+cname-partial-excluded-good-a CNAME partial-excluded-good-a
+cname-partial-excluded-bad-a CNAME partial-excluded-bad-a
+cname-partial-excluded-only CNAME partial-excluded-only
+cname-a-only CNAME a-only
+cname-a-and-aaaa CNAME a-and-aaaa
+cname-aaaa-only CNAME aaaa-only
+cname-a-not-mapped CNAME a-not-mapped
+cname-mx-only CNAME mx-only
+cname-non-existent CNAME non-existent
+ttl-less-than-600 500 A 5.6.7.8
+ttl-more-than-600 700 A 5.6.7.8
+ttl-less-than-minimum 1100 A 5.6.7.8
+ttl-more-than-minimum 1300 A 5.6.7.8
+rpz 1500 A 99.99.99.99
diff --git a/bin/tests/system/dns64/ns1/ipv4only.arpa.db b/bin/tests/system/dns64/ns1/ipv4only.arpa.db
new file mode 100644
index 0000000..9e0726d
--- /dev/null
+++ b/bin/tests/system/dns64/ns1/ipv4only.arpa.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+ipv4only.arpa. 3600 IN SOA . . 2018112766 7200 3600 604800 3600
+ipv4only.arpa. 3600 IN NS .
+ipv4only.arpa. 3600 IN A 192.0.0.170
+ipv4only.arpa. 3600 IN A 192.0.0.171
diff --git a/bin/tests/system/dns64/ns1/named.conf1.in b/bin/tests/system/dns64/ns1/named.conf1.in
new file mode 100644
index 0000000..aaf7aab
--- /dev/null
+++ b/bin/tests/system/dns64/ns1/named.conf1.in
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+
+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; };
+ allow-recursion { 10.53.0.1; };
+ notify yes;
+ dnssec-validation yes;
+
+ dns64 2001:bbbb::/96 {
+ clients { any; };
+ mapped { !rfc1918; any; };
+ exclude { 2001:eeee::/32; 64:FF9B::/96; ::ffff:0000:0000/96; };
+ suffix ::;
+ recursive-only yes;
+ };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "signed" {
+ type primary;
+ file "signed.db.signed";
+};
+
+zone "ipv4only.arpa" {
+ type primary;
+ file "ipv4only.arpa.db";
+};
diff --git a/bin/tests/system/dns64/ns1/named.conf2.in b/bin/tests/system/dns64/ns1/named.conf2.in
new file mode 100644
index 0000000..f3fc40f
--- /dev/null
+++ b/bin/tests/system/dns64/ns1/named.conf2.in
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+
+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; };
+ allow-recursion { 10.53.0.1; };
+ notify yes;
+ dnssec-validation yes;
+
+ dns64 2001:bbbb::/96 {
+ clients { any; };
+ mapped { !rfc1918; any; };
+ exclude { 2001:eeee::/32; 64:FF9B::/96; ::ffff:0000:0000/96; };
+ suffix ::;
+ recursive-only yes;
+ };
+ dns64 2001:aaaa::/64 {
+ mapped { !rfc1918; any; };
+ };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "signed" {
+ type primary;
+ file "signed.db.signed";
+};
+
+zone "ipv4only.arpa" {
+ type primary;
+ file "ipv4only.arpa.db";
+};
diff --git a/bin/tests/system/dns64/ns1/named.conf3.in b/bin/tests/system/dns64/ns1/named.conf3.in
new file mode 100644
index 0000000..cb6237b
--- /dev/null
+++ b/bin/tests/system/dns64/ns1/named.conf3.in
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+
+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; };
+ allow-recursion { 10.53.0.1; };
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "signed" {
+ type primary;
+ file "signed.db.signed";
+};
+
+zone "ipv4only.arpa" {
+ type primary;
+ file "ipv4only.arpa.db";
+};
diff --git a/bin/tests/system/dns64/ns1/root.db b/bin/tests/system/dns64/ns1/root.db
new file mode 100644
index 0000000..0e3bbee
--- /dev/null
+++ b/bin/tests/system/dns64/ns1/root.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA a.root-servers.nil. marka.isc.org. 0 0 0 0 0
+@ NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+example NS ns1.example.
+ns1.example. A 10.53.0.1
+signed NS ns1.example.
+ns1.signed. A 10.53.0.1
diff --git a/bin/tests/system/dns64/ns1/sign.sh b/bin/tests/system/dns64/ns1/sign.sh
new file mode 100644
index 0000000..348ca8a
--- /dev/null
+++ b/bin/tests/system/dns64/ns1/sign.sh
@@ -0,0 +1,25 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=signed
+infile=example.db
+zonefile=signed.db
+
+key1=$($KEYGEN -q -a $DEFAULT_ALGORITHM $zone)
+key2=$($KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone)
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -o $zone $zonefile > /dev/null
diff --git a/bin/tests/system/dns64/ns2/named.conf.in b/bin/tests/system/dns64/ns2/named.conf.in
new file mode 100644
index 0000000..be92d1a
--- /dev/null
+++ b/bin/tests/system/dns64/ns2/named.conf.in
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation yes;
+
+ dns64 2001:aaaa::/96 {
+ clients { 10.53.0.2; };
+ mapped { !rfc1918; any; };
+ exclude { 2001:eeee::/32; 64:FF9B::/96; ::ffff:0000:0000/96; };
+ suffix ::;
+ };
+
+ dns64 64:FF9B::/96 {
+ clients { 10.53.0.1; };
+ mapped { !192.228.79.201; !rfc1918; any; };
+ exclude { 64:FF9B::/96; ::ffff:0000:0000/96; };
+ suffix ::;
+ };
+
+ dns64 2001:bbbb::/96 {
+ clients { 10.53.0.4; };
+ mapped { !rfc1918; any; };
+ suffix ::;
+ };
+
+ dns64-server "dns64.example.net.";
+ dns64-contact "hostmaster.example.net.";
+ dns64 2001:32::/32 { clients { 10.53.0.6; }; };
+ dns64 2001:40::/40 { clients { 10.53.0.6; }; };
+ dns64 2001:48::/48 { clients { 10.53.0.6; }; };
+ dns64 2001:56::/56 { clients { 10.53.0.6; }; };
+ dns64 2001:64::/64 { clients { 10.53.0.6; }; };
+
+ dns64 2001:96::/96 { clients { 10.53.0.7; }; };
+
+ response-policy { zone "rpz"; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "rpz" {
+ type primary;
+ file "rpz.db";
+};
diff --git a/bin/tests/system/dns64/ns2/rpz.db b/bin/tests/system/dns64/ns2/rpz.db
new file mode 100644
index 0000000..014cbf0
--- /dev/null
+++ b/bin/tests/system/dns64/ns2/rpz.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400 ; 1 day
+@ IN SOA rpz. noc.rpz. (
+ 1 ; serial
+ 86400 ; refresh (1 day)
+ 3600 ; retry (1 hour)
+ 2592000 ; expire (4 weeks 2 days)
+ 25200 ; minimum (7 hours)
+ )
+ NS @
+ IN A 10.53.0.2
+
+rpz.example IN A 10.10.10.10
diff --git a/bin/tests/system/dns64/setup.sh b/bin/tests/system/dns64/setup.sh
new file mode 100644
index 0000000..6771f3f
--- /dev/null
+++ b/bin/tests/system/dns64/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf1.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+
+cd ns1 && $SHELL sign.sh
diff --git a/bin/tests/system/dns64/tests.sh b/bin/tests/system/dns64/tests.sh
new file mode 100644
index 0000000..4ee42dc
--- /dev/null
+++ b/bin/tests/system/dns64/tests.sh
@@ -0,0 +1,1456 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}"
+
+for conf in conf/good*.conf
+do
+ echo_i "checking that $conf is accepted ($n)"
+ ret=0
+ $CHECKCONF "$conf" || ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+for conf in conf/bad*.conf
+do
+ echo_i "checking that $conf is rejected ($n)"
+ ret=0
+ $CHECKCONF "$conf" >/dev/null && ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+# Check the example. domain
+
+echo_i "checking non-excluded AAAA lookup works ($n)"
+ret=0
+$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA lookup works ($n)"
+ret=0
+$DIG $DIGOPTS excluded-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A lookup works ($n)"
+ret=0
+$DIG $DIGOPTS excluded-bad-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A lookup works ($n)"
+ret=0
+$DIG $DIGOPTS excluded-good-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:aaaa::1.2.3.4" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking default exclude acl ignores mapped A records (all mapped) ($n)"
+ret=0
+$DIG $DIGOPTS a-and-mapped.example. @10.53.0.2 -b 10.53.0.4 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:bbbb::1.2.3.5" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking default exclude acl ignores mapped A records (some mapped) ($n)"
+ret=0
+$DIG $DIGOPTS a-and-aaaa-and-mapped.example. @10.53.0.2 -b 10.53.0.4 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::4" dig.out.ns2.test$n > /dev/null || ret=1
+grep "::ffff:1.2.3.4" dig.out.ns2.test$n > /dev/null && ret=1
+grep "::ffff:1.2.3.5" dig.out.ns2.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking default exclude acl works with AAAA only ($n)"
+ret=0
+$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.4 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking default exclude acl A only lookup works ($n)"
+ret=0
+$DIG $DIGOPTS a-only.example. @10.53.0.2 -b 10.53.0.4 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:bbbb::102:305" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking partially excluded only AAAA lookup works ($n)"
+ret=0
+$DIG $DIGOPTS partially-excluded-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking partially-excluded AAAA and non-mapped A lookup works ($n)"
+ret=0
+$DIG $DIGOPTS partially-excluded-bad-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking partially-excluded only AAAA and mapped A lookup works ($n)"
+ret=0
+$DIG $DIGOPTS partially-excluded-good-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only lookup works ($n)"
+ret=0
+$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only lookup works ($n)"
+ret=0
+$DIG $DIGOPTS a-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:aaaa::102:305" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA lookup works ($n)"
+ret=0
+$DIG $DIGOPTS a-and-aaaa.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A lookup works ($n)"
+ret=0
+$DIG $DIGOPTS a-not-mapped.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA lookup works ($n)"
+ret=0
+$DIG $DIGOPTS mx-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA lookup works ($n)"
+ret=0
+$DIG $DIGOPTS non-existent.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-excluded AAAA via CNAME lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA via CNAME lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A via CNAME lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-bad-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A via CNAME lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-good-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:aaaa::1.2.3.4" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only via CNAME lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only via CNAME lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:aaaa::102:305" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA via CNAME lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-and-aaaa.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A via CNAME lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-not-mapped.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME a-not-mapped.example." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA via CNAME lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-mx-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME mx-only.example." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA via CNAME lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-non-existent.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check the example. domain recursive only
+
+echo_i "checking non-excluded AAAA lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:bbbb::1.2.3.4" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking partially excluded only AAAA lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS partially-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking partially-excluded AAAA and non-mapped A lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS partially-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking partially-excluded only AAAA and mapped A lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS partially-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:bbbb::102:305" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-excluded AAAA via CNAME lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA via CNAME lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A via CNAME lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A via CNAME lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:bbbb::102:304" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only via CNAME lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only via CNAME lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:bbbb::102:305" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA via CNAME lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A via CNAME lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME a-not-mapped.example." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA via CNAME lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS cname-mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME mx-only.example." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA via CNAME lookup works, recursive only ($n)"
+ret=0
+$DIG $DIGOPTS cname-non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check the example. domain recursive only w/o recursion
+
+echo_i "checking non-excluded AAAA lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking partially excluded only AAAA lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec partially-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee:" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking partially-excluded AAAA and non-mapped A lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec partially-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee:" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking partially-excluded only AAAA and mapped A lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec partially-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee:" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-excluded AAAA via CNAME lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA via CNAME lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec cname-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A via CNAME lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec cname-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A via CNAME lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec cname-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only via CNAME lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only via CNAME lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec cname-a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME a-only.example." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA via CNAME lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec cname-a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A via CNAME lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec cname-a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME a-not-mapped.example." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA via CNAME lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec cname-mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME mx-only.example." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA via CNAME lookup works, recursive only +norec ($n)"
+ret=0
+$DIG $DIGOPTS +norec cname-non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check the example. domain from non client
+
+echo_i "checking non-excluded AAAA from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS excluded-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS excluded-bad-a.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS excluded-good-a.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS a-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS a-and-aaaa.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS a-not-mapped.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS mx-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS non-existent.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-excluded AAAA via CNAME from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA via CNAME from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A via CNAME from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-bad-a.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A via CNAME from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-good-a.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only via CNAME from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only via CNAME from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA via CNAME from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-and-aaaa.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A via CNAME from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-not-mapped.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME a-not-mapped.example." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA via CNAME from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-mx-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME mx-only.example." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA via CNAME from non-client lookup works ($n)"
+ret=0
+$DIG $DIGOPTS cname-non-existent.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check the signed. domain
+
+echo_i "checking non-excluded AAAA lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:aaaa::102:304" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:aaaa::102:305" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-excluded AAAA via CNAME lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA via CNAME lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A via CNAME lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A via CNAME lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS cname-excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:aaaa::102:304" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only via CNAME lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only via CNAME lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:aaaa::102:305" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA via CNAME lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A via CNAME lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS cname-a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME a-not-mapped.signed." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA via CNAME lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS cname-mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME mx-only.signed." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA via CNAME lookup is signed zone works ($n)"
+ret=0
+$DIG $DIGOPTS cname-non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check the signed. domain
+echo_i "checking non-excluded AAAA lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-excluded AAAA via CNAME lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA via CNAME lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec cname-excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded AAAA and non-mapped A via CNAME lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec cname-excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking excluded only AAAA and mapped A via CNAME lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec cname-excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA only via CNAME lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A only via CNAME lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec cname-a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:aaaa::102:305" dig.out.ns2.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A and AAAA via CNAME lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec cname-a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-mapped A via CNAME lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec cname-a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 2" dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME a-not-mapped.signed." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking NODATA AAAA via CNAME lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec cname-mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1
+grep "CNAME mx-only.signed." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking non-existent AAAA via CNAME lookup is signed zone works with +dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +dnssec cname-non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking reverse mapping ($n)"
+ret=0
+$DIG $DIGOPTS -x 2001:aaaa::10.0.0.1 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep -i "CNAME.1.0.0.10.IN-ADDR.ARPA.$" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+list=$($DIG $DIGOPTS -b 10.53.0.6 @10.53.0.2 +short aaaa a-only.example | sort)
+for a in $list
+do
+ ret=0
+ echo_i "checking reverse mapping of $a ($n)"
+ $DIG $DIGOPTS -x $a @10.53.0.2 > dig.out.ns2.test$n || ret=1
+ grep -i "CNAME.5.3.2.1.IN-ADDR.ARPA." dig.out.ns2.test$n > /dev/null || ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+rev=$($ARPANAME 2001:aaaa::10.0.0.1)
+regex='..\(.*.IP6.ARPA\)'
+rev=$(expr "${rev}" : "${regex}")
+fin=$(expr "${rev}" : "............${regex}")
+while test "${rev}" != "${fin}"
+do
+ ret=0
+ echo_i "checking $rev ($n)"
+ $DIG $DIGOPTS $rev ptr @10.53.0.2 > dig.out.ns2.test$n || ret=1
+ grep -i "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+ grep -i "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+ rev=$(expr "${rev}" : "${regex}")
+done
+
+echo_i "checking dns64-server and dns64-contact ($n)"
+ret=0
+$DIG $DIGOPTS soa 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.a.a.a.a.1.0.0.2.ip6.arpa @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "SOA.dns64.example.net..hostmaster.example.net." dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTL less than 600 from zone ($n)"
+ret=0
+#expect 500
+$DIG $DIGOPTS aaaa ttl-less-than-600.example +rec @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep -i "ttl-less-than-600.example..500.IN.AAAA" dig.out.ns1.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTL more than 600 from zone ($n)"
+ret=0
+#expect 700
+$DIG $DIGOPTS aaaa ttl-more-than-600.example +rec @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep -i "ttl-more-than-600.example..700.IN.AAAA" dig.out.ns1.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTL less than minimum from zone ($n)"
+ret=0
+#expect 1100
+$DIG $DIGOPTS aaaa ttl-less-than-minimum.example +rec @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep -i "ttl-less-than-minimum.example..1100.IN.AAAA" dig.out.ns1.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTL limited to minimum from zone ($n)"
+ret=0
+#expect 1200
+$DIG $DIGOPTS aaaa ttl-more-than-minimum.example +rec @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep -i "ttl-more-than-minimum.example..1200.IN.AAAA" dig.out.ns1.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTL less than 600 via cache ($n)"
+ret=0
+#expect 500
+$DIG $DIGOPTS aaaa ttl-less-than-600.example +rec -b 10.53.0.2 @10.53.0.2 > dig.out.ns1.test$n || ret=1
+grep -i "ttl-less-than-600.example..500.IN.AAAA" dig.out.ns1.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTL more than 600 via cache ($n)"
+ret=0
+#expect 700
+$DIG $DIGOPTS aaaa ttl-more-than-600.example +rec -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep -i "ttl-more-than-600.example..700.IN.AAAA" dig.out.ns2.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTL less than minimum via cache ($n)"
+ret=0
+#expect 1100
+$DIG $DIGOPTS aaaa ttl-less-than-minimum.example +rec -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep -i "ttl-less-than-minimum.example..1100.IN.AAAA" dig.out.ns2.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TTL limited to minimum via cache ($n)"
+ret=0
+#expect 1200
+$DIG $DIGOPTS aaaa ttl-more-than-minimum.example +rec -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep -i "ttl-more-than-minimum.example..1200.IN.AAAA" dig.out.ns2.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking synthesis of AAAA from RPZ-remapped A ($n)"
+ret=0
+$DIG $DIGOPTS aaaa rpz.example +rec -b 10.53.0.7 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep -i 'rpz.example.*IN.AAAA.2001:96::a0a:a0a' dig.out.ns2.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking 'dig +dns64prefix' ($n)"
+$DIG $DIGOPTS +dns64prefix @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep '^2001:bbbb::/96$' dig.out.ns1.test$n > /dev/null || ret=1
+test $(wc -l < dig.out.ns1.test$n) -eq 1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+copy_setports ns1/named.conf2.in ns1/named.conf
+rndc_reload ns1 10.53.0.1
+
+echo_i "checking 'dig +dns64prefix' with multiple prefixes ($n)"
+$DIG $DIGOPTS +dns64prefix @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep '^2001:bbbb::/96$' dig.out.ns1.test$n > /dev/null || ret=1
+grep '2001:aaaa::/64' dig.out.ns1.test$n > /dev/null || ret=1
+test $(wc -l < dig.out.ns1.test$n) -eq 2 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+copy_setports ns1/named.conf3.in ns1/named.conf
+rndc_reload ns1 10.53.0.1
+
+echo_i "checking 'dig +dns64prefix' with no prefixes ($n)"
+$DIG $DIGOPTS +dns64prefix @10.53.0.1 > dig.out.ns1.test$n || ret=1
+test $(wc -l < dig.out.ns1.test$n) -eq 0 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking synthesis of AAAA from builtin ipv4only.arpa ($n)"
+ret=0
+$DIG $DIGOPTS aaaa ipv4only.arpa -b 10.53.0.7 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep -i 'ipv4only.arpa.*IN.AAAA.2001:96::c000:aa' dig.out.ns2.test$n >/dev/null || ret=1
+grep -i 'ipv4only.arpa.*IN.AAAA.2001:96::c000:ab' dig.out.ns2.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking reverse of dns64 mapped ipv4only.arpa addresses returns ipv4only.arpa ($n)"
+ret=0
+$DIG $DIGOPTS ptr -x 2001:96::192.0.0.170 -b 10.53.0.7 @10.53.0.2 > dig.out.170.ns2.test$n || ret=1
+$DIG $DIGOPTS ptr -x 2001:96::192.0.0.171 -b 10.53.0.7 @10.53.0.2 > dig.out.171.ns2.test$n || ret=1
+grep "ip6\.arpa\..*PTR.*ipv4only\.arpa\." dig.out.170.ns2.test$n >/dev/null || ret=1
+grep "ip6\.arpa\..*PTR.*ipv4only\.arpa\." dig.out.171.ns2.test$n >/dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dns64/tests_sh_dns64.py b/bin/tests/system/dns64/tests_sh_dns64.py
new file mode 100644
index 0000000..7eb152c
--- /dev/null
+++ b/bin/tests/system/dns64/tests_sh_dns64.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_dns64(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/dnssec/README b/bin/tests/system/dnssec/README
new file mode 100644
index 0000000..fcaa3b6
--- /dev/null
+++ b/bin/tests/system/dnssec/README
@@ -0,0 +1,32 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+The test setup for the DNSSEC tests has a secure root.
+
+ns1 is the root server.
+
+ns2 and ns3 are authoritative servers for the various test domains.
+
+ns4 is a caching-only server, configured with the correct trusted key
+for the root.
+
+ns5 is a caching-only server, configured with the an incorrect trusted
+key for the root. It is used for testing failure cases.
+
+ns6 is an caching and authoritative server used for testing unusual
+server behaviors such as disabled DNSSEC algorithms.
+
+ns7 is used for checking non-cacheable answers.
+
+ns8 is a caching-only server, configured with unsupported and disabled
+algorithms. It is used for testing failure cases.
+
+ns9 is a forwarding-only server.
diff --git a/bin/tests/system/dnssec/ans10/ans.py b/bin/tests/system/dnssec/ans10/ans.py
new file mode 100644
index 0000000..dbe49e5
--- /dev/null
+++ b/bin/tests/system/dnssec/ans10/ans.py
@@ -0,0 +1,158 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from __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, dns.flags
+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.
+# SOA gets a unsigned response.
+# NS gets a unsigned response.
+# DNSKEY get a unsigned NODATA response.
+# A gets a signed response.
+# All other types get a unsigned NODATA response.
+############################################################################
+def create_response(msg):
+ m = dns.message.from_wire(msg)
+ qname = m.question[0].name.to_text()
+ rrtype = m.question[0].rdtype
+ typename = dns.rdatatype.to_text(rrtype)
+
+ with open("query.log", "a") as f:
+ f.write("%s %s\n" % (typename, qname))
+ print("%s %s" % (typename, qname), end=" ")
+
+ r = dns.message.make_response(m)
+ r.set_rcode(NOERROR)
+ if rrtype == A:
+ now = datetime.today()
+ expire = now + timedelta(days=30)
+ inception = now - timedelta(days=1)
+ rrsig = (
+ "A 13 2 60 "
+ + expire.strftime("%Y%m%d%H%M%S")
+ + " "
+ + inception.strftime("%Y%m%d%H%M%S")
+ + " 12345 "
+ + qname
+ + " gB+eISXAhSPZU2i/II0W9ZUhC2SCIrb94mlNvP5092WAeXxqN/vG43/1nmDl"
+ + "y2Qs7y5VCjSMOGn85bnaMoAc7w=="
+ )
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10"))
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, RRSIG, rrsig))
+ elif rrtype == NS:
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, NS, "."))
+ elif rrtype == SOA:
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, SOA, ". . 0 0 0 0 0"))
+ else:
+ r.authority.append(dns.rrset.from_text(qname, 1, IN, SOA, ". . 0 0 0 0 0"))
+ r.flags |= dns.flags.AA
+ 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.10"
+ip6 = "fd92:7065:b8e:ffff::10"
+
+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/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh
new file mode 100644
index 0000000..1a933ad
--- /dev/null
+++ b/bin/tests/system/dnssec/clean.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f ./*/K* ./*/keyset-* ./*/dsset-* ./*/signedkey-* ./*/*.signed
+rm -f ./*/example.bk
+rm -f ./*/named.conf
+rm -f ./*/named.memstats
+rm -f ./*/named.run ./*/named.run.prev
+rm -f ./*/named.secroots
+rm -f ./*/tmp* ./*/*.jnl ./*/*.bk ./*/*.jbk
+rm -f ./*/trusted.conf ./*/managed.conf ./*/revoked.conf
+rm -f ./Kexample.* ./Kkeygen* ./keygen*.err
+rm -f ./ans10/query.log ./ans10/ans.run
+rm -f ./canonical?.*
+rm -f ./delv.out*
+rm -f ./delve.out*
+rm -f ./dig.out.*
+rm -f ./ns2/too-many-iterations.db
+rm -f ./dnssectools.out*
+rm -f ./dsfromkey.out.*
+rm -f ./keygen.err
+rm -f ./named.secroots.test*
+rm -f ./nosign.before
+rm -f ./ns*/*.nta
+rm -f ./ns*/managed-keys.bind ./ns*/managed-keys.bind.jnl ./ns*/*.mkeys*
+rm -f ./ns*/named.lock
+rm -f ./ns1/managed.key.id
+rm -f ./ns1/root.db ./ns2/example.db ./ns2/managed.db ./ns2/trusted.db
+rm -f ./ns1/trusted.keys
+rm -f ./ns2/algroll.db
+rm -f ./ns2/badparam.db ./ns2/badparam.db.bad
+rm -f ./ns2/cdnskey-kskonly.secure.db
+rm -f ./ns2/cdnskey-kskonly.secure.id
+rm -f ./ns2/cdnskey-update.secure.db
+rm -f ./ns2/cdnskey-x.secure.db
+rm -f ./ns2/cdnskey.secure.db
+rm -f ./ns2/cds-auto.secure.db ./ns2/cds-auto.secure.db.jnl
+rm -f ./ns2/cds-kskonly.secure.db
+rm -f ./ns2/cds-kskonly.secure.id
+rm -f ./ns2/cds-update.secure.db ./ns2/cds-update.secure.db.jnl
+rm -f ./ns2/cds.secure.db ./ns2/cds-x.secure.db
+rm -f ./ns2/in-addr.arpa.db
+rm -f ./ns2/nsec3chain-test.db
+rm -f ./ns2/single-nsec3.db
+rm -f ./ns2/updatecheck-kskonly.secure.*
+rm -f ./ns3/auto-nsec.example.db ./ns3/auto-nsec3.example.db
+rm -f ./ns3/badds.example.db
+rm -f ./ns3/dname-at-apex-nsec3.example.db
+rm -f ./ns3/dnskey-nsec3-unknown.example.db
+rm -f ./ns3/dnskey-nsec3-unknown.example.db.tmp
+rm -f ./ns3/dnskey-unknown.example.db
+rm -f ./ns3/dnskey-unknown.example.db.tmp
+rm -f ./ns3/dnskey-unsupported-2.example.db
+rm -f ./ns3/dnskey-unsupported-2.example.db.tmp
+rm -f ./ns3/dnskey-unsupported.example.db
+rm -f ./ns3/dnskey-unsupported.example.db.tmp
+rm -f ./ns3/dynamic.example.db ./ns3/dynamic.example.db.signed.jnl
+rm -f ./ns3/expired.example.db ./ns3/update-nsec3.example.db
+rm -f ./ns3/expiring.example.db ./ns3/nosign.example.db
+rm -f ./ns3/future.example.db ./ns3/trusted-future.key
+rm -f ./ns3/inline.example.db.signed
+rm -f ./ns3/kskonly.example.db
+rm -f ./ns3/lower.example.db ./ns3/upper.example.db ./ns3/upper.example.db.lower
+rm -f ./ns3/managed-future.example.db
+rm -f ./ns3/multiple.example.db ./ns3/nsec3-unknown.example.db ./ns3/nsec3.example.db
+rm -f ./ns3/nsec3.nsec3.example.db
+rm -f ./ns3/nsec3.optout.example.db
+rm -f ./ns3/occluded.example.db
+rm -f ./ns3/optout-unknown.example.db ./ns3/optout.example.db
+rm -f ./ns3/optout.nsec3.example.db
+rm -f ./ns3/optout.optout.example.db
+rm -f ./ns3/publish-inactive.example.db
+rm -f ./ns3/revkey.example.db
+rm -f ./ns3/rsasha256.example.db ./ns3/rsasha512.example.db
+rm -f ./ns3/secure.below-cname.example.db
+rm -f ./ns3/secure.example.db ./ns3/*.managed.db ./ns3/*.trusted.db
+rm -f ./ns3/secure.nsec3.example.db
+rm -f ./ns3/secure.optout.example.db
+rm -f ./ns3/siginterval.conf
+rm -f ./ns3/siginterval.example.db
+rm -f ./ns3/split-dnssec.example.db
+rm -f ./ns3/split-smart.example.db
+rm -f ./ns3/ttlpatch.example.db ./ns3/ttlpatch.example.db.signed
+rm -f ./ns3/ttlpatch.example.db.patched
+rm -f ./ns3/unsecure.example.db ./ns3/bogus.example.db ./ns3/keyless.example.db
+rm -f ./ns3/unsupported.managed.db.tmp ./ns3/unsupported.trusted.db.tmp
+rm -f ./ns3/NSEC ./ns3/NSEC3
+rm -f ./ns4/named_dump.db*
+rm -f ./ns6/optout-tld.db
+rm -f ./ns7/multiple.example.bk ./ns7/nsec3.example.bk ./ns7/optout.example.bk
+rm -f ./ns7/split-rrsig.db ./ns7/split-rrsig.db.unsplit
+rm -f ./nsupdate.out*
+rm -f ./python.out.*
+rm -f ./rndc.out.*
+rm -f ./signer/*.db
+rm -f ./signer/*.signed.post*
+rm -f ./signer/*.signed.pre*
+rm -f ./signer/example.db.after ./signer/example.db.before
+rm -f ./signer/example.db.changed
+rm -f ./signer/general/dsset*
+rm -f ./signer/general/signed.zone
+rm -f ./signer/general/signer.out.*
+rm -f ./signer/nsec3param.out
+rm -f ./signer/signer.out.*
+rm -f ./signing.out*
diff --git a/bin/tests/system/dnssec/dnssec_update_test.pl b/bin/tests/system/dnssec/dnssec_update_test.pl
new file mode 100644
index 0000000..a06c563
--- /dev/null
+++ b/bin/tests/system/dnssec/dnssec_update_test.pl
@@ -0,0 +1,99 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# DNSSEC Dynamic update test suite.
+#
+# Usage:
+#
+# perl update_test.pl [-s server] [-p port] zone
+#
+# The server defaults to 127.0.0.1.
+# The port defaults to 53.
+#
+# Installation notes:
+#
+# This program uses the Net::DNS::Resolver module.
+# You can install it by saying
+#
+# perl -MCPAN -e "install Net::DNS"
+#
+
+use Getopt::Std;
+use Net::DNS;
+use Net::DNS::Update;
+use Net::DNS::Resolver;
+
+$opt_s = "127.0.0.1";
+$opt_p = 53;
+
+getopt('s:p:');
+
+$res = new Net::DNS::Resolver;
+$res->nameservers($opt_s);
+$res->port($opt_p);
+$res->defnames(0); # Do not append default domain.
+
+@ARGV == 1 or die
+ "usage: perl update_test.pl [-s server] [-p port] zone\n";
+
+$zone = shift @ARGV;
+
+my $failures = 0;
+
+sub assert {
+ my ($cond, $explanation) = @_;
+ if (!$cond) {
+ print "Test Failed: $explanation ***\n";
+ $failures++
+ }
+}
+
+sub test {
+ my ($expected, @records) = @_;
+
+ my $update = new Net::DNS::Update("$zone");
+
+ foreach $rec (@records) {
+ $update->push(@$rec);
+ }
+
+ $reply = $res->send($update);
+
+ # Did it work?
+ if (defined $reply) {
+ my $rcode = $reply->header->rcode;
+ assert($rcode eq $expected, "expected $expected, got $rcode");
+ } else {
+ print "Update failed: ", $res->errorstring, "\n";
+ }
+}
+
+sub section {
+ my ($msg) = @_;
+ print "$msg\n";
+}
+
+section("Add a name");
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]);
+
+section("Delete the name");
+test("NOERROR", ["update", rr_del("a.$zone")]);
+
+if ($failures) {
+ print "$failures update tests failed.\n";
+} else {
+ print "All update tests successful.\n";
+}
+
+exit $failures;
diff --git a/bin/tests/system/dnssec/ns1/named.conf.in b/bin/tests/system/dnssec/ns1/named.conf.in
new file mode 100644
index 0000000..bd1ccc4
--- /dev/null
+++ b/bin/tests/system/dnssec/ns1/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+ /* test that we can turn off trust-anchor-telemetry */
+ trust-anchor-telemetry no;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns1/root.db.in b/bin/tests/system/dnssec/ns1/root.db.in
new file mode 100644
index 0000000..526e36c
--- /dev/null
+++ b/bin/tests/system/dnssec/ns1/root.db.in
@@ -0,0 +1,37 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+algroll. NS ns2.algroll.
+ns2.algroll. A 10.53.0.2
+managed. NS ns2.managed.
+ns2.managed. A 10.53.0.2
+trusted. NS ns2.trusted.
+ns2.trusted. A 10.53.0.2
+optout-tld NS ns6.optout-tld.
+ns6.optout-tld. A 10.53.0.6
+in-addr.arpa. NS ns2.example.
+inprogress. NS ns10.inprogress.
+ns10.inprogress. A 10.53.0.10
+too-many-iterations. NS ns2.too-many-iterations.
+ns2.too-many-iterations. A 10.53.0.2
diff --git a/bin/tests/system/dnssec/ns1/sign.sh b/bin/tests/system/dnssec/ns1/sign.sh
new file mode 100644
index 0000000..21c6d71
--- /dev/null
+++ b/bin/tests/system/dnssec/ns1/sign.sh
@@ -0,0 +1,62 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+(cd ../ns2 && $SHELL sign.sh )
+(cd ../ns6 && $SHELL sign.sh )
+(cd ../ns7 && $SHELL sign.sh )
+
+echo_i "ns1/sign.sh"
+
+cp "../ns2/dsset-example." .
+cp "../ns2/dsset-in-addr.arpa." .
+cp "../ns2/dsset-too-many-iterations." .
+
+grep "$DEFAULT_ALGORITHM_NUMBER [12] " "../ns2/dsset-algroll." > "dsset-algroll."
+cp "../ns6/dsset-optout-tld." .
+
+ksk=$("$KEYGEN" -q -fk -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$ksk.key" "$zsk.key" > "$zonefile"
+
+"$SIGNER" -g -o "$zone" "$zonefile" > /dev/null 2>&1
+
+# Configure the resolving server with a staitc key.
+keyfile_to_static_ds "$ksk" > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+cp trusted.conf ../ns3/trusted.conf
+cp trusted.conf ../ns4/trusted.conf
+cp trusted.conf ../ns6/trusted.conf
+cp trusted.conf ../ns7/trusted.conf
+cp trusted.conf ../ns9/trusted.conf
+
+keyfile_to_trusted_keys "$ksk" > trusted.keys
+
+# ...or with an initializing key.
+keyfile_to_initial_ds "$ksk" > managed.conf
+cp managed.conf ../ns4/managed.conf
+
+#
+# Save keyid for managed key id test.
+#
+
+keyfile_to_key_id "$ksk" > managed.key.id
diff --git a/bin/tests/system/dnssec/ns2/algroll.db.in b/bin/tests/system/dnssec/ns2/algroll.db.in
new file mode 100644
index 0000000..6f66fc9
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/algroll.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 30 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 30 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
diff --git a/bin/tests/system/dnssec/ns2/badparam.db.in b/bin/tests/system/dnssec/ns2/badparam.db.in
new file mode 100644
index 0000000..b18d186
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/badparam.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2010081000 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
diff --git a/bin/tests/system/dnssec/ns2/cdnskey-auto.secure.db.in b/bin/tests/system/dnssec/ns2/cdnskey-auto.secure.db.in
new file mode 100644
index 0000000..aa3aaab
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cdnskey-auto.secure.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2.example. . 1 3600 1200 86400 1200
+@ NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/cdnskey-kskonly.secure.db.in b/bin/tests/system/dnssec/ns2/cdnskey-kskonly.secure.db.in
new file mode 100644
index 0000000..aa3aaab
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cdnskey-kskonly.secure.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2.example. . 1 3600 1200 86400 1200
+@ NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/cdnskey-update.secure.db.in b/bin/tests/system/dnssec/ns2/cdnskey-update.secure.db.in
new file mode 100644
index 0000000..aa3aaab
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cdnskey-update.secure.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2.example. . 1 3600 1200 86400 1200
+@ NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/cdnskey.secure.db.in b/bin/tests/system/dnssec/ns2/cdnskey.secure.db.in
new file mode 100644
index 0000000..aa3aaab
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cdnskey.secure.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2.example. . 1 3600 1200 86400 1200
+@ NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/cds-auto.secure.db.in b/bin/tests/system/dnssec/ns2/cds-auto.secure.db.in
new file mode 100644
index 0000000..aa3aaab
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cds-auto.secure.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2.example. . 1 3600 1200 86400 1200
+@ NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/cds-kskonly.secure.db.in b/bin/tests/system/dnssec/ns2/cds-kskonly.secure.db.in
new file mode 100644
index 0000000..aa3aaab
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cds-kskonly.secure.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2.example. . 1 3600 1200 86400 1200
+@ NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/cds-update.secure.db.in b/bin/tests/system/dnssec/ns2/cds-update.secure.db.in
new file mode 100644
index 0000000..aa3aaab
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cds-update.secure.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2.example. . 1 3600 1200 86400 1200
+@ NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/cds.secure.db.in b/bin/tests/system/dnssec/ns2/cds.secure.db.in
new file mode 100644
index 0000000..aa3aaab
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/cds.secure.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2.example. . 1 3600 1200 86400 1200
+@ NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/child.nsec3.example.db b/bin/tests/system/dnssec/ns2/child.nsec3.example.db
new file mode 100644
index 0000000..8fc3bc8
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/child.nsec3.example.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2006081400 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ IN NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/child.optout.example.db b/bin/tests/system/dnssec/ns2/child.optout.example.db
new file mode 100644
index 0000000..8fc3bc8
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/child.optout.example.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2006081400 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ IN NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/corp.db b/bin/tests/system/dnssec/ns2/corp.db
new file mode 100644
index 0000000..b2912bc
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/corp.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 30 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 30 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+
+www A 10.0.0.1
diff --git a/bin/tests/system/dnssec/ns2/dst.example.db.in b/bin/tests/system/dnssec/ns2/dst.example.db.in
new file mode 100644
index 0000000..0039484
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/dst.example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2.example.
+a A 10.0.0.1
diff --git a/bin/tests/system/dnssec/ns2/example.db.in b/bin/tests/system/dnssec/ns2/example.db.in
new file mode 100644
index 0000000..f711f58
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/example.db.in
@@ -0,0 +1,171 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+
+; Used for testing ANY queries
+foo TXT "testing"
+foo A 10.0.1.0
+
+bad-cname CNAME a
+bad-dname DNAME @
+
+; Used for testing CNAME queries
+cname1 CNAME cname1-target
+cname1-target TXT "testing cname"
+
+cname2 CNAME cname2-target
+cname2-target TXT "testing cname"
+
+; Used for testing DNAME queries
+dname1 DNAME dname1-target
+foo.dname1-target TXT "testing dname"
+
+dname2 DNAME dname2-target
+foo.dname2-target TXT "testing dname"
+
+; A secure subdomain
+secure NS ns3.secure
+ns3.secure A 10.53.0.3
+
+; An insecure subdomain
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+
+; A second insecure subdomain
+insecure2 NS ns.insecure2
+ns.insecure2 A 10.53.0.3
+
+; A secure subdomain we're going to inject bogus data into
+bogus NS ns.bogus
+ns.bogus A 10.53.0.3
+
+; A subdomain with a corrupt DS
+badds NS ns.badds
+ns.badds A 10.53.0.3
+
+; A dynamic secure subdomain
+dynamic NS dynamic
+dynamic A 10.53.0.3
+
+; A insecure subdomain
+mustbesecure NS ns.mustbesecure
+ns.mustbesecure A 10.53.0.3
+
+; A subdomain with expired signatures
+expired NS ns.expired
+ns.expired A 10.53.0.3
+
+; A rfc2535 signed zone w/ CNAME
+rfc2535 NS ns.rfc2535
+ns.rfc2535 A 10.53.0.3
+
+z A 10.0.0.26
+
+keyless NS ns.keyless
+ns.keyless A 10.53.0.3
+
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+
+optout NS ns.optout
+ns.optout A 10.53.0.3
+
+nsec3-unknown NS ns.nsec3-unknown
+ns.nsec3-unknown A 10.53.0.3
+
+optout-unknown NS ns.optout-unknown
+ns.optout-unknown A 10.53.0.3
+
+dnskey-unknown NS ns.dnskey-unknown
+ns.dnskey-unknown A 10.53.0.3
+
+dnskey-unsupported NS ns.dnskey-unsupported
+ns.dnskey-unsupported A 10.53.0.3
+
+dnskey-nsec3-unknown NS ns.dnskey-nsec3-unknown
+ns.dnskey-nsec3-unknown A 10.53.0.3
+
+multiple NS ns.multiple
+ns.multiple A 10.53.0.3
+
+*.wild A 10.0.0.27
+
+rsasha256 NS ns.rsasha256
+ns.rsasha256 A 10.53.0.3
+
+rsasha512 NS ns.rsasha512
+ns.rsasha512 A 10.53.0.3
+
+kskonly NS ns.kskonly
+ns.kskonly A 10.53.0.3
+
+update-nsec3 NS ns.update-nsec3
+ns.update-nsec3 A 10.53.0.3
+
+auto-nsec NS ns.auto-nsec
+ns.auto-nsec A 10.53.0.3
+
+auto-nsec3 NS ns.auto-nsec3
+ns.auto-nsec3 A 10.53.0.3
+
+
+below-cname CNAME some.where.else.
+
+insecure.below-cname NS ns.insecure.below-cname
+ns.insecure.below-cname A 10.53.0.3
+
+secure.below-cname NS ns.secure.below-cname
+ns.secure.below-cname A 10.53.0.3
+
+ttlpatch NS ns.ttlpatch
+ns.ttlpatch A 10.53.0.3
+
+split-dnssec NS ns.split-dnssec
+ns.split-dnssec A 10.53.0.3
+
+split-smart NS ns.split-smart
+ns.split-smart A 10.53.0.3
+
+upper NS ns.upper
+ns.upper A 10.53.0.3
+
+LOWER NS NS.LOWER
+NS.LOWER A 10.53.0.3
+
+expiring NS ns.expiring
+ns.expiring A 10.53.0.3
+
+future NS ns.future
+ns.future A 10.53.0.3
+
+managed-future NS ns.managed-future
+ns.managed-future A 10.53.0.3
+
+revkey NS ns.revkey
+ns.revkey A 10.53.0.3
+
+dname-at-apex-nsec3 NS ns3
diff --git a/bin/tests/system/dnssec/ns2/hours-vs-days.db.in b/bin/tests/system/dnssec/ns2/hours-vs-days.db.in
new file mode 100644
index 0000000..5ec8801
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/hours-vs-days.db.in
@@ -0,0 +1,167 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+
+; Used for testing ANY queries
+foo TXT "testing"
+foo A 10.0.1.0
+
+bad-cname CNAME a
+bad-dname DNAME @
+
+; Used for testing CNAME queries
+cname1 CNAME cname1-target
+cname1-target TXT "testing cname"
+
+cname2 CNAME cname2-target
+cname2-target TXT "testing cname"
+
+; Used for testing DNAME queries
+dname1 DNAME dname1-target
+foo.dname1-target TXT "testing dname"
+
+dname2 DNAME dname2-target
+foo.dname2-target TXT "testing dname"
+
+; A secure subdomain
+secure NS ns3.secure
+ns3.secure A 10.53.0.3
+
+; An insecure subdomain
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+
+; A secure subdomain we're going to inject bogus data into
+bogus NS ns.bogus
+ns.bogus A 10.53.0.3
+
+; A subdomain with a corrupt DS
+badds NS ns.badds
+ns.badds A 10.53.0.3
+
+; A dynamic secure subdomain
+dynamic NS dynamic
+dynamic A 10.53.0.3
+
+; A insecure subdomain
+mustbesecure NS ns.mustbesecure
+ns.mustbesecure A 10.53.0.3
+
+; A subdomain with expired signatures
+expired NS ns.expired
+ns.expired A 10.53.0.3
+
+; A rfc2535 signed zone w/ CNAME
+rfc2535 NS ns.rfc2535
+ns.rfc2535 A 10.53.0.3
+
+z A 10.0.0.26
+
+keyless NS ns.keyless
+ns.keyless A 10.53.0.3
+
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+
+optout NS ns.optout
+ns.optout A 10.53.0.3
+
+nsec3-unknown NS ns.nsec3-unknown
+ns.nsec3-unknown A 10.53.0.3
+
+optout-unknown NS ns.optout-unknown
+ns.optout-unknown A 10.53.0.3
+
+dnskey-unknown NS ns.dnskey-unknown
+ns.dnskey-unknown A 10.53.0.3
+
+dnskey-unsupported NS ns.dnskey-unsupported
+ns.dnskey-unsupported A 10.53.0.3
+
+dnskey-nsec3-unknown NS ns.dnskey-nsec3-unknown
+ns.dnskey-nsec3-unknown A 10.53.0.3
+
+multiple NS ns.multiple
+ns.multiple A 10.53.0.3
+
+*.wild A 10.0.0.27
+
+rsasha256 NS ns.rsasha256
+ns.rsasha256 A 10.53.0.3
+
+rsasha512 NS ns.rsasha512
+ns.rsasha512 A 10.53.0.3
+
+kskonly NS ns.kskonly
+ns.kskonly A 10.53.0.3
+
+update-nsec3 NS ns.update-nsec3
+ns.update-nsec3 A 10.53.0.3
+
+auto-nsec NS ns.auto-nsec
+ns.auto-nsec A 10.53.0.3
+
+auto-nsec3 NS ns.auto-nsec3
+ns.auto-nsec3 A 10.53.0.3
+
+
+below-cname CNAME some.where.else.
+
+insecure.below-cname NS ns.insecure.below-cname
+ns.insecure.below-cname A 10.53.0.3
+
+secure.below-cname NS ns.secure.below-cname
+ns.secure.below-cname A 10.53.0.3
+
+ttlpatch NS ns.ttlpatch
+ns.ttlpatch A 10.53.0.3
+
+split-dnssec NS ns.split-dnssec
+ns.split-dnssec A 10.53.0.3
+
+split-smart NS ns.split-smart
+ns.split-smart A 10.53.0.3
+
+upper NS ns.upper
+ns.upper A 10.53.0.3
+
+LOWER NS NS.LOWER
+NS.LOWER A 10.53.0.3
+
+expiring NS ns.expiring
+ns.expiring A 10.53.0.3
+
+future NS ns.future
+ns.future A 10.53.0.3
+
+managed-future NS ns.managed-future
+ns.managed-future A 10.53.0.3
+
+revkey NS ns.revkey
+ns.revkey A 10.53.0.3
+
+dname-at-apex-nsec3 NS ns3
diff --git a/bin/tests/system/dnssec/ns2/in-addr.arpa.db.in b/bin/tests/system/dnssec/ns2/in-addr.arpa.db.in
new file mode 100644
index 0000000..874b915
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/in-addr.arpa.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2.example. . 1 3600 1200 86400 1200
+@ NS ns2.example.
+;
+; As we are testing empty zone behaviour ns3 doesn't need to be
+; configured to serve 10.in-addr.arpa.
+;
+10 NS ns3.example.
diff --git a/bin/tests/system/dnssec/ns2/insecure.secure.example.db b/bin/tests/system/dnssec/ns2/insecure.secure.example.db
new file mode 100644
index 0000000..62862f5
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/insecure.secure.example.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns2/key.db.in b/bin/tests/system/dnssec/ns2/key.db.in
new file mode 100644
index 0000000..2ff5df4
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/key.db.in
@@ -0,0 +1,45 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+
+; A secure subdomain
+secure NS ns3.secure
+ns3.secure A 10.53.0.3
+
+; A subdomain that is signed with an unsupported algorithm
+unsupported NS ns3.unsupported
+ns3.unsupported A 10.53.0.3
+
+; A secure subdomain with a disabled algorithm
+disabled NS ns3.disabled
+ns3.disabled A 10.53.0.3
+
+; A secure subdomain with a disabled algorithm, but not in bailiwick
+enabled NS ns3.enabled
+ns3.enabled A 10.53.0.3
+
+; A secure subdomain with a revoked trust anchor
+revoked NS ns3.revoked
+ns3.revoked A 10.53.0.3
diff --git a/bin/tests/system/dnssec/ns2/named.conf.in b/bin/tests/system/dnssec/ns2/named.conf.in
new file mode 100644
index 0000000..94928c1
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/named.conf.in
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+ notify-delay 1;
+ minimal-responses no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "trusted" {
+ type primary;
+ file "trusted.db.signed";
+};
+
+zone "managed" {
+ type primary;
+ file "managed.db.signed";
+};
+
+zone "example" {
+ type primary;
+ file "example.db.signed";
+ allow-update { any; };
+};
+
+zone "insecure.secure.example" {
+ type primary;
+ file "insecure.secure.example.db";
+ allow-update { any; };
+};
+
+zone "rfc2335.example" {
+ type primary;
+ file "rfc2335.example.db";
+};
+
+zone "child.nsec3.example" {
+ type primary;
+ file "child.nsec3.example.db";
+ allow-update { none; };
+};
+
+zone "child.optout.example" {
+ type primary;
+ file "child.optout.example.db";
+ allow-update { none; };
+};
+
+zone "badparam" {
+ type primary;
+ file "badparam.db.bad";
+};
+
+zone "single-nsec3" {
+ type primary;
+ file "single-nsec3.db.signed";
+};
+
+zone "algroll" {
+ type primary;
+ file "algroll.db.signed";
+};
+
+zone "nsec3chain-test" {
+ type primary;
+ file "nsec3chain-test.db.signed";
+ allow-update {any;};
+};
+
+zone "in-addr.arpa" {
+ type primary;
+ file "in-addr.arpa.db.signed";
+};
+
+zone "cds.secure" {
+ type primary;
+ file "cds.secure.db.signed";
+};
+
+zone "cds-x.secure" {
+ type primary;
+ file "cds-x.secure.db.signed";
+};
+
+zone "cds-update.secure" {
+ type primary;
+ dnssec-dnskey-kskonly no;
+ file "cds-update.secure.db.signed";
+ allow-update { any; };
+};
+
+zone "cds-kskonly.secure" {
+ type primary;
+ dnssec-dnskey-kskonly yes;
+ file "cds-kskonly.secure.db.signed";
+ allow-update { any; };
+};
+
+zone "cds-auto.secure" {
+ type primary;
+ dnssec-dnskey-kskonly no;
+ file "cds-auto.secure.db.signed";
+ auto-dnssec maintain;
+ allow-update { any; };
+};
+
+zone "cdnskey.secure" {
+ type primary;
+ file "cdnskey.secure.db.signed";
+};
+
+zone "cdnskey-x.secure" {
+ type primary;
+ file "cdnskey-x.secure.db.signed";
+};
+
+zone "cdnskey-update.secure" {
+ type primary;
+ dnssec-dnskey-kskonly no;
+ file "cdnskey-update.secure.db.signed";
+ allow-update { any; };
+};
+
+zone "cdnskey-kskonly.secure" {
+ type primary;
+ dnssec-dnskey-kskonly yes;
+ file "cdnskey-kskonly.secure.db.signed";
+ allow-update { any; };
+};
+
+zone "cdnskey-auto.secure" {
+ type primary;
+ dnssec-dnskey-kskonly no;
+ file "cdnskey-auto.secure.db.signed";
+ auto-dnssec maintain;
+ allow-update { any; };
+};
+
+zone "updatecheck-kskonly.secure" {
+ type primary;
+ auto-dnssec maintain;
+ key-directory ".";
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+ sig-validity-interval 10;
+ dnskey-sig-validity 40;
+ file "updatecheck-kskonly.secure.db.signed";
+ allow-update { any; };
+};
+
+zone "corp" {
+ type primary;
+ file "corp.db";
+};
+
+zone "hours-vs-days" {
+ type primary;
+ file "hours-vs-days.db.signed";
+ auto-dnssec maintain;
+ /* validity 500 days, resign in 499 days */
+ sig-validity-interval 500 499;
+ allow-update { any; };
+};
+
+zone "too-many-iterations" {
+ type primary;
+ file "too-many-iterations.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns2/private.secure.example.db.in b/bin/tests/system/dnssec/ns2/private.secure.example.db.in
new file mode 100644
index 0000000..94042ae
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/private.secure.example.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.2
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+private2secure-nxdomain CNAME r.example.
+*.wild CNAME s.example.
diff --git a/bin/tests/system/dnssec/ns2/rfc2335.example.db b/bin/tests/system/dnssec/ns2/rfc2335.example.db
new file mode 100644
index 0000000..78e9326
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/rfc2335.example.db
@@ -0,0 +1,114 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; File written on Fri Apr 30 12:19:15 2004
+; dnssec_signzone version 9.2.4rc3
+rfc2335.example. 300 IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ 300 SIG SOA 1 2 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ nGPJKIzF7X/hMJbZURRz59UeEi/6HRxCn9Er
+ GqSnpw0Ea9Yx5Axu6sLKnF7jXlkZ6NHMCIpJ
+ +Lv+FDHXTs/dQg== )
+ 300 NS ns.rfc2335.example.
+ 300 SIG NS 1 2 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ Q234AL9dJYMvxdWG33lpww6AJ3GplKp+ace7
+ MUaj0oqDdkx4DtJF2XaP2xcqq7kTOObdQ8ES
+ vVxNThqOx7LFzg== )
+ 300 KEY 256 3 1 (
+ AQPZhzXIabI8y5ihWUw7F0WxN2MabnYWkOcV
+ Fn11NgaGSdjBSYPRMMwMCasD5N2KYPRUP83W
+ y8mj+ofcoW1FurcZ
+ ) ; key id = 47799
+ 300 NXT a.rfc2335.example. NS SOA SIG KEY NXT
+ 300 SIG NXT 1 2 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ Y587mqNy6pBEfbsU6+weM2XRSqLwLwRT9Sl7
+ oNuOK9kV3TR4R2M54m2S0MgJCXbRAwU+fF8Q
+ UbZkSTVe2N8Nyg== )
+a.rfc2335.example. 300 IN A 10.0.0.1
+ 300 SIG A 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ FnfWrcw5ire8ut25504zti5l///BdDMUAkJZ
+ UCLFiTW4lBGMcq1pqz64zltDZXCgJ3xUeQ2i
+ nRt19/ZxO6Z1KA== )
+ 300 NXT b.rfc2335.example. A SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ R6SpC3ndMVg4u/eZaaUsXSuMHV/hZXeaM/Op
+ bJLAe3KxMiOHfb6XgLy7wflAiC1xt6A9bWpy
+ kTc5T5gfic33kA== )
+b.rfc2335.example. 300 IN A 10.0.0.2
+ 300 SIG A 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ zjRsYXMGyhDI6ipDtu8YXC9XPN+3hGamzzxL
+ 8uPE/LPo+x19MNdbzEgWzlajAf1/mkSGr2jN
+ BDMVBA5NMKpwAA== )
+ 300 NXT d.rfc2335.example. A SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ aV87iZCYsC5Tqop827Zzb18TNqopGt0QynkR
+ gIF/lIHqZasNFRfaS1/nTnXdDKD8JS5IqxKb
+ oTJr5zswDAtCEw== )
+d.rfc2335.example. 300 IN A 10.0.0.4
+ 300 SIG A 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ NsKyvhUYZxTbOTBX4YwxTxevI5iGBpULKwmt
+ +D4l00ME4XRygOVmiqVDTT9dF1EgjDxOdfMT
+ hSjtCh5M1b2f6g== )
+ 300 NXT ns.rfc2335.example. A SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ OGqlvSDZIZdHYigh4UAFzXfPze7vcQfgj7sN
+ +cAeoh4BL1gpa00DqANCxowNCYluDk3ZCDwt
+ UHZEJa8ZjNvv4g== )
+ns.rfc2335.example. 300 IN A 10.53.0.3
+ 300 SIG A 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ T6ZGeUWflLTku8jO23x/TeAPeUl8t0I18FCh
+ qHUZaHomLQasQ2jlZQn6cLpFd2uFJkBNxZ0G
+ I39aG7G1bObXdA== )
+ 300 NXT x.rfc2335.example. A SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ l46mrf3/Ii5iRm3AiDjYeMg4ZXBgitHxXA2y
+ e/NhKpkxRRpCs7UQ94wT/RiSCjjK49E5FBe6
+ 5bRxtWq0GI7zlg== )
+x.rfc2335.example. 300 IN CNAME a.rfc2335.example.
+ 300 SIG CNAME 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ L3IOluq+kboBd2gR2Mu54uJKCUzfmyHRiWKl
+ kfx+vuFr0I8mEHQRmJtouxNDrBzmzGp5vybK
+ SdabLWw0n6uQEA== )
+ 300 NXT z.rfc2335.example. CNAME SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ CBKoJSkZzdpwiON7JS4yPFY5VVeBjfT19x/O
+ vx+5UK1JZUNKhTXWWgW1er+JlLzNf4Ot40+l
+ z9HUTyaeS0eWyw== )
+z.rfc2335.example. 300 IN A 10.0.0.26
+ 300 SIG A 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ ccqjVHnehvVwlNNd4+7n/GzGlRjj+ul0gCT3
+ X3950LTccxHsOFyjNNm8v/Ho/aurSYdqXEjY
+ jwmjC6elwkzB7A== )
+ 300 NXT rfc2335.example. A SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ W42WoFyd9erysv8HjKo+CpHIH1x6+pAKwCDO
+ /hHnkEpQI3brewxl7cWOPYeA92Ns80Ody/ui
+ m2E28A5gnmWqPw== )
diff --git a/bin/tests/system/dnssec/ns2/sign.sh b/bin/tests/system/dnssec/ns2/sign.sh
new file mode 100644
index 0000000..47248a4
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/sign.sh
@@ -0,0 +1,332 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+# Sign child zones (served by ns3).
+( cd ../ns3 && $SHELL sign.sh )
+
+echo_i "ns2/sign.sh"
+
+# Get the DS records for the "trusted." and "managed." zones.
+for subdomain in secure unsupported disabled enabled
+do
+ cp "../ns3/dsset-$subdomain.managed." .
+ cp "../ns3/dsset-$subdomain.trusted." .
+done
+
+# Sign the "trusted." and "managed." zones.
+zone=managed.
+infile=key.db.in
+zonefile=managed.db
+
+keyname1=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone -f KSK "$zone")
+keyname2=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname1.key" "$keyname2.key" > "$zonefile"
+
+"$SIGNER" -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" > /dev/null 2>&1
+
+zone=trusted.
+infile=key.db.in
+zonefile=trusted.db
+
+keyname1=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone -f KSK "$zone")
+keyname2=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname1.key" "$keyname2.key" > "$zonefile"
+
+"$SIGNER" -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" > /dev/null 2>&1
+
+# The "example." zone.
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+# Get the DS records for the "example." zone.
+for subdomain in secure badds bogus dynamic keyless nsec3 optout \
+ nsec3-unknown optout-unknown multiple rsasha256 rsasha512 \
+ kskonly update-nsec3 auto-nsec auto-nsec3 secure.below-cname \
+ ttlpatch split-dnssec split-smart expired expiring upper lower \
+ dnskey-unknown dnskey-unsupported dnskey-unsupported-2 \
+ dnskey-nsec3-unknown managed-future revkey \
+ dname-at-apex-nsec3 occluded
+do
+ cp "../ns3/dsset-$subdomain.example." .
+done
+
+# Sign the "example." zone.
+keyname1=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone -f KSK "$zone")
+keyname2=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname1.key" "$keyname2.key" > "$zonefile"
+
+"$SIGNER" -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" > /dev/null 2>&1
+
+#
+# lower/uppercase the signature bits with the exception of the last characters
+# changing the last 4 characters will lead to a bad base64 encoding.
+#
+
+zonefiletmp=$(mktemp "$zonefile.XXXXXX") || exit 1
+"$CHECKZONE" -D -q -i local "$zone" "$zonefile.signed" |
+awk '
+tolower($1) == "bad-cname.example." && $4 == "RRSIG" && $5 == "CNAME" {
+ for (i = 1; i <= NF; i++ ) {
+ if (i <= 12) {
+ printf("%s ", $i);
+ continue;
+ }
+ prefix = substr($i, 1, length($i) - 4);
+ suffix = substr($i, length($i) - 4, 4);
+ if (i > 12 && tolower(prefix) != prefix)
+ printf("%s%s", tolower(prefix), suffix);
+ else if (i > 12 && toupper(prefix) != prefix)
+ printf("%s%s", toupper(prefix), suffix);
+ else
+ printf("%s%s ", prefix, suffix);
+ }
+ printf("\n");
+ next;
+}
+
+tolower($1) == "bad-dname.example." && $4 == "RRSIG" && $5 == "DNAME" {
+ for (i = 1; i <= NF; i++ ) {
+ if (i <= 12) {
+ printf("%s ", $i);
+ continue;
+ }
+ prefix = substr($i, 1, length($i) - 4);
+ suffix = substr($i, length($i) - 4, 4);
+ if (i > 12 && tolower(prefix) != prefix)
+ printf("%s%s", tolower(prefix), suffix);
+ else if (i > 12 && toupper(prefix) != prefix)
+ printf("%s%s", toupper(prefix), suffix);
+ else
+ printf("%s%s ", prefix, suffix);
+ }
+ printf("\n");
+ next;
+}
+
+{ print; }' > "$zonefiletmp" && mv "$zonefiletmp" "$zonefile.signed"
+
+#
+# signed in-addr.arpa w/ a delegation for 10.in-addr.arpa which is unsigned.
+#
+zone=in-addr.arpa.
+infile=in-addr.arpa.db.in
+zonefile=in-addr.arpa.db
+
+keyname1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+keyname2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname1.key" "$keyname2.key" > "$zonefile"
+"$SIGNER" -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" > /dev/null 2>&1
+
+# Sign the badparam secure file
+
+zone=badparam.
+infile=badparam.db.in
+zonefile=badparam.db
+
+keyname1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+keyname2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname1.key" "$keyname2.key" > "$zonefile"
+
+"$SIGNER" -3 - -H 1 -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" > /dev/null 2>&1
+
+sed -e 's/IN NSEC3 1 0 1 /IN NSEC3 1 0 10 /' "$zonefile.signed" > "$zonefile.bad"
+
+# Sign the single-nsec3 secure zone with optout
+
+zone=single-nsec3.
+infile=single-nsec3.db.in
+zonefile=single-nsec3.db
+
+keyname1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+keyname2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname1.key" "$keyname2.key" > "$zonefile"
+
+"$SIGNER" -3 - -A -H 1 -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" > /dev/null 2>&1
+
+#
+# algroll has just has the old DNSKEY records removed and is waiting
+# for them to be flushed from caches. We still need to generate
+# RRSIGs for the old DNSKEY.
+#
+zone=algroll.
+infile=algroll.db.in
+zonefile=algroll.db
+
+keyold1=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone -f KSK "$zone")
+keyold2=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone "$zone")
+keynew1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+keynew2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keynew1.key" "$keynew2.key" > "$zonefile"
+
+"$SIGNER" -o "$zone" -k "$keyold1" -k "$keynew1" "$zonefile" "$keyold1" "$keyold2" "$keynew1" "$keynew2" > /dev/null 2>&1
+
+#
+# Make a zone big enough that it takes several seconds to generate a new
+# nsec3 chain.
+#
+zone=nsec3chain-test
+zonefile=nsec3chain-test.db
+cat > "$zonefile" << EOF
+\$TTL 10
+@ 10 SOA ns2 hostmaster 0 3600 1200 864000 1200
+@ 10 NS ns2
+@ 10 NS ns3
+ns2 10 A 10.53.0.2
+ns3 10 A 10.53.0.3
+EOF
+i=1
+while [ $i -le 300 ]; do
+ echo "host$i 10 IN NS ns.elsewhere"
+ i=$((i+1))
+done >> "$zonefile"
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+cat "$key1.key" "$key2.key" >> "$zonefile"
+"$SIGNER" -3 - -A -H 1 -g -o "$zone" -k "$key1" "$zonefile" "$key2" > /dev/null 2>&1
+
+zone=cds.secure
+infile=cds.secure.db.in
+zonefile=cds.secure.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+"$DSFROMKEY" -C "$key1.key" > "$key1.cds"
+cat "$infile" "$key1.key" "$key2.key" "$key1.cds" >$zonefile
+"$SIGNER" -g -o "$zone" "$zonefile" > /dev/null 2>&1
+
+zone=cds-x.secure
+infile=cds.secure.db.in
+zonefile=cds-x.secure.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key3=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+"$DSFROMKEY" -C "$key2.key" > "$key2.cds"
+cat "$infile" "$key1.key" "$key2.key" "$key3.key" "$key2.cds" > "$zonefile"
+"$SIGNER" -g -x -o "$zone" "$zonefile" > /dev/null 2>&1
+
+zone=cds-update.secure
+infile=cds-update.secure.db.in
+zonefile=cds-update.secure.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+cat "$infile" "$key1.key" "$key2.key" > "$zonefile"
+"$SIGNER" -g -o "$zone" "$zonefile" > /dev/null 2>&1
+
+zone=cds-kskonly.secure
+infile=cds-kskonly.secure.db.in
+zonefile=cds-kskonly.secure.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+cat "$infile" "$key1.key" "$key2.key" > "$zonefile"
+"$SIGNER" -g -o "$zone" "$zonefile" > /dev/null 2>&1
+keyfile_to_key_id "$key1" > cds-kskonly.secure.id
+
+zone=cds-auto.secure
+infile=cds-auto.secure.db.in
+zonefile=cds-auto.secure.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+$SETTIME -P sync now "$key1" > /dev/null
+cat "$infile" > "$zonefile.signed"
+
+zone=cdnskey.secure
+infile=cdnskey.secure.db.in
+zonefile=cdnskey.secure.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+sed 's/DNSKEY/CDNSKEY/' "$key1.key" > "$key1.cds"
+cat "$infile" "$key1.key" "$key2.key" "$key1.cds" > "$zonefile"
+"$SIGNER" -g -o "$zone" "$zonefile" > /dev/null 2>&1
+
+zone=cdnskey-x.secure
+infile=cdnskey.secure.db.in
+zonefile=cdnskey-x.secure.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key3=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+sed 's/DNSKEY/CDNSKEY/' "$key1.key" > "$key1.cds"
+cat "$infile" "$key1.key" "$key2.key" "$key3.key" "$key1.cds" > "$zonefile"
+"$SIGNER" -g -x -o "$zone" "$zonefile" > /dev/null 2>&1
+
+zone=cdnskey-update.secure
+infile=cdnskey-update.secure.db.in
+zonefile=cdnskey-update.secure.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+cat "$infile" "$key1.key" "$key2.key" > "$zonefile"
+"$SIGNER" -g -o "$zone" "$zonefile" > /dev/null 2>&1
+
+zone=cdnskey-kskonly.secure
+infile=cdnskey-kskonly.secure.db.in
+zonefile=cdnskey-kskonly.secure.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+cat "$infile" "$key1.key" "$key2.key" > "$zonefile"
+"$SIGNER" -g -o "$zone" "$zonefile" > /dev/null 2>&1
+keyfile_to_key_id "$key1" > cdnskey-kskonly.secure.id
+
+zone=cdnskey-auto.secure
+infile=cdnskey-auto.secure.db.in
+zonefile=cdnskey-auto.secure.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+$SETTIME -P sync now "$key1" > /dev/null
+cat "$infile" > "$zonefile.signed"
+
+zone=updatecheck-kskonly.secure
+infile=template.secure.db.in
+zonefile=${zone}.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+# Save key id's for checking active key usage
+keyfile_to_key_id "$key1" > $zone.ksk.id
+keyfile_to_key_id "$key2" > $zone.zsk.id
+echo "${key1}" > $zone.ksk.key
+echo "${key2}" > $zone.zsk.key
+# Add CDS and CDNSKEY records
+sed 's/DNSKEY/CDNSKEY/' "$key1.key" > "$key1.cdnskey"
+"$DSFROMKEY" -C "$key1.key" > "$key1.cds"
+cat "$infile" "$key1.key" "$key2.key" "$key1.cdnskey" "$key1.cds" > "$zonefile"
+# Don't sign, let auto-dnssec maintain do it.
+mv $zonefile "$zonefile.signed"
+
+zone=hours-vs-days
+infile=hours-vs-days.db.in
+zonefile=hours-vs-days.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+$SETTIME -P sync now "$key1" > /dev/null
+cat "$infile" > "$zonefile.signed"
+
+#
+# Negative result from this zone should come back as insecure.
+#
+zone=too-many-iterations
+infile=too-many-iterations.db.in
+zonefile=too-many-iterations.db
+key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+cat "$infile" "$key1.key" "$key2.key" > "$zonefile"
+"$SIGNER" -P -3 - -H too-many -g -o "$zone" "$zonefile" > /dev/null 2>&1
diff --git a/bin/tests/system/dnssec/ns2/single-nsec3.db.in b/bin/tests/system/dnssec/ns2/single-nsec3.db.in
new file mode 100644
index 0000000..b2e3c13
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/single-nsec3.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns2.example. . (
+ 2010042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2.example.
+delegation NS ns3.example.
diff --git a/bin/tests/system/dnssec/ns2/template.secure.db.in b/bin/tests/system/dnssec/ns2/template.secure.db.in
new file mode 100644
index 0000000..aa3aaab
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/template.secure.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2.example. . 1 3600 1200 86400 1200
+@ NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/too-many-iterations.db.in b/bin/tests/system/dnssec/ns2/too-many-iterations.db.in
new file mode 100644
index 0000000..1527e07
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/too-many-iterations.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 30 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 30 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+*.a A 10.0.0.3
+b A 10.0.0.2
+d A 10.0.0.4
diff --git a/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in b/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in
new file mode 100644
index 0000000..a7792fd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
+nosoa NS ns.nosoa
+ns.nosoa A 10.53.0.7
+
+normalthenrrsig A 10.0.0.28
+rrsigonly A 10.0.0.29
diff --git a/bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in b/bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in
new file mode 100644
index 0000000..a7792fd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
+nosoa NS ns.nosoa
+ns.nosoa A 10.53.0.7
+
+normalthenrrsig A 10.0.0.28
+rrsigonly A 10.0.0.29
diff --git a/bin/tests/system/dnssec/ns3/bogus.example.db.in b/bin/tests/system/dnssec/ns3/bogus.example.db.in
new file mode 100644
index 0000000..0feb441
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/bogus.example.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/dname-at-apex-nsec3.example.db.in b/bin/tests/system/dnssec/ns3/dname-at-apex-nsec3.example.db.in
new file mode 100644
index 0000000..e758cdd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/dname-at-apex-nsec3.example.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns3.example. . 1 1200 1200 1814400 3600
+@ NS ns3.example.
+@ DNAME example.
diff --git a/bin/tests/system/dnssec/ns3/dnskey-nsec3-unknown.example.db.in b/bin/tests/system/dnssec/ns3/dnskey-nsec3-unknown.example.db.in
new file mode 100644
index 0000000..f37dd75
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/dnskey-nsec3-unknown.example.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.e A 10.0.0.6
+child NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns3/dnskey-unknown.example.db.in b/bin/tests/system/dnssec/ns3/dnskey-unknown.example.db.in
new file mode 100644
index 0000000..f37dd75
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/dnskey-unknown.example.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.e A 10.0.0.6
+child NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns3/dnskey-unsupported-2.example.db.in b/bin/tests/system/dnssec/ns3/dnskey-unsupported-2.example.db.in
new file mode 100644
index 0000000..f37dd75
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/dnskey-unsupported-2.example.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.e A 10.0.0.6
+child NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns3/dnskey-unsupported.example.db.in b/bin/tests/system/dnssec/ns3/dnskey-unsupported.example.db.in
new file mode 100644
index 0000000..f37dd75
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/dnskey-unsupported.example.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.e A 10.0.0.6
+child NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns3/dynamic.example.db.in b/bin/tests/system/dnssec/ns3/dynamic.example.db.in
new file mode 100644
index 0000000..babf54c
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/dynamic.example.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This has the NS and glue at the apex because testing RT #2399
+; requires we have only one name in the zone at a certain point
+; during the test.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS @
+@ A 10.53.0.3
diff --git a/bin/tests/system/dnssec/ns3/expired.example.db.in b/bin/tests/system/dnssec/ns3/expired.example.db.in
new file mode 100644
index 0000000..b7706d3
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/expired.example.db.in
@@ -0,0 +1,44 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ MX 10 mx
+ns A 10.53.0.3
+mx A 10.0.0.30
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
+nosoa NS ns.nosoa
+ns.nosoa A 10.53.0.7
+
+normalthenrrsig A 10.0.0.28
+rrsigonly A 10.0.0.29
+
+
diff --git a/bin/tests/system/dnssec/ns3/expiring.example.db.in b/bin/tests/system/dnssec/ns3/expiring.example.db.in
new file mode 100644
index 0000000..8acf7b1
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/expiring.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ MX 10 mx
+ns A 10.53.0.3
+mx A 10.0.0.30
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.wild A 10.0.0.6
+child NS ns2.example.
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17
diff --git a/bin/tests/system/dnssec/ns3/future.example.db.in b/bin/tests/system/dnssec/ns3/future.example.db.in
new file mode 100644
index 0000000..20c19c5
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/future.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.wild A 10.0.0.6
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+child NS ns2.example.
+insecure.empty NS ns.insecure.empty
+ns.insecure.empty A 10.53.0.3
+foo.*.empty-wild NS ns
diff --git a/bin/tests/system/dnssec/ns3/generic.example.db.in b/bin/tests/system/dnssec/ns3/generic.example.db.in
new file mode 100644
index 0000000..5cc3ecc
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/generic.example.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a.b A 10.0.0.1
diff --git a/bin/tests/system/dnssec/ns3/inline.example.db b/bin/tests/system/dnssec/ns3/inline.example.db
new file mode 100644
index 0000000..14971bd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/inline.example.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/insecure.below-cname.example.db b/bin/tests/system/dnssec/ns3/insecure.below-cname.example.db
new file mode 100644
index 0000000..14971bd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure.below-cname.example.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/insecure.example.db b/bin/tests/system/dnssec/ns3/insecure.example.db
new file mode 100644
index 0000000..76e3f47
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure.example.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x DNSKEY 258 3 5 Cg==
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/insecure.nsec3.example.db b/bin/tests/system/dnssec/ns3/insecure.nsec3.example.db
new file mode 100644
index 0000000..14971bd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure.nsec3.example.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/insecure.optout.example.db b/bin/tests/system/dnssec/ns3/insecure.optout.example.db
new file mode 100644
index 0000000..14971bd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure.optout.example.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/insecure2.example.db b/bin/tests/system/dnssec/ns3/insecure2.example.db
new file mode 100644
index 0000000..76e3f47
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure2.example.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x DNSKEY 258 3 5 Cg==
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/key.db.in b/bin/tests/system/dnssec/ns3/key.db.in
new file mode 100644
index 0000000..0165e3f
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/key.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+
diff --git a/bin/tests/system/dnssec/ns3/kskonly.example.db.in b/bin/tests/system/dnssec/ns3/kskonly.example.db.in
new file mode 100644
index 0000000..0b11a00
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/kskonly.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+x CNAME a
diff --git a/bin/tests/system/dnssec/ns3/lower.example.db.in b/bin/tests/system/dnssec/ns3/lower.example.db.in
new file mode 100644
index 0000000..a04793e
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/lower.example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA MNAME1. . (
+ 2012042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS NS
+NS A 10.53.0.3
diff --git a/bin/tests/system/dnssec/ns3/managed-future.example.db.in b/bin/tests/system/dnssec/ns3/managed-future.example.db.in
new file mode 100644
index 0000000..20c19c5
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/managed-future.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.wild A 10.0.0.6
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+child NS ns2.example.
+insecure.empty NS ns.insecure.empty
+ns.insecure.empty A 10.53.0.3
+foo.*.empty-wild NS ns
diff --git a/bin/tests/system/dnssec/ns3/multiple.example.db.in b/bin/tests/system/dnssec/ns3/multiple.example.db.in
new file mode 100644
index 0000000..f37dd75
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/multiple.example.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.e A 10.0.0.6
+child NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns3/named.conf.in b/bin/tests/system/dnssec/ns3/named.conf.in
new file mode 100644
index 0000000..cdc6e02
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/named.conf.in
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 no;
+ notify yes;
+ dnssec-validation yes;
+ session-keyfile "session.key";
+ minimal-responses no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "example.bk";
+};
+
+zone "secure.example" {
+ type primary;
+ file "secure.example.db.signed";
+ allow-update { any; };
+};
+
+zone "bogus.example" {
+ type primary;
+ file "bogus.example.db.signed";
+ allow-update { any; };
+};
+
+zone "badds.example" {
+ type primary;
+ file "badds.example.db.signed";
+ allow-update { any; };
+};
+
+zone "dynamic.example" {
+ type primary;
+ file "dynamic.example.db.signed";
+ allow-update { any; };
+};
+
+zone "insecure.example" {
+ type primary;
+ file "insecure.example.db";
+ allow-update { any; };
+};
+
+zone "insecure2.example" {
+ type primary;
+ file "insecure2.example.db";
+ allow-update { any; };
+};
+
+zone "insecure.nsec3.example" {
+ type primary;
+ file "insecure.nsec3.example.db";
+ allow-update { any; };
+};
+
+zone "insecure.optout.example" {
+ type primary;
+ file "insecure.optout.example.db";
+ allow-update { any; };
+};
+
+zone "keyless.example" {
+ type primary;
+ file "keyless.example.db.signed";
+};
+
+zone "nsec3.example" {
+ type primary;
+ file "nsec3.example.db.signed";
+};
+
+zone "optout.nsec3.example" {
+ type primary;
+ file "optout.nsec3.example.db.signed";
+};
+
+zone "nsec3.nsec3.example" {
+ type primary;
+ file "nsec3.nsec3.example.db.signed";
+};
+
+zone "secure.nsec3.example" {
+ type primary;
+ file "secure.nsec3.example.db.signed";
+};
+
+zone "optout.example" {
+ type primary;
+ file "optout.example.db.signed";
+};
+
+zone "secure.optout.example" {
+ type primary;
+ file "secure.optout.example.db.signed";
+};
+
+zone "nsec3.optout.example" {
+ type primary;
+ file "nsec3.optout.example.db.signed";
+};
+
+zone "optout.optout.example" {
+ type primary;
+ file "optout.optout.example.db.signed";
+};
+
+zone "nsec3-unknown.example" {
+ type primary;
+ nsec3-test-zone yes;
+ file "nsec3-unknown.example.db.signed";
+};
+
+zone "optout-unknown.example" {
+ type primary;
+ nsec3-test-zone yes;
+ file "optout-unknown.example.db.signed";
+};
+
+zone "dnskey-unknown.example" {
+ type primary;
+ file "dnskey-unknown.example.db.signed";
+};
+
+zone "dnskey-unsupported.example" {
+ type primary;
+ file "dnskey-unsupported.example.db.signed";
+};
+
+zone "dnskey-unsupported-2.example" {
+ type primary;
+ file "dnskey-unsupported-2.example.db.signed";
+};
+
+zone "dnskey-nsec3-unknown.example" {
+ type primary;
+ nsec3-test-zone yes;
+ file "dnskey-nsec3-unknown.example.db.signed";
+};
+
+zone "multiple.example" {
+ type primary;
+ file "multiple.example.db.signed";
+ allow-update { any; };
+};
+
+zone "rfc2335.example" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "rfc2335.example.bk";
+};
+
+zone "rsasha256.example" {
+ type primary;
+ file "rsasha256.example.db.signed";
+};
+
+zone "rsasha512.example" {
+ type primary;
+ file "rsasha512.example.db.signed";
+};
+
+zone "kskonly.example" {
+ type primary;
+ file "kskonly.example.db.signed";
+};
+
+zone "expired.example" {
+ type primary;
+ allow-update { none; };
+ file "expired.example.db.signed";
+};
+
+zone "update-nsec3.example" {
+ type primary;
+ allow-update { any; };
+ file "update-nsec3.example.db.signed";
+};
+
+zone "auto-nsec.example" {
+ type primary;
+ auto-dnssec maintain;
+ allow-update { !0.0.0.0; };
+ file "auto-nsec.example.db.signed";
+};
+
+zone "auto-nsec3.example" {
+ type primary;
+ auto-dnssec maintain;
+ allow-update { !0.0.0.0; };
+ file "auto-nsec3.example.db.signed";
+};
+
+zone "insecure.below-cname.example" {
+ type primary;
+ file "insecure.below-cname.example.db";
+};
+
+zone "secure.below-cname.example" {
+ type primary;
+ file "secure.below-cname.example.db.signed";
+};
+
+zone "ttlpatch.example" {
+ type primary;
+ file "ttlpatch.example.db.patched";
+};
+
+zone "split-dnssec.example" {
+ type primary;
+ file "split-dnssec.example.db";
+};
+
+zone "split-smart.example" {
+ type primary;
+ file "split-smart.example.db";
+};
+
+zone "nsec3chain-test" {
+ type secondary;
+ file "nsec3chain-test.bk";
+ primaries { 10.53.0.2; };
+};
+
+zone "expiring.example" {
+ type primary;
+ allow-update { any; };
+ file "expiring.example.db.signed";
+};
+
+zone "nosign.example" {
+ type primary;
+ allow-update { any; };
+ dnssec-update-mode no-resign;
+ file "nosign.example.db.signed";
+};
+
+zone "upper.example" {
+ type primary;
+ file "upper.example.db.signed";
+};
+
+zone "LOWER.EXAMPLE" {
+ type primary;
+ file "lower.example.db.signed";
+};
+
+zone "inline.example" {
+ type primary;
+ file "inline.example.db";
+ inline-signing yes;
+ auto-dnssec maintain;
+};
+
+zone "publish-inactive.example" {
+ type primary;
+ file "publish-inactive.example.db";
+ auto-dnssec maintain;
+ dnssec-dnskey-kskonly no;
+ update-policy local;
+};
+
+zone "future.example" {
+ type primary;
+ file "future.example.db.signed";
+};
+
+zone "managed-future.example" {
+ type primary;
+ file "managed-future.example.db.signed";
+ allow-update { any; };
+};
+
+zone "revkey.example" {
+ type primary;
+ file "revkey.example.db.signed";
+};
+
+zone "dname-at-apex-nsec3.example" {
+ type primary;
+ file "dname-at-apex-nsec3.example.db.signed";
+};
+
+zone "occluded.example" {
+ type primary;
+ file "occluded.example.db.signed";
+};
+
+zone "secure.managed" {
+ type primary;
+ file "secure.managed.db.signed";
+};
+
+zone "disabled.managed" {
+ type primary;
+ file "disabled.managed.db.signed";
+};
+
+zone "enabled.managed" {
+ type primary;
+ file "enabled.managed.db.signed";
+};
+
+zone "unsupported.managed" {
+ type primary;
+ file "unsupported.managed.db.signed";
+};
+
+zone "revoked.managed" {
+ type primary;
+ file "revoked.managed.db.signed";
+};
+
+zone "secure.trusted" {
+ type primary;
+ file "secure.trusted.db.signed";
+};
+
+zone "disabled.trusted" {
+ type primary;
+ file "disabled.trusted.db.signed";
+};
+
+zone "enabled.trusted" {
+ type primary;
+ file "enabled.trusted.db.signed";
+};
+
+zone "unsupported.trusted" {
+ type primary;
+ file "unsupported.trusted.db.signed";
+};
+
+zone "revoked.trusted" {
+ type primary;
+ file "revoked.trusted.db.signed";
+};
+
+zone "too-many-iterations" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "too-many-iterations.bk";
+};
+
+include "siginterval.conf";
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns3/nosign.example.db.in b/bin/tests/system/dnssec/ns3/nosign.example.db.in
new file mode 100644
index 0000000..2be8a28
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nosign.example.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
diff --git a/bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in b/bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in
new file mode 100644
index 0000000..f37dd75
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.e A 10.0.0.6
+child NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns3/nsec3.example.db.in b/bin/tests/system/dnssec/ns3/nsec3.example.db.in
new file mode 100644
index 0000000..55b3877
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3.example.db.in
@@ -0,0 +1,38 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.wild A 10.0.0.6
+child NS ns2.example.
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17
diff --git a/bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in b/bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in b/bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/occluded.example.db.in b/bin/tests/system/dnssec/ns3/occluded.example.db.in
new file mode 100644
index 0000000..ee9c900
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/occluded.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a.b A 10.0.0.1
+delegation NS ns
+ A 10.53.0.3
+ AAAA 2002::
diff --git a/bin/tests/system/dnssec/ns3/optout-unknown.example.db.in b/bin/tests/system/dnssec/ns3/optout-unknown.example.db.in
new file mode 100644
index 0000000..f37dd75
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout-unknown.example.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.e A 10.0.0.6
+child NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns3/optout.example.db.in b/bin/tests/system/dnssec/ns3/optout.example.db.in
new file mode 100644
index 0000000..20c19c5
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.wild A 10.0.0.6
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+child NS ns2.example.
+insecure.empty NS ns.insecure.empty
+ns.insecure.empty A 10.53.0.3
+foo.*.empty-wild NS ns
diff --git a/bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in b/bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/optout.optout.example.db.in b/bin/tests/system/dnssec/ns3/optout.optout.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout.optout.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/publish-inactive.example.db.in b/bin/tests/system/dnssec/ns3/publish-inactive.example.db.in
new file mode 100644
index 0000000..14971bd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/publish-inactive.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/rsasha256.example.db.in b/bin/tests/system/dnssec/ns3/rsasha256.example.db.in
new file mode 100644
index 0000000..f6c4fab
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/rsasha256.example.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
diff --git a/bin/tests/system/dnssec/ns3/rsasha512.example.db.in b/bin/tests/system/dnssec/ns3/rsasha512.example.db.in
new file mode 100644
index 0000000..f6c4fab
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/rsasha512.example.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2009102722 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
diff --git a/bin/tests/system/dnssec/ns3/secure.below-cname.example.db.in b/bin/tests/system/dnssec/ns3/secure.below-cname.example.db.in
new file mode 100644
index 0000000..14971bd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/secure.below-cname.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/secure.example.db.in b/bin/tests/system/dnssec/ns3/secure.example.db.in
new file mode 100644
index 0000000..ec39308
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/secure.example.db.in
@@ -0,0 +1,49 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+d A 10.0.0.4
+e A 10.0.0.5
+f A 10.0.0.6
+g A 10.0.0.7
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+zz DNSKEY 258 3 5 Cg==
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns2.insecure
+ns2.insecure A 10.53.0.2
+
+nosoa NS ns.nosoa
+ns.nosoa A 10.53.0.7
+
+normalthenrrsig A 10.0.0.28
+rrsigonly A 10.0.0.29
+
+cnameandkey CNAME @
+cnamenokey CNAME @
+dnameandkey DNAME @
diff --git a/bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in b/bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/secure.optout.example.db.in b/bin/tests/system/dnssec/ns3/secure.optout.example.db.in
new file mode 100644
index 0000000..15fe621
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/secure.optout.example.db.in
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/siginterval.example.db.in b/bin/tests/system/dnssec/ns3/siginterval.example.db.in
new file mode 100644
index 0000000..ec6603a
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/siginterval.example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2012042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS ns
+ns A 10.53.0.3
diff --git a/bin/tests/system/dnssec/ns3/siginterval1.conf b/bin/tests/system/dnssec/ns3/siginterval1.conf
new file mode 100644
index 0000000..4674cf3
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/siginterval1.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "siginterval.example" {
+ type primary;
+ allow-update { any; };
+ sig-validity-interval 1 23;
+ dnskey-sig-validity 90;
+ auto-dnssec maintain;
+ file "siginterval.example.db";
+};
diff --git a/bin/tests/system/dnssec/ns3/siginterval2.conf b/bin/tests/system/dnssec/ns3/siginterval2.conf
new file mode 100644
index 0000000..46a2007
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/siginterval2.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "siginterval.example" {
+ type primary;
+ allow-update { any; };
+ sig-validity-interval 35 28;
+ dnskey-sig-validity 90;
+ auto-dnssec maintain;
+ file "siginterval.example.db";
+};
diff --git a/bin/tests/system/dnssec/ns3/sign.sh b/bin/tests/system/dnssec/ns3/sign.sh
new file mode 100644
index 0000000..f56edb2
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/sign.sh
@@ -0,0 +1,674 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+echo_i "ns3/sign.sh"
+
+infile=key.db.in
+for tld in managed trusted
+do
+ # A secure zone to test.
+ zone=secure.${tld}
+ zonefile=${zone}.db
+
+ keyname1=$("$KEYGEN" -f KSK -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+ cat "$infile" "$keyname1.key" > "$zonefile"
+ "$SIGNER" -z -P -3 - -o "$zone" -O full -f ${zonefile}.signed "$zonefile" > /dev/null
+
+ # Zone to test trust anchor that matches disabled algorithm.
+ zone=disabled.${tld}
+ zonefile=${zone}.db
+
+ keyname2=$("$KEYGEN" -f KSK -q -a "$DISABLED_ALGORITHM" -b "$DISABLED_BITS" -n zone "$zone")
+ cat "$infile" "$keyname2.key" > "$zonefile"
+ "$SIGNER" -z -P -3 - -o "$zone" -O full -f ${zonefile}.signed "$zonefile" > /dev/null
+
+ # Zone to test trust anchor that has disabled algorithm for other domain.
+ zone=enabled.${tld}
+ zonefile=${zone}.db
+
+ keyname3=$("$KEYGEN" -f KSK -q -a "$DISABLED_ALGORITHM" -b "$DISABLED_BITS" -n zone "$zone")
+ cat "$infile" "$keyname3.key" > "$zonefile"
+ "$SIGNER" -z -P -3 - -o "$zone" -O full -f ${zonefile}.signed "$zonefile" > /dev/null
+
+ # Zone to test trust anchor with unsupported algorithm.
+ zone=unsupported.${tld}
+ zonefile=${zone}.db
+
+ keyname4=$("$KEYGEN" -f KSK -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+ cat "$infile" "$keyname4.key" > "$zonefile"
+ "$SIGNER" -z -3 - -o "$zone" -O full -f ${zonefile}.tmp "$zonefile" > /dev/null
+ awk '$4 == "DNSKEY" { $7 = 255 } $4 == "RRSIG" { $6 = 255 } { print }' ${zonefile}.tmp > ${zonefile}.signed
+
+ # Make trusted-keys and managed keys conf sections for ns8.
+ mv ${keyname4}.key ${keyname4}.tmp
+ awk '$1 == "unsupported.'"${tld}"'." { $6 = 255 } { print }' ${keyname4}.tmp > ${keyname4}.key
+
+ # Zone to test trust anchor that is revoked.
+ zone=revoked.${tld}
+ zonefile=${zone}.db
+
+ keyname5=$("$KEYGEN" -f KSK -f REVOKE -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+ cat "$infile" "$keyname5.key" > "$zonefile"
+ "$SIGNER" -z -P -3 - -o "$zone" -O full -f ${zonefile}.signed "$zonefile" > /dev/null
+
+ case $tld in
+ "managed")
+ keyfile_to_initial_keys $keyname1 $keyname2 $keyname3 $keyname4 $keyname5 > ../ns8/managed.conf
+ ;;
+ "trusted")
+ keyfile_to_static_keys $keyname1 $keyname2 $keyname3 $keyname4 $keyname5 > ../ns8/trusted.conf
+ ;;
+ esac
+done
+
+echo_i "ns3/sign.sh: example zones"
+
+zone=secure.example.
+infile=secure.example.db.in
+zonefile=secure.example.db
+
+cnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "cnameandkey.$zone")
+dnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "dnameandkey.$zone")
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$cnameandkey.key" "$dnameandkey.key" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -o "$zone" "$zonefile" > /dev/null
+
+zone=bogus.example.
+infile=bogus.example.db.in
+zonefile=bogus.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -o "$zone" "$zonefile" > /dev/null
+
+zone=dynamic.example.
+infile=dynamic.example.db.in
+zonefile=dynamic.example.db
+
+keyname1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+keyname2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone")
+
+cat "$infile" "$keyname1.key" "$keyname2.key" > "$zonefile"
+
+"$SIGNER" -o "$zone" "$zonefile" > /dev/null
+
+zone=keyless.example.
+infile=generic.example.db.in
+zonefile=keyless.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -o "$zone" "$zonefile" > /dev/null
+
+# Change the signer field of the a.b.keyless.example RRSIG A
+# to point to a provably nonexistent DNSKEY record.
+zonefiletmp=$(mktemp "$zonefile.XXXXXX") || exit 1
+mv "$zonefile.signed" "$zonefiletmp"
+<"$zonefiletmp" "$PERL" -p -e 's/ keyless.example/ b.keyless.example/
+ if /^a.b.keyless.example/../A RRSIG NSEC/;' > "$zonefile.signed"
+rm -f "$zonefiletmp"
+
+#
+# NSEC3/NSEC test zone
+#
+zone=secure.nsec3.example.
+infile=secure.nsec3.example.db.in
+zonefile=secure.nsec3.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -o "$zone" "$zonefile" > /dev/null
+
+#
+# NSEC3/NSEC3 test zone
+#
+zone=nsec3.nsec3.example.
+infile=nsec3.nsec3.example.db.in
+zonefile=nsec3.nsec3.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -3 - -o "$zone" "$zonefile" > /dev/null
+
+#
+# OPTOUT/NSEC3 test zone
+#
+zone=optout.nsec3.example.
+infile=optout.nsec3.example.db.in
+zonefile=optout.nsec3.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -3 - -A -o "$zone" "$zonefile" > /dev/null
+
+#
+# A nsec3 zone (non-optout).
+#
+zone=nsec3.example.
+infile=nsec3.example.db.in
+zonefile=nsec3.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -g -3 - -o "$zone" "$zonefile" > /dev/null
+
+#
+# OPTOUT/NSEC test zone
+#
+zone=secure.optout.example.
+infile=secure.optout.example.db.in
+zonefile=secure.optout.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -o "$zone" "$zonefile" > /dev/null
+
+#
+# OPTOUT/NSEC3 test zone
+#
+zone=nsec3.optout.example.
+infile=nsec3.optout.example.db.in
+zonefile=nsec3.optout.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -3 - -o "$zone" "$zonefile" > /dev/null
+
+#
+# OPTOUT/OPTOUT test zone
+#
+zone=optout.optout.example.
+infile=optout.optout.example.db.in
+zonefile=optout.optout.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -3 - -A -o "$zone" "$zonefile" > /dev/null
+
+#
+# A optout nsec3 zone.
+#
+zone=optout.example.
+infile=optout.example.db.in
+zonefile=optout.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -g -3 - -A -o "$zone" "$zonefile" > /dev/null
+
+#
+# A nsec3 zone (non-optout) with unknown nsec3 hash algorithm (-U).
+#
+zone=nsec3-unknown.example.
+infile=nsec3-unknown.example.db.in
+zonefile=nsec3-unknown.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -3 - -PU -o "$zone" "$zonefile" > /dev/null
+
+#
+# A optout nsec3 zone with a unknown nsec3 hash algorithm (-U).
+#
+zone=optout-unknown.example.
+infile=optout-unknown.example.db.in
+zonefile=optout-unknown.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -3 - -PU -A -o "$zone" "$zonefile" > /dev/null
+
+#
+# A zone that is signed with an unknown DNSKEY algorithm.
+# Algorithm 7 is replaced by 100 in the zone and dsset.
+#
+zone=dnskey-unknown.example
+infile=dnskey-unknown.example.db.in
+zonefile=dnskey-unknown.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -3 - -o "$zone" -O full -f ${zonefile}.tmp "$zonefile" > /dev/null
+
+awk '$4 == "DNSKEY" { $7 = 100 } $4 == "RRSIG" { $6 = 100 } { print }' ${zonefile}.tmp > ${zonefile}.signed
+
+DSFILE="dsset-${zone}."
+$DSFROMKEY -A -f ${zonefile}.signed "$zone" > "$DSFILE"
+
+#
+# A zone that is signed with an unsupported DNSKEY algorithm (3).
+# Algorithm 7 is replaced by 255 in the zone and dsset.
+#
+zone=dnskey-unsupported.example
+infile=dnskey-unsupported.example.db.in
+zonefile=dnskey-unsupported.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -3 - -o "$zone" -O full -f ${zonefile}.tmp "$zonefile" > /dev/null
+
+awk '$4 == "DNSKEY" { $7 = 255 } $4 == "RRSIG" { $6 = 255 } { print }' ${zonefile}.tmp > ${zonefile}.signed
+
+DSFILE="dsset-${zone}."
+$DSFROMKEY -A -f ${zonefile}.signed "$zone" > "$DSFILE"
+
+#
+# A zone with a published unsupported DNSKEY algorithm (Reserved).
+# Different from above because this key is not intended for signing.
+#
+zone=dnskey-unsupported-2.example
+infile=dnskey-unsupported-2.example.db.in
+zonefile=dnskey-unsupported-2.example.db
+
+ksk=$("$KEYGEN" -f KSK -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$ksk.key" "$zsk.key" unsupported-algorithm.key > "$zonefile"
+
+"$SIGNER" -3 - -o "$zone" -f ${zonefile}.signed "$zonefile" > /dev/null
+
+#
+# A zone with a unknown DNSKEY algorithm + unknown NSEC3 hash algorithm (-U).
+# Algorithm 7 is replaced by 100 in the zone and dsset.
+#
+zone=dnskey-nsec3-unknown.example
+infile=dnskey-nsec3-unknown.example.db.in
+zonefile=dnskey-nsec3-unknown.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -3 - -o "$zone" -PU -O full -f ${zonefile}.tmp "$zonefile" > /dev/null
+
+awk '$4 == "DNSKEY" { $7 = 100; print } $4 == "RRSIG" { $6 = 100; print } { print }' ${zonefile}.tmp > ${zonefile}.signed
+
+DSFILE="dsset-${zone}."
+$DSFROMKEY -A -f ${zonefile}.signed "$zone" > "$DSFILE"
+
+#
+# A multiple parameter nsec3 zone.
+#
+zone=multiple.example.
+infile=multiple.example.db.in
+zonefile=multiple.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -O full -o "$zone" "$zonefile" > /dev/null
+awk '$4 == "NSEC" || ( $4 == "RRSIG" && $5 == "NSEC" ) { print }' "$zonefile".signed > NSEC
+"$SIGNER" -z -O full -u3 - -o "$zone" "$zonefile" > /dev/null
+awk '$4 == "NSEC3" || ( $4 == "RRSIG" && $5 == "NSEC3" ) { print }' "$zonefile".signed > NSEC3
+"$SIGNER" -z -O full -u3 AAAA -o "$zone" "$zonefile" > /dev/null
+awk '$4 == "NSEC3" || ( $4 == "RRSIG" && $5 == "NSEC3" ) { print }' "$zonefile".signed >> NSEC3
+"$SIGNER" -z -O full -u3 BBBB -o "$zone" "$zonefile" > /dev/null
+awk '$4 == "NSEC3" || ( $4 == "RRSIG" && $5 == "NSEC3" ) { print }' "$zonefile".signed >> NSEC3
+"$SIGNER" -z -O full -u3 CCCC -o "$zone" "$zonefile" > /dev/null
+awk '$4 == "NSEC3" || ( $4 == "RRSIG" && $5 == "NSEC3" ) { print }' "$zonefile".signed >> NSEC3
+"$SIGNER" -z -O full -u3 DDDD -o "$zone" "$zonefile" > /dev/null
+cat NSEC NSEC3 >> "$zonefile".signed
+
+#
+# A RSASHA256 zone.
+#
+zone=rsasha256.example.
+infile=rsasha256.example.db.in
+zonefile=rsasha256.example.db
+
+keyname=$("$KEYGEN" -q -a RSASHA256 -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -P -o "$zone" "$zonefile" > /dev/null
+
+#
+# A RSASHA512 zone.
+#
+zone=rsasha512.example.
+infile=rsasha512.example.db.in
+zonefile=rsasha512.example.db
+
+keyname=$("$KEYGEN" -q -a RSASHA512 -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -P -o "$zone" "$zonefile" > /dev/null
+
+#
+# A zone with the DNSKEY set only signed by the KSK
+#
+zone=kskonly.example.
+infile=kskonly.example.db.in
+zonefile=kskonly.example.db
+
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+cat "$infile" "$kskname.key" "$zskname.key" > "$zonefile"
+"$SIGNER" -x -o "$zone" "$zonefile" > /dev/null
+
+#
+# A zone with the expired signatures
+#
+zone=expired.example.
+infile=expired.example.db.in
+zonefile=expired.example.db
+
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+cat "$infile" "$kskname.key" "$zskname.key" > "$zonefile"
+"$SIGNER" -P -o "$zone" -s -1d -e +1h "$zonefile" > /dev/null
+rm -f "$kskname.*" "$zskname.*"
+
+#
+# A NSEC3 signed zone that will have a DNSKEY added to it via UPDATE.
+#
+zone=update-nsec3.example.
+infile=update-nsec3.example.db.in
+zonefile=update-nsec3.example.db
+
+kskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone")
+zskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+cat "$infile" "$kskname.key" "$zskname.key" > "$zonefile"
+"$SIGNER" -P -3 - -o "$zone" "$zonefile" > /dev/null
+
+#
+# A NSEC signed zone that will have auto-dnssec enabled and
+# extra keys not in the initial signed zone.
+#
+zone=auto-nsec.example.
+infile=auto-nsec.example.db.in
+zonefile=auto-nsec.example.db
+
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+cat "$infile" "$kskname.key" "$zskname.key" > "$zonefile"
+"$SIGNER" -P -o "$zone" "$zonefile" > /dev/null
+
+#
+# A NSEC3 signed zone that will have auto-dnssec enabled and
+# extra keys not in the initial signed zone.
+#
+zone=auto-nsec3.example.
+infile=auto-nsec3.example.db.in
+zonefile=auto-nsec3.example.db
+
+kskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone")
+zskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+kskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone")
+zskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+cat "$infile" "$kskname.key" "$zskname.key" > "$zonefile"
+"$SIGNER" -P -3 - -o "$zone" "$zonefile" > /dev/null
+
+#
+# Secure below cname test zone.
+#
+zone=secure.below-cname.example.
+infile=secure.below-cname.example.db.in
+zonefile=secure.below-cname.example.db
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+cat "$infile" "$keyname.key" > "$zonefile"
+"$SIGNER" -P -o "$zone" "$zonefile" > /dev/null
+
+#
+# Patched TTL test zone.
+#
+zone=ttlpatch.example.
+infile=ttlpatch.example.db.in
+zonefile=ttlpatch.example.db
+signedfile=ttlpatch.example.db.signed
+patchedfile=ttlpatch.example.db.patched
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -P -f $signedfile -o "$zone" "$zonefile" > /dev/null
+$CHECKZONE -D -s full "$zone" $signedfile 2> /dev/null | \
+ awk '{$2 = "3600"; print}' > $patchedfile
+
+#
+# Separate DNSSEC records.
+#
+zone=split-dnssec.example.
+infile=split-dnssec.example.db.in
+zonefile=split-dnssec.example.db
+signedfile=split-dnssec.example.db.signed
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+cat "$infile" "$keyname.key" > "$zonefile"
+echo "\$INCLUDE \"$signedfile\"" >> "$zonefile"
+: > "$signedfile"
+"$SIGNER" -P -D -o "$zone" "$zonefile" > /dev/null
+
+#
+# Separate DNSSEC records smart signing.
+#
+zone=split-smart.example.
+infile=split-smart.example.db.in
+zonefile=split-smart.example.db
+signedfile=split-smart.example.db.signed
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+cp "$infile" "$zonefile"
+# shellcheck disable=SC2016
+echo "\$INCLUDE \"$signedfile\"" >> "$zonefile"
+: > "$signedfile"
+"$SIGNER" -P -S -D -o "$zone" "$zonefile" > /dev/null
+
+#
+# Zone with signatures about to expire, but no private key to replace them
+#
+zone="expiring.example."
+infile="expiring.example.db.in"
+zonefile="expiring.example.db"
+signedfile="expiring.example.db.signed"
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+cp "$infile" "$zonefile"
+"$SIGNER" -S -e now+1mi -o "$zone" "$zonefile" > /dev/null
+mv -f "${zskname}.private" "${zskname}.private.moved"
+mv -f "${kskname}.private" "${kskname}.private.moved"
+
+#
+# A zone where the signer's name has been forced to uppercase.
+#
+zone="upper.example."
+infile="upper.example.db.in"
+zonefile="upper.example.db"
+lower="upper.example.db.lower"
+signedfile="upper.example.db.signed"
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+cp "$infile" "$zonefile"
+"$SIGNER" -P -S -o "$zone" -f $lower "$zonefile" > /dev/null
+$CHECKZONE -D upper.example $lower 2>/dev/null | \
+ sed '/RRSIG/s/ upper.example. / UPPER.EXAMPLE. /' > $signedfile
+
+#
+# Check that the signer's name is in lower case when zone name is in
+# upper case.
+#
+zone="LOWER.EXAMPLE."
+infile="lower.example.db.in"
+zonefile="lower.example.db"
+signedfile="lower.example.db.signed"
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+cp "$infile" "$zonefile"
+"$SIGNER" -P -S -o "$zone" "$zonefile" > /dev/null
+
+#
+# Zone with signatures about to expire, and dynamic, but configured
+# not to resign with 'auto-resign no;'
+#
+zone="nosign.example."
+infile="nosign.example.db.in"
+zonefile="nosign.example.db"
+signedfile="nosign.example.db.signed"
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+cp "$infile" "$zonefile"
+"$SIGNER" -S -e "now+1mi" -o "$zone" "$zonefile" > /dev/null
+# preserve a normalized copy of the NS RRSIG for comparison later
+$CHECKZONE -D nosign.example nosign.example.db.signed 2>/dev/null | \
+ awk '$4 == "RRSIG" && $5 == "NS" {$2 = ""; print}' | \
+ sed 's/[ ][ ]*/ /g'> ../nosign.before
+
+#
+# An inline signing zone
+#
+zone=inline.example.
+kskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone")
+zskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+
+#
+# publish a new key while deactivating another key at the same time.
+#
+zone=publish-inactive.example
+infile=publish-inactive.example.db.in
+zonefile=publish-inactive.example.db
+now=$(date -u +%Y%m%d%H%M%S)
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+kskname=$("$KEYGEN" -P "$now+90s" -A "$now+3600s" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+kskname=$("$KEYGEN" -I "$now+90s" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+cp "$infile" "$zonefile"
+"$SIGNER" -S -o "$zone" "$zonefile" > /dev/null
+
+#
+# A zone which will change its sig-validity-interval
+#
+zone=siginterval.example
+infile=siginterval.example.db.in
+zonefile=siginterval.example.db
+kskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone")
+zskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+cp "$infile" "$zonefile"
+
+#
+# A zone with a bad DS in the parent
+# (sourced from bogus.example.db.in)
+#
+zone=badds.example.
+infile=bogus.example.db.in
+zonefile=badds.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -P -o "$zone" "$zonefile" > /dev/null
+sed -e 's/bogus/badds/g' < dsset-bogus.example. > dsset-badds.example.
+
+#
+# A zone with future signatures.
+#
+zone=future.example
+infile=future.example.db.in
+zonefile=future.example.db
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+cat "$infile" "$kskname.key" "$zskname.key" > "$zonefile"
+"$SIGNER" -P -s +3600 -o "$zone" "$zonefile" > /dev/null
+cp -f "$kskname.key" trusted-future.key
+
+#
+# A zone with future signatures.
+#
+zone=managed-future.example
+infile=managed-future.example.db.in
+zonefile=managed-future.example.db
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+cat "$infile" "$kskname.key" "$zskname.key" > "$zonefile"
+"$SIGNER" -P -s +3600 -o "$zone" "$zonefile" > /dev/null
+
+#
+# A zone with a revoked key
+#
+zone=revkey.example.
+infile=generic.example.db.in
+zonefile=revkey.example.db
+
+ksk1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -3fk "$zone")
+ksk1=$("$REVOKE" "$ksk1")
+ksk2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -3fk "$zone")
+zsk1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -3 "$zone")
+
+cat "$infile" "${ksk1}.key" "${ksk2}.key" "${zsk1}.key" > "$zonefile"
+"$SIGNER" -P -o "$zone" "$zonefile" > /dev/null
+
+#
+# Check that NSEC3 are correctly signed and returned from below a DNAME
+#
+zone=dname-at-apex-nsec3.example
+infile=dname-at-apex-nsec3.example.db.in
+zonefile=dname-at-apex-nsec3.example.db
+
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -3fk "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -3 "$zone")
+cat "$infile" "${kskname}.key" "${zskname}.key" >"$zonefile"
+"$SIGNER" -P -3 - -o "$zone" "$zonefile" > /dev/null
+
+#
+# A NSEC zone with occuded data at the delegation
+#
+zone=occluded.example
+infile=occluded.example.db.in
+zonefile=occluded.example.db
+kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -fk "$zone")
+zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" "$zone")
+dnskeyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -fk "delegation.$zone")
+keyname=$("$KEYGEN" -q -a DH -b 1024 -n HOST -T KEY "delegation.$zone")
+$DSFROMKEY "$dnskeyname.key" > "dsset-delegation.${zone}."
+cat "$infile" "${kskname}.key" "${zskname}.key" "${keyname}.key" \
+ "${dnskeyname}.key" "dsset-delegation.${zone}." >"$zonefile"
+"$SIGNER" -P -o "$zone" "$zonefile" > /dev/null
diff --git a/bin/tests/system/dnssec/ns3/split-dnssec.example.db.in b/bin/tests/system/dnssec/ns3/split-dnssec.example.db.in
new file mode 100644
index 0000000..55b3877
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/split-dnssec.example.db.in
@@ -0,0 +1,38 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.wild A 10.0.0.6
+child NS ns2.example.
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17
diff --git a/bin/tests/system/dnssec/ns3/split-smart.example.db.in b/bin/tests/system/dnssec/ns3/split-smart.example.db.in
new file mode 100644
index 0000000..55b3877
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/split-smart.example.db.in
@@ -0,0 +1,38 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.wild A 10.0.0.6
+child NS ns2.example.
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17
diff --git a/bin/tests/system/dnssec/ns3/ttlpatch.example.db.in b/bin/tests/system/dnssec/ns3/ttlpatch.example.db.in
new file mode 100644
index 0000000..14971bd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/ttlpatch.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/unsupported-algorithm.key b/bin/tests/system/dnssec/ns3/unsupported-algorithm.key
new file mode 100644
index 0000000..cc8bb9a
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/unsupported-algorithm.key
@@ -0,0 +1 @@
+dnskey-unsupported-2.example. IN DNSKEY 257 3 255 BJ0eV4dQC0pihdFXiVdlXjPDkzbv4fC+opEvK0RaDU7LLwFXPAi6DOc6tm7vcSr5Tgdnpoal3S4WqHuVw6I1pzy5mPPIZ3OpLSY/QeOyGc2QRAZtOXxiGxERHRjyAk7emlgGscM0Vty2oJVYRgTPX0lTwKX/V2H+mjEgp7u3tyG3cj5XBUQ8J0KUoqkrn1ZKrizH27aWiDaBUvqxJUcotaDhnydkNtcHoQIedm2b4qbyTQsdRkddJiSWxpveEcj3AMdt2PjU6Q4rgSWOc5ylPnW/O+GqqCEAkalGSF7ud0Nl3FVVR9iGwV/73FHzpBLawfkcHaODFmKRjzGqok8giKCih2vdNsxlx7gdJWJIPYYx/ZqNGc2ewzuAnnleJpZdXFo8uL3HYk6Pl51sSkfVUmcn/SM+ ;{id = 38688 (ksk), size = 768b}
diff --git a/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in b/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in
new file mode 100644
index 0000000..a7792fd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
+nosoa NS ns.nosoa
+ns.nosoa A 10.53.0.7
+
+normalthenrrsig A 10.0.0.28
+rrsigonly A 10.0.0.29
diff --git a/bin/tests/system/dnssec/ns3/upper.example.db.in b/bin/tests/system/dnssec/ns3/upper.example.db.in
new file mode 100644
index 0000000..ec6603a
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/upper.example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2012042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS ns
+ns A 10.53.0.3
diff --git a/bin/tests/system/dnssec/ns4/managed-keys.bind.in b/bin/tests/system/dnssec/ns4/managed-keys.bind.in
new file mode 100644
index 0000000..570669d
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/managed-keys.bind.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 0 ; 0 seconds
+@ IN SOA . . (
+ 2 ; serial
+ 0 ; refresh (0 seconds)
+ 0 ; retry (0 seconds)
+ 0 ; expire (0 seconds)
+ 0 ; minimum (0 seconds)
+ )
+ KEYDATA 20221028094934 19700101000000 19700101000000 0 0 0 ; placeholder
diff --git a/bin/tests/system/dnssec/ns4/named1.conf.in b/bin/tests/system/dnssec/ns4/named1.conf.in
new file mode 100644
index 0000000..280217e
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/named1.conf.in
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+ dnssec-must-be-secure mustbesecure.example yes;
+ minimal-responses no;
+
+ nta-lifetime 12s;
+ nta-recheck 9s;
+
+ validate-except { corp; };
+
+ # Note: We only reference the bind.keys file here to confirm that it
+ # is *not* being used. It contains the real root key, and we're
+ # using a local toy root zone for the tests, so it wouldn't work.
+ # But since dnssec-validation is set to "yes" not "auto", that
+ # won't matter.
+ bindkeys-file "../../../../../bind.keys";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "corp" {
+ type static-stub;
+ server-addresses { 10.53.0.2; };
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns4/named2.conf.in b/bin/tests/system/dnssec/ns4/named2.conf.in
new file mode 100644
index 0000000..b01979b
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/named2.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+ minimal-responses no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/dnssec/ns4/named3.conf.in b/bin/tests/system/dnssec/ns4/named3.conf.in
new file mode 100644
index 0000000..3a64e9d
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/named3.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+ dnssec-accept-expired yes;
+ minimal-responses no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/dnssec/ns4/named4.conf.in b/bin/tests/system/dnssec/ns4/named4.conf.in
new file mode 100644
index 0000000..5d3bf3f
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/named4.conf.in
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key auth {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+include "trusted.conf";
+
+view rec {
+ match-recursive-only yes;
+ recursion yes;
+ dnssec-validation yes;
+ dnssec-accept-expired yes;
+ minimal-responses no;
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone secure.example {
+ type static-stub;
+ server-addresses { 10.53.0.4; };
+ };
+
+ zone insecure.secure.example {
+ type static-stub;
+ server-addresses { 10.53.0.4; };
+ };
+};
+
+view auth {
+ recursion no;
+ allow-recursion { none; };
+
+ zone secure.example {
+ type secondary;
+ primaries { 10.53.0.3; };
+ };
+
+ zone insecure.secure.example {
+ type secondary;
+ primaries { 10.53.0.2; };
+ };
+};
diff --git a/bin/tests/system/dnssec/ns4/named5.conf.in b/bin/tests/system/dnssec/ns4/named5.conf.in
new file mode 100644
index 0000000..88caaca
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/named5.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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; };
+ bindkeys-file "managed.conf";
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key auth {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
diff --git a/bin/tests/system/dnssec/ns5/named1.conf.in b/bin/tests/system/dnssec/ns5/named1.conf.in
new file mode 100644
index 0000000..ccb3de9
--- /dev/null
+++ b/bin/tests/system/dnssec/ns5/named1.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns5/named2.conf.in b/bin/tests/system/dnssec/ns5/named2.conf.in
new file mode 100644
index 0000000..6d0474b
--- /dev/null
+++ b/bin/tests/system/dnssec/ns5/named2.conf.in
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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; 127.0.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+};
+
+view root {
+ match-destinations { 127.0.0.1; };
+
+ zone "." {
+ type primary;
+ file "root.db.signed";
+ };
+};
+
+view other {
+include "revoked.conf";
+
+ zone "." {
+ type static-stub;
+ server-addresses { 127.0.0.1; };
+ };
+};
diff --git a/bin/tests/system/dnssec/ns5/sign.sh b/bin/tests/system/dnssec/ns5/sign.sh
new file mode 100644
index 0000000..df0b208
--- /dev/null
+++ b/bin/tests/system/dnssec/ns5/sign.sh
@@ -0,0 +1,39 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+echo_i "ns5/sign.sh"
+
+zone=.
+infile=../ns1/root.db.in
+zonefile=root.db.signed
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+
+# copy the KSK out first, then revoke it
+keyfile_to_initial_ds "$keyname" > revoked.conf
+
+"$SETTIME" -R now "${keyname}.key" > /dev/null
+
+# create a current set of keys, and sign the root zone
+"$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" $zone > /dev/null
+"$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK $zone > /dev/null
+"$SIGNER" -S -o "$zone" -f "$zonefile" "$infile" > /dev/null 2>&1
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone ".")
+
+keyfile_to_static_ds "$keyname" > trusted.conf
diff --git a/bin/tests/system/dnssec/ns6/named.args b/bin/tests/system/dnssec/ns6/named.args
new file mode 100644
index 0000000..4b96405
--- /dev/null
+++ b/bin/tests/system/dnssec/ns6/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 99 -D dnssec-ns6 -X named.lock -g -T maxcachesize=2097152 -T nonearest -T tat=1
diff --git a/bin/tests/system/dnssec/ns6/named.conf.in b/bin/tests/system/dnssec/ns6/named.conf.in
new file mode 100644
index 0000000..4bdc79c
--- /dev/null
+++ b/bin/tests/system/dnssec/ns6/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS6
+
+options {
+ 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.6; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ disable-algorithms . { @ALTERNATIVE_ALGORITHM@; };
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "optout-tld" {
+ type primary;
+ file "optout-tld.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns6/optout-tld.db.in b/bin/tests/system/dnssec/ns6/optout-tld.db.in
new file mode 100644
index 0000000..b2aa393
--- /dev/null
+++ b/bin/tests/system/dnssec/ns6/optout-tld.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+optout-tld. 60 IN SOA example. . 0 0 0 0 0
+optout-tld. 60 IN NS ns6.optout-tld.
+ns6.optout-tld. 60 IN A 10.53.0.6
+a 60 PTR example.
+b 60 PTR example.
+a.b.c.d 60 NS example.
+e 60 PTR example.
+f 60 PTR example.
+g 60 PTR example.
+h 60 PTR example.
diff --git a/bin/tests/system/dnssec/ns6/sign.sh b/bin/tests/system/dnssec/ns6/sign.sh
new file mode 100644
index 0000000..6102e52
--- /dev/null
+++ b/bin/tests/system/dnssec/ns6/sign.sh
@@ -0,0 +1,29 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+echo_i "ns6/sign.sh"
+
+zone=optout-tld
+infile=optout-tld.db.in
+zonefile=optout-tld.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+"$SIGNER" -z -3 - -A -o "$zone" "$zonefile" > /dev/null 2>&1
diff --git a/bin/tests/system/dnssec/ns7/named.conf.in b/bin/tests/system/dnssec/ns7/named.conf.in
new file mode 100644
index 0000000..55cbec9
--- /dev/null
+++ b/bin/tests/system/dnssec/ns7/named.conf.in
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+options {
+ 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.7; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+ minimal-responses yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "nsec3.example" {
+ type secondary;
+ primaries { 10.53.0.3; };
+ file "nsec3.example.bk";
+};
+
+zone "optout.example" {
+ type secondary;
+ primaries { 10.53.0.3; };
+ file "optout.example.bk";
+};
+
+zone "nsec3-unknown.example" {
+ type secondary;
+ primaries { 10.53.0.3; };
+ file "nsec3-unknown.example.bk";
+};
+
+zone "optout-unknown.example" {
+ type secondary;
+ primaries { 10.53.0.3; };
+ file "optout-unknown.example.bk";
+};
+
+zone "multiple.example" {
+ type secondary;
+ primaries { 10.53.0.3; };
+ file "multiple.example.bk";
+};
+
+zone "nosoa.secure.example" {
+ type primary;
+ file "nosoa.secure.example.db";
+};
+
+zone "split-rrsig" {
+ type primary;
+ file "split-rrsig.db.signed";
+ allow-update { any; };
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns7/named.nosoa b/bin/tests/system/dnssec/ns7/named.nosoa
new file mode 100644
index 0000000..caefbbb
--- /dev/null
+++ b/bin/tests/system/dnssec/ns7/named.nosoa
@@ -0,0 +1,12 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+Add -T nosoa.
diff --git a/bin/tests/system/dnssec/ns7/nosoa.secure.example.db b/bin/tests/system/dnssec/ns7/nosoa.secure.example.db
new file mode 100644
index 0000000..d3c9878
--- /dev/null
+++ b/bin/tests/system/dnssec/ns7/nosoa.secure.example.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2010062400 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ IN NS ns
+ns IN A 10.53.0.7
+a IN A 1.2.3.4
diff --git a/bin/tests/system/dnssec/ns7/sign.sh b/bin/tests/system/dnssec/ns7/sign.sh
new file mode 100644
index 0000000..551b217
--- /dev/null
+++ b/bin/tests/system/dnssec/ns7/sign.sh
@@ -0,0 +1,44 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+echo_i "ns7/sign.sh"
+
+zone=split-rrsig
+infile=split-rrsig.db.in
+zonefile=split-rrsig.db
+
+k1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+k2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$k1.key" "$k2.key" > "$zonefile"
+
+# The awk script below achieves two goals:
+#
+# - it puts one of the two RRSIG(SOA) records at the end of the zone file, so
+# that these two records (forming a single RRset) are not placed immediately
+# next to each other; the test then checks if RRSIG RRsets split this way are
+# correctly added to resigning heaps,
+#
+# - it places a copy of one of the RRSIG(SOA) records somewhere else than at the
+# zone apex; the test then checks whether such signatures are automatically
+# removed from the zone after it is loaded.
+"$SIGNER" -P -3 - -A -o "$zone" -O full -f "$zonefile.unsplit" -e now-3600 -s now-7200 "$zonefile" > /dev/null 2>&1
+awk 'BEGIN { r = ""; }
+ $4 == "RRSIG" && $5 == "SOA" && r == "" { r = $0; next; }
+ { print }
+ END { print r; print "not-at-zone-apex." r; }' "$zonefile.unsplit" > "$zonefile.signed"
diff --git a/bin/tests/system/dnssec/ns7/split-rrsig.db.in b/bin/tests/system/dnssec/ns7/split-rrsig.db.in
new file mode 100644
index 0000000..48c2f87
--- /dev/null
+++ b/bin/tests/system/dnssec/ns7/split-rrsig.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+split-rrsig. 3660 IN SOA . . (
+ 1 ; serial
+ 3600 ; refresh (1 hour)
+ 3600 ; retry (1 hour)
+ 3600 ; expire (1 hour)
+ 3600 ; minimum (1 hour)
+ )
+ 3660 NS ns.example.
+a.split-rrsig. 3660 IN A 192.0.2.2
+b.split-rrsig. 3660 IN A 192.0.2.2
diff --git a/bin/tests/system/dnssec/ns8/named.conf.in b/bin/tests/system/dnssec/ns8/named.conf.in
new file mode 100644
index 0000000..d0278ca
--- /dev/null
+++ b/bin/tests/system/dnssec/ns8/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS8
+
+options {
+ query-source address 10.53.0.8;
+ notify-source 10.53.0.8;
+ transfer-source 10.53.0.8;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.8; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ minimal-responses no;
+ disable-algorithms "disabled.managed." { @DISABLED_ALGORITHM@; };
+ disable-algorithms "disabled.trusted." { @DISABLED_ALGORITHM@; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "managed.conf";
+include "trusted.conf";
+
diff --git a/bin/tests/system/dnssec/ns9/named.conf.in b/bin/tests/system/dnssec/ns9/named.conf.in
new file mode 100644
index 0000000..06530a0
--- /dev/null
+++ b/bin/tests/system/dnssec/ns9/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS9
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ forward only;
+ forwarders { 10.53.0.4; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ntadiff.pl b/bin/tests/system/dnssec/ntadiff.pl
new file mode 100755
index 0000000..ca80eac
--- /dev/null
+++ b/bin/tests/system/dnssec/ntadiff.pl
@@ -0,0 +1,24 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+use Time::Piece;
+use Time::Seconds;
+
+exit 1 if (scalar(@ARGV) != 2);
+
+my $actual = Time::Piece->strptime($ARGV[0], '%d-%b-%Y %H:%M:%S.000 %z');
+my $expected = Time::Piece->strptime($ARGV[1], '%s') + ONE_WEEK;
+my $diff = abs($actual - $expected);
+
+print($diff . "\n");
diff --git a/bin/tests/system/dnssec/setup.sh b/bin/tests/system/dnssec/setup.sh
new file mode 100644
index 0000000..6aa0cd0
--- /dev/null
+++ b/bin/tests/system/dnssec/setup.sh
@@ -0,0 +1,52 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+
+copy_setports ns4/named1.conf.in ns4/named.conf
+copy_setports ns5/named1.conf.in ns5/named.conf
+
+copy_setports ns6/named.conf.in ns6/named.conf
+copy_setports ns7/named.conf.in ns7/named.conf
+copy_setports ns8/named.conf.in ns8/named.conf
+
+copy_setports ns9/named.conf.in ns9/named.conf
+
+(
+ cd ns1
+ $SHELL sign.sh
+ {
+ echo "a.bogus.example. A 10.0.0.22"
+ echo "b.bogus.example. A 10.0.0.23"
+ echo "c.bogus.example. A 10.0.0.23"
+ } >>../ns3/bogus.example.db.signed
+)
+
+(
+ cd ns3
+ cp -f siginterval1.conf siginterval.conf
+)
+
+(
+ cd ns5
+ $SHELL sign.sh
+)
diff --git a/bin/tests/system/dnssec/signer/example.db.in b/bin/tests/system/dnssec/signer/example.db.in
new file mode 100644
index 0000000..3ab6aa2
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/example.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+example. 60 IN SOA example. . 0 0 0 0 0
+example. 60 IN NS example.
+example. 60 IN A 1.2.3.4
+; out of zone record
+out-of-zone. 60 IN A 1.2.3.4
diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key
new file mode 100644
index 0000000..d4b8efb
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key
@@ -0,0 +1,5 @@
+; This is a key-signing key, keyid 15002, for example.com.
+; Created: 20210423012926 (Fri Apr 23 11:29:26 2021)
+; Publish: 20210423012926 (Fri Apr 23 11:29:26 2021)
+; Activate: 20210423012926 (Fri Apr 23 11:29:26 2021)
+example.com. IN DNSKEY 257 3 8 AwEAAdp+oCXl7vpKA3Mmyndx6/iA+wLrtxeMUiWL7uWJ9ZF24EdS8Dye 63p0lGlyvjvM9T5dTiyEpTAdutEBr79H0MlDqIBqpadrCdJRI2S4kC+0 nq5+Aj2CEyiAamPGujwWeXwtfLAvVPfBqs42PBr6wPQIJOByFYDaZBU3 enUEWgHYy/7OnJDrt0QlswKphR6SvYtyuixiUR8J/WouWXglUY5qlC7Z vVDxs9E4q7B1mfKCyoqcFMKPh9lzEBH+IfUZ543xXEYf2BEztKB1SZ2R QnpYedjATGDcgPis46uA2gHMfvDYJTQ5UqTBtveGb3Wsqc0oRXVPMEoY 3WnWhaKDzkk=
diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private
new file mode 100644
index 0000000..72b8e2e
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private
@@ -0,0 +1,13 @@
+Private-key-format: v1.3
+Algorithm: 8 (RSASHA256)
+Modulus: 2n6gJeXu+koDcybKd3Hr+ID7Auu3F4xSJYvu5Yn1kXbgR1LwPJ7renSUaXK+O8z1Pl1OLISlMB260QGvv0fQyUOogGqlp2sJ0lEjZLiQL7Sern4CPYITKIBqY8a6PBZ5fC18sC9U98GqzjY8GvrA9Agk4HIVgNpkFTd6dQRaAdjL/s6ckOu3RCWzAqmFHpK9i3K6LGJRHwn9ai5ZeCVRjmqULtm9UPGz0TirsHWZ8oLKipwUwo+H2XMQEf4h9RnnjfFcRh/YETO0oHVJnZFCelh52MBMYNyA+Kzjq4DaAcx+8NglNDlSpMG294ZvdaypzShFdU8wShjdadaFooPOSQ==
+PublicExponent: AQAB
+PrivateExponent: SD4X64/0DTONonRP+2Biej8DP7r6RcHyo1F6QtDzrg4VJ+AHaLPO/iUvsRHsTk99QwqMv3F4QMmDrHmXR3KSWQmS3Crm7M0aaTzErBfOLMfWs7EcQoQQm5KiGq1phFaWAnXzxTlRKb4SIK6T/wOr6sQKlV+DNqB++Pjn92rh67vLM8kZBUzWI14Vl9N0ib+xOOFH1oYFo7ynDgMfJhpnQSkuRfyQls3aD1eKQsNazRtZ7lFi2S0HR/V0AKYH2AQi7SdL5wH6hYba5cHfpKSw7PebI0lYkUJ4PAg3Xw7DPMkg8O0hkpLICpU8x7MPqQQ74eKDaEY+fjbL0KLL0Dy9UQ==
+Prime1: /IDRb7WzMY6wp14LqDORULoUnmiQOqkRjOQnCoEXT2KVpYwPmGMG+GR40hrMFgqqAZFVmi56VBoasWpYbSBEqM4aJv1JVimMPREk23v5i+TY93kxICO/ee9/v0hXgLmrKUkS1Kwu4a1PxLX5U/LAzXPR6zF+EHP9OKFjDRWHqN0=
+Prime2: 3YU9QdtsXofjNmlDETRwemKv45pa0oVNPmNvS1vtzIpQ3m/QSuhJxzyTgSP9x1XMiIsg63er3LOCtkRifXVE1IBrfIUgchp8YD5LsyesRl2ielE8Hw8PwSA1YjUVu90yRHcVfbZJ8lm2KyRKHgDWXz94t2Xnm/9M5XjUGuNW7l0=
+Exponent1: 7KIkpJYZyvW4ZAFk10sMgiUBMbs4f2D2i509YUC9ga4YJD7wVpVncN1nxS9L19RCopl7KbUo+yxDm8TX/dzhu3j7VVLFqbPiM1Cfw/mZUhszoii3ezFFPpbOl4rKRl66I0TSGvEKNoDfYrBPavby7Rf/wHRveifZRXspgpeMvRk=
+Exponent2: yvvtjuxW2CRiopg/+YL40lyd2cy2DpRRnKqW8BHzzGquAbWpwwopmOS8MSjewgqv2irK5pmJJTpku0nciiOsB6EJXVfLzGLSt4o96ZOf+/aPDNBla/xsLkaqRCxqlvPwvOX2DnS8O9PS5qNhOy7/QNYzcrJxUfPV7awTh/Pr040=
+Coefficient: PHxU1tqPKTpI/8nABvso0SRerc1m+RPWGRk7s/SVcADSBvEW7fUDcwiZeRfK9MdlwPvLiVozbYnRbgRQl8GuKSqAD1+Cnvn2yOQk81AgNKbuKPwF7UvKIdq/c/xnhj2bvZUVSavJ91ux/RlZNP50378Ks8bj5HJl1xzAMVHXB5o=
+Created: 20210423012926
+Publish: 20210423012926
+Activate: 20210423012926
diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key
new file mode 100644
index 0000000..990b837
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key
@@ -0,0 +1,5 @@
+; This is a zone-signing key, keyid 63613, for example.com.
+; Created: 20210423012810 (Fri Apr 23 11:28:10 2021)
+; Publish: 20210423012810 (Fri Apr 23 11:28:10 2021)
+; Activate: 20210423012810 (Fri Apr 23 11:28:10 2021)
+example.com. IN DNSKEY 256 3 8 AwEAAZzun7bYfjmGDwUEn4pyJG34vsiawRMW6pEdoNMH87ozxriOzgG6 /4zTjEv8JyYjGQz2k2vcoWWcD+86xD5IUqfa1pdXXUU8bdhG9DBtW/K1 mc4P6g8heU+0f++mq/L4TPlWVZUG8lVH4H8mD6r8PsVK7v/QR7wMeg9b JpCYyxon2A9rZ4zS0J9kX9bfciQVh6ODGVENctwEK5FNp5u0VonPEIx3 5Kj+IVn/mHpfbz4LaC02s7C6Kgvn3ToFFSJczwbOaexl/d+/ai8FLJi7 8UgiAq5/178bcVLItMeY6aD5eQGkRtr2c3JZ/JR4Nf+TQAWFBnl9NSDa RH4Qa55ZNqs=
diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private
new file mode 100644
index 0000000..1765d3f
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private
@@ -0,0 +1,13 @@
+Private-key-format: v1.3
+Algorithm: 8 (RSASHA256)
+Modulus: nO6ftth+OYYPBQSfinIkbfi+yJrBExbqkR2g0wfzujPGuI7OAbr/jNOMS/wnJiMZDPaTa9yhZZwP7zrEPkhSp9rWl1ddRTxt2Eb0MG1b8rWZzg/qDyF5T7R/76ar8vhM+VZVlQbyVUfgfyYPqvw+xUru/9BHvAx6D1smkJjLGifYD2tnjNLQn2Rf1t9yJBWHo4MZUQ1y3AQrkU2nm7RWic8QjHfkqP4hWf+Yel9vPgtoLTazsLoqC+fdOgUVIlzPBs5p7GX9379qLwUsmLvxSCICrn/XvxtxUsi0x5jpoPl5AaRG2vZzcln8lHg1/5NABYUGeX01INpEfhBrnlk2qw==
+PublicExponent: AQAB
+PrivateExponent: N4egcDzO/V/YdLgcFAsrpNY9/BH2e+DCA7NuMv4/WgX0LV4quyYGQzigDksdNzt4I8Qkiig53BCK+uXahwdkaAzhng/F6zfkzoDc6z3nKUzlLasn8U6w9Gk0VAKwGXuPETNheShKG68hWxyGssQrGfjX9SEoIPxxPHnOfZ/zTj95KAnVV5qPz90xVAb0+FUrLXAt72KuRwepOTlsETsMFDKe17uUCqCCdX98Ko0u14wrO6zGRQtNhUsfvNB/pY8fvbHD1GcCTbFSx4FxsUsZMrNtMsvMe3HN9ggC0Y9htbH9HV0hS0w9SKCUyoeOVwf/JZL4hlfoe8+jglsyJpAgoQ==
+Prime1: zeXvO3PT4iXv9GlGeebl39pF1sXs8tXY4B9VHUJGGSYlyOlyCEy4URQJIPfuL6VjFKCErSxUJSrGz0HyQuKr8l9qP/0MGxGRH7wxvUR7YTmai84yyQ4fFENRmn8bzxGwj0MVHIW7cKC59j7nWT24gseT21/NP5m8EnPsjz/K40M=
+Prime2: wx5vVFSydUfr8HtOHNS1kRrTjhnQOfjmj8SxGi72Hk+mgi9fBCTC5fRLifd80wGbgyFk1vZOXeStOC8L3IlnBGLX0O9MNip+vVX3hRzIRhLwHhL1ygN3xEd04qwVH0XJ8+4A0XCzh/FJgW59F62geN6gwedo7GmZAOSZUBAyRHk=
+Exponent1: IlkqeLuQ7Fgx2I87b5iiXp62Keco6TXdkT4I3/GvagCgKw0utc2+rd/uye4ycQZhKg7BM3aCrxScx/STaq8PykY6nmQjgdyDXkzx60YiYwzOCGakuD+/1YyJb4Gm7PthffTN780rgNV/UGIcDBoszrxmoSExR1vpMRbfruIQgas=
+Exponent2: or0Os/KUibc79W6Snv9WlLkgPAQRpViQzNaLtD/47R0Xzrs975HNsMgJ/P+bb86Ga1994MC8ahmh1BuBNCax8nmScWQ1V3QoEzjRYoe4DqIa/aposF4mFWJX/fry/wtRPo+CxSzPwJGh8j86PHaHQmjFAhVFcPE+OP1xVdK8alk=
+Coefficient: r5wPmPXUF5pVC0Y7La3jVkL4w/3wvq9LBz91tH9gA8OUNLpDDBuFZISiJdhOZ4JVw+qSSoHcEa+3Phd+BqxmXzwZDU1Fqta9mLDDGCqCWjVQOopeeJgrvkv9P0TIzEuoGmW50cQhyqHYCtuUxjOnHfiQSc53p7rfD4Vom1VQ3Ok=
+Created: 20210423012810
+Publish: 20210423012810
+Activate: 20210423012810
diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.key
new file mode 100644
index 0000000..47003a4
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.key
@@ -0,0 +1,5 @@
+; This is a zone-signing key, keyid 18240, for example.com.
+; Created: 20211221062121 (Tue Dec 21 17:21:21 2021)
+; Publish: 20211221062121 (Tue Dec 21 17:21:21 2021)
+; Activate: 20211221062121 (Tue Dec 21 17:21:21 2021)
+example.com. IN DNSKEY 256 3 10 AwEAAe5GunnuJFyzmKiGUknSQY3aPtR5UR8vNLLyMCJswffRzoYwY14/ 60ZTsqzh7N+lJV3KAOraocFSsTnmWIM7D7DPpqtaJMQw90ypBG0cnUP1 wKX9L/gdOH/ITlluBiZpCv9Aux3FRECHBO4Gx8Rse8ST2Vag3UuOPW+q HkLsWQt22K/hYuDhEtUWWx2dTIaXUVXNSNbk2zPL+lhC9PaRV+//1Fjo UX4qXCUuUN4TiqlkK2v4UkcIyld1n2R7qTQAkoN9amGFtPu8z5Zw7CxC San03yUSNuKub3fGys11gQRFuEHRX7FxKxvJjmcngG9qCh8AyfHZ8zYb VstTy1unFoM=
diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.private
new file mode 100644
index 0000000..f16b627
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.private
@@ -0,0 +1,13 @@
+Private-key-format: v1.3
+Algorithm: 10 (RSASHA512)
+Modulus: 7ka6ee4kXLOYqIZSSdJBjdo+1HlRHy80svIwImzB99HOhjBjXj/rRlOyrOHs36UlXcoA6tqhwVKxOeZYgzsPsM+mq1okxDD3TKkEbRydQ/XApf0v+B04f8hOWW4GJmkK/0C7HcVEQIcE7gbHxGx7xJPZVqDdS449b6oeQuxZC3bYr+Fi4OES1RZbHZ1MhpdRVc1I1uTbM8v6WEL09pFX7//UWOhRfipcJS5Q3hOKqWQra/hSRwjKV3WfZHupNACSg31qYYW0+7zPlnDsLEJJqfTfJRI24q5vd8bKzXWBBEW4QdFfsXErG8mOZyeAb2oKHwDJ8dnzNhtWy1PLW6cWgw==
+PublicExponent: AQAB
+PrivateExponent: U/ipDv9V4TWJvxpXNZzbbVpUehym8g54y/d97yPU17kgxzmWS0jLaWVluneEOuzAVmUyHZIfHzo9KuJ6nwTZar5DRm/mNR3siR+nZ6yF38VjtxubJB1oI+A7fFjB4hdywLHXP46dlv/+RMQu8pIorAZOubDHTDE8hXW2ZG9WkisJ5P7KoaL4KFHHHXi5vsXAMph4Zphd/zPxVL2tHD3l5c3QXRpQWfTNZNQcZ1f/4yVCuMRibg5LCvpia0ZwRrlygfZdAHUUd0VJDfRO45J5nlIJSAHQtjYtVTL+xNISWOHXovVlInkVyluACqfX94I7qPXTu41yg3SxrrtHE6RTwQ==
+Prime1: +/YsRxmUxgvHKUh4SxdjzqNDDEi8b2BtM5IpctjVG3oYsL6J9xJB3U5/lbrGEPgl/1ndBUSXMQ6zQ5WcDE1qBAdW8t0eyniyuiexcgQ9f04Ds7p7oUiSHGLRn8YqQOzmiASXoZmkzfJZ+42pGhT3RZ+aYKtWQGMHqXabwV3zZl0=
+Prime2: 8hhnKzPzExy6wv/MV0aYKo1g4azrRjug6743/ctTC7zjnMmDW7RMFTXmq5Tu3pFaIL4N4C4m1b7P3abfTrjm+DwHnrlRIvLWS3zJnvUEM22i4BwqqTLRiJpoT5Bfp4pVsdOPT7Iyx1q5UsJZ7Q4qMpg2TFpGiQyieRB5Xwpu4l8=
+Exponent1: ZFPx7Z3SD8pA0793pu75Xx7DY/DSl8bdtNtOhdyxfu9vRXGZnjg24diQFR76H2ewOa2exKo7Sd2ApDi+mmd4/4Gsrag+yoClKlsD3VKy6i42ayqmb+Jly8fNkMFnsdKjOSYa+s4jQZ5vFiuiWjBfBeo3nqabAahtNJ12B9lRQkE=
+Exponent2: tNz4TnVsFo4zFLVHsrghvECM7WxjBMBNc3FToT6CV1WRcjO1+A/Ve08eenc0kYBjpex2r1GrX6pC3uPpFoXav/8Q7kqiTArBf/nFIwUHU2iH8wf38xntIjHA1hgU7jTR2p0kBrUpbHfh1esuhYQ8kDnY7ufOpFqVEv70vcUsm98=
+Coefficient: 3acDCJ9jCnHAP1km7jRO388mOpiI8U6SMv0PBD8l2UoB4CYwujrFxy6PhgUa486bbm5xZEaOwhYZcbw/g1qyC6Qt5kYOb2fVWOob/lEQmyqbDvHMQWTJoIbqaDTKQN/szI4xVdb/xZ6QR4Bq7JgbJpUACgweS540Y7Lf8Dry8C0=
+Created: 20211221062121
+Publish: 20211221062121
+Activate: 20211221062121
diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.key
new file mode 100644
index 0000000..37bd259
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.key
@@ -0,0 +1,5 @@
+; This is a key-signing key, keyid 28633, for example.com.
+; Created: 20211221062130 (Tue Dec 21 17:21:30 2021)
+; Publish: 20211221062130 (Tue Dec 21 17:21:30 2021)
+; Activate: 20211221062130 (Tue Dec 21 17:21:30 2021)
+example.com. IN DNSKEY 257 3 10 AwEAAc4lt8fDsdCzMCLHxXm8Ok/dw6XDiqx06Rf47LTeLmo6b64xm1Fs 0zloNMrcZDgwS5IxjQ3Breqc5aEc+jehueqCXa/fJXMdIt1VpUG0H7GP 4B+1IVmEiziHfmOozktdkuAyLqcsNhsf+J1+bCoHJSffgz6KbjBks/jR 12uyUnZCDrKGE/KfiR0gpT3watqGqqChO0KXq2N2PsnYfyRDea5FMUjM oPgOOyAT8LIMsM8x4f+EbU6m9Zc3Esafek9iLCS9R1333Pm1EEh5ghQT BsZ7omc5aSvrKUaIneojU3RdofceZouCliIDXmqscfY0y6bivGcmCQI/ LM4XUh7GWlM=
diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.private
new file mode 100644
index 0000000..6d7f72e
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.private
@@ -0,0 +1,13 @@
+Private-key-format: v1.3
+Algorithm: 10 (RSASHA512)
+Modulus: ziW3x8Ox0LMwIsfFebw6T93DpcOKrHTpF/jstN4uajpvrjGbUWzTOWg0ytxkODBLkjGNDcGt6pzloRz6N6G56oJdr98lcx0i3VWlQbQfsY/gH7UhWYSLOId+Y6jOS12S4DIupyw2Gx/4nX5sKgclJ9+DPopuMGSz+NHXa7JSdkIOsoYT8p+JHSClPfBq2oaqoKE7QperY3Y+ydh/JEN5rkUxSMyg+A47IBPwsgywzzHh/4RtTqb1lzcSxp96T2IsJL1HXffc+bUQSHmCFBMGxnuiZzlpK+spRoid6iNTdF2h9x5mi4KWIgNeaqxx9jTLpuK8ZyYJAj8szhdSHsZaUw==
+PublicExponent: AQAB
+PrivateExponent: Wr3fl99cdjFqDuVA18UzJdTIOj9I24Da2eKIz1S9uaTfZB4R8FWm5K4qDuHUe6dGnKOTI2sN0ygdLD5FJhfabo/UDYZ8RZ+dqS/5/mH7UX2zekGQ3Iargcaiq9uycxpNfMKaJpwfdPEtzqXHlvhuMo8AhpcIyeSKFAzKdm2YPtUqIrum4RARHyfRLfLyWlkIotPdyiaKCVGQxiRbFsTcmIB2Bizmt7zRjlB+Hxf8MooXmaKUFRQtMCLnFGK0ecFI1CWAxmLSanvYVKQ0HxcFkFKzRiZAz1au7ZfMgYDZj0jF72WAGU3Edcmdc0QIQRTWjb/3wcBfwlr9s6lKoF3ngQ==
+Prime1: 1EIziKhz7dF41rb/hckdr2qeY8eM7tLrT5jIMPLISHCCuKm5IK2u7PY6m6NjMdhx1ilm7K2RGTt+TTFZaqDIEd8qpzRCxAGcfTVOmB9iHwmi9i9RoPSlY6o+iShft68ZnvPiGJWUF2huRYVK2F0cIWErwSqaBGsFd79mXmlkn98=
+Prime2: +KEdNtZj9JyCCR2xbLAw3tnAYxHvJ3skVMjxV3cyUupMWi12NWxGhHH1nnetXxDR2LBBuqIl4pE/4MeXe3sClMHTL3Z9XG+pzQAsHS7yvsfZERdyuWZYYy0ya/7XY2auvRVO6LxN7d47VWjYxAGfoCsbCEivgDxmt1dTZhAtRA0=
+Exponent1: d5TcZ69PsLoEtCLhDkRh/wO4PEqeMaaOf4d5sWn2QCly3Apyi+CN3l5SYoDIT7q7V4Z3v/uA9ZA49dBJqfLvBHKQGycsPjUSLtAreTSlGQtazguWl3F9BAtTs/4U/u0dKBoKVQNgLVfeWDhiFEdQo9WUyvzvTHHm4LHqQGJsGE0=
+Exponent2: EU2dK+DVygNOZXYEkAzfCdNbuUlZPIUsbR4i9bRc8zpNIAWD8YncioEn1+R6U2BnSk5R9LwuKMt1B568YyKXdmTa3rW/WbyHs7WsXEeVK0PbTn40RMTjp9tQZAWzVb6isJQYDsh0H/bUaEhItbNrOYlmczgjxqftehsAudysWc0=
+Coefficient: sl2u/8vttxpiTbspGV4SsaDmKUNdzQH7BgJ5rl3mXPp/aUpLw0Sr7FuARy8W8tq3yVNi9qCOnvGwVl6aQzZP7b8N04KiH8gewlAVdSfxG24yFKJIQNbWGKFZYZFYyjtLVlpK6NYF0f0I1KpAjn58XR0qIBvRFZYWBAkggU9C7ro=
+Created: 20211221062130
+Publish: 20211221062130
+Activate: 20211221062130
diff --git a/bin/tests/system/dnssec/signer/general/bogus-ksk.key b/bin/tests/system/dnssec/signer/general/bogus-ksk.key
new file mode 100644
index 0000000..e468574
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/bogus-ksk.key
@@ -0,0 +1,6 @@
+;
+; This is a bogus key. It will not have a .private file.
+;
+; This will be key id 23221
+;
+example.com. IN DNSKEY 257 3 10 AwEAAbcyptpM++pVjhpYQW2fVtyOw04IBSw4X0SYi/Ke4wVkmDNW2vBm AFkgiVVKmmNbb0IHDYQiIY7seXk0fjEwjzeY2bmeOAZxDdv2KT9VQpoY Matk2y4NTi6F/V04x0lL/CBvyifTeNbZKvY+S1eKFuWHeS5Ss8tiagz9 zdYWUe/msvmin+Hbs2tlLwXVl4hOmABCL9uK9H8R6GPL5VdEXYyFOh/v 71CNhRU5ufrARti69YYkfzH6NpWhlJWyJvDjqAdt2L3H8V71C2vcXbBu S5NscEYl+8JQfwUvOTN553I5IQrG+NQEusW36UM/Rkad8mMnUVM9Vzqk GH86GHKtLMc=
diff --git a/bin/tests/system/dnssec/signer/general/bogus-zsk.key b/bin/tests/system/dnssec/signer/general/bogus-zsk.key
new file mode 100644
index 0000000..aa45938
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/bogus-zsk.key
@@ -0,0 +1,6 @@
+;
+; This is a bogus key. It will not have a .private file.
+;
+; This will be key id 48930
+;
+example.com. IN DNSKEY 256 3 10 AwEAAa/0IcnbGutPVkrz04tw5ZIYx6rU+FprB2rlKS8cTK/wiBOqbOC6 QIDdegDpZG1fOdj04ZQGa3pIizqC2CnlIWfxpfR6W+qSLRBuQ8gmwTmS c/Jy/0vAGB3fv3oVIqKslLNqIXZb3CKNiA2kGcut3aUgfeOW970Jga6z PAGKqPpPZTelW1Qy9N5BO4cRTuYo4uvbZveJv1W/2n5RN+UaeqU0f+AE DP0+wqSWNUfZsi6HygLwk08x3eO8PzTBlqBlAMfvNAygrmXqccMREyyH KEc5dVJ1qOXfj8BAdJUPmunyJhIwC9PxzOW7mn1lW7mZO2D5U/Jaxw2k eX2KblmVk8s=
diff --git a/bin/tests/system/dnssec/signer/general/test1.zone b/bin/tests/system/dnssec/signer/general/test1.zone
new file mode 100644
index 0000000..98c9f02
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test1.zone
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This is a zone which has two DNSKEY records, both of which have
+; existing private key files available. They should be loaded automatically
+; and the zone correctly signed.
+;
+$TTL 3600
+example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+010+18240.key
+$include Kexample.com.+010+28633.key
diff --git a/bin/tests/system/dnssec/signer/general/test2.zone b/bin/tests/system/dnssec/signer/general/test2.zone
new file mode 100644
index 0000000..97c0d3d
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test2.zone
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This is a zone which has one non-KSK DNSKEY record for which the
+; private key file exists. It should be loaded automatically and the zone
+; correctly signed.
+;
+$TTL 3600
+example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+010+18240.key
diff --git a/bin/tests/system/dnssec/signer/general/test3.zone b/bin/tests/system/dnssec/signer/general/test3.zone
new file mode 100644
index 0000000..bf9bc66
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test3.zone
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This is a zone which has one KSK DNSKEY record for which the
+; private key file exists. It should be loaded automatically. As there
+; is no non-KSK DNSKEY the resulting zone should be rejected.
+;
+$TTL 3600
+example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+010+28633.key
diff --git a/bin/tests/system/dnssec/signer/general/test4.zone b/bin/tests/system/dnssec/signer/general/test4.zone
new file mode 100644
index 0000000..9f05de5
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test4.zone
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This is a zone which has three DNSKEY records, two (KSK + ZSK) of
+; which have existing private key files available. The third is a
+; pre-published ZSK.
+;
+$TTL 3600
+example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+010+18240.key
+$include Kexample.com.+010+28633.key
+$include bogus-zsk.key
diff --git a/bin/tests/system/dnssec/signer/general/test5.zone b/bin/tests/system/dnssec/signer/general/test5.zone
new file mode 100644
index 0000000..d61504f
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test5.zone
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This is a zone which has three DNSKEY records, two (KSK +ZSK) of which
+; have existing private key files available. The third is a KSK.
+;
+$TTL 3600
+example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+010+18240.key
+$include Kexample.com.+010+28633.key
+$include bogus-ksk.key
diff --git a/bin/tests/system/dnssec/signer/general/test6.zone b/bin/tests/system/dnssec/signer/general/test6.zone
new file mode 100644
index 0000000..fcfb1ec
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test6.zone
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This is a zone which has four DNSKEY records, two (KK + ZSK) of which
+; have existing private key files available. There are also a KSK and ZSK
+; for which there will be no signatures.
+;
+$TTL 3600
+example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+010+18240.key
+$include Kexample.com.+010+28633.key
+$include bogus-ksk.key
+$include bogus-zsk.key
diff --git a/bin/tests/system/dnssec/signer/general/test7.zone b/bin/tests/system/dnssec/signer/general/test7.zone
new file mode 100644
index 0000000..e52c535
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test7.zone
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This is a zone which has two DNSKEY records, none of which have
+; existing private key files available. The resulting zone should fail
+; the consistency tests.
+;
+$TTL 3600
+example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300
+$include bogus-ksk.key
+$include bogus-zsk.key
diff --git a/bin/tests/system/dnssec/signer/general/test8.zone b/bin/tests/system/dnssec/signer/general/test8.zone
new file mode 100644
index 0000000..893d32d
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test8.zone
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This is a zone which has two DNSKEY records, one of which,
+; the KSK, has a private key. The resulting zone should be rejected as
+; it has no ZSK signatures.
+;
+$TTL 3600
+example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+010+28633.key
+$include bogus-zsk.key
diff --git a/bin/tests/system/dnssec/signer/general/test9.zone b/bin/tests/system/dnssec/signer/general/test9.zone
new file mode 100644
index 0000000..14c47d0
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/general/test9.zone
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This is a zone which has two DNSKEY records, both of which have
+; existing private key files available. They should be loaded automatically
+; and the zone correctly signed.
+;
+$TTL 3600
+example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+008+63613.key
+$include Kexample.com.+008+15002.key
diff --git a/bin/tests/system/dnssec/signer/prepub.db.in b/bin/tests/system/dnssec/signer/prepub.db.in
new file mode 100644
index 0000000..946aac1
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/prepub.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+prepub. 60 IN SOA prepub. . 0 0 0 0 0
+prepub. 60 IN NS prepub.
+prepub. 60 IN A 1.2.3.4
+; out of zone record
+out-of-zone. 60 IN A 1.2.3.4
diff --git a/bin/tests/system/dnssec/signer/remove.db.in b/bin/tests/system/dnssec/signer/remove.db.in
new file mode 100644
index 0000000..5629a42
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/remove.db.in
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+remove. 60 IN SOA remove. . 0 0 0 0 0
+remove. 60 IN NS remove.
+remove. 60 IN A 1.2.3.4
+remove. 60 IN AAAA ::ffff:1.2.3.4
+remove. 60 IN MX 0 remove.
+$INCLUDE remove.db.signed
diff --git a/bin/tests/system/dnssec/signer/remove2.db.in b/bin/tests/system/dnssec/signer/remove2.db.in
new file mode 100644
index 0000000..b2962b9
--- /dev/null
+++ b/bin/tests/system/dnssec/signer/remove2.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+remove. 60 IN SOA remove. . 0 0 0 0 0
+remove. 60 IN NS remove.
+remove. 60 IN A 1.2.3.4
+$INCLUDE remove.db.signed
diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh
new file mode 100644
index 0000000..97bffb5
--- /dev/null
+++ b/bin/tests/system/dnssec/tests.sh
@@ -0,0 +1,4446 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+status=0
+n=1
+
+rm -f dig.out.*
+
+dig_with_opts() {
+ "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
+}
+
+dig_with_additionalopts() {
+ "$DIG" +noall +additional +dnssec -p "$PORT" "$@"
+}
+
+dig_with_answeropts() {
+ "$DIG" +noall +answer +dnssec -p "$PORT" "$@"
+}
+
+delv_with_opts() {
+ "$DELV" -a ns1/trusted.conf -p "$PORT" "$@"
+}
+
+rndccmd() {
+ "$RNDC" -c ../common/rndc.conf -p "$CONTROLPORT" -s "$@"
+}
+
+# TODO: Move loadkeys_on to conf.sh.common
+dnssec_loadkeys_on() {
+ nsidx=$1
+ zone=$2
+ nextpart ns${nsidx}/named.run > /dev/null
+ rndccmd 10.53.0.${nsidx} loadkeys ${zone} | sed "s/^/ns${nsidx} /" | cat_i
+ wait_for_log 20 "next key event" ns${nsidx}/named.run || return 1
+}
+
+# convert private-type records to readable form
+showprivate () {
+ echo "-- $* --"
+ dig_with_opts +nodnssec +short "@$2" -t type65534 "$1" | cut -f3 -d' ' |
+ while read -r record; do
+ # shellcheck disable=SC2016
+ $PERL -e 'my $rdata = pack("H*", @ARGV[0]);
+ die "invalid record" unless length($rdata) == 5;
+ my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata);
+ my $action = "signing";
+ $action = "removing" if $remove;
+ my $state = " (incomplete)";
+ $state = " (complete)" if $complete;
+ print ("$action: alg: $alg, key: $key$state\n");' "$record"
+ done
+}
+
+# check that signing records are marked as complete
+checkprivate () {
+ for i in 1 2 3 4 5 6 7 8 9 10; do
+ showprivate "$@" | grep -q incomplete || return 0
+ sleep 1
+ done
+ echo_d "$1 signing incomplete"
+ return 1
+}
+
+# check that a zone file is raw format, version 0
+israw0 () {
+ # shellcheck disable=SC2016
+ < "$1" $PERL -e 'binmode STDIN;
+ read(STDIN, $input, 8);
+ ($style, $version) = unpack("NN", $input);
+ exit 1 if ($style != 2 || $version != 0);' || return $?
+}
+
+# check that a zone file is raw format, version 1
+israw1 () {
+ # shellcheck disable=SC2016
+ < "$1" $PERL -e 'binmode STDIN;
+ read(STDIN, $input, 8);
+ ($style, $version) = unpack("NN", $input);
+ exit 1 if ($style != 2 || $version != 1);' || return $?
+}
+
+# strip NS and RRSIG NS from input
+stripns () {
+ awk '($4 == "NS") || ($4 == "RRSIG" && $5 == "NS") { next} { print }' "$1"
+}
+
+#
+# Ensure there is not multiple consecutive blank lines.
+# Ensure there is a blank line before "Start view" and
+# "Negative trust anchors:".
+# Ensure there is not a blank line before "Secure roots:".
+#
+check_secroots_layout () {
+ awk '$0 == "" { if (empty) exit(1); empty=1; next }
+ /Start view/ { if (!empty) exit(1) }
+ /Secure roots:/ { if (empty) exit(1) }
+ /Negative trust anchors:/ { if (!empty) exit(1) }
+ { empty=0 }' $1 || return $?
+}
+
+# Check that for a query against a validating resolver where the
+# authoritative zone is unsigned (insecure delegation), glue is returned
+# in the additional section
+echo_i "checking that additional glue is returned for unsigned delegation ($n)"
+ret=0
+$DIG +tcp +dnssec -p "$PORT" a.insecure.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+grep "ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ns\\.insecure\\.example\\..*A.10\\.53\\.0\\.3" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Check the example. domain
+
+echo_i "checking that zone transfer worked ($n)"
+for i in 1 2 3 4 5 6 7 8 9
+do
+ ret=0
+ dig_with_opts a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+ dig_with_opts a.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+ $PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns3.test$n > /dev/null || ret=1
+ [ "$ret" -eq 0 ] && break
+ sleep 1
+done
+digcomp dig.out.ns2.test$n dig.out.ns3.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# test AD bit:
+# - dig +adflag asks for authentication (ad in response)
+echo_i "checking AD bit asking for validation ($n)"
+ret=0
+dig_with_opts +noauth +noadd +nodnssec +adflag a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth +noadd +nodnssec +adflag a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# test AD bit:
+# - dig +noadflag
+echo_i "checking that AD is not set without +adflag or +dnssec ($n)"
+ret=0
+dig_with_opts +noauth +noadd +nodnssec +noadflag a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth +noadd +nodnssec +noadflag a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking for AD in authoritative answer ($n)"
+ret=0
+dig_with_opts a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking positive validation NSEC ($n)"
+ret=0
+dig_with_opts +noauth a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that 'example/DS' from the referral was used in previous validation ($n)"
+ret=0
+grep "query 'example/DS/IN' approved" ns1/named.run > /dev/null && ret=1
+grep "fetch: example/DS" ns4/named.run > /dev/null && ret=1
+grep "validating example/DS: starting" ns4/named.run > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking positive validation NSEC using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a a.example > delv.out$n || ret=1
+ grep "a.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
+ grep "a.example..*.RRSIG.A [0-9][0-9]* 2 300 .*" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+ ret=0
+ echo_i "checking positive validation NSEC using dns_client (trusted-keys) ($n)"
+ "$DELV" -a ns1/trusted.keys -p "$PORT" @10.53.0.4 a a.example > delv.out$n || ret=1
+ grep "a.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
+ grep "a.example..*.RRSIG.A [0-9][0-9]* 2 300 .*" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking positive validation NSEC3 ($n)"
+ret=0
+dig_with_opts +noauth a.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking positive validation NSEC3 using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a a.nsec3.example > delv.out$n || ret=1
+ grep "a.nsec3.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
+ grep "a.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking positive validation OPTOUT ($n)"
+ret=0
+dig_with_opts +noauth a.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+SP="[[:space:]]+"
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking positive validation OPTOUT using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a a.optout.example > delv.out$n || ret=1
+ grep -Eq "^a\\.optout\\.example\\.""$SP""[0-9]+""$SP""IN""$SP""A""$SP""10.0.0.1" delv.out$n || ret=1
+ grep -Eq "^a\\.optout\\.example\\.""$SP""[0-9]+""$SP""IN""$SP""RRSIG""$SP""A""$SP""$DEFAULT_ALGORITHM_NUMBER""$SP""3""$SP""300" delv.out$n || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking positive wildcard validation NSEC ($n)"
+ret=0
+dig_with_opts a.wild.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts a.wild.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+stripns dig.out.ns3.test$n > dig.out.ns3.stripped.test$n
+stripns dig.out.ns4.test$n > dig.out.ns4.stripped.test$n
+digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
+grep "\\*\\.wild\\.example\\..*RRSIG NSEC" dig.out.ns4.test$n > /dev/null || ret=1
+grep "\\*\\.wild\\.example\\..*NSEC z\\.example" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking positive wildcard validation NSEC using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a a.wild.example > delv.out$n || ret=1
+ grep "a.wild.example..*10.0.0.27" delv.out$n > /dev/null || ret=1
+ grep -E "a.wild.example..*RRSIG.A [0-9]+ 2 300.*" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking positive wildcard answer NSEC3 ($n)"
+ret=0
+dig_with_opts a.wild.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+grep "AUTHORITY: 4," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking positive wildcard answer NSEC3 ($n)"
+ret=0
+dig_with_opts a.wild.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+grep "AUTHORITY: 4," dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking positive wildcard validation NSEC3 ($n)"
+ret=0
+dig_with_opts a.wild.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts a.wild.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+stripns dig.out.ns3.test$n > dig.out.ns3.stripped.test$n
+stripns dig.out.ns4.test$n > dig.out.ns4.stripped.test$n
+digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking positive wildcard validation NSEC3 using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a a.wild.nsec3.example > delv.out$n || ret=1
+ grep -E "a.wild.nsec3.example..*10.0.0.6" delv.out$n > /dev/null || ret=1
+ grep -E "a.wild.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking positive wildcard validation OPTOUT ($n)"
+ret=0
+dig_with_opts a.wild.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts a.wild.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+stripns dig.out.ns3.test$n > dig.out.ns3.stripped.test$n
+stripns dig.out.ns4.test$n > dig.out.ns4.stripped.test$n
+digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking positive wildcard validation OPTOUT using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a a.wild.optout.example > delv.out$n || ret=1
+ grep "a.wild.optout.example..*10.0.0.6" delv.out$n > /dev/null || ret=1
+ grep "a.wild.optout.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking negative validation NXDOMAIN NSEC ($n)"
+ret=0
+dig_with_opts +noauth q.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth q.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking negative validation NXDOMAIN NSEC using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a q.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking negative validation NXDOMAIN NSEC3 ($n)"
+ret=0
+dig_with_opts +noauth q.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth q.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking negative validation NXDOMAIN NSEC3 using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a q.nsec3.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking negative validation NXDOMAIN OPTOUT ($n)"
+ret=0
+dig_with_opts +noauth q.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth q.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking negative validation NXDOMAIN OPTOUT using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a q.optout.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking negative validation NODATA NSEC ($n)"
+ret=0
+dig_with_opts +noauth a.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth a.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)"
+ delv_with_opts @10.53.0.4 txt a.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking negative validation NODATA NSEC3 ($n)"
+ret=0
+dig_with_opts +noauth a.nsec3.example. \
+ @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.nsec3.example. \
+ @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking negative validation NODATA NSEC3 using dns_client ($n)"
+ delv_with_opts @10.53.0.4 txt a.nsec3.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking negative validation NODATA OPTOUT ($n)"
+ret=0
+dig_with_opts +noauth a.optout.example. \
+ @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.optout.example. \
+ @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)"
+ delv_with_opts @10.53.0.4 txt a.optout.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking negative wildcard validation NSEC ($n)"
+ret=0
+dig_with_opts b.wild.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+dig_with_opts b.wild.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking negative wildcard validation NSEC using dns_client ($n)"
+ delv_with_opts @10.53.0.4 txt b.wild.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking negative wildcard validation NSEC3 ($n)"
+ret=0
+dig_with_opts b.wild.nsec3.example. @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+dig_with_opts b.wild.nsec3.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking negative wildcard validation NSEC3 using dns_client ($n)"
+ delv_with_opts @10.53.0.4 txt b.wild.nsec3.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking negative wildcard validation OPTOUT ($n)"
+ret=0
+dig_with_opts b.wild.optout.example. \
+ @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+dig_with_opts b.wild.optout.example. \
+ @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking negative wildcard validation OPTOUT using dns_client ($n)"
+ delv_with_opts @10.53.0.4 txt b.optout.nsec3.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+# Check the insecure.example domain
+
+echo_i "checking 1-server insecurity proof NSEC ($n)"
+ret=0
+dig_with_opts +noauth a.insecure.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.insecure.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking 1-server insecurity proof NSEC using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a a.insecure.example > delv.out$n || ret=1
+ grep "a.insecure.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking 1-server insecurity proof NSEC3 ($n)"
+ret=0
+dig_with_opts +noauth a.insecure.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.insecure.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking 1-server insecurity proof NSEC3 using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a a.insecure.nsec3.example > delv.out$n || ret=1
+ grep "a.insecure.nsec3.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking 1-server insecurity proof OPTOUT ($n)"
+ret=0
+dig_with_opts +noauth a.insecure.optout.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.insecure.optout.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking 1-server insecurity proof OPTOUT using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a a.insecure.optout.example > delv.out$n || ret=1
+ grep "a.insecure.optout.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking 1-server negative insecurity proof NSEC ($n)"
+ret=0
+dig_with_opts q.insecure.example. a @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+dig_with_opts q.insecure.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking 1-server negative insecurity proof NSEC using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a q.insecure.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking 1-server negative insecurity proof NSEC3 ($n)"
+ret=0
+dig_with_opts q.insecure.nsec3.example. a @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+dig_with_opts q.insecure.nsec3.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking 1-server negative insecurity proof NSEC3 using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a q.insecure.nsec3.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking 1-server negative insecurity proof OPTOUT ($n)"
+ret=0
+dig_with_opts q.insecure.optout.example. a @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+dig_with_opts q.insecure.optout.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking 1-server negative insecurity proof OPTOUT using dns_client ($n)"
+ delv_with_opts @10.53.0.4 a q.insecure.optout.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking 1-server negative insecurity proof with SOA hack NSEC ($n)"
+ret=0
+dig_with_opts r.insecure.example. soa @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+dig_with_opts r.insecure.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "0 IN SOA" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking 1-server negative insecurity proof with SOA hack NSEC3 ($n)"
+ret=0
+dig_with_opts r.insecure.nsec3.example. soa @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+dig_with_opts r.insecure.nsec3.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "0 IN SOA" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking 1-server negative insecurity proof with SOA hack OPTOUT ($n)"
+ret=0
+dig_with_opts r.insecure.optout.example. soa @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+dig_with_opts r.insecure.optout.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "0 IN SOA" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Check the secure.example domain
+
+echo_i "checking multi-stage positive validation NSEC/NSEC ($n)"
+ret=0
+dig_with_opts +noauth a.secure.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.secure.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking multi-stage positive validation NSEC/NSEC3 ($n)"
+ret=0
+dig_with_opts +noauth a.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking multi-stage positive validation NSEC/OPTOUT ($n)"
+ret=0
+dig_with_opts +noauth a.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking multi-stage positive validation NSEC3/NSEC ($n)"
+ret=0
+dig_with_opts +noauth a.secure.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.secure.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking multi-stage positive validation NSEC3/NSEC3 ($n)"
+ret=0
+dig_with_opts +noauth a.nsec3.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.nsec3.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking multi-stage positive validation NSEC3/OPTOUT ($n)"
+ret=0
+dig_with_opts +noauth a.optout.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.optout.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking multi-stage positive validation OPTOUT/NSEC ($n)"
+ret=0
+dig_with_opts +noauth a.secure.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.secure.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking multi-stage positive validation OPTOUT/NSEC3 ($n)"
+ret=0
+dig_with_opts +noauth a.nsec3.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.nsec3.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking multi-stage positive validation OPTOUT/OPTOUT ($n)"
+ret=0
+dig_with_opts +noauth a.optout.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.optout.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking empty NODATA OPTOUT ($n)"
+ret=0
+dig_with_opts +noauth empty.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth empty.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+#grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Check the bogus domain
+
+echo_i "checking failed validation ($n)"
+ret=0
+dig_with_opts a.bogus.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking failed validation using dns_client ($n)"
+ delv_with_opts +cd @10.53.0.4 a a.bogus.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: RRSIG failed to verify" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+# Try validating with a bad trusted key.
+# This should fail.
+
+echo_i "checking that validation fails with a misconfigured trusted key ($n)"
+ret=0
+dig_with_opts example. soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that negative validation fails with a misconfigured trusted key ($n)"
+ret=0
+dig_with_opts example. ptr @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that insecurity proofs fail with a misconfigured trusted key ($n)"
+ret=0
+dig_with_opts a.insecure.example. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that validation fails when key record is missing ($n)"
+ret=0
+dig_with_opts a.b.keyless.example. a @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking that validation fails when key record is missing using dns_client ($n)"
+ delv_with_opts +cd @10.53.0.4 a a.b.keyless.example > delv.out$n 2>&1 || ret=1
+ grep "resolution failed: insecurity proof failed" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "checking that validation succeeds when a revoked key is encountered ($n)"
+ret=0
+dig_with_opts revkey.example soa @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags: .* ad" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+if [ -x "${DELV}" ] ; then
+ ret=0
+ echo_i "checking that validation succeeds when a revoked key is encountered using dns_client ($n)"
+ delv_with_opts +cd @10.53.0.4 soa revkey.example > delv.out$n 2>&1 || ret=1
+ grep "fully validated" delv.out$n > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+echo_i "Checking that a bad CNAME signature is caught after a +CD query ($n)"
+ret=0
+#prime
+dig_with_opts +cd bad-cname.example. @10.53.0.4 > dig.out.ns4.prime$n || ret=1
+#check: requery with +CD. pending data should be returned even if it's bogus
+expect="a.example.
+10.0.0.1"
+ans=$(dig_with_opts +cd +nodnssec +short bad-cname.example. @10.53.0.4) || ret=1
+test "$ans" = "$expect" || ret=1
+test "$ret" -eq 0 || echo_i "failed, got '$ans', expected '$expect'"
+#check: requery without +CD. bogus cached data should be rejected.
+dig_with_opts +nodnssec bad-cname.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "Checking that a bad DNAME signature is caught after a +CD query ($n)"
+ret=0
+#prime
+dig_with_opts +cd a.bad-dname.example. @10.53.0.4 > dig.out.ns4.prime$n || ret=1
+#check: requery with +CD. pending data should be returned even if it's bogus
+expect="example.
+a.example.
+10.0.0.1"
+ans=$(dig_with_opts +cd +nodnssec +short a.bad-dname.example. @10.53.0.4) || ret=1
+test "$ans" = "$expect" || ret=1
+test "$ret" -eq 0 || echo_i "failed, got '$ans', expected '$expect'"
+#check: requery without +CD. bogus cached data should be rejected.
+dig_with_opts +nodnssec a.bad-dname.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Check the insecure.secure.example domain (insecurity proof)
+
+echo_i "checking 2-server insecurity proof ($n)"
+ret=0
+dig_with_opts +noauth a.insecure.secure.example. @10.53.0.2 a \
+ > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth a.insecure.secure.example. @10.53.0.4 a \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Check a negative response in insecure.secure.example
+
+echo_i "checking 2-server insecurity proof with a negative answer ($n)"
+ret=0
+dig_with_opts q.insecure.secure.example. @10.53.0.2 a > dig.out.ns2.test$n \
+ || ret=1
+dig_with_opts q.insecure.secure.example. @10.53.0.4 a > dig.out.ns4.test$n \
+ || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking 2-server insecurity proof with a negative answer and SOA hack ($n)"
+ret=0
+dig_with_opts r.insecure.secure.example. @10.53.0.2 soa > dig.out.ns2.test$n \
+ || ret=1
+dig_with_opts r.insecure.secure.example. @10.53.0.4 soa > dig.out.ns4.test$n \
+ || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Check that the query for a security root is successful and has ad set
+
+echo_i "checking security root query ($n)"
+ret=0
+dig_with_opts . @10.53.0.4 key > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Check that the setting the cd bit works
+
+echo_i "checking cd bit on a positive answer ($n)"
+ret=0
+dig_with_opts +noauth example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+dig_with_opts +noauth +cdflag example. soa @10.53.0.5 \
+ > dig.out.ns5.test$n || ret=1
+digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking cd bit on a negative answer ($n)"
+ret=0
+dig_with_opts q.example. soa @10.53.0.4 > dig.out.ns4.test$n || ret=1
+dig_with_opts +cdflag q.example. soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
+digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking insecurity proof works using negative cache ($n)"
+ret=0
+rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
+dig_with_opts +cd @10.53.0.4 insecure.example. ds > dig.out.ns4.test$n.1 || ret=1
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
+do
+ dig_with_opts @10.53.0.4 nonexistent.insecure.example. > dig.out.ns4.test$n.2 || ret=1
+ if grep "status: NXDOMAIN" dig.out.ns4.test$n.2 >/dev/null; then
+ break
+ fi
+ sleep 1
+done
+grep "status: NXDOMAIN" dig.out.ns4.test$n.2 >/dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking positive validation RSASHA256 NSEC ($n)"
+ret=0
+dig_with_opts +noauth a.rsasha256.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.rsasha256.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking positive validation RSASHA512 NSEC ($n)"
+ret=0
+dig_with_opts +noauth a.rsasha512.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.rsasha512.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking positive validation with KSK-only DNSKEY signature ($n)"
+ret=0
+dig_with_opts +noauth a.kskonly.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.kskonly.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking cd bit on a query that should fail ($n)"
+ret=0
+dig_with_opts a.bogus.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+dig_with_opts +cdflag a.bogus.example. soa @10.53.0.5 \
+ > dig.out.ns5.test$n || ret=1
+digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking cd bit on an insecurity proof ($n)"
+ret=0
+dig_with_opts +noauth a.insecure.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+dig_with_opts +noauth +cdflag a.insecure.example. soa @10.53.0.5 \
+ > dig.out.ns5.test$n || ret=1
+digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - these are looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking cd bit on a negative insecurity proof ($n)"
+ret=0
+dig_with_opts q.insecure.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+dig_with_opts +cdflag q.insecure.example. a @10.53.0.5 \
+ > dig.out.ns5.test$n || ret=1
+digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - these are looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that validation of an ANY query works ($n)"
+ret=0
+dig_with_opts +noauth foo.example. any @10.53.0.2 > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth foo.example. any @10.53.0.4 > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# 2 records in the zone, 1 NXT, 3 SIGs
+grep "ANSWER: 6" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that validation of a query returning a CNAME works ($n)"
+ret=0
+dig_with_opts +noauth cname1.example. txt @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth cname1.example. txt @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# the CNAME & its sig, the TXT and its SIG
+grep "ANSWER: 4" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that validation of a query returning a DNAME works ($n)"
+ret=0
+dig_with_opts +noauth foo.dname1.example. txt @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth foo.dname1.example. txt @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# The DNAME & its sig, the TXT and its SIG, and the synthesized CNAME.
+# It would be nice to test that the CNAME is being synthesized by the
+# recursive server and not cached, but I don't know how.
+grep "ANSWER: 5" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that validation of an ANY query returning a CNAME works ($n)"
+ret=0
+dig_with_opts +noauth cname2.example. any @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth cname2.example. any @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# The CNAME, NXT, and their SIGs
+grep "ANSWER: 4" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that validation of an ANY query returning a DNAME works ($n)"
+ret=0
+dig_with_opts +noauth foo.dname2.example. any @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth foo.dname2.example. any @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that lookups succeed after disabling an algorithm ($n)"
+ret=0
+dig_with_opts +noauth example. SOA @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth example. SOA @10.53.0.6 \
+ > dig.out.ns6.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns6.test$n || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns6.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking a non-cachable NODATA works ($n)"
+ret=0
+dig_with_opts +noauth a.nosoa.secure.example. txt @10.53.0.7 \
+ > dig.out.ns7.test$n || ret=1
+grep "AUTHORITY: 0" dig.out.ns7.test$n > /dev/null || ret=1
+dig_with_opts +noauth a.nosoa.secure.example. txt @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking a non-cachable NXDOMAIN works ($n)"
+ret=0
+dig_with_opts +noauth b.nosoa.secure.example. txt @10.53.0.7 \
+ > dig.out.ns7.test$n || ret=1
+grep "AUTHORITY: 0" dig.out.ns7.test$n > /dev/null || ret=1
+dig_with_opts +noauth b.nosoa.secure.example. txt @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that we can load a rfc2535 signed zone ($n)"
+ret=0
+dig_with_opts rfc2535.example. SOA @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that we can transfer a rfc2535 signed zone ($n)"
+ret=0
+dig_with_opts rfc2535.example. SOA @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "basic dnssec-signzone checks:"
+echo_ic "two DNSKEYs ($n)"
+ret=0
+(
+cd signer/general || exit 1
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test1.zone > signer.out.$n
+test -f signed.zone
+) || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_ic "one non-KSK DNSKEY ($n)"
+ret=0
+(
+cd signer/general || exit 0
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test2.zone > signer.out.$n
+test -f signed.zone
+) && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_ic "one KSK DNSKEY ($n)"
+ret=0
+(
+cd signer/general || exit 0
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test3.zone > signer.out.$n
+test -f signed.zone
+) && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_ic "three DNSKEY ($n)"
+ret=0
+(
+cd signer/general || exit 1
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test4.zone > signer.out.$n
+test -f signed.zone
+) || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_ic "three DNSKEY, one private key missing ($n)"
+ret=0
+(
+cd signer/general || exit 1
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test5.zone > signer.out.$n
+test -f signed.zone
+) || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_ic "four DNSKEY ($n)"
+ret=0
+(
+cd signer/general || exit 1
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test6.zone > signer.out.$n
+test -f signed.zone
+) || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_ic "two DNSKEY, both private keys missing ($n)"
+ret=0
+(
+cd signer/general || exit 0
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test7.zone > signer.out.$n
+test -f signed.zone
+) && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_ic "two DNSKEY, one private key missing ($n)"
+ret=0
+(
+cd signer/general || exit 0
+rm -f signed.zone
+$SIGNER -f signed.zone -o example.com. test8.zone > signer.out.$n
+test -f signed.zone
+) && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_ic "check that dnssec-signzone rejects excessive NSEC3 iterations ($n)"
+ret=0
+(
+cd signer/general || exit 0
+rm -f signed.zone
+$SIGNER -f signed.zone -3 - -H 151 -o example.com. test9.zone > signer.out.$n
+test -f signed.zone
+) && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_ic "check that dnssec-signzone accepts maximum NSEC3 iterations ($n)"
+ret=0
+(
+cd signer/general || exit 1
+rm -f signed.zone
+$SIGNER -f signed.zone -3 - -H 150 -o example.com. test9.zone > signer.out.$n
+test -f signed.zone
+) || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+get_default_algorithm_key_ids_from_sigs() {
+ zone=$1
+
+ awk -v alg=$DEFAULT_ALGORITHM_NUMBER '
+ NF < 8 { next }
+ $(NF-5) != "RRSIG" { next }
+ $(NF-3) != alg { next }
+ $NF != "(" { next }
+ {
+ getline;
+ print $3;
+ }
+ ' signer/$zone.db.signed | sort -u
+}
+
+# Test dnssec-signzone ZSK prepublish smooth rollover.
+echo_i "check dnssec-signzone doesn't sign with prepublished zsk ($n)"
+ret=0
+zone=prepub
+# Generate keys.
+ksk=$("$KEYGEN" -K signer -f KSK -q -a $DEFAULT_ALGORITHM -n zone "$zone")
+zsk1=$("$KEYGEN" -K signer -q -a $DEFAULT_ALGORITHM -n zone "$zone")
+zsk2=$("$KEYGEN" -K signer -q -a $DEFAULT_ALGORITHM -n zone "$zone")
+zskid1=$(keyfile_to_key_id "$zsk1")
+zskid2=$(keyfile_to_key_id "$zsk2")
+(
+cd signer || exit 1
+# Set times such that the current set of keys are introduced 60 days ago and
+# start signing now. The successor key is prepublished now and will be active
+# next day.
+$SETTIME -P now-60d -A now $ksk > /dev/null
+$SETTIME -P now-60d -A now -I now+1d -D now+60d $zsk1 > /dev/null
+$SETTIME -S $zsk1 -i 1h $zsk2.key > /dev/null
+$SETTIME -P now -A now+1d $zsk2.key > /dev/null
+# Sign the zone with initial keys and prepublish successor. The zone signatures
+# are valid for 30 days and the DNSKEY signature is valid for 60 days.
+cp -f $zone.db.in $zone.db
+$SIGNER -SDx -e +2592000 -X +5184000 -o $zone $zone.db > /dev/null
+echo "\$INCLUDE \"$zone.db.signed\"" >> $zone.db
+)
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid1$" > /dev/null || ret=1
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid2$" > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed: missing signatures from key $zskid1"
+status=$((status+ret))
+
+echo_i "check dnssec-signzone retains signatures of predecessor zsk ($n)"
+ret=0
+zone=prepub
+(
+cd signer || exit 1
+# Roll the ZSK. The predecessor is inactive from now on and the successor is
+# activated. The zone signatures are valid for 30 days and the DNSKEY
+# signature is valid for 60 days. Because of the predecessor/successor
+# relationship, the signatures of the predecessor are retained and no new
+# signatures with the successor should be generated.
+$SETTIME -A now-30d -I now -D now+30d $zsk1 > /dev/null
+$SETTIME -A now $zsk2 > /dev/null
+$SIGNER -SDx -e +2592000 -X +5184000 -o $zone $zone.db > /dev/null
+)
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid1$" > /dev/null || ret=1
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid2$" > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check dnssec-signzone swaps zone signatures after interval ($n)"
+ret=0
+zone=prepub
+(
+cd signer || exit 1
+# After some time the signatures should be replaced. When signing, set the
+# interval to 30 days plus one second, meaning all predecessor signatures
+# are within the refresh interval and should be replaced with successor
+# signatures.
+$SETTIME -A now-50d -I now-20d -D now+10d $zsk1 > /dev/null
+$SETTIME -A now-20d $zsk2 > /dev/null
+$SIGNER -SDx -e +2592000 -X +5184000 -i 2592001 -o $zone $zone.db > /dev/null
+)
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid1$" > /dev/null && ret=1
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid2$" > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that a key using an unsupported algorithm cannot be generated ($n)"
+ret=0
+zone=example
+# If dnssec-keygen fails, the test script will exit immediately. Prevent that
+# from happening, and also trigger a test failure if dnssec-keygen unexpectedly
+# succeeds, by using "&& ret=1".
+$KEYGEN -a 255 $zone > dnssectools.out.test$n 2>&1 && ret=1
+grep -q "unsupported algorithm: 255" dnssectools.out.test$n || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that a DS record cannot be generated for a key using an unsupported algorithm ($n)"
+ret=0
+zone=example
+# Fake an unsupported algorithm key
+unsupportedkey=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+awk '$3 == "DNSKEY" { $6 = 255 } { print }' ${unsupportedkey}.key > ${unsupportedkey}.tmp
+mv ${unsupportedkey}.tmp ${unsupportedkey}.key
+# If dnssec-dsfromkey fails, the test script will exit immediately. Prevent
+# that from happening, and also trigger a test failure if dnssec-dsfromkey
+# unexpectedly succeeds, by using "&& ret=1".
+$DSFROMKEY ${unsupportedkey} > dnssectools.out.test$n 2>&1 && ret=1
+grep -q "algorithm is unsupported" dnssectools.out.test$n || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that a zone cannot be signed with a key using an unsupported algorithm ($n)"
+ret=0
+ret=0
+cat signer/example.db.in "${unsupportedkey}.key" > signer/example.db
+# If dnssec-signzone fails, the test script will exit immediately. Prevent that
+# from happening, and also trigger a test failure if dnssec-signzone
+# unexpectedly succeeds, by using "&& ret=1".
+$SIGNER -o example signer/example.db ${unsupportedkey} > dnssectools.out.test$n 2>&1 && ret=1
+grep -q "algorithm is unsupported" dnssectools.out.test$n || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that we can sign a zone with out-of-zone records ($n)"
+ret=0
+zone=example
+key1=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone)
+key2=$($KEYGEN -K signer -q -f KSK -a $DEFAULT_ALGORITHM -n zone $zone)
+(
+cd signer || exit 1
+cat example.db.in "$key1.key" "$key2.key" > example.db
+$SIGNER -o example -f example.db example.db > /dev/null
+) || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that we can sign a zone (NSEC3) with out-of-zone records ($n)"
+ret=0
+zone=example
+key1=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone)
+key2=$($KEYGEN -K signer -q -f KSK -a $DEFAULT_ALGORITHM -n zone $zone)
+(
+cd signer || exit 1
+cat example.db.in "$key1.key" "$key2.key" > example.db
+$SIGNER -3 - -H 10 -o example -f example.db example.db > /dev/null
+awk '/^IQF9LQTLK/ {
+ printf("%s", $0);
+ while (!index($0, ")")) {
+ if (getline <= 0)
+ break;
+ printf (" %s", $0);
+ }
+ printf("\n");
+ }' example.db | sed 's/[ ][ ]*/ /g' > nsec3param.out
+
+grep "IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG.example. 0 IN NSEC3 1 0 10 - ( IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG A NS SOA RRSIG DNSKEY NSEC3PARAM )" nsec3param.out > /dev/null
+) || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking NSEC3 signing with empty nonterminals above a delegation ($n)"
+ret=0
+zone=example
+key1=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone)
+key2=$($KEYGEN -K signer -q -f KSK -a $DEFAULT_ALGORITHM -n zone $zone)
+(
+cd signer || exit 1
+cat example.db.in "$key1.key" "$key2.key" > example3.db
+echo "some.empty.nonterminal.nodes.example 60 IN NS ns.example.tld" >> example3.db
+$SIGNER -3 - -A -H 10 -o example -f example3.db example3.db > /dev/null
+awk '/^IQF9LQTLK/ {
+ printf("%s", $0);
+ while (!index($0, ")")) {
+ if (getline <= 0)
+ break;
+ printf (" %s", $0);
+ }
+ printf("\n");
+ }' example.db | sed 's/[ ][ ]*/ /g' > nsec3param.out
+
+grep "IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG.example. 0 IN NSEC3 1 0 10 - ( IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG A NS SOA RRSIG DNSKEY NSEC3PARAM )" nsec3param.out > /dev/null
+) || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that dnssec-signzone updates originalttl on ttl changes ($n)"
+ret=0
+zone=example
+key1=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone)
+key2=$($KEYGEN -K signer -q -f KSK -a $DEFAULT_ALGORITHM -n zone $zone)
+(
+cd signer || exit 1
+cat example.db.in "$key1.key" "$key2.key" > example.db
+$SIGNER -o example -f example.db.before example.db > /dev/null
+sed 's/60.IN.SOA./50 IN SOA /' example.db.before > example.db.changed
+$SIGNER -o example -f example.db.after example.db.changed > /dev/null
+)
+grep "SOA $DEFAULT_ALGORITHM_NUMBER 1 50" signer/example.db.after > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking dnssec-signzone keeps valid signatures from removed keys ($n)"
+ret=0
+zone=example
+key1=$($KEYGEN -K signer -q -f KSK -a $DEFAULT_ALGORITHM -n zone $zone)
+key2=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone)
+keyid2=$(keyfile_to_key_id "$key2")
+key3=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone)
+keyid3=$(keyfile_to_key_id "$key3")
+(
+cd signer || exit 1
+cat example.db.in "$key1.key" "$key2.key" > example.db
+$SIGNER -D -o example example.db > /dev/null
+
+# now switch out key2 for key3 and resign the zone
+cat example.db.in "$key1.key" "$key3.key" > example.db
+echo "\$INCLUDE \"example.db.signed\"" >> example.db
+$SIGNER -D -o example example.db > /dev/null
+) || ret=1
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid2$" > /dev/null || ret=1
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid3$" > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking dnssec-signzone -R purges signatures from removed keys ($n)"
+ret=0
+(
+cd signer || exit 1
+$SIGNER -RD -o example example.db > /dev/null
+) || ret=1
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid2$" > /dev/null && ret=1
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid3$" > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking dnssec-signzone keeps valid signatures from inactive keys ($n)"
+ret=0
+zone=example
+(
+cd signer || exit 1
+cp -f example.db.in example.db
+$SIGNER -SD -o example example.db > /dev/null
+echo "\$INCLUDE \"example.db.signed\"" >> example.db
+# now retire key2 and resign the zone
+$SETTIME -I now "$key2" > /dev/null 2>&1
+$SIGNER -SD -o example example.db > /dev/null
+) || ret=1
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid2$" > /dev/null || ret=1
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid3$" > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking dnssec-signzone -Q purges signatures from inactive keys ($n)"
+ret=0
+(
+cd signer || exit 1
+$SIGNER -SDQ -o example example.db > /dev/null
+) || ret=1
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid2$" > /dev/null && ret=1
+get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid3$" > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking dnssec-signzone retains unexpired signatures ($n)"
+ret=0
+(
+cd signer || exit 1
+$SIGNER -Sxt -o example example.db > signer.out.1
+$SIGNER -Sxt -o example -f example.db.signed example.db.signed > signer.out.2
+) || ret=1
+gen1=$(awk '/generated/ {print $3}' signer/signer.out.1)
+retain1=$(awk '/retained/ {print $3}' signer/signer.out.1)
+gen2=$(awk '/generated/ {print $3}' signer/signer.out.2)
+retain2=$(awk '/retained/ {print $3}' signer/signer.out.2)
+drop2=$(awk '/dropped/ {print $3}' signer/signer.out.2)
+[ "$retain2" -eq $((gen1+retain1)) ] || ret=1
+[ "$gen2" -eq 0 ] || ret=1
+[ "$drop2" -eq 0 ] || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec) ($n)"
+ret=0
+(
+cd signer || exit 1
+# remove NSEC-only keys
+rm -f Kexample.+005*
+cp -f example.db.in example2.db
+cat << EOF >> example2.db
+sub1.example. IN A 10.53.0.1
+ns.sub2.example. IN A 10.53.0.2
+EOF
+echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
+touch example2.db.signed
+$SIGNER -DS -O full -f example2.db.signed -o example example2.db > /dev/null
+) || ret=1
+grep "^sub1\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
+grep "^ns\\.sub2\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
+(
+cd signer || exit 1
+cp -f example.db.in example2.db
+cat << EOF >> example2.db
+sub1.example. IN NS sub1.example.
+sub1.example. IN A 10.53.0.1
+sub2.example. IN NS ns.sub2.example.
+ns.sub2.example. IN A 10.53.0.2
+EOF
+echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
+$SIGNER -DS -O full -f example2.db.signed -o example example2.db > /dev/null
+) || ret=1
+grep "^sub1\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
+grep "^ns\\.sub2\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec3) ($n)"
+ret=0
+(
+cd signer || exit 1
+rm -f example2.db.signed
+cp -f example.db.in example2.db
+cat << EOF >> example2.db
+sub1.example. IN A 10.53.0.1
+ns.sub2.example. IN A 10.53.0.2
+EOF
+echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
+touch example2.db.signed
+$SIGNER -DS -3 feedabee -O full -f example2.db.signed -o example example2.db > /dev/null
+) || ret=1
+grep "^sub1\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
+grep "^ns\\.sub2\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
+(
+cd signer || exit 1
+cp -f example.db.in example2.db
+cat << EOF >> example2.db
+sub1.example. IN NS sub1.example.
+sub1.example. IN A 10.53.0.1
+sub2.example. IN NS ns.sub2.example.
+ns.sub2.example. IN A 10.53.0.2
+EOF
+echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
+$SIGNER -DS -3 feedabee -O full -f example2.db.signed -o example example2.db > /dev/null
+) || ret=1
+grep "^sub1\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
+grep "^ns\\.sub2\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking dnssec-signzone output format ($n)"
+ret=0
+(
+cd signer || exit 1
+$SIGNER -O full -f - -Sxt -o example example.db > signer.out.3 2> /dev/null
+$SIGNER -O text -f - -Sxt -o example example.db > signer.out.4 2> /dev/null
+$SIGNER -O raw -f signer.out.5 -Sxt -o example example.db > /dev/null
+$SIGNER -O raw=0 -f signer.out.6 -Sxt -o example example.db > /dev/null
+$SIGNER -O raw -f - -Sxt -o example example.db > signer.out.7 2> /dev/null
+) || ret=1
+awk 'BEGIN { found = 0; }
+ $1 == "example." && $3 == "IN" && $4 == "SOA" { found = 1; if (NF != 11) exit(1); }
+ END { if (!found) exit(1); }' signer/signer.out.3 || ret=1
+awk 'BEGIN { found = 0; }
+ $1 == "example." && $3 == "IN" && $4 == "SOA" { found = 1; if (NF != 7) exit(1); }
+ END { if (!found) exit(1); }' signer/signer.out.4 || ret=1
+israw1 signer/signer.out.5 || ret=1
+israw0 signer/signer.out.6 || ret=1
+israw1 signer/signer.out.7 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking TTLs are capped by dnssec-signzone -M ($n)"
+ret=0
+(
+cd signer || exit 1
+$SIGNER -O full -f signer.out.8 -S -M 30 -o example example.db > /dev/null
+) || ret=1
+awk '/^;/ { next; } $2 > 30 { exit 1; }' signer/signer.out.8 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking dnssec-signzone -N date ($n)"
+ret=0
+(
+cd signer || exit 1
+TZ=UTC $SIGNER -O full -f signer.out.9 -S -N date -o example example2.db > /dev/null
+) || ret=1
+# shellcheck disable=SC2016
+now=$(TZ=UTC $PERL -e '@lt=localtime(); printf "%.4d%0.2d%0.2d00\n",$lt[5]+1900,$lt[4]+1,$lt[3];')
+serial=$(awk '/^;/ { next; } $4 == "SOA" { print $7 }' signer/signer.out.9)
+[ "$now" -eq "$serial" ] || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking validated data are not cached longer than originalttl ($n)"
+ret=0
+dig_with_opts +ttl +noauth a.ttlpatch.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +ttl +noauth a.ttlpatch.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+grep "3600.IN" dig.out.ns3.test$n > /dev/null || ret=1
+grep "300.IN" dig.out.ns3.test$n > /dev/null && ret=1
+grep "300.IN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "3600.IN" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Test that "rndc secroots" is able to dump trusted keys
+echo_i "checking rndc secroots ($n)"
+ret=0
+keyid=$(cat ns1/managed.key.id)
+rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i
+cp ns4/named.secroots named.secroots.test$n
+check_secroots_layout named.secroots.test$n || ret=1
+linecount=$(grep -c "./$DEFAULT_ALGORITHM/$keyid ; static" named.secroots.test$n || true)
+[ "$linecount" -eq 1 ] || ret=1
+linecount=$(< named.secroots.test$n wc -l)
+[ "$linecount" -eq 10 ] || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Check direct query for RRSIG. If we first ask for normal (non RRSIG)
+# record, the corresponding RRSIG should be cached and subsequent query
+# for RRSIG will be returned with the cached record.
+echo_i "checking RRSIG query from cache ($n)"
+ret=0
+dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 a > /dev/null || ret=1
+ans=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.4 rrsig) || ret=1
+expect=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.3 rrsig | grep '^A' ) || ret=1
+test "$ans" = "$expect" || ret=1
+# also check that RA is set
+dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 rrsig > dig.out.ns4.test$n || ret=1
+grep "flags:.*ra.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Check direct query for RRSIG: If it's not cached with other records,
+# it should result in an empty response.
+echo_i "checking RRSIG query not in cache ($n)"
+ret=0
+ans=$(dig_with_opts +short rrsigonly.secure.example. @10.53.0.4 rrsig) || ret=1
+test -z "$ans" || ret=1
+# also check that RA is cleared
+dig_with_opts rrsigonly.secure.example. @10.53.0.4 rrsig > dig.out.ns4.test$n || ret=1
+grep "flags:.*ra.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# RT21868 regression test.
+#
+echo_i "checking NSEC3 zone with mismatched NSEC3PARAM / NSEC parameters ($n)"
+ret=0
+dig_with_opts non-exist.badparam. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# RT22007 regression test.
+#
+echo_i "checking optout NSEC3 referral with only insecure delegations ($n)"
+ret=0
+dig_with_opts +norec delegation.single-nsec3. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking optout NSEC3 NXDOMAIN with only insecure delegations ($n)"
+ret=0
+dig_with_opts +norec nonexist.single-nsec3. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+
+status=$((status+ret))
+echo_i "checking optout NSEC3 nodata with only insecure delegations ($n)"
+ret=0
+dig_with_opts +norec single-nsec3. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that a zone finishing the transition from $ALTERNATIVE_ALGORITHM to $DEFAULT_ALGORITHM validates secure ($n)"
+ret=0
+dig_with_opts ns algroll. @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking validate-except in an insecure local domain ($n)"
+ret=0
+dig_with_opts ns www.corp @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking positive and negative validation with negative trust anchors ($n)"
+ret=0
+
+#
+# check correct initial behavior
+#
+dig_with_opts a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.1 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.1 > /dev/null || ret=1
+dig_with_opts badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null || ret=1
+dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null || ret=1
+
+if [ "$ret" -ne 0 ]; then echo_i "failed - checking initial state"; fi
+status=$((status+ret))
+ret=0
+
+#
+# add negative trust anchors
+#
+rndccmd 10.53.0.4 nta -f -l 20s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i
+rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
+# reconfig should maintain NTAs
+rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
+rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1
+lines=$(wc -l < rndc.out.ns4.test$n.1)
+[ "$lines" -eq 3 ] || ret=1
+rndccmd 10.53.0.4 nta secure.example 2>&1 | sed 's/^/ns4 /' | cat_i
+rndccmd 10.53.0.4 nta fakenode.secure.example 2>&1 | sed 's/^/ns4 /' | cat_i
+# reload should maintain NTAs
+rndc_reload ns4 10.53.0.4
+rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.2
+lines=$(wc -l < rndc.out.ns4.test$n.2)
+[ "$lines" -eq 5 ] || ret=1
+# shellcheck disable=SC2016
+start=$($PERL -e 'print time()."\n";')
+
+if [ "$ret" -ne 0 ]; then echo_i "failed - adding NTA's failed"; fi
+status=$((status+ret))
+ret=0
+
+#
+# check behavior with NTA's in place
+#
+dig_with_opts a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.4 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 > /dev/null && ret=1
+dig_with_opts badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.5 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.5 > /dev/null && ret=1
+dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.6 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.6 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.6 > /dev/null && ret=1
+dig_with_opts a.fakenode.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.7 || ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.7 > /dev/null && ret=1
+echo_i "dumping secroots"
+rndccmd 10.53.0.4 secroots | sed 's/^/ns4 /' | cat_i
+cp ns4/named.secroots named.secroots.test$n
+check_secroots_layout named.secroots.test$n || ret=1
+grep "bogus.example: expiry" named.secroots.test$n > /dev/null || ret=1
+grep "badds.example: expiry" named.secroots.test$n > /dev/null || ret=1
+grep "secure.example: expiry" named.secroots.test$n > /dev/null || ret=1
+grep "fakenode.secure.example: expiry" named.secroots.test$n > /dev/null || ret=1
+
+if [ "$ret" -ne 0 ]; then echo_i "failed - with NTA's in place failed"; fi
+status=$((status+ret))
+ret=0
+
+echo_i "waiting for NTA rechecks/expirations"
+
+#
+# secure.example and badds.example used default nta-duration
+# (configured as 12s in ns4/named1.conf), but nta recheck interval
+# is configured to 9s, so at t=10 the NTAs for secure.example and
+# fakenode.secure.example should both be lifted, but badds.example
+# should still be going.
+#
+# shellcheck disable=SC2016
+$PERL -e 'my $delay = '"$start"' + 10 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
+dig_with_opts b.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.8 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.8 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.8 > /dev/null || ret=1
+dig_with_opts b.fakenode.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.9 || ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.9 > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n.9 > /dev/null || ret=1
+dig_with_opts badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.10 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.10 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.10 > /dev/null && ret=1
+
+if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to recheck"; fi
+status=$((status+ret))
+ret=0
+
+#
+# bogus.example was set to expire in 20s, so at t=13
+# it should still be NTA'd, but badds.example used the default
+# lifetime of 12s, so it should revert to SERVFAIL now.
+#
+# shellcheck disable=SC2016
+$PERL -e 'my $delay = '"$start"' + 13 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
+# check nta table
+rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n._11
+lines=$(grep -c " expiry " rndc.out.ns4.test$n._11 || true)
+[ "$lines" -le 2 ] || ret=1
+grep "bogus.example/_default: expiry" rndc.out.ns4.test$n._11 > /dev/null || ret=1
+grep "badds.example/_default: expiry" rndc.out.ns4.test$n._11 > /dev/null && ret=1
+dig_with_opts b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.11 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.11 > /dev/null && ret=1
+dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.12 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.12 > /dev/null || ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.12 > /dev/null && ret=1
+dig_with_opts c.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.13 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.13 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.13 > /dev/null || ret=1
+
+if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to lifetime"; fi
+status=$((status+ret))
+ret=0
+
+#
+# at t=21, all the NTAs should have expired.
+#
+# shellcheck disable=SC2016
+$PERL -e 'my $delay = '"$start"' + 21 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
+# check correct behavior after bogus.example expiry
+dig_with_opts d.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.14 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.14 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.14 > /dev/null || ret=1
+dig_with_opts c.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.15 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.15 > /dev/null || ret=1
+# check nta table has been cleaned up now
+rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.3
+lines=$(grep -c " expiry " rndc.out.ns4.test$n.3 || true)
+[ "$lines" -eq 0 ] || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed - checking that all nta's have been lifted"; fi
+status=$((status+ret))
+ret=0
+
+echo_i "testing NTA removals ($n)"
+rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
+rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1
+grep "badds.example/_default: expiry" rndc.out.ns4.test$n.1 > /dev/null || ret=1
+dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.1 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.1 > /dev/null && ret=1
+grep "^a.badds.example." dig.out.ns4.test$n.1 > /dev/null || ret=1
+rndccmd 10.53.0.4 nta -remove badds.example > rndc.out.ns4.test$n.2
+grep "Negative trust anchor removed: badds.example/_default" rndc.out.ns4.test$n.2 > /dev/null || ret=1
+rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.3
+grep "badds.example/_default: expiry" rndc.out.ns4.test$n.3 > /dev/null && ret=1
+dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+ret=0
+
+echo_i "remove non-existent NTA three times"
+rndccmd 10.53.0.4 nta -r foo > rndc.out.ns4.test$n.4 2>&1
+rndccmd 10.53.0.4 nta -remove foo > rndc.out.ns4.test$n.5 2>&1
+rndccmd 10.53.0.4 nta -r foo > rndc.out.ns4.test$n.6 2>&1
+grep "not found" rndc.out.ns4.test$n.6 > /dev/null || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+ret=0
+
+n=$((n+1))
+echo_i "testing NTA with bogus lifetimes ($n)"
+echo_i "check with no nta lifetime specified"
+rndccmd 10.53.0.4 nta -l "" foo > rndc.out.ns4.test$n.1 2>&1 || true
+grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.1 > /dev/null || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+ret=0
+
+echo_i "check with bad nta lifetime"
+rndccmd 10.53.0.4 nta -l garbage foo > rndc.out.ns4.test$n.2 2>&1 || true
+grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.2 > /dev/null || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+ret=0
+
+echo_i "check with too long nta lifetime"
+rndccmd 10.53.0.4 nta -l 7d1h foo > rndc.out.ns4.test$n.3 2>&1 || true
+grep "'nta' failed: out of range" rndc.out.ns4.test$n.3 > /dev/null || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+ret=0
+
+#
+# check NTA persistence across restarts
+#
+n=$((n+1))
+echo_i "testing NTA persistence across restarts ($n)"
+rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1
+lines=$(grep -c " expiry " rndc.out.ns4.test$n.1 || true)
+[ "$lines" -eq 0 ] || ret=1
+rndccmd 10.53.0.4 nta -f -l 30s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i
+rndccmd 10.53.0.4 nta -f -l 10s badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
+rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.2
+lines=$(grep -c " expiry " rndc.out.ns4.test$n.2 || true)
+[ "$lines" -eq 2 ] || ret=1
+# shellcheck disable=SC2016
+start=$($PERL -e 'print time()."\n";')
+
+if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: adding NTA's failed"; fi
+status=$((status+ret))
+ret=0
+
+echo_i "killing ns4 with SIGTERM"
+kill -TERM "$(cat ns4/named.pid)"
+rm -f ns4/named.pid
+
+#
+# ns4 has now shutdown. wait until t=14 when badds.example's NTA
+# (lifetime=10s) would have expired, and then restart ns4.
+#
+echo_i "waiting till 14s have passed since NTAs were added before restarting ns4"
+# shellcheck disable=SC2016
+$PERL -e 'my $delay = '"$start"' + 14 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
+
+if
+ start_server --noclean --restart --port "$PORT" ns4
+then
+ echo_i "restarted server ns4"
+else
+ echo_i "could not restart server ns4"
+ exit 1
+fi
+
+echo_i "sleeping for an additional 4 seconds for ns4 to fully startup"
+sleep 4
+
+#
+# ns4 should be back up now. The NTA for bogus.example should still be
+# valid, whereas badds.example should not have been added during named
+# startup (as it had already expired), the fact that it's ignored should
+# be logged.
+#
+rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.3
+lines=$(wc -l < rndc.out.ns4.test$n.3)
+[ "$lines" -eq 2 ] || ret=1
+grep "bogus.example/_default: expiry" rndc.out.ns4.test$n.3 > /dev/null || ret=1
+dig_with_opts b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.4 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 > /dev/null && ret=1
+dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.5 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null || ret=1
+grep "ignoring expired NTA at badds.example" ns4/named.run > /dev/null || ret=1
+
+# cleanup
+rndccmd 10.53.0.4 nta -remove bogus.example > rndc.out.ns4.test$n.6
+
+if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: restoring NTA failed"; fi
+status=$((status+ret))
+ret=0
+
+#
+# check "regular" attribute in NTA file works as expected at named
+# startup.
+#
+n=$((n+1))
+echo_i "testing loading regular attribute from NTA file ($n)"
+rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1 2>/dev/null
+lines=$(wc -l < rndc.out.ns4.test$n.1)
+[ "$lines" -eq 1 ] || ret=1
+# initially, secure.example. validates with AD=1
+dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 > /dev/null || ret=1
+
+echo_i "killing ns4 with SIGTERM"
+kill -TERM "$(cat ns4/named.pid)"
+rm -f ns4/named.pid
+
+echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
+sleep 4
+
+#
+# ns4 has now shutdown. add NTA for secure.example. directly into the
+# _default.nta file with the regular attribute and some future timestamp.
+#
+future="$(($(date +%Y)+20))0101010000"
+echo "secure.example. regular $future" > ns4/_default.nta
+# shellcheck disable=SC2016
+start=$($PERL -e 'print time()."\n";')
+
+if
+ start_server --noclean --restart --port "$PORT" ns4
+then
+ echo_i "restarted server ns4"
+else
+ echo_i "could not restart server ns4"
+ exit 1
+fi
+
+# nta-recheck is configured as 9s, so at t=12 the NTAs for
+# secure.example. should be lifted as it is not a forced NTA.
+echo_i "waiting till 12s have passed after ns4 was restarted"
+# shellcheck disable=SC2016
+$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
+
+# secure.example. should now return an AD=1 answer (still validates) as
+# the NTA has been lifted.
+dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null || ret=1
+
+# cleanup
+rndccmd 10.53.0.4 nta -remove secure.example > rndc.out.ns4.test$n.4 2>/dev/null
+
+if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading regular NTAs failed"; fi
+status=$((status+ret))
+ret=0
+
+#
+# check "forced" attribute in NTA file works as expected at named
+# startup.
+#
+n=$((n+1))
+echo_i "testing loading forced attribute from NTA file ($n)"
+rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1 2>/dev/null
+lines=$(wc -l < rndc.out.ns4.test$n.1)
+[ "$lines" -eq 1 ] || ret=1
+# initially, secure.example. validates with AD=1
+dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 > /dev/null || ret=1
+
+echo_i "killing ns4 with SIGTERM"
+kill -TERM "$(cat ns4/named.pid)"
+rm -f named.pid
+
+echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
+sleep 4
+
+#
+# ns4 has now shutdown. add NTA for secure.example. directly into the
+# _default.nta file with the forced attribute and some future timestamp.
+#
+echo "secure.example. forced $future" > ns4/_default.nta
+start=$($PERL -e 'print time()."\n";')
+
+if
+ start_server --noclean --restart --port "$PORT" ns4
+then
+ echo_i "restarted server ns4"
+else
+ echo_i "could not restart server ns4"
+ exit 1
+fi
+
+# nta-recheck is configured as 9s, but even at t=12 the NTAs for
+# secure.example. should not be lifted as it is a forced NTA.
+echo_i "waiting till 12s have passed after ns4 was restarted"
+# shellcheck disable=SC2016
+$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
+
+# secure.example. should now return an AD=0 answer (non-authenticated)
+# as the NTA is still there.
+dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1
+grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1
+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null && ret=1
+
+# cleanup
+rndccmd 10.53.0.4 nta -remove secure.example > rndc.out.ns4.test$n.4 2>/dev/null
+
+if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading forced NTAs failed"; fi
+status=$((status+ret))
+ret=0
+
+#
+# check that NTA lifetime read from file is clamped to 1 week.
+#
+n=$((n+1))
+echo_i "testing loading out of bounds lifetime from NTA file ($n)"
+
+echo_i "killing ns4 with SIGTERM"
+kill -TERM "$(cat ns4/named.pid)"
+rm -f ns4/named.pid
+
+echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
+sleep 4
+
+#
+# ns4 has now shutdown. add NTA for secure.example. directly into the
+# _default.nta file with a lifetime well into the future.
+#
+echo "secure.example. forced $future" > ns4/_default.nta
+added=$($PERL -e 'print time()."\n";')
+
+if
+ start_server --noclean --restart --port "$PORT" ns4
+then
+ echo_i "restarted server ns4"
+else
+ echo_i "could not restart server ns4"
+ exit 1
+fi
+
+echo_i "sleeping for an additional 4 seconds for ns4 to fully startup"
+sleep 4
+
+# dump the NTA to a file (omit validate-except entries)
+echo_i "testing 'rndc nta -d' with NTA"
+rndccmd 10.53.0.4 nta -d | grep -v ": permanent" > rndc.out.ns4.test$n.1 2>/dev/null
+# "corp" is configured as a validate-except domain and thus should be
+# removed by the grep -v above. only "secure.example" should appear in
+# the dump.
+lines=$(wc -l < rndc.out.ns4.test$n.1)
+[ "$lines" -eq 1 ] || ret=1
+grep 'secure.example' rndc.out.ns4.test$n.1 > /dev/null || ret=1
+ts=$(awk '{print $3" "$4}' < rndc.out.ns4.test$n.1)
+# rndc nta outputs localtime, so append the timezone
+ts_with_zone="$ts $(date +%z)"
+echo "ts=$ts" > rndc.out.ns4.test$n.2
+echo "ts_with_zone=$ts_with_zone" >> rndc.out.ns4.test$n.2
+echo "added=$added" >> rndc.out.ns4.test$n.2
+if $PERL -e 'use Time::Piece; use Time::Seconds;' 2>/dev/null
+then
+ # ntadiff.pl computes $ts_with_zone - ($added + 1week)
+ d=$($PERL ./ntadiff.pl "$ts_with_zone" "$added")
+ echo "d=$d" >> rndc.out.ns4.test$n.2
+ # diff from $added(now) + 1week to the clamped NTA lifetime should be
+ # less than a few seconds (handle daylight saving changes by adding 3600).
+ [ "$d" -lt 3610 ] || ret=1
+else
+ echo_i "skipped ntadiff test; install PERL module Time::Piece"
+fi
+
+echo_i "testing 'rndc nta' lifetime clamping"
+rndccmd 10.53.0.4 nta -d | grep ": permanent" > rndc.out.ns4.test$n.1 2>/dev/null
+# "corp" is configured as a validate-except domain and thus should be
+# the only entry in the dump.
+lines=$(wc -l < rndc.out.ns4.test$n.1)
+[ "$lines" -eq 1 ] || ret=1
+grep 'corp/_default' rndc.out.ns4.test$n.1 > /dev/null || ret=1
+
+# cleanup
+rndccmd 10.53.0.4 nta -remove secure.example > rndc.out.ns4.test$n.3 2>/dev/null
+
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing 'rndc nta -d' displays validate-except entries"
+rndccmd 10.53.0.4 nta -d | grep ": permanent" > rndc.out.ns4.test$n.1 2>/dev/null
+lines=$(wc -l < rndc.out.ns4.test$n.1)
+[ "$lines" -eq 1 ] || ret=1
+grep 'corp/_default' rndc.out.ns4.test$n.1 > /dev/null || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking that NTAs work with 'forward only;' to a validating resolver ($n)"
+ret=0
+# Sanity check behavior without an NTA in place.
+dig_with_opts @10.53.0.9 badds.example. SOA > dig.out.ns9.test$n.1 || ret=1
+grep "SERVFAIL" dig.out.ns9.test$n.1 > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns9.test$n.1 > /dev/null || ret=1
+grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.1 > /dev/null && ret=1
+# Add an NTA, expecting that to cause resolution to succeed.
+rndccmd 10.53.0.9 nta badds.example > rndc.out.ns9.test$n.1 2>&1 || ret=1
+dig_with_opts @10.53.0.9 badds.example. SOA > dig.out.ns9.test$n.2 || ret=1
+grep "NOERROR" dig.out.ns9.test$n.2 > /dev/null || ret=1
+grep "ANSWER: 2" dig.out.ns9.test$n.2 > /dev/null || ret=1
+grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.2 > /dev/null && ret=1
+# Remove the NTA, expecting that to cause resolution to fail again.
+rndccmd 10.53.0.9 nta -remove badds.example > rndc.out.ns9.test$n.2 2>&1 || ret=1
+dig_with_opts @10.53.0.9 badds.example. SOA > dig.out.ns9.test$n.3 || ret=1
+grep "SERVFAIL" dig.out.ns9.test$n.3 > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns9.test$n.3 > /dev/null || ret=1
+grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.3 > /dev/null && ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "completed NTA tests"
+
+# Run a minimal update test if possible. This is really just
+# a regression test for RT #2399; more tests should be added.
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ echo_i "running DNSSEC update test"
+ ret=0
+ { output=$($PERL dnssec_update_test.pl -s 10.53.0.3 -p "$PORT" dynamic.example.); rc=$?; } || true
+ test "$rc" -eq 0 || ret=1
+ echo "$output" | cat_i
+ [ $ret -eq 1 ] && status=1
+else
+ echo_i "The DNSSEC update test requires the Net::DNS library." >&2
+fi
+
+n=$((n+1))
+echo_i "checking managed key maintenance has not started yet ($n)"
+ret=0
+[ -f "ns4/managed-keys.bind.jnl" ] && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Reconfigure caching server to use "dnssec-validation auto", and repeat
+# some of the DNSSEC validation tests to ensure that it works correctly.
+# Also setup a placeholder managed-keys zone to check if named can process it
+# correctly.
+echo_i "switching to automatic root key configuration"
+cp ns4/managed-keys.bind.in ns4/managed-keys.bind
+copy_setports ns4/named2.conf.in ns4/named.conf
+rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
+sleep 5
+
+echo_i "checking managed key maintenance timer has now started ($n)"
+ret=0
+[ -f "ns4/managed-keys.bind.jnl" ] || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking positive validation NSEC ($n)"
+ret=0
+dig_with_opts +noauth a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking positive validation NSEC3 ($n)"
+ret=0
+dig_with_opts +noauth a.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking positive validation OPTOUT ($n)"
+ret=0
+dig_with_opts +noauth a.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth a.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking negative validation ($n)"
+ret=0
+dig_with_opts +noauth q.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth q.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that root DS queries validate ($n)"
+ret=0
+dig_with_opts +noauth . @10.53.0.1 ds > dig.out.ns1.test$n || ret=1
+dig_with_opts +noauth . @10.53.0.4 ds > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns1.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that DS at a RFC 1918 empty zone lookup succeeds ($n)"
+ret=0
+dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.2 >dig.out.ns2.test$n || ret=1
+dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.4 >dig.out.ns6.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns6.test$n || ret=1
+grep "status: NOERROR" dig.out.ns6.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking expired signatures remain with "'"allow-update { none; };"'" and no keys available ($n)"
+ret=0
+dig_with_opts +noauth expired.example. +dnssec @10.53.0.3 soa > dig.out.ns3.test$n || ret=1
+grep "RRSIG.SOA" dig.out.ns3.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+
+status=$((status+ret))
+echo_i "checking expired signatures do not validate ($n)"
+ret=0
+dig_with_opts +noauth expired.example. +dnssec @10.53.0.4 soa > dig.out.ns4.test$n || ret=1
+grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+grep "expired.example/.*: RRSIG has expired" ns4/named.run > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that the NSEC3 record for the apex is properly signed when a DNSKEY is added via UPDATE ($n)"
+ret=0
+(
+cd ns3 || exit 1
+kskname=$($KEYGEN -q -3 -a $DEFAULT_ALGORITHM -fk update-nsec3.example)
+(
+echo zone update-nsec3.example
+echo server 10.53.0.3 "$PORT"
+grep DNSKEY "${kskname}.key" | sed -e 's/^/update add /' -e 's/IN/300 IN/'
+echo send
+) | $NSUPDATE
+)
+dig_with_opts +dnssec a update-nsec3.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
+grep "NSEC3 .* TYPE65534" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that the NSEC record is properly generated when DNSKEY are added via auto-dnssec ($n)"
+ret=0
+dig_with_opts +dnssec a auto-nsec.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
+grep "IN.NSEC[^3].* DNSKEY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that the NSEC3 record is properly generated when DNSKEY are added via auto-dnssec ($n)"
+ret=0
+dig_with_opts +dnssec a auto-nsec3.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
+grep "IN.NSEC3 .* DNSKEY" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that signing records have been marked as complete ($n)"
+ret=0
+checkprivate dynamic.example 10.53.0.3 || ret=1
+checkprivate update-nsec3.example 10.53.0.3 || ret=1
+checkprivate auto-nsec3.example 10.53.0.3 || ret=1
+checkprivate expiring.example 10.53.0.3 || ret=1
+checkprivate auto-nsec.example 10.53.0.3 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing' without arguments is handled ($n)"
+ret=0
+rndccmd 10.53.0.3 signing > /dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -list' without zone is handled ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -list > /dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -clear' without additional arguments is handled ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -clear > /dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -clear all' without zone is handled ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -clear all > /dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -nsec3param' without additional arguments is handled ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -nsec3param > /dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -nsec3param none' without zone is handled ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -nsec3param none > /dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -nsec3param 1' without additional arguments is handled ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -nsec3param 1 > /dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -nsec3param 1 0' without additional arguments is handled ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -nsec3param 1 0 > /dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -nsec3param 1 0 0' without additional arguments is handled ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -nsec3param 1 0 0 > /dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -nsec3param 1 0 0 -' without zone is handled ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -nsec3param 1 0 0 - > /dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -nsec3param' works with salt ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -nsec3param 1 0 0 ffff inline.example > /dev/null 2>&1 || ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+for i in 1 2 3 4 5 6 7 8 9 10 ; do
+ salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
+ if [ "$salt" = "FFFF" ]; then
+ break;
+ fi
+ echo_i "sleeping ...."
+ sleep 1
+done;
+[ "$salt" = "FFFF" ] || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -nsec3param' works without salt ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -nsec3param 1 0 0 - inline.example > /dev/null 2>&1 || ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+for i in 1 2 3 4 5 6 7 8 9 10 ; do
+ salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
+ if [ "$salt" = "-" ]; then
+ break;
+ fi
+ echo_i "sleeping ...."
+ sleep 1
+done;
+[ "$salt" = "-" ] || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -nsec3param' works with 'auto' as salt ($n)"
+ret=0
+rndccmd 10.53.0.3 signing -nsec3param 1 0 0 auto inline.example > /dev/null 2>&1 || ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+for i in 1 2 3 4 5 6 7 8 9 10 ; do
+ salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
+ [ -n "$salt" ] && [ "$salt" != "-" ] && break
+ echo_i "sleeping ...."
+ sleep 1
+done;
+[ "$salt" != "-" ] || ret=1
+[ "${#salt}" -eq 16 ] || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'rndc signing -nsec3param' with 'auto' as salt again generates a different salt ($n)"
+ret=0
+oldsalt=$salt
+rndccmd 10.53.0.3 signing -nsec3param 1 0 0 auto inline.example > /dev/null 2>&1 || ret=1
+rndccmd 10.53.0.3 status > /dev/null || ret=1
+for i in 1 2 3 4 5 6 7 8 9 10 ; do
+ salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
+ [ -n "$salt" ] && [ "$salt" != "$oldsalt" ] && break
+ echo_i "sleeping ...."
+ sleep 1
+done;
+[ "$salt" != "$oldsalt" ] || ret=1
+[ "${#salt}" -eq 16 ] || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check rndc signing -list output ($n)"
+ret=0
+{ rndccmd 10.53.0.3 signing -list dynamic.example > signing.out; } 2>&1
+grep -q "No signing records found" signing.out || {
+ ret=1
+ sed 's/^/ns3 /' signing.out | cat_i
+}
+{ rndccmd 10.53.0.3 signing -list update-nsec3.example > signing.out; } 2>&1
+grep -q "Done signing with key .*/$DEFAULT_ALGORITHM" signing.out || {
+ ret=1
+ sed 's/^/ns3 /' signing.out | cat_i
+}
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "clear signing records ($n)"
+{ rndccmd 10.53.0.3 signing -clear all update-nsec3.example > /dev/null; } 2>&1 || ret=1
+check_no_signing_record_found() {
+ { rndccmd 10.53.0.3 signing -list update-nsec3.example > signing.out; } 2>&1
+ grep -q "No signing records found" signing.out || {
+ sed 's/^/ns3 /' signing.out | cat_i
+ return 1
+ }
+ return 0
+}
+retry_quiet 5 check_no_signing_record_found || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that a insecure zone beneath a cname resolves ($n)"
+ret=0
+dig_with_opts soa insecure.below-cname.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that a secure zone beneath a cname resolves ($n)"
+ret=0
+dig_with_opts soa secure.below-cname.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+my_dig() {
+ "$DIG" +noadd +nosea +nostat +noquest +nocomm +nocmd -p "$PORT" @10.53.0.4 "$@"
+}
+
+echo_i "checking DNSKEY query with no data still gets put in cache ($n)"
+ret=0
+firstVal=$(my_dig insecure.example. dnskey| awk '$1 != ";;" { print $2 }')
+sleep 1
+secondVal=$(my_dig insecure.example. dnskey| awk '$1 != ";;" { print $2 }')
+if [ "${firstVal:-0}" -eq "${secondVal:-0}" ]
+then
+ sleep 1
+ thirdVal=$(my_dig insecure.example. dnskey|awk '$1 != ";;" { print $2 }')
+ if [ "${firstVal:-0}" -eq "${thirdVal:-0}" ]
+ then
+ echo_i "cannot confirm query answer still in cache"
+ ret=1
+ fi
+fi
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that a split dnssec dnssec-signzone work ($n)"
+ret=0
+dig_with_opts soa split-dnssec.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that a smart split dnssec dnssec-signzone work ($n)"
+ret=0
+dig_with_opts soa split-smart.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that NOTIFY is sent at the end of NSEC3 chain generation ($n)"
+ret=0
+(
+echo zone nsec3chain-test
+echo server 10.53.0.2 "$PORT"
+echo update add nsec3chain-test. 0 nsec3param 1 0 1 123456
+echo send
+) | $NSUPDATE
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
+do
+ dig_with_opts nsec3param nsec3chain-test @10.53.0.2 > dig.out.ns2.test$n || ret=1
+ if grep "ANSWER: 3," dig.out.ns2.test$n >/dev/null
+ then
+ break;
+ fi
+ echo_i "sleeping ...."
+ sleep 3
+done
+grep "ANSWER: 3," dig.out.ns2.test$n > /dev/null || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "nsec3 chain generation not complete"; fi
+dig_with_opts +noauth +nodnssec soa nsec3chain-test @10.53.0.2 > dig.out.ns2.test$n || ret=1
+s2=$(awk '$4 == "SOA" { print $7}' dig.out.ns2.test$n)
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ dig_with_opts +noauth +nodnssec soa nsec3chain-test @10.53.0.3 > dig.out.ns3.test$n || ret=1
+ s3=$(awk '$4 == "SOA" { print $7}' dig.out.ns3.test$n)
+ test "$s2" = "$s3" && break
+ sleep 1
+done
+digcomp dig.out.ns2.test$n dig.out.ns3.test$n || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check dnssec-dsfromkey from stdin ($n)"
+ret=0
+dig_with_opts dnskey algroll. @10.53.0.2 | \
+ $DSFROMKEY -f - algroll. > dig.out.ns2.test$n || ret=1
+NF=$(awk '{print NF}' dig.out.ns2.test$n | sort -u)
+[ "${NF}" = 7 ] || ret=1
+# make canonical
+awk '{
+ for (i=1;i<7;i++) printf("%s ", $i);
+ for (i=7;i<=NF;i++) printf("%s", $i);
+ printf("\n");
+}' < dig.out.ns2.test$n > canonical1.$n || ret=1
+awk '{
+ for (i=1;i<7;i++) printf("%s ", $i);
+ for (i=7;i<=NF;i++) printf("%s", $i);
+ printf("\n");
+}' < ns1/dsset-algroll. > canonical2.$n || ret=1
+diff -b canonical1.$n canonical2.$n > /dev/null 2>&1 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Intentionally strip ".key" from keyfile name to ensure the error message
+# includes it anyway to avoid confusion (RT #21731)
+echo_i "check dnssec-dsfromkey error message when keyfile is not found ($n)"
+ret=0
+key=$($KEYGEN -a $DEFAULT_ALGORITHM -q example.) || ret=1
+mv "$key.key" "$key"
+$DSFROMKEY "$key" > dsfromkey.out.$n 2>&1 && ret=1
+grep "$key.key: file not found" dsfromkey.out.$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check dnssec-dsfromkey with revoked key ($n)"
+ret=0
+dig_with_opts revkey.example dnskey @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "DNSKEY.256 3 13" dig.out.ns4.test$n > /dev/null || ret=1 # ZSK
+grep "DNSKEY.385 3 13" dig.out.ns4.test$n > /dev/null || ret=1 # revoked KSK
+grep "DNSKEY.257 3 13" dig.out.ns4.test$n > /dev/null || ret=1 # KSK
+test $(awk '$4 == "DNSKEY" { print }' dig.out.ns4.test$n | wc -l) -eq 3 || ret=1
+$DSFROMKEY -f dig.out.ns4.test$n revkey.example. > dsfromkey.out.test$n || ret=1
+test $(wc -l < dsfromkey.out.test$n) -eq 1 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+
+echo_i "testing soon-to-expire RRSIGs without a replacement private key ($n)"
+ret=0
+dig_with_answeropts +nottlid expiring.example ns @10.53.0.3 | grep RRSIG > dig.out.ns3.test$n 2>&1
+# there must be a signature here
+[ -s dig.out.ns3.test$n ] || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing new records are signed with 'no-resign' ($n)"
+ret=0
+(
+echo zone nosign.example
+echo server 10.53.0.3 "$PORT"
+echo update add new.nosign.example 300 in txt "hi there"
+echo send
+) | $NSUPDATE
+sleep 1
+dig_with_answeropts +nottlid txt new.nosign.example @10.53.0.3 \
+ > dig.out.ns3.test$n 2>&1
+grep RRSIG dig.out.ns3.test$n > /dev/null 2>&1 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing expiring records aren't resigned with 'no-resign' ($n)"
+ret=0
+dig_with_answeropts +nottlid nosign.example ns @10.53.0.3 | \
+ grep RRSIG | sed 's/[ ][ ]*/ /g' > dig.out.ns3.test$n 2>&1
+# the NS RRSIG should not be changed
+diff nosign.before dig.out.ns3.test$n > /dev/null|| ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing updates fail with no private key ($n)"
+ret=0
+rm -f ns3/Knosign.example.*.private
+(
+echo zone nosign.example
+echo server 10.53.0.3 "$PORT"
+echo update add fail.nosign.example 300 in txt "reject me"
+echo send
+) | $NSUPDATE > /dev/null 2>&1 && ret=1
+dig_with_answeropts +nottlid fail.nosign.example txt @10.53.0.3 \
+ > dig.out.ns3.test$n 2>&1
+[ -s dig.out.ns3.test$n ] && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing legacy upper case signer name validation ($n)"
+ret=0
+$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa upper.example @10.53.0.4 \
+ > dig.out.ns4.test$n 2>&1 || ret=1
+grep "flags:.* ad;" dig.out.ns4.test$n > /dev/null || ret=1
+grep "RRSIG.*SOA.* UPPER\\.EXAMPLE\\. " dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing that we lower case signer name ($n)"
+ret=0
+$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa LOWER.EXAMPLE @10.53.0.4 \
+ > dig.out.ns4.test$n 2>&1 || ret=1
+grep "flags:.* ad;" dig.out.ns4.test$n > /dev/null || ret=1
+grep "RRSIG.*SOA.* lower\\.example\\. " dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing TTL is capped at RRSIG expiry time ($n)"
+ret=0
+rndccmd 10.53.0.3 freeze expiring.example 2>&1 | sed 's/^/ns3 /' | cat_i
+(
+cd ns3 || exit 1
+for file in K*.moved; do
+ mv "$file" "$(basename "$file" .moved)"
+done
+$SIGNER -S -N increment -e now+1mi -o expiring.example expiring.example.db > /dev/null
+) || ret=1
+rndc_reload ns3 10.53.0.3 expiring.example
+
+rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
+dig_with_answeropts +cd expiring.example soa @10.53.0.4 > dig.out.ns4.1.$n
+dig_with_answeropts expiring.example soa @10.53.0.4 > dig.out.ns4.2.$n
+ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
+ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
+for ttl in ${ttls:-0}; do
+ [ "${ttl}" -eq 300 ] || ret=1
+done
+for ttl in ${ttls2:-0}; do
+ [ "${ttl}" -le 60 ] || ret=1
+done
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (NS) ($n)"
+ret=0
+rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
+sleep 1
+dig_with_additionalopts +cd expiring.example ns @10.53.0.4 > dig.out.ns4.1.$n
+dig_with_additionalopts expiring.example ns @10.53.0.4 > dig.out.ns4.2.$n
+ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
+ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
+for ttl in ${ttls:-300}; do
+ [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
+done
+for ttl in ${ttls2:-0}; do
+ [ "$ttl" -le 60 ] || ret=1
+done
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (MX) ($n)"
+ret=0
+rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
+sleep 1
+dig_with_additionalopts +cd expiring.example mx @10.53.0.4 > dig.out.ns4.1.$n
+dig_with_additionalopts expiring.example mx @10.53.0.4 > dig.out.ns4.2.$n
+ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
+ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
+for ttl in ${ttls:-300}; do
+ [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
+done
+for ttl in ${ttls2:-0}; do
+ [ "$ttl" -le 60 ] || ret=1
+done
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+copy_setports ns4/named3.conf.in ns4/named.conf
+rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
+sleep 3
+
+echo_i "testing TTL of about to expire RRsets with dnssec-accept-expired yes; ($n)"
+ret=0
+rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
+dig_with_answeropts +cd expiring.example soa @10.53.0.4 > dig.out.ns4.1.$n
+dig_with_answeropts expiring.example soa @10.53.0.4 > dig.out.ns4.2.$n
+ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
+ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
+for ttl in ${ttls:-0}; do
+ [ "$ttl" -eq 300 ] || ret=1
+done
+for ttl in ${ttls2:-0}; do
+ [ "$ttl" -eq 120 ] || ret=1
+done
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing TTL of expired RRsets with dnssec-accept-expired yes; ($n)"
+ret=0
+dig_with_answeropts +cd expired.example soa @10.53.0.4 > dig.out.ns4.1.$n
+dig_with_answeropts expired.example soa @10.53.0.4 > dig.out.ns4.2.$n
+ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
+ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
+for ttl in ${ttls:-0}; do
+ [ "$ttl" -eq 300 ] || ret=1
+done
+for ttl in ${ttls2:-0}; do
+ [ "$ttl" -eq 120 ] || ret=1
+done
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section with dnssec-accept-expired yes; ($n)"
+ret=0
+rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
+dig_with_additionalopts +cd expiring.example mx @10.53.0.4 > dig.out.ns4.1.$n
+dig_with_additionalopts expiring.example mx @10.53.0.4 > dig.out.ns4.2.$n
+ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
+ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
+for ttl in ${ttls:-300}; do
+ [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
+done
+for ttl in ${ttls2:-0}; do
+ [ "$ttl" -le 120 ] && [ "$ttl" -gt 60 ] || ret=1
+done
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing DNSKEY lookup via CNAME ($n)"
+ret=0
+dig_with_opts +noauth cnameandkey.secure.example. \
+ @10.53.0.3 dnskey > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth cnameandkey.secure.example. \
+ @10.53.0.4 dnskey > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "CNAME" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing KEY lookup at CNAME (present) ($n)"
+ret=0
+dig_with_opts +noauth cnameandkey.secure.example. \
+ @10.53.0.3 key > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth cnameandkey.secure.example. \
+ @10.53.0.4 key > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "CNAME" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing KEY lookup at CNAME (not present) ($n)"
+ret=0
+dig_with_opts +noauth cnamenokey.secure.example. \
+ @10.53.0.3 key > dig.out.ns3.test$n || ret=1
+dig_with_opts +noauth cnamenokey.secure.example. \
+ @10.53.0.4 key > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "CNAME" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing DNSKEY lookup via DNAME ($n)"
+ret=0
+dig_with_opts a.dnameandkey.secure.example. \
+ @10.53.0.3 dnskey > dig.out.ns3.test$n || ret=1
+dig_with_opts a.dnameandkey.secure.example. \
+ @10.53.0.4 dnskey > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "CNAME" dig.out.ns4.test$n > /dev/null || ret=1
+grep "DNAME" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "testing KEY lookup via DNAME ($n)"
+ret=0
+dig_with_opts b.dnameandkey.secure.example. \
+ @10.53.0.3 key > dig.out.ns3.test$n || ret=1
+dig_with_opts b.dnameandkey.secure.example. \
+ @10.53.0.4 key > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "DNAME" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that named doesn't loop when all private keys are not available ($n)"
+ret=0
+lines=$(grep -c "reading private key file expiring.example" ns3/named.run || true)
+test "${lines:-1000}" -lt 15 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check against against missing nearest provable proof ($n)"
+dig_with_opts +norec b.c.d.optout-tld. \
+ @10.53.0.6 ds > dig.out.ds.ns6.test$n || ret=1
+nsec3=$(grep -c "IN.NSEC3" dig.out.ds.ns6.test$n || true)
+[ "$nsec3" -eq 2 ] || ret=1
+dig_with_opts +norec b.c.d.optout-tld. \
+ @10.53.0.6 A > dig.out.ns6.test$n || ret=1
+nsec3=$(grep -c "IN.NSEC3" dig.out.ns6.test$n || true)
+[ "$nsec3" -eq 1 ] || ret=1
+dig_with_opts optout-tld. \
+ @10.53.0.4 SOA > dig.out.soa.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.soa.ns4.test$n > /dev/null || ret=1
+dig_with_opts b.c.d.optout-tld. \
+ @10.53.0.4 A > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that key id are logged when dumping the cache ($n)"
+ret=0
+rndc_dumpdb ns4
+grep "; key id = " ns4/named_dump.db.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check KEYDATA records are printed in human readable form in key zone ($n)"
+# force the managed-keys zone to be written out
+rndccmd 10.53.0.4 managed-keys sync 2>&1 | sed 's/^/ns4 /' | cat_i
+for i in 1 2 3 4 5 6 7 8 9
+do
+ ret=0
+ if test -f ns4/managed-keys.bind
+ then
+ grep KEYDATA ns4/managed-keys.bind > /dev/null &&
+ grep "next refresh:" ns4/managed-keys.bind > /dev/null &&
+ break
+ fi
+ ret=1
+ sleep 1
+done
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check dig's +nocrypto flag ($n)"
+ret=0
+dig_with_opts +norec +nocrypto DNSKEY . \
+ @10.53.0.1 > dig.out.dnskey.ns1.test$n || ret=1
+grep -E "256 [0-9]+ $DEFAULT_ALGORITHM_NUMBER \\[key id = [1-9][0-9]*]" dig.out.dnskey.ns1.test$n > /dev/null || ret=1
+grep -E "RRSIG.* \\[omitted]" dig.out.dnskey.ns1.test$n > /dev/null || ret=1
+dig_with_opts +norec +nocrypto DS example \
+ @10.53.0.1 > dig.out.ds.ns1.test$n || ret=1
+grep -E "DS.* [0-9]+ [12] \[omitted]" dig.out.ds.ns1.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check simultaneous inactivation and publishing of dnskeys removes inactive signature ($n)"
+ret=0
+cnt=0
+while :
+do
+dig_with_opts publish-inactive.example @10.53.0.3 dnskey > dig.out.ns3.test$n
+keys=$(awk '$5 == 257 { print; }' dig.out.ns3.test$n | wc -l)
+test "$keys" -gt 2 && break
+cnt=$((cnt+1))
+test "$cnt" -gt 120 && break
+sleep 1
+done
+test "$keys" -gt 2 || ret=1
+sigs=$(grep -c RRSIG dig.out.ns3.test$n || true)
+n=$((n+1))
+test "$sigs" -eq 2 || ret=1
+if test "$ret" -ne 0 ; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "check that increasing the sig-validity-interval resigning triggers re-signing ($n)"
+ret=0
+before=$($DIG axfr siginterval.example -p "$PORT" @10.53.0.3 | grep RRSIG.SOA)
+cp ns3/siginterval2.conf ns3/siginterval.conf
+rndccmd 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+i=10
+while [ "$i" -ge 0 ]; do
+after=$($DIG axfr siginterval.example -p "$PORT" @10.53.0.3 | grep RRSIG.SOA)
+test "$before" != "$after" && break
+sleep 1
+i=$((i-1))
+done
+n=$((n+1))
+if test "$before" = "$after" ; then echo_i "failed"; ret=1; fi
+status=$((status+ret))
+
+if [ -x "$PYTHON" ]; then
+ echo_i "check dnskey-sig-validity sets longer expiry for DNSKEY ($n)"
+ ret=0
+ rndccmd 10.53.0.3 sign siginterval.example 2>&1 | sed 's/^/ns3 /' | cat_i
+ # convert expiry date to a comma-separated list of integers python can
+ # use as input to date(). strip leading 0s in months and days so
+ # python3 will recognize them as integers.
+ $DIG +dnssec +short -p "$PORT" @10.53.0.3 soa siginterval.example > dig.out.soa.test$n || ret=1
+ soaexpire=$(awk '$1 ~ /SOA/ { print $5 }' dig.out.soa.test$n |
+ sed 's/\(....\)\(..\)\(..\).*/\1, \2, \3/' |
+ sed 's/ 0/ /g')
+ $DIG +dnssec +short -p "$PORT" @10.53.0.3 dnskey siginterval.example > dig.out.dnskey.test$n || ret=1
+ dnskeyexpire=$(awk '$1 ~ /DNSKEY/ { print $5; exit 0 }' dig.out.dnskey.test$n |
+ sed 's/\(....\)\(..\)\(..\).*/\1, \2, \3/' |
+ sed 's/ 0/ /g')
+ $PYTHON > python.out.$n <<EOF
+from datetime import date;
+ke=date($dnskeyexpire)
+se=date($soaexpire)
+print((ke-se).days);
+EOF
+ diff=$(cat python.out.$n)
+ [ "$diff" -ge 55 ] || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+fi
+
+copy_setports ns4/named4.conf.in ns4/named.conf
+rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
+sleep 3
+
+echo_i "check insecure delegation between static-stub zones ($n)"
+ret=0
+dig_with_opts ns insecure.secure.example \
+ @10.53.0.4 > dig.out.ns4.1.test$n || ret=1
+grep "SERVFAIL" dig.out.ns4.1.test$n > /dev/null && ret=1
+dig_with_opts ns secure.example \
+ @10.53.0.4 > dig.out.ns4.2.test$n || ret=1
+grep "SERVFAIL" dig.out.ns4.2.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check the acceptance of seconds as inception and expiration times ($n)"
+ret=0
+in="NSEC 8 0 86400 1390003200 1389394800 33655 . NYWjZYBV1b+h4j0yu/SmPOOylR8P4IXKDzHX3NwEmU1SUp27aJ91dP+i+UBcnPmBib0hck4DrFVvpflCEpCnVQd2DexcN0GX+3PM7XobxhtDlmnU X1L47zJlbdHNwTqHuPaMM6Xy9HGMXps7O5JVyfggVhTz2C+G5OVxBdb2rOo="
+
+exp="NSEC 8 0 86400 20140118000000 20140110230000 33655 . NYWjZYBV1b+h4j0yu/SmPOOylR8P4IXKDzHX3NwEmU1SUp27aJ91dP+i +UBcnPmBib0hck4DrFVvpflCEpCnVQd2DexcN0GX+3PM7XobxhtDlmnU X1L47zJlbdHNwTqHuPaMM6Xy9HGMXps7O5JVyfggVhTz2C+G5OVxBdb2 rOo="
+
+out=$(echo "IN RRSIG $in" | $RRCHECKER -p | sed 's/^IN.RRSIG.//')
+[ "$out" = "$exp" ] || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check the correct resigning time is reported in zonestatus ($n)"
+ret=0
+rndccmd 10.53.0.3 \
+ zonestatus secure.example > rndc.out.ns3.test$n
+# next resign node: secure.example/DNSKEY
+qname=$(awk '/next resign node:/ { print $4 }' rndc.out.ns3.test$n | sed 's,/.*,,')
+qtype=$(awk '/next resign node:/ { print $4 }' rndc.out.ns3.test$n | sed 's,.*/,,')
+# next resign time: Thu, 24 Apr 2014 10:38:16 GMT
+time=$(awk 'BEGIN { m["Jan"] = "01"; m["Feb"] = "02"; m["Mar"] = "03";
+ m["Apr"] = "04"; m["May"] = "05"; m["Jun"] = "06";
+ m["Jul"] = "07"; m["Aug"] = "08"; m["Sep"] = "09";
+ m["Oct"] = "10"; m["Nov"] = "11"; m["Dec"] = "12";}
+ /next resign time:/ { printf "%d%s%02d%s\n", $7, m[$6], $5, $8 }' rndc.out.ns3.test$n | sed 's/://g')
+dig_with_opts +noall +answer "$qname" "$qtype" @10.53.0.3 > dig.out.test$n
+expire=$(awk '$4 == "RRSIG" { print $9 }' dig.out.test$n)
+inception=$(awk '$4 == "RRSIG" { print $10 }' dig.out.test$n)
+$PERL -e 'exit(0) if ("'"$time"'" lt "'"$expire"'" && "'"$time"'" gt "'"$inception"'"); exit(1);' || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that split rrsigs are handled ($n)"
+ret=0
+dig_with_opts split-rrsig soa @10.53.0.7 > dig.out.test$n || ret=1
+awk 'BEGIN { ok=0; } $4 == "SOA" { if ($7 > 1) ok=1; } END { if (!ok) exit(1); }' dig.out.test$n || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that not-at-zone-apex RRSIG(SOA) RRsets are removed from the zone after load ($n)"
+ret=0
+dig_with_opts split-rrsig AXFR @10.53.0.7 > dig.out.test$n || ret=1
+grep -q "not-at-zone-apex.*RRSIG.*SOA" dig.out.test$n && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that 'dnssec-keygen -S' works for all supported algorithms ($n)"
+ret=0
+alg=1
+until test $alg -eq 256
+do
+ zone="keygen-$alg."
+ case $alg in
+ 2) # Diffie Helman
+ alg=$((alg+1))
+ continue;;
+ 157|160|161|162|163|164|165) # private - non standard
+ alg=$((alg+1))
+ continue;;
+ 1|5|7|8|10) # RSA algorithms
+ key1=$($KEYGEN -a "$alg" -b "1024" -n zone "$zone" 2> "keygen-$alg.err" || true)
+ ;;
+ 15|16)
+ key1=$($KEYGEN -a "$alg" -n zone "$zone" 2> "keygen-$alg.err" || true)
+ ;;
+ *)
+ key1=$($KEYGEN -a "$alg" -n zone "$zone" 2> "keygen-$alg.err" || true)
+ esac
+ if grep "unsupported algorithm" "keygen-$alg.err" > /dev/null
+ then
+ alg=$((alg+1))
+ continue
+ fi
+ if test -z "$key1"
+ then
+ echo_i "'$KEYGEN -a $alg': failed"
+ cat "keygen-$alg.err"
+ ret=1
+ alg=$((alg+1))
+ continue
+ fi
+ $SETTIME -I now+4d "$key1.private" > /dev/null
+ key2=$($KEYGEN -v 10 -i 3d -S "$key1.private" 2> /dev/null)
+ test -f "$key2.key" -a -f "$key2.private" || {
+ ret=1
+ echo_i "'dnssec-keygen -S' failed for algorithm: $alg"
+ }
+ alg=$((alg+1))
+done
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDS records are signed using KSK by dnssec-signzone ($n)"
+ret=0
+dig_with_opts +noall +answer @10.53.0.2 cds cds.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDS records are not signed using ZSK by dnssec-signzone -x ($n)"
+ret=0
+dig_with_opts +noall +answer @10.53.0.2 cds cds-x.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that positive unknown NSEC3 hash algorithm does validate ($n)"
+ret=0
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example SOA > dig.out.ns3.test$n
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example SOA > dig.out.ns4.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDS records are signed using KSK by with dnssec-auto ($n)"
+ret=0
+dig_with_opts +noall +answer @10.53.0.2 cds cds-auto.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that a CDS deletion record is accepted ($n)"
+ret=0
+(
+echo zone cds-update.secure
+echo server 10.53.0.2 "$PORT"
+echo update delete cds-update.secure CDS
+echo update add cds-update.secure 0 CDS 0 0 0 00
+echo send
+) | $NSUPDATE > nsupdate.out.test$n 2>&1
+dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
+lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
+test "${lines:-10}" -eq 1 || ret=1
+lines=$(awk '$4 == "CDS" && $5 == "0" && $6 == "0" && $7 == "0" && $8 == "00" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDS records are signed using KSK when added by nsupdate ($n)"
+ret=0
+(
+echo zone cds-update.secure
+echo server 10.53.0.2 "$PORT"
+echo update delete cds-update.secure CDS
+echo send
+dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
+grep "DNSKEY.257" |
+$DSFROMKEY -12 -C -f - -T 1 cds-update.secure |
+sed "s/^/update add /"
+echo send
+) | $NSUPDATE
+dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDS records are signed only using KSK when added by"
+echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
+ret=0
+keyid=$(cat ns2/cds-kskonly.secure.id)
+(
+echo zone cds-kskonly.secure
+echo server 10.53.0.2 "$PORT"
+echo update delete cds-kskonly.secure CDS
+echo send
+dig_with_opts +noall +answer @10.53.0.2 dnskey cds-kskonly.secure |
+grep "DNSKEY.257" |
+$DSFROMKEY -12 -C -f - -T 1 cds-kskonly.secure |
+sed "s/^/update add /"
+echo send
+) | $NSUPDATE
+dig_with_opts +noall +answer @10.53.0.2 cds cds-kskonly.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDS" && $11 == id {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDS deletion records are signed only using KSK when added by"
+echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
+ret=0
+keyid=$(cat ns2/cds-kskonly.secure.id)
+(
+echo zone cds-kskonly.secure
+echo server 10.53.0.2 "$PORT"
+echo update delete cds-kskonly.secure CDS
+echo update add cds-kskonly.secure 0 CDS 0 0 0 00
+echo send
+) | $NSUPDATE
+dig_with_opts +noall +answer @10.53.0.2 cds cds-kskonly.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDS" && $11 == id {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+lines=$(awk '$4 == "CDS" && $5 == "0" && $6 == "0" && $7 == "0" && $8 == "00" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that positive unknown NSEC3 hash algorithm with OPTOUT does validate ($n)"
+ret=0
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example SOA > dig.out.ns3.test$n
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example SOA > dig.out.ns4.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that a non matching CDS record is accepted with a matching CDS record ($n)"
+ret=0
+(
+echo zone cds-update.secure
+echo server 10.53.0.2 "$PORT"
+echo update delete cds-update.secure CDS
+echo send
+dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
+grep "DNSKEY.257" |
+$DSFROMKEY -12 -C -f - -T 1 cds-update.secure |
+sed "s/^/update add /"
+dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
+grep "DNSKEY.257" | sed 's/DNSKEY.257/DNSKEY 258/' |
+$DSFROMKEY -12 -C -A -f - -T 1 cds-update.secure |
+sed "s/^/update add /"
+echo send
+) | $NSUPDATE
+dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 4 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that negative unknown NSEC3 hash algorithm does not validate ($n)"
+ret=0
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example A > dig.out.ns3.test$n
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example A > dig.out.ns4.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: SERVFAIL," dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDNSKEY records are signed using KSK by dnssec-signzone ($n)"
+ret=0
+dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDNSKEY records are not signed using ZSK by dnssec-signzone -x ($n)"
+ret=0
+dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-x.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that negative unknown NSEC3 hash algorithm with OPTOUT does not validate ($n)"
+ret=0
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example A > dig.out.ns3.test$n
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example A > dig.out.ns4.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: SERVFAIL," dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDNSKEY records are signed using KSK by with dnssec-auto ($n)"
+ret=0
+dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-auto.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that unknown DNSKEY algorithm validates as insecure ($n)"
+ret=0
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unknown.example A > dig.out.ns3.test$n
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unknown.example A > dig.out.ns4.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that unsupported DNSKEY algorithm validates as insecure ($n)"
+ret=0
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported.example A > dig.out.ns3.test$n
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unsupported.example A > dig.out.ns4.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that unsupported DNSKEY algorithm is in DNSKEY RRset ($n)"
+ret=0
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported-2.example DNSKEY > dig.out.test$n
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+grep "dnskey-unsupported-2\.example\..*IN.*DNSKEY.*257 3 255" dig.out.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# TODO: test case for GL #1689.
+# If we allow the dnssec tools to use deprecated algorithms (such as RSAMD5)
+# we could write a test that signs a zone with supported and unsupported
+# algorithm, apply a fixed rrset order such that the unsupported algorithm
+# precedes the supported one in the DNSKEY RRset, and verify the result still
+# validates succesfully.
+
+echo_i "check that a CDNSKEY deletion record is accepted ($n)"
+ret=0
+(
+echo zone cdnskey-update.secure
+echo server 10.53.0.2 "$PORT"
+echo update delete cdnskey-update.secure CDNSKEY
+echo update add cdnskey-update.secure 0 CDNSKEY 0 3 0 AA==
+echo send
+) | $NSUPDATE > nsupdate.out.test$n 2>&1
+dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
+lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "${lines:-10}" -eq 1 || ret=1
+lines=$(awk '$4 == "CDNSKEY" && $5 == "0" && $6 == "3" && $7 == "0" && $8 == "AA==" {print}' dig.out.test$n | wc -l)
+test "${lines:-10}" -eq 1 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that unknown DNSKEY algorithm + unknown NSEC3 has algorithm validates as insecure ($n)"
+ret=0
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-nsec3-unknown.example A > dig.out.ns3.test$n
+dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-nsec3-unknown.example A > dig.out.ns4.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDNSKEY records are signed using KSK when added by nsupdate ($n)"
+ret=0
+(
+echo zone cdnskey-update.secure
+echo server 10.53.0.2 "$PORT"
+echo update delete cdnskey-update.secure CDNSKEY
+dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
+sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
+echo send
+) | $NSUPDATE
+dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDNSKEY records are signed only using KSK when added by"
+echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
+ret=0
+keyid=$(cat ns2/cdnskey-kskonly.secure.id)
+(
+echo zone cdnskey-kskonly.secure
+echo server 10.53.0.2 "$PORT"
+echo update delete cdnskey-kskonly.secure CDNSKEY
+dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-kskonly.secure |
+sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
+echo send
+) | $NSUPDATE
+dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-kskonly.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDNSKEY" && $11 == id {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that CDNSKEY deletion records are signed only using KSK when added by"
+echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
+ret=0
+keyid=$(cat ns2/cdnskey-kskonly.secure.id)
+(
+echo zone cdnskey-kskonly.secure
+echo server 10.53.0.2 "$PORT"
+echo update delete cdnskey-kskonly.secure CDNSKEY
+echo update add cdnskey-kskonly.secure 0 CDNSKEY 0 3 0 AA==
+echo send
+) | $NSUPDATE
+dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-kskonly.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDNSKEY" && $11 == id {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+lines=$(awk '$4 == "CDNSKEY" && $5 == "0" && $6 == "3" && $7 == "0" && $8 == "AA==" {print}' dig.out.test$n | wc -l)
+test "${lines:-10}" -eq 1 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking initialization with a revoked managed key ($n)"
+ret=0
+copy_setports ns5/named2.conf.in ns5/named.conf
+rndccmd 10.53.0.5 reconfig 2>&1 | sed 's/^/ns5 /' | cat_i
+sleep 3
+dig_with_opts +dnssec @10.53.0.5 SOA . > dig.out.ns5.test$n
+grep "status: SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that a non matching CDNSKEY record is accepted with a matching CDNSKEY record ($n)"
+ret=0
+(
+echo zone cdnskey-update.secure
+echo server 10.53.0.2 "$PORT"
+echo update delete cdnskey-update.secure CDNSKEY
+dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
+sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
+dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
+sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 258/p'
+echo send
+) | $NSUPDATE
+dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
+lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
+test "$lines" -eq 2 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that RRSIGs are correctly removed from apex when RRset is removed NSEC ($n)"
+ret=0
+# generate signed zone with MX and AAAA records at apex.
+(
+cd signer || exit 1
+$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fK remove > /dev/null
+$KEYGEN -q -a $DEFAULT_ALGORITHM -33 remove > /dev/null
+echo > remove.db.signed
+$SIGNER -S -o remove -D -f remove.db.signed remove.db.in > signer.out.1.$n
+)
+grep "RRSIG MX" signer/remove.db.signed > /dev/null || {
+ ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.pre$n;
+}
+# re-generate signed zone without MX and AAAA records at apex.
+(
+cd signer || exit 1
+$SIGNER -S -o remove -D -f remove.db.signed remove2.db.in > signer.out.2.$n
+)
+grep "RRSIG MX" signer/remove.db.signed > /dev/null && {
+ ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.post$n;
+}
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that RRSIGs are correctly removed from apex when RRset is removed NSEC3 ($n)"
+ret=0
+# generate signed zone with MX and AAAA records at apex.
+(
+cd signer || exit 1
+echo > remove.db.signed
+$SIGNER -3 - -S -o remove -D -f remove.db.signed remove.db.in > signer.out.1.$n
+)
+grep "RRSIG MX" signer/remove.db.signed > /dev/null || {
+ ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.pre$n;
+}
+# re-generate signed zone without MX and AAAA records at apex.
+(
+cd signer || exit 1
+$SIGNER -3 - -S -o remove -D -f remove.db.signed remove2.db.in > signer.out.2.$n
+)
+grep "RRSIG MX" signer/remove.db.signed > /dev/null && {
+ ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.post$n;
+}
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that a named managed zone that was signed 'in-the-future' is re-signed when loaded ($n)"
+ret=0
+dig_with_opts managed-future.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that trust-anchor-telemetry queries are logged ($n)"
+ret=0
+grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/NULL" ns6/named.run > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that _ta-XXXX trust-anchor-telemetry queries are logged ($n)"
+ret=0
+grep "trust-anchor-telemetry '_ta-[0-9a-f]*/IN' from" ns1/named.run > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that _ta-AAAA trust-anchor-telemetry are not sent when disabled ($n)"
+ret=0
+grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/IN" ns1/named.run > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that KEY-TAG trust-anchor-telemetry queries are logged ($n)"
+ret=0
+dig_with_opts . dnskey +ednsopt=KEY-TAG:ffff @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "trust-anchor-telemetry './IN' from .* 65535" ns1/named.run > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that multiple KEY-TAG trust-anchor-telemetry options don't leak memory ($n)"
+ret=0
+dig_with_opts . dnskey +ednsopt=KEY-TAG:fffe +ednsopt=KEY-TAG:fffd @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "trust-anchor-telemetry './IN' from .* 65534" ns1/named.run > /dev/null || ret=1
+grep "trust-anchor-telemetry './IN' from .* 65533" ns1/named.run > /dev/null && ret=1
+stop_server ns1 || ret=1
+nextpart ns1/named.run > /dev/null
+start_server --noclean --restart --port ${PORT} ns1 || ret=1
+n=$(($n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "waiting for root server to finish reloading ($n)"
+ret=0
+wait_for_log 20 "all zones loaded" ns1/named.run || ret=1
+n=$(($n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that the view is logged in messages from the validator when using views ($n)"
+ret=0
+grep "view rec: *validat" ns4/named.run > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that DNAME at apex with NSEC3 is correctly signed (dnssec-signzone) ($n)"
+ret=0
+dig_with_opts txt dname-at-apex-nsec3.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "RRSIG.NSEC3 $DEFAULT_ALGORITHM_NUMBER 3 600" dig.out.ns3.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "check that DNSKEY and other occluded data are excluded from the delegating bitmap ($n)"
+ret=0
+dig_with_opts axfr occluded.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "^delegation.occluded.example..*NSEC.*NS KEY DS RRSIG NSEC$" dig.out.ns3.test$n > /dev/null || ret=1
+grep "^delegation.occluded.example..*DNSKEY.*" dig.out.ns3.test$n > /dev/null || ret=1
+grep "^delegation.occluded.example..*AAAA.*" dig.out.ns3.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking DNSSEC records are occluded from ANY in an insecure zone ($n)"
+ret=0
+dig_with_opts any x.insecure.example. @10.53.0.3 > dig.out.ns3.1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.1.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns3.1.test$n > /dev/null || ret=1
+dig_with_opts any zz.secure.example. @10.53.0.3 > dig.out.ns3.2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.2.test$n > /dev/null || ret=1
+# DNSKEY+RRSIG, NSEC+RRSIG
+grep "ANSWER: 4," dig.out.ns3.2.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# DNSSEC tests related to unsupported, disabled and revoked trust anchors.
+#
+
+# This nameserver (ns8) is loaded with a bunch of trust anchors. Some of
+# them are good (enabled.managed, enabled.trusted, secure.managed,
+# secure.trusted), and some of them are bad (disabled.managed,
+# revoked.managed, unsupported.managed, disabled.trusted, revoked.trusted,
+# unsupported.trusted). Make sure that the bad trust anchors are ignored.
+# This is tested by looking for the corresponding lines in the logfile.
+echo_i "checking that keys with unsupported algorithms and disabled algorithms are ignored ($n)"
+ret=0
+grep -q "ignoring static-key for 'disabled\.trusted\.': algorithm is disabled" ns8/named.run || ret=1
+grep -q "ignoring static-key for 'unsupported\.trusted\.': algorithm is unsupported" ns8/named.run || ret=1
+grep -q "ignoring static-key for 'revoked\.trusted\.': bad key type" ns8/named.run || ret=1
+grep -q "ignoring initial-key for 'disabled\.managed\.': algorithm is disabled" ns8/named.run || ret=1
+grep -q "ignoring initial-key for 'unsupported\.managed\.': algorithm is unsupported" ns8/named.run || ret=1
+grep -q "ignoring initial-key for 'revoked\.managed\.': bad key type" ns8/named.run || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# The next two tests are fairly normal DNSSEC queries to signed zones with a
+# default algorithm. First, a query is made against the server that is
+# authoritative for the given zone (ns3). Second, a query is made against a
+# resolver with trust anchors for the given zone (ns8). Both are expected to
+# return an authentic data positive response.
+echo_i "checking that a trusted key using a supported algorithm validates as secure ($n)"
+ret=0
+dig_with_opts @10.53.0.3 a.secure.trusted A > dig.out.ns3.test$n
+dig_with_opts @10.53.0.8 a.secure.trusted A > dig.out.ns8.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that a managed key using a supported algorithm validates as secure ($n)"
+ret=0
+dig_with_opts @10.53.0.3 a.secure.managed A > dig.out.ns3.test$n
+dig_with_opts @10.53.0.8 a.secure.managed A > dig.out.ns8.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# The next two queries ensure that a zone signed with a DNSKEY with an unsupported
+# algorithm will yield insecure positive responses. These trust anchors in ns8 are
+# ignored and so this domain is treated as insecure. The AD bit should not be set
+# in the response.
+echo_i "checking that a trusted key using an unsupported algorithm validates as insecure ($n)"
+ret=0
+dig_with_opts @10.53.0.3 a.unsupported.trusted A > dig.out.ns3.test$n
+dig_with_opts @10.53.0.8 a.unsupported.trusted A > dig.out.ns8.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that a managed key using an unsupported algorithm validates as insecure ($n)"
+ret=0
+dig_with_opts @10.53.0.3 a.unsupported.managed A > dig.out.ns3.test$n
+dig_with_opts @10.53.0.8 a.unsupported.managed A > dig.out.ns8.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# The next two queries ensure that a zone signed with a DNSKEY that the nameserver
+# has a disabled algorithm match for will yield insecure positive responses.
+# These trust anchors in ns8 are ignored and so this domain is treated as insecure.
+# The AD bit should not be set in the response.
+echo_i "checking that a trusted key using a disabled algorithm validates as insecure ($n)"
+ret=0
+dig_with_opts @10.53.0.3 a.disabled.trusted A > dig.out.ns3.test$n
+dig_with_opts @10.53.0.8 a.disabled.trusted A > dig.out.ns8.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that a managed key using a disabled algorithm validates as insecure ($n)"
+ret=0
+dig_with_opts @10.53.0.3 a.disabled.managed A > dig.out.ns3.test$n
+dig_with_opts @10.53.0.8 a.disabled.managed A > dig.out.ns8.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# The next two queries ensure that a zone signed with a DNSKEY that the
+# nameserver has a disabled algorithm for, but for a different domain, will
+# yield secure positive responses. Since "enabled.trusted." and
+# "enabled.managed." do not match the "disable-algorithms" option, no
+# special rules apply and these zones should validate as secure, with the AD
+# bit set.
+echo_i "checking that a trusted key using an algorithm disabled for another domain validates as secure ($n)"
+ret=0
+dig_with_opts @10.53.0.3 a.enabled.trusted A > dig.out.ns3.test$n
+dig_with_opts @10.53.0.8 a.enabled.trusted A > dig.out.ns8.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that a managed key using an algorithm disabled for another domain validates as secure ($n)"
+ret=0
+dig_with_opts @10.53.0.3 a.enabled.managed A > dig.out.ns3.test$n
+dig_with_opts @10.53.0.8 a.enabled.managed A > dig.out.ns8.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# A configured revoked trust anchor is ignored and thus the two queries below
+# should result in insecure responses, since no trust points for the
+# "revoked.trusted." and "revoked.managed." zones are created.
+echo_i "checking that a trusted key that is revoked validates as insecure ($n)"
+ret=0
+dig_with_opts @10.53.0.3 a.revoked.trusted A > dig.out.ns3.test$n
+dig_with_opts @10.53.0.8 a.revoked.trusted A > dig.out.ns8.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that a managed key that is revoked validates as insecure ($n)"
+ret=0
+dig_with_opts @10.53.0.3 a.revoked.managed A > dig.out.ns3.test$n
+dig_with_opts @10.53.0.8 a.revoked.managed A > dig.out.ns8.test$n
+grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
+grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+###
+### Additional checks for when the KSK is offline.
+###
+
+# Save some useful information
+zone="updatecheck-kskonly.secure"
+KSK=$(cat ns2/${zone}.ksk.key)
+ZSK=$(cat ns2/${zone}.zsk.key)
+KSK_ID=$(cat ns2/${zone}.ksk.id)
+ZSK_ID=$(cat ns2/${zone}.zsk.id)
+SECTIONS="+answer +noauthority +noadditional"
+echo_i "testing zone $zone KSK=$KSK_ID ZSK=$ZSK_ID"
+
+# Print IDs of keys used for generating RRSIG records for RRsets of type $1
+# found in dig output file $2.
+get_keys_which_signed() {
+ qtype=$1
+ output=$2
+ # The key ID is the 11th column of the RRSIG record line.
+ awk -v qt="$qtype" '$4 == "RRSIG" && $5 == qt {print $11}' < "$output"
+}
+
+# Basic checks to make sure everything is fine before the KSK is made offline.
+for qtype in "DNSKEY" "CDNSKEY" "CDS"
+do
+ echo_i "checking $qtype RRset is signed with KSK only (update-check-ksk, dnssec-ksk-only) ($n)"
+ ret=0
+ dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
+ lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
+ test "$lines" -eq 1 || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+done
+
+echo_i "checking SOA RRset is signed with ZSK only (update-check-ksk and dnssec-ksk-only) ($n)"
+ret=0
+dig_with_opts $SECTIONS @10.53.0.2 soa $zone > dig.out.test$n
+lines=$(get_keys_which_signed "SOA" dig.out.test$n | wc -l)
+test "$lines" -eq 1 || ret=1
+get_keys_which_signed "SOA" dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
+get_keys_which_signed "SOA" dig.out.test$n | grep "^$ZSK_ID$" > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Roll the ZSK.
+zsk2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -K ns2 -n zone "$zone")
+keyfile_to_key_id "$zsk2" > ns2/$zone.zsk.id2
+ZSK_ID2=$(cat ns2/$zone.zsk.id2)
+
+echo_i "load new ZSK $ZSK_ID2 for $zone ($n)"
+ret=0
+dnssec_loadkeys_on 2 $zone || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Make new ZSK active.
+echo_i "make ZSK $ZSK_ID inactive and make new ZSK $ZSK_ID2 active for zone $zone ($n)"
+ret=0
+$SETTIME -I now -K ns2 $ZSK > /dev/null
+$SETTIME -A now -K ns2 $zsk2 > /dev/null
+dnssec_loadkeys_on 2 $zone || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Remove the KSK from disk.
+echo_i "remove the KSK $KSK_ID for zone $zone from disk"
+mv ns2/$KSK.key ns2/$KSK.key.bak
+mv ns2/$KSK.private ns2/$KSK.private.bak
+
+# Update the zone that requires a resign of the SOA RRset.
+echo_i "update the zone with $zone IN TXT nsupdate added me"
+(
+echo zone $zone
+echo server 10.53.0.2 "$PORT"
+echo update add $zone. 300 in txt "nsupdate added me"
+echo send
+) | $NSUPDATE
+
+# Redo the tests now that the zone is updated and the KSK is offline.
+for qtype in "DNSKEY" "CDNSKEY" "CDS"
+do
+ echo_i "checking $qtype RRset is signed with KSK only, KSK offline (update-check-ksk, dnssec-ksk-only) ($n)"
+ ret=0
+ dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
+ lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
+ test "$lines" -eq 1 || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+done
+
+for qtype in "SOA" "TXT"
+do
+ echo_i "checking $qtype RRset is signed with ZSK only, KSK offline (update-check-ksk and dnssec-ksk-only) ($n)"
+ ret=0
+ dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
+ lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
+ test "$lines" -eq 1 || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+done
+
+# Put back the KSK.
+echo_i "put back the KSK $KSK_ID for zone $zone from disk"
+mv ns2/$KSK.key.bak ns2/$KSK.key
+mv ns2/$KSK.private.bak ns2/$KSK.private
+
+# Roll the ZSK again.
+zsk3=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -K ns2 -n zone "$zone")
+keyfile_to_key_id "$zsk3" > ns2/$zone.zsk.id3
+ZSK_ID3=$(cat ns2/$zone.zsk.id3)
+
+# Schedule the new ZSK (ZSK3) to become active.
+echo_i "delete old ZSK $ZSK_ID schedule ZSK $ZSK_ID2 inactive and new ZSK $ZSK_ID3 active for zone $zone ($n)"
+$SETTIME -D now -K ns2 $ZSK > /dev/null
+$SETTIME -I +3600 -K ns2 $zsk2 > /dev/null
+$SETTIME -A +3600 -K ns2 $zsk3 > /dev/null
+dnssec_loadkeys_on 2 $zone || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Remove the KSK from disk.
+echo_i "remove the KSK $KSK_ID for zone $zone from disk"
+mv ns2/$KSK.key ns2/$KSK.key.bak
+mv ns2/$KSK.private ns2/$KSK.private.bak
+
+# Update the zone that requires a resign of the SOA RRset.
+echo_i "update the zone with $zone IN TXT nsupdate added me again"
+(
+echo zone $zone
+echo server 10.53.0.2 "$PORT"
+echo update add $zone. 300 in txt "nsupdate added me again"
+echo send
+) | $NSUPDATE
+
+# Redo the tests now that the ZSK roll has deleted the old key.
+for qtype in "DNSKEY" "CDNSKEY" "CDS"
+do
+ echo_i "checking $qtype RRset is signed with KSK only, old ZSK deleted (update-check-ksk, dnssec-ksk-only) ($n)"
+ ret=0
+ dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
+ lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
+ test "$lines" -eq 1 || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null && ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+done
+
+for qtype in "SOA" "TXT"
+do
+ echo_i "checking $qtype RRset is signed with ZSK only, old ZSK deleted (update-check-ksk and dnssec-ksk-only) ($n)"
+ ret=0
+ dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
+ lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
+ test "$lines" -eq 1 || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null && ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+done
+
+# Make the new ZSK (ZSK3) active.
+echo_i "make new ZSK $ZSK_ID3 active for zone $zone ($n)"
+$SETTIME -I +1 -K ns2 $zsk2 > /dev/null
+$SETTIME -A +1 -K ns2 $zsk3 > /dev/null
+dnssec_loadkeys_on 2 $zone || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Wait for newest ZSK to become active.
+echo_i "wait until new ZSK $ZSK_ID3 active and ZSK $ZSK_ID2 inactive"
+for i in 1 2 3 4 5 6 7 8 9 10; do
+ ret=0
+ grep "DNSKEY $zone/$DEFAULT_ALGORITHM/$ZSK_ID3 (ZSK) is now active" ns2/named.run > /dev/null || ret=1
+ grep "DNSKEY $zone/$DEFAULT_ALGORITHM/$ZSK_ID2 (ZSK) is now inactive" ns2/named.run > /dev/null || ret=1
+ [ "$ret" -eq 0 ] && break
+ sleep 1
+done
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Update the zone that requires a resign of the SOA RRset.
+echo_i "update the zone with $zone IN TXT nsupdate added me one more time"
+(
+echo zone $zone
+echo server 10.53.0.2 "$PORT"
+echo update add $zone. 300 in txt "nsupdate added me one more time"
+echo send
+) | $NSUPDATE
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Redo the tests one more time.
+for qtype in "DNSKEY" "CDNSKEY" "CDS"
+do
+ echo_i "checking $qtype RRset is signed with KSK only, new ZSK active (update-check-ksk, dnssec-ksk-only) ($n)"
+ ret=0
+ dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
+ lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
+ test "$lines" -eq 1 || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null && ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+done
+
+for qtype in "SOA" "TXT"
+do
+ echo_i "checking $qtype RRset is signed with ZSK only, new ZSK active (update-check-ksk and dnssec-ksk-only) ($n)"
+ ret=0
+ dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
+ lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
+ test "$lines" -eq 1 || ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
+ get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null || ret=1
+ n=$((n+1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+done
+
+echo_i "checking secroots output with multiple views ($n)"
+ret=0
+rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i
+cp ns4/named.secroots named.secroots.test$n
+check_secroots_layout named.secroots.test$n || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking sig-validity-interval second field hours vs days ($n)"
+ret=0
+# zone configured with 'sig-validity-interval 500 499;'
+# 499 days in the future w/ a 20 minute runtime to now allowance
+min=$(TZ=UTC $PERL -e '@lt=localtime(time() + 499*3600*24 - 20*60); printf "%.4d%0.2d%0.2d%0.2d%0.2d%0.2d\n",$lt[5]+1900,$lt[4]+1,$lt[3],$lt[2],$lt[1],$lt[0];')
+dig_with_opts @10.53.0.2 hours-vs-days AXFR > dig.out.ns2.test$n
+awk -v min=$min '$4 == "RRSIG" { if ($9 < min) { exit(1); } }' dig.out.ns2.test$n || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking validation succeeds during transition to signed ($n)"
+ret=0
+dig_with_opts @10.53.0.4 inprogress A > dig.out.ns4.test$n || ret=1
+grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
+grep 'A.10\.53\.0\.10' dig.out.ns4.test$n >/dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking excessive NSEC3 iteration warnings in named.run ($n)"
+ret=0
+grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 150" ns2/named.run >/dev/null 2>&1 || ret=1
+grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 150" ns3/named.run >/dev/null 2>&1 || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Check that the validating resolver will fallback to insecure if the answer
+# contains NSEC3 records with high iteration count.
+echo_i "checking fallback to insecure when NSEC3 iterations is too high (nxdomain) ($n)"
+ret=0
+dig_with_opts @10.53.0.2 does-not-exist.too-many-iterations > dig.out.ns2.test$n || ret=1
+dig_with_opts @10.53.0.4 does-not-exist.too-many-iterations > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
+grep "ANSWER: 0, AUTHORITY: 6" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking fallback to insecure when NSEC3 iterations is too high (nodata) ($n)"
+ret=0
+dig_with_opts @10.53.0.2 a.too-many-iterations txt > dig.out.ns2.test$n || ret=1
+dig_with_opts @10.53.0.4 a.too-many-iterations txt > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
+grep "ANSWER: 0, AUTHORITY: 4" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking fallback to insecure when NSEC3 iterations is too high (wildcard) ($n)"
+ret=0
+dig_with_opts @10.53.0.2 wild.a.too-many-iterations > dig.out.ns2.test$n || ret=1
+dig_with_opts @10.53.0.4 wild.a.too-many-iterations > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
+grep 'wild\.a\.too-many-iterations\..*A.10\.0\.0\.3' dig.out.ns4.test$n >/dev/null || ret=1
+grep "ANSWER: 2, AUTHORITY: 4" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking fallback to insecure when NSEC3 iterations is too high (wildcard nodata) ($n)"
+ret=0
+dig_with_opts @10.53.0.2 type100 wild.a.too-many-iterations > dig.out.ns2.test$n || ret=1
+dig_with_opts @10.53.0.4 type100 wild.a.too-many-iterations > dig.out.ns4.test$n || ret=1
+digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
+grep "ANSWER: 0, AUTHORITY: 8" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n+1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Check that a query against a validating resolver succeeds when there is
+# a negative cache entry with trust level "pending" for the DS. Prime
+# with a +cd DS query to produce the negative cache entry, then send a
+# query that uses that entry as part of the validation process. [GL #3279]
+echo_i "check that pending negative DS cache entry validates ($n)"
+ret=0
+dig_with_opts @10.53.0.4 +cd insecure2.example. ds > dig.out.prime.ns4.test$n || ret=1
+grep "flags: qr rd ra cd;" dig.out.prime.ns4.test$n >/dev/null || ret=1
+grep "status: NOERROR" dig.out.prime.ns4.test$n >/dev/null || ret=1
+grep "ANSWER: 0, AUTHORITY: 4, " dig.out.prime.ns4.test$n > /dev/null || ret=1
+dig_with_opts @10.53.0.4 a.insecure2.example. a > dig.out.ns4.test$n || ret=1
+grep "ANSWER: 1, AUTHORITY: 1, " dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dnssec/tests_sh_dnssec.py b/bin/tests/system/dnssec/tests_sh_dnssec.py
new file mode 100644
index 0000000..65c3d43
--- /dev/null
+++ b/bin/tests/system/dnssec/tests_sh_dnssec.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_dnssec(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/dnstap/README b/bin/tests/system/dnstap/README
new file mode 100644
index 0000000..856fe48
--- /dev/null
+++ b/bin/tests/system/dnstap/README
@@ -0,0 +1,27 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+The "large-answer.fstrm" file was generated by configuring a named instance
+compiled with --enable-dnstap and --enable-fixed-rrset with the following
+directives:
+
+ minimal-responses yes;
+ rrset-order { order fixed; };
+ dnstap { auth response; };
+ dnstap-identity none;
+ dnstap-output file "large-answer.fstrm";
+
+The captured RRset from the "example." zone was created using:
+
+ $GENERATE 1-48 @ IN A 127.0.0.$
+
+A server instance set up this way was then queried non-recursively (RD=0) for
+"example/A".
diff --git a/bin/tests/system/dnstap/bad-fstrm-reopen-interval.conf b/bin/tests/system/dnstap/bad-fstrm-reopen-interval.conf
new file mode 100644
index 0000000..fd673d6
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-reopen-interval.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-reopen-interval 1x;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-max.conf b/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-max.conf
new file mode 100644
index 0000000..cdab66b
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-max.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-buffer-hint 65537;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-min.conf b/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-min.conf
new file mode 100644
index 0000000..c5444e9
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-min.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-buffer-hint 1023;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-max.conf b/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-max.conf
new file mode 100644
index 0000000..05ab1d9
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-max.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-flush-timeout 0;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-min.conf b/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-min.conf
new file mode 100644
index 0000000..398b1ab
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-min.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-flush-timeout 601;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-max.conf b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-max.conf
new file mode 100644
index 0000000..d6c4120
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-max.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-input-queue-size 1;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-min.conf b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-min.conf
new file mode 100644
index 0000000..787f656
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-min.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-input-queue-size 16385;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-po2.conf b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-po2.conf
new file mode 100644
index 0000000..ae713d3
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-po2.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-input-queue-size 513;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-output-notify-threshold.conf b/bin/tests/system/dnstap/bad-fstrm-set-output-notify-threshold.conf
new file mode 100644
index 0000000..643e2b8
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-output-notify-threshold.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-output-notify-threshold 0;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-max.conf b/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-max.conf
new file mode 100644
index 0000000..853713f
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-max.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ /*
+ * This value is system dependent and matches IOV_MAX.
+ */
+ fstrm-set-output-queue-size 10000000;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-min.conf b/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-min.conf
new file mode 100644
index 0000000..7940c89
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-min.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-output-queue-size 1;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-max.conf b/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-max.conf
new file mode 100644
index 0000000..9cfa9e3
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-max.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-reopen-interval 601;
+};
diff --git a/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-min.conf b/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-min.conf
new file mode 100644
index 0000000..be6a640
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-min.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-reopen-interval 0;
+};
diff --git a/bin/tests/system/dnstap/bad-missing-dnstap-output-view.conf b/bin/tests/system/dnstap/bad-missing-dnstap-output-view.conf
new file mode 100644
index 0000000..853da36
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-missing-dnstap-output-view.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view "view" {
+ dnstap { client; auth; };
+};
diff --git a/bin/tests/system/dnstap/bad-missing-dnstap-output.conf b/bin/tests/system/dnstap/bad-missing-dnstap-output.conf
new file mode 100644
index 0000000..b5565e2
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-missing-dnstap-output.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnstap { client; auth; };
+ recursion yes;
+};
diff --git a/bin/tests/system/dnstap/bad-size-version.conf b/bin/tests/system/dnstap/bad-size-version.conf
new file mode 100644
index 0000000..8e31528
--- /dev/null
+++ b/bin/tests/system/dnstap/bad-size-version.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnstap-output unix "/tmp/dnstap.sock" size 10k versions 3;
+};
diff --git a/bin/tests/system/dnstap/clean.sh b/bin/tests/system/dnstap/clean.sh
new file mode 100644
index 0000000..b9e476f
--- /dev/null
+++ b/bin/tests/system/dnstap/clean.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.run.prev
+rm -f */named.stats
+rm -f dig.out*
+rm -f dnstap.*
+rm -f fstrm_capture.out.*
+rm -f ns*/dnstap.out
+rm -f ns*/dnstap.out.save
+rm -f ns*/dnstap.out.save.?
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.lock
+rm -f ns2/dnstap.out.*
+rm -f ns2/example.db ns2/example.db.jnl
+rm -f ns3/dnstap.out.*
+rm -f ydump.out
diff --git a/bin/tests/system/dnstap/good-dnstap-in-options.conf b/bin/tests/system/dnstap/good-dnstap-in-options.conf
new file mode 100644
index 0000000..17feb5e
--- /dev/null
+++ b/bin/tests/system/dnstap/good-dnstap-in-options.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnstap-output unix "/var/run/named/dnstap.sock";
+ dnstap-identity hostname;
+ dnstap { client response; };
+};
diff --git a/bin/tests/system/dnstap/good-dnstap-in-view.conf b/bin/tests/system/dnstap/good-dnstap-in-view.conf
new file mode 100644
index 0000000..2c17f6c
--- /dev/null
+++ b/bin/tests/system/dnstap/good-dnstap-in-view.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnstap-output unix "/var/run/named/dnstap.sock";
+ dnstap-identity hostname;
+};
+
+view "view" {
+ dnstap { client response; };
+};
diff --git a/bin/tests/system/dnstap/good-fstrm-reopen-interval.conf b/bin/tests/system/dnstap/good-fstrm-reopen-interval.conf
new file mode 100644
index 0000000..d525262
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-reopen-interval.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-reopen-interval 5m;
+};
diff --git a/bin/tests/system/dnstap/good-fstrm-set-buffer-hint.conf b/bin/tests/system/dnstap/good-fstrm-set-buffer-hint.conf
new file mode 100644
index 0000000..c550647
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-buffer-hint.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-buffer-hint 8192;
+};
diff --git a/bin/tests/system/dnstap/good-fstrm-set-flush-timeout.conf b/bin/tests/system/dnstap/good-fstrm-set-flush-timeout.conf
new file mode 100644
index 0000000..dd9abf0
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-flush-timeout.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-flush-timeout 1;
+};
diff --git a/bin/tests/system/dnstap/good-fstrm-set-input-queue-size.conf b/bin/tests/system/dnstap/good-fstrm-set-input-queue-size.conf
new file mode 100644
index 0000000..d01b8f8
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-input-queue-size.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-input-queue-size 512;
+};
diff --git a/bin/tests/system/dnstap/good-fstrm-set-output-notify-threshold.conf b/bin/tests/system/dnstap/good-fstrm-set-output-notify-threshold.conf
new file mode 100644
index 0000000..2619dc0
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-output-notify-threshold.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-output-notify-threshold 32;
+};
diff --git a/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-mpsc.conf b/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-mpsc.conf
new file mode 100644
index 0000000..a81ff7c
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-mpsc.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-output-queue-model mpsc;
+};
diff --git a/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-spsc.conf b/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-spsc.conf
new file mode 100644
index 0000000..7b394eb
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-spsc.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-output-queue-model spsc;
+};
diff --git a/bin/tests/system/dnstap/good-fstrm-set-output-queue-size.conf b/bin/tests/system/dnstap/good-fstrm-set-output-queue-size.conf
new file mode 100644
index 0000000..87bf028
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-output-queue-size.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-output-queue-size 64;
+};
diff --git a/bin/tests/system/dnstap/good-fstrm-set-reopen-interval.conf b/bin/tests/system/dnstap/good-fstrm-set-reopen-interval.conf
new file mode 100644
index 0000000..116d3ae
--- /dev/null
+++ b/bin/tests/system/dnstap/good-fstrm-set-reopen-interval.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ fstrm-set-reopen-interval 5;
+};
diff --git a/bin/tests/system/dnstap/good-size-unlimited.conf b/bin/tests/system/dnstap/good-size-unlimited.conf
new file mode 100644
index 0000000..8cb9712
--- /dev/null
+++ b/bin/tests/system/dnstap/good-size-unlimited.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnstap-output file "/tmp/dnstap.log"
+ size unlimited versions unlimited suffix increment;
+};
diff --git a/bin/tests/system/dnstap/good-size-version.conf b/bin/tests/system/dnstap/good-size-version.conf
new file mode 100644
index 0000000..ca1fba3
--- /dev/null
+++ b/bin/tests/system/dnstap/good-size-version.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ dnstap-output file "/tmp/dnstap.log"
+ size 10k versions 3 suffix timestamp;
+};
diff --git a/bin/tests/system/dnstap/large-answer.fstrm b/bin/tests/system/dnstap/large-answer.fstrm
new file mode 100644
index 0000000..873b315
--- /dev/null
+++ b/bin/tests/system/dnstap/large-answer.fstrm
Binary files differ
diff --git a/bin/tests/system/dnstap/ns1/named.conf.in b/bin/tests/system/dnstap/ns1/named.conf.in
new file mode 100644
index 0000000..7f3fb29
--- /dev/null
+++ b/bin/tests/system/dnstap/ns1/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ statistics-file "named.stats";
+ dnstap-identity "ns1";
+ dnstap-version "xxx";
+ dnstap-output file "dnstap.out" size 30k versions 10;
+ dnstap { all; };
+ send-cookie no;
+ require-server-cookie no;
+ dnssec-validation yes;
+ qname-minimization disabled;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/dnstap/ns1/root.db b/bin/tests/system/dnstap/ns1/root.db
new file mode 100644
index 0000000..17780d1
--- /dev/null
+++ b/bin/tests/system/dnstap/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/dnstap/ns2/example.db.in b/bin/tests/system/dnstap/ns2/example.db.in
new file mode 100644
index 0000000..7f88dec
--- /dev/null
+++ b/bin/tests/system/dnstap/ns2/example.db.in
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+$ORIGIN example.
+a A 10.0.0.1
+a A 10.0.0.3
+a A 10.0.0.5
+ MX 10 mail.example.
+
+mail A 10.0.0.2
diff --git a/bin/tests/system/dnstap/ns2/named.conf.in b/bin/tests/system/dnstap/ns2/named.conf.in
new file mode 100644
index 0000000..badc225
--- /dev/null
+++ b/bin/tests/system/dnstap/ns2/named.conf.in
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ statistics-file "named.stats";
+ dnstap-identity "ns2";
+ dnstap-version "xxx";
+ dnstap-output file "dnstap.out" size unlimited versions unlimited;
+ dnstap { all; };
+ send-cookie no;
+ require-server-cookie no;
+ dnssec-validation yes;
+ qname-minimization disabled;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/dnstap/ns3/named.args b/bin/tests/system/dnstap/ns3/named.args
new file mode 100644
index 0000000..7937dee
--- /dev/null
+++ b/bin/tests/system/dnstap/ns3/named.args
@@ -0,0 +1,2 @@
+# Using "-n 1" allows GL #1795 to be reliably reproduced
+-D dnstap-ns3 -X named.lock -m record -c named.conf -d 99 -g -U 4 -n 1 -T maxcachesize=2097152
diff --git a/bin/tests/system/dnstap/ns3/named.conf.in b/bin/tests/system/dnstap/ns3/named.conf.in
new file mode 100644
index 0000000..a5ee2ed
--- /dev/null
+++ b/bin/tests/system/dnstap/ns3/named.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnstap-identity "ns3";
+ dnstap-version "xxx";
+ dnstap-output file "dnstap.out";
+ dnstap { all; };
+ send-cookie no;
+ require-server-cookie no;
+ minimal-responses no;
+ dnssec-validation yes;
+ qname-minimization disabled;
+};
+
+server 10.53.0.1 { tcp-only yes; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/dnstap/ns4/named.conf.in b/bin/tests/system/dnstap/ns4/named.conf.in
new file mode 100644
index 0000000..e2a9207
--- /dev/null
+++ b/bin/tests/system/dnstap/ns4/named.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnstap-identity "ns4";
+ dnstap-version "xxx";
+ dnstap-output unix "dnstap.out";
+ dnstap { all; };
+ send-cookie no;
+ require-server-cookie no;
+ dnssec-validation yes;
+ qname-minimization disabled;
+};
+
+server 10.53.0.1 { tcp-only yes; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/dnstap/prereq.sh b/bin/tests/system/dnstap/prereq.sh
new file mode 100644
index 0000000..f0748f3
--- /dev/null
+++ b/bin/tests/system/dnstap/prereq.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$FEATURETEST --enable-dnstap || {
+ echo_i "This test requires dnstap support." >&2
+ exit 255
+}
+exit 0
diff --git a/bin/tests/system/dnstap/setup.sh b/bin/tests/system/dnstap/setup.sh
new file mode 100644
index 0000000..90a257e
--- /dev/null
+++ b/bin/tests/system/dnstap/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
+
+cp ns2/example.db.in ns2/example.db
diff --git a/bin/tests/system/dnstap/tests.sh b/bin/tests/system/dnstap/tests.sh
new file mode 100644
index 0000000..c5d4f0a
--- /dev/null
+++ b/bin/tests/system/dnstap/tests.sh
@@ -0,0 +1,857 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+short -p ${PORT}"
+RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../common/rndc.conf"
+
+status=0
+
+# dnstap_data_ready <fstrm_capture_PID> <capture_file> <min_file_size>
+# Flushes capture_file and checks wheter its size is >= min_file_size.
+dnstap_data_ready() {
+ # Process id of running fstrm_capture.
+ fstrm_capture_pid=$1
+ # Output file provided to fstrm_capture via -w switch.
+ capture_file=$2
+ # Minimum expected file size.
+ min_size_expected=$3
+
+ kill -HUP $fstrm_capture_pid
+ file_size=$(wc -c < "$capture_file" | tr -d ' ')
+ if [ $file_size -lt $min_size_expected ]; then
+ return 1
+ fi
+}
+
+
+for bad in bad-*.conf
+do
+ ret=0
+ echo_i "checking that named-checkconf detects error in $bad"
+ { $CHECKCONF $bad > /dev/null 2>&1; rc=$?; } || true
+ if [ $rc != 1 ]; then echo_i "failed"; ret=1; fi
+ status=$((status + ret))
+done
+
+for good in good-*.conf
+do
+ ret=0
+ echo_i "checking that named-checkconf detects no error in $good"
+ { $CHECKCONF $good > /dev/null 2>&1; rc=$?; } || true
+ if [ $rc != 0 ]; then echo_i "failed"; ret=1; fi
+ status=$((status + ret))
+done
+
+echo_i "wait for servers to finish loading"
+ret=0
+wait_for_log 20 "all zones loaded" ns1/named.run || ret=1
+wait_for_log 20 "all zones loaded" ns2/named.run || ret=1
+wait_for_log 20 "all zones loaded" ns3/named.run || ret=1
+wait_for_log 20 "all zones loaded" ns4/named.run || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# both the 'a.example/A' lookup and the './NS' lookup to ns1
+# need to complete before reopening/rolling for the counts to
+# be correct.
+
+echo_i "prime cache"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 a.example > dig.out || true
+wait_for_log 20 "(.): reset client" ns1/named.run || true
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# check three different dnstap reopen/roll methods:
+# ns1: dnstap-reopen; ns2: dnstap -reopen; ns3: dnstap -roll
+mv ns1/dnstap.out ns1/dnstap.out.save
+mv ns2/dnstap.out ns2/dnstap.out.save
+
+if [ -n "$FSTRM_CAPTURE" ] ; then
+ ret=0
+ echo_i "starting fstrm_capture"
+ $FSTRM_CAPTURE -t protobuf:dnstap.Dnstap -u ns4/dnstap.out \
+ -w dnstap.out > fstrm_capture.out.1 2>&1 &
+ fstrm_capture_pid=$!
+ wait_for_log 10 "socket path ns4/dnstap.out" fstrm_capture.out.1 || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+echo_i "reopen/roll capture streams"
+ret=0
+$RNDCCMD -s 10.53.0.1 dnstap-reopen | sed 's/^/ns1 /' | cat_i
+$RNDCCMD -s 10.53.0.2 dnstap -reopen | sed 's/^/ns2 /' | cat_i
+$RNDCCMD -s 10.53.0.3 dnstap -roll | sed 's/^/ns3 /' | cat_i
+$RNDCCMD -s 10.53.0.4 dnstap -reopen | sed 's/^/ns4 /' | cat_i
+
+echo_i "send test traffic"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 a.example > dig.out || ret=1
+
+# send an UPDATE to ns2
+$NSUPDATE <<- EOF
+server 10.53.0.2 ${PORT}
+zone example
+update add b.example 3600 in a 10.10.10.10
+send
+EOF
+
+# XXX: file output should be flushed once a second according
+# to the libfstrm source, but it doesn't seem to happen until
+# enough data has accumulated. to get all the output, we stop
+# the name servers, forcing a flush on shutdown. it would be
+# nice to find a better way to do this.
+$RNDCCMD -s 10.53.0.1 stop | sed 's/^/ns1 /' | cat_i
+$RNDCCMD -s 10.53.0.2 stop | sed 's/^/ns2 /' | cat_i
+$RNDCCMD -s 10.53.0.3 stop | sed 's/^/ns3 /' | cat_i
+
+sleep 1
+
+echo_i "checking initial message counts"
+
+udp1=$($DNSTAPREAD ns1/dnstap.out.save | grep "UDP " | wc -l)
+tcp1=$($DNSTAPREAD ns1/dnstap.out.save | grep "TCP " | wc -l)
+aq1=$($DNSTAPREAD ns1/dnstap.out.save | grep "AQ " | wc -l)
+ar1=$($DNSTAPREAD ns1/dnstap.out.save | grep "AR " | wc -l)
+cq1=$($DNSTAPREAD ns1/dnstap.out.save | grep "CQ " | wc -l)
+cr1=$($DNSTAPREAD ns1/dnstap.out.save | grep "CR " | wc -l)
+rq1=$($DNSTAPREAD ns1/dnstap.out.save | grep "RQ " | wc -l)
+rr1=$($DNSTAPREAD ns1/dnstap.out.save | grep "RR " | wc -l)
+uq1=$($DNSTAPREAD ns1/dnstap.out.save | grep "UQ " | wc -l)
+ur1=$($DNSTAPREAD ns1/dnstap.out.save | grep "UR " | wc -l)
+
+udp2=$($DNSTAPREAD ns2/dnstap.out.save | grep "UDP " | wc -l)
+tcp2=$($DNSTAPREAD ns2/dnstap.out.save | grep "TCP " | wc -l)
+aq2=$($DNSTAPREAD ns2/dnstap.out.save | grep "AQ " | wc -l)
+ar2=$($DNSTAPREAD ns2/dnstap.out.save | grep "AR " | wc -l)
+cq2=$($DNSTAPREAD ns2/dnstap.out.save | grep "CQ " | wc -l)
+cr2=$($DNSTAPREAD ns2/dnstap.out.save | grep "CR " | wc -l)
+rq2=$($DNSTAPREAD ns2/dnstap.out.save | grep "RQ " | wc -l)
+rr2=$($DNSTAPREAD ns2/dnstap.out.save | grep "RR " | wc -l)
+uq2=$($DNSTAPREAD ns2/dnstap.out.save | grep "UQ " | wc -l)
+ur2=$($DNSTAPREAD ns2/dnstap.out.save | grep "UR " | wc -l)
+
+mv ns3/dnstap.out.0 ns3/dnstap.out.save
+udp3=$($DNSTAPREAD ns3/dnstap.out.save | grep "UDP " | wc -l)
+tcp3=$($DNSTAPREAD ns3/dnstap.out.save | grep "TCP " | wc -l)
+aq3=$($DNSTAPREAD ns3/dnstap.out.save | grep "AQ " | wc -l)
+ar3=$($DNSTAPREAD ns3/dnstap.out.save | grep "AR " | wc -l)
+cq3=$($DNSTAPREAD ns3/dnstap.out.save | grep "CQ " | wc -l)
+cr3=$($DNSTAPREAD ns3/dnstap.out.save | grep "CR " | wc -l)
+rq3=$($DNSTAPREAD ns3/dnstap.out.save | grep "RQ " | wc -l)
+rr3=$($DNSTAPREAD ns3/dnstap.out.save | grep "RR " | wc -l)
+uq3=$($DNSTAPREAD ns3/dnstap.out.save | grep "UQ " | wc -l)
+ur3=$($DNSTAPREAD ns3/dnstap.out.save | grep "UR " | wc -l)
+
+echo_i "checking UDP message counts"
+ret=0
+[ $udp1 -eq 0 ] || {
+ echo_i "ns1 $udp1 expected 0"
+ ret=1
+}
+[ $udp2 -eq 2 ] || {
+ echo_i "ns2 $udp2 expected 2"
+ ret=1
+}
+[ $udp3 -eq 4 ] || {
+ echo_i "ns3 $udp3 expected 4"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TCP message counts"
+ret=0
+[ $tcp1 -eq 6 ] || {
+ echo_i "ns1 $tcp1 expected 6"
+ ret=1
+}
+[ $tcp2 -eq 2 ] || {
+ echo_i "ns2 $tcp2 expected 2"
+ ret=1
+}
+[ $tcp3 -eq 6 ] || {
+ echo_i "ns3 $tcp3 expected 6"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AUTH_QUERY message counts"
+ret=0
+[ $aq1 -eq 3 ] || {
+ echo_i "ns1 $aq1 exepcted 3"
+ ret=1
+}
+[ $aq2 -eq 2 ] || {
+ echo_i "ns2 $aq2 expected 2"
+ ret=1
+}
+[ $aq3 -eq 1 ] || {
+ echo_i "ns3 $aq3 expected 1"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AUTH_RESPONSE message counts"
+ret=0
+[ $ar1 -eq 2 ] || {
+ echo_i "ns1 $ar1 expected 2"
+ ret=1
+}
+[ $ar2 -eq 1 ] || {
+ echo_i "ns2 $ar2 expected 1"
+ ret=1
+}
+[ $ar3 -eq 0 ] || {
+ echo_i "ns3 $ar3 expected 0"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking CLIENT_QUERY message counts"
+ret=0
+[ $cq1 -eq 0 ] || {
+ echo_i "ns1 $cq1 expected 0"
+ ret=1
+}
+[ $cq2 -eq 0 ] || {
+ echo_i "ns2 $cq2 expected 0"
+ ret=1
+}
+[ $cq3 -eq 1 ] || {
+ echo_i "ns3 $cq3 expected 1"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking CLIENT_RESPONSE message counts"
+ret=0
+[ $cr1 -eq 1 ] || {
+ echo_i "ns1 $cr1 expected 1"
+ ret=1
+}
+[ $cr2 -eq 1 ] || {
+ echo_i "ns2 $cr2 expected 1"
+ ret=1
+}
+[ $cr3 -eq 2 ] || {
+ echo_i "ns3 $cr3 expected 2"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking RESOLVER_QUERY message counts"
+ret=0
+[ $rq1 -eq 0 ] || {
+ echo_i "ns1 $rq1 expected 0"
+ ret=1
+}
+[ $rq2 -eq 0 ] || {
+ echo_i "ns2 $rq2 expected 0"
+ ret=1
+}
+[ $rq3 -eq 3 ] || {
+ echo_i "ns3 $rq3 expected 3"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking RESOLVER_RESPONSE message counts"
+ret=0
+[ $rr1 -eq 0 ] || {
+ echo_i "ns1 $rr1 expected 0"
+ ret=1
+}
+[ $rr2 -eq 0 ] || {
+ echo_i "ns2 $rr2 expected 0"
+ ret=1
+}
+[ $rr3 -eq 3 ] || {
+ echo_i "ns3 $rr3 expected 3"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking UPDATE_QUERY message counts"
+ret=0
+[ $uq1 -eq 0 ] || {
+ echo_i "ns1 $uq1 expected 0"
+ ret=1
+}
+[ $uq2 -eq 0 ] || {
+ echo_i "ns2 $uq2 expected 0"
+ ret=1
+}
+[ $uq3 -eq 0 ] || {
+ echo_i "ns3 $uq3 expected 0"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking UPDATE_RESPONSE message counts"
+ret=0
+[ $ur1 -eq 0 ] || {
+ echo_i "ns1 $ur1 expected 0"
+ ret=1
+}
+[ $ur2 -eq 0 ] || {
+ echo_i "ns2 $ur2 expected 0"
+ ret=1
+}
+[ $ur3 -eq 0 ] || {
+ echo_i "ns3 $ur3 expected 0"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking reopened message counts"
+
+udp1=$($DNSTAPREAD ns1/dnstap.out | grep "UDP " | wc -l)
+tcp1=$($DNSTAPREAD ns1/dnstap.out | grep "TCP " | wc -l)
+aq1=$($DNSTAPREAD ns1/dnstap.out | grep "AQ " | wc -l)
+ar1=$($DNSTAPREAD ns1/dnstap.out | grep "AR " | wc -l)
+cq1=$($DNSTAPREAD ns1/dnstap.out | grep "CQ " | wc -l)
+cr1=$($DNSTAPREAD ns1/dnstap.out | grep "CR " | wc -l)
+rq1=$($DNSTAPREAD ns1/dnstap.out | grep "RQ " | wc -l)
+rr1=$($DNSTAPREAD ns1/dnstap.out | grep "RR " | wc -l)
+uq1=$($DNSTAPREAD ns1/dnstap.out | grep "UQ " | wc -l)
+ur1=$($DNSTAPREAD ns1/dnstap.out | grep "UR " | wc -l)
+
+udp2=$($DNSTAPREAD ns2/dnstap.out | grep "UDP " | wc -l)
+tcp2=$($DNSTAPREAD ns2/dnstap.out | grep "TCP " | wc -l)
+aq2=$($DNSTAPREAD ns2/dnstap.out | grep "AQ " | wc -l)
+ar2=$($DNSTAPREAD ns2/dnstap.out | grep "AR " | wc -l)
+cq2=$($DNSTAPREAD ns2/dnstap.out | grep "CQ " | wc -l)
+cr2=$($DNSTAPREAD ns2/dnstap.out | grep "CR " | wc -l)
+rq2=$($DNSTAPREAD ns2/dnstap.out | grep "RQ " | wc -l)
+rr2=$($DNSTAPREAD ns2/dnstap.out | grep "RR " | wc -l)
+uq2=$($DNSTAPREAD ns2/dnstap.out | grep "UQ " | wc -l)
+ur2=$($DNSTAPREAD ns2/dnstap.out | grep "UR " | wc -l)
+
+udp3=$($DNSTAPREAD ns3/dnstap.out | grep "UDP " | wc -l)
+tcp3=$($DNSTAPREAD ns3/dnstap.out | grep "TCP " | wc -l)
+aq3=$($DNSTAPREAD ns3/dnstap.out | grep "AQ " | wc -l)
+ar3=$($DNSTAPREAD ns3/dnstap.out | grep "AR " | wc -l)
+cq3=$($DNSTAPREAD ns3/dnstap.out | grep "CQ " | wc -l)
+cr3=$($DNSTAPREAD ns3/dnstap.out | grep "CR " | wc -l)
+rq3=$($DNSTAPREAD ns3/dnstap.out | grep "RQ " | wc -l)
+rr3=$($DNSTAPREAD ns3/dnstap.out | grep "RR " | wc -l)
+uq3=$($DNSTAPREAD ns3/dnstap.out | grep "UQ " | wc -l)
+ur3=$($DNSTAPREAD ns3/dnstap.out | grep "UR " | wc -l)
+
+echo_i "checking UDP message counts"
+ret=0
+[ $udp1 -eq 0 ] || {
+ echo_i "ns1 $udp1 expected 0"
+ ret=1
+}
+[ $udp2 -eq 2 ] || {
+ echo_i "ns2 $udp2 expected 2"
+ ret=1
+}
+[ $udp3 -eq 2 ] || {
+ echo_i "ns3 $udp3 expected 2"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking TCP message counts"
+ret=0
+[ $tcp1 -eq 0 ] || {
+ echo_i "ns1 $tcp1 expected 0"
+ ret=1
+}
+[ $tcp2 -eq 0 ] || {
+ echo_i "ns2 $tcp2 expected 0"
+ ret=1
+}
+[ $tcp3 -eq 0 ] || {
+ echo_i "ns3 $tcp3 expected 0"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AUTH_QUERY message counts"
+ret=0
+[ $aq1 -eq 0 ] || {
+ echo_i "ns1 $aq1 exepcted 0"
+ ret=1
+}
+[ $aq2 -eq 0 ] || {
+ echo_i "ns2 $aq2 expected 0"
+ ret=1
+}
+[ $aq3 -eq 0 ] || {
+ echo_i "ns3 $aq3 expected 0"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AUTH_RESPONSE message counts"
+ret=0
+[ $ar1 -eq 0 ] || {
+ echo_i "ns1 $ar1 expected 0"
+ ret=1
+}
+[ $ar2 -eq 0 ] || {
+ echo_i "ns2 $ar2 expected 0"
+ ret=1
+}
+[ $ar3 -eq 0 ] || {
+ echo_i "ns3 $ar3 expected 0"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking CLIENT_QUERY message counts"
+ret=0
+[ $cq1 -eq 0 ] || {
+ echo_i "ns1 $cq1 expected 0"
+ ret=1
+}
+[ $cq2 -eq 0 ] || {
+ echo_i "ns2 $cq2 expected 0"
+ ret=1
+}
+[ $cq3 -eq 1 ] || {
+ echo_i "ns3 $cq3 expected 1"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking CLIENT_RESPONSE message counts"
+ret=0
+[ $cr1 -eq 0 ] || {
+ echo_i "ns1 $cr1 expected 0"
+ ret=1
+}
+[ $cr2 -eq 0 ] || {
+ echo_i "ns2 $cr2 expected 0"
+ ret=1
+}
+[ $cr3 -eq 1 ] || {
+ echo_i "ns3 $cr3 expected 1"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking RESOLVER_QUERY message counts"
+ret=0
+[ $rq1 -eq 0 ] || {
+ echo_i "ns1 $rq1 expected 0"
+ ret=1
+}
+[ $rq2 -eq 0 ] || {
+ echo_i "ns2 $rq2 expected 0"
+ ret=1
+}
+[ $rq3 -eq 0 ] || {
+ echo_i "ns3 $rq3 expected 0"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking RESOLVER_RESPONSE message counts"
+ret=0
+[ $rr1 -eq 0 ] || {
+ echo_i "ns1 $rr1 expected 0"
+ ret=1
+}
+[ $rr2 -eq 0 ] || {
+ echo_i "ns2 $rr2 expected 0"
+ ret=1
+}
+[ $rr3 -eq 0 ] || {
+ echo_i "ns3 $rr3 expected 0"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking UPDATE_QUERY message counts"
+ret=0
+[ $uq1 -eq 0 ] || {
+ echo_i "ns1 $uq1 expected 0"
+ ret=1
+}
+[ $uq2 -eq 1 ] || {
+ echo_i "ns2 $uq2 expected 1"
+ ret=1
+}
+[ $uq3 -eq 0 ] || {
+ echo_i "ns3 $uq3 expected 0"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking UPDATE_RESPONSE message counts"
+ret=0
+[ $ur1 -eq 0 ] || {
+ echo_i "ns1 $ur1 expected 0"
+ ret=1
+}
+[ $ur2 -eq 1 ] || {
+ echo_i "ns2 $ur2 expected 1"
+ ret=1
+}
+[ $ur3 -eq 0 ] || {
+ echo_i "ns3 $ur3 expected 0"
+ ret=1
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking whether destination UDP port is logged for client queries"
+ret=0
+$DNSTAPREAD ns3/dnstap.out.save | grep -Eq "CQ [0-9:.]+ -> 10.53.0.3:${PORT} UDP" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+HAS_PYYAML=0
+if [ -x "$PYTHON" ] ; then
+ $PYTHON -c "import yaml" 2> /dev/null && HAS_PYYAML=1
+fi
+
+if [ $HAS_PYYAML -ne 0 ] ; then
+ echo_i "checking dnstap-read YAML output"
+ ret=0
+ {
+ $PYTHON ydump.py "$DNSTAPREAD" "ns3/dnstap.out.save" > ydump.out || ret=1
+ } | cat_i
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+echo_i "checking dnstap-read hex output"
+ret=0
+hex=$($DNSTAPREAD -x ns3/dnstap.out | tail -1)
+echo $hex | $WIRETEST > dnstap.hex
+grep 'status: NOERROR' dnstap.hex > /dev/null 2>&1 || ret=1
+grep 'ANSWER: 3, AUTHORITY: 1' dnstap.hex > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if [ -n "$FSTRM_CAPTURE" ] ; then
+ $DIG $DIGOPTS @10.53.0.4 a.example > dig.out
+
+ # send an UPDATE to ns4
+ $NSUPDATE <<- EOF > nsupdate.out 2>&1 && ret=1
+ server 10.53.0.4 ${PORT}
+ zone example
+ update add b.example 3600 in a 10.10.10.10
+ send
+EOF
+ grep "update failed: NOTAUTH" nsupdate.out > /dev/null || ret=1
+
+ echo_i "checking unix socket message counts"
+ sleep 2
+ retry_quiet 5 dnstap_data_ready $fstrm_capture_pid dnstap.out 450 || {
+ echo_i "dnstap output file smaller than expected"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+ kill $fstrm_capture_pid
+ wait
+ udp4=$($DNSTAPREAD dnstap.out | grep "UDP " | wc -l)
+ tcp4=$($DNSTAPREAD dnstap.out | grep "TCP " | wc -l)
+ aq4=$($DNSTAPREAD dnstap.out | grep "AQ " | wc -l)
+ ar4=$($DNSTAPREAD dnstap.out | grep "AR " | wc -l)
+ cq4=$($DNSTAPREAD dnstap.out | grep "CQ " | wc -l)
+ cr4=$($DNSTAPREAD dnstap.out | grep "CR " | wc -l)
+ rq4=$($DNSTAPREAD dnstap.out | grep "RQ " | wc -l)
+ rr4=$($DNSTAPREAD dnstap.out | grep "RR " | wc -l)
+ uq4=$($DNSTAPREAD dnstap.out | grep "UQ " | wc -l)
+ ur4=$($DNSTAPREAD dnstap.out | grep "UR " | wc -l)
+
+ echo_i "checking UDP message counts"
+ ret=0
+ [ $udp4 -eq 4 ] || {
+ echo_i "ns4 $udp4 expected 4"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking TCP message counts"
+ ret=0
+ [ $tcp4 -eq 0 ] || {
+ echo_i "ns4 $tcp4 expected 0"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking AUTH_QUERY message counts"
+ ret=0
+ [ $aq4 -eq 0 ] || {
+ echo_i "ns4 $aq4 expected 0"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking AUTH_RESPONSE message counts"
+ ret=0
+ [ $ar4 -eq 0 ] || {
+ echo_i "ns4 $ar4 expected 0"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking CLIENT_QUERY message counts"
+ ret=0
+ [ $cq4 -eq 1 ] || {
+ echo_i "ns4 $cq4 expected 1"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking CLIENT_RESPONSE message counts"
+ ret=0
+ [ $cr4 -eq 1 ] || {
+ echo_i "ns4 $cr4 expected 1"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking RESOLVER_QUERY message counts"
+ ret=0
+ [ $rq4 -eq 0 ] || {
+ echo_i "ns4 $rq4 expected 0"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking RESOLVER_RESPONSE message counts"
+ ret=0
+ [ $rr4 -eq 0 ] || {
+ echo_i "ns4 $rr4 expected 0"
+ ret=1
+ }
+
+ echo_i "checking UPDATE_QUERY message counts"
+ ret=0
+ [ $uq4 -eq 1 ] || {
+ echo_i "ns4 $uq4 expected 1"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking UPDATE_RESPONSE message counts"
+ ret=0
+ [ $ur4 -eq 1 ] || {
+ echo_i "ns4 $ur4 expected 1"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ mv dnstap.out dnstap.out.save
+
+ echo_i "restarting fstrm_capture"
+ $FSTRM_CAPTURE -t protobuf:dnstap.Dnstap -u ns4/dnstap.out \
+ -w dnstap.out > fstrm_capture.out.2 2>&1 &
+ fstrm_capture_pid=$!
+ wait_for_log 10 "socket path ns4/dnstap.out" fstrm_capture.out.2 || {
+ echo_i "failed"
+ ret=1
+ }
+ $RNDCCMD -s 10.53.0.4 dnstap -reopen | sed 's/^/ns4 /' | cat_i
+ $DIG $DIGOPTS @10.53.0.4 a.example > dig.out
+
+ echo_i "checking reopened unix socket message counts"
+ sleep 2
+ retry_quiet 5 dnstap_data_ready $fstrm_capture_pid dnstap.out 270 || {
+ echo_i "dnstap output file smaller than expected"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+ kill $fstrm_capture_pid
+ wait
+ udp4=$($DNSTAPREAD dnstap.out | grep "UDP " | wc -l)
+ tcp4=$($DNSTAPREAD dnstap.out | grep "TCP " | wc -l)
+ aq4=$($DNSTAPREAD dnstap.out | grep "AQ " | wc -l)
+ ar4=$($DNSTAPREAD dnstap.out | grep "AR " | wc -l)
+ cq4=$($DNSTAPREAD dnstap.out | grep "CQ " | wc -l)
+ cr4=$($DNSTAPREAD dnstap.out | grep "CR " | wc -l)
+ rq4=$($DNSTAPREAD dnstap.out | grep "RQ " | wc -l)
+ rr4=$($DNSTAPREAD dnstap.out | grep "RR " | wc -l)
+ uq4=$($DNSTAPREAD dnstap.out | grep "UQ " | wc -l)
+ ur4=$($DNSTAPREAD dnstap.out | grep "UR " | wc -l)
+
+ echo_i "checking UDP message counts"
+ ret=0
+ [ $udp4 -eq 2 ] || {
+ echo_i "ns4 $udp4 expected 2"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking TCP message counts"
+ ret=0
+ [ $tcp4 -eq 0 ] || {
+ echo_i "ns4 $tcp4 expected 0"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking AUTH_QUERY message counts"
+ ret=0
+ [ $aq4 -eq 0 ] || {
+ echo_i "ns4 $aq4 expected 0"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking AUTH_RESPONSE message counts"
+ ret=0
+ [ $ar4 -eq 0 ] || {
+ echo_i "ns4 $ar4 expected 0"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking CLIENT_QUERY message counts"
+ ret=0
+ [ $cq4 -eq 1 ] || {
+ echo_i "ns4 $cq4 expected 1"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking CLIENT_RESPONSE message counts"
+ ret=0
+ [ $cr4 -eq 1 ] || {
+ echo_i "ns4 $cr4 expected 1"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking RESOLVER_QUERY message counts"
+ ret=0
+ [ $rq4 -eq 0 ] || {
+ echo_i "ns4 $rq4 expected 0"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking RESOLVER_RESPONSE message counts"
+ ret=0
+ [ $rr4 -eq 0 ] || {
+ echo_i "ns4 $rr4 expected 0"
+ ret=1
+ }
+
+ echo_i "checking UPDATE_QUERY message counts"
+ ret=0
+ [ $uq4 -eq 0 ] || {
+ echo_i "ns4 $uq4 expected 0"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ echo_i "checking UPDATE_RESPONSE message counts"
+ ret=0
+ [ $ur4 -eq 0 ] || {
+ echo_i "ns4 $ur4 expected 0"
+ ret=1
+ }
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+echo_i "checking large packet printing"
+ret=0
+# Expect one occurrence of "opcode: QUERY" below "reponse_message_data" and
+# another one below "response_message".
+lines=$($DNSTAPREAD -y large-answer.fstrm | grep -c "opcode: QUERY")
+[ $lines -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+_test_dnstap_roll() (
+ ip="$1"
+ ns="$2"
+ n="$3"
+
+ $RNDCCMD -s "${ip}" dnstap -roll "${n}" | sed "s/^/${ns} /" | cat_i &&
+ files=$(find "$ns" -name "dnstap.out.[0-9]" | wc -l) &&
+ test "$files" -eq "${n}" && test "$files" -ge "1" || return 1
+)
+
+
+test_dnstap_roll() {
+ echo_i "checking 'rndc -roll $4' ($1)"
+ ret=0
+
+ try=0
+ while test $try -lt 12
+ do
+ touch "$3/dnstap.out.$try"
+ try=$((try + 1))
+ done
+
+ _repeat 10 _test_dnstap_roll $2 $3 $4 || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+}
+
+start_server --noclean --restart --port "${PORT}" ns3
+test_dnstap_roll "no versions" 10.53.0.3 ns3 6
+test_dnstap_roll "no versions" 10.53.0.3 ns3 3
+test_dnstap_roll "no versions" 10.53.0.3 ns3 1
+
+start_server --noclean --restart --port "${PORT}" ns2
+test_dnstap_roll "versions" 10.53.0.2 ns2 6
+test_dnstap_roll "versions" 10.53.0.2 ns2 3
+test_dnstap_roll "versions" 10.53.0.2 ns2 1
+
+echo_i "exit status: $status"
+[ "$status" -eq 0 ] || exit 1
diff --git a/bin/tests/system/dnstap/tests_dnstap.py b/bin/tests/system/dnstap/tests_dnstap.py
new file mode 100644
index 0000000..ca687b0
--- /dev/null
+++ b/bin/tests/system/dnstap/tests_dnstap.py
@@ -0,0 +1,83 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import os
+import re
+import subprocess
+
+import pytest
+
+pytest.importorskip("dns", minversion="2.0.0")
+import dns.resolver
+
+
+def run_rndc(server, rndc_command):
+ """
+ Send the specified 'rndc_command' to 'server' with a timeout of 10 seconds
+ """
+ rndc = os.getenv("RNDC")
+ port = os.getenv("CONTROLPORT")
+
+ cmdline = [rndc, "-c", "../common/rndc.conf", "-p", port, "-s", server]
+ cmdline.extend(rndc_command)
+
+ subprocess.check_output(cmdline, stderr=subprocess.STDOUT, timeout=10)
+
+
+def test_dnstap_dispatch_socket_addresses(named_port):
+ # Prepare for querying ns3.
+ resolver = dns.resolver.Resolver()
+ resolver.nameservers = ["10.53.0.3"]
+ resolver.port = named_port
+
+ # Send some query to ns3 so that it records something in its dnstap file.
+ ans = resolver.resolve("mail.example.", "A")
+ assert ans[0].address == "10.0.0.2"
+
+ # Before continuing, roll dnstap file to ensure it is flushed to disk.
+ run_rndc("10.53.0.3", ["dnstap", "-roll", "1"])
+
+ # Move the dnstap file aside so that it is retained for troubleshooting.
+ os.rename(os.path.join("ns3", "dnstap.out.0"), "dnstap.out.resolver_addresses")
+
+ # Read the contents of the dnstap file using dnstap-read.
+ output = subprocess.check_output(
+ [os.getenv("DNSTAPREAD"), "dnstap.out.resolver_addresses"], encoding="utf-8"
+ )
+
+ # Check whether all frames contain the expected addresses.
+ #
+ # Expected dnstap-read output format:
+ #
+ # 22-Jun-2022 12:09:06.168 RR 10.53.0.3:0 -> 10.53.0.1:7523 TCP ...
+ # 22-Jun-2022 12:09:06.168 RR 10.53.0.3:0 <- 10.53.0.1:7523 TCP ...
+ # 22-Jun-2022 12:09:06.168 RQ 10.53.0.3:56306 -> 10.53.0.2:7523 UDP ...
+ # 22-Jun-2022 12:09:06.168 RQ 10.53.0.3:56306 <- 10.53.0.2:7523 UDP ...
+ #
+ bad_frames = []
+ inspected_frames = 0
+ addr_regex = r"^10\.53\.0\.[0-9]+:[0-9]{1,5}$"
+ for line in output.splitlines():
+ _, _, frame_type, addr1, _, addr2, _ = line.split(" ", 6)
+ # Only inspect RESOLVER_QUERY and RESOLVER_RESPONSE frames.
+ if frame_type not in ("RQ", "RR"):
+ continue
+ inspected_frames += 1
+ if not re.match(addr_regex, addr1) or not re.match(addr_regex, addr2):
+ bad_frames.append(line)
+
+ assert (
+ len(bad_frames) == 0
+ ), "{} out of {} inspected frames contain unexpected addresses:\n\n{}".format(
+ len(bad_frames), inspected_frames, "\n".join(bad_frames)
+ )
diff --git a/bin/tests/system/dnstap/tests_sh_dnstap.py b/bin/tests/system/dnstap/tests_sh_dnstap.py
new file mode 100644
index 0000000..8094f0d
--- /dev/null
+++ b/bin/tests/system/dnstap/tests_sh_dnstap.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_dnstap(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/dnstap/ydump.py b/bin/tests/system/dnstap/ydump.py
new file mode 100644
index 0000000..ab7e3c9
--- /dev/null
+++ b/bin/tests/system/dnstap/ydump.py
@@ -0,0 +1,29 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import sys
+
+try:
+ import yaml
+except (ModuleNotFoundError, ImportError):
+ print("No python yaml module, skipping")
+ sys.exit(1)
+
+import subprocess
+import pprint
+
+DNSTAP_READ = sys.argv[1]
+DATAFILE = sys.argv[2]
+ARGS = [DNSTAP_READ, "-y", DATAFILE]
+
+with subprocess.Popen(ARGS, stdout=subprocess.PIPE) as f:
+ for y in yaml.load_all(f.stdout, Loader=yaml.SafeLoader):
+ pprint.pprint(y)
diff --git a/bin/tests/system/doth/CA/CA.cfg b/bin/tests/system/doth/CA/CA.cfg
new file mode 100644
index 0000000..97ea088
--- /dev/null
+++ b/bin/tests/system/doth/CA/CA.cfg
@@ -0,0 +1,121 @@
+## How To
+# To issue a certificate:
+#
+# 1. Generate the next certificate serial (if the file does not exist):
+# xxd -l 8 -u -ps /dev/urandom > ./serial
+# 2. Create the new certificate request (e.g. for foo.example.com):
+# openssl req -config ./CA.cfg -new -subj "/CN=foo.example.com" \
+# -addext "subjectAltName=DNS:foo.example.com,IP=X.X.X.X" \
+# -newkey rsa -keyout ./certs/foo.example.com.key \
+# -out ./certs/foo.example.com.csr
+#
+# The above will generate request for an RSA-based certificate. One
+# can issue an ECDSA-based certificate by replacing "-newkey rsa" with
+# "-newkey ec -pkeyopt ec_paramgen_curve:secp384r1".
+#
+# 3. Issue the certificate:
+# openssl ca -config ./CA.cfg -in ./certs/foo.example.com.csr \
+# -out ./certs/foo.example.com.pem
+#
+# To cleanup the internal database from expired certificates:
+#
+# 1. openssl ca -config ./CA.cfg -updatedb
+#
+# To revoke a certificate:
+#
+# 1. Revoke the certificate via file (e.g. for foo.example.com):
+# openssl ca -config ./CA.cfg -revoke ./certs/foo.example.com.pem
+# 2. Optionally remove the certificate file if you do not need it anymore:
+# rm ./certs/foo.example.com.pem
+# 3. Generate the certificate revocation list file: CRL (e.g. revoked.crl):
+# openssl ca -config ./CA.cfg -gencrl > ./revoked.crl
+#
+# The key for CA was generated like follows
+# openssl genrsa -out ./CA.key 3072
+# openssl req -x509 -new -key ./CA.key -days 10950 -out ./CA.pem
+#
+# See also:
+#
+# - https://jamielinux.com/docs/openssl-certificate-authority/index.html
+# - https://www.openssl.org/docs/man1.1.1/man1/ca.html
+# - https://www.openssl.org/docs/man1.1.1/man1/openssl-req.html
+# - https://security.stackexchange.com/questions/74345/provide-subjectaltname-to-openssl-directly-on-the-command-line
+# - https://security.stackexchange.com/a/190646 - for ECDSA certificates
+# - https://gist.github.com/Soarez/9688998
+# - https://habr.com/ru/post/192446/ - Beware, your screen might "go Cyrillic"!
+
+# certificate authority configuration
+[ca]
+default_ca = CA_default # The default ca section
+
+[CA_default]
+dir = .
+new_certs_dir = $dir/newcerts # new certs dir (must be created)
+certificate = $dir/CA.pem # The CA cert
+private_key = $dir/private/CA.key # CA private key
+
+serial = $dir/serial # serial number file for the next certificate
+ # Update before issuing it:
+ # xxd -l 8 -u -ps /dev/urandom > ./serial
+database = $dir/index.txt # (must be created manually: touch ./index.txt)
+
+default_days = 10950 # how long to certify for
+
+#default_crl_days = 30 # the number of days before the
+default_crl_days = 10950 # next CRL is due. That is the
+ # days from now to place in the
+ # CRL nextUpdate field. If CRL
+ # is expired, certificate
+ # verifications will fail even
+ # for otherwise valid
+ # certificates. Clients might
+ # cache the CRL, so the expiry
+ # period should normally be
+ # relatively short (default:
+ # 30) for production CAs.
+
+default_md = sha256 # digest to use
+
+policy = policy_default # default policy
+email_in_dn = no # Don't add the email into cert DN
+
+name_opt = ca_default # Subject name display option
+cert_opt = ca_default # Certificate display option
+
+# We need the following in order to copy Subject Alt Name(s) from a
+# request to the certificate.
+copy_extensions = copy # copy extensions from request
+
+[policy_default]
+countryName = optional
+stateOrProvinceName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# default certificate requests settings
+[req]
+# Options for the `req` tool (`man req`).
+default_bits = 3072 # for RSA only
+distinguished_name = req_default
+string_mask = utf8only
+# SHA-1 is deprecated, so use SHA-256 instead.
+default_md = sha256
+# do not encrypt the private key file
+encrypt_key = no
+
+[req_default]
+# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
+countryName = Country Name (2 letter code)
+stateOrProvinceName = State or Province Name (full name)
+localityName = Locality Name (e.g., city)
+0.organizationName = Organization Name (e.g., company)
+organizationalUnitName = Organizational Unit Name (e.g. department)
+commonName = Common Name (e.g. server FQDN or YOUR name)
+emailAddress = Email Address
+# defaults
+countryName_default = UA
+stateOrProvinceName_default = Kharkiv Oblast
+localityName_default = Kharkiv
+0.organizationName_default = ISC
+organizationalUnitName_default = Software Engeneering (BIND 9)
diff --git a/bin/tests/system/doth/CA/CA.pem b/bin/tests/system/doth/CA/CA.pem
new file mode 100644
index 0000000..1f725db
--- /dev/null
+++ b/bin/tests/system/doth/CA/CA.pem
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIE3TCCA0WgAwIBAgIUeZPKrvbGEBZaRc2jNczlIsJXyPYwDQYJKoZIhvcNAQEL
+BQAwfTELMAkGA1UEBhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4G
+A1UEBwwHS2hhcmtpdjEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0
+aXVtMRwwGgYDVQQDDBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDEyNDEyNDA1
+NFoYDzIwNTIwMTE3MTI0MDU0WjB9MQswCQYDVQQGEwJVQTEYMBYGA1UECAwPS2hh
+cmtpdiBPYmxhc3QnMRAwDgYDVQQHDAdLaGFya2l2MSQwIgYDVQQKDBtJbnRlcm5l
+dCBTeXN0ZW1zIENvbnNvcnRpdW0xHDAaBgNVBAMME2NhLnRlc3QuZXhhbXBsZS5j
+b20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCi6hEegBzpUKbE1NTo
+Z7uz7EMUY7TBckkiw/7ydTLKNa8YI4JpBguFvWQsDY0dGFJIoVwyHyNx3seW/LoI
+B5zWPZ2xbOvLLceA+t2NZpbc98E7jUOVS123yED+nqlfZjCq9Zt0r/ezwnQtjnFF
+ko1mcU4H9Jvg8aIgnU2AxE78zciU9CY8799pFFNThIjbooI8oVbfjbzbpmLzxjA5
+3rDmZBTh+ySTlMa2U2oT4WPjRltZWnJVegRRLpG95GnTbQ1fkJAbj1Iu10XTkCee
+wBOqaA1UJem0a6pby5odE414Y7c0ETKcmaJtYENQyO0IJwZWDKtVe5OTIAklakia
+eyFTCAw1h5tHCYLaJW/Yu2wlLl5RNQcRZ9+cWXnldTY+TI1iBjfmADjLdKJYUlhX
+z7kWJtTi63Sdv6WYcEXxaWpxT+R3e2kaR/R7GOo4gdkWpX1siGlRteHHH2/36CSQ
+ZD2etcTUpGW+KDHFR4grnEfL1rt9UgvCjpa4KcssmZtWSSUCAwEAAaNTMFEwHQYD
+VR0OBBYEFHyJ6Fzr5R9ySATFj/uSCJz1YCY5MB8GA1UdIwQYMBaAFHyJ6Fzr5R9y
+SATFj/uSCJz1YCY5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggGB
+AF3y0hvzyZWtmuG1JwIcOcc1aPl1KdRy8bao/5iHYGYYrsdDgcO5/e+y9S/izalc
+TdW7SKB5iBOCiE8fBNtToCvGP+fxNxHijpAmTr37G5sWuSo1T1VYFizHWL+df/Ig
+TcSvDrEjSnAwaEdNJUWtjoIC4VzNKTLtZf16QIATTzTZa3bfgSetpWS7LhLQbHod
+CSGI2QB1LRbqGC+a1Y85QxHv81jWzPWPzXYvnOLrDdQyBMOBcxDzrN4b6zg+5Itz
+qGYt+IS71jAH0IhxAyD/U5n1jGJv02BnSq0ynLEOD6gsnZjqAwPbt/PM9pGbtbXO
+70Q9rxr+vQc1IISKAEiH3txaEPi10wU98d6LbInJvQrmgHo/ntet8skWNYuxlEzS
+wvynuE9KvvQtOTodWt5AePtKrhHdxu527a4CHVp59nYUjKSdMKjvmhMRXM1cNjFE
+rA/pyyhozR47w3RzHMJVHw2GJ2B/HeqmxpXr1CmJjoRP38QCR7N+mqiZy85Fq2j2
+8Q==
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/README b/bin/tests/system/doth/CA/README
new file mode 100644
index 0000000..13069ca
--- /dev/null
+++ b/bin/tests/system/doth/CA/README
@@ -0,0 +1,2 @@
+Please take a look at the contents of the CA.cfg file for further
+instructions and configurations options.
diff --git a/bin/tests/system/doth/CA/certs/srv01.client01.example.com.key b/bin/tests/system/doth/CA/certs/srv01.client01.example.com.key
new file mode 100644
index 0000000..9da02dd
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.client01.example.com.key
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCq9Z95YLiCPSevj5Xm
+lB/ijFFlZb8AT2bHUyL1fmivBm8JfjSa/j3pZePAF7rltyChZANiAARek2p62nXM
+ZAjk+PkvK4U27uHf+s1MYPFEtRZ7+QPPoAhnb64no5WKaB5jq88uIGJS54w+Hu/e
+DWlkZbbk3/4aSPhodYSDEfuBWQ7Blkh/JNoR3azLCsUJeCQxOt835rM=
+-----END PRIVATE KEY-----
diff --git a/bin/tests/system/doth/CA/certs/srv01.client01.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.client01.example.com.pem
new file mode 100644
index 0000000..0b4c115
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.client01.example.com.pem
@@ -0,0 +1,68 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207431 (0x6bb3183cdef52007)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 10 17:44:20 2022 GMT
+ Not After : Feb 3 17:44:20 2052 GMT
+ Subject: CN=srv01.client01.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:5e:93:6a:7a:da:75:cc:64:08:e4:f8:f9:2f:2b:
+ 85:36:ee:e1:df:fa:cd:4c:60:f1:44:b5:16:7b:f9:
+ 03:cf:a0:08:67:6f:ae:27:a3:95:8a:68:1e:63:ab:
+ cf:2e:20:62:52:e7:8c:3e:1e:ef:de:0d:69:64:65:
+ b6:e4:df:fe:1a:48:f8:68:75:84:83:11:fb:81:59:
+ 0e:c1:96:48:7f:24:da:11:dd:ac:cb:0a:c5:09:78:
+ 24:31:3a:df:37:e6:b3
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv01.client01.example.com
+ Signature Algorithm: sha256WithRSAEncryption
+ 82:bd:eb:8f:4e:a5:d2:46:c7:d8:70:3c:34:1d:58:43:1b:81:
+ 16:5d:c2:b0:76:4b:a9:f2:10:14:23:e4:ef:dc:59:03:b6:7f:
+ b0:40:34:e5:d0:82:4b:95:a6:07:9a:45:51:94:cf:08:c2:4e:
+ c9:44:d5:f3:b6:ed:f2:a0:01:94:ad:e0:0e:0f:ab:85:6f:35:
+ 4b:07:c8:97:25:fb:69:ff:a1:99:bc:ec:70:6c:51:b5:32:95:
+ e9:c9:45:cf:45:e2:c5:5e:b1:59:a2:e1:f2:83:c8:87:68:c4:
+ 60:e2:db:50:6c:18:64:1b:9a:9a:cc:7c:e7:fd:d9:f2:b7:d1:
+ de:1d:ec:29:c9:58:db:7b:9a:a1:06:9a:ce:36:a0:45:10:dc:
+ 7d:81:24:21:34:30:4c:71:f9:fc:96:37:d6:cf:0d:9d:11:12:
+ c7:62:bc:19:5b:79:e5:e0:37:e8:17:36:4b:13:af:fa:2c:2e:
+ 36:d9:be:53:e1:c3:f9:bc:94:a6:7a:97:14:99:36:f9:14:38:
+ 11:20:3a:2a:9d:fd:64:63:d0:a2:8f:f0:99:a9:02:ca:57:48:
+ d2:7d:65:44:b6:85:a0:38:ec:e8:19:7e:c2:48:e3:1d:22:53:
+ cf:3b:d4:0a:98:e1:72:62:ec:8b:01:3f:5a:ea:26:2c:8c:16:
+ c3:80:5a:c2:5d:40:c5:65:1c:e2:9a:e3:d6:65:16:ee:dc:17:
+ 30:d8:26:87:92:d0:ef:c7:72:07:99:86:05:9e:49:35:41:33:
+ b9:bb:cb:1b:25:50:70:85:e3:0f:c7:b9:b2:37:00:1b:87:a2:
+ 47:97:34:5b:cd:dc:66:22:e5:de:25:ec:57:fe:37:75:2c:03:
+ 10:f4:d4:a7:cc:f5:4b:0b:ff:eb:d3:a6:78:2e:cd:8f:65:51:
+ a7:8c:ef:83:67:ec:94:13:c2:1f:74:74:55:7c:a3:0b:b7:2f:
+ 80:5a:62:04:1d:a2:c0:c1:de:b2:7d:31:3b:a1:fa:f7:40:a7:
+ bd:12:25:95:5b:8b
+-----BEGIN CERTIFICATE-----
+MIIDITCCAYmgAwIBAgIIa7MYPN71IAcwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIxMDE3NDQyMFoYDzIwNTIwMjAz
+MTc0NDIwWjAlMSMwIQYDVQQDDBpzcnYwMS5jbGllbnQwMS5leGFtcGxlLmNvbTB2
+MBAGByqGSM49AgEGBSuBBAAiA2IABF6TanradcxkCOT4+S8rhTbu4d/6zUxg8US1
+Fnv5A8+gCGdvriejlYpoHmOrzy4gYlLnjD4e794NaWRltuTf/hpI+Gh1hIMR+4FZ
+DsGWSH8k2hHdrMsKxQl4JDE63zfms6MpMCcwJQYDVR0RBB4wHIIac3J2MDEuY2xp
+ZW50MDEuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggGBAIK9649OpdJGx9hw
+PDQdWEMbgRZdwrB2S6nyEBQj5O/cWQO2f7BANOXQgkuVpgeaRVGUzwjCTslE1fO2
+7fKgAZSt4A4Pq4VvNUsHyJcl+2n/oZm87HBsUbUylenJRc9F4sVesVmi4fKDyIdo
+xGDi21BsGGQbmprMfOf92fK30d4d7CnJWNt7mqEGms42oEUQ3H2BJCE0MExx+fyW
+N9bPDZ0REsdivBlbeeXgN+gXNksTr/osLjbZvlPhw/m8lKZ6lxSZNvkUOBEgOiqd
+/WRj0KKP8JmpAspXSNJ9ZUS2haA47OgZfsJI4x0iU8871AqY4XJi7IsBP1rqJiyM
+FsOAWsJdQMVlHOKa49ZlFu7cFzDYJoeS0O/HcgeZhgWeSTVBM7m7yxslUHCF4w/H
+ubI3ABuHokeXNFvN3GYi5d4l7Ff+N3UsAxD01KfM9UsL/+vTpnguzY9lUaeM74Nn
+7JQTwh90dFV8owu3L4BaYgQdosDB3rJ9MTuh+vdAp70SJZVbiw==
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.key b/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.key
new file mode 100644
index 0000000..91cb6ca
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.key
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDD1/sp/yNsAc9Z6TPhm
+0xT0ZhSf/9XJD6daSpdUDJ/nEJKa+sBXDWJHuXrbNRqUK2qhZANiAATmRfpXEmxZ
+ECOLelx2M+s7Qfq3HJCzLzMtRXvj5baloqKkFPRQnbDGOLrpRWWkZbkQMi+Tm9XY
+z7QpW9xOyOymn1h2JPTF0UhVUutdsIWThe4+uMSxzQhZlRL/e5vuark=
+-----END PRIVATE KEY-----
diff --git a/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.pem
new file mode 100644
index 0000000..1b43bbd
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.pem
@@ -0,0 +1,68 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207432 (0x6bb3183cdef52008)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 11 13:21:12 2022 GMT
+ Not After : Feb 4 13:21:12 2052 GMT
+ Subject: CN=srv01.client02-ns2.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:e6:45:fa:57:12:6c:59:10:23:8b:7a:5c:76:33:
+ eb:3b:41:fa:b7:1c:90:b3:2f:33:2d:45:7b:e3:e5:
+ b6:a5:a2:a2:a4:14:f4:50:9d:b0:c6:38:ba:e9:45:
+ 65:a4:65:b9:10:32:2f:93:9b:d5:d8:cf:b4:29:5b:
+ dc:4e:c8:ec:a6:9f:58:76:24:f4:c5:d1:48:55:52:
+ eb:5d:b0:85:93:85:ee:3e:b8:c4:b1:cd:08:59:95:
+ 12:ff:7b:9b:ee:6a:b9
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv01.client02-ns2.example.com
+ Signature Algorithm: sha256WithRSAEncryption
+ 43:ec:0f:62:17:f6:f4:90:3b:7c:36:21:f2:18:94:a6:42:51:
+ 1e:1d:2a:43:8f:05:b7:8d:3c:ca:f0:20:2f:65:4b:be:48:ad:
+ 6a:0a:cc:2d:1f:d6:27:1d:af:4a:36:86:ed:0d:03:75:c5:71:
+ ec:58:9b:ec:f9:0f:e4:83:ef:6f:91:da:20:73:47:ac:e7:c7:
+ 8b:22:b2:d1:6e:a0:b0:d6:1c:4c:70:1e:74:08:1d:7f:61:06:
+ e5:be:f3:e8:c4:15:60:e2:b0:02:9b:f0:13:af:76:5b:a8:c7:
+ 91:2c:10:5f:0d:32:89:51:5a:7f:17:1b:7c:c6:46:97:ee:e7:
+ bb:8a:48:38:a2:52:d4:ff:3b:1c:ec:4a:a9:8c:a5:23:3a:04:
+ bb:d7:b8:ad:5b:69:7f:1d:be:ca:96:e0:eb:56:05:43:ee:c8:
+ ff:2c:48:03:00:c6:c2:ac:fc:4e:15:47:86:c5:33:ed:70:f6:
+ 98:bc:0b:07:b9:5b:1a:ec:fd:3c:bf:26:61:68:fc:db:02:55:
+ 07:ae:76:0e:be:ff:c5:b8:56:fb:52:54:a4:b1:2d:64:b4:1d:
+ 55:02:4f:da:06:bd:26:e4:22:d2:94:1f:7e:29:c4:97:10:d1:
+ 75:7d:41:53:be:46:52:70:b1:d9:ff:bb:9f:96:19:e3:a0:ba:
+ d0:4a:5a:8d:da:22:73:89:f0:4c:e6:18:80:53:be:bd:64:56:
+ 6a:c9:58:71:40:66:9e:4a:3e:31:3b:74:9e:6e:6a:f5:65:ca:
+ 93:06:52:00:74:65:a0:3a:eb:2e:56:56:d2:a5:4b:0e:85:17:
+ 25:78:cb:f3:f9:53:7b:85:f9:82:15:87:bc:36:70:b5:69:64:
+ 48:11:79:b9:2c:2e:cc:09:fd:0f:b0:b7:cd:97:3b:c7:0f:49:
+ 1a:fc:15:49:d6:1c:a9:dc:14:ff:44:d2:be:5a:36:00:66:0c:
+ d5:b8:bf:16:9e:60:27:79:c0:f5:b4:ff:2f:af:8c:b2:49:75:
+ 61:44:05:1a:e8:cd
+-----BEGIN CERTIFICATE-----
+MIIDKTCCAZGgAwIBAgIIa7MYPN71IAgwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIxMTEzMjExMloYDzIwNTIwMjA0
+MTMyMTEyWjApMScwJQYDVQQDDB5zcnYwMS5jbGllbnQwMi1uczIuZXhhbXBsZS5j
+b20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATmRfpXEmxZECOLelx2M+s7Qfq3HJCz
+LzMtRXvj5baloqKkFPRQnbDGOLrpRWWkZbkQMi+Tm9XYz7QpW9xOyOymn1h2JPTF
+0UhVUutdsIWThe4+uMSxzQhZlRL/e5vuarmjLTArMCkGA1UdEQQiMCCCHnNydjAx
+LmNsaWVudDAyLW5zMi5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAQ+wP
+Yhf29JA7fDYh8hiUpkJRHh0qQ48Ft408yvAgL2VLvkitagrMLR/WJx2vSjaG7Q0D
+dcVx7Fib7PkP5IPvb5HaIHNHrOfHiyKy0W6gsNYcTHAedAgdf2EG5b7z6MQVYOKw
+ApvwE692W6jHkSwQXw0yiVFafxcbfMZGl+7nu4pIOKJS1P87HOxKqYylIzoEu9e4
+rVtpfx2+ypbg61YFQ+7I/yxIAwDGwqz8ThVHhsUz7XD2mLwLB7lbGuz9PL8mYWj8
+2wJVB652Dr7/xbhW+1JUpLEtZLQdVQJP2ga9JuQi0pQffinElxDRdX1BU75GUnCx
+2f+7n5YZ46C60Epajdoic4nwTOYYgFO+vWRWaslYcUBmnko+MTt0nm5q9WXKkwZS
+AHRloDrrLlZW0qVLDoUXJXjL8/lTe4X5ghWHvDZwtWlkSBF5uSwuzAn9D7C3zZc7
+xw9JGvwVSdYcqdwU/0TSvlo2AGYM1bi/Fp5gJ3nA9bT/L6+Mskl1YUQFGujN
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.key b/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.key
new file mode 100644
index 0000000..5d3d283
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.key
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCQvnl9FD/mrb+KQaC8
+VMhKW2sxrYFHhZnUYBc3Luz/X3vECNVqLVc5asLu+NrkioyhZANiAAQ4mpvCaoKm
+0VCKeHrRvmG+1LbT1qICl6RIUMDFHdgtIxklbpECHWnCd9bxqE9Kmh08aVqJQQry
+4GRXGw6e359MezxC3CHILJWrs0xfVsRw7oqk5EbEnpj1yHuyc9dFk/A=
+-----END PRIVATE KEY-----
diff --git a/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.pem
new file mode 100644
index 0000000..99e4a71
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207433 (0x6bb3183cdef52009)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Aug 14 05:00:00 2012 GMT
+ Not After : Aug 14 06:00:00 2012 GMT
+ Subject: CN=srv01.client03-ns2-expired.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:38:9a:9b:c2:6a:82:a6:d1:50:8a:78:7a:d1:be:
+ 61:be:d4:b6:d3:d6:a2:02:97:a4:48:50:c0:c5:1d:
+ d8:2d:23:19:25:6e:91:02:1d:69:c2:77:d6:f1:a8:
+ 4f:4a:9a:1d:3c:69:5a:89:41:0a:f2:e0:64:57:1b:
+ 0e:9e:df:9f:4c:7b:3c:42:dc:21:c8:2c:95:ab:b3:
+ 4c:5f:56:c4:70:ee:8a:a4:e4:46:c4:9e:98:f5:c8:
+ 7b:b2:73:d7:45:93:f0
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv01.client03-ns2-expired.example.com
+ Signature Algorithm: sha256WithRSAEncryption
+ 38:12:1f:5f:26:b6:8e:9b:3f:77:89:5a:b8:e8:46:78:c3:d6:
+ f0:0c:67:5f:d5:a3:9c:f6:f2:0a:ae:9c:87:74:9f:a3:5b:8a:
+ 27:58:47:e5:78:1a:e9:db:b5:cc:28:a7:f8:18:e3:e7:20:43:
+ cf:82:06:5d:a1:d0:82:ab:15:be:86:46:1e:e6:4d:ad:78:a4:
+ 16:6c:99:41:3d:29:21:c8:6b:9d:3d:4a:cd:93:37:1f:1c:88:
+ c7:ae:b6:7c:73:42:57:57:32:9d:e8:c6:e2:3e:da:12:57:3e:
+ c8:56:4a:bb:d4:01:fc:8e:30:8d:19:fe:61:3d:5e:02:64:65:
+ a2:46:b3:6e:ea:f9:cb:4e:f0:b9:f6:bc:6b:38:10:19:d0:93:
+ f8:f7:d9:4c:d2:87:2c:7f:dc:f5:00:c6:29:dd:00:5e:d2:f4:
+ df:52:fb:7a:5a:ad:98:36:77:72:1f:01:ed:48:91:48:16:2d:
+ 35:a5:15:21:98:ff:7e:5d:a1:45:c9:5f:9d:c2:3e:e5:98:e2:
+ ee:ce:4d:18:76:3d:8a:0a:64:9b:f1:19:9d:b6:82:af:1b:15:
+ d3:48:69:f1:9b:67:76:1b:41:8e:1d:69:d5:31:64:95:01:41:
+ 73:c1:a9:29:53:6b:f3:29:ad:e0:96:52:8e:3e:8d:c1:8e:d8:
+ b5:0c:94:5f:a2:6c:3c:0f:3e:5b:10:af:21:00:74:d0:b7:30:
+ 6c:44:fb:3d:09:46:8d:1d:e6:c2:e4:0a:5b:f4:eb:e1:71:c7:
+ d5:36:13:90:05:fe:65:16:61:24:b5:41:f2:10:bd:2c:c3:34:
+ 69:15:25:d1:32:f2:b3:d7:da:23:1b:e9:5b:33:63:43:c8:dc:
+ 68:f2:31:b5:93:0e:64:ea:9a:45:36:9f:96:44:38:1e:4e:d8:
+ 45:ba:37:68:06:4d:da:d4:16:d3:3e:77:86:4e:8d:58:d6:06:
+ a8:60:11:4d:d9:81:f3:85:2b:ee:58:50:6e:ea:2b:f7:84:00:
+ 9c:ec:a1:90:d4:94
+-----BEGIN CERTIFICATE-----
+MIIDNzCCAZ+gAwIBAgIIa7MYPN71IAkwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTEyMDgxNDA1MDAwMFoXDTEyMDgxNDA2
+MDAwMFowMTEvMC0GA1UEAwwmc3J2MDEuY2xpZW50MDMtbnMyLWV4cGlyZWQuZXhh
+bXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ4mpvCaoKm0VCKeHrRvmG+
+1LbT1qICl6RIUMDFHdgtIxklbpECHWnCd9bxqE9Kmh08aVqJQQry4GRXGw6e359M
+ezxC3CHILJWrs0xfVsRw7oqk5EbEnpj1yHuyc9dFk/CjNTAzMDEGA1UdEQQqMCiC
+JnNydjAxLmNsaWVudDAzLW5zMi1leHBpcmVkLmV4YW1wbGUuY29tMA0GCSqGSIb3
+DQEBCwUAA4IBgQA4Eh9fJraOmz93iVq46EZ4w9bwDGdf1aOc9vIKrpyHdJ+jW4on
+WEfleBrp27XMKKf4GOPnIEPPggZdodCCqxW+hkYe5k2teKQWbJlBPSkhyGudPUrN
+kzcfHIjHrrZ8c0JXVzKd6MbiPtoSVz7IVkq71AH8jjCNGf5hPV4CZGWiRrNu6vnL
+TvC59rxrOBAZ0JP499lM0ocsf9z1AMYp3QBe0vTfUvt6Wq2YNndyHwHtSJFIFi01
+pRUhmP9+XaFFyV+dwj7lmOLuzk0Ydj2KCmSb8RmdtoKvGxXTSGnxm2d2G0GOHWnV
+MWSVAUFzwakpU2vzKa3gllKOPo3Bjti1DJRfomw8Dz5bEK8hAHTQtzBsRPs9CUaN
+HebC5Apb9OvhccfVNhOQBf5lFmEktUHyEL0swzRpFSXRMvKz19ojG+lbM2NDyNxo
+8jG1kw5k6ppFNp+WRDgeTthFujdoBk3a1BbTPneGTo1Y1gaoYBFN2YHzhSvuWFBu
+6iv3hACc7KGQ1JQ=
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.key b/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.key
new file mode 100644
index 0000000..a4194bd
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.key
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDB/BdYjkgkVy4gTuXX3
+20DWo80uWsQkKDwMeOoaQ2cYy5Cm2AdTALDdBihGKRfACPqhZANiAAQSoXsPefIp
+9Y9qBtAogxRDjxlMKZE2MA8GplbnV5tYLJ78nKNO9uNvkEDVCf2Ulo4UaHRv6Ken
+q4w1lvLWj12XXdG5IlvvMRWh4ettb6+xL4Dlpak48m/5ZRRwp6Ws4Ro=
+-----END PRIVATE KEY-----
diff --git a/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.pem
new file mode 100644
index 0000000..8671dd3
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207425 (0x6bb3183cdef52001)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 8 17:18:52 2022 GMT
+ Not After : Feb 1 17:18:52 2052 GMT
+ Subject: CN=srv01.crt01.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:12:a1:7b:0f:79:f2:29:f5:8f:6a:06:d0:28:83:
+ 14:43:8f:19:4c:29:91:36:30:0f:06:a6:56:e7:57:
+ 9b:58:2c:9e:fc:9c:a3:4e:f6:e3:6f:90:40:d5:09:
+ fd:94:96:8e:14:68:74:6f:e8:a7:a7:ab:8c:35:96:
+ f2:d6:8f:5d:97:5d:d1:b9:22:5b:ef:31:15:a1:e1:
+ eb:6d:6f:af:b1:2f:80:e5:a5:a9:38:f2:6f:f9:65:
+ 14:70:a7:a5:ac:e1:1a
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv01.crt01.example.com, IP Address:10.53.0.1, IP Address:FD92:7065:B8E:FFFF:0:0:0:1
+ Signature Algorithm: sha256WithRSAEncryption
+ 79:0f:08:ab:18:cc:f9:7a:bd:47:21:99:a1:a3:76:04:7f:d7:
+ 08:33:91:49:3d:2d:fc:8d:ff:c5:c1:8d:b8:70:05:65:32:cd:
+ e2:26:21:49:19:66:a2:94:4f:42:7d:83:3c:4f:ed:c1:87:89:
+ 5b:73:2c:64:64:67:29:f5:73:83:23:72:b7:a8:2e:d6:9a:de:
+ 13:0c:ba:35:d3:38:b1:c4:51:7d:81:fc:25:ca:a6:d9:d2:fa:
+ bb:6d:1f:a4:61:90:50:2d:8a:ed:70:1a:eb:56:2f:fc:7b:f3:
+ 76:df:68:8d:e8:a4:7d:82:b9:5c:c6:cb:d8:06:f7:78:dc:a7:
+ 94:35:d4:83:98:28:51:36:1c:73:47:e4:5b:32:d2:cd:de:1c:
+ 44:f6:de:37:8a:46:d0:14:8d:71:e5:10:22:b1:f9:73:f7:1b:
+ 4f:82:e1:a1:00:73:18:17:71:a2:bf:a2:0c:59:aa:43:58:46:
+ 82:f8:38:c4:5a:5a:9f:13:d7:a9:54:1f:58:9b:5d:52:16:d3:
+ a0:ba:6b:aa:cf:68:3a:d1:12:9c:94:ac:78:6b:7e:bc:69:6c:
+ 75:07:5d:fb:68:cd:e8:8d:bb:8c:b0:7c:6c:9e:f6:a5:7c:32:
+ 74:ef:c5:b1:1f:1d:ec:7b:2f:79:c0:3b:52:60:9b:48:89:09:
+ b4:46:34:69:d3:7b:1b:15:ef:0c:dd:64:1d:58:fe:a7:0b:b1:
+ 9d:28:1f:1e:9e:3c:c0:b1:a6:38:ab:9d:54:24:0e:75:6c:9e:
+ 90:13:b9:39:dc:43:fe:37:e3:14:0f:78:7e:2b:56:a2:d2:60:
+ 51:57:88:3b:4c:cf:24:67:36:77:21:bb:c8:07:eb:48:f7:b0:
+ 1e:e4:99:61:84:15:bb:61:3a:21:55:df:31:43:67:73:8f:6b:
+ e9:04:83:be:2d:8b:94:39:89:cf:40:d5:04:f7:6b:c9:c6:8c:
+ 6e:36:0f:5d:7a:9b:57:86:36:76:2c:75:35:47:50:ed:9a:84:
+ 7e:37:83:b5:21:a2
+-----BEGIN CERTIFICATE-----
+MIIDMzCCAZugAwIBAgIIa7MYPN71IAEwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3MTg1MloYDzIwNTIwMjAx
+MTcxODUyWjAiMSAwHgYDVQQDDBdzcnYwMS5jcnQwMS5leGFtcGxlLmNvbTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABBKhew958in1j2oG0CiDFEOPGUwpkTYwDwamVudX
+m1gsnvyco07242+QQNUJ/ZSWjhRodG/op6erjDWW8taPXZdd0bkiW+8xFaHh621v
+r7EvgOWlqTjyb/llFHCnpazhGqM+MDwwOgYDVR0RBDMwMYIXc3J2MDEuY3J0MDEu
+ZXhhbXBsZS5jb22HBAo1AAGHEP2ScGULjv//AAAAAAAAAAEwDQYJKoZIhvcNAQEL
+BQADggGBAHkPCKsYzPl6vUchmaGjdgR/1wgzkUk9LfyN/8XBjbhwBWUyzeImIUkZ
+ZqKUT0J9gzxP7cGHiVtzLGRkZyn1c4MjcreoLtaa3hMMujXTOLHEUX2B/CXKptnS
++rttH6RhkFAtiu1wGutWL/x783bfaI3opH2CuVzGy9gG93jcp5Q11IOYKFE2HHNH
+5Fsy0s3eHET23jeKRtAUjXHlECKx+XP3G0+C4aEAcxgXcaK/ogxZqkNYRoL4OMRa
+Wp8T16lUH1ibXVIW06C6a6rPaDrREpyUrHhrfrxpbHUHXftozeiNu4ywfGye9qV8
+MnTvxbEfHex7L3nAO1Jgm0iJCbRGNGnTexsV7wzdZB1Y/qcLsZ0oHx6ePMCxpjir
+nVQkDnVsnpATuTncQ/434xQPeH4rVqLSYFFXiDtMzyRnNnchu8gH60j3sB7kmWGE
+FbthOiFV3zFDZ3OPa+kEg74ti5Q5ic9A1QT3a8nGjG42D116m1eGNnYsdTVHUO2a
+hH43g7Uhog==
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.key b/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.key
new file mode 100644
index 0000000..db770c1
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.key
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDC3sc7RaI9GyH5Z1e0D
+WcccNjr43zpavmMqA8bcS9dBBjkiEdvGH47r3EIXTjp0f46hZANiAASjLTP9kpDc
+A+82+aSokPFHab7ojmUI2uWzgmMcr5o3tHV8zkb7GRe8kHJPdLZFOfeWs0SFHK1q
+26R2hu6OJz33YXjf4QSK65GLAWe2aTJUUBxWhtov7+Q9lLr3WwIUtRM=
+-----END PRIVATE KEY-----
diff --git a/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.pem
new file mode 100644
index 0000000..65f0f9f
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.pem
@@ -0,0 +1,64 @@
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number: 7760573232607207426 (0x6bb3183cdef52002)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 8 17:21:43 2022 GMT
+ Not After : Feb 1 17:21:43 2052 GMT
+ Subject: CN=srv01.crt02-no-san.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:a3:2d:33:fd:92:90:dc:03:ef:36:f9:a4:a8:90:
+ f1:47:69:be:e8:8e:65:08:da:e5:b3:82:63:1c:af:
+ 9a:37:b4:75:7c:ce:46:fb:19:17:bc:90:72:4f:74:
+ b6:45:39:f7:96:b3:44:85:1c:ad:6a:db:a4:76:86:
+ ee:8e:27:3d:f7:61:78:df:e1:04:8a:eb:91:8b:01:
+ 67:b6:69:32:54:50:1c:56:86:da:2f:ef:e4:3d:94:
+ ba:f7:5b:02:14:b5:13
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ Signature Algorithm: sha256WithRSAEncryption
+ 07:20:2a:a6:7a:52:52:ba:1e:b7:79:cf:e6:11:9c:ca:3f:43:
+ 2b:f3:d7:2e:74:74:57:81:a1:aa:e6:68:c9:fd:d1:a8:a6:5b:
+ a2:ff:ea:f7:f0:b7:46:dc:a0:5a:64:5f:ce:e7:0f:76:63:14:
+ 6d:c2:51:4b:30:ea:51:7e:4a:1b:d3:b2:f8:c2:3d:3f:c1:bf:
+ ad:db:4d:f8:28:31:e7:75:ae:84:37:90:00:e5:0b:6b:dc:23:
+ 98:69:d5:ef:ce:e2:0d:e7:19:f1:31:01:1f:2a:6c:23:a3:94:
+ 62:7a:bf:b3:b0:13:d0:62:fc:a5:a6:0d:52:bb:f4:31:ff:f3:
+ ce:3a:74:66:30:7f:29:04:8d:34:90:7a:9b:8f:da:82:2e:5c:
+ 81:dd:af:fa:3a:a1:4e:bb:0a:4c:62:01:40:39:67:9c:29:27:
+ 6e:2f:76:81:2d:33:68:ee:ee:ed:00:7f:12:7a:af:43:00:7b:
+ 2d:34:8a:26:9a:66:1c:e5:96:17:7c:f8:6d:1e:8c:17:39:ce:
+ 4f:0b:9e:40:72:e1:5e:33:3f:9e:84:b5:07:f5:ab:58:d7:37:
+ ed:d0:29:ad:ce:02:0d:fa:6f:96:a9:0e:6c:6e:32:d2:dc:11:
+ 23:a3:4a:60:54:b4:98:31:db:8f:4b:4c:58:64:39:4f:ff:27:
+ d0:02:e5:cc:b2:17:e8:46:dc:aa:cb:dc:3d:ed:14:52:ec:6d:
+ a6:cd:04:2f:fd:54:16:6c:7e:63:34:17:f1:1d:b8:37:dd:20:
+ 6c:f6:21:19:6f:bb:62:dd:bc:6c:41:34:ad:b1:90:eb:2a:e0:
+ 63:ea:70:60:6a:02:e8:fe:46:51:b1:9d:3c:54:54:73:25:b7:
+ 41:d1:4c:34:aa:88:48:b8:01:21:ae:d8:d3:06:38:05:65:78:
+ e7:38:f0:f6:e6:2e:61:c0:42:5e:3b:09:59:eb:09:48:4d:55:
+ 7c:af:f4:de:c1:09:a0:b4:60:f7:9e:a2:d5:46:fc:05:61:69:
+ e0:c1:2d:26:dc:42
+-----BEGIN CERTIFICATE-----
+MIIC9TCCAV0CCGuzGDze9SACMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAlVB
+MRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJraXYxJDAi
+BgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UEAwwTY2Eu
+dGVzdC5leGFtcGxlLmNvbTAgFw0yMjAyMDgxNzIxNDNaGA8yMDUyMDIwMTE3MjE0
+M1owKTEnMCUGA1UEAwwec3J2MDEuY3J0MDItbm8tc2FuLmV4YW1wbGUuY29tMHYw
+EAYHKoZIzj0CAQYFK4EEACIDYgAEoy0z/ZKQ3APvNvmkqJDxR2m+6I5lCNrls4Jj
+HK+aN7R1fM5G+xkXvJByT3S2RTn3lrNEhRytatukdobujic992F43+EEiuuRiwFn
+tmkyVFAcVobaL+/kPZS691sCFLUTMA0GCSqGSIb3DQEBCwUAA4IBgQAHICqmelJS
+uh63ec/mEZzKP0Mr89cudHRXgaGq5mjJ/dGoplui/+r38LdG3KBaZF/O5w92YxRt
+wlFLMOpRfkob07L4wj0/wb+t2034KDHnda6EN5AA5Qtr3COYadXvzuIN5xnxMQEf
+Kmwjo5Rier+zsBPQYvylpg1Su/Qx//POOnRmMH8pBI00kHqbj9qCLlyB3a/6OqFO
+uwpMYgFAOWecKSduL3aBLTNo7u7tAH8Seq9DAHstNIommmYc5ZYXfPhtHowXOc5P
+C55AcuFeMz+ehLUH9atY1zft0CmtzgIN+m+WqQ5sbjLS3BEjo0pgVLSYMduPS0xY
+ZDlP/yfQAuXMshfoRtyqy9w97RRS7G2mzQQv/VQWbH5jNBfxHbg33SBs9iEZb7ti
+3bxsQTStsZDrKuBj6nBgagLo/kZRsZ08VFRzJbdB0Uw0qohIuAEhrtjTBjgFZXjn
+OPD25i5hwEJeOwlZ6wlITVV8r/TewQmgtGD3nqLVRvwFYWngwS0m3EI=
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.key b/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.key
new file mode 100644
index 0000000..caef1f0
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.key
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAtAQNSdzyxR3sm6gyx
+2Ob3SNCsYvdsE6+gobSUJWYbdus0CCFBIN6Qpms9oc0hAgqhZANiAAQf1Xurc7Jw
+Ff0zJgJcdhaADHB9V4N1rDy3SgJGNcEbwXq9vvIEmn9pg39UmhsQYtdwve8mkFFQ
+EHdWtxovRF6RRjbhLqRMZy5iqH8aFRBEaIsY6s+4lgm/tTrR7xCPn7s=
+-----END PRIVATE KEY-----
diff --git a/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.pem
new file mode 100644
index 0000000..4befde4
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207430 (0x6bb3183cdef52006)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Aug 15 08:00:00 2012 GMT
+ Not After : Aug 15 09:00:00 2012 GMT
+ Subject: CN=srv01.crt03-expired.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:1f:d5:7b:ab:73:b2:70:15:fd:33:26:02:5c:76:
+ 16:80:0c:70:7d:57:83:75:ac:3c:b7:4a:02:46:35:
+ c1:1b:c1:7a:bd:be:f2:04:9a:7f:69:83:7f:54:9a:
+ 1b:10:62:d7:70:bd:ef:26:90:51:50:10:77:56:b7:
+ 1a:2f:44:5e:91:46:36:e1:2e:a4:4c:67:2e:62:a8:
+ 7f:1a:15:10:44:68:8b:18:ea:cf:b8:96:09:bf:b5:
+ 3a:d1:ef:10:8f:9f:bb
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv01.crt03-expired.example.com, IP Address:10.53.0.1, IP Address:FD92:7065:B8E:FFFF:0:0:0:1
+ Signature Algorithm: sha256WithRSAEncryption
+ 25:35:08:f6:e7:f0:83:81:be:65:31:1b:78:a8:04:84:fe:6a:
+ 2a:1a:5d:c1:73:20:88:08:11:d8:27:be:a5:8e:3c:df:e2:a6:
+ 19:c5:41:40:ea:01:91:85:99:8d:17:4e:4d:9a:3c:03:f9:78:
+ 4c:8a:20:41:5e:96:d6:64:83:2f:b2:fe:e7:77:09:f9:91:bd:
+ 22:1a:57:8b:f6:24:bc:7b:48:2b:2e:14:b7:32:bd:46:91:99:
+ 5e:21:9a:d3:15:a7:27:e1:c0:3a:c7:f5:f9:94:3f:6d:14:7e:
+ 0b:02:bf:05:d9:ac:10:8a:7e:b0:37:36:cd:cb:4a:b4:e1:01:
+ c7:04:8d:83:f3:c6:79:ff:ff:6c:f0:a4:bf:3c:12:61:ea:15:
+ ac:30:62:26:e3:c3:4e:7d:5c:68:d8:88:de:35:8d:44:75:8c:
+ a8:c1:0d:07:67:b5:d0:42:43:41:1f:39:a0:47:35:46:d7:0f:
+ 89:aa:e8:d3:86:45:9a:fb:33:01:06:23:64:53:24:48:5b:69:
+ fa:cf:d9:81:fb:5e:7e:7b:82:65:56:c6:46:65:5c:e1:4f:f2:
+ 3c:09:3c:28:5f:c9:e3:a5:24:e3:7b:aa:b5:b1:8a:6a:b2:02:
+ 32:5f:24:05:f1:67:c8:54:17:0c:cd:ca:3d:e4:44:3e:23:3a:
+ 7c:63:b6:f9:61:3a:21:e7:8f:27:ad:c3:26:86:39:49:6c:41:
+ 40:7f:1d:48:69:8d:db:6f:42:e4:09:fe:24:62:bd:8e:2e:54:
+ 25:f0:14:c2:d8:43:95:09:2e:5f:72:4f:43:b5:9a:8b:bb:8c:
+ 44:c6:77:c9:05:fb:1a:9f:d7:b6:a6:42:d9:5c:3d:a5:09:0f:
+ 9e:e0:c7:06:32:f1:ff:c9:53:5e:42:d4:2a:33:ad:06:ea:ec:
+ b0:26:d3:3c:ef:65:af:15:8e:7b:20:49:ad:f1:56:ef:17:6b:
+ fc:f4:d8:7c:82:9f:30:19:d0:bc:9c:79:e2:dc:9d:a7:f9:6b:
+ 6f:65:ae:21:a0:94
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAamgAwIBAgIIa7MYPN71IAYwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTEyMDgxNTA4MDAwMFoXDTEyMDgxNTA5
+MDAwMFowKjEoMCYGA1UEAwwfc3J2MDEuY3J0MDMtZXhwaXJlZC5leGFtcGxlLmNv
+bTB2MBAGByqGSM49AgEGBSuBBAAiA2IABB/Ve6tzsnAV/TMmAlx2FoAMcH1Xg3Ws
+PLdKAkY1wRvBer2+8gSaf2mDf1SaGxBi13C97yaQUVAQd1a3Gi9EXpFGNuEupExn
+LmKofxoVEERoixjqz7iWCb+1OtHvEI+fu6NGMEQwQgYDVR0RBDswOYIfc3J2MDEu
+Y3J0MDMtZXhwaXJlZC5leGFtcGxlLmNvbYcECjUAAYcQ/ZJwZQuO//8AAAAAAAAA
+ATANBgkqhkiG9w0BAQsFAAOCAYEAJTUI9ufwg4G+ZTEbeKgEhP5qKhpdwXMgiAgR
+2Ce+pY483+KmGcVBQOoBkYWZjRdOTZo8A/l4TIogQV6W1mSDL7L+53cJ+ZG9IhpX
+i/YkvHtIKy4UtzK9RpGZXiGa0xWnJ+HAOsf1+ZQ/bRR+CwK/BdmsEIp+sDc2zctK
+tOEBxwSNg/PGef//bPCkvzwSYeoVrDBiJuPDTn1caNiI3jWNRHWMqMENB2e10EJD
+QR85oEc1RtcPiaro04ZFmvszAQYjZFMkSFtp+s/ZgftefnuCZVbGRmVc4U/yPAk8
+KF/J46Uk43uqtbGKarICMl8kBfFnyFQXDM3KPeREPiM6fGO2+WE6IeePJ63DJoY5
+SWxBQH8dSGmN229C5An+JGK9ji5UJfAUwthDlQkuX3JPQ7Wai7uMRMZ3yQX7Gp/X
+tqZC2Vw9pQkPnuDHBjLx/8lTXkLUKjOtBurssCbTPO9lrxWOeyBJrfFW7xdr/PTY
+fIKfMBnQvJx54tydp/lrb2WuIaCU
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.key b/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.key
new file mode 100644
index 0000000..cf495c1
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.key
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDC/rdGBnhOuZ8hc7fUO
+6v0LO2xd2LMjTS0TCb0pVwsccYN/f6OxWJtu0uGSt0DaN6ihZANiAARD1PvMuIhg
+lRaqKtAxlss+qFzkdqzBv807ZYW7LMv6w0g8g8gI7txZFZciuEIXjHUJ+T62nPLF
+2122impDSAqi3RPCNuRzs2RUebv41H5I9AW+DHdjAf5PMLCqYrzy7fk=
+-----END PRIVATE KEY-----
diff --git a/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.pem b/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.pem
new file mode 100644
index 0000000..d061c2c
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207427 (0x6bb3183cdef52003)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 8 17:57:59 2022 GMT
+ Not After : Feb 1 17:57:59 2052 GMT
+ Subject: CN=srv02.crt01.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:43:d4:fb:cc:b8:88:60:95:16:aa:2a:d0:31:96:
+ cb:3e:a8:5c:e4:76:ac:c1:bf:cd:3b:65:85:bb:2c:
+ cb:fa:c3:48:3c:83:c8:08:ee:dc:59:15:97:22:b8:
+ 42:17:8c:75:09:f9:3e:b6:9c:f2:c5:db:5d:b6:8a:
+ 6a:43:48:0a:a2:dd:13:c2:36:e4:73:b3:64:54:79:
+ bb:f8:d4:7e:48:f4:05:be:0c:77:63:01:fe:4f:30:
+ b0:aa:62:bc:f2:ed:f9
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv02.crt01.example.com, IP Address:10.53.0.2, IP Address:FD92:7065:B8E:FFFF:0:0:0:2
+ Signature Algorithm: sha256WithRSAEncryption
+ 89:ba:ae:4f:f8:3e:da:48:1f:5c:8f:ff:ee:d8:42:b0:0b:9b:
+ f1:b5:e2:90:c9:76:40:09:77:a3:31:d5:73:8f:eb:7d:69:94:
+ 1c:2b:10:31:da:d4:0c:29:e7:80:4e:61:53:ba:15:9d:e1:e8:
+ 0c:0d:19:77:2b:a8:74:46:e3:03:ae:ab:96:ea:af:80:c3:18:
+ e0:93:8e:e9:58:0e:79:47:98:a4:06:95:6b:8f:2c:d1:f7:29:
+ b1:98:85:e8:a4:9c:45:52:ad:c8:60:20:dc:3a:6a:40:78:15:
+ d1:b4:d0:c3:c5:f3:ac:fe:ec:d3:94:ef:66:0b:d7:8c:46:f3:
+ 62:30:c4:c2:78:65:de:40:4e:d8:26:84:8e:18:a7:71:f2:b7:
+ 65:d8:d0:c2:c8:e6:a0:fb:ea:01:de:2f:03:8a:50:3d:f6:6c:
+ 0b:ef:ce:f5:25:1f:80:54:3e:c2:6d:2c:d3:2b:bd:23:b7:3b:
+ 82:6b:91:7f:ea:ff:e6:11:37:d3:f0:d4:db:9f:32:ac:12:cc:
+ ec:25:25:81:58:16:18:90:73:c3:ad:7c:09:a7:08:99:16:ce:
+ e8:6c:4b:9a:e6:09:96:11:c2:f1:cf:19:43:a6:a6:81:f2:57:
+ 21:fa:b1:91:58:39:76:17:89:32:4c:4b:df:fa:59:03:b2:32:
+ b4:b3:95:89:af:f4:5e:94:b1:df:e9:bf:21:73:14:06:5d:08:
+ 1e:0f:d2:84:14:44:20:91:19:72:b9:38:0b:3c:2e:4f:ea:3a:
+ 9b:ef:93:61:e7:36:82:df:49:e2:d7:45:ea:87:45:1d:74:36:
+ 18:f4:aa:30:d5:65:da:1f:c7:98:61:ab:64:2a:49:98:64:a1:
+ 8c:33:3a:a5:97:4a:69:a6:9d:6f:00:b9:6b:81:8d:09:0f:98:
+ 63:0f:85:ae:e4:21:70:a3:da:5a:27:eb:df:6d:82:ac:bb:48:
+ 6b:01:4e:36:95:5a:d3:f0:b9:30:43:72:87:af:41:7a:30:13:
+ f2:92:15:f1:69:e7
+-----BEGIN CERTIFICATE-----
+MIIDMzCCAZugAwIBAgIIa7MYPN71IAMwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTc1OVoYDzIwNTIwMjAx
+MTc1NzU5WjAiMSAwHgYDVQQDDBdzcnYwMi5jcnQwMS5leGFtcGxlLmNvbTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABEPU+8y4iGCVFqoq0DGWyz6oXOR2rMG/zTtlhbss
+y/rDSDyDyAju3FkVlyK4QheMdQn5Prac8sXbXbaKakNICqLdE8I25HOzZFR5u/jU
+fkj0Bb4Md2MB/k8wsKpivPLt+aM+MDwwOgYDVR0RBDMwMYIXc3J2MDIuY3J0MDEu
+ZXhhbXBsZS5jb22HBAo1AAKHEP2ScGULjv//AAAAAAAAAAIwDQYJKoZIhvcNAQEL
+BQADggGBAIm6rk/4PtpIH1yP/+7YQrALm/G14pDJdkAJd6Mx1XOP631plBwrEDHa
+1Awp54BOYVO6FZ3h6AwNGXcrqHRG4wOuq5bqr4DDGOCTjulYDnlHmKQGlWuPLNH3
+KbGYheiknEVSrchgINw6akB4FdG00MPF86z+7NOU72YL14xG82IwxMJ4Zd5ATtgm
+hI4Yp3Hyt2XY0MLI5qD76gHeLwOKUD32bAvvzvUlH4BUPsJtLNMrvSO3O4JrkX/q
+/+YRN9Pw1NufMqwSzOwlJYFYFhiQc8OtfAmnCJkWzuhsS5rmCZYRwvHPGUOmpoHy
+VyH6sZFYOXYXiTJMS9/6WQOyMrSzlYmv9F6Usd/pvyFzFAZdCB4P0oQURCCRGXK5
+OAs8Lk/qOpvvk2HnNoLfSeLXReqHRR10Nhj0qjDVZdofx5hhq2QqSZhkoYwzOqWX
+SmmmnW8AuWuBjQkPmGMPha7kIXCj2lon699tgqy7SGsBTjaVWtPwuTBDcoevQXow
+E/KSFfFp5w==
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.key b/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.key
new file mode 100644
index 0000000..72f8a40
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.key
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBMJxQaJB76ywjBuhZI
+LUz05LQuwmDBAFeZFqe10HG+r0cZvVw4Cr5M7jr2RVLqKRChZANiAARF27kbN2W/
+saGKWjkAjUoVO0OauC//qH2Zg6ic3LbCqp/4UaEOLpcPkBMiTIvx/zxr65EpfUzf
+fAXdrepKTK0K1m+OUbCIWEKILBbURx24j7NODRLfTBT2JyA/lJojgUg=
+-----END PRIVATE KEY-----
diff --git a/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.pem b/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.pem
new file mode 100644
index 0000000..39b48ee
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207428 (0x6bb3183cdef52004)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 8 17:58:15 2022 GMT
+ Not After : Feb 1 17:58:15 2052 GMT
+ Subject: CN=srv03.crt01.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:45:db:b9:1b:37:65:bf:b1:a1:8a:5a:39:00:8d:
+ 4a:15:3b:43:9a:b8:2f:ff:a8:7d:99:83:a8:9c:dc:
+ b6:c2:aa:9f:f8:51:a1:0e:2e:97:0f:90:13:22:4c:
+ 8b:f1:ff:3c:6b:eb:91:29:7d:4c:df:7c:05:dd:ad:
+ ea:4a:4c:ad:0a:d6:6f:8e:51:b0:88:58:42:88:2c:
+ 16:d4:47:1d:b8:8f:b3:4e:0d:12:df:4c:14:f6:27:
+ 20:3f:94:9a:23:81:48
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv03.crt01.example.com, IP Address:10.53.0.3, IP Address:FD92:7065:B8E:FFFF:0:0:0:3
+ Signature Algorithm: sha256WithRSAEncryption
+ 8f:96:88:82:94:76:8e:97:b6:75:8b:e9:2b:4f:f3:8f:14:5c:
+ 50:00:ca:67:96:9e:2e:bd:53:25:25:40:6d:c5:56:e6:1a:f6:
+ cb:fb:58:fc:b3:56:9d:fc:0b:e2:8e:99:7e:e8:e6:ad:b6:e7:
+ e6:3e:8a:59:ef:3e:76:a4:ed:7b:58:fd:a3:4b:aa:4e:11:e1:
+ 57:bf:b1:23:a5:a1:00:f8:95:07:c8:7d:ee:ac:a7:c8:24:ee:
+ cf:e8:c5:a4:9f:96:27:c9:47:c1:7d:11:de:66:d0:6d:d1:8d:
+ e7:8f:a0:0f:46:d9:2e:70:f3:9f:ac:6a:b0:3f:5a:dc:70:d4:
+ b9:a5:f3:ff:5c:21:50:5d:c2:a2:46:26:25:2a:2f:8a:aa:7a:
+ fd:76:31:5f:e0:25:a3:ee:df:36:f0:ab:05:a1:5d:0d:3c:6b:
+ 2c:1d:d5:c5:73:9c:a0:57:1f:c4:26:e6:dc:a1:7c:25:08:21:
+ 61:28:e2:b3:f5:51:83:20:73:14:19:8f:47:79:69:bc:2b:22:
+ f2:17:62:1d:83:f7:4f:a9:c4:51:68:e0:a9:d7:9f:17:6a:d2:
+ fd:f7:04:ce:a4:f5:8e:eb:31:b4:bf:c6:2d:da:0c:70:6e:0c:
+ a5:75:21:54:3c:f6:3d:36:b8:8a:d8:b6:7b:77:7e:54:1d:9f:
+ 91:8f:02:a6:d1:2c:a7:30:d1:cc:e6:d9:6b:76:80:15:4b:ba:
+ fd:55:20:cc:b2:99:85:57:60:11:97:c5:e7:28:50:a6:17:af:
+ d2:bd:1b:7e:06:48:7f:63:dc:70:f8:3f:22:9f:41:a1:66:f5:
+ a7:81:99:cb:07:0e:8a:9a:bb:12:f6:c0:fe:59:0c:00:37:15:
+ b2:9d:f0:f9:93:d1:1a:b6:f8:0a:6b:bd:9e:92:32:45:f5:a2:
+ 44:f0:45:8d:1a:d0:10:b2:db:98:c4:c7:5e:c1:e8:f3:94:33:
+ 6c:06:f5:1a:cc:51:23:72:ae:37:2f:57:d4:f8:ac:1f:25:b4:
+ d3:bf:99:9b:ac:fc
+-----BEGIN CERTIFICATE-----
+MIIDMzCCAZugAwIBAgIIa7MYPN71IAQwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTgxNVoYDzIwNTIwMjAx
+MTc1ODE1WjAiMSAwHgYDVQQDDBdzcnYwMy5jcnQwMS5leGFtcGxlLmNvbTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABEXbuRs3Zb+xoYpaOQCNShU7Q5q4L/+ofZmDqJzc
+tsKqn/hRoQ4ulw+QEyJMi/H/PGvrkSl9TN98Bd2t6kpMrQrWb45RsIhYQogsFtRH
+HbiPs04NEt9MFPYnID+UmiOBSKM+MDwwOgYDVR0RBDMwMYIXc3J2MDMuY3J0MDEu
+ZXhhbXBsZS5jb22HBAo1AAOHEP2ScGULjv//AAAAAAAAAAMwDQYJKoZIhvcNAQEL
+BQADggGBAI+WiIKUdo6XtnWL6StP848UXFAAymeWni69UyUlQG3FVuYa9sv7WPyz
+Vp38C+KOmX7o5q225+Y+ilnvPnak7XtY/aNLqk4R4Ve/sSOloQD4lQfIfe6sp8gk
+7s/oxaSflifJR8F9Ed5m0G3RjeePoA9G2S5w85+sarA/Wtxw1Lml8/9cIVBdwqJG
+JiUqL4qqev12MV/gJaPu3zbwqwWhXQ08aywd1cVznKBXH8Qm5tyhfCUIIWEo4rP1
+UYMgcxQZj0d5abwrIvIXYh2D90+pxFFo4KnXnxdq0v33BM6k9Y7rMbS/xi3aDHBu
+DKV1IVQ89j02uIrYtnt3flQdn5GPAqbRLKcw0czm2Wt2gBVLuv1VIMyymYVXYBGX
+xecoUKYXr9K9G34GSH9j3HD4PyKfQaFm9aeBmcsHDoqauxL2wP5ZDAA3FbKd8PmT
+0Rq2+AprvZ6SMkX1okTwRY0a0BCy25jEx17B6POUM2wG9RrMUSNyrjcvV9T4rB8l
+tNO/mZus/A==
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.key b/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.key
new file mode 100644
index 0000000..5356fc1
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.key
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDDq5a0oiMxJiOdwaSmk
+U2NPPJXOWPZVWpIGxB0kczGcCS6Xq0VinNqLe5YI9M1YwXehZANiAASeQ9fMKeGO
+SzWhj7ePMA9Ws1t/wGKbIyFwsSvnc/nqOAFmS1JDMc8QaRW/awjzaQc/mbu4cNA7
+iSId8iVCWj5VkcP8tL7HLYZRFMSr/nxUNGfHXtuGhMxm61SvnX3czhg=
+-----END PRIVATE KEY-----
diff --git a/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.pem b/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.pem
new file mode 100644
index 0000000..b4e2d22
--- /dev/null
+++ b/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207429 (0x6bb3183cdef52005)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 8 17:59:14 2022 GMT
+ Not After : Feb 1 17:59:14 2052 GMT
+ Subject: CN=srv04.crt01.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:9e:43:d7:cc:29:e1:8e:4b:35:a1:8f:b7:8f:30:
+ 0f:56:b3:5b:7f:c0:62:9b:23:21:70:b1:2b:e7:73:
+ f9:ea:38:01:66:4b:52:43:31:cf:10:69:15:bf:6b:
+ 08:f3:69:07:3f:99:bb:b8:70:d0:3b:89:22:1d:f2:
+ 25:42:5a:3e:55:91:c3:fc:b4:be:c7:2d:86:51:14:
+ c4:ab:fe:7c:54:34:67:c7:5e:db:86:84:cc:66:eb:
+ 54:af:9d:7d:dc:ce:18
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv04.crt01.example.com, IP Address:10.53.0.4, IP Address:FD92:7065:B8E:FFFF:0:0:0:4
+ Signature Algorithm: sha256WithRSAEncryption
+ 48:b5:38:59:79:e6:51:a6:ea:80:d7:d1:3c:29:03:70:31:e4:
+ 43:b4:e3:09:e7:e1:37:8c:d0:0f:2a:19:7a:f2:5a:6d:76:cd:
+ 17:7a:66:1c:3e:74:56:24:b8:29:06:55:b2:1c:af:9a:42:05:
+ 93:a4:70:cb:a5:68:85:ab:71:53:da:d9:29:a3:f4:2a:1e:df:
+ 0c:ec:7d:52:55:fa:9b:e6:a0:18:d5:4c:da:e6:d2:60:da:bc:
+ 09:5b:13:53:6d:c7:d2:30:b9:a8:a5:02:7f:a3:66:28:34:93:
+ de:55:a0:de:b5:c8:dc:43:7b:b9:03:06:1f:ce:8c:5f:82:d8:
+ af:40:56:ce:f8:b9:d4:73:1c:ae:c9:cb:1d:0f:a2:52:71:9b:
+ 8b:05:f4:d6:0b:1e:a8:db:0f:29:a0:43:b5:2f:56:09:d8:68:
+ 58:9c:e5:6a:df:38:91:56:9d:44:e5:d2:ca:9a:b1:41:a1:01:
+ 0c:68:a0:f5:0a:f7:98:4f:d5:a0:6f:99:59:a0:e0:cb:49:57:
+ 26:20:09:5a:fa:c2:75:40:f6:1b:6a:ac:55:47:50:8d:38:81:
+ 61:79:44:e7:d5:d1:b3:c7:3b:db:ec:44:59:ef:e1:82:31:a3:
+ 38:4c:de:40:11:31:52:8b:bb:1c:af:be:ce:c5:2b:f5:0d:c0:
+ 60:13:fb:7e:da:22:41:d4:85:5e:4d:ba:db:f8:f7:26:61:32:
+ 26:fe:fe:9e:37:a3:cc:25:3b:3c:c8:b5:a7:a5:5c:d9:4d:8f:
+ a8:f2:86:98:79:b3:00:08:0f:f2:c9:1f:c6:3f:07:ad:e4:a7:
+ 8d:86:3d:15:fa:5b:1a:0f:96:67:b6:0a:78:0a:bb:6e:05:a6:
+ 54:29:48:b4:f9:48:0d:7f:f0:13:65:32:2f:c5:ee:ab:b8:e8:
+ 0d:b2:f9:c9:96:d2:cf:51:a2:64:3c:58:0f:65:6f:c6:99:93:
+ 76:2c:42:08:d9:f3:f3:13:cd:41:b6:67:8f:1d:9a:2f:da:93:
+ 3d:26:4c:9a:11:c1
+-----BEGIN CERTIFICATE-----
+MIIDMzCCAZugAwIBAgIIa7MYPN71IAUwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTkxNFoYDzIwNTIwMjAx
+MTc1OTE0WjAiMSAwHgYDVQQDDBdzcnYwNC5jcnQwMS5leGFtcGxlLmNvbTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABJ5D18wp4Y5LNaGPt48wD1azW3/AYpsjIXCxK+dz
++eo4AWZLUkMxzxBpFb9rCPNpBz+Zu7hw0DuJIh3yJUJaPlWRw/y0vscthlEUxKv+
+fFQ0Z8de24aEzGbrVK+dfdzOGKM+MDwwOgYDVR0RBDMwMYIXc3J2MDQuY3J0MDEu
+ZXhhbXBsZS5jb22HBAo1AASHEP2ScGULjv//AAAAAAAAAAQwDQYJKoZIhvcNAQEL
+BQADggGBAEi1OFl55lGm6oDX0TwpA3Ax5EO04wnn4TeM0A8qGXryWm12zRd6Zhw+
+dFYkuCkGVbIcr5pCBZOkcMulaIWrcVPa2Smj9Coe3wzsfVJV+pvmoBjVTNrm0mDa
+vAlbE1Ntx9IwuailAn+jZig0k95VoN61yNxDe7kDBh/OjF+C2K9AVs74udRzHK7J
+yx0PolJxm4sF9NYLHqjbDymgQ7UvVgnYaFic5WrfOJFWnUTl0sqasUGhAQxooPUK
+95hP1aBvmVmg4MtJVyYgCVr6wnVA9htqrFVHUI04gWF5ROfV0bPHO9vsRFnv4YIx
+ozhM3kARMVKLuxyvvs7FK/UNwGAT+37aIkHUhV5Nutv49yZhMib+/p43o8wlOzzI
+taelXNlNj6jyhph5swAID/LJH8Y/B63kp42GPRX6WxoPlme2CngKu24FplQpSLT5
+SA1/8BNlMi/F7qu46A2y+cmW0s9RomQ8WA9lb8aZk3YsQgjZ8/MTzUG2Z48dmi/a
+kz0mTJoRwQ==
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/index.txt b/bin/tests/system/doth/CA/index.txt
new file mode 100644
index 0000000..230127d
--- /dev/null
+++ b/bin/tests/system/doth/CA/index.txt
@@ -0,0 +1,9 @@
+V 20520201171852Z 6BB3183CDEF52001 unknown /CN=srv01.crt01.example.com
+V 20520201172143Z 6BB3183CDEF52002 unknown /CN=srv01.crt02-no-san.example.com
+V 20520201175759Z 6BB3183CDEF52003 unknown /CN=srv02.crt01.example.com
+V 20520201175815Z 6BB3183CDEF52004 unknown /CN=srv03.crt01.example.com
+V 20520201175914Z 6BB3183CDEF52005 unknown /CN=srv04.crt01.example.com
+V 120815090000Z 6BB3183CDEF52006 unknown /CN=srv01.crt03-expired.example.com
+V 20520203174420Z 6BB3183CDEF52007 unknown /CN=srv01.client01.example.com
+V 20520204132112Z 6BB3183CDEF52008 unknown /CN=srv01.client02-ns2.example.com
+V 120814060000Z 6BB3183CDEF52009 unknown /CN=srv01.client03-ns2-expired.example.com
diff --git a/bin/tests/system/doth/CA/index.txt.attr b/bin/tests/system/doth/CA/index.txt.attr
new file mode 100644
index 0000000..8f7e63a
--- /dev/null
+++ b/bin/tests/system/doth/CA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52001.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52001.pem
new file mode 100644
index 0000000..8671dd3
--- /dev/null
+++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52001.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207425 (0x6bb3183cdef52001)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 8 17:18:52 2022 GMT
+ Not After : Feb 1 17:18:52 2052 GMT
+ Subject: CN=srv01.crt01.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:12:a1:7b:0f:79:f2:29:f5:8f:6a:06:d0:28:83:
+ 14:43:8f:19:4c:29:91:36:30:0f:06:a6:56:e7:57:
+ 9b:58:2c:9e:fc:9c:a3:4e:f6:e3:6f:90:40:d5:09:
+ fd:94:96:8e:14:68:74:6f:e8:a7:a7:ab:8c:35:96:
+ f2:d6:8f:5d:97:5d:d1:b9:22:5b:ef:31:15:a1:e1:
+ eb:6d:6f:af:b1:2f:80:e5:a5:a9:38:f2:6f:f9:65:
+ 14:70:a7:a5:ac:e1:1a
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv01.crt01.example.com, IP Address:10.53.0.1, IP Address:FD92:7065:B8E:FFFF:0:0:0:1
+ Signature Algorithm: sha256WithRSAEncryption
+ 79:0f:08:ab:18:cc:f9:7a:bd:47:21:99:a1:a3:76:04:7f:d7:
+ 08:33:91:49:3d:2d:fc:8d:ff:c5:c1:8d:b8:70:05:65:32:cd:
+ e2:26:21:49:19:66:a2:94:4f:42:7d:83:3c:4f:ed:c1:87:89:
+ 5b:73:2c:64:64:67:29:f5:73:83:23:72:b7:a8:2e:d6:9a:de:
+ 13:0c:ba:35:d3:38:b1:c4:51:7d:81:fc:25:ca:a6:d9:d2:fa:
+ bb:6d:1f:a4:61:90:50:2d:8a:ed:70:1a:eb:56:2f:fc:7b:f3:
+ 76:df:68:8d:e8:a4:7d:82:b9:5c:c6:cb:d8:06:f7:78:dc:a7:
+ 94:35:d4:83:98:28:51:36:1c:73:47:e4:5b:32:d2:cd:de:1c:
+ 44:f6:de:37:8a:46:d0:14:8d:71:e5:10:22:b1:f9:73:f7:1b:
+ 4f:82:e1:a1:00:73:18:17:71:a2:bf:a2:0c:59:aa:43:58:46:
+ 82:f8:38:c4:5a:5a:9f:13:d7:a9:54:1f:58:9b:5d:52:16:d3:
+ a0:ba:6b:aa:cf:68:3a:d1:12:9c:94:ac:78:6b:7e:bc:69:6c:
+ 75:07:5d:fb:68:cd:e8:8d:bb:8c:b0:7c:6c:9e:f6:a5:7c:32:
+ 74:ef:c5:b1:1f:1d:ec:7b:2f:79:c0:3b:52:60:9b:48:89:09:
+ b4:46:34:69:d3:7b:1b:15:ef:0c:dd:64:1d:58:fe:a7:0b:b1:
+ 9d:28:1f:1e:9e:3c:c0:b1:a6:38:ab:9d:54:24:0e:75:6c:9e:
+ 90:13:b9:39:dc:43:fe:37:e3:14:0f:78:7e:2b:56:a2:d2:60:
+ 51:57:88:3b:4c:cf:24:67:36:77:21:bb:c8:07:eb:48:f7:b0:
+ 1e:e4:99:61:84:15:bb:61:3a:21:55:df:31:43:67:73:8f:6b:
+ e9:04:83:be:2d:8b:94:39:89:cf:40:d5:04:f7:6b:c9:c6:8c:
+ 6e:36:0f:5d:7a:9b:57:86:36:76:2c:75:35:47:50:ed:9a:84:
+ 7e:37:83:b5:21:a2
+-----BEGIN CERTIFICATE-----
+MIIDMzCCAZugAwIBAgIIa7MYPN71IAEwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3MTg1MloYDzIwNTIwMjAx
+MTcxODUyWjAiMSAwHgYDVQQDDBdzcnYwMS5jcnQwMS5leGFtcGxlLmNvbTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABBKhew958in1j2oG0CiDFEOPGUwpkTYwDwamVudX
+m1gsnvyco07242+QQNUJ/ZSWjhRodG/op6erjDWW8taPXZdd0bkiW+8xFaHh621v
+r7EvgOWlqTjyb/llFHCnpazhGqM+MDwwOgYDVR0RBDMwMYIXc3J2MDEuY3J0MDEu
+ZXhhbXBsZS5jb22HBAo1AAGHEP2ScGULjv//AAAAAAAAAAEwDQYJKoZIhvcNAQEL
+BQADggGBAHkPCKsYzPl6vUchmaGjdgR/1wgzkUk9LfyN/8XBjbhwBWUyzeImIUkZ
+ZqKUT0J9gzxP7cGHiVtzLGRkZyn1c4MjcreoLtaa3hMMujXTOLHEUX2B/CXKptnS
++rttH6RhkFAtiu1wGutWL/x783bfaI3opH2CuVzGy9gG93jcp5Q11IOYKFE2HHNH
+5Fsy0s3eHET23jeKRtAUjXHlECKx+XP3G0+C4aEAcxgXcaK/ogxZqkNYRoL4OMRa
+Wp8T16lUH1ibXVIW06C6a6rPaDrREpyUrHhrfrxpbHUHXftozeiNu4ywfGye9qV8
+MnTvxbEfHex7L3nAO1Jgm0iJCbRGNGnTexsV7wzdZB1Y/qcLsZ0oHx6ePMCxpjir
+nVQkDnVsnpATuTncQ/434xQPeH4rVqLSYFFXiDtMzyRnNnchu8gH60j3sB7kmWGE
+FbthOiFV3zFDZ3OPa+kEg74ti5Q5ic9A1QT3a8nGjG42D116m1eGNnYsdTVHUO2a
+hH43g7Uhog==
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52002.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52002.pem
new file mode 100644
index 0000000..65f0f9f
--- /dev/null
+++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52002.pem
@@ -0,0 +1,64 @@
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number: 7760573232607207426 (0x6bb3183cdef52002)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 8 17:21:43 2022 GMT
+ Not After : Feb 1 17:21:43 2052 GMT
+ Subject: CN=srv01.crt02-no-san.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:a3:2d:33:fd:92:90:dc:03:ef:36:f9:a4:a8:90:
+ f1:47:69:be:e8:8e:65:08:da:e5:b3:82:63:1c:af:
+ 9a:37:b4:75:7c:ce:46:fb:19:17:bc:90:72:4f:74:
+ b6:45:39:f7:96:b3:44:85:1c:ad:6a:db:a4:76:86:
+ ee:8e:27:3d:f7:61:78:df:e1:04:8a:eb:91:8b:01:
+ 67:b6:69:32:54:50:1c:56:86:da:2f:ef:e4:3d:94:
+ ba:f7:5b:02:14:b5:13
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ Signature Algorithm: sha256WithRSAEncryption
+ 07:20:2a:a6:7a:52:52:ba:1e:b7:79:cf:e6:11:9c:ca:3f:43:
+ 2b:f3:d7:2e:74:74:57:81:a1:aa:e6:68:c9:fd:d1:a8:a6:5b:
+ a2:ff:ea:f7:f0:b7:46:dc:a0:5a:64:5f:ce:e7:0f:76:63:14:
+ 6d:c2:51:4b:30:ea:51:7e:4a:1b:d3:b2:f8:c2:3d:3f:c1:bf:
+ ad:db:4d:f8:28:31:e7:75:ae:84:37:90:00:e5:0b:6b:dc:23:
+ 98:69:d5:ef:ce:e2:0d:e7:19:f1:31:01:1f:2a:6c:23:a3:94:
+ 62:7a:bf:b3:b0:13:d0:62:fc:a5:a6:0d:52:bb:f4:31:ff:f3:
+ ce:3a:74:66:30:7f:29:04:8d:34:90:7a:9b:8f:da:82:2e:5c:
+ 81:dd:af:fa:3a:a1:4e:bb:0a:4c:62:01:40:39:67:9c:29:27:
+ 6e:2f:76:81:2d:33:68:ee:ee:ed:00:7f:12:7a:af:43:00:7b:
+ 2d:34:8a:26:9a:66:1c:e5:96:17:7c:f8:6d:1e:8c:17:39:ce:
+ 4f:0b:9e:40:72:e1:5e:33:3f:9e:84:b5:07:f5:ab:58:d7:37:
+ ed:d0:29:ad:ce:02:0d:fa:6f:96:a9:0e:6c:6e:32:d2:dc:11:
+ 23:a3:4a:60:54:b4:98:31:db:8f:4b:4c:58:64:39:4f:ff:27:
+ d0:02:e5:cc:b2:17:e8:46:dc:aa:cb:dc:3d:ed:14:52:ec:6d:
+ a6:cd:04:2f:fd:54:16:6c:7e:63:34:17:f1:1d:b8:37:dd:20:
+ 6c:f6:21:19:6f:bb:62:dd:bc:6c:41:34:ad:b1:90:eb:2a:e0:
+ 63:ea:70:60:6a:02:e8:fe:46:51:b1:9d:3c:54:54:73:25:b7:
+ 41:d1:4c:34:aa:88:48:b8:01:21:ae:d8:d3:06:38:05:65:78:
+ e7:38:f0:f6:e6:2e:61:c0:42:5e:3b:09:59:eb:09:48:4d:55:
+ 7c:af:f4:de:c1:09:a0:b4:60:f7:9e:a2:d5:46:fc:05:61:69:
+ e0:c1:2d:26:dc:42
+-----BEGIN CERTIFICATE-----
+MIIC9TCCAV0CCGuzGDze9SACMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAlVB
+MRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJraXYxJDAi
+BgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UEAwwTY2Eu
+dGVzdC5leGFtcGxlLmNvbTAgFw0yMjAyMDgxNzIxNDNaGA8yMDUyMDIwMTE3MjE0
+M1owKTEnMCUGA1UEAwwec3J2MDEuY3J0MDItbm8tc2FuLmV4YW1wbGUuY29tMHYw
+EAYHKoZIzj0CAQYFK4EEACIDYgAEoy0z/ZKQ3APvNvmkqJDxR2m+6I5lCNrls4Jj
+HK+aN7R1fM5G+xkXvJByT3S2RTn3lrNEhRytatukdobujic992F43+EEiuuRiwFn
+tmkyVFAcVobaL+/kPZS691sCFLUTMA0GCSqGSIb3DQEBCwUAA4IBgQAHICqmelJS
+uh63ec/mEZzKP0Mr89cudHRXgaGq5mjJ/dGoplui/+r38LdG3KBaZF/O5w92YxRt
+wlFLMOpRfkob07L4wj0/wb+t2034KDHnda6EN5AA5Qtr3COYadXvzuIN5xnxMQEf
+Kmwjo5Rier+zsBPQYvylpg1Su/Qx//POOnRmMH8pBI00kHqbj9qCLlyB3a/6OqFO
+uwpMYgFAOWecKSduL3aBLTNo7u7tAH8Seq9DAHstNIommmYc5ZYXfPhtHowXOc5P
+C55AcuFeMz+ehLUH9atY1zft0CmtzgIN+m+WqQ5sbjLS3BEjo0pgVLSYMduPS0xY
+ZDlP/yfQAuXMshfoRtyqy9w97RRS7G2mzQQv/VQWbH5jNBfxHbg33SBs9iEZb7ti
+3bxsQTStsZDrKuBj6nBgagLo/kZRsZ08VFRzJbdB0Uw0qohIuAEhrtjTBjgFZXjn
+OPD25i5hwEJeOwlZ6wlITVV8r/TewQmgtGD3nqLVRvwFYWngwS0m3EI=
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52003.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52003.pem
new file mode 100644
index 0000000..d061c2c
--- /dev/null
+++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52003.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207427 (0x6bb3183cdef52003)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 8 17:57:59 2022 GMT
+ Not After : Feb 1 17:57:59 2052 GMT
+ Subject: CN=srv02.crt01.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:43:d4:fb:cc:b8:88:60:95:16:aa:2a:d0:31:96:
+ cb:3e:a8:5c:e4:76:ac:c1:bf:cd:3b:65:85:bb:2c:
+ cb:fa:c3:48:3c:83:c8:08:ee:dc:59:15:97:22:b8:
+ 42:17:8c:75:09:f9:3e:b6:9c:f2:c5:db:5d:b6:8a:
+ 6a:43:48:0a:a2:dd:13:c2:36:e4:73:b3:64:54:79:
+ bb:f8:d4:7e:48:f4:05:be:0c:77:63:01:fe:4f:30:
+ b0:aa:62:bc:f2:ed:f9
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv02.crt01.example.com, IP Address:10.53.0.2, IP Address:FD92:7065:B8E:FFFF:0:0:0:2
+ Signature Algorithm: sha256WithRSAEncryption
+ 89:ba:ae:4f:f8:3e:da:48:1f:5c:8f:ff:ee:d8:42:b0:0b:9b:
+ f1:b5:e2:90:c9:76:40:09:77:a3:31:d5:73:8f:eb:7d:69:94:
+ 1c:2b:10:31:da:d4:0c:29:e7:80:4e:61:53:ba:15:9d:e1:e8:
+ 0c:0d:19:77:2b:a8:74:46:e3:03:ae:ab:96:ea:af:80:c3:18:
+ e0:93:8e:e9:58:0e:79:47:98:a4:06:95:6b:8f:2c:d1:f7:29:
+ b1:98:85:e8:a4:9c:45:52:ad:c8:60:20:dc:3a:6a:40:78:15:
+ d1:b4:d0:c3:c5:f3:ac:fe:ec:d3:94:ef:66:0b:d7:8c:46:f3:
+ 62:30:c4:c2:78:65:de:40:4e:d8:26:84:8e:18:a7:71:f2:b7:
+ 65:d8:d0:c2:c8:e6:a0:fb:ea:01:de:2f:03:8a:50:3d:f6:6c:
+ 0b:ef:ce:f5:25:1f:80:54:3e:c2:6d:2c:d3:2b:bd:23:b7:3b:
+ 82:6b:91:7f:ea:ff:e6:11:37:d3:f0:d4:db:9f:32:ac:12:cc:
+ ec:25:25:81:58:16:18:90:73:c3:ad:7c:09:a7:08:99:16:ce:
+ e8:6c:4b:9a:e6:09:96:11:c2:f1:cf:19:43:a6:a6:81:f2:57:
+ 21:fa:b1:91:58:39:76:17:89:32:4c:4b:df:fa:59:03:b2:32:
+ b4:b3:95:89:af:f4:5e:94:b1:df:e9:bf:21:73:14:06:5d:08:
+ 1e:0f:d2:84:14:44:20:91:19:72:b9:38:0b:3c:2e:4f:ea:3a:
+ 9b:ef:93:61:e7:36:82:df:49:e2:d7:45:ea:87:45:1d:74:36:
+ 18:f4:aa:30:d5:65:da:1f:c7:98:61:ab:64:2a:49:98:64:a1:
+ 8c:33:3a:a5:97:4a:69:a6:9d:6f:00:b9:6b:81:8d:09:0f:98:
+ 63:0f:85:ae:e4:21:70:a3:da:5a:27:eb:df:6d:82:ac:bb:48:
+ 6b:01:4e:36:95:5a:d3:f0:b9:30:43:72:87:af:41:7a:30:13:
+ f2:92:15:f1:69:e7
+-----BEGIN CERTIFICATE-----
+MIIDMzCCAZugAwIBAgIIa7MYPN71IAMwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTc1OVoYDzIwNTIwMjAx
+MTc1NzU5WjAiMSAwHgYDVQQDDBdzcnYwMi5jcnQwMS5leGFtcGxlLmNvbTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABEPU+8y4iGCVFqoq0DGWyz6oXOR2rMG/zTtlhbss
+y/rDSDyDyAju3FkVlyK4QheMdQn5Prac8sXbXbaKakNICqLdE8I25HOzZFR5u/jU
+fkj0Bb4Md2MB/k8wsKpivPLt+aM+MDwwOgYDVR0RBDMwMYIXc3J2MDIuY3J0MDEu
+ZXhhbXBsZS5jb22HBAo1AAKHEP2ScGULjv//AAAAAAAAAAIwDQYJKoZIhvcNAQEL
+BQADggGBAIm6rk/4PtpIH1yP/+7YQrALm/G14pDJdkAJd6Mx1XOP631plBwrEDHa
+1Awp54BOYVO6FZ3h6AwNGXcrqHRG4wOuq5bqr4DDGOCTjulYDnlHmKQGlWuPLNH3
+KbGYheiknEVSrchgINw6akB4FdG00MPF86z+7NOU72YL14xG82IwxMJ4Zd5ATtgm
+hI4Yp3Hyt2XY0MLI5qD76gHeLwOKUD32bAvvzvUlH4BUPsJtLNMrvSO3O4JrkX/q
+/+YRN9Pw1NufMqwSzOwlJYFYFhiQc8OtfAmnCJkWzuhsS5rmCZYRwvHPGUOmpoHy
+VyH6sZFYOXYXiTJMS9/6WQOyMrSzlYmv9F6Usd/pvyFzFAZdCB4P0oQURCCRGXK5
+OAs8Lk/qOpvvk2HnNoLfSeLXReqHRR10Nhj0qjDVZdofx5hhq2QqSZhkoYwzOqWX
+SmmmnW8AuWuBjQkPmGMPha7kIXCj2lon699tgqy7SGsBTjaVWtPwuTBDcoevQXow
+E/KSFfFp5w==
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52004.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52004.pem
new file mode 100644
index 0000000..39b48ee
--- /dev/null
+++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52004.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207428 (0x6bb3183cdef52004)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 8 17:58:15 2022 GMT
+ Not After : Feb 1 17:58:15 2052 GMT
+ Subject: CN=srv03.crt01.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:45:db:b9:1b:37:65:bf:b1:a1:8a:5a:39:00:8d:
+ 4a:15:3b:43:9a:b8:2f:ff:a8:7d:99:83:a8:9c:dc:
+ b6:c2:aa:9f:f8:51:a1:0e:2e:97:0f:90:13:22:4c:
+ 8b:f1:ff:3c:6b:eb:91:29:7d:4c:df:7c:05:dd:ad:
+ ea:4a:4c:ad:0a:d6:6f:8e:51:b0:88:58:42:88:2c:
+ 16:d4:47:1d:b8:8f:b3:4e:0d:12:df:4c:14:f6:27:
+ 20:3f:94:9a:23:81:48
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv03.crt01.example.com, IP Address:10.53.0.3, IP Address:FD92:7065:B8E:FFFF:0:0:0:3
+ Signature Algorithm: sha256WithRSAEncryption
+ 8f:96:88:82:94:76:8e:97:b6:75:8b:e9:2b:4f:f3:8f:14:5c:
+ 50:00:ca:67:96:9e:2e:bd:53:25:25:40:6d:c5:56:e6:1a:f6:
+ cb:fb:58:fc:b3:56:9d:fc:0b:e2:8e:99:7e:e8:e6:ad:b6:e7:
+ e6:3e:8a:59:ef:3e:76:a4:ed:7b:58:fd:a3:4b:aa:4e:11:e1:
+ 57:bf:b1:23:a5:a1:00:f8:95:07:c8:7d:ee:ac:a7:c8:24:ee:
+ cf:e8:c5:a4:9f:96:27:c9:47:c1:7d:11:de:66:d0:6d:d1:8d:
+ e7:8f:a0:0f:46:d9:2e:70:f3:9f:ac:6a:b0:3f:5a:dc:70:d4:
+ b9:a5:f3:ff:5c:21:50:5d:c2:a2:46:26:25:2a:2f:8a:aa:7a:
+ fd:76:31:5f:e0:25:a3:ee:df:36:f0:ab:05:a1:5d:0d:3c:6b:
+ 2c:1d:d5:c5:73:9c:a0:57:1f:c4:26:e6:dc:a1:7c:25:08:21:
+ 61:28:e2:b3:f5:51:83:20:73:14:19:8f:47:79:69:bc:2b:22:
+ f2:17:62:1d:83:f7:4f:a9:c4:51:68:e0:a9:d7:9f:17:6a:d2:
+ fd:f7:04:ce:a4:f5:8e:eb:31:b4:bf:c6:2d:da:0c:70:6e:0c:
+ a5:75:21:54:3c:f6:3d:36:b8:8a:d8:b6:7b:77:7e:54:1d:9f:
+ 91:8f:02:a6:d1:2c:a7:30:d1:cc:e6:d9:6b:76:80:15:4b:ba:
+ fd:55:20:cc:b2:99:85:57:60:11:97:c5:e7:28:50:a6:17:af:
+ d2:bd:1b:7e:06:48:7f:63:dc:70:f8:3f:22:9f:41:a1:66:f5:
+ a7:81:99:cb:07:0e:8a:9a:bb:12:f6:c0:fe:59:0c:00:37:15:
+ b2:9d:f0:f9:93:d1:1a:b6:f8:0a:6b:bd:9e:92:32:45:f5:a2:
+ 44:f0:45:8d:1a:d0:10:b2:db:98:c4:c7:5e:c1:e8:f3:94:33:
+ 6c:06:f5:1a:cc:51:23:72:ae:37:2f:57:d4:f8:ac:1f:25:b4:
+ d3:bf:99:9b:ac:fc
+-----BEGIN CERTIFICATE-----
+MIIDMzCCAZugAwIBAgIIa7MYPN71IAQwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTgxNVoYDzIwNTIwMjAx
+MTc1ODE1WjAiMSAwHgYDVQQDDBdzcnYwMy5jcnQwMS5leGFtcGxlLmNvbTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABEXbuRs3Zb+xoYpaOQCNShU7Q5q4L/+ofZmDqJzc
+tsKqn/hRoQ4ulw+QEyJMi/H/PGvrkSl9TN98Bd2t6kpMrQrWb45RsIhYQogsFtRH
+HbiPs04NEt9MFPYnID+UmiOBSKM+MDwwOgYDVR0RBDMwMYIXc3J2MDMuY3J0MDEu
+ZXhhbXBsZS5jb22HBAo1AAOHEP2ScGULjv//AAAAAAAAAAMwDQYJKoZIhvcNAQEL
+BQADggGBAI+WiIKUdo6XtnWL6StP848UXFAAymeWni69UyUlQG3FVuYa9sv7WPyz
+Vp38C+KOmX7o5q225+Y+ilnvPnak7XtY/aNLqk4R4Ve/sSOloQD4lQfIfe6sp8gk
+7s/oxaSflifJR8F9Ed5m0G3RjeePoA9G2S5w85+sarA/Wtxw1Lml8/9cIVBdwqJG
+JiUqL4qqev12MV/gJaPu3zbwqwWhXQ08aywd1cVznKBXH8Qm5tyhfCUIIWEo4rP1
+UYMgcxQZj0d5abwrIvIXYh2D90+pxFFo4KnXnxdq0v33BM6k9Y7rMbS/xi3aDHBu
+DKV1IVQ89j02uIrYtnt3flQdn5GPAqbRLKcw0czm2Wt2gBVLuv1VIMyymYVXYBGX
+xecoUKYXr9K9G34GSH9j3HD4PyKfQaFm9aeBmcsHDoqauxL2wP5ZDAA3FbKd8PmT
+0Rq2+AprvZ6SMkX1okTwRY0a0BCy25jEx17B6POUM2wG9RrMUSNyrjcvV9T4rB8l
+tNO/mZus/A==
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52005.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52005.pem
new file mode 100644
index 0000000..b4e2d22
--- /dev/null
+++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52005.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207429 (0x6bb3183cdef52005)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 8 17:59:14 2022 GMT
+ Not After : Feb 1 17:59:14 2052 GMT
+ Subject: CN=srv04.crt01.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:9e:43:d7:cc:29:e1:8e:4b:35:a1:8f:b7:8f:30:
+ 0f:56:b3:5b:7f:c0:62:9b:23:21:70:b1:2b:e7:73:
+ f9:ea:38:01:66:4b:52:43:31:cf:10:69:15:bf:6b:
+ 08:f3:69:07:3f:99:bb:b8:70:d0:3b:89:22:1d:f2:
+ 25:42:5a:3e:55:91:c3:fc:b4:be:c7:2d:86:51:14:
+ c4:ab:fe:7c:54:34:67:c7:5e:db:86:84:cc:66:eb:
+ 54:af:9d:7d:dc:ce:18
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv04.crt01.example.com, IP Address:10.53.0.4, IP Address:FD92:7065:B8E:FFFF:0:0:0:4
+ Signature Algorithm: sha256WithRSAEncryption
+ 48:b5:38:59:79:e6:51:a6:ea:80:d7:d1:3c:29:03:70:31:e4:
+ 43:b4:e3:09:e7:e1:37:8c:d0:0f:2a:19:7a:f2:5a:6d:76:cd:
+ 17:7a:66:1c:3e:74:56:24:b8:29:06:55:b2:1c:af:9a:42:05:
+ 93:a4:70:cb:a5:68:85:ab:71:53:da:d9:29:a3:f4:2a:1e:df:
+ 0c:ec:7d:52:55:fa:9b:e6:a0:18:d5:4c:da:e6:d2:60:da:bc:
+ 09:5b:13:53:6d:c7:d2:30:b9:a8:a5:02:7f:a3:66:28:34:93:
+ de:55:a0:de:b5:c8:dc:43:7b:b9:03:06:1f:ce:8c:5f:82:d8:
+ af:40:56:ce:f8:b9:d4:73:1c:ae:c9:cb:1d:0f:a2:52:71:9b:
+ 8b:05:f4:d6:0b:1e:a8:db:0f:29:a0:43:b5:2f:56:09:d8:68:
+ 58:9c:e5:6a:df:38:91:56:9d:44:e5:d2:ca:9a:b1:41:a1:01:
+ 0c:68:a0:f5:0a:f7:98:4f:d5:a0:6f:99:59:a0:e0:cb:49:57:
+ 26:20:09:5a:fa:c2:75:40:f6:1b:6a:ac:55:47:50:8d:38:81:
+ 61:79:44:e7:d5:d1:b3:c7:3b:db:ec:44:59:ef:e1:82:31:a3:
+ 38:4c:de:40:11:31:52:8b:bb:1c:af:be:ce:c5:2b:f5:0d:c0:
+ 60:13:fb:7e:da:22:41:d4:85:5e:4d:ba:db:f8:f7:26:61:32:
+ 26:fe:fe:9e:37:a3:cc:25:3b:3c:c8:b5:a7:a5:5c:d9:4d:8f:
+ a8:f2:86:98:79:b3:00:08:0f:f2:c9:1f:c6:3f:07:ad:e4:a7:
+ 8d:86:3d:15:fa:5b:1a:0f:96:67:b6:0a:78:0a:bb:6e:05:a6:
+ 54:29:48:b4:f9:48:0d:7f:f0:13:65:32:2f:c5:ee:ab:b8:e8:
+ 0d:b2:f9:c9:96:d2:cf:51:a2:64:3c:58:0f:65:6f:c6:99:93:
+ 76:2c:42:08:d9:f3:f3:13:cd:41:b6:67:8f:1d:9a:2f:da:93:
+ 3d:26:4c:9a:11:c1
+-----BEGIN CERTIFICATE-----
+MIIDMzCCAZugAwIBAgIIa7MYPN71IAUwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTkxNFoYDzIwNTIwMjAx
+MTc1OTE0WjAiMSAwHgYDVQQDDBdzcnYwNC5jcnQwMS5leGFtcGxlLmNvbTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABJ5D18wp4Y5LNaGPt48wD1azW3/AYpsjIXCxK+dz
++eo4AWZLUkMxzxBpFb9rCPNpBz+Zu7hw0DuJIh3yJUJaPlWRw/y0vscthlEUxKv+
+fFQ0Z8de24aEzGbrVK+dfdzOGKM+MDwwOgYDVR0RBDMwMYIXc3J2MDQuY3J0MDEu
+ZXhhbXBsZS5jb22HBAo1AASHEP2ScGULjv//AAAAAAAAAAQwDQYJKoZIhvcNAQEL
+BQADggGBAEi1OFl55lGm6oDX0TwpA3Ax5EO04wnn4TeM0A8qGXryWm12zRd6Zhw+
+dFYkuCkGVbIcr5pCBZOkcMulaIWrcVPa2Smj9Coe3wzsfVJV+pvmoBjVTNrm0mDa
+vAlbE1Ntx9IwuailAn+jZig0k95VoN61yNxDe7kDBh/OjF+C2K9AVs74udRzHK7J
+yx0PolJxm4sF9NYLHqjbDymgQ7UvVgnYaFic5WrfOJFWnUTl0sqasUGhAQxooPUK
+95hP1aBvmVmg4MtJVyYgCVr6wnVA9htqrFVHUI04gWF5ROfV0bPHO9vsRFnv4YIx
+ozhM3kARMVKLuxyvvs7FK/UNwGAT+37aIkHUhV5Nutv49yZhMib+/p43o8wlOzzI
+taelXNlNj6jyhph5swAID/LJH8Y/B63kp42GPRX6WxoPlme2CngKu24FplQpSLT5
+SA1/8BNlMi/F7qu46A2y+cmW0s9RomQ8WA9lb8aZk3YsQgjZ8/MTzUG2Z48dmi/a
+kz0mTJoRwQ==
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52006.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52006.pem
new file mode 100644
index 0000000..4befde4
--- /dev/null
+++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52006.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207430 (0x6bb3183cdef52006)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Aug 15 08:00:00 2012 GMT
+ Not After : Aug 15 09:00:00 2012 GMT
+ Subject: CN=srv01.crt03-expired.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:1f:d5:7b:ab:73:b2:70:15:fd:33:26:02:5c:76:
+ 16:80:0c:70:7d:57:83:75:ac:3c:b7:4a:02:46:35:
+ c1:1b:c1:7a:bd:be:f2:04:9a:7f:69:83:7f:54:9a:
+ 1b:10:62:d7:70:bd:ef:26:90:51:50:10:77:56:b7:
+ 1a:2f:44:5e:91:46:36:e1:2e:a4:4c:67:2e:62:a8:
+ 7f:1a:15:10:44:68:8b:18:ea:cf:b8:96:09:bf:b5:
+ 3a:d1:ef:10:8f:9f:bb
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv01.crt03-expired.example.com, IP Address:10.53.0.1, IP Address:FD92:7065:B8E:FFFF:0:0:0:1
+ Signature Algorithm: sha256WithRSAEncryption
+ 25:35:08:f6:e7:f0:83:81:be:65:31:1b:78:a8:04:84:fe:6a:
+ 2a:1a:5d:c1:73:20:88:08:11:d8:27:be:a5:8e:3c:df:e2:a6:
+ 19:c5:41:40:ea:01:91:85:99:8d:17:4e:4d:9a:3c:03:f9:78:
+ 4c:8a:20:41:5e:96:d6:64:83:2f:b2:fe:e7:77:09:f9:91:bd:
+ 22:1a:57:8b:f6:24:bc:7b:48:2b:2e:14:b7:32:bd:46:91:99:
+ 5e:21:9a:d3:15:a7:27:e1:c0:3a:c7:f5:f9:94:3f:6d:14:7e:
+ 0b:02:bf:05:d9:ac:10:8a:7e:b0:37:36:cd:cb:4a:b4:e1:01:
+ c7:04:8d:83:f3:c6:79:ff:ff:6c:f0:a4:bf:3c:12:61:ea:15:
+ ac:30:62:26:e3:c3:4e:7d:5c:68:d8:88:de:35:8d:44:75:8c:
+ a8:c1:0d:07:67:b5:d0:42:43:41:1f:39:a0:47:35:46:d7:0f:
+ 89:aa:e8:d3:86:45:9a:fb:33:01:06:23:64:53:24:48:5b:69:
+ fa:cf:d9:81:fb:5e:7e:7b:82:65:56:c6:46:65:5c:e1:4f:f2:
+ 3c:09:3c:28:5f:c9:e3:a5:24:e3:7b:aa:b5:b1:8a:6a:b2:02:
+ 32:5f:24:05:f1:67:c8:54:17:0c:cd:ca:3d:e4:44:3e:23:3a:
+ 7c:63:b6:f9:61:3a:21:e7:8f:27:ad:c3:26:86:39:49:6c:41:
+ 40:7f:1d:48:69:8d:db:6f:42:e4:09:fe:24:62:bd:8e:2e:54:
+ 25:f0:14:c2:d8:43:95:09:2e:5f:72:4f:43:b5:9a:8b:bb:8c:
+ 44:c6:77:c9:05:fb:1a:9f:d7:b6:a6:42:d9:5c:3d:a5:09:0f:
+ 9e:e0:c7:06:32:f1:ff:c9:53:5e:42:d4:2a:33:ad:06:ea:ec:
+ b0:26:d3:3c:ef:65:af:15:8e:7b:20:49:ad:f1:56:ef:17:6b:
+ fc:f4:d8:7c:82:9f:30:19:d0:bc:9c:79:e2:dc:9d:a7:f9:6b:
+ 6f:65:ae:21:a0:94
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAamgAwIBAgIIa7MYPN71IAYwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTEyMDgxNTA4MDAwMFoXDTEyMDgxNTA5
+MDAwMFowKjEoMCYGA1UEAwwfc3J2MDEuY3J0MDMtZXhwaXJlZC5leGFtcGxlLmNv
+bTB2MBAGByqGSM49AgEGBSuBBAAiA2IABB/Ve6tzsnAV/TMmAlx2FoAMcH1Xg3Ws
+PLdKAkY1wRvBer2+8gSaf2mDf1SaGxBi13C97yaQUVAQd1a3Gi9EXpFGNuEupExn
+LmKofxoVEERoixjqz7iWCb+1OtHvEI+fu6NGMEQwQgYDVR0RBDswOYIfc3J2MDEu
+Y3J0MDMtZXhwaXJlZC5leGFtcGxlLmNvbYcECjUAAYcQ/ZJwZQuO//8AAAAAAAAA
+ATANBgkqhkiG9w0BAQsFAAOCAYEAJTUI9ufwg4G+ZTEbeKgEhP5qKhpdwXMgiAgR
+2Ce+pY483+KmGcVBQOoBkYWZjRdOTZo8A/l4TIogQV6W1mSDL7L+53cJ+ZG9IhpX
+i/YkvHtIKy4UtzK9RpGZXiGa0xWnJ+HAOsf1+ZQ/bRR+CwK/BdmsEIp+sDc2zctK
+tOEBxwSNg/PGef//bPCkvzwSYeoVrDBiJuPDTn1caNiI3jWNRHWMqMENB2e10EJD
+QR85oEc1RtcPiaro04ZFmvszAQYjZFMkSFtp+s/ZgftefnuCZVbGRmVc4U/yPAk8
+KF/J46Uk43uqtbGKarICMl8kBfFnyFQXDM3KPeREPiM6fGO2+WE6IeePJ63DJoY5
+SWxBQH8dSGmN229C5An+JGK9ji5UJfAUwthDlQkuX3JPQ7Wai7uMRMZ3yQX7Gp/X
+tqZC2Vw9pQkPnuDHBjLx/8lTXkLUKjOtBurssCbTPO9lrxWOeyBJrfFW7xdr/PTY
+fIKfMBnQvJx54tydp/lrb2WuIaCU
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52007.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52007.pem
new file mode 100644
index 0000000..0b4c115
--- /dev/null
+++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52007.pem
@@ -0,0 +1,68 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207431 (0x6bb3183cdef52007)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 10 17:44:20 2022 GMT
+ Not After : Feb 3 17:44:20 2052 GMT
+ Subject: CN=srv01.client01.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:5e:93:6a:7a:da:75:cc:64:08:e4:f8:f9:2f:2b:
+ 85:36:ee:e1:df:fa:cd:4c:60:f1:44:b5:16:7b:f9:
+ 03:cf:a0:08:67:6f:ae:27:a3:95:8a:68:1e:63:ab:
+ cf:2e:20:62:52:e7:8c:3e:1e:ef:de:0d:69:64:65:
+ b6:e4:df:fe:1a:48:f8:68:75:84:83:11:fb:81:59:
+ 0e:c1:96:48:7f:24:da:11:dd:ac:cb:0a:c5:09:78:
+ 24:31:3a:df:37:e6:b3
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv01.client01.example.com
+ Signature Algorithm: sha256WithRSAEncryption
+ 82:bd:eb:8f:4e:a5:d2:46:c7:d8:70:3c:34:1d:58:43:1b:81:
+ 16:5d:c2:b0:76:4b:a9:f2:10:14:23:e4:ef:dc:59:03:b6:7f:
+ b0:40:34:e5:d0:82:4b:95:a6:07:9a:45:51:94:cf:08:c2:4e:
+ c9:44:d5:f3:b6:ed:f2:a0:01:94:ad:e0:0e:0f:ab:85:6f:35:
+ 4b:07:c8:97:25:fb:69:ff:a1:99:bc:ec:70:6c:51:b5:32:95:
+ e9:c9:45:cf:45:e2:c5:5e:b1:59:a2:e1:f2:83:c8:87:68:c4:
+ 60:e2:db:50:6c:18:64:1b:9a:9a:cc:7c:e7:fd:d9:f2:b7:d1:
+ de:1d:ec:29:c9:58:db:7b:9a:a1:06:9a:ce:36:a0:45:10:dc:
+ 7d:81:24:21:34:30:4c:71:f9:fc:96:37:d6:cf:0d:9d:11:12:
+ c7:62:bc:19:5b:79:e5:e0:37:e8:17:36:4b:13:af:fa:2c:2e:
+ 36:d9:be:53:e1:c3:f9:bc:94:a6:7a:97:14:99:36:f9:14:38:
+ 11:20:3a:2a:9d:fd:64:63:d0:a2:8f:f0:99:a9:02:ca:57:48:
+ d2:7d:65:44:b6:85:a0:38:ec:e8:19:7e:c2:48:e3:1d:22:53:
+ cf:3b:d4:0a:98:e1:72:62:ec:8b:01:3f:5a:ea:26:2c:8c:16:
+ c3:80:5a:c2:5d:40:c5:65:1c:e2:9a:e3:d6:65:16:ee:dc:17:
+ 30:d8:26:87:92:d0:ef:c7:72:07:99:86:05:9e:49:35:41:33:
+ b9:bb:cb:1b:25:50:70:85:e3:0f:c7:b9:b2:37:00:1b:87:a2:
+ 47:97:34:5b:cd:dc:66:22:e5:de:25:ec:57:fe:37:75:2c:03:
+ 10:f4:d4:a7:cc:f5:4b:0b:ff:eb:d3:a6:78:2e:cd:8f:65:51:
+ a7:8c:ef:83:67:ec:94:13:c2:1f:74:74:55:7c:a3:0b:b7:2f:
+ 80:5a:62:04:1d:a2:c0:c1:de:b2:7d:31:3b:a1:fa:f7:40:a7:
+ bd:12:25:95:5b:8b
+-----BEGIN CERTIFICATE-----
+MIIDITCCAYmgAwIBAgIIa7MYPN71IAcwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIxMDE3NDQyMFoYDzIwNTIwMjAz
+MTc0NDIwWjAlMSMwIQYDVQQDDBpzcnYwMS5jbGllbnQwMS5leGFtcGxlLmNvbTB2
+MBAGByqGSM49AgEGBSuBBAAiA2IABF6TanradcxkCOT4+S8rhTbu4d/6zUxg8US1
+Fnv5A8+gCGdvriejlYpoHmOrzy4gYlLnjD4e794NaWRltuTf/hpI+Gh1hIMR+4FZ
+DsGWSH8k2hHdrMsKxQl4JDE63zfms6MpMCcwJQYDVR0RBB4wHIIac3J2MDEuY2xp
+ZW50MDEuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggGBAIK9649OpdJGx9hw
+PDQdWEMbgRZdwrB2S6nyEBQj5O/cWQO2f7BANOXQgkuVpgeaRVGUzwjCTslE1fO2
+7fKgAZSt4A4Pq4VvNUsHyJcl+2n/oZm87HBsUbUylenJRc9F4sVesVmi4fKDyIdo
+xGDi21BsGGQbmprMfOf92fK30d4d7CnJWNt7mqEGms42oEUQ3H2BJCE0MExx+fyW
+N9bPDZ0REsdivBlbeeXgN+gXNksTr/osLjbZvlPhw/m8lKZ6lxSZNvkUOBEgOiqd
+/WRj0KKP8JmpAspXSNJ9ZUS2haA47OgZfsJI4x0iU8871AqY4XJi7IsBP1rqJiyM
+FsOAWsJdQMVlHOKa49ZlFu7cFzDYJoeS0O/HcgeZhgWeSTVBM7m7yxslUHCF4w/H
+ubI3ABuHokeXNFvN3GYi5d4l7Ff+N3UsAxD01KfM9UsL/+vTpnguzY9lUaeM74Nn
+7JQTwh90dFV8owu3L4BaYgQdosDB3rJ9MTuh+vdAp70SJZVbiw==
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52008.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52008.pem
new file mode 100644
index 0000000..1b43bbd
--- /dev/null
+++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52008.pem
@@ -0,0 +1,68 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207432 (0x6bb3183cdef52008)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Feb 11 13:21:12 2022 GMT
+ Not After : Feb 4 13:21:12 2052 GMT
+ Subject: CN=srv01.client02-ns2.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:e6:45:fa:57:12:6c:59:10:23:8b:7a:5c:76:33:
+ eb:3b:41:fa:b7:1c:90:b3:2f:33:2d:45:7b:e3:e5:
+ b6:a5:a2:a2:a4:14:f4:50:9d:b0:c6:38:ba:e9:45:
+ 65:a4:65:b9:10:32:2f:93:9b:d5:d8:cf:b4:29:5b:
+ dc:4e:c8:ec:a6:9f:58:76:24:f4:c5:d1:48:55:52:
+ eb:5d:b0:85:93:85:ee:3e:b8:c4:b1:cd:08:59:95:
+ 12:ff:7b:9b:ee:6a:b9
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv01.client02-ns2.example.com
+ Signature Algorithm: sha256WithRSAEncryption
+ 43:ec:0f:62:17:f6:f4:90:3b:7c:36:21:f2:18:94:a6:42:51:
+ 1e:1d:2a:43:8f:05:b7:8d:3c:ca:f0:20:2f:65:4b:be:48:ad:
+ 6a:0a:cc:2d:1f:d6:27:1d:af:4a:36:86:ed:0d:03:75:c5:71:
+ ec:58:9b:ec:f9:0f:e4:83:ef:6f:91:da:20:73:47:ac:e7:c7:
+ 8b:22:b2:d1:6e:a0:b0:d6:1c:4c:70:1e:74:08:1d:7f:61:06:
+ e5:be:f3:e8:c4:15:60:e2:b0:02:9b:f0:13:af:76:5b:a8:c7:
+ 91:2c:10:5f:0d:32:89:51:5a:7f:17:1b:7c:c6:46:97:ee:e7:
+ bb:8a:48:38:a2:52:d4:ff:3b:1c:ec:4a:a9:8c:a5:23:3a:04:
+ bb:d7:b8:ad:5b:69:7f:1d:be:ca:96:e0:eb:56:05:43:ee:c8:
+ ff:2c:48:03:00:c6:c2:ac:fc:4e:15:47:86:c5:33:ed:70:f6:
+ 98:bc:0b:07:b9:5b:1a:ec:fd:3c:bf:26:61:68:fc:db:02:55:
+ 07:ae:76:0e:be:ff:c5:b8:56:fb:52:54:a4:b1:2d:64:b4:1d:
+ 55:02:4f:da:06:bd:26:e4:22:d2:94:1f:7e:29:c4:97:10:d1:
+ 75:7d:41:53:be:46:52:70:b1:d9:ff:bb:9f:96:19:e3:a0:ba:
+ d0:4a:5a:8d:da:22:73:89:f0:4c:e6:18:80:53:be:bd:64:56:
+ 6a:c9:58:71:40:66:9e:4a:3e:31:3b:74:9e:6e:6a:f5:65:ca:
+ 93:06:52:00:74:65:a0:3a:eb:2e:56:56:d2:a5:4b:0e:85:17:
+ 25:78:cb:f3:f9:53:7b:85:f9:82:15:87:bc:36:70:b5:69:64:
+ 48:11:79:b9:2c:2e:cc:09:fd:0f:b0:b7:cd:97:3b:c7:0f:49:
+ 1a:fc:15:49:d6:1c:a9:dc:14:ff:44:d2:be:5a:36:00:66:0c:
+ d5:b8:bf:16:9e:60:27:79:c0:f5:b4:ff:2f:af:8c:b2:49:75:
+ 61:44:05:1a:e8:cd
+-----BEGIN CERTIFICATE-----
+MIIDKTCCAZGgAwIBAgIIa7MYPN71IAgwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIxMTEzMjExMloYDzIwNTIwMjA0
+MTMyMTEyWjApMScwJQYDVQQDDB5zcnYwMS5jbGllbnQwMi1uczIuZXhhbXBsZS5j
+b20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATmRfpXEmxZECOLelx2M+s7Qfq3HJCz
+LzMtRXvj5baloqKkFPRQnbDGOLrpRWWkZbkQMi+Tm9XYz7QpW9xOyOymn1h2JPTF
+0UhVUutdsIWThe4+uMSxzQhZlRL/e5vuarmjLTArMCkGA1UdEQQiMCCCHnNydjAx
+LmNsaWVudDAyLW5zMi5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAQ+wP
+Yhf29JA7fDYh8hiUpkJRHh0qQ48Ft408yvAgL2VLvkitagrMLR/WJx2vSjaG7Q0D
+dcVx7Fib7PkP5IPvb5HaIHNHrOfHiyKy0W6gsNYcTHAedAgdf2EG5b7z6MQVYOKw
+ApvwE692W6jHkSwQXw0yiVFafxcbfMZGl+7nu4pIOKJS1P87HOxKqYylIzoEu9e4
+rVtpfx2+ypbg61YFQ+7I/yxIAwDGwqz8ThVHhsUz7XD2mLwLB7lbGuz9PL8mYWj8
+2wJVB652Dr7/xbhW+1JUpLEtZLQdVQJP2ga9JuQi0pQffinElxDRdX1BU75GUnCx
+2f+7n5YZ46C60Epajdoic4nwTOYYgFO+vWRWaslYcUBmnko+MTt0nm5q9WXKkwZS
+AHRloDrrLlZW0qVLDoUXJXjL8/lTe4X5ghWHvDZwtWlkSBF5uSwuzAn9D7C3zZc7
+xw9JGvwVSdYcqdwU/0TSvlo2AGYM1bi/Fp5gJ3nA9bT/L6+Mskl1YUQFGujN
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52009.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52009.pem
new file mode 100644
index 0000000..99e4a71
--- /dev/null
+++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52009.pem
@@ -0,0 +1,69 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7760573232607207433 (0x6bb3183cdef52009)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com
+ Validity
+ Not Before: Aug 14 05:00:00 2012 GMT
+ Not After : Aug 14 06:00:00 2012 GMT
+ Subject: CN=srv01.client03-ns2-expired.example.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:38:9a:9b:c2:6a:82:a6:d1:50:8a:78:7a:d1:be:
+ 61:be:d4:b6:d3:d6:a2:02:97:a4:48:50:c0:c5:1d:
+ d8:2d:23:19:25:6e:91:02:1d:69:c2:77:d6:f1:a8:
+ 4f:4a:9a:1d:3c:69:5a:89:41:0a:f2:e0:64:57:1b:
+ 0e:9e:df:9f:4c:7b:3c:42:dc:21:c8:2c:95:ab:b3:
+ 4c:5f:56:c4:70:ee:8a:a4:e4:46:c4:9e:98:f5:c8:
+ 7b:b2:73:d7:45:93:f0
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:srv01.client03-ns2-expired.example.com
+ Signature Algorithm: sha256WithRSAEncryption
+ 38:12:1f:5f:26:b6:8e:9b:3f:77:89:5a:b8:e8:46:78:c3:d6:
+ f0:0c:67:5f:d5:a3:9c:f6:f2:0a:ae:9c:87:74:9f:a3:5b:8a:
+ 27:58:47:e5:78:1a:e9:db:b5:cc:28:a7:f8:18:e3:e7:20:43:
+ cf:82:06:5d:a1:d0:82:ab:15:be:86:46:1e:e6:4d:ad:78:a4:
+ 16:6c:99:41:3d:29:21:c8:6b:9d:3d:4a:cd:93:37:1f:1c:88:
+ c7:ae:b6:7c:73:42:57:57:32:9d:e8:c6:e2:3e:da:12:57:3e:
+ c8:56:4a:bb:d4:01:fc:8e:30:8d:19:fe:61:3d:5e:02:64:65:
+ a2:46:b3:6e:ea:f9:cb:4e:f0:b9:f6:bc:6b:38:10:19:d0:93:
+ f8:f7:d9:4c:d2:87:2c:7f:dc:f5:00:c6:29:dd:00:5e:d2:f4:
+ df:52:fb:7a:5a:ad:98:36:77:72:1f:01:ed:48:91:48:16:2d:
+ 35:a5:15:21:98:ff:7e:5d:a1:45:c9:5f:9d:c2:3e:e5:98:e2:
+ ee:ce:4d:18:76:3d:8a:0a:64:9b:f1:19:9d:b6:82:af:1b:15:
+ d3:48:69:f1:9b:67:76:1b:41:8e:1d:69:d5:31:64:95:01:41:
+ 73:c1:a9:29:53:6b:f3:29:ad:e0:96:52:8e:3e:8d:c1:8e:d8:
+ b5:0c:94:5f:a2:6c:3c:0f:3e:5b:10:af:21:00:74:d0:b7:30:
+ 6c:44:fb:3d:09:46:8d:1d:e6:c2:e4:0a:5b:f4:eb:e1:71:c7:
+ d5:36:13:90:05:fe:65:16:61:24:b5:41:f2:10:bd:2c:c3:34:
+ 69:15:25:d1:32:f2:b3:d7:da:23:1b:e9:5b:33:63:43:c8:dc:
+ 68:f2:31:b5:93:0e:64:ea:9a:45:36:9f:96:44:38:1e:4e:d8:
+ 45:ba:37:68:06:4d:da:d4:16:d3:3e:77:86:4e:8d:58:d6:06:
+ a8:60:11:4d:d9:81:f3:85:2b:ee:58:50:6e:ea:2b:f7:84:00:
+ 9c:ec:a1:90:d4:94
+-----BEGIN CERTIFICATE-----
+MIIDNzCCAZ+gAwIBAgIIa7MYPN71IAkwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE
+BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp
+djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD
+DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTEyMDgxNDA1MDAwMFoXDTEyMDgxNDA2
+MDAwMFowMTEvMC0GA1UEAwwmc3J2MDEuY2xpZW50MDMtbnMyLWV4cGlyZWQuZXhh
+bXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ4mpvCaoKm0VCKeHrRvmG+
+1LbT1qICl6RIUMDFHdgtIxklbpECHWnCd9bxqE9Kmh08aVqJQQry4GRXGw6e359M
+ezxC3CHILJWrs0xfVsRw7oqk5EbEnpj1yHuyc9dFk/CjNTAzMDEGA1UdEQQqMCiC
+JnNydjAxLmNsaWVudDAzLW5zMi1leHBpcmVkLmV4YW1wbGUuY29tMA0GCSqGSIb3
+DQEBCwUAA4IBgQA4Eh9fJraOmz93iVq46EZ4w9bwDGdf1aOc9vIKrpyHdJ+jW4on
+WEfleBrp27XMKKf4GOPnIEPPggZdodCCqxW+hkYe5k2teKQWbJlBPSkhyGudPUrN
+kzcfHIjHrrZ8c0JXVzKd6MbiPtoSVz7IVkq71AH8jjCNGf5hPV4CZGWiRrNu6vnL
+TvC59rxrOBAZ0JP499lM0ocsf9z1AMYp3QBe0vTfUvt6Wq2YNndyHwHtSJFIFi01
+pRUhmP9+XaFFyV+dwj7lmOLuzk0Ydj2KCmSb8RmdtoKvGxXTSGnxm2d2G0GOHWnV
+MWSVAUFzwakpU2vzKa3gllKOPo3Bjti1DJRfomw8Dz5bEK8hAHTQtzBsRPs9CUaN
+HebC5Apb9OvhccfVNhOQBf5lFmEktUHyEL0swzRpFSXRMvKz19ojG+lbM2NDyNxo
+8jG1kw5k6ppFNp+WRDgeTthFujdoBk3a1BbTPneGTo1Y1gaoYBFN2YHzhSvuWFBu
+6iv3hACc7KGQ1JQ=
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/CA/private/CA.key b/bin/tests/system/doth/CA/private/CA.key
new file mode 100644
index 0000000..2d5419d
--- /dev/null
+++ b/bin/tests/system/doth/CA/private/CA.key
@@ -0,0 +1,39 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIG5AIBAAKCAYEAouoRHoAc6VCmxNTU6Ge7s+xDFGO0wXJJIsP+8nUyyjWvGCOC
+aQYLhb1kLA2NHRhSSKFcMh8jcd7Hlvy6CAec1j2dsWzryy3HgPrdjWaW3PfBO41D
+lUtdt8hA/p6pX2YwqvWbdK/3s8J0LY5xRZKNZnFOB/Sb4PGiIJ1NgMRO/M3IlPQm
+PO/faRRTU4SI26KCPKFW342826Zi88YwOd6w5mQU4fskk5TGtlNqE+Fj40ZbWVpy
+VXoEUS6RveRp020NX5CQG49SLtdF05AnnsATqmgNVCXptGuqW8uaHRONeGO3NBEy
+nJmibWBDUMjtCCcGVgyrVXuTkyAJJWpImnshUwgMNYebRwmC2iVv2LtsJS5eUTUH
+EWffnFl55XU2PkyNYgY35gA4y3SiWFJYV8+5FibU4ut0nb+lmHBF8WlqcU/kd3tp
+Gkf0exjqOIHZFqV9bIhpUbXhxx9v9+gkkGQ9nrXE1KRlvigxxUeIK5xHy9a7fVIL
+wo6WuCnLLJmbVkklAgMBAAECggGBAI5ZV3v/FUQIZK+4CBDKEwizeClotZgR9DWc
+bDgOj8KABe5hmKGL1qWVRuH3NUYm6j7sP1LMQnxM3LjhOuupOzE3xYIyWhW+eoQI
+r23OJiQNl5ohZNweblUXdTMGD5h8AipfUOY0m4tGbZ0gyXixBTxt5HCvG0UB3VgC
+GqZY4Wujo5ADhSXZsqxuRiDDvZGr/YBcuTu87Tg/ulam5ZyrKIcnC9gpSVxqsva9
+DAMy/cSoxUjd7ukhJISK3G3AF3fV4GSslQcJTlyJ2D3+LnqPuHJKYTI4hc46lN3x
+E2g24GdSCPYf6SoEPwACXtbavV8TXwQPJrHN+f+0/ePCI4jkYe5NoA3gwVgMb/WB
+wFchxzVh3V4e8tPGiG+ofKl81DSAW8VZCJLUIbTEce9oxafPT78WJxdC0wWbh5S8
+V/qN6sW/yWnK3oY9SilWhJGRwKOZ+8xtStaDeCzyCaOqEcWi8ZR0QfC33UozlhdC
+SrMKnOXmn/rUuXGrVR56IzIl0M7YAQKBwQDM3GJDdlFuHn6L0syKYdHDS8gXD9ke
+s+ochIP6jvkEPcayaEoZGl8s7RT3iztqXod7wLaZdotktxfDAZnJfeuOcVrCu+Bx
+HLytnBvV6czMfp3REGgQAJQeusSgtlBCTHHVOsDzIjdnkY3WBa7IiFYWO5wnYrGx
+r3ucnwnHaUVDMj1r4YI7mYIpCuYQl6eGyW7mhWewyhVwoQXKbifdrXxjvOigL0Cp
+tgsoU9pql3hpphOaYMX6hLOincTfaMxfnCECgcEAy5UXp3dA0OwK+4iDGKr+cUpk
+AtGTheiE+8zEVh2KYFLt921mW/QZiB1+xtnkknp3c7u07Ugk8jAEXzCkwMnN5ZCx
+LrJ72fC+cLIAbRm6/vMMP8iz83wyttao4qNMeoOBBfE9rEiP+lrugpv282V3ZHYa
+IUZWTeugJbckUHTbD3RZQExmQcRVG3m/TzonBfoZ8HoRj/n3d7V2T911cHUhi8Xn
+RQIi2m63VofOIep86LgartlKneMWnL0oOPq4RKyFAoHAZUzpDkD4nUJZAx025Yrf
+ZfoYNEcy7vq6XmWsuX5vZoiBs4DcezNOMvH9NzdTJxMdXbV61cIHxcK/7j7hZABv
+NZ2Z6sdqgaRbLGIQZaPaEJjfwxygyKDwnY1vY6UjZNVWSMFn3hJiYUVZZKakuiao
+ow/Q9KzZ/2ot7tG5zTCh/ktekfUOKBiNg2wPPc8wGPeMblMzZflXxrzpFyOHdRev
+dcZZJbSX/hO1yrhEPgculNd5xBHsdCegiF4JlwvEW9bhAoHAZQQiy5bx03j8bhkr
+q6bVQFPAUmG5iL16lxLg7TYVPnyH1bk0DDaQIKk6CeN+dmxML2IZgY/FvWK0GKOj
+bIH2J43nTRuFNvwtEvBQI9KbpfvlvRSSriOXaoATJvoObdAoylEM4BrVTk2mgapw
+HA/h8Thk+NPU6S8ctPouC7ogJIf/7Va7erC35j0//0kEqgOSsW9wnXdUItMo1LI3
+nsiQD7Hwcp5/utErKcWTM+MNfdA0dUQesT9ILhfyCGvn2TOdAoHBAKldZkDyRcu9
+r9uDF1bhUEnpV2k4hgvTuCvQ3rzyx3WrVT8ChEmePC8Ke5A54ffu/YdbpDLbdf2c
+j4n5CQhHbMIZs3P2hB3WqDCImApCfMbXaltfBbaT0j7uLJPMp+2+f/wWYpc3R+bn
+HVnaRI2PoXXmG9OjQSQdVZ5gNpkEuemAo3dJOSS6BMqQaSxUynGy7o/a/d4izBjd
+B58Fwq3sZI/Xv90Se9+b6ICST3YJ3p0vn8RKzmlCQjLg/xynpCByiw==
+-----END RSA PRIVATE KEY-----
diff --git a/bin/tests/system/doth/CA/serial b/bin/tests/system/doth/CA/serial
new file mode 100644
index 0000000..a20b068
--- /dev/null
+++ b/bin/tests/system/doth/CA/serial
@@ -0,0 +1 @@
+6BB3183CDEF5200A
diff --git a/bin/tests/system/doth/README.curl b/bin/tests/system/doth/README.curl
new file mode 100644
index 0000000..475f20f
--- /dev/null
+++ b/bin/tests/system/doth/README.curl
@@ -0,0 +1,38 @@
+<!--
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+-->
+
+DoH query values that can be passed on the command line for testing
+with curl can be obtained by encoding binary DNS messages into
+base64url, with trailing '='s removed.
+
+For example:
+
+$ perl bin/tests/system/fromhex.pl << EOF | base64url
+ # Transaction ID
+ 0001
+ # Standard query
+ 0000
+ # Questions: 1, Additional: 0
+ 0001 0000 0000 0000
+ # QNAME: example
+ 07 6578616d706c65 00
+ # Type: SOA
+ 0006
+ Class: IN
+ 0001
+EOF
+
+This produces the string "AAEAAAABAAAAAAAAB2V4YW1wbGUAAAbFrMonAAE=". With
+the trailing '=' removed, this can then be passed to curl:
+
+curl "https://<server>/dns-query?dns=AAEAAAABAAAAAAAAB2V4YW1wbGUAAAbFrMonAAE"
diff --git a/bin/tests/system/doth/clean.sh b/bin/tests/system/doth/clean.sh
new file mode 100644
index 0000000..c81c6a1
--- /dev/null
+++ b/bin/tests/system/doth/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f ./*/named.conf
+rm -f ./*/named.memstats
+rm -f ./*/named.run
+rm -f ./*/named.run.prev
+rm -f ./dig.out.*
+rm -f ./gnutls-cli.*
+rm -f ./sslyze.log.*
+rm -f ./*/example*.db
+rm -rf ./headers.*
diff --git a/bin/tests/system/doth/conftest.py b/bin/tests/system/doth/conftest.py
new file mode 100644
index 0000000..813be14
--- /dev/null
+++ b/bin/tests/system/doth/conftest.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import shutil
+import subprocess
+
+import pytest
+
+
+@pytest.fixture
+def gnutls_cli_executable():
+ # Ensure gnutls-cli is available.
+ executable = shutil.which("gnutls-cli")
+ if not executable:
+ pytest.skip("gnutls-cli not found in PATH")
+
+ # Ensure gnutls-cli supports the --logfile command-line option.
+ output = subprocess.run(
+ [executable, "--logfile=/dev/null"],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ check=False,
+ ).stdout
+ if b"illegal option" in output:
+ pytest.skip("gnutls-cli does not support the --logfile option")
+
+ return executable
+
+
+@pytest.fixture
+def sslyze_executable():
+ # Check whether sslyze is available.
+ executable = shutil.which("sslyze")
+ if not executable:
+ pytest.skip("sslyze not found in PATH")
+
+ return executable
diff --git a/bin/tests/system/doth/dhparam3072.pem b/bin/tests/system/doth/dhparam3072.pem
new file mode 100644
index 0000000..9c2e0aa
--- /dev/null
+++ b/bin/tests/system/doth/dhparam3072.pem
@@ -0,0 +1,11 @@
+-----BEGIN DH PARAMETERS-----
+MIIBiAKCAYEA5D/Oioe+G+EMf/9RVxmcV4rZAtqZpVTFHcX0ZulvdiQGCQmopm6K
+3+0uoU2J6WVMjhna5nHD2NO9miRDI/jIxX9g9k6PedSB4o3fSTtkAnGtUbB8S+Ab
+EHtWfd7FTES8P1n16HN7BfPXVbP8zTcK+jO63KdQoxueYoETcrw0Myi9Lm8ri8os
+O4oQ+XAH7GzZ60bcYV9jge0XIRUGVnYZDjWMlnwMvZyjLivxKXTC9HPNA6FF1/0H
+0LPhsfjdoLNsVHFzfQz7QELMfHbTd0C8y0UMDQw9FqUp0esHZ5gsTlqnDHp2ZHoR
+JDfNl4yVO5Gv4HiFJ0NSdggefhESU3FRAOhMmUkctOCxk5hyPqGMsvofOajY2MBp
+eCffrKuAU6/dGUeq8inwrZlAMIZ20WyskHmbHnc4DXo2Uo6xSZo3xyEq1ofXXwTZ
+vPw4e12so3RJAT2a8UsHf7DG1tH+9ke7HCAJQWxUizRFRsMi1Nl/7ikS4f3zgIbX
+GKz9+uk5eS6jAgEC
+-----END DH PARAMETERS-----
diff --git a/bin/tests/system/doth/example.axfr.good b/bin/tests/system/doth/example.axfr.good
new file mode 100644
index 0000000..539e58b
--- /dev/null
+++ b/bin/tests/system/doth/example.axfr.good
@@ -0,0 +1,2676 @@
+example. 86400 IN SOA ns2.example. hostmaster.example. 1397051952 5 5 1814400 3600
+example. 3600 IN NS ns2.example.
+a01.example. 3600 IN A 0.0.0.0
+a02.example. 3600 IN A 255.255.255.255
+a601.example. 3600 IN A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+a601.example. 3600 IN A6 64 ::ffff:ffff:ffff:ffff foo.
+a601.example. 3600 IN A6 127 ::1 foo.
+a601.example. 3600 IN A6 128 .
+aaaa01.example. 3600 IN AAAA ::1
+aaaa02.example. 3600 IN AAAA fd92:7065:b8e:ffff::5
+afsdb01.example. 3600 IN AFSDB 0 hostname.example.
+afsdb02.example. 3600 IN AFSDB 65535 .
+amtrelay01.example. 3600 IN AMTRELAY 0 0 0
+amtrelay02.example. 3600 IN AMTRELAY 0 1 0
+amtrelay03.example. 3600 IN AMTRELAY 0 0 1 0.0.0.0
+amtrelay04.example. 3600 IN AMTRELAY 0 0 2 ::
+amtrelay05.example. 3600 IN AMTRELAY 0 0 3 example.net.
+amtrelay06.example. 3600 IN AMTRELAY \# 2 0004
+apl01.example. 3600 IN APL !1:10.0.0.1/32 1:10.0.0.0/24
+apl02.example. 3600 IN APL
+atma01.example. 3600 IN ATMA +61200000000
+atma02.example. 3600 IN ATMA +61200000000
+atma03.example. 3600 IN ATMA 1234567890abcdef
+atma04.example. 3600 IN ATMA fedcba0987654321
+avc.example. 3600 IN AVC "foo:bar"
+biganswer.example. 3600 IN A 10.10.1.1
+biganswer.example. 3600 IN A 10.10.1.2
+biganswer.example. 3600 IN A 10.10.1.3
+biganswer.example. 3600 IN A 10.10.1.4
+biganswer.example. 3600 IN A 10.10.1.5
+biganswer.example. 3600 IN A 10.10.1.6
+biganswer.example. 3600 IN A 10.10.1.7
+biganswer.example. 3600 IN A 10.10.1.8
+biganswer.example. 3600 IN A 10.10.1.9
+biganswer.example. 3600 IN A 10.10.1.10
+biganswer.example. 3600 IN A 10.10.1.11
+biganswer.example. 3600 IN A 10.10.1.12
+biganswer.example. 3600 IN A 10.10.1.13
+biganswer.example. 3600 IN A 10.10.1.14
+biganswer.example. 3600 IN A 10.10.1.15
+biganswer.example. 3600 IN A 10.10.1.16
+biganswer.example. 3600 IN A 10.10.1.17
+biganswer.example. 3600 IN A 10.10.1.18
+biganswer.example. 3600 IN A 10.10.1.19
+biganswer.example. 3600 IN A 10.10.1.20
+biganswer.example. 3600 IN A 10.10.1.21
+biganswer.example. 3600 IN A 10.10.1.22
+biganswer.example. 3600 IN A 10.10.1.23
+biganswer.example. 3600 IN A 10.10.1.24
+biganswer.example. 3600 IN A 10.10.1.25
+biganswer.example. 3600 IN A 10.10.1.26
+biganswer.example. 3600 IN A 10.10.1.27
+biganswer.example. 3600 IN A 10.10.1.28
+biganswer.example. 3600 IN A 10.10.1.29
+biganswer.example. 3600 IN A 10.10.1.30
+biganswer.example. 3600 IN A 10.10.1.31
+biganswer.example. 3600 IN A 10.10.1.32
+biganswer.example. 3600 IN A 10.10.1.33
+biganswer.example. 3600 IN A 10.10.1.34
+biganswer.example. 3600 IN A 10.10.1.35
+biganswer.example. 3600 IN A 10.10.1.36
+biganswer.example. 3600 IN A 10.10.1.37
+biganswer.example. 3600 IN A 10.10.1.38
+biganswer.example. 3600 IN A 10.10.1.39
+biganswer.example. 3600 IN A 10.10.1.40
+biganswer.example. 3600 IN A 10.10.1.41
+biganswer.example. 3600 IN A 10.10.1.42
+biganswer.example. 3600 IN A 10.10.1.43
+biganswer.example. 3600 IN A 10.10.1.44
+biganswer.example. 3600 IN A 10.10.1.45
+biganswer.example. 3600 IN A 10.10.1.46
+biganswer.example. 3600 IN A 10.10.1.47
+biganswer.example. 3600 IN A 10.10.1.48
+biganswer.example. 3600 IN A 10.10.1.49
+biganswer.example. 3600 IN A 10.10.1.50
+biganswer.example. 3600 IN A 10.10.2.1
+biganswer.example. 3600 IN A 10.10.2.2
+biganswer.example. 3600 IN A 10.10.2.3
+biganswer.example. 3600 IN A 10.10.2.4
+biganswer.example. 3600 IN A 10.10.2.5
+biganswer.example. 3600 IN A 10.10.2.6
+biganswer.example. 3600 IN A 10.10.2.7
+biganswer.example. 3600 IN A 10.10.2.8
+biganswer.example. 3600 IN A 10.10.2.9
+biganswer.example. 3600 IN A 10.10.2.10
+biganswer.example. 3600 IN A 10.10.2.11
+biganswer.example. 3600 IN A 10.10.2.12
+biganswer.example. 3600 IN A 10.10.2.13
+biganswer.example. 3600 IN A 10.10.2.14
+biganswer.example. 3600 IN A 10.10.2.15
+biganswer.example. 3600 IN A 10.10.2.16
+biganswer.example. 3600 IN A 10.10.2.17
+biganswer.example. 3600 IN A 10.10.2.18
+biganswer.example. 3600 IN A 10.10.2.19
+biganswer.example. 3600 IN A 10.10.2.20
+biganswer.example. 3600 IN A 10.10.2.21
+biganswer.example. 3600 IN A 10.10.2.22
+biganswer.example. 3600 IN A 10.10.2.23
+biganswer.example. 3600 IN A 10.10.2.24
+biganswer.example. 3600 IN A 10.10.2.25
+biganswer.example. 3600 IN A 10.10.2.26
+biganswer.example. 3600 IN A 10.10.2.27
+biganswer.example. 3600 IN A 10.10.2.28
+biganswer.example. 3600 IN A 10.10.2.29
+biganswer.example. 3600 IN A 10.10.2.30
+biganswer.example. 3600 IN A 10.10.2.31
+biganswer.example. 3600 IN A 10.10.2.32
+biganswer.example. 3600 IN A 10.10.2.33
+biganswer.example. 3600 IN A 10.10.2.34
+biganswer.example. 3600 IN A 10.10.2.35
+biganswer.example. 3600 IN A 10.10.2.36
+biganswer.example. 3600 IN A 10.10.2.37
+biganswer.example. 3600 IN A 10.10.2.38
+biganswer.example. 3600 IN A 10.10.2.39
+biganswer.example. 3600 IN A 10.10.2.40
+biganswer.example. 3600 IN A 10.10.2.41
+biganswer.example. 3600 IN A 10.10.2.42
+biganswer.example. 3600 IN A 10.10.2.43
+biganswer.example. 3600 IN A 10.10.2.44
+biganswer.example. 3600 IN A 10.10.2.45
+biganswer.example. 3600 IN A 10.10.2.46
+biganswer.example. 3600 IN A 10.10.2.47
+biganswer.example. 3600 IN A 10.10.2.48
+biganswer.example. 3600 IN A 10.10.2.49
+biganswer.example. 3600 IN A 10.10.2.50
+biganswer.example. 3600 IN A 10.10.3.1
+biganswer.example. 3600 IN A 10.10.3.2
+biganswer.example. 3600 IN A 10.10.3.3
+biganswer.example. 3600 IN A 10.10.3.4
+biganswer.example. 3600 IN A 10.10.3.5
+biganswer.example. 3600 IN A 10.10.3.6
+biganswer.example. 3600 IN A 10.10.3.7
+biganswer.example. 3600 IN A 10.10.3.8
+biganswer.example. 3600 IN A 10.10.3.9
+biganswer.example. 3600 IN A 10.10.3.10
+biganswer.example. 3600 IN A 10.10.3.11
+biganswer.example. 3600 IN A 10.10.3.12
+biganswer.example. 3600 IN A 10.10.3.13
+biganswer.example. 3600 IN A 10.10.3.14
+biganswer.example. 3600 IN A 10.10.3.15
+biganswer.example. 3600 IN A 10.10.3.16
+biganswer.example. 3600 IN A 10.10.3.17
+biganswer.example. 3600 IN A 10.10.3.18
+biganswer.example. 3600 IN A 10.10.3.19
+biganswer.example. 3600 IN A 10.10.3.20
+biganswer.example. 3600 IN A 10.10.3.21
+biganswer.example. 3600 IN A 10.10.3.22
+biganswer.example. 3600 IN A 10.10.3.23
+biganswer.example. 3600 IN A 10.10.3.24
+biganswer.example. 3600 IN A 10.10.3.25
+biganswer.example. 3600 IN A 10.10.3.26
+biganswer.example. 3600 IN A 10.10.3.27
+biganswer.example. 3600 IN A 10.10.3.28
+biganswer.example. 3600 IN A 10.10.3.29
+biganswer.example. 3600 IN A 10.10.3.30
+biganswer.example. 3600 IN A 10.10.3.31
+biganswer.example. 3600 IN A 10.10.3.32
+biganswer.example. 3600 IN A 10.10.3.33
+biganswer.example. 3600 IN A 10.10.3.34
+biganswer.example. 3600 IN A 10.10.3.35
+biganswer.example. 3600 IN A 10.10.3.36
+biganswer.example. 3600 IN A 10.10.3.37
+biganswer.example. 3600 IN A 10.10.3.38
+biganswer.example. 3600 IN A 10.10.3.39
+biganswer.example. 3600 IN A 10.10.3.40
+biganswer.example. 3600 IN A 10.10.3.41
+biganswer.example. 3600 IN A 10.10.3.42
+biganswer.example. 3600 IN A 10.10.3.43
+biganswer.example. 3600 IN A 10.10.3.44
+biganswer.example. 3600 IN A 10.10.3.45
+biganswer.example. 3600 IN A 10.10.3.46
+biganswer.example. 3600 IN A 10.10.3.47
+biganswer.example. 3600 IN A 10.10.3.48
+biganswer.example. 3600 IN A 10.10.3.49
+biganswer.example. 3600 IN A 10.10.3.50
+biganswer.example. 3600 IN A 10.10.4.1
+biganswer.example. 3600 IN A 10.10.4.2
+biganswer.example. 3600 IN A 10.10.4.3
+biganswer.example. 3600 IN A 10.10.4.4
+biganswer.example. 3600 IN A 10.10.4.5
+biganswer.example. 3600 IN A 10.10.4.6
+biganswer.example. 3600 IN A 10.10.4.7
+biganswer.example. 3600 IN A 10.10.4.8
+biganswer.example. 3600 IN A 10.10.4.9
+biganswer.example. 3600 IN A 10.10.4.10
+biganswer.example. 3600 IN A 10.10.4.11
+biganswer.example. 3600 IN A 10.10.4.12
+biganswer.example. 3600 IN A 10.10.4.13
+biganswer.example. 3600 IN A 10.10.4.14
+biganswer.example. 3600 IN A 10.10.4.15
+biganswer.example. 3600 IN A 10.10.4.16
+biganswer.example. 3600 IN A 10.10.4.17
+biganswer.example. 3600 IN A 10.10.4.18
+biganswer.example. 3600 IN A 10.10.4.19
+biganswer.example. 3600 IN A 10.10.4.20
+biganswer.example. 3600 IN A 10.10.4.21
+biganswer.example. 3600 IN A 10.10.4.22
+biganswer.example. 3600 IN A 10.10.4.23
+biganswer.example. 3600 IN A 10.10.4.24
+biganswer.example. 3600 IN A 10.10.4.25
+biganswer.example. 3600 IN A 10.10.4.26
+biganswer.example. 3600 IN A 10.10.4.27
+biganswer.example. 3600 IN A 10.10.4.28
+biganswer.example. 3600 IN A 10.10.4.29
+biganswer.example. 3600 IN A 10.10.4.30
+biganswer.example. 3600 IN A 10.10.4.31
+biganswer.example. 3600 IN A 10.10.4.32
+biganswer.example. 3600 IN A 10.10.4.33
+biganswer.example. 3600 IN A 10.10.4.34
+biganswer.example. 3600 IN A 10.10.4.35
+biganswer.example. 3600 IN A 10.10.4.36
+biganswer.example. 3600 IN A 10.10.4.37
+biganswer.example. 3600 IN A 10.10.4.38
+biganswer.example. 3600 IN A 10.10.4.39
+biganswer.example. 3600 IN A 10.10.4.40
+biganswer.example. 3600 IN A 10.10.4.41
+biganswer.example. 3600 IN A 10.10.4.42
+biganswer.example. 3600 IN A 10.10.4.43
+biganswer.example. 3600 IN A 10.10.4.44
+biganswer.example. 3600 IN A 10.10.4.45
+biganswer.example. 3600 IN A 10.10.4.46
+biganswer.example. 3600 IN A 10.10.4.47
+biganswer.example. 3600 IN A 10.10.4.48
+biganswer.example. 3600 IN A 10.10.4.49
+biganswer.example. 3600 IN A 10.10.4.50
+biganswer.example. 3600 IN A 10.10.5.1
+biganswer.example. 3600 IN A 10.10.5.2
+biganswer.example. 3600 IN A 10.10.5.3
+biganswer.example. 3600 IN A 10.10.5.4
+biganswer.example. 3600 IN A 10.10.5.5
+biganswer.example. 3600 IN A 10.10.5.6
+biganswer.example. 3600 IN A 10.10.5.7
+biganswer.example. 3600 IN A 10.10.5.8
+biganswer.example. 3600 IN A 10.10.5.9
+biganswer.example. 3600 IN A 10.10.5.10
+biganswer.example. 3600 IN A 10.10.5.11
+biganswer.example. 3600 IN A 10.10.5.12
+biganswer.example. 3600 IN A 10.10.5.13
+biganswer.example. 3600 IN A 10.10.5.14
+biganswer.example. 3600 IN A 10.10.5.15
+biganswer.example. 3600 IN A 10.10.5.16
+biganswer.example. 3600 IN A 10.10.5.17
+biganswer.example. 3600 IN A 10.10.5.18
+biganswer.example. 3600 IN A 10.10.5.19
+biganswer.example. 3600 IN A 10.10.5.20
+biganswer.example. 3600 IN A 10.10.5.21
+biganswer.example. 3600 IN A 10.10.5.22
+biganswer.example. 3600 IN A 10.10.5.23
+biganswer.example. 3600 IN A 10.10.5.24
+biganswer.example. 3600 IN A 10.10.5.25
+biganswer.example. 3600 IN A 10.10.5.26
+biganswer.example. 3600 IN A 10.10.5.27
+biganswer.example. 3600 IN A 10.10.5.28
+biganswer.example. 3600 IN A 10.10.5.29
+biganswer.example. 3600 IN A 10.10.5.30
+biganswer.example. 3600 IN A 10.10.5.31
+biganswer.example. 3600 IN A 10.10.5.32
+biganswer.example. 3600 IN A 10.10.5.33
+biganswer.example. 3600 IN A 10.10.5.34
+biganswer.example. 3600 IN A 10.10.5.35
+biganswer.example. 3600 IN A 10.10.5.36
+biganswer.example. 3600 IN A 10.10.5.37
+biganswer.example. 3600 IN A 10.10.5.38
+biganswer.example. 3600 IN A 10.10.5.39
+biganswer.example. 3600 IN A 10.10.5.40
+biganswer.example. 3600 IN A 10.10.5.41
+biganswer.example. 3600 IN A 10.10.5.42
+biganswer.example. 3600 IN A 10.10.5.43
+biganswer.example. 3600 IN A 10.10.5.44
+biganswer.example. 3600 IN A 10.10.5.45
+biganswer.example. 3600 IN A 10.10.5.46
+biganswer.example. 3600 IN A 10.10.5.47
+biganswer.example. 3600 IN A 10.10.5.48
+biganswer.example. 3600 IN A 10.10.5.49
+biganswer.example. 3600 IN A 10.10.5.50
+biganswer.example. 3600 IN A 10.10.6.1
+biganswer.example. 3600 IN A 10.10.6.2
+biganswer.example. 3600 IN A 10.10.6.3
+biganswer.example. 3600 IN A 10.10.6.4
+biganswer.example. 3600 IN A 10.10.6.5
+biganswer.example. 3600 IN A 10.10.6.6
+biganswer.example. 3600 IN A 10.10.6.7
+biganswer.example. 3600 IN A 10.10.6.8
+biganswer.example. 3600 IN A 10.10.6.9
+biganswer.example. 3600 IN A 10.10.6.10
+biganswer.example. 3600 IN A 10.10.6.11
+biganswer.example. 3600 IN A 10.10.6.12
+biganswer.example. 3600 IN A 10.10.6.13
+biganswer.example. 3600 IN A 10.10.6.14
+biganswer.example. 3600 IN A 10.10.6.15
+biganswer.example. 3600 IN A 10.10.6.16
+biganswer.example. 3600 IN A 10.10.6.17
+biganswer.example. 3600 IN A 10.10.6.18
+biganswer.example. 3600 IN A 10.10.6.19
+biganswer.example. 3600 IN A 10.10.6.20
+biganswer.example. 3600 IN A 10.10.6.21
+biganswer.example. 3600 IN A 10.10.6.22
+biganswer.example. 3600 IN A 10.10.6.23
+biganswer.example. 3600 IN A 10.10.6.24
+biganswer.example. 3600 IN A 10.10.6.25
+biganswer.example. 3600 IN A 10.10.6.26
+biganswer.example. 3600 IN A 10.10.6.27
+biganswer.example. 3600 IN A 10.10.6.28
+biganswer.example. 3600 IN A 10.10.6.29
+biganswer.example. 3600 IN A 10.10.6.30
+biganswer.example. 3600 IN A 10.10.6.31
+biganswer.example. 3600 IN A 10.10.6.32
+biganswer.example. 3600 IN A 10.10.6.33
+biganswer.example. 3600 IN A 10.10.6.34
+biganswer.example. 3600 IN A 10.10.6.35
+biganswer.example. 3600 IN A 10.10.6.36
+biganswer.example. 3600 IN A 10.10.6.37
+biganswer.example. 3600 IN A 10.10.6.38
+biganswer.example. 3600 IN A 10.10.6.39
+biganswer.example. 3600 IN A 10.10.6.40
+biganswer.example. 3600 IN A 10.10.6.41
+biganswer.example. 3600 IN A 10.10.6.42
+biganswer.example. 3600 IN A 10.10.6.43
+biganswer.example. 3600 IN A 10.10.6.44
+biganswer.example. 3600 IN A 10.10.6.45
+biganswer.example. 3600 IN A 10.10.6.46
+biganswer.example. 3600 IN A 10.10.6.47
+biganswer.example. 3600 IN A 10.10.6.48
+biganswer.example. 3600 IN A 10.10.6.49
+biganswer.example. 3600 IN A 10.10.6.50
+biganswer.example. 3600 IN A 10.10.7.1
+biganswer.example. 3600 IN A 10.10.7.2
+biganswer.example. 3600 IN A 10.10.7.3
+biganswer.example. 3600 IN A 10.10.7.4
+biganswer.example. 3600 IN A 10.10.7.5
+biganswer.example. 3600 IN A 10.10.7.6
+biganswer.example. 3600 IN A 10.10.7.7
+biganswer.example. 3600 IN A 10.10.7.8
+biganswer.example. 3600 IN A 10.10.7.9
+biganswer.example. 3600 IN A 10.10.7.10
+biganswer.example. 3600 IN A 10.10.7.11
+biganswer.example. 3600 IN A 10.10.7.12
+biganswer.example. 3600 IN A 10.10.7.13
+biganswer.example. 3600 IN A 10.10.7.14
+biganswer.example. 3600 IN A 10.10.7.15
+biganswer.example. 3600 IN A 10.10.7.16
+biganswer.example. 3600 IN A 10.10.7.17
+biganswer.example. 3600 IN A 10.10.7.18
+biganswer.example. 3600 IN A 10.10.7.19
+biganswer.example. 3600 IN A 10.10.7.20
+biganswer.example. 3600 IN A 10.10.7.21
+biganswer.example. 3600 IN A 10.10.7.22
+biganswer.example. 3600 IN A 10.10.7.23
+biganswer.example. 3600 IN A 10.10.7.24
+biganswer.example. 3600 IN A 10.10.7.25
+biganswer.example. 3600 IN A 10.10.7.26
+biganswer.example. 3600 IN A 10.10.7.27
+biganswer.example. 3600 IN A 10.10.7.28
+biganswer.example. 3600 IN A 10.10.7.29
+biganswer.example. 3600 IN A 10.10.7.30
+biganswer.example. 3600 IN A 10.10.7.31
+biganswer.example. 3600 IN A 10.10.7.32
+biganswer.example. 3600 IN A 10.10.7.33
+biganswer.example. 3600 IN A 10.10.7.34
+biganswer.example. 3600 IN A 10.10.7.35
+biganswer.example. 3600 IN A 10.10.7.36
+biganswer.example. 3600 IN A 10.10.7.37
+biganswer.example. 3600 IN A 10.10.7.38
+biganswer.example. 3600 IN A 10.10.7.39
+biganswer.example. 3600 IN A 10.10.7.40
+biganswer.example. 3600 IN A 10.10.7.41
+biganswer.example. 3600 IN A 10.10.7.42
+biganswer.example. 3600 IN A 10.10.7.43
+biganswer.example. 3600 IN A 10.10.7.44
+biganswer.example. 3600 IN A 10.10.7.45
+biganswer.example. 3600 IN A 10.10.7.46
+biganswer.example. 3600 IN A 10.10.7.47
+biganswer.example. 3600 IN A 10.10.7.48
+biganswer.example. 3600 IN A 10.10.7.49
+biganswer.example. 3600 IN A 10.10.7.50
+biganswer.example. 3600 IN A 10.10.8.1
+biganswer.example. 3600 IN A 10.10.8.2
+biganswer.example. 3600 IN A 10.10.8.3
+biganswer.example. 3600 IN A 10.10.8.4
+biganswer.example. 3600 IN A 10.10.8.5
+biganswer.example. 3600 IN A 10.10.8.6
+biganswer.example. 3600 IN A 10.10.8.7
+biganswer.example. 3600 IN A 10.10.8.8
+biganswer.example. 3600 IN A 10.10.8.9
+biganswer.example. 3600 IN A 10.10.8.10
+biganswer.example. 3600 IN A 10.10.8.11
+biganswer.example. 3600 IN A 10.10.8.12
+biganswer.example. 3600 IN A 10.10.8.13
+biganswer.example. 3600 IN A 10.10.8.14
+biganswer.example. 3600 IN A 10.10.8.15
+biganswer.example. 3600 IN A 10.10.8.16
+biganswer.example. 3600 IN A 10.10.8.17
+biganswer.example. 3600 IN A 10.10.8.18
+biganswer.example. 3600 IN A 10.10.8.19
+biganswer.example. 3600 IN A 10.10.8.20
+biganswer.example. 3600 IN A 10.10.8.21
+biganswer.example. 3600 IN A 10.10.8.22
+biganswer.example. 3600 IN A 10.10.8.23
+biganswer.example. 3600 IN A 10.10.8.24
+biganswer.example. 3600 IN A 10.10.8.25
+biganswer.example. 3600 IN A 10.10.8.26
+biganswer.example. 3600 IN A 10.10.8.27
+biganswer.example. 3600 IN A 10.10.8.28
+biganswer.example. 3600 IN A 10.10.8.29
+biganswer.example. 3600 IN A 10.10.8.30
+biganswer.example. 3600 IN A 10.10.8.31
+biganswer.example. 3600 IN A 10.10.8.32
+biganswer.example. 3600 IN A 10.10.8.33
+biganswer.example. 3600 IN A 10.10.8.34
+biganswer.example. 3600 IN A 10.10.8.35
+biganswer.example. 3600 IN A 10.10.8.36
+biganswer.example. 3600 IN A 10.10.8.37
+biganswer.example. 3600 IN A 10.10.8.38
+biganswer.example. 3600 IN A 10.10.8.39
+biganswer.example. 3600 IN A 10.10.8.40
+biganswer.example. 3600 IN A 10.10.8.41
+biganswer.example. 3600 IN A 10.10.8.42
+biganswer.example. 3600 IN A 10.10.8.43
+biganswer.example. 3600 IN A 10.10.8.44
+biganswer.example. 3600 IN A 10.10.8.45
+biganswer.example. 3600 IN A 10.10.8.46
+biganswer.example. 3600 IN A 10.10.8.47
+biganswer.example. 3600 IN A 10.10.8.48
+biganswer.example. 3600 IN A 10.10.8.49
+biganswer.example. 3600 IN A 10.10.8.50
+biganswer.example. 3600 IN A 10.10.9.1
+biganswer.example. 3600 IN A 10.10.9.2
+biganswer.example. 3600 IN A 10.10.9.3
+biganswer.example. 3600 IN A 10.10.9.4
+biganswer.example. 3600 IN A 10.10.9.5
+biganswer.example. 3600 IN A 10.10.9.6
+biganswer.example. 3600 IN A 10.10.9.7
+biganswer.example. 3600 IN A 10.10.9.8
+biganswer.example. 3600 IN A 10.10.9.9
+biganswer.example. 3600 IN A 10.10.9.10
+biganswer.example. 3600 IN A 10.10.9.11
+biganswer.example. 3600 IN A 10.10.9.12
+biganswer.example. 3600 IN A 10.10.9.13
+biganswer.example. 3600 IN A 10.10.9.14
+biganswer.example. 3600 IN A 10.10.9.15
+biganswer.example. 3600 IN A 10.10.9.16
+biganswer.example. 3600 IN A 10.10.9.17
+biganswer.example. 3600 IN A 10.10.9.18
+biganswer.example. 3600 IN A 10.10.9.19
+biganswer.example. 3600 IN A 10.10.9.20
+biganswer.example. 3600 IN A 10.10.9.21
+biganswer.example. 3600 IN A 10.10.9.22
+biganswer.example. 3600 IN A 10.10.9.23
+biganswer.example. 3600 IN A 10.10.9.24
+biganswer.example. 3600 IN A 10.10.9.25
+biganswer.example. 3600 IN A 10.10.9.26
+biganswer.example. 3600 IN A 10.10.9.27
+biganswer.example. 3600 IN A 10.10.9.28
+biganswer.example. 3600 IN A 10.10.9.29
+biganswer.example. 3600 IN A 10.10.9.30
+biganswer.example. 3600 IN A 10.10.9.31
+biganswer.example. 3600 IN A 10.10.9.32
+biganswer.example. 3600 IN A 10.10.9.33
+biganswer.example. 3600 IN A 10.10.9.34
+biganswer.example. 3600 IN A 10.10.9.35
+biganswer.example. 3600 IN A 10.10.9.36
+biganswer.example. 3600 IN A 10.10.9.37
+biganswer.example. 3600 IN A 10.10.9.38
+biganswer.example. 3600 IN A 10.10.9.39
+biganswer.example. 3600 IN A 10.10.9.40
+biganswer.example. 3600 IN A 10.10.9.41
+biganswer.example. 3600 IN A 10.10.9.42
+biganswer.example. 3600 IN A 10.10.9.43
+biganswer.example. 3600 IN A 10.10.9.44
+biganswer.example. 3600 IN A 10.10.9.45
+biganswer.example. 3600 IN A 10.10.9.46
+biganswer.example. 3600 IN A 10.10.9.47
+biganswer.example. 3600 IN A 10.10.9.48
+biganswer.example. 3600 IN A 10.10.9.49
+biganswer.example. 3600 IN A 10.10.9.50
+biganswer.example. 3600 IN A 10.10.10.1
+biganswer.example. 3600 IN A 10.10.10.2
+biganswer.example. 3600 IN A 10.10.10.3
+biganswer.example. 3600 IN A 10.10.10.4
+biganswer.example. 3600 IN A 10.10.10.5
+biganswer.example. 3600 IN A 10.10.10.6
+biganswer.example. 3600 IN A 10.10.10.7
+biganswer.example. 3600 IN A 10.10.10.8
+biganswer.example. 3600 IN A 10.10.10.9
+biganswer.example. 3600 IN A 10.10.10.10
+biganswer.example. 3600 IN A 10.10.10.11
+biganswer.example. 3600 IN A 10.10.10.12
+biganswer.example. 3600 IN A 10.10.10.13
+biganswer.example. 3600 IN A 10.10.10.14
+biganswer.example. 3600 IN A 10.10.10.15
+biganswer.example. 3600 IN A 10.10.10.16
+biganswer.example. 3600 IN A 10.10.10.17
+biganswer.example. 3600 IN A 10.10.10.18
+biganswer.example. 3600 IN A 10.10.10.19
+biganswer.example. 3600 IN A 10.10.10.20
+biganswer.example. 3600 IN A 10.10.10.21
+biganswer.example. 3600 IN A 10.10.10.22
+biganswer.example. 3600 IN A 10.10.10.23
+biganswer.example. 3600 IN A 10.10.10.24
+biganswer.example. 3600 IN A 10.10.10.25
+biganswer.example. 3600 IN A 10.10.10.26
+biganswer.example. 3600 IN A 10.10.10.27
+biganswer.example. 3600 IN A 10.10.10.28
+biganswer.example. 3600 IN A 10.10.10.29
+biganswer.example. 3600 IN A 10.10.10.30
+biganswer.example. 3600 IN A 10.10.10.31
+biganswer.example. 3600 IN A 10.10.10.32
+biganswer.example. 3600 IN A 10.10.10.33
+biganswer.example. 3600 IN A 10.10.10.34
+biganswer.example. 3600 IN A 10.10.10.35
+biganswer.example. 3600 IN A 10.10.10.36
+biganswer.example. 3600 IN A 10.10.10.37
+biganswer.example. 3600 IN A 10.10.10.38
+biganswer.example. 3600 IN A 10.10.10.39
+biganswer.example. 3600 IN A 10.10.10.40
+biganswer.example. 3600 IN A 10.10.10.41
+biganswer.example. 3600 IN A 10.10.10.42
+biganswer.example. 3600 IN A 10.10.10.43
+biganswer.example. 3600 IN A 10.10.10.44
+biganswer.example. 3600 IN A 10.10.10.45
+biganswer.example. 3600 IN A 10.10.10.46
+biganswer.example. 3600 IN A 10.10.10.47
+biganswer.example. 3600 IN A 10.10.10.48
+biganswer.example. 3600 IN A 10.10.10.49
+biganswer.example. 3600 IN A 10.10.10.50
+biganswer.example. 3600 IN A 10.10.11.1
+biganswer.example. 3600 IN A 10.10.11.2
+biganswer.example. 3600 IN A 10.10.11.3
+biganswer.example. 3600 IN A 10.10.11.4
+biganswer.example. 3600 IN A 10.10.11.5
+biganswer.example. 3600 IN A 10.10.11.6
+biganswer.example. 3600 IN A 10.10.11.7
+biganswer.example. 3600 IN A 10.10.11.8
+biganswer.example. 3600 IN A 10.10.11.9
+biganswer.example. 3600 IN A 10.10.11.10
+biganswer.example. 3600 IN A 10.10.11.11
+biganswer.example. 3600 IN A 10.10.11.12
+biganswer.example. 3600 IN A 10.10.11.13
+biganswer.example. 3600 IN A 10.10.11.14
+biganswer.example. 3600 IN A 10.10.11.15
+biganswer.example. 3600 IN A 10.10.11.16
+biganswer.example. 3600 IN A 10.10.11.17
+biganswer.example. 3600 IN A 10.10.11.18
+biganswer.example. 3600 IN A 10.10.11.19
+biganswer.example. 3600 IN A 10.10.11.20
+biganswer.example. 3600 IN A 10.10.11.21
+biganswer.example. 3600 IN A 10.10.11.22
+biganswer.example. 3600 IN A 10.10.11.23
+biganswer.example. 3600 IN A 10.10.11.24
+biganswer.example. 3600 IN A 10.10.11.25
+biganswer.example. 3600 IN A 10.10.11.26
+biganswer.example. 3600 IN A 10.10.11.27
+biganswer.example. 3600 IN A 10.10.11.28
+biganswer.example. 3600 IN A 10.10.11.29
+biganswer.example. 3600 IN A 10.10.11.30
+biganswer.example. 3600 IN A 10.10.11.31
+biganswer.example. 3600 IN A 10.10.11.32
+biganswer.example. 3600 IN A 10.10.11.33
+biganswer.example. 3600 IN A 10.10.11.34
+biganswer.example. 3600 IN A 10.10.11.35
+biganswer.example. 3600 IN A 10.10.11.36
+biganswer.example. 3600 IN A 10.10.11.37
+biganswer.example. 3600 IN A 10.10.11.38
+biganswer.example. 3600 IN A 10.10.11.39
+biganswer.example. 3600 IN A 10.10.11.40
+biganswer.example. 3600 IN A 10.10.11.41
+biganswer.example. 3600 IN A 10.10.11.42
+biganswer.example. 3600 IN A 10.10.11.43
+biganswer.example. 3600 IN A 10.10.11.44
+biganswer.example. 3600 IN A 10.10.11.45
+biganswer.example. 3600 IN A 10.10.11.46
+biganswer.example. 3600 IN A 10.10.11.47
+biganswer.example. 3600 IN A 10.10.11.48
+biganswer.example. 3600 IN A 10.10.11.49
+biganswer.example. 3600 IN A 10.10.11.50
+biganswer.example. 3600 IN A 10.10.12.1
+biganswer.example. 3600 IN A 10.10.12.2
+biganswer.example. 3600 IN A 10.10.12.3
+biganswer.example. 3600 IN A 10.10.12.4
+biganswer.example. 3600 IN A 10.10.12.5
+biganswer.example. 3600 IN A 10.10.12.6
+biganswer.example. 3600 IN A 10.10.12.7
+biganswer.example. 3600 IN A 10.10.12.8
+biganswer.example. 3600 IN A 10.10.12.9
+biganswer.example. 3600 IN A 10.10.12.10
+biganswer.example. 3600 IN A 10.10.12.11
+biganswer.example. 3600 IN A 10.10.12.12
+biganswer.example. 3600 IN A 10.10.12.13
+biganswer.example. 3600 IN A 10.10.12.14
+biganswer.example. 3600 IN A 10.10.12.15
+biganswer.example. 3600 IN A 10.10.12.16
+biganswer.example. 3600 IN A 10.10.12.17
+biganswer.example. 3600 IN A 10.10.12.18
+biganswer.example. 3600 IN A 10.10.12.19
+biganswer.example. 3600 IN A 10.10.12.20
+biganswer.example. 3600 IN A 10.10.12.21
+biganswer.example. 3600 IN A 10.10.12.22
+biganswer.example. 3600 IN A 10.10.12.23
+biganswer.example. 3600 IN A 10.10.12.24
+biganswer.example. 3600 IN A 10.10.12.25
+biganswer.example. 3600 IN A 10.10.12.26
+biganswer.example. 3600 IN A 10.10.12.27
+biganswer.example. 3600 IN A 10.10.12.28
+biganswer.example. 3600 IN A 10.10.12.29
+biganswer.example. 3600 IN A 10.10.12.30
+biganswer.example. 3600 IN A 10.10.12.31
+biganswer.example. 3600 IN A 10.10.12.32
+biganswer.example. 3600 IN A 10.10.12.33
+biganswer.example. 3600 IN A 10.10.12.34
+biganswer.example. 3600 IN A 10.10.12.35
+biganswer.example. 3600 IN A 10.10.12.36
+biganswer.example. 3600 IN A 10.10.12.37
+biganswer.example. 3600 IN A 10.10.12.38
+biganswer.example. 3600 IN A 10.10.12.39
+biganswer.example. 3600 IN A 10.10.12.40
+biganswer.example. 3600 IN A 10.10.12.41
+biganswer.example. 3600 IN A 10.10.12.42
+biganswer.example. 3600 IN A 10.10.12.43
+biganswer.example. 3600 IN A 10.10.12.44
+biganswer.example. 3600 IN A 10.10.12.45
+biganswer.example. 3600 IN A 10.10.12.46
+biganswer.example. 3600 IN A 10.10.12.47
+biganswer.example. 3600 IN A 10.10.12.48
+biganswer.example. 3600 IN A 10.10.12.49
+biganswer.example. 3600 IN A 10.10.12.50
+biganswer.example. 3600 IN A 10.10.13.1
+biganswer.example. 3600 IN A 10.10.13.2
+biganswer.example. 3600 IN A 10.10.13.3
+biganswer.example. 3600 IN A 10.10.13.4
+biganswer.example. 3600 IN A 10.10.13.5
+biganswer.example. 3600 IN A 10.10.13.6
+biganswer.example. 3600 IN A 10.10.13.7
+biganswer.example. 3600 IN A 10.10.13.8
+biganswer.example. 3600 IN A 10.10.13.9
+biganswer.example. 3600 IN A 10.10.13.10
+biganswer.example. 3600 IN A 10.10.13.11
+biganswer.example. 3600 IN A 10.10.13.12
+biganswer.example. 3600 IN A 10.10.13.13
+biganswer.example. 3600 IN A 10.10.13.14
+biganswer.example. 3600 IN A 10.10.13.15
+biganswer.example. 3600 IN A 10.10.13.16
+biganswer.example. 3600 IN A 10.10.13.17
+biganswer.example. 3600 IN A 10.10.13.18
+biganswer.example. 3600 IN A 10.10.13.19
+biganswer.example. 3600 IN A 10.10.13.20
+biganswer.example. 3600 IN A 10.10.13.21
+biganswer.example. 3600 IN A 10.10.13.22
+biganswer.example. 3600 IN A 10.10.13.23
+biganswer.example. 3600 IN A 10.10.13.24
+biganswer.example. 3600 IN A 10.10.13.25
+biganswer.example. 3600 IN A 10.10.13.26
+biganswer.example. 3600 IN A 10.10.13.27
+biganswer.example. 3600 IN A 10.10.13.28
+biganswer.example. 3600 IN A 10.10.13.29
+biganswer.example. 3600 IN A 10.10.13.30
+biganswer.example. 3600 IN A 10.10.13.31
+biganswer.example. 3600 IN A 10.10.13.32
+biganswer.example. 3600 IN A 10.10.13.33
+biganswer.example. 3600 IN A 10.10.13.34
+biganswer.example. 3600 IN A 10.10.13.35
+biganswer.example. 3600 IN A 10.10.13.36
+biganswer.example. 3600 IN A 10.10.13.37
+biganswer.example. 3600 IN A 10.10.13.38
+biganswer.example. 3600 IN A 10.10.13.39
+biganswer.example. 3600 IN A 10.10.13.40
+biganswer.example. 3600 IN A 10.10.13.41
+biganswer.example. 3600 IN A 10.10.13.42
+biganswer.example. 3600 IN A 10.10.13.43
+biganswer.example. 3600 IN A 10.10.13.44
+biganswer.example. 3600 IN A 10.10.13.45
+biganswer.example. 3600 IN A 10.10.13.46
+biganswer.example. 3600 IN A 10.10.13.47
+biganswer.example. 3600 IN A 10.10.13.48
+biganswer.example. 3600 IN A 10.10.13.49
+biganswer.example. 3600 IN A 10.10.13.50
+biganswer.example. 3600 IN A 10.10.14.1
+biganswer.example. 3600 IN A 10.10.14.2
+biganswer.example. 3600 IN A 10.10.14.3
+biganswer.example. 3600 IN A 10.10.14.4
+biganswer.example. 3600 IN A 10.10.14.5
+biganswer.example. 3600 IN A 10.10.14.6
+biganswer.example. 3600 IN A 10.10.14.7
+biganswer.example. 3600 IN A 10.10.14.8
+biganswer.example. 3600 IN A 10.10.14.9
+biganswer.example. 3600 IN A 10.10.14.10
+biganswer.example. 3600 IN A 10.10.14.11
+biganswer.example. 3600 IN A 10.10.14.12
+biganswer.example. 3600 IN A 10.10.14.13
+biganswer.example. 3600 IN A 10.10.14.14
+biganswer.example. 3600 IN A 10.10.14.15
+biganswer.example. 3600 IN A 10.10.14.16
+biganswer.example. 3600 IN A 10.10.14.17
+biganswer.example. 3600 IN A 10.10.14.18
+biganswer.example. 3600 IN A 10.10.14.19
+biganswer.example. 3600 IN A 10.10.14.20
+biganswer.example. 3600 IN A 10.10.14.21
+biganswer.example. 3600 IN A 10.10.14.22
+biganswer.example. 3600 IN A 10.10.14.23
+biganswer.example. 3600 IN A 10.10.14.24
+biganswer.example. 3600 IN A 10.10.14.25
+biganswer.example. 3600 IN A 10.10.14.26
+biganswer.example. 3600 IN A 10.10.14.27
+biganswer.example. 3600 IN A 10.10.14.28
+biganswer.example. 3600 IN A 10.10.14.29
+biganswer.example. 3600 IN A 10.10.14.30
+biganswer.example. 3600 IN A 10.10.14.31
+biganswer.example. 3600 IN A 10.10.14.32
+biganswer.example. 3600 IN A 10.10.14.33
+biganswer.example. 3600 IN A 10.10.14.34
+biganswer.example. 3600 IN A 10.10.14.35
+biganswer.example. 3600 IN A 10.10.14.36
+biganswer.example. 3600 IN A 10.10.14.37
+biganswer.example. 3600 IN A 10.10.14.38
+biganswer.example. 3600 IN A 10.10.14.39
+biganswer.example. 3600 IN A 10.10.14.40
+biganswer.example. 3600 IN A 10.10.14.41
+biganswer.example. 3600 IN A 10.10.14.42
+biganswer.example. 3600 IN A 10.10.14.43
+biganswer.example. 3600 IN A 10.10.14.44
+biganswer.example. 3600 IN A 10.10.14.45
+biganswer.example. 3600 IN A 10.10.14.46
+biganswer.example. 3600 IN A 10.10.14.47
+biganswer.example. 3600 IN A 10.10.14.48
+biganswer.example. 3600 IN A 10.10.14.49
+biganswer.example. 3600 IN A 10.10.14.50
+biganswer.example. 3600 IN A 10.10.15.1
+biganswer.example. 3600 IN A 10.10.15.2
+biganswer.example. 3600 IN A 10.10.15.3
+biganswer.example. 3600 IN A 10.10.15.4
+biganswer.example. 3600 IN A 10.10.15.5
+biganswer.example. 3600 IN A 10.10.15.6
+biganswer.example. 3600 IN A 10.10.15.7
+biganswer.example. 3600 IN A 10.10.15.8
+biganswer.example. 3600 IN A 10.10.15.9
+biganswer.example. 3600 IN A 10.10.15.10
+biganswer.example. 3600 IN A 10.10.15.11
+biganswer.example. 3600 IN A 10.10.15.12
+biganswer.example. 3600 IN A 10.10.15.13
+biganswer.example. 3600 IN A 10.10.15.14
+biganswer.example. 3600 IN A 10.10.15.15
+biganswer.example. 3600 IN A 10.10.15.16
+biganswer.example. 3600 IN A 10.10.15.17
+biganswer.example. 3600 IN A 10.10.15.18
+biganswer.example. 3600 IN A 10.10.15.19
+biganswer.example. 3600 IN A 10.10.15.20
+biganswer.example. 3600 IN A 10.10.15.21
+biganswer.example. 3600 IN A 10.10.15.22
+biganswer.example. 3600 IN A 10.10.15.23
+biganswer.example. 3600 IN A 10.10.15.24
+biganswer.example. 3600 IN A 10.10.15.25
+biganswer.example. 3600 IN A 10.10.15.26
+biganswer.example. 3600 IN A 10.10.15.27
+biganswer.example. 3600 IN A 10.10.15.28
+biganswer.example. 3600 IN A 10.10.15.29
+biganswer.example. 3600 IN A 10.10.15.30
+biganswer.example. 3600 IN A 10.10.15.31
+biganswer.example. 3600 IN A 10.10.15.32
+biganswer.example. 3600 IN A 10.10.15.33
+biganswer.example. 3600 IN A 10.10.15.34
+biganswer.example. 3600 IN A 10.10.15.35
+biganswer.example. 3600 IN A 10.10.15.36
+biganswer.example. 3600 IN A 10.10.15.37
+biganswer.example. 3600 IN A 10.10.15.38
+biganswer.example. 3600 IN A 10.10.15.39
+biganswer.example. 3600 IN A 10.10.15.40
+biganswer.example. 3600 IN A 10.10.15.41
+biganswer.example. 3600 IN A 10.10.15.42
+biganswer.example. 3600 IN A 10.10.15.43
+biganswer.example. 3600 IN A 10.10.15.44
+biganswer.example. 3600 IN A 10.10.15.45
+biganswer.example. 3600 IN A 10.10.15.46
+biganswer.example. 3600 IN A 10.10.15.47
+biganswer.example. 3600 IN A 10.10.15.48
+biganswer.example. 3600 IN A 10.10.15.49
+biganswer.example. 3600 IN A 10.10.15.50
+biganswer.example. 3600 IN A 10.10.16.1
+biganswer.example. 3600 IN A 10.10.16.2
+biganswer.example. 3600 IN A 10.10.16.3
+biganswer.example. 3600 IN A 10.10.16.4
+biganswer.example. 3600 IN A 10.10.16.5
+biganswer.example. 3600 IN A 10.10.16.6
+biganswer.example. 3600 IN A 10.10.16.7
+biganswer.example. 3600 IN A 10.10.16.8
+biganswer.example. 3600 IN A 10.10.16.9
+biganswer.example. 3600 IN A 10.10.16.10
+biganswer.example. 3600 IN A 10.10.16.11
+biganswer.example. 3600 IN A 10.10.16.12
+biganswer.example. 3600 IN A 10.10.16.13
+biganswer.example. 3600 IN A 10.10.16.14
+biganswer.example. 3600 IN A 10.10.16.15
+biganswer.example. 3600 IN A 10.10.16.16
+biganswer.example. 3600 IN A 10.10.16.17
+biganswer.example. 3600 IN A 10.10.16.18
+biganswer.example. 3600 IN A 10.10.16.19
+biganswer.example. 3600 IN A 10.10.16.20
+biganswer.example. 3600 IN A 10.10.16.21
+biganswer.example. 3600 IN A 10.10.16.22
+biganswer.example. 3600 IN A 10.10.16.23
+biganswer.example. 3600 IN A 10.10.16.24
+biganswer.example. 3600 IN A 10.10.16.25
+biganswer.example. 3600 IN A 10.10.16.26
+biganswer.example. 3600 IN A 10.10.16.27
+biganswer.example. 3600 IN A 10.10.16.28
+biganswer.example. 3600 IN A 10.10.16.29
+biganswer.example. 3600 IN A 10.10.16.30
+biganswer.example. 3600 IN A 10.10.16.31
+biganswer.example. 3600 IN A 10.10.16.32
+biganswer.example. 3600 IN A 10.10.16.33
+biganswer.example. 3600 IN A 10.10.16.34
+biganswer.example. 3600 IN A 10.10.16.35
+biganswer.example. 3600 IN A 10.10.16.36
+biganswer.example. 3600 IN A 10.10.16.37
+biganswer.example. 3600 IN A 10.10.16.38
+biganswer.example. 3600 IN A 10.10.16.39
+biganswer.example. 3600 IN A 10.10.16.40
+biganswer.example. 3600 IN A 10.10.16.41
+biganswer.example. 3600 IN A 10.10.16.42
+biganswer.example. 3600 IN A 10.10.16.43
+biganswer.example. 3600 IN A 10.10.16.44
+biganswer.example. 3600 IN A 10.10.16.45
+biganswer.example. 3600 IN A 10.10.16.46
+biganswer.example. 3600 IN A 10.10.16.47
+biganswer.example. 3600 IN A 10.10.16.48
+biganswer.example. 3600 IN A 10.10.16.49
+biganswer.example. 3600 IN A 10.10.16.50
+biganswer.example. 3600 IN A 10.10.17.1
+biganswer.example. 3600 IN A 10.10.17.2
+biganswer.example. 3600 IN A 10.10.17.3
+biganswer.example. 3600 IN A 10.10.17.4
+biganswer.example. 3600 IN A 10.10.17.5
+biganswer.example. 3600 IN A 10.10.17.6
+biganswer.example. 3600 IN A 10.10.17.7
+biganswer.example. 3600 IN A 10.10.17.8
+biganswer.example. 3600 IN A 10.10.17.9
+biganswer.example. 3600 IN A 10.10.17.10
+biganswer.example. 3600 IN A 10.10.17.11
+biganswer.example. 3600 IN A 10.10.17.12
+biganswer.example. 3600 IN A 10.10.17.13
+biganswer.example. 3600 IN A 10.10.17.14
+biganswer.example. 3600 IN A 10.10.17.15
+biganswer.example. 3600 IN A 10.10.17.16
+biganswer.example. 3600 IN A 10.10.17.17
+biganswer.example. 3600 IN A 10.10.17.18
+biganswer.example. 3600 IN A 10.10.17.19
+biganswer.example. 3600 IN A 10.10.17.20
+biganswer.example. 3600 IN A 10.10.17.21
+biganswer.example. 3600 IN A 10.10.17.22
+biganswer.example. 3600 IN A 10.10.17.23
+biganswer.example. 3600 IN A 10.10.17.24
+biganswer.example. 3600 IN A 10.10.17.25
+biganswer.example. 3600 IN A 10.10.17.26
+biganswer.example. 3600 IN A 10.10.17.27
+biganswer.example. 3600 IN A 10.10.17.28
+biganswer.example. 3600 IN A 10.10.17.29
+biganswer.example. 3600 IN A 10.10.17.30
+biganswer.example. 3600 IN A 10.10.17.31
+biganswer.example. 3600 IN A 10.10.17.32
+biganswer.example. 3600 IN A 10.10.17.33
+biganswer.example. 3600 IN A 10.10.17.34
+biganswer.example. 3600 IN A 10.10.17.35
+biganswer.example. 3600 IN A 10.10.17.36
+biganswer.example. 3600 IN A 10.10.17.37
+biganswer.example. 3600 IN A 10.10.17.38
+biganswer.example. 3600 IN A 10.10.17.39
+biganswer.example. 3600 IN A 10.10.17.40
+biganswer.example. 3600 IN A 10.10.17.41
+biganswer.example. 3600 IN A 10.10.17.42
+biganswer.example. 3600 IN A 10.10.17.43
+biganswer.example. 3600 IN A 10.10.17.44
+biganswer.example. 3600 IN A 10.10.17.45
+biganswer.example. 3600 IN A 10.10.17.46
+biganswer.example. 3600 IN A 10.10.17.47
+biganswer.example. 3600 IN A 10.10.17.48
+biganswer.example. 3600 IN A 10.10.17.49
+biganswer.example. 3600 IN A 10.10.17.50
+biganswer.example. 3600 IN A 10.10.18.1
+biganswer.example. 3600 IN A 10.10.18.2
+biganswer.example. 3600 IN A 10.10.18.3
+biganswer.example. 3600 IN A 10.10.18.4
+biganswer.example. 3600 IN A 10.10.18.5
+biganswer.example. 3600 IN A 10.10.18.6
+biganswer.example. 3600 IN A 10.10.18.7
+biganswer.example. 3600 IN A 10.10.18.8
+biganswer.example. 3600 IN A 10.10.18.9
+biganswer.example. 3600 IN A 10.10.18.10
+biganswer.example. 3600 IN A 10.10.18.11
+biganswer.example. 3600 IN A 10.10.18.12
+biganswer.example. 3600 IN A 10.10.18.13
+biganswer.example. 3600 IN A 10.10.18.14
+biganswer.example. 3600 IN A 10.10.18.15
+biganswer.example. 3600 IN A 10.10.18.16
+biganswer.example. 3600 IN A 10.10.18.17
+biganswer.example. 3600 IN A 10.10.18.18
+biganswer.example. 3600 IN A 10.10.18.19
+biganswer.example. 3600 IN A 10.10.18.20
+biganswer.example. 3600 IN A 10.10.18.21
+biganswer.example. 3600 IN A 10.10.18.22
+biganswer.example. 3600 IN A 10.10.18.23
+biganswer.example. 3600 IN A 10.10.18.24
+biganswer.example. 3600 IN A 10.10.18.25
+biganswer.example. 3600 IN A 10.10.18.26
+biganswer.example. 3600 IN A 10.10.18.27
+biganswer.example. 3600 IN A 10.10.18.28
+biganswer.example. 3600 IN A 10.10.18.29
+biganswer.example. 3600 IN A 10.10.18.30
+biganswer.example. 3600 IN A 10.10.18.31
+biganswer.example. 3600 IN A 10.10.18.32
+biganswer.example. 3600 IN A 10.10.18.33
+biganswer.example. 3600 IN A 10.10.18.34
+biganswer.example. 3600 IN A 10.10.18.35
+biganswer.example. 3600 IN A 10.10.18.36
+biganswer.example. 3600 IN A 10.10.18.37
+biganswer.example. 3600 IN A 10.10.18.38
+biganswer.example. 3600 IN A 10.10.18.39
+biganswer.example. 3600 IN A 10.10.18.40
+biganswer.example. 3600 IN A 10.10.18.41
+biganswer.example. 3600 IN A 10.10.18.42
+biganswer.example. 3600 IN A 10.10.18.43
+biganswer.example. 3600 IN A 10.10.18.44
+biganswer.example. 3600 IN A 10.10.18.45
+biganswer.example. 3600 IN A 10.10.18.46
+biganswer.example. 3600 IN A 10.10.18.47
+biganswer.example. 3600 IN A 10.10.18.48
+biganswer.example. 3600 IN A 10.10.18.49
+biganswer.example. 3600 IN A 10.10.18.50
+biganswer.example. 3600 IN A 10.10.19.1
+biganswer.example. 3600 IN A 10.10.19.2
+biganswer.example. 3600 IN A 10.10.19.3
+biganswer.example. 3600 IN A 10.10.19.4
+biganswer.example. 3600 IN A 10.10.19.5
+biganswer.example. 3600 IN A 10.10.19.6
+biganswer.example. 3600 IN A 10.10.19.7
+biganswer.example. 3600 IN A 10.10.19.8
+biganswer.example. 3600 IN A 10.10.19.9
+biganswer.example. 3600 IN A 10.10.19.10
+biganswer.example. 3600 IN A 10.10.19.11
+biganswer.example. 3600 IN A 10.10.19.12
+biganswer.example. 3600 IN A 10.10.19.13
+biganswer.example. 3600 IN A 10.10.19.14
+biganswer.example. 3600 IN A 10.10.19.15
+biganswer.example. 3600 IN A 10.10.19.16
+biganswer.example. 3600 IN A 10.10.19.17
+biganswer.example. 3600 IN A 10.10.19.18
+biganswer.example. 3600 IN A 10.10.19.19
+biganswer.example. 3600 IN A 10.10.19.20
+biganswer.example. 3600 IN A 10.10.19.21
+biganswer.example. 3600 IN A 10.10.19.22
+biganswer.example. 3600 IN A 10.10.19.23
+biganswer.example. 3600 IN A 10.10.19.24
+biganswer.example. 3600 IN A 10.10.19.25
+biganswer.example. 3600 IN A 10.10.19.26
+biganswer.example. 3600 IN A 10.10.19.27
+biganswer.example. 3600 IN A 10.10.19.28
+biganswer.example. 3600 IN A 10.10.19.29
+biganswer.example. 3600 IN A 10.10.19.30
+biganswer.example. 3600 IN A 10.10.19.31
+biganswer.example. 3600 IN A 10.10.19.32
+biganswer.example. 3600 IN A 10.10.19.33
+biganswer.example. 3600 IN A 10.10.19.34
+biganswer.example. 3600 IN A 10.10.19.35
+biganswer.example. 3600 IN A 10.10.19.36
+biganswer.example. 3600 IN A 10.10.19.37
+biganswer.example. 3600 IN A 10.10.19.38
+biganswer.example. 3600 IN A 10.10.19.39
+biganswer.example. 3600 IN A 10.10.19.40
+biganswer.example. 3600 IN A 10.10.19.41
+biganswer.example. 3600 IN A 10.10.19.42
+biganswer.example. 3600 IN A 10.10.19.43
+biganswer.example. 3600 IN A 10.10.19.44
+biganswer.example. 3600 IN A 10.10.19.45
+biganswer.example. 3600 IN A 10.10.19.46
+biganswer.example. 3600 IN A 10.10.19.47
+biganswer.example. 3600 IN A 10.10.19.48
+biganswer.example. 3600 IN A 10.10.19.49
+biganswer.example. 3600 IN A 10.10.19.50
+biganswer.example. 3600 IN A 10.10.20.1
+biganswer.example. 3600 IN A 10.10.20.2
+biganswer.example. 3600 IN A 10.10.20.3
+biganswer.example. 3600 IN A 10.10.20.4
+biganswer.example. 3600 IN A 10.10.20.5
+biganswer.example. 3600 IN A 10.10.20.6
+biganswer.example. 3600 IN A 10.10.20.7
+biganswer.example. 3600 IN A 10.10.20.8
+biganswer.example. 3600 IN A 10.10.20.9
+biganswer.example. 3600 IN A 10.10.20.10
+biganswer.example. 3600 IN A 10.10.20.11
+biganswer.example. 3600 IN A 10.10.20.12
+biganswer.example. 3600 IN A 10.10.20.13
+biganswer.example. 3600 IN A 10.10.20.14
+biganswer.example. 3600 IN A 10.10.20.15
+biganswer.example. 3600 IN A 10.10.20.16
+biganswer.example. 3600 IN A 10.10.20.17
+biganswer.example. 3600 IN A 10.10.20.18
+biganswer.example. 3600 IN A 10.10.20.19
+biganswer.example. 3600 IN A 10.10.20.20
+biganswer.example. 3600 IN A 10.10.20.21
+biganswer.example. 3600 IN A 10.10.20.22
+biganswer.example. 3600 IN A 10.10.20.23
+biganswer.example. 3600 IN A 10.10.20.24
+biganswer.example. 3600 IN A 10.10.20.25
+biganswer.example. 3600 IN A 10.10.20.26
+biganswer.example. 3600 IN A 10.10.20.27
+biganswer.example. 3600 IN A 10.10.20.28
+biganswer.example. 3600 IN A 10.10.20.29
+biganswer.example. 3600 IN A 10.10.20.30
+biganswer.example. 3600 IN A 10.10.20.31
+biganswer.example. 3600 IN A 10.10.20.32
+biganswer.example. 3600 IN A 10.10.20.33
+biganswer.example. 3600 IN A 10.10.20.34
+biganswer.example. 3600 IN A 10.10.20.35
+biganswer.example. 3600 IN A 10.10.20.36
+biganswer.example. 3600 IN A 10.10.20.37
+biganswer.example. 3600 IN A 10.10.20.38
+biganswer.example. 3600 IN A 10.10.20.39
+biganswer.example. 3600 IN A 10.10.20.40
+biganswer.example. 3600 IN A 10.10.20.41
+biganswer.example. 3600 IN A 10.10.20.42
+biganswer.example. 3600 IN A 10.10.20.43
+biganswer.example. 3600 IN A 10.10.20.44
+biganswer.example. 3600 IN A 10.10.20.45
+biganswer.example. 3600 IN A 10.10.20.46
+biganswer.example. 3600 IN A 10.10.20.47
+biganswer.example. 3600 IN A 10.10.20.48
+biganswer.example. 3600 IN A 10.10.20.49
+biganswer.example. 3600 IN A 10.10.20.50
+biganswer.example. 3600 IN A 10.10.21.1
+biganswer.example. 3600 IN A 10.10.21.2
+biganswer.example. 3600 IN A 10.10.21.3
+biganswer.example. 3600 IN A 10.10.21.4
+biganswer.example. 3600 IN A 10.10.21.5
+biganswer.example. 3600 IN A 10.10.21.6
+biganswer.example. 3600 IN A 10.10.21.7
+biganswer.example. 3600 IN A 10.10.21.8
+biganswer.example. 3600 IN A 10.10.21.9
+biganswer.example. 3600 IN A 10.10.21.10
+biganswer.example. 3600 IN A 10.10.21.11
+biganswer.example. 3600 IN A 10.10.21.12
+biganswer.example. 3600 IN A 10.10.21.13
+biganswer.example. 3600 IN A 10.10.21.14
+biganswer.example. 3600 IN A 10.10.21.15
+biganswer.example. 3600 IN A 10.10.21.16
+biganswer.example. 3600 IN A 10.10.21.17
+biganswer.example. 3600 IN A 10.10.21.18
+biganswer.example. 3600 IN A 10.10.21.19
+biganswer.example. 3600 IN A 10.10.21.20
+biganswer.example. 3600 IN A 10.10.21.21
+biganswer.example. 3600 IN A 10.10.21.22
+biganswer.example. 3600 IN A 10.10.21.23
+biganswer.example. 3600 IN A 10.10.21.24
+biganswer.example. 3600 IN A 10.10.21.25
+biganswer.example. 3600 IN A 10.10.21.26
+biganswer.example. 3600 IN A 10.10.21.27
+biganswer.example. 3600 IN A 10.10.21.28
+biganswer.example. 3600 IN A 10.10.21.29
+biganswer.example. 3600 IN A 10.10.21.30
+biganswer.example. 3600 IN A 10.10.21.31
+biganswer.example. 3600 IN A 10.10.21.32
+biganswer.example. 3600 IN A 10.10.21.33
+biganswer.example. 3600 IN A 10.10.21.34
+biganswer.example. 3600 IN A 10.10.21.35
+biganswer.example. 3600 IN A 10.10.21.36
+biganswer.example. 3600 IN A 10.10.21.37
+biganswer.example. 3600 IN A 10.10.21.38
+biganswer.example. 3600 IN A 10.10.21.39
+biganswer.example. 3600 IN A 10.10.21.40
+biganswer.example. 3600 IN A 10.10.21.41
+biganswer.example. 3600 IN A 10.10.21.42
+biganswer.example. 3600 IN A 10.10.21.43
+biganswer.example. 3600 IN A 10.10.21.44
+biganswer.example. 3600 IN A 10.10.21.45
+biganswer.example. 3600 IN A 10.10.21.46
+biganswer.example. 3600 IN A 10.10.21.47
+biganswer.example. 3600 IN A 10.10.21.48
+biganswer.example. 3600 IN A 10.10.21.49
+biganswer.example. 3600 IN A 10.10.21.50
+biganswer.example. 3600 IN A 10.10.22.1
+biganswer.example. 3600 IN A 10.10.22.2
+biganswer.example. 3600 IN A 10.10.22.3
+biganswer.example. 3600 IN A 10.10.22.4
+biganswer.example. 3600 IN A 10.10.22.5
+biganswer.example. 3600 IN A 10.10.22.6
+biganswer.example. 3600 IN A 10.10.22.7
+biganswer.example. 3600 IN A 10.10.22.8
+biganswer.example. 3600 IN A 10.10.22.9
+biganswer.example. 3600 IN A 10.10.22.10
+biganswer.example. 3600 IN A 10.10.22.11
+biganswer.example. 3600 IN A 10.10.22.12
+biganswer.example. 3600 IN A 10.10.22.13
+biganswer.example. 3600 IN A 10.10.22.14
+biganswer.example. 3600 IN A 10.10.22.15
+biganswer.example. 3600 IN A 10.10.22.16
+biganswer.example. 3600 IN A 10.10.22.17
+biganswer.example. 3600 IN A 10.10.22.18
+biganswer.example. 3600 IN A 10.10.22.19
+biganswer.example. 3600 IN A 10.10.22.20
+biganswer.example. 3600 IN A 10.10.22.21
+biganswer.example. 3600 IN A 10.10.22.22
+biganswer.example. 3600 IN A 10.10.22.23
+biganswer.example. 3600 IN A 10.10.22.24
+biganswer.example. 3600 IN A 10.10.22.25
+biganswer.example. 3600 IN A 10.10.22.26
+biganswer.example. 3600 IN A 10.10.22.27
+biganswer.example. 3600 IN A 10.10.22.28
+biganswer.example. 3600 IN A 10.10.22.29
+biganswer.example. 3600 IN A 10.10.22.30
+biganswer.example. 3600 IN A 10.10.22.31
+biganswer.example. 3600 IN A 10.10.22.32
+biganswer.example. 3600 IN A 10.10.22.33
+biganswer.example. 3600 IN A 10.10.22.34
+biganswer.example. 3600 IN A 10.10.22.35
+biganswer.example. 3600 IN A 10.10.22.36
+biganswer.example. 3600 IN A 10.10.22.37
+biganswer.example. 3600 IN A 10.10.22.38
+biganswer.example. 3600 IN A 10.10.22.39
+biganswer.example. 3600 IN A 10.10.22.40
+biganswer.example. 3600 IN A 10.10.22.41
+biganswer.example. 3600 IN A 10.10.22.42
+biganswer.example. 3600 IN A 10.10.22.43
+biganswer.example. 3600 IN A 10.10.22.44
+biganswer.example. 3600 IN A 10.10.22.45
+biganswer.example. 3600 IN A 10.10.22.46
+biganswer.example. 3600 IN A 10.10.22.47
+biganswer.example. 3600 IN A 10.10.22.48
+biganswer.example. 3600 IN A 10.10.22.49
+biganswer.example. 3600 IN A 10.10.22.50
+biganswer.example. 3600 IN A 10.10.23.1
+biganswer.example. 3600 IN A 10.10.23.2
+biganswer.example. 3600 IN A 10.10.23.3
+biganswer.example. 3600 IN A 10.10.23.4
+biganswer.example. 3600 IN A 10.10.23.5
+biganswer.example. 3600 IN A 10.10.23.6
+biganswer.example. 3600 IN A 10.10.23.7
+biganswer.example. 3600 IN A 10.10.23.8
+biganswer.example. 3600 IN A 10.10.23.9
+biganswer.example. 3600 IN A 10.10.23.10
+biganswer.example. 3600 IN A 10.10.23.11
+biganswer.example. 3600 IN A 10.10.23.12
+biganswer.example. 3600 IN A 10.10.23.13
+biganswer.example. 3600 IN A 10.10.23.14
+biganswer.example. 3600 IN A 10.10.23.15
+biganswer.example. 3600 IN A 10.10.23.16
+biganswer.example. 3600 IN A 10.10.23.17
+biganswer.example. 3600 IN A 10.10.23.18
+biganswer.example. 3600 IN A 10.10.23.19
+biganswer.example. 3600 IN A 10.10.23.20
+biganswer.example. 3600 IN A 10.10.23.21
+biganswer.example. 3600 IN A 10.10.23.22
+biganswer.example. 3600 IN A 10.10.23.23
+biganswer.example. 3600 IN A 10.10.23.24
+biganswer.example. 3600 IN A 10.10.23.25
+biganswer.example. 3600 IN A 10.10.23.26
+biganswer.example. 3600 IN A 10.10.23.27
+biganswer.example. 3600 IN A 10.10.23.28
+biganswer.example. 3600 IN A 10.10.23.29
+biganswer.example. 3600 IN A 10.10.23.30
+biganswer.example. 3600 IN A 10.10.23.31
+biganswer.example. 3600 IN A 10.10.23.32
+biganswer.example. 3600 IN A 10.10.23.33
+biganswer.example. 3600 IN A 10.10.23.34
+biganswer.example. 3600 IN A 10.10.23.35
+biganswer.example. 3600 IN A 10.10.23.36
+biganswer.example. 3600 IN A 10.10.23.37
+biganswer.example. 3600 IN A 10.10.23.38
+biganswer.example. 3600 IN A 10.10.23.39
+biganswer.example. 3600 IN A 10.10.23.40
+biganswer.example. 3600 IN A 10.10.23.41
+biganswer.example. 3600 IN A 10.10.23.42
+biganswer.example. 3600 IN A 10.10.23.43
+biganswer.example. 3600 IN A 10.10.23.44
+biganswer.example. 3600 IN A 10.10.23.45
+biganswer.example. 3600 IN A 10.10.23.46
+biganswer.example. 3600 IN A 10.10.23.47
+biganswer.example. 3600 IN A 10.10.23.48
+biganswer.example. 3600 IN A 10.10.23.49
+biganswer.example. 3600 IN A 10.10.23.50
+biganswer.example. 3600 IN A 10.10.24.1
+biganswer.example. 3600 IN A 10.10.24.2
+biganswer.example. 3600 IN A 10.10.24.3
+biganswer.example. 3600 IN A 10.10.24.4
+biganswer.example. 3600 IN A 10.10.24.5
+biganswer.example. 3600 IN A 10.10.24.6
+biganswer.example. 3600 IN A 10.10.24.7
+biganswer.example. 3600 IN A 10.10.24.8
+biganswer.example. 3600 IN A 10.10.24.9
+biganswer.example. 3600 IN A 10.10.24.10
+biganswer.example. 3600 IN A 10.10.24.11
+biganswer.example. 3600 IN A 10.10.24.12
+biganswer.example. 3600 IN A 10.10.24.13
+biganswer.example. 3600 IN A 10.10.24.14
+biganswer.example. 3600 IN A 10.10.24.15
+biganswer.example. 3600 IN A 10.10.24.16
+biganswer.example. 3600 IN A 10.10.24.17
+biganswer.example. 3600 IN A 10.10.24.18
+biganswer.example. 3600 IN A 10.10.24.19
+biganswer.example. 3600 IN A 10.10.24.20
+biganswer.example. 3600 IN A 10.10.24.21
+biganswer.example. 3600 IN A 10.10.24.22
+biganswer.example. 3600 IN A 10.10.24.23
+biganswer.example. 3600 IN A 10.10.24.24
+biganswer.example. 3600 IN A 10.10.24.25
+biganswer.example. 3600 IN A 10.10.24.26
+biganswer.example. 3600 IN A 10.10.24.27
+biganswer.example. 3600 IN A 10.10.24.28
+biganswer.example. 3600 IN A 10.10.24.29
+biganswer.example. 3600 IN A 10.10.24.30
+biganswer.example. 3600 IN A 10.10.24.31
+biganswer.example. 3600 IN A 10.10.24.32
+biganswer.example. 3600 IN A 10.10.24.33
+biganswer.example. 3600 IN A 10.10.24.34
+biganswer.example. 3600 IN A 10.10.24.35
+biganswer.example. 3600 IN A 10.10.24.36
+biganswer.example. 3600 IN A 10.10.24.37
+biganswer.example. 3600 IN A 10.10.24.38
+biganswer.example. 3600 IN A 10.10.24.39
+biganswer.example. 3600 IN A 10.10.24.40
+biganswer.example. 3600 IN A 10.10.24.41
+biganswer.example. 3600 IN A 10.10.24.42
+biganswer.example. 3600 IN A 10.10.24.43
+biganswer.example. 3600 IN A 10.10.24.44
+biganswer.example. 3600 IN A 10.10.24.45
+biganswer.example. 3600 IN A 10.10.24.46
+biganswer.example. 3600 IN A 10.10.24.47
+biganswer.example. 3600 IN A 10.10.24.48
+biganswer.example. 3600 IN A 10.10.24.49
+biganswer.example. 3600 IN A 10.10.24.50
+biganswer.example. 3600 IN A 10.10.25.1
+biganswer.example. 3600 IN A 10.10.25.2
+biganswer.example. 3600 IN A 10.10.25.3
+biganswer.example. 3600 IN A 10.10.25.4
+biganswer.example. 3600 IN A 10.10.25.5
+biganswer.example. 3600 IN A 10.10.25.6
+biganswer.example. 3600 IN A 10.10.25.7
+biganswer.example. 3600 IN A 10.10.25.8
+biganswer.example. 3600 IN A 10.10.25.9
+biganswer.example. 3600 IN A 10.10.25.10
+biganswer.example. 3600 IN A 10.10.25.11
+biganswer.example. 3600 IN A 10.10.25.12
+biganswer.example. 3600 IN A 10.10.25.13
+biganswer.example. 3600 IN A 10.10.25.14
+biganswer.example. 3600 IN A 10.10.25.15
+biganswer.example. 3600 IN A 10.10.25.16
+biganswer.example. 3600 IN A 10.10.25.17
+biganswer.example. 3600 IN A 10.10.25.18
+biganswer.example. 3600 IN A 10.10.25.19
+biganswer.example. 3600 IN A 10.10.25.20
+biganswer.example. 3600 IN A 10.10.25.21
+biganswer.example. 3600 IN A 10.10.25.22
+biganswer.example. 3600 IN A 10.10.25.23
+biganswer.example. 3600 IN A 10.10.25.24
+biganswer.example. 3600 IN A 10.10.25.25
+biganswer.example. 3600 IN A 10.10.25.26
+biganswer.example. 3600 IN A 10.10.25.27
+biganswer.example. 3600 IN A 10.10.25.28
+biganswer.example. 3600 IN A 10.10.25.29
+biganswer.example. 3600 IN A 10.10.25.30
+biganswer.example. 3600 IN A 10.10.25.31
+biganswer.example. 3600 IN A 10.10.25.32
+biganswer.example. 3600 IN A 10.10.25.33
+biganswer.example. 3600 IN A 10.10.25.34
+biganswer.example. 3600 IN A 10.10.25.35
+biganswer.example. 3600 IN A 10.10.25.36
+biganswer.example. 3600 IN A 10.10.25.37
+biganswer.example. 3600 IN A 10.10.25.38
+biganswer.example. 3600 IN A 10.10.25.39
+biganswer.example. 3600 IN A 10.10.25.40
+biganswer.example. 3600 IN A 10.10.25.41
+biganswer.example. 3600 IN A 10.10.25.42
+biganswer.example. 3600 IN A 10.10.25.43
+biganswer.example. 3600 IN A 10.10.25.44
+biganswer.example. 3600 IN A 10.10.25.45
+biganswer.example. 3600 IN A 10.10.25.46
+biganswer.example. 3600 IN A 10.10.25.47
+biganswer.example. 3600 IN A 10.10.25.48
+biganswer.example. 3600 IN A 10.10.25.49
+biganswer.example. 3600 IN A 10.10.25.50
+biganswer.example. 3600 IN A 10.10.26.1
+biganswer.example. 3600 IN A 10.10.26.2
+biganswer.example. 3600 IN A 10.10.26.3
+biganswer.example. 3600 IN A 10.10.26.4
+biganswer.example. 3600 IN A 10.10.26.5
+biganswer.example. 3600 IN A 10.10.26.6
+biganswer.example. 3600 IN A 10.10.26.7
+biganswer.example. 3600 IN A 10.10.26.8
+biganswer.example. 3600 IN A 10.10.26.9
+biganswer.example. 3600 IN A 10.10.26.10
+biganswer.example. 3600 IN A 10.10.26.11
+biganswer.example. 3600 IN A 10.10.26.12
+biganswer.example. 3600 IN A 10.10.26.13
+biganswer.example. 3600 IN A 10.10.26.14
+biganswer.example. 3600 IN A 10.10.26.15
+biganswer.example. 3600 IN A 10.10.26.16
+biganswer.example. 3600 IN A 10.10.26.17
+biganswer.example. 3600 IN A 10.10.26.18
+biganswer.example. 3600 IN A 10.10.26.19
+biganswer.example. 3600 IN A 10.10.26.20
+biganswer.example. 3600 IN A 10.10.26.21
+biganswer.example. 3600 IN A 10.10.26.22
+biganswer.example. 3600 IN A 10.10.26.23
+biganswer.example. 3600 IN A 10.10.26.24
+biganswer.example. 3600 IN A 10.10.26.25
+biganswer.example. 3600 IN A 10.10.26.26
+biganswer.example. 3600 IN A 10.10.26.27
+biganswer.example. 3600 IN A 10.10.26.28
+biganswer.example. 3600 IN A 10.10.26.29
+biganswer.example. 3600 IN A 10.10.26.30
+biganswer.example. 3600 IN A 10.10.26.31
+biganswer.example. 3600 IN A 10.10.26.32
+biganswer.example. 3600 IN A 10.10.26.33
+biganswer.example. 3600 IN A 10.10.26.34
+biganswer.example. 3600 IN A 10.10.26.35
+biganswer.example. 3600 IN A 10.10.26.36
+biganswer.example. 3600 IN A 10.10.26.37
+biganswer.example. 3600 IN A 10.10.26.38
+biganswer.example. 3600 IN A 10.10.26.39
+biganswer.example. 3600 IN A 10.10.26.40
+biganswer.example. 3600 IN A 10.10.26.41
+biganswer.example. 3600 IN A 10.10.26.42
+biganswer.example. 3600 IN A 10.10.26.43
+biganswer.example. 3600 IN A 10.10.26.44
+biganswer.example. 3600 IN A 10.10.26.45
+biganswer.example. 3600 IN A 10.10.26.46
+biganswer.example. 3600 IN A 10.10.26.47
+biganswer.example. 3600 IN A 10.10.26.48
+biganswer.example. 3600 IN A 10.10.26.49
+biganswer.example. 3600 IN A 10.10.26.50
+biganswer.example. 3600 IN A 10.10.27.1
+biganswer.example. 3600 IN A 10.10.27.2
+biganswer.example. 3600 IN A 10.10.27.3
+biganswer.example. 3600 IN A 10.10.27.4
+biganswer.example. 3600 IN A 10.10.27.5
+biganswer.example. 3600 IN A 10.10.27.6
+biganswer.example. 3600 IN A 10.10.27.7
+biganswer.example. 3600 IN A 10.10.27.8
+biganswer.example. 3600 IN A 10.10.27.9
+biganswer.example. 3600 IN A 10.10.27.10
+biganswer.example. 3600 IN A 10.10.27.11
+biganswer.example. 3600 IN A 10.10.27.12
+biganswer.example. 3600 IN A 10.10.27.13
+biganswer.example. 3600 IN A 10.10.27.14
+biganswer.example. 3600 IN A 10.10.27.15
+biganswer.example. 3600 IN A 10.10.27.16
+biganswer.example. 3600 IN A 10.10.27.17
+biganswer.example. 3600 IN A 10.10.27.18
+biganswer.example. 3600 IN A 10.10.27.19
+biganswer.example. 3600 IN A 10.10.27.20
+biganswer.example. 3600 IN A 10.10.27.21
+biganswer.example. 3600 IN A 10.10.27.22
+biganswer.example. 3600 IN A 10.10.27.23
+biganswer.example. 3600 IN A 10.10.27.24
+biganswer.example. 3600 IN A 10.10.27.25
+biganswer.example. 3600 IN A 10.10.27.26
+biganswer.example. 3600 IN A 10.10.27.27
+biganswer.example. 3600 IN A 10.10.27.28
+biganswer.example. 3600 IN A 10.10.27.29
+biganswer.example. 3600 IN A 10.10.27.30
+biganswer.example. 3600 IN A 10.10.27.31
+biganswer.example. 3600 IN A 10.10.27.32
+biganswer.example. 3600 IN A 10.10.27.33
+biganswer.example. 3600 IN A 10.10.27.34
+biganswer.example. 3600 IN A 10.10.27.35
+biganswer.example. 3600 IN A 10.10.27.36
+biganswer.example. 3600 IN A 10.10.27.37
+biganswer.example. 3600 IN A 10.10.27.38
+biganswer.example. 3600 IN A 10.10.27.39
+biganswer.example. 3600 IN A 10.10.27.40
+biganswer.example. 3600 IN A 10.10.27.41
+biganswer.example. 3600 IN A 10.10.27.42
+biganswer.example. 3600 IN A 10.10.27.43
+biganswer.example. 3600 IN A 10.10.27.44
+biganswer.example. 3600 IN A 10.10.27.45
+biganswer.example. 3600 IN A 10.10.27.46
+biganswer.example. 3600 IN A 10.10.27.47
+biganswer.example. 3600 IN A 10.10.27.48
+biganswer.example. 3600 IN A 10.10.27.49
+biganswer.example. 3600 IN A 10.10.27.50
+biganswer.example. 3600 IN A 10.10.28.1
+biganswer.example. 3600 IN A 10.10.28.2
+biganswer.example. 3600 IN A 10.10.28.3
+biganswer.example. 3600 IN A 10.10.28.4
+biganswer.example. 3600 IN A 10.10.28.5
+biganswer.example. 3600 IN A 10.10.28.6
+biganswer.example. 3600 IN A 10.10.28.7
+biganswer.example. 3600 IN A 10.10.28.8
+biganswer.example. 3600 IN A 10.10.28.9
+biganswer.example. 3600 IN A 10.10.28.10
+biganswer.example. 3600 IN A 10.10.28.11
+biganswer.example. 3600 IN A 10.10.28.12
+biganswer.example. 3600 IN A 10.10.28.13
+biganswer.example. 3600 IN A 10.10.28.14
+biganswer.example. 3600 IN A 10.10.28.15
+biganswer.example. 3600 IN A 10.10.28.16
+biganswer.example. 3600 IN A 10.10.28.17
+biganswer.example. 3600 IN A 10.10.28.18
+biganswer.example. 3600 IN A 10.10.28.19
+biganswer.example. 3600 IN A 10.10.28.20
+biganswer.example. 3600 IN A 10.10.28.21
+biganswer.example. 3600 IN A 10.10.28.22
+biganswer.example. 3600 IN A 10.10.28.23
+biganswer.example. 3600 IN A 10.10.28.24
+biganswer.example. 3600 IN A 10.10.28.25
+biganswer.example. 3600 IN A 10.10.28.26
+biganswer.example. 3600 IN A 10.10.28.27
+biganswer.example. 3600 IN A 10.10.28.28
+biganswer.example. 3600 IN A 10.10.28.29
+biganswer.example. 3600 IN A 10.10.28.30
+biganswer.example. 3600 IN A 10.10.28.31
+biganswer.example. 3600 IN A 10.10.28.32
+biganswer.example. 3600 IN A 10.10.28.33
+biganswer.example. 3600 IN A 10.10.28.34
+biganswer.example. 3600 IN A 10.10.28.35
+biganswer.example. 3600 IN A 10.10.28.36
+biganswer.example. 3600 IN A 10.10.28.37
+biganswer.example. 3600 IN A 10.10.28.38
+biganswer.example. 3600 IN A 10.10.28.39
+biganswer.example. 3600 IN A 10.10.28.40
+biganswer.example. 3600 IN A 10.10.28.41
+biganswer.example. 3600 IN A 10.10.28.42
+biganswer.example. 3600 IN A 10.10.28.43
+biganswer.example. 3600 IN A 10.10.28.44
+biganswer.example. 3600 IN A 10.10.28.45
+biganswer.example. 3600 IN A 10.10.28.46
+biganswer.example. 3600 IN A 10.10.28.47
+biganswer.example. 3600 IN A 10.10.28.48
+biganswer.example. 3600 IN A 10.10.28.49
+biganswer.example. 3600 IN A 10.10.28.50
+biganswer.example. 3600 IN A 10.10.29.1
+biganswer.example. 3600 IN A 10.10.29.2
+biganswer.example. 3600 IN A 10.10.29.3
+biganswer.example. 3600 IN A 10.10.29.4
+biganswer.example. 3600 IN A 10.10.29.5
+biganswer.example. 3600 IN A 10.10.29.6
+biganswer.example. 3600 IN A 10.10.29.7
+biganswer.example. 3600 IN A 10.10.29.8
+biganswer.example. 3600 IN A 10.10.29.9
+biganswer.example. 3600 IN A 10.10.29.10
+biganswer.example. 3600 IN A 10.10.29.11
+biganswer.example. 3600 IN A 10.10.29.12
+biganswer.example. 3600 IN A 10.10.29.13
+biganswer.example. 3600 IN A 10.10.29.14
+biganswer.example. 3600 IN A 10.10.29.15
+biganswer.example. 3600 IN A 10.10.29.16
+biganswer.example. 3600 IN A 10.10.29.17
+biganswer.example. 3600 IN A 10.10.29.18
+biganswer.example. 3600 IN A 10.10.29.19
+biganswer.example. 3600 IN A 10.10.29.20
+biganswer.example. 3600 IN A 10.10.29.21
+biganswer.example. 3600 IN A 10.10.29.22
+biganswer.example. 3600 IN A 10.10.29.23
+biganswer.example. 3600 IN A 10.10.29.24
+biganswer.example. 3600 IN A 10.10.29.25
+biganswer.example. 3600 IN A 10.10.29.26
+biganswer.example. 3600 IN A 10.10.29.27
+biganswer.example. 3600 IN A 10.10.29.28
+biganswer.example. 3600 IN A 10.10.29.29
+biganswer.example. 3600 IN A 10.10.29.30
+biganswer.example. 3600 IN A 10.10.29.31
+biganswer.example. 3600 IN A 10.10.29.32
+biganswer.example. 3600 IN A 10.10.29.33
+biganswer.example. 3600 IN A 10.10.29.34
+biganswer.example. 3600 IN A 10.10.29.35
+biganswer.example. 3600 IN A 10.10.29.36
+biganswer.example. 3600 IN A 10.10.29.37
+biganswer.example. 3600 IN A 10.10.29.38
+biganswer.example. 3600 IN A 10.10.29.39
+biganswer.example. 3600 IN A 10.10.29.40
+biganswer.example. 3600 IN A 10.10.29.41
+biganswer.example. 3600 IN A 10.10.29.42
+biganswer.example. 3600 IN A 10.10.29.43
+biganswer.example. 3600 IN A 10.10.29.44
+biganswer.example. 3600 IN A 10.10.29.45
+biganswer.example. 3600 IN A 10.10.29.46
+biganswer.example. 3600 IN A 10.10.29.47
+biganswer.example. 3600 IN A 10.10.29.48
+biganswer.example. 3600 IN A 10.10.29.49
+biganswer.example. 3600 IN A 10.10.29.50
+biganswer.example. 3600 IN A 10.10.30.1
+biganswer.example. 3600 IN A 10.10.30.2
+biganswer.example. 3600 IN A 10.10.30.3
+biganswer.example. 3600 IN A 10.10.30.4
+biganswer.example. 3600 IN A 10.10.30.5
+biganswer.example. 3600 IN A 10.10.30.6
+biganswer.example. 3600 IN A 10.10.30.7
+biganswer.example. 3600 IN A 10.10.30.8
+biganswer.example. 3600 IN A 10.10.30.9
+biganswer.example. 3600 IN A 10.10.30.10
+biganswer.example. 3600 IN A 10.10.30.11
+biganswer.example. 3600 IN A 10.10.30.12
+biganswer.example. 3600 IN A 10.10.30.13
+biganswer.example. 3600 IN A 10.10.30.14
+biganswer.example. 3600 IN A 10.10.30.15
+biganswer.example. 3600 IN A 10.10.30.16
+biganswer.example. 3600 IN A 10.10.30.17
+biganswer.example. 3600 IN A 10.10.30.18
+biganswer.example. 3600 IN A 10.10.30.19
+biganswer.example. 3600 IN A 10.10.30.20
+biganswer.example. 3600 IN A 10.10.30.21
+biganswer.example. 3600 IN A 10.10.30.22
+biganswer.example. 3600 IN A 10.10.30.23
+biganswer.example. 3600 IN A 10.10.30.24
+biganswer.example. 3600 IN A 10.10.30.25
+biganswer.example. 3600 IN A 10.10.30.26
+biganswer.example. 3600 IN A 10.10.30.27
+biganswer.example. 3600 IN A 10.10.30.28
+biganswer.example. 3600 IN A 10.10.30.29
+biganswer.example. 3600 IN A 10.10.30.30
+biganswer.example. 3600 IN A 10.10.30.31
+biganswer.example. 3600 IN A 10.10.30.32
+biganswer.example. 3600 IN A 10.10.30.33
+biganswer.example. 3600 IN A 10.10.30.34
+biganswer.example. 3600 IN A 10.10.30.35
+biganswer.example. 3600 IN A 10.10.30.36
+biganswer.example. 3600 IN A 10.10.30.37
+biganswer.example. 3600 IN A 10.10.30.38
+biganswer.example. 3600 IN A 10.10.30.39
+biganswer.example. 3600 IN A 10.10.30.40
+biganswer.example. 3600 IN A 10.10.30.41
+biganswer.example. 3600 IN A 10.10.30.42
+biganswer.example. 3600 IN A 10.10.30.43
+biganswer.example. 3600 IN A 10.10.30.44
+biganswer.example. 3600 IN A 10.10.30.45
+biganswer.example. 3600 IN A 10.10.30.46
+biganswer.example. 3600 IN A 10.10.30.47
+biganswer.example. 3600 IN A 10.10.30.48
+biganswer.example. 3600 IN A 10.10.30.49
+biganswer.example. 3600 IN A 10.10.30.50
+biganswer.example. 3600 IN A 10.10.31.1
+biganswer.example. 3600 IN A 10.10.31.2
+biganswer.example. 3600 IN A 10.10.31.3
+biganswer.example. 3600 IN A 10.10.31.4
+biganswer.example. 3600 IN A 10.10.31.5
+biganswer.example. 3600 IN A 10.10.31.6
+biganswer.example. 3600 IN A 10.10.31.7
+biganswer.example. 3600 IN A 10.10.31.8
+biganswer.example. 3600 IN A 10.10.31.9
+biganswer.example. 3600 IN A 10.10.31.10
+biganswer.example. 3600 IN A 10.10.31.11
+biganswer.example. 3600 IN A 10.10.31.12
+biganswer.example. 3600 IN A 10.10.31.13
+biganswer.example. 3600 IN A 10.10.31.14
+biganswer.example. 3600 IN A 10.10.31.15
+biganswer.example. 3600 IN A 10.10.31.16
+biganswer.example. 3600 IN A 10.10.31.17
+biganswer.example. 3600 IN A 10.10.31.18
+biganswer.example. 3600 IN A 10.10.31.19
+biganswer.example. 3600 IN A 10.10.31.20
+biganswer.example. 3600 IN A 10.10.31.21
+biganswer.example. 3600 IN A 10.10.31.22
+biganswer.example. 3600 IN A 10.10.31.23
+biganswer.example. 3600 IN A 10.10.31.24
+biganswer.example. 3600 IN A 10.10.31.25
+biganswer.example. 3600 IN A 10.10.31.26
+biganswer.example. 3600 IN A 10.10.31.27
+biganswer.example. 3600 IN A 10.10.31.28
+biganswer.example. 3600 IN A 10.10.31.29
+biganswer.example. 3600 IN A 10.10.31.30
+biganswer.example. 3600 IN A 10.10.31.31
+biganswer.example. 3600 IN A 10.10.31.32
+biganswer.example. 3600 IN A 10.10.31.33
+biganswer.example. 3600 IN A 10.10.31.34
+biganswer.example. 3600 IN A 10.10.31.35
+biganswer.example. 3600 IN A 10.10.31.36
+biganswer.example. 3600 IN A 10.10.31.37
+biganswer.example. 3600 IN A 10.10.31.38
+biganswer.example. 3600 IN A 10.10.31.39
+biganswer.example. 3600 IN A 10.10.31.40
+biganswer.example. 3600 IN A 10.10.31.41
+biganswer.example. 3600 IN A 10.10.31.42
+biganswer.example. 3600 IN A 10.10.31.43
+biganswer.example. 3600 IN A 10.10.31.44
+biganswer.example. 3600 IN A 10.10.31.45
+biganswer.example. 3600 IN A 10.10.31.46
+biganswer.example. 3600 IN A 10.10.31.47
+biganswer.example. 3600 IN A 10.10.31.48
+biganswer.example. 3600 IN A 10.10.31.49
+biganswer.example. 3600 IN A 10.10.31.50
+biganswer.example. 3600 IN A 10.10.32.1
+biganswer.example. 3600 IN A 10.10.32.2
+biganswer.example. 3600 IN A 10.10.32.3
+biganswer.example. 3600 IN A 10.10.32.4
+biganswer.example. 3600 IN A 10.10.32.5
+biganswer.example. 3600 IN A 10.10.32.6
+biganswer.example. 3600 IN A 10.10.32.7
+biganswer.example. 3600 IN A 10.10.32.8
+biganswer.example. 3600 IN A 10.10.32.9
+biganswer.example. 3600 IN A 10.10.32.10
+biganswer.example. 3600 IN A 10.10.32.11
+biganswer.example. 3600 IN A 10.10.32.12
+biganswer.example. 3600 IN A 10.10.32.13
+biganswer.example. 3600 IN A 10.10.32.14
+biganswer.example. 3600 IN A 10.10.32.15
+biganswer.example. 3600 IN A 10.10.32.16
+biganswer.example. 3600 IN A 10.10.32.17
+biganswer.example. 3600 IN A 10.10.32.18
+biganswer.example. 3600 IN A 10.10.32.19
+biganswer.example. 3600 IN A 10.10.32.20
+biganswer.example. 3600 IN A 10.10.32.21
+biganswer.example. 3600 IN A 10.10.32.22
+biganswer.example. 3600 IN A 10.10.32.23
+biganswer.example. 3600 IN A 10.10.32.24
+biganswer.example. 3600 IN A 10.10.32.25
+biganswer.example. 3600 IN A 10.10.32.26
+biganswer.example. 3600 IN A 10.10.32.27
+biganswer.example. 3600 IN A 10.10.32.28
+biganswer.example. 3600 IN A 10.10.32.29
+biganswer.example. 3600 IN A 10.10.32.30
+biganswer.example. 3600 IN A 10.10.32.31
+biganswer.example. 3600 IN A 10.10.32.32
+biganswer.example. 3600 IN A 10.10.32.33
+biganswer.example. 3600 IN A 10.10.32.34
+biganswer.example. 3600 IN A 10.10.32.35
+biganswer.example. 3600 IN A 10.10.32.36
+biganswer.example. 3600 IN A 10.10.32.37
+biganswer.example. 3600 IN A 10.10.32.38
+biganswer.example. 3600 IN A 10.10.32.39
+biganswer.example. 3600 IN A 10.10.32.40
+biganswer.example. 3600 IN A 10.10.32.41
+biganswer.example. 3600 IN A 10.10.32.42
+biganswer.example. 3600 IN A 10.10.32.43
+biganswer.example. 3600 IN A 10.10.32.44
+biganswer.example. 3600 IN A 10.10.32.45
+biganswer.example. 3600 IN A 10.10.32.46
+biganswer.example. 3600 IN A 10.10.32.47
+biganswer.example. 3600 IN A 10.10.32.48
+biganswer.example. 3600 IN A 10.10.32.49
+biganswer.example. 3600 IN A 10.10.32.50
+biganswer.example. 3600 IN A 10.10.33.1
+biganswer.example. 3600 IN A 10.10.33.2
+biganswer.example. 3600 IN A 10.10.33.3
+biganswer.example. 3600 IN A 10.10.33.4
+biganswer.example. 3600 IN A 10.10.33.5
+biganswer.example. 3600 IN A 10.10.33.6
+biganswer.example. 3600 IN A 10.10.33.7
+biganswer.example. 3600 IN A 10.10.33.8
+biganswer.example. 3600 IN A 10.10.33.9
+biganswer.example. 3600 IN A 10.10.33.10
+biganswer.example. 3600 IN A 10.10.33.11
+biganswer.example. 3600 IN A 10.10.33.12
+biganswer.example. 3600 IN A 10.10.33.13
+biganswer.example. 3600 IN A 10.10.33.14
+biganswer.example. 3600 IN A 10.10.33.15
+biganswer.example. 3600 IN A 10.10.33.16
+biganswer.example. 3600 IN A 10.10.33.17
+biganswer.example. 3600 IN A 10.10.33.18
+biganswer.example. 3600 IN A 10.10.33.19
+biganswer.example. 3600 IN A 10.10.33.20
+biganswer.example. 3600 IN A 10.10.33.21
+biganswer.example. 3600 IN A 10.10.33.22
+biganswer.example. 3600 IN A 10.10.33.23
+biganswer.example. 3600 IN A 10.10.33.24
+biganswer.example. 3600 IN A 10.10.33.25
+biganswer.example. 3600 IN A 10.10.33.26
+biganswer.example. 3600 IN A 10.10.33.27
+biganswer.example. 3600 IN A 10.10.33.28
+biganswer.example. 3600 IN A 10.10.33.29
+biganswer.example. 3600 IN A 10.10.33.30
+biganswer.example. 3600 IN A 10.10.33.31
+biganswer.example. 3600 IN A 10.10.33.32
+biganswer.example. 3600 IN A 10.10.33.33
+biganswer.example. 3600 IN A 10.10.33.34
+biganswer.example. 3600 IN A 10.10.33.35
+biganswer.example. 3600 IN A 10.10.33.36
+biganswer.example. 3600 IN A 10.10.33.37
+biganswer.example. 3600 IN A 10.10.33.38
+biganswer.example. 3600 IN A 10.10.33.39
+biganswer.example. 3600 IN A 10.10.33.40
+biganswer.example. 3600 IN A 10.10.33.41
+biganswer.example. 3600 IN A 10.10.33.42
+biganswer.example. 3600 IN A 10.10.33.43
+biganswer.example. 3600 IN A 10.10.33.44
+biganswer.example. 3600 IN A 10.10.33.45
+biganswer.example. 3600 IN A 10.10.33.46
+biganswer.example. 3600 IN A 10.10.33.47
+biganswer.example. 3600 IN A 10.10.33.48
+biganswer.example. 3600 IN A 10.10.33.49
+biganswer.example. 3600 IN A 10.10.33.50
+biganswer.example. 3600 IN A 10.10.34.1
+biganswer.example. 3600 IN A 10.10.34.2
+biganswer.example. 3600 IN A 10.10.34.3
+biganswer.example. 3600 IN A 10.10.34.4
+biganswer.example. 3600 IN A 10.10.34.5
+biganswer.example. 3600 IN A 10.10.34.6
+biganswer.example. 3600 IN A 10.10.34.7
+biganswer.example. 3600 IN A 10.10.34.8
+biganswer.example. 3600 IN A 10.10.34.9
+biganswer.example. 3600 IN A 10.10.34.10
+biganswer.example. 3600 IN A 10.10.34.11
+biganswer.example. 3600 IN A 10.10.34.12
+biganswer.example. 3600 IN A 10.10.34.13
+biganswer.example. 3600 IN A 10.10.34.14
+biganswer.example. 3600 IN A 10.10.34.15
+biganswer.example. 3600 IN A 10.10.34.16
+biganswer.example. 3600 IN A 10.10.34.17
+biganswer.example. 3600 IN A 10.10.34.18
+biganswer.example. 3600 IN A 10.10.34.19
+biganswer.example. 3600 IN A 10.10.34.20
+biganswer.example. 3600 IN A 10.10.34.21
+biganswer.example. 3600 IN A 10.10.34.22
+biganswer.example. 3600 IN A 10.10.34.23
+biganswer.example. 3600 IN A 10.10.34.24
+biganswer.example. 3600 IN A 10.10.34.25
+biganswer.example. 3600 IN A 10.10.34.26
+biganswer.example. 3600 IN A 10.10.34.27
+biganswer.example. 3600 IN A 10.10.34.28
+biganswer.example. 3600 IN A 10.10.34.29
+biganswer.example. 3600 IN A 10.10.34.30
+biganswer.example. 3600 IN A 10.10.34.31
+biganswer.example. 3600 IN A 10.10.34.32
+biganswer.example. 3600 IN A 10.10.34.33
+biganswer.example. 3600 IN A 10.10.34.34
+biganswer.example. 3600 IN A 10.10.34.35
+biganswer.example. 3600 IN A 10.10.34.36
+biganswer.example. 3600 IN A 10.10.34.37
+biganswer.example. 3600 IN A 10.10.34.38
+biganswer.example. 3600 IN A 10.10.34.39
+biganswer.example. 3600 IN A 10.10.34.40
+biganswer.example. 3600 IN A 10.10.34.41
+biganswer.example. 3600 IN A 10.10.34.42
+biganswer.example. 3600 IN A 10.10.34.43
+biganswer.example. 3600 IN A 10.10.34.44
+biganswer.example. 3600 IN A 10.10.34.45
+biganswer.example. 3600 IN A 10.10.34.46
+biganswer.example. 3600 IN A 10.10.34.47
+biganswer.example. 3600 IN A 10.10.34.48
+biganswer.example. 3600 IN A 10.10.34.49
+biganswer.example. 3600 IN A 10.10.34.50
+biganswer.example. 3600 IN A 10.10.35.1
+biganswer.example. 3600 IN A 10.10.35.2
+biganswer.example. 3600 IN A 10.10.35.3
+biganswer.example. 3600 IN A 10.10.35.4
+biganswer.example. 3600 IN A 10.10.35.5
+biganswer.example. 3600 IN A 10.10.35.6
+biganswer.example. 3600 IN A 10.10.35.7
+biganswer.example. 3600 IN A 10.10.35.8
+biganswer.example. 3600 IN A 10.10.35.9
+biganswer.example. 3600 IN A 10.10.35.10
+biganswer.example. 3600 IN A 10.10.35.11
+biganswer.example. 3600 IN A 10.10.35.12
+biganswer.example. 3600 IN A 10.10.35.13
+biganswer.example. 3600 IN A 10.10.35.14
+biganswer.example. 3600 IN A 10.10.35.15
+biganswer.example. 3600 IN A 10.10.35.16
+biganswer.example. 3600 IN A 10.10.35.17
+biganswer.example. 3600 IN A 10.10.35.18
+biganswer.example. 3600 IN A 10.10.35.19
+biganswer.example. 3600 IN A 10.10.35.20
+biganswer.example. 3600 IN A 10.10.35.21
+biganswer.example. 3600 IN A 10.10.35.22
+biganswer.example. 3600 IN A 10.10.35.23
+biganswer.example. 3600 IN A 10.10.35.24
+biganswer.example. 3600 IN A 10.10.35.25
+biganswer.example. 3600 IN A 10.10.35.26
+biganswer.example. 3600 IN A 10.10.35.27
+biganswer.example. 3600 IN A 10.10.35.28
+biganswer.example. 3600 IN A 10.10.35.29
+biganswer.example. 3600 IN A 10.10.35.30
+biganswer.example. 3600 IN A 10.10.35.31
+biganswer.example. 3600 IN A 10.10.35.32
+biganswer.example. 3600 IN A 10.10.35.33
+biganswer.example. 3600 IN A 10.10.35.34
+biganswer.example. 3600 IN A 10.10.35.35
+biganswer.example. 3600 IN A 10.10.35.36
+biganswer.example. 3600 IN A 10.10.35.37
+biganswer.example. 3600 IN A 10.10.35.38
+biganswer.example. 3600 IN A 10.10.35.39
+biganswer.example. 3600 IN A 10.10.35.40
+biganswer.example. 3600 IN A 10.10.35.41
+biganswer.example. 3600 IN A 10.10.35.42
+biganswer.example. 3600 IN A 10.10.35.43
+biganswer.example. 3600 IN A 10.10.35.44
+biganswer.example. 3600 IN A 10.10.35.45
+biganswer.example. 3600 IN A 10.10.35.46
+biganswer.example. 3600 IN A 10.10.35.47
+biganswer.example. 3600 IN A 10.10.35.48
+biganswer.example. 3600 IN A 10.10.35.49
+biganswer.example. 3600 IN A 10.10.35.50
+biganswer.example. 3600 IN A 10.10.36.1
+biganswer.example. 3600 IN A 10.10.36.2
+biganswer.example. 3600 IN A 10.10.36.3
+biganswer.example. 3600 IN A 10.10.36.4
+biganswer.example. 3600 IN A 10.10.36.5
+biganswer.example. 3600 IN A 10.10.36.6
+biganswer.example. 3600 IN A 10.10.36.7
+biganswer.example. 3600 IN A 10.10.36.8
+biganswer.example. 3600 IN A 10.10.36.9
+biganswer.example. 3600 IN A 10.10.36.10
+biganswer.example. 3600 IN A 10.10.36.11
+biganswer.example. 3600 IN A 10.10.36.12
+biganswer.example. 3600 IN A 10.10.36.13
+biganswer.example. 3600 IN A 10.10.36.14
+biganswer.example. 3600 IN A 10.10.36.15
+biganswer.example. 3600 IN A 10.10.36.16
+biganswer.example. 3600 IN A 10.10.36.17
+biganswer.example. 3600 IN A 10.10.36.18
+biganswer.example. 3600 IN A 10.10.36.19
+biganswer.example. 3600 IN A 10.10.36.20
+biganswer.example. 3600 IN A 10.10.36.21
+biganswer.example. 3600 IN A 10.10.36.22
+biganswer.example. 3600 IN A 10.10.36.23
+biganswer.example. 3600 IN A 10.10.36.24
+biganswer.example. 3600 IN A 10.10.36.25
+biganswer.example. 3600 IN A 10.10.36.26
+biganswer.example. 3600 IN A 10.10.36.27
+biganswer.example. 3600 IN A 10.10.36.28
+biganswer.example. 3600 IN A 10.10.36.29
+biganswer.example. 3600 IN A 10.10.36.30
+biganswer.example. 3600 IN A 10.10.36.31
+biganswer.example. 3600 IN A 10.10.36.32
+biganswer.example. 3600 IN A 10.10.36.33
+biganswer.example. 3600 IN A 10.10.36.34
+biganswer.example. 3600 IN A 10.10.36.35
+biganswer.example. 3600 IN A 10.10.36.36
+biganswer.example. 3600 IN A 10.10.36.37
+biganswer.example. 3600 IN A 10.10.36.38
+biganswer.example. 3600 IN A 10.10.36.39
+biganswer.example. 3600 IN A 10.10.36.40
+biganswer.example. 3600 IN A 10.10.36.41
+biganswer.example. 3600 IN A 10.10.36.42
+biganswer.example. 3600 IN A 10.10.36.43
+biganswer.example. 3600 IN A 10.10.36.44
+biganswer.example. 3600 IN A 10.10.36.45
+biganswer.example. 3600 IN A 10.10.36.46
+biganswer.example. 3600 IN A 10.10.36.47
+biganswer.example. 3600 IN A 10.10.36.48
+biganswer.example. 3600 IN A 10.10.36.49
+biganswer.example. 3600 IN A 10.10.36.50
+biganswer.example. 3600 IN A 10.10.37.1
+biganswer.example. 3600 IN A 10.10.37.2
+biganswer.example. 3600 IN A 10.10.37.3
+biganswer.example. 3600 IN A 10.10.37.4
+biganswer.example. 3600 IN A 10.10.37.5
+biganswer.example. 3600 IN A 10.10.37.6
+biganswer.example. 3600 IN A 10.10.37.7
+biganswer.example. 3600 IN A 10.10.37.8
+biganswer.example. 3600 IN A 10.10.37.9
+biganswer.example. 3600 IN A 10.10.37.10
+biganswer.example. 3600 IN A 10.10.37.11
+biganswer.example. 3600 IN A 10.10.37.12
+biganswer.example. 3600 IN A 10.10.37.13
+biganswer.example. 3600 IN A 10.10.37.14
+biganswer.example. 3600 IN A 10.10.37.15
+biganswer.example. 3600 IN A 10.10.37.16
+biganswer.example. 3600 IN A 10.10.37.17
+biganswer.example. 3600 IN A 10.10.37.18
+biganswer.example. 3600 IN A 10.10.37.19
+biganswer.example. 3600 IN A 10.10.37.20
+biganswer.example. 3600 IN A 10.10.37.21
+biganswer.example. 3600 IN A 10.10.37.22
+biganswer.example. 3600 IN A 10.10.37.23
+biganswer.example. 3600 IN A 10.10.37.24
+biganswer.example. 3600 IN A 10.10.37.25
+biganswer.example. 3600 IN A 10.10.37.26
+biganswer.example. 3600 IN A 10.10.37.27
+biganswer.example. 3600 IN A 10.10.37.28
+biganswer.example. 3600 IN A 10.10.37.29
+biganswer.example. 3600 IN A 10.10.37.30
+biganswer.example. 3600 IN A 10.10.37.31
+biganswer.example. 3600 IN A 10.10.37.32
+biganswer.example. 3600 IN A 10.10.37.33
+biganswer.example. 3600 IN A 10.10.37.34
+biganswer.example. 3600 IN A 10.10.37.35
+biganswer.example. 3600 IN A 10.10.37.36
+biganswer.example. 3600 IN A 10.10.37.37
+biganswer.example. 3600 IN A 10.10.37.38
+biganswer.example. 3600 IN A 10.10.37.39
+biganswer.example. 3600 IN A 10.10.37.40
+biganswer.example. 3600 IN A 10.10.37.41
+biganswer.example. 3600 IN A 10.10.37.42
+biganswer.example. 3600 IN A 10.10.37.43
+biganswer.example. 3600 IN A 10.10.37.44
+biganswer.example. 3600 IN A 10.10.37.45
+biganswer.example. 3600 IN A 10.10.37.46
+biganswer.example. 3600 IN A 10.10.37.47
+biganswer.example. 3600 IN A 10.10.37.48
+biganswer.example. 3600 IN A 10.10.37.49
+biganswer.example. 3600 IN A 10.10.37.50
+biganswer.example. 3600 IN A 10.10.38.1
+biganswer.example. 3600 IN A 10.10.38.2
+biganswer.example. 3600 IN A 10.10.38.3
+biganswer.example. 3600 IN A 10.10.38.4
+biganswer.example. 3600 IN A 10.10.38.5
+biganswer.example. 3600 IN A 10.10.38.6
+biganswer.example. 3600 IN A 10.10.38.7
+biganswer.example. 3600 IN A 10.10.38.8
+biganswer.example. 3600 IN A 10.10.38.9
+biganswer.example. 3600 IN A 10.10.38.10
+biganswer.example. 3600 IN A 10.10.38.11
+biganswer.example. 3600 IN A 10.10.38.12
+biganswer.example. 3600 IN A 10.10.38.13
+biganswer.example. 3600 IN A 10.10.38.14
+biganswer.example. 3600 IN A 10.10.38.15
+biganswer.example. 3600 IN A 10.10.38.16
+biganswer.example. 3600 IN A 10.10.38.17
+biganswer.example. 3600 IN A 10.10.38.18
+biganswer.example. 3600 IN A 10.10.38.19
+biganswer.example. 3600 IN A 10.10.38.20
+biganswer.example. 3600 IN A 10.10.38.21
+biganswer.example. 3600 IN A 10.10.38.22
+biganswer.example. 3600 IN A 10.10.38.23
+biganswer.example. 3600 IN A 10.10.38.24
+biganswer.example. 3600 IN A 10.10.38.25
+biganswer.example. 3600 IN A 10.10.38.26
+biganswer.example. 3600 IN A 10.10.38.27
+biganswer.example. 3600 IN A 10.10.38.28
+biganswer.example. 3600 IN A 10.10.38.29
+biganswer.example. 3600 IN A 10.10.38.30
+biganswer.example. 3600 IN A 10.10.38.31
+biganswer.example. 3600 IN A 10.10.38.32
+biganswer.example. 3600 IN A 10.10.38.33
+biganswer.example. 3600 IN A 10.10.38.34
+biganswer.example. 3600 IN A 10.10.38.35
+biganswer.example. 3600 IN A 10.10.38.36
+biganswer.example. 3600 IN A 10.10.38.37
+biganswer.example. 3600 IN A 10.10.38.38
+biganswer.example. 3600 IN A 10.10.38.39
+biganswer.example. 3600 IN A 10.10.38.40
+biganswer.example. 3600 IN A 10.10.38.41
+biganswer.example. 3600 IN A 10.10.38.42
+biganswer.example. 3600 IN A 10.10.38.43
+biganswer.example. 3600 IN A 10.10.38.44
+biganswer.example. 3600 IN A 10.10.38.45
+biganswer.example. 3600 IN A 10.10.38.46
+biganswer.example. 3600 IN A 10.10.38.47
+biganswer.example. 3600 IN A 10.10.38.48
+biganswer.example. 3600 IN A 10.10.38.49
+biganswer.example. 3600 IN A 10.10.38.50
+biganswer.example. 3600 IN A 10.10.39.1
+biganswer.example. 3600 IN A 10.10.39.2
+biganswer.example. 3600 IN A 10.10.39.3
+biganswer.example. 3600 IN A 10.10.39.4
+biganswer.example. 3600 IN A 10.10.39.5
+biganswer.example. 3600 IN A 10.10.39.6
+biganswer.example. 3600 IN A 10.10.39.7
+biganswer.example. 3600 IN A 10.10.39.8
+biganswer.example. 3600 IN A 10.10.39.9
+biganswer.example. 3600 IN A 10.10.39.10
+biganswer.example. 3600 IN A 10.10.39.11
+biganswer.example. 3600 IN A 10.10.39.12
+biganswer.example. 3600 IN A 10.10.39.13
+biganswer.example. 3600 IN A 10.10.39.14
+biganswer.example. 3600 IN A 10.10.39.15
+biganswer.example. 3600 IN A 10.10.39.16
+biganswer.example. 3600 IN A 10.10.39.17
+biganswer.example. 3600 IN A 10.10.39.18
+biganswer.example. 3600 IN A 10.10.39.19
+biganswer.example. 3600 IN A 10.10.39.20
+biganswer.example. 3600 IN A 10.10.39.21
+biganswer.example. 3600 IN A 10.10.39.22
+biganswer.example. 3600 IN A 10.10.39.23
+biganswer.example. 3600 IN A 10.10.39.24
+biganswer.example. 3600 IN A 10.10.39.25
+biganswer.example. 3600 IN A 10.10.39.26
+biganswer.example. 3600 IN A 10.10.39.27
+biganswer.example. 3600 IN A 10.10.39.28
+biganswer.example. 3600 IN A 10.10.39.29
+biganswer.example. 3600 IN A 10.10.39.30
+biganswer.example. 3600 IN A 10.10.39.31
+biganswer.example. 3600 IN A 10.10.39.32
+biganswer.example. 3600 IN A 10.10.39.33
+biganswer.example. 3600 IN A 10.10.39.34
+biganswer.example. 3600 IN A 10.10.39.35
+biganswer.example. 3600 IN A 10.10.39.36
+biganswer.example. 3600 IN A 10.10.39.37
+biganswer.example. 3600 IN A 10.10.39.38
+biganswer.example. 3600 IN A 10.10.39.39
+biganswer.example. 3600 IN A 10.10.39.40
+biganswer.example. 3600 IN A 10.10.39.41
+biganswer.example. 3600 IN A 10.10.39.42
+biganswer.example. 3600 IN A 10.10.39.43
+biganswer.example. 3600 IN A 10.10.39.44
+biganswer.example. 3600 IN A 10.10.39.45
+biganswer.example. 3600 IN A 10.10.39.46
+biganswer.example. 3600 IN A 10.10.39.47
+biganswer.example. 3600 IN A 10.10.39.48
+biganswer.example. 3600 IN A 10.10.39.49
+biganswer.example. 3600 IN A 10.10.39.50
+biganswer.example. 3600 IN A 10.10.40.1
+biganswer.example. 3600 IN A 10.10.40.2
+biganswer.example. 3600 IN A 10.10.40.3
+biganswer.example. 3600 IN A 10.10.40.4
+biganswer.example. 3600 IN A 10.10.40.5
+biganswer.example. 3600 IN A 10.10.40.6
+biganswer.example. 3600 IN A 10.10.40.7
+biganswer.example. 3600 IN A 10.10.40.8
+biganswer.example. 3600 IN A 10.10.40.9
+biganswer.example. 3600 IN A 10.10.40.10
+biganswer.example. 3600 IN A 10.10.40.11
+biganswer.example. 3600 IN A 10.10.40.12
+biganswer.example. 3600 IN A 10.10.40.13
+biganswer.example. 3600 IN A 10.10.40.14
+biganswer.example. 3600 IN A 10.10.40.15
+biganswer.example. 3600 IN A 10.10.40.16
+biganswer.example. 3600 IN A 10.10.40.17
+biganswer.example. 3600 IN A 10.10.40.18
+biganswer.example. 3600 IN A 10.10.40.19
+biganswer.example. 3600 IN A 10.10.40.20
+biganswer.example. 3600 IN A 10.10.40.21
+biganswer.example. 3600 IN A 10.10.40.22
+biganswer.example. 3600 IN A 10.10.40.23
+biganswer.example. 3600 IN A 10.10.40.24
+biganswer.example. 3600 IN A 10.10.40.25
+biganswer.example. 3600 IN A 10.10.40.26
+biganswer.example. 3600 IN A 10.10.40.27
+biganswer.example. 3600 IN A 10.10.40.28
+biganswer.example. 3600 IN A 10.10.40.29
+biganswer.example. 3600 IN A 10.10.40.30
+biganswer.example. 3600 IN A 10.10.40.31
+biganswer.example. 3600 IN A 10.10.40.32
+biganswer.example. 3600 IN A 10.10.40.33
+biganswer.example. 3600 IN A 10.10.40.34
+biganswer.example. 3600 IN A 10.10.40.35
+biganswer.example. 3600 IN A 10.10.40.36
+biganswer.example. 3600 IN A 10.10.40.37
+biganswer.example. 3600 IN A 10.10.40.38
+biganswer.example. 3600 IN A 10.10.40.39
+biganswer.example. 3600 IN A 10.10.40.40
+biganswer.example. 3600 IN A 10.10.40.41
+biganswer.example. 3600 IN A 10.10.40.42
+biganswer.example. 3600 IN A 10.10.40.43
+biganswer.example. 3600 IN A 10.10.40.44
+biganswer.example. 3600 IN A 10.10.40.45
+biganswer.example. 3600 IN A 10.10.40.46
+biganswer.example. 3600 IN A 10.10.40.47
+biganswer.example. 3600 IN A 10.10.40.48
+biganswer.example. 3600 IN A 10.10.40.49
+biganswer.example. 3600 IN A 10.10.40.50
+biganswer.example. 3600 IN A 10.10.41.1
+biganswer.example. 3600 IN A 10.10.41.2
+biganswer.example. 3600 IN A 10.10.41.3
+biganswer.example. 3600 IN A 10.10.41.4
+biganswer.example. 3600 IN A 10.10.41.5
+biganswer.example. 3600 IN A 10.10.41.6
+biganswer.example. 3600 IN A 10.10.41.7
+biganswer.example. 3600 IN A 10.10.41.8
+biganswer.example. 3600 IN A 10.10.41.9
+biganswer.example. 3600 IN A 10.10.41.10
+biganswer.example. 3600 IN A 10.10.41.11
+biganswer.example. 3600 IN A 10.10.41.12
+biganswer.example. 3600 IN A 10.10.41.13
+biganswer.example. 3600 IN A 10.10.41.14
+biganswer.example. 3600 IN A 10.10.41.15
+biganswer.example. 3600 IN A 10.10.41.16
+biganswer.example. 3600 IN A 10.10.41.17
+biganswer.example. 3600 IN A 10.10.41.18
+biganswer.example. 3600 IN A 10.10.41.19
+biganswer.example. 3600 IN A 10.10.41.20
+biganswer.example. 3600 IN A 10.10.41.21
+biganswer.example. 3600 IN A 10.10.41.22
+biganswer.example. 3600 IN A 10.10.41.23
+biganswer.example. 3600 IN A 10.10.41.24
+biganswer.example. 3600 IN A 10.10.41.25
+biganswer.example. 3600 IN A 10.10.41.26
+biganswer.example. 3600 IN A 10.10.41.27
+biganswer.example. 3600 IN A 10.10.41.28
+biganswer.example. 3600 IN A 10.10.41.29
+biganswer.example. 3600 IN A 10.10.41.30
+biganswer.example. 3600 IN A 10.10.41.31
+biganswer.example. 3600 IN A 10.10.41.32
+biganswer.example. 3600 IN A 10.10.41.33
+biganswer.example. 3600 IN A 10.10.41.34
+biganswer.example. 3600 IN A 10.10.41.35
+biganswer.example. 3600 IN A 10.10.41.36
+biganswer.example. 3600 IN A 10.10.41.37
+biganswer.example. 3600 IN A 10.10.41.38
+biganswer.example. 3600 IN A 10.10.41.39
+biganswer.example. 3600 IN A 10.10.41.40
+biganswer.example. 3600 IN A 10.10.41.41
+biganswer.example. 3600 IN A 10.10.41.42
+biganswer.example. 3600 IN A 10.10.41.43
+biganswer.example. 3600 IN A 10.10.41.44
+biganswer.example. 3600 IN A 10.10.41.45
+biganswer.example. 3600 IN A 10.10.41.46
+biganswer.example. 3600 IN A 10.10.41.47
+biganswer.example. 3600 IN A 10.10.41.48
+biganswer.example. 3600 IN A 10.10.41.49
+biganswer.example. 3600 IN A 10.10.41.50
+biganswer.example. 3600 IN A 10.10.42.1
+biganswer.example. 3600 IN A 10.10.42.2
+biganswer.example. 3600 IN A 10.10.42.3
+biganswer.example. 3600 IN A 10.10.42.4
+biganswer.example. 3600 IN A 10.10.42.5
+biganswer.example. 3600 IN A 10.10.42.6
+biganswer.example. 3600 IN A 10.10.42.7
+biganswer.example. 3600 IN A 10.10.42.8
+biganswer.example. 3600 IN A 10.10.42.9
+biganswer.example. 3600 IN A 10.10.42.10
+biganswer.example. 3600 IN A 10.10.42.11
+biganswer.example. 3600 IN A 10.10.42.12
+biganswer.example. 3600 IN A 10.10.42.13
+biganswer.example. 3600 IN A 10.10.42.14
+biganswer.example. 3600 IN A 10.10.42.15
+biganswer.example. 3600 IN A 10.10.42.16
+biganswer.example. 3600 IN A 10.10.42.17
+biganswer.example. 3600 IN A 10.10.42.18
+biganswer.example. 3600 IN A 10.10.42.19
+biganswer.example. 3600 IN A 10.10.42.20
+biganswer.example. 3600 IN A 10.10.42.21
+biganswer.example. 3600 IN A 10.10.42.22
+biganswer.example. 3600 IN A 10.10.42.23
+biganswer.example. 3600 IN A 10.10.42.24
+biganswer.example. 3600 IN A 10.10.42.25
+biganswer.example. 3600 IN A 10.10.42.26
+biganswer.example. 3600 IN A 10.10.42.27
+biganswer.example. 3600 IN A 10.10.42.28
+biganswer.example. 3600 IN A 10.10.42.29
+biganswer.example. 3600 IN A 10.10.42.30
+biganswer.example. 3600 IN A 10.10.42.31
+biganswer.example. 3600 IN A 10.10.42.32
+biganswer.example. 3600 IN A 10.10.42.33
+biganswer.example. 3600 IN A 10.10.42.34
+biganswer.example. 3600 IN A 10.10.42.35
+biganswer.example. 3600 IN A 10.10.42.36
+biganswer.example. 3600 IN A 10.10.42.37
+biganswer.example. 3600 IN A 10.10.42.38
+biganswer.example. 3600 IN A 10.10.42.39
+biganswer.example. 3600 IN A 10.10.42.40
+biganswer.example. 3600 IN A 10.10.42.41
+biganswer.example. 3600 IN A 10.10.42.42
+biganswer.example. 3600 IN A 10.10.42.43
+biganswer.example. 3600 IN A 10.10.42.44
+biganswer.example. 3600 IN A 10.10.42.45
+biganswer.example. 3600 IN A 10.10.42.46
+biganswer.example. 3600 IN A 10.10.42.47
+biganswer.example. 3600 IN A 10.10.42.48
+biganswer.example. 3600 IN A 10.10.42.49
+biganswer.example. 3600 IN A 10.10.42.50
+biganswer.example. 3600 IN A 10.10.43.1
+biganswer.example. 3600 IN A 10.10.43.2
+biganswer.example. 3600 IN A 10.10.43.3
+biganswer.example. 3600 IN A 10.10.43.4
+biganswer.example. 3600 IN A 10.10.43.5
+biganswer.example. 3600 IN A 10.10.43.6
+biganswer.example. 3600 IN A 10.10.43.7
+biganswer.example. 3600 IN A 10.10.43.8
+biganswer.example. 3600 IN A 10.10.43.9
+biganswer.example. 3600 IN A 10.10.43.10
+biganswer.example. 3600 IN A 10.10.43.11
+biganswer.example. 3600 IN A 10.10.43.12
+biganswer.example. 3600 IN A 10.10.43.13
+biganswer.example. 3600 IN A 10.10.43.14
+biganswer.example. 3600 IN A 10.10.43.15
+biganswer.example. 3600 IN A 10.10.43.16
+biganswer.example. 3600 IN A 10.10.43.17
+biganswer.example. 3600 IN A 10.10.43.18
+biganswer.example. 3600 IN A 10.10.43.19
+biganswer.example. 3600 IN A 10.10.43.20
+biganswer.example. 3600 IN A 10.10.43.21
+biganswer.example. 3600 IN A 10.10.43.22
+biganswer.example. 3600 IN A 10.10.43.23
+biganswer.example. 3600 IN A 10.10.43.24
+biganswer.example. 3600 IN A 10.10.43.25
+biganswer.example. 3600 IN A 10.10.43.26
+biganswer.example. 3600 IN A 10.10.43.27
+biganswer.example. 3600 IN A 10.10.43.28
+biganswer.example. 3600 IN A 10.10.43.29
+biganswer.example. 3600 IN A 10.10.43.30
+biganswer.example. 3600 IN A 10.10.43.31
+biganswer.example. 3600 IN A 10.10.43.32
+biganswer.example. 3600 IN A 10.10.43.33
+biganswer.example. 3600 IN A 10.10.43.34
+biganswer.example. 3600 IN A 10.10.43.35
+biganswer.example. 3600 IN A 10.10.43.36
+biganswer.example. 3600 IN A 10.10.43.37
+biganswer.example. 3600 IN A 10.10.43.38
+biganswer.example. 3600 IN A 10.10.43.39
+biganswer.example. 3600 IN A 10.10.43.40
+biganswer.example. 3600 IN A 10.10.43.41
+biganswer.example. 3600 IN A 10.10.43.42
+biganswer.example. 3600 IN A 10.10.43.43
+biganswer.example. 3600 IN A 10.10.43.44
+biganswer.example. 3600 IN A 10.10.43.45
+biganswer.example. 3600 IN A 10.10.43.46
+biganswer.example. 3600 IN A 10.10.43.47
+biganswer.example. 3600 IN A 10.10.43.48
+biganswer.example. 3600 IN A 10.10.43.49
+biganswer.example. 3600 IN A 10.10.43.50
+biganswer.example. 3600 IN A 10.10.44.1
+biganswer.example. 3600 IN A 10.10.44.2
+biganswer.example. 3600 IN A 10.10.44.3
+biganswer.example. 3600 IN A 10.10.44.4
+biganswer.example. 3600 IN A 10.10.44.5
+biganswer.example. 3600 IN A 10.10.44.6
+biganswer.example. 3600 IN A 10.10.44.7
+biganswer.example. 3600 IN A 10.10.44.8
+biganswer.example. 3600 IN A 10.10.44.9
+biganswer.example. 3600 IN A 10.10.44.10
+biganswer.example. 3600 IN A 10.10.44.11
+biganswer.example. 3600 IN A 10.10.44.12
+biganswer.example. 3600 IN A 10.10.44.13
+biganswer.example. 3600 IN A 10.10.44.14
+biganswer.example. 3600 IN A 10.10.44.15
+biganswer.example. 3600 IN A 10.10.44.16
+biganswer.example. 3600 IN A 10.10.44.17
+biganswer.example. 3600 IN A 10.10.44.18
+biganswer.example. 3600 IN A 10.10.44.19
+biganswer.example. 3600 IN A 10.10.44.20
+biganswer.example. 3600 IN A 10.10.44.21
+biganswer.example. 3600 IN A 10.10.44.22
+biganswer.example. 3600 IN A 10.10.44.23
+biganswer.example. 3600 IN A 10.10.44.24
+biganswer.example. 3600 IN A 10.10.44.25
+biganswer.example. 3600 IN A 10.10.44.26
+biganswer.example. 3600 IN A 10.10.44.27
+biganswer.example. 3600 IN A 10.10.44.28
+biganswer.example. 3600 IN A 10.10.44.29
+biganswer.example. 3600 IN A 10.10.44.30
+biganswer.example. 3600 IN A 10.10.44.31
+biganswer.example. 3600 IN A 10.10.44.32
+biganswer.example. 3600 IN A 10.10.44.33
+biganswer.example. 3600 IN A 10.10.44.34
+biganswer.example. 3600 IN A 10.10.44.35
+biganswer.example. 3600 IN A 10.10.44.36
+biganswer.example. 3600 IN A 10.10.44.37
+biganswer.example. 3600 IN A 10.10.44.38
+biganswer.example. 3600 IN A 10.10.44.39
+biganswer.example. 3600 IN A 10.10.44.40
+biganswer.example. 3600 IN A 10.10.44.41
+biganswer.example. 3600 IN A 10.10.44.42
+biganswer.example. 3600 IN A 10.10.44.43
+biganswer.example. 3600 IN A 10.10.44.44
+biganswer.example. 3600 IN A 10.10.44.45
+biganswer.example. 3600 IN A 10.10.44.46
+biganswer.example. 3600 IN A 10.10.44.47
+biganswer.example. 3600 IN A 10.10.44.48
+biganswer.example. 3600 IN A 10.10.44.49
+biganswer.example. 3600 IN A 10.10.44.50
+biganswer.example. 3600 IN A 10.10.45.1
+biganswer.example. 3600 IN A 10.10.45.2
+biganswer.example. 3600 IN A 10.10.45.3
+biganswer.example. 3600 IN A 10.10.45.4
+biganswer.example. 3600 IN A 10.10.45.5
+biganswer.example. 3600 IN A 10.10.45.6
+biganswer.example. 3600 IN A 10.10.45.7
+biganswer.example. 3600 IN A 10.10.45.8
+biganswer.example. 3600 IN A 10.10.45.9
+biganswer.example. 3600 IN A 10.10.45.10
+biganswer.example. 3600 IN A 10.10.45.11
+biganswer.example. 3600 IN A 10.10.45.12
+biganswer.example. 3600 IN A 10.10.45.13
+biganswer.example. 3600 IN A 10.10.45.14
+biganswer.example. 3600 IN A 10.10.45.15
+biganswer.example. 3600 IN A 10.10.45.16
+biganswer.example. 3600 IN A 10.10.45.17
+biganswer.example. 3600 IN A 10.10.45.18
+biganswer.example. 3600 IN A 10.10.45.19
+biganswer.example. 3600 IN A 10.10.45.20
+biganswer.example. 3600 IN A 10.10.45.21
+biganswer.example. 3600 IN A 10.10.45.22
+biganswer.example. 3600 IN A 10.10.45.23
+biganswer.example. 3600 IN A 10.10.45.24
+biganswer.example. 3600 IN A 10.10.45.25
+biganswer.example. 3600 IN A 10.10.45.26
+biganswer.example. 3600 IN A 10.10.45.27
+biganswer.example. 3600 IN A 10.10.45.28
+biganswer.example. 3600 IN A 10.10.45.29
+biganswer.example. 3600 IN A 10.10.45.30
+biganswer.example. 3600 IN A 10.10.45.31
+biganswer.example. 3600 IN A 10.10.45.32
+biganswer.example. 3600 IN A 10.10.45.33
+biganswer.example. 3600 IN A 10.10.45.34
+biganswer.example. 3600 IN A 10.10.45.35
+biganswer.example. 3600 IN A 10.10.45.36
+biganswer.example. 3600 IN A 10.10.45.37
+biganswer.example. 3600 IN A 10.10.45.38
+biganswer.example. 3600 IN A 10.10.45.39
+biganswer.example. 3600 IN A 10.10.45.40
+biganswer.example. 3600 IN A 10.10.45.41
+biganswer.example. 3600 IN A 10.10.45.42
+biganswer.example. 3600 IN A 10.10.45.43
+biganswer.example. 3600 IN A 10.10.45.44
+biganswer.example. 3600 IN A 10.10.45.45
+biganswer.example. 3600 IN A 10.10.45.46
+biganswer.example. 3600 IN A 10.10.45.47
+biganswer.example. 3600 IN A 10.10.45.48
+biganswer.example. 3600 IN A 10.10.45.49
+biganswer.example. 3600 IN A 10.10.45.50
+biganswer.example. 3600 IN A 10.10.46.1
+biganswer.example. 3600 IN A 10.10.46.2
+biganswer.example. 3600 IN A 10.10.46.3
+biganswer.example. 3600 IN A 10.10.46.4
+biganswer.example. 3600 IN A 10.10.46.5
+biganswer.example. 3600 IN A 10.10.46.6
+biganswer.example. 3600 IN A 10.10.46.7
+biganswer.example. 3600 IN A 10.10.46.8
+biganswer.example. 3600 IN A 10.10.46.9
+biganswer.example. 3600 IN A 10.10.46.10
+biganswer.example. 3600 IN A 10.10.46.11
+biganswer.example. 3600 IN A 10.10.46.12
+biganswer.example. 3600 IN A 10.10.46.13
+biganswer.example. 3600 IN A 10.10.46.14
+biganswer.example. 3600 IN A 10.10.46.15
+biganswer.example. 3600 IN A 10.10.46.16
+biganswer.example. 3600 IN A 10.10.46.17
+biganswer.example. 3600 IN A 10.10.46.18
+biganswer.example. 3600 IN A 10.10.46.19
+biganswer.example. 3600 IN A 10.10.46.20
+biganswer.example. 3600 IN A 10.10.46.21
+biganswer.example. 3600 IN A 10.10.46.22
+biganswer.example. 3600 IN A 10.10.46.23
+biganswer.example. 3600 IN A 10.10.46.24
+biganswer.example. 3600 IN A 10.10.46.25
+biganswer.example. 3600 IN A 10.10.46.26
+biganswer.example. 3600 IN A 10.10.46.27
+biganswer.example. 3600 IN A 10.10.46.28
+biganswer.example. 3600 IN A 10.10.46.29
+biganswer.example. 3600 IN A 10.10.46.30
+biganswer.example. 3600 IN A 10.10.46.31
+biganswer.example. 3600 IN A 10.10.46.32
+biganswer.example. 3600 IN A 10.10.46.33
+biganswer.example. 3600 IN A 10.10.46.34
+biganswer.example. 3600 IN A 10.10.46.35
+biganswer.example. 3600 IN A 10.10.46.36
+biganswer.example. 3600 IN A 10.10.46.37
+biganswer.example. 3600 IN A 10.10.46.38
+biganswer.example. 3600 IN A 10.10.46.39
+biganswer.example. 3600 IN A 10.10.46.40
+biganswer.example. 3600 IN A 10.10.46.41
+biganswer.example. 3600 IN A 10.10.46.42
+biganswer.example. 3600 IN A 10.10.46.43
+biganswer.example. 3600 IN A 10.10.46.44
+biganswer.example. 3600 IN A 10.10.46.45
+biganswer.example. 3600 IN A 10.10.46.46
+biganswer.example. 3600 IN A 10.10.46.47
+biganswer.example. 3600 IN A 10.10.46.48
+biganswer.example. 3600 IN A 10.10.46.49
+biganswer.example. 3600 IN A 10.10.46.50
+biganswer.example. 3600 IN A 10.10.47.1
+biganswer.example. 3600 IN A 10.10.47.2
+biganswer.example. 3600 IN A 10.10.47.3
+biganswer.example. 3600 IN A 10.10.47.4
+biganswer.example. 3600 IN A 10.10.47.5
+biganswer.example. 3600 IN A 10.10.47.6
+biganswer.example. 3600 IN A 10.10.47.7
+biganswer.example. 3600 IN A 10.10.47.8
+biganswer.example. 3600 IN A 10.10.47.9
+biganswer.example. 3600 IN A 10.10.47.10
+biganswer.example. 3600 IN A 10.10.47.11
+biganswer.example. 3600 IN A 10.10.47.12
+biganswer.example. 3600 IN A 10.10.47.13
+biganswer.example. 3600 IN A 10.10.47.14
+biganswer.example. 3600 IN A 10.10.47.15
+biganswer.example. 3600 IN A 10.10.47.16
+biganswer.example. 3600 IN A 10.10.47.17
+biganswer.example. 3600 IN A 10.10.47.18
+biganswer.example. 3600 IN A 10.10.47.19
+biganswer.example. 3600 IN A 10.10.47.20
+biganswer.example. 3600 IN A 10.10.47.21
+biganswer.example. 3600 IN A 10.10.47.22
+biganswer.example. 3600 IN A 10.10.47.23
+biganswer.example. 3600 IN A 10.10.47.24
+biganswer.example. 3600 IN A 10.10.47.25
+biganswer.example. 3600 IN A 10.10.47.26
+biganswer.example. 3600 IN A 10.10.47.27
+biganswer.example. 3600 IN A 10.10.47.28
+biganswer.example. 3600 IN A 10.10.47.29
+biganswer.example. 3600 IN A 10.10.47.30
+biganswer.example. 3600 IN A 10.10.47.31
+biganswer.example. 3600 IN A 10.10.47.32
+biganswer.example. 3600 IN A 10.10.47.33
+biganswer.example. 3600 IN A 10.10.47.34
+biganswer.example. 3600 IN A 10.10.47.35
+biganswer.example. 3600 IN A 10.10.47.36
+biganswer.example. 3600 IN A 10.10.47.37
+biganswer.example. 3600 IN A 10.10.47.38
+biganswer.example. 3600 IN A 10.10.47.39
+biganswer.example. 3600 IN A 10.10.47.40
+biganswer.example. 3600 IN A 10.10.47.41
+biganswer.example. 3600 IN A 10.10.47.42
+biganswer.example. 3600 IN A 10.10.47.43
+biganswer.example. 3600 IN A 10.10.47.44
+biganswer.example. 3600 IN A 10.10.47.45
+biganswer.example. 3600 IN A 10.10.47.46
+biganswer.example. 3600 IN A 10.10.47.47
+biganswer.example. 3600 IN A 10.10.47.48
+biganswer.example. 3600 IN A 10.10.47.49
+biganswer.example. 3600 IN A 10.10.47.50
+biganswer.example. 3600 IN A 10.10.48.1
+biganswer.example. 3600 IN A 10.10.48.2
+biganswer.example. 3600 IN A 10.10.48.3
+biganswer.example. 3600 IN A 10.10.48.4
+biganswer.example. 3600 IN A 10.10.48.5
+biganswer.example. 3600 IN A 10.10.48.6
+biganswer.example. 3600 IN A 10.10.48.7
+biganswer.example. 3600 IN A 10.10.48.8
+biganswer.example. 3600 IN A 10.10.48.9
+biganswer.example. 3600 IN A 10.10.48.10
+biganswer.example. 3600 IN A 10.10.48.11
+biganswer.example. 3600 IN A 10.10.48.12
+biganswer.example. 3600 IN A 10.10.48.13
+biganswer.example. 3600 IN A 10.10.48.14
+biganswer.example. 3600 IN A 10.10.48.15
+biganswer.example. 3600 IN A 10.10.48.16
+biganswer.example. 3600 IN A 10.10.48.17
+biganswer.example. 3600 IN A 10.10.48.18
+biganswer.example. 3600 IN A 10.10.48.19
+biganswer.example. 3600 IN A 10.10.48.20
+biganswer.example. 3600 IN A 10.10.48.21
+biganswer.example. 3600 IN A 10.10.48.22
+biganswer.example. 3600 IN A 10.10.48.23
+biganswer.example. 3600 IN A 10.10.48.24
+biganswer.example. 3600 IN A 10.10.48.25
+biganswer.example. 3600 IN A 10.10.48.26
+biganswer.example. 3600 IN A 10.10.48.27
+biganswer.example. 3600 IN A 10.10.48.28
+biganswer.example. 3600 IN A 10.10.48.29
+biganswer.example. 3600 IN A 10.10.48.30
+biganswer.example. 3600 IN A 10.10.48.31
+biganswer.example. 3600 IN A 10.10.48.32
+biganswer.example. 3600 IN A 10.10.48.33
+biganswer.example. 3600 IN A 10.10.48.34
+biganswer.example. 3600 IN A 10.10.48.35
+biganswer.example. 3600 IN A 10.10.48.36
+biganswer.example. 3600 IN A 10.10.48.37
+biganswer.example. 3600 IN A 10.10.48.38
+biganswer.example. 3600 IN A 10.10.48.39
+biganswer.example. 3600 IN A 10.10.48.40
+biganswer.example. 3600 IN A 10.10.48.41
+biganswer.example. 3600 IN A 10.10.48.42
+biganswer.example. 3600 IN A 10.10.48.43
+biganswer.example. 3600 IN A 10.10.48.44
+biganswer.example. 3600 IN A 10.10.48.45
+biganswer.example. 3600 IN A 10.10.48.46
+biganswer.example. 3600 IN A 10.10.48.47
+biganswer.example. 3600 IN A 10.10.48.48
+biganswer.example. 3600 IN A 10.10.48.49
+biganswer.example. 3600 IN A 10.10.48.50
+biganswer.example. 3600 IN A 10.10.49.1
+biganswer.example. 3600 IN A 10.10.49.2
+biganswer.example. 3600 IN A 10.10.49.3
+biganswer.example. 3600 IN A 10.10.49.4
+biganswer.example. 3600 IN A 10.10.49.5
+biganswer.example. 3600 IN A 10.10.49.6
+biganswer.example. 3600 IN A 10.10.49.7
+biganswer.example. 3600 IN A 10.10.49.8
+biganswer.example. 3600 IN A 10.10.49.9
+biganswer.example. 3600 IN A 10.10.49.10
+biganswer.example. 3600 IN A 10.10.49.11
+biganswer.example. 3600 IN A 10.10.49.12
+biganswer.example. 3600 IN A 10.10.49.13
+biganswer.example. 3600 IN A 10.10.49.14
+biganswer.example. 3600 IN A 10.10.49.15
+biganswer.example. 3600 IN A 10.10.49.16
+biganswer.example. 3600 IN A 10.10.49.17
+biganswer.example. 3600 IN A 10.10.49.18
+biganswer.example. 3600 IN A 10.10.49.19
+biganswer.example. 3600 IN A 10.10.49.20
+biganswer.example. 3600 IN A 10.10.49.21
+biganswer.example. 3600 IN A 10.10.49.22
+biganswer.example. 3600 IN A 10.10.49.23
+biganswer.example. 3600 IN A 10.10.49.24
+biganswer.example. 3600 IN A 10.10.49.25
+biganswer.example. 3600 IN A 10.10.49.26
+biganswer.example. 3600 IN A 10.10.49.27
+biganswer.example. 3600 IN A 10.10.49.28
+biganswer.example. 3600 IN A 10.10.49.29
+biganswer.example. 3600 IN A 10.10.49.30
+biganswer.example. 3600 IN A 10.10.49.31
+biganswer.example. 3600 IN A 10.10.49.32
+biganswer.example. 3600 IN A 10.10.49.33
+biganswer.example. 3600 IN A 10.10.49.34
+biganswer.example. 3600 IN A 10.10.49.35
+biganswer.example. 3600 IN A 10.10.49.36
+biganswer.example. 3600 IN A 10.10.49.37
+biganswer.example. 3600 IN A 10.10.49.38
+biganswer.example. 3600 IN A 10.10.49.39
+biganswer.example. 3600 IN A 10.10.49.40
+biganswer.example. 3600 IN A 10.10.49.41
+biganswer.example. 3600 IN A 10.10.49.42
+biganswer.example. 3600 IN A 10.10.49.43
+biganswer.example. 3600 IN A 10.10.49.44
+biganswer.example. 3600 IN A 10.10.49.45
+biganswer.example. 3600 IN A 10.10.49.46
+biganswer.example. 3600 IN A 10.10.49.47
+biganswer.example. 3600 IN A 10.10.49.48
+biganswer.example. 3600 IN A 10.10.49.49
+biganswer.example. 3600 IN A 10.10.49.50
+biganswer.example. 3600 IN A 10.10.50.1
+biganswer.example. 3600 IN A 10.10.50.2
+biganswer.example. 3600 IN A 10.10.50.3
+biganswer.example. 3600 IN A 10.10.50.4
+biganswer.example. 3600 IN A 10.10.50.5
+biganswer.example. 3600 IN A 10.10.50.6
+biganswer.example. 3600 IN A 10.10.50.7
+biganswer.example. 3600 IN A 10.10.50.8
+biganswer.example. 3600 IN A 10.10.50.9
+biganswer.example. 3600 IN A 10.10.50.10
+biganswer.example. 3600 IN A 10.10.50.11
+biganswer.example. 3600 IN A 10.10.50.12
+biganswer.example. 3600 IN A 10.10.50.13
+biganswer.example. 3600 IN A 10.10.50.14
+biganswer.example. 3600 IN A 10.10.50.15
+biganswer.example. 3600 IN A 10.10.50.16
+biganswer.example. 3600 IN A 10.10.50.17
+biganswer.example. 3600 IN A 10.10.50.18
+biganswer.example. 3600 IN A 10.10.50.19
+biganswer.example. 3600 IN A 10.10.50.20
+biganswer.example. 3600 IN A 10.10.50.21
+biganswer.example. 3600 IN A 10.10.50.22
+biganswer.example. 3600 IN A 10.10.50.23
+biganswer.example. 3600 IN A 10.10.50.24
+biganswer.example. 3600 IN A 10.10.50.25
+biganswer.example. 3600 IN A 10.10.50.26
+biganswer.example. 3600 IN A 10.10.50.27
+biganswer.example. 3600 IN A 10.10.50.28
+biganswer.example. 3600 IN A 10.10.50.29
+biganswer.example. 3600 IN A 10.10.50.30
+biganswer.example. 3600 IN A 10.10.50.31
+biganswer.example. 3600 IN A 10.10.50.32
+biganswer.example. 3600 IN A 10.10.50.33
+biganswer.example. 3600 IN A 10.10.50.34
+biganswer.example. 3600 IN A 10.10.50.35
+biganswer.example. 3600 IN A 10.10.50.36
+biganswer.example. 3600 IN A 10.10.50.37
+biganswer.example. 3600 IN A 10.10.50.38
+biganswer.example. 3600 IN A 10.10.50.39
+biganswer.example. 3600 IN A 10.10.50.40
+biganswer.example. 3600 IN A 10.10.50.41
+biganswer.example. 3600 IN A 10.10.50.42
+biganswer.example. 3600 IN A 10.10.50.43
+biganswer.example. 3600 IN A 10.10.50.44
+biganswer.example. 3600 IN A 10.10.50.45
+biganswer.example. 3600 IN A 10.10.50.46
+biganswer.example. 3600 IN A 10.10.50.47
+biganswer.example. 3600 IN A 10.10.50.48
+biganswer.example. 3600 IN A 10.10.50.49
+biganswer.example. 3600 IN A 10.10.50.50
+caa01.example. 3600 IN CAA 0 issue "ca.example.net; policy=ev"
+caa02.example. 3600 IN CAA 128 tbs "Unknown"
+caa03.example. 3600 IN CAA 128 tbs ""
+cdnskey01.example. 3600 IN CDNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+cds01.example. 3600 IN CDS 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+cert01.example. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+cname01.example. 3600 IN CNAME cname-target.
+cname02.example. 3600 IN CNAME cname-target.example.
+cname03.example. 3600 IN CNAME .
+csync01.example. 3600 IN CSYNC 0 0 A NS AAAA
+csync02.example. 3600 IN CSYNC 0 0
+dhcid01.example. 3600 IN DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA=
+dhcid02.example. 3600 IN DHCID AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQdWL3b/NaiUDlW2No=
+dhcid03.example. 3600 IN DHCID AAABxLmlskllE0MVjd57zHcWmEH3pCQ6VytcKD//7es/deY=
+dlv.example. 3600 IN DLV 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+dname01.example. 3600 IN DNAME dname-target.
+dname02.example. 3600 IN DNAME dname-target.example.
+dname03.example. 3600 IN DNAME .
+dnskey01.example. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+doa01.example. 3600 IN DOA 1234567890 1234567890 1 "image/gif" R0lGODlhKAAZAOMCAGZmZgBmmf///zOZzMz//5nM/zNmmWbM/5nMzMzMzACZ/////////////////////yH5BAEKAA8ALAAAAAAoABkAAATH8IFJK5U2a4337F5ogRkpnoCJrly7PrCKyh8c3HgAhzT35MDbbtO7/IJIHbGiOiaTxVTpSVWWLqNq1UVyapNS1wd3OAxug0LhnCubcVhsxysQnOt4ATpvvzHlFzl1AwODhWeFAgRpen5/UhheAYMFdUB4SFcpGEGGdQeCAqBBLTuSk30EeXd9pEsAbKGxjHqDSE0Sp6ixN4N1BJmbc7lIhmsBich1awPAjkY1SZR8bJWrz382SGqIBQQFQd4IsUTaX+ceuudPEQA7
+doa02.example. 3600 IN DOA 0 1 2 "" aHR0cHM6Ly93d3cuaXNjLm9yZy8=
+ds01.example. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13
+ds01.example. 3600 IN NS ns42.example.
+ds02.example. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390
+ds02.example. 3600 IN NS ns43.example.
+eid01.example. 3600 IN EID 1289AB
+eui48.example. 3600 IN EUI48 01-23-45-67-89-ab
+eui64.example. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef
+gid01.example. 3600 IN GID \# 1 03
+gpos01.example. 3600 IN GPOS "-22.6882" "116.8652" "250.0"
+gpos02.example. 3600 IN GPOS "" "" ""
+hinfo01.example. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02.example. 3600 IN HINFO "PC" "NetBSD"
+hip1.example. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
+hip2.example. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com.
+https0.example. 3600 IN HTTPS 0 example.net.
+https1.example. 3600 IN HTTPS 1 . port=60
+ipseckey01.example. 3600 IN IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey02.example. 3600 IN IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey03.example. 3600 IN IPSECKEY 10 1 2 192.0.2.3 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey04.example. 3600 IN IPSECKEY 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey05.example. 3600 IN IPSECKEY 10 2 2 2001:db8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+isdn01.example. 3600 IN ISDN "isdn-address"
+isdn02.example. 3600 IN ISDN "isdn-address" "subaddress"
+isdn03.example. 3600 IN ISDN "isdn-address"
+isdn04.example. 3600 IN ISDN "isdn-address" "subaddress"
+keydata.example. 3600 IN TYPE65533 \# 0
+keydata.example. 3600 IN TYPE65533 \# 6 010203040506
+keydata.example. 3600 IN TYPE65533 \# 18 010203040506010203040506010203040506
+kx01.example. 3600 IN KX 10 kdc.example.
+kx02.example. 3600 IN KX 10 .
+l32.example. 3600 IN L32 10 1.2.3.4
+l64.example. 3600 IN L64 10 14:4fff:ff20:ee64
+loc01.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+lp.example. 3600 IN LP 10 example.net.
+mb01.example. 3600 IN MG madname.example.
+mb02.example. 3600 IN MG .
+mg01.example. 3600 IN MG mgmname.example.
+mg02.example. 3600 IN MG .
+minfo01.example. 3600 IN MINFO rmailbx.example. emailbx.example.
+minfo02.example. 3600 IN MINFO . .
+mr01.example. 3600 IN MR mrname.example.
+mr02.example. 3600 IN MR .
+mx01.example. 3600 IN MX 10 mail.example.
+mx02.example. 3600 IN MX 10 .
+naptr01.example. 3600 IN NAPTR 0 0 "" "" "" .
+naptr02.example. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+nid.example. 3600 IN NID 10 14:4fff:ff20:ee64
+nimloc01.example. 3600 IN NIMLOC 1289AB
+ninfo01.example. 3600 IN NINFO "foo"
+ninfo02.example. 3600 IN NINFO "foo" "bar"
+ninfo03.example. 3600 IN NINFO "foo"
+ninfo04.example. 3600 IN NINFO "foo" "bar"
+ninfo05.example. 3600 IN NINFO "foo bar"
+ninfo06.example. 3600 IN NINFO "foo bar"
+ninfo07.example. 3600 IN NINFO "foo bar"
+ninfo08.example. 3600 IN NINFO "foo\010bar"
+ninfo09.example. 3600 IN NINFO "foo\010bar"
+ninfo10.example. 3600 IN NINFO "foo bar"
+ninfo11.example. 3600 IN NINFO "\"foo\""
+ninfo12.example. 3600 IN NINFO "\"foo\""
+ninfo13.example. 3600 IN NINFO "foo;"
+ninfo14.example. 3600 IN NINFO "foo;"
+ninfo15.example. 3600 IN NINFO "bar\\;"
+ns2.example. 3600 IN A 10.53.0.2
+nsap-ptr01.example. 3600 IN NSAP-PTR foo.
+nsap-ptr01.example. 3600 IN NSAP-PTR .
+nsap01.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsec01.example. 3600 IN NSEC a.secure.nil. NS SOA MX LOC RRSIG NSEC DNSKEY
+nsec02.example. 3600 IN NSEC . NSAP-PTR NSEC
+nsec03.example. 3600 IN NSEC . A
+nsec04.example. 3600 IN NSEC . TYPE127
+openpgpkey.example. 3600 IN OPENPGPKEY AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+ptr01.example. 3600 IN PTR example.
+px01.example. 3600 IN PX 65535 foo. bar.
+px02.example. 3600 IN PX 65535 . .
+rkey01.example. 3600 IN RKEY 0 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+rp01.example. 3600 IN RP mbox-dname.example. txt-dname.example.
+rp02.example. 3600 IN RP . .
+rrsig01.example. 3600 IN RRSIG NSEC 1 3 3600 20000102030405 19961211100908 2143 foo.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+rt01.example. 3600 IN RT 0 intermediate-host.example.
+rt02.example. 3600 IN RT 65535 .
+sink01.example. 3600 IN SINK 1 0 0
+sink02.example. 3600 IN SINK 8 0 2 l4ik
+smimea.example. 3600 IN SMIMEA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC
+spf01.example. 3600 IN SPF "v=spf1 -all"
+spf02.example. 3600 IN SPF "v=spf1" " -all"
+srv01.example. 3600 IN SRV 0 0 0 .
+srv02.example. 3600 IN SRV 65535 65535 65535 old-slow-box.example.
+sshfp01.example. 3600 IN SSHFP 4 2 C76D8329954DA2835751E371544E963EFDA099080D6C58DD2BFD9A31 6E162C83
+sshfp02.example. 3600 IN SSHFP 1 2 BF29468C83AC58CCF8C85AB7B3BEB054ECF1E38512B8353AB36471FA 88961DCC
+svcb0.example. 3600 IN SVCB 0 example.net.
+svcb1.example. 3600 IN SVCB 1 . port=60
+ta.example. 3600 IN TA 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+talink0.example. 3600 IN TALINK . talink1.example.
+talink1.example. 3600 IN TALINK talink0.example. talink2.example.
+talink2.example. 3600 IN TALINK talink2.example. .
+tlsa.example. 3600 IN TLSA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC
+txt01.example. 3600 IN TXT "foo"
+txt02.example. 3600 IN TXT "foo" "bar"
+txt03.example. 3600 IN TXT "foo"
+txt04.example. 3600 IN TXT "foo" "bar"
+txt05.example. 3600 IN TXT "foo bar"
+txt06.example. 3600 IN TXT "foo bar"
+txt07.example. 3600 IN TXT "foo bar"
+txt08.example. 3600 IN TXT "foo\010bar"
+txt09.example. 3600 IN TXT "foo\010bar"
+txt10.example. 3600 IN TXT "foo bar"
+txt11.example. 3600 IN TXT "\"foo\""
+txt12.example. 3600 IN TXT "\"foo\""
+txt13.example. 3600 IN TXT "foo;"
+txt14.example. 3600 IN TXT "foo;"
+txt15.example. 3600 IN TXT "bar\\;"
+uid01.example. 3600 IN UID \# 1 02
+uinfo01.example. 3600 IN UINFO \# 1 01
+unspec01.example. 3600 IN UNSPEC \# 1 04
+uri01.example. 3600 IN URI 10 20 "https://www.isc.org/"
+uri02.example. 3600 IN URI 30 40 "https://www.isc.org/HolyCowThisSureIsAVeryLongURIRecordIDontEvenKnowWhatSomeoneWouldEverWantWithSuchAThingButTheSpecificationRequiresThatWesupportItSoHereWeGoTestingItLaLaLaLaLaLaLaSeriouslyThoughWhyWouldYouEvenConsiderUsingAURIThisLongItSeemsLikeASillyIdeaButEnhWhatAreYouGonnaDo/"
+uri03.example. 3600 IN URI 30 40 ""
+wks01.example. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23
+wks02.example. 3600 IN WKS 10.0.0.1 17 0 1 2 53
+wks03.example. 3600 IN WKS 10.0.0.2 6 65535
+x2501.example. 3600 IN X25 "123456789"
+zonemd01.example. 3600 IN ZONEMD 2019020700 1 1 C220B8A6ED5728A971902F7E3D4FD93ADEEA88B0453C2E8E8C863D46 5AB06CF34EB95B266398C98B59124FA239CB7EEB
+zonemd02.example. 3600 IN ZONEMD 2019020700 1 2 08CFA1115C7B948C4163A901270395EA226A930CD2CBCF2FA9A5E6EB 85F37C8A4E114D884E66F176EAB121CB02DB7D652E0CC4827E7A3204 F166B47E5613FD27
+8f1tmio9avcom2k0frp92lgcumak0cad.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C 8FPNS2UCT7FBS643THP2B77PEQ77K6IU A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
+kcd3juae64f9c5csl1kif1htaui7un0g.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C KD5MN2M20340DGO0BL7NTSB8JP4BSC7E
+mr5ukvsk1l37btu4q7b1dfevft4hkqdk.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C MT38J6VG7S0SN5G17MCUF6IQIKFUAJ05 A AAAA RRSIG
+example. 86400 IN SOA ns2.example. hostmaster.example. 1397051952 5 5 1814400 3600
diff --git a/bin/tests/system/doth/example8.axfr.good b/bin/tests/system/doth/example8.axfr.good
new file mode 100644
index 0000000..3eb511c
--- /dev/null
+++ b/bin/tests/system/doth/example8.axfr.good
@@ -0,0 +1,2676 @@
+example8. 86400 IN SOA ns2.example8. hostmaster.example8. 1397051952 5 5 1814400 3600
+example8. 3600 IN NS ns2.example8.
+a01.example8. 3600 IN A 0.0.0.0
+a02.example8. 3600 IN A 255.255.255.255
+a601.example8. 3600 IN A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+a601.example8. 3600 IN A6 64 ::ffff:ffff:ffff:ffff foo.
+a601.example8. 3600 IN A6 127 ::1 foo.
+a601.example8. 3600 IN A6 128 .
+aaaa01.example8. 3600 IN AAAA ::1
+aaaa02.example8. 3600 IN AAAA fd92:7065:b8e:ffff::5
+afsdb01.example8. 3600 IN AFSDB 0 hostname.example8.
+afsdb02.example8. 3600 IN AFSDB 65535 .
+amtrelay01.example8. 3600 IN AMTRELAY 0 0 0
+amtrelay02.example8. 3600 IN AMTRELAY 0 1 0
+amtrelay03.example8. 3600 IN AMTRELAY 0 0 1 0.0.0.0
+amtrelay04.example8. 3600 IN AMTRELAY 0 0 2 ::
+amtrelay05.example8. 3600 IN AMTRELAY 0 0 3 example.net.
+amtrelay06.example8. 3600 IN AMTRELAY \# 2 0004
+apl01.example8. 3600 IN APL !1:10.0.0.1/32 1:10.0.0.0/24
+apl02.example8. 3600 IN APL
+atma01.example8. 3600 IN ATMA +61200000000
+atma02.example8. 3600 IN ATMA +61200000000
+atma03.example8. 3600 IN ATMA 1234567890abcdef
+atma04.example8. 3600 IN ATMA fedcba0987654321
+avc.example8. 3600 IN AVC "foo:bar"
+biganswer.example8. 3600 IN A 10.10.1.1
+biganswer.example8. 3600 IN A 10.10.1.2
+biganswer.example8. 3600 IN A 10.10.1.3
+biganswer.example8. 3600 IN A 10.10.1.4
+biganswer.example8. 3600 IN A 10.10.1.5
+biganswer.example8. 3600 IN A 10.10.1.6
+biganswer.example8. 3600 IN A 10.10.1.7
+biganswer.example8. 3600 IN A 10.10.1.8
+biganswer.example8. 3600 IN A 10.10.1.9
+biganswer.example8. 3600 IN A 10.10.1.10
+biganswer.example8. 3600 IN A 10.10.1.11
+biganswer.example8. 3600 IN A 10.10.1.12
+biganswer.example8. 3600 IN A 10.10.1.13
+biganswer.example8. 3600 IN A 10.10.1.14
+biganswer.example8. 3600 IN A 10.10.1.15
+biganswer.example8. 3600 IN A 10.10.1.16
+biganswer.example8. 3600 IN A 10.10.1.17
+biganswer.example8. 3600 IN A 10.10.1.18
+biganswer.example8. 3600 IN A 10.10.1.19
+biganswer.example8. 3600 IN A 10.10.1.20
+biganswer.example8. 3600 IN A 10.10.1.21
+biganswer.example8. 3600 IN A 10.10.1.22
+biganswer.example8. 3600 IN A 10.10.1.23
+biganswer.example8. 3600 IN A 10.10.1.24
+biganswer.example8. 3600 IN A 10.10.1.25
+biganswer.example8. 3600 IN A 10.10.1.26
+biganswer.example8. 3600 IN A 10.10.1.27
+biganswer.example8. 3600 IN A 10.10.1.28
+biganswer.example8. 3600 IN A 10.10.1.29
+biganswer.example8. 3600 IN A 10.10.1.30
+biganswer.example8. 3600 IN A 10.10.1.31
+biganswer.example8. 3600 IN A 10.10.1.32
+biganswer.example8. 3600 IN A 10.10.1.33
+biganswer.example8. 3600 IN A 10.10.1.34
+biganswer.example8. 3600 IN A 10.10.1.35
+biganswer.example8. 3600 IN A 10.10.1.36
+biganswer.example8. 3600 IN A 10.10.1.37
+biganswer.example8. 3600 IN A 10.10.1.38
+biganswer.example8. 3600 IN A 10.10.1.39
+biganswer.example8. 3600 IN A 10.10.1.40
+biganswer.example8. 3600 IN A 10.10.1.41
+biganswer.example8. 3600 IN A 10.10.1.42
+biganswer.example8. 3600 IN A 10.10.1.43
+biganswer.example8. 3600 IN A 10.10.1.44
+biganswer.example8. 3600 IN A 10.10.1.45
+biganswer.example8. 3600 IN A 10.10.1.46
+biganswer.example8. 3600 IN A 10.10.1.47
+biganswer.example8. 3600 IN A 10.10.1.48
+biganswer.example8. 3600 IN A 10.10.1.49
+biganswer.example8. 3600 IN A 10.10.1.50
+biganswer.example8. 3600 IN A 10.10.2.1
+biganswer.example8. 3600 IN A 10.10.2.2
+biganswer.example8. 3600 IN A 10.10.2.3
+biganswer.example8. 3600 IN A 10.10.2.4
+biganswer.example8. 3600 IN A 10.10.2.5
+biganswer.example8. 3600 IN A 10.10.2.6
+biganswer.example8. 3600 IN A 10.10.2.7
+biganswer.example8. 3600 IN A 10.10.2.8
+biganswer.example8. 3600 IN A 10.10.2.9
+biganswer.example8. 3600 IN A 10.10.2.10
+biganswer.example8. 3600 IN A 10.10.2.11
+biganswer.example8. 3600 IN A 10.10.2.12
+biganswer.example8. 3600 IN A 10.10.2.13
+biganswer.example8. 3600 IN A 10.10.2.14
+biganswer.example8. 3600 IN A 10.10.2.15
+biganswer.example8. 3600 IN A 10.10.2.16
+biganswer.example8. 3600 IN A 10.10.2.17
+biganswer.example8. 3600 IN A 10.10.2.18
+biganswer.example8. 3600 IN A 10.10.2.19
+biganswer.example8. 3600 IN A 10.10.2.20
+biganswer.example8. 3600 IN A 10.10.2.21
+biganswer.example8. 3600 IN A 10.10.2.22
+biganswer.example8. 3600 IN A 10.10.2.23
+biganswer.example8. 3600 IN A 10.10.2.24
+biganswer.example8. 3600 IN A 10.10.2.25
+biganswer.example8. 3600 IN A 10.10.2.26
+biganswer.example8. 3600 IN A 10.10.2.27
+biganswer.example8. 3600 IN A 10.10.2.28
+biganswer.example8. 3600 IN A 10.10.2.29
+biganswer.example8. 3600 IN A 10.10.2.30
+biganswer.example8. 3600 IN A 10.10.2.31
+biganswer.example8. 3600 IN A 10.10.2.32
+biganswer.example8. 3600 IN A 10.10.2.33
+biganswer.example8. 3600 IN A 10.10.2.34
+biganswer.example8. 3600 IN A 10.10.2.35
+biganswer.example8. 3600 IN A 10.10.2.36
+biganswer.example8. 3600 IN A 10.10.2.37
+biganswer.example8. 3600 IN A 10.10.2.38
+biganswer.example8. 3600 IN A 10.10.2.39
+biganswer.example8. 3600 IN A 10.10.2.40
+biganswer.example8. 3600 IN A 10.10.2.41
+biganswer.example8. 3600 IN A 10.10.2.42
+biganswer.example8. 3600 IN A 10.10.2.43
+biganswer.example8. 3600 IN A 10.10.2.44
+biganswer.example8. 3600 IN A 10.10.2.45
+biganswer.example8. 3600 IN A 10.10.2.46
+biganswer.example8. 3600 IN A 10.10.2.47
+biganswer.example8. 3600 IN A 10.10.2.48
+biganswer.example8. 3600 IN A 10.10.2.49
+biganswer.example8. 3600 IN A 10.10.2.50
+biganswer.example8. 3600 IN A 10.10.3.1
+biganswer.example8. 3600 IN A 10.10.3.2
+biganswer.example8. 3600 IN A 10.10.3.3
+biganswer.example8. 3600 IN A 10.10.3.4
+biganswer.example8. 3600 IN A 10.10.3.5
+biganswer.example8. 3600 IN A 10.10.3.6
+biganswer.example8. 3600 IN A 10.10.3.7
+biganswer.example8. 3600 IN A 10.10.3.8
+biganswer.example8. 3600 IN A 10.10.3.9
+biganswer.example8. 3600 IN A 10.10.3.10
+biganswer.example8. 3600 IN A 10.10.3.11
+biganswer.example8. 3600 IN A 10.10.3.12
+biganswer.example8. 3600 IN A 10.10.3.13
+biganswer.example8. 3600 IN A 10.10.3.14
+biganswer.example8. 3600 IN A 10.10.3.15
+biganswer.example8. 3600 IN A 10.10.3.16
+biganswer.example8. 3600 IN A 10.10.3.17
+biganswer.example8. 3600 IN A 10.10.3.18
+biganswer.example8. 3600 IN A 10.10.3.19
+biganswer.example8. 3600 IN A 10.10.3.20
+biganswer.example8. 3600 IN A 10.10.3.21
+biganswer.example8. 3600 IN A 10.10.3.22
+biganswer.example8. 3600 IN A 10.10.3.23
+biganswer.example8. 3600 IN A 10.10.3.24
+biganswer.example8. 3600 IN A 10.10.3.25
+biganswer.example8. 3600 IN A 10.10.3.26
+biganswer.example8. 3600 IN A 10.10.3.27
+biganswer.example8. 3600 IN A 10.10.3.28
+biganswer.example8. 3600 IN A 10.10.3.29
+biganswer.example8. 3600 IN A 10.10.3.30
+biganswer.example8. 3600 IN A 10.10.3.31
+biganswer.example8. 3600 IN A 10.10.3.32
+biganswer.example8. 3600 IN A 10.10.3.33
+biganswer.example8. 3600 IN A 10.10.3.34
+biganswer.example8. 3600 IN A 10.10.3.35
+biganswer.example8. 3600 IN A 10.10.3.36
+biganswer.example8. 3600 IN A 10.10.3.37
+biganswer.example8. 3600 IN A 10.10.3.38
+biganswer.example8. 3600 IN A 10.10.3.39
+biganswer.example8. 3600 IN A 10.10.3.40
+biganswer.example8. 3600 IN A 10.10.3.41
+biganswer.example8. 3600 IN A 10.10.3.42
+biganswer.example8. 3600 IN A 10.10.3.43
+biganswer.example8. 3600 IN A 10.10.3.44
+biganswer.example8. 3600 IN A 10.10.3.45
+biganswer.example8. 3600 IN A 10.10.3.46
+biganswer.example8. 3600 IN A 10.10.3.47
+biganswer.example8. 3600 IN A 10.10.3.48
+biganswer.example8. 3600 IN A 10.10.3.49
+biganswer.example8. 3600 IN A 10.10.3.50
+biganswer.example8. 3600 IN A 10.10.4.1
+biganswer.example8. 3600 IN A 10.10.4.2
+biganswer.example8. 3600 IN A 10.10.4.3
+biganswer.example8. 3600 IN A 10.10.4.4
+biganswer.example8. 3600 IN A 10.10.4.5
+biganswer.example8. 3600 IN A 10.10.4.6
+biganswer.example8. 3600 IN A 10.10.4.7
+biganswer.example8. 3600 IN A 10.10.4.8
+biganswer.example8. 3600 IN A 10.10.4.9
+biganswer.example8. 3600 IN A 10.10.4.10
+biganswer.example8. 3600 IN A 10.10.4.11
+biganswer.example8. 3600 IN A 10.10.4.12
+biganswer.example8. 3600 IN A 10.10.4.13
+biganswer.example8. 3600 IN A 10.10.4.14
+biganswer.example8. 3600 IN A 10.10.4.15
+biganswer.example8. 3600 IN A 10.10.4.16
+biganswer.example8. 3600 IN A 10.10.4.17
+biganswer.example8. 3600 IN A 10.10.4.18
+biganswer.example8. 3600 IN A 10.10.4.19
+biganswer.example8. 3600 IN A 10.10.4.20
+biganswer.example8. 3600 IN A 10.10.4.21
+biganswer.example8. 3600 IN A 10.10.4.22
+biganswer.example8. 3600 IN A 10.10.4.23
+biganswer.example8. 3600 IN A 10.10.4.24
+biganswer.example8. 3600 IN A 10.10.4.25
+biganswer.example8. 3600 IN A 10.10.4.26
+biganswer.example8. 3600 IN A 10.10.4.27
+biganswer.example8. 3600 IN A 10.10.4.28
+biganswer.example8. 3600 IN A 10.10.4.29
+biganswer.example8. 3600 IN A 10.10.4.30
+biganswer.example8. 3600 IN A 10.10.4.31
+biganswer.example8. 3600 IN A 10.10.4.32
+biganswer.example8. 3600 IN A 10.10.4.33
+biganswer.example8. 3600 IN A 10.10.4.34
+biganswer.example8. 3600 IN A 10.10.4.35
+biganswer.example8. 3600 IN A 10.10.4.36
+biganswer.example8. 3600 IN A 10.10.4.37
+biganswer.example8. 3600 IN A 10.10.4.38
+biganswer.example8. 3600 IN A 10.10.4.39
+biganswer.example8. 3600 IN A 10.10.4.40
+biganswer.example8. 3600 IN A 10.10.4.41
+biganswer.example8. 3600 IN A 10.10.4.42
+biganswer.example8. 3600 IN A 10.10.4.43
+biganswer.example8. 3600 IN A 10.10.4.44
+biganswer.example8. 3600 IN A 10.10.4.45
+biganswer.example8. 3600 IN A 10.10.4.46
+biganswer.example8. 3600 IN A 10.10.4.47
+biganswer.example8. 3600 IN A 10.10.4.48
+biganswer.example8. 3600 IN A 10.10.4.49
+biganswer.example8. 3600 IN A 10.10.4.50
+biganswer.example8. 3600 IN A 10.10.5.1
+biganswer.example8. 3600 IN A 10.10.5.2
+biganswer.example8. 3600 IN A 10.10.5.3
+biganswer.example8. 3600 IN A 10.10.5.4
+biganswer.example8. 3600 IN A 10.10.5.5
+biganswer.example8. 3600 IN A 10.10.5.6
+biganswer.example8. 3600 IN A 10.10.5.7
+biganswer.example8. 3600 IN A 10.10.5.8
+biganswer.example8. 3600 IN A 10.10.5.9
+biganswer.example8. 3600 IN A 10.10.5.10
+biganswer.example8. 3600 IN A 10.10.5.11
+biganswer.example8. 3600 IN A 10.10.5.12
+biganswer.example8. 3600 IN A 10.10.5.13
+biganswer.example8. 3600 IN A 10.10.5.14
+biganswer.example8. 3600 IN A 10.10.5.15
+biganswer.example8. 3600 IN A 10.10.5.16
+biganswer.example8. 3600 IN A 10.10.5.17
+biganswer.example8. 3600 IN A 10.10.5.18
+biganswer.example8. 3600 IN A 10.10.5.19
+biganswer.example8. 3600 IN A 10.10.5.20
+biganswer.example8. 3600 IN A 10.10.5.21
+biganswer.example8. 3600 IN A 10.10.5.22
+biganswer.example8. 3600 IN A 10.10.5.23
+biganswer.example8. 3600 IN A 10.10.5.24
+biganswer.example8. 3600 IN A 10.10.5.25
+biganswer.example8. 3600 IN A 10.10.5.26
+biganswer.example8. 3600 IN A 10.10.5.27
+biganswer.example8. 3600 IN A 10.10.5.28
+biganswer.example8. 3600 IN A 10.10.5.29
+biganswer.example8. 3600 IN A 10.10.5.30
+biganswer.example8. 3600 IN A 10.10.5.31
+biganswer.example8. 3600 IN A 10.10.5.32
+biganswer.example8. 3600 IN A 10.10.5.33
+biganswer.example8. 3600 IN A 10.10.5.34
+biganswer.example8. 3600 IN A 10.10.5.35
+biganswer.example8. 3600 IN A 10.10.5.36
+biganswer.example8. 3600 IN A 10.10.5.37
+biganswer.example8. 3600 IN A 10.10.5.38
+biganswer.example8. 3600 IN A 10.10.5.39
+biganswer.example8. 3600 IN A 10.10.5.40
+biganswer.example8. 3600 IN A 10.10.5.41
+biganswer.example8. 3600 IN A 10.10.5.42
+biganswer.example8. 3600 IN A 10.10.5.43
+biganswer.example8. 3600 IN A 10.10.5.44
+biganswer.example8. 3600 IN A 10.10.5.45
+biganswer.example8. 3600 IN A 10.10.5.46
+biganswer.example8. 3600 IN A 10.10.5.47
+biganswer.example8. 3600 IN A 10.10.5.48
+biganswer.example8. 3600 IN A 10.10.5.49
+biganswer.example8. 3600 IN A 10.10.5.50
+biganswer.example8. 3600 IN A 10.10.6.1
+biganswer.example8. 3600 IN A 10.10.6.2
+biganswer.example8. 3600 IN A 10.10.6.3
+biganswer.example8. 3600 IN A 10.10.6.4
+biganswer.example8. 3600 IN A 10.10.6.5
+biganswer.example8. 3600 IN A 10.10.6.6
+biganswer.example8. 3600 IN A 10.10.6.7
+biganswer.example8. 3600 IN A 10.10.6.8
+biganswer.example8. 3600 IN A 10.10.6.9
+biganswer.example8. 3600 IN A 10.10.6.10
+biganswer.example8. 3600 IN A 10.10.6.11
+biganswer.example8. 3600 IN A 10.10.6.12
+biganswer.example8. 3600 IN A 10.10.6.13
+biganswer.example8. 3600 IN A 10.10.6.14
+biganswer.example8. 3600 IN A 10.10.6.15
+biganswer.example8. 3600 IN A 10.10.6.16
+biganswer.example8. 3600 IN A 10.10.6.17
+biganswer.example8. 3600 IN A 10.10.6.18
+biganswer.example8. 3600 IN A 10.10.6.19
+biganswer.example8. 3600 IN A 10.10.6.20
+biganswer.example8. 3600 IN A 10.10.6.21
+biganswer.example8. 3600 IN A 10.10.6.22
+biganswer.example8. 3600 IN A 10.10.6.23
+biganswer.example8. 3600 IN A 10.10.6.24
+biganswer.example8. 3600 IN A 10.10.6.25
+biganswer.example8. 3600 IN A 10.10.6.26
+biganswer.example8. 3600 IN A 10.10.6.27
+biganswer.example8. 3600 IN A 10.10.6.28
+biganswer.example8. 3600 IN A 10.10.6.29
+biganswer.example8. 3600 IN A 10.10.6.30
+biganswer.example8. 3600 IN A 10.10.6.31
+biganswer.example8. 3600 IN A 10.10.6.32
+biganswer.example8. 3600 IN A 10.10.6.33
+biganswer.example8. 3600 IN A 10.10.6.34
+biganswer.example8. 3600 IN A 10.10.6.35
+biganswer.example8. 3600 IN A 10.10.6.36
+biganswer.example8. 3600 IN A 10.10.6.37
+biganswer.example8. 3600 IN A 10.10.6.38
+biganswer.example8. 3600 IN A 10.10.6.39
+biganswer.example8. 3600 IN A 10.10.6.40
+biganswer.example8. 3600 IN A 10.10.6.41
+biganswer.example8. 3600 IN A 10.10.6.42
+biganswer.example8. 3600 IN A 10.10.6.43
+biganswer.example8. 3600 IN A 10.10.6.44
+biganswer.example8. 3600 IN A 10.10.6.45
+biganswer.example8. 3600 IN A 10.10.6.46
+biganswer.example8. 3600 IN A 10.10.6.47
+biganswer.example8. 3600 IN A 10.10.6.48
+biganswer.example8. 3600 IN A 10.10.6.49
+biganswer.example8. 3600 IN A 10.10.6.50
+biganswer.example8. 3600 IN A 10.10.7.1
+biganswer.example8. 3600 IN A 10.10.7.2
+biganswer.example8. 3600 IN A 10.10.7.3
+biganswer.example8. 3600 IN A 10.10.7.4
+biganswer.example8. 3600 IN A 10.10.7.5
+biganswer.example8. 3600 IN A 10.10.7.6
+biganswer.example8. 3600 IN A 10.10.7.7
+biganswer.example8. 3600 IN A 10.10.7.8
+biganswer.example8. 3600 IN A 10.10.7.9
+biganswer.example8. 3600 IN A 10.10.7.10
+biganswer.example8. 3600 IN A 10.10.7.11
+biganswer.example8. 3600 IN A 10.10.7.12
+biganswer.example8. 3600 IN A 10.10.7.13
+biganswer.example8. 3600 IN A 10.10.7.14
+biganswer.example8. 3600 IN A 10.10.7.15
+biganswer.example8. 3600 IN A 10.10.7.16
+biganswer.example8. 3600 IN A 10.10.7.17
+biganswer.example8. 3600 IN A 10.10.7.18
+biganswer.example8. 3600 IN A 10.10.7.19
+biganswer.example8. 3600 IN A 10.10.7.20
+biganswer.example8. 3600 IN A 10.10.7.21
+biganswer.example8. 3600 IN A 10.10.7.22
+biganswer.example8. 3600 IN A 10.10.7.23
+biganswer.example8. 3600 IN A 10.10.7.24
+biganswer.example8. 3600 IN A 10.10.7.25
+biganswer.example8. 3600 IN A 10.10.7.26
+biganswer.example8. 3600 IN A 10.10.7.27
+biganswer.example8. 3600 IN A 10.10.7.28
+biganswer.example8. 3600 IN A 10.10.7.29
+biganswer.example8. 3600 IN A 10.10.7.30
+biganswer.example8. 3600 IN A 10.10.7.31
+biganswer.example8. 3600 IN A 10.10.7.32
+biganswer.example8. 3600 IN A 10.10.7.33
+biganswer.example8. 3600 IN A 10.10.7.34
+biganswer.example8. 3600 IN A 10.10.7.35
+biganswer.example8. 3600 IN A 10.10.7.36
+biganswer.example8. 3600 IN A 10.10.7.37
+biganswer.example8. 3600 IN A 10.10.7.38
+biganswer.example8. 3600 IN A 10.10.7.39
+biganswer.example8. 3600 IN A 10.10.7.40
+biganswer.example8. 3600 IN A 10.10.7.41
+biganswer.example8. 3600 IN A 10.10.7.42
+biganswer.example8. 3600 IN A 10.10.7.43
+biganswer.example8. 3600 IN A 10.10.7.44
+biganswer.example8. 3600 IN A 10.10.7.45
+biganswer.example8. 3600 IN A 10.10.7.46
+biganswer.example8. 3600 IN A 10.10.7.47
+biganswer.example8. 3600 IN A 10.10.7.48
+biganswer.example8. 3600 IN A 10.10.7.49
+biganswer.example8. 3600 IN A 10.10.7.50
+biganswer.example8. 3600 IN A 10.10.8.1
+biganswer.example8. 3600 IN A 10.10.8.2
+biganswer.example8. 3600 IN A 10.10.8.3
+biganswer.example8. 3600 IN A 10.10.8.4
+biganswer.example8. 3600 IN A 10.10.8.5
+biganswer.example8. 3600 IN A 10.10.8.6
+biganswer.example8. 3600 IN A 10.10.8.7
+biganswer.example8. 3600 IN A 10.10.8.8
+biganswer.example8. 3600 IN A 10.10.8.9
+biganswer.example8. 3600 IN A 10.10.8.10
+biganswer.example8. 3600 IN A 10.10.8.11
+biganswer.example8. 3600 IN A 10.10.8.12
+biganswer.example8. 3600 IN A 10.10.8.13
+biganswer.example8. 3600 IN A 10.10.8.14
+biganswer.example8. 3600 IN A 10.10.8.15
+biganswer.example8. 3600 IN A 10.10.8.16
+biganswer.example8. 3600 IN A 10.10.8.17
+biganswer.example8. 3600 IN A 10.10.8.18
+biganswer.example8. 3600 IN A 10.10.8.19
+biganswer.example8. 3600 IN A 10.10.8.20
+biganswer.example8. 3600 IN A 10.10.8.21
+biganswer.example8. 3600 IN A 10.10.8.22
+biganswer.example8. 3600 IN A 10.10.8.23
+biganswer.example8. 3600 IN A 10.10.8.24
+biganswer.example8. 3600 IN A 10.10.8.25
+biganswer.example8. 3600 IN A 10.10.8.26
+biganswer.example8. 3600 IN A 10.10.8.27
+biganswer.example8. 3600 IN A 10.10.8.28
+biganswer.example8. 3600 IN A 10.10.8.29
+biganswer.example8. 3600 IN A 10.10.8.30
+biganswer.example8. 3600 IN A 10.10.8.31
+biganswer.example8. 3600 IN A 10.10.8.32
+biganswer.example8. 3600 IN A 10.10.8.33
+biganswer.example8. 3600 IN A 10.10.8.34
+biganswer.example8. 3600 IN A 10.10.8.35
+biganswer.example8. 3600 IN A 10.10.8.36
+biganswer.example8. 3600 IN A 10.10.8.37
+biganswer.example8. 3600 IN A 10.10.8.38
+biganswer.example8. 3600 IN A 10.10.8.39
+biganswer.example8. 3600 IN A 10.10.8.40
+biganswer.example8. 3600 IN A 10.10.8.41
+biganswer.example8. 3600 IN A 10.10.8.42
+biganswer.example8. 3600 IN A 10.10.8.43
+biganswer.example8. 3600 IN A 10.10.8.44
+biganswer.example8. 3600 IN A 10.10.8.45
+biganswer.example8. 3600 IN A 10.10.8.46
+biganswer.example8. 3600 IN A 10.10.8.47
+biganswer.example8. 3600 IN A 10.10.8.48
+biganswer.example8. 3600 IN A 10.10.8.49
+biganswer.example8. 3600 IN A 10.10.8.50
+biganswer.example8. 3600 IN A 10.10.9.1
+biganswer.example8. 3600 IN A 10.10.9.2
+biganswer.example8. 3600 IN A 10.10.9.3
+biganswer.example8. 3600 IN A 10.10.9.4
+biganswer.example8. 3600 IN A 10.10.9.5
+biganswer.example8. 3600 IN A 10.10.9.6
+biganswer.example8. 3600 IN A 10.10.9.7
+biganswer.example8. 3600 IN A 10.10.9.8
+biganswer.example8. 3600 IN A 10.10.9.9
+biganswer.example8. 3600 IN A 10.10.9.10
+biganswer.example8. 3600 IN A 10.10.9.11
+biganswer.example8. 3600 IN A 10.10.9.12
+biganswer.example8. 3600 IN A 10.10.9.13
+biganswer.example8. 3600 IN A 10.10.9.14
+biganswer.example8. 3600 IN A 10.10.9.15
+biganswer.example8. 3600 IN A 10.10.9.16
+biganswer.example8. 3600 IN A 10.10.9.17
+biganswer.example8. 3600 IN A 10.10.9.18
+biganswer.example8. 3600 IN A 10.10.9.19
+biganswer.example8. 3600 IN A 10.10.9.20
+biganswer.example8. 3600 IN A 10.10.9.21
+biganswer.example8. 3600 IN A 10.10.9.22
+biganswer.example8. 3600 IN A 10.10.9.23
+biganswer.example8. 3600 IN A 10.10.9.24
+biganswer.example8. 3600 IN A 10.10.9.25
+biganswer.example8. 3600 IN A 10.10.9.26
+biganswer.example8. 3600 IN A 10.10.9.27
+biganswer.example8. 3600 IN A 10.10.9.28
+biganswer.example8. 3600 IN A 10.10.9.29
+biganswer.example8. 3600 IN A 10.10.9.30
+biganswer.example8. 3600 IN A 10.10.9.31
+biganswer.example8. 3600 IN A 10.10.9.32
+biganswer.example8. 3600 IN A 10.10.9.33
+biganswer.example8. 3600 IN A 10.10.9.34
+biganswer.example8. 3600 IN A 10.10.9.35
+biganswer.example8. 3600 IN A 10.10.9.36
+biganswer.example8. 3600 IN A 10.10.9.37
+biganswer.example8. 3600 IN A 10.10.9.38
+biganswer.example8. 3600 IN A 10.10.9.39
+biganswer.example8. 3600 IN A 10.10.9.40
+biganswer.example8. 3600 IN A 10.10.9.41
+biganswer.example8. 3600 IN A 10.10.9.42
+biganswer.example8. 3600 IN A 10.10.9.43
+biganswer.example8. 3600 IN A 10.10.9.44
+biganswer.example8. 3600 IN A 10.10.9.45
+biganswer.example8. 3600 IN A 10.10.9.46
+biganswer.example8. 3600 IN A 10.10.9.47
+biganswer.example8. 3600 IN A 10.10.9.48
+biganswer.example8. 3600 IN A 10.10.9.49
+biganswer.example8. 3600 IN A 10.10.9.50
+biganswer.example8. 3600 IN A 10.10.10.1
+biganswer.example8. 3600 IN A 10.10.10.2
+biganswer.example8. 3600 IN A 10.10.10.3
+biganswer.example8. 3600 IN A 10.10.10.4
+biganswer.example8. 3600 IN A 10.10.10.5
+biganswer.example8. 3600 IN A 10.10.10.6
+biganswer.example8. 3600 IN A 10.10.10.7
+biganswer.example8. 3600 IN A 10.10.10.8
+biganswer.example8. 3600 IN A 10.10.10.9
+biganswer.example8. 3600 IN A 10.10.10.10
+biganswer.example8. 3600 IN A 10.10.10.11
+biganswer.example8. 3600 IN A 10.10.10.12
+biganswer.example8. 3600 IN A 10.10.10.13
+biganswer.example8. 3600 IN A 10.10.10.14
+biganswer.example8. 3600 IN A 10.10.10.15
+biganswer.example8. 3600 IN A 10.10.10.16
+biganswer.example8. 3600 IN A 10.10.10.17
+biganswer.example8. 3600 IN A 10.10.10.18
+biganswer.example8. 3600 IN A 10.10.10.19
+biganswer.example8. 3600 IN A 10.10.10.20
+biganswer.example8. 3600 IN A 10.10.10.21
+biganswer.example8. 3600 IN A 10.10.10.22
+biganswer.example8. 3600 IN A 10.10.10.23
+biganswer.example8. 3600 IN A 10.10.10.24
+biganswer.example8. 3600 IN A 10.10.10.25
+biganswer.example8. 3600 IN A 10.10.10.26
+biganswer.example8. 3600 IN A 10.10.10.27
+biganswer.example8. 3600 IN A 10.10.10.28
+biganswer.example8. 3600 IN A 10.10.10.29
+biganswer.example8. 3600 IN A 10.10.10.30
+biganswer.example8. 3600 IN A 10.10.10.31
+biganswer.example8. 3600 IN A 10.10.10.32
+biganswer.example8. 3600 IN A 10.10.10.33
+biganswer.example8. 3600 IN A 10.10.10.34
+biganswer.example8. 3600 IN A 10.10.10.35
+biganswer.example8. 3600 IN A 10.10.10.36
+biganswer.example8. 3600 IN A 10.10.10.37
+biganswer.example8. 3600 IN A 10.10.10.38
+biganswer.example8. 3600 IN A 10.10.10.39
+biganswer.example8. 3600 IN A 10.10.10.40
+biganswer.example8. 3600 IN A 10.10.10.41
+biganswer.example8. 3600 IN A 10.10.10.42
+biganswer.example8. 3600 IN A 10.10.10.43
+biganswer.example8. 3600 IN A 10.10.10.44
+biganswer.example8. 3600 IN A 10.10.10.45
+biganswer.example8. 3600 IN A 10.10.10.46
+biganswer.example8. 3600 IN A 10.10.10.47
+biganswer.example8. 3600 IN A 10.10.10.48
+biganswer.example8. 3600 IN A 10.10.10.49
+biganswer.example8. 3600 IN A 10.10.10.50
+biganswer.example8. 3600 IN A 10.10.11.1
+biganswer.example8. 3600 IN A 10.10.11.2
+biganswer.example8. 3600 IN A 10.10.11.3
+biganswer.example8. 3600 IN A 10.10.11.4
+biganswer.example8. 3600 IN A 10.10.11.5
+biganswer.example8. 3600 IN A 10.10.11.6
+biganswer.example8. 3600 IN A 10.10.11.7
+biganswer.example8. 3600 IN A 10.10.11.8
+biganswer.example8. 3600 IN A 10.10.11.9
+biganswer.example8. 3600 IN A 10.10.11.10
+biganswer.example8. 3600 IN A 10.10.11.11
+biganswer.example8. 3600 IN A 10.10.11.12
+biganswer.example8. 3600 IN A 10.10.11.13
+biganswer.example8. 3600 IN A 10.10.11.14
+biganswer.example8. 3600 IN A 10.10.11.15
+biganswer.example8. 3600 IN A 10.10.11.16
+biganswer.example8. 3600 IN A 10.10.11.17
+biganswer.example8. 3600 IN A 10.10.11.18
+biganswer.example8. 3600 IN A 10.10.11.19
+biganswer.example8. 3600 IN A 10.10.11.20
+biganswer.example8. 3600 IN A 10.10.11.21
+biganswer.example8. 3600 IN A 10.10.11.22
+biganswer.example8. 3600 IN A 10.10.11.23
+biganswer.example8. 3600 IN A 10.10.11.24
+biganswer.example8. 3600 IN A 10.10.11.25
+biganswer.example8. 3600 IN A 10.10.11.26
+biganswer.example8. 3600 IN A 10.10.11.27
+biganswer.example8. 3600 IN A 10.10.11.28
+biganswer.example8. 3600 IN A 10.10.11.29
+biganswer.example8. 3600 IN A 10.10.11.30
+biganswer.example8. 3600 IN A 10.10.11.31
+biganswer.example8. 3600 IN A 10.10.11.32
+biganswer.example8. 3600 IN A 10.10.11.33
+biganswer.example8. 3600 IN A 10.10.11.34
+biganswer.example8. 3600 IN A 10.10.11.35
+biganswer.example8. 3600 IN A 10.10.11.36
+biganswer.example8. 3600 IN A 10.10.11.37
+biganswer.example8. 3600 IN A 10.10.11.38
+biganswer.example8. 3600 IN A 10.10.11.39
+biganswer.example8. 3600 IN A 10.10.11.40
+biganswer.example8. 3600 IN A 10.10.11.41
+biganswer.example8. 3600 IN A 10.10.11.42
+biganswer.example8. 3600 IN A 10.10.11.43
+biganswer.example8. 3600 IN A 10.10.11.44
+biganswer.example8. 3600 IN A 10.10.11.45
+biganswer.example8. 3600 IN A 10.10.11.46
+biganswer.example8. 3600 IN A 10.10.11.47
+biganswer.example8. 3600 IN A 10.10.11.48
+biganswer.example8. 3600 IN A 10.10.11.49
+biganswer.example8. 3600 IN A 10.10.11.50
+biganswer.example8. 3600 IN A 10.10.12.1
+biganswer.example8. 3600 IN A 10.10.12.2
+biganswer.example8. 3600 IN A 10.10.12.3
+biganswer.example8. 3600 IN A 10.10.12.4
+biganswer.example8. 3600 IN A 10.10.12.5
+biganswer.example8. 3600 IN A 10.10.12.6
+biganswer.example8. 3600 IN A 10.10.12.7
+biganswer.example8. 3600 IN A 10.10.12.8
+biganswer.example8. 3600 IN A 10.10.12.9
+biganswer.example8. 3600 IN A 10.10.12.10
+biganswer.example8. 3600 IN A 10.10.12.11
+biganswer.example8. 3600 IN A 10.10.12.12
+biganswer.example8. 3600 IN A 10.10.12.13
+biganswer.example8. 3600 IN A 10.10.12.14
+biganswer.example8. 3600 IN A 10.10.12.15
+biganswer.example8. 3600 IN A 10.10.12.16
+biganswer.example8. 3600 IN A 10.10.12.17
+biganswer.example8. 3600 IN A 10.10.12.18
+biganswer.example8. 3600 IN A 10.10.12.19
+biganswer.example8. 3600 IN A 10.10.12.20
+biganswer.example8. 3600 IN A 10.10.12.21
+biganswer.example8. 3600 IN A 10.10.12.22
+biganswer.example8. 3600 IN A 10.10.12.23
+biganswer.example8. 3600 IN A 10.10.12.24
+biganswer.example8. 3600 IN A 10.10.12.25
+biganswer.example8. 3600 IN A 10.10.12.26
+biganswer.example8. 3600 IN A 10.10.12.27
+biganswer.example8. 3600 IN A 10.10.12.28
+biganswer.example8. 3600 IN A 10.10.12.29
+biganswer.example8. 3600 IN A 10.10.12.30
+biganswer.example8. 3600 IN A 10.10.12.31
+biganswer.example8. 3600 IN A 10.10.12.32
+biganswer.example8. 3600 IN A 10.10.12.33
+biganswer.example8. 3600 IN A 10.10.12.34
+biganswer.example8. 3600 IN A 10.10.12.35
+biganswer.example8. 3600 IN A 10.10.12.36
+biganswer.example8. 3600 IN A 10.10.12.37
+biganswer.example8. 3600 IN A 10.10.12.38
+biganswer.example8. 3600 IN A 10.10.12.39
+biganswer.example8. 3600 IN A 10.10.12.40
+biganswer.example8. 3600 IN A 10.10.12.41
+biganswer.example8. 3600 IN A 10.10.12.42
+biganswer.example8. 3600 IN A 10.10.12.43
+biganswer.example8. 3600 IN A 10.10.12.44
+biganswer.example8. 3600 IN A 10.10.12.45
+biganswer.example8. 3600 IN A 10.10.12.46
+biganswer.example8. 3600 IN A 10.10.12.47
+biganswer.example8. 3600 IN A 10.10.12.48
+biganswer.example8. 3600 IN A 10.10.12.49
+biganswer.example8. 3600 IN A 10.10.12.50
+biganswer.example8. 3600 IN A 10.10.13.1
+biganswer.example8. 3600 IN A 10.10.13.2
+biganswer.example8. 3600 IN A 10.10.13.3
+biganswer.example8. 3600 IN A 10.10.13.4
+biganswer.example8. 3600 IN A 10.10.13.5
+biganswer.example8. 3600 IN A 10.10.13.6
+biganswer.example8. 3600 IN A 10.10.13.7
+biganswer.example8. 3600 IN A 10.10.13.8
+biganswer.example8. 3600 IN A 10.10.13.9
+biganswer.example8. 3600 IN A 10.10.13.10
+biganswer.example8. 3600 IN A 10.10.13.11
+biganswer.example8. 3600 IN A 10.10.13.12
+biganswer.example8. 3600 IN A 10.10.13.13
+biganswer.example8. 3600 IN A 10.10.13.14
+biganswer.example8. 3600 IN A 10.10.13.15
+biganswer.example8. 3600 IN A 10.10.13.16
+biganswer.example8. 3600 IN A 10.10.13.17
+biganswer.example8. 3600 IN A 10.10.13.18
+biganswer.example8. 3600 IN A 10.10.13.19
+biganswer.example8. 3600 IN A 10.10.13.20
+biganswer.example8. 3600 IN A 10.10.13.21
+biganswer.example8. 3600 IN A 10.10.13.22
+biganswer.example8. 3600 IN A 10.10.13.23
+biganswer.example8. 3600 IN A 10.10.13.24
+biganswer.example8. 3600 IN A 10.10.13.25
+biganswer.example8. 3600 IN A 10.10.13.26
+biganswer.example8. 3600 IN A 10.10.13.27
+biganswer.example8. 3600 IN A 10.10.13.28
+biganswer.example8. 3600 IN A 10.10.13.29
+biganswer.example8. 3600 IN A 10.10.13.30
+biganswer.example8. 3600 IN A 10.10.13.31
+biganswer.example8. 3600 IN A 10.10.13.32
+biganswer.example8. 3600 IN A 10.10.13.33
+biganswer.example8. 3600 IN A 10.10.13.34
+biganswer.example8. 3600 IN A 10.10.13.35
+biganswer.example8. 3600 IN A 10.10.13.36
+biganswer.example8. 3600 IN A 10.10.13.37
+biganswer.example8. 3600 IN A 10.10.13.38
+biganswer.example8. 3600 IN A 10.10.13.39
+biganswer.example8. 3600 IN A 10.10.13.40
+biganswer.example8. 3600 IN A 10.10.13.41
+biganswer.example8. 3600 IN A 10.10.13.42
+biganswer.example8. 3600 IN A 10.10.13.43
+biganswer.example8. 3600 IN A 10.10.13.44
+biganswer.example8. 3600 IN A 10.10.13.45
+biganswer.example8. 3600 IN A 10.10.13.46
+biganswer.example8. 3600 IN A 10.10.13.47
+biganswer.example8. 3600 IN A 10.10.13.48
+biganswer.example8. 3600 IN A 10.10.13.49
+biganswer.example8. 3600 IN A 10.10.13.50
+biganswer.example8. 3600 IN A 10.10.14.1
+biganswer.example8. 3600 IN A 10.10.14.2
+biganswer.example8. 3600 IN A 10.10.14.3
+biganswer.example8. 3600 IN A 10.10.14.4
+biganswer.example8. 3600 IN A 10.10.14.5
+biganswer.example8. 3600 IN A 10.10.14.6
+biganswer.example8. 3600 IN A 10.10.14.7
+biganswer.example8. 3600 IN A 10.10.14.8
+biganswer.example8. 3600 IN A 10.10.14.9
+biganswer.example8. 3600 IN A 10.10.14.10
+biganswer.example8. 3600 IN A 10.10.14.11
+biganswer.example8. 3600 IN A 10.10.14.12
+biganswer.example8. 3600 IN A 10.10.14.13
+biganswer.example8. 3600 IN A 10.10.14.14
+biganswer.example8. 3600 IN A 10.10.14.15
+biganswer.example8. 3600 IN A 10.10.14.16
+biganswer.example8. 3600 IN A 10.10.14.17
+biganswer.example8. 3600 IN A 10.10.14.18
+biganswer.example8. 3600 IN A 10.10.14.19
+biganswer.example8. 3600 IN A 10.10.14.20
+biganswer.example8. 3600 IN A 10.10.14.21
+biganswer.example8. 3600 IN A 10.10.14.22
+biganswer.example8. 3600 IN A 10.10.14.23
+biganswer.example8. 3600 IN A 10.10.14.24
+biganswer.example8. 3600 IN A 10.10.14.25
+biganswer.example8. 3600 IN A 10.10.14.26
+biganswer.example8. 3600 IN A 10.10.14.27
+biganswer.example8. 3600 IN A 10.10.14.28
+biganswer.example8. 3600 IN A 10.10.14.29
+biganswer.example8. 3600 IN A 10.10.14.30
+biganswer.example8. 3600 IN A 10.10.14.31
+biganswer.example8. 3600 IN A 10.10.14.32
+biganswer.example8. 3600 IN A 10.10.14.33
+biganswer.example8. 3600 IN A 10.10.14.34
+biganswer.example8. 3600 IN A 10.10.14.35
+biganswer.example8. 3600 IN A 10.10.14.36
+biganswer.example8. 3600 IN A 10.10.14.37
+biganswer.example8. 3600 IN A 10.10.14.38
+biganswer.example8. 3600 IN A 10.10.14.39
+biganswer.example8. 3600 IN A 10.10.14.40
+biganswer.example8. 3600 IN A 10.10.14.41
+biganswer.example8. 3600 IN A 10.10.14.42
+biganswer.example8. 3600 IN A 10.10.14.43
+biganswer.example8. 3600 IN A 10.10.14.44
+biganswer.example8. 3600 IN A 10.10.14.45
+biganswer.example8. 3600 IN A 10.10.14.46
+biganswer.example8. 3600 IN A 10.10.14.47
+biganswer.example8. 3600 IN A 10.10.14.48
+biganswer.example8. 3600 IN A 10.10.14.49
+biganswer.example8. 3600 IN A 10.10.14.50
+biganswer.example8. 3600 IN A 10.10.15.1
+biganswer.example8. 3600 IN A 10.10.15.2
+biganswer.example8. 3600 IN A 10.10.15.3
+biganswer.example8. 3600 IN A 10.10.15.4
+biganswer.example8. 3600 IN A 10.10.15.5
+biganswer.example8. 3600 IN A 10.10.15.6
+biganswer.example8. 3600 IN A 10.10.15.7
+biganswer.example8. 3600 IN A 10.10.15.8
+biganswer.example8. 3600 IN A 10.10.15.9
+biganswer.example8. 3600 IN A 10.10.15.10
+biganswer.example8. 3600 IN A 10.10.15.11
+biganswer.example8. 3600 IN A 10.10.15.12
+biganswer.example8. 3600 IN A 10.10.15.13
+biganswer.example8. 3600 IN A 10.10.15.14
+biganswer.example8. 3600 IN A 10.10.15.15
+biganswer.example8. 3600 IN A 10.10.15.16
+biganswer.example8. 3600 IN A 10.10.15.17
+biganswer.example8. 3600 IN A 10.10.15.18
+biganswer.example8. 3600 IN A 10.10.15.19
+biganswer.example8. 3600 IN A 10.10.15.20
+biganswer.example8. 3600 IN A 10.10.15.21
+biganswer.example8. 3600 IN A 10.10.15.22
+biganswer.example8. 3600 IN A 10.10.15.23
+biganswer.example8. 3600 IN A 10.10.15.24
+biganswer.example8. 3600 IN A 10.10.15.25
+biganswer.example8. 3600 IN A 10.10.15.26
+biganswer.example8. 3600 IN A 10.10.15.27
+biganswer.example8. 3600 IN A 10.10.15.28
+biganswer.example8. 3600 IN A 10.10.15.29
+biganswer.example8. 3600 IN A 10.10.15.30
+biganswer.example8. 3600 IN A 10.10.15.31
+biganswer.example8. 3600 IN A 10.10.15.32
+biganswer.example8. 3600 IN A 10.10.15.33
+biganswer.example8. 3600 IN A 10.10.15.34
+biganswer.example8. 3600 IN A 10.10.15.35
+biganswer.example8. 3600 IN A 10.10.15.36
+biganswer.example8. 3600 IN A 10.10.15.37
+biganswer.example8. 3600 IN A 10.10.15.38
+biganswer.example8. 3600 IN A 10.10.15.39
+biganswer.example8. 3600 IN A 10.10.15.40
+biganswer.example8. 3600 IN A 10.10.15.41
+biganswer.example8. 3600 IN A 10.10.15.42
+biganswer.example8. 3600 IN A 10.10.15.43
+biganswer.example8. 3600 IN A 10.10.15.44
+biganswer.example8. 3600 IN A 10.10.15.45
+biganswer.example8. 3600 IN A 10.10.15.46
+biganswer.example8. 3600 IN A 10.10.15.47
+biganswer.example8. 3600 IN A 10.10.15.48
+biganswer.example8. 3600 IN A 10.10.15.49
+biganswer.example8. 3600 IN A 10.10.15.50
+biganswer.example8. 3600 IN A 10.10.16.1
+biganswer.example8. 3600 IN A 10.10.16.2
+biganswer.example8. 3600 IN A 10.10.16.3
+biganswer.example8. 3600 IN A 10.10.16.4
+biganswer.example8. 3600 IN A 10.10.16.5
+biganswer.example8. 3600 IN A 10.10.16.6
+biganswer.example8. 3600 IN A 10.10.16.7
+biganswer.example8. 3600 IN A 10.10.16.8
+biganswer.example8. 3600 IN A 10.10.16.9
+biganswer.example8. 3600 IN A 10.10.16.10
+biganswer.example8. 3600 IN A 10.10.16.11
+biganswer.example8. 3600 IN A 10.10.16.12
+biganswer.example8. 3600 IN A 10.10.16.13
+biganswer.example8. 3600 IN A 10.10.16.14
+biganswer.example8. 3600 IN A 10.10.16.15
+biganswer.example8. 3600 IN A 10.10.16.16
+biganswer.example8. 3600 IN A 10.10.16.17
+biganswer.example8. 3600 IN A 10.10.16.18
+biganswer.example8. 3600 IN A 10.10.16.19
+biganswer.example8. 3600 IN A 10.10.16.20
+biganswer.example8. 3600 IN A 10.10.16.21
+biganswer.example8. 3600 IN A 10.10.16.22
+biganswer.example8. 3600 IN A 10.10.16.23
+biganswer.example8. 3600 IN A 10.10.16.24
+biganswer.example8. 3600 IN A 10.10.16.25
+biganswer.example8. 3600 IN A 10.10.16.26
+biganswer.example8. 3600 IN A 10.10.16.27
+biganswer.example8. 3600 IN A 10.10.16.28
+biganswer.example8. 3600 IN A 10.10.16.29
+biganswer.example8. 3600 IN A 10.10.16.30
+biganswer.example8. 3600 IN A 10.10.16.31
+biganswer.example8. 3600 IN A 10.10.16.32
+biganswer.example8. 3600 IN A 10.10.16.33
+biganswer.example8. 3600 IN A 10.10.16.34
+biganswer.example8. 3600 IN A 10.10.16.35
+biganswer.example8. 3600 IN A 10.10.16.36
+biganswer.example8. 3600 IN A 10.10.16.37
+biganswer.example8. 3600 IN A 10.10.16.38
+biganswer.example8. 3600 IN A 10.10.16.39
+biganswer.example8. 3600 IN A 10.10.16.40
+biganswer.example8. 3600 IN A 10.10.16.41
+biganswer.example8. 3600 IN A 10.10.16.42
+biganswer.example8. 3600 IN A 10.10.16.43
+biganswer.example8. 3600 IN A 10.10.16.44
+biganswer.example8. 3600 IN A 10.10.16.45
+biganswer.example8. 3600 IN A 10.10.16.46
+biganswer.example8. 3600 IN A 10.10.16.47
+biganswer.example8. 3600 IN A 10.10.16.48
+biganswer.example8. 3600 IN A 10.10.16.49
+biganswer.example8. 3600 IN A 10.10.16.50
+biganswer.example8. 3600 IN A 10.10.17.1
+biganswer.example8. 3600 IN A 10.10.17.2
+biganswer.example8. 3600 IN A 10.10.17.3
+biganswer.example8. 3600 IN A 10.10.17.4
+biganswer.example8. 3600 IN A 10.10.17.5
+biganswer.example8. 3600 IN A 10.10.17.6
+biganswer.example8. 3600 IN A 10.10.17.7
+biganswer.example8. 3600 IN A 10.10.17.8
+biganswer.example8. 3600 IN A 10.10.17.9
+biganswer.example8. 3600 IN A 10.10.17.10
+biganswer.example8. 3600 IN A 10.10.17.11
+biganswer.example8. 3600 IN A 10.10.17.12
+biganswer.example8. 3600 IN A 10.10.17.13
+biganswer.example8. 3600 IN A 10.10.17.14
+biganswer.example8. 3600 IN A 10.10.17.15
+biganswer.example8. 3600 IN A 10.10.17.16
+biganswer.example8. 3600 IN A 10.10.17.17
+biganswer.example8. 3600 IN A 10.10.17.18
+biganswer.example8. 3600 IN A 10.10.17.19
+biganswer.example8. 3600 IN A 10.10.17.20
+biganswer.example8. 3600 IN A 10.10.17.21
+biganswer.example8. 3600 IN A 10.10.17.22
+biganswer.example8. 3600 IN A 10.10.17.23
+biganswer.example8. 3600 IN A 10.10.17.24
+biganswer.example8. 3600 IN A 10.10.17.25
+biganswer.example8. 3600 IN A 10.10.17.26
+biganswer.example8. 3600 IN A 10.10.17.27
+biganswer.example8. 3600 IN A 10.10.17.28
+biganswer.example8. 3600 IN A 10.10.17.29
+biganswer.example8. 3600 IN A 10.10.17.30
+biganswer.example8. 3600 IN A 10.10.17.31
+biganswer.example8. 3600 IN A 10.10.17.32
+biganswer.example8. 3600 IN A 10.10.17.33
+biganswer.example8. 3600 IN A 10.10.17.34
+biganswer.example8. 3600 IN A 10.10.17.35
+biganswer.example8. 3600 IN A 10.10.17.36
+biganswer.example8. 3600 IN A 10.10.17.37
+biganswer.example8. 3600 IN A 10.10.17.38
+biganswer.example8. 3600 IN A 10.10.17.39
+biganswer.example8. 3600 IN A 10.10.17.40
+biganswer.example8. 3600 IN A 10.10.17.41
+biganswer.example8. 3600 IN A 10.10.17.42
+biganswer.example8. 3600 IN A 10.10.17.43
+biganswer.example8. 3600 IN A 10.10.17.44
+biganswer.example8. 3600 IN A 10.10.17.45
+biganswer.example8. 3600 IN A 10.10.17.46
+biganswer.example8. 3600 IN A 10.10.17.47
+biganswer.example8. 3600 IN A 10.10.17.48
+biganswer.example8. 3600 IN A 10.10.17.49
+biganswer.example8. 3600 IN A 10.10.17.50
+biganswer.example8. 3600 IN A 10.10.18.1
+biganswer.example8. 3600 IN A 10.10.18.2
+biganswer.example8. 3600 IN A 10.10.18.3
+biganswer.example8. 3600 IN A 10.10.18.4
+biganswer.example8. 3600 IN A 10.10.18.5
+biganswer.example8. 3600 IN A 10.10.18.6
+biganswer.example8. 3600 IN A 10.10.18.7
+biganswer.example8. 3600 IN A 10.10.18.8
+biganswer.example8. 3600 IN A 10.10.18.9
+biganswer.example8. 3600 IN A 10.10.18.10
+biganswer.example8. 3600 IN A 10.10.18.11
+biganswer.example8. 3600 IN A 10.10.18.12
+biganswer.example8. 3600 IN A 10.10.18.13
+biganswer.example8. 3600 IN A 10.10.18.14
+biganswer.example8. 3600 IN A 10.10.18.15
+biganswer.example8. 3600 IN A 10.10.18.16
+biganswer.example8. 3600 IN A 10.10.18.17
+biganswer.example8. 3600 IN A 10.10.18.18
+biganswer.example8. 3600 IN A 10.10.18.19
+biganswer.example8. 3600 IN A 10.10.18.20
+biganswer.example8. 3600 IN A 10.10.18.21
+biganswer.example8. 3600 IN A 10.10.18.22
+biganswer.example8. 3600 IN A 10.10.18.23
+biganswer.example8. 3600 IN A 10.10.18.24
+biganswer.example8. 3600 IN A 10.10.18.25
+biganswer.example8. 3600 IN A 10.10.18.26
+biganswer.example8. 3600 IN A 10.10.18.27
+biganswer.example8. 3600 IN A 10.10.18.28
+biganswer.example8. 3600 IN A 10.10.18.29
+biganswer.example8. 3600 IN A 10.10.18.30
+biganswer.example8. 3600 IN A 10.10.18.31
+biganswer.example8. 3600 IN A 10.10.18.32
+biganswer.example8. 3600 IN A 10.10.18.33
+biganswer.example8. 3600 IN A 10.10.18.34
+biganswer.example8. 3600 IN A 10.10.18.35
+biganswer.example8. 3600 IN A 10.10.18.36
+biganswer.example8. 3600 IN A 10.10.18.37
+biganswer.example8. 3600 IN A 10.10.18.38
+biganswer.example8. 3600 IN A 10.10.18.39
+biganswer.example8. 3600 IN A 10.10.18.40
+biganswer.example8. 3600 IN A 10.10.18.41
+biganswer.example8. 3600 IN A 10.10.18.42
+biganswer.example8. 3600 IN A 10.10.18.43
+biganswer.example8. 3600 IN A 10.10.18.44
+biganswer.example8. 3600 IN A 10.10.18.45
+biganswer.example8. 3600 IN A 10.10.18.46
+biganswer.example8. 3600 IN A 10.10.18.47
+biganswer.example8. 3600 IN A 10.10.18.48
+biganswer.example8. 3600 IN A 10.10.18.49
+biganswer.example8. 3600 IN A 10.10.18.50
+biganswer.example8. 3600 IN A 10.10.19.1
+biganswer.example8. 3600 IN A 10.10.19.2
+biganswer.example8. 3600 IN A 10.10.19.3
+biganswer.example8. 3600 IN A 10.10.19.4
+biganswer.example8. 3600 IN A 10.10.19.5
+biganswer.example8. 3600 IN A 10.10.19.6
+biganswer.example8. 3600 IN A 10.10.19.7
+biganswer.example8. 3600 IN A 10.10.19.8
+biganswer.example8. 3600 IN A 10.10.19.9
+biganswer.example8. 3600 IN A 10.10.19.10
+biganswer.example8. 3600 IN A 10.10.19.11
+biganswer.example8. 3600 IN A 10.10.19.12
+biganswer.example8. 3600 IN A 10.10.19.13
+biganswer.example8. 3600 IN A 10.10.19.14
+biganswer.example8. 3600 IN A 10.10.19.15
+biganswer.example8. 3600 IN A 10.10.19.16
+biganswer.example8. 3600 IN A 10.10.19.17
+biganswer.example8. 3600 IN A 10.10.19.18
+biganswer.example8. 3600 IN A 10.10.19.19
+biganswer.example8. 3600 IN A 10.10.19.20
+biganswer.example8. 3600 IN A 10.10.19.21
+biganswer.example8. 3600 IN A 10.10.19.22
+biganswer.example8. 3600 IN A 10.10.19.23
+biganswer.example8. 3600 IN A 10.10.19.24
+biganswer.example8. 3600 IN A 10.10.19.25
+biganswer.example8. 3600 IN A 10.10.19.26
+biganswer.example8. 3600 IN A 10.10.19.27
+biganswer.example8. 3600 IN A 10.10.19.28
+biganswer.example8. 3600 IN A 10.10.19.29
+biganswer.example8. 3600 IN A 10.10.19.30
+biganswer.example8. 3600 IN A 10.10.19.31
+biganswer.example8. 3600 IN A 10.10.19.32
+biganswer.example8. 3600 IN A 10.10.19.33
+biganswer.example8. 3600 IN A 10.10.19.34
+biganswer.example8. 3600 IN A 10.10.19.35
+biganswer.example8. 3600 IN A 10.10.19.36
+biganswer.example8. 3600 IN A 10.10.19.37
+biganswer.example8. 3600 IN A 10.10.19.38
+biganswer.example8. 3600 IN A 10.10.19.39
+biganswer.example8. 3600 IN A 10.10.19.40
+biganswer.example8. 3600 IN A 10.10.19.41
+biganswer.example8. 3600 IN A 10.10.19.42
+biganswer.example8. 3600 IN A 10.10.19.43
+biganswer.example8. 3600 IN A 10.10.19.44
+biganswer.example8. 3600 IN A 10.10.19.45
+biganswer.example8. 3600 IN A 10.10.19.46
+biganswer.example8. 3600 IN A 10.10.19.47
+biganswer.example8. 3600 IN A 10.10.19.48
+biganswer.example8. 3600 IN A 10.10.19.49
+biganswer.example8. 3600 IN A 10.10.19.50
+biganswer.example8. 3600 IN A 10.10.20.1
+biganswer.example8. 3600 IN A 10.10.20.2
+biganswer.example8. 3600 IN A 10.10.20.3
+biganswer.example8. 3600 IN A 10.10.20.4
+biganswer.example8. 3600 IN A 10.10.20.5
+biganswer.example8. 3600 IN A 10.10.20.6
+biganswer.example8. 3600 IN A 10.10.20.7
+biganswer.example8. 3600 IN A 10.10.20.8
+biganswer.example8. 3600 IN A 10.10.20.9
+biganswer.example8. 3600 IN A 10.10.20.10
+biganswer.example8. 3600 IN A 10.10.20.11
+biganswer.example8. 3600 IN A 10.10.20.12
+biganswer.example8. 3600 IN A 10.10.20.13
+biganswer.example8. 3600 IN A 10.10.20.14
+biganswer.example8. 3600 IN A 10.10.20.15
+biganswer.example8. 3600 IN A 10.10.20.16
+biganswer.example8. 3600 IN A 10.10.20.17
+biganswer.example8. 3600 IN A 10.10.20.18
+biganswer.example8. 3600 IN A 10.10.20.19
+biganswer.example8. 3600 IN A 10.10.20.20
+biganswer.example8. 3600 IN A 10.10.20.21
+biganswer.example8. 3600 IN A 10.10.20.22
+biganswer.example8. 3600 IN A 10.10.20.23
+biganswer.example8. 3600 IN A 10.10.20.24
+biganswer.example8. 3600 IN A 10.10.20.25
+biganswer.example8. 3600 IN A 10.10.20.26
+biganswer.example8. 3600 IN A 10.10.20.27
+biganswer.example8. 3600 IN A 10.10.20.28
+biganswer.example8. 3600 IN A 10.10.20.29
+biganswer.example8. 3600 IN A 10.10.20.30
+biganswer.example8. 3600 IN A 10.10.20.31
+biganswer.example8. 3600 IN A 10.10.20.32
+biganswer.example8. 3600 IN A 10.10.20.33
+biganswer.example8. 3600 IN A 10.10.20.34
+biganswer.example8. 3600 IN A 10.10.20.35
+biganswer.example8. 3600 IN A 10.10.20.36
+biganswer.example8. 3600 IN A 10.10.20.37
+biganswer.example8. 3600 IN A 10.10.20.38
+biganswer.example8. 3600 IN A 10.10.20.39
+biganswer.example8. 3600 IN A 10.10.20.40
+biganswer.example8. 3600 IN A 10.10.20.41
+biganswer.example8. 3600 IN A 10.10.20.42
+biganswer.example8. 3600 IN A 10.10.20.43
+biganswer.example8. 3600 IN A 10.10.20.44
+biganswer.example8. 3600 IN A 10.10.20.45
+biganswer.example8. 3600 IN A 10.10.20.46
+biganswer.example8. 3600 IN A 10.10.20.47
+biganswer.example8. 3600 IN A 10.10.20.48
+biganswer.example8. 3600 IN A 10.10.20.49
+biganswer.example8. 3600 IN A 10.10.20.50
+biganswer.example8. 3600 IN A 10.10.21.1
+biganswer.example8. 3600 IN A 10.10.21.2
+biganswer.example8. 3600 IN A 10.10.21.3
+biganswer.example8. 3600 IN A 10.10.21.4
+biganswer.example8. 3600 IN A 10.10.21.5
+biganswer.example8. 3600 IN A 10.10.21.6
+biganswer.example8. 3600 IN A 10.10.21.7
+biganswer.example8. 3600 IN A 10.10.21.8
+biganswer.example8. 3600 IN A 10.10.21.9
+biganswer.example8. 3600 IN A 10.10.21.10
+biganswer.example8. 3600 IN A 10.10.21.11
+biganswer.example8. 3600 IN A 10.10.21.12
+biganswer.example8. 3600 IN A 10.10.21.13
+biganswer.example8. 3600 IN A 10.10.21.14
+biganswer.example8. 3600 IN A 10.10.21.15
+biganswer.example8. 3600 IN A 10.10.21.16
+biganswer.example8. 3600 IN A 10.10.21.17
+biganswer.example8. 3600 IN A 10.10.21.18
+biganswer.example8. 3600 IN A 10.10.21.19
+biganswer.example8. 3600 IN A 10.10.21.20
+biganswer.example8. 3600 IN A 10.10.21.21
+biganswer.example8. 3600 IN A 10.10.21.22
+biganswer.example8. 3600 IN A 10.10.21.23
+biganswer.example8. 3600 IN A 10.10.21.24
+biganswer.example8. 3600 IN A 10.10.21.25
+biganswer.example8. 3600 IN A 10.10.21.26
+biganswer.example8. 3600 IN A 10.10.21.27
+biganswer.example8. 3600 IN A 10.10.21.28
+biganswer.example8. 3600 IN A 10.10.21.29
+biganswer.example8. 3600 IN A 10.10.21.30
+biganswer.example8. 3600 IN A 10.10.21.31
+biganswer.example8. 3600 IN A 10.10.21.32
+biganswer.example8. 3600 IN A 10.10.21.33
+biganswer.example8. 3600 IN A 10.10.21.34
+biganswer.example8. 3600 IN A 10.10.21.35
+biganswer.example8. 3600 IN A 10.10.21.36
+biganswer.example8. 3600 IN A 10.10.21.37
+biganswer.example8. 3600 IN A 10.10.21.38
+biganswer.example8. 3600 IN A 10.10.21.39
+biganswer.example8. 3600 IN A 10.10.21.40
+biganswer.example8. 3600 IN A 10.10.21.41
+biganswer.example8. 3600 IN A 10.10.21.42
+biganswer.example8. 3600 IN A 10.10.21.43
+biganswer.example8. 3600 IN A 10.10.21.44
+biganswer.example8. 3600 IN A 10.10.21.45
+biganswer.example8. 3600 IN A 10.10.21.46
+biganswer.example8. 3600 IN A 10.10.21.47
+biganswer.example8. 3600 IN A 10.10.21.48
+biganswer.example8. 3600 IN A 10.10.21.49
+biganswer.example8. 3600 IN A 10.10.21.50
+biganswer.example8. 3600 IN A 10.10.22.1
+biganswer.example8. 3600 IN A 10.10.22.2
+biganswer.example8. 3600 IN A 10.10.22.3
+biganswer.example8. 3600 IN A 10.10.22.4
+biganswer.example8. 3600 IN A 10.10.22.5
+biganswer.example8. 3600 IN A 10.10.22.6
+biganswer.example8. 3600 IN A 10.10.22.7
+biganswer.example8. 3600 IN A 10.10.22.8
+biganswer.example8. 3600 IN A 10.10.22.9
+biganswer.example8. 3600 IN A 10.10.22.10
+biganswer.example8. 3600 IN A 10.10.22.11
+biganswer.example8. 3600 IN A 10.10.22.12
+biganswer.example8. 3600 IN A 10.10.22.13
+biganswer.example8. 3600 IN A 10.10.22.14
+biganswer.example8. 3600 IN A 10.10.22.15
+biganswer.example8. 3600 IN A 10.10.22.16
+biganswer.example8. 3600 IN A 10.10.22.17
+biganswer.example8. 3600 IN A 10.10.22.18
+biganswer.example8. 3600 IN A 10.10.22.19
+biganswer.example8. 3600 IN A 10.10.22.20
+biganswer.example8. 3600 IN A 10.10.22.21
+biganswer.example8. 3600 IN A 10.10.22.22
+biganswer.example8. 3600 IN A 10.10.22.23
+biganswer.example8. 3600 IN A 10.10.22.24
+biganswer.example8. 3600 IN A 10.10.22.25
+biganswer.example8. 3600 IN A 10.10.22.26
+biganswer.example8. 3600 IN A 10.10.22.27
+biganswer.example8. 3600 IN A 10.10.22.28
+biganswer.example8. 3600 IN A 10.10.22.29
+biganswer.example8. 3600 IN A 10.10.22.30
+biganswer.example8. 3600 IN A 10.10.22.31
+biganswer.example8. 3600 IN A 10.10.22.32
+biganswer.example8. 3600 IN A 10.10.22.33
+biganswer.example8. 3600 IN A 10.10.22.34
+biganswer.example8. 3600 IN A 10.10.22.35
+biganswer.example8. 3600 IN A 10.10.22.36
+biganswer.example8. 3600 IN A 10.10.22.37
+biganswer.example8. 3600 IN A 10.10.22.38
+biganswer.example8. 3600 IN A 10.10.22.39
+biganswer.example8. 3600 IN A 10.10.22.40
+biganswer.example8. 3600 IN A 10.10.22.41
+biganswer.example8. 3600 IN A 10.10.22.42
+biganswer.example8. 3600 IN A 10.10.22.43
+biganswer.example8. 3600 IN A 10.10.22.44
+biganswer.example8. 3600 IN A 10.10.22.45
+biganswer.example8. 3600 IN A 10.10.22.46
+biganswer.example8. 3600 IN A 10.10.22.47
+biganswer.example8. 3600 IN A 10.10.22.48
+biganswer.example8. 3600 IN A 10.10.22.49
+biganswer.example8. 3600 IN A 10.10.22.50
+biganswer.example8. 3600 IN A 10.10.23.1
+biganswer.example8. 3600 IN A 10.10.23.2
+biganswer.example8. 3600 IN A 10.10.23.3
+biganswer.example8. 3600 IN A 10.10.23.4
+biganswer.example8. 3600 IN A 10.10.23.5
+biganswer.example8. 3600 IN A 10.10.23.6
+biganswer.example8. 3600 IN A 10.10.23.7
+biganswer.example8. 3600 IN A 10.10.23.8
+biganswer.example8. 3600 IN A 10.10.23.9
+biganswer.example8. 3600 IN A 10.10.23.10
+biganswer.example8. 3600 IN A 10.10.23.11
+biganswer.example8. 3600 IN A 10.10.23.12
+biganswer.example8. 3600 IN A 10.10.23.13
+biganswer.example8. 3600 IN A 10.10.23.14
+biganswer.example8. 3600 IN A 10.10.23.15
+biganswer.example8. 3600 IN A 10.10.23.16
+biganswer.example8. 3600 IN A 10.10.23.17
+biganswer.example8. 3600 IN A 10.10.23.18
+biganswer.example8. 3600 IN A 10.10.23.19
+biganswer.example8. 3600 IN A 10.10.23.20
+biganswer.example8. 3600 IN A 10.10.23.21
+biganswer.example8. 3600 IN A 10.10.23.22
+biganswer.example8. 3600 IN A 10.10.23.23
+biganswer.example8. 3600 IN A 10.10.23.24
+biganswer.example8. 3600 IN A 10.10.23.25
+biganswer.example8. 3600 IN A 10.10.23.26
+biganswer.example8. 3600 IN A 10.10.23.27
+biganswer.example8. 3600 IN A 10.10.23.28
+biganswer.example8. 3600 IN A 10.10.23.29
+biganswer.example8. 3600 IN A 10.10.23.30
+biganswer.example8. 3600 IN A 10.10.23.31
+biganswer.example8. 3600 IN A 10.10.23.32
+biganswer.example8. 3600 IN A 10.10.23.33
+biganswer.example8. 3600 IN A 10.10.23.34
+biganswer.example8. 3600 IN A 10.10.23.35
+biganswer.example8. 3600 IN A 10.10.23.36
+biganswer.example8. 3600 IN A 10.10.23.37
+biganswer.example8. 3600 IN A 10.10.23.38
+biganswer.example8. 3600 IN A 10.10.23.39
+biganswer.example8. 3600 IN A 10.10.23.40
+biganswer.example8. 3600 IN A 10.10.23.41
+biganswer.example8. 3600 IN A 10.10.23.42
+biganswer.example8. 3600 IN A 10.10.23.43
+biganswer.example8. 3600 IN A 10.10.23.44
+biganswer.example8. 3600 IN A 10.10.23.45
+biganswer.example8. 3600 IN A 10.10.23.46
+biganswer.example8. 3600 IN A 10.10.23.47
+biganswer.example8. 3600 IN A 10.10.23.48
+biganswer.example8. 3600 IN A 10.10.23.49
+biganswer.example8. 3600 IN A 10.10.23.50
+biganswer.example8. 3600 IN A 10.10.24.1
+biganswer.example8. 3600 IN A 10.10.24.2
+biganswer.example8. 3600 IN A 10.10.24.3
+biganswer.example8. 3600 IN A 10.10.24.4
+biganswer.example8. 3600 IN A 10.10.24.5
+biganswer.example8. 3600 IN A 10.10.24.6
+biganswer.example8. 3600 IN A 10.10.24.7
+biganswer.example8. 3600 IN A 10.10.24.8
+biganswer.example8. 3600 IN A 10.10.24.9
+biganswer.example8. 3600 IN A 10.10.24.10
+biganswer.example8. 3600 IN A 10.10.24.11
+biganswer.example8. 3600 IN A 10.10.24.12
+biganswer.example8. 3600 IN A 10.10.24.13
+biganswer.example8. 3600 IN A 10.10.24.14
+biganswer.example8. 3600 IN A 10.10.24.15
+biganswer.example8. 3600 IN A 10.10.24.16
+biganswer.example8. 3600 IN A 10.10.24.17
+biganswer.example8. 3600 IN A 10.10.24.18
+biganswer.example8. 3600 IN A 10.10.24.19
+biganswer.example8. 3600 IN A 10.10.24.20
+biganswer.example8. 3600 IN A 10.10.24.21
+biganswer.example8. 3600 IN A 10.10.24.22
+biganswer.example8. 3600 IN A 10.10.24.23
+biganswer.example8. 3600 IN A 10.10.24.24
+biganswer.example8. 3600 IN A 10.10.24.25
+biganswer.example8. 3600 IN A 10.10.24.26
+biganswer.example8. 3600 IN A 10.10.24.27
+biganswer.example8. 3600 IN A 10.10.24.28
+biganswer.example8. 3600 IN A 10.10.24.29
+biganswer.example8. 3600 IN A 10.10.24.30
+biganswer.example8. 3600 IN A 10.10.24.31
+biganswer.example8. 3600 IN A 10.10.24.32
+biganswer.example8. 3600 IN A 10.10.24.33
+biganswer.example8. 3600 IN A 10.10.24.34
+biganswer.example8. 3600 IN A 10.10.24.35
+biganswer.example8. 3600 IN A 10.10.24.36
+biganswer.example8. 3600 IN A 10.10.24.37
+biganswer.example8. 3600 IN A 10.10.24.38
+biganswer.example8. 3600 IN A 10.10.24.39
+biganswer.example8. 3600 IN A 10.10.24.40
+biganswer.example8. 3600 IN A 10.10.24.41
+biganswer.example8. 3600 IN A 10.10.24.42
+biganswer.example8. 3600 IN A 10.10.24.43
+biganswer.example8. 3600 IN A 10.10.24.44
+biganswer.example8. 3600 IN A 10.10.24.45
+biganswer.example8. 3600 IN A 10.10.24.46
+biganswer.example8. 3600 IN A 10.10.24.47
+biganswer.example8. 3600 IN A 10.10.24.48
+biganswer.example8. 3600 IN A 10.10.24.49
+biganswer.example8. 3600 IN A 10.10.24.50
+biganswer.example8. 3600 IN A 10.10.25.1
+biganswer.example8. 3600 IN A 10.10.25.2
+biganswer.example8. 3600 IN A 10.10.25.3
+biganswer.example8. 3600 IN A 10.10.25.4
+biganswer.example8. 3600 IN A 10.10.25.5
+biganswer.example8. 3600 IN A 10.10.25.6
+biganswer.example8. 3600 IN A 10.10.25.7
+biganswer.example8. 3600 IN A 10.10.25.8
+biganswer.example8. 3600 IN A 10.10.25.9
+biganswer.example8. 3600 IN A 10.10.25.10
+biganswer.example8. 3600 IN A 10.10.25.11
+biganswer.example8. 3600 IN A 10.10.25.12
+biganswer.example8. 3600 IN A 10.10.25.13
+biganswer.example8. 3600 IN A 10.10.25.14
+biganswer.example8. 3600 IN A 10.10.25.15
+biganswer.example8. 3600 IN A 10.10.25.16
+biganswer.example8. 3600 IN A 10.10.25.17
+biganswer.example8. 3600 IN A 10.10.25.18
+biganswer.example8. 3600 IN A 10.10.25.19
+biganswer.example8. 3600 IN A 10.10.25.20
+biganswer.example8. 3600 IN A 10.10.25.21
+biganswer.example8. 3600 IN A 10.10.25.22
+biganswer.example8. 3600 IN A 10.10.25.23
+biganswer.example8. 3600 IN A 10.10.25.24
+biganswer.example8. 3600 IN A 10.10.25.25
+biganswer.example8. 3600 IN A 10.10.25.26
+biganswer.example8. 3600 IN A 10.10.25.27
+biganswer.example8. 3600 IN A 10.10.25.28
+biganswer.example8. 3600 IN A 10.10.25.29
+biganswer.example8. 3600 IN A 10.10.25.30
+biganswer.example8. 3600 IN A 10.10.25.31
+biganswer.example8. 3600 IN A 10.10.25.32
+biganswer.example8. 3600 IN A 10.10.25.33
+biganswer.example8. 3600 IN A 10.10.25.34
+biganswer.example8. 3600 IN A 10.10.25.35
+biganswer.example8. 3600 IN A 10.10.25.36
+biganswer.example8. 3600 IN A 10.10.25.37
+biganswer.example8. 3600 IN A 10.10.25.38
+biganswer.example8. 3600 IN A 10.10.25.39
+biganswer.example8. 3600 IN A 10.10.25.40
+biganswer.example8. 3600 IN A 10.10.25.41
+biganswer.example8. 3600 IN A 10.10.25.42
+biganswer.example8. 3600 IN A 10.10.25.43
+biganswer.example8. 3600 IN A 10.10.25.44
+biganswer.example8. 3600 IN A 10.10.25.45
+biganswer.example8. 3600 IN A 10.10.25.46
+biganswer.example8. 3600 IN A 10.10.25.47
+biganswer.example8. 3600 IN A 10.10.25.48
+biganswer.example8. 3600 IN A 10.10.25.49
+biganswer.example8. 3600 IN A 10.10.25.50
+biganswer.example8. 3600 IN A 10.10.26.1
+biganswer.example8. 3600 IN A 10.10.26.2
+biganswer.example8. 3600 IN A 10.10.26.3
+biganswer.example8. 3600 IN A 10.10.26.4
+biganswer.example8. 3600 IN A 10.10.26.5
+biganswer.example8. 3600 IN A 10.10.26.6
+biganswer.example8. 3600 IN A 10.10.26.7
+biganswer.example8. 3600 IN A 10.10.26.8
+biganswer.example8. 3600 IN A 10.10.26.9
+biganswer.example8. 3600 IN A 10.10.26.10
+biganswer.example8. 3600 IN A 10.10.26.11
+biganswer.example8. 3600 IN A 10.10.26.12
+biganswer.example8. 3600 IN A 10.10.26.13
+biganswer.example8. 3600 IN A 10.10.26.14
+biganswer.example8. 3600 IN A 10.10.26.15
+biganswer.example8. 3600 IN A 10.10.26.16
+biganswer.example8. 3600 IN A 10.10.26.17
+biganswer.example8. 3600 IN A 10.10.26.18
+biganswer.example8. 3600 IN A 10.10.26.19
+biganswer.example8. 3600 IN A 10.10.26.20
+biganswer.example8. 3600 IN A 10.10.26.21
+biganswer.example8. 3600 IN A 10.10.26.22
+biganswer.example8. 3600 IN A 10.10.26.23
+biganswer.example8. 3600 IN A 10.10.26.24
+biganswer.example8. 3600 IN A 10.10.26.25
+biganswer.example8. 3600 IN A 10.10.26.26
+biganswer.example8. 3600 IN A 10.10.26.27
+biganswer.example8. 3600 IN A 10.10.26.28
+biganswer.example8. 3600 IN A 10.10.26.29
+biganswer.example8. 3600 IN A 10.10.26.30
+biganswer.example8. 3600 IN A 10.10.26.31
+biganswer.example8. 3600 IN A 10.10.26.32
+biganswer.example8. 3600 IN A 10.10.26.33
+biganswer.example8. 3600 IN A 10.10.26.34
+biganswer.example8. 3600 IN A 10.10.26.35
+biganswer.example8. 3600 IN A 10.10.26.36
+biganswer.example8. 3600 IN A 10.10.26.37
+biganswer.example8. 3600 IN A 10.10.26.38
+biganswer.example8. 3600 IN A 10.10.26.39
+biganswer.example8. 3600 IN A 10.10.26.40
+biganswer.example8. 3600 IN A 10.10.26.41
+biganswer.example8. 3600 IN A 10.10.26.42
+biganswer.example8. 3600 IN A 10.10.26.43
+biganswer.example8. 3600 IN A 10.10.26.44
+biganswer.example8. 3600 IN A 10.10.26.45
+biganswer.example8. 3600 IN A 10.10.26.46
+biganswer.example8. 3600 IN A 10.10.26.47
+biganswer.example8. 3600 IN A 10.10.26.48
+biganswer.example8. 3600 IN A 10.10.26.49
+biganswer.example8. 3600 IN A 10.10.26.50
+biganswer.example8. 3600 IN A 10.10.27.1
+biganswer.example8. 3600 IN A 10.10.27.2
+biganswer.example8. 3600 IN A 10.10.27.3
+biganswer.example8. 3600 IN A 10.10.27.4
+biganswer.example8. 3600 IN A 10.10.27.5
+biganswer.example8. 3600 IN A 10.10.27.6
+biganswer.example8. 3600 IN A 10.10.27.7
+biganswer.example8. 3600 IN A 10.10.27.8
+biganswer.example8. 3600 IN A 10.10.27.9
+biganswer.example8. 3600 IN A 10.10.27.10
+biganswer.example8. 3600 IN A 10.10.27.11
+biganswer.example8. 3600 IN A 10.10.27.12
+biganswer.example8. 3600 IN A 10.10.27.13
+biganswer.example8. 3600 IN A 10.10.27.14
+biganswer.example8. 3600 IN A 10.10.27.15
+biganswer.example8. 3600 IN A 10.10.27.16
+biganswer.example8. 3600 IN A 10.10.27.17
+biganswer.example8. 3600 IN A 10.10.27.18
+biganswer.example8. 3600 IN A 10.10.27.19
+biganswer.example8. 3600 IN A 10.10.27.20
+biganswer.example8. 3600 IN A 10.10.27.21
+biganswer.example8. 3600 IN A 10.10.27.22
+biganswer.example8. 3600 IN A 10.10.27.23
+biganswer.example8. 3600 IN A 10.10.27.24
+biganswer.example8. 3600 IN A 10.10.27.25
+biganswer.example8. 3600 IN A 10.10.27.26
+biganswer.example8. 3600 IN A 10.10.27.27
+biganswer.example8. 3600 IN A 10.10.27.28
+biganswer.example8. 3600 IN A 10.10.27.29
+biganswer.example8. 3600 IN A 10.10.27.30
+biganswer.example8. 3600 IN A 10.10.27.31
+biganswer.example8. 3600 IN A 10.10.27.32
+biganswer.example8. 3600 IN A 10.10.27.33
+biganswer.example8. 3600 IN A 10.10.27.34
+biganswer.example8. 3600 IN A 10.10.27.35
+biganswer.example8. 3600 IN A 10.10.27.36
+biganswer.example8. 3600 IN A 10.10.27.37
+biganswer.example8. 3600 IN A 10.10.27.38
+biganswer.example8. 3600 IN A 10.10.27.39
+biganswer.example8. 3600 IN A 10.10.27.40
+biganswer.example8. 3600 IN A 10.10.27.41
+biganswer.example8. 3600 IN A 10.10.27.42
+biganswer.example8. 3600 IN A 10.10.27.43
+biganswer.example8. 3600 IN A 10.10.27.44
+biganswer.example8. 3600 IN A 10.10.27.45
+biganswer.example8. 3600 IN A 10.10.27.46
+biganswer.example8. 3600 IN A 10.10.27.47
+biganswer.example8. 3600 IN A 10.10.27.48
+biganswer.example8. 3600 IN A 10.10.27.49
+biganswer.example8. 3600 IN A 10.10.27.50
+biganswer.example8. 3600 IN A 10.10.28.1
+biganswer.example8. 3600 IN A 10.10.28.2
+biganswer.example8. 3600 IN A 10.10.28.3
+biganswer.example8. 3600 IN A 10.10.28.4
+biganswer.example8. 3600 IN A 10.10.28.5
+biganswer.example8. 3600 IN A 10.10.28.6
+biganswer.example8. 3600 IN A 10.10.28.7
+biganswer.example8. 3600 IN A 10.10.28.8
+biganswer.example8. 3600 IN A 10.10.28.9
+biganswer.example8. 3600 IN A 10.10.28.10
+biganswer.example8. 3600 IN A 10.10.28.11
+biganswer.example8. 3600 IN A 10.10.28.12
+biganswer.example8. 3600 IN A 10.10.28.13
+biganswer.example8. 3600 IN A 10.10.28.14
+biganswer.example8. 3600 IN A 10.10.28.15
+biganswer.example8. 3600 IN A 10.10.28.16
+biganswer.example8. 3600 IN A 10.10.28.17
+biganswer.example8. 3600 IN A 10.10.28.18
+biganswer.example8. 3600 IN A 10.10.28.19
+biganswer.example8. 3600 IN A 10.10.28.20
+biganswer.example8. 3600 IN A 10.10.28.21
+biganswer.example8. 3600 IN A 10.10.28.22
+biganswer.example8. 3600 IN A 10.10.28.23
+biganswer.example8. 3600 IN A 10.10.28.24
+biganswer.example8. 3600 IN A 10.10.28.25
+biganswer.example8. 3600 IN A 10.10.28.26
+biganswer.example8. 3600 IN A 10.10.28.27
+biganswer.example8. 3600 IN A 10.10.28.28
+biganswer.example8. 3600 IN A 10.10.28.29
+biganswer.example8. 3600 IN A 10.10.28.30
+biganswer.example8. 3600 IN A 10.10.28.31
+biganswer.example8. 3600 IN A 10.10.28.32
+biganswer.example8. 3600 IN A 10.10.28.33
+biganswer.example8. 3600 IN A 10.10.28.34
+biganswer.example8. 3600 IN A 10.10.28.35
+biganswer.example8. 3600 IN A 10.10.28.36
+biganswer.example8. 3600 IN A 10.10.28.37
+biganswer.example8. 3600 IN A 10.10.28.38
+biganswer.example8. 3600 IN A 10.10.28.39
+biganswer.example8. 3600 IN A 10.10.28.40
+biganswer.example8. 3600 IN A 10.10.28.41
+biganswer.example8. 3600 IN A 10.10.28.42
+biganswer.example8. 3600 IN A 10.10.28.43
+biganswer.example8. 3600 IN A 10.10.28.44
+biganswer.example8. 3600 IN A 10.10.28.45
+biganswer.example8. 3600 IN A 10.10.28.46
+biganswer.example8. 3600 IN A 10.10.28.47
+biganswer.example8. 3600 IN A 10.10.28.48
+biganswer.example8. 3600 IN A 10.10.28.49
+biganswer.example8. 3600 IN A 10.10.28.50
+biganswer.example8. 3600 IN A 10.10.29.1
+biganswer.example8. 3600 IN A 10.10.29.2
+biganswer.example8. 3600 IN A 10.10.29.3
+biganswer.example8. 3600 IN A 10.10.29.4
+biganswer.example8. 3600 IN A 10.10.29.5
+biganswer.example8. 3600 IN A 10.10.29.6
+biganswer.example8. 3600 IN A 10.10.29.7
+biganswer.example8. 3600 IN A 10.10.29.8
+biganswer.example8. 3600 IN A 10.10.29.9
+biganswer.example8. 3600 IN A 10.10.29.10
+biganswer.example8. 3600 IN A 10.10.29.11
+biganswer.example8. 3600 IN A 10.10.29.12
+biganswer.example8. 3600 IN A 10.10.29.13
+biganswer.example8. 3600 IN A 10.10.29.14
+biganswer.example8. 3600 IN A 10.10.29.15
+biganswer.example8. 3600 IN A 10.10.29.16
+biganswer.example8. 3600 IN A 10.10.29.17
+biganswer.example8. 3600 IN A 10.10.29.18
+biganswer.example8. 3600 IN A 10.10.29.19
+biganswer.example8. 3600 IN A 10.10.29.20
+biganswer.example8. 3600 IN A 10.10.29.21
+biganswer.example8. 3600 IN A 10.10.29.22
+biganswer.example8. 3600 IN A 10.10.29.23
+biganswer.example8. 3600 IN A 10.10.29.24
+biganswer.example8. 3600 IN A 10.10.29.25
+biganswer.example8. 3600 IN A 10.10.29.26
+biganswer.example8. 3600 IN A 10.10.29.27
+biganswer.example8. 3600 IN A 10.10.29.28
+biganswer.example8. 3600 IN A 10.10.29.29
+biganswer.example8. 3600 IN A 10.10.29.30
+biganswer.example8. 3600 IN A 10.10.29.31
+biganswer.example8. 3600 IN A 10.10.29.32
+biganswer.example8. 3600 IN A 10.10.29.33
+biganswer.example8. 3600 IN A 10.10.29.34
+biganswer.example8. 3600 IN A 10.10.29.35
+biganswer.example8. 3600 IN A 10.10.29.36
+biganswer.example8. 3600 IN A 10.10.29.37
+biganswer.example8. 3600 IN A 10.10.29.38
+biganswer.example8. 3600 IN A 10.10.29.39
+biganswer.example8. 3600 IN A 10.10.29.40
+biganswer.example8. 3600 IN A 10.10.29.41
+biganswer.example8. 3600 IN A 10.10.29.42
+biganswer.example8. 3600 IN A 10.10.29.43
+biganswer.example8. 3600 IN A 10.10.29.44
+biganswer.example8. 3600 IN A 10.10.29.45
+biganswer.example8. 3600 IN A 10.10.29.46
+biganswer.example8. 3600 IN A 10.10.29.47
+biganswer.example8. 3600 IN A 10.10.29.48
+biganswer.example8. 3600 IN A 10.10.29.49
+biganswer.example8. 3600 IN A 10.10.29.50
+biganswer.example8. 3600 IN A 10.10.30.1
+biganswer.example8. 3600 IN A 10.10.30.2
+biganswer.example8. 3600 IN A 10.10.30.3
+biganswer.example8. 3600 IN A 10.10.30.4
+biganswer.example8. 3600 IN A 10.10.30.5
+biganswer.example8. 3600 IN A 10.10.30.6
+biganswer.example8. 3600 IN A 10.10.30.7
+biganswer.example8. 3600 IN A 10.10.30.8
+biganswer.example8. 3600 IN A 10.10.30.9
+biganswer.example8. 3600 IN A 10.10.30.10
+biganswer.example8. 3600 IN A 10.10.30.11
+biganswer.example8. 3600 IN A 10.10.30.12
+biganswer.example8. 3600 IN A 10.10.30.13
+biganswer.example8. 3600 IN A 10.10.30.14
+biganswer.example8. 3600 IN A 10.10.30.15
+biganswer.example8. 3600 IN A 10.10.30.16
+biganswer.example8. 3600 IN A 10.10.30.17
+biganswer.example8. 3600 IN A 10.10.30.18
+biganswer.example8. 3600 IN A 10.10.30.19
+biganswer.example8. 3600 IN A 10.10.30.20
+biganswer.example8. 3600 IN A 10.10.30.21
+biganswer.example8. 3600 IN A 10.10.30.22
+biganswer.example8. 3600 IN A 10.10.30.23
+biganswer.example8. 3600 IN A 10.10.30.24
+biganswer.example8. 3600 IN A 10.10.30.25
+biganswer.example8. 3600 IN A 10.10.30.26
+biganswer.example8. 3600 IN A 10.10.30.27
+biganswer.example8. 3600 IN A 10.10.30.28
+biganswer.example8. 3600 IN A 10.10.30.29
+biganswer.example8. 3600 IN A 10.10.30.30
+biganswer.example8. 3600 IN A 10.10.30.31
+biganswer.example8. 3600 IN A 10.10.30.32
+biganswer.example8. 3600 IN A 10.10.30.33
+biganswer.example8. 3600 IN A 10.10.30.34
+biganswer.example8. 3600 IN A 10.10.30.35
+biganswer.example8. 3600 IN A 10.10.30.36
+biganswer.example8. 3600 IN A 10.10.30.37
+biganswer.example8. 3600 IN A 10.10.30.38
+biganswer.example8. 3600 IN A 10.10.30.39
+biganswer.example8. 3600 IN A 10.10.30.40
+biganswer.example8. 3600 IN A 10.10.30.41
+biganswer.example8. 3600 IN A 10.10.30.42
+biganswer.example8. 3600 IN A 10.10.30.43
+biganswer.example8. 3600 IN A 10.10.30.44
+biganswer.example8. 3600 IN A 10.10.30.45
+biganswer.example8. 3600 IN A 10.10.30.46
+biganswer.example8. 3600 IN A 10.10.30.47
+biganswer.example8. 3600 IN A 10.10.30.48
+biganswer.example8. 3600 IN A 10.10.30.49
+biganswer.example8. 3600 IN A 10.10.30.50
+biganswer.example8. 3600 IN A 10.10.31.1
+biganswer.example8. 3600 IN A 10.10.31.2
+biganswer.example8. 3600 IN A 10.10.31.3
+biganswer.example8. 3600 IN A 10.10.31.4
+biganswer.example8. 3600 IN A 10.10.31.5
+biganswer.example8. 3600 IN A 10.10.31.6
+biganswer.example8. 3600 IN A 10.10.31.7
+biganswer.example8. 3600 IN A 10.10.31.8
+biganswer.example8. 3600 IN A 10.10.31.9
+biganswer.example8. 3600 IN A 10.10.31.10
+biganswer.example8. 3600 IN A 10.10.31.11
+biganswer.example8. 3600 IN A 10.10.31.12
+biganswer.example8. 3600 IN A 10.10.31.13
+biganswer.example8. 3600 IN A 10.10.31.14
+biganswer.example8. 3600 IN A 10.10.31.15
+biganswer.example8. 3600 IN A 10.10.31.16
+biganswer.example8. 3600 IN A 10.10.31.17
+biganswer.example8. 3600 IN A 10.10.31.18
+biganswer.example8. 3600 IN A 10.10.31.19
+biganswer.example8. 3600 IN A 10.10.31.20
+biganswer.example8. 3600 IN A 10.10.31.21
+biganswer.example8. 3600 IN A 10.10.31.22
+biganswer.example8. 3600 IN A 10.10.31.23
+biganswer.example8. 3600 IN A 10.10.31.24
+biganswer.example8. 3600 IN A 10.10.31.25
+biganswer.example8. 3600 IN A 10.10.31.26
+biganswer.example8. 3600 IN A 10.10.31.27
+biganswer.example8. 3600 IN A 10.10.31.28
+biganswer.example8. 3600 IN A 10.10.31.29
+biganswer.example8. 3600 IN A 10.10.31.30
+biganswer.example8. 3600 IN A 10.10.31.31
+biganswer.example8. 3600 IN A 10.10.31.32
+biganswer.example8. 3600 IN A 10.10.31.33
+biganswer.example8. 3600 IN A 10.10.31.34
+biganswer.example8. 3600 IN A 10.10.31.35
+biganswer.example8. 3600 IN A 10.10.31.36
+biganswer.example8. 3600 IN A 10.10.31.37
+biganswer.example8. 3600 IN A 10.10.31.38
+biganswer.example8. 3600 IN A 10.10.31.39
+biganswer.example8. 3600 IN A 10.10.31.40
+biganswer.example8. 3600 IN A 10.10.31.41
+biganswer.example8. 3600 IN A 10.10.31.42
+biganswer.example8. 3600 IN A 10.10.31.43
+biganswer.example8. 3600 IN A 10.10.31.44
+biganswer.example8. 3600 IN A 10.10.31.45
+biganswer.example8. 3600 IN A 10.10.31.46
+biganswer.example8. 3600 IN A 10.10.31.47
+biganswer.example8. 3600 IN A 10.10.31.48
+biganswer.example8. 3600 IN A 10.10.31.49
+biganswer.example8. 3600 IN A 10.10.31.50
+biganswer.example8. 3600 IN A 10.10.32.1
+biganswer.example8. 3600 IN A 10.10.32.2
+biganswer.example8. 3600 IN A 10.10.32.3
+biganswer.example8. 3600 IN A 10.10.32.4
+biganswer.example8. 3600 IN A 10.10.32.5
+biganswer.example8. 3600 IN A 10.10.32.6
+biganswer.example8. 3600 IN A 10.10.32.7
+biganswer.example8. 3600 IN A 10.10.32.8
+biganswer.example8. 3600 IN A 10.10.32.9
+biganswer.example8. 3600 IN A 10.10.32.10
+biganswer.example8. 3600 IN A 10.10.32.11
+biganswer.example8. 3600 IN A 10.10.32.12
+biganswer.example8. 3600 IN A 10.10.32.13
+biganswer.example8. 3600 IN A 10.10.32.14
+biganswer.example8. 3600 IN A 10.10.32.15
+biganswer.example8. 3600 IN A 10.10.32.16
+biganswer.example8. 3600 IN A 10.10.32.17
+biganswer.example8. 3600 IN A 10.10.32.18
+biganswer.example8. 3600 IN A 10.10.32.19
+biganswer.example8. 3600 IN A 10.10.32.20
+biganswer.example8. 3600 IN A 10.10.32.21
+biganswer.example8. 3600 IN A 10.10.32.22
+biganswer.example8. 3600 IN A 10.10.32.23
+biganswer.example8. 3600 IN A 10.10.32.24
+biganswer.example8. 3600 IN A 10.10.32.25
+biganswer.example8. 3600 IN A 10.10.32.26
+biganswer.example8. 3600 IN A 10.10.32.27
+biganswer.example8. 3600 IN A 10.10.32.28
+biganswer.example8. 3600 IN A 10.10.32.29
+biganswer.example8. 3600 IN A 10.10.32.30
+biganswer.example8. 3600 IN A 10.10.32.31
+biganswer.example8. 3600 IN A 10.10.32.32
+biganswer.example8. 3600 IN A 10.10.32.33
+biganswer.example8. 3600 IN A 10.10.32.34
+biganswer.example8. 3600 IN A 10.10.32.35
+biganswer.example8. 3600 IN A 10.10.32.36
+biganswer.example8. 3600 IN A 10.10.32.37
+biganswer.example8. 3600 IN A 10.10.32.38
+biganswer.example8. 3600 IN A 10.10.32.39
+biganswer.example8. 3600 IN A 10.10.32.40
+biganswer.example8. 3600 IN A 10.10.32.41
+biganswer.example8. 3600 IN A 10.10.32.42
+biganswer.example8. 3600 IN A 10.10.32.43
+biganswer.example8. 3600 IN A 10.10.32.44
+biganswer.example8. 3600 IN A 10.10.32.45
+biganswer.example8. 3600 IN A 10.10.32.46
+biganswer.example8. 3600 IN A 10.10.32.47
+biganswer.example8. 3600 IN A 10.10.32.48
+biganswer.example8. 3600 IN A 10.10.32.49
+biganswer.example8. 3600 IN A 10.10.32.50
+biganswer.example8. 3600 IN A 10.10.33.1
+biganswer.example8. 3600 IN A 10.10.33.2
+biganswer.example8. 3600 IN A 10.10.33.3
+biganswer.example8. 3600 IN A 10.10.33.4
+biganswer.example8. 3600 IN A 10.10.33.5
+biganswer.example8. 3600 IN A 10.10.33.6
+biganswer.example8. 3600 IN A 10.10.33.7
+biganswer.example8. 3600 IN A 10.10.33.8
+biganswer.example8. 3600 IN A 10.10.33.9
+biganswer.example8. 3600 IN A 10.10.33.10
+biganswer.example8. 3600 IN A 10.10.33.11
+biganswer.example8. 3600 IN A 10.10.33.12
+biganswer.example8. 3600 IN A 10.10.33.13
+biganswer.example8. 3600 IN A 10.10.33.14
+biganswer.example8. 3600 IN A 10.10.33.15
+biganswer.example8. 3600 IN A 10.10.33.16
+biganswer.example8. 3600 IN A 10.10.33.17
+biganswer.example8. 3600 IN A 10.10.33.18
+biganswer.example8. 3600 IN A 10.10.33.19
+biganswer.example8. 3600 IN A 10.10.33.20
+biganswer.example8. 3600 IN A 10.10.33.21
+biganswer.example8. 3600 IN A 10.10.33.22
+biganswer.example8. 3600 IN A 10.10.33.23
+biganswer.example8. 3600 IN A 10.10.33.24
+biganswer.example8. 3600 IN A 10.10.33.25
+biganswer.example8. 3600 IN A 10.10.33.26
+biganswer.example8. 3600 IN A 10.10.33.27
+biganswer.example8. 3600 IN A 10.10.33.28
+biganswer.example8. 3600 IN A 10.10.33.29
+biganswer.example8. 3600 IN A 10.10.33.30
+biganswer.example8. 3600 IN A 10.10.33.31
+biganswer.example8. 3600 IN A 10.10.33.32
+biganswer.example8. 3600 IN A 10.10.33.33
+biganswer.example8. 3600 IN A 10.10.33.34
+biganswer.example8. 3600 IN A 10.10.33.35
+biganswer.example8. 3600 IN A 10.10.33.36
+biganswer.example8. 3600 IN A 10.10.33.37
+biganswer.example8. 3600 IN A 10.10.33.38
+biganswer.example8. 3600 IN A 10.10.33.39
+biganswer.example8. 3600 IN A 10.10.33.40
+biganswer.example8. 3600 IN A 10.10.33.41
+biganswer.example8. 3600 IN A 10.10.33.42
+biganswer.example8. 3600 IN A 10.10.33.43
+biganswer.example8. 3600 IN A 10.10.33.44
+biganswer.example8. 3600 IN A 10.10.33.45
+biganswer.example8. 3600 IN A 10.10.33.46
+biganswer.example8. 3600 IN A 10.10.33.47
+biganswer.example8. 3600 IN A 10.10.33.48
+biganswer.example8. 3600 IN A 10.10.33.49
+biganswer.example8. 3600 IN A 10.10.33.50
+biganswer.example8. 3600 IN A 10.10.34.1
+biganswer.example8. 3600 IN A 10.10.34.2
+biganswer.example8. 3600 IN A 10.10.34.3
+biganswer.example8. 3600 IN A 10.10.34.4
+biganswer.example8. 3600 IN A 10.10.34.5
+biganswer.example8. 3600 IN A 10.10.34.6
+biganswer.example8. 3600 IN A 10.10.34.7
+biganswer.example8. 3600 IN A 10.10.34.8
+biganswer.example8. 3600 IN A 10.10.34.9
+biganswer.example8. 3600 IN A 10.10.34.10
+biganswer.example8. 3600 IN A 10.10.34.11
+biganswer.example8. 3600 IN A 10.10.34.12
+biganswer.example8. 3600 IN A 10.10.34.13
+biganswer.example8. 3600 IN A 10.10.34.14
+biganswer.example8. 3600 IN A 10.10.34.15
+biganswer.example8. 3600 IN A 10.10.34.16
+biganswer.example8. 3600 IN A 10.10.34.17
+biganswer.example8. 3600 IN A 10.10.34.18
+biganswer.example8. 3600 IN A 10.10.34.19
+biganswer.example8. 3600 IN A 10.10.34.20
+biganswer.example8. 3600 IN A 10.10.34.21
+biganswer.example8. 3600 IN A 10.10.34.22
+biganswer.example8. 3600 IN A 10.10.34.23
+biganswer.example8. 3600 IN A 10.10.34.24
+biganswer.example8. 3600 IN A 10.10.34.25
+biganswer.example8. 3600 IN A 10.10.34.26
+biganswer.example8. 3600 IN A 10.10.34.27
+biganswer.example8. 3600 IN A 10.10.34.28
+biganswer.example8. 3600 IN A 10.10.34.29
+biganswer.example8. 3600 IN A 10.10.34.30
+biganswer.example8. 3600 IN A 10.10.34.31
+biganswer.example8. 3600 IN A 10.10.34.32
+biganswer.example8. 3600 IN A 10.10.34.33
+biganswer.example8. 3600 IN A 10.10.34.34
+biganswer.example8. 3600 IN A 10.10.34.35
+biganswer.example8. 3600 IN A 10.10.34.36
+biganswer.example8. 3600 IN A 10.10.34.37
+biganswer.example8. 3600 IN A 10.10.34.38
+biganswer.example8. 3600 IN A 10.10.34.39
+biganswer.example8. 3600 IN A 10.10.34.40
+biganswer.example8. 3600 IN A 10.10.34.41
+biganswer.example8. 3600 IN A 10.10.34.42
+biganswer.example8. 3600 IN A 10.10.34.43
+biganswer.example8. 3600 IN A 10.10.34.44
+biganswer.example8. 3600 IN A 10.10.34.45
+biganswer.example8. 3600 IN A 10.10.34.46
+biganswer.example8. 3600 IN A 10.10.34.47
+biganswer.example8. 3600 IN A 10.10.34.48
+biganswer.example8. 3600 IN A 10.10.34.49
+biganswer.example8. 3600 IN A 10.10.34.50
+biganswer.example8. 3600 IN A 10.10.35.1
+biganswer.example8. 3600 IN A 10.10.35.2
+biganswer.example8. 3600 IN A 10.10.35.3
+biganswer.example8. 3600 IN A 10.10.35.4
+biganswer.example8. 3600 IN A 10.10.35.5
+biganswer.example8. 3600 IN A 10.10.35.6
+biganswer.example8. 3600 IN A 10.10.35.7
+biganswer.example8. 3600 IN A 10.10.35.8
+biganswer.example8. 3600 IN A 10.10.35.9
+biganswer.example8. 3600 IN A 10.10.35.10
+biganswer.example8. 3600 IN A 10.10.35.11
+biganswer.example8. 3600 IN A 10.10.35.12
+biganswer.example8. 3600 IN A 10.10.35.13
+biganswer.example8. 3600 IN A 10.10.35.14
+biganswer.example8. 3600 IN A 10.10.35.15
+biganswer.example8. 3600 IN A 10.10.35.16
+biganswer.example8. 3600 IN A 10.10.35.17
+biganswer.example8. 3600 IN A 10.10.35.18
+biganswer.example8. 3600 IN A 10.10.35.19
+biganswer.example8. 3600 IN A 10.10.35.20
+biganswer.example8. 3600 IN A 10.10.35.21
+biganswer.example8. 3600 IN A 10.10.35.22
+biganswer.example8. 3600 IN A 10.10.35.23
+biganswer.example8. 3600 IN A 10.10.35.24
+biganswer.example8. 3600 IN A 10.10.35.25
+biganswer.example8. 3600 IN A 10.10.35.26
+biganswer.example8. 3600 IN A 10.10.35.27
+biganswer.example8. 3600 IN A 10.10.35.28
+biganswer.example8. 3600 IN A 10.10.35.29
+biganswer.example8. 3600 IN A 10.10.35.30
+biganswer.example8. 3600 IN A 10.10.35.31
+biganswer.example8. 3600 IN A 10.10.35.32
+biganswer.example8. 3600 IN A 10.10.35.33
+biganswer.example8. 3600 IN A 10.10.35.34
+biganswer.example8. 3600 IN A 10.10.35.35
+biganswer.example8. 3600 IN A 10.10.35.36
+biganswer.example8. 3600 IN A 10.10.35.37
+biganswer.example8. 3600 IN A 10.10.35.38
+biganswer.example8. 3600 IN A 10.10.35.39
+biganswer.example8. 3600 IN A 10.10.35.40
+biganswer.example8. 3600 IN A 10.10.35.41
+biganswer.example8. 3600 IN A 10.10.35.42
+biganswer.example8. 3600 IN A 10.10.35.43
+biganswer.example8. 3600 IN A 10.10.35.44
+biganswer.example8. 3600 IN A 10.10.35.45
+biganswer.example8. 3600 IN A 10.10.35.46
+biganswer.example8. 3600 IN A 10.10.35.47
+biganswer.example8. 3600 IN A 10.10.35.48
+biganswer.example8. 3600 IN A 10.10.35.49
+biganswer.example8. 3600 IN A 10.10.35.50
+biganswer.example8. 3600 IN A 10.10.36.1
+biganswer.example8. 3600 IN A 10.10.36.2
+biganswer.example8. 3600 IN A 10.10.36.3
+biganswer.example8. 3600 IN A 10.10.36.4
+biganswer.example8. 3600 IN A 10.10.36.5
+biganswer.example8. 3600 IN A 10.10.36.6
+biganswer.example8. 3600 IN A 10.10.36.7
+biganswer.example8. 3600 IN A 10.10.36.8
+biganswer.example8. 3600 IN A 10.10.36.9
+biganswer.example8. 3600 IN A 10.10.36.10
+biganswer.example8. 3600 IN A 10.10.36.11
+biganswer.example8. 3600 IN A 10.10.36.12
+biganswer.example8. 3600 IN A 10.10.36.13
+biganswer.example8. 3600 IN A 10.10.36.14
+biganswer.example8. 3600 IN A 10.10.36.15
+biganswer.example8. 3600 IN A 10.10.36.16
+biganswer.example8. 3600 IN A 10.10.36.17
+biganswer.example8. 3600 IN A 10.10.36.18
+biganswer.example8. 3600 IN A 10.10.36.19
+biganswer.example8. 3600 IN A 10.10.36.20
+biganswer.example8. 3600 IN A 10.10.36.21
+biganswer.example8. 3600 IN A 10.10.36.22
+biganswer.example8. 3600 IN A 10.10.36.23
+biganswer.example8. 3600 IN A 10.10.36.24
+biganswer.example8. 3600 IN A 10.10.36.25
+biganswer.example8. 3600 IN A 10.10.36.26
+biganswer.example8. 3600 IN A 10.10.36.27
+biganswer.example8. 3600 IN A 10.10.36.28
+biganswer.example8. 3600 IN A 10.10.36.29
+biganswer.example8. 3600 IN A 10.10.36.30
+biganswer.example8. 3600 IN A 10.10.36.31
+biganswer.example8. 3600 IN A 10.10.36.32
+biganswer.example8. 3600 IN A 10.10.36.33
+biganswer.example8. 3600 IN A 10.10.36.34
+biganswer.example8. 3600 IN A 10.10.36.35
+biganswer.example8. 3600 IN A 10.10.36.36
+biganswer.example8. 3600 IN A 10.10.36.37
+biganswer.example8. 3600 IN A 10.10.36.38
+biganswer.example8. 3600 IN A 10.10.36.39
+biganswer.example8. 3600 IN A 10.10.36.40
+biganswer.example8. 3600 IN A 10.10.36.41
+biganswer.example8. 3600 IN A 10.10.36.42
+biganswer.example8. 3600 IN A 10.10.36.43
+biganswer.example8. 3600 IN A 10.10.36.44
+biganswer.example8. 3600 IN A 10.10.36.45
+biganswer.example8. 3600 IN A 10.10.36.46
+biganswer.example8. 3600 IN A 10.10.36.47
+biganswer.example8. 3600 IN A 10.10.36.48
+biganswer.example8. 3600 IN A 10.10.36.49
+biganswer.example8. 3600 IN A 10.10.36.50
+biganswer.example8. 3600 IN A 10.10.37.1
+biganswer.example8. 3600 IN A 10.10.37.2
+biganswer.example8. 3600 IN A 10.10.37.3
+biganswer.example8. 3600 IN A 10.10.37.4
+biganswer.example8. 3600 IN A 10.10.37.5
+biganswer.example8. 3600 IN A 10.10.37.6
+biganswer.example8. 3600 IN A 10.10.37.7
+biganswer.example8. 3600 IN A 10.10.37.8
+biganswer.example8. 3600 IN A 10.10.37.9
+biganswer.example8. 3600 IN A 10.10.37.10
+biganswer.example8. 3600 IN A 10.10.37.11
+biganswer.example8. 3600 IN A 10.10.37.12
+biganswer.example8. 3600 IN A 10.10.37.13
+biganswer.example8. 3600 IN A 10.10.37.14
+biganswer.example8. 3600 IN A 10.10.37.15
+biganswer.example8. 3600 IN A 10.10.37.16
+biganswer.example8. 3600 IN A 10.10.37.17
+biganswer.example8. 3600 IN A 10.10.37.18
+biganswer.example8. 3600 IN A 10.10.37.19
+biganswer.example8. 3600 IN A 10.10.37.20
+biganswer.example8. 3600 IN A 10.10.37.21
+biganswer.example8. 3600 IN A 10.10.37.22
+biganswer.example8. 3600 IN A 10.10.37.23
+biganswer.example8. 3600 IN A 10.10.37.24
+biganswer.example8. 3600 IN A 10.10.37.25
+biganswer.example8. 3600 IN A 10.10.37.26
+biganswer.example8. 3600 IN A 10.10.37.27
+biganswer.example8. 3600 IN A 10.10.37.28
+biganswer.example8. 3600 IN A 10.10.37.29
+biganswer.example8. 3600 IN A 10.10.37.30
+biganswer.example8. 3600 IN A 10.10.37.31
+biganswer.example8. 3600 IN A 10.10.37.32
+biganswer.example8. 3600 IN A 10.10.37.33
+biganswer.example8. 3600 IN A 10.10.37.34
+biganswer.example8. 3600 IN A 10.10.37.35
+biganswer.example8. 3600 IN A 10.10.37.36
+biganswer.example8. 3600 IN A 10.10.37.37
+biganswer.example8. 3600 IN A 10.10.37.38
+biganswer.example8. 3600 IN A 10.10.37.39
+biganswer.example8. 3600 IN A 10.10.37.40
+biganswer.example8. 3600 IN A 10.10.37.41
+biganswer.example8. 3600 IN A 10.10.37.42
+biganswer.example8. 3600 IN A 10.10.37.43
+biganswer.example8. 3600 IN A 10.10.37.44
+biganswer.example8. 3600 IN A 10.10.37.45
+biganswer.example8. 3600 IN A 10.10.37.46
+biganswer.example8. 3600 IN A 10.10.37.47
+biganswer.example8. 3600 IN A 10.10.37.48
+biganswer.example8. 3600 IN A 10.10.37.49
+biganswer.example8. 3600 IN A 10.10.37.50
+biganswer.example8. 3600 IN A 10.10.38.1
+biganswer.example8. 3600 IN A 10.10.38.2
+biganswer.example8. 3600 IN A 10.10.38.3
+biganswer.example8. 3600 IN A 10.10.38.4
+biganswer.example8. 3600 IN A 10.10.38.5
+biganswer.example8. 3600 IN A 10.10.38.6
+biganswer.example8. 3600 IN A 10.10.38.7
+biganswer.example8. 3600 IN A 10.10.38.8
+biganswer.example8. 3600 IN A 10.10.38.9
+biganswer.example8. 3600 IN A 10.10.38.10
+biganswer.example8. 3600 IN A 10.10.38.11
+biganswer.example8. 3600 IN A 10.10.38.12
+biganswer.example8. 3600 IN A 10.10.38.13
+biganswer.example8. 3600 IN A 10.10.38.14
+biganswer.example8. 3600 IN A 10.10.38.15
+biganswer.example8. 3600 IN A 10.10.38.16
+biganswer.example8. 3600 IN A 10.10.38.17
+biganswer.example8. 3600 IN A 10.10.38.18
+biganswer.example8. 3600 IN A 10.10.38.19
+biganswer.example8. 3600 IN A 10.10.38.20
+biganswer.example8. 3600 IN A 10.10.38.21
+biganswer.example8. 3600 IN A 10.10.38.22
+biganswer.example8. 3600 IN A 10.10.38.23
+biganswer.example8. 3600 IN A 10.10.38.24
+biganswer.example8. 3600 IN A 10.10.38.25
+biganswer.example8. 3600 IN A 10.10.38.26
+biganswer.example8. 3600 IN A 10.10.38.27
+biganswer.example8. 3600 IN A 10.10.38.28
+biganswer.example8. 3600 IN A 10.10.38.29
+biganswer.example8. 3600 IN A 10.10.38.30
+biganswer.example8. 3600 IN A 10.10.38.31
+biganswer.example8. 3600 IN A 10.10.38.32
+biganswer.example8. 3600 IN A 10.10.38.33
+biganswer.example8. 3600 IN A 10.10.38.34
+biganswer.example8. 3600 IN A 10.10.38.35
+biganswer.example8. 3600 IN A 10.10.38.36
+biganswer.example8. 3600 IN A 10.10.38.37
+biganswer.example8. 3600 IN A 10.10.38.38
+biganswer.example8. 3600 IN A 10.10.38.39
+biganswer.example8. 3600 IN A 10.10.38.40
+biganswer.example8. 3600 IN A 10.10.38.41
+biganswer.example8. 3600 IN A 10.10.38.42
+biganswer.example8. 3600 IN A 10.10.38.43
+biganswer.example8. 3600 IN A 10.10.38.44
+biganswer.example8. 3600 IN A 10.10.38.45
+biganswer.example8. 3600 IN A 10.10.38.46
+biganswer.example8. 3600 IN A 10.10.38.47
+biganswer.example8. 3600 IN A 10.10.38.48
+biganswer.example8. 3600 IN A 10.10.38.49
+biganswer.example8. 3600 IN A 10.10.38.50
+biganswer.example8. 3600 IN A 10.10.39.1
+biganswer.example8. 3600 IN A 10.10.39.2
+biganswer.example8. 3600 IN A 10.10.39.3
+biganswer.example8. 3600 IN A 10.10.39.4
+biganswer.example8. 3600 IN A 10.10.39.5
+biganswer.example8. 3600 IN A 10.10.39.6
+biganswer.example8. 3600 IN A 10.10.39.7
+biganswer.example8. 3600 IN A 10.10.39.8
+biganswer.example8. 3600 IN A 10.10.39.9
+biganswer.example8. 3600 IN A 10.10.39.10
+biganswer.example8. 3600 IN A 10.10.39.11
+biganswer.example8. 3600 IN A 10.10.39.12
+biganswer.example8. 3600 IN A 10.10.39.13
+biganswer.example8. 3600 IN A 10.10.39.14
+biganswer.example8. 3600 IN A 10.10.39.15
+biganswer.example8. 3600 IN A 10.10.39.16
+biganswer.example8. 3600 IN A 10.10.39.17
+biganswer.example8. 3600 IN A 10.10.39.18
+biganswer.example8. 3600 IN A 10.10.39.19
+biganswer.example8. 3600 IN A 10.10.39.20
+biganswer.example8. 3600 IN A 10.10.39.21
+biganswer.example8. 3600 IN A 10.10.39.22
+biganswer.example8. 3600 IN A 10.10.39.23
+biganswer.example8. 3600 IN A 10.10.39.24
+biganswer.example8. 3600 IN A 10.10.39.25
+biganswer.example8. 3600 IN A 10.10.39.26
+biganswer.example8. 3600 IN A 10.10.39.27
+biganswer.example8. 3600 IN A 10.10.39.28
+biganswer.example8. 3600 IN A 10.10.39.29
+biganswer.example8. 3600 IN A 10.10.39.30
+biganswer.example8. 3600 IN A 10.10.39.31
+biganswer.example8. 3600 IN A 10.10.39.32
+biganswer.example8. 3600 IN A 10.10.39.33
+biganswer.example8. 3600 IN A 10.10.39.34
+biganswer.example8. 3600 IN A 10.10.39.35
+biganswer.example8. 3600 IN A 10.10.39.36
+biganswer.example8. 3600 IN A 10.10.39.37
+biganswer.example8. 3600 IN A 10.10.39.38
+biganswer.example8. 3600 IN A 10.10.39.39
+biganswer.example8. 3600 IN A 10.10.39.40
+biganswer.example8. 3600 IN A 10.10.39.41
+biganswer.example8. 3600 IN A 10.10.39.42
+biganswer.example8. 3600 IN A 10.10.39.43
+biganswer.example8. 3600 IN A 10.10.39.44
+biganswer.example8. 3600 IN A 10.10.39.45
+biganswer.example8. 3600 IN A 10.10.39.46
+biganswer.example8. 3600 IN A 10.10.39.47
+biganswer.example8. 3600 IN A 10.10.39.48
+biganswer.example8. 3600 IN A 10.10.39.49
+biganswer.example8. 3600 IN A 10.10.39.50
+biganswer.example8. 3600 IN A 10.10.40.1
+biganswer.example8. 3600 IN A 10.10.40.2
+biganswer.example8. 3600 IN A 10.10.40.3
+biganswer.example8. 3600 IN A 10.10.40.4
+biganswer.example8. 3600 IN A 10.10.40.5
+biganswer.example8. 3600 IN A 10.10.40.6
+biganswer.example8. 3600 IN A 10.10.40.7
+biganswer.example8. 3600 IN A 10.10.40.8
+biganswer.example8. 3600 IN A 10.10.40.9
+biganswer.example8. 3600 IN A 10.10.40.10
+biganswer.example8. 3600 IN A 10.10.40.11
+biganswer.example8. 3600 IN A 10.10.40.12
+biganswer.example8. 3600 IN A 10.10.40.13
+biganswer.example8. 3600 IN A 10.10.40.14
+biganswer.example8. 3600 IN A 10.10.40.15
+biganswer.example8. 3600 IN A 10.10.40.16
+biganswer.example8. 3600 IN A 10.10.40.17
+biganswer.example8. 3600 IN A 10.10.40.18
+biganswer.example8. 3600 IN A 10.10.40.19
+biganswer.example8. 3600 IN A 10.10.40.20
+biganswer.example8. 3600 IN A 10.10.40.21
+biganswer.example8. 3600 IN A 10.10.40.22
+biganswer.example8. 3600 IN A 10.10.40.23
+biganswer.example8. 3600 IN A 10.10.40.24
+biganswer.example8. 3600 IN A 10.10.40.25
+biganswer.example8. 3600 IN A 10.10.40.26
+biganswer.example8. 3600 IN A 10.10.40.27
+biganswer.example8. 3600 IN A 10.10.40.28
+biganswer.example8. 3600 IN A 10.10.40.29
+biganswer.example8. 3600 IN A 10.10.40.30
+biganswer.example8. 3600 IN A 10.10.40.31
+biganswer.example8. 3600 IN A 10.10.40.32
+biganswer.example8. 3600 IN A 10.10.40.33
+biganswer.example8. 3600 IN A 10.10.40.34
+biganswer.example8. 3600 IN A 10.10.40.35
+biganswer.example8. 3600 IN A 10.10.40.36
+biganswer.example8. 3600 IN A 10.10.40.37
+biganswer.example8. 3600 IN A 10.10.40.38
+biganswer.example8. 3600 IN A 10.10.40.39
+biganswer.example8. 3600 IN A 10.10.40.40
+biganswer.example8. 3600 IN A 10.10.40.41
+biganswer.example8. 3600 IN A 10.10.40.42
+biganswer.example8. 3600 IN A 10.10.40.43
+biganswer.example8. 3600 IN A 10.10.40.44
+biganswer.example8. 3600 IN A 10.10.40.45
+biganswer.example8. 3600 IN A 10.10.40.46
+biganswer.example8. 3600 IN A 10.10.40.47
+biganswer.example8. 3600 IN A 10.10.40.48
+biganswer.example8. 3600 IN A 10.10.40.49
+biganswer.example8. 3600 IN A 10.10.40.50
+biganswer.example8. 3600 IN A 10.10.41.1
+biganswer.example8. 3600 IN A 10.10.41.2
+biganswer.example8. 3600 IN A 10.10.41.3
+biganswer.example8. 3600 IN A 10.10.41.4
+biganswer.example8. 3600 IN A 10.10.41.5
+biganswer.example8. 3600 IN A 10.10.41.6
+biganswer.example8. 3600 IN A 10.10.41.7
+biganswer.example8. 3600 IN A 10.10.41.8
+biganswer.example8. 3600 IN A 10.10.41.9
+biganswer.example8. 3600 IN A 10.10.41.10
+biganswer.example8. 3600 IN A 10.10.41.11
+biganswer.example8. 3600 IN A 10.10.41.12
+biganswer.example8. 3600 IN A 10.10.41.13
+biganswer.example8. 3600 IN A 10.10.41.14
+biganswer.example8. 3600 IN A 10.10.41.15
+biganswer.example8. 3600 IN A 10.10.41.16
+biganswer.example8. 3600 IN A 10.10.41.17
+biganswer.example8. 3600 IN A 10.10.41.18
+biganswer.example8. 3600 IN A 10.10.41.19
+biganswer.example8. 3600 IN A 10.10.41.20
+biganswer.example8. 3600 IN A 10.10.41.21
+biganswer.example8. 3600 IN A 10.10.41.22
+biganswer.example8. 3600 IN A 10.10.41.23
+biganswer.example8. 3600 IN A 10.10.41.24
+biganswer.example8. 3600 IN A 10.10.41.25
+biganswer.example8. 3600 IN A 10.10.41.26
+biganswer.example8. 3600 IN A 10.10.41.27
+biganswer.example8. 3600 IN A 10.10.41.28
+biganswer.example8. 3600 IN A 10.10.41.29
+biganswer.example8. 3600 IN A 10.10.41.30
+biganswer.example8. 3600 IN A 10.10.41.31
+biganswer.example8. 3600 IN A 10.10.41.32
+biganswer.example8. 3600 IN A 10.10.41.33
+biganswer.example8. 3600 IN A 10.10.41.34
+biganswer.example8. 3600 IN A 10.10.41.35
+biganswer.example8. 3600 IN A 10.10.41.36
+biganswer.example8. 3600 IN A 10.10.41.37
+biganswer.example8. 3600 IN A 10.10.41.38
+biganswer.example8. 3600 IN A 10.10.41.39
+biganswer.example8. 3600 IN A 10.10.41.40
+biganswer.example8. 3600 IN A 10.10.41.41
+biganswer.example8. 3600 IN A 10.10.41.42
+biganswer.example8. 3600 IN A 10.10.41.43
+biganswer.example8. 3600 IN A 10.10.41.44
+biganswer.example8. 3600 IN A 10.10.41.45
+biganswer.example8. 3600 IN A 10.10.41.46
+biganswer.example8. 3600 IN A 10.10.41.47
+biganswer.example8. 3600 IN A 10.10.41.48
+biganswer.example8. 3600 IN A 10.10.41.49
+biganswer.example8. 3600 IN A 10.10.41.50
+biganswer.example8. 3600 IN A 10.10.42.1
+biganswer.example8. 3600 IN A 10.10.42.2
+biganswer.example8. 3600 IN A 10.10.42.3
+biganswer.example8. 3600 IN A 10.10.42.4
+biganswer.example8. 3600 IN A 10.10.42.5
+biganswer.example8. 3600 IN A 10.10.42.6
+biganswer.example8. 3600 IN A 10.10.42.7
+biganswer.example8. 3600 IN A 10.10.42.8
+biganswer.example8. 3600 IN A 10.10.42.9
+biganswer.example8. 3600 IN A 10.10.42.10
+biganswer.example8. 3600 IN A 10.10.42.11
+biganswer.example8. 3600 IN A 10.10.42.12
+biganswer.example8. 3600 IN A 10.10.42.13
+biganswer.example8. 3600 IN A 10.10.42.14
+biganswer.example8. 3600 IN A 10.10.42.15
+biganswer.example8. 3600 IN A 10.10.42.16
+biganswer.example8. 3600 IN A 10.10.42.17
+biganswer.example8. 3600 IN A 10.10.42.18
+biganswer.example8. 3600 IN A 10.10.42.19
+biganswer.example8. 3600 IN A 10.10.42.20
+biganswer.example8. 3600 IN A 10.10.42.21
+biganswer.example8. 3600 IN A 10.10.42.22
+biganswer.example8. 3600 IN A 10.10.42.23
+biganswer.example8. 3600 IN A 10.10.42.24
+biganswer.example8. 3600 IN A 10.10.42.25
+biganswer.example8. 3600 IN A 10.10.42.26
+biganswer.example8. 3600 IN A 10.10.42.27
+biganswer.example8. 3600 IN A 10.10.42.28
+biganswer.example8. 3600 IN A 10.10.42.29
+biganswer.example8. 3600 IN A 10.10.42.30
+biganswer.example8. 3600 IN A 10.10.42.31
+biganswer.example8. 3600 IN A 10.10.42.32
+biganswer.example8. 3600 IN A 10.10.42.33
+biganswer.example8. 3600 IN A 10.10.42.34
+biganswer.example8. 3600 IN A 10.10.42.35
+biganswer.example8. 3600 IN A 10.10.42.36
+biganswer.example8. 3600 IN A 10.10.42.37
+biganswer.example8. 3600 IN A 10.10.42.38
+biganswer.example8. 3600 IN A 10.10.42.39
+biganswer.example8. 3600 IN A 10.10.42.40
+biganswer.example8. 3600 IN A 10.10.42.41
+biganswer.example8. 3600 IN A 10.10.42.42
+biganswer.example8. 3600 IN A 10.10.42.43
+biganswer.example8. 3600 IN A 10.10.42.44
+biganswer.example8. 3600 IN A 10.10.42.45
+biganswer.example8. 3600 IN A 10.10.42.46
+biganswer.example8. 3600 IN A 10.10.42.47
+biganswer.example8. 3600 IN A 10.10.42.48
+biganswer.example8. 3600 IN A 10.10.42.49
+biganswer.example8. 3600 IN A 10.10.42.50
+biganswer.example8. 3600 IN A 10.10.43.1
+biganswer.example8. 3600 IN A 10.10.43.2
+biganswer.example8. 3600 IN A 10.10.43.3
+biganswer.example8. 3600 IN A 10.10.43.4
+biganswer.example8. 3600 IN A 10.10.43.5
+biganswer.example8. 3600 IN A 10.10.43.6
+biganswer.example8. 3600 IN A 10.10.43.7
+biganswer.example8. 3600 IN A 10.10.43.8
+biganswer.example8. 3600 IN A 10.10.43.9
+biganswer.example8. 3600 IN A 10.10.43.10
+biganswer.example8. 3600 IN A 10.10.43.11
+biganswer.example8. 3600 IN A 10.10.43.12
+biganswer.example8. 3600 IN A 10.10.43.13
+biganswer.example8. 3600 IN A 10.10.43.14
+biganswer.example8. 3600 IN A 10.10.43.15
+biganswer.example8. 3600 IN A 10.10.43.16
+biganswer.example8. 3600 IN A 10.10.43.17
+biganswer.example8. 3600 IN A 10.10.43.18
+biganswer.example8. 3600 IN A 10.10.43.19
+biganswer.example8. 3600 IN A 10.10.43.20
+biganswer.example8. 3600 IN A 10.10.43.21
+biganswer.example8. 3600 IN A 10.10.43.22
+biganswer.example8. 3600 IN A 10.10.43.23
+biganswer.example8. 3600 IN A 10.10.43.24
+biganswer.example8. 3600 IN A 10.10.43.25
+biganswer.example8. 3600 IN A 10.10.43.26
+biganswer.example8. 3600 IN A 10.10.43.27
+biganswer.example8. 3600 IN A 10.10.43.28
+biganswer.example8. 3600 IN A 10.10.43.29
+biganswer.example8. 3600 IN A 10.10.43.30
+biganswer.example8. 3600 IN A 10.10.43.31
+biganswer.example8. 3600 IN A 10.10.43.32
+biganswer.example8. 3600 IN A 10.10.43.33
+biganswer.example8. 3600 IN A 10.10.43.34
+biganswer.example8. 3600 IN A 10.10.43.35
+biganswer.example8. 3600 IN A 10.10.43.36
+biganswer.example8. 3600 IN A 10.10.43.37
+biganswer.example8. 3600 IN A 10.10.43.38
+biganswer.example8. 3600 IN A 10.10.43.39
+biganswer.example8. 3600 IN A 10.10.43.40
+biganswer.example8. 3600 IN A 10.10.43.41
+biganswer.example8. 3600 IN A 10.10.43.42
+biganswer.example8. 3600 IN A 10.10.43.43
+biganswer.example8. 3600 IN A 10.10.43.44
+biganswer.example8. 3600 IN A 10.10.43.45
+biganswer.example8. 3600 IN A 10.10.43.46
+biganswer.example8. 3600 IN A 10.10.43.47
+biganswer.example8. 3600 IN A 10.10.43.48
+biganswer.example8. 3600 IN A 10.10.43.49
+biganswer.example8. 3600 IN A 10.10.43.50
+biganswer.example8. 3600 IN A 10.10.44.1
+biganswer.example8. 3600 IN A 10.10.44.2
+biganswer.example8. 3600 IN A 10.10.44.3
+biganswer.example8. 3600 IN A 10.10.44.4
+biganswer.example8. 3600 IN A 10.10.44.5
+biganswer.example8. 3600 IN A 10.10.44.6
+biganswer.example8. 3600 IN A 10.10.44.7
+biganswer.example8. 3600 IN A 10.10.44.8
+biganswer.example8. 3600 IN A 10.10.44.9
+biganswer.example8. 3600 IN A 10.10.44.10
+biganswer.example8. 3600 IN A 10.10.44.11
+biganswer.example8. 3600 IN A 10.10.44.12
+biganswer.example8. 3600 IN A 10.10.44.13
+biganswer.example8. 3600 IN A 10.10.44.14
+biganswer.example8. 3600 IN A 10.10.44.15
+biganswer.example8. 3600 IN A 10.10.44.16
+biganswer.example8. 3600 IN A 10.10.44.17
+biganswer.example8. 3600 IN A 10.10.44.18
+biganswer.example8. 3600 IN A 10.10.44.19
+biganswer.example8. 3600 IN A 10.10.44.20
+biganswer.example8. 3600 IN A 10.10.44.21
+biganswer.example8. 3600 IN A 10.10.44.22
+biganswer.example8. 3600 IN A 10.10.44.23
+biganswer.example8. 3600 IN A 10.10.44.24
+biganswer.example8. 3600 IN A 10.10.44.25
+biganswer.example8. 3600 IN A 10.10.44.26
+biganswer.example8. 3600 IN A 10.10.44.27
+biganswer.example8. 3600 IN A 10.10.44.28
+biganswer.example8. 3600 IN A 10.10.44.29
+biganswer.example8. 3600 IN A 10.10.44.30
+biganswer.example8. 3600 IN A 10.10.44.31
+biganswer.example8. 3600 IN A 10.10.44.32
+biganswer.example8. 3600 IN A 10.10.44.33
+biganswer.example8. 3600 IN A 10.10.44.34
+biganswer.example8. 3600 IN A 10.10.44.35
+biganswer.example8. 3600 IN A 10.10.44.36
+biganswer.example8. 3600 IN A 10.10.44.37
+biganswer.example8. 3600 IN A 10.10.44.38
+biganswer.example8. 3600 IN A 10.10.44.39
+biganswer.example8. 3600 IN A 10.10.44.40
+biganswer.example8. 3600 IN A 10.10.44.41
+biganswer.example8. 3600 IN A 10.10.44.42
+biganswer.example8. 3600 IN A 10.10.44.43
+biganswer.example8. 3600 IN A 10.10.44.44
+biganswer.example8. 3600 IN A 10.10.44.45
+biganswer.example8. 3600 IN A 10.10.44.46
+biganswer.example8. 3600 IN A 10.10.44.47
+biganswer.example8. 3600 IN A 10.10.44.48
+biganswer.example8. 3600 IN A 10.10.44.49
+biganswer.example8. 3600 IN A 10.10.44.50
+biganswer.example8. 3600 IN A 10.10.45.1
+biganswer.example8. 3600 IN A 10.10.45.2
+biganswer.example8. 3600 IN A 10.10.45.3
+biganswer.example8. 3600 IN A 10.10.45.4
+biganswer.example8. 3600 IN A 10.10.45.5
+biganswer.example8. 3600 IN A 10.10.45.6
+biganswer.example8. 3600 IN A 10.10.45.7
+biganswer.example8. 3600 IN A 10.10.45.8
+biganswer.example8. 3600 IN A 10.10.45.9
+biganswer.example8. 3600 IN A 10.10.45.10
+biganswer.example8. 3600 IN A 10.10.45.11
+biganswer.example8. 3600 IN A 10.10.45.12
+biganswer.example8. 3600 IN A 10.10.45.13
+biganswer.example8. 3600 IN A 10.10.45.14
+biganswer.example8. 3600 IN A 10.10.45.15
+biganswer.example8. 3600 IN A 10.10.45.16
+biganswer.example8. 3600 IN A 10.10.45.17
+biganswer.example8. 3600 IN A 10.10.45.18
+biganswer.example8. 3600 IN A 10.10.45.19
+biganswer.example8. 3600 IN A 10.10.45.20
+biganswer.example8. 3600 IN A 10.10.45.21
+biganswer.example8. 3600 IN A 10.10.45.22
+biganswer.example8. 3600 IN A 10.10.45.23
+biganswer.example8. 3600 IN A 10.10.45.24
+biganswer.example8. 3600 IN A 10.10.45.25
+biganswer.example8. 3600 IN A 10.10.45.26
+biganswer.example8. 3600 IN A 10.10.45.27
+biganswer.example8. 3600 IN A 10.10.45.28
+biganswer.example8. 3600 IN A 10.10.45.29
+biganswer.example8. 3600 IN A 10.10.45.30
+biganswer.example8. 3600 IN A 10.10.45.31
+biganswer.example8. 3600 IN A 10.10.45.32
+biganswer.example8. 3600 IN A 10.10.45.33
+biganswer.example8. 3600 IN A 10.10.45.34
+biganswer.example8. 3600 IN A 10.10.45.35
+biganswer.example8. 3600 IN A 10.10.45.36
+biganswer.example8. 3600 IN A 10.10.45.37
+biganswer.example8. 3600 IN A 10.10.45.38
+biganswer.example8. 3600 IN A 10.10.45.39
+biganswer.example8. 3600 IN A 10.10.45.40
+biganswer.example8. 3600 IN A 10.10.45.41
+biganswer.example8. 3600 IN A 10.10.45.42
+biganswer.example8. 3600 IN A 10.10.45.43
+biganswer.example8. 3600 IN A 10.10.45.44
+biganswer.example8. 3600 IN A 10.10.45.45
+biganswer.example8. 3600 IN A 10.10.45.46
+biganswer.example8. 3600 IN A 10.10.45.47
+biganswer.example8. 3600 IN A 10.10.45.48
+biganswer.example8. 3600 IN A 10.10.45.49
+biganswer.example8. 3600 IN A 10.10.45.50
+biganswer.example8. 3600 IN A 10.10.46.1
+biganswer.example8. 3600 IN A 10.10.46.2
+biganswer.example8. 3600 IN A 10.10.46.3
+biganswer.example8. 3600 IN A 10.10.46.4
+biganswer.example8. 3600 IN A 10.10.46.5
+biganswer.example8. 3600 IN A 10.10.46.6
+biganswer.example8. 3600 IN A 10.10.46.7
+biganswer.example8. 3600 IN A 10.10.46.8
+biganswer.example8. 3600 IN A 10.10.46.9
+biganswer.example8. 3600 IN A 10.10.46.10
+biganswer.example8. 3600 IN A 10.10.46.11
+biganswer.example8. 3600 IN A 10.10.46.12
+biganswer.example8. 3600 IN A 10.10.46.13
+biganswer.example8. 3600 IN A 10.10.46.14
+biganswer.example8. 3600 IN A 10.10.46.15
+biganswer.example8. 3600 IN A 10.10.46.16
+biganswer.example8. 3600 IN A 10.10.46.17
+biganswer.example8. 3600 IN A 10.10.46.18
+biganswer.example8. 3600 IN A 10.10.46.19
+biganswer.example8. 3600 IN A 10.10.46.20
+biganswer.example8. 3600 IN A 10.10.46.21
+biganswer.example8. 3600 IN A 10.10.46.22
+biganswer.example8. 3600 IN A 10.10.46.23
+biganswer.example8. 3600 IN A 10.10.46.24
+biganswer.example8. 3600 IN A 10.10.46.25
+biganswer.example8. 3600 IN A 10.10.46.26
+biganswer.example8. 3600 IN A 10.10.46.27
+biganswer.example8. 3600 IN A 10.10.46.28
+biganswer.example8. 3600 IN A 10.10.46.29
+biganswer.example8. 3600 IN A 10.10.46.30
+biganswer.example8. 3600 IN A 10.10.46.31
+biganswer.example8. 3600 IN A 10.10.46.32
+biganswer.example8. 3600 IN A 10.10.46.33
+biganswer.example8. 3600 IN A 10.10.46.34
+biganswer.example8. 3600 IN A 10.10.46.35
+biganswer.example8. 3600 IN A 10.10.46.36
+biganswer.example8. 3600 IN A 10.10.46.37
+biganswer.example8. 3600 IN A 10.10.46.38
+biganswer.example8. 3600 IN A 10.10.46.39
+biganswer.example8. 3600 IN A 10.10.46.40
+biganswer.example8. 3600 IN A 10.10.46.41
+biganswer.example8. 3600 IN A 10.10.46.42
+biganswer.example8. 3600 IN A 10.10.46.43
+biganswer.example8. 3600 IN A 10.10.46.44
+biganswer.example8. 3600 IN A 10.10.46.45
+biganswer.example8. 3600 IN A 10.10.46.46
+biganswer.example8. 3600 IN A 10.10.46.47
+biganswer.example8. 3600 IN A 10.10.46.48
+biganswer.example8. 3600 IN A 10.10.46.49
+biganswer.example8. 3600 IN A 10.10.46.50
+biganswer.example8. 3600 IN A 10.10.47.1
+biganswer.example8. 3600 IN A 10.10.47.2
+biganswer.example8. 3600 IN A 10.10.47.3
+biganswer.example8. 3600 IN A 10.10.47.4
+biganswer.example8. 3600 IN A 10.10.47.5
+biganswer.example8. 3600 IN A 10.10.47.6
+biganswer.example8. 3600 IN A 10.10.47.7
+biganswer.example8. 3600 IN A 10.10.47.8
+biganswer.example8. 3600 IN A 10.10.47.9
+biganswer.example8. 3600 IN A 10.10.47.10
+biganswer.example8. 3600 IN A 10.10.47.11
+biganswer.example8. 3600 IN A 10.10.47.12
+biganswer.example8. 3600 IN A 10.10.47.13
+biganswer.example8. 3600 IN A 10.10.47.14
+biganswer.example8. 3600 IN A 10.10.47.15
+biganswer.example8. 3600 IN A 10.10.47.16
+biganswer.example8. 3600 IN A 10.10.47.17
+biganswer.example8. 3600 IN A 10.10.47.18
+biganswer.example8. 3600 IN A 10.10.47.19
+biganswer.example8. 3600 IN A 10.10.47.20
+biganswer.example8. 3600 IN A 10.10.47.21
+biganswer.example8. 3600 IN A 10.10.47.22
+biganswer.example8. 3600 IN A 10.10.47.23
+biganswer.example8. 3600 IN A 10.10.47.24
+biganswer.example8. 3600 IN A 10.10.47.25
+biganswer.example8. 3600 IN A 10.10.47.26
+biganswer.example8. 3600 IN A 10.10.47.27
+biganswer.example8. 3600 IN A 10.10.47.28
+biganswer.example8. 3600 IN A 10.10.47.29
+biganswer.example8. 3600 IN A 10.10.47.30
+biganswer.example8. 3600 IN A 10.10.47.31
+biganswer.example8. 3600 IN A 10.10.47.32
+biganswer.example8. 3600 IN A 10.10.47.33
+biganswer.example8. 3600 IN A 10.10.47.34
+biganswer.example8. 3600 IN A 10.10.47.35
+biganswer.example8. 3600 IN A 10.10.47.36
+biganswer.example8. 3600 IN A 10.10.47.37
+biganswer.example8. 3600 IN A 10.10.47.38
+biganswer.example8. 3600 IN A 10.10.47.39
+biganswer.example8. 3600 IN A 10.10.47.40
+biganswer.example8. 3600 IN A 10.10.47.41
+biganswer.example8. 3600 IN A 10.10.47.42
+biganswer.example8. 3600 IN A 10.10.47.43
+biganswer.example8. 3600 IN A 10.10.47.44
+biganswer.example8. 3600 IN A 10.10.47.45
+biganswer.example8. 3600 IN A 10.10.47.46
+biganswer.example8. 3600 IN A 10.10.47.47
+biganswer.example8. 3600 IN A 10.10.47.48
+biganswer.example8. 3600 IN A 10.10.47.49
+biganswer.example8. 3600 IN A 10.10.47.50
+biganswer.example8. 3600 IN A 10.10.48.1
+biganswer.example8. 3600 IN A 10.10.48.2
+biganswer.example8. 3600 IN A 10.10.48.3
+biganswer.example8. 3600 IN A 10.10.48.4
+biganswer.example8. 3600 IN A 10.10.48.5
+biganswer.example8. 3600 IN A 10.10.48.6
+biganswer.example8. 3600 IN A 10.10.48.7
+biganswer.example8. 3600 IN A 10.10.48.8
+biganswer.example8. 3600 IN A 10.10.48.9
+biganswer.example8. 3600 IN A 10.10.48.10
+biganswer.example8. 3600 IN A 10.10.48.11
+biganswer.example8. 3600 IN A 10.10.48.12
+biganswer.example8. 3600 IN A 10.10.48.13
+biganswer.example8. 3600 IN A 10.10.48.14
+biganswer.example8. 3600 IN A 10.10.48.15
+biganswer.example8. 3600 IN A 10.10.48.16
+biganswer.example8. 3600 IN A 10.10.48.17
+biganswer.example8. 3600 IN A 10.10.48.18
+biganswer.example8. 3600 IN A 10.10.48.19
+biganswer.example8. 3600 IN A 10.10.48.20
+biganswer.example8. 3600 IN A 10.10.48.21
+biganswer.example8. 3600 IN A 10.10.48.22
+biganswer.example8. 3600 IN A 10.10.48.23
+biganswer.example8. 3600 IN A 10.10.48.24
+biganswer.example8. 3600 IN A 10.10.48.25
+biganswer.example8. 3600 IN A 10.10.48.26
+biganswer.example8. 3600 IN A 10.10.48.27
+biganswer.example8. 3600 IN A 10.10.48.28
+biganswer.example8. 3600 IN A 10.10.48.29
+biganswer.example8. 3600 IN A 10.10.48.30
+biganswer.example8. 3600 IN A 10.10.48.31
+biganswer.example8. 3600 IN A 10.10.48.32
+biganswer.example8. 3600 IN A 10.10.48.33
+biganswer.example8. 3600 IN A 10.10.48.34
+biganswer.example8. 3600 IN A 10.10.48.35
+biganswer.example8. 3600 IN A 10.10.48.36
+biganswer.example8. 3600 IN A 10.10.48.37
+biganswer.example8. 3600 IN A 10.10.48.38
+biganswer.example8. 3600 IN A 10.10.48.39
+biganswer.example8. 3600 IN A 10.10.48.40
+biganswer.example8. 3600 IN A 10.10.48.41
+biganswer.example8. 3600 IN A 10.10.48.42
+biganswer.example8. 3600 IN A 10.10.48.43
+biganswer.example8. 3600 IN A 10.10.48.44
+biganswer.example8. 3600 IN A 10.10.48.45
+biganswer.example8. 3600 IN A 10.10.48.46
+biganswer.example8. 3600 IN A 10.10.48.47
+biganswer.example8. 3600 IN A 10.10.48.48
+biganswer.example8. 3600 IN A 10.10.48.49
+biganswer.example8. 3600 IN A 10.10.48.50
+biganswer.example8. 3600 IN A 10.10.49.1
+biganswer.example8. 3600 IN A 10.10.49.2
+biganswer.example8. 3600 IN A 10.10.49.3
+biganswer.example8. 3600 IN A 10.10.49.4
+biganswer.example8. 3600 IN A 10.10.49.5
+biganswer.example8. 3600 IN A 10.10.49.6
+biganswer.example8. 3600 IN A 10.10.49.7
+biganswer.example8. 3600 IN A 10.10.49.8
+biganswer.example8. 3600 IN A 10.10.49.9
+biganswer.example8. 3600 IN A 10.10.49.10
+biganswer.example8. 3600 IN A 10.10.49.11
+biganswer.example8. 3600 IN A 10.10.49.12
+biganswer.example8. 3600 IN A 10.10.49.13
+biganswer.example8. 3600 IN A 10.10.49.14
+biganswer.example8. 3600 IN A 10.10.49.15
+biganswer.example8. 3600 IN A 10.10.49.16
+biganswer.example8. 3600 IN A 10.10.49.17
+biganswer.example8. 3600 IN A 10.10.49.18
+biganswer.example8. 3600 IN A 10.10.49.19
+biganswer.example8. 3600 IN A 10.10.49.20
+biganswer.example8. 3600 IN A 10.10.49.21
+biganswer.example8. 3600 IN A 10.10.49.22
+biganswer.example8. 3600 IN A 10.10.49.23
+biganswer.example8. 3600 IN A 10.10.49.24
+biganswer.example8. 3600 IN A 10.10.49.25
+biganswer.example8. 3600 IN A 10.10.49.26
+biganswer.example8. 3600 IN A 10.10.49.27
+biganswer.example8. 3600 IN A 10.10.49.28
+biganswer.example8. 3600 IN A 10.10.49.29
+biganswer.example8. 3600 IN A 10.10.49.30
+biganswer.example8. 3600 IN A 10.10.49.31
+biganswer.example8. 3600 IN A 10.10.49.32
+biganswer.example8. 3600 IN A 10.10.49.33
+biganswer.example8. 3600 IN A 10.10.49.34
+biganswer.example8. 3600 IN A 10.10.49.35
+biganswer.example8. 3600 IN A 10.10.49.36
+biganswer.example8. 3600 IN A 10.10.49.37
+biganswer.example8. 3600 IN A 10.10.49.38
+biganswer.example8. 3600 IN A 10.10.49.39
+biganswer.example8. 3600 IN A 10.10.49.40
+biganswer.example8. 3600 IN A 10.10.49.41
+biganswer.example8. 3600 IN A 10.10.49.42
+biganswer.example8. 3600 IN A 10.10.49.43
+biganswer.example8. 3600 IN A 10.10.49.44
+biganswer.example8. 3600 IN A 10.10.49.45
+biganswer.example8. 3600 IN A 10.10.49.46
+biganswer.example8. 3600 IN A 10.10.49.47
+biganswer.example8. 3600 IN A 10.10.49.48
+biganswer.example8. 3600 IN A 10.10.49.49
+biganswer.example8. 3600 IN A 10.10.49.50
+biganswer.example8. 3600 IN A 10.10.50.1
+biganswer.example8. 3600 IN A 10.10.50.2
+biganswer.example8. 3600 IN A 10.10.50.3
+biganswer.example8. 3600 IN A 10.10.50.4
+biganswer.example8. 3600 IN A 10.10.50.5
+biganswer.example8. 3600 IN A 10.10.50.6
+biganswer.example8. 3600 IN A 10.10.50.7
+biganswer.example8. 3600 IN A 10.10.50.8
+biganswer.example8. 3600 IN A 10.10.50.9
+biganswer.example8. 3600 IN A 10.10.50.10
+biganswer.example8. 3600 IN A 10.10.50.11
+biganswer.example8. 3600 IN A 10.10.50.12
+biganswer.example8. 3600 IN A 10.10.50.13
+biganswer.example8. 3600 IN A 10.10.50.14
+biganswer.example8. 3600 IN A 10.10.50.15
+biganswer.example8. 3600 IN A 10.10.50.16
+biganswer.example8. 3600 IN A 10.10.50.17
+biganswer.example8. 3600 IN A 10.10.50.18
+biganswer.example8. 3600 IN A 10.10.50.19
+biganswer.example8. 3600 IN A 10.10.50.20
+biganswer.example8. 3600 IN A 10.10.50.21
+biganswer.example8. 3600 IN A 10.10.50.22
+biganswer.example8. 3600 IN A 10.10.50.23
+biganswer.example8. 3600 IN A 10.10.50.24
+biganswer.example8. 3600 IN A 10.10.50.25
+biganswer.example8. 3600 IN A 10.10.50.26
+biganswer.example8. 3600 IN A 10.10.50.27
+biganswer.example8. 3600 IN A 10.10.50.28
+biganswer.example8. 3600 IN A 10.10.50.29
+biganswer.example8. 3600 IN A 10.10.50.30
+biganswer.example8. 3600 IN A 10.10.50.31
+biganswer.example8. 3600 IN A 10.10.50.32
+biganswer.example8. 3600 IN A 10.10.50.33
+biganswer.example8. 3600 IN A 10.10.50.34
+biganswer.example8. 3600 IN A 10.10.50.35
+biganswer.example8. 3600 IN A 10.10.50.36
+biganswer.example8. 3600 IN A 10.10.50.37
+biganswer.example8. 3600 IN A 10.10.50.38
+biganswer.example8. 3600 IN A 10.10.50.39
+biganswer.example8. 3600 IN A 10.10.50.40
+biganswer.example8. 3600 IN A 10.10.50.41
+biganswer.example8. 3600 IN A 10.10.50.42
+biganswer.example8. 3600 IN A 10.10.50.43
+biganswer.example8. 3600 IN A 10.10.50.44
+biganswer.example8. 3600 IN A 10.10.50.45
+biganswer.example8. 3600 IN A 10.10.50.46
+biganswer.example8. 3600 IN A 10.10.50.47
+biganswer.example8. 3600 IN A 10.10.50.48
+biganswer.example8. 3600 IN A 10.10.50.49
+biganswer.example8. 3600 IN A 10.10.50.50
+caa01.example8. 3600 IN CAA 0 issue "ca.example.net; policy=ev"
+caa02.example8. 3600 IN CAA 128 tbs "Unknown"
+caa03.example8. 3600 IN CAA 128 tbs ""
+cdnskey01.example8. 3600 IN CDNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+cds01.example8. 3600 IN CDS 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+cert01.example8. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+cname01.example8. 3600 IN CNAME cname-target.
+cname02.example8. 3600 IN CNAME cname-target.example8.
+cname03.example8. 3600 IN CNAME .
+csync01.example8. 3600 IN CSYNC 0 0 A NS AAAA
+csync02.example8. 3600 IN CSYNC 0 0
+dhcid01.example8. 3600 IN DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA=
+dhcid02.example8. 3600 IN DHCID AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQdWL3b/NaiUDlW2No=
+dhcid03.example8. 3600 IN DHCID AAABxLmlskllE0MVjd57zHcWmEH3pCQ6VytcKD//7es/deY=
+dlv.example8. 3600 IN DLV 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+dname01.example8. 3600 IN DNAME dname-target.
+dname02.example8. 3600 IN DNAME dname-target.example8.
+dname03.example8. 3600 IN DNAME .
+dnskey01.example8. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+doa01.example8. 3600 IN DOA 1234567890 1234567890 1 "image/gif" R0lGODlhKAAZAOMCAGZmZgBmmf///zOZzMz//5nM/zNmmWbM/5nMzMzMzACZ/////////////////////yH5BAEKAA8ALAAAAAAoABkAAATH8IFJK5U2a4337F5ogRkpnoCJrly7PrCKyh8c3HgAhzT35MDbbtO7/IJIHbGiOiaTxVTpSVWWLqNq1UVyapNS1wd3OAxug0LhnCubcVhsxysQnOt4ATpvvzHlFzl1AwODhWeFAgRpen5/UhheAYMFdUB4SFcpGEGGdQeCAqBBLTuSk30EeXd9pEsAbKGxjHqDSE0Sp6ixN4N1BJmbc7lIhmsBich1awPAjkY1SZR8bJWrz382SGqIBQQFQd4IsUTaX+ceuudPEQA7
+doa02.example8. 3600 IN DOA 0 1 2 "" aHR0cHM6Ly93d3cuaXNjLm9yZy8=
+ds01.example8. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13
+ds01.example8. 3600 IN NS ns42.example8.
+ds02.example8. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390
+ds02.example8. 3600 IN NS ns43.example8.
+eid01.example8. 3600 IN EID 1289AB
+eui48.example8. 3600 IN EUI48 01-23-45-67-89-ab
+eui64.example8. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef
+gid01.example8. 3600 IN GID \# 1 03
+gpos01.example8. 3600 IN GPOS "-22.6882" "116.8652" "250.0"
+gpos02.example8. 3600 IN GPOS "" "" ""
+hinfo01.example8. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02.example8. 3600 IN HINFO "PC" "NetBSD"
+hip1.example8. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
+hip2.example8. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com.
+https0.example8. 3600 IN HTTPS 0 example.net.
+https1.example8. 3600 IN HTTPS 1 . port=60
+ipseckey01.example8. 3600 IN IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey02.example8. 3600 IN IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey03.example8. 3600 IN IPSECKEY 10 1 2 192.0.2.3 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey04.example8. 3600 IN IPSECKEY 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey05.example8. 3600 IN IPSECKEY 10 2 2 2001:db8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+isdn01.example8. 3600 IN ISDN "isdn-address"
+isdn02.example8. 3600 IN ISDN "isdn-address" "subaddress"
+isdn03.example8. 3600 IN ISDN "isdn-address"
+isdn04.example8. 3600 IN ISDN "isdn-address" "subaddress"
+keydata.example8. 3600 IN TYPE65533 \# 0
+keydata.example8. 3600 IN TYPE65533 \# 6 010203040506
+keydata.example8. 3600 IN TYPE65533 \# 18 010203040506010203040506010203040506
+kx01.example8. 3600 IN KX 10 kdc.example8.
+kx02.example8. 3600 IN KX 10 .
+l32.example8. 3600 IN L32 10 1.2.3.4
+l64.example8. 3600 IN L64 10 14:4fff:ff20:ee64
+loc01.example8. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02.example8. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+lp.example8. 3600 IN LP 10 example.net.
+mb01.example8. 3600 IN MG madname.example8.
+mb02.example8. 3600 IN MG .
+mg01.example8. 3600 IN MG mgmname.example8.
+mg02.example8. 3600 IN MG .
+minfo01.example8. 3600 IN MINFO rmailbx.example8. emailbx.example8.
+minfo02.example8. 3600 IN MINFO . .
+mr01.example8. 3600 IN MR mrname.example8.
+mr02.example8. 3600 IN MR .
+mx01.example8. 3600 IN MX 10 mail.example8.
+mx02.example8. 3600 IN MX 10 .
+naptr01.example8. 3600 IN NAPTR 0 0 "" "" "" .
+naptr02.example8. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+nid.example8. 3600 IN NID 10 14:4fff:ff20:ee64
+nimloc01.example8. 3600 IN NIMLOC 1289AB
+ninfo01.example8. 3600 IN NINFO "foo"
+ninfo02.example8. 3600 IN NINFO "foo" "bar"
+ninfo03.example8. 3600 IN NINFO "foo"
+ninfo04.example8. 3600 IN NINFO "foo" "bar"
+ninfo05.example8. 3600 IN NINFO "foo bar"
+ninfo06.example8. 3600 IN NINFO "foo bar"
+ninfo07.example8. 3600 IN NINFO "foo bar"
+ninfo08.example8. 3600 IN NINFO "foo\010bar"
+ninfo09.example8. 3600 IN NINFO "foo\010bar"
+ninfo10.example8. 3600 IN NINFO "foo bar"
+ninfo11.example8. 3600 IN NINFO "\"foo\""
+ninfo12.example8. 3600 IN NINFO "\"foo\""
+ninfo13.example8. 3600 IN NINFO "foo;"
+ninfo14.example8. 3600 IN NINFO "foo;"
+ninfo15.example8. 3600 IN NINFO "bar\\;"
+ns2.example8. 3600 IN A 10.53.0.2
+nsap-ptr01.example8. 3600 IN NSAP-PTR foo.
+nsap-ptr01.example8. 3600 IN NSAP-PTR .
+nsap01.example8. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02.example8. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsec01.example8. 3600 IN NSEC a.secure.nil. NS SOA MX LOC RRSIG NSEC DNSKEY
+nsec02.example8. 3600 IN NSEC . NSAP-PTR NSEC
+nsec03.example8. 3600 IN NSEC . A
+nsec04.example8. 3600 IN NSEC . TYPE127
+openpgpkey.example8. 3600 IN OPENPGPKEY AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+ptr01.example8. 3600 IN PTR example8.
+px01.example8. 3600 IN PX 65535 foo. bar.
+px02.example8. 3600 IN PX 65535 . .
+rkey01.example8. 3600 IN RKEY 0 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+rp01.example8. 3600 IN RP mbox-dname.example8. txt-dname.example8.
+rp02.example8. 3600 IN RP . .
+rrsig01.example8. 3600 IN RRSIG NSEC 1 3 3600 20000102030405 19961211100908 2143 foo.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+rt01.example8. 3600 IN RT 0 intermediate-host.example8.
+rt02.example8. 3600 IN RT 65535 .
+sink01.example8. 3600 IN SINK 1 0 0
+sink02.example8. 3600 IN SINK 8 0 2 l4ik
+smimea.example8. 3600 IN SMIMEA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC
+spf01.example8. 3600 IN SPF "v=spf1 -all"
+spf02.example8. 3600 IN SPF "v=spf1" " -all"
+srv01.example8. 3600 IN SRV 0 0 0 .
+srv02.example8. 3600 IN SRV 65535 65535 65535 old-slow-box.example8.
+sshfp01.example8. 3600 IN SSHFP 4 2 C76D8329954DA2835751E371544E963EFDA099080D6C58DD2BFD9A31 6E162C83
+sshfp02.example8. 3600 IN SSHFP 1 2 BF29468C83AC58CCF8C85AB7B3BEB054ECF1E38512B8353AB36471FA 88961DCC
+svcb0.example8. 3600 IN SVCB 0 example.net.
+svcb1.example8. 3600 IN SVCB 1 . port=60
+ta.example8. 3600 IN TA 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+talink0.example8. 3600 IN TALINK . talink1.example8.
+talink1.example8. 3600 IN TALINK talink0.example8. talink2.example8.
+talink2.example8. 3600 IN TALINK talink2.example8. .
+tlsa.example8. 3600 IN TLSA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC
+txt01.example8. 3600 IN TXT "foo"
+txt02.example8. 3600 IN TXT "foo" "bar"
+txt03.example8. 3600 IN TXT "foo"
+txt04.example8. 3600 IN TXT "foo" "bar"
+txt05.example8. 3600 IN TXT "foo bar"
+txt06.example8. 3600 IN TXT "foo bar"
+txt07.example8. 3600 IN TXT "foo bar"
+txt08.example8. 3600 IN TXT "foo\010bar"
+txt09.example8. 3600 IN TXT "foo\010bar"
+txt10.example8. 3600 IN TXT "foo bar"
+txt11.example8. 3600 IN TXT "\"foo\""
+txt12.example8. 3600 IN TXT "\"foo\""
+txt13.example8. 3600 IN TXT "foo;"
+txt14.example8. 3600 IN TXT "foo;"
+txt15.example8. 3600 IN TXT "bar\\;"
+uid01.example8. 3600 IN UID \# 1 02
+uinfo01.example8. 3600 IN UINFO \# 1 01
+unspec01.example8. 3600 IN UNSPEC \# 1 04
+uri01.example8. 3600 IN URI 10 20 "https://www.isc.org/"
+uri02.example8. 3600 IN URI 30 40 "https://www.isc.org/HolyCowThisSureIsAVeryLongURIRecordIDontEvenKnowWhatSomeoneWouldEverWantWithSuchAThingButTheSpecificationRequiresThatWesupportItSoHereWeGoTestingItLaLaLaLaLaLaLaSeriouslyThoughWhyWouldYouEvenConsiderUsingAURIThisLongItSeemsLikeASillyIdeaButEnhWhatAreYouGonnaDo/"
+uri03.example8. 3600 IN URI 30 40 ""
+wks01.example8. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23
+wks02.example8. 3600 IN WKS 10.0.0.1 17 0 1 2 53
+wks03.example8. 3600 IN WKS 10.0.0.2 6 65535
+x2501.example8. 3600 IN X25 "123456789"
+zonemd01.example8. 3600 IN ZONEMD 2019020700 1 1 C220B8A6ED5728A971902F7E3D4FD93ADEEA88B0453C2E8E8C863D46 5AB06CF34EB95B266398C98B59124FA239CB7EEB
+zonemd02.example8. 3600 IN ZONEMD 2019020700 1 2 08CFA1115C7B948C4163A901270395EA226A930CD2CBCF2FA9A5E6EB 85F37C8A4E114D884E66F176EAB121CB02DB7D652E0CC4827E7A3204 F166B47E5613FD27
+8f1tmio9avcom2k0frp92lgcumak0cad.example8. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C 8FPNS2UCT7FBS643THP2B77PEQ77K6IU A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
+kcd3juae64f9c5csl1kif1htaui7un0g.example8. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C KD5MN2M20340DGO0BL7NTSB8JP4BSC7E
+mr5ukvsk1l37btu4q7b1dfevft4hkqdk.example8. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C MT38J6VG7S0SN5G17MCUF6IQIKFUAJ05 A AAAA RRSIG
+example8. 86400 IN SOA ns2.example8. hostmaster.example8. 1397051952 5 5 1814400 3600
diff --git a/bin/tests/system/doth/get_openssl_version.py b/bin/tests/system/doth/get_openssl_version.py
new file mode 100755
index 0000000..f1d6f4b
--- /dev/null
+++ b/bin/tests/system/doth/get_openssl_version.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import ssl
+
+version = ssl.OPENSSL_VERSION_INFO
+print(version[0], version[1], version[2])
diff --git a/bin/tests/system/doth/ns1/named.conf.in b/bin/tests/system/doth/ns1/named.conf.in
new file mode 100644
index 0000000..500675f
--- /dev/null
+++ b/bin/tests/system/doth/ns1/named.conf.in
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+http local {
+ endpoints { "/dns-query"; "/alter"; };
+ listener-clients 100;
+};
+
+tls tls-forward-secrecy {
+ protocols { TLSv1.2; };
+ ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+ prefer-server-ciphers yes;
+ key-file "../CA/certs/srv01.crt01.example.com.key";
+ cert-file "../CA/certs/srv01.crt01.example.com.pem";
+ dhparam-file "../dhparam3072.pem";
+};
+
+tls tls-pfs-aes256 {
+ protocols { TLSv1.2; };
+ ciphers "AES256:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+ prefer-server-ciphers yes;
+ key-file "../CA/certs/srv01.crt01.example.com.key";
+ cert-file "../CA/certs/srv01.crt01.example.com.pem";
+ dhparam-file "../dhparam3072.pem";
+};
+
+tls tls-no-subject-alt-name {
+ protocols { TLSv1.2; };
+ ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+ prefer-server-ciphers yes;
+ key-file "../CA/certs/srv01.crt02-no-san.example.com.key";
+ cert-file "../CA/certs/srv01.crt02-no-san.example.com.pem";
+ dhparam-file "../dhparam3072.pem";
+};
+
+tls tls-expired {
+ protocols { TLSv1.2; };
+ ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+ prefer-server-ciphers yes;
+ key-file "../CA/certs/srv01.crt03-expired.example.com.key";
+ cert-file "../CA/certs/srv01.crt03-expired.example.com.pem";
+ dhparam-file "../dhparam3072.pem";
+};
+
+tls tls-forward-secrecy-mutual-tls {
+ protocols { TLSv1.2; };
+ ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+ prefer-server-ciphers yes;
+ key-file "../CA/certs/srv01.crt01.example.com.key";
+ cert-file "../CA/certs/srv01.crt01.example.com.pem";
+ dhparam-file "../dhparam3072.pem";
+ ca-file "../CA/CA.pem";
+};
+
+options {
+ port @PORT@;
+ tls-port @TLSPORT@;
+ https-port @HTTPSPORT@;
+ http-port @HTTPPORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on tls tls-forward-secrecy { 10.53.0.1; }; // DoT
+ listen-on-v6 tls tls-forward-secrecy { fd92:7065:b8e:ffff::1;};
+ listen-on tls ephemeral http local { 10.53.0.1; }; // DoH
+ listen-on-v6 tls ephemeral http local { fd92:7065:b8e:ffff::1; };
+ listen-on tls none http local { 10.53.0.1; }; // unencrypted DoH
+ listen-on-v6 tls none http local { fd92:7065:b8e:ffff::1; };
+ listen-on-v6 { none; };
+ listen-on port @EXTRAPORT1@ tls tls-pfs-aes256 { 10.53.0.1; }; // DoT
+ listen-on-v6 port @EXTRAPORT1@ tls tls-pfs-aes256 { fd92:7065:b8e:ffff::1;};
+ listen-on port @EXTRAPORT2@ tls tls-no-subject-alt-name { 10.53.0.1; }; // DoT
+ listen-on port @EXTRAPORT3@ tls tls-no-subject-alt-name http local { 10.53.0.1; }; // DoH
+ listen-on port @EXTRAPORT4@ tls tls-expired { 10.53.0.1; }; // DoT
+ listen-on port @EXTRAPORT5@ tls tls-forward-secrecy-mutual-tls { 10.53.0.1; }; // DoT
+ listen-on port @EXTRAPORT6@ tls tls-forward-secrecy-mutual-tls http local { 10.53.0.1; }; // DoH
+ recursion no;
+ notify explicit;
+ also-notify { 10.53.0.2 port @PORT@; };
+ statistics-file "named.stats";
+ dnssec-validation yes;
+ tcp-initial-timeout 1200;
+ transfers-in 100;
+ transfers-out 100;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+ allow-transfer port @TLSPORT@ transport tls { any; };
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-transfer port @TLSPORT@ transport tls { any; };
+};
+
+zone "example2" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT1@ transport tls { any; };
+};
+
+zone "example3" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT3@ transport tls { any; };
+};
+
+zone "example4" {
+ type primary;
+ file "example.db";
+ allow-transfer transport tls { any; };
+};
+
+zone "example5" {
+ type primary;
+ file "example.db";
+ allow-transfer transport tls { any; };
+};
+
+zone "example6" {
+ type primary;
+ file "example.db";
+ allow-transfer transport tls { any; };
+};
+
+zone "example7" {
+ type primary;
+ file "example.db";
+ allow-transfer transport tls { any; };
+};
+
+zone "example8" {
+ type primary;
+ file "example.db";
+ allow-transfer transport tls { any; };
+};
+
+zone "example9" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT5@ transport tls { any; };
+};
+
+zone "example10" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT5@ transport tls { any; };
+};
+
+zone "example11" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT5@ transport tls { any; };
+};
diff --git a/bin/tests/system/doth/ns1/root.db b/bin/tests/system/doth/ns1/root.db
new file mode 100644
index 0000000..47a18a1
--- /dev/null
+++ b/bin/tests/system/doth/ns1/root.db
@@ -0,0 +1,10023 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+dom0001. NS a.root-servers.nil.
+dom0002. NS a.root-servers.nil.
+dom0003. NS a.root-servers.nil.
+dom0004. NS a.root-servers.nil.
+dom0005. NS a.root-servers.nil.
+dom0006. NS a.root-servers.nil.
+dom0007. NS a.root-servers.nil.
+dom0008. NS a.root-servers.nil.
+dom0009. NS a.root-servers.nil.
+dom0010. NS a.root-servers.nil.
+dom0011. NS a.root-servers.nil.
+dom0012. NS a.root-servers.nil.
+dom0013. NS a.root-servers.nil.
+dom0014. NS a.root-servers.nil.
+dom0015. NS a.root-servers.nil.
+dom0016. NS a.root-servers.nil.
+dom0017. NS a.root-servers.nil.
+dom0018. NS a.root-servers.nil.
+dom0019. NS a.root-servers.nil.
+dom0020. NS a.root-servers.nil.
+dom0021. NS a.root-servers.nil.
+dom0022. NS a.root-servers.nil.
+dom0023. NS a.root-servers.nil.
+dom0024. NS a.root-servers.nil.
+dom0025. NS a.root-servers.nil.
+dom0026. NS a.root-servers.nil.
+dom0027. NS a.root-servers.nil.
+dom0028. NS a.root-servers.nil.
+dom0029. NS a.root-servers.nil.
+dom0030. NS a.root-servers.nil.
+dom0031. NS a.root-servers.nil.
+dom0032. NS a.root-servers.nil.
+dom0033. NS a.root-servers.nil.
+dom0034. NS a.root-servers.nil.
+dom0035. NS a.root-servers.nil.
+dom0036. NS a.root-servers.nil.
+dom0037. NS a.root-servers.nil.
+dom0038. NS a.root-servers.nil.
+dom0039. NS a.root-servers.nil.
+dom0040. NS a.root-servers.nil.
+dom0041. NS a.root-servers.nil.
+dom0042. NS a.root-servers.nil.
+dom0043. NS a.root-servers.nil.
+dom0044. NS a.root-servers.nil.
+dom0045. NS a.root-servers.nil.
+dom0046. NS a.root-servers.nil.
+dom0047. NS a.root-servers.nil.
+dom0048. NS a.root-servers.nil.
+dom0049. NS a.root-servers.nil.
+dom0050. NS a.root-servers.nil.
+dom0051. NS a.root-servers.nil.
+dom0052. NS a.root-servers.nil.
+dom0053. NS a.root-servers.nil.
+dom0054. NS a.root-servers.nil.
+dom0055. NS a.root-servers.nil.
+dom0056. NS a.root-servers.nil.
+dom0057. NS a.root-servers.nil.
+dom0058. NS a.root-servers.nil.
+dom0059. NS a.root-servers.nil.
+dom0060. NS a.root-servers.nil.
+dom0061. NS a.root-servers.nil.
+dom0062. NS a.root-servers.nil.
+dom0063. NS a.root-servers.nil.
+dom0064. NS a.root-servers.nil.
+dom0065. NS a.root-servers.nil.
+dom0066. NS a.root-servers.nil.
+dom0067. NS a.root-servers.nil.
+dom0068. NS a.root-servers.nil.
+dom0069. NS a.root-servers.nil.
+dom0070. NS a.root-servers.nil.
+dom0071. NS a.root-servers.nil.
+dom0072. NS a.root-servers.nil.
+dom0073. NS a.root-servers.nil.
+dom0074. NS a.root-servers.nil.
+dom0075. NS a.root-servers.nil.
+dom0076. NS a.root-servers.nil.
+dom0077. NS a.root-servers.nil.
+dom0078. NS a.root-servers.nil.
+dom0079. NS a.root-servers.nil.
+dom0080. NS a.root-servers.nil.
+dom0081. NS a.root-servers.nil.
+dom0082. NS a.root-servers.nil.
+dom0083. NS a.root-servers.nil.
+dom0084. NS a.root-servers.nil.
+dom0085. NS a.root-servers.nil.
+dom0086. NS a.root-servers.nil.
+dom0087. NS a.root-servers.nil.
+dom0088. NS a.root-servers.nil.
+dom0089. NS a.root-servers.nil.
+dom0090. NS a.root-servers.nil.
+dom0091. NS a.root-servers.nil.
+dom0092. NS a.root-servers.nil.
+dom0093. NS a.root-servers.nil.
+dom0094. NS a.root-servers.nil.
+dom0095. NS a.root-servers.nil.
+dom0096. NS a.root-servers.nil.
+dom0097. NS a.root-servers.nil.
+dom0098. NS a.root-servers.nil.
+dom0099. NS a.root-servers.nil.
+dom0100. NS a.root-servers.nil.
+dom0101. NS a.root-servers.nil.
+dom0102. NS a.root-servers.nil.
+dom0103. NS a.root-servers.nil.
+dom0104. NS a.root-servers.nil.
+dom0105. NS a.root-servers.nil.
+dom0106. NS a.root-servers.nil.
+dom0107. NS a.root-servers.nil.
+dom0108. NS a.root-servers.nil.
+dom0109. NS a.root-servers.nil.
+dom0110. NS a.root-servers.nil.
+dom0111. NS a.root-servers.nil.
+dom0112. NS a.root-servers.nil.
+dom0113. NS a.root-servers.nil.
+dom0114. NS a.root-servers.nil.
+dom0115. NS a.root-servers.nil.
+dom0116. NS a.root-servers.nil.
+dom0117. NS a.root-servers.nil.
+dom0118. NS a.root-servers.nil.
+dom0119. NS a.root-servers.nil.
+dom0120. NS a.root-servers.nil.
+dom0121. NS a.root-servers.nil.
+dom0122. NS a.root-servers.nil.
+dom0123. NS a.root-servers.nil.
+dom0124. NS a.root-servers.nil.
+dom0125. NS a.root-servers.nil.
+dom0126. NS a.root-servers.nil.
+dom0127. NS a.root-servers.nil.
+dom0128. NS a.root-servers.nil.
+dom0129. NS a.root-servers.nil.
+dom0130. NS a.root-servers.nil.
+dom0131. NS a.root-servers.nil.
+dom0132. NS a.root-servers.nil.
+dom0133. NS a.root-servers.nil.
+dom0134. NS a.root-servers.nil.
+dom0135. NS a.root-servers.nil.
+dom0136. NS a.root-servers.nil.
+dom0137. NS a.root-servers.nil.
+dom0138. NS a.root-servers.nil.
+dom0139. NS a.root-servers.nil.
+dom0140. NS a.root-servers.nil.
+dom0141. NS a.root-servers.nil.
+dom0142. NS a.root-servers.nil.
+dom0143. NS a.root-servers.nil.
+dom0144. NS a.root-servers.nil.
+dom0145. NS a.root-servers.nil.
+dom0146. NS a.root-servers.nil.
+dom0147. NS a.root-servers.nil.
+dom0148. NS a.root-servers.nil.
+dom0149. NS a.root-servers.nil.
+dom0150. NS a.root-servers.nil.
+dom0151. NS a.root-servers.nil.
+dom0152. NS a.root-servers.nil.
+dom0153. NS a.root-servers.nil.
+dom0154. NS a.root-servers.nil.
+dom0155. NS a.root-servers.nil.
+dom0156. NS a.root-servers.nil.
+dom0157. NS a.root-servers.nil.
+dom0158. NS a.root-servers.nil.
+dom0159. NS a.root-servers.nil.
+dom0160. NS a.root-servers.nil.
+dom0161. NS a.root-servers.nil.
+dom0162. NS a.root-servers.nil.
+dom0163. NS a.root-servers.nil.
+dom0164. NS a.root-servers.nil.
+dom0165. NS a.root-servers.nil.
+dom0166. NS a.root-servers.nil.
+dom0167. NS a.root-servers.nil.
+dom0168. NS a.root-servers.nil.
+dom0169. NS a.root-servers.nil.
+dom0170. NS a.root-servers.nil.
+dom0171. NS a.root-servers.nil.
+dom0172. NS a.root-servers.nil.
+dom0173. NS a.root-servers.nil.
+dom0174. NS a.root-servers.nil.
+dom0175. NS a.root-servers.nil.
+dom0176. NS a.root-servers.nil.
+dom0177. NS a.root-servers.nil.
+dom0178. NS a.root-servers.nil.
+dom0179. NS a.root-servers.nil.
+dom0180. NS a.root-servers.nil.
+dom0181. NS a.root-servers.nil.
+dom0182. NS a.root-servers.nil.
+dom0183. NS a.root-servers.nil.
+dom0184. NS a.root-servers.nil.
+dom0185. NS a.root-servers.nil.
+dom0186. NS a.root-servers.nil.
+dom0187. NS a.root-servers.nil.
+dom0188. NS a.root-servers.nil.
+dom0189. NS a.root-servers.nil.
+dom0190. NS a.root-servers.nil.
+dom0191. NS a.root-servers.nil.
+dom0192. NS a.root-servers.nil.
+dom0193. NS a.root-servers.nil.
+dom0194. NS a.root-servers.nil.
+dom0195. NS a.root-servers.nil.
+dom0196. NS a.root-servers.nil.
+dom0197. NS a.root-servers.nil.
+dom0198. NS a.root-servers.nil.
+dom0199. NS a.root-servers.nil.
+dom0200. NS a.root-servers.nil.
+dom0201. NS a.root-servers.nil.
+dom0202. NS a.root-servers.nil.
+dom0203. NS a.root-servers.nil.
+dom0204. NS a.root-servers.nil.
+dom0205. NS a.root-servers.nil.
+dom0206. NS a.root-servers.nil.
+dom0207. NS a.root-servers.nil.
+dom0208. NS a.root-servers.nil.
+dom0209. NS a.root-servers.nil.
+dom0210. NS a.root-servers.nil.
+dom0211. NS a.root-servers.nil.
+dom0212. NS a.root-servers.nil.
+dom0213. NS a.root-servers.nil.
+dom0214. NS a.root-servers.nil.
+dom0215. NS a.root-servers.nil.
+dom0216. NS a.root-servers.nil.
+dom0217. NS a.root-servers.nil.
+dom0218. NS a.root-servers.nil.
+dom0219. NS a.root-servers.nil.
+dom0220. NS a.root-servers.nil.
+dom0221. NS a.root-servers.nil.
+dom0222. NS a.root-servers.nil.
+dom0223. NS a.root-servers.nil.
+dom0224. NS a.root-servers.nil.
+dom0225. NS a.root-servers.nil.
+dom0226. NS a.root-servers.nil.
+dom0227. NS a.root-servers.nil.
+dom0228. NS a.root-servers.nil.
+dom0229. NS a.root-servers.nil.
+dom0230. NS a.root-servers.nil.
+dom0231. NS a.root-servers.nil.
+dom0232. NS a.root-servers.nil.
+dom0233. NS a.root-servers.nil.
+dom0234. NS a.root-servers.nil.
+dom0235. NS a.root-servers.nil.
+dom0236. NS a.root-servers.nil.
+dom0237. NS a.root-servers.nil.
+dom0238. NS a.root-servers.nil.
+dom0239. NS a.root-servers.nil.
+dom0240. NS a.root-servers.nil.
+dom0241. NS a.root-servers.nil.
+dom0242. NS a.root-servers.nil.
+dom0243. NS a.root-servers.nil.
+dom0244. NS a.root-servers.nil.
+dom0245. NS a.root-servers.nil.
+dom0246. NS a.root-servers.nil.
+dom0247. NS a.root-servers.nil.
+dom0248. NS a.root-servers.nil.
+dom0249. NS a.root-servers.nil.
+dom0250. NS a.root-servers.nil.
+dom0251. NS a.root-servers.nil.
+dom0252. NS a.root-servers.nil.
+dom0253. NS a.root-servers.nil.
+dom0254. NS a.root-servers.nil.
+dom0255. NS a.root-servers.nil.
+dom0256. NS a.root-servers.nil.
+dom0257. NS a.root-servers.nil.
+dom0258. NS a.root-servers.nil.
+dom0259. NS a.root-servers.nil.
+dom0260. NS a.root-servers.nil.
+dom0261. NS a.root-servers.nil.
+dom0262. NS a.root-servers.nil.
+dom0263. NS a.root-servers.nil.
+dom0264. NS a.root-servers.nil.
+dom0265. NS a.root-servers.nil.
+dom0266. NS a.root-servers.nil.
+dom0267. NS a.root-servers.nil.
+dom0268. NS a.root-servers.nil.
+dom0269. NS a.root-servers.nil.
+dom0270. NS a.root-servers.nil.
+dom0271. NS a.root-servers.nil.
+dom0272. NS a.root-servers.nil.
+dom0273. NS a.root-servers.nil.
+dom0274. NS a.root-servers.nil.
+dom0275. NS a.root-servers.nil.
+dom0276. NS a.root-servers.nil.
+dom0277. NS a.root-servers.nil.
+dom0278. NS a.root-servers.nil.
+dom0279. NS a.root-servers.nil.
+dom0280. NS a.root-servers.nil.
+dom0281. NS a.root-servers.nil.
+dom0282. NS a.root-servers.nil.
+dom0283. NS a.root-servers.nil.
+dom0284. NS a.root-servers.nil.
+dom0285. NS a.root-servers.nil.
+dom0286. NS a.root-servers.nil.
+dom0287. NS a.root-servers.nil.
+dom0288. NS a.root-servers.nil.
+dom0289. NS a.root-servers.nil.
+dom0290. NS a.root-servers.nil.
+dom0291. NS a.root-servers.nil.
+dom0292. NS a.root-servers.nil.
+dom0293. NS a.root-servers.nil.
+dom0294. NS a.root-servers.nil.
+dom0295. NS a.root-servers.nil.
+dom0296. NS a.root-servers.nil.
+dom0297. NS a.root-servers.nil.
+dom0298. NS a.root-servers.nil.
+dom0299. NS a.root-servers.nil.
+dom0300. NS a.root-servers.nil.
+dom0301. NS a.root-servers.nil.
+dom0302. NS a.root-servers.nil.
+dom0303. NS a.root-servers.nil.
+dom0304. NS a.root-servers.nil.
+dom0305. NS a.root-servers.nil.
+dom0306. NS a.root-servers.nil.
+dom0307. NS a.root-servers.nil.
+dom0308. NS a.root-servers.nil.
+dom0309. NS a.root-servers.nil.
+dom0310. NS a.root-servers.nil.
+dom0311. NS a.root-servers.nil.
+dom0312. NS a.root-servers.nil.
+dom0313. NS a.root-servers.nil.
+dom0314. NS a.root-servers.nil.
+dom0315. NS a.root-servers.nil.
+dom0316. NS a.root-servers.nil.
+dom0317. NS a.root-servers.nil.
+dom0318. NS a.root-servers.nil.
+dom0319. NS a.root-servers.nil.
+dom0320. NS a.root-servers.nil.
+dom0321. NS a.root-servers.nil.
+dom0322. NS a.root-servers.nil.
+dom0323. NS a.root-servers.nil.
+dom0324. NS a.root-servers.nil.
+dom0325. NS a.root-servers.nil.
+dom0326. NS a.root-servers.nil.
+dom0327. NS a.root-servers.nil.
+dom0328. NS a.root-servers.nil.
+dom0329. NS a.root-servers.nil.
+dom0330. NS a.root-servers.nil.
+dom0331. NS a.root-servers.nil.
+dom0332. NS a.root-servers.nil.
+dom0333. NS a.root-servers.nil.
+dom0334. NS a.root-servers.nil.
+dom0335. NS a.root-servers.nil.
+dom0336. NS a.root-servers.nil.
+dom0337. NS a.root-servers.nil.
+dom0338. NS a.root-servers.nil.
+dom0339. NS a.root-servers.nil.
+dom0340. NS a.root-servers.nil.
+dom0341. NS a.root-servers.nil.
+dom0342. NS a.root-servers.nil.
+dom0343. NS a.root-servers.nil.
+dom0344. NS a.root-servers.nil.
+dom0345. NS a.root-servers.nil.
+dom0346. NS a.root-servers.nil.
+dom0347. NS a.root-servers.nil.
+dom0348. NS a.root-servers.nil.
+dom0349. NS a.root-servers.nil.
+dom0350. NS a.root-servers.nil.
+dom0351. NS a.root-servers.nil.
+dom0352. NS a.root-servers.nil.
+dom0353. NS a.root-servers.nil.
+dom0354. NS a.root-servers.nil.
+dom0355. NS a.root-servers.nil.
+dom0356. NS a.root-servers.nil.
+dom0357. NS a.root-servers.nil.
+dom0358. NS a.root-servers.nil.
+dom0359. NS a.root-servers.nil.
+dom0360. NS a.root-servers.nil.
+dom0361. NS a.root-servers.nil.
+dom0362. NS a.root-servers.nil.
+dom0363. NS a.root-servers.nil.
+dom0364. NS a.root-servers.nil.
+dom0365. NS a.root-servers.nil.
+dom0366. NS a.root-servers.nil.
+dom0367. NS a.root-servers.nil.
+dom0368. NS a.root-servers.nil.
+dom0369. NS a.root-servers.nil.
+dom0370. NS a.root-servers.nil.
+dom0371. NS a.root-servers.nil.
+dom0372. NS a.root-servers.nil.
+dom0373. NS a.root-servers.nil.
+dom0374. NS a.root-servers.nil.
+dom0375. NS a.root-servers.nil.
+dom0376. NS a.root-servers.nil.
+dom0377. NS a.root-servers.nil.
+dom0378. NS a.root-servers.nil.
+dom0379. NS a.root-servers.nil.
+dom0380. NS a.root-servers.nil.
+dom0381. NS a.root-servers.nil.
+dom0382. NS a.root-servers.nil.
+dom0383. NS a.root-servers.nil.
+dom0384. NS a.root-servers.nil.
+dom0385. NS a.root-servers.nil.
+dom0386. NS a.root-servers.nil.
+dom0387. NS a.root-servers.nil.
+dom0388. NS a.root-servers.nil.
+dom0389. NS a.root-servers.nil.
+dom0390. NS a.root-servers.nil.
+dom0391. NS a.root-servers.nil.
+dom0392. NS a.root-servers.nil.
+dom0393. NS a.root-servers.nil.
+dom0394. NS a.root-servers.nil.
+dom0395. NS a.root-servers.nil.
+dom0396. NS a.root-servers.nil.
+dom0397. NS a.root-servers.nil.
+dom0398. NS a.root-servers.nil.
+dom0399. NS a.root-servers.nil.
+dom0400. NS a.root-servers.nil.
+dom0401. NS a.root-servers.nil.
+dom0402. NS a.root-servers.nil.
+dom0403. NS a.root-servers.nil.
+dom0404. NS a.root-servers.nil.
+dom0405. NS a.root-servers.nil.
+dom0406. NS a.root-servers.nil.
+dom0407. NS a.root-servers.nil.
+dom0408. NS a.root-servers.nil.
+dom0409. NS a.root-servers.nil.
+dom0410. NS a.root-servers.nil.
+dom0411. NS a.root-servers.nil.
+dom0412. NS a.root-servers.nil.
+dom0413. NS a.root-servers.nil.
+dom0414. NS a.root-servers.nil.
+dom0415. NS a.root-servers.nil.
+dom0416. NS a.root-servers.nil.
+dom0417. NS a.root-servers.nil.
+dom0418. NS a.root-servers.nil.
+dom0419. NS a.root-servers.nil.
+dom0420. NS a.root-servers.nil.
+dom0421. NS a.root-servers.nil.
+dom0422. NS a.root-servers.nil.
+dom0423. NS a.root-servers.nil.
+dom0424. NS a.root-servers.nil.
+dom0425. NS a.root-servers.nil.
+dom0426. NS a.root-servers.nil.
+dom0427. NS a.root-servers.nil.
+dom0428. NS a.root-servers.nil.
+dom0429. NS a.root-servers.nil.
+dom0430. NS a.root-servers.nil.
+dom0431. NS a.root-servers.nil.
+dom0432. NS a.root-servers.nil.
+dom0433. NS a.root-servers.nil.
+dom0434. NS a.root-servers.nil.
+dom0435. NS a.root-servers.nil.
+dom0436. NS a.root-servers.nil.
+dom0437. NS a.root-servers.nil.
+dom0438. NS a.root-servers.nil.
+dom0439. NS a.root-servers.nil.
+dom0440. NS a.root-servers.nil.
+dom0441. NS a.root-servers.nil.
+dom0442. NS a.root-servers.nil.
+dom0443. NS a.root-servers.nil.
+dom0444. NS a.root-servers.nil.
+dom0445. NS a.root-servers.nil.
+dom0446. NS a.root-servers.nil.
+dom0447. NS a.root-servers.nil.
+dom0448. NS a.root-servers.nil.
+dom0449. NS a.root-servers.nil.
+dom0450. NS a.root-servers.nil.
+dom0451. NS a.root-servers.nil.
+dom0452. NS a.root-servers.nil.
+dom0453. NS a.root-servers.nil.
+dom0454. NS a.root-servers.nil.
+dom0455. NS a.root-servers.nil.
+dom0456. NS a.root-servers.nil.
+dom0457. NS a.root-servers.nil.
+dom0458. NS a.root-servers.nil.
+dom0459. NS a.root-servers.nil.
+dom0460. NS a.root-servers.nil.
+dom0461. NS a.root-servers.nil.
+dom0462. NS a.root-servers.nil.
+dom0463. NS a.root-servers.nil.
+dom0464. NS a.root-servers.nil.
+dom0465. NS a.root-servers.nil.
+dom0466. NS a.root-servers.nil.
+dom0467. NS a.root-servers.nil.
+dom0468. NS a.root-servers.nil.
+dom0469. NS a.root-servers.nil.
+dom0470. NS a.root-servers.nil.
+dom0471. NS a.root-servers.nil.
+dom0472. NS a.root-servers.nil.
+dom0473. NS a.root-servers.nil.
+dom0474. NS a.root-servers.nil.
+dom0475. NS a.root-servers.nil.
+dom0476. NS a.root-servers.nil.
+dom0477. NS a.root-servers.nil.
+dom0478. NS a.root-servers.nil.
+dom0479. NS a.root-servers.nil.
+dom0480. NS a.root-servers.nil.
+dom0481. NS a.root-servers.nil.
+dom0482. NS a.root-servers.nil.
+dom0483. NS a.root-servers.nil.
+dom0484. NS a.root-servers.nil.
+dom0485. NS a.root-servers.nil.
+dom0486. NS a.root-servers.nil.
+dom0487. NS a.root-servers.nil.
+dom0488. NS a.root-servers.nil.
+dom0489. NS a.root-servers.nil.
+dom0490. NS a.root-servers.nil.
+dom0491. NS a.root-servers.nil.
+dom0492. NS a.root-servers.nil.
+dom0493. NS a.root-servers.nil.
+dom0494. NS a.root-servers.nil.
+dom0495. NS a.root-servers.nil.
+dom0496. NS a.root-servers.nil.
+dom0497. NS a.root-servers.nil.
+dom0498. NS a.root-servers.nil.
+dom0499. NS a.root-servers.nil.
+dom0500. NS a.root-servers.nil.
+dom0501. NS a.root-servers.nil.
+dom0502. NS a.root-servers.nil.
+dom0503. NS a.root-servers.nil.
+dom0504. NS a.root-servers.nil.
+dom0505. NS a.root-servers.nil.
+dom0506. NS a.root-servers.nil.
+dom0507. NS a.root-servers.nil.
+dom0508. NS a.root-servers.nil.
+dom0509. NS a.root-servers.nil.
+dom0510. NS a.root-servers.nil.
+dom0511. NS a.root-servers.nil.
+dom0512. NS a.root-servers.nil.
+dom0513. NS a.root-servers.nil.
+dom0514. NS a.root-servers.nil.
+dom0515. NS a.root-servers.nil.
+dom0516. NS a.root-servers.nil.
+dom0517. NS a.root-servers.nil.
+dom0518. NS a.root-servers.nil.
+dom0519. NS a.root-servers.nil.
+dom0520. NS a.root-servers.nil.
+dom0521. NS a.root-servers.nil.
+dom0522. NS a.root-servers.nil.
+dom0523. NS a.root-servers.nil.
+dom0524. NS a.root-servers.nil.
+dom0525. NS a.root-servers.nil.
+dom0526. NS a.root-servers.nil.
+dom0527. NS a.root-servers.nil.
+dom0528. NS a.root-servers.nil.
+dom0529. NS a.root-servers.nil.
+dom0530. NS a.root-servers.nil.
+dom0531. NS a.root-servers.nil.
+dom0532. NS a.root-servers.nil.
+dom0533. NS a.root-servers.nil.
+dom0534. NS a.root-servers.nil.
+dom0535. NS a.root-servers.nil.
+dom0536. NS a.root-servers.nil.
+dom0537. NS a.root-servers.nil.
+dom0538. NS a.root-servers.nil.
+dom0539. NS a.root-servers.nil.
+dom0540. NS a.root-servers.nil.
+dom0541. NS a.root-servers.nil.
+dom0542. NS a.root-servers.nil.
+dom0543. NS a.root-servers.nil.
+dom0544. NS a.root-servers.nil.
+dom0545. NS a.root-servers.nil.
+dom0546. NS a.root-servers.nil.
+dom0547. NS a.root-servers.nil.
+dom0548. NS a.root-servers.nil.
+dom0549. NS a.root-servers.nil.
+dom0550. NS a.root-servers.nil.
+dom0551. NS a.root-servers.nil.
+dom0552. NS a.root-servers.nil.
+dom0553. NS a.root-servers.nil.
+dom0554. NS a.root-servers.nil.
+dom0555. NS a.root-servers.nil.
+dom0556. NS a.root-servers.nil.
+dom0557. NS a.root-servers.nil.
+dom0558. NS a.root-servers.nil.
+dom0559. NS a.root-servers.nil.
+dom0560. NS a.root-servers.nil.
+dom0561. NS a.root-servers.nil.
+dom0562. NS a.root-servers.nil.
+dom0563. NS a.root-servers.nil.
+dom0564. NS a.root-servers.nil.
+dom0565. NS a.root-servers.nil.
+dom0566. NS a.root-servers.nil.
+dom0567. NS a.root-servers.nil.
+dom0568. NS a.root-servers.nil.
+dom0569. NS a.root-servers.nil.
+dom0570. NS a.root-servers.nil.
+dom0571. NS a.root-servers.nil.
+dom0572. NS a.root-servers.nil.
+dom0573. NS a.root-servers.nil.
+dom0574. NS a.root-servers.nil.
+dom0575. NS a.root-servers.nil.
+dom0576. NS a.root-servers.nil.
+dom0577. NS a.root-servers.nil.
+dom0578. NS a.root-servers.nil.
+dom0579. NS a.root-servers.nil.
+dom0580. NS a.root-servers.nil.
+dom0581. NS a.root-servers.nil.
+dom0582. NS a.root-servers.nil.
+dom0583. NS a.root-servers.nil.
+dom0584. NS a.root-servers.nil.
+dom0585. NS a.root-servers.nil.
+dom0586. NS a.root-servers.nil.
+dom0587. NS a.root-servers.nil.
+dom0588. NS a.root-servers.nil.
+dom0589. NS a.root-servers.nil.
+dom0590. NS a.root-servers.nil.
+dom0591. NS a.root-servers.nil.
+dom0592. NS a.root-servers.nil.
+dom0593. NS a.root-servers.nil.
+dom0594. NS a.root-servers.nil.
+dom0595. NS a.root-servers.nil.
+dom0596. NS a.root-servers.nil.
+dom0597. NS a.root-servers.nil.
+dom0598. NS a.root-servers.nil.
+dom0599. NS a.root-servers.nil.
+dom0600. NS a.root-servers.nil.
+dom0601. NS a.root-servers.nil.
+dom0602. NS a.root-servers.nil.
+dom0603. NS a.root-servers.nil.
+dom0604. NS a.root-servers.nil.
+dom0605. NS a.root-servers.nil.
+dom0606. NS a.root-servers.nil.
+dom0607. NS a.root-servers.nil.
+dom0608. NS a.root-servers.nil.
+dom0609. NS a.root-servers.nil.
+dom0610. NS a.root-servers.nil.
+dom0611. NS a.root-servers.nil.
+dom0612. NS a.root-servers.nil.
+dom0613. NS a.root-servers.nil.
+dom0614. NS a.root-servers.nil.
+dom0615. NS a.root-servers.nil.
+dom0616. NS a.root-servers.nil.
+dom0617. NS a.root-servers.nil.
+dom0618. NS a.root-servers.nil.
+dom0619. NS a.root-servers.nil.
+dom0620. NS a.root-servers.nil.
+dom0621. NS a.root-servers.nil.
+dom0622. NS a.root-servers.nil.
+dom0623. NS a.root-servers.nil.
+dom0624. NS a.root-servers.nil.
+dom0625. NS a.root-servers.nil.
+dom0626. NS a.root-servers.nil.
+dom0627. NS a.root-servers.nil.
+dom0628. NS a.root-servers.nil.
+dom0629. NS a.root-servers.nil.
+dom0630. NS a.root-servers.nil.
+dom0631. NS a.root-servers.nil.
+dom0632. NS a.root-servers.nil.
+dom0633. NS a.root-servers.nil.
+dom0634. NS a.root-servers.nil.
+dom0635. NS a.root-servers.nil.
+dom0636. NS a.root-servers.nil.
+dom0637. NS a.root-servers.nil.
+dom0638. NS a.root-servers.nil.
+dom0639. NS a.root-servers.nil.
+dom0640. NS a.root-servers.nil.
+dom0641. NS a.root-servers.nil.
+dom0642. NS a.root-servers.nil.
+dom0643. NS a.root-servers.nil.
+dom0644. NS a.root-servers.nil.
+dom0645. NS a.root-servers.nil.
+dom0646. NS a.root-servers.nil.
+dom0647. NS a.root-servers.nil.
+dom0648. NS a.root-servers.nil.
+dom0649. NS a.root-servers.nil.
+dom0650. NS a.root-servers.nil.
+dom0651. NS a.root-servers.nil.
+dom0652. NS a.root-servers.nil.
+dom0653. NS a.root-servers.nil.
+dom0654. NS a.root-servers.nil.
+dom0655. NS a.root-servers.nil.
+dom0656. NS a.root-servers.nil.
+dom0657. NS a.root-servers.nil.
+dom0658. NS a.root-servers.nil.
+dom0659. NS a.root-servers.nil.
+dom0660. NS a.root-servers.nil.
+dom0661. NS a.root-servers.nil.
+dom0662. NS a.root-servers.nil.
+dom0663. NS a.root-servers.nil.
+dom0664. NS a.root-servers.nil.
+dom0665. NS a.root-servers.nil.
+dom0666. NS a.root-servers.nil.
+dom0667. NS a.root-servers.nil.
+dom0668. NS a.root-servers.nil.
+dom0669. NS a.root-servers.nil.
+dom0670. NS a.root-servers.nil.
+dom0671. NS a.root-servers.nil.
+dom0672. NS a.root-servers.nil.
+dom0673. NS a.root-servers.nil.
+dom0674. NS a.root-servers.nil.
+dom0675. NS a.root-servers.nil.
+dom0676. NS a.root-servers.nil.
+dom0677. NS a.root-servers.nil.
+dom0678. NS a.root-servers.nil.
+dom0679. NS a.root-servers.nil.
+dom0680. NS a.root-servers.nil.
+dom0681. NS a.root-servers.nil.
+dom0682. NS a.root-servers.nil.
+dom0683. NS a.root-servers.nil.
+dom0684. NS a.root-servers.nil.
+dom0685. NS a.root-servers.nil.
+dom0686. NS a.root-servers.nil.
+dom0687. NS a.root-servers.nil.
+dom0688. NS a.root-servers.nil.
+dom0689. NS a.root-servers.nil.
+dom0690. NS a.root-servers.nil.
+dom0691. NS a.root-servers.nil.
+dom0692. NS a.root-servers.nil.
+dom0693. NS a.root-servers.nil.
+dom0694. NS a.root-servers.nil.
+dom0695. NS a.root-servers.nil.
+dom0696. NS a.root-servers.nil.
+dom0697. NS a.root-servers.nil.
+dom0698. NS a.root-servers.nil.
+dom0699. NS a.root-servers.nil.
+dom0700. NS a.root-servers.nil.
+dom0701. NS a.root-servers.nil.
+dom0702. NS a.root-servers.nil.
+dom0703. NS a.root-servers.nil.
+dom0704. NS a.root-servers.nil.
+dom0705. NS a.root-servers.nil.
+dom0706. NS a.root-servers.nil.
+dom0707. NS a.root-servers.nil.
+dom0708. NS a.root-servers.nil.
+dom0709. NS a.root-servers.nil.
+dom0710. NS a.root-servers.nil.
+dom0711. NS a.root-servers.nil.
+dom0712. NS a.root-servers.nil.
+dom0713. NS a.root-servers.nil.
+dom0714. NS a.root-servers.nil.
+dom0715. NS a.root-servers.nil.
+dom0716. NS a.root-servers.nil.
+dom0717. NS a.root-servers.nil.
+dom0718. NS a.root-servers.nil.
+dom0719. NS a.root-servers.nil.
+dom0720. NS a.root-servers.nil.
+dom0721. NS a.root-servers.nil.
+dom0722. NS a.root-servers.nil.
+dom0723. NS a.root-servers.nil.
+dom0724. NS a.root-servers.nil.
+dom0725. NS a.root-servers.nil.
+dom0726. NS a.root-servers.nil.
+dom0727. NS a.root-servers.nil.
+dom0728. NS a.root-servers.nil.
+dom0729. NS a.root-servers.nil.
+dom0730. NS a.root-servers.nil.
+dom0731. NS a.root-servers.nil.
+dom0732. NS a.root-servers.nil.
+dom0733. NS a.root-servers.nil.
+dom0734. NS a.root-servers.nil.
+dom0735. NS a.root-servers.nil.
+dom0736. NS a.root-servers.nil.
+dom0737. NS a.root-servers.nil.
+dom0738. NS a.root-servers.nil.
+dom0739. NS a.root-servers.nil.
+dom0740. NS a.root-servers.nil.
+dom0741. NS a.root-servers.nil.
+dom0742. NS a.root-servers.nil.
+dom0743. NS a.root-servers.nil.
+dom0744. NS a.root-servers.nil.
+dom0745. NS a.root-servers.nil.
+dom0746. NS a.root-servers.nil.
+dom0747. NS a.root-servers.nil.
+dom0748. NS a.root-servers.nil.
+dom0749. NS a.root-servers.nil.
+dom0750. NS a.root-servers.nil.
+dom0751. NS a.root-servers.nil.
+dom0752. NS a.root-servers.nil.
+dom0753. NS a.root-servers.nil.
+dom0754. NS a.root-servers.nil.
+dom0755. NS a.root-servers.nil.
+dom0756. NS a.root-servers.nil.
+dom0757. NS a.root-servers.nil.
+dom0758. NS a.root-servers.nil.
+dom0759. NS a.root-servers.nil.
+dom0760. NS a.root-servers.nil.
+dom0761. NS a.root-servers.nil.
+dom0762. NS a.root-servers.nil.
+dom0763. NS a.root-servers.nil.
+dom0764. NS a.root-servers.nil.
+dom0765. NS a.root-servers.nil.
+dom0766. NS a.root-servers.nil.
+dom0767. NS a.root-servers.nil.
+dom0768. NS a.root-servers.nil.
+dom0769. NS a.root-servers.nil.
+dom0770. NS a.root-servers.nil.
+dom0771. NS a.root-servers.nil.
+dom0772. NS a.root-servers.nil.
+dom0773. NS a.root-servers.nil.
+dom0774. NS a.root-servers.nil.
+dom0775. NS a.root-servers.nil.
+dom0776. NS a.root-servers.nil.
+dom0777. NS a.root-servers.nil.
+dom0778. NS a.root-servers.nil.
+dom0779. NS a.root-servers.nil.
+dom0780. NS a.root-servers.nil.
+dom0781. NS a.root-servers.nil.
+dom0782. NS a.root-servers.nil.
+dom0783. NS a.root-servers.nil.
+dom0784. NS a.root-servers.nil.
+dom0785. NS a.root-servers.nil.
+dom0786. NS a.root-servers.nil.
+dom0787. NS a.root-servers.nil.
+dom0788. NS a.root-servers.nil.
+dom0789. NS a.root-servers.nil.
+dom0790. NS a.root-servers.nil.
+dom0791. NS a.root-servers.nil.
+dom0792. NS a.root-servers.nil.
+dom0793. NS a.root-servers.nil.
+dom0794. NS a.root-servers.nil.
+dom0795. NS a.root-servers.nil.
+dom0796. NS a.root-servers.nil.
+dom0797. NS a.root-servers.nil.
+dom0798. NS a.root-servers.nil.
+dom0799. NS a.root-servers.nil.
+dom0800. NS a.root-servers.nil.
+dom0801. NS a.root-servers.nil.
+dom0802. NS a.root-servers.nil.
+dom0803. NS a.root-servers.nil.
+dom0804. NS a.root-servers.nil.
+dom0805. NS a.root-servers.nil.
+dom0806. NS a.root-servers.nil.
+dom0807. NS a.root-servers.nil.
+dom0808. NS a.root-servers.nil.
+dom0809. NS a.root-servers.nil.
+dom0810. NS a.root-servers.nil.
+dom0811. NS a.root-servers.nil.
+dom0812. NS a.root-servers.nil.
+dom0813. NS a.root-servers.nil.
+dom0814. NS a.root-servers.nil.
+dom0815. NS a.root-servers.nil.
+dom0816. NS a.root-servers.nil.
+dom0817. NS a.root-servers.nil.
+dom0818. NS a.root-servers.nil.
+dom0819. NS a.root-servers.nil.
+dom0820. NS a.root-servers.nil.
+dom0821. NS a.root-servers.nil.
+dom0822. NS a.root-servers.nil.
+dom0823. NS a.root-servers.nil.
+dom0824. NS a.root-servers.nil.
+dom0825. NS a.root-servers.nil.
+dom0826. NS a.root-servers.nil.
+dom0827. NS a.root-servers.nil.
+dom0828. NS a.root-servers.nil.
+dom0829. NS a.root-servers.nil.
+dom0830. NS a.root-servers.nil.
+dom0831. NS a.root-servers.nil.
+dom0832. NS a.root-servers.nil.
+dom0833. NS a.root-servers.nil.
+dom0834. NS a.root-servers.nil.
+dom0835. NS a.root-servers.nil.
+dom0836. NS a.root-servers.nil.
+dom0837. NS a.root-servers.nil.
+dom0838. NS a.root-servers.nil.
+dom0839. NS a.root-servers.nil.
+dom0840. NS a.root-servers.nil.
+dom0841. NS a.root-servers.nil.
+dom0842. NS a.root-servers.nil.
+dom0843. NS a.root-servers.nil.
+dom0844. NS a.root-servers.nil.
+dom0845. NS a.root-servers.nil.
+dom0846. NS a.root-servers.nil.
+dom0847. NS a.root-servers.nil.
+dom0848. NS a.root-servers.nil.
+dom0849. NS a.root-servers.nil.
+dom0850. NS a.root-servers.nil.
+dom0851. NS a.root-servers.nil.
+dom0852. NS a.root-servers.nil.
+dom0853. NS a.root-servers.nil.
+dom0854. NS a.root-servers.nil.
+dom0855. NS a.root-servers.nil.
+dom0856. NS a.root-servers.nil.
+dom0857. NS a.root-servers.nil.
+dom0858. NS a.root-servers.nil.
+dom0859. NS a.root-servers.nil.
+dom0860. NS a.root-servers.nil.
+dom0861. NS a.root-servers.nil.
+dom0862. NS a.root-servers.nil.
+dom0863. NS a.root-servers.nil.
+dom0864. NS a.root-servers.nil.
+dom0865. NS a.root-servers.nil.
+dom0866. NS a.root-servers.nil.
+dom0867. NS a.root-servers.nil.
+dom0868. NS a.root-servers.nil.
+dom0869. NS a.root-servers.nil.
+dom0870. NS a.root-servers.nil.
+dom0871. NS a.root-servers.nil.
+dom0872. NS a.root-servers.nil.
+dom0873. NS a.root-servers.nil.
+dom0874. NS a.root-servers.nil.
+dom0875. NS a.root-servers.nil.
+dom0876. NS a.root-servers.nil.
+dom0877. NS a.root-servers.nil.
+dom0878. NS a.root-servers.nil.
+dom0879. NS a.root-servers.nil.
+dom0880. NS a.root-servers.nil.
+dom0881. NS a.root-servers.nil.
+dom0882. NS a.root-servers.nil.
+dom0883. NS a.root-servers.nil.
+dom0884. NS a.root-servers.nil.
+dom0885. NS a.root-servers.nil.
+dom0886. NS a.root-servers.nil.
+dom0887. NS a.root-servers.nil.
+dom0888. NS a.root-servers.nil.
+dom0889. NS a.root-servers.nil.
+dom0890. NS a.root-servers.nil.
+dom0891. NS a.root-servers.nil.
+dom0892. NS a.root-servers.nil.
+dom0893. NS a.root-servers.nil.
+dom0894. NS a.root-servers.nil.
+dom0895. NS a.root-servers.nil.
+dom0896. NS a.root-servers.nil.
+dom0897. NS a.root-servers.nil.
+dom0898. NS a.root-servers.nil.
+dom0899. NS a.root-servers.nil.
+dom0900. NS a.root-servers.nil.
+dom0901. NS a.root-servers.nil.
+dom0902. NS a.root-servers.nil.
+dom0903. NS a.root-servers.nil.
+dom0904. NS a.root-servers.nil.
+dom0905. NS a.root-servers.nil.
+dom0906. NS a.root-servers.nil.
+dom0907. NS a.root-servers.nil.
+dom0908. NS a.root-servers.nil.
+dom0909. NS a.root-servers.nil.
+dom0910. NS a.root-servers.nil.
+dom0911. NS a.root-servers.nil.
+dom0912. NS a.root-servers.nil.
+dom0913. NS a.root-servers.nil.
+dom0914. NS a.root-servers.nil.
+dom0915. NS a.root-servers.nil.
+dom0916. NS a.root-servers.nil.
+dom0917. NS a.root-servers.nil.
+dom0918. NS a.root-servers.nil.
+dom0919. NS a.root-servers.nil.
+dom0920. NS a.root-servers.nil.
+dom0921. NS a.root-servers.nil.
+dom0922. NS a.root-servers.nil.
+dom0923. NS a.root-servers.nil.
+dom0924. NS a.root-servers.nil.
+dom0925. NS a.root-servers.nil.
+dom0926. NS a.root-servers.nil.
+dom0927. NS a.root-servers.nil.
+dom0928. NS a.root-servers.nil.
+dom0929. NS a.root-servers.nil.
+dom0930. NS a.root-servers.nil.
+dom0931. NS a.root-servers.nil.
+dom0932. NS a.root-servers.nil.
+dom0933. NS a.root-servers.nil.
+dom0934. NS a.root-servers.nil.
+dom0935. NS a.root-servers.nil.
+dom0936. NS a.root-servers.nil.
+dom0937. NS a.root-servers.nil.
+dom0938. NS a.root-servers.nil.
+dom0939. NS a.root-servers.nil.
+dom0940. NS a.root-servers.nil.
+dom0941. NS a.root-servers.nil.
+dom0942. NS a.root-servers.nil.
+dom0943. NS a.root-servers.nil.
+dom0944. NS a.root-servers.nil.
+dom0945. NS a.root-servers.nil.
+dom0946. NS a.root-servers.nil.
+dom0947. NS a.root-servers.nil.
+dom0948. NS a.root-servers.nil.
+dom0949. NS a.root-servers.nil.
+dom0950. NS a.root-servers.nil.
+dom0951. NS a.root-servers.nil.
+dom0952. NS a.root-servers.nil.
+dom0953. NS a.root-servers.nil.
+dom0954. NS a.root-servers.nil.
+dom0955. NS a.root-servers.nil.
+dom0956. NS a.root-servers.nil.
+dom0957. NS a.root-servers.nil.
+dom0958. NS a.root-servers.nil.
+dom0959. NS a.root-servers.nil.
+dom0960. NS a.root-servers.nil.
+dom0961. NS a.root-servers.nil.
+dom0962. NS a.root-servers.nil.
+dom0963. NS a.root-servers.nil.
+dom0964. NS a.root-servers.nil.
+dom0965. NS a.root-servers.nil.
+dom0966. NS a.root-servers.nil.
+dom0967. NS a.root-servers.nil.
+dom0968. NS a.root-servers.nil.
+dom0969. NS a.root-servers.nil.
+dom0970. NS a.root-servers.nil.
+dom0971. NS a.root-servers.nil.
+dom0972. NS a.root-servers.nil.
+dom0973. NS a.root-servers.nil.
+dom0974. NS a.root-servers.nil.
+dom0975. NS a.root-servers.nil.
+dom0976. NS a.root-servers.nil.
+dom0977. NS a.root-servers.nil.
+dom0978. NS a.root-servers.nil.
+dom0979. NS a.root-servers.nil.
+dom0980. NS a.root-servers.nil.
+dom0981. NS a.root-servers.nil.
+dom0982. NS a.root-servers.nil.
+dom0983. NS a.root-servers.nil.
+dom0984. NS a.root-servers.nil.
+dom0985. NS a.root-servers.nil.
+dom0986. NS a.root-servers.nil.
+dom0987. NS a.root-servers.nil.
+dom0988. NS a.root-servers.nil.
+dom0989. NS a.root-servers.nil.
+dom0990. NS a.root-servers.nil.
+dom0991. NS a.root-servers.nil.
+dom0992. NS a.root-servers.nil.
+dom0993. NS a.root-servers.nil.
+dom0994. NS a.root-servers.nil.
+dom0995. NS a.root-servers.nil.
+dom0996. NS a.root-servers.nil.
+dom0997. NS a.root-servers.nil.
+dom0998. NS a.root-servers.nil.
+dom0999. NS a.root-servers.nil.
+dom1000. NS a.root-servers.nil.
+dom1001. NS a.root-servers.nil.
+dom1002. NS a.root-servers.nil.
+dom1003. NS a.root-servers.nil.
+dom1004. NS a.root-servers.nil.
+dom1005. NS a.root-servers.nil.
+dom1006. NS a.root-servers.nil.
+dom1007. NS a.root-servers.nil.
+dom1008. NS a.root-servers.nil.
+dom1009. NS a.root-servers.nil.
+dom1010. NS a.root-servers.nil.
+dom1011. NS a.root-servers.nil.
+dom1012. NS a.root-servers.nil.
+dom1013. NS a.root-servers.nil.
+dom1014. NS a.root-servers.nil.
+dom1015. NS a.root-servers.nil.
+dom1016. NS a.root-servers.nil.
+dom1017. NS a.root-servers.nil.
+dom1018. NS a.root-servers.nil.
+dom1019. NS a.root-servers.nil.
+dom1020. NS a.root-servers.nil.
+dom1021. NS a.root-servers.nil.
+dom1022. NS a.root-servers.nil.
+dom1023. NS a.root-servers.nil.
+dom1024. NS a.root-servers.nil.
+dom1025. NS a.root-servers.nil.
+dom1026. NS a.root-servers.nil.
+dom1027. NS a.root-servers.nil.
+dom1028. NS a.root-servers.nil.
+dom1029. NS a.root-servers.nil.
+dom1030. NS a.root-servers.nil.
+dom1031. NS a.root-servers.nil.
+dom1032. NS a.root-servers.nil.
+dom1033. NS a.root-servers.nil.
+dom1034. NS a.root-servers.nil.
+dom1035. NS a.root-servers.nil.
+dom1036. NS a.root-servers.nil.
+dom1037. NS a.root-servers.nil.
+dom1038. NS a.root-servers.nil.
+dom1039. NS a.root-servers.nil.
+dom1040. NS a.root-servers.nil.
+dom1041. NS a.root-servers.nil.
+dom1042. NS a.root-servers.nil.
+dom1043. NS a.root-servers.nil.
+dom1044. NS a.root-servers.nil.
+dom1045. NS a.root-servers.nil.
+dom1046. NS a.root-servers.nil.
+dom1047. NS a.root-servers.nil.
+dom1048. NS a.root-servers.nil.
+dom1049. NS a.root-servers.nil.
+dom1050. NS a.root-servers.nil.
+dom1051. NS a.root-servers.nil.
+dom1052. NS a.root-servers.nil.
+dom1053. NS a.root-servers.nil.
+dom1054. NS a.root-servers.nil.
+dom1055. NS a.root-servers.nil.
+dom1056. NS a.root-servers.nil.
+dom1057. NS a.root-servers.nil.
+dom1058. NS a.root-servers.nil.
+dom1059. NS a.root-servers.nil.
+dom1060. NS a.root-servers.nil.
+dom1061. NS a.root-servers.nil.
+dom1062. NS a.root-servers.nil.
+dom1063. NS a.root-servers.nil.
+dom1064. NS a.root-servers.nil.
+dom1065. NS a.root-servers.nil.
+dom1066. NS a.root-servers.nil.
+dom1067. NS a.root-servers.nil.
+dom1068. NS a.root-servers.nil.
+dom1069. NS a.root-servers.nil.
+dom1070. NS a.root-servers.nil.
+dom1071. NS a.root-servers.nil.
+dom1072. NS a.root-servers.nil.
+dom1073. NS a.root-servers.nil.
+dom1074. NS a.root-servers.nil.
+dom1075. NS a.root-servers.nil.
+dom1076. NS a.root-servers.nil.
+dom1077. NS a.root-servers.nil.
+dom1078. NS a.root-servers.nil.
+dom1079. NS a.root-servers.nil.
+dom1080. NS a.root-servers.nil.
+dom1081. NS a.root-servers.nil.
+dom1082. NS a.root-servers.nil.
+dom1083. NS a.root-servers.nil.
+dom1084. NS a.root-servers.nil.
+dom1085. NS a.root-servers.nil.
+dom1086. NS a.root-servers.nil.
+dom1087. NS a.root-servers.nil.
+dom1088. NS a.root-servers.nil.
+dom1089. NS a.root-servers.nil.
+dom1090. NS a.root-servers.nil.
+dom1091. NS a.root-servers.nil.
+dom1092. NS a.root-servers.nil.
+dom1093. NS a.root-servers.nil.
+dom1094. NS a.root-servers.nil.
+dom1095. NS a.root-servers.nil.
+dom1096. NS a.root-servers.nil.
+dom1097. NS a.root-servers.nil.
+dom1098. NS a.root-servers.nil.
+dom1099. NS a.root-servers.nil.
+dom1100. NS a.root-servers.nil.
+dom1101. NS a.root-servers.nil.
+dom1102. NS a.root-servers.nil.
+dom1103. NS a.root-servers.nil.
+dom1104. NS a.root-servers.nil.
+dom1105. NS a.root-servers.nil.
+dom1106. NS a.root-servers.nil.
+dom1107. NS a.root-servers.nil.
+dom1108. NS a.root-servers.nil.
+dom1109. NS a.root-servers.nil.
+dom1110. NS a.root-servers.nil.
+dom1111. NS a.root-servers.nil.
+dom1112. NS a.root-servers.nil.
+dom1113. NS a.root-servers.nil.
+dom1114. NS a.root-servers.nil.
+dom1115. NS a.root-servers.nil.
+dom1116. NS a.root-servers.nil.
+dom1117. NS a.root-servers.nil.
+dom1118. NS a.root-servers.nil.
+dom1119. NS a.root-servers.nil.
+dom1120. NS a.root-servers.nil.
+dom1121. NS a.root-servers.nil.
+dom1122. NS a.root-servers.nil.
+dom1123. NS a.root-servers.nil.
+dom1124. NS a.root-servers.nil.
+dom1125. NS a.root-servers.nil.
+dom1126. NS a.root-servers.nil.
+dom1127. NS a.root-servers.nil.
+dom1128. NS a.root-servers.nil.
+dom1129. NS a.root-servers.nil.
+dom1130. NS a.root-servers.nil.
+dom1131. NS a.root-servers.nil.
+dom1132. NS a.root-servers.nil.
+dom1133. NS a.root-servers.nil.
+dom1134. NS a.root-servers.nil.
+dom1135. NS a.root-servers.nil.
+dom1136. NS a.root-servers.nil.
+dom1137. NS a.root-servers.nil.
+dom1138. NS a.root-servers.nil.
+dom1139. NS a.root-servers.nil.
+dom1140. NS a.root-servers.nil.
+dom1141. NS a.root-servers.nil.
+dom1142. NS a.root-servers.nil.
+dom1143. NS a.root-servers.nil.
+dom1144. NS a.root-servers.nil.
+dom1145. NS a.root-servers.nil.
+dom1146. NS a.root-servers.nil.
+dom1147. NS a.root-servers.nil.
+dom1148. NS a.root-servers.nil.
+dom1149. NS a.root-servers.nil.
+dom1150. NS a.root-servers.nil.
+dom1151. NS a.root-servers.nil.
+dom1152. NS a.root-servers.nil.
+dom1153. NS a.root-servers.nil.
+dom1154. NS a.root-servers.nil.
+dom1155. NS a.root-servers.nil.
+dom1156. NS a.root-servers.nil.
+dom1157. NS a.root-servers.nil.
+dom1158. NS a.root-servers.nil.
+dom1159. NS a.root-servers.nil.
+dom1160. NS a.root-servers.nil.
+dom1161. NS a.root-servers.nil.
+dom1162. NS a.root-servers.nil.
+dom1163. NS a.root-servers.nil.
+dom1164. NS a.root-servers.nil.
+dom1165. NS a.root-servers.nil.
+dom1166. NS a.root-servers.nil.
+dom1167. NS a.root-servers.nil.
+dom1168. NS a.root-servers.nil.
+dom1169. NS a.root-servers.nil.
+dom1170. NS a.root-servers.nil.
+dom1171. NS a.root-servers.nil.
+dom1172. NS a.root-servers.nil.
+dom1173. NS a.root-servers.nil.
+dom1174. NS a.root-servers.nil.
+dom1175. NS a.root-servers.nil.
+dom1176. NS a.root-servers.nil.
+dom1177. NS a.root-servers.nil.
+dom1178. NS a.root-servers.nil.
+dom1179. NS a.root-servers.nil.
+dom1180. NS a.root-servers.nil.
+dom1181. NS a.root-servers.nil.
+dom1182. NS a.root-servers.nil.
+dom1183. NS a.root-servers.nil.
+dom1184. NS a.root-servers.nil.
+dom1185. NS a.root-servers.nil.
+dom1186. NS a.root-servers.nil.
+dom1187. NS a.root-servers.nil.
+dom1188. NS a.root-servers.nil.
+dom1189. NS a.root-servers.nil.
+dom1190. NS a.root-servers.nil.
+dom1191. NS a.root-servers.nil.
+dom1192. NS a.root-servers.nil.
+dom1193. NS a.root-servers.nil.
+dom1194. NS a.root-servers.nil.
+dom1195. NS a.root-servers.nil.
+dom1196. NS a.root-servers.nil.
+dom1197. NS a.root-servers.nil.
+dom1198. NS a.root-servers.nil.
+dom1199. NS a.root-servers.nil.
+dom1200. NS a.root-servers.nil.
+dom1201. NS a.root-servers.nil.
+dom1202. NS a.root-servers.nil.
+dom1203. NS a.root-servers.nil.
+dom1204. NS a.root-servers.nil.
+dom1205. NS a.root-servers.nil.
+dom1206. NS a.root-servers.nil.
+dom1207. NS a.root-servers.nil.
+dom1208. NS a.root-servers.nil.
+dom1209. NS a.root-servers.nil.
+dom1210. NS a.root-servers.nil.
+dom1211. NS a.root-servers.nil.
+dom1212. NS a.root-servers.nil.
+dom1213. NS a.root-servers.nil.
+dom1214. NS a.root-servers.nil.
+dom1215. NS a.root-servers.nil.
+dom1216. NS a.root-servers.nil.
+dom1217. NS a.root-servers.nil.
+dom1218. NS a.root-servers.nil.
+dom1219. NS a.root-servers.nil.
+dom1220. NS a.root-servers.nil.
+dom1221. NS a.root-servers.nil.
+dom1222. NS a.root-servers.nil.
+dom1223. NS a.root-servers.nil.
+dom1224. NS a.root-servers.nil.
+dom1225. NS a.root-servers.nil.
+dom1226. NS a.root-servers.nil.
+dom1227. NS a.root-servers.nil.
+dom1228. NS a.root-servers.nil.
+dom1229. NS a.root-servers.nil.
+dom1230. NS a.root-servers.nil.
+dom1231. NS a.root-servers.nil.
+dom1232. NS a.root-servers.nil.
+dom1233. NS a.root-servers.nil.
+dom1234. NS a.root-servers.nil.
+dom1235. NS a.root-servers.nil.
+dom1236. NS a.root-servers.nil.
+dom1237. NS a.root-servers.nil.
+dom1238. NS a.root-servers.nil.
+dom1239. NS a.root-servers.nil.
+dom1240. NS a.root-servers.nil.
+dom1241. NS a.root-servers.nil.
+dom1242. NS a.root-servers.nil.
+dom1243. NS a.root-servers.nil.
+dom1244. NS a.root-servers.nil.
+dom1245. NS a.root-servers.nil.
+dom1246. NS a.root-servers.nil.
+dom1247. NS a.root-servers.nil.
+dom1248. NS a.root-servers.nil.
+dom1249. NS a.root-servers.nil.
+dom1250. NS a.root-servers.nil.
+dom1251. NS a.root-servers.nil.
+dom1252. NS a.root-servers.nil.
+dom1253. NS a.root-servers.nil.
+dom1254. NS a.root-servers.nil.
+dom1255. NS a.root-servers.nil.
+dom1256. NS a.root-servers.nil.
+dom1257. NS a.root-servers.nil.
+dom1258. NS a.root-servers.nil.
+dom1259. NS a.root-servers.nil.
+dom1260. NS a.root-servers.nil.
+dom1261. NS a.root-servers.nil.
+dom1262. NS a.root-servers.nil.
+dom1263. NS a.root-servers.nil.
+dom1264. NS a.root-servers.nil.
+dom1265. NS a.root-servers.nil.
+dom1266. NS a.root-servers.nil.
+dom1267. NS a.root-servers.nil.
+dom1268. NS a.root-servers.nil.
+dom1269. NS a.root-servers.nil.
+dom1270. NS a.root-servers.nil.
+dom1271. NS a.root-servers.nil.
+dom1272. NS a.root-servers.nil.
+dom1273. NS a.root-servers.nil.
+dom1274. NS a.root-servers.nil.
+dom1275. NS a.root-servers.nil.
+dom1276. NS a.root-servers.nil.
+dom1277. NS a.root-servers.nil.
+dom1278. NS a.root-servers.nil.
+dom1279. NS a.root-servers.nil.
+dom1280. NS a.root-servers.nil.
+dom1281. NS a.root-servers.nil.
+dom1282. NS a.root-servers.nil.
+dom1283. NS a.root-servers.nil.
+dom1284. NS a.root-servers.nil.
+dom1285. NS a.root-servers.nil.
+dom1286. NS a.root-servers.nil.
+dom1287. NS a.root-servers.nil.
+dom1288. NS a.root-servers.nil.
+dom1289. NS a.root-servers.nil.
+dom1290. NS a.root-servers.nil.
+dom1291. NS a.root-servers.nil.
+dom1292. NS a.root-servers.nil.
+dom1293. NS a.root-servers.nil.
+dom1294. NS a.root-servers.nil.
+dom1295. NS a.root-servers.nil.
+dom1296. NS a.root-servers.nil.
+dom1297. NS a.root-servers.nil.
+dom1298. NS a.root-servers.nil.
+dom1299. NS a.root-servers.nil.
+dom1300. NS a.root-servers.nil.
+dom1301. NS a.root-servers.nil.
+dom1302. NS a.root-servers.nil.
+dom1303. NS a.root-servers.nil.
+dom1304. NS a.root-servers.nil.
+dom1305. NS a.root-servers.nil.
+dom1306. NS a.root-servers.nil.
+dom1307. NS a.root-servers.nil.
+dom1308. NS a.root-servers.nil.
+dom1309. NS a.root-servers.nil.
+dom1310. NS a.root-servers.nil.
+dom1311. NS a.root-servers.nil.
+dom1312. NS a.root-servers.nil.
+dom1313. NS a.root-servers.nil.
+dom1314. NS a.root-servers.nil.
+dom1315. NS a.root-servers.nil.
+dom1316. NS a.root-servers.nil.
+dom1317. NS a.root-servers.nil.
+dom1318. NS a.root-servers.nil.
+dom1319. NS a.root-servers.nil.
+dom1320. NS a.root-servers.nil.
+dom1321. NS a.root-servers.nil.
+dom1322. NS a.root-servers.nil.
+dom1323. NS a.root-servers.nil.
+dom1324. NS a.root-servers.nil.
+dom1325. NS a.root-servers.nil.
+dom1326. NS a.root-servers.nil.
+dom1327. NS a.root-servers.nil.
+dom1328. NS a.root-servers.nil.
+dom1329. NS a.root-servers.nil.
+dom1330. NS a.root-servers.nil.
+dom1331. NS a.root-servers.nil.
+dom1332. NS a.root-servers.nil.
+dom1333. NS a.root-servers.nil.
+dom1334. NS a.root-servers.nil.
+dom1335. NS a.root-servers.nil.
+dom1336. NS a.root-servers.nil.
+dom1337. NS a.root-servers.nil.
+dom1338. NS a.root-servers.nil.
+dom1339. NS a.root-servers.nil.
+dom1340. NS a.root-servers.nil.
+dom1341. NS a.root-servers.nil.
+dom1342. NS a.root-servers.nil.
+dom1343. NS a.root-servers.nil.
+dom1344. NS a.root-servers.nil.
+dom1345. NS a.root-servers.nil.
+dom1346. NS a.root-servers.nil.
+dom1347. NS a.root-servers.nil.
+dom1348. NS a.root-servers.nil.
+dom1349. NS a.root-servers.nil.
+dom1350. NS a.root-servers.nil.
+dom1351. NS a.root-servers.nil.
+dom1352. NS a.root-servers.nil.
+dom1353. NS a.root-servers.nil.
+dom1354. NS a.root-servers.nil.
+dom1355. NS a.root-servers.nil.
+dom1356. NS a.root-servers.nil.
+dom1357. NS a.root-servers.nil.
+dom1358. NS a.root-servers.nil.
+dom1359. NS a.root-servers.nil.
+dom1360. NS a.root-servers.nil.
+dom1361. NS a.root-servers.nil.
+dom1362. NS a.root-servers.nil.
+dom1363. NS a.root-servers.nil.
+dom1364. NS a.root-servers.nil.
+dom1365. NS a.root-servers.nil.
+dom1366. NS a.root-servers.nil.
+dom1367. NS a.root-servers.nil.
+dom1368. NS a.root-servers.nil.
+dom1369. NS a.root-servers.nil.
+dom1370. NS a.root-servers.nil.
+dom1371. NS a.root-servers.nil.
+dom1372. NS a.root-servers.nil.
+dom1373. NS a.root-servers.nil.
+dom1374. NS a.root-servers.nil.
+dom1375. NS a.root-servers.nil.
+dom1376. NS a.root-servers.nil.
+dom1377. NS a.root-servers.nil.
+dom1378. NS a.root-servers.nil.
+dom1379. NS a.root-servers.nil.
+dom1380. NS a.root-servers.nil.
+dom1381. NS a.root-servers.nil.
+dom1382. NS a.root-servers.nil.
+dom1383. NS a.root-servers.nil.
+dom1384. NS a.root-servers.nil.
+dom1385. NS a.root-servers.nil.
+dom1386. NS a.root-servers.nil.
+dom1387. NS a.root-servers.nil.
+dom1388. NS a.root-servers.nil.
+dom1389. NS a.root-servers.nil.
+dom1390. NS a.root-servers.nil.
+dom1391. NS a.root-servers.nil.
+dom1392. NS a.root-servers.nil.
+dom1393. NS a.root-servers.nil.
+dom1394. NS a.root-servers.nil.
+dom1395. NS a.root-servers.nil.
+dom1396. NS a.root-servers.nil.
+dom1397. NS a.root-servers.nil.
+dom1398. NS a.root-servers.nil.
+dom1399. NS a.root-servers.nil.
+dom1400. NS a.root-servers.nil.
+dom1401. NS a.root-servers.nil.
+dom1402. NS a.root-servers.nil.
+dom1403. NS a.root-servers.nil.
+dom1404. NS a.root-servers.nil.
+dom1405. NS a.root-servers.nil.
+dom1406. NS a.root-servers.nil.
+dom1407. NS a.root-servers.nil.
+dom1408. NS a.root-servers.nil.
+dom1409. NS a.root-servers.nil.
+dom1410. NS a.root-servers.nil.
+dom1411. NS a.root-servers.nil.
+dom1412. NS a.root-servers.nil.
+dom1413. NS a.root-servers.nil.
+dom1414. NS a.root-servers.nil.
+dom1415. NS a.root-servers.nil.
+dom1416. NS a.root-servers.nil.
+dom1417. NS a.root-servers.nil.
+dom1418. NS a.root-servers.nil.
+dom1419. NS a.root-servers.nil.
+dom1420. NS a.root-servers.nil.
+dom1421. NS a.root-servers.nil.
+dom1422. NS a.root-servers.nil.
+dom1423. NS a.root-servers.nil.
+dom1424. NS a.root-servers.nil.
+dom1425. NS a.root-servers.nil.
+dom1426. NS a.root-servers.nil.
+dom1427. NS a.root-servers.nil.
+dom1428. NS a.root-servers.nil.
+dom1429. NS a.root-servers.nil.
+dom1430. NS a.root-servers.nil.
+dom1431. NS a.root-servers.nil.
+dom1432. NS a.root-servers.nil.
+dom1433. NS a.root-servers.nil.
+dom1434. NS a.root-servers.nil.
+dom1435. NS a.root-servers.nil.
+dom1436. NS a.root-servers.nil.
+dom1437. NS a.root-servers.nil.
+dom1438. NS a.root-servers.nil.
+dom1439. NS a.root-servers.nil.
+dom1440. NS a.root-servers.nil.
+dom1441. NS a.root-servers.nil.
+dom1442. NS a.root-servers.nil.
+dom1443. NS a.root-servers.nil.
+dom1444. NS a.root-servers.nil.
+dom1445. NS a.root-servers.nil.
+dom1446. NS a.root-servers.nil.
+dom1447. NS a.root-servers.nil.
+dom1448. NS a.root-servers.nil.
+dom1449. NS a.root-servers.nil.
+dom1450. NS a.root-servers.nil.
+dom1451. NS a.root-servers.nil.
+dom1452. NS a.root-servers.nil.
+dom1453. NS a.root-servers.nil.
+dom1454. NS a.root-servers.nil.
+dom1455. NS a.root-servers.nil.
+dom1456. NS a.root-servers.nil.
+dom1457. NS a.root-servers.nil.
+dom1458. NS a.root-servers.nil.
+dom1459. NS a.root-servers.nil.
+dom1460. NS a.root-servers.nil.
+dom1461. NS a.root-servers.nil.
+dom1462. NS a.root-servers.nil.
+dom1463. NS a.root-servers.nil.
+dom1464. NS a.root-servers.nil.
+dom1465. NS a.root-servers.nil.
+dom1466. NS a.root-servers.nil.
+dom1467. NS a.root-servers.nil.
+dom1468. NS a.root-servers.nil.
+dom1469. NS a.root-servers.nil.
+dom1470. NS a.root-servers.nil.
+dom1471. NS a.root-servers.nil.
+dom1472. NS a.root-servers.nil.
+dom1473. NS a.root-servers.nil.
+dom1474. NS a.root-servers.nil.
+dom1475. NS a.root-servers.nil.
+dom1476. NS a.root-servers.nil.
+dom1477. NS a.root-servers.nil.
+dom1478. NS a.root-servers.nil.
+dom1479. NS a.root-servers.nil.
+dom1480. NS a.root-servers.nil.
+dom1481. NS a.root-servers.nil.
+dom1482. NS a.root-servers.nil.
+dom1483. NS a.root-servers.nil.
+dom1484. NS a.root-servers.nil.
+dom1485. NS a.root-servers.nil.
+dom1486. NS a.root-servers.nil.
+dom1487. NS a.root-servers.nil.
+dom1488. NS a.root-servers.nil.
+dom1489. NS a.root-servers.nil.
+dom1490. NS a.root-servers.nil.
+dom1491. NS a.root-servers.nil.
+dom1492. NS a.root-servers.nil.
+dom1493. NS a.root-servers.nil.
+dom1494. NS a.root-servers.nil.
+dom1495. NS a.root-servers.nil.
+dom1496. NS a.root-servers.nil.
+dom1497. NS a.root-servers.nil.
+dom1498. NS a.root-servers.nil.
+dom1499. NS a.root-servers.nil.
+dom1500. NS a.root-servers.nil.
+dom1501. NS a.root-servers.nil.
+dom1502. NS a.root-servers.nil.
+dom1503. NS a.root-servers.nil.
+dom1504. NS a.root-servers.nil.
+dom1505. NS a.root-servers.nil.
+dom1506. NS a.root-servers.nil.
+dom1507. NS a.root-servers.nil.
+dom1508. NS a.root-servers.nil.
+dom1509. NS a.root-servers.nil.
+dom1510. NS a.root-servers.nil.
+dom1511. NS a.root-servers.nil.
+dom1512. NS a.root-servers.nil.
+dom1513. NS a.root-servers.nil.
+dom1514. NS a.root-servers.nil.
+dom1515. NS a.root-servers.nil.
+dom1516. NS a.root-servers.nil.
+dom1517. NS a.root-servers.nil.
+dom1518. NS a.root-servers.nil.
+dom1519. NS a.root-servers.nil.
+dom1520. NS a.root-servers.nil.
+dom1521. NS a.root-servers.nil.
+dom1522. NS a.root-servers.nil.
+dom1523. NS a.root-servers.nil.
+dom1524. NS a.root-servers.nil.
+dom1525. NS a.root-servers.nil.
+dom1526. NS a.root-servers.nil.
+dom1527. NS a.root-servers.nil.
+dom1528. NS a.root-servers.nil.
+dom1529. NS a.root-servers.nil.
+dom1530. NS a.root-servers.nil.
+dom1531. NS a.root-servers.nil.
+dom1532. NS a.root-servers.nil.
+dom1533. NS a.root-servers.nil.
+dom1534. NS a.root-servers.nil.
+dom1535. NS a.root-servers.nil.
+dom1536. NS a.root-servers.nil.
+dom1537. NS a.root-servers.nil.
+dom1538. NS a.root-servers.nil.
+dom1539. NS a.root-servers.nil.
+dom1540. NS a.root-servers.nil.
+dom1541. NS a.root-servers.nil.
+dom1542. NS a.root-servers.nil.
+dom1543. NS a.root-servers.nil.
+dom1544. NS a.root-servers.nil.
+dom1545. NS a.root-servers.nil.
+dom1546. NS a.root-servers.nil.
+dom1547. NS a.root-servers.nil.
+dom1548. NS a.root-servers.nil.
+dom1549. NS a.root-servers.nil.
+dom1550. NS a.root-servers.nil.
+dom1551. NS a.root-servers.nil.
+dom1552. NS a.root-servers.nil.
+dom1553. NS a.root-servers.nil.
+dom1554. NS a.root-servers.nil.
+dom1555. NS a.root-servers.nil.
+dom1556. NS a.root-servers.nil.
+dom1557. NS a.root-servers.nil.
+dom1558. NS a.root-servers.nil.
+dom1559. NS a.root-servers.nil.
+dom1560. NS a.root-servers.nil.
+dom1561. NS a.root-servers.nil.
+dom1562. NS a.root-servers.nil.
+dom1563. NS a.root-servers.nil.
+dom1564. NS a.root-servers.nil.
+dom1565. NS a.root-servers.nil.
+dom1566. NS a.root-servers.nil.
+dom1567. NS a.root-servers.nil.
+dom1568. NS a.root-servers.nil.
+dom1569. NS a.root-servers.nil.
+dom1570. NS a.root-servers.nil.
+dom1571. NS a.root-servers.nil.
+dom1572. NS a.root-servers.nil.
+dom1573. NS a.root-servers.nil.
+dom1574. NS a.root-servers.nil.
+dom1575. NS a.root-servers.nil.
+dom1576. NS a.root-servers.nil.
+dom1577. NS a.root-servers.nil.
+dom1578. NS a.root-servers.nil.
+dom1579. NS a.root-servers.nil.
+dom1580. NS a.root-servers.nil.
+dom1581. NS a.root-servers.nil.
+dom1582. NS a.root-servers.nil.
+dom1583. NS a.root-servers.nil.
+dom1584. NS a.root-servers.nil.
+dom1585. NS a.root-servers.nil.
+dom1586. NS a.root-servers.nil.
+dom1587. NS a.root-servers.nil.
+dom1588. NS a.root-servers.nil.
+dom1589. NS a.root-servers.nil.
+dom1590. NS a.root-servers.nil.
+dom1591. NS a.root-servers.nil.
+dom1592. NS a.root-servers.nil.
+dom1593. NS a.root-servers.nil.
+dom1594. NS a.root-servers.nil.
+dom1595. NS a.root-servers.nil.
+dom1596. NS a.root-servers.nil.
+dom1597. NS a.root-servers.nil.
+dom1598. NS a.root-servers.nil.
+dom1599. NS a.root-servers.nil.
+dom1600. NS a.root-servers.nil.
+dom1601. NS a.root-servers.nil.
+dom1602. NS a.root-servers.nil.
+dom1603. NS a.root-servers.nil.
+dom1604. NS a.root-servers.nil.
+dom1605. NS a.root-servers.nil.
+dom1606. NS a.root-servers.nil.
+dom1607. NS a.root-servers.nil.
+dom1608. NS a.root-servers.nil.
+dom1609. NS a.root-servers.nil.
+dom1610. NS a.root-servers.nil.
+dom1611. NS a.root-servers.nil.
+dom1612. NS a.root-servers.nil.
+dom1613. NS a.root-servers.nil.
+dom1614. NS a.root-servers.nil.
+dom1615. NS a.root-servers.nil.
+dom1616. NS a.root-servers.nil.
+dom1617. NS a.root-servers.nil.
+dom1618. NS a.root-servers.nil.
+dom1619. NS a.root-servers.nil.
+dom1620. NS a.root-servers.nil.
+dom1621. NS a.root-servers.nil.
+dom1622. NS a.root-servers.nil.
+dom1623. NS a.root-servers.nil.
+dom1624. NS a.root-servers.nil.
+dom1625. NS a.root-servers.nil.
+dom1626. NS a.root-servers.nil.
+dom1627. NS a.root-servers.nil.
+dom1628. NS a.root-servers.nil.
+dom1629. NS a.root-servers.nil.
+dom1630. NS a.root-servers.nil.
+dom1631. NS a.root-servers.nil.
+dom1632. NS a.root-servers.nil.
+dom1633. NS a.root-servers.nil.
+dom1634. NS a.root-servers.nil.
+dom1635. NS a.root-servers.nil.
+dom1636. NS a.root-servers.nil.
+dom1637. NS a.root-servers.nil.
+dom1638. NS a.root-servers.nil.
+dom1639. NS a.root-servers.nil.
+dom1640. NS a.root-servers.nil.
+dom1641. NS a.root-servers.nil.
+dom1642. NS a.root-servers.nil.
+dom1643. NS a.root-servers.nil.
+dom1644. NS a.root-servers.nil.
+dom1645. NS a.root-servers.nil.
+dom1646. NS a.root-servers.nil.
+dom1647. NS a.root-servers.nil.
+dom1648. NS a.root-servers.nil.
+dom1649. NS a.root-servers.nil.
+dom1650. NS a.root-servers.nil.
+dom1651. NS a.root-servers.nil.
+dom1652. NS a.root-servers.nil.
+dom1653. NS a.root-servers.nil.
+dom1654. NS a.root-servers.nil.
+dom1655. NS a.root-servers.nil.
+dom1656. NS a.root-servers.nil.
+dom1657. NS a.root-servers.nil.
+dom1658. NS a.root-servers.nil.
+dom1659. NS a.root-servers.nil.
+dom1660. NS a.root-servers.nil.
+dom1661. NS a.root-servers.nil.
+dom1662. NS a.root-servers.nil.
+dom1663. NS a.root-servers.nil.
+dom1664. NS a.root-servers.nil.
+dom1665. NS a.root-servers.nil.
+dom1666. NS a.root-servers.nil.
+dom1667. NS a.root-servers.nil.
+dom1668. NS a.root-servers.nil.
+dom1669. NS a.root-servers.nil.
+dom1670. NS a.root-servers.nil.
+dom1671. NS a.root-servers.nil.
+dom1672. NS a.root-servers.nil.
+dom1673. NS a.root-servers.nil.
+dom1674. NS a.root-servers.nil.
+dom1675. NS a.root-servers.nil.
+dom1676. NS a.root-servers.nil.
+dom1677. NS a.root-servers.nil.
+dom1678. NS a.root-servers.nil.
+dom1679. NS a.root-servers.nil.
+dom1680. NS a.root-servers.nil.
+dom1681. NS a.root-servers.nil.
+dom1682. NS a.root-servers.nil.
+dom1683. NS a.root-servers.nil.
+dom1684. NS a.root-servers.nil.
+dom1685. NS a.root-servers.nil.
+dom1686. NS a.root-servers.nil.
+dom1687. NS a.root-servers.nil.
+dom1688. NS a.root-servers.nil.
+dom1689. NS a.root-servers.nil.
+dom1690. NS a.root-servers.nil.
+dom1691. NS a.root-servers.nil.
+dom1692. NS a.root-servers.nil.
+dom1693. NS a.root-servers.nil.
+dom1694. NS a.root-servers.nil.
+dom1695. NS a.root-servers.nil.
+dom1696. NS a.root-servers.nil.
+dom1697. NS a.root-servers.nil.
+dom1698. NS a.root-servers.nil.
+dom1699. NS a.root-servers.nil.
+dom1700. NS a.root-servers.nil.
+dom1701. NS a.root-servers.nil.
+dom1702. NS a.root-servers.nil.
+dom1703. NS a.root-servers.nil.
+dom1704. NS a.root-servers.nil.
+dom1705. NS a.root-servers.nil.
+dom1706. NS a.root-servers.nil.
+dom1707. NS a.root-servers.nil.
+dom1708. NS a.root-servers.nil.
+dom1709. NS a.root-servers.nil.
+dom1710. NS a.root-servers.nil.
+dom1711. NS a.root-servers.nil.
+dom1712. NS a.root-servers.nil.
+dom1713. NS a.root-servers.nil.
+dom1714. NS a.root-servers.nil.
+dom1715. NS a.root-servers.nil.
+dom1716. NS a.root-servers.nil.
+dom1717. NS a.root-servers.nil.
+dom1718. NS a.root-servers.nil.
+dom1719. NS a.root-servers.nil.
+dom1720. NS a.root-servers.nil.
+dom1721. NS a.root-servers.nil.
+dom1722. NS a.root-servers.nil.
+dom1723. NS a.root-servers.nil.
+dom1724. NS a.root-servers.nil.
+dom1725. NS a.root-servers.nil.
+dom1726. NS a.root-servers.nil.
+dom1727. NS a.root-servers.nil.
+dom1728. NS a.root-servers.nil.
+dom1729. NS a.root-servers.nil.
+dom1730. NS a.root-servers.nil.
+dom1731. NS a.root-servers.nil.
+dom1732. NS a.root-servers.nil.
+dom1733. NS a.root-servers.nil.
+dom1734. NS a.root-servers.nil.
+dom1735. NS a.root-servers.nil.
+dom1736. NS a.root-servers.nil.
+dom1737. NS a.root-servers.nil.
+dom1738. NS a.root-servers.nil.
+dom1739. NS a.root-servers.nil.
+dom1740. NS a.root-servers.nil.
+dom1741. NS a.root-servers.nil.
+dom1742. NS a.root-servers.nil.
+dom1743. NS a.root-servers.nil.
+dom1744. NS a.root-servers.nil.
+dom1745. NS a.root-servers.nil.
+dom1746. NS a.root-servers.nil.
+dom1747. NS a.root-servers.nil.
+dom1748. NS a.root-servers.nil.
+dom1749. NS a.root-servers.nil.
+dom1750. NS a.root-servers.nil.
+dom1751. NS a.root-servers.nil.
+dom1752. NS a.root-servers.nil.
+dom1753. NS a.root-servers.nil.
+dom1754. NS a.root-servers.nil.
+dom1755. NS a.root-servers.nil.
+dom1756. NS a.root-servers.nil.
+dom1757. NS a.root-servers.nil.
+dom1758. NS a.root-servers.nil.
+dom1759. NS a.root-servers.nil.
+dom1760. NS a.root-servers.nil.
+dom1761. NS a.root-servers.nil.
+dom1762. NS a.root-servers.nil.
+dom1763. NS a.root-servers.nil.
+dom1764. NS a.root-servers.nil.
+dom1765. NS a.root-servers.nil.
+dom1766. NS a.root-servers.nil.
+dom1767. NS a.root-servers.nil.
+dom1768. NS a.root-servers.nil.
+dom1769. NS a.root-servers.nil.
+dom1770. NS a.root-servers.nil.
+dom1771. NS a.root-servers.nil.
+dom1772. NS a.root-servers.nil.
+dom1773. NS a.root-servers.nil.
+dom1774. NS a.root-servers.nil.
+dom1775. NS a.root-servers.nil.
+dom1776. NS a.root-servers.nil.
+dom1777. NS a.root-servers.nil.
+dom1778. NS a.root-servers.nil.
+dom1779. NS a.root-servers.nil.
+dom1780. NS a.root-servers.nil.
+dom1781. NS a.root-servers.nil.
+dom1782. NS a.root-servers.nil.
+dom1783. NS a.root-servers.nil.
+dom1784. NS a.root-servers.nil.
+dom1785. NS a.root-servers.nil.
+dom1786. NS a.root-servers.nil.
+dom1787. NS a.root-servers.nil.
+dom1788. NS a.root-servers.nil.
+dom1789. NS a.root-servers.nil.
+dom1790. NS a.root-servers.nil.
+dom1791. NS a.root-servers.nil.
+dom1792. NS a.root-servers.nil.
+dom1793. NS a.root-servers.nil.
+dom1794. NS a.root-servers.nil.
+dom1795. NS a.root-servers.nil.
+dom1796. NS a.root-servers.nil.
+dom1797. NS a.root-servers.nil.
+dom1798. NS a.root-servers.nil.
+dom1799. NS a.root-servers.nil.
+dom1800. NS a.root-servers.nil.
+dom1801. NS a.root-servers.nil.
+dom1802. NS a.root-servers.nil.
+dom1803. NS a.root-servers.nil.
+dom1804. NS a.root-servers.nil.
+dom1805. NS a.root-servers.nil.
+dom1806. NS a.root-servers.nil.
+dom1807. NS a.root-servers.nil.
+dom1808. NS a.root-servers.nil.
+dom1809. NS a.root-servers.nil.
+dom1810. NS a.root-servers.nil.
+dom1811. NS a.root-servers.nil.
+dom1812. NS a.root-servers.nil.
+dom1813. NS a.root-servers.nil.
+dom1814. NS a.root-servers.nil.
+dom1815. NS a.root-servers.nil.
+dom1816. NS a.root-servers.nil.
+dom1817. NS a.root-servers.nil.
+dom1818. NS a.root-servers.nil.
+dom1819. NS a.root-servers.nil.
+dom1820. NS a.root-servers.nil.
+dom1821. NS a.root-servers.nil.
+dom1822. NS a.root-servers.nil.
+dom1823. NS a.root-servers.nil.
+dom1824. NS a.root-servers.nil.
+dom1825. NS a.root-servers.nil.
+dom1826. NS a.root-servers.nil.
+dom1827. NS a.root-servers.nil.
+dom1828. NS a.root-servers.nil.
+dom1829. NS a.root-servers.nil.
+dom1830. NS a.root-servers.nil.
+dom1831. NS a.root-servers.nil.
+dom1832. NS a.root-servers.nil.
+dom1833. NS a.root-servers.nil.
+dom1834. NS a.root-servers.nil.
+dom1835. NS a.root-servers.nil.
+dom1836. NS a.root-servers.nil.
+dom1837. NS a.root-servers.nil.
+dom1838. NS a.root-servers.nil.
+dom1839. NS a.root-servers.nil.
+dom1840. NS a.root-servers.nil.
+dom1841. NS a.root-servers.nil.
+dom1842. NS a.root-servers.nil.
+dom1843. NS a.root-servers.nil.
+dom1844. NS a.root-servers.nil.
+dom1845. NS a.root-servers.nil.
+dom1846. NS a.root-servers.nil.
+dom1847. NS a.root-servers.nil.
+dom1848. NS a.root-servers.nil.
+dom1849. NS a.root-servers.nil.
+dom1850. NS a.root-servers.nil.
+dom1851. NS a.root-servers.nil.
+dom1852. NS a.root-servers.nil.
+dom1853. NS a.root-servers.nil.
+dom1854. NS a.root-servers.nil.
+dom1855. NS a.root-servers.nil.
+dom1856. NS a.root-servers.nil.
+dom1857. NS a.root-servers.nil.
+dom1858. NS a.root-servers.nil.
+dom1859. NS a.root-servers.nil.
+dom1860. NS a.root-servers.nil.
+dom1861. NS a.root-servers.nil.
+dom1862. NS a.root-servers.nil.
+dom1863. NS a.root-servers.nil.
+dom1864. NS a.root-servers.nil.
+dom1865. NS a.root-servers.nil.
+dom1866. NS a.root-servers.nil.
+dom1867. NS a.root-servers.nil.
+dom1868. NS a.root-servers.nil.
+dom1869. NS a.root-servers.nil.
+dom1870. NS a.root-servers.nil.
+dom1871. NS a.root-servers.nil.
+dom1872. NS a.root-servers.nil.
+dom1873. NS a.root-servers.nil.
+dom1874. NS a.root-servers.nil.
+dom1875. NS a.root-servers.nil.
+dom1876. NS a.root-servers.nil.
+dom1877. NS a.root-servers.nil.
+dom1878. NS a.root-servers.nil.
+dom1879. NS a.root-servers.nil.
+dom1880. NS a.root-servers.nil.
+dom1881. NS a.root-servers.nil.
+dom1882. NS a.root-servers.nil.
+dom1883. NS a.root-servers.nil.
+dom1884. NS a.root-servers.nil.
+dom1885. NS a.root-servers.nil.
+dom1886. NS a.root-servers.nil.
+dom1887. NS a.root-servers.nil.
+dom1888. NS a.root-servers.nil.
+dom1889. NS a.root-servers.nil.
+dom1890. NS a.root-servers.nil.
+dom1891. NS a.root-servers.nil.
+dom1892. NS a.root-servers.nil.
+dom1893. NS a.root-servers.nil.
+dom1894. NS a.root-servers.nil.
+dom1895. NS a.root-servers.nil.
+dom1896. NS a.root-servers.nil.
+dom1897. NS a.root-servers.nil.
+dom1898. NS a.root-servers.nil.
+dom1899. NS a.root-servers.nil.
+dom1900. NS a.root-servers.nil.
+dom1901. NS a.root-servers.nil.
+dom1902. NS a.root-servers.nil.
+dom1903. NS a.root-servers.nil.
+dom1904. NS a.root-servers.nil.
+dom1905. NS a.root-servers.nil.
+dom1906. NS a.root-servers.nil.
+dom1907. NS a.root-servers.nil.
+dom1908. NS a.root-servers.nil.
+dom1909. NS a.root-servers.nil.
+dom1910. NS a.root-servers.nil.
+dom1911. NS a.root-servers.nil.
+dom1912. NS a.root-servers.nil.
+dom1913. NS a.root-servers.nil.
+dom1914. NS a.root-servers.nil.
+dom1915. NS a.root-servers.nil.
+dom1916. NS a.root-servers.nil.
+dom1917. NS a.root-servers.nil.
+dom1918. NS a.root-servers.nil.
+dom1919. NS a.root-servers.nil.
+dom1920. NS a.root-servers.nil.
+dom1921. NS a.root-servers.nil.
+dom1922. NS a.root-servers.nil.
+dom1923. NS a.root-servers.nil.
+dom1924. NS a.root-servers.nil.
+dom1925. NS a.root-servers.nil.
+dom1926. NS a.root-servers.nil.
+dom1927. NS a.root-servers.nil.
+dom1928. NS a.root-servers.nil.
+dom1929. NS a.root-servers.nil.
+dom1930. NS a.root-servers.nil.
+dom1931. NS a.root-servers.nil.
+dom1932. NS a.root-servers.nil.
+dom1933. NS a.root-servers.nil.
+dom1934. NS a.root-servers.nil.
+dom1935. NS a.root-servers.nil.
+dom1936. NS a.root-servers.nil.
+dom1937. NS a.root-servers.nil.
+dom1938. NS a.root-servers.nil.
+dom1939. NS a.root-servers.nil.
+dom1940. NS a.root-servers.nil.
+dom1941. NS a.root-servers.nil.
+dom1942. NS a.root-servers.nil.
+dom1943. NS a.root-servers.nil.
+dom1944. NS a.root-servers.nil.
+dom1945. NS a.root-servers.nil.
+dom1946. NS a.root-servers.nil.
+dom1947. NS a.root-servers.nil.
+dom1948. NS a.root-servers.nil.
+dom1949. NS a.root-servers.nil.
+dom1950. NS a.root-servers.nil.
+dom1951. NS a.root-servers.nil.
+dom1952. NS a.root-servers.nil.
+dom1953. NS a.root-servers.nil.
+dom1954. NS a.root-servers.nil.
+dom1955. NS a.root-servers.nil.
+dom1956. NS a.root-servers.nil.
+dom1957. NS a.root-servers.nil.
+dom1958. NS a.root-servers.nil.
+dom1959. NS a.root-servers.nil.
+dom1960. NS a.root-servers.nil.
+dom1961. NS a.root-servers.nil.
+dom1962. NS a.root-servers.nil.
+dom1963. NS a.root-servers.nil.
+dom1964. NS a.root-servers.nil.
+dom1965. NS a.root-servers.nil.
+dom1966. NS a.root-servers.nil.
+dom1967. NS a.root-servers.nil.
+dom1968. NS a.root-servers.nil.
+dom1969. NS a.root-servers.nil.
+dom1970. NS a.root-servers.nil.
+dom1971. NS a.root-servers.nil.
+dom1972. NS a.root-servers.nil.
+dom1973. NS a.root-servers.nil.
+dom1974. NS a.root-servers.nil.
+dom1975. NS a.root-servers.nil.
+dom1976. NS a.root-servers.nil.
+dom1977. NS a.root-servers.nil.
+dom1978. NS a.root-servers.nil.
+dom1979. NS a.root-servers.nil.
+dom1980. NS a.root-servers.nil.
+dom1981. NS a.root-servers.nil.
+dom1982. NS a.root-servers.nil.
+dom1983. NS a.root-servers.nil.
+dom1984. NS a.root-servers.nil.
+dom1985. NS a.root-servers.nil.
+dom1986. NS a.root-servers.nil.
+dom1987. NS a.root-servers.nil.
+dom1988. NS a.root-servers.nil.
+dom1989. NS a.root-servers.nil.
+dom1990. NS a.root-servers.nil.
+dom1991. NS a.root-servers.nil.
+dom1992. NS a.root-servers.nil.
+dom1993. NS a.root-servers.nil.
+dom1994. NS a.root-servers.nil.
+dom1995. NS a.root-servers.nil.
+dom1996. NS a.root-servers.nil.
+dom1997. NS a.root-servers.nil.
+dom1998. NS a.root-servers.nil.
+dom1999. NS a.root-servers.nil.
+dom2000. NS a.root-servers.nil.
+dom2001. NS a.root-servers.nil.
+dom2002. NS a.root-servers.nil.
+dom2003. NS a.root-servers.nil.
+dom2004. NS a.root-servers.nil.
+dom2005. NS a.root-servers.nil.
+dom2006. NS a.root-servers.nil.
+dom2007. NS a.root-servers.nil.
+dom2008. NS a.root-servers.nil.
+dom2009. NS a.root-servers.nil.
+dom2010. NS a.root-servers.nil.
+dom2011. NS a.root-servers.nil.
+dom2012. NS a.root-servers.nil.
+dom2013. NS a.root-servers.nil.
+dom2014. NS a.root-servers.nil.
+dom2015. NS a.root-servers.nil.
+dom2016. NS a.root-servers.nil.
+dom2017. NS a.root-servers.nil.
+dom2018. NS a.root-servers.nil.
+dom2019. NS a.root-servers.nil.
+dom2020. NS a.root-servers.nil.
+dom2021. NS a.root-servers.nil.
+dom2022. NS a.root-servers.nil.
+dom2023. NS a.root-servers.nil.
+dom2024. NS a.root-servers.nil.
+dom2025. NS a.root-servers.nil.
+dom2026. NS a.root-servers.nil.
+dom2027. NS a.root-servers.nil.
+dom2028. NS a.root-servers.nil.
+dom2029. NS a.root-servers.nil.
+dom2030. NS a.root-servers.nil.
+dom2031. NS a.root-servers.nil.
+dom2032. NS a.root-servers.nil.
+dom2033. NS a.root-servers.nil.
+dom2034. NS a.root-servers.nil.
+dom2035. NS a.root-servers.nil.
+dom2036. NS a.root-servers.nil.
+dom2037. NS a.root-servers.nil.
+dom2038. NS a.root-servers.nil.
+dom2039. NS a.root-servers.nil.
+dom2040. NS a.root-servers.nil.
+dom2041. NS a.root-servers.nil.
+dom2042. NS a.root-servers.nil.
+dom2043. NS a.root-servers.nil.
+dom2044. NS a.root-servers.nil.
+dom2045. NS a.root-servers.nil.
+dom2046. NS a.root-servers.nil.
+dom2047. NS a.root-servers.nil.
+dom2048. NS a.root-servers.nil.
+dom2049. NS a.root-servers.nil.
+dom2050. NS a.root-servers.nil.
+dom2051. NS a.root-servers.nil.
+dom2052. NS a.root-servers.nil.
+dom2053. NS a.root-servers.nil.
+dom2054. NS a.root-servers.nil.
+dom2055. NS a.root-servers.nil.
+dom2056. NS a.root-servers.nil.
+dom2057. NS a.root-servers.nil.
+dom2058. NS a.root-servers.nil.
+dom2059. NS a.root-servers.nil.
+dom2060. NS a.root-servers.nil.
+dom2061. NS a.root-servers.nil.
+dom2062. NS a.root-servers.nil.
+dom2063. NS a.root-servers.nil.
+dom2064. NS a.root-servers.nil.
+dom2065. NS a.root-servers.nil.
+dom2066. NS a.root-servers.nil.
+dom2067. NS a.root-servers.nil.
+dom2068. NS a.root-servers.nil.
+dom2069. NS a.root-servers.nil.
+dom2070. NS a.root-servers.nil.
+dom2071. NS a.root-servers.nil.
+dom2072. NS a.root-servers.nil.
+dom2073. NS a.root-servers.nil.
+dom2074. NS a.root-servers.nil.
+dom2075. NS a.root-servers.nil.
+dom2076. NS a.root-servers.nil.
+dom2077. NS a.root-servers.nil.
+dom2078. NS a.root-servers.nil.
+dom2079. NS a.root-servers.nil.
+dom2080. NS a.root-servers.nil.
+dom2081. NS a.root-servers.nil.
+dom2082. NS a.root-servers.nil.
+dom2083. NS a.root-servers.nil.
+dom2084. NS a.root-servers.nil.
+dom2085. NS a.root-servers.nil.
+dom2086. NS a.root-servers.nil.
+dom2087. NS a.root-servers.nil.
+dom2088. NS a.root-servers.nil.
+dom2089. NS a.root-servers.nil.
+dom2090. NS a.root-servers.nil.
+dom2091. NS a.root-servers.nil.
+dom2092. NS a.root-servers.nil.
+dom2093. NS a.root-servers.nil.
+dom2094. NS a.root-servers.nil.
+dom2095. NS a.root-servers.nil.
+dom2096. NS a.root-servers.nil.
+dom2097. NS a.root-servers.nil.
+dom2098. NS a.root-servers.nil.
+dom2099. NS a.root-servers.nil.
+dom2100. NS a.root-servers.nil.
+dom2101. NS a.root-servers.nil.
+dom2102. NS a.root-servers.nil.
+dom2103. NS a.root-servers.nil.
+dom2104. NS a.root-servers.nil.
+dom2105. NS a.root-servers.nil.
+dom2106. NS a.root-servers.nil.
+dom2107. NS a.root-servers.nil.
+dom2108. NS a.root-servers.nil.
+dom2109. NS a.root-servers.nil.
+dom2110. NS a.root-servers.nil.
+dom2111. NS a.root-servers.nil.
+dom2112. NS a.root-servers.nil.
+dom2113. NS a.root-servers.nil.
+dom2114. NS a.root-servers.nil.
+dom2115. NS a.root-servers.nil.
+dom2116. NS a.root-servers.nil.
+dom2117. NS a.root-servers.nil.
+dom2118. NS a.root-servers.nil.
+dom2119. NS a.root-servers.nil.
+dom2120. NS a.root-servers.nil.
+dom2121. NS a.root-servers.nil.
+dom2122. NS a.root-servers.nil.
+dom2123. NS a.root-servers.nil.
+dom2124. NS a.root-servers.nil.
+dom2125. NS a.root-servers.nil.
+dom2126. NS a.root-servers.nil.
+dom2127. NS a.root-servers.nil.
+dom2128. NS a.root-servers.nil.
+dom2129. NS a.root-servers.nil.
+dom2130. NS a.root-servers.nil.
+dom2131. NS a.root-servers.nil.
+dom2132. NS a.root-servers.nil.
+dom2133. NS a.root-servers.nil.
+dom2134. NS a.root-servers.nil.
+dom2135. NS a.root-servers.nil.
+dom2136. NS a.root-servers.nil.
+dom2137. NS a.root-servers.nil.
+dom2138. NS a.root-servers.nil.
+dom2139. NS a.root-servers.nil.
+dom2140. NS a.root-servers.nil.
+dom2141. NS a.root-servers.nil.
+dom2142. NS a.root-servers.nil.
+dom2143. NS a.root-servers.nil.
+dom2144. NS a.root-servers.nil.
+dom2145. NS a.root-servers.nil.
+dom2146. NS a.root-servers.nil.
+dom2147. NS a.root-servers.nil.
+dom2148. NS a.root-servers.nil.
+dom2149. NS a.root-servers.nil.
+dom2150. NS a.root-servers.nil.
+dom2151. NS a.root-servers.nil.
+dom2152. NS a.root-servers.nil.
+dom2153. NS a.root-servers.nil.
+dom2154. NS a.root-servers.nil.
+dom2155. NS a.root-servers.nil.
+dom2156. NS a.root-servers.nil.
+dom2157. NS a.root-servers.nil.
+dom2158. NS a.root-servers.nil.
+dom2159. NS a.root-servers.nil.
+dom2160. NS a.root-servers.nil.
+dom2161. NS a.root-servers.nil.
+dom2162. NS a.root-servers.nil.
+dom2163. NS a.root-servers.nil.
+dom2164. NS a.root-servers.nil.
+dom2165. NS a.root-servers.nil.
+dom2166. NS a.root-servers.nil.
+dom2167. NS a.root-servers.nil.
+dom2168. NS a.root-servers.nil.
+dom2169. NS a.root-servers.nil.
+dom2170. NS a.root-servers.nil.
+dom2171. NS a.root-servers.nil.
+dom2172. NS a.root-servers.nil.
+dom2173. NS a.root-servers.nil.
+dom2174. NS a.root-servers.nil.
+dom2175. NS a.root-servers.nil.
+dom2176. NS a.root-servers.nil.
+dom2177. NS a.root-servers.nil.
+dom2178. NS a.root-servers.nil.
+dom2179. NS a.root-servers.nil.
+dom2180. NS a.root-servers.nil.
+dom2181. NS a.root-servers.nil.
+dom2182. NS a.root-servers.nil.
+dom2183. NS a.root-servers.nil.
+dom2184. NS a.root-servers.nil.
+dom2185. NS a.root-servers.nil.
+dom2186. NS a.root-servers.nil.
+dom2187. NS a.root-servers.nil.
+dom2188. NS a.root-servers.nil.
+dom2189. NS a.root-servers.nil.
+dom2190. NS a.root-servers.nil.
+dom2191. NS a.root-servers.nil.
+dom2192. NS a.root-servers.nil.
+dom2193. NS a.root-servers.nil.
+dom2194. NS a.root-servers.nil.
+dom2195. NS a.root-servers.nil.
+dom2196. NS a.root-servers.nil.
+dom2197. NS a.root-servers.nil.
+dom2198. NS a.root-servers.nil.
+dom2199. NS a.root-servers.nil.
+dom2200. NS a.root-servers.nil.
+dom2201. NS a.root-servers.nil.
+dom2202. NS a.root-servers.nil.
+dom2203. NS a.root-servers.nil.
+dom2204. NS a.root-servers.nil.
+dom2205. NS a.root-servers.nil.
+dom2206. NS a.root-servers.nil.
+dom2207. NS a.root-servers.nil.
+dom2208. NS a.root-servers.nil.
+dom2209. NS a.root-servers.nil.
+dom2210. NS a.root-servers.nil.
+dom2211. NS a.root-servers.nil.
+dom2212. NS a.root-servers.nil.
+dom2213. NS a.root-servers.nil.
+dom2214. NS a.root-servers.nil.
+dom2215. NS a.root-servers.nil.
+dom2216. NS a.root-servers.nil.
+dom2217. NS a.root-servers.nil.
+dom2218. NS a.root-servers.nil.
+dom2219. NS a.root-servers.nil.
+dom2220. NS a.root-servers.nil.
+dom2221. NS a.root-servers.nil.
+dom2222. NS a.root-servers.nil.
+dom2223. NS a.root-servers.nil.
+dom2224. NS a.root-servers.nil.
+dom2225. NS a.root-servers.nil.
+dom2226. NS a.root-servers.nil.
+dom2227. NS a.root-servers.nil.
+dom2228. NS a.root-servers.nil.
+dom2229. NS a.root-servers.nil.
+dom2230. NS a.root-servers.nil.
+dom2231. NS a.root-servers.nil.
+dom2232. NS a.root-servers.nil.
+dom2233. NS a.root-servers.nil.
+dom2234. NS a.root-servers.nil.
+dom2235. NS a.root-servers.nil.
+dom2236. NS a.root-servers.nil.
+dom2237. NS a.root-servers.nil.
+dom2238. NS a.root-servers.nil.
+dom2239. NS a.root-servers.nil.
+dom2240. NS a.root-servers.nil.
+dom2241. NS a.root-servers.nil.
+dom2242. NS a.root-servers.nil.
+dom2243. NS a.root-servers.nil.
+dom2244. NS a.root-servers.nil.
+dom2245. NS a.root-servers.nil.
+dom2246. NS a.root-servers.nil.
+dom2247. NS a.root-servers.nil.
+dom2248. NS a.root-servers.nil.
+dom2249. NS a.root-servers.nil.
+dom2250. NS a.root-servers.nil.
+dom2251. NS a.root-servers.nil.
+dom2252. NS a.root-servers.nil.
+dom2253. NS a.root-servers.nil.
+dom2254. NS a.root-servers.nil.
+dom2255. NS a.root-servers.nil.
+dom2256. NS a.root-servers.nil.
+dom2257. NS a.root-servers.nil.
+dom2258. NS a.root-servers.nil.
+dom2259. NS a.root-servers.nil.
+dom2260. NS a.root-servers.nil.
+dom2261. NS a.root-servers.nil.
+dom2262. NS a.root-servers.nil.
+dom2263. NS a.root-servers.nil.
+dom2264. NS a.root-servers.nil.
+dom2265. NS a.root-servers.nil.
+dom2266. NS a.root-servers.nil.
+dom2267. NS a.root-servers.nil.
+dom2268. NS a.root-servers.nil.
+dom2269. NS a.root-servers.nil.
+dom2270. NS a.root-servers.nil.
+dom2271. NS a.root-servers.nil.
+dom2272. NS a.root-servers.nil.
+dom2273. NS a.root-servers.nil.
+dom2274. NS a.root-servers.nil.
+dom2275. NS a.root-servers.nil.
+dom2276. NS a.root-servers.nil.
+dom2277. NS a.root-servers.nil.
+dom2278. NS a.root-servers.nil.
+dom2279. NS a.root-servers.nil.
+dom2280. NS a.root-servers.nil.
+dom2281. NS a.root-servers.nil.
+dom2282. NS a.root-servers.nil.
+dom2283. NS a.root-servers.nil.
+dom2284. NS a.root-servers.nil.
+dom2285. NS a.root-servers.nil.
+dom2286. NS a.root-servers.nil.
+dom2287. NS a.root-servers.nil.
+dom2288. NS a.root-servers.nil.
+dom2289. NS a.root-servers.nil.
+dom2290. NS a.root-servers.nil.
+dom2291. NS a.root-servers.nil.
+dom2292. NS a.root-servers.nil.
+dom2293. NS a.root-servers.nil.
+dom2294. NS a.root-servers.nil.
+dom2295. NS a.root-servers.nil.
+dom2296. NS a.root-servers.nil.
+dom2297. NS a.root-servers.nil.
+dom2298. NS a.root-servers.nil.
+dom2299. NS a.root-servers.nil.
+dom2300. NS a.root-servers.nil.
+dom2301. NS a.root-servers.nil.
+dom2302. NS a.root-servers.nil.
+dom2303. NS a.root-servers.nil.
+dom2304. NS a.root-servers.nil.
+dom2305. NS a.root-servers.nil.
+dom2306. NS a.root-servers.nil.
+dom2307. NS a.root-servers.nil.
+dom2308. NS a.root-servers.nil.
+dom2309. NS a.root-servers.nil.
+dom2310. NS a.root-servers.nil.
+dom2311. NS a.root-servers.nil.
+dom2312. NS a.root-servers.nil.
+dom2313. NS a.root-servers.nil.
+dom2314. NS a.root-servers.nil.
+dom2315. NS a.root-servers.nil.
+dom2316. NS a.root-servers.nil.
+dom2317. NS a.root-servers.nil.
+dom2318. NS a.root-servers.nil.
+dom2319. NS a.root-servers.nil.
+dom2320. NS a.root-servers.nil.
+dom2321. NS a.root-servers.nil.
+dom2322. NS a.root-servers.nil.
+dom2323. NS a.root-servers.nil.
+dom2324. NS a.root-servers.nil.
+dom2325. NS a.root-servers.nil.
+dom2326. NS a.root-servers.nil.
+dom2327. NS a.root-servers.nil.
+dom2328. NS a.root-servers.nil.
+dom2329. NS a.root-servers.nil.
+dom2330. NS a.root-servers.nil.
+dom2331. NS a.root-servers.nil.
+dom2332. NS a.root-servers.nil.
+dom2333. NS a.root-servers.nil.
+dom2334. NS a.root-servers.nil.
+dom2335. NS a.root-servers.nil.
+dom2336. NS a.root-servers.nil.
+dom2337. NS a.root-servers.nil.
+dom2338. NS a.root-servers.nil.
+dom2339. NS a.root-servers.nil.
+dom2340. NS a.root-servers.nil.
+dom2341. NS a.root-servers.nil.
+dom2342. NS a.root-servers.nil.
+dom2343. NS a.root-servers.nil.
+dom2344. NS a.root-servers.nil.
+dom2345. NS a.root-servers.nil.
+dom2346. NS a.root-servers.nil.
+dom2347. NS a.root-servers.nil.
+dom2348. NS a.root-servers.nil.
+dom2349. NS a.root-servers.nil.
+dom2350. NS a.root-servers.nil.
+dom2351. NS a.root-servers.nil.
+dom2352. NS a.root-servers.nil.
+dom2353. NS a.root-servers.nil.
+dom2354. NS a.root-servers.nil.
+dom2355. NS a.root-servers.nil.
+dom2356. NS a.root-servers.nil.
+dom2357. NS a.root-servers.nil.
+dom2358. NS a.root-servers.nil.
+dom2359. NS a.root-servers.nil.
+dom2360. NS a.root-servers.nil.
+dom2361. NS a.root-servers.nil.
+dom2362. NS a.root-servers.nil.
+dom2363. NS a.root-servers.nil.
+dom2364. NS a.root-servers.nil.
+dom2365. NS a.root-servers.nil.
+dom2366. NS a.root-servers.nil.
+dom2367. NS a.root-servers.nil.
+dom2368. NS a.root-servers.nil.
+dom2369. NS a.root-servers.nil.
+dom2370. NS a.root-servers.nil.
+dom2371. NS a.root-servers.nil.
+dom2372. NS a.root-servers.nil.
+dom2373. NS a.root-servers.nil.
+dom2374. NS a.root-servers.nil.
+dom2375. NS a.root-servers.nil.
+dom2376. NS a.root-servers.nil.
+dom2377. NS a.root-servers.nil.
+dom2378. NS a.root-servers.nil.
+dom2379. NS a.root-servers.nil.
+dom2380. NS a.root-servers.nil.
+dom2381. NS a.root-servers.nil.
+dom2382. NS a.root-servers.nil.
+dom2383. NS a.root-servers.nil.
+dom2384. NS a.root-servers.nil.
+dom2385. NS a.root-servers.nil.
+dom2386. NS a.root-servers.nil.
+dom2387. NS a.root-servers.nil.
+dom2388. NS a.root-servers.nil.
+dom2389. NS a.root-servers.nil.
+dom2390. NS a.root-servers.nil.
+dom2391. NS a.root-servers.nil.
+dom2392. NS a.root-servers.nil.
+dom2393. NS a.root-servers.nil.
+dom2394. NS a.root-servers.nil.
+dom2395. NS a.root-servers.nil.
+dom2396. NS a.root-servers.nil.
+dom2397. NS a.root-servers.nil.
+dom2398. NS a.root-servers.nil.
+dom2399. NS a.root-servers.nil.
+dom2400. NS a.root-servers.nil.
+dom2401. NS a.root-servers.nil.
+dom2402. NS a.root-servers.nil.
+dom2403. NS a.root-servers.nil.
+dom2404. NS a.root-servers.nil.
+dom2405. NS a.root-servers.nil.
+dom2406. NS a.root-servers.nil.
+dom2407. NS a.root-servers.nil.
+dom2408. NS a.root-servers.nil.
+dom2409. NS a.root-servers.nil.
+dom2410. NS a.root-servers.nil.
+dom2411. NS a.root-servers.nil.
+dom2412. NS a.root-servers.nil.
+dom2413. NS a.root-servers.nil.
+dom2414. NS a.root-servers.nil.
+dom2415. NS a.root-servers.nil.
+dom2416. NS a.root-servers.nil.
+dom2417. NS a.root-servers.nil.
+dom2418. NS a.root-servers.nil.
+dom2419. NS a.root-servers.nil.
+dom2420. NS a.root-servers.nil.
+dom2421. NS a.root-servers.nil.
+dom2422. NS a.root-servers.nil.
+dom2423. NS a.root-servers.nil.
+dom2424. NS a.root-servers.nil.
+dom2425. NS a.root-servers.nil.
+dom2426. NS a.root-servers.nil.
+dom2427. NS a.root-servers.nil.
+dom2428. NS a.root-servers.nil.
+dom2429. NS a.root-servers.nil.
+dom2430. NS a.root-servers.nil.
+dom2431. NS a.root-servers.nil.
+dom2432. NS a.root-servers.nil.
+dom2433. NS a.root-servers.nil.
+dom2434. NS a.root-servers.nil.
+dom2435. NS a.root-servers.nil.
+dom2436. NS a.root-servers.nil.
+dom2437. NS a.root-servers.nil.
+dom2438. NS a.root-servers.nil.
+dom2439. NS a.root-servers.nil.
+dom2440. NS a.root-servers.nil.
+dom2441. NS a.root-servers.nil.
+dom2442. NS a.root-servers.nil.
+dom2443. NS a.root-servers.nil.
+dom2444. NS a.root-servers.nil.
+dom2445. NS a.root-servers.nil.
+dom2446. NS a.root-servers.nil.
+dom2447. NS a.root-servers.nil.
+dom2448. NS a.root-servers.nil.
+dom2449. NS a.root-servers.nil.
+dom2450. NS a.root-servers.nil.
+dom2451. NS a.root-servers.nil.
+dom2452. NS a.root-servers.nil.
+dom2453. NS a.root-servers.nil.
+dom2454. NS a.root-servers.nil.
+dom2455. NS a.root-servers.nil.
+dom2456. NS a.root-servers.nil.
+dom2457. NS a.root-servers.nil.
+dom2458. NS a.root-servers.nil.
+dom2459. NS a.root-servers.nil.
+dom2460. NS a.root-servers.nil.
+dom2461. NS a.root-servers.nil.
+dom2462. NS a.root-servers.nil.
+dom2463. NS a.root-servers.nil.
+dom2464. NS a.root-servers.nil.
+dom2465. NS a.root-servers.nil.
+dom2466. NS a.root-servers.nil.
+dom2467. NS a.root-servers.nil.
+dom2468. NS a.root-servers.nil.
+dom2469. NS a.root-servers.nil.
+dom2470. NS a.root-servers.nil.
+dom2471. NS a.root-servers.nil.
+dom2472. NS a.root-servers.nil.
+dom2473. NS a.root-servers.nil.
+dom2474. NS a.root-servers.nil.
+dom2475. NS a.root-servers.nil.
+dom2476. NS a.root-servers.nil.
+dom2477. NS a.root-servers.nil.
+dom2478. NS a.root-servers.nil.
+dom2479. NS a.root-servers.nil.
+dom2480. NS a.root-servers.nil.
+dom2481. NS a.root-servers.nil.
+dom2482. NS a.root-servers.nil.
+dom2483. NS a.root-servers.nil.
+dom2484. NS a.root-servers.nil.
+dom2485. NS a.root-servers.nil.
+dom2486. NS a.root-servers.nil.
+dom2487. NS a.root-servers.nil.
+dom2488. NS a.root-servers.nil.
+dom2489. NS a.root-servers.nil.
+dom2490. NS a.root-servers.nil.
+dom2491. NS a.root-servers.nil.
+dom2492. NS a.root-servers.nil.
+dom2493. NS a.root-servers.nil.
+dom2494. NS a.root-servers.nil.
+dom2495. NS a.root-servers.nil.
+dom2496. NS a.root-servers.nil.
+dom2497. NS a.root-servers.nil.
+dom2498. NS a.root-servers.nil.
+dom2499. NS a.root-servers.nil.
+dom2500. NS a.root-servers.nil.
+dom2501. NS a.root-servers.nil.
+dom2502. NS a.root-servers.nil.
+dom2503. NS a.root-servers.nil.
+dom2504. NS a.root-servers.nil.
+dom2505. NS a.root-servers.nil.
+dom2506. NS a.root-servers.nil.
+dom2507. NS a.root-servers.nil.
+dom2508. NS a.root-servers.nil.
+dom2509. NS a.root-servers.nil.
+dom2510. NS a.root-servers.nil.
+dom2511. NS a.root-servers.nil.
+dom2512. NS a.root-servers.nil.
+dom2513. NS a.root-servers.nil.
+dom2514. NS a.root-servers.nil.
+dom2515. NS a.root-servers.nil.
+dom2516. NS a.root-servers.nil.
+dom2517. NS a.root-servers.nil.
+dom2518. NS a.root-servers.nil.
+dom2519. NS a.root-servers.nil.
+dom2520. NS a.root-servers.nil.
+dom2521. NS a.root-servers.nil.
+dom2522. NS a.root-servers.nil.
+dom2523. NS a.root-servers.nil.
+dom2524. NS a.root-servers.nil.
+dom2525. NS a.root-servers.nil.
+dom2526. NS a.root-servers.nil.
+dom2527. NS a.root-servers.nil.
+dom2528. NS a.root-servers.nil.
+dom2529. NS a.root-servers.nil.
+dom2530. NS a.root-servers.nil.
+dom2531. NS a.root-servers.nil.
+dom2532. NS a.root-servers.nil.
+dom2533. NS a.root-servers.nil.
+dom2534. NS a.root-servers.nil.
+dom2535. NS a.root-servers.nil.
+dom2536. NS a.root-servers.nil.
+dom2537. NS a.root-servers.nil.
+dom2538. NS a.root-servers.nil.
+dom2539. NS a.root-servers.nil.
+dom2540. NS a.root-servers.nil.
+dom2541. NS a.root-servers.nil.
+dom2542. NS a.root-servers.nil.
+dom2543. NS a.root-servers.nil.
+dom2544. NS a.root-servers.nil.
+dom2545. NS a.root-servers.nil.
+dom2546. NS a.root-servers.nil.
+dom2547. NS a.root-servers.nil.
+dom2548. NS a.root-servers.nil.
+dom2549. NS a.root-servers.nil.
+dom2550. NS a.root-servers.nil.
+dom2551. NS a.root-servers.nil.
+dom2552. NS a.root-servers.nil.
+dom2553. NS a.root-servers.nil.
+dom2554. NS a.root-servers.nil.
+dom2555. NS a.root-servers.nil.
+dom2556. NS a.root-servers.nil.
+dom2557. NS a.root-servers.nil.
+dom2558. NS a.root-servers.nil.
+dom2559. NS a.root-servers.nil.
+dom2560. NS a.root-servers.nil.
+dom2561. NS a.root-servers.nil.
+dom2562. NS a.root-servers.nil.
+dom2563. NS a.root-servers.nil.
+dom2564. NS a.root-servers.nil.
+dom2565. NS a.root-servers.nil.
+dom2566. NS a.root-servers.nil.
+dom2567. NS a.root-servers.nil.
+dom2568. NS a.root-servers.nil.
+dom2569. NS a.root-servers.nil.
+dom2570. NS a.root-servers.nil.
+dom2571. NS a.root-servers.nil.
+dom2572. NS a.root-servers.nil.
+dom2573. NS a.root-servers.nil.
+dom2574. NS a.root-servers.nil.
+dom2575. NS a.root-servers.nil.
+dom2576. NS a.root-servers.nil.
+dom2577. NS a.root-servers.nil.
+dom2578. NS a.root-servers.nil.
+dom2579. NS a.root-servers.nil.
+dom2580. NS a.root-servers.nil.
+dom2581. NS a.root-servers.nil.
+dom2582. NS a.root-servers.nil.
+dom2583. NS a.root-servers.nil.
+dom2584. NS a.root-servers.nil.
+dom2585. NS a.root-servers.nil.
+dom2586. NS a.root-servers.nil.
+dom2587. NS a.root-servers.nil.
+dom2588. NS a.root-servers.nil.
+dom2589. NS a.root-servers.nil.
+dom2590. NS a.root-servers.nil.
+dom2591. NS a.root-servers.nil.
+dom2592. NS a.root-servers.nil.
+dom2593. NS a.root-servers.nil.
+dom2594. NS a.root-servers.nil.
+dom2595. NS a.root-servers.nil.
+dom2596. NS a.root-servers.nil.
+dom2597. NS a.root-servers.nil.
+dom2598. NS a.root-servers.nil.
+dom2599. NS a.root-servers.nil.
+dom2600. NS a.root-servers.nil.
+dom2601. NS a.root-servers.nil.
+dom2602. NS a.root-servers.nil.
+dom2603. NS a.root-servers.nil.
+dom2604. NS a.root-servers.nil.
+dom2605. NS a.root-servers.nil.
+dom2606. NS a.root-servers.nil.
+dom2607. NS a.root-servers.nil.
+dom2608. NS a.root-servers.nil.
+dom2609. NS a.root-servers.nil.
+dom2610. NS a.root-servers.nil.
+dom2611. NS a.root-servers.nil.
+dom2612. NS a.root-servers.nil.
+dom2613. NS a.root-servers.nil.
+dom2614. NS a.root-servers.nil.
+dom2615. NS a.root-servers.nil.
+dom2616. NS a.root-servers.nil.
+dom2617. NS a.root-servers.nil.
+dom2618. NS a.root-servers.nil.
+dom2619. NS a.root-servers.nil.
+dom2620. NS a.root-servers.nil.
+dom2621. NS a.root-servers.nil.
+dom2622. NS a.root-servers.nil.
+dom2623. NS a.root-servers.nil.
+dom2624. NS a.root-servers.nil.
+dom2625. NS a.root-servers.nil.
+dom2626. NS a.root-servers.nil.
+dom2627. NS a.root-servers.nil.
+dom2628. NS a.root-servers.nil.
+dom2629. NS a.root-servers.nil.
+dom2630. NS a.root-servers.nil.
+dom2631. NS a.root-servers.nil.
+dom2632. NS a.root-servers.nil.
+dom2633. NS a.root-servers.nil.
+dom2634. NS a.root-servers.nil.
+dom2635. NS a.root-servers.nil.
+dom2636. NS a.root-servers.nil.
+dom2637. NS a.root-servers.nil.
+dom2638. NS a.root-servers.nil.
+dom2639. NS a.root-servers.nil.
+dom2640. NS a.root-servers.nil.
+dom2641. NS a.root-servers.nil.
+dom2642. NS a.root-servers.nil.
+dom2643. NS a.root-servers.nil.
+dom2644. NS a.root-servers.nil.
+dom2645. NS a.root-servers.nil.
+dom2646. NS a.root-servers.nil.
+dom2647. NS a.root-servers.nil.
+dom2648. NS a.root-servers.nil.
+dom2649. NS a.root-servers.nil.
+dom2650. NS a.root-servers.nil.
+dom2651. NS a.root-servers.nil.
+dom2652. NS a.root-servers.nil.
+dom2653. NS a.root-servers.nil.
+dom2654. NS a.root-servers.nil.
+dom2655. NS a.root-servers.nil.
+dom2656. NS a.root-servers.nil.
+dom2657. NS a.root-servers.nil.
+dom2658. NS a.root-servers.nil.
+dom2659. NS a.root-servers.nil.
+dom2660. NS a.root-servers.nil.
+dom2661. NS a.root-servers.nil.
+dom2662. NS a.root-servers.nil.
+dom2663. NS a.root-servers.nil.
+dom2664. NS a.root-servers.nil.
+dom2665. NS a.root-servers.nil.
+dom2666. NS a.root-servers.nil.
+dom2667. NS a.root-servers.nil.
+dom2668. NS a.root-servers.nil.
+dom2669. NS a.root-servers.nil.
+dom2670. NS a.root-servers.nil.
+dom2671. NS a.root-servers.nil.
+dom2672. NS a.root-servers.nil.
+dom2673. NS a.root-servers.nil.
+dom2674. NS a.root-servers.nil.
+dom2675. NS a.root-servers.nil.
+dom2676. NS a.root-servers.nil.
+dom2677. NS a.root-servers.nil.
+dom2678. NS a.root-servers.nil.
+dom2679. NS a.root-servers.nil.
+dom2680. NS a.root-servers.nil.
+dom2681. NS a.root-servers.nil.
+dom2682. NS a.root-servers.nil.
+dom2683. NS a.root-servers.nil.
+dom2684. NS a.root-servers.nil.
+dom2685. NS a.root-servers.nil.
+dom2686. NS a.root-servers.nil.
+dom2687. NS a.root-servers.nil.
+dom2688. NS a.root-servers.nil.
+dom2689. NS a.root-servers.nil.
+dom2690. NS a.root-servers.nil.
+dom2691. NS a.root-servers.nil.
+dom2692. NS a.root-servers.nil.
+dom2693. NS a.root-servers.nil.
+dom2694. NS a.root-servers.nil.
+dom2695. NS a.root-servers.nil.
+dom2696. NS a.root-servers.nil.
+dom2697. NS a.root-servers.nil.
+dom2698. NS a.root-servers.nil.
+dom2699. NS a.root-servers.nil.
+dom2700. NS a.root-servers.nil.
+dom2701. NS a.root-servers.nil.
+dom2702. NS a.root-servers.nil.
+dom2703. NS a.root-servers.nil.
+dom2704. NS a.root-servers.nil.
+dom2705. NS a.root-servers.nil.
+dom2706. NS a.root-servers.nil.
+dom2707. NS a.root-servers.nil.
+dom2708. NS a.root-servers.nil.
+dom2709. NS a.root-servers.nil.
+dom2710. NS a.root-servers.nil.
+dom2711. NS a.root-servers.nil.
+dom2712. NS a.root-servers.nil.
+dom2713. NS a.root-servers.nil.
+dom2714. NS a.root-servers.nil.
+dom2715. NS a.root-servers.nil.
+dom2716. NS a.root-servers.nil.
+dom2717. NS a.root-servers.nil.
+dom2718. NS a.root-servers.nil.
+dom2719. NS a.root-servers.nil.
+dom2720. NS a.root-servers.nil.
+dom2721. NS a.root-servers.nil.
+dom2722. NS a.root-servers.nil.
+dom2723. NS a.root-servers.nil.
+dom2724. NS a.root-servers.nil.
+dom2725. NS a.root-servers.nil.
+dom2726. NS a.root-servers.nil.
+dom2727. NS a.root-servers.nil.
+dom2728. NS a.root-servers.nil.
+dom2729. NS a.root-servers.nil.
+dom2730. NS a.root-servers.nil.
+dom2731. NS a.root-servers.nil.
+dom2732. NS a.root-servers.nil.
+dom2733. NS a.root-servers.nil.
+dom2734. NS a.root-servers.nil.
+dom2735. NS a.root-servers.nil.
+dom2736. NS a.root-servers.nil.
+dom2737. NS a.root-servers.nil.
+dom2738. NS a.root-servers.nil.
+dom2739. NS a.root-servers.nil.
+dom2740. NS a.root-servers.nil.
+dom2741. NS a.root-servers.nil.
+dom2742. NS a.root-servers.nil.
+dom2743. NS a.root-servers.nil.
+dom2744. NS a.root-servers.nil.
+dom2745. NS a.root-servers.nil.
+dom2746. NS a.root-servers.nil.
+dom2747. NS a.root-servers.nil.
+dom2748. NS a.root-servers.nil.
+dom2749. NS a.root-servers.nil.
+dom2750. NS a.root-servers.nil.
+dom2751. NS a.root-servers.nil.
+dom2752. NS a.root-servers.nil.
+dom2753. NS a.root-servers.nil.
+dom2754. NS a.root-servers.nil.
+dom2755. NS a.root-servers.nil.
+dom2756. NS a.root-servers.nil.
+dom2757. NS a.root-servers.nil.
+dom2758. NS a.root-servers.nil.
+dom2759. NS a.root-servers.nil.
+dom2760. NS a.root-servers.nil.
+dom2761. NS a.root-servers.nil.
+dom2762. NS a.root-servers.nil.
+dom2763. NS a.root-servers.nil.
+dom2764. NS a.root-servers.nil.
+dom2765. NS a.root-servers.nil.
+dom2766. NS a.root-servers.nil.
+dom2767. NS a.root-servers.nil.
+dom2768. NS a.root-servers.nil.
+dom2769. NS a.root-servers.nil.
+dom2770. NS a.root-servers.nil.
+dom2771. NS a.root-servers.nil.
+dom2772. NS a.root-servers.nil.
+dom2773. NS a.root-servers.nil.
+dom2774. NS a.root-servers.nil.
+dom2775. NS a.root-servers.nil.
+dom2776. NS a.root-servers.nil.
+dom2777. NS a.root-servers.nil.
+dom2778. NS a.root-servers.nil.
+dom2779. NS a.root-servers.nil.
+dom2780. NS a.root-servers.nil.
+dom2781. NS a.root-servers.nil.
+dom2782. NS a.root-servers.nil.
+dom2783. NS a.root-servers.nil.
+dom2784. NS a.root-servers.nil.
+dom2785. NS a.root-servers.nil.
+dom2786. NS a.root-servers.nil.
+dom2787. NS a.root-servers.nil.
+dom2788. NS a.root-servers.nil.
+dom2789. NS a.root-servers.nil.
+dom2790. NS a.root-servers.nil.
+dom2791. NS a.root-servers.nil.
+dom2792. NS a.root-servers.nil.
+dom2793. NS a.root-servers.nil.
+dom2794. NS a.root-servers.nil.
+dom2795. NS a.root-servers.nil.
+dom2796. NS a.root-servers.nil.
+dom2797. NS a.root-servers.nil.
+dom2798. NS a.root-servers.nil.
+dom2799. NS a.root-servers.nil.
+dom2800. NS a.root-servers.nil.
+dom2801. NS a.root-servers.nil.
+dom2802. NS a.root-servers.nil.
+dom2803. NS a.root-servers.nil.
+dom2804. NS a.root-servers.nil.
+dom2805. NS a.root-servers.nil.
+dom2806. NS a.root-servers.nil.
+dom2807. NS a.root-servers.nil.
+dom2808. NS a.root-servers.nil.
+dom2809. NS a.root-servers.nil.
+dom2810. NS a.root-servers.nil.
+dom2811. NS a.root-servers.nil.
+dom2812. NS a.root-servers.nil.
+dom2813. NS a.root-servers.nil.
+dom2814. NS a.root-servers.nil.
+dom2815. NS a.root-servers.nil.
+dom2816. NS a.root-servers.nil.
+dom2817. NS a.root-servers.nil.
+dom2818. NS a.root-servers.nil.
+dom2819. NS a.root-servers.nil.
+dom2820. NS a.root-servers.nil.
+dom2821. NS a.root-servers.nil.
+dom2822. NS a.root-servers.nil.
+dom2823. NS a.root-servers.nil.
+dom2824. NS a.root-servers.nil.
+dom2825. NS a.root-servers.nil.
+dom2826. NS a.root-servers.nil.
+dom2827. NS a.root-servers.nil.
+dom2828. NS a.root-servers.nil.
+dom2829. NS a.root-servers.nil.
+dom2830. NS a.root-servers.nil.
+dom2831. NS a.root-servers.nil.
+dom2832. NS a.root-servers.nil.
+dom2833. NS a.root-servers.nil.
+dom2834. NS a.root-servers.nil.
+dom2835. NS a.root-servers.nil.
+dom2836. NS a.root-servers.nil.
+dom2837. NS a.root-servers.nil.
+dom2838. NS a.root-servers.nil.
+dom2839. NS a.root-servers.nil.
+dom2840. NS a.root-servers.nil.
+dom2841. NS a.root-servers.nil.
+dom2842. NS a.root-servers.nil.
+dom2843. NS a.root-servers.nil.
+dom2844. NS a.root-servers.nil.
+dom2845. NS a.root-servers.nil.
+dom2846. NS a.root-servers.nil.
+dom2847. NS a.root-servers.nil.
+dom2848. NS a.root-servers.nil.
+dom2849. NS a.root-servers.nil.
+dom2850. NS a.root-servers.nil.
+dom2851. NS a.root-servers.nil.
+dom2852. NS a.root-servers.nil.
+dom2853. NS a.root-servers.nil.
+dom2854. NS a.root-servers.nil.
+dom2855. NS a.root-servers.nil.
+dom2856. NS a.root-servers.nil.
+dom2857. NS a.root-servers.nil.
+dom2858. NS a.root-servers.nil.
+dom2859. NS a.root-servers.nil.
+dom2860. NS a.root-servers.nil.
+dom2861. NS a.root-servers.nil.
+dom2862. NS a.root-servers.nil.
+dom2863. NS a.root-servers.nil.
+dom2864. NS a.root-servers.nil.
+dom2865. NS a.root-servers.nil.
+dom2866. NS a.root-servers.nil.
+dom2867. NS a.root-servers.nil.
+dom2868. NS a.root-servers.nil.
+dom2869. NS a.root-servers.nil.
+dom2870. NS a.root-servers.nil.
+dom2871. NS a.root-servers.nil.
+dom2872. NS a.root-servers.nil.
+dom2873. NS a.root-servers.nil.
+dom2874. NS a.root-servers.nil.
+dom2875. NS a.root-servers.nil.
+dom2876. NS a.root-servers.nil.
+dom2877. NS a.root-servers.nil.
+dom2878. NS a.root-servers.nil.
+dom2879. NS a.root-servers.nil.
+dom2880. NS a.root-servers.nil.
+dom2881. NS a.root-servers.nil.
+dom2882. NS a.root-servers.nil.
+dom2883. NS a.root-servers.nil.
+dom2884. NS a.root-servers.nil.
+dom2885. NS a.root-servers.nil.
+dom2886. NS a.root-servers.nil.
+dom2887. NS a.root-servers.nil.
+dom2888. NS a.root-servers.nil.
+dom2889. NS a.root-servers.nil.
+dom2890. NS a.root-servers.nil.
+dom2891. NS a.root-servers.nil.
+dom2892. NS a.root-servers.nil.
+dom2893. NS a.root-servers.nil.
+dom2894. NS a.root-servers.nil.
+dom2895. NS a.root-servers.nil.
+dom2896. NS a.root-servers.nil.
+dom2897. NS a.root-servers.nil.
+dom2898. NS a.root-servers.nil.
+dom2899. NS a.root-servers.nil.
+dom2900. NS a.root-servers.nil.
+dom2901. NS a.root-servers.nil.
+dom2902. NS a.root-servers.nil.
+dom2903. NS a.root-servers.nil.
+dom2904. NS a.root-servers.nil.
+dom2905. NS a.root-servers.nil.
+dom2906. NS a.root-servers.nil.
+dom2907. NS a.root-servers.nil.
+dom2908. NS a.root-servers.nil.
+dom2909. NS a.root-servers.nil.
+dom2910. NS a.root-servers.nil.
+dom2911. NS a.root-servers.nil.
+dom2912. NS a.root-servers.nil.
+dom2913. NS a.root-servers.nil.
+dom2914. NS a.root-servers.nil.
+dom2915. NS a.root-servers.nil.
+dom2916. NS a.root-servers.nil.
+dom2917. NS a.root-servers.nil.
+dom2918. NS a.root-servers.nil.
+dom2919. NS a.root-servers.nil.
+dom2920. NS a.root-servers.nil.
+dom2921. NS a.root-servers.nil.
+dom2922. NS a.root-servers.nil.
+dom2923. NS a.root-servers.nil.
+dom2924. NS a.root-servers.nil.
+dom2925. NS a.root-servers.nil.
+dom2926. NS a.root-servers.nil.
+dom2927. NS a.root-servers.nil.
+dom2928. NS a.root-servers.nil.
+dom2929. NS a.root-servers.nil.
+dom2930. NS a.root-servers.nil.
+dom2931. NS a.root-servers.nil.
+dom2932. NS a.root-servers.nil.
+dom2933. NS a.root-servers.nil.
+dom2934. NS a.root-servers.nil.
+dom2935. NS a.root-servers.nil.
+dom2936. NS a.root-servers.nil.
+dom2937. NS a.root-servers.nil.
+dom2938. NS a.root-servers.nil.
+dom2939. NS a.root-servers.nil.
+dom2940. NS a.root-servers.nil.
+dom2941. NS a.root-servers.nil.
+dom2942. NS a.root-servers.nil.
+dom2943. NS a.root-servers.nil.
+dom2944. NS a.root-servers.nil.
+dom2945. NS a.root-servers.nil.
+dom2946. NS a.root-servers.nil.
+dom2947. NS a.root-servers.nil.
+dom2948. NS a.root-servers.nil.
+dom2949. NS a.root-servers.nil.
+dom2950. NS a.root-servers.nil.
+dom2951. NS a.root-servers.nil.
+dom2952. NS a.root-servers.nil.
+dom2953. NS a.root-servers.nil.
+dom2954. NS a.root-servers.nil.
+dom2955. NS a.root-servers.nil.
+dom2956. NS a.root-servers.nil.
+dom2957. NS a.root-servers.nil.
+dom2958. NS a.root-servers.nil.
+dom2959. NS a.root-servers.nil.
+dom2960. NS a.root-servers.nil.
+dom2961. NS a.root-servers.nil.
+dom2962. NS a.root-servers.nil.
+dom2963. NS a.root-servers.nil.
+dom2964. NS a.root-servers.nil.
+dom2965. NS a.root-servers.nil.
+dom2966. NS a.root-servers.nil.
+dom2967. NS a.root-servers.nil.
+dom2968. NS a.root-servers.nil.
+dom2969. NS a.root-servers.nil.
+dom2970. NS a.root-servers.nil.
+dom2971. NS a.root-servers.nil.
+dom2972. NS a.root-servers.nil.
+dom2973. NS a.root-servers.nil.
+dom2974. NS a.root-servers.nil.
+dom2975. NS a.root-servers.nil.
+dom2976. NS a.root-servers.nil.
+dom2977. NS a.root-servers.nil.
+dom2978. NS a.root-servers.nil.
+dom2979. NS a.root-servers.nil.
+dom2980. NS a.root-servers.nil.
+dom2981. NS a.root-servers.nil.
+dom2982. NS a.root-servers.nil.
+dom2983. NS a.root-servers.nil.
+dom2984. NS a.root-servers.nil.
+dom2985. NS a.root-servers.nil.
+dom2986. NS a.root-servers.nil.
+dom2987. NS a.root-servers.nil.
+dom2988. NS a.root-servers.nil.
+dom2989. NS a.root-servers.nil.
+dom2990. NS a.root-servers.nil.
+dom2991. NS a.root-servers.nil.
+dom2992. NS a.root-servers.nil.
+dom2993. NS a.root-servers.nil.
+dom2994. NS a.root-servers.nil.
+dom2995. NS a.root-servers.nil.
+dom2996. NS a.root-servers.nil.
+dom2997. NS a.root-servers.nil.
+dom2998. NS a.root-servers.nil.
+dom2999. NS a.root-servers.nil.
+dom3000. NS a.root-servers.nil.
+dom3001. NS a.root-servers.nil.
+dom3002. NS a.root-servers.nil.
+dom3003. NS a.root-servers.nil.
+dom3004. NS a.root-servers.nil.
+dom3005. NS a.root-servers.nil.
+dom3006. NS a.root-servers.nil.
+dom3007. NS a.root-servers.nil.
+dom3008. NS a.root-servers.nil.
+dom3009. NS a.root-servers.nil.
+dom3010. NS a.root-servers.nil.
+dom3011. NS a.root-servers.nil.
+dom3012. NS a.root-servers.nil.
+dom3013. NS a.root-servers.nil.
+dom3014. NS a.root-servers.nil.
+dom3015. NS a.root-servers.nil.
+dom3016. NS a.root-servers.nil.
+dom3017. NS a.root-servers.nil.
+dom3018. NS a.root-servers.nil.
+dom3019. NS a.root-servers.nil.
+dom3020. NS a.root-servers.nil.
+dom3021. NS a.root-servers.nil.
+dom3022. NS a.root-servers.nil.
+dom3023. NS a.root-servers.nil.
+dom3024. NS a.root-servers.nil.
+dom3025. NS a.root-servers.nil.
+dom3026. NS a.root-servers.nil.
+dom3027. NS a.root-servers.nil.
+dom3028. NS a.root-servers.nil.
+dom3029. NS a.root-servers.nil.
+dom3030. NS a.root-servers.nil.
+dom3031. NS a.root-servers.nil.
+dom3032. NS a.root-servers.nil.
+dom3033. NS a.root-servers.nil.
+dom3034. NS a.root-servers.nil.
+dom3035. NS a.root-servers.nil.
+dom3036. NS a.root-servers.nil.
+dom3037. NS a.root-servers.nil.
+dom3038. NS a.root-servers.nil.
+dom3039. NS a.root-servers.nil.
+dom3040. NS a.root-servers.nil.
+dom3041. NS a.root-servers.nil.
+dom3042. NS a.root-servers.nil.
+dom3043. NS a.root-servers.nil.
+dom3044. NS a.root-servers.nil.
+dom3045. NS a.root-servers.nil.
+dom3046. NS a.root-servers.nil.
+dom3047. NS a.root-servers.nil.
+dom3048. NS a.root-servers.nil.
+dom3049. NS a.root-servers.nil.
+dom3050. NS a.root-servers.nil.
+dom3051. NS a.root-servers.nil.
+dom3052. NS a.root-servers.nil.
+dom3053. NS a.root-servers.nil.
+dom3054. NS a.root-servers.nil.
+dom3055. NS a.root-servers.nil.
+dom3056. NS a.root-servers.nil.
+dom3057. NS a.root-servers.nil.
+dom3058. NS a.root-servers.nil.
+dom3059. NS a.root-servers.nil.
+dom3060. NS a.root-servers.nil.
+dom3061. NS a.root-servers.nil.
+dom3062. NS a.root-servers.nil.
+dom3063. NS a.root-servers.nil.
+dom3064. NS a.root-servers.nil.
+dom3065. NS a.root-servers.nil.
+dom3066. NS a.root-servers.nil.
+dom3067. NS a.root-servers.nil.
+dom3068. NS a.root-servers.nil.
+dom3069. NS a.root-servers.nil.
+dom3070. NS a.root-servers.nil.
+dom3071. NS a.root-servers.nil.
+dom3072. NS a.root-servers.nil.
+dom3073. NS a.root-servers.nil.
+dom3074. NS a.root-servers.nil.
+dom3075. NS a.root-servers.nil.
+dom3076. NS a.root-servers.nil.
+dom3077. NS a.root-servers.nil.
+dom3078. NS a.root-servers.nil.
+dom3079. NS a.root-servers.nil.
+dom3080. NS a.root-servers.nil.
+dom3081. NS a.root-servers.nil.
+dom3082. NS a.root-servers.nil.
+dom3083. NS a.root-servers.nil.
+dom3084. NS a.root-servers.nil.
+dom3085. NS a.root-servers.nil.
+dom3086. NS a.root-servers.nil.
+dom3087. NS a.root-servers.nil.
+dom3088. NS a.root-servers.nil.
+dom3089. NS a.root-servers.nil.
+dom3090. NS a.root-servers.nil.
+dom3091. NS a.root-servers.nil.
+dom3092. NS a.root-servers.nil.
+dom3093. NS a.root-servers.nil.
+dom3094. NS a.root-servers.nil.
+dom3095. NS a.root-servers.nil.
+dom3096. NS a.root-servers.nil.
+dom3097. NS a.root-servers.nil.
+dom3098. NS a.root-servers.nil.
+dom3099. NS a.root-servers.nil.
+dom3100. NS a.root-servers.nil.
+dom3101. NS a.root-servers.nil.
+dom3102. NS a.root-servers.nil.
+dom3103. NS a.root-servers.nil.
+dom3104. NS a.root-servers.nil.
+dom3105. NS a.root-servers.nil.
+dom3106. NS a.root-servers.nil.
+dom3107. NS a.root-servers.nil.
+dom3108. NS a.root-servers.nil.
+dom3109. NS a.root-servers.nil.
+dom3110. NS a.root-servers.nil.
+dom3111. NS a.root-servers.nil.
+dom3112. NS a.root-servers.nil.
+dom3113. NS a.root-servers.nil.
+dom3114. NS a.root-servers.nil.
+dom3115. NS a.root-servers.nil.
+dom3116. NS a.root-servers.nil.
+dom3117. NS a.root-servers.nil.
+dom3118. NS a.root-servers.nil.
+dom3119. NS a.root-servers.nil.
+dom3120. NS a.root-servers.nil.
+dom3121. NS a.root-servers.nil.
+dom3122. NS a.root-servers.nil.
+dom3123. NS a.root-servers.nil.
+dom3124. NS a.root-servers.nil.
+dom3125. NS a.root-servers.nil.
+dom3126. NS a.root-servers.nil.
+dom3127. NS a.root-servers.nil.
+dom3128. NS a.root-servers.nil.
+dom3129. NS a.root-servers.nil.
+dom3130. NS a.root-servers.nil.
+dom3131. NS a.root-servers.nil.
+dom3132. NS a.root-servers.nil.
+dom3133. NS a.root-servers.nil.
+dom3134. NS a.root-servers.nil.
+dom3135. NS a.root-servers.nil.
+dom3136. NS a.root-servers.nil.
+dom3137. NS a.root-servers.nil.
+dom3138. NS a.root-servers.nil.
+dom3139. NS a.root-servers.nil.
+dom3140. NS a.root-servers.nil.
+dom3141. NS a.root-servers.nil.
+dom3142. NS a.root-servers.nil.
+dom3143. NS a.root-servers.nil.
+dom3144. NS a.root-servers.nil.
+dom3145. NS a.root-servers.nil.
+dom3146. NS a.root-servers.nil.
+dom3147. NS a.root-servers.nil.
+dom3148. NS a.root-servers.nil.
+dom3149. NS a.root-servers.nil.
+dom3150. NS a.root-servers.nil.
+dom3151. NS a.root-servers.nil.
+dom3152. NS a.root-servers.nil.
+dom3153. NS a.root-servers.nil.
+dom3154. NS a.root-servers.nil.
+dom3155. NS a.root-servers.nil.
+dom3156. NS a.root-servers.nil.
+dom3157. NS a.root-servers.nil.
+dom3158. NS a.root-servers.nil.
+dom3159. NS a.root-servers.nil.
+dom3160. NS a.root-servers.nil.
+dom3161. NS a.root-servers.nil.
+dom3162. NS a.root-servers.nil.
+dom3163. NS a.root-servers.nil.
+dom3164. NS a.root-servers.nil.
+dom3165. NS a.root-servers.nil.
+dom3166. NS a.root-servers.nil.
+dom3167. NS a.root-servers.nil.
+dom3168. NS a.root-servers.nil.
+dom3169. NS a.root-servers.nil.
+dom3170. NS a.root-servers.nil.
+dom3171. NS a.root-servers.nil.
+dom3172. NS a.root-servers.nil.
+dom3173. NS a.root-servers.nil.
+dom3174. NS a.root-servers.nil.
+dom3175. NS a.root-servers.nil.
+dom3176. NS a.root-servers.nil.
+dom3177. NS a.root-servers.nil.
+dom3178. NS a.root-servers.nil.
+dom3179. NS a.root-servers.nil.
+dom3180. NS a.root-servers.nil.
+dom3181. NS a.root-servers.nil.
+dom3182. NS a.root-servers.nil.
+dom3183. NS a.root-servers.nil.
+dom3184. NS a.root-servers.nil.
+dom3185. NS a.root-servers.nil.
+dom3186. NS a.root-servers.nil.
+dom3187. NS a.root-servers.nil.
+dom3188. NS a.root-servers.nil.
+dom3189. NS a.root-servers.nil.
+dom3190. NS a.root-servers.nil.
+dom3191. NS a.root-servers.nil.
+dom3192. NS a.root-servers.nil.
+dom3193. NS a.root-servers.nil.
+dom3194. NS a.root-servers.nil.
+dom3195. NS a.root-servers.nil.
+dom3196. NS a.root-servers.nil.
+dom3197. NS a.root-servers.nil.
+dom3198. NS a.root-servers.nil.
+dom3199. NS a.root-servers.nil.
+dom3200. NS a.root-servers.nil.
+dom3201. NS a.root-servers.nil.
+dom3202. NS a.root-servers.nil.
+dom3203. NS a.root-servers.nil.
+dom3204. NS a.root-servers.nil.
+dom3205. NS a.root-servers.nil.
+dom3206. NS a.root-servers.nil.
+dom3207. NS a.root-servers.nil.
+dom3208. NS a.root-servers.nil.
+dom3209. NS a.root-servers.nil.
+dom3210. NS a.root-servers.nil.
+dom3211. NS a.root-servers.nil.
+dom3212. NS a.root-servers.nil.
+dom3213. NS a.root-servers.nil.
+dom3214. NS a.root-servers.nil.
+dom3215. NS a.root-servers.nil.
+dom3216. NS a.root-servers.nil.
+dom3217. NS a.root-servers.nil.
+dom3218. NS a.root-servers.nil.
+dom3219. NS a.root-servers.nil.
+dom3220. NS a.root-servers.nil.
+dom3221. NS a.root-servers.nil.
+dom3222. NS a.root-servers.nil.
+dom3223. NS a.root-servers.nil.
+dom3224. NS a.root-servers.nil.
+dom3225. NS a.root-servers.nil.
+dom3226. NS a.root-servers.nil.
+dom3227. NS a.root-servers.nil.
+dom3228. NS a.root-servers.nil.
+dom3229. NS a.root-servers.nil.
+dom3230. NS a.root-servers.nil.
+dom3231. NS a.root-servers.nil.
+dom3232. NS a.root-servers.nil.
+dom3233. NS a.root-servers.nil.
+dom3234. NS a.root-servers.nil.
+dom3235. NS a.root-servers.nil.
+dom3236. NS a.root-servers.nil.
+dom3237. NS a.root-servers.nil.
+dom3238. NS a.root-servers.nil.
+dom3239. NS a.root-servers.nil.
+dom3240. NS a.root-servers.nil.
+dom3241. NS a.root-servers.nil.
+dom3242. NS a.root-servers.nil.
+dom3243. NS a.root-servers.nil.
+dom3244. NS a.root-servers.nil.
+dom3245. NS a.root-servers.nil.
+dom3246. NS a.root-servers.nil.
+dom3247. NS a.root-servers.nil.
+dom3248. NS a.root-servers.nil.
+dom3249. NS a.root-servers.nil.
+dom3250. NS a.root-servers.nil.
+dom3251. NS a.root-servers.nil.
+dom3252. NS a.root-servers.nil.
+dom3253. NS a.root-servers.nil.
+dom3254. NS a.root-servers.nil.
+dom3255. NS a.root-servers.nil.
+dom3256. NS a.root-servers.nil.
+dom3257. NS a.root-servers.nil.
+dom3258. NS a.root-servers.nil.
+dom3259. NS a.root-servers.nil.
+dom3260. NS a.root-servers.nil.
+dom3261. NS a.root-servers.nil.
+dom3262. NS a.root-servers.nil.
+dom3263. NS a.root-servers.nil.
+dom3264. NS a.root-servers.nil.
+dom3265. NS a.root-servers.nil.
+dom3266. NS a.root-servers.nil.
+dom3267. NS a.root-servers.nil.
+dom3268. NS a.root-servers.nil.
+dom3269. NS a.root-servers.nil.
+dom3270. NS a.root-servers.nil.
+dom3271. NS a.root-servers.nil.
+dom3272. NS a.root-servers.nil.
+dom3273. NS a.root-servers.nil.
+dom3274. NS a.root-servers.nil.
+dom3275. NS a.root-servers.nil.
+dom3276. NS a.root-servers.nil.
+dom3277. NS a.root-servers.nil.
+dom3278. NS a.root-servers.nil.
+dom3279. NS a.root-servers.nil.
+dom3280. NS a.root-servers.nil.
+dom3281. NS a.root-servers.nil.
+dom3282. NS a.root-servers.nil.
+dom3283. NS a.root-servers.nil.
+dom3284. NS a.root-servers.nil.
+dom3285. NS a.root-servers.nil.
+dom3286. NS a.root-servers.nil.
+dom3287. NS a.root-servers.nil.
+dom3288. NS a.root-servers.nil.
+dom3289. NS a.root-servers.nil.
+dom3290. NS a.root-servers.nil.
+dom3291. NS a.root-servers.nil.
+dom3292. NS a.root-servers.nil.
+dom3293. NS a.root-servers.nil.
+dom3294. NS a.root-servers.nil.
+dom3295. NS a.root-servers.nil.
+dom3296. NS a.root-servers.nil.
+dom3297. NS a.root-servers.nil.
+dom3298. NS a.root-servers.nil.
+dom3299. NS a.root-servers.nil.
+dom3300. NS a.root-servers.nil.
+dom3301. NS a.root-servers.nil.
+dom3302. NS a.root-servers.nil.
+dom3303. NS a.root-servers.nil.
+dom3304. NS a.root-servers.nil.
+dom3305. NS a.root-servers.nil.
+dom3306. NS a.root-servers.nil.
+dom3307. NS a.root-servers.nil.
+dom3308. NS a.root-servers.nil.
+dom3309. NS a.root-servers.nil.
+dom3310. NS a.root-servers.nil.
+dom3311. NS a.root-servers.nil.
+dom3312. NS a.root-servers.nil.
+dom3313. NS a.root-servers.nil.
+dom3314. NS a.root-servers.nil.
+dom3315. NS a.root-servers.nil.
+dom3316. NS a.root-servers.nil.
+dom3317. NS a.root-servers.nil.
+dom3318. NS a.root-servers.nil.
+dom3319. NS a.root-servers.nil.
+dom3320. NS a.root-servers.nil.
+dom3321. NS a.root-servers.nil.
+dom3322. NS a.root-servers.nil.
+dom3323. NS a.root-servers.nil.
+dom3324. NS a.root-servers.nil.
+dom3325. NS a.root-servers.nil.
+dom3326. NS a.root-servers.nil.
+dom3327. NS a.root-servers.nil.
+dom3328. NS a.root-servers.nil.
+dom3329. NS a.root-servers.nil.
+dom3330. NS a.root-servers.nil.
+dom3331. NS a.root-servers.nil.
+dom3332. NS a.root-servers.nil.
+dom3333. NS a.root-servers.nil.
+dom3334. NS a.root-servers.nil.
+dom3335. NS a.root-servers.nil.
+dom3336. NS a.root-servers.nil.
+dom3337. NS a.root-servers.nil.
+dom3338. NS a.root-servers.nil.
+dom3339. NS a.root-servers.nil.
+dom3340. NS a.root-servers.nil.
+dom3341. NS a.root-servers.nil.
+dom3342. NS a.root-servers.nil.
+dom3343. NS a.root-servers.nil.
+dom3344. NS a.root-servers.nil.
+dom3345. NS a.root-servers.nil.
+dom3346. NS a.root-servers.nil.
+dom3347. NS a.root-servers.nil.
+dom3348. NS a.root-servers.nil.
+dom3349. NS a.root-servers.nil.
+dom3350. NS a.root-servers.nil.
+dom3351. NS a.root-servers.nil.
+dom3352. NS a.root-servers.nil.
+dom3353. NS a.root-servers.nil.
+dom3354. NS a.root-servers.nil.
+dom3355. NS a.root-servers.nil.
+dom3356. NS a.root-servers.nil.
+dom3357. NS a.root-servers.nil.
+dom3358. NS a.root-servers.nil.
+dom3359. NS a.root-servers.nil.
+dom3360. NS a.root-servers.nil.
+dom3361. NS a.root-servers.nil.
+dom3362. NS a.root-servers.nil.
+dom3363. NS a.root-servers.nil.
+dom3364. NS a.root-servers.nil.
+dom3365. NS a.root-servers.nil.
+dom3366. NS a.root-servers.nil.
+dom3367. NS a.root-servers.nil.
+dom3368. NS a.root-servers.nil.
+dom3369. NS a.root-servers.nil.
+dom3370. NS a.root-servers.nil.
+dom3371. NS a.root-servers.nil.
+dom3372. NS a.root-servers.nil.
+dom3373. NS a.root-servers.nil.
+dom3374. NS a.root-servers.nil.
+dom3375. NS a.root-servers.nil.
+dom3376. NS a.root-servers.nil.
+dom3377. NS a.root-servers.nil.
+dom3378. NS a.root-servers.nil.
+dom3379. NS a.root-servers.nil.
+dom3380. NS a.root-servers.nil.
+dom3381. NS a.root-servers.nil.
+dom3382. NS a.root-servers.nil.
+dom3383. NS a.root-servers.nil.
+dom3384. NS a.root-servers.nil.
+dom3385. NS a.root-servers.nil.
+dom3386. NS a.root-servers.nil.
+dom3387. NS a.root-servers.nil.
+dom3388. NS a.root-servers.nil.
+dom3389. NS a.root-servers.nil.
+dom3390. NS a.root-servers.nil.
+dom3391. NS a.root-servers.nil.
+dom3392. NS a.root-servers.nil.
+dom3393. NS a.root-servers.nil.
+dom3394. NS a.root-servers.nil.
+dom3395. NS a.root-servers.nil.
+dom3396. NS a.root-servers.nil.
+dom3397. NS a.root-servers.nil.
+dom3398. NS a.root-servers.nil.
+dom3399. NS a.root-servers.nil.
+dom3400. NS a.root-servers.nil.
+dom3401. NS a.root-servers.nil.
+dom3402. NS a.root-servers.nil.
+dom3403. NS a.root-servers.nil.
+dom3404. NS a.root-servers.nil.
+dom3405. NS a.root-servers.nil.
+dom3406. NS a.root-servers.nil.
+dom3407. NS a.root-servers.nil.
+dom3408. NS a.root-servers.nil.
+dom3409. NS a.root-servers.nil.
+dom3410. NS a.root-servers.nil.
+dom3411. NS a.root-servers.nil.
+dom3412. NS a.root-servers.nil.
+dom3413. NS a.root-servers.nil.
+dom3414. NS a.root-servers.nil.
+dom3415. NS a.root-servers.nil.
+dom3416. NS a.root-servers.nil.
+dom3417. NS a.root-servers.nil.
+dom3418. NS a.root-servers.nil.
+dom3419. NS a.root-servers.nil.
+dom3420. NS a.root-servers.nil.
+dom3421. NS a.root-servers.nil.
+dom3422. NS a.root-servers.nil.
+dom3423. NS a.root-servers.nil.
+dom3424. NS a.root-servers.nil.
+dom3425. NS a.root-servers.nil.
+dom3426. NS a.root-servers.nil.
+dom3427. NS a.root-servers.nil.
+dom3428. NS a.root-servers.nil.
+dom3429. NS a.root-servers.nil.
+dom3430. NS a.root-servers.nil.
+dom3431. NS a.root-servers.nil.
+dom3432. NS a.root-servers.nil.
+dom3433. NS a.root-servers.nil.
+dom3434. NS a.root-servers.nil.
+dom3435. NS a.root-servers.nil.
+dom3436. NS a.root-servers.nil.
+dom3437. NS a.root-servers.nil.
+dom3438. NS a.root-servers.nil.
+dom3439. NS a.root-servers.nil.
+dom3440. NS a.root-servers.nil.
+dom3441. NS a.root-servers.nil.
+dom3442. NS a.root-servers.nil.
+dom3443. NS a.root-servers.nil.
+dom3444. NS a.root-servers.nil.
+dom3445. NS a.root-servers.nil.
+dom3446. NS a.root-servers.nil.
+dom3447. NS a.root-servers.nil.
+dom3448. NS a.root-servers.nil.
+dom3449. NS a.root-servers.nil.
+dom3450. NS a.root-servers.nil.
+dom3451. NS a.root-servers.nil.
+dom3452. NS a.root-servers.nil.
+dom3453. NS a.root-servers.nil.
+dom3454. NS a.root-servers.nil.
+dom3455. NS a.root-servers.nil.
+dom3456. NS a.root-servers.nil.
+dom3457. NS a.root-servers.nil.
+dom3458. NS a.root-servers.nil.
+dom3459. NS a.root-servers.nil.
+dom3460. NS a.root-servers.nil.
+dom3461. NS a.root-servers.nil.
+dom3462. NS a.root-servers.nil.
+dom3463. NS a.root-servers.nil.
+dom3464. NS a.root-servers.nil.
+dom3465. NS a.root-servers.nil.
+dom3466. NS a.root-servers.nil.
+dom3467. NS a.root-servers.nil.
+dom3468. NS a.root-servers.nil.
+dom3469. NS a.root-servers.nil.
+dom3470. NS a.root-servers.nil.
+dom3471. NS a.root-servers.nil.
+dom3472. NS a.root-servers.nil.
+dom3473. NS a.root-servers.nil.
+dom3474. NS a.root-servers.nil.
+dom3475. NS a.root-servers.nil.
+dom3476. NS a.root-servers.nil.
+dom3477. NS a.root-servers.nil.
+dom3478. NS a.root-servers.nil.
+dom3479. NS a.root-servers.nil.
+dom3480. NS a.root-servers.nil.
+dom3481. NS a.root-servers.nil.
+dom3482. NS a.root-servers.nil.
+dom3483. NS a.root-servers.nil.
+dom3484. NS a.root-servers.nil.
+dom3485. NS a.root-servers.nil.
+dom3486. NS a.root-servers.nil.
+dom3487. NS a.root-servers.nil.
+dom3488. NS a.root-servers.nil.
+dom3489. NS a.root-servers.nil.
+dom3490. NS a.root-servers.nil.
+dom3491. NS a.root-servers.nil.
+dom3492. NS a.root-servers.nil.
+dom3493. NS a.root-servers.nil.
+dom3494. NS a.root-servers.nil.
+dom3495. NS a.root-servers.nil.
+dom3496. NS a.root-servers.nil.
+dom3497. NS a.root-servers.nil.
+dom3498. NS a.root-servers.nil.
+dom3499. NS a.root-servers.nil.
+dom3500. NS a.root-servers.nil.
+dom3501. NS a.root-servers.nil.
+dom3502. NS a.root-servers.nil.
+dom3503. NS a.root-servers.nil.
+dom3504. NS a.root-servers.nil.
+dom3505. NS a.root-servers.nil.
+dom3506. NS a.root-servers.nil.
+dom3507. NS a.root-servers.nil.
+dom3508. NS a.root-servers.nil.
+dom3509. NS a.root-servers.nil.
+dom3510. NS a.root-servers.nil.
+dom3511. NS a.root-servers.nil.
+dom3512. NS a.root-servers.nil.
+dom3513. NS a.root-servers.nil.
+dom3514. NS a.root-servers.nil.
+dom3515. NS a.root-servers.nil.
+dom3516. NS a.root-servers.nil.
+dom3517. NS a.root-servers.nil.
+dom3518. NS a.root-servers.nil.
+dom3519. NS a.root-servers.nil.
+dom3520. NS a.root-servers.nil.
+dom3521. NS a.root-servers.nil.
+dom3522. NS a.root-servers.nil.
+dom3523. NS a.root-servers.nil.
+dom3524. NS a.root-servers.nil.
+dom3525. NS a.root-servers.nil.
+dom3526. NS a.root-servers.nil.
+dom3527. NS a.root-servers.nil.
+dom3528. NS a.root-servers.nil.
+dom3529. NS a.root-servers.nil.
+dom3530. NS a.root-servers.nil.
+dom3531. NS a.root-servers.nil.
+dom3532. NS a.root-servers.nil.
+dom3533. NS a.root-servers.nil.
+dom3534. NS a.root-servers.nil.
+dom3535. NS a.root-servers.nil.
+dom3536. NS a.root-servers.nil.
+dom3537. NS a.root-servers.nil.
+dom3538. NS a.root-servers.nil.
+dom3539. NS a.root-servers.nil.
+dom3540. NS a.root-servers.nil.
+dom3541. NS a.root-servers.nil.
+dom3542. NS a.root-servers.nil.
+dom3543. NS a.root-servers.nil.
+dom3544. NS a.root-servers.nil.
+dom3545. NS a.root-servers.nil.
+dom3546. NS a.root-servers.nil.
+dom3547. NS a.root-servers.nil.
+dom3548. NS a.root-servers.nil.
+dom3549. NS a.root-servers.nil.
+dom3550. NS a.root-servers.nil.
+dom3551. NS a.root-servers.nil.
+dom3552. NS a.root-servers.nil.
+dom3553. NS a.root-servers.nil.
+dom3554. NS a.root-servers.nil.
+dom3555. NS a.root-servers.nil.
+dom3556. NS a.root-servers.nil.
+dom3557. NS a.root-servers.nil.
+dom3558. NS a.root-servers.nil.
+dom3559. NS a.root-servers.nil.
+dom3560. NS a.root-servers.nil.
+dom3561. NS a.root-servers.nil.
+dom3562. NS a.root-servers.nil.
+dom3563. NS a.root-servers.nil.
+dom3564. NS a.root-servers.nil.
+dom3565. NS a.root-servers.nil.
+dom3566. NS a.root-servers.nil.
+dom3567. NS a.root-servers.nil.
+dom3568. NS a.root-servers.nil.
+dom3569. NS a.root-servers.nil.
+dom3570. NS a.root-servers.nil.
+dom3571. NS a.root-servers.nil.
+dom3572. NS a.root-servers.nil.
+dom3573. NS a.root-servers.nil.
+dom3574. NS a.root-servers.nil.
+dom3575. NS a.root-servers.nil.
+dom3576. NS a.root-servers.nil.
+dom3577. NS a.root-servers.nil.
+dom3578. NS a.root-servers.nil.
+dom3579. NS a.root-servers.nil.
+dom3580. NS a.root-servers.nil.
+dom3581. NS a.root-servers.nil.
+dom3582. NS a.root-servers.nil.
+dom3583. NS a.root-servers.nil.
+dom3584. NS a.root-servers.nil.
+dom3585. NS a.root-servers.nil.
+dom3586. NS a.root-servers.nil.
+dom3587. NS a.root-servers.nil.
+dom3588. NS a.root-servers.nil.
+dom3589. NS a.root-servers.nil.
+dom3590. NS a.root-servers.nil.
+dom3591. NS a.root-servers.nil.
+dom3592. NS a.root-servers.nil.
+dom3593. NS a.root-servers.nil.
+dom3594. NS a.root-servers.nil.
+dom3595. NS a.root-servers.nil.
+dom3596. NS a.root-servers.nil.
+dom3597. NS a.root-servers.nil.
+dom3598. NS a.root-servers.nil.
+dom3599. NS a.root-servers.nil.
+dom3600. NS a.root-servers.nil.
+dom3601. NS a.root-servers.nil.
+dom3602. NS a.root-servers.nil.
+dom3603. NS a.root-servers.nil.
+dom3604. NS a.root-servers.nil.
+dom3605. NS a.root-servers.nil.
+dom3606. NS a.root-servers.nil.
+dom3607. NS a.root-servers.nil.
+dom3608. NS a.root-servers.nil.
+dom3609. NS a.root-servers.nil.
+dom3610. NS a.root-servers.nil.
+dom3611. NS a.root-servers.nil.
+dom3612. NS a.root-servers.nil.
+dom3613. NS a.root-servers.nil.
+dom3614. NS a.root-servers.nil.
+dom3615. NS a.root-servers.nil.
+dom3616. NS a.root-servers.nil.
+dom3617. NS a.root-servers.nil.
+dom3618. NS a.root-servers.nil.
+dom3619. NS a.root-servers.nil.
+dom3620. NS a.root-servers.nil.
+dom3621. NS a.root-servers.nil.
+dom3622. NS a.root-servers.nil.
+dom3623. NS a.root-servers.nil.
+dom3624. NS a.root-servers.nil.
+dom3625. NS a.root-servers.nil.
+dom3626. NS a.root-servers.nil.
+dom3627. NS a.root-servers.nil.
+dom3628. NS a.root-servers.nil.
+dom3629. NS a.root-servers.nil.
+dom3630. NS a.root-servers.nil.
+dom3631. NS a.root-servers.nil.
+dom3632. NS a.root-servers.nil.
+dom3633. NS a.root-servers.nil.
+dom3634. NS a.root-servers.nil.
+dom3635. NS a.root-servers.nil.
+dom3636. NS a.root-servers.nil.
+dom3637. NS a.root-servers.nil.
+dom3638. NS a.root-servers.nil.
+dom3639. NS a.root-servers.nil.
+dom3640. NS a.root-servers.nil.
+dom3641. NS a.root-servers.nil.
+dom3642. NS a.root-servers.nil.
+dom3643. NS a.root-servers.nil.
+dom3644. NS a.root-servers.nil.
+dom3645. NS a.root-servers.nil.
+dom3646. NS a.root-servers.nil.
+dom3647. NS a.root-servers.nil.
+dom3648. NS a.root-servers.nil.
+dom3649. NS a.root-servers.nil.
+dom3650. NS a.root-servers.nil.
+dom3651. NS a.root-servers.nil.
+dom3652. NS a.root-servers.nil.
+dom3653. NS a.root-servers.nil.
+dom3654. NS a.root-servers.nil.
+dom3655. NS a.root-servers.nil.
+dom3656. NS a.root-servers.nil.
+dom3657. NS a.root-servers.nil.
+dom3658. NS a.root-servers.nil.
+dom3659. NS a.root-servers.nil.
+dom3660. NS a.root-servers.nil.
+dom3661. NS a.root-servers.nil.
+dom3662. NS a.root-servers.nil.
+dom3663. NS a.root-servers.nil.
+dom3664. NS a.root-servers.nil.
+dom3665. NS a.root-servers.nil.
+dom3666. NS a.root-servers.nil.
+dom3667. NS a.root-servers.nil.
+dom3668. NS a.root-servers.nil.
+dom3669. NS a.root-servers.nil.
+dom3670. NS a.root-servers.nil.
+dom3671. NS a.root-servers.nil.
+dom3672. NS a.root-servers.nil.
+dom3673. NS a.root-servers.nil.
+dom3674. NS a.root-servers.nil.
+dom3675. NS a.root-servers.nil.
+dom3676. NS a.root-servers.nil.
+dom3677. NS a.root-servers.nil.
+dom3678. NS a.root-servers.nil.
+dom3679. NS a.root-servers.nil.
+dom3680. NS a.root-servers.nil.
+dom3681. NS a.root-servers.nil.
+dom3682. NS a.root-servers.nil.
+dom3683. NS a.root-servers.nil.
+dom3684. NS a.root-servers.nil.
+dom3685. NS a.root-servers.nil.
+dom3686. NS a.root-servers.nil.
+dom3687. NS a.root-servers.nil.
+dom3688. NS a.root-servers.nil.
+dom3689. NS a.root-servers.nil.
+dom3690. NS a.root-servers.nil.
+dom3691. NS a.root-servers.nil.
+dom3692. NS a.root-servers.nil.
+dom3693. NS a.root-servers.nil.
+dom3694. NS a.root-servers.nil.
+dom3695. NS a.root-servers.nil.
+dom3696. NS a.root-servers.nil.
+dom3697. NS a.root-servers.nil.
+dom3698. NS a.root-servers.nil.
+dom3699. NS a.root-servers.nil.
+dom3700. NS a.root-servers.nil.
+dom3701. NS a.root-servers.nil.
+dom3702. NS a.root-servers.nil.
+dom3703. NS a.root-servers.nil.
+dom3704. NS a.root-servers.nil.
+dom3705. NS a.root-servers.nil.
+dom3706. NS a.root-servers.nil.
+dom3707. NS a.root-servers.nil.
+dom3708. NS a.root-servers.nil.
+dom3709. NS a.root-servers.nil.
+dom3710. NS a.root-servers.nil.
+dom3711. NS a.root-servers.nil.
+dom3712. NS a.root-servers.nil.
+dom3713. NS a.root-servers.nil.
+dom3714. NS a.root-servers.nil.
+dom3715. NS a.root-servers.nil.
+dom3716. NS a.root-servers.nil.
+dom3717. NS a.root-servers.nil.
+dom3718. NS a.root-servers.nil.
+dom3719. NS a.root-servers.nil.
+dom3720. NS a.root-servers.nil.
+dom3721. NS a.root-servers.nil.
+dom3722. NS a.root-servers.nil.
+dom3723. NS a.root-servers.nil.
+dom3724. NS a.root-servers.nil.
+dom3725. NS a.root-servers.nil.
+dom3726. NS a.root-servers.nil.
+dom3727. NS a.root-servers.nil.
+dom3728. NS a.root-servers.nil.
+dom3729. NS a.root-servers.nil.
+dom3730. NS a.root-servers.nil.
+dom3731. NS a.root-servers.nil.
+dom3732. NS a.root-servers.nil.
+dom3733. NS a.root-servers.nil.
+dom3734. NS a.root-servers.nil.
+dom3735. NS a.root-servers.nil.
+dom3736. NS a.root-servers.nil.
+dom3737. NS a.root-servers.nil.
+dom3738. NS a.root-servers.nil.
+dom3739. NS a.root-servers.nil.
+dom3740. NS a.root-servers.nil.
+dom3741. NS a.root-servers.nil.
+dom3742. NS a.root-servers.nil.
+dom3743. NS a.root-servers.nil.
+dom3744. NS a.root-servers.nil.
+dom3745. NS a.root-servers.nil.
+dom3746. NS a.root-servers.nil.
+dom3747. NS a.root-servers.nil.
+dom3748. NS a.root-servers.nil.
+dom3749. NS a.root-servers.nil.
+dom3750. NS a.root-servers.nil.
+dom3751. NS a.root-servers.nil.
+dom3752. NS a.root-servers.nil.
+dom3753. NS a.root-servers.nil.
+dom3754. NS a.root-servers.nil.
+dom3755. NS a.root-servers.nil.
+dom3756. NS a.root-servers.nil.
+dom3757. NS a.root-servers.nil.
+dom3758. NS a.root-servers.nil.
+dom3759. NS a.root-servers.nil.
+dom3760. NS a.root-servers.nil.
+dom3761. NS a.root-servers.nil.
+dom3762. NS a.root-servers.nil.
+dom3763. NS a.root-servers.nil.
+dom3764. NS a.root-servers.nil.
+dom3765. NS a.root-servers.nil.
+dom3766. NS a.root-servers.nil.
+dom3767. NS a.root-servers.nil.
+dom3768. NS a.root-servers.nil.
+dom3769. NS a.root-servers.nil.
+dom3770. NS a.root-servers.nil.
+dom3771. NS a.root-servers.nil.
+dom3772. NS a.root-servers.nil.
+dom3773. NS a.root-servers.nil.
+dom3774. NS a.root-servers.nil.
+dom3775. NS a.root-servers.nil.
+dom3776. NS a.root-servers.nil.
+dom3777. NS a.root-servers.nil.
+dom3778. NS a.root-servers.nil.
+dom3779. NS a.root-servers.nil.
+dom3780. NS a.root-servers.nil.
+dom3781. NS a.root-servers.nil.
+dom3782. NS a.root-servers.nil.
+dom3783. NS a.root-servers.nil.
+dom3784. NS a.root-servers.nil.
+dom3785. NS a.root-servers.nil.
+dom3786. NS a.root-servers.nil.
+dom3787. NS a.root-servers.nil.
+dom3788. NS a.root-servers.nil.
+dom3789. NS a.root-servers.nil.
+dom3790. NS a.root-servers.nil.
+dom3791. NS a.root-servers.nil.
+dom3792. NS a.root-servers.nil.
+dom3793. NS a.root-servers.nil.
+dom3794. NS a.root-servers.nil.
+dom3795. NS a.root-servers.nil.
+dom3796. NS a.root-servers.nil.
+dom3797. NS a.root-servers.nil.
+dom3798. NS a.root-servers.nil.
+dom3799. NS a.root-servers.nil.
+dom3800. NS a.root-servers.nil.
+dom3801. NS a.root-servers.nil.
+dom3802. NS a.root-servers.nil.
+dom3803. NS a.root-servers.nil.
+dom3804. NS a.root-servers.nil.
+dom3805. NS a.root-servers.nil.
+dom3806. NS a.root-servers.nil.
+dom3807. NS a.root-servers.nil.
+dom3808. NS a.root-servers.nil.
+dom3809. NS a.root-servers.nil.
+dom3810. NS a.root-servers.nil.
+dom3811. NS a.root-servers.nil.
+dom3812. NS a.root-servers.nil.
+dom3813. NS a.root-servers.nil.
+dom3814. NS a.root-servers.nil.
+dom3815. NS a.root-servers.nil.
+dom3816. NS a.root-servers.nil.
+dom3817. NS a.root-servers.nil.
+dom3818. NS a.root-servers.nil.
+dom3819. NS a.root-servers.nil.
+dom3820. NS a.root-servers.nil.
+dom3821. NS a.root-servers.nil.
+dom3822. NS a.root-servers.nil.
+dom3823. NS a.root-servers.nil.
+dom3824. NS a.root-servers.nil.
+dom3825. NS a.root-servers.nil.
+dom3826. NS a.root-servers.nil.
+dom3827. NS a.root-servers.nil.
+dom3828. NS a.root-servers.nil.
+dom3829. NS a.root-servers.nil.
+dom3830. NS a.root-servers.nil.
+dom3831. NS a.root-servers.nil.
+dom3832. NS a.root-servers.nil.
+dom3833. NS a.root-servers.nil.
+dom3834. NS a.root-servers.nil.
+dom3835. NS a.root-servers.nil.
+dom3836. NS a.root-servers.nil.
+dom3837. NS a.root-servers.nil.
+dom3838. NS a.root-servers.nil.
+dom3839. NS a.root-servers.nil.
+dom3840. NS a.root-servers.nil.
+dom3841. NS a.root-servers.nil.
+dom3842. NS a.root-servers.nil.
+dom3843. NS a.root-servers.nil.
+dom3844. NS a.root-servers.nil.
+dom3845. NS a.root-servers.nil.
+dom3846. NS a.root-servers.nil.
+dom3847. NS a.root-servers.nil.
+dom3848. NS a.root-servers.nil.
+dom3849. NS a.root-servers.nil.
+dom3850. NS a.root-servers.nil.
+dom3851. NS a.root-servers.nil.
+dom3852. NS a.root-servers.nil.
+dom3853. NS a.root-servers.nil.
+dom3854. NS a.root-servers.nil.
+dom3855. NS a.root-servers.nil.
+dom3856. NS a.root-servers.nil.
+dom3857. NS a.root-servers.nil.
+dom3858. NS a.root-servers.nil.
+dom3859. NS a.root-servers.nil.
+dom3860. NS a.root-servers.nil.
+dom3861. NS a.root-servers.nil.
+dom3862. NS a.root-servers.nil.
+dom3863. NS a.root-servers.nil.
+dom3864. NS a.root-servers.nil.
+dom3865. NS a.root-servers.nil.
+dom3866. NS a.root-servers.nil.
+dom3867. NS a.root-servers.nil.
+dom3868. NS a.root-servers.nil.
+dom3869. NS a.root-servers.nil.
+dom3870. NS a.root-servers.nil.
+dom3871. NS a.root-servers.nil.
+dom3872. NS a.root-servers.nil.
+dom3873. NS a.root-servers.nil.
+dom3874. NS a.root-servers.nil.
+dom3875. NS a.root-servers.nil.
+dom3876. NS a.root-servers.nil.
+dom3877. NS a.root-servers.nil.
+dom3878. NS a.root-servers.nil.
+dom3879. NS a.root-servers.nil.
+dom3880. NS a.root-servers.nil.
+dom3881. NS a.root-servers.nil.
+dom3882. NS a.root-servers.nil.
+dom3883. NS a.root-servers.nil.
+dom3884. NS a.root-servers.nil.
+dom3885. NS a.root-servers.nil.
+dom3886. NS a.root-servers.nil.
+dom3887. NS a.root-servers.nil.
+dom3888. NS a.root-servers.nil.
+dom3889. NS a.root-servers.nil.
+dom3890. NS a.root-servers.nil.
+dom3891. NS a.root-servers.nil.
+dom3892. NS a.root-servers.nil.
+dom3893. NS a.root-servers.nil.
+dom3894. NS a.root-servers.nil.
+dom3895. NS a.root-servers.nil.
+dom3896. NS a.root-servers.nil.
+dom3897. NS a.root-servers.nil.
+dom3898. NS a.root-servers.nil.
+dom3899. NS a.root-servers.nil.
+dom3900. NS a.root-servers.nil.
+dom3901. NS a.root-servers.nil.
+dom3902. NS a.root-servers.nil.
+dom3903. NS a.root-servers.nil.
+dom3904. NS a.root-servers.nil.
+dom3905. NS a.root-servers.nil.
+dom3906. NS a.root-servers.nil.
+dom3907. NS a.root-servers.nil.
+dom3908. NS a.root-servers.nil.
+dom3909. NS a.root-servers.nil.
+dom3910. NS a.root-servers.nil.
+dom3911. NS a.root-servers.nil.
+dom3912. NS a.root-servers.nil.
+dom3913. NS a.root-servers.nil.
+dom3914. NS a.root-servers.nil.
+dom3915. NS a.root-servers.nil.
+dom3916. NS a.root-servers.nil.
+dom3917. NS a.root-servers.nil.
+dom3918. NS a.root-servers.nil.
+dom3919. NS a.root-servers.nil.
+dom3920. NS a.root-servers.nil.
+dom3921. NS a.root-servers.nil.
+dom3922. NS a.root-servers.nil.
+dom3923. NS a.root-servers.nil.
+dom3924. NS a.root-servers.nil.
+dom3925. NS a.root-servers.nil.
+dom3926. NS a.root-servers.nil.
+dom3927. NS a.root-servers.nil.
+dom3928. NS a.root-servers.nil.
+dom3929. NS a.root-servers.nil.
+dom3930. NS a.root-servers.nil.
+dom3931. NS a.root-servers.nil.
+dom3932. NS a.root-servers.nil.
+dom3933. NS a.root-servers.nil.
+dom3934. NS a.root-servers.nil.
+dom3935. NS a.root-servers.nil.
+dom3936. NS a.root-servers.nil.
+dom3937. NS a.root-servers.nil.
+dom3938. NS a.root-servers.nil.
+dom3939. NS a.root-servers.nil.
+dom3940. NS a.root-servers.nil.
+dom3941. NS a.root-servers.nil.
+dom3942. NS a.root-servers.nil.
+dom3943. NS a.root-servers.nil.
+dom3944. NS a.root-servers.nil.
+dom3945. NS a.root-servers.nil.
+dom3946. NS a.root-servers.nil.
+dom3947. NS a.root-servers.nil.
+dom3948. NS a.root-servers.nil.
+dom3949. NS a.root-servers.nil.
+dom3950. NS a.root-servers.nil.
+dom3951. NS a.root-servers.nil.
+dom3952. NS a.root-servers.nil.
+dom3953. NS a.root-servers.nil.
+dom3954. NS a.root-servers.nil.
+dom3955. NS a.root-servers.nil.
+dom3956. NS a.root-servers.nil.
+dom3957. NS a.root-servers.nil.
+dom3958. NS a.root-servers.nil.
+dom3959. NS a.root-servers.nil.
+dom3960. NS a.root-servers.nil.
+dom3961. NS a.root-servers.nil.
+dom3962. NS a.root-servers.nil.
+dom3963. NS a.root-servers.nil.
+dom3964. NS a.root-servers.nil.
+dom3965. NS a.root-servers.nil.
+dom3966. NS a.root-servers.nil.
+dom3967. NS a.root-servers.nil.
+dom3968. NS a.root-servers.nil.
+dom3969. NS a.root-servers.nil.
+dom3970. NS a.root-servers.nil.
+dom3971. NS a.root-servers.nil.
+dom3972. NS a.root-servers.nil.
+dom3973. NS a.root-servers.nil.
+dom3974. NS a.root-servers.nil.
+dom3975. NS a.root-servers.nil.
+dom3976. NS a.root-servers.nil.
+dom3977. NS a.root-servers.nil.
+dom3978. NS a.root-servers.nil.
+dom3979. NS a.root-servers.nil.
+dom3980. NS a.root-servers.nil.
+dom3981. NS a.root-servers.nil.
+dom3982. NS a.root-servers.nil.
+dom3983. NS a.root-servers.nil.
+dom3984. NS a.root-servers.nil.
+dom3985. NS a.root-servers.nil.
+dom3986. NS a.root-servers.nil.
+dom3987. NS a.root-servers.nil.
+dom3988. NS a.root-servers.nil.
+dom3989. NS a.root-servers.nil.
+dom3990. NS a.root-servers.nil.
+dom3991. NS a.root-servers.nil.
+dom3992. NS a.root-servers.nil.
+dom3993. NS a.root-servers.nil.
+dom3994. NS a.root-servers.nil.
+dom3995. NS a.root-servers.nil.
+dom3996. NS a.root-servers.nil.
+dom3997. NS a.root-servers.nil.
+dom3998. NS a.root-servers.nil.
+dom3999. NS a.root-servers.nil.
+dom4000. NS a.root-servers.nil.
+dom4001. NS a.root-servers.nil.
+dom4002. NS a.root-servers.nil.
+dom4003. NS a.root-servers.nil.
+dom4004. NS a.root-servers.nil.
+dom4005. NS a.root-servers.nil.
+dom4006. NS a.root-servers.nil.
+dom4007. NS a.root-servers.nil.
+dom4008. NS a.root-servers.nil.
+dom4009. NS a.root-servers.nil.
+dom4010. NS a.root-servers.nil.
+dom4011. NS a.root-servers.nil.
+dom4012. NS a.root-servers.nil.
+dom4013. NS a.root-servers.nil.
+dom4014. NS a.root-servers.nil.
+dom4015. NS a.root-servers.nil.
+dom4016. NS a.root-servers.nil.
+dom4017. NS a.root-servers.nil.
+dom4018. NS a.root-servers.nil.
+dom4019. NS a.root-servers.nil.
+dom4020. NS a.root-servers.nil.
+dom4021. NS a.root-servers.nil.
+dom4022. NS a.root-servers.nil.
+dom4023. NS a.root-servers.nil.
+dom4024. NS a.root-servers.nil.
+dom4025. NS a.root-servers.nil.
+dom4026. NS a.root-servers.nil.
+dom4027. NS a.root-servers.nil.
+dom4028. NS a.root-servers.nil.
+dom4029. NS a.root-servers.nil.
+dom4030. NS a.root-servers.nil.
+dom4031. NS a.root-servers.nil.
+dom4032. NS a.root-servers.nil.
+dom4033. NS a.root-servers.nil.
+dom4034. NS a.root-servers.nil.
+dom4035. NS a.root-servers.nil.
+dom4036. NS a.root-servers.nil.
+dom4037. NS a.root-servers.nil.
+dom4038. NS a.root-servers.nil.
+dom4039. NS a.root-servers.nil.
+dom4040. NS a.root-servers.nil.
+dom4041. NS a.root-servers.nil.
+dom4042. NS a.root-servers.nil.
+dom4043. NS a.root-servers.nil.
+dom4044. NS a.root-servers.nil.
+dom4045. NS a.root-servers.nil.
+dom4046. NS a.root-servers.nil.
+dom4047. NS a.root-servers.nil.
+dom4048. NS a.root-servers.nil.
+dom4049. NS a.root-servers.nil.
+dom4050. NS a.root-servers.nil.
+dom4051. NS a.root-servers.nil.
+dom4052. NS a.root-servers.nil.
+dom4053. NS a.root-servers.nil.
+dom4054. NS a.root-servers.nil.
+dom4055. NS a.root-servers.nil.
+dom4056. NS a.root-servers.nil.
+dom4057. NS a.root-servers.nil.
+dom4058. NS a.root-servers.nil.
+dom4059. NS a.root-servers.nil.
+dom4060. NS a.root-servers.nil.
+dom4061. NS a.root-servers.nil.
+dom4062. NS a.root-servers.nil.
+dom4063. NS a.root-servers.nil.
+dom4064. NS a.root-servers.nil.
+dom4065. NS a.root-servers.nil.
+dom4066. NS a.root-servers.nil.
+dom4067. NS a.root-servers.nil.
+dom4068. NS a.root-servers.nil.
+dom4069. NS a.root-servers.nil.
+dom4070. NS a.root-servers.nil.
+dom4071. NS a.root-servers.nil.
+dom4072. NS a.root-servers.nil.
+dom4073. NS a.root-servers.nil.
+dom4074. NS a.root-servers.nil.
+dom4075. NS a.root-servers.nil.
+dom4076. NS a.root-servers.nil.
+dom4077. NS a.root-servers.nil.
+dom4078. NS a.root-servers.nil.
+dom4079. NS a.root-servers.nil.
+dom4080. NS a.root-servers.nil.
+dom4081. NS a.root-servers.nil.
+dom4082. NS a.root-servers.nil.
+dom4083. NS a.root-servers.nil.
+dom4084. NS a.root-servers.nil.
+dom4085. NS a.root-servers.nil.
+dom4086. NS a.root-servers.nil.
+dom4087. NS a.root-servers.nil.
+dom4088. NS a.root-servers.nil.
+dom4089. NS a.root-servers.nil.
+dom4090. NS a.root-servers.nil.
+dom4091. NS a.root-servers.nil.
+dom4092. NS a.root-servers.nil.
+dom4093. NS a.root-servers.nil.
+dom4094. NS a.root-servers.nil.
+dom4095. NS a.root-servers.nil.
+dom4096. NS a.root-servers.nil.
+dom4097. NS a.root-servers.nil.
+dom4098. NS a.root-servers.nil.
+dom4099. NS a.root-servers.nil.
+dom4100. NS a.root-servers.nil.
+dom4101. NS a.root-servers.nil.
+dom4102. NS a.root-servers.nil.
+dom4103. NS a.root-servers.nil.
+dom4104. NS a.root-servers.nil.
+dom4105. NS a.root-servers.nil.
+dom4106. NS a.root-servers.nil.
+dom4107. NS a.root-servers.nil.
+dom4108. NS a.root-servers.nil.
+dom4109. NS a.root-servers.nil.
+dom4110. NS a.root-servers.nil.
+dom4111. NS a.root-servers.nil.
+dom4112. NS a.root-servers.nil.
+dom4113. NS a.root-servers.nil.
+dom4114. NS a.root-servers.nil.
+dom4115. NS a.root-servers.nil.
+dom4116. NS a.root-servers.nil.
+dom4117. NS a.root-servers.nil.
+dom4118. NS a.root-servers.nil.
+dom4119. NS a.root-servers.nil.
+dom4120. NS a.root-servers.nil.
+dom4121. NS a.root-servers.nil.
+dom4122. NS a.root-servers.nil.
+dom4123. NS a.root-servers.nil.
+dom4124. NS a.root-servers.nil.
+dom4125. NS a.root-servers.nil.
+dom4126. NS a.root-servers.nil.
+dom4127. NS a.root-servers.nil.
+dom4128. NS a.root-servers.nil.
+dom4129. NS a.root-servers.nil.
+dom4130. NS a.root-servers.nil.
+dom4131. NS a.root-servers.nil.
+dom4132. NS a.root-servers.nil.
+dom4133. NS a.root-servers.nil.
+dom4134. NS a.root-servers.nil.
+dom4135. NS a.root-servers.nil.
+dom4136. NS a.root-servers.nil.
+dom4137. NS a.root-servers.nil.
+dom4138. NS a.root-servers.nil.
+dom4139. NS a.root-servers.nil.
+dom4140. NS a.root-servers.nil.
+dom4141. NS a.root-servers.nil.
+dom4142. NS a.root-servers.nil.
+dom4143. NS a.root-servers.nil.
+dom4144. NS a.root-servers.nil.
+dom4145. NS a.root-servers.nil.
+dom4146. NS a.root-servers.nil.
+dom4147. NS a.root-servers.nil.
+dom4148. NS a.root-servers.nil.
+dom4149. NS a.root-servers.nil.
+dom4150. NS a.root-servers.nil.
+dom4151. NS a.root-servers.nil.
+dom4152. NS a.root-servers.nil.
+dom4153. NS a.root-servers.nil.
+dom4154. NS a.root-servers.nil.
+dom4155. NS a.root-servers.nil.
+dom4156. NS a.root-servers.nil.
+dom4157. NS a.root-servers.nil.
+dom4158. NS a.root-servers.nil.
+dom4159. NS a.root-servers.nil.
+dom4160. NS a.root-servers.nil.
+dom4161. NS a.root-servers.nil.
+dom4162. NS a.root-servers.nil.
+dom4163. NS a.root-servers.nil.
+dom4164. NS a.root-servers.nil.
+dom4165. NS a.root-servers.nil.
+dom4166. NS a.root-servers.nil.
+dom4167. NS a.root-servers.nil.
+dom4168. NS a.root-servers.nil.
+dom4169. NS a.root-servers.nil.
+dom4170. NS a.root-servers.nil.
+dom4171. NS a.root-servers.nil.
+dom4172. NS a.root-servers.nil.
+dom4173. NS a.root-servers.nil.
+dom4174. NS a.root-servers.nil.
+dom4175. NS a.root-servers.nil.
+dom4176. NS a.root-servers.nil.
+dom4177. NS a.root-servers.nil.
+dom4178. NS a.root-servers.nil.
+dom4179. NS a.root-servers.nil.
+dom4180. NS a.root-servers.nil.
+dom4181. NS a.root-servers.nil.
+dom4182. NS a.root-servers.nil.
+dom4183. NS a.root-servers.nil.
+dom4184. NS a.root-servers.nil.
+dom4185. NS a.root-servers.nil.
+dom4186. NS a.root-servers.nil.
+dom4187. NS a.root-servers.nil.
+dom4188. NS a.root-servers.nil.
+dom4189. NS a.root-servers.nil.
+dom4190. NS a.root-servers.nil.
+dom4191. NS a.root-servers.nil.
+dom4192. NS a.root-servers.nil.
+dom4193. NS a.root-servers.nil.
+dom4194. NS a.root-servers.nil.
+dom4195. NS a.root-servers.nil.
+dom4196. NS a.root-servers.nil.
+dom4197. NS a.root-servers.nil.
+dom4198. NS a.root-servers.nil.
+dom4199. NS a.root-servers.nil.
+dom4200. NS a.root-servers.nil.
+dom4201. NS a.root-servers.nil.
+dom4202. NS a.root-servers.nil.
+dom4203. NS a.root-servers.nil.
+dom4204. NS a.root-servers.nil.
+dom4205. NS a.root-servers.nil.
+dom4206. NS a.root-servers.nil.
+dom4207. NS a.root-servers.nil.
+dom4208. NS a.root-servers.nil.
+dom4209. NS a.root-servers.nil.
+dom4210. NS a.root-servers.nil.
+dom4211. NS a.root-servers.nil.
+dom4212. NS a.root-servers.nil.
+dom4213. NS a.root-servers.nil.
+dom4214. NS a.root-servers.nil.
+dom4215. NS a.root-servers.nil.
+dom4216. NS a.root-servers.nil.
+dom4217. NS a.root-servers.nil.
+dom4218. NS a.root-servers.nil.
+dom4219. NS a.root-servers.nil.
+dom4220. NS a.root-servers.nil.
+dom4221. NS a.root-servers.nil.
+dom4222. NS a.root-servers.nil.
+dom4223. NS a.root-servers.nil.
+dom4224. NS a.root-servers.nil.
+dom4225. NS a.root-servers.nil.
+dom4226. NS a.root-servers.nil.
+dom4227. NS a.root-servers.nil.
+dom4228. NS a.root-servers.nil.
+dom4229. NS a.root-servers.nil.
+dom4230. NS a.root-servers.nil.
+dom4231. NS a.root-servers.nil.
+dom4232. NS a.root-servers.nil.
+dom4233. NS a.root-servers.nil.
+dom4234. NS a.root-servers.nil.
+dom4235. NS a.root-servers.nil.
+dom4236. NS a.root-servers.nil.
+dom4237. NS a.root-servers.nil.
+dom4238. NS a.root-servers.nil.
+dom4239. NS a.root-servers.nil.
+dom4240. NS a.root-servers.nil.
+dom4241. NS a.root-servers.nil.
+dom4242. NS a.root-servers.nil.
+dom4243. NS a.root-servers.nil.
+dom4244. NS a.root-servers.nil.
+dom4245. NS a.root-servers.nil.
+dom4246. NS a.root-servers.nil.
+dom4247. NS a.root-servers.nil.
+dom4248. NS a.root-servers.nil.
+dom4249. NS a.root-servers.nil.
+dom4250. NS a.root-servers.nil.
+dom4251. NS a.root-servers.nil.
+dom4252. NS a.root-servers.nil.
+dom4253. NS a.root-servers.nil.
+dom4254. NS a.root-servers.nil.
+dom4255. NS a.root-servers.nil.
+dom4256. NS a.root-servers.nil.
+dom4257. NS a.root-servers.nil.
+dom4258. NS a.root-servers.nil.
+dom4259. NS a.root-servers.nil.
+dom4260. NS a.root-servers.nil.
+dom4261. NS a.root-servers.nil.
+dom4262. NS a.root-servers.nil.
+dom4263. NS a.root-servers.nil.
+dom4264. NS a.root-servers.nil.
+dom4265. NS a.root-servers.nil.
+dom4266. NS a.root-servers.nil.
+dom4267. NS a.root-servers.nil.
+dom4268. NS a.root-servers.nil.
+dom4269. NS a.root-servers.nil.
+dom4270. NS a.root-servers.nil.
+dom4271. NS a.root-servers.nil.
+dom4272. NS a.root-servers.nil.
+dom4273. NS a.root-servers.nil.
+dom4274. NS a.root-servers.nil.
+dom4275. NS a.root-servers.nil.
+dom4276. NS a.root-servers.nil.
+dom4277. NS a.root-servers.nil.
+dom4278. NS a.root-servers.nil.
+dom4279. NS a.root-servers.nil.
+dom4280. NS a.root-servers.nil.
+dom4281. NS a.root-servers.nil.
+dom4282. NS a.root-servers.nil.
+dom4283. NS a.root-servers.nil.
+dom4284. NS a.root-servers.nil.
+dom4285. NS a.root-servers.nil.
+dom4286. NS a.root-servers.nil.
+dom4287. NS a.root-servers.nil.
+dom4288. NS a.root-servers.nil.
+dom4289. NS a.root-servers.nil.
+dom4290. NS a.root-servers.nil.
+dom4291. NS a.root-servers.nil.
+dom4292. NS a.root-servers.nil.
+dom4293. NS a.root-servers.nil.
+dom4294. NS a.root-servers.nil.
+dom4295. NS a.root-servers.nil.
+dom4296. NS a.root-servers.nil.
+dom4297. NS a.root-servers.nil.
+dom4298. NS a.root-servers.nil.
+dom4299. NS a.root-servers.nil.
+dom4300. NS a.root-servers.nil.
+dom4301. NS a.root-servers.nil.
+dom4302. NS a.root-servers.nil.
+dom4303. NS a.root-servers.nil.
+dom4304. NS a.root-servers.nil.
+dom4305. NS a.root-servers.nil.
+dom4306. NS a.root-servers.nil.
+dom4307. NS a.root-servers.nil.
+dom4308. NS a.root-servers.nil.
+dom4309. NS a.root-servers.nil.
+dom4310. NS a.root-servers.nil.
+dom4311. NS a.root-servers.nil.
+dom4312. NS a.root-servers.nil.
+dom4313. NS a.root-servers.nil.
+dom4314. NS a.root-servers.nil.
+dom4315. NS a.root-servers.nil.
+dom4316. NS a.root-servers.nil.
+dom4317. NS a.root-servers.nil.
+dom4318. NS a.root-servers.nil.
+dom4319. NS a.root-servers.nil.
+dom4320. NS a.root-servers.nil.
+dom4321. NS a.root-servers.nil.
+dom4322. NS a.root-servers.nil.
+dom4323. NS a.root-servers.nil.
+dom4324. NS a.root-servers.nil.
+dom4325. NS a.root-servers.nil.
+dom4326. NS a.root-servers.nil.
+dom4327. NS a.root-servers.nil.
+dom4328. NS a.root-servers.nil.
+dom4329. NS a.root-servers.nil.
+dom4330. NS a.root-servers.nil.
+dom4331. NS a.root-servers.nil.
+dom4332. NS a.root-servers.nil.
+dom4333. NS a.root-servers.nil.
+dom4334. NS a.root-servers.nil.
+dom4335. NS a.root-servers.nil.
+dom4336. NS a.root-servers.nil.
+dom4337. NS a.root-servers.nil.
+dom4338. NS a.root-servers.nil.
+dom4339. NS a.root-servers.nil.
+dom4340. NS a.root-servers.nil.
+dom4341. NS a.root-servers.nil.
+dom4342. NS a.root-servers.nil.
+dom4343. NS a.root-servers.nil.
+dom4344. NS a.root-servers.nil.
+dom4345. NS a.root-servers.nil.
+dom4346. NS a.root-servers.nil.
+dom4347. NS a.root-servers.nil.
+dom4348. NS a.root-servers.nil.
+dom4349. NS a.root-servers.nil.
+dom4350. NS a.root-servers.nil.
+dom4351. NS a.root-servers.nil.
+dom4352. NS a.root-servers.nil.
+dom4353. NS a.root-servers.nil.
+dom4354. NS a.root-servers.nil.
+dom4355. NS a.root-servers.nil.
+dom4356. NS a.root-servers.nil.
+dom4357. NS a.root-servers.nil.
+dom4358. NS a.root-servers.nil.
+dom4359. NS a.root-servers.nil.
+dom4360. NS a.root-servers.nil.
+dom4361. NS a.root-servers.nil.
+dom4362. NS a.root-servers.nil.
+dom4363. NS a.root-servers.nil.
+dom4364. NS a.root-servers.nil.
+dom4365. NS a.root-servers.nil.
+dom4366. NS a.root-servers.nil.
+dom4367. NS a.root-servers.nil.
+dom4368. NS a.root-servers.nil.
+dom4369. NS a.root-servers.nil.
+dom4370. NS a.root-servers.nil.
+dom4371. NS a.root-servers.nil.
+dom4372. NS a.root-servers.nil.
+dom4373. NS a.root-servers.nil.
+dom4374. NS a.root-servers.nil.
+dom4375. NS a.root-servers.nil.
+dom4376. NS a.root-servers.nil.
+dom4377. NS a.root-servers.nil.
+dom4378. NS a.root-servers.nil.
+dom4379. NS a.root-servers.nil.
+dom4380. NS a.root-servers.nil.
+dom4381. NS a.root-servers.nil.
+dom4382. NS a.root-servers.nil.
+dom4383. NS a.root-servers.nil.
+dom4384. NS a.root-servers.nil.
+dom4385. NS a.root-servers.nil.
+dom4386. NS a.root-servers.nil.
+dom4387. NS a.root-servers.nil.
+dom4388. NS a.root-servers.nil.
+dom4389. NS a.root-servers.nil.
+dom4390. NS a.root-servers.nil.
+dom4391. NS a.root-servers.nil.
+dom4392. NS a.root-servers.nil.
+dom4393. NS a.root-servers.nil.
+dom4394. NS a.root-servers.nil.
+dom4395. NS a.root-servers.nil.
+dom4396. NS a.root-servers.nil.
+dom4397. NS a.root-servers.nil.
+dom4398. NS a.root-servers.nil.
+dom4399. NS a.root-servers.nil.
+dom4400. NS a.root-servers.nil.
+dom4401. NS a.root-servers.nil.
+dom4402. NS a.root-servers.nil.
+dom4403. NS a.root-servers.nil.
+dom4404. NS a.root-servers.nil.
+dom4405. NS a.root-servers.nil.
+dom4406. NS a.root-servers.nil.
+dom4407. NS a.root-servers.nil.
+dom4408. NS a.root-servers.nil.
+dom4409. NS a.root-servers.nil.
+dom4410. NS a.root-servers.nil.
+dom4411. NS a.root-servers.nil.
+dom4412. NS a.root-servers.nil.
+dom4413. NS a.root-servers.nil.
+dom4414. NS a.root-servers.nil.
+dom4415. NS a.root-servers.nil.
+dom4416. NS a.root-servers.nil.
+dom4417. NS a.root-servers.nil.
+dom4418. NS a.root-servers.nil.
+dom4419. NS a.root-servers.nil.
+dom4420. NS a.root-servers.nil.
+dom4421. NS a.root-servers.nil.
+dom4422. NS a.root-servers.nil.
+dom4423. NS a.root-servers.nil.
+dom4424. NS a.root-servers.nil.
+dom4425. NS a.root-servers.nil.
+dom4426. NS a.root-servers.nil.
+dom4427. NS a.root-servers.nil.
+dom4428. NS a.root-servers.nil.
+dom4429. NS a.root-servers.nil.
+dom4430. NS a.root-servers.nil.
+dom4431. NS a.root-servers.nil.
+dom4432. NS a.root-servers.nil.
+dom4433. NS a.root-servers.nil.
+dom4434. NS a.root-servers.nil.
+dom4435. NS a.root-servers.nil.
+dom4436. NS a.root-servers.nil.
+dom4437. NS a.root-servers.nil.
+dom4438. NS a.root-servers.nil.
+dom4439. NS a.root-servers.nil.
+dom4440. NS a.root-servers.nil.
+dom4441. NS a.root-servers.nil.
+dom4442. NS a.root-servers.nil.
+dom4443. NS a.root-servers.nil.
+dom4444. NS a.root-servers.nil.
+dom4445. NS a.root-servers.nil.
+dom4446. NS a.root-servers.nil.
+dom4447. NS a.root-servers.nil.
+dom4448. NS a.root-servers.nil.
+dom4449. NS a.root-servers.nil.
+dom4450. NS a.root-servers.nil.
+dom4451. NS a.root-servers.nil.
+dom4452. NS a.root-servers.nil.
+dom4453. NS a.root-servers.nil.
+dom4454. NS a.root-servers.nil.
+dom4455. NS a.root-servers.nil.
+dom4456. NS a.root-servers.nil.
+dom4457. NS a.root-servers.nil.
+dom4458. NS a.root-servers.nil.
+dom4459. NS a.root-servers.nil.
+dom4460. NS a.root-servers.nil.
+dom4461. NS a.root-servers.nil.
+dom4462. NS a.root-servers.nil.
+dom4463. NS a.root-servers.nil.
+dom4464. NS a.root-servers.nil.
+dom4465. NS a.root-servers.nil.
+dom4466. NS a.root-servers.nil.
+dom4467. NS a.root-servers.nil.
+dom4468. NS a.root-servers.nil.
+dom4469. NS a.root-servers.nil.
+dom4470. NS a.root-servers.nil.
+dom4471. NS a.root-servers.nil.
+dom4472. NS a.root-servers.nil.
+dom4473. NS a.root-servers.nil.
+dom4474. NS a.root-servers.nil.
+dom4475. NS a.root-servers.nil.
+dom4476. NS a.root-servers.nil.
+dom4477. NS a.root-servers.nil.
+dom4478. NS a.root-servers.nil.
+dom4479. NS a.root-servers.nil.
+dom4480. NS a.root-servers.nil.
+dom4481. NS a.root-servers.nil.
+dom4482. NS a.root-servers.nil.
+dom4483. NS a.root-servers.nil.
+dom4484. NS a.root-servers.nil.
+dom4485. NS a.root-servers.nil.
+dom4486. NS a.root-servers.nil.
+dom4487. NS a.root-servers.nil.
+dom4488. NS a.root-servers.nil.
+dom4489. NS a.root-servers.nil.
+dom4490. NS a.root-servers.nil.
+dom4491. NS a.root-servers.nil.
+dom4492. NS a.root-servers.nil.
+dom4493. NS a.root-servers.nil.
+dom4494. NS a.root-servers.nil.
+dom4495. NS a.root-servers.nil.
+dom4496. NS a.root-servers.nil.
+dom4497. NS a.root-servers.nil.
+dom4498. NS a.root-servers.nil.
+dom4499. NS a.root-servers.nil.
+dom4500. NS a.root-servers.nil.
+dom4501. NS a.root-servers.nil.
+dom4502. NS a.root-servers.nil.
+dom4503. NS a.root-servers.nil.
+dom4504. NS a.root-servers.nil.
+dom4505. NS a.root-servers.nil.
+dom4506. NS a.root-servers.nil.
+dom4507. NS a.root-servers.nil.
+dom4508. NS a.root-servers.nil.
+dom4509. NS a.root-servers.nil.
+dom4510. NS a.root-servers.nil.
+dom4511. NS a.root-servers.nil.
+dom4512. NS a.root-servers.nil.
+dom4513. NS a.root-servers.nil.
+dom4514. NS a.root-servers.nil.
+dom4515. NS a.root-servers.nil.
+dom4516. NS a.root-servers.nil.
+dom4517. NS a.root-servers.nil.
+dom4518. NS a.root-servers.nil.
+dom4519. NS a.root-servers.nil.
+dom4520. NS a.root-servers.nil.
+dom4521. NS a.root-servers.nil.
+dom4522. NS a.root-servers.nil.
+dom4523. NS a.root-servers.nil.
+dom4524. NS a.root-servers.nil.
+dom4525. NS a.root-servers.nil.
+dom4526. NS a.root-servers.nil.
+dom4527. NS a.root-servers.nil.
+dom4528. NS a.root-servers.nil.
+dom4529. NS a.root-servers.nil.
+dom4530. NS a.root-servers.nil.
+dom4531. NS a.root-servers.nil.
+dom4532. NS a.root-servers.nil.
+dom4533. NS a.root-servers.nil.
+dom4534. NS a.root-servers.nil.
+dom4535. NS a.root-servers.nil.
+dom4536. NS a.root-servers.nil.
+dom4537. NS a.root-servers.nil.
+dom4538. NS a.root-servers.nil.
+dom4539. NS a.root-servers.nil.
+dom4540. NS a.root-servers.nil.
+dom4541. NS a.root-servers.nil.
+dom4542. NS a.root-servers.nil.
+dom4543. NS a.root-servers.nil.
+dom4544. NS a.root-servers.nil.
+dom4545. NS a.root-servers.nil.
+dom4546. NS a.root-servers.nil.
+dom4547. NS a.root-servers.nil.
+dom4548. NS a.root-servers.nil.
+dom4549. NS a.root-servers.nil.
+dom4550. NS a.root-servers.nil.
+dom4551. NS a.root-servers.nil.
+dom4552. NS a.root-servers.nil.
+dom4553. NS a.root-servers.nil.
+dom4554. NS a.root-servers.nil.
+dom4555. NS a.root-servers.nil.
+dom4556. NS a.root-servers.nil.
+dom4557. NS a.root-servers.nil.
+dom4558. NS a.root-servers.nil.
+dom4559. NS a.root-servers.nil.
+dom4560. NS a.root-servers.nil.
+dom4561. NS a.root-servers.nil.
+dom4562. NS a.root-servers.nil.
+dom4563. NS a.root-servers.nil.
+dom4564. NS a.root-servers.nil.
+dom4565. NS a.root-servers.nil.
+dom4566. NS a.root-servers.nil.
+dom4567. NS a.root-servers.nil.
+dom4568. NS a.root-servers.nil.
+dom4569. NS a.root-servers.nil.
+dom4570. NS a.root-servers.nil.
+dom4571. NS a.root-servers.nil.
+dom4572. NS a.root-servers.nil.
+dom4573. NS a.root-servers.nil.
+dom4574. NS a.root-servers.nil.
+dom4575. NS a.root-servers.nil.
+dom4576. NS a.root-servers.nil.
+dom4577. NS a.root-servers.nil.
+dom4578. NS a.root-servers.nil.
+dom4579. NS a.root-servers.nil.
+dom4580. NS a.root-servers.nil.
+dom4581. NS a.root-servers.nil.
+dom4582. NS a.root-servers.nil.
+dom4583. NS a.root-servers.nil.
+dom4584. NS a.root-servers.nil.
+dom4585. NS a.root-servers.nil.
+dom4586. NS a.root-servers.nil.
+dom4587. NS a.root-servers.nil.
+dom4588. NS a.root-servers.nil.
+dom4589. NS a.root-servers.nil.
+dom4590. NS a.root-servers.nil.
+dom4591. NS a.root-servers.nil.
+dom4592. NS a.root-servers.nil.
+dom4593. NS a.root-servers.nil.
+dom4594. NS a.root-servers.nil.
+dom4595. NS a.root-servers.nil.
+dom4596. NS a.root-servers.nil.
+dom4597. NS a.root-servers.nil.
+dom4598. NS a.root-servers.nil.
+dom4599. NS a.root-servers.nil.
+dom4600. NS a.root-servers.nil.
+dom4601. NS a.root-servers.nil.
+dom4602. NS a.root-servers.nil.
+dom4603. NS a.root-servers.nil.
+dom4604. NS a.root-servers.nil.
+dom4605. NS a.root-servers.nil.
+dom4606. NS a.root-servers.nil.
+dom4607. NS a.root-servers.nil.
+dom4608. NS a.root-servers.nil.
+dom4609. NS a.root-servers.nil.
+dom4610. NS a.root-servers.nil.
+dom4611. NS a.root-servers.nil.
+dom4612. NS a.root-servers.nil.
+dom4613. NS a.root-servers.nil.
+dom4614. NS a.root-servers.nil.
+dom4615. NS a.root-servers.nil.
+dom4616. NS a.root-servers.nil.
+dom4617. NS a.root-servers.nil.
+dom4618. NS a.root-servers.nil.
+dom4619. NS a.root-servers.nil.
+dom4620. NS a.root-servers.nil.
+dom4621. NS a.root-servers.nil.
+dom4622. NS a.root-servers.nil.
+dom4623. NS a.root-servers.nil.
+dom4624. NS a.root-servers.nil.
+dom4625. NS a.root-servers.nil.
+dom4626. NS a.root-servers.nil.
+dom4627. NS a.root-servers.nil.
+dom4628. NS a.root-servers.nil.
+dom4629. NS a.root-servers.nil.
+dom4630. NS a.root-servers.nil.
+dom4631. NS a.root-servers.nil.
+dom4632. NS a.root-servers.nil.
+dom4633. NS a.root-servers.nil.
+dom4634. NS a.root-servers.nil.
+dom4635. NS a.root-servers.nil.
+dom4636. NS a.root-servers.nil.
+dom4637. NS a.root-servers.nil.
+dom4638. NS a.root-servers.nil.
+dom4639. NS a.root-servers.nil.
+dom4640. NS a.root-servers.nil.
+dom4641. NS a.root-servers.nil.
+dom4642. NS a.root-servers.nil.
+dom4643. NS a.root-servers.nil.
+dom4644. NS a.root-servers.nil.
+dom4645. NS a.root-servers.nil.
+dom4646. NS a.root-servers.nil.
+dom4647. NS a.root-servers.nil.
+dom4648. NS a.root-servers.nil.
+dom4649. NS a.root-servers.nil.
+dom4650. NS a.root-servers.nil.
+dom4651. NS a.root-servers.nil.
+dom4652. NS a.root-servers.nil.
+dom4653. NS a.root-servers.nil.
+dom4654. NS a.root-servers.nil.
+dom4655. NS a.root-servers.nil.
+dom4656. NS a.root-servers.nil.
+dom4657. NS a.root-servers.nil.
+dom4658. NS a.root-servers.nil.
+dom4659. NS a.root-servers.nil.
+dom4660. NS a.root-servers.nil.
+dom4661. NS a.root-servers.nil.
+dom4662. NS a.root-servers.nil.
+dom4663. NS a.root-servers.nil.
+dom4664. NS a.root-servers.nil.
+dom4665. NS a.root-servers.nil.
+dom4666. NS a.root-servers.nil.
+dom4667. NS a.root-servers.nil.
+dom4668. NS a.root-servers.nil.
+dom4669. NS a.root-servers.nil.
+dom4670. NS a.root-servers.nil.
+dom4671. NS a.root-servers.nil.
+dom4672. NS a.root-servers.nil.
+dom4673. NS a.root-servers.nil.
+dom4674. NS a.root-servers.nil.
+dom4675. NS a.root-servers.nil.
+dom4676. NS a.root-servers.nil.
+dom4677. NS a.root-servers.nil.
+dom4678. NS a.root-servers.nil.
+dom4679. NS a.root-servers.nil.
+dom4680. NS a.root-servers.nil.
+dom4681. NS a.root-servers.nil.
+dom4682. NS a.root-servers.nil.
+dom4683. NS a.root-servers.nil.
+dom4684. NS a.root-servers.nil.
+dom4685. NS a.root-servers.nil.
+dom4686. NS a.root-servers.nil.
+dom4687. NS a.root-servers.nil.
+dom4688. NS a.root-servers.nil.
+dom4689. NS a.root-servers.nil.
+dom4690. NS a.root-servers.nil.
+dom4691. NS a.root-servers.nil.
+dom4692. NS a.root-servers.nil.
+dom4693. NS a.root-servers.nil.
+dom4694. NS a.root-servers.nil.
+dom4695. NS a.root-servers.nil.
+dom4696. NS a.root-servers.nil.
+dom4697. NS a.root-servers.nil.
+dom4698. NS a.root-servers.nil.
+dom4699. NS a.root-servers.nil.
+dom4700. NS a.root-servers.nil.
+dom4701. NS a.root-servers.nil.
+dom4702. NS a.root-servers.nil.
+dom4703. NS a.root-servers.nil.
+dom4704. NS a.root-servers.nil.
+dom4705. NS a.root-servers.nil.
+dom4706. NS a.root-servers.nil.
+dom4707. NS a.root-servers.nil.
+dom4708. NS a.root-servers.nil.
+dom4709. NS a.root-servers.nil.
+dom4710. NS a.root-servers.nil.
+dom4711. NS a.root-servers.nil.
+dom4712. NS a.root-servers.nil.
+dom4713. NS a.root-servers.nil.
+dom4714. NS a.root-servers.nil.
+dom4715. NS a.root-servers.nil.
+dom4716. NS a.root-servers.nil.
+dom4717. NS a.root-servers.nil.
+dom4718. NS a.root-servers.nil.
+dom4719. NS a.root-servers.nil.
+dom4720. NS a.root-servers.nil.
+dom4721. NS a.root-servers.nil.
+dom4722. NS a.root-servers.nil.
+dom4723. NS a.root-servers.nil.
+dom4724. NS a.root-servers.nil.
+dom4725. NS a.root-servers.nil.
+dom4726. NS a.root-servers.nil.
+dom4727. NS a.root-servers.nil.
+dom4728. NS a.root-servers.nil.
+dom4729. NS a.root-servers.nil.
+dom4730. NS a.root-servers.nil.
+dom4731. NS a.root-servers.nil.
+dom4732. NS a.root-servers.nil.
+dom4733. NS a.root-servers.nil.
+dom4734. NS a.root-servers.nil.
+dom4735. NS a.root-servers.nil.
+dom4736. NS a.root-servers.nil.
+dom4737. NS a.root-servers.nil.
+dom4738. NS a.root-servers.nil.
+dom4739. NS a.root-servers.nil.
+dom4740. NS a.root-servers.nil.
+dom4741. NS a.root-servers.nil.
+dom4742. NS a.root-servers.nil.
+dom4743. NS a.root-servers.nil.
+dom4744. NS a.root-servers.nil.
+dom4745. NS a.root-servers.nil.
+dom4746. NS a.root-servers.nil.
+dom4747. NS a.root-servers.nil.
+dom4748. NS a.root-servers.nil.
+dom4749. NS a.root-servers.nil.
+dom4750. NS a.root-servers.nil.
+dom4751. NS a.root-servers.nil.
+dom4752. NS a.root-servers.nil.
+dom4753. NS a.root-servers.nil.
+dom4754. NS a.root-servers.nil.
+dom4755. NS a.root-servers.nil.
+dom4756. NS a.root-servers.nil.
+dom4757. NS a.root-servers.nil.
+dom4758. NS a.root-servers.nil.
+dom4759. NS a.root-servers.nil.
+dom4760. NS a.root-servers.nil.
+dom4761. NS a.root-servers.nil.
+dom4762. NS a.root-servers.nil.
+dom4763. NS a.root-servers.nil.
+dom4764. NS a.root-servers.nil.
+dom4765. NS a.root-servers.nil.
+dom4766. NS a.root-servers.nil.
+dom4767. NS a.root-servers.nil.
+dom4768. NS a.root-servers.nil.
+dom4769. NS a.root-servers.nil.
+dom4770. NS a.root-servers.nil.
+dom4771. NS a.root-servers.nil.
+dom4772. NS a.root-servers.nil.
+dom4773. NS a.root-servers.nil.
+dom4774. NS a.root-servers.nil.
+dom4775. NS a.root-servers.nil.
+dom4776. NS a.root-servers.nil.
+dom4777. NS a.root-servers.nil.
+dom4778. NS a.root-servers.nil.
+dom4779. NS a.root-servers.nil.
+dom4780. NS a.root-servers.nil.
+dom4781. NS a.root-servers.nil.
+dom4782. NS a.root-servers.nil.
+dom4783. NS a.root-servers.nil.
+dom4784. NS a.root-servers.nil.
+dom4785. NS a.root-servers.nil.
+dom4786. NS a.root-servers.nil.
+dom4787. NS a.root-servers.nil.
+dom4788. NS a.root-servers.nil.
+dom4789. NS a.root-servers.nil.
+dom4790. NS a.root-servers.nil.
+dom4791. NS a.root-servers.nil.
+dom4792. NS a.root-servers.nil.
+dom4793. NS a.root-servers.nil.
+dom4794. NS a.root-servers.nil.
+dom4795. NS a.root-servers.nil.
+dom4796. NS a.root-servers.nil.
+dom4797. NS a.root-servers.nil.
+dom4798. NS a.root-servers.nil.
+dom4799. NS a.root-servers.nil.
+dom4800. NS a.root-servers.nil.
+dom4801. NS a.root-servers.nil.
+dom4802. NS a.root-servers.nil.
+dom4803. NS a.root-servers.nil.
+dom4804. NS a.root-servers.nil.
+dom4805. NS a.root-servers.nil.
+dom4806. NS a.root-servers.nil.
+dom4807. NS a.root-servers.nil.
+dom4808. NS a.root-servers.nil.
+dom4809. NS a.root-servers.nil.
+dom4810. NS a.root-servers.nil.
+dom4811. NS a.root-servers.nil.
+dom4812. NS a.root-servers.nil.
+dom4813. NS a.root-servers.nil.
+dom4814. NS a.root-servers.nil.
+dom4815. NS a.root-servers.nil.
+dom4816. NS a.root-servers.nil.
+dom4817. NS a.root-servers.nil.
+dom4818. NS a.root-servers.nil.
+dom4819. NS a.root-servers.nil.
+dom4820. NS a.root-servers.nil.
+dom4821. NS a.root-servers.nil.
+dom4822. NS a.root-servers.nil.
+dom4823. NS a.root-servers.nil.
+dom4824. NS a.root-servers.nil.
+dom4825. NS a.root-servers.nil.
+dom4826. NS a.root-servers.nil.
+dom4827. NS a.root-servers.nil.
+dom4828. NS a.root-servers.nil.
+dom4829. NS a.root-servers.nil.
+dom4830. NS a.root-servers.nil.
+dom4831. NS a.root-servers.nil.
+dom4832. NS a.root-servers.nil.
+dom4833. NS a.root-servers.nil.
+dom4834. NS a.root-servers.nil.
+dom4835. NS a.root-servers.nil.
+dom4836. NS a.root-servers.nil.
+dom4837. NS a.root-servers.nil.
+dom4838. NS a.root-servers.nil.
+dom4839. NS a.root-servers.nil.
+dom4840. NS a.root-servers.nil.
+dom4841. NS a.root-servers.nil.
+dom4842. NS a.root-servers.nil.
+dom4843. NS a.root-servers.nil.
+dom4844. NS a.root-servers.nil.
+dom4845. NS a.root-servers.nil.
+dom4846. NS a.root-servers.nil.
+dom4847. NS a.root-servers.nil.
+dom4848. NS a.root-servers.nil.
+dom4849. NS a.root-servers.nil.
+dom4850. NS a.root-servers.nil.
+dom4851. NS a.root-servers.nil.
+dom4852. NS a.root-servers.nil.
+dom4853. NS a.root-servers.nil.
+dom4854. NS a.root-servers.nil.
+dom4855. NS a.root-servers.nil.
+dom4856. NS a.root-servers.nil.
+dom4857. NS a.root-servers.nil.
+dom4858. NS a.root-servers.nil.
+dom4859. NS a.root-servers.nil.
+dom4860. NS a.root-servers.nil.
+dom4861. NS a.root-servers.nil.
+dom4862. NS a.root-servers.nil.
+dom4863. NS a.root-servers.nil.
+dom4864. NS a.root-servers.nil.
+dom4865. NS a.root-servers.nil.
+dom4866. NS a.root-servers.nil.
+dom4867. NS a.root-servers.nil.
+dom4868. NS a.root-servers.nil.
+dom4869. NS a.root-servers.nil.
+dom4870. NS a.root-servers.nil.
+dom4871. NS a.root-servers.nil.
+dom4872. NS a.root-servers.nil.
+dom4873. NS a.root-servers.nil.
+dom4874. NS a.root-servers.nil.
+dom4875. NS a.root-servers.nil.
+dom4876. NS a.root-servers.nil.
+dom4877. NS a.root-servers.nil.
+dom4878. NS a.root-servers.nil.
+dom4879. NS a.root-servers.nil.
+dom4880. NS a.root-servers.nil.
+dom4881. NS a.root-servers.nil.
+dom4882. NS a.root-servers.nil.
+dom4883. NS a.root-servers.nil.
+dom4884. NS a.root-servers.nil.
+dom4885. NS a.root-servers.nil.
+dom4886. NS a.root-servers.nil.
+dom4887. NS a.root-servers.nil.
+dom4888. NS a.root-servers.nil.
+dom4889. NS a.root-servers.nil.
+dom4890. NS a.root-servers.nil.
+dom4891. NS a.root-servers.nil.
+dom4892. NS a.root-servers.nil.
+dom4893. NS a.root-servers.nil.
+dom4894. NS a.root-servers.nil.
+dom4895. NS a.root-servers.nil.
+dom4896. NS a.root-servers.nil.
+dom4897. NS a.root-servers.nil.
+dom4898. NS a.root-servers.nil.
+dom4899. NS a.root-servers.nil.
+dom4900. NS a.root-servers.nil.
+dom4901. NS a.root-servers.nil.
+dom4902. NS a.root-servers.nil.
+dom4903. NS a.root-servers.nil.
+dom4904. NS a.root-servers.nil.
+dom4905. NS a.root-servers.nil.
+dom4906. NS a.root-servers.nil.
+dom4907. NS a.root-servers.nil.
+dom4908. NS a.root-servers.nil.
+dom4909. NS a.root-servers.nil.
+dom4910. NS a.root-servers.nil.
+dom4911. NS a.root-servers.nil.
+dom4912. NS a.root-servers.nil.
+dom4913. NS a.root-servers.nil.
+dom4914. NS a.root-servers.nil.
+dom4915. NS a.root-servers.nil.
+dom4916. NS a.root-servers.nil.
+dom4917. NS a.root-servers.nil.
+dom4918. NS a.root-servers.nil.
+dom4919. NS a.root-servers.nil.
+dom4920. NS a.root-servers.nil.
+dom4921. NS a.root-servers.nil.
+dom4922. NS a.root-servers.nil.
+dom4923. NS a.root-servers.nil.
+dom4924. NS a.root-servers.nil.
+dom4925. NS a.root-servers.nil.
+dom4926. NS a.root-servers.nil.
+dom4927. NS a.root-servers.nil.
+dom4928. NS a.root-servers.nil.
+dom4929. NS a.root-servers.nil.
+dom4930. NS a.root-servers.nil.
+dom4931. NS a.root-servers.nil.
+dom4932. NS a.root-servers.nil.
+dom4933. NS a.root-servers.nil.
+dom4934. NS a.root-servers.nil.
+dom4935. NS a.root-servers.nil.
+dom4936. NS a.root-servers.nil.
+dom4937. NS a.root-servers.nil.
+dom4938. NS a.root-servers.nil.
+dom4939. NS a.root-servers.nil.
+dom4940. NS a.root-servers.nil.
+dom4941. NS a.root-servers.nil.
+dom4942. NS a.root-servers.nil.
+dom4943. NS a.root-servers.nil.
+dom4944. NS a.root-servers.nil.
+dom4945. NS a.root-servers.nil.
+dom4946. NS a.root-servers.nil.
+dom4947. NS a.root-servers.nil.
+dom4948. NS a.root-servers.nil.
+dom4949. NS a.root-servers.nil.
+dom4950. NS a.root-servers.nil.
+dom4951. NS a.root-servers.nil.
+dom4952. NS a.root-servers.nil.
+dom4953. NS a.root-servers.nil.
+dom4954. NS a.root-servers.nil.
+dom4955. NS a.root-servers.nil.
+dom4956. NS a.root-servers.nil.
+dom4957. NS a.root-servers.nil.
+dom4958. NS a.root-servers.nil.
+dom4959. NS a.root-servers.nil.
+dom4960. NS a.root-servers.nil.
+dom4961. NS a.root-servers.nil.
+dom4962. NS a.root-servers.nil.
+dom4963. NS a.root-servers.nil.
+dom4964. NS a.root-servers.nil.
+dom4965. NS a.root-servers.nil.
+dom4966. NS a.root-servers.nil.
+dom4967. NS a.root-servers.nil.
+dom4968. NS a.root-servers.nil.
+dom4969. NS a.root-servers.nil.
+dom4970. NS a.root-servers.nil.
+dom4971. NS a.root-servers.nil.
+dom4972. NS a.root-servers.nil.
+dom4973. NS a.root-servers.nil.
+dom4974. NS a.root-servers.nil.
+dom4975. NS a.root-servers.nil.
+dom4976. NS a.root-servers.nil.
+dom4977. NS a.root-servers.nil.
+dom4978. NS a.root-servers.nil.
+dom4979. NS a.root-servers.nil.
+dom4980. NS a.root-servers.nil.
+dom4981. NS a.root-servers.nil.
+dom4982. NS a.root-servers.nil.
+dom4983. NS a.root-servers.nil.
+dom4984. NS a.root-servers.nil.
+dom4985. NS a.root-servers.nil.
+dom4986. NS a.root-servers.nil.
+dom4987. NS a.root-servers.nil.
+dom4988. NS a.root-servers.nil.
+dom4989. NS a.root-servers.nil.
+dom4990. NS a.root-servers.nil.
+dom4991. NS a.root-servers.nil.
+dom4992. NS a.root-servers.nil.
+dom4993. NS a.root-servers.nil.
+dom4994. NS a.root-servers.nil.
+dom4995. NS a.root-servers.nil.
+dom4996. NS a.root-servers.nil.
+dom4997. NS a.root-servers.nil.
+dom4998. NS a.root-servers.nil.
+dom4999. NS a.root-servers.nil.
+dom5000. NS a.root-servers.nil.
+dom5001. NS a.root-servers.nil.
+dom5002. NS a.root-servers.nil.
+dom5003. NS a.root-servers.nil.
+dom5004. NS a.root-servers.nil.
+dom5005. NS a.root-servers.nil.
+dom5006. NS a.root-servers.nil.
+dom5007. NS a.root-servers.nil.
+dom5008. NS a.root-servers.nil.
+dom5009. NS a.root-servers.nil.
+dom5010. NS a.root-servers.nil.
+dom5011. NS a.root-servers.nil.
+dom5012. NS a.root-servers.nil.
+dom5013. NS a.root-servers.nil.
+dom5014. NS a.root-servers.nil.
+dom5015. NS a.root-servers.nil.
+dom5016. NS a.root-servers.nil.
+dom5017. NS a.root-servers.nil.
+dom5018. NS a.root-servers.nil.
+dom5019. NS a.root-servers.nil.
+dom5020. NS a.root-servers.nil.
+dom5021. NS a.root-servers.nil.
+dom5022. NS a.root-servers.nil.
+dom5023. NS a.root-servers.nil.
+dom5024. NS a.root-servers.nil.
+dom5025. NS a.root-servers.nil.
+dom5026. NS a.root-servers.nil.
+dom5027. NS a.root-servers.nil.
+dom5028. NS a.root-servers.nil.
+dom5029. NS a.root-servers.nil.
+dom5030. NS a.root-servers.nil.
+dom5031. NS a.root-servers.nil.
+dom5032. NS a.root-servers.nil.
+dom5033. NS a.root-servers.nil.
+dom5034. NS a.root-servers.nil.
+dom5035. NS a.root-servers.nil.
+dom5036. NS a.root-servers.nil.
+dom5037. NS a.root-servers.nil.
+dom5038. NS a.root-servers.nil.
+dom5039. NS a.root-servers.nil.
+dom5040. NS a.root-servers.nil.
+dom5041. NS a.root-servers.nil.
+dom5042. NS a.root-servers.nil.
+dom5043. NS a.root-servers.nil.
+dom5044. NS a.root-servers.nil.
+dom5045. NS a.root-servers.nil.
+dom5046. NS a.root-servers.nil.
+dom5047. NS a.root-servers.nil.
+dom5048. NS a.root-servers.nil.
+dom5049. NS a.root-servers.nil.
+dom5050. NS a.root-servers.nil.
+dom5051. NS a.root-servers.nil.
+dom5052. NS a.root-servers.nil.
+dom5053. NS a.root-servers.nil.
+dom5054. NS a.root-servers.nil.
+dom5055. NS a.root-servers.nil.
+dom5056. NS a.root-servers.nil.
+dom5057. NS a.root-servers.nil.
+dom5058. NS a.root-servers.nil.
+dom5059. NS a.root-servers.nil.
+dom5060. NS a.root-servers.nil.
+dom5061. NS a.root-servers.nil.
+dom5062. NS a.root-servers.nil.
+dom5063. NS a.root-servers.nil.
+dom5064. NS a.root-servers.nil.
+dom5065. NS a.root-servers.nil.
+dom5066. NS a.root-servers.nil.
+dom5067. NS a.root-servers.nil.
+dom5068. NS a.root-servers.nil.
+dom5069. NS a.root-servers.nil.
+dom5070. NS a.root-servers.nil.
+dom5071. NS a.root-servers.nil.
+dom5072. NS a.root-servers.nil.
+dom5073. NS a.root-servers.nil.
+dom5074. NS a.root-servers.nil.
+dom5075. NS a.root-servers.nil.
+dom5076. NS a.root-servers.nil.
+dom5077. NS a.root-servers.nil.
+dom5078. NS a.root-servers.nil.
+dom5079. NS a.root-servers.nil.
+dom5080. NS a.root-servers.nil.
+dom5081. NS a.root-servers.nil.
+dom5082. NS a.root-servers.nil.
+dom5083. NS a.root-servers.nil.
+dom5084. NS a.root-servers.nil.
+dom5085. NS a.root-servers.nil.
+dom5086. NS a.root-servers.nil.
+dom5087. NS a.root-servers.nil.
+dom5088. NS a.root-servers.nil.
+dom5089. NS a.root-servers.nil.
+dom5090. NS a.root-servers.nil.
+dom5091. NS a.root-servers.nil.
+dom5092. NS a.root-servers.nil.
+dom5093. NS a.root-servers.nil.
+dom5094. NS a.root-servers.nil.
+dom5095. NS a.root-servers.nil.
+dom5096. NS a.root-servers.nil.
+dom5097. NS a.root-servers.nil.
+dom5098. NS a.root-servers.nil.
+dom5099. NS a.root-servers.nil.
+dom5100. NS a.root-servers.nil.
+dom5101. NS a.root-servers.nil.
+dom5102. NS a.root-servers.nil.
+dom5103. NS a.root-servers.nil.
+dom5104. NS a.root-servers.nil.
+dom5105. NS a.root-servers.nil.
+dom5106. NS a.root-servers.nil.
+dom5107. NS a.root-servers.nil.
+dom5108. NS a.root-servers.nil.
+dom5109. NS a.root-servers.nil.
+dom5110. NS a.root-servers.nil.
+dom5111. NS a.root-servers.nil.
+dom5112. NS a.root-servers.nil.
+dom5113. NS a.root-servers.nil.
+dom5114. NS a.root-servers.nil.
+dom5115. NS a.root-servers.nil.
+dom5116. NS a.root-servers.nil.
+dom5117. NS a.root-servers.nil.
+dom5118. NS a.root-servers.nil.
+dom5119. NS a.root-servers.nil.
+dom5120. NS a.root-servers.nil.
+dom5121. NS a.root-servers.nil.
+dom5122. NS a.root-servers.nil.
+dom5123. NS a.root-servers.nil.
+dom5124. NS a.root-servers.nil.
+dom5125. NS a.root-servers.nil.
+dom5126. NS a.root-servers.nil.
+dom5127. NS a.root-servers.nil.
+dom5128. NS a.root-servers.nil.
+dom5129. NS a.root-servers.nil.
+dom5130. NS a.root-servers.nil.
+dom5131. NS a.root-servers.nil.
+dom5132. NS a.root-servers.nil.
+dom5133. NS a.root-servers.nil.
+dom5134. NS a.root-servers.nil.
+dom5135. NS a.root-servers.nil.
+dom5136. NS a.root-servers.nil.
+dom5137. NS a.root-servers.nil.
+dom5138. NS a.root-servers.nil.
+dom5139. NS a.root-servers.nil.
+dom5140. NS a.root-servers.nil.
+dom5141. NS a.root-servers.nil.
+dom5142. NS a.root-servers.nil.
+dom5143. NS a.root-servers.nil.
+dom5144. NS a.root-servers.nil.
+dom5145. NS a.root-servers.nil.
+dom5146. NS a.root-servers.nil.
+dom5147. NS a.root-servers.nil.
+dom5148. NS a.root-servers.nil.
+dom5149. NS a.root-servers.nil.
+dom5150. NS a.root-servers.nil.
+dom5151. NS a.root-servers.nil.
+dom5152. NS a.root-servers.nil.
+dom5153. NS a.root-servers.nil.
+dom5154. NS a.root-servers.nil.
+dom5155. NS a.root-servers.nil.
+dom5156. NS a.root-servers.nil.
+dom5157. NS a.root-servers.nil.
+dom5158. NS a.root-servers.nil.
+dom5159. NS a.root-servers.nil.
+dom5160. NS a.root-servers.nil.
+dom5161. NS a.root-servers.nil.
+dom5162. NS a.root-servers.nil.
+dom5163. NS a.root-servers.nil.
+dom5164. NS a.root-servers.nil.
+dom5165. NS a.root-servers.nil.
+dom5166. NS a.root-servers.nil.
+dom5167. NS a.root-servers.nil.
+dom5168. NS a.root-servers.nil.
+dom5169. NS a.root-servers.nil.
+dom5170. NS a.root-servers.nil.
+dom5171. NS a.root-servers.nil.
+dom5172. NS a.root-servers.nil.
+dom5173. NS a.root-servers.nil.
+dom5174. NS a.root-servers.nil.
+dom5175. NS a.root-servers.nil.
+dom5176. NS a.root-servers.nil.
+dom5177. NS a.root-servers.nil.
+dom5178. NS a.root-servers.nil.
+dom5179. NS a.root-servers.nil.
+dom5180. NS a.root-servers.nil.
+dom5181. NS a.root-servers.nil.
+dom5182. NS a.root-servers.nil.
+dom5183. NS a.root-servers.nil.
+dom5184. NS a.root-servers.nil.
+dom5185. NS a.root-servers.nil.
+dom5186. NS a.root-servers.nil.
+dom5187. NS a.root-servers.nil.
+dom5188. NS a.root-servers.nil.
+dom5189. NS a.root-servers.nil.
+dom5190. NS a.root-servers.nil.
+dom5191. NS a.root-servers.nil.
+dom5192. NS a.root-servers.nil.
+dom5193. NS a.root-servers.nil.
+dom5194. NS a.root-servers.nil.
+dom5195. NS a.root-servers.nil.
+dom5196. NS a.root-servers.nil.
+dom5197. NS a.root-servers.nil.
+dom5198. NS a.root-servers.nil.
+dom5199. NS a.root-servers.nil.
+dom5200. NS a.root-servers.nil.
+dom5201. NS a.root-servers.nil.
+dom5202. NS a.root-servers.nil.
+dom5203. NS a.root-servers.nil.
+dom5204. NS a.root-servers.nil.
+dom5205. NS a.root-servers.nil.
+dom5206. NS a.root-servers.nil.
+dom5207. NS a.root-servers.nil.
+dom5208. NS a.root-servers.nil.
+dom5209. NS a.root-servers.nil.
+dom5210. NS a.root-servers.nil.
+dom5211. NS a.root-servers.nil.
+dom5212. NS a.root-servers.nil.
+dom5213. NS a.root-servers.nil.
+dom5214. NS a.root-servers.nil.
+dom5215. NS a.root-servers.nil.
+dom5216. NS a.root-servers.nil.
+dom5217. NS a.root-servers.nil.
+dom5218. NS a.root-servers.nil.
+dom5219. NS a.root-servers.nil.
+dom5220. NS a.root-servers.nil.
+dom5221. NS a.root-servers.nil.
+dom5222. NS a.root-servers.nil.
+dom5223. NS a.root-servers.nil.
+dom5224. NS a.root-servers.nil.
+dom5225. NS a.root-servers.nil.
+dom5226. NS a.root-servers.nil.
+dom5227. NS a.root-servers.nil.
+dom5228. NS a.root-servers.nil.
+dom5229. NS a.root-servers.nil.
+dom5230. NS a.root-servers.nil.
+dom5231. NS a.root-servers.nil.
+dom5232. NS a.root-servers.nil.
+dom5233. NS a.root-servers.nil.
+dom5234. NS a.root-servers.nil.
+dom5235. NS a.root-servers.nil.
+dom5236. NS a.root-servers.nil.
+dom5237. NS a.root-servers.nil.
+dom5238. NS a.root-servers.nil.
+dom5239. NS a.root-servers.nil.
+dom5240. NS a.root-servers.nil.
+dom5241. NS a.root-servers.nil.
+dom5242. NS a.root-servers.nil.
+dom5243. NS a.root-servers.nil.
+dom5244. NS a.root-servers.nil.
+dom5245. NS a.root-servers.nil.
+dom5246. NS a.root-servers.nil.
+dom5247. NS a.root-servers.nil.
+dom5248. NS a.root-servers.nil.
+dom5249. NS a.root-servers.nil.
+dom5250. NS a.root-servers.nil.
+dom5251. NS a.root-servers.nil.
+dom5252. NS a.root-servers.nil.
+dom5253. NS a.root-servers.nil.
+dom5254. NS a.root-servers.nil.
+dom5255. NS a.root-servers.nil.
+dom5256. NS a.root-servers.nil.
+dom5257. NS a.root-servers.nil.
+dom5258. NS a.root-servers.nil.
+dom5259. NS a.root-servers.nil.
+dom5260. NS a.root-servers.nil.
+dom5261. NS a.root-servers.nil.
+dom5262. NS a.root-servers.nil.
+dom5263. NS a.root-servers.nil.
+dom5264. NS a.root-servers.nil.
+dom5265. NS a.root-servers.nil.
+dom5266. NS a.root-servers.nil.
+dom5267. NS a.root-servers.nil.
+dom5268. NS a.root-servers.nil.
+dom5269. NS a.root-servers.nil.
+dom5270. NS a.root-servers.nil.
+dom5271. NS a.root-servers.nil.
+dom5272. NS a.root-servers.nil.
+dom5273. NS a.root-servers.nil.
+dom5274. NS a.root-servers.nil.
+dom5275. NS a.root-servers.nil.
+dom5276. NS a.root-servers.nil.
+dom5277. NS a.root-servers.nil.
+dom5278. NS a.root-servers.nil.
+dom5279. NS a.root-servers.nil.
+dom5280. NS a.root-servers.nil.
+dom5281. NS a.root-servers.nil.
+dom5282. NS a.root-servers.nil.
+dom5283. NS a.root-servers.nil.
+dom5284. NS a.root-servers.nil.
+dom5285. NS a.root-servers.nil.
+dom5286. NS a.root-servers.nil.
+dom5287. NS a.root-servers.nil.
+dom5288. NS a.root-servers.nil.
+dom5289. NS a.root-servers.nil.
+dom5290. NS a.root-servers.nil.
+dom5291. NS a.root-servers.nil.
+dom5292. NS a.root-servers.nil.
+dom5293. NS a.root-servers.nil.
+dom5294. NS a.root-servers.nil.
+dom5295. NS a.root-servers.nil.
+dom5296. NS a.root-servers.nil.
+dom5297. NS a.root-servers.nil.
+dom5298. NS a.root-servers.nil.
+dom5299. NS a.root-servers.nil.
+dom5300. NS a.root-servers.nil.
+dom5301. NS a.root-servers.nil.
+dom5302. NS a.root-servers.nil.
+dom5303. NS a.root-servers.nil.
+dom5304. NS a.root-servers.nil.
+dom5305. NS a.root-servers.nil.
+dom5306. NS a.root-servers.nil.
+dom5307. NS a.root-servers.nil.
+dom5308. NS a.root-servers.nil.
+dom5309. NS a.root-servers.nil.
+dom5310. NS a.root-servers.nil.
+dom5311. NS a.root-servers.nil.
+dom5312. NS a.root-servers.nil.
+dom5313. NS a.root-servers.nil.
+dom5314. NS a.root-servers.nil.
+dom5315. NS a.root-servers.nil.
+dom5316. NS a.root-servers.nil.
+dom5317. NS a.root-servers.nil.
+dom5318. NS a.root-servers.nil.
+dom5319. NS a.root-servers.nil.
+dom5320. NS a.root-servers.nil.
+dom5321. NS a.root-servers.nil.
+dom5322. NS a.root-servers.nil.
+dom5323. NS a.root-servers.nil.
+dom5324. NS a.root-servers.nil.
+dom5325. NS a.root-servers.nil.
+dom5326. NS a.root-servers.nil.
+dom5327. NS a.root-servers.nil.
+dom5328. NS a.root-servers.nil.
+dom5329. NS a.root-servers.nil.
+dom5330. NS a.root-servers.nil.
+dom5331. NS a.root-servers.nil.
+dom5332. NS a.root-servers.nil.
+dom5333. NS a.root-servers.nil.
+dom5334. NS a.root-servers.nil.
+dom5335. NS a.root-servers.nil.
+dom5336. NS a.root-servers.nil.
+dom5337. NS a.root-servers.nil.
+dom5338. NS a.root-servers.nil.
+dom5339. NS a.root-servers.nil.
+dom5340. NS a.root-servers.nil.
+dom5341. NS a.root-servers.nil.
+dom5342. NS a.root-servers.nil.
+dom5343. NS a.root-servers.nil.
+dom5344. NS a.root-servers.nil.
+dom5345. NS a.root-servers.nil.
+dom5346. NS a.root-servers.nil.
+dom5347. NS a.root-servers.nil.
+dom5348. NS a.root-servers.nil.
+dom5349. NS a.root-servers.nil.
+dom5350. NS a.root-servers.nil.
+dom5351. NS a.root-servers.nil.
+dom5352. NS a.root-servers.nil.
+dom5353. NS a.root-servers.nil.
+dom5354. NS a.root-servers.nil.
+dom5355. NS a.root-servers.nil.
+dom5356. NS a.root-servers.nil.
+dom5357. NS a.root-servers.nil.
+dom5358. NS a.root-servers.nil.
+dom5359. NS a.root-servers.nil.
+dom5360. NS a.root-servers.nil.
+dom5361. NS a.root-servers.nil.
+dom5362. NS a.root-servers.nil.
+dom5363. NS a.root-servers.nil.
+dom5364. NS a.root-servers.nil.
+dom5365. NS a.root-servers.nil.
+dom5366. NS a.root-servers.nil.
+dom5367. NS a.root-servers.nil.
+dom5368. NS a.root-servers.nil.
+dom5369. NS a.root-servers.nil.
+dom5370. NS a.root-servers.nil.
+dom5371. NS a.root-servers.nil.
+dom5372. NS a.root-servers.nil.
+dom5373. NS a.root-servers.nil.
+dom5374. NS a.root-servers.nil.
+dom5375. NS a.root-servers.nil.
+dom5376. NS a.root-servers.nil.
+dom5377. NS a.root-servers.nil.
+dom5378. NS a.root-servers.nil.
+dom5379. NS a.root-servers.nil.
+dom5380. NS a.root-servers.nil.
+dom5381. NS a.root-servers.nil.
+dom5382. NS a.root-servers.nil.
+dom5383. NS a.root-servers.nil.
+dom5384. NS a.root-servers.nil.
+dom5385. NS a.root-servers.nil.
+dom5386. NS a.root-servers.nil.
+dom5387. NS a.root-servers.nil.
+dom5388. NS a.root-servers.nil.
+dom5389. NS a.root-servers.nil.
+dom5390. NS a.root-servers.nil.
+dom5391. NS a.root-servers.nil.
+dom5392. NS a.root-servers.nil.
+dom5393. NS a.root-servers.nil.
+dom5394. NS a.root-servers.nil.
+dom5395. NS a.root-servers.nil.
+dom5396. NS a.root-servers.nil.
+dom5397. NS a.root-servers.nil.
+dom5398. NS a.root-servers.nil.
+dom5399. NS a.root-servers.nil.
+dom5400. NS a.root-servers.nil.
+dom5401. NS a.root-servers.nil.
+dom5402. NS a.root-servers.nil.
+dom5403. NS a.root-servers.nil.
+dom5404. NS a.root-servers.nil.
+dom5405. NS a.root-servers.nil.
+dom5406. NS a.root-servers.nil.
+dom5407. NS a.root-servers.nil.
+dom5408. NS a.root-servers.nil.
+dom5409. NS a.root-servers.nil.
+dom5410. NS a.root-servers.nil.
+dom5411. NS a.root-servers.nil.
+dom5412. NS a.root-servers.nil.
+dom5413. NS a.root-servers.nil.
+dom5414. NS a.root-servers.nil.
+dom5415. NS a.root-servers.nil.
+dom5416. NS a.root-servers.nil.
+dom5417. NS a.root-servers.nil.
+dom5418. NS a.root-servers.nil.
+dom5419. NS a.root-servers.nil.
+dom5420. NS a.root-servers.nil.
+dom5421. NS a.root-servers.nil.
+dom5422. NS a.root-servers.nil.
+dom5423. NS a.root-servers.nil.
+dom5424. NS a.root-servers.nil.
+dom5425. NS a.root-servers.nil.
+dom5426. NS a.root-servers.nil.
+dom5427. NS a.root-servers.nil.
+dom5428. NS a.root-servers.nil.
+dom5429. NS a.root-servers.nil.
+dom5430. NS a.root-servers.nil.
+dom5431. NS a.root-servers.nil.
+dom5432. NS a.root-servers.nil.
+dom5433. NS a.root-servers.nil.
+dom5434. NS a.root-servers.nil.
+dom5435. NS a.root-servers.nil.
+dom5436. NS a.root-servers.nil.
+dom5437. NS a.root-servers.nil.
+dom5438. NS a.root-servers.nil.
+dom5439. NS a.root-servers.nil.
+dom5440. NS a.root-servers.nil.
+dom5441. NS a.root-servers.nil.
+dom5442. NS a.root-servers.nil.
+dom5443. NS a.root-servers.nil.
+dom5444. NS a.root-servers.nil.
+dom5445. NS a.root-servers.nil.
+dom5446. NS a.root-servers.nil.
+dom5447. NS a.root-servers.nil.
+dom5448. NS a.root-servers.nil.
+dom5449. NS a.root-servers.nil.
+dom5450. NS a.root-servers.nil.
+dom5451. NS a.root-servers.nil.
+dom5452. NS a.root-servers.nil.
+dom5453. NS a.root-servers.nil.
+dom5454. NS a.root-servers.nil.
+dom5455. NS a.root-servers.nil.
+dom5456. NS a.root-servers.nil.
+dom5457. NS a.root-servers.nil.
+dom5458. NS a.root-servers.nil.
+dom5459. NS a.root-servers.nil.
+dom5460. NS a.root-servers.nil.
+dom5461. NS a.root-servers.nil.
+dom5462. NS a.root-servers.nil.
+dom5463. NS a.root-servers.nil.
+dom5464. NS a.root-servers.nil.
+dom5465. NS a.root-servers.nil.
+dom5466. NS a.root-servers.nil.
+dom5467. NS a.root-servers.nil.
+dom5468. NS a.root-servers.nil.
+dom5469. NS a.root-servers.nil.
+dom5470. NS a.root-servers.nil.
+dom5471. NS a.root-servers.nil.
+dom5472. NS a.root-servers.nil.
+dom5473. NS a.root-servers.nil.
+dom5474. NS a.root-servers.nil.
+dom5475. NS a.root-servers.nil.
+dom5476. NS a.root-servers.nil.
+dom5477. NS a.root-servers.nil.
+dom5478. NS a.root-servers.nil.
+dom5479. NS a.root-servers.nil.
+dom5480. NS a.root-servers.nil.
+dom5481. NS a.root-servers.nil.
+dom5482. NS a.root-servers.nil.
+dom5483. NS a.root-servers.nil.
+dom5484. NS a.root-servers.nil.
+dom5485. NS a.root-servers.nil.
+dom5486. NS a.root-servers.nil.
+dom5487. NS a.root-servers.nil.
+dom5488. NS a.root-servers.nil.
+dom5489. NS a.root-servers.nil.
+dom5490. NS a.root-servers.nil.
+dom5491. NS a.root-servers.nil.
+dom5492. NS a.root-servers.nil.
+dom5493. NS a.root-servers.nil.
+dom5494. NS a.root-servers.nil.
+dom5495. NS a.root-servers.nil.
+dom5496. NS a.root-servers.nil.
+dom5497. NS a.root-servers.nil.
+dom5498. NS a.root-servers.nil.
+dom5499. NS a.root-servers.nil.
+dom5500. NS a.root-servers.nil.
+dom5501. NS a.root-servers.nil.
+dom5502. NS a.root-servers.nil.
+dom5503. NS a.root-servers.nil.
+dom5504. NS a.root-servers.nil.
+dom5505. NS a.root-servers.nil.
+dom5506. NS a.root-servers.nil.
+dom5507. NS a.root-servers.nil.
+dom5508. NS a.root-servers.nil.
+dom5509. NS a.root-servers.nil.
+dom5510. NS a.root-servers.nil.
+dom5511. NS a.root-servers.nil.
+dom5512. NS a.root-servers.nil.
+dom5513. NS a.root-servers.nil.
+dom5514. NS a.root-servers.nil.
+dom5515. NS a.root-servers.nil.
+dom5516. NS a.root-servers.nil.
+dom5517. NS a.root-servers.nil.
+dom5518. NS a.root-servers.nil.
+dom5519. NS a.root-servers.nil.
+dom5520. NS a.root-servers.nil.
+dom5521. NS a.root-servers.nil.
+dom5522. NS a.root-servers.nil.
+dom5523. NS a.root-servers.nil.
+dom5524. NS a.root-servers.nil.
+dom5525. NS a.root-servers.nil.
+dom5526. NS a.root-servers.nil.
+dom5527. NS a.root-servers.nil.
+dom5528. NS a.root-servers.nil.
+dom5529. NS a.root-servers.nil.
+dom5530. NS a.root-servers.nil.
+dom5531. NS a.root-servers.nil.
+dom5532. NS a.root-servers.nil.
+dom5533. NS a.root-servers.nil.
+dom5534. NS a.root-servers.nil.
+dom5535. NS a.root-servers.nil.
+dom5536. NS a.root-servers.nil.
+dom5537. NS a.root-servers.nil.
+dom5538. NS a.root-servers.nil.
+dom5539. NS a.root-servers.nil.
+dom5540. NS a.root-servers.nil.
+dom5541. NS a.root-servers.nil.
+dom5542. NS a.root-servers.nil.
+dom5543. NS a.root-servers.nil.
+dom5544. NS a.root-servers.nil.
+dom5545. NS a.root-servers.nil.
+dom5546. NS a.root-servers.nil.
+dom5547. NS a.root-servers.nil.
+dom5548. NS a.root-servers.nil.
+dom5549. NS a.root-servers.nil.
+dom5550. NS a.root-servers.nil.
+dom5551. NS a.root-servers.nil.
+dom5552. NS a.root-servers.nil.
+dom5553. NS a.root-servers.nil.
+dom5554. NS a.root-servers.nil.
+dom5555. NS a.root-servers.nil.
+dom5556. NS a.root-servers.nil.
+dom5557. NS a.root-servers.nil.
+dom5558. NS a.root-servers.nil.
+dom5559. NS a.root-servers.nil.
+dom5560. NS a.root-servers.nil.
+dom5561. NS a.root-servers.nil.
+dom5562. NS a.root-servers.nil.
+dom5563. NS a.root-servers.nil.
+dom5564. NS a.root-servers.nil.
+dom5565. NS a.root-servers.nil.
+dom5566. NS a.root-servers.nil.
+dom5567. NS a.root-servers.nil.
+dom5568. NS a.root-servers.nil.
+dom5569. NS a.root-servers.nil.
+dom5570. NS a.root-servers.nil.
+dom5571. NS a.root-servers.nil.
+dom5572. NS a.root-servers.nil.
+dom5573. NS a.root-servers.nil.
+dom5574. NS a.root-servers.nil.
+dom5575. NS a.root-servers.nil.
+dom5576. NS a.root-servers.nil.
+dom5577. NS a.root-servers.nil.
+dom5578. NS a.root-servers.nil.
+dom5579. NS a.root-servers.nil.
+dom5580. NS a.root-servers.nil.
+dom5581. NS a.root-servers.nil.
+dom5582. NS a.root-servers.nil.
+dom5583. NS a.root-servers.nil.
+dom5584. NS a.root-servers.nil.
+dom5585. NS a.root-servers.nil.
+dom5586. NS a.root-servers.nil.
+dom5587. NS a.root-servers.nil.
+dom5588. NS a.root-servers.nil.
+dom5589. NS a.root-servers.nil.
+dom5590. NS a.root-servers.nil.
+dom5591. NS a.root-servers.nil.
+dom5592. NS a.root-servers.nil.
+dom5593. NS a.root-servers.nil.
+dom5594. NS a.root-servers.nil.
+dom5595. NS a.root-servers.nil.
+dom5596. NS a.root-servers.nil.
+dom5597. NS a.root-servers.nil.
+dom5598. NS a.root-servers.nil.
+dom5599. NS a.root-servers.nil.
+dom5600. NS a.root-servers.nil.
+dom5601. NS a.root-servers.nil.
+dom5602. NS a.root-servers.nil.
+dom5603. NS a.root-servers.nil.
+dom5604. NS a.root-servers.nil.
+dom5605. NS a.root-servers.nil.
+dom5606. NS a.root-servers.nil.
+dom5607. NS a.root-servers.nil.
+dom5608. NS a.root-servers.nil.
+dom5609. NS a.root-servers.nil.
+dom5610. NS a.root-servers.nil.
+dom5611. NS a.root-servers.nil.
+dom5612. NS a.root-servers.nil.
+dom5613. NS a.root-servers.nil.
+dom5614. NS a.root-servers.nil.
+dom5615. NS a.root-servers.nil.
+dom5616. NS a.root-servers.nil.
+dom5617. NS a.root-servers.nil.
+dom5618. NS a.root-servers.nil.
+dom5619. NS a.root-servers.nil.
+dom5620. NS a.root-servers.nil.
+dom5621. NS a.root-servers.nil.
+dom5622. NS a.root-servers.nil.
+dom5623. NS a.root-servers.nil.
+dom5624. NS a.root-servers.nil.
+dom5625. NS a.root-servers.nil.
+dom5626. NS a.root-servers.nil.
+dom5627. NS a.root-servers.nil.
+dom5628. NS a.root-servers.nil.
+dom5629. NS a.root-servers.nil.
+dom5630. NS a.root-servers.nil.
+dom5631. NS a.root-servers.nil.
+dom5632. NS a.root-servers.nil.
+dom5633. NS a.root-servers.nil.
+dom5634. NS a.root-servers.nil.
+dom5635. NS a.root-servers.nil.
+dom5636. NS a.root-servers.nil.
+dom5637. NS a.root-servers.nil.
+dom5638. NS a.root-servers.nil.
+dom5639. NS a.root-servers.nil.
+dom5640. NS a.root-servers.nil.
+dom5641. NS a.root-servers.nil.
+dom5642. NS a.root-servers.nil.
+dom5643. NS a.root-servers.nil.
+dom5644. NS a.root-servers.nil.
+dom5645. NS a.root-servers.nil.
+dom5646. NS a.root-servers.nil.
+dom5647. NS a.root-servers.nil.
+dom5648. NS a.root-servers.nil.
+dom5649. NS a.root-servers.nil.
+dom5650. NS a.root-servers.nil.
+dom5651. NS a.root-servers.nil.
+dom5652. NS a.root-servers.nil.
+dom5653. NS a.root-servers.nil.
+dom5654. NS a.root-servers.nil.
+dom5655. NS a.root-servers.nil.
+dom5656. NS a.root-servers.nil.
+dom5657. NS a.root-servers.nil.
+dom5658. NS a.root-servers.nil.
+dom5659. NS a.root-servers.nil.
+dom5660. NS a.root-servers.nil.
+dom5661. NS a.root-servers.nil.
+dom5662. NS a.root-servers.nil.
+dom5663. NS a.root-servers.nil.
+dom5664. NS a.root-servers.nil.
+dom5665. NS a.root-servers.nil.
+dom5666. NS a.root-servers.nil.
+dom5667. NS a.root-servers.nil.
+dom5668. NS a.root-servers.nil.
+dom5669. NS a.root-servers.nil.
+dom5670. NS a.root-servers.nil.
+dom5671. NS a.root-servers.nil.
+dom5672. NS a.root-servers.nil.
+dom5673. NS a.root-servers.nil.
+dom5674. NS a.root-servers.nil.
+dom5675. NS a.root-servers.nil.
+dom5676. NS a.root-servers.nil.
+dom5677. NS a.root-servers.nil.
+dom5678. NS a.root-servers.nil.
+dom5679. NS a.root-servers.nil.
+dom5680. NS a.root-servers.nil.
+dom5681. NS a.root-servers.nil.
+dom5682. NS a.root-servers.nil.
+dom5683. NS a.root-servers.nil.
+dom5684. NS a.root-servers.nil.
+dom5685. NS a.root-servers.nil.
+dom5686. NS a.root-servers.nil.
+dom5687. NS a.root-servers.nil.
+dom5688. NS a.root-servers.nil.
+dom5689. NS a.root-servers.nil.
+dom5690. NS a.root-servers.nil.
+dom5691. NS a.root-servers.nil.
+dom5692. NS a.root-servers.nil.
+dom5693. NS a.root-servers.nil.
+dom5694. NS a.root-servers.nil.
+dom5695. NS a.root-servers.nil.
+dom5696. NS a.root-servers.nil.
+dom5697. NS a.root-servers.nil.
+dom5698. NS a.root-servers.nil.
+dom5699. NS a.root-servers.nil.
+dom5700. NS a.root-servers.nil.
+dom5701. NS a.root-servers.nil.
+dom5702. NS a.root-servers.nil.
+dom5703. NS a.root-servers.nil.
+dom5704. NS a.root-servers.nil.
+dom5705. NS a.root-servers.nil.
+dom5706. NS a.root-servers.nil.
+dom5707. NS a.root-servers.nil.
+dom5708. NS a.root-servers.nil.
+dom5709. NS a.root-servers.nil.
+dom5710. NS a.root-servers.nil.
+dom5711. NS a.root-servers.nil.
+dom5712. NS a.root-servers.nil.
+dom5713. NS a.root-servers.nil.
+dom5714. NS a.root-servers.nil.
+dom5715. NS a.root-servers.nil.
+dom5716. NS a.root-servers.nil.
+dom5717. NS a.root-servers.nil.
+dom5718. NS a.root-servers.nil.
+dom5719. NS a.root-servers.nil.
+dom5720. NS a.root-servers.nil.
+dom5721. NS a.root-servers.nil.
+dom5722. NS a.root-servers.nil.
+dom5723. NS a.root-servers.nil.
+dom5724. NS a.root-servers.nil.
+dom5725. NS a.root-servers.nil.
+dom5726. NS a.root-servers.nil.
+dom5727. NS a.root-servers.nil.
+dom5728. NS a.root-servers.nil.
+dom5729. NS a.root-servers.nil.
+dom5730. NS a.root-servers.nil.
+dom5731. NS a.root-servers.nil.
+dom5732. NS a.root-servers.nil.
+dom5733. NS a.root-servers.nil.
+dom5734. NS a.root-servers.nil.
+dom5735. NS a.root-servers.nil.
+dom5736. NS a.root-servers.nil.
+dom5737. NS a.root-servers.nil.
+dom5738. NS a.root-servers.nil.
+dom5739. NS a.root-servers.nil.
+dom5740. NS a.root-servers.nil.
+dom5741. NS a.root-servers.nil.
+dom5742. NS a.root-servers.nil.
+dom5743. NS a.root-servers.nil.
+dom5744. NS a.root-servers.nil.
+dom5745. NS a.root-servers.nil.
+dom5746. NS a.root-servers.nil.
+dom5747. NS a.root-servers.nil.
+dom5748. NS a.root-servers.nil.
+dom5749. NS a.root-servers.nil.
+dom5750. NS a.root-servers.nil.
+dom5751. NS a.root-servers.nil.
+dom5752. NS a.root-servers.nil.
+dom5753. NS a.root-servers.nil.
+dom5754. NS a.root-servers.nil.
+dom5755. NS a.root-servers.nil.
+dom5756. NS a.root-servers.nil.
+dom5757. NS a.root-servers.nil.
+dom5758. NS a.root-servers.nil.
+dom5759. NS a.root-servers.nil.
+dom5760. NS a.root-servers.nil.
+dom5761. NS a.root-servers.nil.
+dom5762. NS a.root-servers.nil.
+dom5763. NS a.root-servers.nil.
+dom5764. NS a.root-servers.nil.
+dom5765. NS a.root-servers.nil.
+dom5766. NS a.root-servers.nil.
+dom5767. NS a.root-servers.nil.
+dom5768. NS a.root-servers.nil.
+dom5769. NS a.root-servers.nil.
+dom5770. NS a.root-servers.nil.
+dom5771. NS a.root-servers.nil.
+dom5772. NS a.root-servers.nil.
+dom5773. NS a.root-servers.nil.
+dom5774. NS a.root-servers.nil.
+dom5775. NS a.root-servers.nil.
+dom5776. NS a.root-servers.nil.
+dom5777. NS a.root-servers.nil.
+dom5778. NS a.root-servers.nil.
+dom5779. NS a.root-servers.nil.
+dom5780. NS a.root-servers.nil.
+dom5781. NS a.root-servers.nil.
+dom5782. NS a.root-servers.nil.
+dom5783. NS a.root-servers.nil.
+dom5784. NS a.root-servers.nil.
+dom5785. NS a.root-servers.nil.
+dom5786. NS a.root-servers.nil.
+dom5787. NS a.root-servers.nil.
+dom5788. NS a.root-servers.nil.
+dom5789. NS a.root-servers.nil.
+dom5790. NS a.root-servers.nil.
+dom5791. NS a.root-servers.nil.
+dom5792. NS a.root-servers.nil.
+dom5793. NS a.root-servers.nil.
+dom5794. NS a.root-servers.nil.
+dom5795. NS a.root-servers.nil.
+dom5796. NS a.root-servers.nil.
+dom5797. NS a.root-servers.nil.
+dom5798. NS a.root-servers.nil.
+dom5799. NS a.root-servers.nil.
+dom5800. NS a.root-servers.nil.
+dom5801. NS a.root-servers.nil.
+dom5802. NS a.root-servers.nil.
+dom5803. NS a.root-servers.nil.
+dom5804. NS a.root-servers.nil.
+dom5805. NS a.root-servers.nil.
+dom5806. NS a.root-servers.nil.
+dom5807. NS a.root-servers.nil.
+dom5808. NS a.root-servers.nil.
+dom5809. NS a.root-servers.nil.
+dom5810. NS a.root-servers.nil.
+dom5811. NS a.root-servers.nil.
+dom5812. NS a.root-servers.nil.
+dom5813. NS a.root-servers.nil.
+dom5814. NS a.root-servers.nil.
+dom5815. NS a.root-servers.nil.
+dom5816. NS a.root-servers.nil.
+dom5817. NS a.root-servers.nil.
+dom5818. NS a.root-servers.nil.
+dom5819. NS a.root-servers.nil.
+dom5820. NS a.root-servers.nil.
+dom5821. NS a.root-servers.nil.
+dom5822. NS a.root-servers.nil.
+dom5823. NS a.root-servers.nil.
+dom5824. NS a.root-servers.nil.
+dom5825. NS a.root-servers.nil.
+dom5826. NS a.root-servers.nil.
+dom5827. NS a.root-servers.nil.
+dom5828. NS a.root-servers.nil.
+dom5829. NS a.root-servers.nil.
+dom5830. NS a.root-servers.nil.
+dom5831. NS a.root-servers.nil.
+dom5832. NS a.root-servers.nil.
+dom5833. NS a.root-servers.nil.
+dom5834. NS a.root-servers.nil.
+dom5835. NS a.root-servers.nil.
+dom5836. NS a.root-servers.nil.
+dom5837. NS a.root-servers.nil.
+dom5838. NS a.root-servers.nil.
+dom5839. NS a.root-servers.nil.
+dom5840. NS a.root-servers.nil.
+dom5841. NS a.root-servers.nil.
+dom5842. NS a.root-servers.nil.
+dom5843. NS a.root-servers.nil.
+dom5844. NS a.root-servers.nil.
+dom5845. NS a.root-servers.nil.
+dom5846. NS a.root-servers.nil.
+dom5847. NS a.root-servers.nil.
+dom5848. NS a.root-servers.nil.
+dom5849. NS a.root-servers.nil.
+dom5850. NS a.root-servers.nil.
+dom5851. NS a.root-servers.nil.
+dom5852. NS a.root-servers.nil.
+dom5853. NS a.root-servers.nil.
+dom5854. NS a.root-servers.nil.
+dom5855. NS a.root-servers.nil.
+dom5856. NS a.root-servers.nil.
+dom5857. NS a.root-servers.nil.
+dom5858. NS a.root-servers.nil.
+dom5859. NS a.root-servers.nil.
+dom5860. NS a.root-servers.nil.
+dom5861. NS a.root-servers.nil.
+dom5862. NS a.root-servers.nil.
+dom5863. NS a.root-servers.nil.
+dom5864. NS a.root-servers.nil.
+dom5865. NS a.root-servers.nil.
+dom5866. NS a.root-servers.nil.
+dom5867. NS a.root-servers.nil.
+dom5868. NS a.root-servers.nil.
+dom5869. NS a.root-servers.nil.
+dom5870. NS a.root-servers.nil.
+dom5871. NS a.root-servers.nil.
+dom5872. NS a.root-servers.nil.
+dom5873. NS a.root-servers.nil.
+dom5874. NS a.root-servers.nil.
+dom5875. NS a.root-servers.nil.
+dom5876. NS a.root-servers.nil.
+dom5877. NS a.root-servers.nil.
+dom5878. NS a.root-servers.nil.
+dom5879. NS a.root-servers.nil.
+dom5880. NS a.root-servers.nil.
+dom5881. NS a.root-servers.nil.
+dom5882. NS a.root-servers.nil.
+dom5883. NS a.root-servers.nil.
+dom5884. NS a.root-servers.nil.
+dom5885. NS a.root-servers.nil.
+dom5886. NS a.root-servers.nil.
+dom5887. NS a.root-servers.nil.
+dom5888. NS a.root-servers.nil.
+dom5889. NS a.root-servers.nil.
+dom5890. NS a.root-servers.nil.
+dom5891. NS a.root-servers.nil.
+dom5892. NS a.root-servers.nil.
+dom5893. NS a.root-servers.nil.
+dom5894. NS a.root-servers.nil.
+dom5895. NS a.root-servers.nil.
+dom5896. NS a.root-servers.nil.
+dom5897. NS a.root-servers.nil.
+dom5898. NS a.root-servers.nil.
+dom5899. NS a.root-servers.nil.
+dom5900. NS a.root-servers.nil.
+dom5901. NS a.root-servers.nil.
+dom5902. NS a.root-servers.nil.
+dom5903. NS a.root-servers.nil.
+dom5904. NS a.root-servers.nil.
+dom5905. NS a.root-servers.nil.
+dom5906. NS a.root-servers.nil.
+dom5907. NS a.root-servers.nil.
+dom5908. NS a.root-servers.nil.
+dom5909. NS a.root-servers.nil.
+dom5910. NS a.root-servers.nil.
+dom5911. NS a.root-servers.nil.
+dom5912. NS a.root-servers.nil.
+dom5913. NS a.root-servers.nil.
+dom5914. NS a.root-servers.nil.
+dom5915. NS a.root-servers.nil.
+dom5916. NS a.root-servers.nil.
+dom5917. NS a.root-servers.nil.
+dom5918. NS a.root-servers.nil.
+dom5919. NS a.root-servers.nil.
+dom5920. NS a.root-servers.nil.
+dom5921. NS a.root-servers.nil.
+dom5922. NS a.root-servers.nil.
+dom5923. NS a.root-servers.nil.
+dom5924. NS a.root-servers.nil.
+dom5925. NS a.root-servers.nil.
+dom5926. NS a.root-servers.nil.
+dom5927. NS a.root-servers.nil.
+dom5928. NS a.root-servers.nil.
+dom5929. NS a.root-servers.nil.
+dom5930. NS a.root-servers.nil.
+dom5931. NS a.root-servers.nil.
+dom5932. NS a.root-servers.nil.
+dom5933. NS a.root-servers.nil.
+dom5934. NS a.root-servers.nil.
+dom5935. NS a.root-servers.nil.
+dom5936. NS a.root-servers.nil.
+dom5937. NS a.root-servers.nil.
+dom5938. NS a.root-servers.nil.
+dom5939. NS a.root-servers.nil.
+dom5940. NS a.root-servers.nil.
+dom5941. NS a.root-servers.nil.
+dom5942. NS a.root-servers.nil.
+dom5943. NS a.root-servers.nil.
+dom5944. NS a.root-servers.nil.
+dom5945. NS a.root-servers.nil.
+dom5946. NS a.root-servers.nil.
+dom5947. NS a.root-servers.nil.
+dom5948. NS a.root-servers.nil.
+dom5949. NS a.root-servers.nil.
+dom5950. NS a.root-servers.nil.
+dom5951. NS a.root-servers.nil.
+dom5952. NS a.root-servers.nil.
+dom5953. NS a.root-servers.nil.
+dom5954. NS a.root-servers.nil.
+dom5955. NS a.root-servers.nil.
+dom5956. NS a.root-servers.nil.
+dom5957. NS a.root-servers.nil.
+dom5958. NS a.root-servers.nil.
+dom5959. NS a.root-servers.nil.
+dom5960. NS a.root-servers.nil.
+dom5961. NS a.root-servers.nil.
+dom5962. NS a.root-servers.nil.
+dom5963. NS a.root-servers.nil.
+dom5964. NS a.root-servers.nil.
+dom5965. NS a.root-servers.nil.
+dom5966. NS a.root-servers.nil.
+dom5967. NS a.root-servers.nil.
+dom5968. NS a.root-servers.nil.
+dom5969. NS a.root-servers.nil.
+dom5970. NS a.root-servers.nil.
+dom5971. NS a.root-servers.nil.
+dom5972. NS a.root-servers.nil.
+dom5973. NS a.root-servers.nil.
+dom5974. NS a.root-servers.nil.
+dom5975. NS a.root-servers.nil.
+dom5976. NS a.root-servers.nil.
+dom5977. NS a.root-servers.nil.
+dom5978. NS a.root-servers.nil.
+dom5979. NS a.root-servers.nil.
+dom5980. NS a.root-servers.nil.
+dom5981. NS a.root-servers.nil.
+dom5982. NS a.root-servers.nil.
+dom5983. NS a.root-servers.nil.
+dom5984. NS a.root-servers.nil.
+dom5985. NS a.root-servers.nil.
+dom5986. NS a.root-servers.nil.
+dom5987. NS a.root-servers.nil.
+dom5988. NS a.root-servers.nil.
+dom5989. NS a.root-servers.nil.
+dom5990. NS a.root-servers.nil.
+dom5991. NS a.root-servers.nil.
+dom5992. NS a.root-servers.nil.
+dom5993. NS a.root-servers.nil.
+dom5994. NS a.root-servers.nil.
+dom5995. NS a.root-servers.nil.
+dom5996. NS a.root-servers.nil.
+dom5997. NS a.root-servers.nil.
+dom5998. NS a.root-servers.nil.
+dom5999. NS a.root-servers.nil.
+dom6000. NS a.root-servers.nil.
+dom6001. NS a.root-servers.nil.
+dom6002. NS a.root-servers.nil.
+dom6003. NS a.root-servers.nil.
+dom6004. NS a.root-servers.nil.
+dom6005. NS a.root-servers.nil.
+dom6006. NS a.root-servers.nil.
+dom6007. NS a.root-servers.nil.
+dom6008. NS a.root-servers.nil.
+dom6009. NS a.root-servers.nil.
+dom6010. NS a.root-servers.nil.
+dom6011. NS a.root-servers.nil.
+dom6012. NS a.root-servers.nil.
+dom6013. NS a.root-servers.nil.
+dom6014. NS a.root-servers.nil.
+dom6015. NS a.root-servers.nil.
+dom6016. NS a.root-servers.nil.
+dom6017. NS a.root-servers.nil.
+dom6018. NS a.root-servers.nil.
+dom6019. NS a.root-servers.nil.
+dom6020. NS a.root-servers.nil.
+dom6021. NS a.root-servers.nil.
+dom6022. NS a.root-servers.nil.
+dom6023. NS a.root-servers.nil.
+dom6024. NS a.root-servers.nil.
+dom6025. NS a.root-servers.nil.
+dom6026. NS a.root-servers.nil.
+dom6027. NS a.root-servers.nil.
+dom6028. NS a.root-servers.nil.
+dom6029. NS a.root-servers.nil.
+dom6030. NS a.root-servers.nil.
+dom6031. NS a.root-servers.nil.
+dom6032. NS a.root-servers.nil.
+dom6033. NS a.root-servers.nil.
+dom6034. NS a.root-servers.nil.
+dom6035. NS a.root-servers.nil.
+dom6036. NS a.root-servers.nil.
+dom6037. NS a.root-servers.nil.
+dom6038. NS a.root-servers.nil.
+dom6039. NS a.root-servers.nil.
+dom6040. NS a.root-servers.nil.
+dom6041. NS a.root-servers.nil.
+dom6042. NS a.root-servers.nil.
+dom6043. NS a.root-servers.nil.
+dom6044. NS a.root-servers.nil.
+dom6045. NS a.root-servers.nil.
+dom6046. NS a.root-servers.nil.
+dom6047. NS a.root-servers.nil.
+dom6048. NS a.root-servers.nil.
+dom6049. NS a.root-servers.nil.
+dom6050. NS a.root-servers.nil.
+dom6051. NS a.root-servers.nil.
+dom6052. NS a.root-servers.nil.
+dom6053. NS a.root-servers.nil.
+dom6054. NS a.root-servers.nil.
+dom6055. NS a.root-servers.nil.
+dom6056. NS a.root-servers.nil.
+dom6057. NS a.root-servers.nil.
+dom6058. NS a.root-servers.nil.
+dom6059. NS a.root-servers.nil.
+dom6060. NS a.root-servers.nil.
+dom6061. NS a.root-servers.nil.
+dom6062. NS a.root-servers.nil.
+dom6063. NS a.root-servers.nil.
+dom6064. NS a.root-servers.nil.
+dom6065. NS a.root-servers.nil.
+dom6066. NS a.root-servers.nil.
+dom6067. NS a.root-servers.nil.
+dom6068. NS a.root-servers.nil.
+dom6069. NS a.root-servers.nil.
+dom6070. NS a.root-servers.nil.
+dom6071. NS a.root-servers.nil.
+dom6072. NS a.root-servers.nil.
+dom6073. NS a.root-servers.nil.
+dom6074. NS a.root-servers.nil.
+dom6075. NS a.root-servers.nil.
+dom6076. NS a.root-servers.nil.
+dom6077. NS a.root-servers.nil.
+dom6078. NS a.root-servers.nil.
+dom6079. NS a.root-servers.nil.
+dom6080. NS a.root-servers.nil.
+dom6081. NS a.root-servers.nil.
+dom6082. NS a.root-servers.nil.
+dom6083. NS a.root-servers.nil.
+dom6084. NS a.root-servers.nil.
+dom6085. NS a.root-servers.nil.
+dom6086. NS a.root-servers.nil.
+dom6087. NS a.root-servers.nil.
+dom6088. NS a.root-servers.nil.
+dom6089. NS a.root-servers.nil.
+dom6090. NS a.root-servers.nil.
+dom6091. NS a.root-servers.nil.
+dom6092. NS a.root-servers.nil.
+dom6093. NS a.root-servers.nil.
+dom6094. NS a.root-servers.nil.
+dom6095. NS a.root-servers.nil.
+dom6096. NS a.root-servers.nil.
+dom6097. NS a.root-servers.nil.
+dom6098. NS a.root-servers.nil.
+dom6099. NS a.root-servers.nil.
+dom6100. NS a.root-servers.nil.
+dom6101. NS a.root-servers.nil.
+dom6102. NS a.root-servers.nil.
+dom6103. NS a.root-servers.nil.
+dom6104. NS a.root-servers.nil.
+dom6105. NS a.root-servers.nil.
+dom6106. NS a.root-servers.nil.
+dom6107. NS a.root-servers.nil.
+dom6108. NS a.root-servers.nil.
+dom6109. NS a.root-servers.nil.
+dom6110. NS a.root-servers.nil.
+dom6111. NS a.root-servers.nil.
+dom6112. NS a.root-servers.nil.
+dom6113. NS a.root-servers.nil.
+dom6114. NS a.root-servers.nil.
+dom6115. NS a.root-servers.nil.
+dom6116. NS a.root-servers.nil.
+dom6117. NS a.root-servers.nil.
+dom6118. NS a.root-servers.nil.
+dom6119. NS a.root-servers.nil.
+dom6120. NS a.root-servers.nil.
+dom6121. NS a.root-servers.nil.
+dom6122. NS a.root-servers.nil.
+dom6123. NS a.root-servers.nil.
+dom6124. NS a.root-servers.nil.
+dom6125. NS a.root-servers.nil.
+dom6126. NS a.root-servers.nil.
+dom6127. NS a.root-servers.nil.
+dom6128. NS a.root-servers.nil.
+dom6129. NS a.root-servers.nil.
+dom6130. NS a.root-servers.nil.
+dom6131. NS a.root-servers.nil.
+dom6132. NS a.root-servers.nil.
+dom6133. NS a.root-servers.nil.
+dom6134. NS a.root-servers.nil.
+dom6135. NS a.root-servers.nil.
+dom6136. NS a.root-servers.nil.
+dom6137. NS a.root-servers.nil.
+dom6138. NS a.root-servers.nil.
+dom6139. NS a.root-servers.nil.
+dom6140. NS a.root-servers.nil.
+dom6141. NS a.root-servers.nil.
+dom6142. NS a.root-servers.nil.
+dom6143. NS a.root-servers.nil.
+dom6144. NS a.root-servers.nil.
+dom6145. NS a.root-servers.nil.
+dom6146. NS a.root-servers.nil.
+dom6147. NS a.root-servers.nil.
+dom6148. NS a.root-servers.nil.
+dom6149. NS a.root-servers.nil.
+dom6150. NS a.root-servers.nil.
+dom6151. NS a.root-servers.nil.
+dom6152. NS a.root-servers.nil.
+dom6153. NS a.root-servers.nil.
+dom6154. NS a.root-servers.nil.
+dom6155. NS a.root-servers.nil.
+dom6156. NS a.root-servers.nil.
+dom6157. NS a.root-servers.nil.
+dom6158. NS a.root-servers.nil.
+dom6159. NS a.root-servers.nil.
+dom6160. NS a.root-servers.nil.
+dom6161. NS a.root-servers.nil.
+dom6162. NS a.root-servers.nil.
+dom6163. NS a.root-servers.nil.
+dom6164. NS a.root-servers.nil.
+dom6165. NS a.root-servers.nil.
+dom6166. NS a.root-servers.nil.
+dom6167. NS a.root-servers.nil.
+dom6168. NS a.root-servers.nil.
+dom6169. NS a.root-servers.nil.
+dom6170. NS a.root-servers.nil.
+dom6171. NS a.root-servers.nil.
+dom6172. NS a.root-servers.nil.
+dom6173. NS a.root-servers.nil.
+dom6174. NS a.root-servers.nil.
+dom6175. NS a.root-servers.nil.
+dom6176. NS a.root-servers.nil.
+dom6177. NS a.root-servers.nil.
+dom6178. NS a.root-servers.nil.
+dom6179. NS a.root-servers.nil.
+dom6180. NS a.root-servers.nil.
+dom6181. NS a.root-servers.nil.
+dom6182. NS a.root-servers.nil.
+dom6183. NS a.root-servers.nil.
+dom6184. NS a.root-servers.nil.
+dom6185. NS a.root-servers.nil.
+dom6186. NS a.root-servers.nil.
+dom6187. NS a.root-servers.nil.
+dom6188. NS a.root-servers.nil.
+dom6189. NS a.root-servers.nil.
+dom6190. NS a.root-servers.nil.
+dom6191. NS a.root-servers.nil.
+dom6192. NS a.root-servers.nil.
+dom6193. NS a.root-servers.nil.
+dom6194. NS a.root-servers.nil.
+dom6195. NS a.root-servers.nil.
+dom6196. NS a.root-servers.nil.
+dom6197. NS a.root-servers.nil.
+dom6198. NS a.root-servers.nil.
+dom6199. NS a.root-servers.nil.
+dom6200. NS a.root-servers.nil.
+dom6201. NS a.root-servers.nil.
+dom6202. NS a.root-servers.nil.
+dom6203. NS a.root-servers.nil.
+dom6204. NS a.root-servers.nil.
+dom6205. NS a.root-servers.nil.
+dom6206. NS a.root-servers.nil.
+dom6207. NS a.root-servers.nil.
+dom6208. NS a.root-servers.nil.
+dom6209. NS a.root-servers.nil.
+dom6210. NS a.root-servers.nil.
+dom6211. NS a.root-servers.nil.
+dom6212. NS a.root-servers.nil.
+dom6213. NS a.root-servers.nil.
+dom6214. NS a.root-servers.nil.
+dom6215. NS a.root-servers.nil.
+dom6216. NS a.root-servers.nil.
+dom6217. NS a.root-servers.nil.
+dom6218. NS a.root-servers.nil.
+dom6219. NS a.root-servers.nil.
+dom6220. NS a.root-servers.nil.
+dom6221. NS a.root-servers.nil.
+dom6222. NS a.root-servers.nil.
+dom6223. NS a.root-servers.nil.
+dom6224. NS a.root-servers.nil.
+dom6225. NS a.root-servers.nil.
+dom6226. NS a.root-servers.nil.
+dom6227. NS a.root-servers.nil.
+dom6228. NS a.root-servers.nil.
+dom6229. NS a.root-servers.nil.
+dom6230. NS a.root-servers.nil.
+dom6231. NS a.root-servers.nil.
+dom6232. NS a.root-servers.nil.
+dom6233. NS a.root-servers.nil.
+dom6234. NS a.root-servers.nil.
+dom6235. NS a.root-servers.nil.
+dom6236. NS a.root-servers.nil.
+dom6237. NS a.root-servers.nil.
+dom6238. NS a.root-servers.nil.
+dom6239. NS a.root-servers.nil.
+dom6240. NS a.root-servers.nil.
+dom6241. NS a.root-servers.nil.
+dom6242. NS a.root-servers.nil.
+dom6243. NS a.root-servers.nil.
+dom6244. NS a.root-servers.nil.
+dom6245. NS a.root-servers.nil.
+dom6246. NS a.root-servers.nil.
+dom6247. NS a.root-servers.nil.
+dom6248. NS a.root-servers.nil.
+dom6249. NS a.root-servers.nil.
+dom6250. NS a.root-servers.nil.
+dom6251. NS a.root-servers.nil.
+dom6252. NS a.root-servers.nil.
+dom6253. NS a.root-servers.nil.
+dom6254. NS a.root-servers.nil.
+dom6255. NS a.root-servers.nil.
+dom6256. NS a.root-servers.nil.
+dom6257. NS a.root-servers.nil.
+dom6258. NS a.root-servers.nil.
+dom6259. NS a.root-servers.nil.
+dom6260. NS a.root-servers.nil.
+dom6261. NS a.root-servers.nil.
+dom6262. NS a.root-servers.nil.
+dom6263. NS a.root-servers.nil.
+dom6264. NS a.root-servers.nil.
+dom6265. NS a.root-servers.nil.
+dom6266. NS a.root-servers.nil.
+dom6267. NS a.root-servers.nil.
+dom6268. NS a.root-servers.nil.
+dom6269. NS a.root-servers.nil.
+dom6270. NS a.root-servers.nil.
+dom6271. NS a.root-servers.nil.
+dom6272. NS a.root-servers.nil.
+dom6273. NS a.root-servers.nil.
+dom6274. NS a.root-servers.nil.
+dom6275. NS a.root-servers.nil.
+dom6276. NS a.root-servers.nil.
+dom6277. NS a.root-servers.nil.
+dom6278. NS a.root-servers.nil.
+dom6279. NS a.root-servers.nil.
+dom6280. NS a.root-servers.nil.
+dom6281. NS a.root-servers.nil.
+dom6282. NS a.root-servers.nil.
+dom6283. NS a.root-servers.nil.
+dom6284. NS a.root-servers.nil.
+dom6285. NS a.root-servers.nil.
+dom6286. NS a.root-servers.nil.
+dom6287. NS a.root-servers.nil.
+dom6288. NS a.root-servers.nil.
+dom6289. NS a.root-servers.nil.
+dom6290. NS a.root-servers.nil.
+dom6291. NS a.root-servers.nil.
+dom6292. NS a.root-servers.nil.
+dom6293. NS a.root-servers.nil.
+dom6294. NS a.root-servers.nil.
+dom6295. NS a.root-servers.nil.
+dom6296. NS a.root-servers.nil.
+dom6297. NS a.root-servers.nil.
+dom6298. NS a.root-servers.nil.
+dom6299. NS a.root-servers.nil.
+dom6300. NS a.root-servers.nil.
+dom6301. NS a.root-servers.nil.
+dom6302. NS a.root-servers.nil.
+dom6303. NS a.root-servers.nil.
+dom6304. NS a.root-servers.nil.
+dom6305. NS a.root-servers.nil.
+dom6306. NS a.root-servers.nil.
+dom6307. NS a.root-servers.nil.
+dom6308. NS a.root-servers.nil.
+dom6309. NS a.root-servers.nil.
+dom6310. NS a.root-servers.nil.
+dom6311. NS a.root-servers.nil.
+dom6312. NS a.root-servers.nil.
+dom6313. NS a.root-servers.nil.
+dom6314. NS a.root-servers.nil.
+dom6315. NS a.root-servers.nil.
+dom6316. NS a.root-servers.nil.
+dom6317. NS a.root-servers.nil.
+dom6318. NS a.root-servers.nil.
+dom6319. NS a.root-servers.nil.
+dom6320. NS a.root-servers.nil.
+dom6321. NS a.root-servers.nil.
+dom6322. NS a.root-servers.nil.
+dom6323. NS a.root-servers.nil.
+dom6324. NS a.root-servers.nil.
+dom6325. NS a.root-servers.nil.
+dom6326. NS a.root-servers.nil.
+dom6327. NS a.root-servers.nil.
+dom6328. NS a.root-servers.nil.
+dom6329. NS a.root-servers.nil.
+dom6330. NS a.root-servers.nil.
+dom6331. NS a.root-servers.nil.
+dom6332. NS a.root-servers.nil.
+dom6333. NS a.root-servers.nil.
+dom6334. NS a.root-servers.nil.
+dom6335. NS a.root-servers.nil.
+dom6336. NS a.root-servers.nil.
+dom6337. NS a.root-servers.nil.
+dom6338. NS a.root-servers.nil.
+dom6339. NS a.root-servers.nil.
+dom6340. NS a.root-servers.nil.
+dom6341. NS a.root-servers.nil.
+dom6342. NS a.root-servers.nil.
+dom6343. NS a.root-servers.nil.
+dom6344. NS a.root-servers.nil.
+dom6345. NS a.root-servers.nil.
+dom6346. NS a.root-servers.nil.
+dom6347. NS a.root-servers.nil.
+dom6348. NS a.root-servers.nil.
+dom6349. NS a.root-servers.nil.
+dom6350. NS a.root-servers.nil.
+dom6351. NS a.root-servers.nil.
+dom6352. NS a.root-servers.nil.
+dom6353. NS a.root-servers.nil.
+dom6354. NS a.root-servers.nil.
+dom6355. NS a.root-servers.nil.
+dom6356. NS a.root-servers.nil.
+dom6357. NS a.root-servers.nil.
+dom6358. NS a.root-servers.nil.
+dom6359. NS a.root-servers.nil.
+dom6360. NS a.root-servers.nil.
+dom6361. NS a.root-servers.nil.
+dom6362. NS a.root-servers.nil.
+dom6363. NS a.root-servers.nil.
+dom6364. NS a.root-servers.nil.
+dom6365. NS a.root-servers.nil.
+dom6366. NS a.root-servers.nil.
+dom6367. NS a.root-servers.nil.
+dom6368. NS a.root-servers.nil.
+dom6369. NS a.root-servers.nil.
+dom6370. NS a.root-servers.nil.
+dom6371. NS a.root-servers.nil.
+dom6372. NS a.root-servers.nil.
+dom6373. NS a.root-servers.nil.
+dom6374. NS a.root-servers.nil.
+dom6375. NS a.root-servers.nil.
+dom6376. NS a.root-servers.nil.
+dom6377. NS a.root-servers.nil.
+dom6378. NS a.root-servers.nil.
+dom6379. NS a.root-servers.nil.
+dom6380. NS a.root-servers.nil.
+dom6381. NS a.root-servers.nil.
+dom6382. NS a.root-servers.nil.
+dom6383. NS a.root-servers.nil.
+dom6384. NS a.root-servers.nil.
+dom6385. NS a.root-servers.nil.
+dom6386. NS a.root-servers.nil.
+dom6387. NS a.root-servers.nil.
+dom6388. NS a.root-servers.nil.
+dom6389. NS a.root-servers.nil.
+dom6390. NS a.root-servers.nil.
+dom6391. NS a.root-servers.nil.
+dom6392. NS a.root-servers.nil.
+dom6393. NS a.root-servers.nil.
+dom6394. NS a.root-servers.nil.
+dom6395. NS a.root-servers.nil.
+dom6396. NS a.root-servers.nil.
+dom6397. NS a.root-servers.nil.
+dom6398. NS a.root-servers.nil.
+dom6399. NS a.root-servers.nil.
+dom6400. NS a.root-servers.nil.
+dom6401. NS a.root-servers.nil.
+dom6402. NS a.root-servers.nil.
+dom6403. NS a.root-servers.nil.
+dom6404. NS a.root-servers.nil.
+dom6405. NS a.root-servers.nil.
+dom6406. NS a.root-servers.nil.
+dom6407. NS a.root-servers.nil.
+dom6408. NS a.root-servers.nil.
+dom6409. NS a.root-servers.nil.
+dom6410. NS a.root-servers.nil.
+dom6411. NS a.root-servers.nil.
+dom6412. NS a.root-servers.nil.
+dom6413. NS a.root-servers.nil.
+dom6414. NS a.root-servers.nil.
+dom6415. NS a.root-servers.nil.
+dom6416. NS a.root-servers.nil.
+dom6417. NS a.root-servers.nil.
+dom6418. NS a.root-servers.nil.
+dom6419. NS a.root-servers.nil.
+dom6420. NS a.root-servers.nil.
+dom6421. NS a.root-servers.nil.
+dom6422. NS a.root-servers.nil.
+dom6423. NS a.root-servers.nil.
+dom6424. NS a.root-servers.nil.
+dom6425. NS a.root-servers.nil.
+dom6426. NS a.root-servers.nil.
+dom6427. NS a.root-servers.nil.
+dom6428. NS a.root-servers.nil.
+dom6429. NS a.root-servers.nil.
+dom6430. NS a.root-servers.nil.
+dom6431. NS a.root-servers.nil.
+dom6432. NS a.root-servers.nil.
+dom6433. NS a.root-servers.nil.
+dom6434. NS a.root-servers.nil.
+dom6435. NS a.root-servers.nil.
+dom6436. NS a.root-servers.nil.
+dom6437. NS a.root-servers.nil.
+dom6438. NS a.root-servers.nil.
+dom6439. NS a.root-servers.nil.
+dom6440. NS a.root-servers.nil.
+dom6441. NS a.root-servers.nil.
+dom6442. NS a.root-servers.nil.
+dom6443. NS a.root-servers.nil.
+dom6444. NS a.root-servers.nil.
+dom6445. NS a.root-servers.nil.
+dom6446. NS a.root-servers.nil.
+dom6447. NS a.root-servers.nil.
+dom6448. NS a.root-servers.nil.
+dom6449. NS a.root-servers.nil.
+dom6450. NS a.root-servers.nil.
+dom6451. NS a.root-servers.nil.
+dom6452. NS a.root-servers.nil.
+dom6453. NS a.root-servers.nil.
+dom6454. NS a.root-servers.nil.
+dom6455. NS a.root-servers.nil.
+dom6456. NS a.root-servers.nil.
+dom6457. NS a.root-servers.nil.
+dom6458. NS a.root-servers.nil.
+dom6459. NS a.root-servers.nil.
+dom6460. NS a.root-servers.nil.
+dom6461. NS a.root-servers.nil.
+dom6462. NS a.root-servers.nil.
+dom6463. NS a.root-servers.nil.
+dom6464. NS a.root-servers.nil.
+dom6465. NS a.root-servers.nil.
+dom6466. NS a.root-servers.nil.
+dom6467. NS a.root-servers.nil.
+dom6468. NS a.root-servers.nil.
+dom6469. NS a.root-servers.nil.
+dom6470. NS a.root-servers.nil.
+dom6471. NS a.root-servers.nil.
+dom6472. NS a.root-servers.nil.
+dom6473. NS a.root-servers.nil.
+dom6474. NS a.root-servers.nil.
+dom6475. NS a.root-servers.nil.
+dom6476. NS a.root-servers.nil.
+dom6477. NS a.root-servers.nil.
+dom6478. NS a.root-servers.nil.
+dom6479. NS a.root-servers.nil.
+dom6480. NS a.root-servers.nil.
+dom6481. NS a.root-servers.nil.
+dom6482. NS a.root-servers.nil.
+dom6483. NS a.root-servers.nil.
+dom6484. NS a.root-servers.nil.
+dom6485. NS a.root-servers.nil.
+dom6486. NS a.root-servers.nil.
+dom6487. NS a.root-servers.nil.
+dom6488. NS a.root-servers.nil.
+dom6489. NS a.root-servers.nil.
+dom6490. NS a.root-servers.nil.
+dom6491. NS a.root-servers.nil.
+dom6492. NS a.root-servers.nil.
+dom6493. NS a.root-servers.nil.
+dom6494. NS a.root-servers.nil.
+dom6495. NS a.root-servers.nil.
+dom6496. NS a.root-servers.nil.
+dom6497. NS a.root-servers.nil.
+dom6498. NS a.root-servers.nil.
+dom6499. NS a.root-servers.nil.
+dom6500. NS a.root-servers.nil.
+dom6501. NS a.root-servers.nil.
+dom6502. NS a.root-servers.nil.
+dom6503. NS a.root-servers.nil.
+dom6504. NS a.root-servers.nil.
+dom6505. NS a.root-servers.nil.
+dom6506. NS a.root-servers.nil.
+dom6507. NS a.root-servers.nil.
+dom6508. NS a.root-servers.nil.
+dom6509. NS a.root-servers.nil.
+dom6510. NS a.root-servers.nil.
+dom6511. NS a.root-servers.nil.
+dom6512. NS a.root-servers.nil.
+dom6513. NS a.root-servers.nil.
+dom6514. NS a.root-servers.nil.
+dom6515. NS a.root-servers.nil.
+dom6516. NS a.root-servers.nil.
+dom6517. NS a.root-servers.nil.
+dom6518. NS a.root-servers.nil.
+dom6519. NS a.root-servers.nil.
+dom6520. NS a.root-servers.nil.
+dom6521. NS a.root-servers.nil.
+dom6522. NS a.root-servers.nil.
+dom6523. NS a.root-servers.nil.
+dom6524. NS a.root-servers.nil.
+dom6525. NS a.root-servers.nil.
+dom6526. NS a.root-servers.nil.
+dom6527. NS a.root-servers.nil.
+dom6528. NS a.root-servers.nil.
+dom6529. NS a.root-servers.nil.
+dom6530. NS a.root-servers.nil.
+dom6531. NS a.root-servers.nil.
+dom6532. NS a.root-servers.nil.
+dom6533. NS a.root-servers.nil.
+dom6534. NS a.root-servers.nil.
+dom6535. NS a.root-servers.nil.
+dom6536. NS a.root-servers.nil.
+dom6537. NS a.root-servers.nil.
+dom6538. NS a.root-servers.nil.
+dom6539. NS a.root-servers.nil.
+dom6540. NS a.root-servers.nil.
+dom6541. NS a.root-servers.nil.
+dom6542. NS a.root-servers.nil.
+dom6543. NS a.root-servers.nil.
+dom6544. NS a.root-servers.nil.
+dom6545. NS a.root-servers.nil.
+dom6546. NS a.root-servers.nil.
+dom6547. NS a.root-servers.nil.
+dom6548. NS a.root-servers.nil.
+dom6549. NS a.root-servers.nil.
+dom6550. NS a.root-servers.nil.
+dom6551. NS a.root-servers.nil.
+dom6552. NS a.root-servers.nil.
+dom6553. NS a.root-servers.nil.
+dom6554. NS a.root-servers.nil.
+dom6555. NS a.root-servers.nil.
+dom6556. NS a.root-servers.nil.
+dom6557. NS a.root-servers.nil.
+dom6558. NS a.root-servers.nil.
+dom6559. NS a.root-servers.nil.
+dom6560. NS a.root-servers.nil.
+dom6561. NS a.root-servers.nil.
+dom6562. NS a.root-servers.nil.
+dom6563. NS a.root-servers.nil.
+dom6564. NS a.root-servers.nil.
+dom6565. NS a.root-servers.nil.
+dom6566. NS a.root-servers.nil.
+dom6567. NS a.root-servers.nil.
+dom6568. NS a.root-servers.nil.
+dom6569. NS a.root-servers.nil.
+dom6570. NS a.root-servers.nil.
+dom6571. NS a.root-servers.nil.
+dom6572. NS a.root-servers.nil.
+dom6573. NS a.root-servers.nil.
+dom6574. NS a.root-servers.nil.
+dom6575. NS a.root-servers.nil.
+dom6576. NS a.root-servers.nil.
+dom6577. NS a.root-servers.nil.
+dom6578. NS a.root-servers.nil.
+dom6579. NS a.root-servers.nil.
+dom6580. NS a.root-servers.nil.
+dom6581. NS a.root-servers.nil.
+dom6582. NS a.root-servers.nil.
+dom6583. NS a.root-servers.nil.
+dom6584. NS a.root-servers.nil.
+dom6585. NS a.root-servers.nil.
+dom6586. NS a.root-servers.nil.
+dom6587. NS a.root-servers.nil.
+dom6588. NS a.root-servers.nil.
+dom6589. NS a.root-servers.nil.
+dom6590. NS a.root-servers.nil.
+dom6591. NS a.root-servers.nil.
+dom6592. NS a.root-servers.nil.
+dom6593. NS a.root-servers.nil.
+dom6594. NS a.root-servers.nil.
+dom6595. NS a.root-servers.nil.
+dom6596. NS a.root-servers.nil.
+dom6597. NS a.root-servers.nil.
+dom6598. NS a.root-servers.nil.
+dom6599. NS a.root-servers.nil.
+dom6600. NS a.root-servers.nil.
+dom6601. NS a.root-servers.nil.
+dom6602. NS a.root-servers.nil.
+dom6603. NS a.root-servers.nil.
+dom6604. NS a.root-servers.nil.
+dom6605. NS a.root-servers.nil.
+dom6606. NS a.root-servers.nil.
+dom6607. NS a.root-servers.nil.
+dom6608. NS a.root-servers.nil.
+dom6609. NS a.root-servers.nil.
+dom6610. NS a.root-servers.nil.
+dom6611. NS a.root-servers.nil.
+dom6612. NS a.root-servers.nil.
+dom6613. NS a.root-servers.nil.
+dom6614. NS a.root-servers.nil.
+dom6615. NS a.root-servers.nil.
+dom6616. NS a.root-servers.nil.
+dom6617. NS a.root-servers.nil.
+dom6618. NS a.root-servers.nil.
+dom6619. NS a.root-servers.nil.
+dom6620. NS a.root-servers.nil.
+dom6621. NS a.root-servers.nil.
+dom6622. NS a.root-servers.nil.
+dom6623. NS a.root-servers.nil.
+dom6624. NS a.root-servers.nil.
+dom6625. NS a.root-servers.nil.
+dom6626. NS a.root-servers.nil.
+dom6627. NS a.root-servers.nil.
+dom6628. NS a.root-servers.nil.
+dom6629. NS a.root-servers.nil.
+dom6630. NS a.root-servers.nil.
+dom6631. NS a.root-servers.nil.
+dom6632. NS a.root-servers.nil.
+dom6633. NS a.root-servers.nil.
+dom6634. NS a.root-servers.nil.
+dom6635. NS a.root-servers.nil.
+dom6636. NS a.root-servers.nil.
+dom6637. NS a.root-servers.nil.
+dom6638. NS a.root-servers.nil.
+dom6639. NS a.root-servers.nil.
+dom6640. NS a.root-servers.nil.
+dom6641. NS a.root-servers.nil.
+dom6642. NS a.root-servers.nil.
+dom6643. NS a.root-servers.nil.
+dom6644. NS a.root-servers.nil.
+dom6645. NS a.root-servers.nil.
+dom6646. NS a.root-servers.nil.
+dom6647. NS a.root-servers.nil.
+dom6648. NS a.root-servers.nil.
+dom6649. NS a.root-servers.nil.
+dom6650. NS a.root-servers.nil.
+dom6651. NS a.root-servers.nil.
+dom6652. NS a.root-servers.nil.
+dom6653. NS a.root-servers.nil.
+dom6654. NS a.root-servers.nil.
+dom6655. NS a.root-servers.nil.
+dom6656. NS a.root-servers.nil.
+dom6657. NS a.root-servers.nil.
+dom6658. NS a.root-servers.nil.
+dom6659. NS a.root-servers.nil.
+dom6660. NS a.root-servers.nil.
+dom6661. NS a.root-servers.nil.
+dom6662. NS a.root-servers.nil.
+dom6663. NS a.root-servers.nil.
+dom6664. NS a.root-servers.nil.
+dom6665. NS a.root-servers.nil.
+dom6666. NS a.root-servers.nil.
+dom6667. NS a.root-servers.nil.
+dom6668. NS a.root-servers.nil.
+dom6669. NS a.root-servers.nil.
+dom6670. NS a.root-servers.nil.
+dom6671. NS a.root-servers.nil.
+dom6672. NS a.root-servers.nil.
+dom6673. NS a.root-servers.nil.
+dom6674. NS a.root-servers.nil.
+dom6675. NS a.root-servers.nil.
+dom6676. NS a.root-servers.nil.
+dom6677. NS a.root-servers.nil.
+dom6678. NS a.root-servers.nil.
+dom6679. NS a.root-servers.nil.
+dom6680. NS a.root-servers.nil.
+dom6681. NS a.root-servers.nil.
+dom6682. NS a.root-servers.nil.
+dom6683. NS a.root-servers.nil.
+dom6684. NS a.root-servers.nil.
+dom6685. NS a.root-servers.nil.
+dom6686. NS a.root-servers.nil.
+dom6687. NS a.root-servers.nil.
+dom6688. NS a.root-servers.nil.
+dom6689. NS a.root-servers.nil.
+dom6690. NS a.root-servers.nil.
+dom6691. NS a.root-servers.nil.
+dom6692. NS a.root-servers.nil.
+dom6693. NS a.root-servers.nil.
+dom6694. NS a.root-servers.nil.
+dom6695. NS a.root-servers.nil.
+dom6696. NS a.root-servers.nil.
+dom6697. NS a.root-servers.nil.
+dom6698. NS a.root-servers.nil.
+dom6699. NS a.root-servers.nil.
+dom6700. NS a.root-servers.nil.
+dom6701. NS a.root-servers.nil.
+dom6702. NS a.root-servers.nil.
+dom6703. NS a.root-servers.nil.
+dom6704. NS a.root-servers.nil.
+dom6705. NS a.root-servers.nil.
+dom6706. NS a.root-servers.nil.
+dom6707. NS a.root-servers.nil.
+dom6708. NS a.root-servers.nil.
+dom6709. NS a.root-servers.nil.
+dom6710. NS a.root-servers.nil.
+dom6711. NS a.root-servers.nil.
+dom6712. NS a.root-servers.nil.
+dom6713. NS a.root-servers.nil.
+dom6714. NS a.root-servers.nil.
+dom6715. NS a.root-servers.nil.
+dom6716. NS a.root-servers.nil.
+dom6717. NS a.root-servers.nil.
+dom6718. NS a.root-servers.nil.
+dom6719. NS a.root-servers.nil.
+dom6720. NS a.root-servers.nil.
+dom6721. NS a.root-servers.nil.
+dom6722. NS a.root-servers.nil.
+dom6723. NS a.root-servers.nil.
+dom6724. NS a.root-servers.nil.
+dom6725. NS a.root-servers.nil.
+dom6726. NS a.root-servers.nil.
+dom6727. NS a.root-servers.nil.
+dom6728. NS a.root-servers.nil.
+dom6729. NS a.root-servers.nil.
+dom6730. NS a.root-servers.nil.
+dom6731. NS a.root-servers.nil.
+dom6732. NS a.root-servers.nil.
+dom6733. NS a.root-servers.nil.
+dom6734. NS a.root-servers.nil.
+dom6735. NS a.root-servers.nil.
+dom6736. NS a.root-servers.nil.
+dom6737. NS a.root-servers.nil.
+dom6738. NS a.root-servers.nil.
+dom6739. NS a.root-servers.nil.
+dom6740. NS a.root-servers.nil.
+dom6741. NS a.root-servers.nil.
+dom6742. NS a.root-servers.nil.
+dom6743. NS a.root-servers.nil.
+dom6744. NS a.root-servers.nil.
+dom6745. NS a.root-servers.nil.
+dom6746. NS a.root-servers.nil.
+dom6747. NS a.root-servers.nil.
+dom6748. NS a.root-servers.nil.
+dom6749. NS a.root-servers.nil.
+dom6750. NS a.root-servers.nil.
+dom6751. NS a.root-servers.nil.
+dom6752. NS a.root-servers.nil.
+dom6753. NS a.root-servers.nil.
+dom6754. NS a.root-servers.nil.
+dom6755. NS a.root-servers.nil.
+dom6756. NS a.root-servers.nil.
+dom6757. NS a.root-servers.nil.
+dom6758. NS a.root-servers.nil.
+dom6759. NS a.root-servers.nil.
+dom6760. NS a.root-servers.nil.
+dom6761. NS a.root-servers.nil.
+dom6762. NS a.root-servers.nil.
+dom6763. NS a.root-servers.nil.
+dom6764. NS a.root-servers.nil.
+dom6765. NS a.root-servers.nil.
+dom6766. NS a.root-servers.nil.
+dom6767. NS a.root-servers.nil.
+dom6768. NS a.root-servers.nil.
+dom6769. NS a.root-servers.nil.
+dom6770. NS a.root-servers.nil.
+dom6771. NS a.root-servers.nil.
+dom6772. NS a.root-servers.nil.
+dom6773. NS a.root-servers.nil.
+dom6774. NS a.root-servers.nil.
+dom6775. NS a.root-servers.nil.
+dom6776. NS a.root-servers.nil.
+dom6777. NS a.root-servers.nil.
+dom6778. NS a.root-servers.nil.
+dom6779. NS a.root-servers.nil.
+dom6780. NS a.root-servers.nil.
+dom6781. NS a.root-servers.nil.
+dom6782. NS a.root-servers.nil.
+dom6783. NS a.root-servers.nil.
+dom6784. NS a.root-servers.nil.
+dom6785. NS a.root-servers.nil.
+dom6786. NS a.root-servers.nil.
+dom6787. NS a.root-servers.nil.
+dom6788. NS a.root-servers.nil.
+dom6789. NS a.root-servers.nil.
+dom6790. NS a.root-servers.nil.
+dom6791. NS a.root-servers.nil.
+dom6792. NS a.root-servers.nil.
+dom6793. NS a.root-servers.nil.
+dom6794. NS a.root-servers.nil.
+dom6795. NS a.root-servers.nil.
+dom6796. NS a.root-servers.nil.
+dom6797. NS a.root-servers.nil.
+dom6798. NS a.root-servers.nil.
+dom6799. NS a.root-servers.nil.
+dom6800. NS a.root-servers.nil.
+dom6801. NS a.root-servers.nil.
+dom6802. NS a.root-servers.nil.
+dom6803. NS a.root-servers.nil.
+dom6804. NS a.root-servers.nil.
+dom6805. NS a.root-servers.nil.
+dom6806. NS a.root-servers.nil.
+dom6807. NS a.root-servers.nil.
+dom6808. NS a.root-servers.nil.
+dom6809. NS a.root-servers.nil.
+dom6810. NS a.root-servers.nil.
+dom6811. NS a.root-servers.nil.
+dom6812. NS a.root-servers.nil.
+dom6813. NS a.root-servers.nil.
+dom6814. NS a.root-servers.nil.
+dom6815. NS a.root-servers.nil.
+dom6816. NS a.root-servers.nil.
+dom6817. NS a.root-servers.nil.
+dom6818. NS a.root-servers.nil.
+dom6819. NS a.root-servers.nil.
+dom6820. NS a.root-servers.nil.
+dom6821. NS a.root-servers.nil.
+dom6822. NS a.root-servers.nil.
+dom6823. NS a.root-servers.nil.
+dom6824. NS a.root-servers.nil.
+dom6825. NS a.root-servers.nil.
+dom6826. NS a.root-servers.nil.
+dom6827. NS a.root-servers.nil.
+dom6828. NS a.root-servers.nil.
+dom6829. NS a.root-servers.nil.
+dom6830. NS a.root-servers.nil.
+dom6831. NS a.root-servers.nil.
+dom6832. NS a.root-servers.nil.
+dom6833. NS a.root-servers.nil.
+dom6834. NS a.root-servers.nil.
+dom6835. NS a.root-servers.nil.
+dom6836. NS a.root-servers.nil.
+dom6837. NS a.root-servers.nil.
+dom6838. NS a.root-servers.nil.
+dom6839. NS a.root-servers.nil.
+dom6840. NS a.root-servers.nil.
+dom6841. NS a.root-servers.nil.
+dom6842. NS a.root-servers.nil.
+dom6843. NS a.root-servers.nil.
+dom6844. NS a.root-servers.nil.
+dom6845. NS a.root-servers.nil.
+dom6846. NS a.root-servers.nil.
+dom6847. NS a.root-servers.nil.
+dom6848. NS a.root-servers.nil.
+dom6849. NS a.root-servers.nil.
+dom6850. NS a.root-servers.nil.
+dom6851. NS a.root-servers.nil.
+dom6852. NS a.root-servers.nil.
+dom6853. NS a.root-servers.nil.
+dom6854. NS a.root-servers.nil.
+dom6855. NS a.root-servers.nil.
+dom6856. NS a.root-servers.nil.
+dom6857. NS a.root-servers.nil.
+dom6858. NS a.root-servers.nil.
+dom6859. NS a.root-servers.nil.
+dom6860. NS a.root-servers.nil.
+dom6861. NS a.root-servers.nil.
+dom6862. NS a.root-servers.nil.
+dom6863. NS a.root-servers.nil.
+dom6864. NS a.root-servers.nil.
+dom6865. NS a.root-servers.nil.
+dom6866. NS a.root-servers.nil.
+dom6867. NS a.root-servers.nil.
+dom6868. NS a.root-servers.nil.
+dom6869. NS a.root-servers.nil.
+dom6870. NS a.root-servers.nil.
+dom6871. NS a.root-servers.nil.
+dom6872. NS a.root-servers.nil.
+dom6873. NS a.root-servers.nil.
+dom6874. NS a.root-servers.nil.
+dom6875. NS a.root-servers.nil.
+dom6876. NS a.root-servers.nil.
+dom6877. NS a.root-servers.nil.
+dom6878. NS a.root-servers.nil.
+dom6879. NS a.root-servers.nil.
+dom6880. NS a.root-servers.nil.
+dom6881. NS a.root-servers.nil.
+dom6882. NS a.root-servers.nil.
+dom6883. NS a.root-servers.nil.
+dom6884. NS a.root-servers.nil.
+dom6885. NS a.root-servers.nil.
+dom6886. NS a.root-servers.nil.
+dom6887. NS a.root-servers.nil.
+dom6888. NS a.root-servers.nil.
+dom6889. NS a.root-servers.nil.
+dom6890. NS a.root-servers.nil.
+dom6891. NS a.root-servers.nil.
+dom6892. NS a.root-servers.nil.
+dom6893. NS a.root-servers.nil.
+dom6894. NS a.root-servers.nil.
+dom6895. NS a.root-servers.nil.
+dom6896. NS a.root-servers.nil.
+dom6897. NS a.root-servers.nil.
+dom6898. NS a.root-servers.nil.
+dom6899. NS a.root-servers.nil.
+dom6900. NS a.root-servers.nil.
+dom6901. NS a.root-servers.nil.
+dom6902. NS a.root-servers.nil.
+dom6903. NS a.root-servers.nil.
+dom6904. NS a.root-servers.nil.
+dom6905. NS a.root-servers.nil.
+dom6906. NS a.root-servers.nil.
+dom6907. NS a.root-servers.nil.
+dom6908. NS a.root-servers.nil.
+dom6909. NS a.root-servers.nil.
+dom6910. NS a.root-servers.nil.
+dom6911. NS a.root-servers.nil.
+dom6912. NS a.root-servers.nil.
+dom6913. NS a.root-servers.nil.
+dom6914. NS a.root-servers.nil.
+dom6915. NS a.root-servers.nil.
+dom6916. NS a.root-servers.nil.
+dom6917. NS a.root-servers.nil.
+dom6918. NS a.root-servers.nil.
+dom6919. NS a.root-servers.nil.
+dom6920. NS a.root-servers.nil.
+dom6921. NS a.root-servers.nil.
+dom6922. NS a.root-servers.nil.
+dom6923. NS a.root-servers.nil.
+dom6924. NS a.root-servers.nil.
+dom6925. NS a.root-servers.nil.
+dom6926. NS a.root-servers.nil.
+dom6927. NS a.root-servers.nil.
+dom6928. NS a.root-servers.nil.
+dom6929. NS a.root-servers.nil.
+dom6930. NS a.root-servers.nil.
+dom6931. NS a.root-servers.nil.
+dom6932. NS a.root-servers.nil.
+dom6933. NS a.root-servers.nil.
+dom6934. NS a.root-servers.nil.
+dom6935. NS a.root-servers.nil.
+dom6936. NS a.root-servers.nil.
+dom6937. NS a.root-servers.nil.
+dom6938. NS a.root-servers.nil.
+dom6939. NS a.root-servers.nil.
+dom6940. NS a.root-servers.nil.
+dom6941. NS a.root-servers.nil.
+dom6942. NS a.root-servers.nil.
+dom6943. NS a.root-servers.nil.
+dom6944. NS a.root-servers.nil.
+dom6945. NS a.root-servers.nil.
+dom6946. NS a.root-servers.nil.
+dom6947. NS a.root-servers.nil.
+dom6948. NS a.root-servers.nil.
+dom6949. NS a.root-servers.nil.
+dom6950. NS a.root-servers.nil.
+dom6951. NS a.root-servers.nil.
+dom6952. NS a.root-servers.nil.
+dom6953. NS a.root-servers.nil.
+dom6954. NS a.root-servers.nil.
+dom6955. NS a.root-servers.nil.
+dom6956. NS a.root-servers.nil.
+dom6957. NS a.root-servers.nil.
+dom6958. NS a.root-servers.nil.
+dom6959. NS a.root-servers.nil.
+dom6960. NS a.root-servers.nil.
+dom6961. NS a.root-servers.nil.
+dom6962. NS a.root-servers.nil.
+dom6963. NS a.root-servers.nil.
+dom6964. NS a.root-servers.nil.
+dom6965. NS a.root-servers.nil.
+dom6966. NS a.root-servers.nil.
+dom6967. NS a.root-servers.nil.
+dom6968. NS a.root-servers.nil.
+dom6969. NS a.root-servers.nil.
+dom6970. NS a.root-servers.nil.
+dom6971. NS a.root-servers.nil.
+dom6972. NS a.root-servers.nil.
+dom6973. NS a.root-servers.nil.
+dom6974. NS a.root-servers.nil.
+dom6975. NS a.root-servers.nil.
+dom6976. NS a.root-servers.nil.
+dom6977. NS a.root-servers.nil.
+dom6978. NS a.root-servers.nil.
+dom6979. NS a.root-servers.nil.
+dom6980. NS a.root-servers.nil.
+dom6981. NS a.root-servers.nil.
+dom6982. NS a.root-servers.nil.
+dom6983. NS a.root-servers.nil.
+dom6984. NS a.root-servers.nil.
+dom6985. NS a.root-servers.nil.
+dom6986. NS a.root-servers.nil.
+dom6987. NS a.root-servers.nil.
+dom6988. NS a.root-servers.nil.
+dom6989. NS a.root-servers.nil.
+dom6990. NS a.root-servers.nil.
+dom6991. NS a.root-servers.nil.
+dom6992. NS a.root-servers.nil.
+dom6993. NS a.root-servers.nil.
+dom6994. NS a.root-servers.nil.
+dom6995. NS a.root-servers.nil.
+dom6996. NS a.root-servers.nil.
+dom6997. NS a.root-servers.nil.
+dom6998. NS a.root-servers.nil.
+dom6999. NS a.root-servers.nil.
+dom7000. NS a.root-servers.nil.
+dom7001. NS a.root-servers.nil.
+dom7002. NS a.root-servers.nil.
+dom7003. NS a.root-servers.nil.
+dom7004. NS a.root-servers.nil.
+dom7005. NS a.root-servers.nil.
+dom7006. NS a.root-servers.nil.
+dom7007. NS a.root-servers.nil.
+dom7008. NS a.root-servers.nil.
+dom7009. NS a.root-servers.nil.
+dom7010. NS a.root-servers.nil.
+dom7011. NS a.root-servers.nil.
+dom7012. NS a.root-servers.nil.
+dom7013. NS a.root-servers.nil.
+dom7014. NS a.root-servers.nil.
+dom7015. NS a.root-servers.nil.
+dom7016. NS a.root-servers.nil.
+dom7017. NS a.root-servers.nil.
+dom7018. NS a.root-servers.nil.
+dom7019. NS a.root-servers.nil.
+dom7020. NS a.root-servers.nil.
+dom7021. NS a.root-servers.nil.
+dom7022. NS a.root-servers.nil.
+dom7023. NS a.root-servers.nil.
+dom7024. NS a.root-servers.nil.
+dom7025. NS a.root-servers.nil.
+dom7026. NS a.root-servers.nil.
+dom7027. NS a.root-servers.nil.
+dom7028. NS a.root-servers.nil.
+dom7029. NS a.root-servers.nil.
+dom7030. NS a.root-servers.nil.
+dom7031. NS a.root-servers.nil.
+dom7032. NS a.root-servers.nil.
+dom7033. NS a.root-servers.nil.
+dom7034. NS a.root-servers.nil.
+dom7035. NS a.root-servers.nil.
+dom7036. NS a.root-servers.nil.
+dom7037. NS a.root-servers.nil.
+dom7038. NS a.root-servers.nil.
+dom7039. NS a.root-servers.nil.
+dom7040. NS a.root-servers.nil.
+dom7041. NS a.root-servers.nil.
+dom7042. NS a.root-servers.nil.
+dom7043. NS a.root-servers.nil.
+dom7044. NS a.root-servers.nil.
+dom7045. NS a.root-servers.nil.
+dom7046. NS a.root-servers.nil.
+dom7047. NS a.root-servers.nil.
+dom7048. NS a.root-servers.nil.
+dom7049. NS a.root-servers.nil.
+dom7050. NS a.root-servers.nil.
+dom7051. NS a.root-servers.nil.
+dom7052. NS a.root-servers.nil.
+dom7053. NS a.root-servers.nil.
+dom7054. NS a.root-servers.nil.
+dom7055. NS a.root-servers.nil.
+dom7056. NS a.root-servers.nil.
+dom7057. NS a.root-servers.nil.
+dom7058. NS a.root-servers.nil.
+dom7059. NS a.root-servers.nil.
+dom7060. NS a.root-servers.nil.
+dom7061. NS a.root-servers.nil.
+dom7062. NS a.root-servers.nil.
+dom7063. NS a.root-servers.nil.
+dom7064. NS a.root-servers.nil.
+dom7065. NS a.root-servers.nil.
+dom7066. NS a.root-servers.nil.
+dom7067. NS a.root-servers.nil.
+dom7068. NS a.root-servers.nil.
+dom7069. NS a.root-servers.nil.
+dom7070. NS a.root-servers.nil.
+dom7071. NS a.root-servers.nil.
+dom7072. NS a.root-servers.nil.
+dom7073. NS a.root-servers.nil.
+dom7074. NS a.root-servers.nil.
+dom7075. NS a.root-servers.nil.
+dom7076. NS a.root-servers.nil.
+dom7077. NS a.root-servers.nil.
+dom7078. NS a.root-servers.nil.
+dom7079. NS a.root-servers.nil.
+dom7080. NS a.root-servers.nil.
+dom7081. NS a.root-servers.nil.
+dom7082. NS a.root-servers.nil.
+dom7083. NS a.root-servers.nil.
+dom7084. NS a.root-servers.nil.
+dom7085. NS a.root-servers.nil.
+dom7086. NS a.root-servers.nil.
+dom7087. NS a.root-servers.nil.
+dom7088. NS a.root-servers.nil.
+dom7089. NS a.root-servers.nil.
+dom7090. NS a.root-servers.nil.
+dom7091. NS a.root-servers.nil.
+dom7092. NS a.root-servers.nil.
+dom7093. NS a.root-servers.nil.
+dom7094. NS a.root-servers.nil.
+dom7095. NS a.root-servers.nil.
+dom7096. NS a.root-servers.nil.
+dom7097. NS a.root-servers.nil.
+dom7098. NS a.root-servers.nil.
+dom7099. NS a.root-servers.nil.
+dom7100. NS a.root-servers.nil.
+dom7101. NS a.root-servers.nil.
+dom7102. NS a.root-servers.nil.
+dom7103. NS a.root-servers.nil.
+dom7104. NS a.root-servers.nil.
+dom7105. NS a.root-servers.nil.
+dom7106. NS a.root-servers.nil.
+dom7107. NS a.root-servers.nil.
+dom7108. NS a.root-servers.nil.
+dom7109. NS a.root-servers.nil.
+dom7110. NS a.root-servers.nil.
+dom7111. NS a.root-servers.nil.
+dom7112. NS a.root-servers.nil.
+dom7113. NS a.root-servers.nil.
+dom7114. NS a.root-servers.nil.
+dom7115. NS a.root-servers.nil.
+dom7116. NS a.root-servers.nil.
+dom7117. NS a.root-servers.nil.
+dom7118. NS a.root-servers.nil.
+dom7119. NS a.root-servers.nil.
+dom7120. NS a.root-servers.nil.
+dom7121. NS a.root-servers.nil.
+dom7122. NS a.root-servers.nil.
+dom7123. NS a.root-servers.nil.
+dom7124. NS a.root-servers.nil.
+dom7125. NS a.root-servers.nil.
+dom7126. NS a.root-servers.nil.
+dom7127. NS a.root-servers.nil.
+dom7128. NS a.root-servers.nil.
+dom7129. NS a.root-servers.nil.
+dom7130. NS a.root-servers.nil.
+dom7131. NS a.root-servers.nil.
+dom7132. NS a.root-servers.nil.
+dom7133. NS a.root-servers.nil.
+dom7134. NS a.root-servers.nil.
+dom7135. NS a.root-servers.nil.
+dom7136. NS a.root-servers.nil.
+dom7137. NS a.root-servers.nil.
+dom7138. NS a.root-servers.nil.
+dom7139. NS a.root-servers.nil.
+dom7140. NS a.root-servers.nil.
+dom7141. NS a.root-servers.nil.
+dom7142. NS a.root-servers.nil.
+dom7143. NS a.root-servers.nil.
+dom7144. NS a.root-servers.nil.
+dom7145. NS a.root-servers.nil.
+dom7146. NS a.root-servers.nil.
+dom7147. NS a.root-servers.nil.
+dom7148. NS a.root-servers.nil.
+dom7149. NS a.root-servers.nil.
+dom7150. NS a.root-servers.nil.
+dom7151. NS a.root-servers.nil.
+dom7152. NS a.root-servers.nil.
+dom7153. NS a.root-servers.nil.
+dom7154. NS a.root-servers.nil.
+dom7155. NS a.root-servers.nil.
+dom7156. NS a.root-servers.nil.
+dom7157. NS a.root-servers.nil.
+dom7158. NS a.root-servers.nil.
+dom7159. NS a.root-servers.nil.
+dom7160. NS a.root-servers.nil.
+dom7161. NS a.root-servers.nil.
+dom7162. NS a.root-servers.nil.
+dom7163. NS a.root-servers.nil.
+dom7164. NS a.root-servers.nil.
+dom7165. NS a.root-servers.nil.
+dom7166. NS a.root-servers.nil.
+dom7167. NS a.root-servers.nil.
+dom7168. NS a.root-servers.nil.
+dom7169. NS a.root-servers.nil.
+dom7170. NS a.root-servers.nil.
+dom7171. NS a.root-servers.nil.
+dom7172. NS a.root-servers.nil.
+dom7173. NS a.root-servers.nil.
+dom7174. NS a.root-servers.nil.
+dom7175. NS a.root-servers.nil.
+dom7176. NS a.root-servers.nil.
+dom7177. NS a.root-servers.nil.
+dom7178. NS a.root-servers.nil.
+dom7179. NS a.root-servers.nil.
+dom7180. NS a.root-servers.nil.
+dom7181. NS a.root-servers.nil.
+dom7182. NS a.root-servers.nil.
+dom7183. NS a.root-servers.nil.
+dom7184. NS a.root-servers.nil.
+dom7185. NS a.root-servers.nil.
+dom7186. NS a.root-servers.nil.
+dom7187. NS a.root-servers.nil.
+dom7188. NS a.root-servers.nil.
+dom7189. NS a.root-servers.nil.
+dom7190. NS a.root-servers.nil.
+dom7191. NS a.root-servers.nil.
+dom7192. NS a.root-servers.nil.
+dom7193. NS a.root-servers.nil.
+dom7194. NS a.root-servers.nil.
+dom7195. NS a.root-servers.nil.
+dom7196. NS a.root-servers.nil.
+dom7197. NS a.root-servers.nil.
+dom7198. NS a.root-servers.nil.
+dom7199. NS a.root-servers.nil.
+dom7200. NS a.root-servers.nil.
+dom7201. NS a.root-servers.nil.
+dom7202. NS a.root-servers.nil.
+dom7203. NS a.root-servers.nil.
+dom7204. NS a.root-servers.nil.
+dom7205. NS a.root-servers.nil.
+dom7206. NS a.root-servers.nil.
+dom7207. NS a.root-servers.nil.
+dom7208. NS a.root-servers.nil.
+dom7209. NS a.root-servers.nil.
+dom7210. NS a.root-servers.nil.
+dom7211. NS a.root-servers.nil.
+dom7212. NS a.root-servers.nil.
+dom7213. NS a.root-servers.nil.
+dom7214. NS a.root-servers.nil.
+dom7215. NS a.root-servers.nil.
+dom7216. NS a.root-servers.nil.
+dom7217. NS a.root-servers.nil.
+dom7218. NS a.root-servers.nil.
+dom7219. NS a.root-servers.nil.
+dom7220. NS a.root-servers.nil.
+dom7221. NS a.root-servers.nil.
+dom7222. NS a.root-servers.nil.
+dom7223. NS a.root-servers.nil.
+dom7224. NS a.root-servers.nil.
+dom7225. NS a.root-servers.nil.
+dom7226. NS a.root-servers.nil.
+dom7227. NS a.root-servers.nil.
+dom7228. NS a.root-servers.nil.
+dom7229. NS a.root-servers.nil.
+dom7230. NS a.root-servers.nil.
+dom7231. NS a.root-servers.nil.
+dom7232. NS a.root-servers.nil.
+dom7233. NS a.root-servers.nil.
+dom7234. NS a.root-servers.nil.
+dom7235. NS a.root-servers.nil.
+dom7236. NS a.root-servers.nil.
+dom7237. NS a.root-servers.nil.
+dom7238. NS a.root-servers.nil.
+dom7239. NS a.root-servers.nil.
+dom7240. NS a.root-servers.nil.
+dom7241. NS a.root-servers.nil.
+dom7242. NS a.root-servers.nil.
+dom7243. NS a.root-servers.nil.
+dom7244. NS a.root-servers.nil.
+dom7245. NS a.root-servers.nil.
+dom7246. NS a.root-servers.nil.
+dom7247. NS a.root-servers.nil.
+dom7248. NS a.root-servers.nil.
+dom7249. NS a.root-servers.nil.
+dom7250. NS a.root-servers.nil.
+dom7251. NS a.root-servers.nil.
+dom7252. NS a.root-servers.nil.
+dom7253. NS a.root-servers.nil.
+dom7254. NS a.root-servers.nil.
+dom7255. NS a.root-servers.nil.
+dom7256. NS a.root-servers.nil.
+dom7257. NS a.root-servers.nil.
+dom7258. NS a.root-servers.nil.
+dom7259. NS a.root-servers.nil.
+dom7260. NS a.root-servers.nil.
+dom7261. NS a.root-servers.nil.
+dom7262. NS a.root-servers.nil.
+dom7263. NS a.root-servers.nil.
+dom7264. NS a.root-servers.nil.
+dom7265. NS a.root-servers.nil.
+dom7266. NS a.root-servers.nil.
+dom7267. NS a.root-servers.nil.
+dom7268. NS a.root-servers.nil.
+dom7269. NS a.root-servers.nil.
+dom7270. NS a.root-servers.nil.
+dom7271. NS a.root-servers.nil.
+dom7272. NS a.root-servers.nil.
+dom7273. NS a.root-servers.nil.
+dom7274. NS a.root-servers.nil.
+dom7275. NS a.root-servers.nil.
+dom7276. NS a.root-servers.nil.
+dom7277. NS a.root-servers.nil.
+dom7278. NS a.root-servers.nil.
+dom7279. NS a.root-servers.nil.
+dom7280. NS a.root-servers.nil.
+dom7281. NS a.root-servers.nil.
+dom7282. NS a.root-servers.nil.
+dom7283. NS a.root-servers.nil.
+dom7284. NS a.root-servers.nil.
+dom7285. NS a.root-servers.nil.
+dom7286. NS a.root-servers.nil.
+dom7287. NS a.root-servers.nil.
+dom7288. NS a.root-servers.nil.
+dom7289. NS a.root-servers.nil.
+dom7290. NS a.root-servers.nil.
+dom7291. NS a.root-servers.nil.
+dom7292. NS a.root-servers.nil.
+dom7293. NS a.root-servers.nil.
+dom7294. NS a.root-servers.nil.
+dom7295. NS a.root-servers.nil.
+dom7296. NS a.root-servers.nil.
+dom7297. NS a.root-servers.nil.
+dom7298. NS a.root-servers.nil.
+dom7299. NS a.root-servers.nil.
+dom7300. NS a.root-servers.nil.
+dom7301. NS a.root-servers.nil.
+dom7302. NS a.root-servers.nil.
+dom7303. NS a.root-servers.nil.
+dom7304. NS a.root-servers.nil.
+dom7305. NS a.root-servers.nil.
+dom7306. NS a.root-servers.nil.
+dom7307. NS a.root-servers.nil.
+dom7308. NS a.root-servers.nil.
+dom7309. NS a.root-servers.nil.
+dom7310. NS a.root-servers.nil.
+dom7311. NS a.root-servers.nil.
+dom7312. NS a.root-servers.nil.
+dom7313. NS a.root-servers.nil.
+dom7314. NS a.root-servers.nil.
+dom7315. NS a.root-servers.nil.
+dom7316. NS a.root-servers.nil.
+dom7317. NS a.root-servers.nil.
+dom7318. NS a.root-servers.nil.
+dom7319. NS a.root-servers.nil.
+dom7320. NS a.root-servers.nil.
+dom7321. NS a.root-servers.nil.
+dom7322. NS a.root-servers.nil.
+dom7323. NS a.root-servers.nil.
+dom7324. NS a.root-servers.nil.
+dom7325. NS a.root-servers.nil.
+dom7326. NS a.root-servers.nil.
+dom7327. NS a.root-servers.nil.
+dom7328. NS a.root-servers.nil.
+dom7329. NS a.root-servers.nil.
+dom7330. NS a.root-servers.nil.
+dom7331. NS a.root-servers.nil.
+dom7332. NS a.root-servers.nil.
+dom7333. NS a.root-servers.nil.
+dom7334. NS a.root-servers.nil.
+dom7335. NS a.root-servers.nil.
+dom7336. NS a.root-servers.nil.
+dom7337. NS a.root-servers.nil.
+dom7338. NS a.root-servers.nil.
+dom7339. NS a.root-servers.nil.
+dom7340. NS a.root-servers.nil.
+dom7341. NS a.root-servers.nil.
+dom7342. NS a.root-servers.nil.
+dom7343. NS a.root-servers.nil.
+dom7344. NS a.root-servers.nil.
+dom7345. NS a.root-servers.nil.
+dom7346. NS a.root-servers.nil.
+dom7347. NS a.root-servers.nil.
+dom7348. NS a.root-servers.nil.
+dom7349. NS a.root-servers.nil.
+dom7350. NS a.root-servers.nil.
+dom7351. NS a.root-servers.nil.
+dom7352. NS a.root-servers.nil.
+dom7353. NS a.root-servers.nil.
+dom7354. NS a.root-servers.nil.
+dom7355. NS a.root-servers.nil.
+dom7356. NS a.root-servers.nil.
+dom7357. NS a.root-servers.nil.
+dom7358. NS a.root-servers.nil.
+dom7359. NS a.root-servers.nil.
+dom7360. NS a.root-servers.nil.
+dom7361. NS a.root-servers.nil.
+dom7362. NS a.root-servers.nil.
+dom7363. NS a.root-servers.nil.
+dom7364. NS a.root-servers.nil.
+dom7365. NS a.root-servers.nil.
+dom7366. NS a.root-servers.nil.
+dom7367. NS a.root-servers.nil.
+dom7368. NS a.root-servers.nil.
+dom7369. NS a.root-servers.nil.
+dom7370. NS a.root-servers.nil.
+dom7371. NS a.root-servers.nil.
+dom7372. NS a.root-servers.nil.
+dom7373. NS a.root-servers.nil.
+dom7374. NS a.root-servers.nil.
+dom7375. NS a.root-servers.nil.
+dom7376. NS a.root-servers.nil.
+dom7377. NS a.root-servers.nil.
+dom7378. NS a.root-servers.nil.
+dom7379. NS a.root-servers.nil.
+dom7380. NS a.root-servers.nil.
+dom7381. NS a.root-servers.nil.
+dom7382. NS a.root-servers.nil.
+dom7383. NS a.root-servers.nil.
+dom7384. NS a.root-servers.nil.
+dom7385. NS a.root-servers.nil.
+dom7386. NS a.root-servers.nil.
+dom7387. NS a.root-servers.nil.
+dom7388. NS a.root-servers.nil.
+dom7389. NS a.root-servers.nil.
+dom7390. NS a.root-servers.nil.
+dom7391. NS a.root-servers.nil.
+dom7392. NS a.root-servers.nil.
+dom7393. NS a.root-servers.nil.
+dom7394. NS a.root-servers.nil.
+dom7395. NS a.root-servers.nil.
+dom7396. NS a.root-servers.nil.
+dom7397. NS a.root-servers.nil.
+dom7398. NS a.root-servers.nil.
+dom7399. NS a.root-servers.nil.
+dom7400. NS a.root-servers.nil.
+dom7401. NS a.root-servers.nil.
+dom7402. NS a.root-servers.nil.
+dom7403. NS a.root-servers.nil.
+dom7404. NS a.root-servers.nil.
+dom7405. NS a.root-servers.nil.
+dom7406. NS a.root-servers.nil.
+dom7407. NS a.root-servers.nil.
+dom7408. NS a.root-servers.nil.
+dom7409. NS a.root-servers.nil.
+dom7410. NS a.root-servers.nil.
+dom7411. NS a.root-servers.nil.
+dom7412. NS a.root-servers.nil.
+dom7413. NS a.root-servers.nil.
+dom7414. NS a.root-servers.nil.
+dom7415. NS a.root-servers.nil.
+dom7416. NS a.root-servers.nil.
+dom7417. NS a.root-servers.nil.
+dom7418. NS a.root-servers.nil.
+dom7419. NS a.root-servers.nil.
+dom7420. NS a.root-servers.nil.
+dom7421. NS a.root-servers.nil.
+dom7422. NS a.root-servers.nil.
+dom7423. NS a.root-servers.nil.
+dom7424. NS a.root-servers.nil.
+dom7425. NS a.root-servers.nil.
+dom7426. NS a.root-servers.nil.
+dom7427. NS a.root-servers.nil.
+dom7428. NS a.root-servers.nil.
+dom7429. NS a.root-servers.nil.
+dom7430. NS a.root-servers.nil.
+dom7431. NS a.root-servers.nil.
+dom7432. NS a.root-servers.nil.
+dom7433. NS a.root-servers.nil.
+dom7434. NS a.root-servers.nil.
+dom7435. NS a.root-servers.nil.
+dom7436. NS a.root-servers.nil.
+dom7437. NS a.root-servers.nil.
+dom7438. NS a.root-servers.nil.
+dom7439. NS a.root-servers.nil.
+dom7440. NS a.root-servers.nil.
+dom7441. NS a.root-servers.nil.
+dom7442. NS a.root-servers.nil.
+dom7443. NS a.root-servers.nil.
+dom7444. NS a.root-servers.nil.
+dom7445. NS a.root-servers.nil.
+dom7446. NS a.root-servers.nil.
+dom7447. NS a.root-servers.nil.
+dom7448. NS a.root-servers.nil.
+dom7449. NS a.root-servers.nil.
+dom7450. NS a.root-servers.nil.
+dom7451. NS a.root-servers.nil.
+dom7452. NS a.root-servers.nil.
+dom7453. NS a.root-servers.nil.
+dom7454. NS a.root-servers.nil.
+dom7455. NS a.root-servers.nil.
+dom7456. NS a.root-servers.nil.
+dom7457. NS a.root-servers.nil.
+dom7458. NS a.root-servers.nil.
+dom7459. NS a.root-servers.nil.
+dom7460. NS a.root-servers.nil.
+dom7461. NS a.root-servers.nil.
+dom7462. NS a.root-servers.nil.
+dom7463. NS a.root-servers.nil.
+dom7464. NS a.root-servers.nil.
+dom7465. NS a.root-servers.nil.
+dom7466. NS a.root-servers.nil.
+dom7467. NS a.root-servers.nil.
+dom7468. NS a.root-servers.nil.
+dom7469. NS a.root-servers.nil.
+dom7470. NS a.root-servers.nil.
+dom7471. NS a.root-servers.nil.
+dom7472. NS a.root-servers.nil.
+dom7473. NS a.root-servers.nil.
+dom7474. NS a.root-servers.nil.
+dom7475. NS a.root-servers.nil.
+dom7476. NS a.root-servers.nil.
+dom7477. NS a.root-servers.nil.
+dom7478. NS a.root-servers.nil.
+dom7479. NS a.root-servers.nil.
+dom7480. NS a.root-servers.nil.
+dom7481. NS a.root-servers.nil.
+dom7482. NS a.root-servers.nil.
+dom7483. NS a.root-servers.nil.
+dom7484. NS a.root-servers.nil.
+dom7485. NS a.root-servers.nil.
+dom7486. NS a.root-servers.nil.
+dom7487. NS a.root-servers.nil.
+dom7488. NS a.root-servers.nil.
+dom7489. NS a.root-servers.nil.
+dom7490. NS a.root-servers.nil.
+dom7491. NS a.root-servers.nil.
+dom7492. NS a.root-servers.nil.
+dom7493. NS a.root-servers.nil.
+dom7494. NS a.root-servers.nil.
+dom7495. NS a.root-servers.nil.
+dom7496. NS a.root-servers.nil.
+dom7497. NS a.root-servers.nil.
+dom7498. NS a.root-servers.nil.
+dom7499. NS a.root-servers.nil.
+dom7500. NS a.root-servers.nil.
+dom7501. NS a.root-servers.nil.
+dom7502. NS a.root-servers.nil.
+dom7503. NS a.root-servers.nil.
+dom7504. NS a.root-servers.nil.
+dom7505. NS a.root-servers.nil.
+dom7506. NS a.root-servers.nil.
+dom7507. NS a.root-servers.nil.
+dom7508. NS a.root-servers.nil.
+dom7509. NS a.root-servers.nil.
+dom7510. NS a.root-servers.nil.
+dom7511. NS a.root-servers.nil.
+dom7512. NS a.root-servers.nil.
+dom7513. NS a.root-servers.nil.
+dom7514. NS a.root-servers.nil.
+dom7515. NS a.root-servers.nil.
+dom7516. NS a.root-servers.nil.
+dom7517. NS a.root-servers.nil.
+dom7518. NS a.root-servers.nil.
+dom7519. NS a.root-servers.nil.
+dom7520. NS a.root-servers.nil.
+dom7521. NS a.root-servers.nil.
+dom7522. NS a.root-servers.nil.
+dom7523. NS a.root-servers.nil.
+dom7524. NS a.root-servers.nil.
+dom7525. NS a.root-servers.nil.
+dom7526. NS a.root-servers.nil.
+dom7527. NS a.root-servers.nil.
+dom7528. NS a.root-servers.nil.
+dom7529. NS a.root-servers.nil.
+dom7530. NS a.root-servers.nil.
+dom7531. NS a.root-servers.nil.
+dom7532. NS a.root-servers.nil.
+dom7533. NS a.root-servers.nil.
+dom7534. NS a.root-servers.nil.
+dom7535. NS a.root-servers.nil.
+dom7536. NS a.root-servers.nil.
+dom7537. NS a.root-servers.nil.
+dom7538. NS a.root-servers.nil.
+dom7539. NS a.root-servers.nil.
+dom7540. NS a.root-servers.nil.
+dom7541. NS a.root-servers.nil.
+dom7542. NS a.root-servers.nil.
+dom7543. NS a.root-servers.nil.
+dom7544. NS a.root-servers.nil.
+dom7545. NS a.root-servers.nil.
+dom7546. NS a.root-servers.nil.
+dom7547. NS a.root-servers.nil.
+dom7548. NS a.root-servers.nil.
+dom7549. NS a.root-servers.nil.
+dom7550. NS a.root-servers.nil.
+dom7551. NS a.root-servers.nil.
+dom7552. NS a.root-servers.nil.
+dom7553. NS a.root-servers.nil.
+dom7554. NS a.root-servers.nil.
+dom7555. NS a.root-servers.nil.
+dom7556. NS a.root-servers.nil.
+dom7557. NS a.root-servers.nil.
+dom7558. NS a.root-servers.nil.
+dom7559. NS a.root-servers.nil.
+dom7560. NS a.root-servers.nil.
+dom7561. NS a.root-servers.nil.
+dom7562. NS a.root-servers.nil.
+dom7563. NS a.root-servers.nil.
+dom7564. NS a.root-servers.nil.
+dom7565. NS a.root-servers.nil.
+dom7566. NS a.root-servers.nil.
+dom7567. NS a.root-servers.nil.
+dom7568. NS a.root-servers.nil.
+dom7569. NS a.root-servers.nil.
+dom7570. NS a.root-servers.nil.
+dom7571. NS a.root-servers.nil.
+dom7572. NS a.root-servers.nil.
+dom7573. NS a.root-servers.nil.
+dom7574. NS a.root-servers.nil.
+dom7575. NS a.root-servers.nil.
+dom7576. NS a.root-servers.nil.
+dom7577. NS a.root-servers.nil.
+dom7578. NS a.root-servers.nil.
+dom7579. NS a.root-servers.nil.
+dom7580. NS a.root-servers.nil.
+dom7581. NS a.root-servers.nil.
+dom7582. NS a.root-servers.nil.
+dom7583. NS a.root-servers.nil.
+dom7584. NS a.root-servers.nil.
+dom7585. NS a.root-servers.nil.
+dom7586. NS a.root-servers.nil.
+dom7587. NS a.root-servers.nil.
+dom7588. NS a.root-servers.nil.
+dom7589. NS a.root-servers.nil.
+dom7590. NS a.root-servers.nil.
+dom7591. NS a.root-servers.nil.
+dom7592. NS a.root-servers.nil.
+dom7593. NS a.root-servers.nil.
+dom7594. NS a.root-servers.nil.
+dom7595. NS a.root-servers.nil.
+dom7596. NS a.root-servers.nil.
+dom7597. NS a.root-servers.nil.
+dom7598. NS a.root-servers.nil.
+dom7599. NS a.root-servers.nil.
+dom7600. NS a.root-servers.nil.
+dom7601. NS a.root-servers.nil.
+dom7602. NS a.root-servers.nil.
+dom7603. NS a.root-servers.nil.
+dom7604. NS a.root-servers.nil.
+dom7605. NS a.root-servers.nil.
+dom7606. NS a.root-servers.nil.
+dom7607. NS a.root-servers.nil.
+dom7608. NS a.root-servers.nil.
+dom7609. NS a.root-servers.nil.
+dom7610. NS a.root-servers.nil.
+dom7611. NS a.root-servers.nil.
+dom7612. NS a.root-servers.nil.
+dom7613. NS a.root-servers.nil.
+dom7614. NS a.root-servers.nil.
+dom7615. NS a.root-servers.nil.
+dom7616. NS a.root-servers.nil.
+dom7617. NS a.root-servers.nil.
+dom7618. NS a.root-servers.nil.
+dom7619. NS a.root-servers.nil.
+dom7620. NS a.root-servers.nil.
+dom7621. NS a.root-servers.nil.
+dom7622. NS a.root-servers.nil.
+dom7623. NS a.root-servers.nil.
+dom7624. NS a.root-servers.nil.
+dom7625. NS a.root-servers.nil.
+dom7626. NS a.root-servers.nil.
+dom7627. NS a.root-servers.nil.
+dom7628. NS a.root-servers.nil.
+dom7629. NS a.root-servers.nil.
+dom7630. NS a.root-servers.nil.
+dom7631. NS a.root-servers.nil.
+dom7632. NS a.root-servers.nil.
+dom7633. NS a.root-servers.nil.
+dom7634. NS a.root-servers.nil.
+dom7635. NS a.root-servers.nil.
+dom7636. NS a.root-servers.nil.
+dom7637. NS a.root-servers.nil.
+dom7638. NS a.root-servers.nil.
+dom7639. NS a.root-servers.nil.
+dom7640. NS a.root-servers.nil.
+dom7641. NS a.root-servers.nil.
+dom7642. NS a.root-servers.nil.
+dom7643. NS a.root-servers.nil.
+dom7644. NS a.root-servers.nil.
+dom7645. NS a.root-servers.nil.
+dom7646. NS a.root-servers.nil.
+dom7647. NS a.root-servers.nil.
+dom7648. NS a.root-servers.nil.
+dom7649. NS a.root-servers.nil.
+dom7650. NS a.root-servers.nil.
+dom7651. NS a.root-servers.nil.
+dom7652. NS a.root-servers.nil.
+dom7653. NS a.root-servers.nil.
+dom7654. NS a.root-servers.nil.
+dom7655. NS a.root-servers.nil.
+dom7656. NS a.root-servers.nil.
+dom7657. NS a.root-servers.nil.
+dom7658. NS a.root-servers.nil.
+dom7659. NS a.root-servers.nil.
+dom7660. NS a.root-servers.nil.
+dom7661. NS a.root-servers.nil.
+dom7662. NS a.root-servers.nil.
+dom7663. NS a.root-servers.nil.
+dom7664. NS a.root-servers.nil.
+dom7665. NS a.root-servers.nil.
+dom7666. NS a.root-servers.nil.
+dom7667. NS a.root-servers.nil.
+dom7668. NS a.root-servers.nil.
+dom7669. NS a.root-servers.nil.
+dom7670. NS a.root-servers.nil.
+dom7671. NS a.root-servers.nil.
+dom7672. NS a.root-servers.nil.
+dom7673. NS a.root-servers.nil.
+dom7674. NS a.root-servers.nil.
+dom7675. NS a.root-servers.nil.
+dom7676. NS a.root-servers.nil.
+dom7677. NS a.root-servers.nil.
+dom7678. NS a.root-servers.nil.
+dom7679. NS a.root-servers.nil.
+dom7680. NS a.root-servers.nil.
+dom7681. NS a.root-servers.nil.
+dom7682. NS a.root-servers.nil.
+dom7683. NS a.root-servers.nil.
+dom7684. NS a.root-servers.nil.
+dom7685. NS a.root-servers.nil.
+dom7686. NS a.root-servers.nil.
+dom7687. NS a.root-servers.nil.
+dom7688. NS a.root-servers.nil.
+dom7689. NS a.root-servers.nil.
+dom7690. NS a.root-servers.nil.
+dom7691. NS a.root-servers.nil.
+dom7692. NS a.root-servers.nil.
+dom7693. NS a.root-servers.nil.
+dom7694. NS a.root-servers.nil.
+dom7695. NS a.root-servers.nil.
+dom7696. NS a.root-servers.nil.
+dom7697. NS a.root-servers.nil.
+dom7698. NS a.root-servers.nil.
+dom7699. NS a.root-servers.nil.
+dom7700. NS a.root-servers.nil.
+dom7701. NS a.root-servers.nil.
+dom7702. NS a.root-servers.nil.
+dom7703. NS a.root-servers.nil.
+dom7704. NS a.root-servers.nil.
+dom7705. NS a.root-servers.nil.
+dom7706. NS a.root-servers.nil.
+dom7707. NS a.root-servers.nil.
+dom7708. NS a.root-servers.nil.
+dom7709. NS a.root-servers.nil.
+dom7710. NS a.root-servers.nil.
+dom7711. NS a.root-servers.nil.
+dom7712. NS a.root-servers.nil.
+dom7713. NS a.root-servers.nil.
+dom7714. NS a.root-servers.nil.
+dom7715. NS a.root-servers.nil.
+dom7716. NS a.root-servers.nil.
+dom7717. NS a.root-servers.nil.
+dom7718. NS a.root-servers.nil.
+dom7719. NS a.root-servers.nil.
+dom7720. NS a.root-servers.nil.
+dom7721. NS a.root-servers.nil.
+dom7722. NS a.root-servers.nil.
+dom7723. NS a.root-servers.nil.
+dom7724. NS a.root-servers.nil.
+dom7725. NS a.root-servers.nil.
+dom7726. NS a.root-servers.nil.
+dom7727. NS a.root-servers.nil.
+dom7728. NS a.root-servers.nil.
+dom7729. NS a.root-servers.nil.
+dom7730. NS a.root-servers.nil.
+dom7731. NS a.root-servers.nil.
+dom7732. NS a.root-servers.nil.
+dom7733. NS a.root-servers.nil.
+dom7734. NS a.root-servers.nil.
+dom7735. NS a.root-servers.nil.
+dom7736. NS a.root-servers.nil.
+dom7737. NS a.root-servers.nil.
+dom7738. NS a.root-servers.nil.
+dom7739. NS a.root-servers.nil.
+dom7740. NS a.root-servers.nil.
+dom7741. NS a.root-servers.nil.
+dom7742. NS a.root-servers.nil.
+dom7743. NS a.root-servers.nil.
+dom7744. NS a.root-servers.nil.
+dom7745. NS a.root-servers.nil.
+dom7746. NS a.root-servers.nil.
+dom7747. NS a.root-servers.nil.
+dom7748. NS a.root-servers.nil.
+dom7749. NS a.root-servers.nil.
+dom7750. NS a.root-servers.nil.
+dom7751. NS a.root-servers.nil.
+dom7752. NS a.root-servers.nil.
+dom7753. NS a.root-servers.nil.
+dom7754. NS a.root-servers.nil.
+dom7755. NS a.root-servers.nil.
+dom7756. NS a.root-servers.nil.
+dom7757. NS a.root-servers.nil.
+dom7758. NS a.root-servers.nil.
+dom7759. NS a.root-servers.nil.
+dom7760. NS a.root-servers.nil.
+dom7761. NS a.root-servers.nil.
+dom7762. NS a.root-servers.nil.
+dom7763. NS a.root-servers.nil.
+dom7764. NS a.root-servers.nil.
+dom7765. NS a.root-servers.nil.
+dom7766. NS a.root-servers.nil.
+dom7767. NS a.root-servers.nil.
+dom7768. NS a.root-servers.nil.
+dom7769. NS a.root-servers.nil.
+dom7770. NS a.root-servers.nil.
+dom7771. NS a.root-servers.nil.
+dom7772. NS a.root-servers.nil.
+dom7773. NS a.root-servers.nil.
+dom7774. NS a.root-servers.nil.
+dom7775. NS a.root-servers.nil.
+dom7776. NS a.root-servers.nil.
+dom7777. NS a.root-servers.nil.
+dom7778. NS a.root-servers.nil.
+dom7779. NS a.root-servers.nil.
+dom7780. NS a.root-servers.nil.
+dom7781. NS a.root-servers.nil.
+dom7782. NS a.root-servers.nil.
+dom7783. NS a.root-servers.nil.
+dom7784. NS a.root-servers.nil.
+dom7785. NS a.root-servers.nil.
+dom7786. NS a.root-servers.nil.
+dom7787. NS a.root-servers.nil.
+dom7788. NS a.root-servers.nil.
+dom7789. NS a.root-servers.nil.
+dom7790. NS a.root-servers.nil.
+dom7791. NS a.root-servers.nil.
+dom7792. NS a.root-servers.nil.
+dom7793. NS a.root-servers.nil.
+dom7794. NS a.root-servers.nil.
+dom7795. NS a.root-servers.nil.
+dom7796. NS a.root-servers.nil.
+dom7797. NS a.root-servers.nil.
+dom7798. NS a.root-servers.nil.
+dom7799. NS a.root-servers.nil.
+dom7800. NS a.root-servers.nil.
+dom7801. NS a.root-servers.nil.
+dom7802. NS a.root-servers.nil.
+dom7803. NS a.root-servers.nil.
+dom7804. NS a.root-servers.nil.
+dom7805. NS a.root-servers.nil.
+dom7806. NS a.root-servers.nil.
+dom7807. NS a.root-servers.nil.
+dom7808. NS a.root-servers.nil.
+dom7809. NS a.root-servers.nil.
+dom7810. NS a.root-servers.nil.
+dom7811. NS a.root-servers.nil.
+dom7812. NS a.root-servers.nil.
+dom7813. NS a.root-servers.nil.
+dom7814. NS a.root-servers.nil.
+dom7815. NS a.root-servers.nil.
+dom7816. NS a.root-servers.nil.
+dom7817. NS a.root-servers.nil.
+dom7818. NS a.root-servers.nil.
+dom7819. NS a.root-servers.nil.
+dom7820. NS a.root-servers.nil.
+dom7821. NS a.root-servers.nil.
+dom7822. NS a.root-servers.nil.
+dom7823. NS a.root-servers.nil.
+dom7824. NS a.root-servers.nil.
+dom7825. NS a.root-servers.nil.
+dom7826. NS a.root-servers.nil.
+dom7827. NS a.root-servers.nil.
+dom7828. NS a.root-servers.nil.
+dom7829. NS a.root-servers.nil.
+dom7830. NS a.root-servers.nil.
+dom7831. NS a.root-servers.nil.
+dom7832. NS a.root-servers.nil.
+dom7833. NS a.root-servers.nil.
+dom7834. NS a.root-servers.nil.
+dom7835. NS a.root-servers.nil.
+dom7836. NS a.root-servers.nil.
+dom7837. NS a.root-servers.nil.
+dom7838. NS a.root-servers.nil.
+dom7839. NS a.root-servers.nil.
+dom7840. NS a.root-servers.nil.
+dom7841. NS a.root-servers.nil.
+dom7842. NS a.root-servers.nil.
+dom7843. NS a.root-servers.nil.
+dom7844. NS a.root-servers.nil.
+dom7845. NS a.root-servers.nil.
+dom7846. NS a.root-servers.nil.
+dom7847. NS a.root-servers.nil.
+dom7848. NS a.root-servers.nil.
+dom7849. NS a.root-servers.nil.
+dom7850. NS a.root-servers.nil.
+dom7851. NS a.root-servers.nil.
+dom7852. NS a.root-servers.nil.
+dom7853. NS a.root-servers.nil.
+dom7854. NS a.root-servers.nil.
+dom7855. NS a.root-servers.nil.
+dom7856. NS a.root-servers.nil.
+dom7857. NS a.root-servers.nil.
+dom7858. NS a.root-servers.nil.
+dom7859. NS a.root-servers.nil.
+dom7860. NS a.root-servers.nil.
+dom7861. NS a.root-servers.nil.
+dom7862. NS a.root-servers.nil.
+dom7863. NS a.root-servers.nil.
+dom7864. NS a.root-servers.nil.
+dom7865. NS a.root-servers.nil.
+dom7866. NS a.root-servers.nil.
+dom7867. NS a.root-servers.nil.
+dom7868. NS a.root-servers.nil.
+dom7869. NS a.root-servers.nil.
+dom7870. NS a.root-servers.nil.
+dom7871. NS a.root-servers.nil.
+dom7872. NS a.root-servers.nil.
+dom7873. NS a.root-servers.nil.
+dom7874. NS a.root-servers.nil.
+dom7875. NS a.root-servers.nil.
+dom7876. NS a.root-servers.nil.
+dom7877. NS a.root-servers.nil.
+dom7878. NS a.root-servers.nil.
+dom7879. NS a.root-servers.nil.
+dom7880. NS a.root-servers.nil.
+dom7881. NS a.root-servers.nil.
+dom7882. NS a.root-servers.nil.
+dom7883. NS a.root-servers.nil.
+dom7884. NS a.root-servers.nil.
+dom7885. NS a.root-servers.nil.
+dom7886. NS a.root-servers.nil.
+dom7887. NS a.root-servers.nil.
+dom7888. NS a.root-servers.nil.
+dom7889. NS a.root-servers.nil.
+dom7890. NS a.root-servers.nil.
+dom7891. NS a.root-servers.nil.
+dom7892. NS a.root-servers.nil.
+dom7893. NS a.root-servers.nil.
+dom7894. NS a.root-servers.nil.
+dom7895. NS a.root-servers.nil.
+dom7896. NS a.root-servers.nil.
+dom7897. NS a.root-servers.nil.
+dom7898. NS a.root-servers.nil.
+dom7899. NS a.root-servers.nil.
+dom7900. NS a.root-servers.nil.
+dom7901. NS a.root-servers.nil.
+dom7902. NS a.root-servers.nil.
+dom7903. NS a.root-servers.nil.
+dom7904. NS a.root-servers.nil.
+dom7905. NS a.root-servers.nil.
+dom7906. NS a.root-servers.nil.
+dom7907. NS a.root-servers.nil.
+dom7908. NS a.root-servers.nil.
+dom7909. NS a.root-servers.nil.
+dom7910. NS a.root-servers.nil.
+dom7911. NS a.root-servers.nil.
+dom7912. NS a.root-servers.nil.
+dom7913. NS a.root-servers.nil.
+dom7914. NS a.root-servers.nil.
+dom7915. NS a.root-servers.nil.
+dom7916. NS a.root-servers.nil.
+dom7917. NS a.root-servers.nil.
+dom7918. NS a.root-servers.nil.
+dom7919. NS a.root-servers.nil.
+dom7920. NS a.root-servers.nil.
+dom7921. NS a.root-servers.nil.
+dom7922. NS a.root-servers.nil.
+dom7923. NS a.root-servers.nil.
+dom7924. NS a.root-servers.nil.
+dom7925. NS a.root-servers.nil.
+dom7926. NS a.root-servers.nil.
+dom7927. NS a.root-servers.nil.
+dom7928. NS a.root-servers.nil.
+dom7929. NS a.root-servers.nil.
+dom7930. NS a.root-servers.nil.
+dom7931. NS a.root-servers.nil.
+dom7932. NS a.root-servers.nil.
+dom7933. NS a.root-servers.nil.
+dom7934. NS a.root-servers.nil.
+dom7935. NS a.root-servers.nil.
+dom7936. NS a.root-servers.nil.
+dom7937. NS a.root-servers.nil.
+dom7938. NS a.root-servers.nil.
+dom7939. NS a.root-servers.nil.
+dom7940. NS a.root-servers.nil.
+dom7941. NS a.root-servers.nil.
+dom7942. NS a.root-servers.nil.
+dom7943. NS a.root-servers.nil.
+dom7944. NS a.root-servers.nil.
+dom7945. NS a.root-servers.nil.
+dom7946. NS a.root-servers.nil.
+dom7947. NS a.root-servers.nil.
+dom7948. NS a.root-servers.nil.
+dom7949. NS a.root-servers.nil.
+dom7950. NS a.root-servers.nil.
+dom7951. NS a.root-servers.nil.
+dom7952. NS a.root-servers.nil.
+dom7953. NS a.root-servers.nil.
+dom7954. NS a.root-servers.nil.
+dom7955. NS a.root-servers.nil.
+dom7956. NS a.root-servers.nil.
+dom7957. NS a.root-servers.nil.
+dom7958. NS a.root-servers.nil.
+dom7959. NS a.root-servers.nil.
+dom7960. NS a.root-servers.nil.
+dom7961. NS a.root-servers.nil.
+dom7962. NS a.root-servers.nil.
+dom7963. NS a.root-servers.nil.
+dom7964. NS a.root-servers.nil.
+dom7965. NS a.root-servers.nil.
+dom7966. NS a.root-servers.nil.
+dom7967. NS a.root-servers.nil.
+dom7968. NS a.root-servers.nil.
+dom7969. NS a.root-servers.nil.
+dom7970. NS a.root-servers.nil.
+dom7971. NS a.root-servers.nil.
+dom7972. NS a.root-servers.nil.
+dom7973. NS a.root-servers.nil.
+dom7974. NS a.root-servers.nil.
+dom7975. NS a.root-servers.nil.
+dom7976. NS a.root-servers.nil.
+dom7977. NS a.root-servers.nil.
+dom7978. NS a.root-servers.nil.
+dom7979. NS a.root-servers.nil.
+dom7980. NS a.root-servers.nil.
+dom7981. NS a.root-servers.nil.
+dom7982. NS a.root-servers.nil.
+dom7983. NS a.root-servers.nil.
+dom7984. NS a.root-servers.nil.
+dom7985. NS a.root-servers.nil.
+dom7986. NS a.root-servers.nil.
+dom7987. NS a.root-servers.nil.
+dom7988. NS a.root-servers.nil.
+dom7989. NS a.root-servers.nil.
+dom7990. NS a.root-servers.nil.
+dom7991. NS a.root-servers.nil.
+dom7992. NS a.root-servers.nil.
+dom7993. NS a.root-servers.nil.
+dom7994. NS a.root-servers.nil.
+dom7995. NS a.root-servers.nil.
+dom7996. NS a.root-servers.nil.
+dom7997. NS a.root-servers.nil.
+dom7998. NS a.root-servers.nil.
+dom7999. NS a.root-servers.nil.
+dom8000. NS a.root-servers.nil.
+dom8001. NS a.root-servers.nil.
+dom8002. NS a.root-servers.nil.
+dom8003. NS a.root-servers.nil.
+dom8004. NS a.root-servers.nil.
+dom8005. NS a.root-servers.nil.
+dom8006. NS a.root-servers.nil.
+dom8007. NS a.root-servers.nil.
+dom8008. NS a.root-servers.nil.
+dom8009. NS a.root-servers.nil.
+dom8010. NS a.root-servers.nil.
+dom8011. NS a.root-servers.nil.
+dom8012. NS a.root-servers.nil.
+dom8013. NS a.root-servers.nil.
+dom8014. NS a.root-servers.nil.
+dom8015. NS a.root-servers.nil.
+dom8016. NS a.root-servers.nil.
+dom8017. NS a.root-servers.nil.
+dom8018. NS a.root-servers.nil.
+dom8019. NS a.root-servers.nil.
+dom8020. NS a.root-servers.nil.
+dom8021. NS a.root-servers.nil.
+dom8022. NS a.root-servers.nil.
+dom8023. NS a.root-servers.nil.
+dom8024. NS a.root-servers.nil.
+dom8025. NS a.root-servers.nil.
+dom8026. NS a.root-servers.nil.
+dom8027. NS a.root-servers.nil.
+dom8028. NS a.root-servers.nil.
+dom8029. NS a.root-servers.nil.
+dom8030. NS a.root-servers.nil.
+dom8031. NS a.root-servers.nil.
+dom8032. NS a.root-servers.nil.
+dom8033. NS a.root-servers.nil.
+dom8034. NS a.root-servers.nil.
+dom8035. NS a.root-servers.nil.
+dom8036. NS a.root-servers.nil.
+dom8037. NS a.root-servers.nil.
+dom8038. NS a.root-servers.nil.
+dom8039. NS a.root-servers.nil.
+dom8040. NS a.root-servers.nil.
+dom8041. NS a.root-servers.nil.
+dom8042. NS a.root-servers.nil.
+dom8043. NS a.root-servers.nil.
+dom8044. NS a.root-servers.nil.
+dom8045. NS a.root-servers.nil.
+dom8046. NS a.root-servers.nil.
+dom8047. NS a.root-servers.nil.
+dom8048. NS a.root-servers.nil.
+dom8049. NS a.root-servers.nil.
+dom8050. NS a.root-servers.nil.
+dom8051. NS a.root-servers.nil.
+dom8052. NS a.root-servers.nil.
+dom8053. NS a.root-servers.nil.
+dom8054. NS a.root-servers.nil.
+dom8055. NS a.root-servers.nil.
+dom8056. NS a.root-servers.nil.
+dom8057. NS a.root-servers.nil.
+dom8058. NS a.root-servers.nil.
+dom8059. NS a.root-servers.nil.
+dom8060. NS a.root-servers.nil.
+dom8061. NS a.root-servers.nil.
+dom8062. NS a.root-servers.nil.
+dom8063. NS a.root-servers.nil.
+dom8064. NS a.root-servers.nil.
+dom8065. NS a.root-servers.nil.
+dom8066. NS a.root-servers.nil.
+dom8067. NS a.root-servers.nil.
+dom8068. NS a.root-servers.nil.
+dom8069. NS a.root-servers.nil.
+dom8070. NS a.root-servers.nil.
+dom8071. NS a.root-servers.nil.
+dom8072. NS a.root-servers.nil.
+dom8073. NS a.root-servers.nil.
+dom8074. NS a.root-servers.nil.
+dom8075. NS a.root-servers.nil.
+dom8076. NS a.root-servers.nil.
+dom8077. NS a.root-servers.nil.
+dom8078. NS a.root-servers.nil.
+dom8079. NS a.root-servers.nil.
+dom8080. NS a.root-servers.nil.
+dom8081. NS a.root-servers.nil.
+dom8082. NS a.root-servers.nil.
+dom8083. NS a.root-servers.nil.
+dom8084. NS a.root-servers.nil.
+dom8085. NS a.root-servers.nil.
+dom8086. NS a.root-servers.nil.
+dom8087. NS a.root-servers.nil.
+dom8088. NS a.root-servers.nil.
+dom8089. NS a.root-servers.nil.
+dom8090. NS a.root-servers.nil.
+dom8091. NS a.root-servers.nil.
+dom8092. NS a.root-servers.nil.
+dom8093. NS a.root-servers.nil.
+dom8094. NS a.root-servers.nil.
+dom8095. NS a.root-servers.nil.
+dom8096. NS a.root-servers.nil.
+dom8097. NS a.root-servers.nil.
+dom8098. NS a.root-servers.nil.
+dom8099. NS a.root-servers.nil.
+dom8100. NS a.root-servers.nil.
+dom8101. NS a.root-servers.nil.
+dom8102. NS a.root-servers.nil.
+dom8103. NS a.root-servers.nil.
+dom8104. NS a.root-servers.nil.
+dom8105. NS a.root-servers.nil.
+dom8106. NS a.root-servers.nil.
+dom8107. NS a.root-servers.nil.
+dom8108. NS a.root-servers.nil.
+dom8109. NS a.root-servers.nil.
+dom8110. NS a.root-servers.nil.
+dom8111. NS a.root-servers.nil.
+dom8112. NS a.root-servers.nil.
+dom8113. NS a.root-servers.nil.
+dom8114. NS a.root-servers.nil.
+dom8115. NS a.root-servers.nil.
+dom8116. NS a.root-servers.nil.
+dom8117. NS a.root-servers.nil.
+dom8118. NS a.root-servers.nil.
+dom8119. NS a.root-servers.nil.
+dom8120. NS a.root-servers.nil.
+dom8121. NS a.root-servers.nil.
+dom8122. NS a.root-servers.nil.
+dom8123. NS a.root-servers.nil.
+dom8124. NS a.root-servers.nil.
+dom8125. NS a.root-servers.nil.
+dom8126. NS a.root-servers.nil.
+dom8127. NS a.root-servers.nil.
+dom8128. NS a.root-servers.nil.
+dom8129. NS a.root-servers.nil.
+dom8130. NS a.root-servers.nil.
+dom8131. NS a.root-servers.nil.
+dom8132. NS a.root-servers.nil.
+dom8133. NS a.root-servers.nil.
+dom8134. NS a.root-servers.nil.
+dom8135. NS a.root-servers.nil.
+dom8136. NS a.root-servers.nil.
+dom8137. NS a.root-servers.nil.
+dom8138. NS a.root-servers.nil.
+dom8139. NS a.root-servers.nil.
+dom8140. NS a.root-servers.nil.
+dom8141. NS a.root-servers.nil.
+dom8142. NS a.root-servers.nil.
+dom8143. NS a.root-servers.nil.
+dom8144. NS a.root-servers.nil.
+dom8145. NS a.root-servers.nil.
+dom8146. NS a.root-servers.nil.
+dom8147. NS a.root-servers.nil.
+dom8148. NS a.root-servers.nil.
+dom8149. NS a.root-servers.nil.
+dom8150. NS a.root-servers.nil.
+dom8151. NS a.root-servers.nil.
+dom8152. NS a.root-servers.nil.
+dom8153. NS a.root-servers.nil.
+dom8154. NS a.root-servers.nil.
+dom8155. NS a.root-servers.nil.
+dom8156. NS a.root-servers.nil.
+dom8157. NS a.root-servers.nil.
+dom8158. NS a.root-servers.nil.
+dom8159. NS a.root-servers.nil.
+dom8160. NS a.root-servers.nil.
+dom8161. NS a.root-servers.nil.
+dom8162. NS a.root-servers.nil.
+dom8163. NS a.root-servers.nil.
+dom8164. NS a.root-servers.nil.
+dom8165. NS a.root-servers.nil.
+dom8166. NS a.root-servers.nil.
+dom8167. NS a.root-servers.nil.
+dom8168. NS a.root-servers.nil.
+dom8169. NS a.root-servers.nil.
+dom8170. NS a.root-servers.nil.
+dom8171. NS a.root-servers.nil.
+dom8172. NS a.root-servers.nil.
+dom8173. NS a.root-servers.nil.
+dom8174. NS a.root-servers.nil.
+dom8175. NS a.root-servers.nil.
+dom8176. NS a.root-servers.nil.
+dom8177. NS a.root-servers.nil.
+dom8178. NS a.root-servers.nil.
+dom8179. NS a.root-servers.nil.
+dom8180. NS a.root-servers.nil.
+dom8181. NS a.root-servers.nil.
+dom8182. NS a.root-servers.nil.
+dom8183. NS a.root-servers.nil.
+dom8184. NS a.root-servers.nil.
+dom8185. NS a.root-servers.nil.
+dom8186. NS a.root-servers.nil.
+dom8187. NS a.root-servers.nil.
+dom8188. NS a.root-servers.nil.
+dom8189. NS a.root-servers.nil.
+dom8190. NS a.root-servers.nil.
+dom8191. NS a.root-servers.nil.
+dom8192. NS a.root-servers.nil.
+dom8193. NS a.root-servers.nil.
+dom8194. NS a.root-servers.nil.
+dom8195. NS a.root-servers.nil.
+dom8196. NS a.root-servers.nil.
+dom8197. NS a.root-servers.nil.
+dom8198. NS a.root-servers.nil.
+dom8199. NS a.root-servers.nil.
+dom8200. NS a.root-servers.nil.
+dom8201. NS a.root-servers.nil.
+dom8202. NS a.root-servers.nil.
+dom8203. NS a.root-servers.nil.
+dom8204. NS a.root-servers.nil.
+dom8205. NS a.root-servers.nil.
+dom8206. NS a.root-servers.nil.
+dom8207. NS a.root-servers.nil.
+dom8208. NS a.root-servers.nil.
+dom8209. NS a.root-servers.nil.
+dom8210. NS a.root-servers.nil.
+dom8211. NS a.root-servers.nil.
+dom8212. NS a.root-servers.nil.
+dom8213. NS a.root-servers.nil.
+dom8214. NS a.root-servers.nil.
+dom8215. NS a.root-servers.nil.
+dom8216. NS a.root-servers.nil.
+dom8217. NS a.root-servers.nil.
+dom8218. NS a.root-servers.nil.
+dom8219. NS a.root-servers.nil.
+dom8220. NS a.root-servers.nil.
+dom8221. NS a.root-servers.nil.
+dom8222. NS a.root-servers.nil.
+dom8223. NS a.root-servers.nil.
+dom8224. NS a.root-servers.nil.
+dom8225. NS a.root-servers.nil.
+dom8226. NS a.root-servers.nil.
+dom8227. NS a.root-servers.nil.
+dom8228. NS a.root-servers.nil.
+dom8229. NS a.root-servers.nil.
+dom8230. NS a.root-servers.nil.
+dom8231. NS a.root-servers.nil.
+dom8232. NS a.root-servers.nil.
+dom8233. NS a.root-servers.nil.
+dom8234. NS a.root-servers.nil.
+dom8235. NS a.root-servers.nil.
+dom8236. NS a.root-servers.nil.
+dom8237. NS a.root-servers.nil.
+dom8238. NS a.root-servers.nil.
+dom8239. NS a.root-servers.nil.
+dom8240. NS a.root-servers.nil.
+dom8241. NS a.root-servers.nil.
+dom8242. NS a.root-servers.nil.
+dom8243. NS a.root-servers.nil.
+dom8244. NS a.root-servers.nil.
+dom8245. NS a.root-servers.nil.
+dom8246. NS a.root-servers.nil.
+dom8247. NS a.root-servers.nil.
+dom8248. NS a.root-servers.nil.
+dom8249. NS a.root-servers.nil.
+dom8250. NS a.root-servers.nil.
+dom8251. NS a.root-servers.nil.
+dom8252. NS a.root-servers.nil.
+dom8253. NS a.root-servers.nil.
+dom8254. NS a.root-servers.nil.
+dom8255. NS a.root-servers.nil.
+dom8256. NS a.root-servers.nil.
+dom8257. NS a.root-servers.nil.
+dom8258. NS a.root-servers.nil.
+dom8259. NS a.root-servers.nil.
+dom8260. NS a.root-servers.nil.
+dom8261. NS a.root-servers.nil.
+dom8262. NS a.root-servers.nil.
+dom8263. NS a.root-servers.nil.
+dom8264. NS a.root-servers.nil.
+dom8265. NS a.root-servers.nil.
+dom8266. NS a.root-servers.nil.
+dom8267. NS a.root-servers.nil.
+dom8268. NS a.root-servers.nil.
+dom8269. NS a.root-servers.nil.
+dom8270. NS a.root-servers.nil.
+dom8271. NS a.root-servers.nil.
+dom8272. NS a.root-servers.nil.
+dom8273. NS a.root-servers.nil.
+dom8274. NS a.root-servers.nil.
+dom8275. NS a.root-servers.nil.
+dom8276. NS a.root-servers.nil.
+dom8277. NS a.root-servers.nil.
+dom8278. NS a.root-servers.nil.
+dom8279. NS a.root-servers.nil.
+dom8280. NS a.root-servers.nil.
+dom8281. NS a.root-servers.nil.
+dom8282. NS a.root-servers.nil.
+dom8283. NS a.root-servers.nil.
+dom8284. NS a.root-servers.nil.
+dom8285. NS a.root-servers.nil.
+dom8286. NS a.root-servers.nil.
+dom8287. NS a.root-servers.nil.
+dom8288. NS a.root-servers.nil.
+dom8289. NS a.root-servers.nil.
+dom8290. NS a.root-servers.nil.
+dom8291. NS a.root-servers.nil.
+dom8292. NS a.root-servers.nil.
+dom8293. NS a.root-servers.nil.
+dom8294. NS a.root-servers.nil.
+dom8295. NS a.root-servers.nil.
+dom8296. NS a.root-servers.nil.
+dom8297. NS a.root-servers.nil.
+dom8298. NS a.root-servers.nil.
+dom8299. NS a.root-servers.nil.
+dom8300. NS a.root-servers.nil.
+dom8301. NS a.root-servers.nil.
+dom8302. NS a.root-servers.nil.
+dom8303. NS a.root-servers.nil.
+dom8304. NS a.root-servers.nil.
+dom8305. NS a.root-servers.nil.
+dom8306. NS a.root-servers.nil.
+dom8307. NS a.root-servers.nil.
+dom8308. NS a.root-servers.nil.
+dom8309. NS a.root-servers.nil.
+dom8310. NS a.root-servers.nil.
+dom8311. NS a.root-servers.nil.
+dom8312. NS a.root-servers.nil.
+dom8313. NS a.root-servers.nil.
+dom8314. NS a.root-servers.nil.
+dom8315. NS a.root-servers.nil.
+dom8316. NS a.root-servers.nil.
+dom8317. NS a.root-servers.nil.
+dom8318. NS a.root-servers.nil.
+dom8319. NS a.root-servers.nil.
+dom8320. NS a.root-servers.nil.
+dom8321. NS a.root-servers.nil.
+dom8322. NS a.root-servers.nil.
+dom8323. NS a.root-servers.nil.
+dom8324. NS a.root-servers.nil.
+dom8325. NS a.root-servers.nil.
+dom8326. NS a.root-servers.nil.
+dom8327. NS a.root-servers.nil.
+dom8328. NS a.root-servers.nil.
+dom8329. NS a.root-servers.nil.
+dom8330. NS a.root-servers.nil.
+dom8331. NS a.root-servers.nil.
+dom8332. NS a.root-servers.nil.
+dom8333. NS a.root-servers.nil.
+dom8334. NS a.root-servers.nil.
+dom8335. NS a.root-servers.nil.
+dom8336. NS a.root-servers.nil.
+dom8337. NS a.root-servers.nil.
+dom8338. NS a.root-servers.nil.
+dom8339. NS a.root-servers.nil.
+dom8340. NS a.root-servers.nil.
+dom8341. NS a.root-servers.nil.
+dom8342. NS a.root-servers.nil.
+dom8343. NS a.root-servers.nil.
+dom8344. NS a.root-servers.nil.
+dom8345. NS a.root-servers.nil.
+dom8346. NS a.root-servers.nil.
+dom8347. NS a.root-servers.nil.
+dom8348. NS a.root-servers.nil.
+dom8349. NS a.root-servers.nil.
+dom8350. NS a.root-servers.nil.
+dom8351. NS a.root-servers.nil.
+dom8352. NS a.root-servers.nil.
+dom8353. NS a.root-servers.nil.
+dom8354. NS a.root-servers.nil.
+dom8355. NS a.root-servers.nil.
+dom8356. NS a.root-servers.nil.
+dom8357. NS a.root-servers.nil.
+dom8358. NS a.root-servers.nil.
+dom8359. NS a.root-servers.nil.
+dom8360. NS a.root-servers.nil.
+dom8361. NS a.root-servers.nil.
+dom8362. NS a.root-servers.nil.
+dom8363. NS a.root-servers.nil.
+dom8364. NS a.root-servers.nil.
+dom8365. NS a.root-servers.nil.
+dom8366. NS a.root-servers.nil.
+dom8367. NS a.root-servers.nil.
+dom8368. NS a.root-servers.nil.
+dom8369. NS a.root-servers.nil.
+dom8370. NS a.root-servers.nil.
+dom8371. NS a.root-servers.nil.
+dom8372. NS a.root-servers.nil.
+dom8373. NS a.root-servers.nil.
+dom8374. NS a.root-servers.nil.
+dom8375. NS a.root-servers.nil.
+dom8376. NS a.root-servers.nil.
+dom8377. NS a.root-servers.nil.
+dom8378. NS a.root-servers.nil.
+dom8379. NS a.root-servers.nil.
+dom8380. NS a.root-servers.nil.
+dom8381. NS a.root-servers.nil.
+dom8382. NS a.root-servers.nil.
+dom8383. NS a.root-servers.nil.
+dom8384. NS a.root-servers.nil.
+dom8385. NS a.root-servers.nil.
+dom8386. NS a.root-servers.nil.
+dom8387. NS a.root-servers.nil.
+dom8388. NS a.root-servers.nil.
+dom8389. NS a.root-servers.nil.
+dom8390. NS a.root-servers.nil.
+dom8391. NS a.root-servers.nil.
+dom8392. NS a.root-servers.nil.
+dom8393. NS a.root-servers.nil.
+dom8394. NS a.root-servers.nil.
+dom8395. NS a.root-servers.nil.
+dom8396. NS a.root-servers.nil.
+dom8397. NS a.root-servers.nil.
+dom8398. NS a.root-servers.nil.
+dom8399. NS a.root-servers.nil.
+dom8400. NS a.root-servers.nil.
+dom8401. NS a.root-servers.nil.
+dom8402. NS a.root-servers.nil.
+dom8403. NS a.root-servers.nil.
+dom8404. NS a.root-servers.nil.
+dom8405. NS a.root-servers.nil.
+dom8406. NS a.root-servers.nil.
+dom8407. NS a.root-servers.nil.
+dom8408. NS a.root-servers.nil.
+dom8409. NS a.root-servers.nil.
+dom8410. NS a.root-servers.nil.
+dom8411. NS a.root-servers.nil.
+dom8412. NS a.root-servers.nil.
+dom8413. NS a.root-servers.nil.
+dom8414. NS a.root-servers.nil.
+dom8415. NS a.root-servers.nil.
+dom8416. NS a.root-servers.nil.
+dom8417. NS a.root-servers.nil.
+dom8418. NS a.root-servers.nil.
+dom8419. NS a.root-servers.nil.
+dom8420. NS a.root-servers.nil.
+dom8421. NS a.root-servers.nil.
+dom8422. NS a.root-servers.nil.
+dom8423. NS a.root-servers.nil.
+dom8424. NS a.root-servers.nil.
+dom8425. NS a.root-servers.nil.
+dom8426. NS a.root-servers.nil.
+dom8427. NS a.root-servers.nil.
+dom8428. NS a.root-servers.nil.
+dom8429. NS a.root-servers.nil.
+dom8430. NS a.root-servers.nil.
+dom8431. NS a.root-servers.nil.
+dom8432. NS a.root-servers.nil.
+dom8433. NS a.root-servers.nil.
+dom8434. NS a.root-servers.nil.
+dom8435. NS a.root-servers.nil.
+dom8436. NS a.root-servers.nil.
+dom8437. NS a.root-servers.nil.
+dom8438. NS a.root-servers.nil.
+dom8439. NS a.root-servers.nil.
+dom8440. NS a.root-servers.nil.
+dom8441. NS a.root-servers.nil.
+dom8442. NS a.root-servers.nil.
+dom8443. NS a.root-servers.nil.
+dom8444. NS a.root-servers.nil.
+dom8445. NS a.root-servers.nil.
+dom8446. NS a.root-servers.nil.
+dom8447. NS a.root-servers.nil.
+dom8448. NS a.root-servers.nil.
+dom8449. NS a.root-servers.nil.
+dom8450. NS a.root-servers.nil.
+dom8451. NS a.root-servers.nil.
+dom8452. NS a.root-servers.nil.
+dom8453. NS a.root-servers.nil.
+dom8454. NS a.root-servers.nil.
+dom8455. NS a.root-servers.nil.
+dom8456. NS a.root-servers.nil.
+dom8457. NS a.root-servers.nil.
+dom8458. NS a.root-servers.nil.
+dom8459. NS a.root-servers.nil.
+dom8460. NS a.root-servers.nil.
+dom8461. NS a.root-servers.nil.
+dom8462. NS a.root-servers.nil.
+dom8463. NS a.root-servers.nil.
+dom8464. NS a.root-servers.nil.
+dom8465. NS a.root-servers.nil.
+dom8466. NS a.root-servers.nil.
+dom8467. NS a.root-servers.nil.
+dom8468. NS a.root-servers.nil.
+dom8469. NS a.root-servers.nil.
+dom8470. NS a.root-servers.nil.
+dom8471. NS a.root-servers.nil.
+dom8472. NS a.root-servers.nil.
+dom8473. NS a.root-servers.nil.
+dom8474. NS a.root-servers.nil.
+dom8475. NS a.root-servers.nil.
+dom8476. NS a.root-servers.nil.
+dom8477. NS a.root-servers.nil.
+dom8478. NS a.root-servers.nil.
+dom8479. NS a.root-servers.nil.
+dom8480. NS a.root-servers.nil.
+dom8481. NS a.root-servers.nil.
+dom8482. NS a.root-servers.nil.
+dom8483. NS a.root-servers.nil.
+dom8484. NS a.root-servers.nil.
+dom8485. NS a.root-servers.nil.
+dom8486. NS a.root-servers.nil.
+dom8487. NS a.root-servers.nil.
+dom8488. NS a.root-servers.nil.
+dom8489. NS a.root-servers.nil.
+dom8490. NS a.root-servers.nil.
+dom8491. NS a.root-servers.nil.
+dom8492. NS a.root-servers.nil.
+dom8493. NS a.root-servers.nil.
+dom8494. NS a.root-servers.nil.
+dom8495. NS a.root-servers.nil.
+dom8496. NS a.root-servers.nil.
+dom8497. NS a.root-servers.nil.
+dom8498. NS a.root-servers.nil.
+dom8499. NS a.root-servers.nil.
+dom8500. NS a.root-servers.nil.
+dom8501. NS a.root-servers.nil.
+dom8502. NS a.root-servers.nil.
+dom8503. NS a.root-servers.nil.
+dom8504. NS a.root-servers.nil.
+dom8505. NS a.root-servers.nil.
+dom8506. NS a.root-servers.nil.
+dom8507. NS a.root-servers.nil.
+dom8508. NS a.root-servers.nil.
+dom8509. NS a.root-servers.nil.
+dom8510. NS a.root-servers.nil.
+dom8511. NS a.root-servers.nil.
+dom8512. NS a.root-servers.nil.
+dom8513. NS a.root-servers.nil.
+dom8514. NS a.root-servers.nil.
+dom8515. NS a.root-servers.nil.
+dom8516. NS a.root-servers.nil.
+dom8517. NS a.root-servers.nil.
+dom8518. NS a.root-servers.nil.
+dom8519. NS a.root-servers.nil.
+dom8520. NS a.root-servers.nil.
+dom8521. NS a.root-servers.nil.
+dom8522. NS a.root-servers.nil.
+dom8523. NS a.root-servers.nil.
+dom8524. NS a.root-servers.nil.
+dom8525. NS a.root-servers.nil.
+dom8526. NS a.root-servers.nil.
+dom8527. NS a.root-servers.nil.
+dom8528. NS a.root-servers.nil.
+dom8529. NS a.root-servers.nil.
+dom8530. NS a.root-servers.nil.
+dom8531. NS a.root-servers.nil.
+dom8532. NS a.root-servers.nil.
+dom8533. NS a.root-servers.nil.
+dom8534. NS a.root-servers.nil.
+dom8535. NS a.root-servers.nil.
+dom8536. NS a.root-servers.nil.
+dom8537. NS a.root-servers.nil.
+dom8538. NS a.root-servers.nil.
+dom8539. NS a.root-servers.nil.
+dom8540. NS a.root-servers.nil.
+dom8541. NS a.root-servers.nil.
+dom8542. NS a.root-servers.nil.
+dom8543. NS a.root-servers.nil.
+dom8544. NS a.root-servers.nil.
+dom8545. NS a.root-servers.nil.
+dom8546. NS a.root-servers.nil.
+dom8547. NS a.root-servers.nil.
+dom8548. NS a.root-servers.nil.
+dom8549. NS a.root-servers.nil.
+dom8550. NS a.root-servers.nil.
+dom8551. NS a.root-servers.nil.
+dom8552. NS a.root-servers.nil.
+dom8553. NS a.root-servers.nil.
+dom8554. NS a.root-servers.nil.
+dom8555. NS a.root-servers.nil.
+dom8556. NS a.root-servers.nil.
+dom8557. NS a.root-servers.nil.
+dom8558. NS a.root-servers.nil.
+dom8559. NS a.root-servers.nil.
+dom8560. NS a.root-servers.nil.
+dom8561. NS a.root-servers.nil.
+dom8562. NS a.root-servers.nil.
+dom8563. NS a.root-servers.nil.
+dom8564. NS a.root-servers.nil.
+dom8565. NS a.root-servers.nil.
+dom8566. NS a.root-servers.nil.
+dom8567. NS a.root-servers.nil.
+dom8568. NS a.root-servers.nil.
+dom8569. NS a.root-servers.nil.
+dom8570. NS a.root-servers.nil.
+dom8571. NS a.root-servers.nil.
+dom8572. NS a.root-servers.nil.
+dom8573. NS a.root-servers.nil.
+dom8574. NS a.root-servers.nil.
+dom8575. NS a.root-servers.nil.
+dom8576. NS a.root-servers.nil.
+dom8577. NS a.root-servers.nil.
+dom8578. NS a.root-servers.nil.
+dom8579. NS a.root-servers.nil.
+dom8580. NS a.root-servers.nil.
+dom8581. NS a.root-servers.nil.
+dom8582. NS a.root-servers.nil.
+dom8583. NS a.root-servers.nil.
+dom8584. NS a.root-servers.nil.
+dom8585. NS a.root-servers.nil.
+dom8586. NS a.root-servers.nil.
+dom8587. NS a.root-servers.nil.
+dom8588. NS a.root-servers.nil.
+dom8589. NS a.root-servers.nil.
+dom8590. NS a.root-servers.nil.
+dom8591. NS a.root-servers.nil.
+dom8592. NS a.root-servers.nil.
+dom8593. NS a.root-servers.nil.
+dom8594. NS a.root-servers.nil.
+dom8595. NS a.root-servers.nil.
+dom8596. NS a.root-servers.nil.
+dom8597. NS a.root-servers.nil.
+dom8598. NS a.root-servers.nil.
+dom8599. NS a.root-servers.nil.
+dom8600. NS a.root-servers.nil.
+dom8601. NS a.root-servers.nil.
+dom8602. NS a.root-servers.nil.
+dom8603. NS a.root-servers.nil.
+dom8604. NS a.root-servers.nil.
+dom8605. NS a.root-servers.nil.
+dom8606. NS a.root-servers.nil.
+dom8607. NS a.root-servers.nil.
+dom8608. NS a.root-servers.nil.
+dom8609. NS a.root-servers.nil.
+dom8610. NS a.root-servers.nil.
+dom8611. NS a.root-servers.nil.
+dom8612. NS a.root-servers.nil.
+dom8613. NS a.root-servers.nil.
+dom8614. NS a.root-servers.nil.
+dom8615. NS a.root-servers.nil.
+dom8616. NS a.root-servers.nil.
+dom8617. NS a.root-servers.nil.
+dom8618. NS a.root-servers.nil.
+dom8619. NS a.root-servers.nil.
+dom8620. NS a.root-servers.nil.
+dom8621. NS a.root-servers.nil.
+dom8622. NS a.root-servers.nil.
+dom8623. NS a.root-servers.nil.
+dom8624. NS a.root-servers.nil.
+dom8625. NS a.root-servers.nil.
+dom8626. NS a.root-servers.nil.
+dom8627. NS a.root-servers.nil.
+dom8628. NS a.root-servers.nil.
+dom8629. NS a.root-servers.nil.
+dom8630. NS a.root-servers.nil.
+dom8631. NS a.root-servers.nil.
+dom8632. NS a.root-servers.nil.
+dom8633. NS a.root-servers.nil.
+dom8634. NS a.root-servers.nil.
+dom8635. NS a.root-servers.nil.
+dom8636. NS a.root-servers.nil.
+dom8637. NS a.root-servers.nil.
+dom8638. NS a.root-servers.nil.
+dom8639. NS a.root-servers.nil.
+dom8640. NS a.root-servers.nil.
+dom8641. NS a.root-servers.nil.
+dom8642. NS a.root-servers.nil.
+dom8643. NS a.root-servers.nil.
+dom8644. NS a.root-servers.nil.
+dom8645. NS a.root-servers.nil.
+dom8646. NS a.root-servers.nil.
+dom8647. NS a.root-servers.nil.
+dom8648. NS a.root-servers.nil.
+dom8649. NS a.root-servers.nil.
+dom8650. NS a.root-servers.nil.
+dom8651. NS a.root-servers.nil.
+dom8652. NS a.root-servers.nil.
+dom8653. NS a.root-servers.nil.
+dom8654. NS a.root-servers.nil.
+dom8655. NS a.root-servers.nil.
+dom8656. NS a.root-servers.nil.
+dom8657. NS a.root-servers.nil.
+dom8658. NS a.root-servers.nil.
+dom8659. NS a.root-servers.nil.
+dom8660. NS a.root-servers.nil.
+dom8661. NS a.root-servers.nil.
+dom8662. NS a.root-servers.nil.
+dom8663. NS a.root-servers.nil.
+dom8664. NS a.root-servers.nil.
+dom8665. NS a.root-servers.nil.
+dom8666. NS a.root-servers.nil.
+dom8667. NS a.root-servers.nil.
+dom8668. NS a.root-servers.nil.
+dom8669. NS a.root-servers.nil.
+dom8670. NS a.root-servers.nil.
+dom8671. NS a.root-servers.nil.
+dom8672. NS a.root-servers.nil.
+dom8673. NS a.root-servers.nil.
+dom8674. NS a.root-servers.nil.
+dom8675. NS a.root-servers.nil.
+dom8676. NS a.root-servers.nil.
+dom8677. NS a.root-servers.nil.
+dom8678. NS a.root-servers.nil.
+dom8679. NS a.root-servers.nil.
+dom8680. NS a.root-servers.nil.
+dom8681. NS a.root-servers.nil.
+dom8682. NS a.root-servers.nil.
+dom8683. NS a.root-servers.nil.
+dom8684. NS a.root-servers.nil.
+dom8685. NS a.root-servers.nil.
+dom8686. NS a.root-servers.nil.
+dom8687. NS a.root-servers.nil.
+dom8688. NS a.root-servers.nil.
+dom8689. NS a.root-servers.nil.
+dom8690. NS a.root-servers.nil.
+dom8691. NS a.root-servers.nil.
+dom8692. NS a.root-servers.nil.
+dom8693. NS a.root-servers.nil.
+dom8694. NS a.root-servers.nil.
+dom8695. NS a.root-servers.nil.
+dom8696. NS a.root-servers.nil.
+dom8697. NS a.root-servers.nil.
+dom8698. NS a.root-servers.nil.
+dom8699. NS a.root-servers.nil.
+dom8700. NS a.root-servers.nil.
+dom8701. NS a.root-servers.nil.
+dom8702. NS a.root-servers.nil.
+dom8703. NS a.root-servers.nil.
+dom8704. NS a.root-servers.nil.
+dom8705. NS a.root-servers.nil.
+dom8706. NS a.root-servers.nil.
+dom8707. NS a.root-servers.nil.
+dom8708. NS a.root-servers.nil.
+dom8709. NS a.root-servers.nil.
+dom8710. NS a.root-servers.nil.
+dom8711. NS a.root-servers.nil.
+dom8712. NS a.root-servers.nil.
+dom8713. NS a.root-servers.nil.
+dom8714. NS a.root-servers.nil.
+dom8715. NS a.root-servers.nil.
+dom8716. NS a.root-servers.nil.
+dom8717. NS a.root-servers.nil.
+dom8718. NS a.root-servers.nil.
+dom8719. NS a.root-servers.nil.
+dom8720. NS a.root-servers.nil.
+dom8721. NS a.root-servers.nil.
+dom8722. NS a.root-servers.nil.
+dom8723. NS a.root-servers.nil.
+dom8724. NS a.root-servers.nil.
+dom8725. NS a.root-servers.nil.
+dom8726. NS a.root-servers.nil.
+dom8727. NS a.root-servers.nil.
+dom8728. NS a.root-servers.nil.
+dom8729. NS a.root-servers.nil.
+dom8730. NS a.root-servers.nil.
+dom8731. NS a.root-servers.nil.
+dom8732. NS a.root-servers.nil.
+dom8733. NS a.root-servers.nil.
+dom8734. NS a.root-servers.nil.
+dom8735. NS a.root-servers.nil.
+dom8736. NS a.root-servers.nil.
+dom8737. NS a.root-servers.nil.
+dom8738. NS a.root-servers.nil.
+dom8739. NS a.root-servers.nil.
+dom8740. NS a.root-servers.nil.
+dom8741. NS a.root-servers.nil.
+dom8742. NS a.root-servers.nil.
+dom8743. NS a.root-servers.nil.
+dom8744. NS a.root-servers.nil.
+dom8745. NS a.root-servers.nil.
+dom8746. NS a.root-servers.nil.
+dom8747. NS a.root-servers.nil.
+dom8748. NS a.root-servers.nil.
+dom8749. NS a.root-servers.nil.
+dom8750. NS a.root-servers.nil.
+dom8751. NS a.root-servers.nil.
+dom8752. NS a.root-servers.nil.
+dom8753. NS a.root-servers.nil.
+dom8754. NS a.root-servers.nil.
+dom8755. NS a.root-servers.nil.
+dom8756. NS a.root-servers.nil.
+dom8757. NS a.root-servers.nil.
+dom8758. NS a.root-servers.nil.
+dom8759. NS a.root-servers.nil.
+dom8760. NS a.root-servers.nil.
+dom8761. NS a.root-servers.nil.
+dom8762. NS a.root-servers.nil.
+dom8763. NS a.root-servers.nil.
+dom8764. NS a.root-servers.nil.
+dom8765. NS a.root-servers.nil.
+dom8766. NS a.root-servers.nil.
+dom8767. NS a.root-servers.nil.
+dom8768. NS a.root-servers.nil.
+dom8769. NS a.root-servers.nil.
+dom8770. NS a.root-servers.nil.
+dom8771. NS a.root-servers.nil.
+dom8772. NS a.root-servers.nil.
+dom8773. NS a.root-servers.nil.
+dom8774. NS a.root-servers.nil.
+dom8775. NS a.root-servers.nil.
+dom8776. NS a.root-servers.nil.
+dom8777. NS a.root-servers.nil.
+dom8778. NS a.root-servers.nil.
+dom8779. NS a.root-servers.nil.
+dom8780. NS a.root-servers.nil.
+dom8781. NS a.root-servers.nil.
+dom8782. NS a.root-servers.nil.
+dom8783. NS a.root-servers.nil.
+dom8784. NS a.root-servers.nil.
+dom8785. NS a.root-servers.nil.
+dom8786. NS a.root-servers.nil.
+dom8787. NS a.root-servers.nil.
+dom8788. NS a.root-servers.nil.
+dom8789. NS a.root-servers.nil.
+dom8790. NS a.root-servers.nil.
+dom8791. NS a.root-servers.nil.
+dom8792. NS a.root-servers.nil.
+dom8793. NS a.root-servers.nil.
+dom8794. NS a.root-servers.nil.
+dom8795. NS a.root-servers.nil.
+dom8796. NS a.root-servers.nil.
+dom8797. NS a.root-servers.nil.
+dom8798. NS a.root-servers.nil.
+dom8799. NS a.root-servers.nil.
+dom8800. NS a.root-servers.nil.
+dom8801. NS a.root-servers.nil.
+dom8802. NS a.root-servers.nil.
+dom8803. NS a.root-servers.nil.
+dom8804. NS a.root-servers.nil.
+dom8805. NS a.root-servers.nil.
+dom8806. NS a.root-servers.nil.
+dom8807. NS a.root-servers.nil.
+dom8808. NS a.root-servers.nil.
+dom8809. NS a.root-servers.nil.
+dom8810. NS a.root-servers.nil.
+dom8811. NS a.root-servers.nil.
+dom8812. NS a.root-servers.nil.
+dom8813. NS a.root-servers.nil.
+dom8814. NS a.root-servers.nil.
+dom8815. NS a.root-servers.nil.
+dom8816. NS a.root-servers.nil.
+dom8817. NS a.root-servers.nil.
+dom8818. NS a.root-servers.nil.
+dom8819. NS a.root-servers.nil.
+dom8820. NS a.root-servers.nil.
+dom8821. NS a.root-servers.nil.
+dom8822. NS a.root-servers.nil.
+dom8823. NS a.root-servers.nil.
+dom8824. NS a.root-servers.nil.
+dom8825. NS a.root-servers.nil.
+dom8826. NS a.root-servers.nil.
+dom8827. NS a.root-servers.nil.
+dom8828. NS a.root-servers.nil.
+dom8829. NS a.root-servers.nil.
+dom8830. NS a.root-servers.nil.
+dom8831. NS a.root-servers.nil.
+dom8832. NS a.root-servers.nil.
+dom8833. NS a.root-servers.nil.
+dom8834. NS a.root-servers.nil.
+dom8835. NS a.root-servers.nil.
+dom8836. NS a.root-servers.nil.
+dom8837. NS a.root-servers.nil.
+dom8838. NS a.root-servers.nil.
+dom8839. NS a.root-servers.nil.
+dom8840. NS a.root-servers.nil.
+dom8841. NS a.root-servers.nil.
+dom8842. NS a.root-servers.nil.
+dom8843. NS a.root-servers.nil.
+dom8844. NS a.root-servers.nil.
+dom8845. NS a.root-servers.nil.
+dom8846. NS a.root-servers.nil.
+dom8847. NS a.root-servers.nil.
+dom8848. NS a.root-servers.nil.
+dom8849. NS a.root-servers.nil.
+dom8850. NS a.root-servers.nil.
+dom8851. NS a.root-servers.nil.
+dom8852. NS a.root-servers.nil.
+dom8853. NS a.root-servers.nil.
+dom8854. NS a.root-servers.nil.
+dom8855. NS a.root-servers.nil.
+dom8856. NS a.root-servers.nil.
+dom8857. NS a.root-servers.nil.
+dom8858. NS a.root-servers.nil.
+dom8859. NS a.root-servers.nil.
+dom8860. NS a.root-servers.nil.
+dom8861. NS a.root-servers.nil.
+dom8862. NS a.root-servers.nil.
+dom8863. NS a.root-servers.nil.
+dom8864. NS a.root-servers.nil.
+dom8865. NS a.root-servers.nil.
+dom8866. NS a.root-servers.nil.
+dom8867. NS a.root-servers.nil.
+dom8868. NS a.root-servers.nil.
+dom8869. NS a.root-servers.nil.
+dom8870. NS a.root-servers.nil.
+dom8871. NS a.root-servers.nil.
+dom8872. NS a.root-servers.nil.
+dom8873. NS a.root-servers.nil.
+dom8874. NS a.root-servers.nil.
+dom8875. NS a.root-servers.nil.
+dom8876. NS a.root-servers.nil.
+dom8877. NS a.root-servers.nil.
+dom8878. NS a.root-servers.nil.
+dom8879. NS a.root-servers.nil.
+dom8880. NS a.root-servers.nil.
+dom8881. NS a.root-servers.nil.
+dom8882. NS a.root-servers.nil.
+dom8883. NS a.root-servers.nil.
+dom8884. NS a.root-servers.nil.
+dom8885. NS a.root-servers.nil.
+dom8886. NS a.root-servers.nil.
+dom8887. NS a.root-servers.nil.
+dom8888. NS a.root-servers.nil.
+dom8889. NS a.root-servers.nil.
+dom8890. NS a.root-servers.nil.
+dom8891. NS a.root-servers.nil.
+dom8892. NS a.root-servers.nil.
+dom8893. NS a.root-servers.nil.
+dom8894. NS a.root-servers.nil.
+dom8895. NS a.root-servers.nil.
+dom8896. NS a.root-servers.nil.
+dom8897. NS a.root-servers.nil.
+dom8898. NS a.root-servers.nil.
+dom8899. NS a.root-servers.nil.
+dom8900. NS a.root-servers.nil.
+dom8901. NS a.root-servers.nil.
+dom8902. NS a.root-servers.nil.
+dom8903. NS a.root-servers.nil.
+dom8904. NS a.root-servers.nil.
+dom8905. NS a.root-servers.nil.
+dom8906. NS a.root-servers.nil.
+dom8907. NS a.root-servers.nil.
+dom8908. NS a.root-servers.nil.
+dom8909. NS a.root-servers.nil.
+dom8910. NS a.root-servers.nil.
+dom8911. NS a.root-servers.nil.
+dom8912. NS a.root-servers.nil.
+dom8913. NS a.root-servers.nil.
+dom8914. NS a.root-servers.nil.
+dom8915. NS a.root-servers.nil.
+dom8916. NS a.root-servers.nil.
+dom8917. NS a.root-servers.nil.
+dom8918. NS a.root-servers.nil.
+dom8919. NS a.root-servers.nil.
+dom8920. NS a.root-servers.nil.
+dom8921. NS a.root-servers.nil.
+dom8922. NS a.root-servers.nil.
+dom8923. NS a.root-servers.nil.
+dom8924. NS a.root-servers.nil.
+dom8925. NS a.root-servers.nil.
+dom8926. NS a.root-servers.nil.
+dom8927. NS a.root-servers.nil.
+dom8928. NS a.root-servers.nil.
+dom8929. NS a.root-servers.nil.
+dom8930. NS a.root-servers.nil.
+dom8931. NS a.root-servers.nil.
+dom8932. NS a.root-servers.nil.
+dom8933. NS a.root-servers.nil.
+dom8934. NS a.root-servers.nil.
+dom8935. NS a.root-servers.nil.
+dom8936. NS a.root-servers.nil.
+dom8937. NS a.root-servers.nil.
+dom8938. NS a.root-servers.nil.
+dom8939. NS a.root-servers.nil.
+dom8940. NS a.root-servers.nil.
+dom8941. NS a.root-servers.nil.
+dom8942. NS a.root-servers.nil.
+dom8943. NS a.root-servers.nil.
+dom8944. NS a.root-servers.nil.
+dom8945. NS a.root-servers.nil.
+dom8946. NS a.root-servers.nil.
+dom8947. NS a.root-servers.nil.
+dom8948. NS a.root-servers.nil.
+dom8949. NS a.root-servers.nil.
+dom8950. NS a.root-servers.nil.
+dom8951. NS a.root-servers.nil.
+dom8952. NS a.root-servers.nil.
+dom8953. NS a.root-servers.nil.
+dom8954. NS a.root-servers.nil.
+dom8955. NS a.root-servers.nil.
+dom8956. NS a.root-servers.nil.
+dom8957. NS a.root-servers.nil.
+dom8958. NS a.root-servers.nil.
+dom8959. NS a.root-servers.nil.
+dom8960. NS a.root-servers.nil.
+dom8961. NS a.root-servers.nil.
+dom8962. NS a.root-servers.nil.
+dom8963. NS a.root-servers.nil.
+dom8964. NS a.root-servers.nil.
+dom8965. NS a.root-servers.nil.
+dom8966. NS a.root-servers.nil.
+dom8967. NS a.root-servers.nil.
+dom8968. NS a.root-servers.nil.
+dom8969. NS a.root-servers.nil.
+dom8970. NS a.root-servers.nil.
+dom8971. NS a.root-servers.nil.
+dom8972. NS a.root-servers.nil.
+dom8973. NS a.root-servers.nil.
+dom8974. NS a.root-servers.nil.
+dom8975. NS a.root-servers.nil.
+dom8976. NS a.root-servers.nil.
+dom8977. NS a.root-servers.nil.
+dom8978. NS a.root-servers.nil.
+dom8979. NS a.root-servers.nil.
+dom8980. NS a.root-servers.nil.
+dom8981. NS a.root-servers.nil.
+dom8982. NS a.root-servers.nil.
+dom8983. NS a.root-servers.nil.
+dom8984. NS a.root-servers.nil.
+dom8985. NS a.root-servers.nil.
+dom8986. NS a.root-servers.nil.
+dom8987. NS a.root-servers.nil.
+dom8988. NS a.root-servers.nil.
+dom8989. NS a.root-servers.nil.
+dom8990. NS a.root-servers.nil.
+dom8991. NS a.root-servers.nil.
+dom8992. NS a.root-servers.nil.
+dom8993. NS a.root-servers.nil.
+dom8994. NS a.root-servers.nil.
+dom8995. NS a.root-servers.nil.
+dom8996. NS a.root-servers.nil.
+dom8997. NS a.root-servers.nil.
+dom8998. NS a.root-servers.nil.
+dom8999. NS a.root-servers.nil.
+dom9000. NS a.root-servers.nil.
+dom9001. NS a.root-servers.nil.
+dom9002. NS a.root-servers.nil.
+dom9003. NS a.root-servers.nil.
+dom9004. NS a.root-servers.nil.
+dom9005. NS a.root-servers.nil.
+dom9006. NS a.root-servers.nil.
+dom9007. NS a.root-servers.nil.
+dom9008. NS a.root-servers.nil.
+dom9009. NS a.root-servers.nil.
+dom9010. NS a.root-servers.nil.
+dom9011. NS a.root-servers.nil.
+dom9012. NS a.root-servers.nil.
+dom9013. NS a.root-servers.nil.
+dom9014. NS a.root-servers.nil.
+dom9015. NS a.root-servers.nil.
+dom9016. NS a.root-servers.nil.
+dom9017. NS a.root-servers.nil.
+dom9018. NS a.root-servers.nil.
+dom9019. NS a.root-servers.nil.
+dom9020. NS a.root-servers.nil.
+dom9021. NS a.root-servers.nil.
+dom9022. NS a.root-servers.nil.
+dom9023. NS a.root-servers.nil.
+dom9024. NS a.root-servers.nil.
+dom9025. NS a.root-servers.nil.
+dom9026. NS a.root-servers.nil.
+dom9027. NS a.root-servers.nil.
+dom9028. NS a.root-servers.nil.
+dom9029. NS a.root-servers.nil.
+dom9030. NS a.root-servers.nil.
+dom9031. NS a.root-servers.nil.
+dom9032. NS a.root-servers.nil.
+dom9033. NS a.root-servers.nil.
+dom9034. NS a.root-servers.nil.
+dom9035. NS a.root-servers.nil.
+dom9036. NS a.root-servers.nil.
+dom9037. NS a.root-servers.nil.
+dom9038. NS a.root-servers.nil.
+dom9039. NS a.root-servers.nil.
+dom9040. NS a.root-servers.nil.
+dom9041. NS a.root-servers.nil.
+dom9042. NS a.root-servers.nil.
+dom9043. NS a.root-servers.nil.
+dom9044. NS a.root-servers.nil.
+dom9045. NS a.root-servers.nil.
+dom9046. NS a.root-servers.nil.
+dom9047. NS a.root-servers.nil.
+dom9048. NS a.root-servers.nil.
+dom9049. NS a.root-servers.nil.
+dom9050. NS a.root-servers.nil.
+dom9051. NS a.root-servers.nil.
+dom9052. NS a.root-servers.nil.
+dom9053. NS a.root-servers.nil.
+dom9054. NS a.root-servers.nil.
+dom9055. NS a.root-servers.nil.
+dom9056. NS a.root-servers.nil.
+dom9057. NS a.root-servers.nil.
+dom9058. NS a.root-servers.nil.
+dom9059. NS a.root-servers.nil.
+dom9060. NS a.root-servers.nil.
+dom9061. NS a.root-servers.nil.
+dom9062. NS a.root-servers.nil.
+dom9063. NS a.root-servers.nil.
+dom9064. NS a.root-servers.nil.
+dom9065. NS a.root-servers.nil.
+dom9066. NS a.root-servers.nil.
+dom9067. NS a.root-servers.nil.
+dom9068. NS a.root-servers.nil.
+dom9069. NS a.root-servers.nil.
+dom9070. NS a.root-servers.nil.
+dom9071. NS a.root-servers.nil.
+dom9072. NS a.root-servers.nil.
+dom9073. NS a.root-servers.nil.
+dom9074. NS a.root-servers.nil.
+dom9075. NS a.root-servers.nil.
+dom9076. NS a.root-servers.nil.
+dom9077. NS a.root-servers.nil.
+dom9078. NS a.root-servers.nil.
+dom9079. NS a.root-servers.nil.
+dom9080. NS a.root-servers.nil.
+dom9081. NS a.root-servers.nil.
+dom9082. NS a.root-servers.nil.
+dom9083. NS a.root-servers.nil.
+dom9084. NS a.root-servers.nil.
+dom9085. NS a.root-servers.nil.
+dom9086. NS a.root-servers.nil.
+dom9087. NS a.root-servers.nil.
+dom9088. NS a.root-servers.nil.
+dom9089. NS a.root-servers.nil.
+dom9090. NS a.root-servers.nil.
+dom9091. NS a.root-servers.nil.
+dom9092. NS a.root-servers.nil.
+dom9093. NS a.root-servers.nil.
+dom9094. NS a.root-servers.nil.
+dom9095. NS a.root-servers.nil.
+dom9096. NS a.root-servers.nil.
+dom9097. NS a.root-servers.nil.
+dom9098. NS a.root-servers.nil.
+dom9099. NS a.root-servers.nil.
+dom9100. NS a.root-servers.nil.
+dom9101. NS a.root-servers.nil.
+dom9102. NS a.root-servers.nil.
+dom9103. NS a.root-servers.nil.
+dom9104. NS a.root-servers.nil.
+dom9105. NS a.root-servers.nil.
+dom9106. NS a.root-servers.nil.
+dom9107. NS a.root-servers.nil.
+dom9108. NS a.root-servers.nil.
+dom9109. NS a.root-servers.nil.
+dom9110. NS a.root-servers.nil.
+dom9111. NS a.root-servers.nil.
+dom9112. NS a.root-servers.nil.
+dom9113. NS a.root-servers.nil.
+dom9114. NS a.root-servers.nil.
+dom9115. NS a.root-servers.nil.
+dom9116. NS a.root-servers.nil.
+dom9117. NS a.root-servers.nil.
+dom9118. NS a.root-servers.nil.
+dom9119. NS a.root-servers.nil.
+dom9120. NS a.root-servers.nil.
+dom9121. NS a.root-servers.nil.
+dom9122. NS a.root-servers.nil.
+dom9123. NS a.root-servers.nil.
+dom9124. NS a.root-servers.nil.
+dom9125. NS a.root-servers.nil.
+dom9126. NS a.root-servers.nil.
+dom9127. NS a.root-servers.nil.
+dom9128. NS a.root-servers.nil.
+dom9129. NS a.root-servers.nil.
+dom9130. NS a.root-servers.nil.
+dom9131. NS a.root-servers.nil.
+dom9132. NS a.root-servers.nil.
+dom9133. NS a.root-servers.nil.
+dom9134. NS a.root-servers.nil.
+dom9135. NS a.root-servers.nil.
+dom9136. NS a.root-servers.nil.
+dom9137. NS a.root-servers.nil.
+dom9138. NS a.root-servers.nil.
+dom9139. NS a.root-servers.nil.
+dom9140. NS a.root-servers.nil.
+dom9141. NS a.root-servers.nil.
+dom9142. NS a.root-servers.nil.
+dom9143. NS a.root-servers.nil.
+dom9144. NS a.root-servers.nil.
+dom9145. NS a.root-servers.nil.
+dom9146. NS a.root-servers.nil.
+dom9147. NS a.root-servers.nil.
+dom9148. NS a.root-servers.nil.
+dom9149. NS a.root-servers.nil.
+dom9150. NS a.root-servers.nil.
+dom9151. NS a.root-servers.nil.
+dom9152. NS a.root-servers.nil.
+dom9153. NS a.root-servers.nil.
+dom9154. NS a.root-servers.nil.
+dom9155. NS a.root-servers.nil.
+dom9156. NS a.root-servers.nil.
+dom9157. NS a.root-servers.nil.
+dom9158. NS a.root-servers.nil.
+dom9159. NS a.root-servers.nil.
+dom9160. NS a.root-servers.nil.
+dom9161. NS a.root-servers.nil.
+dom9162. NS a.root-servers.nil.
+dom9163. NS a.root-servers.nil.
+dom9164. NS a.root-servers.nil.
+dom9165. NS a.root-servers.nil.
+dom9166. NS a.root-servers.nil.
+dom9167. NS a.root-servers.nil.
+dom9168. NS a.root-servers.nil.
+dom9169. NS a.root-servers.nil.
+dom9170. NS a.root-servers.nil.
+dom9171. NS a.root-servers.nil.
+dom9172. NS a.root-servers.nil.
+dom9173. NS a.root-servers.nil.
+dom9174. NS a.root-servers.nil.
+dom9175. NS a.root-servers.nil.
+dom9176. NS a.root-servers.nil.
+dom9177. NS a.root-servers.nil.
+dom9178. NS a.root-servers.nil.
+dom9179. NS a.root-servers.nil.
+dom9180. NS a.root-servers.nil.
+dom9181. NS a.root-servers.nil.
+dom9182. NS a.root-servers.nil.
+dom9183. NS a.root-servers.nil.
+dom9184. NS a.root-servers.nil.
+dom9185. NS a.root-servers.nil.
+dom9186. NS a.root-servers.nil.
+dom9187. NS a.root-servers.nil.
+dom9188. NS a.root-servers.nil.
+dom9189. NS a.root-servers.nil.
+dom9190. NS a.root-servers.nil.
+dom9191. NS a.root-servers.nil.
+dom9192. NS a.root-servers.nil.
+dom9193. NS a.root-servers.nil.
+dom9194. NS a.root-servers.nil.
+dom9195. NS a.root-servers.nil.
+dom9196. NS a.root-servers.nil.
+dom9197. NS a.root-servers.nil.
+dom9198. NS a.root-servers.nil.
+dom9199. NS a.root-servers.nil.
+dom9200. NS a.root-servers.nil.
+dom9201. NS a.root-servers.nil.
+dom9202. NS a.root-servers.nil.
+dom9203. NS a.root-servers.nil.
+dom9204. NS a.root-servers.nil.
+dom9205. NS a.root-servers.nil.
+dom9206. NS a.root-servers.nil.
+dom9207. NS a.root-servers.nil.
+dom9208. NS a.root-servers.nil.
+dom9209. NS a.root-servers.nil.
+dom9210. NS a.root-servers.nil.
+dom9211. NS a.root-servers.nil.
+dom9212. NS a.root-servers.nil.
+dom9213. NS a.root-servers.nil.
+dom9214. NS a.root-servers.nil.
+dom9215. NS a.root-servers.nil.
+dom9216. NS a.root-servers.nil.
+dom9217. NS a.root-servers.nil.
+dom9218. NS a.root-servers.nil.
+dom9219. NS a.root-servers.nil.
+dom9220. NS a.root-servers.nil.
+dom9221. NS a.root-servers.nil.
+dom9222. NS a.root-servers.nil.
+dom9223. NS a.root-servers.nil.
+dom9224. NS a.root-servers.nil.
+dom9225. NS a.root-servers.nil.
+dom9226. NS a.root-servers.nil.
+dom9227. NS a.root-servers.nil.
+dom9228. NS a.root-servers.nil.
+dom9229. NS a.root-servers.nil.
+dom9230. NS a.root-servers.nil.
+dom9231. NS a.root-servers.nil.
+dom9232. NS a.root-servers.nil.
+dom9233. NS a.root-servers.nil.
+dom9234. NS a.root-servers.nil.
+dom9235. NS a.root-servers.nil.
+dom9236. NS a.root-servers.nil.
+dom9237. NS a.root-servers.nil.
+dom9238. NS a.root-servers.nil.
+dom9239. NS a.root-servers.nil.
+dom9240. NS a.root-servers.nil.
+dom9241. NS a.root-servers.nil.
+dom9242. NS a.root-servers.nil.
+dom9243. NS a.root-servers.nil.
+dom9244. NS a.root-servers.nil.
+dom9245. NS a.root-servers.nil.
+dom9246. NS a.root-servers.nil.
+dom9247. NS a.root-servers.nil.
+dom9248. NS a.root-servers.nil.
+dom9249. NS a.root-servers.nil.
+dom9250. NS a.root-servers.nil.
+dom9251. NS a.root-servers.nil.
+dom9252. NS a.root-servers.nil.
+dom9253. NS a.root-servers.nil.
+dom9254. NS a.root-servers.nil.
+dom9255. NS a.root-servers.nil.
+dom9256. NS a.root-servers.nil.
+dom9257. NS a.root-servers.nil.
+dom9258. NS a.root-servers.nil.
+dom9259. NS a.root-servers.nil.
+dom9260. NS a.root-servers.nil.
+dom9261. NS a.root-servers.nil.
+dom9262. NS a.root-servers.nil.
+dom9263. NS a.root-servers.nil.
+dom9264. NS a.root-servers.nil.
+dom9265. NS a.root-servers.nil.
+dom9266. NS a.root-servers.nil.
+dom9267. NS a.root-servers.nil.
+dom9268. NS a.root-servers.nil.
+dom9269. NS a.root-servers.nil.
+dom9270. NS a.root-servers.nil.
+dom9271. NS a.root-servers.nil.
+dom9272. NS a.root-servers.nil.
+dom9273. NS a.root-servers.nil.
+dom9274. NS a.root-servers.nil.
+dom9275. NS a.root-servers.nil.
+dom9276. NS a.root-servers.nil.
+dom9277. NS a.root-servers.nil.
+dom9278. NS a.root-servers.nil.
+dom9279. NS a.root-servers.nil.
+dom9280. NS a.root-servers.nil.
+dom9281. NS a.root-servers.nil.
+dom9282. NS a.root-servers.nil.
+dom9283. NS a.root-servers.nil.
+dom9284. NS a.root-servers.nil.
+dom9285. NS a.root-servers.nil.
+dom9286. NS a.root-servers.nil.
+dom9287. NS a.root-servers.nil.
+dom9288. NS a.root-servers.nil.
+dom9289. NS a.root-servers.nil.
+dom9290. NS a.root-servers.nil.
+dom9291. NS a.root-servers.nil.
+dom9292. NS a.root-servers.nil.
+dom9293. NS a.root-servers.nil.
+dom9294. NS a.root-servers.nil.
+dom9295. NS a.root-servers.nil.
+dom9296. NS a.root-servers.nil.
+dom9297. NS a.root-servers.nil.
+dom9298. NS a.root-servers.nil.
+dom9299. NS a.root-servers.nil.
+dom9300. NS a.root-servers.nil.
+dom9301. NS a.root-servers.nil.
+dom9302. NS a.root-servers.nil.
+dom9303. NS a.root-servers.nil.
+dom9304. NS a.root-servers.nil.
+dom9305. NS a.root-servers.nil.
+dom9306. NS a.root-servers.nil.
+dom9307. NS a.root-servers.nil.
+dom9308. NS a.root-servers.nil.
+dom9309. NS a.root-servers.nil.
+dom9310. NS a.root-servers.nil.
+dom9311. NS a.root-servers.nil.
+dom9312. NS a.root-servers.nil.
+dom9313. NS a.root-servers.nil.
+dom9314. NS a.root-servers.nil.
+dom9315. NS a.root-servers.nil.
+dom9316. NS a.root-servers.nil.
+dom9317. NS a.root-servers.nil.
+dom9318. NS a.root-servers.nil.
+dom9319. NS a.root-servers.nil.
+dom9320. NS a.root-servers.nil.
+dom9321. NS a.root-servers.nil.
+dom9322. NS a.root-servers.nil.
+dom9323. NS a.root-servers.nil.
+dom9324. NS a.root-servers.nil.
+dom9325. NS a.root-servers.nil.
+dom9326. NS a.root-servers.nil.
+dom9327. NS a.root-servers.nil.
+dom9328. NS a.root-servers.nil.
+dom9329. NS a.root-servers.nil.
+dom9330. NS a.root-servers.nil.
+dom9331. NS a.root-servers.nil.
+dom9332. NS a.root-servers.nil.
+dom9333. NS a.root-servers.nil.
+dom9334. NS a.root-servers.nil.
+dom9335. NS a.root-servers.nil.
+dom9336. NS a.root-servers.nil.
+dom9337. NS a.root-servers.nil.
+dom9338. NS a.root-servers.nil.
+dom9339. NS a.root-servers.nil.
+dom9340. NS a.root-servers.nil.
+dom9341. NS a.root-servers.nil.
+dom9342. NS a.root-servers.nil.
+dom9343. NS a.root-servers.nil.
+dom9344. NS a.root-servers.nil.
+dom9345. NS a.root-servers.nil.
+dom9346. NS a.root-servers.nil.
+dom9347. NS a.root-servers.nil.
+dom9348. NS a.root-servers.nil.
+dom9349. NS a.root-servers.nil.
+dom9350. NS a.root-servers.nil.
+dom9351. NS a.root-servers.nil.
+dom9352. NS a.root-servers.nil.
+dom9353. NS a.root-servers.nil.
+dom9354. NS a.root-servers.nil.
+dom9355. NS a.root-servers.nil.
+dom9356. NS a.root-servers.nil.
+dom9357. NS a.root-servers.nil.
+dom9358. NS a.root-servers.nil.
+dom9359. NS a.root-servers.nil.
+dom9360. NS a.root-servers.nil.
+dom9361. NS a.root-servers.nil.
+dom9362. NS a.root-servers.nil.
+dom9363. NS a.root-servers.nil.
+dom9364. NS a.root-servers.nil.
+dom9365. NS a.root-servers.nil.
+dom9366. NS a.root-servers.nil.
+dom9367. NS a.root-servers.nil.
+dom9368. NS a.root-servers.nil.
+dom9369. NS a.root-servers.nil.
+dom9370. NS a.root-servers.nil.
+dom9371. NS a.root-servers.nil.
+dom9372. NS a.root-servers.nil.
+dom9373. NS a.root-servers.nil.
+dom9374. NS a.root-servers.nil.
+dom9375. NS a.root-servers.nil.
+dom9376. NS a.root-servers.nil.
+dom9377. NS a.root-servers.nil.
+dom9378. NS a.root-servers.nil.
+dom9379. NS a.root-servers.nil.
+dom9380. NS a.root-servers.nil.
+dom9381. NS a.root-servers.nil.
+dom9382. NS a.root-servers.nil.
+dom9383. NS a.root-servers.nil.
+dom9384. NS a.root-servers.nil.
+dom9385. NS a.root-servers.nil.
+dom9386. NS a.root-servers.nil.
+dom9387. NS a.root-servers.nil.
+dom9388. NS a.root-servers.nil.
+dom9389. NS a.root-servers.nil.
+dom9390. NS a.root-servers.nil.
+dom9391. NS a.root-servers.nil.
+dom9392. NS a.root-servers.nil.
+dom9393. NS a.root-servers.nil.
+dom9394. NS a.root-servers.nil.
+dom9395. NS a.root-servers.nil.
+dom9396. NS a.root-servers.nil.
+dom9397. NS a.root-servers.nil.
+dom9398. NS a.root-servers.nil.
+dom9399. NS a.root-servers.nil.
+dom9400. NS a.root-servers.nil.
+dom9401. NS a.root-servers.nil.
+dom9402. NS a.root-servers.nil.
+dom9403. NS a.root-servers.nil.
+dom9404. NS a.root-servers.nil.
+dom9405. NS a.root-servers.nil.
+dom9406. NS a.root-servers.nil.
+dom9407. NS a.root-servers.nil.
+dom9408. NS a.root-servers.nil.
+dom9409. NS a.root-servers.nil.
+dom9410. NS a.root-servers.nil.
+dom9411. NS a.root-servers.nil.
+dom9412. NS a.root-servers.nil.
+dom9413. NS a.root-servers.nil.
+dom9414. NS a.root-servers.nil.
+dom9415. NS a.root-servers.nil.
+dom9416. NS a.root-servers.nil.
+dom9417. NS a.root-servers.nil.
+dom9418. NS a.root-servers.nil.
+dom9419. NS a.root-servers.nil.
+dom9420. NS a.root-servers.nil.
+dom9421. NS a.root-servers.nil.
+dom9422. NS a.root-servers.nil.
+dom9423. NS a.root-servers.nil.
+dom9424. NS a.root-servers.nil.
+dom9425. NS a.root-servers.nil.
+dom9426. NS a.root-servers.nil.
+dom9427. NS a.root-servers.nil.
+dom9428. NS a.root-servers.nil.
+dom9429. NS a.root-servers.nil.
+dom9430. NS a.root-servers.nil.
+dom9431. NS a.root-servers.nil.
+dom9432. NS a.root-servers.nil.
+dom9433. NS a.root-servers.nil.
+dom9434. NS a.root-servers.nil.
+dom9435. NS a.root-servers.nil.
+dom9436. NS a.root-servers.nil.
+dom9437. NS a.root-servers.nil.
+dom9438. NS a.root-servers.nil.
+dom9439. NS a.root-servers.nil.
+dom9440. NS a.root-servers.nil.
+dom9441. NS a.root-servers.nil.
+dom9442. NS a.root-servers.nil.
+dom9443. NS a.root-servers.nil.
+dom9444. NS a.root-servers.nil.
+dom9445. NS a.root-servers.nil.
+dom9446. NS a.root-servers.nil.
+dom9447. NS a.root-servers.nil.
+dom9448. NS a.root-servers.nil.
+dom9449. NS a.root-servers.nil.
+dom9450. NS a.root-servers.nil.
+dom9451. NS a.root-servers.nil.
+dom9452. NS a.root-servers.nil.
+dom9453. NS a.root-servers.nil.
+dom9454. NS a.root-servers.nil.
+dom9455. NS a.root-servers.nil.
+dom9456. NS a.root-servers.nil.
+dom9457. NS a.root-servers.nil.
+dom9458. NS a.root-servers.nil.
+dom9459. NS a.root-servers.nil.
+dom9460. NS a.root-servers.nil.
+dom9461. NS a.root-servers.nil.
+dom9462. NS a.root-servers.nil.
+dom9463. NS a.root-servers.nil.
+dom9464. NS a.root-servers.nil.
+dom9465. NS a.root-servers.nil.
+dom9466. NS a.root-servers.nil.
+dom9467. NS a.root-servers.nil.
+dom9468. NS a.root-servers.nil.
+dom9469. NS a.root-servers.nil.
+dom9470. NS a.root-servers.nil.
+dom9471. NS a.root-servers.nil.
+dom9472. NS a.root-servers.nil.
+dom9473. NS a.root-servers.nil.
+dom9474. NS a.root-servers.nil.
+dom9475. NS a.root-servers.nil.
+dom9476. NS a.root-servers.nil.
+dom9477. NS a.root-servers.nil.
+dom9478. NS a.root-servers.nil.
+dom9479. NS a.root-servers.nil.
+dom9480. NS a.root-servers.nil.
+dom9481. NS a.root-servers.nil.
+dom9482. NS a.root-servers.nil.
+dom9483. NS a.root-servers.nil.
+dom9484. NS a.root-servers.nil.
+dom9485. NS a.root-servers.nil.
+dom9486. NS a.root-servers.nil.
+dom9487. NS a.root-servers.nil.
+dom9488. NS a.root-servers.nil.
+dom9489. NS a.root-servers.nil.
+dom9490. NS a.root-servers.nil.
+dom9491. NS a.root-servers.nil.
+dom9492. NS a.root-servers.nil.
+dom9493. NS a.root-servers.nil.
+dom9494. NS a.root-servers.nil.
+dom9495. NS a.root-servers.nil.
+dom9496. NS a.root-servers.nil.
+dom9497. NS a.root-servers.nil.
+dom9498. NS a.root-servers.nil.
+dom9499. NS a.root-servers.nil.
+dom9500. NS a.root-servers.nil.
+dom9501. NS a.root-servers.nil.
+dom9502. NS a.root-servers.nil.
+dom9503. NS a.root-servers.nil.
+dom9504. NS a.root-servers.nil.
+dom9505. NS a.root-servers.nil.
+dom9506. NS a.root-servers.nil.
+dom9507. NS a.root-servers.nil.
+dom9508. NS a.root-servers.nil.
+dom9509. NS a.root-servers.nil.
+dom9510. NS a.root-servers.nil.
+dom9511. NS a.root-servers.nil.
+dom9512. NS a.root-servers.nil.
+dom9513. NS a.root-servers.nil.
+dom9514. NS a.root-servers.nil.
+dom9515. NS a.root-servers.nil.
+dom9516. NS a.root-servers.nil.
+dom9517. NS a.root-servers.nil.
+dom9518. NS a.root-servers.nil.
+dom9519. NS a.root-servers.nil.
+dom9520. NS a.root-servers.nil.
+dom9521. NS a.root-servers.nil.
+dom9522. NS a.root-servers.nil.
+dom9523. NS a.root-servers.nil.
+dom9524. NS a.root-servers.nil.
+dom9525. NS a.root-servers.nil.
+dom9526. NS a.root-servers.nil.
+dom9527. NS a.root-servers.nil.
+dom9528. NS a.root-servers.nil.
+dom9529. NS a.root-servers.nil.
+dom9530. NS a.root-servers.nil.
+dom9531. NS a.root-servers.nil.
+dom9532. NS a.root-servers.nil.
+dom9533. NS a.root-servers.nil.
+dom9534. NS a.root-servers.nil.
+dom9535. NS a.root-servers.nil.
+dom9536. NS a.root-servers.nil.
+dom9537. NS a.root-servers.nil.
+dom9538. NS a.root-servers.nil.
+dom9539. NS a.root-servers.nil.
+dom9540. NS a.root-servers.nil.
+dom9541. NS a.root-servers.nil.
+dom9542. NS a.root-servers.nil.
+dom9543. NS a.root-servers.nil.
+dom9544. NS a.root-servers.nil.
+dom9545. NS a.root-servers.nil.
+dom9546. NS a.root-servers.nil.
+dom9547. NS a.root-servers.nil.
+dom9548. NS a.root-servers.nil.
+dom9549. NS a.root-servers.nil.
+dom9550. NS a.root-servers.nil.
+dom9551. NS a.root-servers.nil.
+dom9552. NS a.root-servers.nil.
+dom9553. NS a.root-servers.nil.
+dom9554. NS a.root-servers.nil.
+dom9555. NS a.root-servers.nil.
+dom9556. NS a.root-servers.nil.
+dom9557. NS a.root-servers.nil.
+dom9558. NS a.root-servers.nil.
+dom9559. NS a.root-servers.nil.
+dom9560. NS a.root-servers.nil.
+dom9561. NS a.root-servers.nil.
+dom9562. NS a.root-servers.nil.
+dom9563. NS a.root-servers.nil.
+dom9564. NS a.root-servers.nil.
+dom9565. NS a.root-servers.nil.
+dom9566. NS a.root-servers.nil.
+dom9567. NS a.root-servers.nil.
+dom9568. NS a.root-servers.nil.
+dom9569. NS a.root-servers.nil.
+dom9570. NS a.root-servers.nil.
+dom9571. NS a.root-servers.nil.
+dom9572. NS a.root-servers.nil.
+dom9573. NS a.root-servers.nil.
+dom9574. NS a.root-servers.nil.
+dom9575. NS a.root-servers.nil.
+dom9576. NS a.root-servers.nil.
+dom9577. NS a.root-servers.nil.
+dom9578. NS a.root-servers.nil.
+dom9579. NS a.root-servers.nil.
+dom9580. NS a.root-servers.nil.
+dom9581. NS a.root-servers.nil.
+dom9582. NS a.root-servers.nil.
+dom9583. NS a.root-servers.nil.
+dom9584. NS a.root-servers.nil.
+dom9585. NS a.root-servers.nil.
+dom9586. NS a.root-servers.nil.
+dom9587. NS a.root-servers.nil.
+dom9588. NS a.root-servers.nil.
+dom9589. NS a.root-servers.nil.
+dom9590. NS a.root-servers.nil.
+dom9591. NS a.root-servers.nil.
+dom9592. NS a.root-servers.nil.
+dom9593. NS a.root-servers.nil.
+dom9594. NS a.root-servers.nil.
+dom9595. NS a.root-servers.nil.
+dom9596. NS a.root-servers.nil.
+dom9597. NS a.root-servers.nil.
+dom9598. NS a.root-servers.nil.
+dom9599. NS a.root-servers.nil.
+dom9600. NS a.root-servers.nil.
+dom9601. NS a.root-servers.nil.
+dom9602. NS a.root-servers.nil.
+dom9603. NS a.root-servers.nil.
+dom9604. NS a.root-servers.nil.
+dom9605. NS a.root-servers.nil.
+dom9606. NS a.root-servers.nil.
+dom9607. NS a.root-servers.nil.
+dom9608. NS a.root-servers.nil.
+dom9609. NS a.root-servers.nil.
+dom9610. NS a.root-servers.nil.
+dom9611. NS a.root-servers.nil.
+dom9612. NS a.root-servers.nil.
+dom9613. NS a.root-servers.nil.
+dom9614. NS a.root-servers.nil.
+dom9615. NS a.root-servers.nil.
+dom9616. NS a.root-servers.nil.
+dom9617. NS a.root-servers.nil.
+dom9618. NS a.root-servers.nil.
+dom9619. NS a.root-servers.nil.
+dom9620. NS a.root-servers.nil.
+dom9621. NS a.root-servers.nil.
+dom9622. NS a.root-servers.nil.
+dom9623. NS a.root-servers.nil.
+dom9624. NS a.root-servers.nil.
+dom9625. NS a.root-servers.nil.
+dom9626. NS a.root-servers.nil.
+dom9627. NS a.root-servers.nil.
+dom9628. NS a.root-servers.nil.
+dom9629. NS a.root-servers.nil.
+dom9630. NS a.root-servers.nil.
+dom9631. NS a.root-servers.nil.
+dom9632. NS a.root-servers.nil.
+dom9633. NS a.root-servers.nil.
+dom9634. NS a.root-servers.nil.
+dom9635. NS a.root-servers.nil.
+dom9636. NS a.root-servers.nil.
+dom9637. NS a.root-servers.nil.
+dom9638. NS a.root-servers.nil.
+dom9639. NS a.root-servers.nil.
+dom9640. NS a.root-servers.nil.
+dom9641. NS a.root-servers.nil.
+dom9642. NS a.root-servers.nil.
+dom9643. NS a.root-servers.nil.
+dom9644. NS a.root-servers.nil.
+dom9645. NS a.root-servers.nil.
+dom9646. NS a.root-servers.nil.
+dom9647. NS a.root-servers.nil.
+dom9648. NS a.root-servers.nil.
+dom9649. NS a.root-servers.nil.
+dom9650. NS a.root-servers.nil.
+dom9651. NS a.root-servers.nil.
+dom9652. NS a.root-servers.nil.
+dom9653. NS a.root-servers.nil.
+dom9654. NS a.root-servers.nil.
+dom9655. NS a.root-servers.nil.
+dom9656. NS a.root-servers.nil.
+dom9657. NS a.root-servers.nil.
+dom9658. NS a.root-servers.nil.
+dom9659. NS a.root-servers.nil.
+dom9660. NS a.root-servers.nil.
+dom9661. NS a.root-servers.nil.
+dom9662. NS a.root-servers.nil.
+dom9663. NS a.root-servers.nil.
+dom9664. NS a.root-servers.nil.
+dom9665. NS a.root-servers.nil.
+dom9666. NS a.root-servers.nil.
+dom9667. NS a.root-servers.nil.
+dom9668. NS a.root-servers.nil.
+dom9669. NS a.root-servers.nil.
+dom9670. NS a.root-servers.nil.
+dom9671. NS a.root-servers.nil.
+dom9672. NS a.root-servers.nil.
+dom9673. NS a.root-servers.nil.
+dom9674. NS a.root-servers.nil.
+dom9675. NS a.root-servers.nil.
+dom9676. NS a.root-servers.nil.
+dom9677. NS a.root-servers.nil.
+dom9678. NS a.root-servers.nil.
+dom9679. NS a.root-servers.nil.
+dom9680. NS a.root-servers.nil.
+dom9681. NS a.root-servers.nil.
+dom9682. NS a.root-servers.nil.
+dom9683. NS a.root-servers.nil.
+dom9684. NS a.root-servers.nil.
+dom9685. NS a.root-servers.nil.
+dom9686. NS a.root-servers.nil.
+dom9687. NS a.root-servers.nil.
+dom9688. NS a.root-servers.nil.
+dom9689. NS a.root-servers.nil.
+dom9690. NS a.root-servers.nil.
+dom9691. NS a.root-servers.nil.
+dom9692. NS a.root-servers.nil.
+dom9693. NS a.root-servers.nil.
+dom9694. NS a.root-servers.nil.
+dom9695. NS a.root-servers.nil.
+dom9696. NS a.root-servers.nil.
+dom9697. NS a.root-servers.nil.
+dom9698. NS a.root-servers.nil.
+dom9699. NS a.root-servers.nil.
+dom9700. NS a.root-servers.nil.
+dom9701. NS a.root-servers.nil.
+dom9702. NS a.root-servers.nil.
+dom9703. NS a.root-servers.nil.
+dom9704. NS a.root-servers.nil.
+dom9705. NS a.root-servers.nil.
+dom9706. NS a.root-servers.nil.
+dom9707. NS a.root-servers.nil.
+dom9708. NS a.root-servers.nil.
+dom9709. NS a.root-servers.nil.
+dom9710. NS a.root-servers.nil.
+dom9711. NS a.root-servers.nil.
+dom9712. NS a.root-servers.nil.
+dom9713. NS a.root-servers.nil.
+dom9714. NS a.root-servers.nil.
+dom9715. NS a.root-servers.nil.
+dom9716. NS a.root-servers.nil.
+dom9717. NS a.root-servers.nil.
+dom9718. NS a.root-servers.nil.
+dom9719. NS a.root-servers.nil.
+dom9720. NS a.root-servers.nil.
+dom9721. NS a.root-servers.nil.
+dom9722. NS a.root-servers.nil.
+dom9723. NS a.root-servers.nil.
+dom9724. NS a.root-servers.nil.
+dom9725. NS a.root-servers.nil.
+dom9726. NS a.root-servers.nil.
+dom9727. NS a.root-servers.nil.
+dom9728. NS a.root-servers.nil.
+dom9729. NS a.root-servers.nil.
+dom9730. NS a.root-servers.nil.
+dom9731. NS a.root-servers.nil.
+dom9732. NS a.root-servers.nil.
+dom9733. NS a.root-servers.nil.
+dom9734. NS a.root-servers.nil.
+dom9735. NS a.root-servers.nil.
+dom9736. NS a.root-servers.nil.
+dom9737. NS a.root-servers.nil.
+dom9738. NS a.root-servers.nil.
+dom9739. NS a.root-servers.nil.
+dom9740. NS a.root-servers.nil.
+dom9741. NS a.root-servers.nil.
+dom9742. NS a.root-servers.nil.
+dom9743. NS a.root-servers.nil.
+dom9744. NS a.root-servers.nil.
+dom9745. NS a.root-servers.nil.
+dom9746. NS a.root-servers.nil.
+dom9747. NS a.root-servers.nil.
+dom9748. NS a.root-servers.nil.
+dom9749. NS a.root-servers.nil.
+dom9750. NS a.root-servers.nil.
+dom9751. NS a.root-servers.nil.
+dom9752. NS a.root-servers.nil.
+dom9753. NS a.root-servers.nil.
+dom9754. NS a.root-servers.nil.
+dom9755. NS a.root-servers.nil.
+dom9756. NS a.root-servers.nil.
+dom9757. NS a.root-servers.nil.
+dom9758. NS a.root-servers.nil.
+dom9759. NS a.root-servers.nil.
+dom9760. NS a.root-servers.nil.
+dom9761. NS a.root-servers.nil.
+dom9762. NS a.root-servers.nil.
+dom9763. NS a.root-servers.nil.
+dom9764. NS a.root-servers.nil.
+dom9765. NS a.root-servers.nil.
+dom9766. NS a.root-servers.nil.
+dom9767. NS a.root-servers.nil.
+dom9768. NS a.root-servers.nil.
+dom9769. NS a.root-servers.nil.
+dom9770. NS a.root-servers.nil.
+dom9771. NS a.root-servers.nil.
+dom9772. NS a.root-servers.nil.
+dom9773. NS a.root-servers.nil.
+dom9774. NS a.root-servers.nil.
+dom9775. NS a.root-servers.nil.
+dom9776. NS a.root-servers.nil.
+dom9777. NS a.root-servers.nil.
+dom9778. NS a.root-servers.nil.
+dom9779. NS a.root-servers.nil.
+dom9780. NS a.root-servers.nil.
+dom9781. NS a.root-servers.nil.
+dom9782. NS a.root-servers.nil.
+dom9783. NS a.root-servers.nil.
+dom9784. NS a.root-servers.nil.
+dom9785. NS a.root-servers.nil.
+dom9786. NS a.root-servers.nil.
+dom9787. NS a.root-servers.nil.
+dom9788. NS a.root-servers.nil.
+dom9789. NS a.root-servers.nil.
+dom9790. NS a.root-servers.nil.
+dom9791. NS a.root-servers.nil.
+dom9792. NS a.root-servers.nil.
+dom9793. NS a.root-servers.nil.
+dom9794. NS a.root-servers.nil.
+dom9795. NS a.root-servers.nil.
+dom9796. NS a.root-servers.nil.
+dom9797. NS a.root-servers.nil.
+dom9798. NS a.root-servers.nil.
+dom9799. NS a.root-servers.nil.
+dom9800. NS a.root-servers.nil.
+dom9801. NS a.root-servers.nil.
+dom9802. NS a.root-servers.nil.
+dom9803. NS a.root-servers.nil.
+dom9804. NS a.root-servers.nil.
+dom9805. NS a.root-servers.nil.
+dom9806. NS a.root-servers.nil.
+dom9807. NS a.root-servers.nil.
+dom9808. NS a.root-servers.nil.
+dom9809. NS a.root-servers.nil.
+dom9810. NS a.root-servers.nil.
+dom9811. NS a.root-servers.nil.
+dom9812. NS a.root-servers.nil.
+dom9813. NS a.root-servers.nil.
+dom9814. NS a.root-servers.nil.
+dom9815. NS a.root-servers.nil.
+dom9816. NS a.root-servers.nil.
+dom9817. NS a.root-servers.nil.
+dom9818. NS a.root-servers.nil.
+dom9819. NS a.root-servers.nil.
+dom9820. NS a.root-servers.nil.
+dom9821. NS a.root-servers.nil.
+dom9822. NS a.root-servers.nil.
+dom9823. NS a.root-servers.nil.
+dom9824. NS a.root-servers.nil.
+dom9825. NS a.root-servers.nil.
+dom9826. NS a.root-servers.nil.
+dom9827. NS a.root-servers.nil.
+dom9828. NS a.root-servers.nil.
+dom9829. NS a.root-servers.nil.
+dom9830. NS a.root-servers.nil.
+dom9831. NS a.root-servers.nil.
+dom9832. NS a.root-servers.nil.
+dom9833. NS a.root-servers.nil.
+dom9834. NS a.root-servers.nil.
+dom9835. NS a.root-servers.nil.
+dom9836. NS a.root-servers.nil.
+dom9837. NS a.root-servers.nil.
+dom9838. NS a.root-servers.nil.
+dom9839. NS a.root-servers.nil.
+dom9840. NS a.root-servers.nil.
+dom9841. NS a.root-servers.nil.
+dom9842. NS a.root-servers.nil.
+dom9843. NS a.root-servers.nil.
+dom9844. NS a.root-servers.nil.
+dom9845. NS a.root-servers.nil.
+dom9846. NS a.root-servers.nil.
+dom9847. NS a.root-servers.nil.
+dom9848. NS a.root-servers.nil.
+dom9849. NS a.root-servers.nil.
+dom9850. NS a.root-servers.nil.
+dom9851. NS a.root-servers.nil.
+dom9852. NS a.root-servers.nil.
+dom9853. NS a.root-servers.nil.
+dom9854. NS a.root-servers.nil.
+dom9855. NS a.root-servers.nil.
+dom9856. NS a.root-servers.nil.
+dom9857. NS a.root-servers.nil.
+dom9858. NS a.root-servers.nil.
+dom9859. NS a.root-servers.nil.
+dom9860. NS a.root-servers.nil.
+dom9861. NS a.root-servers.nil.
+dom9862. NS a.root-servers.nil.
+dom9863. NS a.root-servers.nil.
+dom9864. NS a.root-servers.nil.
+dom9865. NS a.root-servers.nil.
+dom9866. NS a.root-servers.nil.
+dom9867. NS a.root-servers.nil.
+dom9868. NS a.root-servers.nil.
+dom9869. NS a.root-servers.nil.
+dom9870. NS a.root-servers.nil.
+dom9871. NS a.root-servers.nil.
+dom9872. NS a.root-servers.nil.
+dom9873. NS a.root-servers.nil.
+dom9874. NS a.root-servers.nil.
+dom9875. NS a.root-servers.nil.
+dom9876. NS a.root-servers.nil.
+dom9877. NS a.root-servers.nil.
+dom9878. NS a.root-servers.nil.
+dom9879. NS a.root-servers.nil.
+dom9880. NS a.root-servers.nil.
+dom9881. NS a.root-servers.nil.
+dom9882. NS a.root-servers.nil.
+dom9883. NS a.root-servers.nil.
+dom9884. NS a.root-servers.nil.
+dom9885. NS a.root-servers.nil.
+dom9886. NS a.root-servers.nil.
+dom9887. NS a.root-servers.nil.
+dom9888. NS a.root-servers.nil.
+dom9889. NS a.root-servers.nil.
+dom9890. NS a.root-servers.nil.
+dom9891. NS a.root-servers.nil.
+dom9892. NS a.root-servers.nil.
+dom9893. NS a.root-servers.nil.
+dom9894. NS a.root-servers.nil.
+dom9895. NS a.root-servers.nil.
+dom9896. NS a.root-servers.nil.
+dom9897. NS a.root-servers.nil.
+dom9898. NS a.root-servers.nil.
+dom9899. NS a.root-servers.nil.
+dom9900. NS a.root-servers.nil.
+dom9901. NS a.root-servers.nil.
+dom9902. NS a.root-servers.nil.
+dom9903. NS a.root-servers.nil.
+dom9904. NS a.root-servers.nil.
+dom9905. NS a.root-servers.nil.
+dom9906. NS a.root-servers.nil.
+dom9907. NS a.root-servers.nil.
+dom9908. NS a.root-servers.nil.
+dom9909. NS a.root-servers.nil.
+dom9910. NS a.root-servers.nil.
+dom9911. NS a.root-servers.nil.
+dom9912. NS a.root-servers.nil.
+dom9913. NS a.root-servers.nil.
+dom9914. NS a.root-servers.nil.
+dom9915. NS a.root-servers.nil.
+dom9916. NS a.root-servers.nil.
+dom9917. NS a.root-servers.nil.
+dom9918. NS a.root-servers.nil.
+dom9919. NS a.root-servers.nil.
+dom9920. NS a.root-servers.nil.
+dom9921. NS a.root-servers.nil.
+dom9922. NS a.root-servers.nil.
+dom9923. NS a.root-servers.nil.
+dom9924. NS a.root-servers.nil.
+dom9925. NS a.root-servers.nil.
+dom9926. NS a.root-servers.nil.
+dom9927. NS a.root-servers.nil.
+dom9928. NS a.root-servers.nil.
+dom9929. NS a.root-servers.nil.
+dom9930. NS a.root-servers.nil.
+dom9931. NS a.root-servers.nil.
+dom9932. NS a.root-servers.nil.
+dom9933. NS a.root-servers.nil.
+dom9934. NS a.root-servers.nil.
+dom9935. NS a.root-servers.nil.
+dom9936. NS a.root-servers.nil.
+dom9937. NS a.root-servers.nil.
+dom9938. NS a.root-servers.nil.
+dom9939. NS a.root-servers.nil.
+dom9940. NS a.root-servers.nil.
+dom9941. NS a.root-servers.nil.
+dom9942. NS a.root-servers.nil.
+dom9943. NS a.root-servers.nil.
+dom9944. NS a.root-servers.nil.
+dom9945. NS a.root-servers.nil.
+dom9946. NS a.root-servers.nil.
+dom9947. NS a.root-servers.nil.
+dom9948. NS a.root-servers.nil.
+dom9949. NS a.root-servers.nil.
+dom9950. NS a.root-servers.nil.
+dom9951. NS a.root-servers.nil.
+dom9952. NS a.root-servers.nil.
+dom9953. NS a.root-servers.nil.
+dom9954. NS a.root-servers.nil.
+dom9955. NS a.root-servers.nil.
+dom9956. NS a.root-servers.nil.
+dom9957. NS a.root-servers.nil.
+dom9958. NS a.root-servers.nil.
+dom9959. NS a.root-servers.nil.
+dom9960. NS a.root-servers.nil.
+dom9961. NS a.root-servers.nil.
+dom9962. NS a.root-servers.nil.
+dom9963. NS a.root-servers.nil.
+dom9964. NS a.root-servers.nil.
+dom9965. NS a.root-servers.nil.
+dom9966. NS a.root-servers.nil.
+dom9967. NS a.root-servers.nil.
+dom9968. NS a.root-servers.nil.
+dom9969. NS a.root-servers.nil.
+dom9970. NS a.root-servers.nil.
+dom9971. NS a.root-servers.nil.
+dom9972. NS a.root-servers.nil.
+dom9973. NS a.root-servers.nil.
+dom9974. NS a.root-servers.nil.
+dom9975. NS a.root-servers.nil.
+dom9976. NS a.root-servers.nil.
+dom9977. NS a.root-servers.nil.
+dom9978. NS a.root-servers.nil.
+dom9979. NS a.root-servers.nil.
+dom9980. NS a.root-servers.nil.
+dom9981. NS a.root-servers.nil.
+dom9982. NS a.root-servers.nil.
+dom9983. NS a.root-servers.nil.
+dom9984. NS a.root-servers.nil.
+dom9985. NS a.root-servers.nil.
+dom9986. NS a.root-servers.nil.
+dom9987. NS a.root-servers.nil.
+dom9988. NS a.root-servers.nil.
+dom9989. NS a.root-servers.nil.
+dom9990. NS a.root-servers.nil.
+dom9991. NS a.root-servers.nil.
+dom9992. NS a.root-servers.nil.
+dom9993. NS a.root-servers.nil.
+dom9994. NS a.root-servers.nil.
+dom9995. NS a.root-servers.nil.
+dom9996. NS a.root-servers.nil.
+dom9997. NS a.root-servers.nil.
+dom9998. NS a.root-servers.nil.
+dom9999. NS a.root-servers.nil.
diff --git a/bin/tests/system/doth/ns2/cert.pem b/bin/tests/system/doth/ns2/cert.pem
new file mode 100644
index 0000000..f9c7e61
--- /dev/null
+++ b/bin/tests/system/doth/ns2/cert.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICHTCCAcOgAwIBAgIUATq1E48Hj7vAQBwn8H/1oQvqvJ0wCgYIKoZIzj0EAwIw
+YzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQHDAxSZWR3b29kIENp
+dHkxDDAKBgNVBAoMA0lTQzEOMAwGA1UECwwFQklORDkxEjAQBgNVBAMMCWxvY2Fs
+aG9zdDAgFw0yMTAyMTIwMzIxMzFaGA8yMTIxMDExOTAzMjEzMVowYzELMAkGA1UE
+BhMCVVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQHDAxSZWR3b29kIENpdHkxDDAKBgNV
+BAoMA0lTQzEOMAwGA1UECwwFQklORDkxEjAQBgNVBAMMCWxvY2FsaG9zdDBZMBMG
+ByqGSM49AgEGCCqGSM49AwEHA0IABC1uCviud7QFTJ8DfdrLwjkBolYHJJR9c9HP
+bshvKDXahhRU9+HCbWBNLlqFR6aMs8wyE32cXHLZ70XaILkH88SjUzBRMB0GA1Ud
+DgQWBBRPpE9aC2MO0TAlCp18vR9vqe4R2TAfBgNVHSMEGDAWgBRPpE9aC2MO0TAl
+Cp18vR9vqe4R2TAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIE3L
+zx4iRVqjnOACc+/G0Shru+AIk/MEglfrvP5wxZaVAiEArcmut+hYb+cG0UW5ct/U
+Q183Kk25XYJkTj39GSBiiiA=
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/doth/ns2/key.pem b/bin/tests/system/doth/ns2/key.pem
new file mode 100644
index 0000000..90716c8
--- /dev/null
+++ b/bin/tests/system/doth/ns2/key.pem
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIFBLYPWvhrGBMyfi04oC53LOl00LZRZbVOVnC0K30XOCoAoGCCqGSM49
+AwEHoUQDQgAELW4K+K53tAVMnwN92svCOQGiVgcklH1z0c9uyG8oNdqGFFT34cJt
+YE0uWoVHpoyzzDITfZxcctnvRdoguQfzxA==
+-----END EC PRIVATE KEY-----
diff --git a/bin/tests/system/doth/ns2/named.conf.in b/bin/tests/system/doth/ns2/named.conf.in
new file mode 100644
index 0000000..3cb2042
--- /dev/null
+++ b/bin/tests/system/doth/ns2/named.conf.in
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+tls local {
+ key-file "../CA/certs/srv02.crt01.example.com.key";
+ cert-file "../CA/certs/srv02.crt01.example.com.pem";
+ dhparam-file "../dhparam3072.pem";
+};
+
+http local {
+ endpoints { "/dns-query"; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ tls-port @TLSPORT@;
+ https-port @HTTPSPORT@;
+ http-port @HTTPPORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on tls local { 10.53.0.2; }; // DoT
+ listen-on-v6 tls local { fd92:7065:b8e:ffff::2; };
+ listen-on tls local http local { 10.53.0.2; }; // DoH
+ listen-on-v6 tls local http local { fd92:7065:b8e:ffff::2; };
+ listen-on tls none http local { 10.53.0.2; }; // unencrypted DoH
+ listen-on-v6 tls none http local { fd92:7065:b8e:ffff::2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ ixfr-from-differences yes;
+ check-integrity no;
+ dnssec-validation yes;
+ transfers-in 100;
+ transfers-out 100;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+tls tls-example-primary {
+ remote-hostname "srv01.crt01.example.com"; // enable Strict TLS
+ ca-file "../CA/CA.pem";
+};
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.1 tls tls-example-primary; };
+ file "example.db";
+ allow-transfer { any; };
+};
+
+# the server's certificate does not contain SubjectAltName, which is required for DoT
+tls tls-example-primary-no-san {
+ remote-hostname "srv01.crt02-no-san.example.com"; // enable Strict TLS
+ ca-file "../CA/CA.pem";
+};
+
+zone "example3" {
+ type secondary;
+ primaries { 10.53.0.1 port @EXTRAPORT2@ tls tls-example-primary-no-san; };
+ file "example3.db";
+ allow-transfer { any; };
+};
+
+# As you can see, the "remote-hostname" is missing, but "ca-file" is
+# specified. As the result, the primaries server certificate will be
+# verified using the IP address instead of hostname. That is fine,
+# because the server certificate is issued with IP address in the
+# SubjectAltName section.
+tls tls-example-primary-strict-tls-no-hostname {
+ ca-file "../CA/CA.pem"; // enable Strict TLS
+};
+
+zone "example4" {
+ type secondary;
+ primaries { 10.53.0.1 tls tls-example-primary-strict-tls-no-hostname; };
+ file "example4.db";
+ allow-transfer { any; };
+};
+
+tls tls-example-primary-strict-tls-ipv4 {
+ remote-hostname "10.53.0.1"; # the IP is in the server's cert SAN
+ ca-file "../CA/CA.pem"; # enable Strict TLS
+};
+
+zone "example5" {
+ type secondary;
+ primaries { 10.53.0.1 tls tls-example-primary-strict-tls-ipv4; };
+ file "example5.db";
+ allow-transfer { any; };
+};
+
+tls tls-example-primary-strict-tls-ipv6 {
+ remote-hostname "fd92:7065:b8e:ffff::1"; # the IP is in the server's cert SAN
+ ca-file "../CA/CA.pem"; # enable Strict TLS
+};
+
+zone "example6" {
+ type secondary;
+ primaries { 10.53.0.1 tls tls-example-primary-strict-tls-ipv6; };
+ file "example6.db";
+ allow-transfer { any; };
+};
+
+tls tls-example-primary-strict-tls-wrong-host {
+ remote-hostname "not-present.example.com"; # this is not present in the server's cert SAN
+ ca-file "../CA/CA.pem"; # enable Strict TLS
+};
+
+zone "example7" {
+ type secondary;
+ primaries { 10.53.0.1 tls tls-example-primary-strict-tls-wrong-host; };
+ file "example7.db";
+ allow-transfer { any; };
+};
+
+tls tls-example-primary-strict-tls-expired {
+ remote-hostname "srv01.crt03-expired.example.com";
+ ca-file "../CA/CA.pem";
+};
+
+zone "example8" {
+ type secondary;
+ primaries { 10.53.0.1 port @EXTRAPORT4@ tls tls-example-primary-strict-tls-expired; };
+ file "example8.db";
+ allow-transfer { any; };
+};
+
+tls tls-example-primary-mutual-tls {
+ remote-hostname "srv01.crt01.example.com";
+ ca-file "../CA/CA.pem";
+ cert-file "../CA/certs/srv01.client02-ns2.example.com.pem";
+ key-file "../CA/certs/srv01.client02-ns2.example.com.key";
+};
+
+zone "example9" {
+ type secondary;
+ primaries { 10.53.0.1 port @EXTRAPORT5@ tls tls-example-primary-mutual-tls; };
+ file "example9.db";
+ allow-transfer { any; };
+};
+
+zone "example10" {
+ type secondary;
+ primaries { 10.53.0.1 port @EXTRAPORT5@ tls tls-example-primary; };
+ file "example10.db";
+ allow-transfer { any; };
+};
+
+tls tls-example-primary-mutual-tls-expired {
+ remote-hostname "srv01.crt01.example.com";
+ ca-file "../CA/CA.pem";
+ cert-file "../CA/certs/srv01.client03-ns2-expired.example.com.pem";
+ key-file "../CA/certs/srv01.client03-ns2-expired.example.com.key";
+};
+
+zone "example11" {
+ type secondary;
+ primaries { 10.53.0.1 port @EXTRAPORT5@ tls tls-example-primary-mutual-tls-expired; };
+ file "example11.db";
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/doth/ns3/named.conf.in b/bin/tests/system/doth/ns3/named.conf.in
new file mode 100644
index 0000000..74d3957
--- /dev/null
+++ b/bin/tests/system/doth/ns3/named.conf.in
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+tls local {
+ key-file "../CA/certs/srv03.crt01.example.com.key";
+ cert-file "../CA/certs/srv03.crt01.example.com.pem";
+ dhparam-file "../dhparam3072.pem";
+};
+
+http local {
+ endpoints { "/dns-query"; };
+};
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ tls-port @TLSPORT@;
+ https-port @HTTPSPORT@;
+ http-port @HTTPPORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on tls local { 10.53.0.3; }; // DoT
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ ixfr-from-differences yes;
+ check-integrity no;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+tls tls-v1.2-pfs {
+ protocols { TLSv1.2; };
+ ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+ prefer-server-ciphers no;
+};
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.1 tls tls-v1.2-pfs; };
+ file "example.db";
+ allow-transfer { any; };
+};
+
+tls tls-pfs-aes-128 {
+ protocols { TLSv1.2; };
+ // AES128 does not match the setting on the server: AES256
+ ciphers "AES128:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+ prefer-server-ciphers no;
+};
+
+zone "example2" {
+ type secondary;
+ primaries port @EXTRAPORT1@ { 10.53.0.1 tls tls-pfs-aes-128; };
+ file "example2.db";
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/doth/ns4/named.conf.in b/bin/tests/system/doth/ns4/named.conf.in
new file mode 100644
index 0000000..077226a
--- /dev/null
+++ b/bin/tests/system/doth/ns4/named.conf.in
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# We need a separate instance for the "rndc reconfig" test in order to
+# ensure that it does not use ephemeral keys (these are costly to
+# generate) and creates a minimal amount of TLS contexts, reducing the
+# time needed for startup/reconfiguration. Long
+# startup/reconfiguration was known to cause timeout issues in the CI
+# system, where many tests run in parallel.
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+tls local {
+ key-file "../CA/certs/srv04.crt01.example.com.key";
+ cert-file "../CA/certs/srv04.crt01.example.com.pem";
+ dhparam-file "../dhparam3072.pem";
+};
+
+http local {
+ endpoints { "/dns-query"; };
+};
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ tls-port @TLSPORT@;
+ https-port @HTTPSPORT@;
+ http-port @HTTPPORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on tls local { 10.53.0.4; }; // DoT
+ listen-on tls local http local { 10.53.0.4; }; // DoH
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ ixfr-from-differences yes;
+ check-integrity no;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+tls tls-v1.2-pfs {
+ protocols { TLSv1.2; };
+ ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+ prefer-server-ciphers no;
+};
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.1 tls tls-v1.2-pfs; };
+ file "example.db";
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/doth/prereq.sh b/bin/tests/system/doth/prereq.sh
new file mode 100644
index 0000000..36a8e37
--- /dev/null
+++ b/bin/tests/system/doth/prereq.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$FEATURETEST --with-libnghttp2 || {
+ echo_i "This test requires libnghttp2 support." >&2
+ exit 255
+}
+exit 0
diff --git a/bin/tests/system/doth/setup.sh b/bin/tests/system/doth/setup.sh
new file mode 100644
index 0000000..c50c31f
--- /dev/null
+++ b/bin/tests/system/doth/setup.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns1/example.db
+
+echo '; huge answer' >> ns1/example.db
+x=1
+while [ $x -le 50 ]; do
+ y=1
+ while [ $y -le 50 ]; do
+ printf 'biganswer\t\tA\t\t10.10.%d.%d\n' $x $y >> ns1/example.db
+ y=$((y+1))
+ done
+ x=$((x+1))
+done
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
diff --git a/bin/tests/system/doth/stress_http_quota.py b/bin/tests/system/doth/stress_http_quota.py
new file mode 100755
index 0000000..12e29c8
--- /dev/null
+++ b/bin/tests/system/doth/stress_http_quota.py
@@ -0,0 +1,252 @@
+#!/usr/bin/env python
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import os
+import sys
+import socket
+import subprocess
+import random
+import time
+
+from functools import reduce
+from resource import getrlimit
+from resource import setrlimit
+from resource import RLIMIT_NOFILE
+
+MULTIDIG_INSTANCES = 10
+CONNECT_TRIES = 5
+
+random.seed()
+
+# Ensure we have enough file desriptors to work
+rlimit_nofile = getrlimit(RLIMIT_NOFILE)
+if rlimit_nofile[0] < 1024:
+ setrlimit(RLIMIT_NOFILE, (1024, rlimit_nofile[1]))
+
+
+# Introduce some random delay
+def jitter():
+ time.sleep((500 + random.randint(0, 250)) / 1000000.0)
+
+
+# A set of simple procedures to get the test's configuration options
+def get_http_port(http_secure=False):
+ http_port_env = None
+ if http_secure:
+ http_port_env = os.getenv("HTTPSPORT")
+ else:
+ http_port_env = os.getenv("HTTPPORT")
+ if http_port_env:
+ return int(http_port_env)
+ return 443
+
+
+def get_http_host():
+ bind_host = os.getenv("BINDHOST")
+ if bind_host:
+ return bind_host
+ return "localhost"
+
+
+def get_dig_path():
+ dig_path = os.getenv("DIG")
+ if dig_path:
+ return dig_path
+ return "dig"
+
+
+# A simple class which creates the given number of TCP connections to
+# the given host in order to stress the BIND's quota facility
+class TCPConnector:
+ def __init__(self, host, port):
+ self.host = host
+ self.port = port
+ self.connections = []
+
+ def connect_one(self):
+ tries = CONNECT_TRIES
+ while tries > 0:
+ try:
+ sock = socket.create_connection(
+ address=(self.host, self.port), timeout=None
+ )
+ self.connections.append(sock)
+ break
+ except ConnectionResetError:
+ # some jitter for BSDs
+ jitter()
+ continue
+ except TimeoutError:
+ jitter()
+ continue
+ finally:
+ tries -= 1
+
+ # Close an established connection (randomly)
+ def disconnect_random(self):
+ pos = random.randint(0, len(self.connections) - 1)
+ conn = self.connections[pos]
+ try:
+ conn.shutdown(socket.SHUT_RDWR)
+ conn.close()
+ except OSError:
+ conn.close()
+ finally:
+ self.connections.remove(conn)
+
+ def disconnect_all(self):
+ while len(self.connections) != 0:
+ self.disconnect_random()
+
+
+# A simple class which allows running a dig instance under control of
+# the process
+class SubDIG:
+ def __init__(self, http_secure=None, extra_args=None):
+ self.sub_process = None
+ self.dig_path = get_dig_path()
+ self.host = get_http_host()
+ self.port = get_http_port(http_secure=http_secure)
+ if http_secure:
+ self.http_secure = True
+ else:
+ self.http_secure = False
+ self.extra_args = extra_args
+
+ # This method constructs a command string
+ def get_command(self):
+ command = self.dig_path + " -p " + str(self.port) + " "
+ command = command + "+noadd +nosea +nostat +noquest +nocmd +time=30 "
+ if self.http_secure:
+ command = command + "+https "
+ else:
+ command = command + "+http-plain "
+ command = command + "@" + self.host + " "
+ if self.extra_args:
+ command = command + self.extra_args
+ return command
+
+ def run(self):
+ # pylint: disable=consider-using-with
+ with open(os.devnull, "w", encoding="utf-8") as devnull:
+ self.sub_process = subprocess.Popen(
+ self.get_command(), shell=True, stdout=devnull
+ )
+
+ def wait(self, timeout=None):
+ res = None
+ if timeout is None:
+ return self.sub_process.wait()
+ try:
+ res = self.sub_process.wait(timeout=timeout)
+ except subprocess.TimeoutExpired:
+ return None
+ return res
+
+ def alive(self):
+ return self.sub_process.poll() is None
+
+
+# A simple wrapper class which allows running multiple dig instances
+# and examining their statuses in one logical operation.
+class MultiDIG:
+ def __init__(self, numdigs, http_secure=None, extra_args=None):
+ assert int(numdigs) > 0
+ digs = []
+ for _ in range(1, int(numdigs) + 1):
+ digs.append(SubDIG(http_secure=http_secure, extra_args=extra_args))
+ self.digs = digs
+ assert len(self.digs) == int(numdigs)
+
+ def run(self):
+ for p in self.digs:
+ p.run()
+
+ def wait(self):
+ return map(lambda p: (p.wait()), self.digs)
+
+ # Wait for the all instances to terminate with expected given
+ # status. Returns true or false.
+ def wait_for_result(self, result):
+ return reduce(
+ lambda a, b: ((a == result or a is True) and b == result), self.wait()
+ )
+
+ def alive(self):
+ return reduce(lambda a, b: (a and b), map(lambda p: (p.alive()), self.digs))
+
+ def completed(self):
+ total = 0
+ for p in self.digs:
+ if not p.alive():
+ total += 1
+ return total
+
+
+# The test's main logic
+def run_test(http_secure=True):
+ query_args = "SOA ."
+ # Let's try to make a successful query
+ subdig = SubDIG(http_secure=http_secure, extra_args=query_args)
+ subdig.run()
+ assert subdig.wait() == 0, "DIG was expected to succeed"
+ # Let's create a lot of TCP connections to the server stress the
+ # HTTP quota
+ connector = TCPConnector(get_http_host(), get_http_port(http_secure=http_secure))
+ # Let's make queries until the quota kicks in
+ subdig = SubDIG(http_secure=http_secure, extra_args=query_args)
+ subdig.run()
+ while True:
+ connector.connect_one()
+ subdig = SubDIG(http_secure=http_secure, extra_args=query_args)
+ subdig.run()
+ if subdig.wait(timeout=5) is None:
+ break
+
+ # At this point quota has kicked in. Additionally, let's create a
+ # bunch of dig processes all trying to make a query against the
+ # server with exceeded quota
+ multidig = MultiDIG(
+ MULTIDIG_INSTANCES, http_secure=http_secure, extra_args=query_args
+ )
+ multidig.run()
+ # Wait for the dig instance to complete. Not a single instance has
+ # a chance to complete successfully because of the exceeded quota
+ assert (
+ subdig.wait(timeout=5) is None
+ ), "The single DIG instance has stopped prematurely"
+ assert subdig.alive(), "The single DIG instance is expected to be alive"
+ assert multidig.alive(), (
+ "The DIG instances from the set are all expected to "
+ "be alive, but {} of them have completed"
+ ).format(multidig.completed())
+ # Let's close opened connections (in random order) to let all dig
+ # processes to complete
+ connector.disconnect_all()
+ # Wait for all processes to complete successfully
+ assert subdig.wait() == 0, "Single DIG instance failed"
+ assert (
+ multidig.wait_for_result(0) is True
+ ), "One or more of DIG instances returned unexpected results"
+
+
+def main():
+ run_test(http_secure=True)
+ run_test(http_secure=False)
+ # If we have reached this point we could safely return 0
+ # (success). If the test fails because of an assert, the whole
+ # program will return non-zero exit code and produce the backtrace
+ return 0
+
+
+sys.exit(main())
diff --git a/bin/tests/system/doth/tests.sh b/bin/tests/system/doth/tests.sh
new file mode 100644
index 0000000..a95bd8c
--- /dev/null
+++ b/bin/tests/system/doth/tests.sh
@@ -0,0 +1,889 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck disable=SC1091
+. ../conf.sh
+
+common_dig_options="+noadd +nosea +nostat +noquest +nocmd"
+msg_xfrs_not_allowed=";; zone transfers over the established TLS connection are not allowed"
+msg_peer_verification_failed=";; TLS peer certificate verification"
+
+ca_file="./CA/CA.pem"
+
+if [ -x "$PYTHON" ]; then
+ OPENSSL_VERSION=$("$PYTHON" "$TOP_SRCDIR/bin/tests/system/doth/get_openssl_version.py")
+ OPENSSL_VERSION_MAJOR=$(echo "$OPENSSL_VERSION" | cut -d ' ' -f 1)
+ OPENSSL_VERSION_MINOR=$(echo "$OPENSSL_VERSION" | cut -d ' ' -f 2)
+fi
+
+# According to the RFC 8310, Section 8.1, Subject field MUST
+# NOT be inspected when verifying a hostname when using
+# DoT. Only SubjectAltName must be checked instead. That is
+# not the case for HTTPS, though.
+
+# Unfortunately, some quite old versions of OpenSSL (< 1.1.1)
+# might lack the functionality to implement that. It should
+# have very little real-world consequences, as most of the
+# production-ready certificates issued by real CAs will have
+# SubjectAltName set. In such a case, the Subject field is
+# ignored.
+#
+# On the platforms with too old TLS versions, e.g. RedHat 7, we should
+# ignore the tests checking the correct handling of absence of
+# SubjectAltName.
+if [ -n "$OPENSSL_VERSION" ]; then
+ if [ $OPENSSL_VERSION_MAJOR -gt 1 ]; then
+ run_san_tests=1
+ elif [ $OPENSSL_VERSION_MAJOR -eq 1 ] && [ $OPENSSL_VERSION_MINOR -ge 1 ]; then
+ run_san_tests=1
+ fi
+fi
+
+dig_with_tls_opts() {
+ # shellcheck disable=SC2086
+ "$DIG" +tls $common_dig_options -p "${TLSPORT}" "$@"
+}
+
+dig_with_https_opts() {
+ # shellcheck disable=SC2086
+ "$DIG" +https $common_dig_options -p "${HTTPSPORT}" "$@"
+}
+
+dig_with_http_opts() {
+ # shellcheck disable=SC2086
+ "$DIG" +http-plain $common_dig_options -p "${HTTPPORT}" "$@"
+}
+
+dig_with_opts() {
+ # shellcheck disable=SC2086
+ "$DIG" $common_dig_options -p "${PORT}" "$@"
+}
+
+wait_for_tls_xfer() (
+ srv_number="$1"
+ shift
+ zone_name="$1"
+ shift
+ # Let's bind to .10 to make it possible to easily distinguish dig from NSs in packet traces
+ dig_with_tls_opts -b 10.53.0.10 "@10.53.0.$srv_number" "${zone_name}." AXFR > "dig.out.ns$srv_number.${zone_name}.test$n" || return 1
+ grep "^;" "dig.out.ns$srv_number.${zone_name}.test$n" > /dev/null && return 1
+ return 0
+)
+
+status=0
+n=0
+
+n=$((n+1))
+echo_i "testing XoT server functionality (using dig) ($n)"
+ret=0
+dig_with_tls_opts example. -b 10.53.0.10 @10.53.0.1 axfr > dig.out.ns1.test$n || ret=1
+grep "^;" dig.out.ns1.test$n | cat_i
+digcomp example.axfr.good dig.out.ns1.test$n || ret=1
+if test $ret != 0 ; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing incoming XoT functionality (from the first secondary) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 2 example; then
+ digcomp example.axfr.good "dig.out.ns2.example.test$n" || ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+ grep "^;" "dig.out.ns2.example.test$n" | cat_i
+ ret=1
+fi
+if test $ret != 0 ; then echo_i "failed"; fi
+status=$((status+ret))
+
+if [ -n "$run_san_tests" ]; then
+ n=$((n + 1))
+ echo_i "testing incoming XoT functionality (from the first secondary, no SubjectAltName, failure expected) ($n)"
+ ret=0
+ if retry_quiet 10 wait_for_tls_xfer 2 example3; then
+ ret=1
+ else
+ echo_i "timed out waiting for zone transfer"
+ fi
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n + 1))
+echo_i "testing incoming XoT functionality (from the first secondary, StrictTLS via implicit IP) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 2 example4; then
+ retry_quiet 5 test -f "ns2/example4.db" || ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+ grep "^;" "dig.out.ns2.example4.test$n" | cat_i
+ ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing incoming XoT functionality (from the first secondary, StrictTLS via specified IPv4) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 2 example5; then
+ retry_quiet 5 test -f "ns2/example5.db" || ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+ grep "^;" "dig.out.ns2.example5.test$n" | cat_i
+ ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing incoming XoT functionality (from the first secondary, StrictTLS via specified IPv6) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 2 example6; then
+ retry_quiet 5 test -f "ns2/example6.db" || ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+ grep "^;" "dig.out.ns2.example6.test$n" | cat_i
+ ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing incoming XoT functionality (from the first secondary, wrong hostname, failure expected) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 2 example7; then
+ ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing incoming XoT functionality (from the first secondary, expired certificate, failure expected) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 2 example8; then
+ ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing incoming XoT functionality (from the first secondary, MutualTLS) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 2 example9; then
+ retry_quiet 5 test -f "ns2/example9.db" || ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+ grep "^;" "dig.out.ns2.example9.test$n" | cat_i
+ ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing incoming XoT functionality (from the first secondary, MutualTLS, no client cert, failure expected) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 2 example10; then
+ ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing incoming XoT functionality (from the first secondary, MutualTLS, expired client cert, failure expected) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 2 example11; then
+ ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "testing incoming XoT functionality (from the second secondary) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 3 example; then
+ digcomp example.axfr.good "dig.out.ns3.example.test$n" || ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+ grep "^;" "dig.out.ns3.example.test$n" | cat_i
+ ret=1
+fi
+if test $ret != 0 ; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing incoming XoT functionality (from the second secondary, mismatching ciphers, failure expected) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 3 example2; then
+ ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+fi
+if test $ret != 0 ; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing incoming XoT functionality (from the third secondary) ($n)"
+ret=0
+if retry_quiet 10 wait_for_tls_xfer 4 example; then
+ digcomp example.axfr.good "dig.out.ns4.example.test$n" || ret=1
+else
+ echo_i "timed out waiting for zone transfer"
+ grep "^;" "dig.out.ns4.example.test$n" | cat_i
+ ret=1
+fi
+if test $ret != 0 ; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n + 1))
+echo_i "checking DoT query (ephemeral key) ($n)"
+ret=0
+dig_with_tls_opts @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoT query via IPv6 (ephemeral key) ($n)"
+ret=0
+dig_with_tls_opts -6 @fd92:7065:b8e:ffff::1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoT query (static key) ($n)"
+ret=0
+dig_with_tls_opts @10.53.0.2 example SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoT query via IPv6 (static key) ($n)"
+ret=0
+dig_with_tls_opts -6 @fd92:7065:b8e:ffff::2 example SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoT XFR ($n)"
+ret=0
+dig_with_tls_opts +comm @10.53.0.1 . AXFR > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# zone transfers are allowed only via TLS
+n=$((n+1))
+echo_i "testing zone transfer over Do53 server functionality (using dig, failure expected) ($n)"
+ret=0
+dig_with_opts example. -b 10.53.0.10 @10.53.0.1 axfr > dig.out.ns1.test$n || ret=1
+grep "; Transfer failed." dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# querying zones is still allowed via UDP/TCP
+n=$((n + 1))
+echo_i "checking Do53 query ($n)"
+ret=0
+dig_with_opts @10.53.0.1 example SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# In this test we are trying to establish a DoT connection over the
+# DoH port. That is intentional, as dig should fail right after
+# handshake has happened and before sending any queries, as XFRs, per
+# the RFC, could happen only over a connection where "dot" ALPN token
+# was negotiated. over DoH it cannot happen, as only "h2" token could
+# be selected for a DoH connection.
+n=$((n + 1))
+echo_i "checking DoT XFR with wrong ALPN token (h2, failure expected) ($n)"
+ret=0
+# shellcheck disable=SC2086
+"$DIG" +tls $common_dig_options -p "${HTTPSPORT}" +comm @10.53.0.1 . AXFR > dig.out.test$n
+grep "$msg_xfrs_not_allowed" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Let's try to issue an HTTP/2 query over TLS port to check if dig
+# will detect ALPN token negotiation problem.
+n=$((n + 1))
+echo_i "checking DoH query when ALPN is expected to fail (dot, failure expected) ($n)"
+ret=0
+# shellcheck disable=SC2086
+"$DIG" +https $common_dig_options -p "${TLSPORT}" "$@" @10.53.0.1 . SOA > dig.out.test$n && ret=1
+grep "ALPN for HTTP/2 failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (POST) ($n)"
+ret=0
+dig_with_https_opts +stat @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep -F "(HTTPS)" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query via IPv6 (POST) ($n)"
+ret=0
+dig_with_https_opts +stat -6 @fd92:7065:b8e:ffff::1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep -F "(HTTPS)" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (POST, static key) ($n)"
+ret=0
+dig_with_https_opts @10.53.0.2 example SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query via IPv6 (POST, static key) ($n)"
+ret=0
+dig_with_https_opts -6 @fd92:7065:b8e:ffff::2 example SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (POST, nonstandard endpoint) ($n)"
+ret=0
+dig_with_https_opts +https=/alter @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query via IPv6 (POST, nonstandard endpoint) ($n)"
+ret=0
+dig_with_https_opts -6 +https=/alter @fd92:7065:b8e:ffff::1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (POST, undefined endpoint, failure expected) ($n)"
+ret=0
+dig_with_https_opts +tries=1 +time=1 +https=/fake @10.53.0.1 . SOA > dig.out.test$n && ret=1
+grep "communications error" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query via IPv6 (POST, undefined endpoint, failure expected) ($n)"
+ret=0
+dig_with_https_opts -6 +tries=1 +time=1 +https=/fake @fd92:7065:b8e:ffff::1 . SOA > dig.out.test$n && ret=1
+grep "communications error" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH XFR (POST) (failure expected) ($n)"
+ret=0
+dig_with_https_opts +comm @10.53.0.1 . AXFR > dig.out.test$n || ret=1
+grep "; Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (GET) ($n)"
+ret=0
+dig_with_https_opts +stat +https-get @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep -F "(HTTPS-GET)" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query via IPv6 (GET) ($n)"
+ret=0
+dig_with_https_opts -6 +stat +https-get @fd92:7065:b8e:ffff::1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep -F "(HTTPS-GET)" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (GET, static key) ($n)"
+ret=0
+dig_with_https_opts +https-get @10.53.0.2 example SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query via IPv6 (GET, static key) ($n)"
+ret=0
+dig_with_https_opts -6 +https-get @fd92:7065:b8e:ffff::2 example SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (GET, nonstandard endpoint) ($n)"
+ret=0
+dig_with_https_opts +https-get=/alter @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query via IPv6 (GET, nonstandard endpoint) ($n)"
+ret=0
+dig_with_https_opts -6 +https-get=/alter @fd92:7065:b8e:ffff::1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (GET, undefined endpoint, failure expected) ($n)"
+ret=0
+dig_with_https_opts +tries=1 +time=1 +https-get=/fake @10.53.0.1 . SOA > dig.out.test$n && ret=1
+grep "communications error" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query via IPv6 (GET, undefined endpoint, failure expected) ($n)"
+ret=0
+dig_with_https_opts -6 +tries=1 +time=1 +https-get=/fake @fd92:7065:b8e:ffff::1 . SOA > dig.out.test$n && ret=1
+grep "communications error" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH XFR (GET) (failure expected) ($n)"
+ret=0
+dig_with_https_opts +https-get +comm @10.53.0.1 . AXFR > dig.out.test$n || ret=1
+grep "; Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking unencrypted DoH query (POST) ($n)"
+ret=0
+dig_with_http_opts +stat @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep -F "(HTTP)" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking unencrypted DoH query via IPv6 (POST) ($n)"
+ret=0
+dig_with_http_opts -6 +stat @fd92:7065:b8e:ffff::1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep -F "(HTTP)" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking unencrypted DoH query (GET) ($n)"
+ret=0
+dig_with_http_opts +stat +http-plain-get @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep -F "(HTTP-GET)" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking unencrypted DoH query via IPv6 (GET) ($n)"
+ret=0
+dig_with_http_opts -6 +stat +http-plain-get @fd92:7065:b8e:ffff::1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep -F "(HTTP-GET)" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking unencrypted DoH XFR (failure expected) ($n)"
+ret=0
+dig_with_http_opts +comm @10.53.0.1 . AXFR > dig.out.test$n || ret=1
+grep "; Transfer failed." dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query for a large answer (POST) ($n)"
+ret=0
+dig_with_https_opts @10.53.0.1 biganswer.example A > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2500" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query via IPv6 for a large answer (POST) ($n)"
+ret=0
+dig_with_https_opts -6 @fd92:7065:b8e:ffff::1 biganswer.example A > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2500" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query for a large answer (GET) ($n)"
+ret=0
+dig_with_https_opts +https-get @10.53.0.1 biganswer.example A > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2500" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query via IPv6 for a large answer (GET) ($n)"
+ret=0
+dig_with_https_opts -6 +https-get @fd92:7065:b8e:ffff::1 biganswer.example A > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2500" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking unencrypted DoH query for a large answer (POST) ($n)"
+ret=0
+dig_with_http_opts @10.53.0.1 biganswer.example A > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2500" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking unencrypted DoH query via IPv6 for a large answer (POST) ($n)"
+ret=0
+dig_with_http_opts -6 @fd92:7065:b8e:ffff::1 biganswer.example A > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2500" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking unencrypted DoH query for a large answer (GET) ($n)"
+ret=0
+dig_with_http_opts +http-plain-get @10.53.0.1 biganswer.example A > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2500" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking unencrypted DoH query via IPv6 for a large answer (GET) ($n)"
+ret=0
+dig_with_http_opts -6 +http-plain-get @fd92:7065:b8e:ffff::1 biganswer.example A > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2500" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+wait_for_tlsctx_update_ns4 () {
+ grep "updating TLS context on 10.53.0.4#${HTTPSPORT}" ns4/named.run > /dev/null || return 1
+ grep "updating TLS context on 10.53.0.4#${TLSPORT}" ns4/named.run > /dev/null || return 1
+ return 0
+}
+
+n=$((n + 1))
+echo_i "doing rndc reconfig to see that queries keep being served after that ($n)"
+ret=0
+rndc_reconfig ns4 10.53.0.4 60
+retry_quiet 15 wait_for_tlsctx_update_ns4 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoT query after a reconfiguration ($n)"
+ret=0
+dig_with_tls_opts @10.53.0.4 example SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (POST) after a reconfiguration ($n)"
+ret=0
+dig_with_https_opts @10.53.0.4 example SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "doing rndc reconfig to see if HTTP endpoints have gotten reconfigured ($n)"
+ret=0
+# 'sed -i ...' is not portable. Sigh...
+sed 's/\/dns-query/\/dns-query-test/g' "ns4/named.conf" > "ns4/named.conf.sed"
+mv -f "ns4/named.conf.sed" "ns4/named.conf"
+rndc_reconfig ns4 10.53.0.4 60
+retry_quiet 15 wait_for_tlsctx_update_ns4 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (POST) to verify HTTP endpoint reconfiguration ($n)"
+ret=0
+dig_with_https_opts +https='/dns-query-test' @10.53.0.4 example SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoT query (with TLS verification enabled) ($n)"
+ret=0
+dig_with_tls_opts +tls-ca="$ca_file" +tls-hostname="srv01.crt01.example.com" @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (with TLS verification enabled, self-signed cert, failure expected) ($n)"
+ret=0
+dig_with_https_opts +tls-ca="$ca_file" +tls-hostname="srv01.crt01.example.com" @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "$msg_peer_verification_failed" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoT query (with TLS verification using the system's CA store, failure expected) ($n)"
+ret=0
+dig_with_tls_opts +tls-ca +tls-hostname="srv01.crt01.example.com" @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "$msg_peer_verification_failed" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (with TLS verification using the system's CA store, failure expected) ($n)"
+ret=0
+dig_with_https_opts +tls-ca +tls-hostname="srv01.crt01.example.com" @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "$msg_peer_verification_failed" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# the primary server's certificate contains the IP address in the
+# SubjectAltName section
+n=$((n + 1))
+echo_i "checking DoT query (with TLS verification, hostname is not specified, IP address is used instead) ($n)"
+ret=0
+dig_with_tls_opts +tls-ca="$ca_file" @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "$msg_peer_verification_failed" dig.out.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if [ -n "$run_san_tests" ]; then
+ # SubjectAltName is required for DoT as according to RFC 8310, Subject
+ # field MUST NOT be inspected when verifying hostname for DoT.
+ n=$((n + 1))
+ echo_i "checking DoT query (with TLS verification enabled when SubjectAltName is not set, failure expected) ($n)"
+ ret=0
+ dig_with_tls_opts +tls-ca="$ca_file" +tls-hostname="srv01.crt02-no-san.example.com" @10.53.0.1 . SOA > dig.out.test$n || ret=1
+ grep "$msg_peer_verification_failed" dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ n=$((n + 1))
+ echo_i "checking DoT XFR over a TLS port where SubjectAltName is not set (failure expected) ($n)"
+ ret=0
+ # shellcheck disable=SC2086
+ dig_with_tls_opts +tls-ca="$ca_file" +tls-hostname="srv01.crt02-no-san.example.com" -p "${EXTRAPORT2}" +comm @10.53.0.1 . AXFR > dig.out.test$n || ret=1
+ grep "$msg_peer_verification_failed" dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+# SubjectAltName is not required for HTTPS. Having a properly set
+# Common Name in the Subject field is enough.
+n=$((n + 1))
+echo_i "checking DoH query (when SubjectAltName is not set) ($n)"
+ret=0
+dig_with_https_opts +tls-ca="$ca_file" +tls-hostname="srv01.crt02-no-san.example.com" -p "${EXTRAPORT3}" +comm @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoT query (expired certificate, Opportunistic TLS) ($n)"
+ret=0
+dig_with_tls_opts +tls -p "${EXTRAPORT4}" +comm @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoT query (expired certificate, Strict TLS, failure expected) ($n)"
+ret=0
+dig_with_tls_opts +tls-ca="$ca_file" -p "${EXTRAPORT4}" +comm @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "$msg_peer_verification_failed" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "testing XoT server functionality (using dig, client certificate required, failure expected) ($n)"
+ret=0
+dig_with_tls_opts +tls-ca="$ca_file" -p "${EXTRAPORT5}" example8. -b 10.53.0.10 @10.53.0.1 axfr > dig.out.ns1.test$n || ret=1
+grep "; Transfer failed." dig.out.ns1.test$n > /dev/null || ret=1
+if test $ret != 0 ; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "testing XoT server functionality (using dig, client certificate used) ($n)"
+ret=0
+dig_with_tls_opts +tls-ca="$ca_file" +tls-certfile="./CA/certs/srv01.client01.example.com.pem" +tls-keyfile="./CA/certs/srv01.client01.example.com.key" -p "${EXTRAPORT5}" example8. -b 10.53.0.10 @10.53.0.1 axfr > dig.out.ns1.test$n || ret=1
+digcomp dig.out.ns1.test$n example8.axfr.good > /dev/null || ret=1
+if test $ret != 0 ; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (client certificate required, failure expected) ($n)"
+ret=0
+dig_with_https_opts +tls-ca="$ca_file" -p "${EXTRAPORT6}" +comm @10.53.0.1 . SOA > dig.out.test$n && ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking DoH query (client certificate used) ($n)"
+ret=0
+# shellcheck disable=SC2086
+dig_with_https_opts +https +tls-ca="$ca_file" +tls-certfile="./CA/certs/srv01.client01.example.com.pem" +tls-keyfile="./CA/certs/srv01.client01.example.com.key" -p "${EXTRAPORT6}" +comm @10.53.0.1 . SOA > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# send two requests one after another so that session resumption will happen
+n=$((n + 1))
+echo_i "checking DoH query (client certificate used - session resumption when using Mutual TLS) ($n)"
+ret=0
+# shellcheck disable=SC2086
+dig_with_https_opts +https +tls-ca="$ca_file" +tls-certfile="./CA/certs/srv01.client01.example.com.pem" +tls-keyfile="./CA/certs/srv01.client01.example.com.key" -p "${EXTRAPORT6}" +comm @10.53.0.1 . SOA . SOA > dig.out.test$n || ret=1
+grep "TLS error" dig.out.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+test_opcodes() {
+ EXPECT_STATUS="$1"
+ shift
+ for op in "$@";
+ do
+ n=$((n + 1))
+ echo_i "checking unexpected opcode query over DoH for opcode $op ($n)"
+ ret=0
+ dig_with_https_opts +https @10.53.0.1 +opcode="$op" > dig.out.test$n || ret=1
+ grep "status: $EXPECT_STATUS" dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ n=$((n + 1))
+ echo_i "checking unexpected opcode query over DoH via IPv6 for opcode $op ($n)"
+ ret=0
+ dig_with_https_opts -6 +https @fd92:7065:b8e:ffff::1 +opcode="$op" > dig.out.test$n || ret=1
+ grep "status: $EXPECT_STATUS" dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ n=$((n + 1))
+ echo_i "checking unexpected opcode query over DoH without encryption for opcode $op ($n)"
+ ret=0
+ dig_with_http_opts +http-plain @10.53.0.1 +opcode="$op" > dig.out.test$n || ret=1
+ grep "status: $EXPECT_STATUS" dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ n=$((n + 1))
+ echo_i "checking unexpected opcode query over DoH via IPv6 without encryption for opcode $op ($n)"
+ ret=0
+ dig_with_http_opts -6 +http-plain @fd92:7065:b8e:ffff::1 +opcode="$op" > dig.out.test$n || ret=1
+ grep "status: $EXPECT_STATUS" dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ n=$((n + 1))
+ echo_i "checking unexpected opcode query over DoT for opcode $op ($n)"
+ ret=0
+ dig_with_tls_opts +tls @10.53.0.1 +opcode="$op" > dig.out.test$n || ret=1
+ grep "status: $EXPECT_STATUS" dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ n=$((n + 1))
+ echo_i "checking unexpected opcode query over DoT via IPv6 for opcode $op ($n)"
+ ret=0
+ dig_with_tls_opts -6 +tls @fd92:7065:b8e:ffff::1 +opcode="$op" > dig.out.test$n || ret=1
+ grep "status: $EXPECT_STATUS" dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+ done
+}
+
+test_opcodes NOERROR 0
+test_opcodes NOTIMP 1 2 3 6 7 8 9 10 11 12 13 14 15
+test_opcodes FORMERR 4 5
+
+n=$((n + 1))
+echo_i "checking server quotas for both encrypted and unencrypted HTTP ($n)"
+ret=0
+if [ -x "$PYTHON" ]; then
+ BINDHOST="10.53.0.1" "$PYTHON" "$TOP_SRCDIR/bin/tests/system/doth/stress_http_quota.py" || ret=$?
+else
+ echo_i "Python is not available. Skipping the test..."
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# check whether we can use curl for sending test queries.
+if [ -x "${CURL}" ] ; then
+ CURL_HTTP2="$(${CURL} --version | grep -E '^Features:.* HTTP2( |$)' || true)"
+
+ if [ -n "$CURL_HTTP2" ]; then
+ testcurl=1
+ else
+ echo_i "The available version of CURL does not have HTTP/2 support"
+ fi
+fi
+
+# Note: see README.curl for information on how to generate curl
+# queries.
+if [ -n "$testcurl" ]; then
+ n=$((n + 1))
+ echo_i "checking max-age for positive answer ($n)"
+ ret=0
+ # use curl to query for 'example/SOA'
+ $CURL -kD headers.$n "https://10.53.0.1:${HTTPSPORT}/dns-query?dns=AAEAAAABAAAAAAAAB2V4YW1wbGUAAAYAAQ" > /dev/null 2>&1 || ret=1
+ grep "cache-control: max-age=86400" headers.$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ n=$((n + 1))
+ echo_i "checking max-age for negative answer ($n)"
+ ret=0
+ # use curl to query for 'fake.example/TXT'
+ $CURL -kD headers.$n "https://10.53.0.1:${HTTPSPORT}/dns-query?dns=AAEAAAABAAAAAAAABGZha2UHZXhhbXBsZQAAEAAB" > /dev/null 2>&1 || ret=1
+ grep "cache-control: max-age=3600" headers.$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/doth/tests_gnutls.py b/bin/tests/system/doth/tests_gnutls.py
new file mode 100644
index 0000000..5ddb708
--- /dev/null
+++ b/bin/tests/system/doth/tests_gnutls.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import selectors
+import struct
+import subprocess
+import time
+
+import pytest
+
+pytest.importorskip("dns")
+import dns.exception
+import dns.message
+import dns.name
+import dns.rdataclass
+import dns.rdatatype
+
+
+def test_gnutls_cli_query(gnutls_cli_executable, named_tlsport):
+ # Prepare the example/SOA query which will be sent over TLS.
+ query = dns.message.make_query("example.", dns.rdatatype.SOA)
+ query_wire = query.to_wire()
+ query_with_length = struct.pack(">H", len(query_wire)) + query_wire
+
+ # Run gnutls-cli.
+ gnutls_cli_args = [
+ gnutls_cli_executable,
+ "--no-ca-verification",
+ "-V",
+ "--no-ocsp",
+ "--alpn=dot",
+ "--logfile=gnutls-cli.log",
+ "--port=%d" % named_tlsport,
+ "10.53.0.1",
+ ]
+ with open("gnutls-cli.err", "wb") as gnutls_cli_stderr, subprocess.Popen(
+ gnutls_cli_args,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=gnutls_cli_stderr,
+ bufsize=0,
+ ) as gnutls_cli:
+ # Send the example/SOA query to the standard input of gnutls-cli. Do
+ # not close standard input yet because that causes gnutls-cli to close
+ # the TLS connection immediately, preventing the response from being
+ # read.
+ gnutls_cli.stdin.write(query_with_length)
+ gnutls_cli.stdin.flush()
+
+ # Keep reading data from the standard output of gnutls-cli until a full
+ # DNS message is received or a timeout is exceeded or gnutls-cli exits.
+ # Popen.communicate() cannot be used here because: a) it closes
+ # standard input after sending data to the process (see above why this
+ # is a problem), b) gnutls-cli is not DNS-aware, so it does not exit
+ # upon receiving a DNS response.
+ selector = selectors.DefaultSelector()
+ selector.register(gnutls_cli.stdout, selectors.EVENT_READ)
+ deadline = time.time() + 10
+ gnutls_cli_output = b""
+ response = b""
+ while not response and not gnutls_cli.poll():
+ if not selector.select(timeout=deadline - time.time()):
+ break
+ gnutls_cli_output += gnutls_cli.stdout.read(512)
+ try:
+ # Ignore TCP length, just try to parse a DNS message from
+ # the rest of the data received.
+ response = dns.message.from_wire(gnutls_cli_output[2:])
+ except dns.exception.FormError:
+ continue
+
+ # At this point either a DNS response was received or a timeout fired
+ # or gnutls-cli exited prematurely. Close the standard input of
+ # gnutls-cli. Terminate it if that does not cause it to shut down
+ # gracefully.
+ gnutls_cli.stdin.close()
+ try:
+ gnutls_cli.wait(5)
+ except subprocess.TimeoutExpired:
+ gnutls_cli.kill()
+
+ # Store the response received for diagnostic purposes.
+ with open("gnutls-cli.out.bin", "wb") as response_bin:
+ response_bin.write(gnutls_cli_output)
+ if response:
+ with open("gnutls-cli.out.txt", "w", encoding="utf-8") as response_txt:
+ response_txt.write(response.to_text())
+
+ # Check whether a response was received and whether it is sane.
+ assert response
+ assert query.id == response.id
+ assert len(response.answer) == 1
+ assert response.answer[0].match(
+ dns.name.from_text("example."),
+ dns.rdataclass.IN,
+ dns.rdatatype.SOA,
+ dns.rdatatype.NONE,
+ )
diff --git a/bin/tests/system/doth/tests_sh_doth.py b/bin/tests/system/doth/tests_sh_doth.py
new file mode 100644
index 0000000..ef87a06
--- /dev/null
+++ b/bin/tests/system/doth/tests_sh_doth.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_doth(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/doth/tests_sslyze.py b/bin/tests/system/doth/tests_sslyze.py
new file mode 100644
index 0000000..2562fe4
--- /dev/null
+++ b/bin/tests/system/doth/tests_sslyze.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import os
+import pathlib
+import subprocess
+
+import pytest
+
+
+def is_pid_alive(pid):
+ try:
+ os.kill(pid, 0)
+ return True
+ except OSError:
+ return False
+
+
+def run_sslyze_in_a_loop(executable, port, log_file_prefix):
+ # Determine the PID of ns1.
+ with open(pathlib.Path("ns1", "named.pid"), encoding="utf-8") as pidfile:
+ pid = int(pidfile.read())
+
+ # Ensure ns1 is alive before starting the loop below to avoid reporting
+ # false positives.
+ if not is_pid_alive(pid):
+ pytest.skip(f"ns1 (PID: {pid}) is not running")
+
+ # Run sslyze on ns1 in a loop with a limit of 30 iterations. Interrupt the
+ # test as soon as ns1 is determined to not be running any more. Log sslyze
+ # output.
+ sslyze_args = [executable, f"10.53.0.1:{port}"]
+ for i in range(0, 30):
+ log_file = f"{log_file_prefix}.ns1.{port}.{i + 1}"
+ with open(log_file, "wb") as sslyze_log:
+ # Run sslyze, logging stdout+stderr. Ignore the exit code since
+ # sslyze is only used for triggering crashes here rather than
+ # actual TLS analysis.
+ subprocess.run(
+ sslyze_args,
+ stdout=sslyze_log,
+ stderr=subprocess.STDOUT,
+ timeout=30,
+ check=False,
+ )
+ # Ensure ns1 is still alive after each sslyze run.
+ assert is_pid_alive(pid), f"ns1 (PID: {pid}) exited prematurely"
+
+
+def test_sslyze_doh(sslyze_executable, named_httpsport):
+ run_sslyze_in_a_loop(sslyze_executable, named_httpsport, "sslyze.log.doh")
+
+
+def test_sslyze_dot(sslyze_executable, named_tlsport):
+ run_sslyze_in_a_loop(sslyze_executable, named_tlsport, "sslyze.log.dot")
diff --git a/bin/tests/system/dsdigest/clean.sh b/bin/tests/system/dsdigest/clean.sh
new file mode 100644
index 0000000..172cf1e
--- /dev/null
+++ b/bin/tests/system/dsdigest/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f supported
+rm -f */K* */dsset-* */*.signed */trusted.conf
+rm -f ns1/root.db
+rm -f ns1/signer.err
+rm -f ns2/good.db ns2/bad.db
+rm -f dig.out*
+rm -f */named.conf
+rm -f */named.run
+rm -f */named.memstats
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/dsdigest/ns1/named.conf.in b/bin/tests/system/dsdigest/ns1/named.conf.in
new file mode 100644
index 0000000..da27c58
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns1/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+controls { /* empty */ };
+
+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;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dsdigest/ns1/root.db.in b/bin/tests/system/dsdigest/ns1/root.db.in
new file mode 100644
index 0000000..30c61e9
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns1/root.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA marka.isc.org. a.root.servers.nil. (
+ 2012062000 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+good. NS ns2.good.
+ns2.good. A 10.53.0.2
+bad. NS ns2.bad.
+ns2.bad. A 10.53.0.2
diff --git a/bin/tests/system/dsdigest/ns1/sign.sh b/bin/tests/system/dsdigest/ns1/sign.sh
new file mode 100644
index 0000000..d7efd9a
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns1/sign.sh
@@ -0,0 +1,36 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+(cd ../ns2 && $SHELL sign.sh)
+
+cp ../ns2/dsset-good. .
+cp ../ns2/dsset-bad. .
+
+key1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+key2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a static key.
+keyfile_to_static_ds $key2 > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+cp trusted.conf ../ns3/trusted.conf
+cp trusted.conf ../ns4/trusted.conf
diff --git a/bin/tests/system/dsdigest/ns2/bad.db.in b/bin/tests/system/dsdigest/ns2/bad.db.in
new file mode 100644
index 0000000..c5e8c83
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns2/bad.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+
+a A 10.0.0.1
diff --git a/bin/tests/system/dsdigest/ns2/good.db.in b/bin/tests/system/dsdigest/ns2/good.db.in
new file mode 100644
index 0000000..c5e8c83
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns2/good.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+
+a A 10.0.0.1
diff --git a/bin/tests/system/dsdigest/ns2/named.conf.in b/bin/tests/system/dsdigest/ns2/named.conf.in
new file mode 100644
index 0000000..d3fd750
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns2/named.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "good" {
+ type primary;
+ file "good.db.signed";
+};
+
+zone "bad" {
+ type primary;
+ file "bad.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dsdigest/ns2/sign.sh b/bin/tests/system/dsdigest/ns2/sign.sh
new file mode 100644
index 0000000..5bb4fce
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns2/sign.sh
@@ -0,0 +1,43 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone1=good
+infile1=good.db.in
+zonefile1=good.db
+zone2=bad
+infile2=bad.db.in
+zonefile2=bad.db
+
+keyname11=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone1)
+keyname12=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone1)
+keyname21=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone2)
+keyname22=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone2)
+
+cat $infile1 $keyname11.key $keyname12.key >$zonefile1
+cat $infile2 $keyname21.key $keyname22.key >$zonefile2
+
+$SIGNER -P -g -o $zone1 $zonefile1 > /dev/null
+$SIGNER -P -g -o $zone2 $zonefile2 > /dev/null
+
+DSFILENAME1=dsset-${zone1}.
+DSFILENAME2=dsset-${zone2}.
+$DSFROMKEY -a SHA-256 $keyname12 > $DSFILENAME1
+$DSFROMKEY -a SHA-256 $keyname22 > $DSFILENAME2
+
+algo=SHA-384
+
+$DSFROMKEY -a $algo $keyname12 >> $DSFILENAME1
+$DSFROMKEY -a $algo $keyname22 > $DSFILENAME2
+
diff --git a/bin/tests/system/dsdigest/ns3/named.conf.in b/bin/tests/system/dsdigest/ns3/named.conf.in
new file mode 100644
index 0000000..a2b105c
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns3/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+controls { /* empty */ };
+
+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;
+ dnssec-validation yes;
+ dnssec-must-be-secure . yes;
+ /* only SHA-256 is enabled */
+ disable-ds-digests . { SHA-1; SHA-384; 5; 6; 7; 8; 9; };
+
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dsdigest/ns4/named.conf.in b/bin/tests/system/dsdigest/ns4/named.conf.in
new file mode 100644
index 0000000..e43763b
--- /dev/null
+++ b/bin/tests/system/dsdigest/ns4/named.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+controls { /* empty */ };
+
+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;
+ dnssec-validation yes;
+ /* only SHA-256 is enabled */
+ disable-ds-digests . { SHA-1; SHA-384; 5; 6; 7; 8; 9; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dsdigest/setup.sh b/bin/tests/system/dsdigest/setup.sh
new file mode 100644
index 0000000..44bcc9d
--- /dev/null
+++ b/bin/tests/system/dsdigest/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
+
+cd ns1 && $SHELL sign.sh
diff --git a/bin/tests/system/dsdigest/tests.sh b/bin/tests/system/dsdigest/tests.sh
new file mode 100644
index 0000000..3650f4a
--- /dev/null
+++ b/bin/tests/system/dsdigest/tests.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+
+# Check the good. domain
+
+echo_i "checking that validation with enabled digest types works"
+ret=0
+$DIG $DIGOPTS a.good. @10.53.0.3 a > dig.out.good || ret=1
+grep "status: NOERROR" dig.out.good > /dev/null || ret=1
+grep "flags:[^;]* ad[ ;]" dig.out.good > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check the bad. domain
+
+echo_i "checking that validation with no supported digest types and must-be-secure results in SERVFAIL"
+ret=0
+$DIG $DIGOPTS a.bad. @10.53.0.3 a > dig.out.bad || ret=1
+grep "SERVFAIL" dig.out.bad > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that validation with no supported digest algorithms results in insecure"
+ret=0
+$DIG $DIGOPTS bad. @10.53.0.4 ds > dig.out.ds || ret=1
+grep "NOERROR" dig.out.ds > /dev/null || ret=1
+grep "flags:[^;]* ad[ ;]" dig.out.ds > /dev/null || ret=1
+$DIG $DIGOPTS a.bad. @10.53.0.4 a > dig.out.insecure || ret=1
+grep "NOERROR" dig.out.insecure > /dev/null || ret=1
+grep "flags:[^;]* ad[ ;]" dig.out.insecure > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+echo_i "exit status: $status"
+
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dsdigest/tests_sh_dsdigest.py b/bin/tests/system/dsdigest/tests_sh_dsdigest.py
new file mode 100644
index 0000000..348d704
--- /dev/null
+++ b/bin/tests/system/dsdigest/tests_sh_dsdigest.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_dsdigest(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/dupsigs/check_journal.pl b/bin/tests/system/dupsigs/check_journal.pl
new file mode 100644
index 0000000..0747432
--- /dev/null
+++ b/bin/tests/system/dupsigs/check_journal.pl
@@ -0,0 +1,206 @@
+#!/usr/bin/env perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+use warnings;
+
+sub process_changeset;
+
+my @changeset;
+
+while( my $line = <> ) {
+ chomp $line;
+
+ if( $line =~ /^(?<op>add|del) (?<label>\S+)\s+(?<ttl>\d+)\s+IN\s+(?<rrtype>\S+)\s+(?<rdata>.*)/ ) {
+ my $change = {
+ op => $+{op},
+ label => $+{label},
+ ttl => $+{ttl},
+ rrtype => $+{rrtype},
+ rdata => $+{rdata},
+ };
+
+ if( $change->{op} eq 'del' and $change->{rrtype} eq 'SOA' ) {
+ if( @changeset ) {
+ process_changeset( @changeset );
+ @changeset = ();
+ }
+ }
+
+ push @changeset, $change;
+ }
+ else {
+ die "error parsing journal data";
+ }
+}
+
+if( @changeset ) {
+ process_changeset( @changeset );
+}
+
+{
+ my %rrsig_db;
+ my %keys;
+ my $apex;
+
+ sub process_changeset {
+ my @changeset = @_;
+
+ if( not $apex ) {
+ # the first record of the first changeset is guaranteed to be the apex
+ $apex = $changeset[0]{label};
+ }
+
+ my $newserial;
+ my %touched_rrsigs;
+ my %touched_keys;
+
+ foreach my $change( @changeset ) {
+ if( $change->{rrtype} eq 'SOA' ) {
+ if( $change->{op} eq 'add' ) {
+ if( $change->{rdata} !~ /^\S+ \S+ (?<serial>\d+)/ ) {
+ die "unable to parse SOA";
+ }
+
+ $newserial = $+{serial};
+ }
+ }
+ elsif( $change->{rrtype} eq 'NSEC' ) {
+ ; # do nothing
+ }
+ elsif( $change->{rrtype} eq 'DNSKEY' ) {
+ ; # ignore for now
+ }
+ elsif( $change->{rrtype} eq 'TYPE65534' and $change->{label} eq $apex ) {
+ # key status
+ if( $change->{rdata} !~ /^\\# (?<datasize>\d+) (?<data>[0-9A-F]+)$/ ) {
+ die "unable to parse key status record";
+ }
+
+ my $datasize = $+{datasize};
+ my $data = $+{data};
+
+ if( $datasize == 5 ) {
+ my( $alg, $id, $flag_del, $flag_done ) = unpack 'CnCC', pack( 'H10', $data );
+
+ if( $change->{op} eq 'add' ) {
+ if( not exists $keys{$id} ) {
+ $touched_keys{$id} //= 1;
+
+ $keys{$id} = {
+ $data => 1,
+ rrs => 1,
+ done_signing => $flag_done,
+ deleting => $flag_del,
+ };
+ }
+ else {
+ if( not exists $keys{$id}{$data} ) {
+ my $keydata = $keys{$id};
+ $touched_keys{$id} = { %$keydata };
+
+ $keydata->{rrs}++;
+ $keydata->{$data} = 1;
+ $keydata->{done_signing} += $flag_done;
+ $keydata->{deleting} += $flag_del;
+ }
+ }
+ }
+ else {
+ # this logic relies upon the convention that there won't
+ # ever be multiple records with the same flag set
+ if( exists $keys{$id} ) {
+ my $keydata = $keys{$id};
+
+ if( exists $keydata->{$data} ) {
+ $touched_keys{$id} = { %$keydata };
+
+ $keydata->{rrs}--;
+ delete $keydata->{$data};
+ $keydata->{done_signing} -= $flag_done;
+ $keydata->{deleting} -= $flag_del;
+
+ if( $keydata->{rrs} == 0 ) {
+ delete $keys{$id};
+ }
+ }
+ }
+ }
+ }
+ else {
+ die "unexpected key status record content";
+ }
+ }
+ elsif( $change->{rrtype} eq 'RRSIG' ) {
+ if( $change->{rdata} !~ /^(?<covers>\S+) \d+ \d+ \d+ (?<validity_end>\d+) (?<validity_start>\d+) (?<signing_key>\d+)/ ) {
+ die "unable to parse RRSIG rdata";
+ }
+
+ $change->{covers} = $+{covers};
+ $change->{validity_end} = $+{validity_end};
+ $change->{validity_start} = $+{validity_start};
+ $change->{signing_key} = $+{signing_key};
+
+ my $db_key = $change->{label} . ':' . $change->{covers};
+
+ $rrsig_db{$db_key} //= {};
+ $touched_rrsigs{$db_key} = 1;
+
+ if( $change->{op} eq 'add' ) {
+ $rrsig_db{$db_key}{ $change->{signing_key} } = 1;
+ }
+ else {
+ # del
+ delete $rrsig_db{$db_key}{ $change->{signing_key} };
+ }
+ }
+ }
+
+ foreach my $key_id( sort keys %touched_keys ) {
+ my $old_data;
+ my $new_data;
+
+ if( ref $touched_keys{$key_id} ) {
+ $old_data = $touched_keys{$key_id};
+ }
+
+ if( exists $keys{$key_id} ) {
+ $new_data = $keys{$key_id};
+ }
+
+ if( $old_data ) {
+ if( $new_data ) {
+ print "at serial $newserial key $key_id status changed from ($old_data->{deleting},$old_data->{done_signing}) to ($new_data->{deleting},$new_data->{done_signing})\n";
+ }
+ else {
+ print "at serial $newserial key $key_id status removed from zone\n";
+ }
+ }
+ else {
+ print "at serial $newserial key $key_id status added with flags ($new_data->{deleting},$new_data->{done_signing})\n";
+ }
+ }
+
+ foreach my $rrsig_id( sort keys %touched_rrsigs ) {
+ my $n_signing_keys = keys %{ $rrsig_db{$rrsig_id} };
+
+ if( $n_signing_keys == 0 ) {
+ print "at serial $newserial $rrsig_id went unsigned\n";
+ }
+ elsif( $n_signing_keys > 1 ) {
+ my @signing_keys = sort { $a <=> $b } keys %{ $rrsig_db{$rrsig_id} };
+ print "at serial $newserial $rrsig_id was signed too many times, keys (@signing_keys)\n";
+ }
+ }
+ }
+}
diff --git a/bin/tests/system/dupsigs/clean.sh b/bin/tests/system/dupsigs/clean.sh
new file mode 100644
index 0000000..2af75a0
--- /dev/null
+++ b/bin/tests/system/dupsigs/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out*
+rm -f ns1/named.conf
+rm -f ns1/named.lock
+rm -f ns1/named.memstats
+rm -f ns1/named.run
+rm -f ns1/signing.test.db
+rm -f ns1/signing.test.db.jbk
+rm -f ns1/signing.test.db.signed
+rm -f ns1/signing.test.db.signed.jnl
+rm -f ns1/keys/signing.test/K*
+rm -f ns1/managed-keys.bind*
diff --git a/bin/tests/system/dupsigs/ns1/named.args b/bin/tests/system/dupsigs/ns1/named.args
new file mode 100644
index 0000000..adf6968
--- /dev/null
+++ b/bin/tests/system/dupsigs/ns1/named.args
@@ -0,0 +1 @@
+-D dupsigs-ns1 -X named.lock -m record -c named.conf -d 99 -g -U 4 -T maxcachesize=2097152 -T sigvalinsecs
diff --git a/bin/tests/system/dupsigs/ns1/named.conf.in b/bin/tests/system/dupsigs/ns1/named.conf.in
new file mode 100644
index 0000000..d35eb79
--- /dev/null
+++ b/bin/tests/system/dupsigs/ns1/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ recursion no;
+ max-journal-size unlimited;
+ port @PORT@;
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ pid-file "named.pid";
+ dnssec-validation no;
+};
+
+zone "signing.test" {
+ type primary;
+ masterfile-format text;
+ allow-update { any; };
+ file "signing.test.db";
+ update-check-ksk yes;
+ key-directory "keys/signing.test";
+ inline-signing yes;
+ auto-dnssec maintain;
+ sig-validity-interval 20 5;
+};
diff --git a/bin/tests/system/dupsigs/ns1/reset_keys.sh b/bin/tests/system/dupsigs/ns1/reset_keys.sh
new file mode 100644
index 0000000..6f96c6a
--- /dev/null
+++ b/bin/tests/system/dupsigs/ns1/reset_keys.sh
@@ -0,0 +1,99 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=signing.test
+rm -rf keys/signing.test
+mkdir -p keys/signing.test
+
+timetodnssec() {
+ $PERL -e 'my ($S,$M,$H,$d,$m,$y,$x) = gmtime(@ARGV[0]);
+ printf("%04u%02u%02u%02u%02u%02u\n", $y+1900,$m+1,$d,$H,$M,$S);' ${1}
+}
+
+KEYDIR=keys/signing.test
+KSK=$($KEYGEN -a RSASHA256 -K $KEYDIR -q -f KSK $zone)
+
+ZSK0=$($KEYGEN -a RSASHA256 -K $KEYDIR -q $zone)
+ZSK1=$($KEYGEN -a RSASHA256 -K $KEYDIR -q $zone)
+ZSK2=$($KEYGEN -a RSASHA256 -K $KEYDIR -q $zone)
+ZSK3=$($KEYGEN -a RSASHA256 -K $KEYDIR -q $zone)
+ZSK4=$($KEYGEN -a RSASHA256 -K $KEYDIR -q $zone)
+ZSK5=$($KEYGEN -a RSASHA256 -K $KEYDIR -q $zone)
+ZSK6=$($KEYGEN -a RSASHA256 -K $KEYDIR -q $zone)
+ZSK7=$($KEYGEN -a RSASHA256 -K $KEYDIR -q $zone)
+ZSK8=$($KEYGEN -a RSASHA256 -K $KEYDIR -q $zone)
+ZSK9=$($KEYGEN -a RSASHA256 -K $KEYDIR -q $zone)
+
+# clear all times on all keys
+for FILEN in keys/signing.test/*.key
+do
+ $SETTIME -P none -A none -R none -I none -D none $FILEN
+done
+
+BASE=$(date +%s)
+BASET=$(timetodnssec $BASE)
+
+# reset the publish and activation time on the KSK
+$SETTIME -P $BASET -A $BASET $KEYDIR/$KSK
+
+# reset the publish and activation time on the first ZSK
+$SETTIME -P $BASET -A $BASET $KEYDIR/$ZSK0
+
+# schedule the first roll
+R1=$((BASE + 50))
+R1T=$(timetodnssec $R1)
+
+$SETTIME -I $R1T $KEYDIR/$ZSK0
+$SETTIME -P $BASET -A $R1T $KEYDIR/$ZSK1
+
+# schedule the second roll (which includes the delete of the first key)
+R2=$((R1 + 50))
+R2T=$(timetodnssec $R2)
+DT=$R2
+DTT=$(timetodnssec $DT)
+
+$SETTIME -D $DTT $KEYDIR/$ZSK0
+$SETTIME -I $R2T $KEYDIR/$ZSK1
+$SETTIME -P $R1T -A $R2T $KEYDIR/$ZSK2
+
+# schedule the third roll
+R3=$((R2 + 25))
+R3T=$(timetodnssec $R3)
+
+$SETTIME -D $R3T $KEYDIR/$ZSK1
+$SETTIME -I $R3T $KEYDIR/$ZSK2
+$SETTIME -P $R2T -A $R3T $KEYDIR/$ZSK3
+
+$SETTIME -P $R3T $KEYDIR/$ZSK4
+
+echo KSK=$KSK
+echo ZSK0=$ZSK0
+echo ZSK1=$ZSK1
+echo ZSK2=$ZSK2
+echo ZSK3=$ZSK3
+echo ZSK4=$ZSK4
+
+exit
+
+# schedule the fourth roll
+# this isn't long enough for the signing to complete and would result in
+# duplicate signatures, see
+# https://gitlab.isc.org/isc-projects/bind9/-/merge_requests/231#note_9597
+R4=$((R3 + 10))
+R4T=$(timetodnssec $R4)
+
+$SETTIME -D $R4T $KEYDIR/$ZSK2
+$SETTIME -I $R4T $KEYDIR/$ZSK3
+$SETTIME -P $R3T -A $R4T $KEYDIR/$ZSK4
diff --git a/bin/tests/system/dupsigs/ns1/signing.test.db.in b/bin/tests/system/dupsigs/ns1/signing.test.db.in
new file mode 100644
index 0000000..b522b6f
--- /dev/null
+++ b/bin/tests/system/dupsigs/ns1/signing.test.db.in
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA ns root.ns 1996072700 3600 1800 86400 60
+@ NS ns
+ns A 127.0.0.1
+ns AAAA ::1
+
+$GENERATE 0-499 a${0,4,d} AAAA ::$
diff --git a/bin/tests/system/dupsigs/setup.sh b/bin/tests/system/dupsigs/setup.sh
new file mode 100644
index 0000000..4ac8a8d
--- /dev/null
+++ b/bin/tests/system/dupsigs/setup.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 800 $RANDFILE
+
+copy_setports ns1/named.conf.in ns1/named.conf
+
+cp -f ns1/signing.test.db.in ns1/signing.test.db
+(cd ns1; $SHELL ./reset_keys.sh)
diff --git a/bin/tests/system/dupsigs/tests.sh b/bin/tests/system/dupsigs/tests.sh
new file mode 100644
index 0000000..4ab3a73
--- /dev/null
+++ b/bin/tests/system/dupsigs/tests.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+
+# Wait for the zone to be fully signed before beginning test
+#
+# We expect the zone to have the following:
+#
+# - 5 signatures for signing.test.
+# - 3 signatures for ns.signing.test.
+# - 2 x 500 signatures for a{0000-0499}.signing.test.
+#
+# for a total of 1008.
+fully_signed () {
+ $DIG axfr signing.test -p ${PORT} @10.53.0.1 > "dig.out.ns1.axfr"
+ awk 'BEGIN { lines = 0 }
+ $4 == "RRSIG" {lines++}
+ END { if (lines != 1008) exit(1) }' < "dig.out.ns1.axfr"
+}
+
+# Wait for the last NSEC record in the zone to be signed. This is a lightweight
+# alternative to avoid many AXFR requests while waiting for the zone to be
+# fully signed.
+_wait_for_last_nsec_signed() {
+ $DIG +dnssec a0499.signing.test -p ${PORT} @10.53.0.1 nsec > "dig.out.ns1.wait" || return 1
+ grep "signing.test\..*IN.*RRSIG.*signing.test" "dig.out.ns1.wait" > /dev/null || return 1
+ return 0
+}
+
+echo_i "wait for the zone to be fully signed"
+retry_quiet 60 _wait_for_last_nsec_signed
+retry_quiet 10 fully_signed || status=1
+if [ $status != 0 ]; then echo_i "failed"; fi
+
+start=$(date +%s)
+now=$start
+end=$((start + 140))
+
+while [ $now -lt $end ] && [ $status -eq 0 ]; do
+ et=$((now - start))
+ echo_i "............... $et ............"
+ $JOURNALPRINT ns1/signing.test.db.signed.jnl | $PERL check_journal.pl | cat_i
+ $DIG axfr signing.test -p ${PORT} @10.53.0.1 > dig.out.at$et
+ awk '$4 == "RRSIG" { print $11 }' dig.out.at$et | sort | uniq -c | cat_i
+ lines=$(awk '$4 == "RRSIG" { print}' dig.out.at$et | wc -l)
+ if [ ${et} -ne 0 -a ${lines} -ne 1008 ]
+ then
+ echo_i "failed"
+ status=$((status + 1))
+ fi
+ sleep 5
+ now=$(date +%s)
+done
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dupsigs/tests_sh_dupsigs.py b/bin/tests/system/dupsigs/tests_sh_dupsigs.py
new file mode 100644
index 0000000..1e065db
--- /dev/null
+++ b/bin/tests/system/dupsigs/tests_sh_dupsigs.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_dupsigs(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/dyndb/clean.sh b/bin/tests/system/dyndb/clean.sh
new file mode 100644
index 0000000..cb8ae94
--- /dev/null
+++ b/bin/tests/system/dyndb/clean.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after dyndb tests.
+#
+rm -f */named.conf
+rm -f */named.run
+rm -f ns1/named.memstats
+rm -f ns1/update.txt
+rm -f added.a.out.*
+rm -f added.ptr.out.*
+rm -f deleted.a.out.*
+rm -f deleted.ptr.out.*
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/dyndb/driver/AUTHORS b/bin/tests/system/dyndb/driver/AUTHORS
new file mode 100644
index 0000000..5b37853
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/AUTHORS
@@ -0,0 +1,33 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+Copyright (C) 2009-2015 Red Hat
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+This sample driver is based on bind-dyndb-ldap project and small portions
+of code from ISC BIND 9.10.
+
+Authors listed in alphabetical order:
+Adam Tkac <atkac@redhat.com>
+Jiri Kuncar <jkuncar@redhat.com>
+Martin Nagy <mnagy@redhat.com>
+Petr Spacek <pspacek@redhat.com>
diff --git a/bin/tests/system/dyndb/driver/Makefile.am b/bin/tests/system/dyndb/driver/Makefile.am
new file mode 100644
index 0000000..86dddb6
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/Makefile.am
@@ -0,0 +1,25 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+noinst_LTLIBRARIES = sample.la
+
+sample_la_SOURCES = \
+ db.c \
+ driver.c \
+ instance.c \
+ lock.c \
+ log.c \
+ syncptr.c \
+ zone.c \
+ db.h \
+ instance.h \
+ lock.h \
+ log.h \
+ syncptr.h \
+ util.h \
+ zone.h
+
+sample_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir)
diff --git a/bin/tests/system/dyndb/driver/Makefile.in b/bin/tests/system/dyndb/driver/Makefile.in
new file mode 100644
index 0000000..ccfad1d
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/Makefile.in
@@ -0,0 +1,811 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+subdir = bin/tests/system/dyndb/driver
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+sample_la_LIBADD =
+am_sample_la_OBJECTS = db.lo driver.lo instance.lo lock.lo log.lo \
+ syncptr.lo zone.lo
+sample_la_OBJECTS = $(am_sample_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+sample_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(sample_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/db.Plo ./$(DEPDIR)/driver.Plo \
+ ./$(DEPDIR)/instance.Plo ./$(DEPDIR)/lock.Plo \
+ ./$(DEPDIR)/log.Plo ./$(DEPDIR)/syncptr.Plo \
+ ./$(DEPDIR)/zone.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(sample_la_SOURCES)
+DIST_SOURCES = $(sample_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp AUTHORS README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS)
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD =
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+noinst_LTLIBRARIES = sample.la
+sample_la_SOURCES = \
+ db.c \
+ driver.c \
+ instance.c \
+ lock.c \
+ log.c \
+ syncptr.c \
+ zone.c \
+ db.h \
+ instance.h \
+ lock.h \
+ log.h \
+ syncptr.h \
+ util.h \
+ zone.h
+
+sample_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tests/system/dyndb/driver/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/tests/system/dyndb/driver/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+sample.la: $(sample_la_OBJECTS) $(sample_la_DEPENDENCIES) $(EXTRA_sample_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(sample_la_LINK) $(sample_la_OBJECTS) $(sample_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/driver.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instance.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncptr.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/db.Plo
+ -rm -f ./$(DEPDIR)/driver.Plo
+ -rm -f ./$(DEPDIR)/instance.Plo
+ -rm -f ./$(DEPDIR)/lock.Plo
+ -rm -f ./$(DEPDIR)/log.Plo
+ -rm -f ./$(DEPDIR)/syncptr.Plo
+ -rm -f ./$(DEPDIR)/zone.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/db.Plo
+ -rm -f ./$(DEPDIR)/driver.Plo
+ -rm -f ./$(DEPDIR)/instance.Plo
+ -rm -f ./$(DEPDIR)/lock.Plo
+ -rm -f ./$(DEPDIR)/log.Plo
+ -rm -f ./$(DEPDIR)/syncptr.Plo
+ -rm -f ./$(DEPDIR)/zone.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am:
+
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir \
+ doc-am doc-local dvi dvi-am html html-am info info-am install \
+ install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \
+ uninstall-am unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/tests/system/dyndb/driver/README b/bin/tests/system/dyndb/driver/README
new file mode 100644
index 0000000..db73396
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/README
@@ -0,0 +1,92 @@
+<!--
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0 and 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 https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+Copyright (C) Red Hat
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+-->
+
+To use the Dynamic DB sample driver, run named and check the log.
+
+ $ cd testing
+ $ named -gc named.conf
+
+You should be able to see something like:
+
+zone test/IN: loaded serial 0
+zone arpa/IN: loaded serial 0
+
+This means that the sample driver created empty zones "test." and
+"arpa." as defined by "arg" parameters in named.conf.
+
+$ dig @localhost test.
+
+should work as usual and you should be able to see the dummy zone with
+NS record pointing to the zone apex and A record with 127.0.0.1:
+
+;; ANSWER SECTION:
+test. 86400 IN A 127.0.0.1
+test. 86400 IN NS test.
+test. 86400 IN SOA test. test. 0 28800 7200 604800 86400
+
+This driver creates two empty zones and allows query/transfer/update to
+all IP addresses for demonstration purposes.
+
+The driver wraps the RBT database implementation used natively by BIND,
+and modifies the addrdataset() and substractrdataset() functions to do
+additional work during dynamic updates.
+
+A dynamic update modifies the target zone as usual. After that, the
+driver detects whether the modified RR was of type A or AAAA, and if so,
+attempts to appropriately generate or delete a matching PTR record in
+one of the two zones managed by the driver.
+
+E.g.:
+
+$ nsupdate
+> update add a.test. 300 IN A 192.0.2.1
+> send
+
+will add the A record
+a.test. 300 IN A 192.0.2.1
+
+and also automatically generate the PTR record
+1.2.0.192.in-addr.arpa. 300 IN PTR a.test.
+
+AXFR and RR deletion via dynamic updates should work as usual. Deletion
+of a type A or AAAA record should delete the corresponding PTR record
+too.
+
+The zone is stored only in memory, and all changes will be lost on
+reload/reconfig.
+
+Hints for code readers:
+- Driver initialization starts in driver.c: dyndb_init() function.
+- New database implementation is registered by calling dns_db_register()
+ and passing a function pointer to it. This sample uses the function
+ create_db() to initialize the database.
+- Zones are created later in instance.c: load_sample_instance_zones().
+- Database entry points are in structure db.c: dns_dbmethods_t
+ sampledb_methods
+- sampledb_methods points to an implementation of the database interface.
+ See the db.c: addrdataset() implementation and look at how the RBT
+ database instance is wrapped into an additional layer of logic.
diff --git a/bin/tests/system/dyndb/driver/db.c b/bin/tests/system/dyndb/driver/db.c
new file mode 100644
index 0000000..334fd54
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/db.c
@@ -0,0 +1,776 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) 2009-2015 Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Database API implementation. The interface is defined in lib/dns/db.h.
+ *
+ * dns_db_*() calls on database instances backed by this driver use
+ * struct sampledb_methods to find appropriate function implementation.
+ *
+ * This example re-uses RBT DB implementation from original BIND and blindly
+ * proxies most of dns_db_*() calls to this underlying RBT DB.
+ * See struct sampledb below.
+ */
+
+#include "db.h"
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/diff.h>
+#include <dns/enumclass.h>
+#include <dns/rbt.h>
+#include <dns/rdatalist.h>
+#include <dns/rdatastruct.h>
+#include <dns/soa.h>
+#include <dns/types.h>
+
+#include "instance.h"
+#include "syncptr.h"
+#include "util.h"
+
+#define SAMPLEDB_MAGIC ISC_MAGIC('S', 'M', 'D', 'B')
+#define VALID_SAMPLEDB(sampledb) \
+ ((sampledb) != NULL && (sampledb)->common.impmagic == SAMPLEDB_MAGIC)
+
+struct sampledb {
+ dns_db_t common;
+ isc_refcount_t refs;
+ sample_instance_t *inst;
+
+ /*
+ * Internal RBT database implementation provided by BIND.
+ * Most dns_db_* calls (find(), createiterator(), etc.)
+ * are blindly forwarded to this RBT DB.
+ */
+ dns_db_t *rbtdb;
+};
+
+typedef struct sampledb sampledb_t;
+
+/*
+ * Get full DNS name from the node.
+ *
+ * @warning
+ * The code silently expects that "node" came from RBTDB and thus
+ * assumption dns_dbnode_t (from RBTDB) == dns_rbtnode_t is correct.
+ *
+ * This should work as long as we use only RBTDB and nothing else.
+ */
+static isc_result_t
+sample_name_fromnode(dns_dbnode_t *node, dns_name_t *name) {
+ dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
+ return (dns_rbt_fullnamefromnode(rbtnode, name));
+}
+
+static void
+attach(dns_db_t *source, dns_db_t **targetp) {
+ sampledb_t *sampledb = (sampledb_t *)source;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ isc_refcount_increment(&sampledb->refs);
+ *targetp = source;
+}
+
+static void
+free_sampledb(sampledb_t *sampledb) {
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_detach(&sampledb->rbtdb);
+ dns_name_free(&sampledb->common.origin, sampledb->common.mctx);
+ isc_mem_putanddetach(&sampledb->common.mctx, sampledb,
+ sizeof(*sampledb));
+}
+
+static void
+detach(dns_db_t **dbp) {
+ REQUIRE(dbp != NULL && VALID_SAMPLEDB((sampledb_t *)(*dbp)));
+ sampledb_t *sampledb = (sampledb_t *)(*dbp);
+ *dbp = NULL;
+
+ if (isc_refcount_decrement(&sampledb->refs) == 1) {
+ free_sampledb(sampledb);
+ }
+}
+
+/*
+ * This method should never be called, because DB is "persistent".
+ * See ispersistent() function. It means that database do not need to be
+ * loaded in the usual sense.
+ */
+static isc_result_t
+beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
+ UNUSED(db);
+ UNUSED(callbacks);
+
+ FATAL_ERROR("current implementation should never call beginload()");
+
+ /* Not reached */
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This method should never be called, because DB is "persistent".
+ * See ispersistent() function. It means that database do not need to be
+ * loaded in the usual sense.
+ */
+static isc_result_t
+endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
+ UNUSED(db);
+ UNUSED(callbacks);
+
+ FATAL_ERROR("current implementation should never call endload()");
+
+ /* Not reached */
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
+ dns_masterformat_t masterformat) {
+ UNUSED(db);
+ UNUSED(version);
+ UNUSED(filename);
+ UNUSED(masterformat);
+
+ FATAL_ERROR("current implementation should never call dump()");
+
+ /* Not reached */
+ return (ISC_R_SUCCESS);
+}
+
+static void
+currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_currentversion(sampledb->rbtdb, versionp);
+}
+
+static isc_result_t
+newversion(dns_db_t *db, dns_dbversion_t **versionp) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_newversion(sampledb->rbtdb, versionp));
+}
+
+static void
+attachversion(dns_db_t *db, dns_dbversion_t *source,
+ dns_dbversion_t **targetp) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_attachversion(sampledb->rbtdb, source, targetp);
+}
+
+static void
+closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_closeversion(sampledb->rbtdb, versionp, commit);
+}
+
+static isc_result_t
+findnode(dns_db_t *db, const dns_name_t *name, bool create,
+ dns_dbnode_t **nodep) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_findnode(sampledb->rbtdb, name, create, nodep));
+}
+
+static isc_result_t
+find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
+ dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
+ dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_find(sampledb->rbtdb, name, version, type, options, now,
+ nodep, foundname, rdataset, sigrdataset));
+}
+
+static isc_result_t
+findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
+ isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
+ dns_name_t *dcname, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_findzonecut(sampledb->rbtdb, name, options, now, nodep,
+ foundname, dcname, rdataset, sigrdataset));
+}
+
+static void
+attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_attachnode(sampledb->rbtdb, source, targetp);
+}
+
+static void
+detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_detachnode(sampledb->rbtdb, targetp);
+}
+
+static isc_result_t
+expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_expirenode(sampledb->rbtdb, node, now));
+}
+
+static void
+printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_printnode(sampledb->rbtdb, node, out);
+}
+
+static isc_result_t
+createiterator(dns_db_t *db, unsigned int options,
+ dns_dbiterator_t **iteratorp) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_createiterator(sampledb->rbtdb, options, iteratorp));
+}
+
+static isc_result_t
+findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_findrdataset(sampledb->rbtdb, node, version, type,
+ covers, now, rdataset, sigrdataset));
+}
+
+static isc_result_t
+allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ unsigned int options, isc_stdtime_t now,
+ dns_rdatasetiter_t **iteratorp) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_allrdatasets(sampledb->rbtdb, node, version, options,
+ now, iteratorp));
+}
+
+static isc_result_t
+addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
+ dns_rdataset_t *addedrdataset) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+ isc_result_t result;
+ dns_fixedname_t name;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_fixedname_init(&name);
+ CHECK(dns_db_addrdataset(sampledb->rbtdb, node, version, now, rdataset,
+ options, addedrdataset));
+ if (rdataset->type == dns_rdatatype_a ||
+ rdataset->type == dns_rdatatype_aaaa)
+ {
+ CHECK(sample_name_fromnode(node, dns_fixedname_name(&name)));
+ CHECK(syncptrs(sampledb->inst, dns_fixedname_name(&name),
+ rdataset, DNS_DIFFOP_ADD));
+ }
+
+cleanup:
+ return (result);
+}
+
+static isc_result_t
+subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdataset_t *rdataset, unsigned int options,
+ dns_rdataset_t *newrdataset) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+ isc_result_t result;
+ dns_fixedname_t name;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_fixedname_init(&name);
+ result = dns_db_subtractrdataset(sampledb->rbtdb, node, version,
+ rdataset, options, newrdataset);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET) {
+ goto cleanup;
+ }
+
+ if (rdataset->type == dns_rdatatype_a ||
+ rdataset->type == dns_rdatatype_aaaa)
+ {
+ CHECK(sample_name_fromnode(node, dns_fixedname_name(&name)));
+ CHECK(syncptrs(sampledb->inst, dns_fixedname_name(&name),
+ rdataset, DNS_DIFFOP_DEL));
+ }
+
+cleanup:
+ return (result);
+}
+
+/*
+ * deleterdataset() function is not used during DNS update processing so syncptr
+ * implementation is left as an exercise to the reader.
+ */
+static isc_result_t
+deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdatatype_t type, dns_rdatatype_t covers) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_deleterdataset(sampledb->rbtdb, node, version, type,
+ covers));
+}
+
+static bool
+issecure(dns_db_t *db) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_issecure(sampledb->rbtdb));
+}
+
+static unsigned int
+nodecount(dns_db_t *db, dns_dbtree_t tree) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_nodecount(sampledb->rbtdb, tree));
+}
+
+/*
+ * The database does not need to be loaded from disk or written to disk.
+ * Always return true.
+ */
+static bool
+ispersistent(dns_db_t *db) {
+ UNUSED(db);
+
+ return (true);
+}
+
+static void
+overmem(dns_db_t *db, bool over) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_overmem(sampledb->rbtdb, over);
+}
+
+static void
+settask(dns_db_t *db, isc_task_t *task) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_settask(sampledb->rbtdb, task);
+}
+
+static isc_result_t
+getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_getoriginnode(sampledb->rbtdb, nodep));
+}
+
+static void
+transfernode(dns_db_t *db, dns_dbnode_t **sourcep, dns_dbnode_t **targetp) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_transfernode(sampledb->rbtdb, sourcep, targetp);
+}
+
+static isc_result_t
+getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash,
+ uint8_t *flags, uint16_t *iterations, unsigned char *salt,
+ size_t *salt_length) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_getnsec3parameters(sampledb->rbtdb, version, hash, flags,
+ iterations, salt, salt_length));
+}
+
+static isc_result_t
+findnsec3node(dns_db_t *db, const dns_name_t *name, bool create,
+ dns_dbnode_t **nodep) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_findnsec3node(sampledb->rbtdb, name, create, nodep));
+}
+
+static isc_result_t
+setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_setsigningtime(sampledb->rbtdb, rdataset, resign));
+}
+
+static isc_result_t
+getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_getsigningtime(sampledb->rbtdb, rdataset, name));
+}
+
+static void
+resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ dns_db_resigned(sampledb->rbtdb, rdataset, version);
+}
+
+static bool
+isdnssec(dns_db_t *db) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_isdnssec(sampledb->rbtdb));
+}
+
+static dns_stats_t *
+getrrsetstats(dns_db_t *db) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_getrrsetstats(sampledb->rbtdb));
+}
+
+static isc_result_t
+findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
+ dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
+ dns_dbnode_t **nodep) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_findnodeext(sampledb->rbtdb, name, create, methods,
+ clientinfo, nodep));
+}
+
+static isc_result_t
+findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
+ dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
+ dns_dbnode_t **nodep, dns_name_t *foundname,
+ dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_findext(sampledb->rbtdb, name, version, type, options,
+ now, nodep, foundname, methods, clientinfo,
+ rdataset, sigrdataset));
+}
+
+static isc_result_t
+setcachestats(dns_db_t *db, isc_stats_t *stats) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_setcachestats(sampledb->rbtdb, stats));
+}
+
+static size_t
+hashsize(dns_db_t *db) {
+ sampledb_t *sampledb = (sampledb_t *)db;
+
+ REQUIRE(VALID_SAMPLEDB(sampledb));
+
+ return (dns_db_hashsize(sampledb->rbtdb));
+}
+
+/*
+ * DB interface definition. Database driver uses this structure to
+ * determine which implementation of dns_db_*() function to call.
+ */
+static dns_dbmethods_t sampledb_methods = {
+ attach, detach, beginload,
+ endload, dump, currentversion,
+ newversion, attachversion, closeversion,
+ findnode, find, findzonecut,
+ attachnode, detachnode, expirenode,
+ printnode, createiterator, findrdataset,
+ allrdatasets, addrdataset, subtractrdataset,
+ deleterdataset, issecure, nodecount,
+ ispersistent, overmem, settask,
+ getoriginnode, transfernode, getnsec3parameters,
+ findnsec3node, setsigningtime, getsigningtime,
+ resigned, isdnssec, getrrsetstats,
+ NULL, /* rpz_attach */
+ NULL, /* rpz_ready */
+ findnodeext, findext, setcachestats,
+ hashsize, NULL, /* nodefullname */
+ NULL, /* getsize */
+ NULL, /* setservestalettl */
+ NULL, /* getservestalettl */
+ NULL, /* setservestalerefresh */
+ NULL, /* getservestalerefresh */
+ NULL, /* setgluecachestats */
+};
+
+/* Auxiliary driver functions. */
+
+/*
+ * Auxiliary functions add_*() create minimal database which can be loaded.
+ * This is necessary because this driver create empty 'fake' zone which
+ * is not loaded from disk so there is no way for user to supply SOA, NS and A
+ * records.
+ *
+ * Following functions were copied from BIND 9.10.2rc1 named/server.c,
+ * credit goes to ISC.
+ */
+static isc_result_t
+add_soa(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name,
+ const dns_name_t *origin, const dns_name_t *contact) {
+ dns_dbnode_t *node = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+ unsigned char buf[DNS_SOA_BUFFERSIZE];
+
+ dns_rdataset_init(&rdataset);
+ dns_rdatalist_init(&rdatalist);
+ CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), 0, 28800,
+ 7200, 604800, 86400, buf, &rdata));
+ rdatalist.type = rdata.type;
+ rdatalist.covers = 0;
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.ttl = 86400;
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+ CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
+ CHECK(dns_db_findnode(db, name, true, &node));
+ CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL));
+cleanup:
+ if (node != NULL) {
+ dns_db_detachnode(db, &node);
+ }
+ return (result);
+}
+
+static isc_result_t
+add_ns(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name,
+ const dns_name_t *nsname) {
+ dns_dbnode_t *node = NULL;
+ dns_rdata_ns_t ns;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+ isc_buffer_t b;
+ unsigned char buf[DNS_NAME_MAXWIRE];
+
+ isc_buffer_init(&b, buf, sizeof(buf));
+
+ dns_rdataset_init(&rdataset);
+ dns_rdatalist_init(&rdatalist);
+ ns.common.rdtype = dns_rdatatype_ns;
+ ns.common.rdclass = dns_db_class(db);
+ ns.mctx = NULL;
+ dns_name_init(&ns.name, NULL);
+ dns_name_clone(nsname, &ns.name);
+ CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns,
+ &ns, &b));
+ rdatalist.type = rdata.type;
+ rdatalist.covers = 0;
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.ttl = 86400;
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+ CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
+ CHECK(dns_db_findnode(db, name, true, &node));
+ CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL));
+cleanup:
+ if (node != NULL) {
+ dns_db_detachnode(db, &node);
+ }
+ return (result);
+}
+
+static isc_result_t
+add_a(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name,
+ struct in_addr addr) {
+ dns_dbnode_t *node = NULL;
+ dns_rdata_in_a_t a;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+ isc_buffer_t b;
+ unsigned char buf[DNS_NAME_MAXWIRE];
+
+ isc_buffer_init(&b, buf, sizeof(buf));
+
+ dns_rdataset_init(&rdataset);
+ dns_rdatalist_init(&rdatalist);
+ a.common.rdtype = dns_rdatatype_a;
+ a.common.rdclass = dns_db_class(db);
+ a.in_addr = addr;
+ CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_a,
+ &a, &b));
+ rdatalist.type = rdata.type;
+ rdatalist.covers = 0;
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.ttl = 86400;
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+ CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
+ CHECK(dns_db_findnode(db, name, true, &node));
+ CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL));
+cleanup:
+ if (node != NULL) {
+ dns_db_detachnode(db, &node);
+ }
+ return (result);
+}
+
+/*
+ * Driver-specific implementation of dns_db_create().
+ *
+ * @param[in] argv Database-specific parameters from dns_db_create().
+ * @param[in] driverarg Driver-specific parameter from dns_db_register().
+ */
+isc_result_t
+create_db(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
+ dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
+ void *driverarg, dns_db_t **dbp) {
+ sampledb_t *sampledb = NULL;
+ isc_result_t result;
+ dns_dbversion_t *version = NULL;
+ struct in_addr a_addr;
+
+ REQUIRE(type == dns_dbtype_zone);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(argc == 0);
+ REQUIRE(argv != NULL);
+ REQUIRE(driverarg != NULL); /* pointer to driver instance */
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ UNUSED(driverarg); /* no driver-specific configuration */
+
+ a_addr.s_addr = 0x0100007fU;
+
+ CHECKED_MEM_GET_PTR(mctx, sampledb);
+ ZERO_PTR(sampledb);
+
+ isc_mem_attach(mctx, &sampledb->common.mctx);
+ dns_name_init(&sampledb->common.origin, NULL);
+
+ sampledb->common.magic = DNS_DB_MAGIC;
+ sampledb->common.impmagic = SAMPLEDB_MAGIC;
+
+ sampledb->common.methods = &sampledb_methods;
+ sampledb->common.attributes = 0;
+ sampledb->common.rdclass = rdclass;
+
+ CHECK(dns_name_dupwithoffsets(origin, mctx, &sampledb->common.origin));
+
+ isc_refcount_init(&sampledb->refs, 1);
+
+ /* Translate instance name to instance pointer. */
+ sampledb->inst = driverarg;
+
+ /* Create internal instance of RBT DB implementation from BIND. */
+ CHECK(dns_db_create(mctx, "rbt", origin, dns_dbtype_zone,
+ dns_rdataclass_in, 0, NULL, &sampledb->rbtdb));
+
+ /* Create fake SOA, NS, and A records to make database loadable. */
+ CHECK(dns_db_newversion(sampledb->rbtdb, &version));
+ CHECK(add_soa(sampledb->rbtdb, version, origin, origin, origin));
+ CHECK(add_ns(sampledb->rbtdb, version, origin, origin));
+ CHECK(add_a(sampledb->rbtdb, version, origin, a_addr));
+ dns_db_closeversion(sampledb->rbtdb, &version, true);
+
+ *dbp = (dns_db_t *)sampledb;
+
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (sampledb != NULL) {
+ if (dns_name_dynamic(&sampledb->common.origin)) {
+ dns_name_free(&sampledb->common.origin, mctx);
+ }
+
+ isc_mem_putanddetach(&sampledb->common.mctx, sampledb,
+ sizeof(*sampledb));
+ }
+
+ return (result);
+}
diff --git a/bin/tests/system/dyndb/driver/db.h b/bin/tests/system/dyndb/driver/db.h
new file mode 100644
index 0000000..c520c8b
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/db.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) 2009-2015 Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * Database API implementation.
+ */
+
+#pragma once
+
+#include <isc/mem.h>
+#include <isc/result.h>
+
+#include <dns/db.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+
+isc_result_t
+create_db(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
+ dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
+ void *driverarg, dns_db_t **dbp);
diff --git a/bin/tests/system/dyndb/driver/driver.c b/bin/tests/system/dyndb/driver/driver.c
new file mode 100644
index 0000000..7e8a249
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/driver.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver API implementation and main entry point for BIND.
+ *
+ * BIND calls dyndb_version() before loading, dyndb_init() during startup
+ * and dyndb_destroy() during shutdown.
+ *
+ * It is completely up to implementation what to do.
+ *
+ * dyndb <name> <driver> {} sections in named.conf are independent so
+ * driver init() and destroy() functions are called independently for
+ * each section even if they reference the same driver/library. It is
+ * up to driver implementation to detect and catch this situation if
+ * it is undesirable.
+ */
+
+#include <isc/commandline.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dyndb.h>
+#include <dns/types.h>
+
+#include "db.h"
+#include "instance.h"
+#include "log.h"
+#include "util.h"
+
+/* aliases for the exported symbols */
+
+dns_dyndb_destroy_t dyndb_destroy;
+dns_dyndb_register_t dyndb_init;
+dns_dyndb_version_t dyndb_version;
+
+/*
+ * Driver init is called for each dyndb section in named.conf
+ * once during startup and then again on every reload.
+ *
+ * @code
+ * dyndb example-name "sample.so" { param1 param2 };
+ * @endcode
+ *
+ * @param[in] name User-defined string from dyndb "name" {}; definition
+ * in named.conf.
+ * The example above will have name = "example-name".
+ * @param[in] parameters User-defined parameters from dyndb section as one
+ * string. The example above will have
+ * params = "param1 param2";
+ * @param[in] file The name of the file from which the parameters
+ * were read.
+ * @param[in] line The line number from which the parameters were read.
+ * @param[out] instp Pointer to instance-specific data
+ * (for one dyndb section).
+ */
+isc_result_t
+dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters,
+ const char *file, unsigned long line, const dns_dyndbctx_t *dctx,
+ void **instp) {
+ isc_result_t result;
+ unsigned int argc;
+ char **argv = NULL;
+ char *s = NULL;
+ sample_instance_t *sample_inst = NULL;
+
+ REQUIRE(name != NULL);
+ REQUIRE(dctx != NULL);
+
+ s = isc_mem_strdup(mctx, parameters);
+
+ result = isc_commandline_strtoargv(mctx, s, &argc, &argv, 0);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "dyndb_init: isc_commandline_strtoargv -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ log_write(ISC_LOG_DEBUG(9), "loading params for dyndb '%s' from %s:%lu",
+ name, file, line);
+
+ /* Finally, create the instance. */
+ result = new_sample_instance(mctx, name, argc, argv, dctx,
+ &sample_inst);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "dyndb_init: new_sample_instance -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ /*
+ * This is an example so we create and load zones
+ * right now. This step can be arbitrarily postponed.
+ */
+ result = load_sample_instance_zones(sample_inst);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "dyndb_init: load_sample_instance_zones -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ *instp = sample_inst;
+
+cleanup:
+ isc_mem_free(mctx, s);
+ if (argv != NULL) {
+ isc_mem_put(mctx, argv, argc * sizeof(*argv));
+ }
+
+ return (result);
+}
+
+/*
+ * Driver destroy is called for every instance on every reload and then once
+ * during shutdown.
+ *
+ * @param[out] instp Pointer to instance-specific data (for one dyndb section).
+ */
+void
+dyndb_destroy(void **instp) {
+ destroy_sample_instance((sample_instance_t **)instp);
+}
+
+/*
+ * Driver version is called when loading the driver to ensure there
+ * is no API mismatch between the driver and the caller.
+ */
+int
+dyndb_version(unsigned int *flags) {
+ UNUSED(flags);
+
+ return (DNS_DYNDB_VERSION);
+}
diff --git a/bin/tests/system/dyndb/driver/instance.c b/bin/tests/system/dyndb/driver/instance.c
new file mode 100644
index 0000000..9e90a2c
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/instance.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) 2009-2015 Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver instance object.
+ *
+ * One instance is equivalent to dynamic-db section in named.conf.
+ * This module parses arguments and provide high-level operations
+ * instance init/zone load/instance destroy.
+ */
+
+#include "instance.h"
+
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dyndb.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+
+#include "db.h"
+#include "log.h"
+#include "util.h"
+#include "zone.h"
+
+/*
+ * Parse parameters and convert them to zone names. Caller has to deallocate
+ * resulting DNS names.
+ *
+ * @param[in] argv NULL-terminated string array of length 2 (excluding NULL)
+ * Each string has to be a valid DNS name.
+ * @param[out] z1 Zone name from argv[0]
+ * @param[out] z2 Zone name from argv[1]
+ */
+static isc_result_t
+parse_params(isc_mem_t *mctx, int argc, char **argv, dns_name_t *z1,
+ dns_name_t *z2) {
+ isc_result_t result;
+ int i;
+
+ REQUIRE(argv != NULL);
+ REQUIRE(z1 != NULL);
+ REQUIRE(z2 != NULL);
+
+ for (i = 0; i < argc; i++) {
+ log_info("param: '%s'", argv[i]);
+ }
+ log_info("number of params: %d", i);
+
+ if (argc != 2) {
+ log_error("exactly two parameters "
+ "(absolute zone names) are required");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ result = dns_name_fromstring2(z1, argv[0], dns_rootname, 0, mctx);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "parse_params: dns_name_fromstring2 -> %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ result = dns_name_fromstring2(z2, argv[1], dns_rootname, 0, mctx);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "parse_params: dns_name_fromstring2 -> %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ return (result);
+}
+
+/*
+ * Initialize new driver instance. It will not create zones until
+ * load_sample_instance_zones() is called.
+ */
+isc_result_t
+new_sample_instance(isc_mem_t *mctx, const char *db_name, int argc, char **argv,
+ const dns_dyndbctx_t *dctx,
+ sample_instance_t **sample_instp) {
+ isc_result_t result;
+ sample_instance_t *inst = NULL;
+
+ REQUIRE(sample_instp != NULL && *sample_instp == NULL);
+
+ CHECKED_MEM_GET_PTR(mctx, inst);
+ ZERO_PTR(inst);
+ isc_mem_attach(mctx, &inst->mctx);
+
+ inst->db_name = isc_mem_strdup(mctx, db_name);
+
+ inst->zone1_name = dns_fixedname_initname(&inst->zone1_fn);
+ inst->zone2_name = dns_fixedname_initname(&inst->zone2_fn);
+
+ result = parse_params(mctx, argc, argv, inst->zone1_name,
+ inst->zone2_name);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "new_sample_instance: parse_params -> %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ dns_view_attach(dctx->view, &inst->view);
+ dns_zonemgr_attach(dctx->zmgr, &inst->zmgr);
+ isc_task_attach(dctx->task, &inst->task);
+
+ /* Register new DNS DB implementation. */
+ result = dns_db_register(db_name, create_db, inst, mctx, &inst->db_imp);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "new_sample_instance: dns_db_register -> %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ *sample_instp = inst;
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (result != ISC_R_SUCCESS) {
+ destroy_sample_instance(&inst);
+ }
+ return (result);
+}
+
+/*
+ * Create empty zones, add fake SOA, NS, and A records, load fake zones
+ * and add them to inst->view.
+ */
+isc_result_t
+load_sample_instance_zones(sample_instance_t *inst) {
+ isc_result_t result;
+
+ result = create_zone(inst, inst->zone1_name, &inst->zone1);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "load_sample_instance_zones: create_zone -> %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ result = activate_zone(inst, inst->zone1);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "load_sample_instance_zones: activate_zone -> %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ result = create_zone(inst, inst->zone2_name, &inst->zone2);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "load_sample_instance_zones: create_zone -> %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ result = activate_zone(inst, inst->zone2);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "load_sample_instance_zones: activate_zone -> %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+cleanup:
+ return (result);
+}
+
+void
+destroy_sample_instance(sample_instance_t **instp) {
+ sample_instance_t *inst;
+ REQUIRE(instp != NULL);
+
+ inst = *instp;
+ *instp = NULL;
+ if (inst == NULL) {
+ return;
+ }
+
+ if (inst->db_name != NULL) {
+ isc_mem_free(inst->mctx, inst->db_name);
+ }
+ if (inst->zone1 != NULL) {
+ dns_zone_detach(&inst->zone1);
+ }
+ if (inst->zone2 != NULL) {
+ dns_zone_detach(&inst->zone2);
+ }
+ if (inst->db_imp != NULL) {
+ dns_db_unregister(&inst->db_imp);
+ }
+
+ dns_view_detach(&inst->view);
+ dns_zonemgr_detach(&inst->zmgr);
+ isc_task_detach(&inst->task);
+
+ MEM_PUT_AND_DETACH(inst);
+}
diff --git a/bin/tests/system/dyndb/driver/instance.h b/bin/tests/system/dyndb/driver/instance.h
new file mode 100644
index 0000000..67a219c
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/instance.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) 2009-2015 Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * Driver instance object.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/types.h>
+
+struct sample_instance {
+ isc_mem_t *mctx;
+ char *db_name;
+ dns_dbimplementation_t *db_imp;
+
+ /* These are needed for zone creation. */
+ dns_view_t *view;
+ dns_zonemgr_t *zmgr;
+ isc_task_t *task;
+ bool exiting;
+
+ dns_zone_t *zone1;
+ dns_fixedname_t zone1_fn;
+ dns_name_t *zone1_name;
+
+ dns_zone_t *zone2;
+ dns_fixedname_t zone2_fn;
+ dns_name_t *zone2_name;
+};
+
+typedef struct sample_instance sample_instance_t;
+
+isc_result_t
+new_sample_instance(isc_mem_t *mctx, const char *db_name, int argc, char **argv,
+ const dns_dyndbctx_t *dctx,
+ sample_instance_t **sample_instp);
+
+isc_result_t
+load_sample_instance_zones(sample_instance_t *inst);
+
+void
+destroy_sample_instance(sample_instance_t **sample_instp);
diff --git a/bin/tests/system/dyndb/driver/lock.c b/bin/tests/system/dyndb/driver/lock.c
new file mode 100644
index 0000000..5d73871
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/lock.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "lock.h"
+
+#include <isc/task.h>
+#include <isc/util.h>
+
+/*
+ * Lock BIND dispatcher and allow only single task to run.
+ *
+ * @warning
+ * All calls to isc_task_beginexclusive() have to operate on the same task
+ * otherwise it would not be possible to distinguish recursive locking
+ * from real conflict on the dispatcher lock.
+ * For this reason this wrapper function always works with inst->task.
+ * As a result, this function have to be be called only from inst->task.
+ *
+ * Recursive locking is allowed. Auxiliary variable pointed to by "statep"
+ * stores information if last run_exclusive_enter() operation really locked
+ * something or if the lock was called recursively and was no-op.
+ *
+ * The pair (inst, state) used for run_exclusive_enter() has to be
+ * used for run_exclusive_exit().
+ *
+ * @param[in] inst The instance with the only task which is allowed to
+ * run.
+ * @param[in,out] statep Lock state: ISC_R_SUCCESS or ISC_R_LOCKBUSY
+ */
+void
+run_exclusive_enter(sample_instance_t *inst, isc_result_t *statep) {
+ REQUIRE(statep != NULL);
+ REQUIRE(*statep == ISC_R_IGNORE);
+
+ *statep = isc_task_beginexclusive(inst->task);
+ RUNTIME_CHECK(*statep == ISC_R_SUCCESS || *statep == ISC_R_LOCKBUSY);
+}
+
+/*
+ * Exit task-exclusive mode.
+ *
+ * @param[in] inst The instance used for previous run_exclusive_enter() call.
+ * @param[in] state Lock state as returned by run_exclusive_enter().
+ */
+void
+run_exclusive_exit(sample_instance_t *inst, isc_result_t state) {
+ if (state == ISC_R_SUCCESS) {
+ isc_task_endexclusive(inst->task);
+ } else {
+ /* Unlocking recursive lock or the lock was never locked. */
+ INSIST(state == ISC_R_LOCKBUSY || state == ISC_R_IGNORE);
+ }
+
+ return;
+}
diff --git a/bin/tests/system/dyndb/driver/lock.h b/bin/tests/system/dyndb/driver/lock.h
new file mode 100644
index 0000000..9f2ed9e
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/lock.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#pragma once
+
+#include "instance.h"
+#include "util.h"
+
+void
+run_exclusive_enter(sample_instance_t *inst, isc_result_t *statep);
+
+void
+run_exclusive_exit(sample_instance_t *inst, isc_result_t state);
diff --git a/bin/tests/system/dyndb/driver/log.c b/bin/tests/system/dyndb/driver/log.c
new file mode 100644
index 0000000..ef8b1ee
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/log.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "log.h"
+
+#include <isc/util.h>
+
+#include <dns/log.h>
+
+void
+log_write(int level, const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DYNDB,
+ level, format, args);
+ va_end(args);
+}
diff --git a/bin/tests/system/dyndb/driver/log.h b/bin/tests/system/dyndb/driver/log.h
new file mode 100644
index 0000000..375db2b
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/log.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#pragma once
+
+#include <isc/error.h>
+#include <isc/result.h>
+
+#include <dns/log.h>
+
+#define log_error_r(fmt, ...) \
+ log_error(fmt ": %s", ##__VA_ARGS__, isc_result_totext(result))
+
+#define log_error(format, ...) log_write(ISC_LOG_ERROR, format, ##__VA_ARGS__)
+
+#define log_info(format, ...) log_write(ISC_LOG_INFO, format, ##__VA_ARGS__)
+
+void
+log_write(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
diff --git a/bin/tests/system/dyndb/driver/syncptr.c b/bin/tests/system/dyndb/driver/syncptr.c
new file mode 100644
index 0000000..5124df3
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/syncptr.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Automatic A/AAAA/PTR record synchronization.
+ */
+
+#include "syncptr.h"
+
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/netaddr.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/db.h>
+#include <dns/name.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+
+#include "instance.h"
+#include "util.h"
+
+/* Almost random value. See eventclass.h */
+#define SYNCPTR_WRITE_EVENT (ISC_EVENTCLASS(1025) + 1)
+
+/*
+ * Event used for making changes to reverse zones.
+ */
+typedef struct syncptrevent syncptrevent_t;
+struct syncptrevent {
+ ISC_EVENT_COMMON(syncptrevent_t);
+ isc_mem_t *mctx;
+ dns_zone_t *zone;
+ dns_diff_t diff;
+ dns_fixedname_t ptr_target_name; /* referenced by owner name in
+ * tuple */
+ isc_buffer_t b; /* referenced by target name in tuple */
+ unsigned char buf[DNS_NAME_MAXWIRE];
+};
+
+/*
+ * Write diff generated in syncptr() to reverse zone.
+ *
+ * This function will be called asynchronously and syncptr() will not get
+ * any result from it.
+ *
+ */
+static void
+syncptr_write(isc_task_t *task, isc_event_t *event) {
+ syncptrevent_t *pevent = (syncptrevent_t *)event;
+ dns_dbversion_t *version = NULL;
+ dns_db_t *db = NULL;
+ isc_result_t result;
+
+ REQUIRE(event->ev_type == SYNCPTR_WRITE_EVENT);
+
+ UNUSED(task);
+
+ log_write(ISC_LOG_INFO, "ENTER: syncptr_write");
+
+ result = dns_zone_getdb(pevent->zone, &db);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "syncptr_write: dns_zone_getdb -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ result = dns_db_newversion(db, &version);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "syncptr_write: dns_db_newversion -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ result = dns_diff_apply(&pevent->diff, db, version);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "syncptr_write: dns_diff_apply -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+cleanup:
+ if (db != NULL) {
+ if (version != NULL) {
+ dns_db_closeversion(db, &version, true);
+ }
+ dns_db_detach(&db);
+ }
+ dns_zone_detach(&pevent->zone);
+ dns_diff_clear(&pevent->diff);
+ isc_event_free(&event);
+}
+
+/*
+ * Find a reverse zone for given IP address.
+ *
+ * @param[in] rdata IP address as A/AAAA record
+ * @param[out] name Owner name for the PTR record
+ * @param[out] zone DNS zone for reverse record matching the IP address
+ *
+ * @retval ISC_R_SUCCESS DNS name derived from given IP address belongs to an
+ * reverse zone managed by this driver instance.
+ * PTR record synchronization can continue.
+ * @retval ISC_R_NOTFOUND Suitable reverse zone was not found because it
+ * does not exist or is not managed by this driver.
+ */
+static isc_result_t
+syncptr_find_zone(sample_instance_t *inst, dns_rdata_t *rdata, dns_name_t *name,
+ dns_zone_t **zone) {
+ isc_result_t result;
+ isc_netaddr_t isc_ip; /* internal net address representation */
+ dns_rdata_in_a_t ipv4;
+ dns_rdata_in_aaaa_t ipv6;
+
+ REQUIRE(inst != NULL);
+ REQUIRE(zone != NULL && *zone == NULL);
+
+ switch (rdata->type) {
+ case dns_rdatatype_a:
+ CHECK(dns_rdata_tostruct(rdata, &ipv4, inst->mctx));
+ isc_netaddr_fromin(&isc_ip, &ipv4.in_addr);
+ break;
+
+ case dns_rdatatype_aaaa:
+ CHECK(dns_rdata_tostruct(rdata, &ipv6, inst->mctx));
+ isc_netaddr_fromin6(&isc_ip, &ipv6.in6_addr);
+ break;
+
+ default:
+ FATAL_ERROR("unsupported address type 0x%x", rdata->type);
+ break;
+ }
+
+ /*
+ * Convert IP address to PTR owner name.
+ *
+ * @example
+ * 192.168.0.1 -> 1.0.168.192.in-addr.arpa
+ */
+ result = dns_byaddr_createptrname(&isc_ip, 0, name);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "syncptr_find_zone: dns_byaddr_createptrname -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ /* Find a zone containing owner name of the PTR record. */
+ result = dns_zt_find(inst->view->zonetable, name, 0, NULL, zone);
+ if (result == DNS_R_PARTIALMATCH) {
+ result = ISC_R_SUCCESS;
+ } else if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "syncptr_find_zone: dns_zt_find -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ /* Make sure that the zone is managed by this driver. */
+ if (*zone != inst->zone1 && *zone != inst->zone2) {
+ dns_zone_detach(zone);
+ log_write(ISC_LOG_INFO, "syncptr_find_zone: zone not managed");
+ result = ISC_R_NOTFOUND;
+ }
+
+cleanup:
+ if (rdata->type == dns_rdatatype_a) {
+ dns_rdata_freestruct(&ipv4);
+ } else {
+ dns_rdata_freestruct(&ipv6);
+ }
+
+ return (result);
+}
+
+/*
+ * Generate update event for PTR record to reflect change in A/AAAA record.
+ *
+ * @pre Reverse zone is managed by this driver.
+ *
+ * @param[in] a_name DNS domain of modified A/AAAA record
+ * @param[in] af Address family
+ * @param[in] ip_str IP address as a string (IPv4 or IPv6)
+ * @param[in] mod_op LDAP_MOD_DELETE if A/AAAA record is being deleted
+ * or LDAP_MOD_ADD if A/AAAA record is being added.
+ *
+ * @retval ISC_R_SUCCESS Event for PTR record update was generated and send.
+ * Change to reverse zone will be done asynchronously.
+ * @retval other Synchronization failed - reverse doesn't exist,
+ * is not managed by this driver instance,
+ * memory allocation error, etc.
+ */
+static isc_result_t
+syncptr(sample_instance_t *inst, dns_name_t *name, dns_rdata_t *addr_rdata,
+ dns_ttl_t ttl, dns_diffop_t op) {
+ isc_result_t result;
+ isc_mem_t *mctx = inst->mctx;
+ dns_fixedname_t ptr_name;
+ dns_zone_t *ptr_zone = NULL;
+ dns_rdata_ptr_t ptr_struct;
+ dns_rdata_t ptr_rdata = DNS_RDATA_INIT;
+ dns_difftuple_t *tp = NULL;
+ isc_task_t *task = NULL;
+ syncptrevent_t *pevent = NULL;
+
+ dns_fixedname_init(&ptr_name);
+ DNS_RDATACOMMON_INIT(&ptr_struct, dns_rdatatype_ptr, dns_rdataclass_in);
+ dns_name_init(&ptr_struct.ptr, NULL);
+
+ pevent = (syncptrevent_t *)isc_event_allocate(
+ inst->mctx, inst, SYNCPTR_WRITE_EVENT, syncptr_write, NULL,
+ sizeof(syncptrevent_t));
+ isc_buffer_init(&pevent->b, pevent->buf, sizeof(pevent->buf));
+ dns_fixedname_init(&pevent->ptr_target_name);
+
+ /* Check if reverse zone is managed by this driver */
+ result = syncptr_find_zone(inst, addr_rdata,
+ dns_fixedname_name(&ptr_name), &ptr_zone);
+ if (result != ISC_R_SUCCESS) {
+ log_error_r("PTR record synchronization skipped: reverse zone "
+ "is not managed by driver instance '%s'",
+ inst->db_name);
+ goto cleanup;
+ }
+
+ /* Reverse zone is managed by this driver, prepare PTR record */
+ pevent->zone = NULL;
+ dns_zone_attach(ptr_zone, &pevent->zone);
+ dns_name_copy(name, dns_fixedname_name(&pevent->ptr_target_name));
+ dns_name_clone(dns_fixedname_name(&pevent->ptr_target_name),
+ &ptr_struct.ptr);
+ dns_diff_init(inst->mctx, &pevent->diff);
+ result = dns_rdata_fromstruct(&ptr_rdata, dns_rdataclass_in,
+ dns_rdatatype_ptr, &ptr_struct,
+ &pevent->b);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "syncptr: dns_rdata_fromstruct -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ /* Create diff */
+ result = dns_difftuple_create(mctx, op, dns_fixedname_name(&ptr_name),
+ ttl, &ptr_rdata, &tp);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "syncptr: dns_difftuple_create -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ dns_diff_append(&pevent->diff, &tp);
+
+ /*
+ * Send update event to the reverse zone.
+ * It will be processed asynchronously.
+ */
+ dns_zone_gettask(ptr_zone, &task);
+ isc_task_send(task, (isc_event_t **)&pevent);
+
+cleanup:
+ if (ptr_zone != NULL) {
+ dns_zone_detach(&ptr_zone);
+ }
+ if (tp != NULL) {
+ dns_difftuple_free(&tp);
+ }
+ if (task != NULL) {
+ isc_task_detach(&task);
+ }
+ if (pevent != NULL) {
+ isc_event_free((isc_event_t **)&pevent);
+ }
+
+ return (result);
+}
+
+/*
+ * Generate update event for every rdata in rdataset.
+ *
+ * @param[in] name Owner name for A/AAAA records in rdataset.
+ * @param[in] rdataset A/AAAA records.
+ * @param[in] op DNS_DIFFOP_ADD / DNS_DIFFOP_DEL for adding / deleting
+ * the rdata
+ */
+isc_result_t
+syncptrs(sample_instance_t *inst, dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_diffop_t op) {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ dns_rdataset_current(rdataset, &rdata);
+ result = syncptr(inst, name, &rdata, rdataset->ttl, op);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
+ goto cleanup;
+ }
+ }
+ if (result == ISC_R_NOMORE) {
+ result = ISC_R_SUCCESS;
+ }
+
+cleanup:
+ return (result);
+}
diff --git a/bin/tests/system/dyndb/driver/syncptr.h b/bin/tests/system/dyndb/driver/syncptr.h
new file mode 100644
index 0000000..91edee1
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/syncptr.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Sync PTR records
+ */
+
+#pragma once
+
+#include <isc/result.h>
+
+#include <dns/diff.h>
+#include <dns/name.h>
+#include <dns/rdataset.h>
+
+#include "instance.h"
+
+isc_result_t
+syncptrs(sample_instance_t *inst, dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_diffop_t op);
diff --git a/bin/tests/system/dyndb/driver/util.h b/bin/tests/system/dyndb/driver/util.h
new file mode 100644
index 0000000..d59a7fd
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/util.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Memory allocation and error handling utilities.
+ */
+
+#pragma once
+
+#include <isc/mem.h>
+
+#include <dns/types.h>
+
+#include "log.h"
+
+#define CLEANUP_WITH(result_code) \
+ do { \
+ result = (result_code); \
+ goto cleanup; \
+ } while (0)
+
+#define CHECK(op) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+#define CHECKED_MEM_GET(m, target_ptr, s) \
+ do { \
+ (target_ptr) = isc_mem_get((m), (s)); \
+ if ((target_ptr) == NULL) { \
+ result = ISC_R_NOMEMORY; \
+ log_error("Memory allocation failed"); \
+ goto cleanup; \
+ } \
+ } while (0)
+
+#define CHECKED_MEM_GET_PTR(m, target_ptr) \
+ CHECKED_MEM_GET(m, target_ptr, sizeof(*(target_ptr)))
+
+#define CHECKED_MEM_STRDUP(m, source, target) \
+ do { \
+ (target) = isc_mem_strdup((m), (source)); \
+ if ((target) == NULL) { \
+ result = ISC_R_NOMEMORY; \
+ log_error("Memory allocation failed"); \
+ goto cleanup; \
+ } \
+ } while (0)
+
+#define ZERO_PTR(ptr) memset((ptr), 0, sizeof(*(ptr)))
+
+#define MEM_PUT_AND_DETACH(target_ptr) \
+ isc_mem_putanddetach(&(target_ptr)->mctx, target_ptr, \
+ sizeof(*(target_ptr)))
diff --git a/bin/tests/system/dyndb/driver/zone.c b/bin/tests/system/dyndb/driver/zone.c
new file mode 100644
index 0000000..59f87a6
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/zone.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) Red Hat
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Zone management.
+ */
+
+#include "zone.h"
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/util.h>
+
+#include <dns/dyndb.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+
+#include "instance.h"
+#include "lock.h"
+#include "log.h"
+#include "util.h"
+
+extern const char *impname;
+
+/*
+ * Create a new zone with origin 'name'. The zone stay invisible to clients
+ * until it is explicitly added to a view.
+ */
+isc_result_t
+create_zone(sample_instance_t *const inst, dns_name_t *const name,
+ dns_zone_t **const rawp) {
+ isc_result_t result;
+ dns_zone_t *raw = NULL;
+ const char *zone_argv[1];
+ char zone_name[DNS_NAME_FORMATSIZE];
+ dns_acl_t *acl_any = NULL;
+
+ REQUIRE(inst != NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(rawp != NULL && *rawp == NULL);
+
+ zone_argv[0] = inst->db_name;
+
+ result = dns_zone_create(&raw, inst->mctx);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR, "create_zone: dns_zone_create -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ result = dns_zone_setorigin(raw, name);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "create_zone: dns_zone_setorigin -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ dns_zone_setclass(raw, dns_rdataclass_in);
+ dns_zone_settype(raw, dns_zone_primary);
+ dns_zone_setdbtype(raw, 1, zone_argv);
+
+ result = dns_zonemgr_managezone(inst->zmgr, raw);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "create_zone: dns_zonemgr_managezone -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ /* This is completely insecure - use some sensible values instead! */
+ result = dns_acl_any(inst->mctx, &acl_any);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR, "create_zone: dns_acl_any -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ dns_zone_setupdateacl(raw, acl_any);
+ dns_zone_setqueryacl(raw, acl_any);
+ dns_zone_setxfracl(raw, acl_any);
+ dns_acl_detach(&acl_any);
+
+ *rawp = raw;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ dns_name_format(name, zone_name, DNS_NAME_FORMATSIZE);
+ log_error_r("failed to create new zone '%s'", zone_name);
+
+ if (raw != NULL) {
+ if (dns_zone_getmgr(raw) != NULL) {
+ dns_zonemgr_releasezone(inst->zmgr, raw);
+ }
+ dns_zone_detach(&raw);
+ }
+ if (acl_any != NULL) {
+ dns_acl_detach(&acl_any);
+ }
+
+ return (result);
+}
+
+/*
+ * Add zone to the view defined in inst->view. This will make the zone visible
+ * to clients.
+ */
+static isc_result_t
+publish_zone(sample_instance_t *inst, dns_zone_t *zone) {
+ isc_result_t result;
+ bool freeze = false;
+ dns_zone_t *zone_in_view = NULL;
+ dns_view_t *view_in_zone = NULL;
+ isc_result_t lock_state = ISC_R_IGNORE;
+
+ REQUIRE(inst != NULL);
+ REQUIRE(zone != NULL);
+
+ /* Return success if the zone is already in the view as expected. */
+ result = dns_view_findzone(inst->view, dns_zone_getorigin(zone),
+ &zone_in_view);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
+ goto cleanup;
+ }
+
+ view_in_zone = dns_zone_getview(zone);
+ if (view_in_zone != NULL) {
+ /* Zone has a view set -> view should contain the same zone. */
+ if (zone_in_view == zone) {
+ /* Zone is already published in the right view. */
+ CLEANUP_WITH(ISC_R_SUCCESS);
+ } else if (view_in_zone != inst->view) {
+ /*
+ * Un-published inactive zone will have
+ * inst->view in zone but will not be present
+ * in the view itself.
+ */
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone->view doesn't "
+ "match data in the view");
+ CLEANUP_WITH(ISC_R_UNEXPECTED);
+ }
+ }
+
+ if (zone_in_view != NULL) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "cannot publish zone: view already "
+ "contains another zone with this name");
+ CLEANUP_WITH(ISC_R_UNEXPECTED);
+ }
+
+ run_exclusive_enter(inst, &lock_state);
+ if (inst->view->frozen) {
+ freeze = true;
+ dns_view_thaw(inst->view);
+ }
+
+ dns_zone_setview(zone, inst->view);
+ result = dns_view_addzone(inst->view, zone);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "publish_zone: dns_view_addzone -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+cleanup:
+ if (zone_in_view != NULL) {
+ dns_zone_detach(&zone_in_view);
+ }
+ if (freeze) {
+ dns_view_freeze(inst->view);
+ }
+ run_exclusive_exit(inst, lock_state);
+
+ return (result);
+}
+
+/*
+ * @warning Never call this on raw part of in-line secure zone, call it only
+ * on the secure zone!
+ */
+static isc_result_t
+load_zone(dns_zone_t *zone) {
+ isc_result_t result;
+ bool zone_dynamic;
+ uint32_t serial;
+
+ result = dns_zone_load(zone, false);
+ if (result != ISC_R_SUCCESS && result != DNS_R_UPTODATE &&
+ result != DNS_R_DYNAMIC && result != DNS_R_CONTINUE)
+ {
+ goto cleanup;
+ }
+ zone_dynamic = (result == DNS_R_DYNAMIC);
+
+ result = dns_zone_getserial(zone, &serial);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR,
+ "load_zone: dns_zone_getserial -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u", serial);
+
+ if (zone_dynamic) {
+ dns_zone_notify(zone);
+ }
+
+cleanup:
+ return (result);
+}
+
+/*
+ * Add zone to view and call dns_zone_load().
+ */
+isc_result_t
+activate_zone(sample_instance_t *inst, dns_zone_t *raw) {
+ isc_result_t result;
+
+ /*
+ * Zone has to be published *before* zone load
+ * otherwise it will race with zone->view != NULL check
+ * in zone_maintenance() in zone.c.
+ */
+ result = publish_zone(inst, raw);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(raw, ISC_LOG_ERROR, "cannot add zone to view: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ result = load_zone(raw);
+ if (result != ISC_R_SUCCESS) {
+ log_write(ISC_LOG_ERROR, "activate_zone: load_zone -> %s\n",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+cleanup:
+ return (result);
+}
diff --git a/bin/tests/system/dyndb/driver/zone.h b/bin/tests/system/dyndb/driver/zone.h
new file mode 100644
index 0000000..85575a0
--- /dev/null
+++ b/bin/tests/system/dyndb/driver/zone.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (C) Red Hat
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#pragma once
+
+#include <isc/result.h>
+
+#include <dns/name.h>
+
+#include "instance.h"
+
+isc_result_t
+create_zone(sample_instance_t *const inst, dns_name_t *const name,
+ dns_zone_t **const rawp);
+
+isc_result_t
+activate_zone(sample_instance_t *inst, dns_zone_t *raw);
diff --git a/bin/tests/system/dyndb/ns1/named.conf.in b/bin/tests/system/dyndb/ns1/named.conf.in
new file mode 100644
index 0000000..d319a2a
--- /dev/null
+++ b/bin/tests/system/dyndb/ns1/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { };
+
+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";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.1; 127.0.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+dyndb sample "../driver/.libs/sample.so" { ipv4.example.nil. in-addr.arpa. };
+dyndb sample2 "../driver/.libs/sample.so" { ipv6.example.nil. 8.b.d.0.1.0.0.2.ip6.arpa. };
diff --git a/bin/tests/system/dyndb/prereq.sh b/bin/tests/system/dyndb/prereq.sh
new file mode 100644
index 0000000..19e0467
--- /dev/null
+++ b/bin/tests/system/dyndb/prereq.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$FEATURETEST --tsan && {
+ echo_i "TSAN - skipping dyndb test"
+ exit 255
+}
+
+exit 0
diff --git a/bin/tests/system/dyndb/setup.sh b/bin/tests/system/dyndb/setup.sh
new file mode 100644
index 0000000..82240a7
--- /dev/null
+++ b/bin/tests/system/dyndb/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/dyndb/tests.sh b/bin/tests/system/dyndb/tests.sh
new file mode 100644
index 0000000..ef02dea
--- /dev/null
+++ b/bin/tests/system/dyndb/tests.sh
@@ -0,0 +1,166 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+DIGOPTS="@10.53.0.1 -p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+newtest() {
+ n=$((n + 1))
+ echo_i "${1} (${n})"
+ ret=0
+}
+
+test_add() {
+ host="$1"
+ type="$2"
+ ip="$3"
+
+ cat <<EOF > ns1/update.txt
+server 10.53.0.1 ${PORT}
+ttl 86400
+update add $host $type $ip
+send
+EOF
+
+ newtest "adding $host $type $ip"
+ $NSUPDATE ns1/update.txt > /dev/null 2>&1 || {
+ [ "$should_fail" ] || \
+ echo_i "update failed for $host $type $ip"
+ return 1
+ }
+
+ out=$($DIG $DIGOPTS +noall +answer -t $type -q $host)
+ echo $out > added.a.out.$n
+ lines=$(echo "$out" | grep "$ip" | wc -l)
+ [ $lines -eq 1 ] || {
+ [ "$should_fail" ] || \
+ echo_i "dig output incorrect for $host $type $cmd: $out"
+ return 1
+ }
+
+ for i in 1 2 3 4 5 6 7 8 9 10
+ do
+ out=$($DIG $DIGOPTS +noall +answer -x $ip)
+ echo $out > added.ptr.out.$n
+ lines=$(echo "$out" | grep "$host" | wc -l)
+ [ $lines -eq 1 ] && break;
+ $PERL -e 'select(undef, undef, undef, 0.1);'
+ done
+ [ $lines -eq 1 ] || {
+ [ "$should_fail" ] || \
+ echo_i "dig reverse output incorrect for $host $type $cmd: $out"
+ return 1
+ }
+
+ return 0
+}
+
+test_del() {
+ host="$1"
+ type="$2"
+
+ ip=$($DIG $DIGOPTS +short $host $type)
+
+ cat <<EOF > ns1/update.txt
+server 10.53.0.1 ${PORT}
+update del $host $type
+send
+EOF
+
+ newtest "deleting $host $type (was $ip)"
+ $NSUPDATE ns1/update.txt > /dev/null 2>&1 || {
+ [ "$should_fail" ] || \
+ echo_i "update failed deleting $host $type"
+ return 1
+ }
+
+ out=$($DIG $DIGOPTS +noall +answer -t $type -q $host)
+ echo $out > deleted.a.out.$n
+ lines=$(echo "$out" | grep "$ip" | wc -l)
+ [ $lines -eq 0 ] || {
+ [ "$should_fail" ] || \
+ echo_i "dig output incorrect for $host $type $cmd: $out"
+ return 1
+ }
+
+ for i in 1 2 3 4 5 6 7 8 9 10
+ do
+ out=$($DIG $DIGOPTS +noall +answer -x $ip)
+ echo $out > deleted.ptr.out.$n
+ lines=$(echo "$out" | grep "$host" | wc -l)
+ [ $lines -eq 0 ] && break
+ $PERL -e 'select(undef, undef, undef, 0.1);'
+ done
+ [ $lines -eq 0 ] || {
+ [ "$should_fail" ] || \
+ echo_i "dig reverse output incorrect for $host $type $cmd: $out"
+ return 1
+ }
+
+ return 0
+}
+
+test_add test1.ipv4.example.nil. A "10.53.0.10" || ret=1
+status=$((status + ret))
+
+test_add test2.ipv4.example.nil. A "10.53.0.11" || ret=1
+status=$((status + ret))
+
+test_add test3.ipv4.example.nil. A "10.53.0.12" || ret=1
+status=$((status + ret))
+
+test_add test4.ipv6.example.nil. AAAA "2001:db8::1" || ret=1
+status=$((status + ret))
+
+test_del test1.ipv4.example.nil. A || ret=1
+status=$((status + ret))
+
+test_del test2.ipv4.example.nil. A || ret=1
+status=$((status + ret))
+
+test_del test3.ipv4.example.nil. A || ret=1
+status=$((status + ret))
+
+test_del test4.ipv6.example.nil. AAAA || ret=1
+status=$((status + ret))
+
+newtest "checking parameter logging"
+grep "loading params for dyndb 'sample' from .*named.conf:" ns1/named.run > /dev/null || ret=1
+grep "loading params for dyndb 'sample2' from .*named.conf:" ns1/named.run > /dev/null || ret=1
+[ $ret -eq 1 ] && echo_i "failed"
+status=$((status + ret))
+
+echo_i "checking dyndb still works after reload"
+rndc_reload ns1 10.53.0.1
+
+test_add test5.ipv4.example.nil. A "10.53.0.10" || ret=1
+status=$((status + ret))
+
+test_add test6.ipv6.example.nil. AAAA "2001:db8::1" || ret=1
+status=$((status + ret))
+
+test_del test5.ipv4.example.nil. A || ret=1
+status=$((status + ret))
+
+test_del test6.ipv6.example.nil. AAAA || ret=1
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/dyndb/tests_sh_dyndb.py b/bin/tests/system/dyndb/tests_sh_dyndb.py
new file mode 100644
index 0000000..ca8f7a1
--- /dev/null
+++ b/bin/tests/system/dyndb/tests_sh_dyndb.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_dyndb(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/ecdsa/clean.sh b/bin/tests/system/ecdsa/clean.sh
new file mode 100644
index 0000000..86aded6
--- /dev/null
+++ b/bin/tests/system/ecdsa/clean.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f ./dig.out*
+rm -f ns*/*.signed
+rm -f ns*/K*
+rm -f ns*/dsset-*
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.conf
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/root.db
+rm -f ns*/signer.err
+rm -f ns*/trusted.conf
+rm -f *-supported.file
diff --git a/bin/tests/system/ecdsa/ns1/named.conf.in b/bin/tests/system/ecdsa/ns1/named.conf.in
new file mode 100644
index 0000000..da27c58
--- /dev/null
+++ b/bin/tests/system/ecdsa/ns1/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+controls { /* empty */ };
+
+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;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/ecdsa/ns1/root.db.in b/bin/tests/system/ecdsa/ns1/root.db.in
new file mode 100644
index 0000000..3bff1d1
--- /dev/null
+++ b/bin/tests/system/ecdsa/ns1/root.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA fdupont.isc.org. a.root.servers.nil. (
+ 2012040600 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
diff --git a/bin/tests/system/ecdsa/ns1/sign.sh b/bin/tests/system/ecdsa/ns1/sign.sh
new file mode 100644
index 0000000..f922225
--- /dev/null
+++ b/bin/tests/system/ecdsa/ns1/sign.sh
@@ -0,0 +1,57 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../../conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+echo_i "ns1/sign.sh"
+
+cp $infile $zonefile
+
+if [ -f ../ecdsa256-supported.file ]; then
+ zsk256=$($KEYGEN -q -a ECDSA256 -n zone "$zone")
+ ksk256=$($KEYGEN -q -a ECDSA256 -n zone -f KSK "$zone")
+ cat "$ksk256.key" "$zsk256.key" >> "$zonefile"
+ $DSFROMKEY -a sha-256 "$ksk256.key" >> dsset-256
+fi
+
+if [ -f ../ecdsa384-supported.file ]; then
+ zsk384=$($KEYGEN -q -a ECDSA384 -n zone "$zone")
+ ksk384=$($KEYGEN -q -a ECDSA384 -n zone -f KSK "$zone")
+ cat "$ksk384.key" "$zsk384.key" >> "$zonefile"
+ $DSFROMKEY -a sha-256 "$ksk384.key" >> dsset-256
+fi
+
+# Configure the resolving server with a static key.
+if [ -f ../ecdsa256-supported.file ]; then
+ keyfile_to_static_ds $ksk256 > trusted.conf
+ cp trusted.conf ../ns2/trusted.conf
+else
+ keyfile_to_static_ds $ksk384 > trusted.conf
+ cp trusted.conf ../ns2/trusted.conf
+fi
+
+if [ -f ../ecdsa384-supported.file ]; then
+ keyfile_to_static_ds $ksk384 > trusted.conf
+ cp trusted.conf ../ns3/trusted.conf
+else
+ keyfile_to_static_ds $ksk256 > trusted.conf
+ cp trusted.conf ../ns3/trusted.conf
+fi
+
+$SIGNER -P -g -o "$zone" "$zonefile" > /dev/null 2> signer.err || cat signer.err
diff --git a/bin/tests/system/ecdsa/ns2/named.conf.in b/bin/tests/system/ecdsa/ns2/named.conf.in
new file mode 100644
index 0000000..fd125d3
--- /dev/null
+++ b/bin/tests/system/ecdsa/ns2/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/ecdsa/ns3/named.conf.in b/bin/tests/system/ecdsa/ns3/named.conf.in
new file mode 100644
index 0000000..f1a80b6
--- /dev/null
+++ b/bin/tests/system/ecdsa/ns3/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+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;
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/ecdsa/setup.sh b/bin/tests/system/ecdsa/setup.sh
new file mode 100644
index 0000000..86cd1cf
--- /dev/null
+++ b/bin/tests/system/ecdsa/setup.sh
@@ -0,0 +1,32 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+if $SHELL ../testcrypto.sh ecdsap256sha256; then
+ echo "yes" > ecdsa256-supported.file
+fi
+
+if $SHELL ../testcrypto.sh ecdsap384sha384; then
+ echo "yes" > ecdsa384-supported.file
+fi
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+(
+ cd ns1
+ $SHELL sign.sh
+)
diff --git a/bin/tests/system/ecdsa/tests.sh b/bin/tests/system/ecdsa/tests.sh
new file mode 100644
index 0000000..f1210ec
--- /dev/null
+++ b/bin/tests/system/ecdsa/tests.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+dig_with_opts() {
+ "$DIG" +tcp +noau +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
+}
+
+if [ -f ecdsa256-supported.file ]; then
+ n=$((n+1))
+ echo_i "checking that ECDSA256 positive validation works ($n)"
+ ret=0
+ dig_with_opts . @10.53.0.1 soa > dig.out.ns1.test$n || ret=1
+ dig_with_opts . @10.53.0.2 soa > dig.out.ns2.test$n || ret=1
+ $PERL ../digcomp.pl dig.out.ns1.test$n dig.out.ns2.test$n || ret=1
+ grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+else
+ echo_i "algorithm ECDSA256 not supported, skipping test"
+fi
+
+if [ -f ecdsa384-supported.file ]; then
+ n=$((n+1))
+ echo_i "checking that ECDSA384 positive validation works ($n)"
+ ret=0
+ dig_with_opts . @10.53.0.1 soa > dig.out.ns1.test$n || ret=1
+ dig_with_opts . @10.53.0.3 soa > dig.out.ns3.test$n || ret=1
+ $PERL ../digcomp.pl dig.out.ns1.test$n dig.out.ns3.test$n || ret=1
+ grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+else
+ echo_i "algorithm ECDSA384 not supported, skipping test"
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/ecdsa/tests_sh_ecdsa.py b/bin/tests/system/ecdsa/tests_sh_ecdsa.py
new file mode 100644
index 0000000..98b9eee
--- /dev/null
+++ b/bin/tests/system/ecdsa/tests_sh_ecdsa.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_ecdsa(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/eddsa/clean.sh b/bin/tests/system/eddsa/clean.sh
new file mode 100644
index 0000000..42f5f75
--- /dev/null
+++ b/bin/tests/system/eddsa/clean.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f ./dig.out*
+rm -f ns*/*.signed
+rm -f ns*/K*
+rm -f ns*/dsset-*
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.conf
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/root.db
+rm -f ns*/signer.err
+rm -f ns*/trusted.conf
+rm -f ns*/example.com.db
+rm -f *-supported.file
diff --git a/bin/tests/system/eddsa/ns1/named.conf.in b/bin/tests/system/eddsa/ns1/named.conf.in
new file mode 100644
index 0000000..da27c58
--- /dev/null
+++ b/bin/tests/system/eddsa/ns1/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+controls { /* empty */ };
+
+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;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/eddsa/ns1/root.db.in b/bin/tests/system/eddsa/ns1/root.db.in
new file mode 100644
index 0000000..3bff1d1
--- /dev/null
+++ b/bin/tests/system/eddsa/ns1/root.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA fdupont.isc.org. a.root.servers.nil. (
+ 2012040600 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
diff --git a/bin/tests/system/eddsa/ns1/sign.sh b/bin/tests/system/eddsa/ns1/sign.sh
new file mode 100644
index 0000000..9bf07f0
--- /dev/null
+++ b/bin/tests/system/eddsa/ns1/sign.sh
@@ -0,0 +1,57 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../../conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+echo_i "ns1/sign.sh"
+
+cp $infile $zonefile
+
+if [ -f ../ed25519-supported.file ]; then
+ zsk25519=$($KEYGEN -q -a ED25519 -n zone "$zone")
+ ksk25519=$($KEYGEN -q -a ED25519 -n zone -f KSK "$zone")
+ cat "$ksk25519.key" "$zsk25519.key" >> "$zonefile"
+ $DSFROMKEY -a sha-256 "$ksk25519.key" >> dsset-256
+fi
+
+if [ -f ../ed448-supported.file ]; then
+ zsk448=$($KEYGEN -q -a ED448 -n zone "$zone")
+ ksk448=$($KEYGEN -q -a ED448 -n zone -f KSK "$zone")
+ cat "$ksk448.key" "$zsk448.key" >> "$zonefile"
+ $DSFROMKEY -a sha-256 "$ksk448.key" >> dsset-256
+fi
+
+# Configure the resolving server with a static key.
+if [ -f ../ed25519-supported.file ]; then
+ keyfile_to_static_ds $ksk25519 > trusted.conf
+ cp trusted.conf ../ns2/trusted.conf
+else
+ keyfile_to_static_ds $ksk448 > trusted.conf
+ cp trusted.conf ../ns2/trusted.conf
+fi
+
+if [ -f ../ed448-supported.file ]; then
+ keyfile_to_static_ds $ksk448 > trusted.conf
+ cp trusted.conf ../ns3/trusted.conf
+else
+ keyfile_to_static_ds $ksk25519 > trusted.conf
+ cp trusted.conf ../ns3/trusted.conf
+fi
+
+$SIGNER -P -g -o "$zone" "$zonefile" > /dev/null 2> signer.err || cat signer.err
diff --git a/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.key b/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.key
new file mode 100644
index 0000000..ff6d5bf
--- /dev/null
+++ b/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.key
@@ -0,0 +1 @@
+example.com. IN DNSKEY 257 3 15 l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4=
diff --git a/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.private b/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.private
new file mode 100644
index 0000000..788b2d7
--- /dev/null
+++ b/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.private
@@ -0,0 +1,4 @@
+Private-key-format: v1.2
+Algorithm: 15 (ED25519)
+PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=
+
diff --git a/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.key b/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.key
new file mode 100644
index 0000000..71e4620
--- /dev/null
+++ b/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.key
@@ -0,0 +1 @@
+example.com. IN DNSKEY 257 3 15 zPnZ/QwEe7S8C5SPz2OfS5RR40ATk2/rYnE9xHIEijs=
diff --git a/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.private b/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.private
new file mode 100644
index 0000000..78ec36d
--- /dev/null
+++ b/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.private
@@ -0,0 +1,3 @@
+Private-key-format: v1.2
+Algorithm: 15 (ED25519)
+PrivateKey: DSSF3o0s0f+ElWzj9E/Osxw8hLpk55chkmx0LYN5WiY=
diff --git a/bin/tests/system/eddsa/ns2/example.com.db.in b/bin/tests/system/eddsa/ns2/example.com.db.in
new file mode 100644
index 0000000..0ecda67
--- /dev/null
+++ b/bin/tests/system/eddsa/ns2/example.com.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA fdupont.isc.org. ns.example.com. (
+ 2012040600 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 3600 ; minimum
+ )
+ MX 10 mail.example.com.
+ NS ns.example.com.
+ns.example.com. A 10.53.0.2
diff --git a/bin/tests/system/eddsa/ns2/named.conf.in b/bin/tests/system/eddsa/ns2/named.conf.in
new file mode 100644
index 0000000..fd125d3
--- /dev/null
+++ b/bin/tests/system/eddsa/ns2/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/eddsa/ns2/sign.sh b/bin/tests/system/eddsa/ns2/sign.sh
new file mode 100644
index 0000000..6c1c479
--- /dev/null
+++ b/bin/tests/system/eddsa/ns2/sign.sh
@@ -0,0 +1,38 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../../conf.sh
+
+zone=example.com.
+infile=example.com.db.in
+zonefile=example.com.db
+starttime=20150729220000
+endtime=20150819220000
+
+echo_i "ns2/sign.sh"
+
+cp $infile $zonefile
+
+if [ -f ../ed25519-supported.file ]; then
+
+ for i in Xexample.com.+015+03613 Xexample.com.+015+35217
+ do
+ cp "$i.key" "$(echo $i.key | sed s/X/K/)"
+ cp "$i.private" "$(echo $i.private | sed s/X/K/)"
+ cat "$(echo $i.key | sed s/X/K/)" >> "$zonefile"
+ done
+fi
+
+$SIGNER -P -z -s "$starttime" -e "$endtime" -o "$zone" "$zonefile" > /dev/null 2> signer.err || cat signer.err
diff --git a/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.key b/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.key
new file mode 100644
index 0000000..5c4628f
--- /dev/null
+++ b/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.key
@@ -0,0 +1 @@
+example.com. IN DNSKEY 257 3 16 3kgROaDjrh0H2iuixWBrc8g2EpBBLCdGzHmn+G2MpTPhpj/OiBVHHSfPodx1FYYUcJKm1MDpJtIA
diff --git a/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.private b/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.private
new file mode 100644
index 0000000..eb065f9
--- /dev/null
+++ b/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.private
@@ -0,0 +1,3 @@
+Private-key-format: v1.2
+Algorithm: 16 (ED448)
+PrivateKey: xZ+5Cgm463xugtkY5B0Jx6erFTXp13rYegst0qRtNsOYnaVpMx0Z/c5EiA9x8wWbDDct/U3FhYWA
diff --git a/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.key b/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.key
new file mode 100644
index 0000000..705856d
--- /dev/null
+++ b/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.key
@@ -0,0 +1 @@
+example.com. IN DNSKEY 257 3 16 kkreGWoccSDmUBGAe7+zsbG6ZAFQp+syPmYUurBRQc3tDjeMCJcVMRDmgcNLp5HlHAMy12VoISsA
diff --git a/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.private b/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.private
new file mode 100644
index 0000000..b512d80
--- /dev/null
+++ b/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.private
@@ -0,0 +1,3 @@
+Private-key-format: v1.2
+Algorithm: 16 (ED448)
+PrivateKey: WEykD3ht3MHkU8iH4uVOLz8JLwtRBSqiBoM6fF72+Mrp/u5gjxuB1DV6NnPO2BlZdz4hdSTkOdOA
diff --git a/bin/tests/system/eddsa/ns3/example.com.db.in b/bin/tests/system/eddsa/ns3/example.com.db.in
new file mode 100644
index 0000000..9a1aab6
--- /dev/null
+++ b/bin/tests/system/eddsa/ns3/example.com.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA fdupont.isc.org. ns.example.com. (
+ 2012040600 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 3600 ; minimum
+ )
+ MX 10 mail.example.com.
+ NS ns.example.com.
+ns.example.com. A 10.53.0.3
diff --git a/bin/tests/system/eddsa/ns3/named.conf.in b/bin/tests/system/eddsa/ns3/named.conf.in
new file mode 100644
index 0000000..f1a80b6
--- /dev/null
+++ b/bin/tests/system/eddsa/ns3/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+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;
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/eddsa/ns3/sign.sh b/bin/tests/system/eddsa/ns3/sign.sh
new file mode 100644
index 0000000..e501923
--- /dev/null
+++ b/bin/tests/system/eddsa/ns3/sign.sh
@@ -0,0 +1,37 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../../conf.sh
+
+zone=example.com.
+infile=example.com.db.in
+zonefile=example.com.db
+starttime=20150729220000
+endtime=20150819220000
+
+echo_i "ns3/sign.sh"
+
+cp $infile $zonefile
+
+if [ -f ../ed448-supported.file ]; then
+ for i in Xexample.com.+016+09713 Xexample.com.+016+38353
+ do
+ cp "$i.key" "$(echo $i.key | sed s/X/K/)"
+ cp "$i.private" "$(echo $i.private | sed s/X/K/)"
+ cat "$(echo $i.key | sed s/X/K/)" >> "$zonefile"
+ done
+fi
+
+$SIGNER -P -z -s "$starttime" -e "$endtime" -o "$zone" "$zonefile" > /dev/null 2> signer.err || cat signer.err
diff --git a/bin/tests/system/eddsa/prereq.sh b/bin/tests/system/eddsa/prereq.sh
new file mode 100644
index 0000000..5b1385b
--- /dev/null
+++ b/bin/tests/system/eddsa/prereq.sh
@@ -0,0 +1,26 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+supported=0
+if $SHELL ../testcrypto.sh ed25519; then
+ supported=1
+fi
+if $SHELL ../testcrypto.sh ed448; then
+ supported=1
+fi
+
+[ "$supported" -eq 1 ] || exit 1
diff --git a/bin/tests/system/eddsa/setup.sh b/bin/tests/system/eddsa/setup.sh
new file mode 100644
index 0000000..a0d95a9
--- /dev/null
+++ b/bin/tests/system/eddsa/setup.sh
@@ -0,0 +1,41 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+if $SHELL ../testcrypto.sh ed25519; then
+ echo "yes" > ed25519-supported.file
+fi
+
+if $SHELL ../testcrypto.sh ed448; then
+ echo "yes" > ed448-supported.file
+fi
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+
+(
+ cd ns1
+ $SHELL sign.sh
+)
+(
+ cd ns2
+ $SHELL sign.sh
+)
+(
+ cd ns3
+ $SHELL sign.sh
+)
diff --git a/bin/tests/system/eddsa/tests.sh b/bin/tests/system/eddsa/tests.sh
new file mode 100644
index 0000000..4fe0a0c
--- /dev/null
+++ b/bin/tests/system/eddsa/tests.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+dig_with_opts() {
+ "$DIG" +tcp +noau +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
+}
+
+if [ -f ed25519-supported.file ]; then
+ # Check the example. domain
+ n=$((n+1))
+ echo_i "checking that Ed25519 positive validation works ($n)"
+ ret=0
+ dig_with_opts . @10.53.0.1 soa > dig.out.ns1.test$n || ret=1
+ dig_with_opts . @10.53.0.2 soa > dig.out.ns2.test$n || ret=1
+ $PERL ../digcomp.pl dig.out.ns1.test$n dig.out.ns2.test$n || ret=1
+ grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ # Check test vectors (RFC 8080 + errata)
+ n=$((n+1))
+ echo_i "checking that Ed25519 test vectors match ($n)"
+ ret=0
+ grep 'oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jP' ns2/example.com.db.signed > /dev/null || ret=1
+ grep 'VrbpMngwcrqNAg==' ns2/example.com.db.signed > /dev/null || ret=1
+ grep 'zXQ0bkYgQTEFyfLyi9QoiY6D8ZdYo4wyUhVi' ns2/example.com.db.signed > /dev/null || ret=1
+ grep 'R0O7KuI5k2pcBg==' ns2/example.com.db.signed > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+else
+ echo_i "algorithm Ed25519 not supported, skipping vectors match test"
+fi
+
+n=$((n+1))
+ret=0
+if [ -f ed448-supported.file ]; then
+ # Check the example. domain
+ n=$((n+1))
+ echo_i "checking that Ed448 positive validation works ($n)"
+ ret=0
+ dig_with_opts . @10.53.0.1 soa > dig.out.ns1.test$n || ret=1
+ dig_with_opts . @10.53.0.3 soa > dig.out.ns3.test$n || ret=1
+ $PERL ../digcomp.pl dig.out.ns1.test$n dig.out.ns3.test$n || ret=1
+ grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ # Check test vectors (RFC 8080 + errata)
+ n=$((n+1))
+ echo_i "checking that Ed448 test vectors match ($n)"
+ ret=0
+ grep '3cPAHkmlnxcDHMyg7vFC34l0blBhuG1qpwLm' ns3/example.com.db.signed > /dev/null || ret=1
+ grep 'jInI8w1CMB29FkEAIJUA0amxWndkmnBZ6SKi' ns3/example.com.db.signed > /dev/null || ret=1
+ grep 'wZSAxGILn/NBtOXft0+Gj7FSvOKxE/07+4RQ' ns3/example.com.db.signed > /dev/null || ret=1
+ grep 'vE581N3Aj/JtIyaiYVdnYtyMWbSNyGEY2213' ns3/example.com.db.signed > /dev/null || ret=1
+ grep 'WKsJlwEA' ns3/example.com.db.signed > /dev/null || ret=1
+
+ grep 'E1/oLjSGIbmLny/4fcgM1z4oL6aqo+izT3ur' ns3/example.com.db.signed > /dev/null || ret=1
+ grep 'CyHyvEp4Sp8Syg1eI+lJ57CSnZqjJP41O/9l' ns3/example.com.db.signed > /dev/null || ret=1
+ grep '4m0AsQ4f7qI1gVnML8vWWiyW2KXhT9kuAICU' ns3/example.com.db.signed > /dev/null || ret=1
+ grep 'Sxv5OWbf81Rq7Yu60npabODB0QFPb/rkW3kU' ns3/example.com.db.signed > /dev/null || ret=1
+ grep 'ZmQ0YQUA' ns3/example.com.db.signed > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+else
+ echo_i "algorithm Ed448 not supported, skipping vectors match test"
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/eddsa/tests_sh_eddsa.py b/bin/tests/system/eddsa/tests_sh_eddsa.py
new file mode 100644
index 0000000..6646e36
--- /dev/null
+++ b/bin/tests/system/eddsa/tests_sh_eddsa.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_eddsa(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/ednscompliance/clean.sh b/bin/tests/system/ednscompliance/clean.sh
new file mode 100644
index 0000000..ad6176a
--- /dev/null
+++ b/bin/tests/system/ednscompliance/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out*
+rm -f ns*/named.lock
+rm -f ns*/named.conf
+rm -f ns*/named.run
+rm -f ns*/named.memstats
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/ednscompliance/ns1/named.conf.in b/bin/tests/system/ednscompliance/ns1/named.conf.in
new file mode 100644
index 0000000..1334c85
--- /dev/null
+++ b/bin/tests/system/ednscompliance/ns1/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/ednscompliance/ns1/root.db b/bin/tests/system/ednscompliance/ns1/root.db
new file mode 100644
index 0000000..f9bfbe9
--- /dev/null
+++ b/bin/tests/system/ednscompliance/ns1/root.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA marka.isc.org. a.root.servers.nil. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.6
diff --git a/bin/tests/system/ednscompliance/setup.sh b/bin/tests/system/ednscompliance/setup.sh
new file mode 100644
index 0000000..82240a7
--- /dev/null
+++ b/bin/tests/system/ednscompliance/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/ednscompliance/tests.sh b/bin/tests/system/ednscompliance/tests.sh
new file mode 100644
index 0000000..0c630f4
--- /dev/null
+++ b/bin/tests/system/ednscompliance/tests.sh
@@ -0,0 +1,114 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+norec -p ${PORT}"
+
+status=0
+n=0
+zone=.
+
+n=$((n + 1))
+echo_i "check +edns=100 sets version 100 ($n)"
+ret=0 reason=
+$DIG $DIGOPTS @10.53.0.1 +qr +edns=100 soa $zone > dig.out$n || ret=1
+grep "EDNS: version: 100," dig.out$n > /dev/null || { ret=1; reason="version"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+ret=0 reason=
+echo_i "check +ednsopt=100 adds option 100 ($n)"
+$DIG $DIGOPTS @10.53.0.1 +qr +ednsopt=100 soa $zone > dig.out$n || ret=1
+grep "; OPT=100" dig.out$n > /dev/null || { ret=1; reason="option"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check +ednsflags=0x80 sets flags to 0x0080 ($n)"
+ret=0 reason=
+$DIG $DIGOPTS @10.53.0.1 +qr +ednsflags=0x80 soa $zone > dig.out$n || ret=1
+grep "MBZ: 0x0080," dig.out$n > /dev/null || { ret=1; reason="flags"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "Unknown EDNS version ($n)"
+ret=0 reason=
+$DIG $DIGOPTS @10.53.0.1 +edns=100 +noednsnegotiation soa $zone > dig.out$n || ret=1
+grep "status: BADVERS," dig.out$n > /dev/null || { ret=1; reason="status"; }
+grep "EDNS: version: 0," dig.out$n > /dev/null || { ret=1; reason="version"; }
+grep "IN.SOA." dig.out$n > /dev/null && { ret=1; reason="soa"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "Unknown EDNS option ($n)"
+ret=0 reason=
+$DIG $DIGOPTS @10.53.0.1 +ednsopt=100 soa $zone > dig.out$n || ret=1
+grep "status: NOERROR," dig.out$n > /dev/null || { ret=1; reason="status"; }
+grep "EDNS: version: 0," dig.out$n > /dev/null || { ret=1; reason="version"; }
+grep "; OPT=100" dig.out$n > /dev/null && { ret=1; reason="option"; }
+grep "IN.SOA." dig.out$n > /dev/null || { ret=1; reason="nosoa"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "Unknown EDNS version + option ($n)"
+ret=0 reason=
+$DIG $DIGOPTS @10.53.0.1 +edns=100 +noednsneg +ednsopt=100 soa $zone > dig.out$n || ret=1
+grep "status: BADVERS," dig.out$n > /dev/null || { ret=1; reason="status"; }
+grep "EDNS: version: 0," dig.out$n > /dev/null || { ret=1; reason="version"; }
+grep "; OPT=100" dig.out$n > /dev/null && { ret=1; reason="option"; }
+grep "IN.SOA." dig.out$n > /dev/null && { ret=1; reason="soa"; }
+if [ $ret != 0 ]; then echo_i "failed: $reason"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "Unknown EDNS flag ($n)"
+ret=0 reason=
+$DIG $DIGOPTS @10.53.0.1 +ednsflags=0x80 soa $zone > dig.out$n || ret=1
+grep "status: NOERROR," dig.out$n > /dev/null || { ret=1; reason="status"; }
+grep "EDNS: version: 0," dig.out$n > /dev/null || { ret=1; reason="version"; }
+grep "EDNS:.*MBZ" dig.out$n > /dev/null > /dev/null && { ret=1; reason="mbz"; }
+grep ".IN.SOA." dig.out$n > /dev/null || { ret=1; reason="nosoa"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "Unknown EDNS version + flag ($n)"
+ret=0 reason=
+$DIG $DIGOPTS @10.53.0.1 +edns=100 +noednsneg +ednsflags=0x80 soa $zone > dig.out$n || ret=1
+grep "status: BADVERS," dig.out$n > /dev/null || { ret=1; reason="status"; }
+grep "EDNS: version: 0," dig.out$n > /dev/null || { ret=1; reason="version"; }
+grep "EDNS:.*MBZ" dig.out$n > /dev/null > /dev/null && { ret=1; reason="mbz"; }
+grep "IN.SOA." dig.out$n > /dev/null && { ret=1; reason="soa"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "DiG's EDNS negotiation ($n)"
+ret=0 reason=
+$DIG $DIGOPTS @10.53.0.1 +edns=100 soa $zone > dig.out$n || ret=1
+grep "status: NOERROR," dig.out$n > /dev/null || { ret=1; reason="status"; }
+grep "EDNS: version: 0," dig.out$n > /dev/null || { ret=1; reason="version"; }
+grep "IN.SOA." dig.out$n > /dev/null || { ret=1; reason="soa"; }
+if [ $ret != 0 ]; then echo_i "failed $reason"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/ednscompliance/tests_sh_ednscompliance.py b/bin/tests/system/ednscompliance/tests_sh_ednscompliance.py
new file mode 100644
index 0000000..8eea611
--- /dev/null
+++ b/bin/tests/system/ednscompliance/tests_sh_ednscompliance.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_ednscompliance(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/emptyzones/clean.sh b/bin/tests/system/emptyzones/clean.sh
new file mode 100644
index 0000000..c7ff161
--- /dev/null
+++ b/bin/tests/system/emptyzones/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns1/named.conf
+rm -f ns*/named.lock
+rm -f ns*/named.run
+rm -f ns*/named.memstats
+rm -f dig.out.test*
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/emptyzones/ns1/empty.db b/bin/tests/system/emptyzones/ns1/empty.db
new file mode 100644
index 0000000..70dbcaf
--- /dev/null
+++ b/bin/tests/system/emptyzones/ns1/empty.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 0 0 0 0 0
+@ 0 NS .
diff --git a/bin/tests/system/emptyzones/ns1/named1.conf.in b/bin/tests/system/emptyzones/ns1/named1.conf.in
new file mode 100644
index 0000000..4aad843
--- /dev/null
+++ b/bin/tests/system/emptyzones/ns1/named1.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ algorithm @DEFAULT_HMAC@;
+ secret "1234abcd8765";
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 yes;
+ dnssec-validation no;
+ deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; }
+ except-from { "example.org"; };
+ deny-answer-aliases { "example.org"; }
+ except-from { "goodcname.example.net";
+ "gooddname.example.net"; };
+ allow-query {!10.53.0.8; any; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+include "rfc1918.zones";
diff --git a/bin/tests/system/emptyzones/ns1/named2.conf.in b/bin/tests/system/emptyzones/ns1/named2.conf.in
new file mode 100644
index 0000000..89fe2b4
--- /dev/null
+++ b/bin/tests/system/emptyzones/ns1/named2.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ algorithm @DEFAULT_HMAC@;
+ secret "1234abcd8765";
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 yes;
+ dnssec-validation no;
+ deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; }
+ except-from { "example.org"; };
+ deny-answer-aliases { "example.org"; }
+ except-from { "goodcname.example.net";
+ "gooddname.example.net"; };
+ allow-query {!10.53.0.8; any; };
+ allow-transfer { none; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "1.10.in-addr.arpa" {
+ type primary; file "empty.db";
+};
diff --git a/bin/tests/system/emptyzones/ns1/rfc1918.zones b/bin/tests/system/emptyzones/ns1/rfc1918.zones
new file mode 100644
index 0000000..07858f9
--- /dev/null
+++ b/bin/tests/system/emptyzones/ns1/rfc1918.zones
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "10.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "16.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "17.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "18.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "19.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "20.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "21.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "22.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "23.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "24.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "25.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "26.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "27.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "28.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "29.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "30.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "31.172.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+zone "168.192.IN-ADDR.ARPA" { type primary; file "empty.db"; };
+
diff --git a/bin/tests/system/emptyzones/ns1/root.hint b/bin/tests/system/emptyzones/ns1/root.hint
new file mode 100644
index 0000000..993227d
--- /dev/null
+++ b/bin/tests/system/emptyzones/ns1/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.2
diff --git a/bin/tests/system/emptyzones/setup.sh b/bin/tests/system/emptyzones/setup.sh
new file mode 100644
index 0000000..935067f
--- /dev/null
+++ b/bin/tests/system/emptyzones/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+copy_setports ns1/named1.conf.in ns1/named.conf
diff --git a/bin/tests/system/emptyzones/tests.sh b/bin/tests/system/emptyzones/tests.sh
new file mode 100644
index 0000000..c968d51
--- /dev/null
+++ b/bin/tests/system/emptyzones/tests.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+n=$((n + 1))
+echo_i "check that switching to automatic empty zones works ($n)"
+ret=0
+rndc_reload ns1 10.53.0.1
+
+copy_setports ns1/named2.conf.in ns1/named.conf
+$RNDCCMD 10.53.0.1 reload > /dev/null || ret=1
+sleep 5
+
+$DIG $DIGOPTS +vc version.bind txt ch @10.53.0.1 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that allow-transfer { none; } works ($n)"
+ret=0
+$DIG $DIGOPTS axfr 10.in-addr.arpa @10.53.0.1 +all > dig.out.test$n || ret=1
+grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/emptyzones/tests_sh_emptyzones.py b/bin/tests/system/emptyzones/tests_sh_emptyzones.py
new file mode 100644
index 0000000..66dc9dc
--- /dev/null
+++ b/bin/tests/system/emptyzones/tests_sh_emptyzones.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_emptyzones(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/enginepkcs11/2037-pk11_numbits-crash-test.pkt b/bin/tests/system/enginepkcs11/2037-pk11_numbits-crash-test.pkt
new file mode 100644
index 0000000..b9c5a32
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/2037-pk11_numbits-crash-test.pkt
@@ -0,0 +1,30 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+edda 2800 0001 0000 0001 0000 0972 7361
+7368 6132 3536 0765 7861 6d70 6c65 0000
+0600 01c0 0c00 3000 0100 0001 2c01 0801
+0003 0803 0100 0100 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 00
diff --git a/bin/tests/system/enginepkcs11/clean.sh b/bin/tests/system/enginepkcs11/clean.sh
new file mode 100644
index 0000000..789666e
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/clean.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+rm -f dig.out.*
+rm -f dsset-*
+rm -f pin
+rm -f keyfromlabel.err.* keyfromlabel.out.*
+rm -f pkcs11-tool.err.* pkcs11-tool.out.*
+rm -f signer.out.*
+rm -f ns1/*.example.db ns1/*.example.db.signed
+rm -f ns1/*.kskid1 ns1/*.kskid2 ns1/*.zskid1 ns1/*.zskid2
+rm -f ns1/dig.out.*
+rm -f ns1/K*
+rm -f ns1/named.conf ns1/named.run ns1/named.memstats
+rm -f ns1/update.cmd.*
+rm -f ns1/update.log.*
+rm -f ns1/verify.out.*
+rm -f ns1/zone.*.signed.jnl ns1/zone.*.signed.jbk
+
+softhsm2-util --delete-token --token "softhsm2-enginepkcs11" >/dev/null 2>&1 || echo_i "softhsm2-enginepkcs11 token not found for cleaning"
diff --git a/bin/tests/system/enginepkcs11/ns1/named.args b/bin/tests/system/enginepkcs11/ns1/named.args
new file mode 100644
index 0000000..0568fa9
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/ns1/named.args
@@ -0,0 +1 @@
+-E pkcs11 -D enginepkcs11-ns1 -X named.lock -m record -c named.conf -d 99 -U 4 -T maxcachesize=2097152
diff --git a/bin/tests/system/enginepkcs11/ns1/named.conf.in b/bin/tests/system/enginepkcs11/ns1/named.conf.in
new file mode 100644
index 0000000..985974d
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/ns1/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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;
+ dnssec-validation no;
+ notify no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/enginepkcs11/ns1/template.db.in b/bin/tests/system/enginepkcs11/ns1/template.db.in
new file mode 100644
index 0000000..7941903
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/ns1/template.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "test"
+
diff --git a/bin/tests/system/enginepkcs11/prereq.sh b/bin/tests/system/enginepkcs11/prereq.sh
new file mode 100644
index 0000000..296452b
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/prereq.sh
@@ -0,0 +1,21 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+if [ -n "${SOFTHSM2_MODULE}" ] && command -v softhsm2-util >/dev/null; then
+ exit 0
+fi
+
+echo_i "skip: softhsm2-util not available"
+exit 255
diff --git a/bin/tests/system/enginepkcs11/setup.sh b/bin/tests/system/enginepkcs11/setup.sh
new file mode 100644
index 0000000..49988ad
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/setup.sh
@@ -0,0 +1,125 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+softhsm2-util --init-token --free --pin 1234 --so-pin 1234 --label "softhsm2-enginepkcs11" | awk '/^The token has been initialized and is reassigned to slot/ { print $NF }'
+
+printf '%s' "${HSMPIN:-1234}" > pin
+PWD=$(pwd)
+
+copy_setports ns1/named.conf.in ns1/named.conf
+
+keygen() {
+ type="$1"
+ bits="$2"
+ zone="$3"
+ id="$4"
+
+ label="${id}-${zone}"
+ p11id=$(echo "${label}" | openssl sha1 -r | awk '{print $1}')
+ pkcs11-tool --module $SOFTHSM2_MODULE --token-label "softhsm2-enginepkcs11" -l -k --key-type $type:$bits --label "${label}" --id "${p11id}" --pin $(cat $PWD/pin) > pkcs11-tool.out.$zone.$id 2> pkcs11-tool.err.$zone.$id || return 1
+}
+
+keyfromlabel() {
+ alg="$1"
+ zone="$2"
+ id="$3"
+ dir="$4"
+ shift 4
+
+ $KEYFRLAB -K $dir -E pkcs11 -a $alg -l "token=softhsm2-enginepkcs11;object=${id}-${zone};pin-source=$PWD/pin" "$@" $zone >> keyfromlabel.out.$zone.$id 2> keyfromlabel.err.$zone.$id || return 1
+ cat keyfromlabel.out.$zone.$id
+}
+
+
+# Setup ns1.
+dir="ns1"
+infile="${dir}/template.db.in"
+for algtypebits in rsasha256:rsa:2048 rsasha512:rsa:2048 \
+ ecdsap256sha256:EC:prime256v1 ecdsap384sha384:EC:prime384v1
+ # Edwards curves are not yet supported by OpenSC
+ # ed25519:EC:edwards25519 ed448:EC:edwards448
+do
+ alg=$(echo "$algtypebits" | cut -f 1 -d :)
+ type=$(echo "$algtypebits" | cut -f 2 -d :)
+ bits=$(echo "$algtypebits" | cut -f 3 -d :)
+
+ if $SHELL ../testcrypto.sh $alg; then
+ zone="$alg.example"
+ zonefile="zone.$alg.example.db"
+ ret=0
+
+ echo_i "Generate keys $alg $type:$bits for zone $zone"
+ keygen $type $bits $zone enginepkcs11-zsk || ret=1
+ keygen $type $bits $zone enginepkcs11-ksk || ret=1
+ test "$ret" -eq 0 || exit 1
+
+ echo_i "Get ZSK $alg $zone $type:$bits"
+ zsk1=$(keyfromlabel $alg $zone enginepkcs11-zsk $dir)
+ test -z "$zsk1" && exit 1
+
+ echo_i "Get KSK $alg $zone $type:$bits"
+ ksk1=$(keyfromlabel $alg $zone enginepkcs11-ksk $dir -f KSK)
+ test -z "$ksk1" && exit 1
+
+ (
+ cd $dir
+ zskid1=$(keyfile_to_key_id $zsk1)
+ kskid1=$(keyfile_to_key_id $ksk1)
+ echo "$zskid1" > $zone.zskid1
+ echo "$kskid1" > $zone.kskid1
+ )
+
+ echo_i "Sign zone with $ksk1 $zsk1"
+ cat "$infile" "${dir}/${ksk1}.key" "${dir}/${zsk1}.key" > "${dir}/${zonefile}"
+ $SIGNER -K $dir -E pkcs11 -S -a -g -O full -o "$zone" "${dir}/${zonefile}" > signer.out.$zone || ret=1
+ test "$ret" -eq 0 || exit 1
+
+ echo_i "Generate successor keys $alg $type:$bits for zone $zone"
+ keygen $type $bits $zone enginepkcs11-zsk2 || ret=1
+ keygen $type $bits $zone enginepkcs11-ksk2 || ret=1
+ test "$ret" -eq 0 || exit 1
+
+ echo_i "Get ZSK $alg $id-$zone $type:$bits"
+ zsk2=$(keyfromlabel $alg $zone enginepkcs11-zsk2 $dir)
+ test -z "$zsk2" && exit 1
+
+ echo_i "Get KSK $alg $id-$zone $type:$bits"
+ ksk2=$(keyfromlabel $alg $zone enginepkcs11-ksk2 $dir -f KSK)
+ test -z "$ksk2" && exit 1
+
+ (
+ cd $dir
+ zskid2=$(keyfile_to_key_id $zsk2)
+ kskid2=$(keyfile_to_key_id $ksk2)
+ echo "$zskid2" > $zone.zskid2
+ echo "$kskid2" > $zone.kskid2
+ cp "${zsk2}.key" "${zsk2}.zsk2"
+ cp "${ksk2}.key" "${ksk2}.ksk2"
+ )
+
+ echo_i "Add zone $zone to named.conf"
+ cat >> "${dir}/named.conf" <<EOF
+zone "$zone" {
+ type primary;
+ file "${zonefile}.signed";
+ allow-update { any; };
+};
+
+EOF
+ fi
+done
diff --git a/bin/tests/system/enginepkcs11/tests.sh b/bin/tests/system/enginepkcs11/tests.sh
new file mode 100644
index 0000000..f8f0317
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/tests.sh
@@ -0,0 +1,176 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+PWD=$(pwd)
+
+status=0
+ret=0
+n=0
+
+dig_with_opts() (
+ $DIG +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
+)
+
+# Perform tests inside ns1 dir
+cd ns1
+
+for algtypebits in rsasha256:rsa:2048 rsasha512:rsa:2048 \
+ ecdsap256sha256:EC:prime256v1 ecdsap384sha384:EC:prime384v1
+ # Edwards curves are not yet supported by OpenSC
+ # ed25519:EC:edwards25519 ed448:EC:edwards448
+do
+ alg=$(echo "$algtypebits" | cut -f 1 -d :)
+ type=$(echo "$algtypebits" | cut -f 2 -d :)
+ bits=$(echo "$algtypebits" | cut -f 3 -d :)
+ zone="${alg}.example"
+ zonefile="zone.${zone}.db.signed"
+
+ if [ ! -f $zonefile ]; then
+ echo_i "skipping test for ${alg}:${type}:${bits}, no signed zone file ${zonefile}"
+ continue
+ fi
+
+ # Basic checks if setup was successful.
+ n=$((n+1))
+ ret=0
+ echo_i "Test key generation was successful for $zone ($n)"
+ count=$(ls K*.key | grep "K${zone}" | wc -l)
+ test "$count" -eq 4 || ret=1
+ test "$ret" -eq 0 || echo_i "failed (expected 4 keys, got $count)"
+ status=$((status+ret))
+
+ n=$((n+1))
+ ret=0
+ echo_i "Test zone signing was successful for $zone ($n)"
+ $VERIFY -z -o $zone "${zonefile}" > verify.out.$zone.$n 2>&1 || ret=1
+ test "$ret" -eq 0 || echo_i "failed (dnssec-verify failed)"
+ status=$((status+ret))
+
+ # Test inline signing with keys stored in engine.
+ zskid1=$(cat "${zone}.zskid1")
+ zskid2=$(cat "${zone}.zskid2")
+
+ n=$((n+1))
+ ret=0
+ echo_i "Test inline signing for $zone ($n)"
+ dig_with_opts "$zone" @10.53.0.1 SOA > dig.out.soa.$zone.$n || ret=1
+ awk '$4 == "RRSIG" { print $11 }' dig.out.soa.$zone.$n > dig.out.keyids.$zone.$n || return 1
+ numsigs=$(cat dig.out.keyids.$zone.$n | wc -l)
+ test $numsigs -eq 1 || return 1
+ grep -w "$zskid1" dig.out.keyids.$zone.$n > /dev/null || return 1
+ test "$ret" -eq 0 || echo_i "failed (SOA RRset not signed with key $zskid1)"
+ status=$((status+ret))
+
+
+ n=$((n+1))
+ ret=0
+ echo_i "Dynamically update $zone, add new zsk ($n)"
+ zsk2=$(grep -v ';' K${zone}.*.zsk2)
+ cat > "update.cmd.zsk.$zone.$n" <<EOF
+server 10.53.0.1 $PORT
+ttl 300
+zone $zone
+update add $zsk2
+send
+EOF
+
+ $NSUPDATE -v > "update.log.zsk.$zone.$n" < "update.cmd.zsk.$zone.$n" || ret=1
+ test "$ret" -eq 0 || echo_i "failed (update failed)"
+ status=$((status+ret))
+
+ n=$((n+1))
+ ret=0
+ echo_i "Test DNSKEY response for $zone after inline signing ($n)"
+ _dig_dnskey() (
+ dig_with_opts "$zone" @10.53.0.1 DNSKEY > dig.out.dnskey.$zone.$n || return 1
+ count=$(awk 'BEGIN { count = 0 } $4 == "DNSKEY" { count++ } END {print count}' dig.out.dnskey.$zone.$n)
+ test $count -eq 3
+ )
+ retry_quiet 10 _dig_dnskey || ret=1
+ test "$ret" -eq 0 || echo_i "failed (expected 3 DNSKEY records)"
+ status=$((status+ret))
+
+ n=$((n+1))
+ ret=0
+ echo_i "Test SOA response for $zone after inline signing ($n)"
+ _dig_soa() (
+ dig_with_opts "$zone" @10.53.0.1 SOA > dig.out.soa.$zone.$n || return 1
+ awk '$4 == "RRSIG" { print $11 }' dig.out.soa.$zone.$n > dig.out.keyids.$zone.$n || return 1
+ numsigs=$(cat dig.out.keyids.$zone.$n | wc -l)
+ test $numsigs -eq 2 || return 1
+ grep -w "$zskid1" dig.out.keyids.$zone.$n > /dev/null || return 1
+ grep -w "$zskid2" dig.out.keyids.$zone.$n > /dev/null || return 1
+ return 0
+ )
+ retry_quiet 10 _dig_soa || ret=1
+ test "$ret" -eq 0 || echo_i "failed (expected 2 SOA RRSIG records)"
+ status=$((status+ret))
+
+ # Test inline signing with keys stored in engine (key signing).
+ kskid1=$(cat "${zone}.kskid1")
+ kskid2=$(cat "${zone}.kskid2")
+
+ n=$((n+1))
+ ret=0
+ echo_i "Dynamically update $zone, add new ksk ($n)"
+ ksk2=$(grep -v ';' K${zone}.*.ksk2)
+ cat > "update.cmd.ksk.$zone.$n" <<EOF
+server 10.53.0.1 $PORT
+ttl 300
+zone $zone
+update add $ksk2
+send
+EOF
+
+ $NSUPDATE -v > "update.log.ksk.$zone.$n" < "update.cmd.ksk.$zone.$n" || ret=1
+ test "$ret" -eq 0 || echo_i "failed (update failed)"
+ status=$((status+ret))
+
+ n=$((n+1))
+ ret=0
+ echo_i "Test DNSKEY response for $zone after inline signing (key signing) ($n)"
+ _dig_dnskey_ksk() (
+ dig_with_opts "$zone" @10.53.0.1 DNSKEY > dig.out.dnskey.$zone.$n || return 1
+ count=$(awk 'BEGIN { count = 0 } $4 == "DNSKEY" { count++ } END {print count}' dig.out.dnskey.$zone.$n)
+ test $count -eq 4 || return 1
+ awk '$4 == "RRSIG" { print $11 }' dig.out.dnskey.$zone.$n > dig.out.keyids.$zone.$n || return 1
+ numsigs=$(cat dig.out.keyids.$zone.$n | wc -l)
+ test $numsigs -eq 2 || return 1
+ grep -w "$kskid1" dig.out.keyids.$zone.$n > /dev/null || return 1
+ grep -w "$kskid2" dig.out.keyids.$zone.$n > /dev/null || return 1
+ return 0
+ )
+ retry_quiet 10 _dig_dnskey_ksk || ret=1
+ test "$ret" -eq 0 || echo_i "failed (expected 4 DNSKEY records, 2 KSK signatures)"
+ status=$((status+ret))
+
+done
+
+# Go back to main test dir.
+cd ..
+
+n=$((n+1))
+ret=0
+echo_i "Checking for assertion failure in pk11_numbits()"
+$PERL ../packet.pl -a "10.53.0.1" -p "$PORT" -t udp 2037-pk11_numbits-crash-test.pkt
+dig_with_opts @10.53.0.1 version.bind. CH TXT > dig.out.pk11_numbits || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/enginepkcs11/tests_sh_enginepkcs11.py b/bin/tests/system/enginepkcs11/tests_sh_enginepkcs11.py
new file mode 100644
index 0000000..334142d
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/tests_sh_enginepkcs11.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_enginepkcs11(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/feature-test.c b/bin/tests/system/feature-test.c
new file mode 100644
index 0000000..e6b1eb1
--- /dev/null
+++ b/bin/tests/system/feature-test.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/md.h>
+#include <isc/net.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+#include <dns/edns.h>
+
+static void
+usage(void) {
+ fprintf(stderr, "usage: feature-test <arg>\n");
+ fprintf(stderr, "args:\n");
+ fprintf(stderr, "\t--edns-version\n");
+ fprintf(stderr, "\t--enable-dnsrps\n");
+ fprintf(stderr, "\t--enable-dnstap\n");
+ fprintf(stderr, "\t--enable-querytrace\n");
+ fprintf(stderr, "\t--gethostname\n");
+ fprintf(stderr, "\t--gssapi\n");
+ fprintf(stderr, "\t--have-geoip2\n");
+ fprintf(stderr, "\t--have-json-c\n");
+ fprintf(stderr, "\t--have-libxml2\n");
+ fprintf(stderr, "\t--ipv6only=no\n");
+ fprintf(stderr, "\t--md5\n");
+ fprintf(stderr, "\t--tsan\n");
+ fprintf(stderr, "\t--with-dlz-filesystem\n");
+ fprintf(stderr, "\t--with-libidn2\n");
+ fprintf(stderr, "\t--with-lmdb\n");
+ fprintf(stderr, "\t--with-libnghttp2\n");
+ fprintf(stderr, "\t--with-zlib\n");
+}
+
+int
+main(int argc, char **argv) {
+ if (argc != 2) {
+ usage();
+ return (1);
+ }
+
+ if (strcmp(argv[1], "--edns-version") == 0) {
+#ifdef DNS_EDNS_VERSION
+ printf("%d\n", DNS_EDNS_VERSION);
+#else /* ifdef DNS_EDNS_VERSION */
+ printf("0\n");
+#endif /* ifdef DNS_EDNS_VERSION */
+ return (0);
+ }
+
+ if (strcmp(argv[1], "--enable-dnsrps") == 0) {
+#ifdef USE_DNSRPS
+ return (0);
+#else /* ifdef USE_DNSRPS */
+ return (1);
+#endif /* ifdef USE_DNSRPS */
+ }
+
+ if (strcmp(argv[1], "--enable-dnstap") == 0) {
+#ifdef HAVE_DNSTAP
+ return (0);
+#else /* ifdef HAVE_DNSTAP */
+ return (1);
+#endif /* ifdef HAVE_DNSTAP */
+ }
+
+ if (strcmp(argv[1], "--enable-querytrace") == 0) {
+#ifdef WANT_QUERYTRACE
+ return (0);
+#else /* ifdef WANT_QUERYTRACE */
+ return (1);
+#endif /* ifdef WANT_QUERYTRACE */
+ }
+
+ if (strcmp(argv[1], "--gethostname") == 0) {
+ char hostname[_POSIX_HOST_NAME_MAX + 1];
+ int n;
+
+ n = gethostname(hostname, sizeof(hostname));
+ if (n == -1) {
+ perror("gethostname");
+ return (1);
+ }
+ fprintf(stdout, "%s\n", hostname);
+ return (0);
+ }
+
+ if (strcmp(argv[1], "--gssapi") == 0) {
+#if HAVE_GSSAPI
+ return (0);
+#else /* HAVE_GSSAPI */
+ return (1);
+#endif /* HAVE_GSSAPI */
+ }
+
+ if (strcmp(argv[1], "--have-geoip2") == 0) {
+#ifdef HAVE_GEOIP2
+ return (0);
+#else /* ifdef HAVE_GEOIP2 */
+ return (1);
+#endif /* ifdef HAVE_GEOIP2 */
+ }
+
+ if (strcmp(argv[1], "--have-json-c") == 0) {
+#ifdef HAVE_JSON_C
+ return (0);
+#else /* ifdef HAVE_JSON_C */
+ return (1);
+#endif /* ifdef HAVE_JSON_C */
+ }
+
+ if (strcmp(argv[1], "--have-libxml2") == 0) {
+#ifdef HAVE_LIBXML2
+ return (0);
+#else /* ifdef HAVE_LIBXML2 */
+ return (1);
+#endif /* ifdef HAVE_LIBXML2 */
+ }
+
+ if (strcmp(argv[1], "--tsan") == 0) {
+#if defined(__has_feature)
+#if __has_feature(thread_sanitizer)
+ return (0);
+#endif
+#endif
+#if __SANITIZE_THREAD__
+ return (0);
+#else
+ return (1);
+#endif
+ }
+
+ if (strcmp(argv[1], "--md5") == 0) {
+ unsigned char digest[ISC_MAX_MD_SIZE];
+ const unsigned char test[] = "test";
+ unsigned int size = sizeof(digest);
+
+ if (isc_md(ISC_MD_MD5, test, sizeof(test), digest, &size) ==
+ ISC_R_SUCCESS)
+ {
+ return (0);
+ } else {
+ return (1);
+ }
+ }
+
+ if (strcmp(argv[1], "--ipv6only=no") == 0) {
+#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
+ int s;
+ int n = -1;
+ int v6only = -1;
+ socklen_t len = sizeof(v6only);
+
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s >= 0) {
+ n = getsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+ (void *)&v6only, &len);
+ close(s);
+ }
+ return ((n == 0 && v6only == 0) ? 0 : 1);
+#else /* defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) */
+ return (1);
+#endif /* defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) */
+ }
+
+ if (strcmp(argv[1], "--with-dlz-filesystem") == 0) {
+#ifdef DLZ_FILESYSTEM
+ return (0);
+#else /* ifdef DLZ_FILESYSTEM */
+ return (1);
+#endif /* ifdef DLZ_FILESYSTEM */
+ }
+
+ if (strcmp(argv[1], "--with-libidn2") == 0) {
+#ifdef HAVE_LIBIDN2
+ return (0);
+#else /* ifdef HAVE_LIBIDN2 */
+ return (1);
+#endif /* ifdef HAVE_LIBIDN2 */
+ }
+
+ if (strcmp(argv[1], "--with-lmdb") == 0) {
+#ifdef HAVE_LMDB
+ return (0);
+#else /* ifdef HAVE_LMDB */
+ return (1);
+#endif /* ifdef HAVE_LMDB */
+ }
+
+ if (strcmp(argv[1], "--with-libnghttp2") == 0) {
+#ifdef HAVE_LIBNGHTTP2
+ return (0);
+#else /* ifdef HAVE_LIBNGHTTP2 */
+ return (1);
+#endif /* ifdef HAVE_LIBNGHTTP2 */
+ }
+
+ if (strcmp(argv[1], "--with-zlib") == 0) {
+#ifdef HAVE_ZLIB
+ return (0);
+#else /* ifdef HAVE_ZLIB */
+ return (1);
+#endif /* ifdef HAVE_ZLIB */
+ }
+
+ fprintf(stderr, "unknown arg: %s\n", argv[1]);
+ usage();
+ return (1);
+}
diff --git a/bin/tests/system/fetchlimit/ans4/ans.pl b/bin/tests/system/fetchlimit/ans4/ans.pl
new file mode 100644
index 0000000..f44cf8b
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ans4/ans.pl
@@ -0,0 +1,90 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Don't respond if the "norespond" file exists; otherwise respond to
+# any A or AAAA query.
+#
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.4",
+ LocalPort => $localport, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+for (;;) {
+ $sock->recv($buf, 512);
+
+ print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
+
+ my $packet;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ print "REQUEST:\n";
+ $packet->print;
+
+ $packet->header->qr(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+
+ my $donotrespond = 0;
+
+ if (-e 'norespond') {
+ $donotrespond = 1;
+ } else {
+ $packet->header->aa(1);
+ if ($qtype eq "A") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 300 A 192.0.2.1"));
+ } elsif ($qtype eq "AAAA") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 300 AAAA 2001:db8:beef::1"));
+ }
+ }
+
+ if ($donotrespond == 0) {
+ if (index($qname, "latency") == 0) {
+ # 50ms latency
+ select(undef, undef, undef, 0.05);
+ }
+ $sock->send($packet->data);
+ print "RESPONSE:\n";
+ $packet->print;
+ print "\n";
+ }
+}
diff --git a/bin/tests/system/fetchlimit/clean.sh b/bin/tests/system/fetchlimit/clean.sh
new file mode 100644
index 0000000..20bbd60
--- /dev/null
+++ b/bin/tests/system/fetchlimit/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.conf */named.memstats */ans.run */named.recursing */named.run */named.run.prev
+rm -f ans4/norespond
+rm -f burst.input.*
+rm -f dig.out*
+rm -f wait_for_message.*
+rm -f ns*/managed-keys.bind*
+rm -f ns3/named.stats ns3/named.stats.prev ns3/named_dump.db
+rm -f ns5/named.stats ns5/named.stats.prev
diff --git a/bin/tests/system/fetchlimit/ns1/named.conf.in b/bin/tests/system/fetchlimit/ns1/named.conf.in
new file mode 100644
index 0000000..9725d01
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns1/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example.info." {
+ type primary;
+ file "example-info.db";
+};
diff --git a/bin/tests/system/fetchlimit/ns1/root.db b/bin/tests/system/fetchlimit/ns1/root.db
new file mode 100644
index 0000000..17780d1
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/fetchlimit/ns2/example.db b/bin/tests/system/fetchlimit/ns2/example.db
new file mode 100644
index 0000000..5bf9999
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns2/example.db
@@ -0,0 +1,37 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example NS ns2.example.
+ns2.example. A 10.53.0.2
+
+a.example. A 10.0.0.1
+ MX 10 mail.example.
+
+mail.example. A 10.0.0.2
+
+lamesub.example. NS ns4.example.
+ns4.example. A 10.53.0.4
+
+0.example. A 10.53.1.0
+1.example. A 10.53.1.1
+2.example. A 10.53.1.2
+3.example. A 10.53.1.3
+4.example. A 10.53.1.4
+5.example. A 10.53.1.5
diff --git a/bin/tests/system/fetchlimit/ns2/named.conf.in b/bin/tests/system/fetchlimit/ns2/named.conf.in
new file mode 100644
index 0000000..1d57632
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns2/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/fetchlimit/ns3/named.args b/bin/tests/system/fetchlimit/ns3/named.args
new file mode 100644
index 0000000..d3488ce
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns3/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 1 -D fetchlimit-ns3 -X named.lock -g -T maxcachesize=2097152
diff --git a/bin/tests/system/fetchlimit/ns3/named1.conf.in b/bin/tests/system/fetchlimit/ns3/named1.conf.in
new file mode 100644
index 0000000..e493d8a
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns3/named1.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ fetches-per-server 400;
+};
+
+server 10.53.0.4 {
+ edns no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/fetchlimit/ns3/named2.conf.in b/bin/tests/system/fetchlimit/ns3/named2.conf.in
new file mode 100644
index 0000000..2d0dcef
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns3/named2.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ fetches-per-zone 40;
+};
+
+server 10.53.0.4 {
+ edns no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/fetchlimit/ns3/named3.conf.in b/bin/tests/system/fetchlimit/ns3/named3.conf.in
new file mode 100644
index 0000000..f056fbb
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns3/named3.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ recursive-clients 400;
+};
+
+server 10.53.0.4 {
+ edns no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/fetchlimit/ns3/root.hint b/bin/tests/system/fetchlimit/ns3/root.hint
new file mode 100644
index 0000000..e0f186c
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns3/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.1
diff --git a/bin/tests/system/fetchlimit/ns5/named1.conf.in b/bin/tests/system/fetchlimit/ns5/named1.conf.in
new file mode 100644
index 0000000..d3c62c2
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns5/named1.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ clients-per-query 5;
+ max-clients-per-query 10;
+};
+
+server 10.53.0.4 {
+ edns no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/fetchlimit/ns5/named2.conf.in b/bin/tests/system/fetchlimit/ns5/named2.conf.in
new file mode 100644
index 0000000..cb33d30
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns5/named2.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ stale-answer-enable yes;
+ stale-cache-enable yes;
+ stale-answer-client-timeout 1800;
+ clients-per-query 5;
+ max-clients-per-query 10;
+};
+
+server 10.53.0.4 {
+ edns no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/fetchlimit/ns5/root.hint b/bin/tests/system/fetchlimit/ns5/root.hint
new file mode 100644
index 0000000..e0f186c
--- /dev/null
+++ b/bin/tests/system/fetchlimit/ns5/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.1
diff --git a/bin/tests/system/fetchlimit/setup.sh b/bin/tests/system/fetchlimit/setup.sh
new file mode 100644
index 0000000..f98749b
--- /dev/null
+++ b/bin/tests/system/fetchlimit/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named1.conf.in ns3/named.conf
+copy_setports ns5/named1.conf.in ns5/named.conf
diff --git a/bin/tests/system/fetchlimit/tests.sh b/bin/tests/system/fetchlimit/tests.sh
new file mode 100644
index 0000000..a16659d
--- /dev/null
+++ b/bin/tests/system/fetchlimit/tests.sh
@@ -0,0 +1,325 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGCMD="$DIG @10.53.0.3 -p ${PORT} +tcp +tries=1 +time=1"
+
+rndccmd() (
+ "$RNDC" -c ../common/rndc.conf -p "${CONTROLPORT}" -s "$@"
+)
+
+burst() {
+ server=${1}
+ num=${4:-20}
+ rm -f burst.input.$$
+ while [ $num -gt 0 ]; do
+ num=$((num-1))
+ if [ "${5}" = "dup" ]; then
+ # burst with duplicate queries
+ echo "${2}${3}.lamesub.example A" >> burst.input.$$
+ else
+ # burst with unique queries
+ echo "${num}${2}${3}.lamesub.example A" >> burst.input.$$
+ fi
+ done
+ $PERL ../ditch.pl -p ${PORT} -s ${server} burst.input.$$
+ rm -f burst.input.$$
+}
+
+stat() {
+ clients=$(rndccmd ${1} status | grep "recursive clients" |
+ sed 's;.*: \([^/][^/]*\)/.*;\1;')
+ echo_i "clients: $clients"
+ [ "$clients" = "" ] && return 1
+ [ "$clients" -ge $2 ] || return 1
+ [ "$clients" -le $3 ] || return 1
+ return 0
+}
+
+_wait_for_message() (
+ nextpartpeek "$1" > wait_for_message.$n
+ grep -F "$2" wait_for_message.$n >/dev/null
+)
+
+wait_for_message() (
+ retry_quiet 20 _wait_for_message "$@"
+)
+
+n=0
+status=0
+
+n=$((n + 1))
+echo_i "checking recursing clients are dropped at the per-server limit ($n)"
+ret=0
+# make the server lame and restart
+rndccmd 10.53.0.3 flush
+touch ans4/norespond
+for try in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
+ burst 10.53.0.3 a $try
+ # fetches-per-server is at 400, but at 20qps against a lame server,
+ # we'll reach 200 at the tenth second, and the quota should have been
+ # tuned to less than that by then.
+ [ $try -le 5 ] && low=$((try*10))
+ stat 10.53.0.3 20 200 || ret=1
+ [ $ret -eq 1 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n + 1))
+echo_i "dumping ADB data ($n)"
+ret=0
+rndccmd 10.53.0.3 dumpdb -adb
+info=$(grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/\1 \2/')
+echo_i $info
+set -- $info
+quota=$4
+[ ${4:-200} -lt 200 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n + 1))
+echo_i "checking servfail statistics ($n)"
+ret=0
+rm -f ns3/named.stats
+rndccmd 10.53.0.3 stats
+for try in 1 2 3 4 5; do
+ [ -f ns3/named.stats ] && break
+ sleep 1
+done
+sspill=$(grep 'spilled due to server' ns3/named.stats | sed 's/\([0-9][0-9]*\) spilled.*/\1/')
+[ -z "$sspill" ] && sspill=0
+fails=$(grep 'queries resulted in SERVFAIL' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.*/\1/')
+[ -z "$fails" ] && fails=0
+[ "$fails" -ge "$sspill" ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n + 1))
+echo_i "checking lame server recovery ($n)"
+ret=0
+test -f ans4/norespond && rm -f ans4/norespond
+for try in 1 2 3 4 5; do
+ burst 10.53.0.3 b $try
+ stat 10.53.0.3 0 200 || ret=1
+ [ $ret -eq 1 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n + 1))
+echo_i "dumping ADB data ($n)"
+ret=0
+rndccmd 10.53.0.3 dumpdb -adb
+info=$(grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/\1 \2/')
+echo_i $info
+set -- $info
+[ ${4:-${quota}} -lt $quota ] || ret=1
+quota=$4
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n + 1))
+echo_i "checking lame server recovery (continued) ($n)"
+ret=0
+for try in 1 2 3 4 5 6 7 8 9 10; do
+ burst 10.53.0.3 c $try
+ stat 10.53.0.3 0 20 || ret=1
+ [ $ret -eq 1 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n + 1))
+echo_i "dumping ADB data ($n)"
+ret=0
+rndccmd 10.53.0.3 dumpdb -adb
+info=$(grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/\1 \2/')
+echo_i $info
+set -- $info
+[ ${4:-${quota}} -gt $quota ] || ret=1
+quota=$4
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+copy_setports ns3/named2.conf.in ns3/named.conf
+rndc_reconfig ns3 10.53.0.3
+
+n=$((n + 1))
+echo_i "checking lame server clients are dropped at the per-domain limit ($n)"
+ret=0
+fail=0
+success=0
+touch ans4/norespond
+for try in 1 2 3 4 5; do
+ burst 10.53.0.3 b $try 300
+ $DIGCMD a ${try}.example > dig.out.ns3.$n.$try
+ grep "status: NOERROR" dig.out.ns3.$n.$try > /dev/null 2>&1 && \
+ success=$((success+1))
+ grep "status: SERVFAIL" dig.out.ns3.$n.$try > /dev/null 2>&1 && \
+ fail=$(($fail+1))
+ stat 10.53.0.3 30 50 || ret=1
+ [ $ret -eq 1 ] && break
+ rndccmd 10.53.0.3 recursing 2>&1 | sed 's/^/ns3 /' | cat_i
+ sleep 1
+done
+echo_i "$success successful valid queries, $fail SERVFAIL"
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n + 1))
+echo_i "checking drop statistics ($n)"
+ret=0
+rm -f ns3/named.stats
+rndccmd 10.53.0.3 stats
+for try in 1 2 3 4 5; do
+ [ -f ns3/named.stats ] && break
+ sleep 1
+done
+zspill=$(grep 'spilled due to zone' ns3/named.stats | sed 's/\([0-9][0-9]*\) spilled.*/\1/')
+[ -z "$zspill" ] && zspill=0
+drops=$(grep 'queries dropped' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.*/\1/')
+[ -z "$drops" ] && drops=0
+[ "$drops" -ge "$zspill" ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+copy_setports ns3/named3.conf.in ns3/named.conf
+rndc_reconfig ns3 10.53.0.3
+
+n=$((n + 1))
+echo_i "checking lame server clients are dropped below the hard limit ($n)"
+ret=0
+fail=0
+exceeded=0
+success=0
+touch ans4/norespond
+for try in 1 2 3 4 5; do
+ burst 10.53.0.3 b $try 400
+ $DIGCMD +time=2 a ${try}.example > dig.out.ns3.$n.$try
+ stat 10.53.0.3 1 400 || exceeded=$((exceeded + 1))
+ grep "status: NOERROR" dig.out.ns3.$n.$try > /dev/null 2>&1 && \
+ success=$((success+1))
+ grep "status: SERVFAIL" dig.out.ns3.$n.$try > /dev/null 2>&1 && \
+ fail=$(($fail+1))
+ sleep 1
+done
+echo_i "$success successful valid queries (expected 5)"
+[ "$success" -eq 5 ] || { echo_i "failed"; ret=1; }
+echo_i "$fail SERVFAIL responses (expected 0)"
+[ "$fail" -eq 0 ] || { echo_i "failed"; ret=1; }
+echo_i "clients count exceeded 400 on $exceeded trials (expected 0)"
+[ "$exceeded" -eq 0 ] || { echo_i "failed"; ret=1; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n + 1))
+echo_i "checking drop statistics ($n)"
+ret=0
+rm -f ns3/named.stats
+touch ns3/named.stats
+rndccmd 10.53.0.3 stats
+wait_for_log 5 "queries dropped due to recursive client limit" ns3/named.stats || ret=1
+drops=$(grep 'queries dropped due to recursive client limit' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.*/\1/')
+[ "${drops:-0}" -ne 0 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns5/named.run >/dev/null
+
+n=$((n + 1))
+echo_i "checking clients are dropped at the clients-per-query limit ($n)"
+ret=0
+test -f ans4/norespond && rm -f ans4/norespond
+for try in 1 2 3 4 5; do
+ burst 10.53.0.5 latency $try 20 "dup"
+ sleep 1
+done
+wait_for_message ns5/named.run "clients-per-query increased to 10" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n + 1))
+echo_i "checking drop statistics ($n)"
+ret=0
+rm -f ns5/named.stats
+rndccmd 10.53.0.5 stats
+for try in 1 2 3 4 5; do
+ [ -f ns5/named.stats ] && break
+ sleep 1
+done
+zspill=$(grep 'spilled due to clients per query' ns5/named.stats | sed 's/ *\([0-9][0-9]*\) spilled.*/\1/')
+[ -z "$zspill" ] && zspill=0
+# ns5 configuration:
+# clients-per-query 5
+# max-clients-per-query 10
+# expected spills:
+# 15 (out of 20) spilled for the first burst, and 10 (out of 20) spilled for
+# the next 4 bursts (because of auto-tuning): 15 + (4 * 10) == 55
+expected=55
+[ "$zspill" -eq "$expected" ] || ret=1
+echo_i "$zspill clients spilled (expected $expected)"
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "stop ns5"
+stop_server --use-rndc --port ${CONTROLPORT} ns5
+copy_setports ns5/named2.conf.in ns5/named.conf
+echo_i "start ns5"
+start_server --noclean --restart --port ${PORT} ns5
+
+nextpart ns5/named.run >/dev/null
+
+n=$((n + 1))
+echo_i "checking clients are dropped at the clients-per-query limit with stale-answer-client-timeout ($n)"
+ret=0
+test -f ans4/norespond && rm -f ans4/norespond
+for try in 1 2 3 4 5; do
+ burst 10.53.0.5 latency $try 20 "dup"
+ sleep 1
+done
+wait_for_message ns5/named.run "clients-per-query increased to 10" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n + 1))
+echo_i "checking drop statistics ($n)"
+ret=0
+rm -f ns5/named.stats
+rndccmd 10.53.0.5 stats
+for try in 1 2 3 4 5; do
+ [ -f ns5/named.stats ] && break
+ sleep 1
+done
+zspill=$(grep 'spilled due to clients per query' ns5/named.stats | sed 's/ *\([0-9][0-9]*\) spilled.*/\1/')
+[ -z "$zspill" ] && zspill=0
+# ns5 configuration:
+# clients-per-query 5
+# max-clients-per-query 10
+# expected spills:
+# 15 (out of 20) spilled for the first burst, and 10 (out of 20) spilled for
+# the next 4 bursts (because of auto-tuning): 15 + (4 * 10) == 55
+expected=55
+[ "$zspill" -eq "$expected" ] || ret=1
+echo_i "$zspill clients spilled (expected $expected)"
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/fetchlimit/tests_sh_fetchlimit.py b/bin/tests/system/fetchlimit/tests_sh_fetchlimit.py
new file mode 100644
index 0000000..6df4441
--- /dev/null
+++ b/bin/tests/system/fetchlimit/tests_sh_fetchlimit.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_fetchlimit(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/filter-aaaa/clean.sh b/bin/tests/system/filter-aaaa/clean.sh
new file mode 100644
index 0000000..b7a2372
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/clean.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns1/K*
+rm -f ns1/*.signed
+rm -f ns1/signer.err
+rm -f ns1/dsset-*
+
+rm -f */named.run
+rm -f */named.conf
+rm -f */named.memstats
+
+rm -f ns4/K*
+rm -f ns4/*.signed
+rm -f ns4/signer.err
+rm -f ns4/dsset-*
+
+rm -f dig.out.*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
+
+rm -f ns*/trusted.conf
+rm -f ns*/keygen.out
diff --git a/bin/tests/system/filter-aaaa/conf/bad1.conf b/bin/tests/system/filter-aaaa/conf/bad1.conf
new file mode 100644
index 0000000..e498c19
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/bad1.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+plugin query "../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 yes;
+ filter-aaaa { none; };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/bad2.conf b/bin/tests/system/filter-aaaa/conf/bad2.conf
new file mode 100644
index 0000000..fcb972a
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/bad2.conf
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+plugin query "../../../plugins/.libs/filter-aaaa.so" {
+ /*
+ * While this matches the defaults, it is not a good configuration
+ * to have in named.conf as the two options contradict each other
+ * indicating a error on behalf of the operator.
+ *
+ * The default is to have filter-aaaa-on-v4 off, but if it is turned
+ * on then it applies to all IPv4 queries. This results in
+ * contradictory defaults.
+ */
+ filter-aaaa-on-v4 no;
+ filter-aaaa { any; };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/bad3.conf b/bin/tests/system/filter-aaaa/conf/bad3.conf
new file mode 100644
index 0000000..5f77361
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/bad3.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view myview {
+ plugin query "../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 no;
+ filter-aaaa { any; };
+ };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/bad4.conf b/bin/tests/system/filter-aaaa/conf/bad4.conf
new file mode 100644
index 0000000..4a37e64
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/bad4.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view myview {
+ plugin query "../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 yes;
+ filter-aaaa { none; };
+ };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/bad5.conf b/bin/tests/system/filter-aaaa/conf/bad5.conf
new file mode 100644
index 0000000..eee2336
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/bad5.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+plugin query "../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 yes;
+ filter-aaaa { 1.0.0.0/8; };
+};
+
+view myview {
+ match-clients { any; };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good1.conf b/bin/tests/system/filter-aaaa/conf/good1.conf
new file mode 100644
index 0000000..c330d86
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good1.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+plugin query "../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 yes;
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good2.conf b/bin/tests/system/filter-aaaa/conf/good2.conf
new file mode 100644
index 0000000..aa3c9a5
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good2.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+plugin query "../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 break-dnssec;
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good3.conf b/bin/tests/system/filter-aaaa/conf/good3.conf
new file mode 100644
index 0000000..26e50f5
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good3.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+plugin query "../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 break-dnssec;
+ filter-aaaa { 1.0.0.0/8; };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good4.conf b/bin/tests/system/filter-aaaa/conf/good4.conf
new file mode 100644
index 0000000..b646c8d
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good4.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+plugin query "../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 yes;
+ filter-aaaa { 1.0.0.0/8; };
+};
diff --git a/bin/tests/system/filter-aaaa/conf/good5.conf b/bin/tests/system/filter-aaaa/conf/good5.conf
new file mode 100644
index 0000000..260fdf1
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/conf/good5.conf
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+view myview {
+ plugin query "../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 yes;
+ filter-aaaa { 1.0.0.0/8; };
+ };
+};
diff --git a/bin/tests/system/filter-aaaa/ns1/named1.conf.in b/bin/tests/system/filter-aaaa/ns1/named1.conf.in
new file mode 100644
index 0000000..f5f0905
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/named1.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { fd92:7065:b8e:ffff::1; };
+ recursion no;
+ dnssec-validation yes;
+ notify yes;
+ minimal-responses no;
+};
+
+acl filterees { 10.53.0.1; };
+
+plugin query "../../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 yes;
+ filter-aaaa { filterees; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." { type primary; file "root.db"; };
+zone "signed" { type primary; file "signed.db.signed"; };
+zone "unsigned" { type primary; file "unsigned.db"; };
diff --git a/bin/tests/system/filter-aaaa/ns1/named2.conf.in b/bin/tests/system/filter-aaaa/ns1/named2.conf.in
new file mode 100644
index 0000000..3152f96
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/named2.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { fd92:7065:b8e:ffff::1; };
+ recursion no;
+ dnssec-validation yes;
+ notify yes;
+ minimal-responses no;
+};
+
+plugin query "../../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v6 yes;
+ filter-aaaa { fd92:7065:b8e:ffff::1; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type primary; file "root.db"; };
+zone "signed" { type primary; file "signed.db.signed"; };
+zone "unsigned" { type primary; file "unsigned.db"; };
diff --git a/bin/tests/system/filter-aaaa/ns1/root.db b/bin/tests/system/filter-aaaa/ns1/root.db
new file mode 100644
index 0000000..150aa72
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/root.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns.utld hostmaster.ns.utld ( 1 3600 1200 604800 60 )
+@ NS ns.utld
+ns.utld A 10.53.0.1
+ns.utld AAAA fd92:7065:b8e:ffff::1
+;
+
+signed NS ns.signed
+ns.signed A 10.53.0.1
+ns.signed AAAA fd92:7065:b8e:ffff::1
+
+unsigned NS ns.unsigned
+ns.unsigned A 10.53.0.1
+ns.unsigned AAAA fd92:7065:b8e:ffff::1
diff --git a/bin/tests/system/filter-aaaa/ns1/sign.sh b/bin/tests/system/filter-aaaa/ns1/sign.sh
new file mode 100755
index 0000000..bf6f458
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/sign.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+SYSTESTDIR=filter-aaaa
+
+zone=signed.
+infile=signed.db.in
+zonefile=signed.db.signed
+outfile=signed.db.signed
+
+$KEYGEN -a $DEFAULT_ALGORITHM $zone 2>&1 > /dev/null | cat_i
+$KEYGEN -f KSK -a $DEFAULT_ALGORITHM $zone 2>&1 > keygen.out | cat_i
+keyname=$(cat keygen.out)
+rm -f keygen.out
+
+keyfile_to_static_ds $keyname > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+cp trusted.conf ../ns3/trusted.conf
+cp trusted.conf ../ns5/trusted.conf
+
+$SIGNER -S -o $zone -f $outfile $infile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed zone '$zone'"
diff --git a/bin/tests/system/filter-aaaa/ns1/signed.db.in b/bin/tests/system/filter-aaaa/ns1/signed.db.in
new file mode 100644
index 0000000..36a0373
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/signed.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns.signed. hostmaster.ns.signed. ( 1 3600 1200 604800 60 )
+@ NS ns
+@ MX 10 mx
+
+ns A 10.53.0.1
+ AAAA fd92:7065:b8e:ffff::1
+
+a-only NS 1.0.0.1
+aaaa-only AAAA 2001:db8::2
+dual A 1.0.0.3
+dual AAAA 2001:db8::3
+mx A 1.0.0.3
+mx AAAA 2001:db8::3
diff --git a/bin/tests/system/filter-aaaa/ns1/unsigned.db b/bin/tests/system/filter-aaaa/ns1/unsigned.db
new file mode 100644
index 0000000..abc3947
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns1/unsigned.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns.unsigned. hostmaster.ns.unsigned. ( 1 3600 1200 604800 60 )
+@ NS ns
+@ MX 10 mx
+
+ns A 10.53.0.1
+ AAAA fd92:7065:b8e:ffff::1
+
+a-only NS 1.0.0.4
+aaaa-only AAAA 2001:db8::5
+dual A 1.0.0.6
+dual AAAA 2001:db8::6
+mx A 1.0.0.3
+mx AAAA 2001:db8::3
diff --git a/bin/tests/system/filter-aaaa/ns2/hints b/bin/tests/system/filter-aaaa/ns2/hints
new file mode 100644
index 0000000..fa0d3e4
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns2/hints
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+
+. NS ns.utld.
+ns.utld. A 10.53.0.1
+ns.utld. AAAA fd92:7065:b8e:ffff::1
diff --git a/bin/tests/system/filter-aaaa/ns2/named1.conf.in b/bin/tests/system/filter-aaaa/ns2/named1.conf.in
new file mode 100644
index 0000000..2a1486d
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns2/named1.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ minimal-responses no;
+};
+
+plugin query "../../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 yes;
+ filter-aaaa { 10.53.0.2; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints"; };
+
+include "trusted.conf";
diff --git a/bin/tests/system/filter-aaaa/ns2/named2.conf.in b/bin/tests/system/filter-aaaa/ns2/named2.conf.in
new file mode 100644
index 0000000..4e5a1ef
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns2/named2.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ minimal-responses no;
+};
+
+plugin query "../../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v6 yes;
+ filter-aaaa { fd92:7065:b8e:ffff::2; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints"; };
+
+include "trusted.conf";
diff --git a/bin/tests/system/filter-aaaa/ns3/hints b/bin/tests/system/filter-aaaa/ns3/hints
new file mode 100644
index 0000000..fa0d3e4
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns3/hints
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+
+. NS ns.utld.
+ns.utld. A 10.53.0.1
+ns.utld. AAAA fd92:7065:b8e:ffff::1
diff --git a/bin/tests/system/filter-aaaa/ns3/named1.conf.in b/bin/tests/system/filter-aaaa/ns3/named1.conf.in
new file mode 100644
index 0000000..602859b
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns3/named1.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::3; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ minimal-responses no;
+};
+
+plugin query "../../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 break-dnssec;
+ filter-aaaa { 10.53.0.3; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints"; };
+
+include "trusted.conf";
diff --git a/bin/tests/system/filter-aaaa/ns3/named2.conf.in b/bin/tests/system/filter-aaaa/ns3/named2.conf.in
new file mode 100644
index 0000000..db449af
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns3/named2.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::3; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ minimal-responses no;
+};
+
+plugin query "../../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v6 break-dnssec;
+ filter-aaaa { fd92:7065:b8e:ffff::3; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints"; };
+
+include "trusted.conf";
diff --git a/bin/tests/system/filter-aaaa/ns4/named1.conf.in b/bin/tests/system/filter-aaaa/ns4/named1.conf.in
new file mode 100644
index 0000000..0aa3007
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/named1.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { fd92:7065:b8e:ffff::4; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ minimal-responses no;
+};
+
+plugin query "../../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 break-dnssec;
+ filter-aaaa { 10.53.0.4; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type primary; file "root.db"; };
+zone "signed" { type primary; file "signed.db.signed"; };
+zone "unsigned" { type primary; file "unsigned.db"; };
diff --git a/bin/tests/system/filter-aaaa/ns4/named2.conf.in b/bin/tests/system/filter-aaaa/ns4/named2.conf.in
new file mode 100644
index 0000000..e534e54
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/named2.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { fd92:7065:b8e:ffff::4; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ minimal-responses no;
+};
+
+plugin query "../../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v6 break-dnssec;
+ filter-aaaa { fd92:7065:b8e:ffff::4; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type primary; file "root.db"; };
+zone "signed" { type primary; file "signed.db.signed"; };
+zone "unsigned" { type primary; file "unsigned.db"; };
diff --git a/bin/tests/system/filter-aaaa/ns4/root.db b/bin/tests/system/filter-aaaa/ns4/root.db
new file mode 100644
index 0000000..7984c37
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA ns.utld hostmaster.ns.utld ( 1 3600 1200 604800 60 )
+@ NS ns.utld
+ns.utld A 10.53.0.4
+ns.utld AAAA fd92:7065:b8e:ffff::4
+;
+
+signed NS ns.signed
+ns.signed A 10.53.0.4
+ns.signed AAAA fd92:7065:b8e:ffff::4
+
+unsigned NS ns.unsigned
+ns.unsigned A 10.53.0.4
+ns.unsigned AAAA fd92:7065:b8e:ffff::4
diff --git a/bin/tests/system/filter-aaaa/ns4/sign.sh b/bin/tests/system/filter-aaaa/ns4/sign.sh
new file mode 100755
index 0000000..b9ce09f
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/sign.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+SYSTESTDIR=filter-aaaa
+
+zone=signed.
+infile=signed.db.in
+zonefile=signed.db.signed
+outfile=signed.db.signed
+
+$KEYGEN -a $DEFAULT_ALGORITHM $zone 2>&1 > /dev/null | cat_i
+$KEYGEN -f KSK -a $DEFAULT_ALGORITHM $zone 2>&1 > /dev/null | cat_i
+
+$SIGNER -S -o $zone -f $outfile $infile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed zone '$zone'"
diff --git a/bin/tests/system/filter-aaaa/ns4/signed.db.in b/bin/tests/system/filter-aaaa/ns4/signed.db.in
new file mode 100644
index 0000000..fa52106
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/signed.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns.signed. hostmaster.ns.signed. ( 1 3600 1200 604800 60 )
+@ NS ns
+@ MX 10 mx
+
+ns A 10.53.0.4
+ AAAA fd92:7065:b8e:ffff::4
+
+a-only NS 1.0.0.1
+aaaa-only AAAA 2001:db8::2
+dual A 1.0.0.3
+dual AAAA 2001:db8::3
+mx A 1.0.0.3
+mx AAAA 2001:db8::3
diff --git a/bin/tests/system/filter-aaaa/ns4/unsigned.db b/bin/tests/system/filter-aaaa/ns4/unsigned.db
new file mode 100644
index 0000000..4baa462
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns4/unsigned.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns.unsigned. hostmaster.ns.unsigned. ( 1 3600 1200 604800 60 )
+@ NS ns
+@ MX 10 mx
+
+ns A 10.53.0.4
+ AAAA fd92:7065:b8e:ffff::4
+
+a-only NS 1.0.0.4
+aaaa-only AAAA 2001:db8::5
+dual A 1.0.0.6
+dual AAAA 2001:db8::6
+mx A 1.0.0.3
+mx AAAA 2001:db8::3
diff --git a/bin/tests/system/filter-aaaa/ns5/hints b/bin/tests/system/filter-aaaa/ns5/hints
new file mode 100644
index 0000000..fa0d3e4
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns5/hints
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+
+. NS ns.utld.
+ns.utld. A 10.53.0.1
+ns.utld. AAAA fd92:7065:b8e:ffff::1
diff --git a/bin/tests/system/filter-aaaa/ns5/named.conf.in b/bin/tests/system/filter-aaaa/ns5/named.conf.in
new file mode 100644
index 0000000..36380cd
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/ns5/named.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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 { fd92:7065:b8e:ffff::5; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+ dns64 64:ff9b::/96 {
+ clients { any; };
+ exclude { any; };
+ mapped { any; };
+ };
+ minimal-responses no;
+};
+
+plugin query "../../../../plugins/.libs/filter-aaaa.so" {
+ filter-aaaa-on-v4 break-dnssec;
+ filter-aaaa { any; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints"; };
+
+include "trusted.conf";
diff --git a/bin/tests/system/filter-aaaa/setup.sh b/bin/tests/system/filter-aaaa/setup.sh
new file mode 100644
index 0000000..c3901c5
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/setup.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named1.conf.in ns1/named.conf
+copy_setports ns2/named1.conf.in ns2/named.conf
+copy_setports ns3/named1.conf.in ns3/named.conf
+copy_setports ns4/named1.conf.in ns4/named.conf
+copy_setports ns5/named.conf.in ns5/named.conf
+
+(cd ns1 && $SHELL -e sign.sh)
+(cd ns4 && $SHELL -e sign.sh)
diff --git a/bin/tests/system/filter-aaaa/tests.sh b/bin/tests/system/filter-aaaa/tests.sh
new file mode 100644
index 0000000..5ed97eb
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/tests.sh
@@ -0,0 +1,1420 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+for conf in conf/good*.conf
+do
+ n=$((n + 1))
+ echo_i "checking that $conf is accepted ($n)"
+ ret=0
+ $CHECKCONF "$conf" || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+for conf in conf/bad*.conf
+do
+ n=$((n + 1))
+ echo_i "checking that $conf is rejected ($n)"
+ ret=0
+ $CHECKCONF "$conf" >/dev/null && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+#
+# Authoritative tests against:
+# filter-aaaa-on-v4 yes;
+# filter-aaaa { 10.53.0.1; };
+#
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, signed ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1
+grep ::2 dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, unsigned ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1
+grep ::5 dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns1.test$n > /dev/null || ret=1
+grep "AUTHORITY: 0" dig.out.ns1.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns1.test$n > /dev/null || ret=1
+grep "AUTHORITY: 0" dig.out.ns1.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist, signed and DO set ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed +dnssec -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "AUTHORITY: 2," dig.out.ns1.test$n > /dev/null || ret=1
+grep ::3 dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns1.test$n > /dev/null || ret=1
+grep "AUTHORITY: 0," dig.out.ns1.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.2 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns1.test$n > /dev/null || ret=1
+grep "::3" dig.out.ns1.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns1.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns1.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, signed, qtype=ANY and DO is set ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed +dnssec -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "AUTHORITY: 2," dig.out.ns1.test$n > /dev/null || ret=1
+grep ::3 dig.out.ns1.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned +dnssec -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns1.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns1.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b 10.53.0.2 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1
+grep 1.0.0.6 dig.out.ns1.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv6 ($n)"
+if testsock6 fd92:7065:b8e:ffff::1
+then
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep 2001:db8::6 dig.out.ns1.test$n > /dev/null || ret=1
+grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+else
+echo_i "skipped."
+fi
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=NS ($n)"
+ret=0
+$DIG $DIGOPTS +add ns unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep AAAA dig.out.ns1.test$n > /dev/null 2>&1 && ret=1
+grep "ANSWER: 1," dig.out.ns1.test$n > /dev/null || ret=1
+grep "ADDITIONAL: 2" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns1.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, signed ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx signed -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "^mx.signed.*AAAA" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
+grep "AUTHORITY: 2," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv6 ($n)"
+if testsock6 fd92:7065:b8e:ffff::1
+then
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
+grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+else
+echo_i "skipped."
+fi
+
+#
+# Authoritative tests against:
+# filter-aaaa-on-v4 break-dnssec;
+# filter-aaaa { 10.53.0.4; };
+#
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, signed with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "AUTHORITY: 1," dig.out.ns4.test$n > /dev/null || ret=1
+grep ::2 dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, unsigned with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.unsigned -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "AUTHORITY: 1," dig.out.ns4.test$n > /dev/null || ret=1
+grep ::5 dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+grep "AUTHORITY: 0," dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed and DO set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed +dnssec -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.2 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns4.test$n > /dev/null || ret=1
+grep "::3" dig.out.ns4.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns4.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns4.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed, qtype=ANY and DO is set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed +dnssec -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns4.test$n > /dev/null || ret=1
+grep ::3 dig.out.ns4.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned +dnssec -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns4.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns4.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b 10.53.0.2 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep 1.0.0.6 dig.out.ns4.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv6 with break-dnssec ($n)"
+if testsock6 fd92:7065:b8e:ffff::4
+then
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep 2001:db8::6 dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+else
+echo_i "skipped."
+fi
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=NS, with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add ns unsigned -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep AAAA dig.out.ns4.test$n > /dev/null 2>&1 && ret=1
+grep "ADDITIONAL: 2" dig.out.ns4.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned, with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns4.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, signed, with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx signed -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "^mx.signed.*AAAA" dig.out.ns4.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv6, with break-dnssec ($n)"
+if testsock6 fd92:7065:b8e:ffff::4
+then
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns4.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+else
+echo_i "skipped."
+fi
+
+
+#
+# Recursive tests against:
+# filter-aaaa-on-v4 yes;
+# filter-aaaa { 10.53.0.2; };
+#
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep ::2 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, unsigned, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.unsigned -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep ::5 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist, signed and DO set, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed +dnssec -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep ::3 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY recursive ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns2.test$n > /dev/null || ret=1
+grep "::3" dig.out.ns2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY recursive ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns2.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, signed, qtype=ANY and DO is set, recursive ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed +dnssec -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep ::3 dig.out.ns2.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set, recursive ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned +dnssec -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns2.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl, recursive ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b 10.53.0.1 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep 1.0.0.6 dig.out.ns2.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv6, recursive ($n)"
+if testsock6 fd92:7065:b8e:ffff::2
+then
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep 2001:db8::6 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+else
+echo_i "skipped."
+fi
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=NS ($n)"
+ret=0
+$DIG $DIGOPTS +add ns unsigned -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep AAAA dig.out.ns2.test$n > /dev/null 2>&1 && ret=1
+grep "ADDITIONAL: 2" dig.out.ns2.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned, recursive ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns2.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, signed, recursive ($n)"
+ret=0
+# we need to prime the cache with addresses for the MX, since additional
+# section data won't be included unless it's validated, and that doesn't
+# necessarily happen otherwise.
+$DIG $DIGOPTS +dnssec mx.signed @10.53.0.2 > /dev/null
+$DIG $DIGOPTS +dnssec mx.signed aaaa @10.53.0.2 > /dev/null
+$DIG $DIGOPTS +add +dnssec mx signed -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "^mx.signed.*AAAA" dig.out.ns2.test$n > /dev/null 2>&1 || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, recursive, over IPv6 ($n)"
+if testsock6 fd92:7065:b8e:ffff::2
+then
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns2.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+else
+echo_i "skipped."
+fi
+
+#
+# Recursive tests against:
+# filter-aaaa-on-v4 break-dnssec;
+# filter-aaaa { 10.53.0.3; };
+#
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null || ret=1
+grep ::2 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, unsigned, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.unsigned -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep ::5 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed and DO set, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed +dnssec -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns3.test$n > /dev/null || ret=1
+grep "::3" dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns3.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed, qtype=ANY and DO is set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed +dnssec -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns3.test$n > /dev/null || ret=1
+grep ::3 dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned +dnssec -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns3.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b 10.53.0.1 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep 1.0.0.6 dig.out.ns3.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv6, recursive with break-dnssec ($n)"
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep 2001:db8::6 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+else
+echo_i "skipped."
+fi
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=NS, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add ns unsigned -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep AAAA dig.out.ns3.test$n > /dev/null 2>&1 && ret=1
+grep "ADDITIONAL: 2" dig.out.ns3.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns3.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, signed, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx signed -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "^mx.signed.*AAAA" dig.out.ns3.test$n > /dev/null 2>&1 && ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv6, recursive with break-dnssec ($n)"
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns3.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+else
+echo_i "skipped."
+fi
+
+if ! testsock6 fd92:7065:b8e:ffff::1
+then
+ echo_i "IPv6 address not configured; skipping IPv6 query tests"
+ echo_i "exit status: $status"
+ exit $status
+fi
+
+# Reconfiguring for IPv6 tests
+echo_i "reconfiguring servers"
+copy_setports ns1/named2.conf.in ns1/named.conf
+rndc_reconfig ns1 10.53.0.1
+copy_setports ns2/named2.conf.in ns2/named.conf
+rndc_reconfig ns2 10.53.0.2
+copy_setports ns3/named2.conf.in ns3/named.conf
+rndc_reconfig ns3 10.53.0.3
+copy_setports ns4/named2.conf.in ns4/named.conf
+rndc_reconfig ns4 10.53.0.4
+
+# BEGIN IPv6 TESTS
+
+#
+# Authoritative tests against:
+# filter-aaaa-on-v6 yes;
+# filter-aaaa { fd92:7065:b8e:ffff::1; };
+#
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, signed ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.signed -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep ::2 dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, unsigned ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep ::5 dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns1.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns1.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist, signed and DO set ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed +dnssec -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep ::3 dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns1.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns1.test$n > /dev/null || ret=1
+grep "::3" dig.out.ns1.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns1.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns1.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, signed, qtype=ANY and DO is set ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed +dnssec -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep ::3 dig.out.ns1.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned +dnssec -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns1.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns1.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep 1.0.0.6 dig.out.ns1.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv4 ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep 2001:db8::6 dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=NS ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec ns unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep AAAA dig.out.ns1.test$n > /dev/null 2>&1 && ret=1
+grep "ADDITIONAL: 2" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns1.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, signed ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx signed -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1
+grep "^mx.signed.*AAAA" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv4 ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+
+#
+# Authoritative tests against:
+# filter-aaaa-on-v6 break-dnssec;
+# filter-aaaa { fd92:7065:b8e:ffff::4; };
+#
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, signed with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.signed -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep ::2 dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, unsigned with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep ::5 dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed and DO set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed +dnssec -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns4.test$n > /dev/null || ret=1
+grep "::3" dig.out.ns4.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns4.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns4.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed, qtype=ANY and DO is set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed +dnssec -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns4.test$n > /dev/null || ret=1
+grep ::3 dig.out.ns4.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned +dnssec -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns4.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns4.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep 1.0.0.6 dig.out.ns4.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv4 with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep 2001:db8::6 dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=NS, with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec ns unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep AAAA dig.out.ns4.test$n > /dev/null 2>&1 && ret=1
+grep "ADDITIONAL: 2" dig.out.ns4.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned, with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns4.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, signed, with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx signed -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 > dig.out.ns4.test$n || ret=1
+grep "^mx.signed.*AAAA" dig.out.ns4.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv4, with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns4.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+
+#
+# Recursive tests against:
+# filter-aaaa-on-v6 yes;
+# filter-aaaa { fd92:7065:b8e:ffff::2; };
+#
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.signed -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep ::2 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, unsigned, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep ::5 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist, signed and DO set, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed +dnssec -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep ::3 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY recursive ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns2.test$n > /dev/null || ret=1
+grep "::3" dig.out.ns2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY recursive ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns2.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, signed, qtype=ANY and DO is set, recursive ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed +dnssec -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep ::3 dig.out.ns2.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set, recursive ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned +dnssec -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns2.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl, recursive ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep 1.0.0.6 dig.out.ns2.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv4, recursive ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep 2001:db8::6 dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=NS ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec ns unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep AAAA dig.out.ns2.test$n > /dev/null 2>&1 && ret=1
+grep "ADDITIONAL: 2" dig.out.ns2.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns2.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, signed ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx signed -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1
+grep "^mx.signed.*AAAA" dig.out.ns2.test$n > /dev/null 2>&1 || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv4 ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.2 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns2.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+
+#
+# Recursive tests against:
+# filter-aaaa-on-v6 yes;
+# filter-aaaa { fd92:7065:b8e:ffff::3; };
+#
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.signed -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null || ret=1
+grep ::2 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when only AAAA record exists, unsigned, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep ::5 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed and DO set, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.signed +dnssec -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns3.test$n > /dev/null || ret=1
+grep "::3" dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns3.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed, qtype=ANY and DO is set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.signed +dnssec -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "1.0.0.3" dig.out.ns3.test$n > /dev/null || ret=1
+grep ::3 dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned +dnssec -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "1.0.0.6" dig.out.ns3.test$n > /dev/null || ret=1
+grep "::6" dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep 1.0.0.6 dig.out.ns3.test$n > /dev/null || ret=1
+grep ::6 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv4, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep 2001:db8::6 dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=NS, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec ns unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep AAAA dig.out.ns3.test$n > /dev/null 2>&1 && ret=1
+grep "ADDITIONAL: 2" dig.out.ns3.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns3.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is omitted from additional section, qtype=MX, signed, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx signed -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 > dig.out.ns3.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null || ret=1
+grep "^mx.signed.*AAAA" dig.out.ns3.test$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv4, recursive with break-dnssec ($n)"
+ret=0
+$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep "^mx.unsigned.*AAAA" dig.out.ns3.test$n > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# We don't check for the AAAA record here as configuration in ns5 does
+# not make sense. The AAAA record is wanted by filter-aaaa but discarded
+# by the dns64 configuration. We just want to ensure the server stays
+# running.
+n=$((n + 1))
+echo_i "checking filter-aaaa with dns64 ($n)"
+ret=0
+$DIG $DIGOPTS aaaa aaaa-only.unsigned @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "status: NOERROR" dig.out.ns5.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/filter-aaaa/tests_sh_filter_aaaa.py b/bin/tests/system/filter-aaaa/tests_sh_filter_aaaa.py
new file mode 100644
index 0000000..bc6a90d
--- /dev/null
+++ b/bin/tests/system/filter-aaaa/tests_sh_filter_aaaa.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_filter_aaaa(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/formerr/clean.sh b/bin/tests/system/formerr/clean.sh
new file mode 100644
index 0000000..05d08a7
--- /dev/null
+++ b/bin/tests/system/formerr/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f nametoolong.out
+rm -f twoquestions.out
+rm -f noquestions.out
+rm -f ns*/named.conf
+rm -f ns*/named.lock
+rm -f ns*/named.run
+rm -f ns*/named.memstats
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/formerr/formerr.pl b/bin/tests/system/formerr/formerr.pl
new file mode 100644
index 0000000..fd7d298
--- /dev/null
+++ b/bin/tests/system/formerr/formerr.pl
@@ -0,0 +1,97 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# This is a tool for sending an arbitrary packet via UDP or TCP to an
+# arbitrary address and port. The packet is specified in a file or on
+# the standard input, in the form of a series of bytes in hexadecimal.
+# Whitespace is ignored, as is anything following a '#' symbol.
+#
+# For example, the following input would generate normal query for
+# isc.org/NS/IN":
+#
+# # QID:
+# 0c d8
+# # header:
+# 01 00 00 01 00 00 00 00 00 00
+# # qname isc.org:
+# 03 69 73 63 03 6f 72 67 00
+# # qtype NS:
+# 00 02
+# # qclass IN:
+# 00 01
+#
+# Note that we do not wait for a response for the server. This is simply
+# a way of injecting arbitrary packets to test server resposnes.
+#
+# Usage: packet.pl [-a <address>] [-p <port>] [-t (udp|tcp)] [filename]
+#
+# If not specified, address defaults to 127.0.0.1, port to 53, protocol
+# to udp, and file to stdin.
+#
+# XXX: Doesn't support IPv6 yet
+
+require 5.006_001;
+
+use strict;
+use Getopt::Std;
+use IO::File;
+use IO::Socket;
+
+sub usage {
+ print ("Usage: packet.pl [-a address] [-p port] [file]\n");
+ exit 1;
+}
+
+my %options={};
+getopts("a:p:", \%options);
+
+my $addr = "127.0.0.1";
+$addr = $options{a} if defined $options{a};
+
+my $port = 53;
+$port = $options{p} if defined $options{p};
+
+my $file = "STDIN";
+if (@ARGV >= 1) {
+ my $filename = shift @ARGV;
+ open FH, "<$filename" or die "$filename: $!";
+ $file = "FH";
+}
+
+my $input = "";
+while (defined(my $line = <$file>) ) {
+ chomp $line;
+ $line =~ s/#.*$//;
+ $input .= $line;
+}
+
+$input =~ s/\s+//g;
+my $data = pack("H*", $input);
+my $len = length $data;
+
+my $output = unpack("H*", $data);
+print ("sending: $output\n");
+
+my $sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port,
+ Proto => "tcp") or die "$!";
+
+my $bytes;
+$bytes = $sock->syswrite(pack("n", $len), 2);
+$bytes = $sock->syswrite($data, $len);
+$bytes = $sock->sysread($data, 2);
+$len = unpack("n", $data);
+$bytes = $sock->sysread($data, $len);
+print "got: ", unpack("H*", $data). "\n";
+
+$sock->close;
+close $file;
diff --git a/bin/tests/system/formerr/nametoolong b/bin/tests/system/formerr/nametoolong
new file mode 100644
index 0000000..b81545f
--- /dev/null
+++ b/bin/tests/system/formerr/nametoolong
@@ -0,0 +1,19 @@
+00 00 00 00 00 01 00 00 00 00 00 00
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
+0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
+00 01
+00 01
diff --git a/bin/tests/system/formerr/noquestions b/bin/tests/system/formerr/noquestions
new file mode 100644
index 0000000..f087bcd
--- /dev/null
+++ b/bin/tests/system/formerr/noquestions
@@ -0,0 +1 @@
+00 00 00 00 00 00 00 00 00 00 00 00
diff --git a/bin/tests/system/formerr/ns1/named.conf.in b/bin/tests/system/formerr/ns1/named.conf.in
new file mode 100644
index 0000000..1334c85
--- /dev/null
+++ b/bin/tests/system/formerr/ns1/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/formerr/ns1/root.db b/bin/tests/system/formerr/ns1/root.db
new file mode 100644
index 0000000..f4d4c69
--- /dev/null
+++ b/bin/tests/system/formerr/ns1/root.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA marka.isc.org. a.root.servers.nil. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.4
diff --git a/bin/tests/system/formerr/setup.sh b/bin/tests/system/formerr/setup.sh
new file mode 100644
index 0000000..82240a7
--- /dev/null
+++ b/bin/tests/system/formerr/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/formerr/tests.sh b/bin/tests/system/formerr/tests.sh
new file mode 100644
index 0000000..75f4cc0
--- /dev/null
+++ b/bin/tests/system/formerr/tests.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+
+echo_i "test name too long"
+$PERL formerr.pl -a 10.53.0.1 -p ${PORT} nametoolong > nametoolong.out
+ans=$(grep got: nametoolong.out)
+if [ "${ans}" != "got: 000080010000000000000000" ];
+then
+ echo_i "failed"; status=$((status + 1));
+fi
+
+echo_i "two questions"
+$PERL formerr.pl -a 10.53.0.1 -p ${PORT} twoquestions > twoquestions.out
+ans=$(grep got: twoquestions.out)
+if [ "${ans}" != "got: 000080010000000000000000" ];
+then
+ echo_i "failed"; status=$((status + 1));
+fi
+
+# this would be NOERROR if it included a COOKIE option,
+# but is a FORMERR without one.
+echo_i "empty question section (and no COOKIE option)"
+$PERL formerr.pl -a 10.53.0.1 -p ${PORT} noquestions > noquestions.out
+ans=$(grep got: noquestions.out)
+if [ "${ans}" != "got: 000080010000000000000000" ];
+then
+ echo_i "failed"; status=$((status + 1));
+fi
+
+echo_i "exit status: $status"
+
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/formerr/tests_sh_formerr.py b/bin/tests/system/formerr/tests_sh_formerr.py
new file mode 100644
index 0000000..7363856
--- /dev/null
+++ b/bin/tests/system/formerr/tests_sh_formerr.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_formerr(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/formerr/twoquestions b/bin/tests/system/formerr/twoquestions
new file mode 100644
index 0000000..2192e3d
--- /dev/null
+++ b/bin/tests/system/formerr/twoquestions
@@ -0,0 +1,7 @@
+00 00 00 00 00 02 00 00 00 00 00 00
+0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
+00 01
+00 02
+0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
+00 01
+00 01
diff --git a/bin/tests/system/forward/ans11/ans.py b/bin/tests/system/forward/ans11/ans.py
new file mode 100644
index 0000000..00b5895
--- /dev/null
+++ b/bin/tests/system/forward/ans11/ans.py
@@ -0,0 +1,272 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from __future__ import print_function
+import os
+import sys
+import signal
+import socket
+import select
+import struct
+from datetime import datetime, timedelta
+import time
+import functools
+
+import dns, dns.message, dns.query, dns.flags
+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)
+
+
+# Create a UDP listener
+def udp_listen(ip, port, is_ipv6=False):
+ try:
+ udp = socket.socket(
+ socket.AF_INET6 if is_ipv6 else socket.AF_INET, socket.SOCK_DGRAM
+ )
+ try:
+ udp.bind((ip, port))
+ except:
+ udp.close()
+ udp = None
+ except:
+ udp = None
+
+ if udp is None and not is_ipv6:
+ raise socket.error("Can not create an IPv4 UDP listener")
+
+ return udp
+
+
+# Create a TCP listener
+def tcp_listen(ip, port, is_ipv6=False):
+ try:
+ tcp = socket.socket(
+ socket.AF_INET6 if is_ipv6 else socket.AF_INET, socket.SOCK_STREAM
+ )
+ try:
+ tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ tcp.bind((ip, port))
+ tcp.listen(100)
+ except:
+ tcp.close()
+ tcp = None
+ except:
+ tcp = None
+
+ if tcp is None and not is_ipv6:
+ raise socket.error("Can not create an IPv4 TCP listener")
+
+ return tcp
+
+
+############################################################################
+# Control channel - send "1" or "0" to enable or disable the "silent" mode.
+############################################################################
+silent = False
+
+
+def ctrl_channel(msg):
+ global silent
+
+ msg = msg.splitlines().pop(0)
+ print("Received control message: %s" % msg)
+
+ if len(msg) != 1:
+ return
+
+ if silent:
+ if msg == b"0":
+ silent = False
+ print("Silent mode was disabled")
+ else:
+ if msg == b"1":
+ silent = True
+ print("Silent mode was enabled")
+
+
+############################################################################
+# Respond to a DNS query.
+############################################################################
+def create_response(msg):
+ m = dns.message.from_wire(msg)
+ qname = m.question[0].name.to_text()
+ rrtype = m.question[0].rdtype
+ typename = dns.rdatatype.to_text(rrtype)
+
+ with open("query.log", "a") as f:
+ f.write("%s %s\n" % (typename, qname))
+ print("%s %s" % (typename, qname), end=" ")
+
+ r = dns.message.make_response(m)
+ r.set_rcode(NOERROR)
+ if rrtype == A:
+ tld = qname.split(".")[-2] + "."
+ ns = "local." + tld
+ r.answer.append(dns.rrset.from_text(qname, 300, IN, A, "10.53.0.11"))
+ r.answer.append(dns.rrset.from_text(tld, 300, IN, NS, "local." + tld))
+ r.additional.append(dns.rrset.from_text(ns, 300, IN, A, "10.53.0.11"))
+ elif rrtype == NS:
+ r.answer.append(dns.rrset.from_text(qname, 300, IN, NS, "."))
+ elif rrtype == SOA:
+ r.answer.append(dns.rrset.from_text(qname, 300, IN, SOA, ". . 0 0 0 0 0"))
+ else:
+ r.authority.append(dns.rrset.from_text(qname, 300, IN, SOA, ". . 0 0 0 0 0"))
+ r.flags |= dns.flags.AA
+ 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.11"
+ip6 = "fd92:7065:b8e:ffff::11"
+
+try:
+ port = int(os.environ["PORT"])
+except:
+ port = 5300
+
+try:
+ ctrlport = int(os.environ["EXTRAPORT1"])
+except:
+ ctrlport = 5300
+
+ctrl4_tcp = tcp_listen(ip4, ctrlport)
+query4_udp = udp_listen(ip4, port)
+query6_udp = udp_listen(ip6, port, is_ipv6=True)
+query4_tcp = tcp_listen(ip4, port)
+query6_tcp = tcp_listen(ip6, port, is_ipv6=True)
+
+havev6 = query6_udp is not None and query6_tcp is not None
+
+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, ctrlport))
+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 = [ctrl4_tcp, query4_udp, query6_udp, query4_tcp, query6_tcp]
+else:
+ input = [ctrl4_tcp, query4_udp, query4_tcp]
+
+hung_conns = []
+
+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 == ctrl4_tcp:
+ print("Control channel connected")
+ conn = None
+ try:
+ # Handle control channel input
+ conn, addr = s.accept()
+ msg = conn.recv(1)
+ if msg:
+ ctrl_channel(msg)
+ conn.close()
+ except s.timeout:
+ pass
+ if conn:
+ conn.close()
+ elif s == query4_tcp or s == query6_tcp:
+ print(
+ "TCP query received on %s" % (ip4 if s == query4_tcp else ip6), end=" "
+ )
+ conn = None
+ try:
+ # Handle incoming queries
+ conn, addr = s.accept()
+ if not silent:
+ # get TCP message length
+ msg = conn.recv(2)
+ if len(msg) != 2:
+ print("NO RESPONSE (can not read the message length)")
+ conn.close()
+ continue
+ length = struct.unpack(">H", msg[:2])[0]
+ msg = conn.recv(length)
+ if len(msg) != length:
+ print("NO RESPONSE (can not read the message)")
+ conn.close()
+ continue
+ rsp = create_response(msg)
+ if rsp:
+ print(dns.rcode.to_text(rsp.rcode()))
+ wire = rsp.to_wire()
+ conn.send(struct.pack(">H", len(wire)))
+ conn.send(wire)
+ else:
+ print("NO RESPONSE (can not create a response)")
+ else:
+ # Do not respond and hang the connection.
+ print("NO RESPONSE (silent mode)")
+ hung_conns.append(conn)
+ continue
+ except socket.error as e:
+ print("NO RESPONSE (error: %s)" % str(e))
+ if conn:
+ conn.close()
+ elif s == query4_udp or s == query6_udp:
+ print(
+ "UDP query received on %s" % (ip4 if s == query4_udp else ip6), end=" "
+ )
+ # Handle incoming queries
+ msg = s.recvfrom(65535)
+ if not silent:
+ 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 (can not create a response)")
+ else:
+ # Do not respond.
+ print("NO RESPONSE (silent mode)")
+ if not running:
+ break
diff --git a/bin/tests/system/forward/ans6/ans.pl b/bin/tests/system/forward/ans6/ans.pl
new file mode 100644
index 0000000..6102e4a
--- /dev/null
+++ b/bin/tests/system/forward/ans6/ans.pl
@@ -0,0 +1,562 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# This is the name server from hell. It provides canned
+# responses based on pattern matching the queries, and
+# can be reprogrammed on-the-fly over a TCP connection.
+#
+# The server listens for queries on port 5300 (or PORT).
+#
+# The server listens for control connections on port 5301 (or EXTRAPORT1).
+#
+# A control connection is a TCP stream of lines like
+#
+# /pattern/
+# name ttl type rdata
+# name ttl type rdata
+# ...
+# /pattern/
+# name ttl type rdata
+# name ttl type rdata
+# ...
+#
+# There can be any number of patterns, each associated
+# with any number of response RRs. Each pattern is a
+# Perl regular expression. If an empty pattern ("//") is
+# received, the server will ignore all incoming queries (TCP
+# connections will still be accepted, but both UDP queries
+# and TCP queries will not be responded to). If a non-empty
+# pattern is then received over the same control connection,
+# default behavior is restored.
+#
+# Each incoming query is converted into a string of the form
+# "qname qtype" (the printable query domain name, space,
+# printable query type) and matched against each pattern.
+#
+# The first pattern matching the query is selected, and
+# the RR following the pattern line are sent in the
+# answer section of the response.
+#
+# Each new control connection causes the current set of
+# patterns and responses to be cleared before adding new
+# ones.
+#
+# The server handles UDP and TCP queries. Zone transfer
+# responses work, but must fit in a single 64 k message.
+#
+# Now you can add TSIG, just specify key/key data with:
+#
+# /pattern <key> <key_data>/
+# name ttl type rdata
+# name ttl type rdata
+#
+# Note that this data will still be sent with any request for
+# pattern, only this data will be signed. Currently, this is only
+# done for TCP.
+#
+# /pattern bad-id <key> <key_data>/
+# /pattern bad-id/
+#
+# will add 50 to the message id of the response.
+
+
+use IO::File;
+use IO::Socket;
+use Data::Dumper;
+use Net::DNS;
+use Net::DNS::Packet;
+use strict;
+
+# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early
+local $SIG{PIPE} = 'IGNORE';
+
+# Flush logged output after every line
+local $| = 1;
+
+# We default to listening on 10.53.0.2 for historical reasons
+# XXX: we should also be able to specify IPv6
+my $server_addr = "10.53.0.6";
+if (@ARGV > 0) {
+ $server_addr = @ARGV[0];
+}
+
+my $mainport = int($ENV{'PORT'});
+if (!$mainport) { $mainport = 5300; }
+my $ctrlport = int($ENV{'EXTRAPORT1'});
+if (!$ctrlport) { $ctrlport = 5301; }
+
+print "listening on $server_addr:$mainport,$ctrlport.\n";
+print "Using Net::DNS $Net::DNS::VERSION\n";
+
+# XXX: we should also be able to set the port numbers to listen on.
+my $ctlsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $ctrlport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $mainport, Proto => "udp", Reuse => 1) or die "$!";
+
+my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $mainport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";;
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+#my @answers = ();
+my @rules;
+my $udphandler;
+my $tcphandler;
+
+sub handleUDP {
+ my ($buf) = @_;
+ my $request;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($request, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ my @questions = $request->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+ my $qclass = $questions[0]->qclass;
+ my $id = $request->header->id;
+
+ my $packet = new Net::DNS::Packet($qname, $qtype, $qclass);
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ $packet->header->id($id);
+
+ # get the existing signature if any, and clear the additional section
+ my $prev_tsig;
+ while (my $rr = $request->pop("additional")) {
+ $prev_tsig = $rr if ($rr->type eq "TSIG");
+ }
+
+ my $r;
+ my $answers = 0;
+ my $match;
+ my $key_name;
+ my $key_data;
+ foreach $r (@rules) {
+ my $pattern = $r->{pattern};
+ ($match, $key_name, $key_data) = split(/ /,$pattern);
+ print "[handleUDP] $match, $key_name, $key_data\n";
+ $match =~ tr/\// /;
+ if ("$qname $qtype" =~ /$match/) {
+ my $a;
+ foreach $a (@{$r->{answer}}) {
+ my $resp;
+ $resp = new Net::DNS::RR("$qname $a");
+ $packet->push("answer", $resp);
+ ++$answers;
+ }
+ last;
+ }
+ }
+ if ($answers eq 0) {
+ my $soa;
+ $soa = new Net::DNS::RR("$qname 300 IN SOA . . 0 0 0 0 0");
+ $packet->push("authority", $soa)
+ }
+ if (defined($key_name) && defined($key_data)) {
+ my $tsig;
+ # Sign the packet
+ print " Signing the response with " .
+ "$key_name/$key_data\n";
+
+ if ($Net::DNS::VERSION < 0.69) {
+ $tsig = Net::DNS::RR->new(
+ "$key_name TSIG $key_data");
+ } else {
+ $tsig = Net::DNS::RR->new(
+ name => $key_name,
+ type => 'TSIG',
+ key => $key_data);
+ }
+
+ # These kluges are necessary because Net::DNS
+ # doesn't know how to sign responses. We
+ # clear compnames so that the TSIG key and
+ # algorithm name won't be compressed, and
+ # add one to arcount because the signing
+ # function will attempt to decrement it,
+ # which is incorrect in a response. Finally
+ # we set request_mac to the previous digest.
+ $packet->{"compnames"} = {}
+ if ($Net::DNS::VERSION < 0.70);
+ $packet->{"header"}{"arcount"} += 1
+ if ($Net::DNS::VERSION < 0.70);
+ if (defined($prev_tsig)) {
+ if ($Net::DNS::VERSION < 0.73) {
+ my $rmac = pack('n H*',
+ length($prev_tsig->mac)/2,
+ $prev_tsig->mac);
+ $tsig->{"request_mac"} =
+ unpack("H*", $rmac);
+ } else {
+ $tsig->request_mac(
+ $prev_tsig->mac);
+ }
+ }
+
+ $packet->sign_tsig($tsig);
+ }
+ #$packet->print;
+
+ return $packet->data;
+}
+
+# namelen:
+# given a stream of data, reads a DNS-formatted name and returns its
+# total length, thus making it possible to skip past it.
+sub namelen {
+ my ($data) = @_;
+ my $len = 0;
+ my $label_len = 0;
+ do {
+ $label_len = unpack("c", $data);
+ $data = substr($data, $label_len + 1);
+ $len += $label_len + 1;
+ } while ($label_len != 0);
+ return ($len);
+}
+
+# packetlen:
+# given a stream of data, reads a DNS wire-format packet and returns
+# its total length, making it possible to skip past it.
+sub packetlen {
+ my ($data) = @_;
+ my $q;
+ my $rr;
+ my $header;
+ my $offset;
+
+ #
+ # decode/encode were introduced in Net::DNS 0.68
+ # parse is no longer a method and calling it here makes perl croak.
+ #
+ my $decode = 0;
+ $decode = 1 if ($Net::DNS::VERSION >= 0.68);
+
+ if ($decode) {
+ ($header, $offset) = Net::DNS::Header->decode(\$data);
+ } else {
+ ($header, $offset) = Net::DNS::Header->parse(\$data);
+ }
+
+ for (1 .. $header->qdcount) {
+ if ($decode) {
+ ($q, $offset) =
+ Net::DNS::Question->decode(\$data, $offset);
+ } else {
+ ($q, $offset) =
+ Net::DNS::Question->parse(\$data, $offset);
+ }
+ }
+ for (1 .. $header->ancount) {
+ if ($decode) {
+ ($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
+ } else {
+ ($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ }
+ for (1 .. $header->nscount) {
+ if ($decode) {
+ ($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
+ } else {
+ ($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ }
+ for (1 .. $header->arcount) {
+ if ($decode) {
+ ($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
+ } else {
+ ($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ }
+ return $offset;
+}
+
+# sign_tcp_continuation:
+# This is a hack to correct the problem that Net::DNS has no idea how
+# to sign multiple-message TCP responses. Several data that are included
+# in the digest when signing a query or the first message of a response are
+# omitted when signing subsequent messages in a TCP stream.
+#
+# Net::DNS::Packet->sign_tsig() has the ability to use a custom signing
+# function (specified by calling Packet->sign_func()). We use this
+# function as the signing function for TCP continuations, and it removes
+# the unwanted data from the digest before calling the default sign_hmac
+# function.
+sub sign_tcp_continuation {
+ my ($key, $data) = @_;
+
+ # copy out first two bytes: size of the previous MAC
+ my $rmacsize = unpack("n", $data);
+ $data = substr($data, 2);
+
+ # copy out previous MAC
+ my $rmac = substr($data, 0, $rmacsize);
+ $data = substr($data, $rmacsize);
+
+ # try parsing out the packet information
+ my $plen = packetlen($data);
+ my $pdata = substr($data, 0, $plen);
+ $data = substr($data, $plen);
+
+ # remove the keyname, ttl, class, and algorithm name
+ $data = substr($data, namelen($data));
+ $data = substr($data, 6);
+ $data = substr($data, namelen($data));
+
+ # preserve the TSIG data
+ my $tdata = substr($data, 0, 8);
+
+ # prepare a new digest and sign with it
+ $data = pack("n", $rmacsize) . $rmac . $pdata . $tdata;
+ return Net::DNS::RR::TSIG::sign_hmac($key, $data);
+}
+
+sub handleTCP {
+ my ($buf) = @_;
+ my $request;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($request, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ my @questions = $request->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+ my $qclass = $questions[0]->qclass;
+ my $id = $request->header->id;
+
+ my $opaque;
+
+ my $packet = new Net::DNS::Packet($qname, $qtype, $qclass);
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ $packet->header->id($id);
+
+ # get the existing signature if any, and clear the additional section
+ my $prev_tsig;
+ my $signer;
+ my $continuation = 0;
+ if ($Net::DNS::VERSION < 0.81) {
+ while (my $rr = $request->pop("additional")) {
+ if ($rr->type eq "TSIG") {
+ $prev_tsig = $rr;
+ }
+ }
+ }
+
+ my @results = ();
+ my $count_these = 0;
+
+ my $r;
+ my $answers = 0;
+ my $match;
+ my $key_name;
+ my $key_data;
+ my $tname;
+ foreach $r (@rules) {
+ my $pattern = $r->{pattern};
+ my($match, $key_name, $key_data, $tname) = split(/ /,$pattern);
+ print "[handleTCP] $match, $key_name, $key_data, $tname \n";
+ $match =~ tr/\// /;
+ if ("$qname $qtype" =~ /$match/) {
+ $count_these++;
+ my $a;
+ foreach $a (@{$r->{answer}}) {
+ my $resp;
+ $resp = new Net::DNS::RR("$qname $a");
+ $packet->push("answer", $resp);
+ ++$answers;
+ }
+ last;
+ }
+ }
+ if ($answers eq 0) {
+ my $soa;
+ $soa = new Net::DNS::RR("$qname 300 SOA . . 0 0 0 0 0");
+ $packet->push("authority", $soa)
+ }
+ if (defined($key_name) && $key_name eq "bad-id") {
+ $packet->header->id(($id+50)%0xffff);
+ $key_name = $key_data;
+ ($key_data, $tname) = split(/ /,$tname)
+ }
+ if (defined($key_name) && defined($key_data)) {
+ my $tsig;
+ # sign the packet
+ print " Signing the data with " .
+ "$key_name/$key_data\n";
+
+ if ($Net::DNS::VERSION < 0.69) {
+ $tsig = Net::DNS::RR->new(
+ "$key_name TSIG $key_data");
+ } elsif ($Net::DNS::VERSION >= 0.81 &&
+ $continuation) {
+ } elsif ($Net::DNS::VERSION >= 0.75 &&
+ $continuation) {
+ $tsig = $prev_tsig;
+ } else {
+ $tsig = Net::DNS::RR->new(
+ name => $key_name,
+ type => 'TSIG',
+ key => $key_data);
+ }
+
+ # These kluges are necessary because Net::DNS
+ # doesn't know how to sign responses. We
+ # clear compnames so that the TSIG key and
+ # algorithm name won't be compressed, and
+ # add one to arcount because the signing
+ # function will attempt to decrement it,
+ # which is incorrect in a response. Finally
+ # we set request_mac to the previous digest.
+ $packet->{"compnames"} = {}
+ if ($Net::DNS::VERSION < 0.70);
+ $packet->{"header"}{"arcount"} += 1
+ if ($Net::DNS::VERSION < 0.70);
+ if (defined($prev_tsig)) {
+ if ($Net::DNS::VERSION < 0.73) {
+ my $rmac = pack('n H*',
+ length($prev_tsig->mac)/2,
+ $prev_tsig->mac);
+ $tsig->{"request_mac"} =
+ unpack("H*", $rmac);
+ } elsif ($Net::DNS::VERSION < 0.81) {
+ $tsig->request_mac(
+ $prev_tsig->mac);
+ }
+ }
+
+ $tsig->sign_func($signer) if defined($signer);
+ $tsig->continuation($continuation) if
+ ($Net::DNS::VERSION >= 0.71 &&
+ $Net::DNS::VERSION <= 0.74 );
+ if ($Net::DNS::VERSION < 0.81) {
+ $packet->sign_tsig($tsig);
+ } elsif ($continuation) {
+ $opaque = $packet->sign_tsig($opaque);
+ } else {
+ $opaque = $packet->sign_tsig($request);
+ }
+ $signer = \&sign_tcp_continuation
+ if ($Net::DNS::VERSION < 0.70);
+ $continuation = 1;
+
+ my $copy =
+ Net::DNS::Packet->new(\($packet->data));
+ $prev_tsig = $copy->pop("additional");
+ }
+
+ #$packet->print;
+ push(@results,$packet->data);
+ if ($tname eq "") {
+ $tname = $qname;
+ }
+ $packet = new Net::DNS::Packet($tname, $qtype, $qclass);
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ $packet->header->id($id);
+ print " A total of $count_these patterns matched\n";
+ return \@results;
+}
+
+# Main
+my $rin;
+my $rout;
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($ctlsock), 1) = 1;
+ vec($rin, fileno($tcpsock), 1) = 1;
+ vec($rin, fileno($udpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($ctlsock), 1)) {
+ warn "ctl conn";
+ my $conn = $ctlsock->accept;
+ my $rule = ();
+ @rules = ();
+ while (my $line = $conn->getline) {
+ chomp $line;
+ if ($line =~ m!^/(.*)/$!) {
+ if (length($1) == 0) {
+ $udphandler = sub { return; };
+ $tcphandler = sub { return; };
+ } else {
+ $udphandler = \&handleUDP;
+ $tcphandler = \&handleTCP;
+ $rule = { pattern => $1, answer => [] };
+ push(@rules, $rule);
+ }
+ } else {
+ push(@{$rule->{answer}}, $line);
+ }
+ }
+ $conn->close;
+ #print Dumper(@rules);
+ #print "+=+=+ $rules[0]->{'pattern'}\n";
+ #print "+=+=+ $rules[0]->{'answer'}->[0]->{'rname'}\n";
+ #print "+=+=+ $rules[0]->{'answer'}->[0]\n";
+ } elsif (vec($rout, fileno($udpsock), 1)) {
+ printf "UDP request\n";
+ my $buf;
+ $udpsock->recv($buf, 512);
+ my $result = &$udphandler($buf);
+ if (defined($result)) {
+ my $num_chars = $udpsock->send($result);
+ print " Sent $num_chars bytes via UDP\n";
+ }
+ } elsif (vec($rout, fileno($tcpsock), 1)) {
+ my $conn = $tcpsock->accept;
+ my $buf;
+ for (;;) {
+ my $lenbuf;
+ my $n = $conn->sysread($lenbuf, 2);
+ last unless $n == 2;
+ my $len = unpack("n", $lenbuf);
+ $n = $conn->sysread($buf, $len);
+ last unless $n == $len;
+ print "TCP request\n";
+ my $result = &$tcphandler($buf);
+ if (defined($result)) {
+ foreach my $response (@$result) {
+ $len = length($response);
+ $n = $conn->syswrite(pack("n", $len), 2);
+ $n = $conn->syswrite($response, $len);
+ print " Sent: $n chars via TCP\n";
+ }
+ }
+ }
+ $conn->close;
+ }
+}
diff --git a/bin/tests/system/forward/clean.sh b/bin/tests/system/forward/clean.sh
new file mode 100644
index 0000000..6d76bb0
--- /dev/null
+++ b/bin/tests/system/forward/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after forward tests.
+#
+rm -f ./dig.out.*
+rm -f ./*/named.conf
+rm -f ./*/named.memstats
+rm -f ./*/named.run ./*/named.run.prev ./*/ans.run
+rm -f ./*/named_dump.db
+rm -f ./ns*/named.lock
+rm -f ./ns*/managed-keys.bind*
+rm -f ./ns1/root.db ./ns1/root.db.signed
+rm -f ./ns*/trusted.conf
+rm -f ./ns1/K* ./ns1/dsset-*
diff --git a/bin/tests/system/forward/ns1/diditwork.net.db b/bin/tests/system/forward/ns1/diditwork.net.db
new file mode 100644
index 0000000..fd9a46e
--- /dev/null
+++ b/bin/tests/system/forward/ns1/diditwork.net.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ TXT "recursed"
+ns A 10.53.0.1
diff --git a/bin/tests/system/forward/ns1/example.db b/bin/tests/system/forward/ns1/example.db
new file mode 100644
index 0000000..aac1bef
--- /dev/null
+++ b/bin/tests/system/forward/ns1/example.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "recursed"
diff --git a/bin/tests/system/forward/ns1/named.conf.in b/bin/tests/system/forward/ns1/named.conf.in
new file mode 100644
index 0000000..f871fd6
--- /dev/null
+++ b/bin/tests/system/forward/ns1/named.conf.in
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ query-source-v6 address fd92:7065:b8e:ffff::1;
+ notify-source 10.53.0.1;
+ notify-source-v6 fd92:7065:b8e:ffff::1;
+ transfer-source 10.53.0.1;
+ transfer-source-v6 fd92:7065:b8e:ffff::1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { fd92:7065:b8e:ffff::1; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+zone "example1." {
+ type primary;
+ file "example.db";
+};
+
+zone "example2." {
+ type primary;
+ file "example.db";
+};
+
+zone "example3." {
+ type primary;
+ file "example.db";
+};
+
+zone "example4." {
+ type primary;
+ file "example.db";
+};
+
+zone "example5." {
+ type primary;
+ file "example.db";
+};
+
+zone "sld.tld" {
+ type primary;
+ file "sld.tld.db";
+};
+
+/* A forward zone without forwarders. */
+zone "example6" {
+ type forward;
+};
+
+zone "diditwork.net" {
+ type primary;
+ file "diditwork.net.db";
+};
+
+zone "spoofed.net" {
+ type primary;
+ file "spoofed.net.db";
+};
+
+zone "sub.local.net" {
+ type primary;
+ file "sub.local.net.db";
+};
+
+zone "net.example.lll" {
+ type master;
+ file "net.example.lll";
+};
diff --git a/bin/tests/system/forward/ns1/net.example.lll b/bin/tests/system/forward/ns1/net.example.lll
new file mode 100644
index 0000000..ba0804f
--- /dev/null
+++ b/bin/tests/system/forward/ns1/net.example.lll
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+net.example.lll. SOA . . 0 0 0 0 0
+net.example.lll. NS attackSecureDomain.net.
+didItWork.net.example.lll. TXT "if you can see this record the attack worked"
diff --git a/bin/tests/system/forward/ns1/root.db.in b/bin/tests/system/forward/ns1/root.db.in
new file mode 100644
index 0000000..95ffac3
--- /dev/null
+++ b/bin/tests/system/forward/ns1/root.db.in
@@ -0,0 +1,36 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
+
+example7 NS ns.example7
+ns.example7 A 10.53.0.2
+
+tld NS ns.tld
+ns.tld A 10.53.0.2
diff --git a/bin/tests/system/forward/ns1/sign.sh b/bin/tests/system/forward/ns1/sign.sh
new file mode 100644
index 0000000..0888c5f
--- /dev/null
+++ b/bin/tests/system/forward/ns1/sign.sh
@@ -0,0 +1,34 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+echo_i "ns1/sign.sh"
+
+ksk=$("$KEYGEN" -q -fk -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$ksk.key" "$zsk.key" > "$zonefile"
+
+"$SIGNER" -P -g -o "$zone" "$zonefile" > /dev/null 2>&1
+
+# Configure the resolving server with a static key.
+keyfile_to_static_ds "$ksk" > trusted.conf
+cp trusted.conf ../ns3/trusted.conf
diff --git a/bin/tests/system/forward/ns1/sld.tld.db b/bin/tests/system/forward/ns1/sld.tld.db
new file mode 100644
index 0000000..f0d4b05
--- /dev/null
+++ b/bin/tests/system/forward/ns1/sld.tld.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+xxx TXT "foo"
diff --git a/bin/tests/system/forward/ns1/spoofed.net.db b/bin/tests/system/forward/ns1/spoofed.net.db
new file mode 100644
index 0000000..eedc46f
--- /dev/null
+++ b/bin/tests/system/forward/ns1/spoofed.net.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+sub TXT "recursed"
diff --git a/bin/tests/system/forward/ns1/sub.local.net.db b/bin/tests/system/forward/ns1/sub.local.net.db
new file mode 100644
index 0000000..fd9a46e
--- /dev/null
+++ b/bin/tests/system/forward/ns1/sub.local.net.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ TXT "recursed"
+ns A 10.53.0.1
diff --git a/bin/tests/system/forward/ns10/fakenet.zone b/bin/tests/system/forward/ns10/fakenet.zone
new file mode 100644
index 0000000..b655a32
--- /dev/null
+++ b/bin/tests/system/forward/ns10/fakenet.zone
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+net. SOA . . 0 0 0 0 0
+net. NS attackSecureDomain.net.
+attackSecureDomain.net. A 10.53.0.10
+didItWork.net. TXT "if you can see this record the attack worked"
+ns.spoofed.net. A 10.53.0.10
diff --git a/bin/tests/system/forward/ns10/fakenet2.zone b/bin/tests/system/forward/ns10/fakenet2.zone
new file mode 100644
index 0000000..cd1e6e9
--- /dev/null
+++ b/bin/tests/system/forward/ns10/fakenet2.zone
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+net2. SOA . . 0 0 0 0 0
+net2. NS attackSecureDomain.net.
+net2. DNAME net.example.lll.
diff --git a/bin/tests/system/forward/ns10/fakesublocalnet.zone b/bin/tests/system/forward/ns10/fakesublocalnet.zone
new file mode 100644
index 0000000..160b533
--- /dev/null
+++ b/bin/tests/system/forward/ns10/fakesublocalnet.zone
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+sub.local.net. SOA . . 0 0 0 0 0
+sub.local.net. NS ns.spoofed.net.
+sub.local.net. TXT "if you see this attacker overrode local delegation"
diff --git a/bin/tests/system/forward/ns10/fakesublocaltld.zone b/bin/tests/system/forward/ns10/fakesublocaltld.zone
new file mode 100644
index 0000000..f78cbc7
--- /dev/null
+++ b/bin/tests/system/forward/ns10/fakesublocaltld.zone
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+sub.local.tld. 3600 IN SOA . . 0 0 0 0 0
+sub.local.tld. 3600 IN NS ns.sub.local.tld.
+sub.local.tld. 3600 IN TXT bad
+ns.sub.local.tld. 3600 IN A 10.53.0.8
diff --git a/bin/tests/system/forward/ns10/named.conf.in b/bin/tests/system/forward/ns10/named.conf.in
new file mode 100644
index 0000000..8148d9e
--- /dev/null
+++ b/bin/tests/system/forward/ns10/named.conf.in
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.10;
+ notify-source 10.53.0.10;
+ transfer-source 10.53.0.10;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.10; };
+ listen-on-v6 { none; };
+ minimal-responses no;
+ dnssec-validation no;
+};
+
+zone "net." {
+ type master;
+ file "fakenet.zone";
+};
+
+zone "spoofed.net." {
+ type master;
+ file "spoofednet.zone";
+};
+
+zone "sub.local.net." {
+ type master;
+ file "fakesublocalnet.zone";
+};
+
+zone "net2" {
+ type master;
+ file "fakenet2.zone";
+};
+
+zone "net.example.lll" {
+ type master;
+ file "net.example.lll";
+};
+
+zone "sub.local.tld." {
+ type master;
+ file "fakesublocaltld.zone";
+};
diff --git a/bin/tests/system/forward/ns10/net.example.lll b/bin/tests/system/forward/ns10/net.example.lll
new file mode 100644
index 0000000..ba0804f
--- /dev/null
+++ b/bin/tests/system/forward/ns10/net.example.lll
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+net.example.lll. SOA . . 0 0 0 0 0
+net.example.lll. NS attackSecureDomain.net.
+didItWork.net.example.lll. TXT "if you can see this record the attack worked"
diff --git a/bin/tests/system/forward/ns10/spoofednet.zone b/bin/tests/system/forward/ns10/spoofednet.zone
new file mode 100644
index 0000000..fb70a43
--- /dev/null
+++ b/bin/tests/system/forward/ns10/spoofednet.zone
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+spoofed.net. SOA . . 0 0 0 0 0
+spoofed.net. NS ns.spoofed.net.
+ns.spoofed.net. A 10.53.0.10
+spoofed.net. TXT "this record is clearly spoofed"
diff --git a/bin/tests/system/forward/ns2/example.db b/bin/tests/system/forward/ns2/example.db
new file mode 100644
index 0000000..df3e52c
--- /dev/null
+++ b/bin/tests/system/forward/ns2/example.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "forwarded"
diff --git a/bin/tests/system/forward/ns2/named.conf.in b/bin/tests/system/forward/ns2/named.conf.in
new file mode 100644
index 0000000..f9a081a
--- /dev/null
+++ b/bin/tests/system/forward/ns2/named.conf.in
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ query-source-v6 address fd92:7065:b8e:ffff::2;
+ notify-source 10.53.0.2;
+ notify-source-v6 fd92:7065:b8e:ffff::2;
+ transfer-source 10.53.0.2;
+ transfer-source-v6 fd92:7065:b8e:ffff::2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "example1." {
+ type primary;
+ file "example.db";
+};
+
+zone "example2." {
+ type primary;
+ file "example.db";
+};
+
+zone "example3." {
+ type primary;
+ file "example.db";
+};
+
+zone "example4." {
+ type primary;
+ file "example.db";
+};
+
+zone "example7." {
+ type primary;
+ file "example.db";
+};
+
+zone "grafted." {
+ type primary;
+ file "example.db";
+};
+
+zone "1.0.10.in-addr.arpa." {
+ type primary;
+ file "example.db";
+};
+
+zone "tld" {
+ type primary;
+ file "tld.db";
+};
diff --git a/bin/tests/system/forward/ns2/root.db b/bin/tests/system/forward/ns2/root.db
new file mode 100644
index 0000000..7108723
--- /dev/null
+++ b/bin/tests/system/forward/ns2/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns2/tld.db b/bin/tests/system/forward/ns2/tld.db
new file mode 100644
index 0000000..965f2a4
--- /dev/null
+++ b/bin/tests/system/forward/ns2/tld.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.2
+sld NS ns.sld
+ns.sld A 10.53.0.1
+local NS ns.local
+ns.local A 10.53.0.9
+sibling NS ns.sibling
+ns.sibling A 10.53.0.4
+sibling NS ns.sub.local
+ns.sub.local A 10.53.0.10
diff --git a/bin/tests/system/forward/ns3/named1.conf.in b/bin/tests/system/forward/ns3/named1.conf.in
new file mode 100644
index 0000000..ffc0718
--- /dev/null
+++ b/bin/tests/system/forward/ns3/named1.conf.in
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ query-source-v6 address fd92:7065:b8e:ffff::3;
+ notify-source 10.53.0.3;
+ notify-source-v6 fd92:7065:b8e:ffff::3;
+ transfer-source 10.53.0.3;
+ transfer-source-v6 fd92:7065:b8e:ffff::3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::3; };
+ forwarders { fd92:7065:b8e:ffff::2; };
+ forward first;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "example1." {
+ type forward;
+ forward first;
+ forwarders { 10.53.0.2; };
+};
+
+zone "example2." {
+ type forward;
+ forward first;
+ forwarders { };
+};
+
+zone "example3." {
+ type forward;
+ forward only;
+ forwarders { };
+};
+
+zone "example7." {
+ type forward;
+ forward first;
+ forwarders { 10.53.0.6; };
+};
diff --git a/bin/tests/system/forward/ns3/named2.conf.in b/bin/tests/system/forward/ns3/named2.conf.in
new file mode 100644
index 0000000..986a60e
--- /dev/null
+++ b/bin/tests/system/forward/ns3/named2.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ query-source-v6 address fd92:7065:b8e:ffff::3;
+ notify-source 10.53.0.3;
+ notify-source-v6 fd92:7065:b8e:ffff::3;
+ transfer-source 10.53.0.3;
+ transfer-source-v6 fd92:7065:b8e:ffff::3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::3; };
+ forwarders { 10.53.0.6; };
+ dnssec-validation yes;
+};
+
+include "trusted.conf";
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
diff --git a/bin/tests/system/forward/ns3/root.db b/bin/tests/system/forward/ns3/root.db
new file mode 100644
index 0000000..7108723
--- /dev/null
+++ b/bin/tests/system/forward/ns3/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns3/root2.db b/bin/tests/system/forward/ns3/root2.db
new file mode 100644
index 0000000..40586f0
--- /dev/null
+++ b/bin/tests/system/forward/ns3/root2.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.11
diff --git a/bin/tests/system/forward/ns4/malicious.db b/bin/tests/system/forward/ns4/malicious.db
new file mode 100644
index 0000000..e4859c1
--- /dev/null
+++ b/bin/tests/system/forward/ns4/malicious.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA malicious. admin.malicious. (
+ 1 ; Serial
+ 604800 ; Refresh
+ 86400 ; Retry
+ 2419200 ; Expire
+ 86400 ) ; Negative Cache TTL
+
+@ IN NS ns
+
+ns IN A 10.53.0.4
+
+target IN CNAME subdomain.rebind.
diff --git a/bin/tests/system/forward/ns4/named.conf.in b/bin/tests/system/forward/ns4/named.conf.in
new file mode 100644
index 0000000..c97823d
--- /dev/null
+++ b/bin/tests/system/forward/ns4/named.conf.in
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ minimal-responses yes;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "example1." {
+ type forward;
+ forward first;
+ forwarders { 10.53.0.2; };
+};
+
+zone "example3." {
+ type forward;
+ forwarders { 10.53.0.2; };
+};
+
+zone "example5." {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.2; };
+};
+
+zone "1.0.10.in-addr.arpa" {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.2; };
+};
+
+zone "grafted" {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.2; };
+};
+
+zone "malicious." {
+ type primary;
+ file "malicious.db";
+};
+
+zone "sibling.tld" {
+ type primary;
+ file "sibling.tld.db";
+};
diff --git a/bin/tests/system/forward/ns4/root.db b/bin/tests/system/forward/ns4/root.db
new file mode 100644
index 0000000..7108723
--- /dev/null
+++ b/bin/tests/system/forward/ns4/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns4/sibling.tld.db b/bin/tests/system/forward/ns4/sibling.tld.db
new file mode 100644
index 0000000..fe080ae
--- /dev/null
+++ b/bin/tests/system/forward/ns4/sibling.tld.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA malicious. admin.malicious. (
+ 1 ; Serial
+ 604800 ; Refresh
+ 86400 ; Retry
+ 2419200 ; Expire
+ 86400 ) ; Negative Cache TTL
+
+@ IN NS ns
+
+ns IN A 10.53.0.4
diff --git a/bin/tests/system/forward/ns5/named.conf.in b/bin/tests/system/forward/ns5/named.conf.in
new file mode 100644
index 0000000..024f49b
--- /dev/null
+++ b/bin/tests/system/forward/ns5/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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; };
+ forward only;
+ forwarders { 10.53.0.4; };
+ deny-answer-aliases { "rebind"; };
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "rebind" {
+ type primary;
+ file "rebind.db";
+};
diff --git a/bin/tests/system/forward/ns5/rebind.db b/bin/tests/system/forward/ns5/rebind.db
new file mode 100644
index 0000000..aed6c2e
--- /dev/null
+++ b/bin/tests/system/forward/ns5/rebind.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA rebind. admin.rebind. (
+ 1 ; Serial
+ 604800 ; Refresh
+ 86400 ; Retry
+ 2419200 ; Expire
+ 86400 ) ; Negative Cache TTL
+
+@ IN NS ns
+
+ns IN A 10.53.0.5
+
+subdomain IN A 10.53.0.1
diff --git a/bin/tests/system/forward/ns5/root.db b/bin/tests/system/forward/ns5/root.db
new file mode 100644
index 0000000..7108723
--- /dev/null
+++ b/bin/tests/system/forward/ns5/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns7/named.conf.in b/bin/tests/system/forward/ns7/named.conf.in
new file mode 100644
index 0000000..302bb55
--- /dev/null
+++ b/bin/tests/system/forward/ns7/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.7;
+ notify-source 10.53.0.7;
+ transfer-source 10.53.0.7;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.7; };
+ listen-on-v6 { none; };
+ forwarders { 10.53.0.4; };
+ forward first;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
diff --git a/bin/tests/system/forward/ns7/root.db b/bin/tests/system/forward/ns7/root.db
new file mode 100644
index 0000000..7108723
--- /dev/null
+++ b/bin/tests/system/forward/ns7/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns8/named.conf.in b/bin/tests/system/forward/ns8/named.conf.in
new file mode 100644
index 0000000..2de656f
--- /dev/null
+++ b/bin/tests/system/forward/ns8/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.8;
+ notify-source 10.53.0.8;
+ transfer-source 10.53.0.8;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.8; };
+ listen-on-v6 { none; };
+ forwarders { 10.53.0.2; }; // returns referrals
+ forward first;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "sub.local.tld" {
+ type primary;
+ file "sub.local.tld.db";
+};
diff --git a/bin/tests/system/forward/ns8/root.db b/bin/tests/system/forward/ns8/root.db
new file mode 100644
index 0000000..2cbdff5
--- /dev/null
+++ b/bin/tests/system/forward/ns8/root.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
diff --git a/bin/tests/system/forward/ns8/sub.local.tld.db b/bin/tests/system/forward/ns8/sub.local.tld.db
new file mode 100644
index 0000000..f2234c7
--- /dev/null
+++ b/bin/tests/system/forward/ns8/sub.local.tld.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+sub.local.tld. 3600 IN SOA . . 0 0 0 0 0
+sub.local.tld. 3600 IN NS ns.sub.local.tld.
+sub.local.tld. 3600 IN TXT good
+ns.sub.local.tld. 3600 IN A 10.53.0.8
diff --git a/bin/tests/system/forward/ns9/local.net.db b/bin/tests/system/forward/ns9/local.net.db
new file mode 100644
index 0000000..af0d2a5
--- /dev/null
+++ b/bin/tests/system/forward/ns9/local.net.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+local.net. 3600 IN SOA . . 0 0 0 0 0
+local.net. 3600 IN NS localhost.
+ns.local.net. 3600 IN A 10.53.0.9
+txt.local.net. 3600 IN TXT "something in the local auth zone"
+sub.local.net. 3600 IN NS ns.spoofed.net. ; attacker will try to override this
diff --git a/bin/tests/system/forward/ns9/local.tld.db b/bin/tests/system/forward/ns9/local.tld.db
new file mode 100644
index 0000000..876a913
--- /dev/null
+++ b/bin/tests/system/forward/ns9/local.tld.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+local.tld. 3600 IN SOA . . 0 0 0 0 0
+local.tld. 3600 IN NS localhost.
+sub.local.tld. 3600 IN NS ns.sub.local.tld.
+ns.sub.local.tld. 3600 IN A 10.53.0.8
diff --git a/bin/tests/system/forward/ns9/named1.conf.in b/bin/tests/system/forward/ns9/named1.conf.in
new file mode 100644
index 0000000..54fed8f
--- /dev/null
+++ b/bin/tests/system/forward/ns9/named1.conf.in
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ edns-udp-size 1232;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+server 10.53.0.10 {
+ edns no;
+};
+
+server 10.53.0.11 {
+ edns no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "attacksecuredomain.net." {
+ type forward;
+ forwarders { 10.53.0.10; };
+};
+
+zone "attacksecuredomain.net2." {
+ type forward;
+ forwarders { 10.53.0.10; };
+};
+
+zone "attacksecuredomain.net3." {
+ type forward;
+ forwarders { 10.53.0.11; };
+};
+
+zone "local.net." {
+ type primary;
+ file "local.net.db";
+ forwarders {};
+};
diff --git a/bin/tests/system/forward/ns9/named2.conf.in b/bin/tests/system/forward/ns9/named2.conf.in
new file mode 100644
index 0000000..34f7eea
--- /dev/null
+++ b/bin/tests/system/forward/ns9/named2.conf.in
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ edns-udp-size 1232;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+server 10.53.0.10 {
+ edns no;
+};
+
+server 10.53.0.11 {
+ edns no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "attacksecuredomain.net." {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.10; };
+};
+
+zone "attacksecuredomain.net2." {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.10; };
+};
+
+zone "attacksecuredomain.net3." {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.11; };
+};
+
+zone "local.net." {
+ type primary;
+ file "local.net.db";
+ forwarders {};
+};
diff --git a/bin/tests/system/forward/ns9/named3.conf.in b/bin/tests/system/forward/ns9/named3.conf.in
new file mode 100644
index 0000000..c07281f
--- /dev/null
+++ b/bin/tests/system/forward/ns9/named3.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ edns-udp-size 1232;
+ forward only;
+ forwarders { 10.53.0.10; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+server 10.53.0.10 {
+ edns no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "local.net." {
+ type primary;
+ file "local.net.db";
+ forwarders {};
+};
diff --git a/bin/tests/system/forward/ns9/named4.conf.in b/bin/tests/system/forward/ns9/named4.conf.in
new file mode 100644
index 0000000..c06b361
--- /dev/null
+++ b/bin/tests/system/forward/ns9/named4.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ edns-udp-size 1232;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+server 10.53.0.10 {
+ edns no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "local.tld." {
+ type primary;
+ file "local.tld.db";
+};
diff --git a/bin/tests/system/forward/ns9/root.db b/bin/tests/system/forward/ns9/root.db
new file mode 100644
index 0000000..2cbdff5
--- /dev/null
+++ b/bin/tests/system/forward/ns9/root.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
diff --git a/bin/tests/system/forward/rfc1918-inherited.conf b/bin/tests/system/forward/rfc1918-inherited.conf
new file mode 100644
index 0000000..66569dc
--- /dev/null
+++ b/bin/tests/system/forward/rfc1918-inherited.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone 10.in-addr.arpa {
+ type forward;
+ forwarders { 1.2.3.4; };
+};
diff --git a/bin/tests/system/forward/rfc1918-notinherited.conf b/bin/tests/system/forward/rfc1918-notinherited.conf
new file mode 100644
index 0000000..d6d5c2d
--- /dev/null
+++ b/bin/tests/system/forward/rfc1918-notinherited.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone 10.in-addr.arpa {
+ type forward;
+ forward first;
+ forwarders { 1.2.3.4; };
+};
diff --git a/bin/tests/system/forward/setup.sh b/bin/tests/system/forward/setup.sh
new file mode 100644
index 0000000..09624ca
--- /dev/null
+++ b/bin/tests/system/forward/setup.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named1.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 ns7/named.conf.in ns7/named.conf
+copy_setports ns8/named.conf.in ns8/named.conf
+copy_setports ns9/named1.conf.in ns9/named.conf
+copy_setports ns10/named.conf.in ns10/named.conf
+
+(
+ cd ns1
+ $SHELL sign.sh
+)
diff --git a/bin/tests/system/forward/tests.sh b/bin/tests/system/forward/tests.sh
new file mode 100644
index 0000000..4037f22
--- /dev/null
+++ b/bin/tests/system/forward/tests.sh
@@ -0,0 +1,406 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+#shellcheck source=conf.sh
+. ../conf.sh
+
+dig_with_opts() (
+ "$DIG" -p "$PORT" "$@"
+)
+
+sendcmd() (
+ send "$1" "$EXTRAPORT1"
+)
+
+rndccmd() {
+ "$RNDC" -c ../common/rndc.conf -p "$CONTROLPORT" -s "$@"
+}
+
+root=10.53.0.1
+hidden=10.53.0.2
+f1=10.53.0.3
+f2=10.53.0.4
+
+status=0
+n=0
+
+n=$((n+1))
+echo_i "checking that a forward zone overrides global forwarders ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example1. txt @$hidden > dig.out.$n.hidden || ret=1
+dig_with_opts +noadd +noauth txt.example1. txt @$f1 > dig.out.$n.f1 || ret=1
+digcomp dig.out.$n.hidden dig.out.$n.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that a forward first zone no forwarders recurses ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example2. txt @$root > dig.out.$n.root || ret=1
+dig_with_opts +noadd +noauth txt.example2. txt @$f1 > dig.out.$n.f1 || ret=1
+digcomp dig.out.$n.root dig.out.$n.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that a forward only zone no forwarders fails ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example2. txt @$root > dig.out.$n.root || ret=1
+dig_with_opts +noadd +noauth txt.example2. txt @$f1 > dig.out.$n.f1 || ret=1
+digcomp dig.out.$n.root dig.out.$n.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that global forwarders work ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example4. txt @$hidden > dig.out.$n.hidden || ret=1
+dig_with_opts +noadd +noauth txt.example4. txt @$f1 > dig.out.$n.f1 || ret=1
+digcomp dig.out.$n.hidden dig.out.$n.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that a forward zone works ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example1. txt @$hidden > dig.out.$n.hidden || ret=1
+dig_with_opts +noadd +noauth txt.example1. txt @$f2 > dig.out.$n.f2 || ret=1
+digcomp dig.out.$n.hidden dig.out.$n.f2 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that forwarding doesn't spontaneously happen ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example2. txt @$root > dig.out.$n.root || ret=1
+dig_with_opts +noadd +noauth txt.example2. txt @$f2 > dig.out.$n.f2 || ret=1
+digcomp dig.out.$n.root dig.out.$n.f2 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that a forward zone with no specified policy works ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example3. txt @$hidden > dig.out.$n.hidden || ret=1
+dig_with_opts +noadd +noauth txt.example3. txt @$f2 > dig.out.$n.f2 || ret=1
+digcomp dig.out.$n.hidden dig.out.$n.f2 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that a forward only doesn't recurse ($n)"
+ret=0
+dig_with_opts txt.example5. txt @$f2 > dig.out.$n.f2 || ret=1
+grep "SERVFAIL" dig.out.$n.f2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking for negative caching of forwarder response ($n)"
+# prime the cache, shutdown the forwarder then check that we can
+# get the answer from the cache. restart forwarder.
+ret=0
+dig_with_opts nonexist. txt @10.53.0.5 > dig.out.$n.f2 || ret=1
+grep "status: NXDOMAIN" dig.out.$n.f2 > /dev/null || ret=1
+stop_server ns4 || ret=1
+dig_with_opts nonexist. txt @10.53.0.5 > dig.out.$n.f2 || ret=1
+grep "status: NXDOMAIN" dig.out.$n.f2 > /dev/null || ret=1
+start_server --restart --noclean --port "${PORT}" ns4 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+check_override() (
+ dig_with_opts 1.0.10.in-addr.arpa TXT @10.53.0.4 > dig.out.$n.f2 &&
+ grep "status: NOERROR" dig.out.$n.f2 > /dev/null &&
+ dig_with_opts 2.0.10.in-addr.arpa TXT @10.53.0.4 > dig.out.$n.f2 &&
+ grep "status: NXDOMAIN" dig.out.$n.f2 > /dev/null
+)
+
+n=$((n+1))
+echo_i "checking that forward only zone overrides empty zone ($n)"
+ret=0
+# retry loop in case the server restart above causes transient failure
+retry_quiet 10 check_override || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that DS lookups for grafting forward zones are isolated ($n)"
+ret=0
+dig_with_opts grafted A @10.53.0.4 > dig.out.$n.q1 || ret=1
+dig_with_opts grafted DS @10.53.0.4 > dig.out.$n.q2 || ret=1
+dig_with_opts grafted A @10.53.0.4 > dig.out.$n.q3 || ret=1
+dig_with_opts grafted AAAA @10.53.0.4 > dig.out.$n.q4 || ret=1
+grep "status: NOERROR" dig.out.$n.q1 > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.$n.q2 > /dev/null || ret=1
+grep "status: NOERROR" dig.out.$n.q3 > /dev/null || ret=1
+grep "status: NOERROR" dig.out.$n.q4 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that rfc1918 inherited 'forward first;' zones are warned about ($n)"
+ret=0
+$CHECKCONF rfc1918-inherited.conf | grep "forward first;" >/dev/null || ret=1
+$CHECKCONF rfc1918-notinherited.conf | grep "forward first;" >/dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that ULA inherited 'forward first;' zones are warned about ($n)"
+ret=0
+$CHECKCONF ula-inherited.conf | grep "forward first;" >/dev/null || ret=1
+$CHECKCONF ula-notinherited.conf | grep "forward first;" >/dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+count_sent() (
+ logfile="$1"
+ start_pattern="$2"
+ pattern="$3"
+ nextpartpeek "$logfile" | sed -n "/$start_pattern/,/^\$/p" | grep -c "$pattern"
+)
+
+check_sent() (
+ expected="$1"
+ shift
+ count=$(count_sent "$@")
+ [ "$expected" = "$count" ]
+)
+
+wait_for_log() (
+ nextpartpeek "$1" | grep "$2" >/dev/null
+
+)
+
+n=$((n+1))
+echo_i "checking that a forwarder timeout prevents it from being reused in the same fetch context ($n)"
+ret=0
+# Make ans6 receive queries without responding to them.
+echo "//" | sendcmd 10.53.0.6
+# Query for a record in a zone which is forwarded to a non-responding forwarder
+# and is delegated from the root to check whether the forwarder will be retried
+# when a delegation is encountered after falling back to full recursive
+# resolution.
+nextpart ns3/named.run >/dev/null
+dig_with_opts txt.example7. txt @$f1 > dig.out.$n.f1 || ret=1
+# The forwarder for the "example7" zone should only be queried once.
+start_pattern="sending packet to 10\.53\.0\.6"
+retry_quiet 5 wait_for_log ns3/named.run "$start_pattern"
+check_sent 1 ns3/named.run "$start_pattern" ";txt\.example7\.[[:space:]]*IN[[:space:]]*TXT$" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that priming queries are not forwarded ($n)"
+ret=0
+nextpart ns7/named.run >/dev/null
+dig_with_opts +noadd +noauth txt.example1. txt @10.53.0.7 > dig.out.$n.f7 || ret=1
+received_pattern="received packet from 10\.53\.0\.1"
+start_pattern="sending packet to 10\.53\.0\.1"
+retry_quiet 5 wait_for_log ns7/named.run "$received_pattern" || ret=1
+check_sent 1 ns7/named.run "$start_pattern" ";\.[[:space:]]*IN[[:space:]]*NS$" || ret=1
+sent=$(grep -c "10.53.0.7#.* (.): query '\./NS/IN' approved" ns4/named.run || true)
+[ "$sent" -eq 0 ] || ret=1
+sent=$(grep -c "10.53.0.7#.* (.): query '\./NS/IN' approved" ns1/named.run || true)
+[ "$sent" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking recovery from forwarding to a non-recursive server ($n)"
+ret=0
+dig_with_opts xxx.sld.tld txt @10.53.0.8 > dig.out.$n.f8 || ret=1
+grep "status: NOERROR" dig.out.$n.f8 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that rebinding protection works in forward only mode ($n)"
+ret=0
+# 10.53.0.5 will forward target.malicious. query to 10.53.0.4
+# which in turn will return a CNAME for subdomain.rebind.
+# to honor the option deny-answer-aliases { "rebind"; };
+# ns5 should return a SERVFAIL to avoid potential rebinding attacks
+dig_with_opts +noadd +noauth @10.53.0.5 target.malicious. > dig.out.$n || ret=1
+grep "status: SERVFAIL" dig.out.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Prepare ans6 for the chasing DS tests.
+sendcmd 10.53.0.6 << EOF
+/ns1.sld.tld/A/
+300 A 10.53.0.2
+/sld.tld/NS/
+300 NS ns1.sld.tld.
+/sld.tld/
+EOF
+
+n=$((n+1))
+echo_i "checking switch from forwarding to normal resolution while chasing DS ($n)"
+ret=0
+copy_setports ns3/named2.conf.in ns3/named.conf
+rndccmd 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 1
+nextpart ns3/named.run >/dev/null
+dig_with_opts @$f1 xxx.yyy.sld.tld ds > dig.out.$n.f1 || ret=1
+grep "status: SERVFAIL" dig.out.$n.f1 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# See [GL #3129].
+# Enable silent mode for ans11.
+echo "1" | sendcmd 10.53.0.11
+n=$((n+1))
+echo_i "checking the handling of hung DS fetch while chasing DS ($n)"
+ret=0
+copy_setports ns3/named2.conf.in ns3/tmp
+sed 's/root.db/root2.db/' ns3/tmp > ns3/named.conf
+rm -f ns3/tmp
+rndccmd 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+rndccmd 10.53.0.3 flush 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 1
+nextpart ns3/named.run >/dev/null
+dig_with_opts @$f1 xxx.yyy.sld.tld ds > dig.out.$n.f1 || ret=1
+grep "status: SERVFAIL" dig.out.$n.f1 > /dev/null || ret=1
+# Disable silent mode for ans11.
+echo "0" | sendcmd 10.53.0.11
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#
+# Check various spoofed response scenarios. The same tests will be
+# run twice, with "forward first" and "forward only" configurations.
+#
+run_spooftests () {
+ n=$((n+1))
+ echo_i "checking spoofed response scenario 1 - out of bailiwick NS ($n)"
+ ret=0
+ # prime
+ dig_with_opts @10.53.0.9 attackSecureDomain.net > dig.out.$n.prime || ret=1
+ # check 'net' is not poisoned.
+ dig_with_opts @10.53.0.9 diditwork.net. TXT > dig.out.$n.net || ret=1
+ grep '^diditwork\.net\..*TXT.*"recursed"' dig.out.$n.net > /dev/null || ret=1
+ # check 'sub.local.net' is not poisoned.
+ dig_with_opts @10.53.0.9 sub.local.net TXT > dig.out.$n.sub || ret=1
+ grep '^sub\.local\.net\..*TXT.*"recursed"' dig.out.$n.sub > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking spoofed response scenario 2 - inject DNAME/net2. ($n)"
+ ret=0
+ # prime
+ dig_with_opts @10.53.0.9 attackSecureDomain.net2 > dig.out.$n.prime || ret=1
+ # check that net2/DNAME is not cached
+ dig_with_opts @10.53.0.9 net2. DNAME > dig.out.$n.net2 || ret=1
+ grep "ANSWER: 0," dig.out.$n.net2 > /dev/null || ret=1
+ grep "status: NXDOMAIN" dig.out.$n.net2 > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking spoofed response scenario 3 - extra answer ($n)"
+ ret=0
+ # prime
+ dig_with_opts @10.53.0.9 attackSecureDomain.net3 > dig.out.$n.prime || ret=1
+ # check extra net3 records are not cached
+ rndccmd 10.53.0.9 dumpdb -cache 2>&1 | sed 's/^/ns9 /' | cat_i
+ for try in 1 2 3 4 5; do
+ lines=$(grep "net3" ns9/named_dump.db | wc -l)
+ if [ ${lines} -eq 0 ]; then
+ sleep 1
+ continue
+ fi
+ [ ${lines} -eq 1 ] || ret=1
+ grep -q '^attackSecureDomain.net3' ns9/named_dump.db || ret=1
+ grep -q '^local.net3' ns9/named_dump.db && ret=1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+}
+
+echo_i "checking spoofed response scenarios with forward first zones"
+run_spooftests
+
+copy_setports ns9/named2.conf.in ns9/named.conf
+rndccmd 10.53.0.9 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+rndccmd 10.53.0.9 flush 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 1
+
+echo_i "rechecking spoofed response scenarios with forward only zones"
+run_spooftests
+
+#
+# This scenario expects the spoofed response to succeed. The tests are
+# similar to the ones above, but not identical.
+#
+echo_i "rechecking spoofed response scenarios with 'forward only' set globally"
+copy_setports ns9/named3.conf.in ns9/named.conf
+rndccmd 10.53.0.9 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+rndccmd 10.53.0.9 flush 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 1
+
+n=$((n+1))
+echo_i "checking spoofed response scenario 1 - out of bailiwick NS ($n)"
+ret=0
+# prime
+dig_with_opts @10.53.0.9 attackSecureDomain.net > dig.out.$n.prime || ret=1
+# check 'net' is poisoned.
+dig_with_opts @10.53.0.9 diditwork.net. TXT > dig.out.$n.net || ret=1
+grep '^didItWork\.net\..*TXT.*"if you can see this record the attack worked"' dig.out.$n.net > /dev/null || ret=1
+# check 'sub.local.net' is poisoned.
+dig_with_opts @10.53.0.9 sub.local.net TXT > dig.out.$n.sub || ret=1
+grep '^sub\.local\.net\..*TXT.*"if you see this attacker overrode local delegation"' dig.out.$n.sub > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking spoofed response scenario 2 - inject DNAME/net2. ($n)"
+ret=0
+# prime
+dig_with_opts @10.53.0.9 attackSecureDomain.net2 > dig.out.$n.prime || ret=1
+# check that net2/DNAME is cached
+dig_with_opts @10.53.0.9 net2. DNAME > dig.out.$n.net2 || ret=1
+grep "ANSWER: 1," dig.out.$n.net2 > /dev/null || ret=1
+grep "net2\..*IN.DNAME.net\.example\.lll\." dig.out.$n.net2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#
+# This test doesn't use any forwarder clauses but is here because it
+# is similar to forwarders, as the set of servers that can populate
+# the namespace is defined by the zone content.
+#
+echo_i "rechecking spoofed response scenarios glue below local zone"
+copy_setports ns9/named4.conf.in ns9/named.conf
+rndccmd 10.53.0.9 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+rndccmd 10.53.0.9 flush 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 1
+
+n=$((n+1))
+echo_i "checking sibling glue below zone ($n)"
+ret=0
+# prime
+dig_with_opts @10.53.0.9 sibling.tld > dig.out.$n.prime || ret=1
+# check for glue A record for sub.local.tld is not used
+dig_with_opts @10.53.0.9 sub.local.tld TXT > dig.out.$n.sub || ret=1
+grep "ANSWER: 1," dig.out.$n.sub > /dev/null || ret=1
+grep 'sub\.local\.tld\..*IN.TXT."good"$' dig.out.$n.sub > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/forward/tests_sh_forward.py b/bin/tests/system/forward/tests_sh_forward.py
new file mode 100644
index 0000000..4380a49
--- /dev/null
+++ b/bin/tests/system/forward/tests_sh_forward.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_forward(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/forward/ula-inherited.conf b/bin/tests/system/forward/ula-inherited.conf
new file mode 100644
index 0000000..1fb94b1
--- /dev/null
+++ b/bin/tests/system/forward/ula-inherited.conf
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone d.f.ip6.arpa {
+ type forward;
+ forwarders { 1.2.3.4; };
+};
diff --git a/bin/tests/system/forward/ula-notinherited.conf b/bin/tests/system/forward/ula-notinherited.conf
new file mode 100644
index 0000000..300001a
--- /dev/null
+++ b/bin/tests/system/forward/ula-notinherited.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone d.f.ip6.arpa {
+ type forward;
+ forward first;
+ forwarders { 1.2.3.4; };
+};
diff --git a/bin/tests/system/fromhex.pl b/bin/tests/system/fromhex.pl
new file mode 100644
index 0000000..2a229e0
--- /dev/null
+++ b/bin/tests/system/fromhex.pl
@@ -0,0 +1,47 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Converts hex ascii into raw data.
+# (This can be used, for example, to construct input for "wire_data -d".)
+
+require 5.006.001;
+
+use strict;
+use IO::File;
+
+sub usage {
+ print ("Usage: packet.pl [file]\n");
+ exit 1;
+}
+
+my $file = "STDIN";
+if (@ARGV >= 1) {
+ my $filename = shift @ARGV;
+ open FH, "<$filename" or die "$filename: $!";
+ $file = "FH";
+}
+
+my $input = "";
+while (defined(my $line = <$file>) ) {
+ chomp $line;
+ $line =~ s/#.*$//;
+ $input .= $line;
+}
+
+$input =~ s/\s+//g;
+my $data = pack("H*", $input);
+my $len = length $data;
+
+binmode(STDOUT);
+print($data);
+exit(0);
diff --git a/bin/tests/system/genzone.sh b/bin/tests/system/genzone.sh
new file mode 100644
index 0000000..f436559
--- /dev/null
+++ b/bin/tests/system/genzone.sh
@@ -0,0 +1,511 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Set up a test zone
+#
+# Usage: genzone.sh primary-server-number secondary-server-number...
+#
+# e.g., "genzone.sh 2 3 4" means ns2 is the primary and ns3, ns4
+# are secondaries.
+#
+
+primary="$1"
+
+cat <<EOF
+\$TTL 3600
+
+@ 86400 IN SOA ns${primary} hostmaster (
+ 1397051952 ; "SER0"
+ 5
+ 5
+ 1814400
+ 3600 )
+EOF
+
+for n
+do
+ cat <<EOF
+@ NS ns${n}
+ns${n} A 10.53.0.${n}
+EOF
+done
+
+cat <<\EOF
+
+; type 1
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+
+; type 2
+; see NS records at top of file
+
+; type 3
+; md01 MD madname
+; MD .
+
+; type 4
+; mf01 MF madname
+; mf01 MF .
+
+; type 5
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+
+; type 6
+; see SOA record at top of file
+
+; type 7
+mb01 MG madname
+mb02 MG .
+
+; type 8
+mg01 MG mgmname
+mg02 MG .
+
+; type 9
+mr01 MR mrname
+mr02 MR .
+
+; type 10
+; NULL RRs are not allowed in master files per RFC1035.
+;null01 NULL
+
+; type 11
+wks01 WKS 10.0.0.1 tcp telnet ftp 0 1 2
+wks02 WKS 10.0.0.1 udp domain 0 1 2
+wks03 WKS 10.0.0.2 tcp 65535
+
+; type 12
+ptr01 PTR @
+
+; type 13
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO PC NetBSD
+
+; type 14
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+
+; type 15
+mx01 MX 10 mail
+mx02 MX 10 .
+
+; type 16
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT foo
+txt04 TXT foo bar
+txt05 TXT "foo bar"
+txt06 TXT "foo\032bar"
+txt07 TXT foo\032bar
+txt08 TXT "foo\010bar"
+txt09 TXT foo\010bar
+txt10 TXT foo\ bar
+txt11 TXT "\"foo\""
+txt12 TXT \"foo\"
+txt13 TXT "foo;"
+txt14 TXT "foo\;"
+txt15 TXT "bar\\;"
+
+; type 17
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+
+; type 18
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+
+; type 19
+x2501 X25 123456789
+;x2502 X25 "123456789"
+
+; type 20
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN isdn-address
+isdn04 ISDN isdn-address subaddress
+
+; type 21
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+
+; type 22
+nsap01 NSAP (
+ 0x47.0005.80.005a00.0000.0001.e133.ffffff000161.00 )
+nsap02 NSAP (
+ 0x47.0005.80.005a00.0000.0001.e133.ffffff000161.00. )
+;nsap03 NSAP 0x
+
+; type 23
+nsap-ptr01 NSAP-PTR foo.
+nsap-ptr01 NSAP-PTR .
+
+; type 24
+;sig01 SIG NXT 1 3 ( 3600 20000102030405
+; 19961211100908 2143 foo.nil.
+; MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45I
+; kskceFGgiWCn/GxHhai6VAuHAoNUz4YoU1t
+; VfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= )
+
+; type 25
+;key01 KEY 512 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY
+; 9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV
+; sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg
+; a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= )
+
+; type 26
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+
+; type 27
+gpos01 GPOS -22.6882 116.8652 250.0
+gpos02 GPOS "" "" ""
+
+; type 28
+aaaa01 AAAA ::1
+aaaa02 AAAA fd92:7065:b8e:ffff::5
+
+; type 29
+loc01 LOC 60 9 N 24 39 E 10 20 2000 20
+loc02 LOC 60 09 00.000 N 24 39 00.000 E 10.00m 20.00m (
+ 2000.00m 20.00m )
+
+; type 30
+;nxt01 NXT a.secure.nil. ( NS SOA MX RRSIG KEY LOC NXT )
+;nxt02 NXT . NXT NSAP-PTR
+;nxt03 NXT . 1
+;nxt04 NXT . 127
+
+; type 31
+eid01 EID 12 89 AB
+
+; type 32
+nimloc01 NIMLOC 12 89 AB
+
+; type 33
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box
+
+; type 34
+atma01 ATMA +61200000000
+atma02 ATMA +61.2.0000.0000
+atma03 ATMA 1234567890abcdef
+atma04 ATMA f.e.d.c.b.a.0.9.8.7.6.5.4.3.2.1
+
+; type 35
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 blurgh blorf blllbb foo.
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+
+; type 36
+kx01 KX 10 kdc
+kx02 KX 10 .
+
+; type 37
+cert01 CERT 65534 65535 254 (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45I
+ kskceFGgiWCn/GxHhai6VAuHAoNUz4YoU1t
+ VfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= )
+; type 38
+a601 A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+a601 A6 64 ::ffff:ffff:ffff:ffff foo.
+a601 A6 127 ::1 foo.
+a601 A6 128 .
+
+; type 39
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+
+; type 40
+sink01 SINK 1 0 0
+sink02 SINK 8 0 2 l4ik
+
+; type 41
+; OPT is a meta-type and should never occur in master files.
+
+; type 42
+apl01 APL !1:10.0.0.1/32 1:10.0.0.0/24
+apl02 APL
+
+; type 43
+ds01 DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13
+ds01 NS ns42
+ds02 DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390
+ds02 NS ns43
+
+; type 44
+sshfp01 SSHFP 4 2 C76D8329954DA2835751E371544E963EFDA099080D6C58DD2BFD9A31 6E162C83
+sshfp02 SSHFP 1 2 BF29468C83AC58CCF8C85AB7B3BEB054ECF1E38512B8353AB36471FA 88961DCC
+
+; type 45
+ipseckey01 IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey02 IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey03 IPSECKEY ( 10 1 2
+ 192.0.2.3
+ AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )
+ipseckey04 IPSECKEY ( 10 3 2
+ mygateway.example.com.
+ AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )
+
+ipseckey05 IPSECKEY ( 10 2 2
+ 2001:0DB8:0:8002::2000:1
+ AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )
+
+; type 46
+rrsig01 RRSIG NSEC 1 3 ( 3600 20000102030405
+ 19961211100908 2143 foo.nil.
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45I
+ kskceFGgiWCn/GxHhai6VAuHAoNUz4YoU1t
+ VfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= )
+
+; type 47
+nsec01 NSEC a.secure.nil. ( NS SOA MX RRSIG DNSKEY LOC NSEC )
+nsec02 NSEC . NSEC NSAP-PTR
+nsec03 NSEC . TYPE1
+nsec04 NSEC . TYPE127
+
+; type 48
+dnskey01 DNSKEY 512 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY
+ 9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV
+ sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg
+ a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= )
+
+; type 49
+dhcid01 DHCID ( AAIBY2/AuCccgoJbsaxcQc9TUapptP69l
+ OjxfNuVAA2kjEA= )
+dhcid02 DHCID ( AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQdW
+ L3b/NaiUDlW2No= )
+dhcid03 DHCID ( AAABxLmlskllE0MVjd57zHcWmEH3pCQ6V
+ ytcKD//7es/deY= )
+
+; type 50
+8f1tmio9avcom2k0frp92lgcumak0cad NSEC3 1 0 10 D2CF0294C020CE6C 8FPNS2UCT7FBS643THP2B77PEQ77K6IU A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
+kcd3juae64f9c5csl1kif1htaui7un0g NSEC3 1 0 10 D2CF0294C020CE6C KD5MN2M20340DGO0BL7NTSB8JP4BSC7E
+mr5ukvsk1l37btu4q7b1dfevft4hkqdk NSEC3 1 0 10 D2CF0294C020CE6C MT38J6VG7S0SN5G17MCUF6IQIKFUAJ05 A AAAA RRSIG
+
+; type 51
+; @ NSEC3PARAM 1 0 1 868BCF7ED4108929
+
+; type 52
+tlsa TLSA ( 1 1 2 92003ba34942dc74152e2f2c408d29ec
+ a5a520e7f2e06bb944f4dca346baf63c
+ 1b177615d466f6c4b71c216a50292bd5
+ 8c9ebdd2f74e38fe51ffd48c43326cbc )
+
+; type 53
+smimea SMIMEA ( 1 1 2 92003ba34942dc74152e2f2c408d29ec
+ a5a520e7f2e06bb944f4dca346baf63c
+ 1b177615d466f6c4b71c216a50292bd5
+ 8c9ebdd2f74e38fe51ffd48c43326cbc )
+
+; type 54 (unassigned)
+
+; type 55
+hip1 HIP ( 2 200100107B1A74DF365639CC39F1D578
+ AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D )
+
+hip2 HIP ( 2 200100107B1A74DF365639CC39F1D578
+ AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
+ rvs.example.com. )
+
+; type 56
+ninfo01 NINFO "foo"
+ninfo02 NINFO "foo" "bar"
+ninfo03 NINFO foo
+ninfo04 NINFO foo bar
+ninfo05 NINFO "foo bar"
+ninfo06 NINFO "foo\032bar"
+ninfo07 NINFO foo\032bar
+ninfo08 NINFO "foo\010bar"
+ninfo09 NINFO foo\010bar
+ninfo10 NINFO foo\ bar
+ninfo11 NINFO "\"foo\""
+ninfo12 NINFO \"foo\"
+ninfo13 NINFO "foo;"
+ninfo14 NINFO "foo\;"
+ninfo15 NINFO "bar\\;"
+
+; type 57
+rkey01 RKEY 0 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY
+ 9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV
+ sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg
+ a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= )
+
+; type 58
+talink0 TALINK . talink1
+talink1 TALINK talink0 talink2
+talink2 TALINK talink2 .
+
+; type 59
+cds01 CDS 30795 1 1 (
+ 310D27F4D82C1FC2400704EA9939FE6E1CEA
+ A3B9 )
+
+; type 60
+cdnskey01 CDNSKEY 512 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY
+ 9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV
+ sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg
+ a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= )
+
+; type 61
+openpgpkey OPENPGPKEY ( AQMFD5raczCJHViKtLYhWGz8hMY
+ 9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV
+ sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg
+ a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= )
+
+;type 62
+csync01 CSYNC 0 0 A NS AAAA
+csync02 CSYNC 0 0
+
+;type 63
+zonemd01 ZONEMD 2019020700 1 1 (
+ C220B8A6ED5728A971902F7E3D4FD93A
+ DEEA88B0453C2E8E8C863D465AB06CF3
+ 4EB95B266398C98B59124FA239CB7EEB
+ )
+zonemd02 ZONEMD 2019020700 1 2 (
+ 08CFA1115C7B948C4163A901270395EA
+ 226A930CD2CBCF2FA9A5E6EB85F37C8A
+ 4E114D884E66F176EAB121CB02DB7D65
+ 2E0CC4827E7A3204F166B47E5613FD27
+ )
+
+; type 64 -- 98 (unassigned)
+
+; type 99
+spf01 SPF "v=spf1 -all"
+spf02 SPF "v=spf1" " -all"
+
+; type 100 (UINFO - not implemented by BIND - unknown record format only)
+uinfo01 UINFO \# 1 01
+
+; type 101 (UID - not implemented by BIND - unknown record format only)
+uid01 UID \# 1 02
+
+; type 102 (GID - not implemented by BIND - unknown record format only)
+gid01 GID \# 1 03
+
+; type 103 (UNSPEC - not implemented by BIND - unknown record format only)
+unspec01 UNSPEC \# 1 04
+
+; type 104
+nid NID 10 0014:4fff:ff20:ee64
+
+; type 105
+l32 L32 10 1.2.3.4
+
+; type 106
+l64 L64 10 0014:4fff:ff20:ee64
+
+; type 107
+lp LP 10 example.net.
+
+; type 108
+eui48 EUI48 01-23-45-67-89-ab
+
+; type 109
+eui64 EUI64 01-23-45-67-89-ab-cd-ef
+
+; type 110 -- 248 (unassigned)
+
+; type 249
+; TKEY is a meta-type and should never occur in master files.
+; The text representation is not specified in the draft.
+; This example was written based on the bind9 RR parsing code.
+;tkey01 TKEY 928321914 928321915 (
+; algorithm-name. ; algorithm
+; 65535 ; mode
+; 0 ; error
+; 3 ; key size
+; aaaa ; key data
+; 3 ; other size
+; bbbb ; other data
+; )
+;; A TKEY with empty "other data"
+;tkey02 TKEY 928321914 928321915 (
+; algorithm-name. ; algorithm
+; 65535 ; mode
+; 0 ; error
+; 3 ; key size
+; aaaa ; key data
+; 0 ; other size
+; ; other data
+; )
+
+; type 255
+; * is a meta-type and should never occur in master files.
+
+; type 256
+uri01 URI 10 20 "https://www.isc.org/"
+uri02 URI 30 40 "https://www.isc.org/HolyCowThisSureIsAVeryLongURIRecordIDontEvenKnowWhatSomeoneWouldEverWantWithSuchAThingButTheSpecificationRequiresThatWesupportItSoHereWeGoTestingItLaLaLaLaLaLaLaSeriouslyThoughWhyWouldYouEvenConsiderUsingAURIThisLongItSeemsLikeASillyIdeaButEnhWhatAreYouGonnaDo/"
+uri03 URI 30 40 ""
+
+; type 257
+caa01 CAA 0 issue "ca.example.net; policy=ev"
+caa02 CAA 128 tbs "Unknown"
+caa03 CAA 128 tbs ""
+
+; type 258
+avc AVC foo:bar
+
+; type 259
+doa01 DOA ( 1234567890 1234567890 1 "image/gif"
+ R0lGODlhKAAZAOMCAGZmZgBmmf///zOZzMz//5nM/zNmmWbM/5nMzMzMzACZ////
+ /////////////////yH5BAEKAA8ALAAAAAAoABkAAATH8IFJK5U2a4337F5ogRkp
+ noCJrly7PrCKyh8c3HgAhzT35MDbbtO7/IJIHbGiOiaTxVTpSVWWLqNq1UVyapNS
+ 1wd3OAxug0LhnCubcVhsxysQnOt4ATpvvzHlFzl1AwODhWeFAgRpen5/UhheAYMF
+ dUB4SFcpGEGGdQeCAqBBLTuSk30EeXd9pEsAbKGxjHqDSE0Sp6ixN4N1BJmbc7lI
+ hmsBich1awPAjkY1SZR8bJWrz382SGqIBQQFQd4IsUTaX+ceuudPEQA7 )
+doa02 DOA 0 1 2 "" aHR0cHM6Ly93d3cuaXNjLm9yZy8=
+
+; type 260
+amtrelay01 AMTRELAY 0 0 0
+amtrelay02 AMTRELAY 0 1 0
+amtrelay03 AMTRELAY 0 0 1 0.0.0.0
+amtrelay04 AMTRELAY 0 0 2 ::
+amtrelay05 AMTRELAY 0 0 3 example.net.
+amtrelay06 AMTRELAY \# 2 0004
+
+; type 261 -- 32767 (unassigned)
+
+; type 32768
+ta TA 30795 1 1 (
+ 310D27F4D82C1FC2400704EA9939FE6E1CEA
+ A3B9 )
+
+; type 32769
+dlv DLV 30795 1 1 (
+ 310D27F4D82C1FC2400704EA9939FE6E1CEA
+ A3B9 )
+
+; type 32770 -- 65279 (unassigned)
+
+; type 65280-65534 (private use)
+
+https0 HTTPS 0 example.net.
+https1 HTTPS 1 . port=60
+
+svcb0 SVCB 0 example.net.
+svcb1 SVCB 1 . port=60
+
+; keydata (internal type used for managed keys)
+keydata TYPE65533 \# 0
+keydata TYPE65533 \# 6 010203040506
+keydata TYPE65533 \# 18 010203040506010203040506010203040506
+
+; type 65535 (reserved)
+
+EOF
diff --git a/bin/tests/system/geoip2/clean.sh b/bin/tests/system/geoip2/clean.sh
new file mode 100644
index 0000000..46de65b
--- /dev/null
+++ b/bin/tests/system/geoip2/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns2/named.conf
+rm -f ns2/example*.db
+rm -f dig.out.* rndc.out.*
+rm -f ns?/named.run
+rm -f ns?/named.memstats
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
diff --git a/bin/tests/system/geoip2/conf/bad-areacode.conf b/bin/tests/system/geoip2/conf/bad-areacode.conf
new file mode 100644
index 0000000..2ca9dd4
--- /dev/null
+++ b/bin/tests/system/geoip2/conf/bad-areacode.conf
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ geoip-directory "data";
+ allow-query {
+ geoip area 831;
+ geoip areacode 831;
+ geoip metro 828;
+ geoip metrocode 828;
+ geoip tz "America/Los_Angeles";
+ geoip timezone "America/Los_Angeles";
+ geoip postal 95060;
+ geoip postalcode 95060;
+ };
+};
diff --git a/bin/tests/system/geoip2/conf/bad-dbname.conf b/bin/tests/system/geoip2/conf/bad-dbname.conf
new file mode 100644
index 0000000..9fc5238
--- /dev/null
+++ b/bin/tests/system/geoip2/conf/bad-dbname.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+};
+
+view one {
+ match-clients { geoip db unknown asnum "WX"; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
diff --git a/bin/tests/system/geoip2/conf/bad-netspeed.conf b/bin/tests/system/geoip2/conf/bad-netspeed.conf
new file mode 100644
index 0000000..133fd42
--- /dev/null
+++ b/bin/tests/system/geoip2/conf/bad-netspeed.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ geoip-directory "data";
+ allow-query {
+ geoip netspeed 100;
+ geoip metro 828;
+ geoip metrocode 828;
+ geoip tz "America/Los_Angeles";
+ geoip timezone "America/Los_Angeles";
+ geoip postal 95060;
+ geoip postalcode 95060;
+ };
+};
diff --git a/bin/tests/system/geoip2/conf/bad-regiondb.conf b/bin/tests/system/geoip2/conf/bad-regiondb.conf
new file mode 100644
index 0000000..62a93cd
--- /dev/null
+++ b/bin/tests/system/geoip2/conf/bad-regiondb.conf
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip db region region "California"; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
diff --git a/bin/tests/system/geoip2/conf/bad-threeletter.conf b/bin/tests/system/geoip2/conf/bad-threeletter.conf
new file mode 100644
index 0000000..ec0a9df
--- /dev/null
+++ b/bin/tests/system/geoip2/conf/bad-threeletter.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+view one {
+ match-clients { geoip db country country AUS; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
diff --git a/bin/tests/system/geoip2/conf/good-options.conf b/bin/tests/system/geoip2/conf/good-options.conf
new file mode 100644
index 0000000..02c5e5d
--- /dev/null
+++ b/bin/tests/system/geoip2/conf/good-options.conf
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ geoip-directory "data";
+ allow-query {
+ geoip metro 828;
+ geoip metrocode 828;
+ geoip tz "America/Los_Angeles";
+ geoip timezone "America/Los_Angeles";
+ geoip postal 95060;
+ geoip postalcode 95060;
+ };
+};
diff --git a/bin/tests/system/geoip2/data/GeoIP2-City.json b/bin/tests/system/geoip2/data/GeoIP2-City.json
new file mode 100644
index 0000000..5490d42
--- /dev/null
+++ b/bin/tests/system/geoip2/data/GeoIP2-City.json
@@ -0,0 +1,506 @@
+[
+ {
+ "::10.53.0.1/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Redwood City"
+ }
+ },
+ "location" : {
+ "metro_code" : "807",
+ "time_zone" : "America/Los_Angeles"
+ },
+ "postal" : {
+ "code" : "94063"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "CA",
+ "names" : {
+ "en" : "California"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "::10.53.0.2/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Santa Cruz"
+ }
+ },
+ "location" : {
+ "metro_code" : "828",
+ "time_zone" : "America/Los_Angeles"
+ },
+ "postal" : {
+ "code" : "95060"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "CA",
+ "names" : {
+ "en" : "California"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "::10.53.0.3/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Oklahoma City"
+ }
+ },
+ "location" : {
+ "metro_code" : "650",
+ "time_zone" : "America/Chicago"
+ },
+ "postal" : {
+ "code" : "73120"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "OK",
+ "names" : {
+ "en" : "Oklahoma"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "::10.53.0.4/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Ashland"
+ }
+ },
+ "location" : {
+ "metro_code" : "556",
+ "time_zone" : "America/New_York"
+ },
+ "postal" : {
+ "code" : "23005"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "VA",
+ "names" : {
+ "en" : "Virginia"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "::10.53.0.5/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Atlanta"
+ }
+ },
+ "location" : {
+ "metro_code" : "524",
+ "time_zone" : "America/New_York"
+ },
+ "postal" : {
+ "code" : "30345"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "GA",
+ "names" : {
+ "en" : "Georgia"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "::10.53.0.6/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Morrison"
+ }
+ },
+ "location" : {
+ "metro_code" : "751",
+ "time_zone" : "America/Denver"
+ },
+ "postal" : {
+ "code" : "80465"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "CO",
+ "names" : {
+ "en" : "Colorado"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "::10.53.0.7/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Ketchikan"
+ }
+ },
+ "location" : {
+ "metro_code" : "747",
+ "time_zone" : "America/Anchorage"
+ },
+ "postal" : {
+ "code" : "99901"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "AK",
+ "names" : {
+ "en" : "Alaska"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::1/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Redwood City"
+ }
+ },
+ "location" : {
+ "metro_code" : "807",
+ "time_zone" : "America/Los_Angeles"
+ },
+ "postal" : {
+ "code" : "94063"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "CA",
+ "names" : {
+ "en" : "California"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::2/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Santa Cruz"
+ }
+ },
+ "location" : {
+ "metro_code" : "828",
+ "time_zone" : "America/Los_Angeles"
+ },
+ "postal" : {
+ "code" : "95060"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "CA",
+ "names" : {
+ "en" : "California"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::3/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Oklahoma City"
+ }
+ },
+ "location" : {
+ "metro_code" : "650",
+ "time_zone" : "America/Chicago"
+ },
+ "postal" : {
+ "code" : "73120"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "OK",
+ "names" : {
+ "en" : "Oklahoma"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::4/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Ashland"
+ }
+ },
+ "location" : {
+ "metro_code" : "556",
+ "time_zone" : "America/New_York"
+ },
+ "postal" : {
+ "code" : "23005"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "VA",
+ "names" : {
+ "en" : "Virginia"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::5/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Atlanta"
+ }
+ },
+ "location" : {
+ "metro_code" : "524",
+ "time_zone" : "America/New_York"
+ },
+ "postal" : {
+ "code" : "30345"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "GA",
+ "names" : {
+ "en" : "Georgia"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::6/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Morrison"
+ }
+ },
+ "location" : {
+ "metro_code" : "751",
+ "time_zone" : "America/Denver"
+ },
+ "postal" : {
+ "code" : "80465"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "CO",
+ "names" : {
+ "en" : "Colorado"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::7/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ },
+ "city" : {
+ "names" : {
+ "en" : "Ketchikan"
+ }
+ },
+ "location" : {
+ "metro_code" : "747",
+ "time_zone" : "America/Anchorage"
+ },
+ "postal" : {
+ "code" : "99901"
+ },
+ "subdivisions" : [
+ {
+ "iso_code" : "AK",
+ "names" : {
+ "en" : "Alaska"
+ }
+ }
+ ]
+ }
+ }
+]
diff --git a/bin/tests/system/geoip2/data/GeoIP2-City.mmdb b/bin/tests/system/geoip2/data/GeoIP2-City.mmdb
new file mode 100644
index 0000000..79c5314
--- /dev/null
+++ b/bin/tests/system/geoip2/data/GeoIP2-City.mmdb
Binary files differ
diff --git a/bin/tests/system/geoip2/data/GeoIP2-Country.json b/bin/tests/system/geoip2/data/GeoIP2-Country.json
new file mode 100644
index 0000000..83a8ca8
--- /dev/null
+++ b/bin/tests/system/geoip2/data/GeoIP2-Country.json
@@ -0,0 +1,242 @@
+[
+ {
+ "::10.53.0.1/128" : {
+ "continent" : {
+ "code" : "OC",
+ "names" : {
+ "en" : "Oceania"
+ }
+ },
+ "country" : {
+ "iso_code" : "AU",
+ "names" : {
+ "en" : "Australia"
+ }
+ }
+ }
+ },
+ {
+ "::10.53.0.2/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ }
+ }
+ },
+ {
+ "::10.53.0.3/128" : {
+ "continent" : {
+ "code" : "EU",
+ "names" : {
+ "en" : "Europe"
+ }
+ },
+ "country" : {
+ "iso_code" : "GB",
+ "names" : {
+ "en" : "United Kingdom"
+ }
+ }
+ }
+ },
+ {
+ "::10.53.0.4/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "CA",
+ "names" : {
+ "en" : "Canada"
+ }
+ }
+ }
+ },
+ {
+ "::10.53.0.5/128" : {
+ "continent" : {
+ "code" : "SA",
+ "names" : {
+ "en" : "South America"
+ }
+ },
+ "country" : {
+ "iso_code" : "CL",
+ "names" : {
+ "en" : "Chile"
+ }
+ }
+ }
+ },
+ {
+ "::10.53.0.6/128" : {
+ "continent" : {
+ "code" : "EU",
+ "names" : {
+ "en" : "Europe"
+ }
+ },
+ "country" : {
+ "iso_code" : "DE",
+ "names" : {
+ "en" : "Germany"
+ }
+ }
+ }
+ },
+ {
+ "::10.53.0.7/128" : {
+ "continent" : {
+ "code" : "AF",
+ "names" : {
+ "en" : "Africa"
+ }
+ },
+ "country" : {
+ "iso_code" : "EH",
+ "names" : {
+ "en" : "Western Sahara"
+ }
+ }
+ }
+ },
+ {
+ "::192.0.2.0/120" : {
+ "continent" : {
+ "code" : "O1",
+ "names" : {
+ "en" : "Other"
+ }
+ },
+ "country" : {
+ "iso_code" : "O1",
+ "names" : {
+ "en" : "Other"
+ }
+ }
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::1/128" : {
+ "continent" : {
+ "code" : "OC",
+ "names" : {
+ "en" : "Oceania"
+ }
+ },
+ "country" : {
+ "iso_code" : "AU",
+ "names" : {
+ "en" : "Australia"
+ }
+ }
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::2/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "US",
+ "names" : {
+ "en" : "United States"
+ }
+ }
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::3/128" : {
+ "continent" : {
+ "code" : "EU",
+ "names" : {
+ "en" : "Europe"
+ }
+ },
+ "country" : {
+ "iso_code" : "GB",
+ "names" : {
+ "en" : "United Kingdom"
+ }
+ }
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::4/128" : {
+ "continent" : {
+ "code" : "NA",
+ "names" : {
+ "en" : "North America"
+ }
+ },
+ "country" : {
+ "iso_code" : "CA",
+ "names" : {
+ "en" : "Canada"
+ }
+ }
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::5/128" : {
+ "continent" : {
+ "code" : "SA",
+ "names" : {
+ "en" : "South America"
+ }
+ },
+ "country" : {
+ "iso_code" : "CL",
+ "names" : {
+ "en" : "Chile"
+ }
+ }
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::6/128" : {
+ "continent" : {
+ "code" : "EU",
+ "names" : {
+ "en" : "Europe"
+ }
+ },
+ "country" : {
+ "iso_code" : "DE",
+ "names" : {
+ "en" : "Germany"
+ }
+ }
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::7/128" : {
+ "continent" : {
+ "code" : "AF",
+ "names" : {
+ "en" : "Africa"
+ }
+ },
+ "country" : {
+ "iso_code" : "EH",
+ "names" : {
+ "en" : "Western Sahara"
+ }
+ }
+ }
+ }
+]
diff --git a/bin/tests/system/geoip2/data/GeoIP2-Country.mmdb b/bin/tests/system/geoip2/data/GeoIP2-Country.mmdb
new file mode 100644
index 0000000..7771dc7
--- /dev/null
+++ b/bin/tests/system/geoip2/data/GeoIP2-Country.mmdb
Binary files differ
diff --git a/bin/tests/system/geoip2/data/GeoIP2-Domain.json b/bin/tests/system/geoip2/data/GeoIP2-Domain.json
new file mode 100644
index 0000000..fb8e914
--- /dev/null
+++ b/bin/tests/system/geoip2/data/GeoIP2-Domain.json
@@ -0,0 +1,72 @@
+[
+ {
+ "::10.53.0.1/128" : {
+ "domain" : "one.de"
+ }
+ },
+ {
+ "::10.53.0.2/128" : {
+ "domain" : "two.com"
+ }
+ },
+ {
+ "::10.53.0.3/128" : {
+ "domain" : "three.com"
+ }
+ },
+ {
+ "::10.53.0.4/128" : {
+ "domain" : "four.edu"
+ }
+ },
+ {
+ "::10.53.0.5/128" : {
+ "domain" : "five.es"
+ }
+ },
+ {
+ "::10.53.0.6/128" : {
+ "domain" : "six.it"
+ }
+ },
+ {
+ "::10.53.0.7/128" : {
+ "domain" : "seven.org"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::1/128" : {
+ "domain" : "one.de"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::2/128" : {
+ "domain" : "two.com"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::3/128" : {
+ "domain" : "three.com"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::4/128" : {
+ "domain" : "four.edu"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::5/128" : {
+ "domain" : "five.es"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::6/128" : {
+ "domain" : "six.it"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::7/128" : {
+ "domain" : "seven.org"
+ }
+ }
+]
diff --git a/bin/tests/system/geoip2/data/GeoIP2-Domain.mmdb b/bin/tests/system/geoip2/data/GeoIP2-Domain.mmdb
new file mode 100644
index 0000000..fe93dec
--- /dev/null
+++ b/bin/tests/system/geoip2/data/GeoIP2-Domain.mmdb
Binary files differ
diff --git a/bin/tests/system/geoip2/data/GeoIP2-ISP.json b/bin/tests/system/geoip2/data/GeoIP2-ISP.json
new file mode 100644
index 0000000..c6b0a5d
--- /dev/null
+++ b/bin/tests/system/geoip2/data/GeoIP2-ISP.json
@@ -0,0 +1,86 @@
+[
+ {
+ "::10.53.0.1/128" : {
+ "isp" : "One Systems, Inc.",
+ "organization" : "One Systems, Inc."
+ }
+ },
+ {
+ "::10.53.0.2/128" : {
+ "isp" : "Two Technology Ltd.",
+ "organization" : "Two Technology Ltd."
+ }
+ },
+ {
+ "::10.53.0.3/128" : {
+ "isp" : "Three Network Labs",
+ "organization" : "Three Network Labs"
+ }
+ },
+ {
+ "::10.53.0.4/128" : {
+ "isp" : "Four University",
+ "organization" : "Four University"
+ }
+ },
+ {
+ "::10.53.0.5/128" : {
+ "isp" : "Five Telecom",
+ "organization" : "Five Telecom"
+ }
+ },
+ {
+ "::10.53.0.6/128" : {
+ "isp" : "Six Company",
+ "organization" : "Six Company"
+ }
+ },
+ {
+ "::10.53.0.7/128" : {
+ "isp" : "Seven Communications",
+ "organization" : "Seven Communications"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::1/128" : {
+ "isp" : "One Systems, Inc.",
+ "organization" : "One Systems, Inc."
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::2/128" : {
+ "isp" : "Two Technology Ltd.",
+ "organization" : "Two Technology Ltd."
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::3/128" : {
+ "isp" : "Three Network Labs",
+ "organization" : "Three Network Labs"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::4/128" : {
+ "isp" : "Four University",
+ "organization" : "Four University"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::5/128" : {
+ "isp" : "Five Telecom",
+ "organization" : "Five Telecom"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::6/128" : {
+ "isp" : "Six Company",
+ "organization" : "Six Company"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::7/128" : {
+ "isp" : "Seven Communications",
+ "organization" : "Seven Communications"
+ }
+ }
+]
diff --git a/bin/tests/system/geoip2/data/GeoIP2-ISP.mmdb b/bin/tests/system/geoip2/data/GeoIP2-ISP.mmdb
new file mode 100644
index 0000000..73f0718
--- /dev/null
+++ b/bin/tests/system/geoip2/data/GeoIP2-ISP.mmdb
Binary files differ
diff --git a/bin/tests/system/geoip2/data/GeoLite2-ASN.json b/bin/tests/system/geoip2/data/GeoLite2-ASN.json
new file mode 100644
index 0000000..8fad0ce
--- /dev/null
+++ b/bin/tests/system/geoip2/data/GeoLite2-ASN.json
@@ -0,0 +1,86 @@
+[
+ {
+ "::10.53.0.1/128" : {
+ "autonomous_system_number" : 100001,
+ "autonomous_system_organization" : "One Systems, Inc."
+ }
+ },
+ {
+ "::10.53.0.2/128" : {
+ "autonomous_system_number" : 100002,
+ "autonomous_system_organization" : "Two Technology Ltd."
+ }
+ },
+ {
+ "::10.53.0.3/128" : {
+ "autonomous_system_number" : 100003,
+ "autonomous_system_organization" : "Three Network Labs"
+ }
+ },
+ {
+ "::10.53.0.4/128" : {
+ "autonomous_system_number" : 100004,
+ "autonomous_system_organization" : "Four University"
+ }
+ },
+ {
+ "::10.53.0.5/128" : {
+ "autonomous_system_number" : 100005,
+ "autonomous_system_organization" : "Five Telecom"
+ }
+ },
+ {
+ "::10.53.0.6/128" : {
+ "autonomous_system_number" : 100006,
+ "autonomous_system_organization" : "Six Company"
+ }
+ },
+ {
+ "::10.53.0.7/128" : {
+ "autonomous_system_number" : 100007,
+ "autonomous_system_organization" : "Seven Communications"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::1/128" : {
+ "autonomous_system_number" : 100001,
+ "autonomous_system_organization" : "One Systems, Inc."
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::2/128" : {
+ "autonomous_system_number" : 100002,
+ "autonomous_system_organization" : "Two Technology Ltd."
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::3/128" : {
+ "autonomous_system_number" : 100003,
+ "autonomous_system_organization" : "Three Network Labs"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::4/128" : {
+ "autonomous_system_number" : 100004,
+ "autonomous_system_organization" : "Four University"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::5/128" : {
+ "autonomous_system_number" : 100005,
+ "autonomous_system_organization" : "Five Telecom"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::6/128" : {
+ "autonomous_system_number" : 100006,
+ "autonomous_system_organization" : "Six Company"
+ }
+ },
+ {
+ "fd92:7065:b8e:ffff::7/128" : {
+ "autonomous_system_number" : 100007,
+ "autonomous_system_organization" : "Seven Communications"
+ }
+ }
+]
diff --git a/bin/tests/system/geoip2/data/GeoLite2-ASN.mmdb b/bin/tests/system/geoip2/data/GeoLite2-ASN.mmdb
new file mode 100644
index 0000000..05260c0
--- /dev/null
+++ b/bin/tests/system/geoip2/data/GeoLite2-ASN.mmdb
Binary files differ
diff --git a/bin/tests/system/geoip2/data/README.md b/bin/tests/system/geoip2/data/README.md
new file mode 100644
index 0000000..e326843
--- /dev/null
+++ b/bin/tests/system/geoip2/data/README.md
@@ -0,0 +1,23 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+##### Test MMDB databases
+
+This directory contains test versions of the GeoIP2/GeoLite2 CIty,
+Country, Domain, ISP, and ASN databases. The `.mmdb` files are built
+from the corresponding `.json` source files; to regenerate them, modify
+the source files and run `perl write-test-data.pl`.
+
+This script is adapted from one in
+[https://github.com/maxmind/MaxMind-DB](https://github.com/maxmind/MaxMind-DB).
+It depends on the MaxMind:DB:Writer module, which can be found in
+CPAN or at
+[https://github.com/maxmind/MaxMind-DB-Writer-perl](https://github.com/maxmind/MaxMind-DB-Writer-perl) .
diff --git a/bin/tests/system/geoip2/data/write-test-data.pl b/bin/tests/system/geoip2/data/write-test-data.pl
new file mode 100755
index 0000000..d12a014
--- /dev/null
+++ b/bin/tests/system/geoip2/data/write-test-data.pl
@@ -0,0 +1,194 @@
+#!/usr/bin/env perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+use warnings;
+use autodie;
+use utf8;
+
+use Carp qw( croak );
+use Cwd qw( abs_path );
+use File::Basename qw( dirname );
+use File::Slurper qw( read_binary write_binary );
+use Cpanel::JSON::XS qw( decode_json );
+use Math::Int128 qw( MAX_UINT128 string_to_uint128 uint128 );
+use MaxMind::DB::Writer::Serializer 0.100004;
+use MaxMind::DB::Writer::Tree 0.100004;
+use MaxMind::DB::Writer::Util qw( key_for_data );
+use Net::Works::Network;
+use Test::MaxMind::DB::Common::Util qw( standard_test_metadata );
+
+my $Dir = dirname( abs_path($0) );
+
+sub main {
+ write_geoip2_dbs();
+}
+
+sub write_geoip2_dbs {
+ _write_geoip2_db( @{$_}[ 0, 1 ], 'Test' )
+ for (
+ ['GeoIP2-City'],
+ ['GeoIP2-Country'],
+ ['GeoIP2-Domain'],
+ ['GeoIP2-ISP'],
+ ['GeoLite2-ASN'],
+ );
+}
+
+sub _universal_map_key_type_callback {
+ my $map = {
+
+ # languages
+ de => 'utf8_string',
+ en => 'utf8_string',
+ es => 'utf8_string',
+ fr => 'utf8_string',
+ ja => 'utf8_string',
+ 'pt-BR' => 'utf8_string',
+ ru => 'utf8_string',
+ 'zh-CN' => 'utf8_string',
+
+ # production
+ accuracy_radius => 'uint16',
+ autonomous_system_number => 'uint32',
+ autonomous_system_organization => 'utf8_string',
+ average_income => 'uint32',
+ city => 'map',
+ code => 'utf8_string',
+ confidence => 'uint16',
+ connection_type => 'utf8_string',
+ continent => 'map',
+ country => 'map',
+ domain => 'utf8_string',
+ geoname_id => 'uint32',
+ ipv4_24 => 'uint32',
+ ipv4_32 => 'uint32',
+ ipv6_32 => 'uint32',
+ ipv6_48 => 'uint32',
+ ipv6_64 => 'uint32',
+ is_anonymous => 'boolean',
+ is_anonymous_proxy => 'boolean',
+ is_anonymous_vpn => 'boolean',
+ is_hosting_provider => 'boolean',
+ is_in_european_union => 'boolean',
+ is_legitimate_proxy => 'boolean',
+ is_public_proxy => 'boolean',
+ is_satellite_provider => 'boolean',
+ is_tor_exit_node => 'boolean',
+ iso_code => 'utf8_string',
+ isp => 'utf8_string',
+ latitude => 'double',
+ location => 'map',
+ longitude => 'double',
+ metro_code => 'uint16',
+ names => 'map',
+ organization => 'utf8_string',
+ population_density => 'uint32',
+ postal => 'map',
+ registered_country => 'map',
+ represented_country => 'map',
+ subdivisions => [ 'array', 'map' ],
+ time_zone => 'utf8_string',
+ traits => 'map',
+ traits => 'map',
+ type => 'utf8_string',
+ user_type => 'utf8_string',
+
+ # for testing only
+ foo => 'utf8_string',
+ bar => 'utf8_string',
+ buzz => 'utf8_string',
+ our_value => 'utf8_string',
+ };
+
+ my $callback = sub {
+ my $key = shift;
+
+ return $map->{$key} || die <<"ERROR";
+Unknown tree key '$key'.
+
+The universal_map_key_type_callback doesn't know what type to use for the passed
+key. If you are adding a new key that will be used in a frozen tree / mmdb then
+you should update the mapping in both our internal code and here.
+ERROR
+ };
+
+ return $callback;
+}
+
+sub _write_geoip2_db {
+ my $type = shift;
+ my $populate_all_networks_with_data = shift;
+ my $description = shift;
+
+ my $writer = MaxMind::DB::Writer::Tree->new(
+ ip_version => 6,
+ record_size => 28,
+ ip_version => 6,
+ database_type => $type,
+ languages => [ 'en', $type eq 'GeoIP2-City' ? ('zh') : () ],
+ description => {
+ en => ( $type =~ s/-/ /gr )
+ . " $description Database (fake GeoIP2 data, for example purposes only)",
+ $type eq 'GeoIP2-City' ? ( zh => 'å°åž‹æ•°æ®åº“' ) : (),
+ },
+ alias_ipv6_to_ipv4 => 1,
+ map_key_type_callback => _universal_map_key_type_callback(),
+ remove_reserved_networks => 0,
+ );
+
+ _populate_all_networks( $writer, $populate_all_networks_with_data )
+ if $populate_all_networks_with_data;
+
+ my $value = shift;
+ my $nodes
+ = decode_json( read_binary("$Dir/$type.json") );
+
+ for my $node (@$nodes) {
+ for my $network ( keys %$node ) {
+ $writer->insert_network(
+ Net::Works::Network->new_from_string( string => $network ),
+ $node->{$network}
+ );
+ }
+ }
+
+ open my $output_fh, '>', "$Dir/$type.mmdb";
+ $writer->write_tree($output_fh);
+ close $output_fh;
+
+ return;
+}
+
+sub _populate_all_networks {
+ my $writer = shift;
+ my $data = shift;
+
+ my $max_uint128 = uint128(0) - 1;
+ my @networks = Net::Works::Network->range_as_subnets(
+ Net::Works::Address->new_from_integer(
+ integer => 0,
+ version => 6,
+ ),
+ Net::Works::Address->new_from_integer(
+ integer => $max_uint128,
+ version => 6,
+ ),
+ );
+
+ for my $network (@networks) {
+ $writer->insert_network( $network => $data );
+ }
+}
+
+main();
diff --git a/bin/tests/system/geoip2/ns2/example.db.in b/bin/tests/system/geoip2/ns2/example.db.in
new file mode 100644
index 0000000..fa3874c
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
diff --git a/bin/tests/system/geoip2/ns2/named1.conf.in b/bin/tests/system/geoip2/ns2/named1.conf.in
new file mode 100644
index 0000000..2b01a5c
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named1.conf.in
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip db country country AU; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip db country country US; };
+ zone "example" {
+ type primary;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip db country country GB; };
+ zone "example" {
+ type primary;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip db country country CA; };
+ zone "example" {
+ type primary;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip db country country CL; };
+ zone "example" {
+ type primary;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip db country country DE; };
+ zone "example" {
+ type primary;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip db country country EH; };
+ zone "example" {
+ type primary;
+ file "example7.db";
+ };
+};
+
+view other {
+ match-clients { geoip db country country O1; };
+ zone "example" {
+ type primary;
+ file "exampleother.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type primary;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip2/ns2/named10.conf.in b/bin/tests/system/geoip2/ns2/named10.conf.in
new file mode 100644
index 0000000..5cac0f7
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named10.conf.in
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip asnum 100001; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip asnum 100002; };
+ zone "example" {
+ type primary;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip asnum 100003; };
+ zone "example" {
+ type primary;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip asnum 100004; };
+ zone "example" {
+ type primary;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip asnum 100005; };
+ zone "example" {
+ type primary;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip asnum 100006; };
+ zone "example" {
+ type primary;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip asnum 100007; };
+ zone "example" {
+ type primary;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type primary;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip2/ns2/named11.conf.in b/bin/tests/system/geoip2/ns2/named11.conf.in
new file mode 100644
index 0000000..b6d2a44
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named11.conf.in
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip domain one.de; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip domain two.com; };
+ zone "example" {
+ type primary;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip domain three.com; };
+ zone "example" {
+ type primary;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip domain four.edu; };
+ zone "example" {
+ type primary;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip domain five.es; };
+ zone "example" {
+ type primary;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip domain six.it; };
+ zone "example" {
+ type primary;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip domain seven.org; };
+ zone "example" {
+ type primary;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type primary;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip2/ns2/named12.conf.in b/bin/tests/system/geoip2/ns2/named12.conf.in
new file mode 100644
index 0000000..2528164
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named12.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+acl blocking {
+ geoip db country country AU;
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+ blackhole { blocking; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/geoip2/ns2/named2.conf.in b/bin/tests/system/geoip2/ns2/named2.conf.in
new file mode 100644
index 0000000..c28f15b
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named2.conf.in
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 127.0.0.1; 10.53.0.2; };
+ listen-on-v6 { ::1; fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+acl gAU { geoip db country country AU; };
+acl gUS { geoip db country country US; };
+acl gGB { geoip db country country GB; };
+acl gCA { geoip db country country CA; };
+acl gCL { geoip db country country CL; };
+acl gDE { geoip db country country DE; };
+acl gEH { geoip db country country EH; };
+
+view one {
+ match-clients { gAU; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { gUS; };
+ zone "example" {
+ type primary;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { gGB; };
+ zone "example" {
+ type primary;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { gCA; };
+ zone "example" {
+ type primary;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { gCL; };
+ zone "example" {
+ type primary;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { gDE; };
+ zone "example" {
+ type primary;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { gEH; };
+ zone "example" {
+ type primary;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type primary;
+ file "examplebogus.db";
+ };
+};
diff --git a/bin/tests/system/geoip2/ns2/named3.conf.in b/bin/tests/system/geoip2/ns2/named3.conf.in
new file mode 100644
index 0000000..f3b35e5
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named3.conf.in
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip db country country Australia; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip db country country "United States"; };
+ zone "example" {
+ type primary;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip db country country "United Kingdom"; };
+ zone "example" {
+ type primary;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip db country country Canada; };
+ zone "example" {
+ type primary;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip db country country Chile; };
+ zone "example" {
+ type primary;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip db country country Germany; };
+ zone "example" {
+ type primary;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip db country country "Western Sahara"; };
+ zone "example" {
+ type primary;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type primary;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip2/ns2/named4.conf.in b/bin/tests/system/geoip2/ns2/named4.conf.in
new file mode 100644
index 0000000..7ccd200
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named4.conf.in
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip db country continent OC; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip db country continent NA; };
+ zone "example" {
+ type primary;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip db country continent EU; };
+ zone "example" {
+ type primary;
+ file "example3.db";
+ };
+};
+
+view five {
+ match-clients { geoip db country continent SA; };
+ zone "example" {
+ type primary;
+ file "example5.db";
+ };
+};
+
+view seven {
+ match-clients { geoip db country continent AF; };
+ zone "example" {
+ type primary;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type primary;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip2/ns2/named5.conf.in b/bin/tests/system/geoip2/ns2/named5.conf.in
new file mode 100644
index 0000000..ec0b371
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named5.conf.in
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip region CA; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view three {
+ match-clients { geoip region OK; };
+ zone "example" {
+ type primary;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip region VA; };
+ zone "example" {
+ type primary;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip region GA; };
+ zone "example" {
+ type primary;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip region CO; };
+ zone "example" {
+ type primary;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip region AK; };
+ zone "example" {
+ type primary;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type primary;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip2/ns2/named6.conf.in b/bin/tests/system/geoip2/ns2/named6.conf.in
new file mode 100644
index 0000000..b2bb091
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named6.conf.in
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip city "Redwood City"; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip city "Santa Cruz"; };
+ zone "example" {
+ type primary;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip city "Oklahoma City"; };
+ zone "example" {
+ type primary;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip city "Ashland"; };
+ zone "example" {
+ type primary;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip city "Atlanta"; };
+ zone "example" {
+ type primary;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip city "Morrison"; };
+ zone "example" {
+ type primary;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip city "Ketchikan"; };
+ zone "example" {
+ type primary;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type primary;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip2/ns2/named7.conf.in b/bin/tests/system/geoip2/ns2/named7.conf.in
new file mode 100644
index 0000000..99b6960
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named7.conf.in
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip isp "One Systems, Inc."; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip isp "Two Technology Ltd."; };
+ zone "example" {
+ type primary;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip isp "Three Network Labs"; };
+ zone "example" {
+ type primary;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip isp "Four University"; };
+ zone "example" {
+ type primary;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip isp "Five Telecom"; };
+ zone "example" {
+ type primary;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip isp "Six Company"; };
+ zone "example" {
+ type primary;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip isp "Seven Communications"; };
+ zone "example" {
+ type primary;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type primary;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip2/ns2/named8.conf.in b/bin/tests/system/geoip2/ns2/named8.conf.in
new file mode 100644
index 0000000..4470ad6
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named8.conf.in
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip org "One Systems, Inc."; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip org "Two Technology Ltd."; };
+ zone "example" {
+ type primary;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip org "Three Network Labs"; };
+ zone "example" {
+ type primary;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip org "Four University"; };
+ zone "example" {
+ type primary;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip org "Five Telecom"; };
+ zone "example" {
+ type primary;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip org "Six Company"; };
+ zone "example" {
+ type primary;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip org "Seven Communications"; };
+ zone "example" {
+ type primary;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type primary;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip2/ns2/named9.conf.in b/bin/tests/system/geoip2/ns2/named9.conf.in
new file mode 100644
index 0000000..5aee393
--- /dev/null
+++ b/bin/tests/system/geoip2/ns2/named9.conf.in
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+ geoip-directory "../data";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view one {
+ match-clients { geoip asnum "AS100001"; };
+ zone "example" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view two {
+ match-clients { geoip asnum "AS100002"; };
+ zone "example" {
+ type primary;
+ file "example2.db";
+ };
+};
+
+view three {
+ match-clients { geoip asnum "AS100003"; };
+ zone "example" {
+ type primary;
+ file "example3.db";
+ };
+};
+
+view four {
+ match-clients { geoip asnum "AS100004"; };
+ zone "example" {
+ type primary;
+ file "example4.db";
+ };
+};
+
+view five {
+ match-clients { geoip asnum "AS100005"; };
+ zone "example" {
+ type primary;
+ file "example5.db";
+ };
+};
+
+view six {
+ match-clients { geoip asnum "AS100006"; };
+ zone "example" {
+ type primary;
+ file "example6.db";
+ };
+};
+
+view seven {
+ match-clients { geoip asnum "AS100007"; };
+ zone "example" {
+ type primary;
+ file "example7.db";
+ };
+};
+
+view none {
+ match-clients { any; };
+ zone "example" {
+ type primary;
+ file "example.db.in";
+ };
+};
diff --git a/bin/tests/system/geoip2/prereq.sh b/bin/tests/system/geoip2/prereq.sh
new file mode 100644
index 0000000..c06d752
--- /dev/null
+++ b/bin/tests/system/geoip2/prereq.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$FEATURETEST --have-geoip2 || {
+ echo_i "This test requires GeoIP support." >&2
+ exit 255
+}
+exit 0
diff --git a/bin/tests/system/geoip2/setup.sh b/bin/tests/system/geoip2/setup.sh
new file mode 100644
index 0000000..646388f
--- /dev/null
+++ b/bin/tests/system/geoip2/setup.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns2/named1.conf.in ns2/named.conf
+
+for i in 1 2 3 4 5 6 7 other bogus; do
+ cp ns2/example.db.in ns2/example${i}.db
+ echo "@ IN TXT \"$i\"" >> ns2/example$i.db
+done
diff --git a/bin/tests/system/geoip2/tests.sh b/bin/tests/system/geoip2/tests.sh
new file mode 100644
index 0000000..b72a870
--- /dev/null
+++ b/bin/tests/system/geoip2/tests.sh
@@ -0,0 +1,490 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +short -p ${PORT} @10.53.0.2"
+DIGOPTS6="+tcp +short -p ${PORT} @fd92:7065:b8e:ffff::2 -6"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+for conf in conf/good*.conf
+do
+ n=$((n + 1))
+ echo_i "checking that $conf is accepted ($n)"
+ ret=0
+ $CHECKCONF "$conf" || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+for conf in conf/bad*.conf
+do
+ n=$((n + 1))
+ echo_i "checking that $conf is rejected ($n)"
+ ret=0
+ $CHECKCONF "$conf" >/dev/null && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+n=$((n + 1))
+echo_i "checking Country database by code using IPv4 ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ n=$((n + 1))
+ echo_i "checking Country database by code using IPv6 ($n)"
+ ret=0
+ lret=0
+ for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+ done
+ [ $lret -eq 1 ] && ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+else
+ echo_i "IPv6 unavailable; skipping IPv6 country code test"
+fi
+
+echo_i "reloading server"
+copy_setports ns2/named2.conf.in ns2/named.conf
+$CHECKCONF ns2/named.conf | cat_i
+rndc_reload ns2 10.53.0.2
+sleep 3
+
+n=$((n + 1))
+echo_i "checking Country database with nested ACLs using IPv4 ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ n=$((n + 1))
+ echo_i "checking Country database with nested ACLs using IPv6 ($n)"
+ ret=0
+ lret=0
+ for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+ done
+ [ $lret -eq 1 ] && ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+else
+ echo_i "IPv6 unavailable; skipping IPv6 country nested ACL test"
+fi
+
+echo_i "reloading server"
+copy_setports ns2/named3.conf.in ns2/named.conf
+$CHECKCONF ns2/named.conf | cat_i
+rndc_reload ns2 10.53.0.2
+sleep 3
+
+n=$((n + 1))
+echo_i "checking Country database by name using IPv4 ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ n=$((n + 1))
+ echo_i "checking Country database by name using IPv6 ($n)"
+ ret=0
+ lret=0
+ for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+ done
+ [ $lret -eq 1 ] && ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+else
+ echo_i "IPv6 unavailable; skipping IPv6 country name test"
+fi
+
+echo_i "reloading server"
+copy_setports ns2/named4.conf.in ns2/named.conf
+$CHECKCONF ns2/named.conf | cat_i
+rndc_reload ns2 10.53.0.2
+sleep 3
+
+n=$((n + 1))
+echo_i "checking Country database by continent code using IPv4 ($n)"
+ret=0
+lret=0
+# deliberately skipping 4 and 6 as they have duplicate continents
+for i in 1 2 3 5 7; do
+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ n=$((n + 1))
+ echo_i "checking Country database by continent code using IPv6 ($n)"
+ ret=0
+ lret=0
+ # deliberately skipping 4 and 6 as they have duplicate continents
+ for i in 1 2 3 5 7; do
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+ done
+ [ $lret -eq 1 ] && ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+else
+ echo_i "IPv6 unavailable; skipping IPv6 continent code test"
+fi
+
+echo_i "reloading server"
+copy_setports ns2/named5.conf.in ns2/named.conf
+$CHECKCONF ns2/named.conf | cat_i
+rndc_reload ns2 10.53.0.2
+sleep 3
+
+n=$((n + 1))
+echo_i "checking City database by region code using IPv4 ($n)"
+ret=0
+lret=0
+# skipping 2 on purpose here; it has the same region code as 1
+for i in 1 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ n=$((n + 1))
+ echo_i "checking City database by region code using IPv6 ($n)"
+ ret=0
+ lret=0
+# skipping 2 on purpose here; it has the same region code as 1
+ for i in 1 3 4 5 6 7; do
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+ done
+ [ $lret -eq 1 ] && ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+else
+ echo_i "IPv6 unavailable; skipping IPv6 region code test"
+fi
+
+n=$((n + 1))
+echo_i "reloading server"
+copy_setports ns2/named6.conf.in ns2/named.conf
+$CHECKCONF ns2/named.conf | cat_i
+rndc_reload ns2 10.53.0.2
+sleep 3
+
+n=$((n + 1))
+echo_i "checking City database by city name using IPv4 ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ n=$((n + 1))
+ echo_i "checking City database by city name using IPv6 ($n)"
+ ret=0
+ lret=0
+ for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+ done
+ [ $lret -eq 1 ] && ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+else
+ echo_i "IPv6 unavailable; skipping IPv6 city test"
+fi
+
+echo_i "reloading server"
+copy_setports ns2/named7.conf.in ns2/named.conf
+$CHECKCONF ns2/named.conf | cat_i
+rndc_reload ns2 10.53.0.2
+sleep 3
+
+n=$((n + 1))
+echo_i "checking ISP database using IPv4 ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ n=$((n + 1))
+ echo_i "checking ISP database using IPv6 ($n)"
+ ret=0
+ lret=0
+ for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+ done
+ [ $lret -eq 1 ] && ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+else
+ echo_i "IPv6 unavailable; skipping IPv6 ISP test"
+fi
+
+echo_i "reloading server"
+copy_setports ns2/named8.conf.in ns2/named.conf
+$CHECKCONF ns2/named.conf | cat_i
+rndc_reload ns2 10.53.0.2
+sleep 3
+
+n=$((n + 1))
+echo_i "checking ASN database by org name using IPv4 ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ n=$((n + 1))
+ echo_i "checking ASN database by org name using IPv6 ($n)"
+ ret=0
+ lret=0
+ for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+ done
+ [ $lret -eq 1 ] && ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+else
+ echo_i "IPv6 unavailable; skipping IPv6 ASN test"
+fi
+
+echo_i "reloading server"
+copy_setports ns2/named9.conf.in ns2/named.conf
+$CHECKCONF ns2/named.conf | cat_i
+rndc_reload ns2 10.53.0.2
+sleep 3
+
+n=$((n + 1))
+echo_i "checking GeoIP6 ASN database, ASNNNN only, using IPv4 ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ n=$((n + 1))
+ echo_i "checking ASN database, ASNNNN only, using IPv6 ($n)"
+ ret=0
+ lret=0
+ for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+ done
+ [ $lret -eq 1 ] && ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+else
+ echo_i "IPv6 unavailable; skipping IPv6 ASN test"
+fi
+
+echo_i "reloading server"
+copy_setports ns2/named10.conf.in ns2/named.conf
+$CHECKCONF ns2/named.conf | cat_i
+rndc_reload ns2 10.53.0.2
+sleep 3
+
+n=$((n + 1))
+echo_i "checking GeoIP6 ASN database, NNNN only, using IPv4 ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ n=$((n + 1))
+ echo_i "checking ASN database, NNNN only, using IPv6 ($n)"
+ ret=0
+ lret=0
+ for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+ done
+ [ $lret -eq 1 ] && ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+else
+ echo_i "IPv6 unavailable; skipping IPv6 ASN test"
+fi
+
+echo_i "reloading server"
+copy_setports ns2/named11.conf.in ns2/named.conf
+$CHECKCONF ns2/named.conf | cat_i
+rndc_reload ns2 10.53.0.2
+sleep 3
+
+n=$((n + 1))
+echo_i "checking Domain database using IPv4 ($n)"
+ret=0
+lret=0
+for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+done
+[ $lret -eq 1 ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+if testsock6 fd92:7065:b8e:ffff::3
+then
+ n=$((n + 1))
+ echo_i "checking Domain database using IPv6 ($n)"
+ ret=0
+ lret=0
+ for i in 1 2 3 4 5 6 7; do
+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i > dig.out.ns2.test$n.$i || lret=1
+ j=$(cat dig.out.ns2.test$n.$i | tr -d '"')
+ [ "$i" = "$j" ] || lret=1
+ [ $lret -eq 1 ] && break
+ done
+ [ $lret -eq 1 ] && ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+else
+ echo_i "IPv6 unavailable; skipping IPv6 Domain test"
+fi
+
+echo_i "reloading server"
+copy_setports ns2/named12.conf.in ns2/named.conf
+$CHECKCONF ns2/named.conf | cat_i
+rndc_reload ns2 10.53.0.2
+sleep 3
+
+n=$((n + 1))
+echo_i "checking geoip blackhole ACL ($n)"
+ret=0
+$DIG $DIGOPTS txt example -b 10.53.0.7 > dig.out.ns2.test$n || ret=1
+$RNDCCMD 10.53.0.2 status 2>&1 > rndc.out.ns2.test$n || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/geoip2/tests_sh_geoip2.py b/bin/tests/system/geoip2/tests_sh_geoip2.py
new file mode 100644
index 0000000..7cac6a8
--- /dev/null
+++ b/bin/tests/system/geoip2/tests_sh_geoip2.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_geoip2(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/get_algorithms.py b/bin/tests/system/get_algorithms.py
new file mode 100755
index 0000000..b2a060d
--- /dev/null
+++ b/bin/tests/system/get_algorithms.py
@@ -0,0 +1,241 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# This script is a 'port' broker. It keeps track of ports given to the
+# individual system subtests, so every test is given a unique port range.
+
+import logging
+import os
+from pathlib import Path
+import platform
+import random
+import subprocess
+import time
+from typing import Dict, List, NamedTuple, Union
+
+# Uncomment to enable DEBUG logging
+# logging.basicConfig(
+# format="get_algorithms.py %(levelname)s %(message)s", level=logging.DEBUG
+# )
+
+STABLE_PERIOD = 3600 * 3
+"""number of secs during which algorithm selection remains stable"""
+
+
+class Algorithm(NamedTuple):
+ name: str
+ number: int
+ bits: int
+
+
+class AlgorithmSet(NamedTuple):
+ """Collection of DEFAULT, ALTERNATIVE and DISABLED algorithms"""
+
+ default: Union[Algorithm, List[Algorithm]]
+ """DEFAULT is the algorithm for testing."""
+
+ alternative: Union[Algorithm, List[Algorithm]]
+ """ALTERNATIVE is an alternative algorithm for test cases that require more
+ than one algorithm (for example algorithm rollover)."""
+
+ disabled: Union[Algorithm, List[Algorithm]]
+ """DISABLED is an algorithm that is used for tests against the
+ "disable-algorithms" configuration option."""
+
+
+RSASHA1 = Algorithm("RSASHA1", 5, 1280)
+RSASHA256 = Algorithm("RSASHA256", 8, 1280)
+RSASHA512 = Algorithm("RSASHA512", 10, 1280)
+ECDSAP256SHA256 = Algorithm("ECDSAP256SHA256", 13, 256)
+ECDSAP384SHA384 = Algorithm("ECDSAP384SHA384", 14, 384)
+ED25519 = Algorithm("ED25519", 15, 256)
+ED448 = Algorithm("ED448", 16, 456)
+
+ALL_ALGORITHMS = [
+ RSASHA1,
+ RSASHA256,
+ RSASHA512,
+ ECDSAP256SHA256,
+ ECDSAP384SHA384,
+ ED25519,
+ ED448,
+]
+
+ALGORITHM_SETS = {
+ "stable": AlgorithmSet(
+ default=ECDSAP256SHA256, alternative=RSASHA256, disabled=ECDSAP384SHA384
+ ),
+ "ecc_default": AlgorithmSet(
+ default=[
+ ECDSAP256SHA256,
+ ECDSAP384SHA384,
+ ED25519,
+ ED448,
+ ],
+ alternative=RSASHA256,
+ disabled=RSASHA512,
+ ),
+ # FUTURE The system tests needs more work before they're ready for this.
+ # "random": AlgorithmSet(
+ # default=ALL_ALGORITHMS,
+ # alternative=ALL_ALGORITHMS,
+ # disabled=ALL_ALGORITHMS,
+ # ),
+}
+
+TESTCRYPTO = Path(__file__).resolve().parent / "testcrypto.sh"
+
+KEYGEN = os.getenv("KEYGEN", "")
+if not KEYGEN:
+ raise RuntimeError("KEYGEN environment variable has to be set")
+
+ALGORITHM_SET = os.getenv("ALGORITHM_SET", "stable")
+assert ALGORITHM_SET in ALGORITHM_SETS, f'ALGORITHM_SET "{ALGORITHM_SET}" unknown'
+logging.debug('choosing from ALGORITHM_SET "%s"', ALGORITHM_SET)
+
+
+def is_supported(alg: Algorithm) -> bool:
+ """Test whether a given algorithm is supported on the current platform."""
+ try:
+ subprocess.run(
+ f"{TESTCRYPTO} -q {alg.name}",
+ shell=True,
+ check=True,
+ env={
+ "KEYGEN": KEYGEN,
+ "TMPDIR": os.getenv("TMPDIR", "/tmp"),
+ },
+ stdout=subprocess.DEVNULL,
+ )
+ except subprocess.CalledProcessError as exc:
+ logging.debug(exc)
+ logging.info("algorithm %s not supported", alg.name)
+ return False
+ return True
+
+
+def filter_supported(algs: AlgorithmSet) -> AlgorithmSet:
+ """Select supported algorithms from the set."""
+ filtered = {}
+ for alg_type in algs._fields:
+ candidates = getattr(algs, alg_type)
+ if isinstance(candidates, Algorithm):
+ candidates = [candidates]
+ supported = list(filter(is_supported, candidates))
+ if len(supported) == 1:
+ supported = supported.pop()
+ elif not supported:
+ raise RuntimeError(
+ f'no {alg_type.upper()} algorithm from "{ALGORITHM_SET}" set '
+ "supported on this platform"
+ )
+ filtered[alg_type] = supported
+ return AlgorithmSet(**filtered)
+
+
+def select_random(algs: AlgorithmSet, stable_period=STABLE_PERIOD) -> AlgorithmSet:
+ """Select random DEFAULT, ALTERNATIVE and DISABLED algorithms from the set.
+
+ The algorithm selection is deterministic for a given time period and
+ platform. This should make potential issues more reproducible.
+
+ To increase the likelyhood of detecting an issue with a given algorithm in
+ CI, the current platform is used as a randomness source. When testing on
+ multiple platforms at the same time, this ensures more algorithm variance
+ while keeping reproducibility for a single platform.
+
+ The function also ensures that DEFAULT, ALTERNATIVE and DISABLED algorithms
+ are all different.
+ """
+ # FUTURE Random selection of ALTERNATIVE and DISABLED algorithms needs to
+ # be implemented.
+ alternative = algs.alternative
+ disabled = algs.disabled
+ assert isinstance(
+ alternative, Algorithm
+ ), "ALTERNATIVE algorithm randomization not supported yet"
+ assert isinstance(
+ disabled, Algorithm
+ ), "DISABLED algorithm randomization not supported yet"
+
+ # initialize randomness
+ now = time.time()
+ time_seed = int(now - now % stable_period)
+ seed = f"{platform.platform()}_{time_seed}"
+ random.seed(seed)
+
+ # DEFAULT selection
+ if isinstance(algs.default, Algorithm):
+ default = algs.default
+ else:
+ candidates = algs.default
+ for taken in [alternative, disabled]:
+ try:
+ candidates.remove(taken)
+ except ValueError:
+ pass
+ assert len(candidates), "no possible choice for DEFAULT algorithm"
+ random.shuffle(candidates)
+ default = candidates[0]
+
+ # Ensure only single algorithm is present for each option
+ assert isinstance(default, Algorithm)
+ assert isinstance(alternative, Algorithm)
+ assert isinstance(disabled, Algorithm)
+
+ assert default != alternative, "DEFAULT and ALTERNATIVE algorithms are the same"
+ assert default != disabled, "DEFAULT and DISABLED algorithms are the same"
+ assert alternative != disabled, "ALTERNATIVE and DISABLED algorithms are the same"
+
+ return AlgorithmSet(default, alternative, disabled)
+
+
+def algorithms_env(algs: AlgorithmSet) -> Dict[str, str]:
+ """Return environment variables with selected algorithms as a dict."""
+ algs_env: Dict[str, str] = {}
+
+ def set_alg_env(alg: Algorithm, prefix):
+ algs_env[f"{prefix}_ALGORITHM"] = alg.name
+ algs_env[f"{prefix}_ALGORITHM_NUMBER"] = str(alg.number)
+ algs_env[f"{prefix}_BITS"] = str(alg.bits)
+
+ assert isinstance(algs.default, Algorithm)
+ assert isinstance(algs.alternative, Algorithm)
+ assert isinstance(algs.disabled, Algorithm)
+
+ set_alg_env(algs.default, "DEFAULT")
+ set_alg_env(algs.alternative, "ALTERNATIVE")
+ set_alg_env(algs.disabled, "DISABLED")
+
+ logging.info("selected algorithms: %s", algs_env)
+ return algs_env
+
+
+def main():
+ try:
+ algs = ALGORITHM_SETS[ALGORITHM_SET]
+ algs = filter_supported(algs)
+ algs = select_random(algs)
+ algs_env = algorithms_env(algs)
+ except Exception:
+ # if anything goes wrong, the conf.sh ignores error codes, so make sure
+ # we set an environment variable to an error value that can be checked
+ # later by the test runner and/or tests themselves
+ print("export ALGORITHM_SET=error")
+ raise
+ for name, value in algs_env.items():
+ print(f"export {name}={value}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/bin/tests/system/get_core_dumps.sh b/bin/tests/system/get_core_dumps.sh
new file mode 100755
index 0000000..d4f6ec7
--- /dev/null
+++ b/bin/tests/system/get_core_dumps.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+dir=$(dirname "$0")
+. "$dir/conf.sh"
+
+systest=$1
+status=0
+
+export SYSTESTDIR="${TOP_BUILDDIR}/bin/tests/system/${systest}"
+
+get_core_dumps() {
+ find "$SYSTESTDIR/" \( -name 'core' -or -name 'core.*' -or -name '*.core' \) ! -name '*.gz' ! -name '*.txt' | sort
+}
+
+core_dumps=$(get_core_dumps | tr '\n' ' ')
+if [ -n "$core_dumps" ]; then
+ status=1
+ echoinfo "I:$systest:Core dump(s) found: $core_dumps"
+ get_core_dumps | while read -r coredump; do
+ echoinfo "D:$systest:backtrace from $coredump:"
+ echoinfo "D:$systest:--------------------------------------------------------------------------------"
+ binary=$(gdb --batch --core="$coredump" 2>/dev/null | sed -ne "s|Core was generated by \`\([^' ]*\)[' ].*|\1|p")
+ if [ ! -f "${binary}" ]; then
+ binary=$(find "${TOP_BUILDDIR}" -path "*/.libs/${binary}" -type f)
+ fi
+ "${TOP_BUILDDIR}/libtool" --mode=execute gdb \
+ -batch \
+ -ex bt \
+ -core="$coredump" \
+ -- \
+ "$binary" 2>/dev/null | sed -n '/^Core was generated by/,$p' | cat_d
+ echoinfo "D:$systest:--------------------------------------------------------------------------------"
+ coredump_backtrace="${coredump}-backtrace.txt"
+ echoinfo "D:$systest:full backtrace from $coredump saved in $coredump_backtrace"
+ "${TOP_BUILDDIR}/libtool" --mode=execute gdb \
+ -batch \
+ -command="${TOP_SRCDIR}/bin/tests/system/run.gdb" \
+ -core="$coredump" \
+ -- \
+ "$binary" > "$coredump_backtrace" 2>&1
+ echoinfo "D:$systest:core dump $coredump archived as $coredump.gz"
+ gzip -1 "${coredump}"
+ done
+fi
+
+assertion_failures=$(find "$SYSTESTDIR/" -name named.run -exec grep "assertion failure" {} + | wc -l)
+if [ "$assertion_failures" -ne 0 ]; then
+ status=1
+ echoinfo "I:$systest:$assertion_failures assertion failure(s) found"
+fi
+
+tsan_failures=$(find "$SYSTESTDIR/" -name 'tsan.*' | wc -l)
+if [ "$tsan_failures" -ne 0 ]; then
+ status=1
+ echoinfo "I:$systest:$tsan_failures TSAN sanitizer report(s) found"
+ find "$SYSTESTDIR/" -name 'tsan.*' -exec grep "SUMMARY: " {} + | sort -u | cat_d
+fi
+
+exit $status
diff --git a/bin/tests/system/get_ports.sh b/bin/tests/system/get_ports.sh
new file mode 100755
index 0000000..b44e3ef
--- /dev/null
+++ b/bin/tests/system/get_ports.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# This script is a 'port' broker. It keeps track of ports given to the
+# individual system subtests, so every test is given a unique port range.
+
+get_sorted_test_names() {
+ find . -maxdepth 2 -mindepth 2 -type f \( -name "tests.sh" -o -name "tests*.py" \) | cut -d/ -f2 | sort -u
+}
+
+total_tests=$(get_sorted_test_names | wc -l)
+ports_per_test=20
+
+port_min=5001
+port_max=$((32767 - (total_tests * ports_per_test)))
+
+baseport=0
+test_index=0
+while getopts "p:t:-:" OPT; do
+ if [ "$OPT" = "-" ] && [ -n "$OPTARG" ]; then
+ OPT="${OPTARG%%=*}"
+ OPTARG="${OPTARG#$OPT}"
+ OPTARG="${OPTARG#=}"
+ fi
+
+ # shellcheck disable=SC2214
+ case "$OPT" in
+ p | port) baseport=$OPTARG ;;
+ t | test)
+ test_index=$(get_sorted_test_names | awk "/^${OPTARG}\$/ { print NR }")
+ if [ -z "${test_index}" ]; then
+ echo "Test '${OPTARG}' not found" >&2
+ exit 1
+ fi
+ ;;
+ -) break ;;
+ *) echo "invalid option" >&2; exit 1 ;;
+ esac
+done
+
+port_pool_size=$((port_max - port_min))
+if [ "${baseport}" -eq 0 ]; then
+ baseport="$((($(date +%s) / 3600 % port_pool_size) + port_min + (test_index * ports_per_test)))"
+fi
+
+echo "export PORT=$((baseport))"
+echo "export TLSPORT=$((baseport + 1))"
+echo "export HTTPPORT=$((baseport + 2))"
+echo "export HTTPSPORT=$((baseport + 3))"
+echo "export EXTRAPORT1=$((baseport + 4))"
+echo "export EXTRAPORT2=$((baseport + 5))"
+echo "export EXTRAPORT3=$((baseport + 6))"
+echo "export EXTRAPORT4=$((baseport + 7))"
+echo "export EXTRAPORT5=$((baseport + 8))"
+echo "export EXTRAPORT6=$((baseport + 9))"
+echo "export EXTRAPORT7=$((baseport + 10))"
+echo "export EXTRAPORT8=$((baseport + 11))"
+echo "export CONTROLPORT=$((baseport + 12))"
+
+# Local Variables:
+# sh-basic-offset: 4
+# End:
diff --git a/bin/tests/system/glue/clean.sh b/bin/tests/system/glue/clean.sh
new file mode 100644
index 0000000..4d84f06
--- /dev/null
+++ b/bin/tests/system/glue/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after glue tests.
+#
+
+rm -f dig.out
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/glue/fi.good b/bin/tests/system/glue/fi.good
new file mode 100644
index 0000000..a08bc7a
--- /dev/null
+++ b/bin/tests/system/glue/fi.good
@@ -0,0 +1,27 @@
+
+; <<>> DiG 9.0 <<>> +norec @10.53.0.1 -p 5300 foo.bar.fi. A
+;; global options: printcmd
+;; Got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58772
+;; flags: qr ad; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 7
+
+;; QUESTION SECTION:
+;foo.bar.fi. IN A
+
+;; AUTHORITY SECTION:
+fi. 172800 IN NS NS.EU.NET.
+fi. 172800 IN NS NS.TELE.fi.
+fi. 172800 IN NS PRIFI.EUNET.fi.
+fi. 172800 IN NS NS.UU.NET.
+fi. 172800 IN NS T.NS.VERIO.NET.
+fi. 172800 IN NS HYDRA.HELSINKI.fi.
+
+;; ADDITIONAL SECTION:
+NS.TELE.fi. 172800 IN A 193.210.19.19
+NS.TELE.fi. 172800 IN A 193.210.18.18
+PRIFI.EUNET.fi. 172800 IN A 193.66.1.146
+NS.UU.NET. 172800 IN A 137.39.1.3
+T.NS.VERIO.NET. 172800 IN A 192.67.14.16
+HYDRA.HELSINKI.fi. 172800 IN A 128.214.4.29
+NS.EU.NET. 172800 IN A 192.16.202.11
+
diff --git a/bin/tests/system/glue/noglue.good b/bin/tests/system/glue/noglue.good
new file mode 100644
index 0000000..22eca7b
--- /dev/null
+++ b/bin/tests/system/glue/noglue.good
@@ -0,0 +1,14 @@
+
+; <<>> DiG 9.0 <<>> @10.53.0.1 -p 5300 example.net a
+;; global options: printcmd
+;; Got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29409
+;; flags: qr rd ad; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 0
+
+;; QUESTION SECTION:
+;example.net. IN A
+
+;; AUTHORITY SECTION:
+example.net. 300 IN NS ns2.example.
+example.net. 300 IN NS ns1.example.
+
diff --git a/bin/tests/system/glue/ns1/named.conf.in b/bin/tests/system/glue/ns1/named.conf.in
new file mode 100644
index 0000000..9ac9bc5
--- /dev/null
+++ b/bin/tests/system/glue/ns1/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "root-servers.nil" {
+ type primary;
+ file "root-servers.nil.db";
+};
+zone "net" {
+ type primary;
+ file "net.db";
+};
diff --git a/bin/tests/system/glue/ns1/net.db b/bin/tests/system/glue/ns1/net.db
new file mode 100644
index 0000000..db784cc
--- /dev/null
+++ b/bin/tests/system/glue/ns1/net.db
@@ -0,0 +1,34 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN net.
+$TTL 300
+@ IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS a.root-servers.nil.
+
+; FI. authoritative servers, for the FI. glue test.
+uu.net. NS ns.uu.net.
+NS.UU.NET. 172800 IN A 137.39.1.3
+eu.net. NS ns.eu.net.
+NS.EU.NET. 172800 IN A 192.16.202.11
+
+; Referral outside of server authority, but with glue records present.
+; Don't hand out the glue.
+example.net. NS ns1.example.
+example.net. NS ns2.example.
+ns1.example. 172800 IN A 1.1.1.1
+ns2.example. 172800 IN A 2.2.2.2
diff --git a/bin/tests/system/glue/ns1/root-servers.nil.db b/bin/tests/system/glue/ns1/root-servers.nil.db
new file mode 100644
index 0000000..1475aed
--- /dev/null
+++ b/bin/tests/system/glue/ns1/root-servers.nil.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA ns hostmaster (
+ 1
+ 3600
+ 1800
+ 1814400
+ 3600
+ )
+ NS a
+a A 10.53.0.1
+b A 10.53.0.2
+
+
+
diff --git a/bin/tests/system/glue/ns1/root.db b/bin/tests/system/glue/ns1/root.db
new file mode 100644
index 0000000..debdf01
--- /dev/null
+++ b/bin/tests/system/glue/ns1/root.db
@@ -0,0 +1,44 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+
+root-servers.nil. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+; Delegate some domains that contain name servers for the sample
+; ccTLDs below.
+net. 172800 IN NS a.root-servers.nil.
+
+;
+; A sample ccTLD
+;
+fi. 172800 IN NS NS.TELE.fi.
+fi. 172800 IN NS PRIFI.EUNET.fi.
+fi. 172800 IN NS NS.UU.NET.
+fi. 172800 IN NS T.NS.VERIO.NET.
+fi. 172800 IN NS HYDRA.HELSINKI.fi.
+fi. 172800 IN NS NS.EU.NET.
+NS.TELE.fi. 172800 IN A 193.210.18.18
+NS.TELE.fi. 172800 IN A 193.210.19.19
+PRIFI.EUNET.fi. 172800 IN A 193.66.1.146
+NS.UU.NET. 172800 IN A 137.39.1.3
+T.NS.VERIO.NET. 172800 IN A 192.67.14.16
+HYDRA.HELSINKI.fi. 172800 IN A 128.214.4.29
+NS.EU.NET. 172800 IN A 192.16.202.11
diff --git a/bin/tests/system/glue/setup.sh b/bin/tests/system/glue/setup.sh
new file mode 100644
index 0000000..82240a7
--- /dev/null
+++ b/bin/tests/system/glue/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/glue/tests.sh b/bin/tests/system/glue/tests.sh
new file mode 100644
index 0000000..2dcacbf
--- /dev/null
+++ b/bin/tests/system/glue/tests.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+#
+# Do glue tests.
+#
+
+DIGOPTS="+norec -p ${PORT}"
+
+status=0
+
+echo_i "testing that a ccTLD referral gets a full glue set from the root zone"
+$DIG $DIGOPTS @10.53.0.1 foo.bar.fi. A >dig.out || status=1
+digcomp --lc fi.good dig.out || status=1
+
+echo_i "testing that we don't find out-of-zone glue"
+$DIG $DIGOPTS @10.53.0.1 example.net. a > dig.out || status=1
+digcomp noglue.good dig.out || status=1
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/glue/tests_sh_glue.py b/bin/tests/system/glue/tests_sh_glue.py
new file mode 100644
index 0000000..4f3ff04
--- /dev/null
+++ b/bin/tests/system/glue/tests_sh_glue.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_glue(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/hooks/clean.sh b/bin/tests/system/hooks/clean.sh
new file mode 100644
index 0000000..83463eb
--- /dev/null
+++ b/bin/tests/system/hooks/clean.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.run
+rm -f */named.conf
+rm -f */named.memstats
diff --git a/bin/tests/system/hooks/driver/Makefile.am b/bin/tests/system/hooks/driver/Makefile.am
new file mode 100644
index 0000000..b0c4b79
--- /dev/null
+++ b/bin/tests/system/hooks/driver/Makefile.am
@@ -0,0 +1,12 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS) \
+ $(LIBNS_CFLAGS) \
+ $(LIBISCCFG_CFLAGS)
+
+noinst_LTLIBRARIES = test-async.la
+
+test_async_la_SOURCES = test-async.c
+test_async_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir)
diff --git a/bin/tests/system/hooks/driver/Makefile.in b/bin/tests/system/hooks/driver/Makefile.in
new file mode 100644
index 0000000..f97a712
--- /dev/null
+++ b/bin/tests/system/hooks/driver/Makefile.in
@@ -0,0 +1,775 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+subdir = bin/tests/system/hooks/driver
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+test_async_la_LIBADD =
+am_test_async_la_OBJECTS = test-async.lo
+test_async_la_OBJECTS = $(am_test_async_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+test_async_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(test_async_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/test-async.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(test_async_la_SOURCES)
+DIST_SOURCES = $(test_async_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \
+ $(LIBNS_CFLAGS) $(LIBISCCFG_CFLAGS)
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD =
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+noinst_LTLIBRARIES = test-async.la
+test_async_la_SOURCES = test-async.c
+test_async_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tests/system/hooks/driver/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/tests/system/hooks/driver/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+test-async.la: $(test_async_la_OBJECTS) $(test_async_la_DEPENDENCIES) $(EXTRA_test_async_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(test_async_la_LINK) $(test_async_la_OBJECTS) $(test_async_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-async.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/test-async.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/test-async.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am:
+
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir \
+ doc-am doc-local dvi dvi-am html html-am info info-am install \
+ install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \
+ uninstall-am unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/tests/system/hooks/driver/test-async.c b/bin/tests/system/hooks/driver/test-async.c
new file mode 100644
index 0000000..652b671
--- /dev/null
+++ b/bin/tests/system/hooks/driver/test-async.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+/* aliases for the exported symbols */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/hash.h>
+#include <isc/ht.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <ns/client.h>
+#include <ns/events.h>
+#include <ns/hooks.h>
+#include <ns/log.h>
+#include <ns/query.h>
+#include <ns/types.h>
+
+#define CHECK(op) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ goto cleanup; \
+ } \
+ } while (0)
+
+/*
+ * Persistent data for use by this module. This will be associated
+ * with client object address in the hash table, and will remain
+ * accessible until the client object is detached.
+ */
+typedef struct async_instance {
+ ns_plugin_t *module;
+ isc_mem_t *mctx;
+ isc_ht_t *ht;
+ isc_mutex_t hlock;
+ isc_log_t *lctx;
+} async_instance_t;
+
+typedef struct state {
+ bool async;
+ ns_hook_resevent_t *rev;
+ ns_hookpoint_t hookpoint;
+ isc_result_t origresult;
+} state_t;
+
+/*
+ * Forward declarations of functions referenced in install_hooks().
+ */
+static ns_hookresult_t
+async_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+async_query_done_begin(void *arg, void *cbdata, isc_result_t *resp);
+static ns_hookresult_t
+async_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp);
+
+/*%
+ * Register the functions to be called at each hook point in 'hooktable', using
+ * memory context 'mctx' for allocating copies of stack-allocated structures
+ * passed to ns_hook_add(). Make sure 'inst' will be passed as the 'cbdata'
+ * argument to every callback.
+ */
+static void
+install_hooks(ns_hooktable_t *hooktable, isc_mem_t *mctx,
+ async_instance_t *inst) {
+ const ns_hook_t async_init = {
+ .action = async_qctx_initialize,
+ .action_data = inst,
+ };
+ const ns_hook_t async_donebegin = {
+ .action = async_query_done_begin,
+ .action_data = inst,
+ };
+ const ns_hook_t async_destroy = {
+ .action = async_qctx_destroy,
+ .action_data = inst,
+ };
+
+ ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_INITIALIZED, &async_init);
+ ns_hook_add(hooktable, mctx, NS_QUERY_DONE_BEGIN, &async_donebegin);
+ ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_DESTROYED, &async_destroy);
+}
+
+static void
+logmsg(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS,
+ ISC_LOG_INFO, fmt, ap);
+ va_end(ap);
+}
+
+/**
+** Mandatory plugin API functions:
+**
+** - plugin_destroy
+** - plugin_register
+** - plugin_version
+** - plugin_check
+**/
+
+/*
+ * Called by ns_plugin_register() to initialize the plugin and
+ * register hook functions into the view hook table.
+ */
+isc_result_t
+plugin_register(const char *parameters, const void *cfg, const char *cfg_file,
+ unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx,
+ void *actx, ns_hooktable_t *hooktable, void **instp) {
+ async_instance_t *inst = NULL;
+
+ UNUSED(parameters);
+ UNUSED(cfg);
+ UNUSED(actx);
+
+ isc_log_write(lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS,
+ ISC_LOG_INFO,
+ "registering 'test-async' module from %s:%lu", cfg_file,
+ cfg_line);
+
+ inst = isc_mem_get(mctx, sizeof(*inst));
+ *inst = (async_instance_t){ .mctx = NULL };
+ isc_mem_attach(mctx, &inst->mctx);
+
+ isc_ht_init(&inst->ht, mctx, 16, ISC_HT_CASE_SENSITIVE);
+ isc_mutex_init(&inst->hlock);
+
+ /*
+ * Set hook points in the view's hooktable.
+ */
+ install_hooks(hooktable, mctx, inst);
+
+ *instp = inst;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+plugin_check(const char *parameters, const void *cfg, const char *cfg_file,
+ unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx,
+ void *actx) {
+ UNUSED(parameters);
+ UNUSED(cfg);
+ UNUSED(cfg_file);
+ UNUSED(cfg_line);
+ UNUSED(mctx);
+ UNUSED(lctx);
+ UNUSED(actx);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Called by ns_plugins_free(); frees memory allocated by
+ * the module when it was registered.
+ */
+void
+plugin_destroy(void **instp) {
+ async_instance_t *inst = (async_instance_t *)*instp;
+
+ if (inst->ht != NULL) {
+ isc_ht_destroy(&inst->ht);
+ isc_mutex_destroy(&inst->hlock);
+ }
+
+ isc_mem_putanddetach(&inst->mctx, inst, sizeof(*inst));
+ *instp = NULL;
+
+ return;
+}
+
+/*
+ * Returns plugin API version for compatibility checks.
+ */
+int
+plugin_version(void) {
+ return (NS_PLUGIN_VERSION);
+}
+
+static state_t *
+client_state_get(const query_ctx_t *qctx, async_instance_t *inst) {
+ state_t *state = NULL;
+ isc_result_t result;
+
+ LOCK(&inst->hlock);
+ result = isc_ht_find(inst->ht, (const unsigned char *)&qctx->client,
+ sizeof(qctx->client), (void **)&state);
+ UNLOCK(&inst->hlock);
+
+ return (result == ISC_R_SUCCESS ? state : NULL);
+}
+
+static void
+client_state_create(const query_ctx_t *qctx, async_instance_t *inst) {
+ state_t *state = NULL;
+ isc_result_t result;
+
+ state = isc_mem_get(inst->mctx, sizeof(*state));
+ *state = (state_t){ .async = false };
+
+ LOCK(&inst->hlock);
+ result = isc_ht_add(inst->ht, (const unsigned char *)&qctx->client,
+ sizeof(qctx->client), state);
+ UNLOCK(&inst->hlock);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+}
+
+static void
+client_state_destroy(const query_ctx_t *qctx, async_instance_t *inst) {
+ state_t *state = client_state_get(qctx, inst);
+ isc_result_t result;
+
+ if (state == NULL) {
+ return;
+ }
+
+ LOCK(&inst->hlock);
+ result = isc_ht_delete(inst->ht, (const unsigned char *)&qctx->client,
+ sizeof(qctx->client));
+ UNLOCK(&inst->hlock);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ isc_mem_put(inst->mctx, state, sizeof(*state));
+}
+
+static ns_hookresult_t
+async_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ async_instance_t *inst = (async_instance_t *)cbdata;
+ state_t *state = NULL;
+
+ logmsg("qctx init hook");
+ *resp = ISC_R_UNSET;
+
+ state = client_state_get(qctx, inst);
+ if (state == NULL) {
+ client_state_create(qctx, inst);
+ }
+
+ return (NS_HOOK_CONTINUE);
+}
+
+static void
+cancelasync(ns_hookasync_t *hctx) {
+ UNUSED(hctx);
+ logmsg("cancelasync");
+}
+
+static void
+destroyasync(ns_hookasync_t **ctxp) {
+ ns_hookasync_t *ctx = *ctxp;
+
+ logmsg("destroyasync");
+ *ctxp = NULL;
+ isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx));
+}
+
+static isc_result_t
+doasync(query_ctx_t *qctx, isc_mem_t *mctx, void *arg, isc_task_t *task,
+ isc_taskaction_t action, void *evarg, ns_hookasync_t **ctxp) {
+ ns_hook_resevent_t *rev = (ns_hook_resevent_t *)isc_event_allocate(
+ mctx, task, NS_EVENT_HOOKASYNCDONE, action, evarg,
+ sizeof(*rev));
+ ns_hookasync_t *ctx = isc_mem_get(mctx, sizeof(*ctx));
+ state_t *state = (state_t *)arg;
+
+ logmsg("doasync");
+ *ctx = (ns_hookasync_t){ .mctx = NULL };
+ isc_mem_attach(mctx, &ctx->mctx);
+ ctx->cancel = cancelasync;
+ ctx->destroy = destroyasync;
+
+ rev->hookpoint = state->hookpoint;
+ rev->origresult = state->origresult;
+ qctx->result = DNS_R_NOTIMP;
+ rev->saved_qctx = qctx;
+ rev->ctx = ctx;
+
+ state->rev = rev;
+
+ isc_task_send(task, (isc_event_t **)&rev);
+
+ *ctxp = ctx;
+ return (ISC_R_SUCCESS);
+}
+
+static ns_hookresult_t
+async_query_done_begin(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ async_instance_t *inst = (async_instance_t *)cbdata;
+ state_t *state = client_state_get(qctx, inst);
+
+ UNUSED(qctx);
+ UNUSED(cbdata);
+ UNUSED(state);
+
+ logmsg("done begin hook");
+ if (state->async) {
+ /* resuming */
+ state->async = false;
+ return (NS_HOOK_CONTINUE);
+ }
+
+ /* initial call */
+ state->async = true;
+ state->hookpoint = NS_QUERY_DONE_BEGIN;
+ state->origresult = *resp;
+ ns_query_hookasync(qctx, doasync, state);
+ return (NS_HOOK_RETURN);
+}
+
+static ns_hookresult_t
+async_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp) {
+ query_ctx_t *qctx = (query_ctx_t *)arg;
+ async_instance_t *inst = (async_instance_t *)cbdata;
+
+ logmsg("qctx destroy hook");
+ *resp = ISC_R_UNSET;
+
+ if (!qctx->detach_client) {
+ return (NS_HOOK_CONTINUE);
+ }
+
+ client_state_destroy(qctx, inst);
+
+ return (NS_HOOK_CONTINUE);
+}
diff --git a/bin/tests/system/hooks/ns1/example.db b/bin/tests/system/hooks/ns1/example.db
new file mode 100644
index 0000000..1d7173f
--- /dev/null
+++ b/bin/tests/system/hooks/ns1/example.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns.unsigned. hostmaster.ns.unsigned. ( 1 3600 1200 604800 60 )
+@ NS ns
+@ MX 10 mx
+
+ns A 10.53.0.1
+ AAAA fd92:7065:b8e:ffff::1
+
+a A 1.1.1.1
+mx A 2.2.2.2
diff --git a/bin/tests/system/hooks/ns1/named.conf.in b/bin/tests/system/hooks/ns1/named.conf.in
new file mode 100644
index 0000000..956bf41
--- /dev/null
+++ b/bin/tests/system/hooks/ns1/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ recursion no;
+ dnssec-validation yes;
+ notify yes;
+ minimal-responses no;
+};
+
+plugin query "../driver/.libs/test-async.so";
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example.com" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/hooks/setup.sh b/bin/tests/system/hooks/setup.sh
new file mode 100644
index 0000000..82240a7
--- /dev/null
+++ b/bin/tests/system/hooks/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/hooks/tests_async_plugin.py b/bin/tests/system/hooks/tests_async_plugin.py
new file mode 100644
index 0000000..2f42e27
--- /dev/null
+++ b/bin/tests/system/hooks/tests_async_plugin.py
@@ -0,0 +1,27 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import pytest
+
+pytest.importorskip("dns")
+import dns.message
+import dns.query
+import dns.rcode
+
+
+def test_async_hook(named_port):
+ msg = dns.message.make_query(
+ "example.com.",
+ "A",
+ )
+ ans = dns.query.udp(msg, "10.53.0.1", timeout=10, port=named_port)
+ # the test-async plugin changes the status of any positive answer to NOTIMP
+ assert ans.rcode() == dns.rcode.NOTIMP
diff --git a/bin/tests/system/host/clean.sh b/bin/tests/system/host/clean.sh
new file mode 100644
index 0000000..b03c459
--- /dev/null
+++ b/bin/tests/system/host/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns1/example.db
+rm -f host.out*
+rm -f host.err*
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/named.conf
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/host/ns1/example.net.db b/bin/tests/system/host/ns1/example.net.db
new file mode 100644
index 0000000..73aeeb1
--- /dev/null
+++ b/bin/tests/system/host/ns1/example.net.db
@@ -0,0 +1,31 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+
+@ 86400 IN SOA ns1 hostmaster (
+ 1397051952 ; "SER0"
+ 5
+ 5
+ 1814400
+ 3600 )
+@ NS ns1
+ns1 A 10.53.0.1
+
+a-only A 1.2.3.4
+aaaa-only AAAA 2001::ffff
+
+dual A 1.2.3.4
+ AAAA 2001::ffff
+
+cname-a-only CNAME a-only
+cname-aaaa-only CNAME aaaa-only
+cname-dual CNAME dual
diff --git a/bin/tests/system/host/ns1/named.conf.in b/bin/tests/system/host/ns1/named.conf.in
new file mode 100644
index 0000000..8338a9c
--- /dev/null
+++ b/bin/tests/system/host/ns1/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "example.net" {
+ type primary;
+ file "example.net.db";
+};
diff --git a/bin/tests/system/host/setup.sh b/bin/tests/system/host/setup.sh
new file mode 100644
index 0000000..754d4f3
--- /dev/null
+++ b/bin/tests/system/host/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 1 >ns1/example.db
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/host/tests.sh b/bin/tests/system/host/tests.sh
new file mode 100644
index 0000000..c640a40
--- /dev/null
+++ b/bin/tests/system/host/tests.sh
@@ -0,0 +1,128 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck disable=SC2086
+. ../conf.sh
+
+status=0
+n=0
+
+n=$((n+1))
+echo_i "Check A only lookup ($n)"
+ret=0
+$HOST -p ${PORT} a-only.example.net 10.53.0.1 2> host.err${n} > host.out${n} || ret=1
+lines=$(wc -l < host.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Address:" host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c a-only.example.net host.out${n})
+test $lines -eq 1 || ret=1
+grep "1.2.3.4" host.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check AAAA only lookup ($n)"
+ret=0
+$HOST -p ${PORT} aaaa-only.example.net 10.53.0.1 2> host.err${n} > host.out${n} || ret=1
+lines=$(wc -l < host.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Address:" host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c aaaa-only.example.net host.out${n})
+test $lines -eq 1 || ret=1
+grep "2001::ffff" host.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check dual A + AAAA lookup ($n)"
+ret=0
+$HOST -p ${PORT} dual.example.net 10.53.0.1 2> host.err${n} > host.out${n} || ret=1
+lines=$(wc -l < host.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Address:" host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c dual.example.net host.out${n})
+test $lines -eq 2 || ret=1
+grep "1.2.3.4" host.out${n} > /dev/null || ret=1
+grep "2001::ffff" host.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check CNAME to A only lookup ($n)"
+ret=0
+$HOST -p ${PORT} cname-a-only.example.net 10.53.0.1 2> host.err${n} > host.out${n} || ret=1
+lines=$(wc -l < host.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Address:" host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c "cname-a-only.example.net is an alias for a-only.example.net" host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep a-only.example.net host.out${n} | grep -cv "is an alias for")
+test $lines -eq 1 || ret=1
+grep "1.2.3.4" host.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check CNAME to AAAA only lookup ($n)"
+ret=0
+$HOST -p ${PORT} cname-aaaa-only.example.net 10.53.0.1 2> host.err${n} > host.out${n} || ret=1
+lines=$(wc -l < host.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Address:" host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c "cname-aaaa-only.example.net is an alias for aaaa-only.example.net" host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep aaaa-only.example.net host.out${n} | grep -cv "is an alias for")
+test $lines -eq 1 || ret=1
+grep "2001::ffff" host.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check CNAME to dual A + AAAA lookup ($n)"
+ret=0
+$HOST -p ${PORT} cname-dual.example.net 10.53.0.1 2> host.err${n} > host.out${n} || ret=1
+lines=$(wc -l < host.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Address:" host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c "cname-dual.example.net is an alias for dual.example.net." host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c "dual.example.net has address 1.2.3.4" host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c "dual.example.net has IPv6 address 2001::ffff" host.out${n})
+test $lines -eq 1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check ANY lookup ($n)"
+ret=0
+$HOST -p ${PORT} -t ANY example.net 10.53.0.1 2> host.err${n} > host.out${n} || ret=1
+lines=$(grep -c 'Address:.10\.53\.0\.1#'"${PORT}" host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c 'example.net has SOA record ns1.example.net. hostmaster.example.net. 1397051952 5 5 1814400 3600' host.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c 'example.net name server ns1.example.net.' host.out${n})
+test $lines -eq 1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/host/tests_sh_host.py b/bin/tests/system/host/tests_sh_host.py
new file mode 100644
index 0000000..56da3b1
--- /dev/null
+++ b/bin/tests/system/host/tests_sh_host.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_host(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/idna/clean.sh b/bin/tests/system/idna/clean.sh
new file mode 100644
index 0000000..f99ecb5
--- /dev/null
+++ b/bin/tests/system/idna/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f dig.out.*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/idna/ns1/named.conf.in b/bin/tests/system/idna/ns1/named.conf.in
new file mode 100644
index 0000000..df552bd
--- /dev/null
+++ b/bin/tests/system/idna/ns1/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ query-source address 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { fd92:7065:b8e:ffff::1; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/idna/ns1/root.db b/bin/tests/system/idna/ns1/root.db
new file mode 100644
index 0000000..b43cc40
--- /dev/null
+++ b/bin/tests/system/idna/ns1/root.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+a.root-servers.nil. AAAA fd92:7065:b8e:ffff::1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+ns2.example. AAAA fd92:7065:b8e:ffff::2
diff --git a/bin/tests/system/idna/setup.sh b/bin/tests/system/idna/setup.sh
new file mode 100644
index 0000000..2ac2ce8
--- /dev/null
+++ b/bin/tests/system/idna/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/idna/tests.sh b/bin/tests/system/idna/tests.sh
new file mode 100644
index 0000000..5f525d6
--- /dev/null
+++ b/bin/tests/system/idna/tests.sh
@@ -0,0 +1,393 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+# Set known locale for the tests
+
+if locale -a | grep -qE "^C\\.(UTF-8|utf8)"; then
+ LC_ALL="C.UTF-8"
+elif locale -a | grep -qE "^en_US\\.(UTF-8|utf8)"; then
+ LC_ALL="en_US.UTF-8"
+fi
+export LC_ALL
+
+# This set of tests check the behavior of the IDNA options in "dig".
+#
+# "dig" supports two IDNA-related options:
+#
+# +[no]idnin - Translates a domain name into punycode format before sending
+# the query to the server.
+#
+# Should the input name be a punycode name, "dig +idnin" will also
+# validate the punycode, rejecting it if it is invalid.
+#
+# +[no]idnout - Translates the received punycode domain names into appropriate
+# unicode characters before displaying.
+#
+# The tests run "dig" against an authoritative server configured with a minimal
+# root zone and nothing else. As a result, all queries will result in an
+# NXDOMAIN. The server will return the qname sent, which "dig" will display
+# according to the options selected. This returned string is compared with
+# the qname originally sent.
+#
+# In the comments below, the following nomenclature (taken from RFC 5890) is
+# used:
+#
+# A-label: Label comprising ASCII characters that starts xn-- and whose
+# characters after the xn-- are a valid output of the Punycode
+# algorithm.
+#
+# Fake A-label: An A-label whose characters after the xn-- are not valid
+# Punycode output.
+#
+# U-label: Unicode (native character) form of a label.
+#
+# For the purpose of this test script, U-labels do not include labels that
+# comprise purely ASCII characters, which are referred to as "ASCII-labels"
+# here. Valid ASCII-labels comprise letters, digits and hyphens and do not
+# start with a hyphen.
+#
+# References:
+# 1. http://www.unicode.org/reports/tr46/#Deviations
+# 2. http://www.unicode.org/reports/tr46/#IDNAComparison
+
+# Using dig insecure mode as we are not testing DNSSEC here
+DIGCMD="$DIG -i -p ${PORT} @10.53.0.1"
+
+# Initialize test count and status return
+n=0
+status=0
+
+
+# Function for extracting the qname from the response
+#
+# This is the first field in the line after the line starting
+# ";; QUESTION SECTION:".
+#
+# The string returned includes the trailing period.
+
+qname() {
+ awk 'BEGIN { qs = 0; } \
+ /;; QUESTION SECTION:/ { qs = 1; next; } \
+ qs == 1 {sub(";", "", $1) ; print $1; exit 0; }' \
+ $1
+}
+
+# Function for performing a test where "dig" is expected to succeed.
+#
+# $1 - Description of the test
+# $2 - Dig command additional options
+# $3 - Name being queried
+# $4 - The name that is expected to be displayed by "dig". Note that names
+# displayed by "dig" will always have a trailing period, so this
+# parameter should have that period as well.
+
+idna_test() {
+ n=$((n+1))
+ description=$1
+ if [ "$2" != "" ]; then
+ description="${description}: $2"
+ fi
+ echo_i "$description ($n)"
+
+ ret=0
+ { $DIGCMD $2 $3 > dig.out.$n 2>&1; rc=$?; } || true
+ if [ $rc -ne 0 ]; then
+ echo_i "failed: dig command returned non-zero status"
+ ret=1
+ else
+ actual=$(qname dig.out.$n)
+ if [ "$4" != "$actual" ]; then
+ echo_i "failed: expected answer $4, actual result $actual"
+ ret=1
+ fi
+ fi
+ status=$((status+ret))
+}
+
+# Function for performing a test where "dig" is expected to fail
+#
+# $1 - Description of the test
+# $2 - Dig command additional options
+# $3 - Name being queried
+
+idna_fail() {
+ n=$((n+1))
+ description=$1
+ if [ "$2" != "" ]; then
+ description="${description}: $2"
+ fi
+ echo_i "$description ($n)"
+
+ ret=0
+ { $DIGCMD $2 $3 > dig.out.$n 2>&1; rc=$?; } || true
+ if [ $rc -eq 0 ]; then
+ echo_i "failed: dig command unexpectedly succeeded"
+ ret=1
+ fi
+ status=$((status+ret))
+}
+
+# Function to check that case is preserved for an all-ASCII label.
+#
+# Without IDNA support, case-preservation is the expected behavior.
+#
+# With IDNA support... not really. IDNA maps uppercase ASCII characters to
+# their lower-case equivalent. When IDNA support in "dig" was updated to
+# non-transitional IDNA 2008, the switch "+idnin" was added and made the default
+# behaviour. This meant that the command "dig LocalhosT" (no command switches)
+# sends the qname "localhost", a change in behavior from earlier versions.
+#
+# This was felt to be confusing to the significant number of users who are
+# not interested in IDNA. For this reason, after "dig" passes the input qname
+# through the IDNA conversion, is does a case-insensitive comparison with the
+# result. If the two are the same, "dig" can conclude that the qname is
+# entirely ASCII and is uses the entered string instead of the converted string
+# as the qname.
+
+ascii_case_preservation_test() {
+ text="Checking valid ASCII label"
+ idna_test "$text" "" LocalhosT LocalhosT.
+ idna_test "$text" "+noidnin +noidnout" LocalhosT LocalhosT.
+ idna_test "$text" "+noidnin +idnout" LocalhosT LocalhosT.
+ idna_test "$text" "+idnin +noidnout" LocalhosT LocalhosT.
+ idna_test "$text" "+idnin +idnout" LocalhosT LocalhosT.
+}
+
+# Function to perform the tests if IDNA is enabled.
+
+idna_enabled_test() {
+ echo_i "IDNA is enabled, all IDNA tests will be performed"
+ # Check that case is preserved on an ASCII label.
+
+ ascii_case_preservation_test
+
+
+ # Test of a valid U-label
+ #
+ # +noidnin +noidnout: The label is sent as a unicode octet stream and dig
+ # will display the string in the \nnn format.
+ # +noidnin +idnout: As for the previous case.
+ # +idnin +noidnout: The label is converted to the xn-- format. "dig"
+ # displays the returned xn-- text.
+ # +idnin +idnout: The label is converted to the xn-- format. "dig"
+ # converts the returned xn-- string back to the original
+ # unicode text.
+ #
+ # Note that ASCII characters are converted to lower-case.
+
+ text="Checking valid non-ASCII label"
+ idna_test "$text" "" "München" "M\195\188nchen."
+ idna_test "$text" "+noidnin +noidnout" "München" "M\195\188nchen."
+ idna_test "$text" "+noidnin +idnout" "München" "M\195\188nchen."
+ idna_test "$text" "+idnin +noidnout" "München" "xn--mnchen-3ya."
+ idna_test "$text" "+idnin +idnout" "München" "münchen."
+
+
+ # Tests of transitional processing of a valid U-label
+ #
+ # IDNA2003 introduced national character sets but, unfortunately, didn't
+ # support several characters properly. One of those was the German
+ # character "ß" (the "Eszett" or "sharp s"), which was interpreted as "ss".
+ # So the domain “faß.de†domain (for example) was processed as “fass.deâ€.
+ #
+ # This was corrected in IDNA2008, although some vendors that adopted this
+ # standard chose to keep the existing IDNA2003 translation for this
+ # character to prevent problems (e.g. people visiting www.faß.example would,
+ # under IDNA2003, go to www.fass.example but under IDNA2008 would end up at
+ # www.fa\195\159.example - a different web site).
+ #
+ # BIND has adopted a hard transition, so this test checks that these
+ # transitional mapping is not used. The tests are essentially the same as
+ # for the valid U-label.
+
+ text="Checking that non-transitional IDNA processing is used"
+ idna_test "$text" "" "faß.de" "fa\195\159.de."
+ idna_test "$text" "+noidnin +noidnout" "faß.de" "fa\195\159.de."
+ idna_test "$text" "+noidnin +idnout" "faß.de" "fa\195\159.de."
+ idna_test "$text" "+idnin +noidnout" "faß.de" "xn--fa-hia.de."
+ idna_test "$text" "+idnin +idnout" "faß.de" "faß.de."
+
+ # Another problem character. The final character in the first label mapped
+ # onto the Greek sigma character ("σ") in IDNA2003.
+
+ text="Second check that non-transitional IDNA processing is used"
+ idna_test "$text" "" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com."
+ idna_test "$text" "+noidnin +noidnout" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com."
+ idna_test "$text" "+noidnin +idnout" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com."
+ idna_test "$text" "+idnin +noidnout" "βόλος.com" "xn--nxasmm1c.com."
+ idna_test "$text" "+idnin +idnout" "βόλος.com" "βόλος.com."
+
+
+
+ # Tests of a valid A-label (i.e. starting xn--)
+ #
+ # +noidnout: The string is sent as-is to the server and the returned qname
+ # is displayed in the same form.
+ # +idnout: The string is sent as-is to the server and the returned qname
+ # is displayed as the corresponding U-label.
+ #
+ # The "+[no]idnin" flag has no effect in these cases.
+
+ text="Checking valid A-label"
+ idna_test "$text" "" "xn--nxasmq6b.com" "xn--nxasmq6b.com."
+ idna_test "$text" "+noidnin +noidnout" "xn--nxasmq6b.com" "xn--nxasmq6b.com."
+ idna_test "$text" "+noidnin +idnout" "xn--nxasmq6b.com" "βόλοσ.com."
+ idna_test "$text" "+idnin +noidnout" "xn--nxasmq6b.com" "xn--nxasmq6b.com."
+ idna_test "$text" "+idnin +idnout" "xn--nxasmq6b.com" "βόλοσ.com."
+
+ # Test of valid A-label in locale that cannot display it
+ #
+ # +noidnout: The string is sent as-is to the server and the returned qname
+ # is displayed in the same form.
+ # +idnout: The string is sent as-is to the server and the returned qname
+ # is displayed as the corresponding A-label.
+ #
+ # The "+[no]idnout" flag has no effect in these cases.
+ saved_LC_ALL="${LC_ALL}"
+ LC_ALL="C"
+ text="Checking valid A-label in C locale"
+ label="xn--nxasmq6b.com"
+ if command -v idn2 >/dev/null && ! idn2 -d "$label" >/dev/null 2>/dev/null; then
+ idna_test "$text" "" "$label" "$label."
+ idna_test "$text" "+noidnin +noidnout" "$label" "$label."
+ idna_test "$text" "+noidnin +idnout" "$label" "$label."
+ idna_test "$text" "+idnin +noidnout" "$label" "$label."
+ idna_test "$text" "+idnin +idnout" "$label" "$label."
+ idna_test "$text" "+noidnin +idnout" "$label" "$label."
+ fi
+ LC_ALL="${saved_LC_ALL}"
+
+
+
+ # Tests of invalid A-labels
+ #
+ # +noidnin: The label is sent as-is to the server and dig will display the
+ # returned fake A-label in the same form.
+ # +idnin: "dig" should report that the label is not correct.
+ #
+ # +[no]idnout: If the label makes it to the server (via +noidnin), "dig"
+ # should report an error if +idnout is specified.
+
+ # The minimum length of a punycode A-label is 7 characters. Check that
+ # a shorter label is detected and rejected.
+
+ text="Checking punycode label shorter than minimum valid length"
+ idna_test "$text" "" "xn--xx" "xn--xx."
+ idna_test "$text" "+noidnin +noidnout" "xn--xx" "xn--xx."
+ idna_fail "$text" "+noidnin +idnout" "xn--xx"
+ idna_fail "$text" "+idnin +noidnout" "xn--xx"
+ idna_fail "$text" "+idnin +idnout" "xn--xx"
+
+ # Fake A-label - the string does not translate to anything.
+
+ text="Checking fake A-label"
+ idna_test "$text" "" "xn--ahahah" "xn--ahahah."
+ idna_test "$text" "+noidnin +noidnout" "xn--ahahah" "xn--ahahah."
+ idna_fail "$text" "+noidnin +idnout" "xn--ahahah"
+ idna_fail "$text" "+idnin +noidnout" "xn--ahahah"
+ idna_fail "$text" "+idnin +idnout" "xn--ahahah"
+
+ # Too long a label. The punycode string is too long (at 64 characters).
+ # BIND rejects such labels: with +idnin
+
+ label="xn--xflod18hstflod18hstflod18hstflod18hstflod18hstflod18-1iejjjj"
+ text="Checking punycode label longer than maximum valid length"
+ idna_fail "$text" "" "$label"
+ idna_fail "$text" "+noidnin +noidnout" "$label"
+ idna_fail "$text" "+noidnin +idnout" "$label"
+ idna_fail "$text" "+idnin +noidnout" "$label"
+ idna_fail "$text" "+idnin +idnout" "$label"
+
+ # Tests of a valid unicode string but an invalid U-label (input)
+ #
+ # Symbols are not valid IDNA2008 names. Check whether dig rejects them
+ # when they are supplied on the command line to ensure no IDNA2003
+ # fallbacks are in place.
+ #
+ # +noidnin: "dig" should send unicode octets to the server and display the
+ # returned qname in the same form.
+ # +idnin: "dig" should generate an error.
+ #
+ # The +[no]idnout options should not have any effect on the test.
+
+ text="Checking invalid input U-label"
+ idna_test "$text" "" "√.com" "\226\136\154.com."
+ idna_test "$text" "+noidnin +noidnout" "√.com" "\226\136\154.com."
+ idna_test "$text" "+noidnin +idnout" "√.com" "\226\136\154.com."
+ idna_test "$text" "+idnin +noidnout" "√.com" "xn--19g.com."
+ idna_test "$text" "+idnin +idnout" "√.com" "√.com."
+
+ # Tests of a valid unicode string but an invalid U-label (output)
+ #
+ # Symbols are not valid IDNA2008 names. Check whether dig rejects them
+ # when they are received in DNS responses to ensure no IDNA2003 fallbacks
+ # are in place.
+ #
+ # Note that "+idnin +noidnout" is not tested because libidn2 2.2.0+ parses
+ # Punycode more strictly than older versions and thus dig fails with that
+ # combination of options with libidn2 2.2.0+ but succeeds with older
+ # versions.
+ #
+ # +noidnout: "dig" should send the ACE string to the server and display the
+ # returned qname.
+ # +idnout: "dig" should generate an error.
+ #
+ # The +[no]idnin options should not have any effect on the test.
+
+ text="Checking invalid output U-label"
+ idna_test "$text" "" "xn--19g" "xn--19g."
+ idna_test "$text" "+noidnin +noidnout" "xn--19g" "xn--19g."
+ idna_test "$text" "+noidnin +idnout" "xn--19g" "√."
+ idna_test "$text" "+idnin +idnout" "xn--19g" "√."
+
+
+ # Test that non-letter characters are preserved in the output. When
+ # UseSTD3ASCIIRules are enabled, it would mangle non-letter characters like
+ # `_` (underscore) and `*` (wildcard.
+
+ text="Checking valid non-letter characters"
+ idna_test "$text" "" "*.xn--nxasmq6b.com" "*.xn--nxasmq6b.com."
+ idna_test "$text" "+noidnin +noidnout" "*.xn--nxasmq6b.com" "*.xn--nxasmq6b.com."
+ idna_test "$text" "+noidnin +idnout" "*.xn--nxasmq6b.com" "*.βόλοσ.com."
+ idna_test "$text" "+idnin +noidnout" "*.xn--nxasmq6b.com" "*.xn--nxasmq6b.com."
+ idna_test "$text" "+idnin +idnout" "*.xn--nxasmq6b.com" "*.βόλοσ.com."
+
+ idna_test "$text" "" "_tcp.xn--nxasmq6b.com" "_tcp.xn--nxasmq6b.com."
+ idna_test "$text" "+noidnin +noidnout" "_tcp.xn--nxasmq6b.com" "_tcp.xn--nxasmq6b.com."
+ idna_test "$text" "+noidnin +idnout" "_tcp.xn--nxasmq6b.com" "_tcp.βόλοσ.com."
+ idna_test "$text" "+idnin +noidnout" "_tcp.xn--nxasmq6b.com" "_tcp.xn--nxasmq6b.com."
+ idna_test "$text" "+idnin +idnout" "_tcp.xn--nxasmq6b.com" "_tcp.βόλοσ.com."
+}
+
+
+# Function to perform tests if IDNA is not enabled.
+
+idna_disabled_test() {
+ echo_i "IDNA is disabled, only case mapping tests will be performed"
+ ascii_case_preservation_test
+}
+
+
+# Main test begins here
+
+if $FEATURETEST --with-libidn2; then
+ idna_enabled_test
+else
+ idna_disabled_test
+fi
+
+exit $status
diff --git a/bin/tests/system/idna/tests_sh_idna.py b/bin/tests/system/idna/tests_sh_idna.py
new file mode 100644
index 0000000..82a640c
--- /dev/null
+++ b/bin/tests/system/idna/tests_sh_idna.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_idna(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/ifconfig.sh.in b/bin/tests/system/ifconfig.sh.in
new file mode 100755
index 0000000..ed84fd1
--- /dev/null
+++ b/bin/tests/system/ifconfig.sh.in
@@ -0,0 +1,268 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Set up interface aliases for bind9 system tests.
+#
+# IPv4: 10.53.0.{1..11} RFC 1918
+# 10.53.1.{1..2}
+# 10.53.2.{1..2}
+# IPv6: fd92:7065:b8e:ffff::{1..11} ULA
+# fd92:7065:b8e:99ff::{1..2}
+# fd92:7065:b8e:ff::{1..2}
+#
+# We also set the MTU on the 1500 bytes to match the default MTU on physical
+# interfaces, so we can properly test the cases with packets bigger than
+# interface MTU.
+#
+# See also org.isc.bind.system (a version of this script for use on macOS)
+# and testsock.pl (which checks the interfaces are configured)
+#
+
+top_srcdir=@abs_top_srcdir@
+
+sys=$(@SHELL@ "$top_srcdir/config.guess")
+
+use_ip=
+case "$sys" in
+ *-*-linux*)
+ if type ip > /dev/null; then
+ use_ip=yes
+ elif type ifconfig > /dev/null; then
+ :
+ else
+ echo "$0: can't find ip or ifconfig" >&2
+ exit 1
+ fi
+ ;;
+esac
+
+up() {
+ case "$sys" in
+ *-pc-solaris2.5.1)
+ [ "$a" ] && ifconfig lo0:$int $a netmask 0xffffffff up
+ ;;
+ *-sun-solaris2.[6-7])
+ [ "$a" ] && ifconfig lo0:$int $a netmask 0xffffffff up
+ ;;
+ *-*-solaris2.[8-9]|*-*-solaris2.10)
+ [ "$a" ] && {
+ /sbin/ifconfig lo0:$int plumb
+ /sbin/ifconfig lo0:$int $a up
+ /sbin/ifconfig lo0:$int mtu 1500
+ }
+ [ "$aaaa" ] && {
+ /sbin/ifconfig lo0:$int inet6 plumb
+ /sbin/ifconfig lo0:$int inet6 $aaaa up
+ }
+ ;;
+ *-*-solaris2.1[1-9])
+ [ "$a" ] && {
+ /sbin/ipadm create-addr -t -T static \
+ -a $a lo0/bind9v4$int ||
+ echo failed lo0/bind9v4$int
+ }
+ [ "$aaaa" ] && {
+ /sbin/ipadm create-addr -t -T static \
+ -a $aaaa lo0/bind9v6$int ||
+ echo failed lo0/bind9v6$int
+ }
+ ;;
+ *-*-linux*)
+ if [ "$use_ip" ]; then
+ ip address add $a/24 dev lo:$int
+ ip link set dev lo:$int mtu 1500
+ [ "$aaaa" ] && ip address add $aaaa/64 dev lo
+ else
+ ifconfig lo:$int $a up netmask 255.255.255.0 mtu 1500
+ [ "$aaaa" ] && ifconfig lo inet6 add $aaaa/64
+ fi
+ ;;
+ *-unknown-freebsd*)
+ [ "$a" ] && ifconfig lo0 $a alias netmask 0xffffffff mtu 1500
+ [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa alias
+ ;;
+ *-unknown-dragonfly*|*-unknown-netbsd*|*-unknown-openbsd*)
+ [ "$a" ] && ifconfig lo0 $a alias netmask 255.255.255.0 mtu 1500
+ [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa alias
+ ;;
+ *-*-bsdi[3-5].*)
+ [ "$a" ] && ifconfig lo0 add $a netmask 255.255.255.0
+ ;;
+ *-dec-osf[4-5].*)
+ [ "$a" ] && ifconfig lo0 alias $a
+ ;;
+ *-sgi-irix6.*)
+ [ "$a" ] && ifconfig lo0 alias $a
+ ;;
+ *-*-sysv5uw7*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ [ "$a" ] && ifconfig lo0 $a alias netmask 0xffffffff
+ ;;
+ *-ibm-aix4.*|*-ibm-aix5.*)
+ [ "$a" ] && ifconfig lo0 alias $a
+ [ "$aaaa" ] && ifconfig lo0 inet6 alias -dad $aaaa/64
+ ;;
+ hpux)
+ [ "$a" ] && ifconfig lo0:$int $a netmask 255.255.255.0 up
+ [ "$aaaa" ] && ifconfig lo0:$int inet6 $aaaa up
+ ;;
+ *-sco3.2v*)
+ [ "$a" ] && ifconfig lo0 alias $a
+ ;;
+ *-darwin*)
+ [ "$a" ] && ifconfig lo0 alias $a
+ [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa alias
+ ;;
+ *)
+ echo "Don't know how to set up interface. Giving up."
+ exit 1
+ ;;
+ esac
+}
+
+down() {
+ case "$sys" in
+ *-pc-solaris2.5.1)
+ [ "$a" ] && ifconfig lo0:$int 0.0.0.0 down
+ ;;
+ *-sun-solaris2.[6-7])
+ [ "$a" ] && ifconfig lo0:$int $a down
+ ;;
+ *-*-solaris2.[8-9]|*-*-solaris2.10)
+ [ "$a" ] && {
+ ifconfig lo0:$int $a down
+ ifconfig lo0:$int $a unplumb
+ }
+ [ "$aaaa" ] && {
+ ifconfig lo0:$int inet6 down
+ ifconfig lo0:$int inet6 unplumb
+ }
+ ;;
+ *-*-solaris2.1[1-9])
+ [ "$a" ] && {
+ ipadm delete-addr lo0/bind9v4$int ||
+ echo failed lo0/bind9v4$int
+ }
+ [ "$aaaa" ] && {
+ ipadm delete-addr lo0/bind9v6$int ||
+ echo failed lo0/bind9v6$int
+ }
+ ;;
+
+ *-*-linux*)
+ if [ "$use_ip" ]; then
+ [ "$a" ] && ip address del $a/24 dev lo:$int
+ [ "$aaaa" ] && ip address del $aaaa/64 dev lo
+ else
+ [ "$a" ] && ifconfig lo:$int $a down
+ [ "$aaaa" ] && ifconfig lo inet6 del $aaaa/64
+ fi
+ ;;
+ *-unknown-freebsd*)
+ [ "$a" ] && ifconfig lo0 $a delete
+ [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa delete
+ ;;
+ *-unknown-netbsd*)
+ [ "$a" ] && ifconfig lo0 $a delete
+ [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa delete
+ ;;
+ *-unknown-openbsd*)
+ [ "$a" ] && ifconfig lo0 $a delete
+ [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa delete
+ ;;
+ *-*-bsdi[3-5].*)
+ [ "$a" ] && ifconfig lo0 remove $a
+ ;;
+ *-dec-osf[4-5].*)
+ [ "$a" ] && ifconfig lo0 -alias $a
+ ;;
+ *-sgi-irix6.*)
+ [ "$a" ] && ifconfig lo0 -alias $a
+ ;;
+ *-*-sysv5uw7*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ [ "$a" ] && ifconfig lo0 -alias $a
+ ;;
+ *-ibm-aix4.*|*-ibm-aix5.*)
+ [ "$a" ] && ifconfig lo0 delete $a
+ [ "$aaaa" ] && ifconfig lo0 delete inet6 $aaaa/64
+ ;;
+ hpux)
+ [ "$a" ] && ifconfig lo0:$int 0.0.0.0
+ [ "$aaaa" ] && ifconfig lo0:$int inet6 ::
+ ;;
+ *-sco3.2v*)
+ [ "$a" ] && ifconfig lo0 -alias $a
+ ;;
+ *darwin*)
+ [ "$a" ] && ifconfig lo0 -alias $a
+ [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa delete
+ ;;
+ *)
+ echo "Don't know how to destroy interface. Giving up."
+ exit 1
+ ;;
+ esac
+}
+
+sequence() (
+ awk -v s=$1 -v e=$2 '
+ BEGIN {
+ for (i = s ; i <= e; i++) { print i; }
+ exit;
+ }'
+)
+
+#
+# 'max', 'i' and 'ns' are used to compute the interface identifier for
+# systems that need it and must be unique for each interface (e.g. lo:$int).
+#
+# int=$((i * max + ns))
+#
+# 'max' is the number of nameservers configured in the inner loop.
+# 'i' is the outer loop counter.
+# 'ns' in the namserver being configured.
+# 'int' interface identifier.
+#
+# See also `org.isc.bind.system`.
+#
+# This `max` setting is grepped out for use by testsock.pl
+#
+max=11
+case $1 in
+ start|up|stop|down)
+ for i in $(sequence 0 2)
+ do
+ case $i in
+ 0) ipv6="ff" ;;
+ 1) ipv6="99" ;;
+ 2) ipv6="00" ;;
+ *) ipv6="" ;;
+ esac
+ for ns in $(sequence 1 $max)
+ do
+ [ $i -gt 0 -a $ns -gt 2 ] && break
+ int=$((i * max + ns))
+ a=10.53.$i.$ns
+ aaaa=fd92:7065:b8e:${ipv6}ff::$ns
+ case "$1" in
+ start|up) up;;
+ stop|down) down;;
+ esac
+ done
+ done
+ ;;
+ *)
+ echo "Usage: $0 { up | down }"
+ exit 1
+ ;;
+esac
diff --git a/bin/tests/system/include-multiplecfg/clean.sh b/bin/tests/system/include-multiplecfg/clean.sh
new file mode 100644
index 0000000..905b2dd
--- /dev/null
+++ b/bin/tests/system/include-multiplecfg/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after allow query tests.
+#
+
+rm -f dig.out.*
+rm -f ns*/named.conf
+rm -f */named.memstats
+rm -f ns*/named.lock
+rm -f ns*/named.run ns*/named.run.prev
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
diff --git a/bin/tests/system/include-multiplecfg/ns2/mars.com.db b/bin/tests/system/include-multiplecfg/ns2/mars.com.db
new file mode 100644
index 0000000..cbae017
--- /dev/null
+++ b/bin/tests/system/include-multiplecfg/ns2/mars.com.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA dns1.mars.com. hostmaster.mars.com. (
+ 2001062501 ; serial
+ 21600 ; refresh after 6 hours
+ 3600 ; retry after 1 hour
+ 604800 ; expire after 1 week
+ 86400 ) ; minimum TTL of 1 day
+
+ IN NS dns1.mars.com.
+
+ IN A 10.53.0.1
+
+dns1 IN A 10.53.0.1
diff --git a/bin/tests/system/include-multiplecfg/ns2/mars.conf b/bin/tests/system/include-multiplecfg/ns2/mars.conf
new file mode 100644
index 0000000..31f6da3
--- /dev/null
+++ b/bin/tests/system/include-multiplecfg/ns2/mars.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "mars.com" {
+ type primary;
+ file "mars.com.db";
+};
+
diff --git a/bin/tests/system/include-multiplecfg/ns2/named.conf.in b/bin/tests/system/include-multiplecfg/ns2/named.conf.in
new file mode 100644
index 0000000..b38c228
--- /dev/null
+++ b/bin/tests/system/include-multiplecfg/ns2/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ dnssec-validation no;
+};
+
+# Should include all files matching pattern.
+include "zone*.conf";
+
+# Shouldn't break standard file pattern.
+include "mars.conf";
+
diff --git a/bin/tests/system/include-multiplecfg/ns2/zone1.com.db b/bin/tests/system/include-multiplecfg/ns2/zone1.com.db
new file mode 100644
index 0000000..ef9cff4
--- /dev/null
+++ b/bin/tests/system/include-multiplecfg/ns2/zone1.com.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA dns1.zone1.com. hostmaster.zone1.com. (
+ 2001062501 ; serial
+ 21600 ; refresh after 6 hours
+ 3600 ; retry after 1 hour
+ 604800 ; expire after 1 week
+ 86400 ) ; minimum TTL of 1 day
+
+ IN NS dns1.zone1.com.
+
+ IN A 10.53.0.1
+
+dns1 IN A 10.53.0.1
diff --git a/bin/tests/system/include-multiplecfg/ns2/zone1.conf b/bin/tests/system/include-multiplecfg/ns2/zone1.conf
new file mode 100644
index 0000000..e5c15ad
--- /dev/null
+++ b/bin/tests/system/include-multiplecfg/ns2/zone1.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "zone1.com" {
+ type primary;
+ file "zone1.com.db";
+};
+
diff --git a/bin/tests/system/include-multiplecfg/ns2/zone2.com.db b/bin/tests/system/include-multiplecfg/ns2/zone2.com.db
new file mode 100644
index 0000000..6df12b2
--- /dev/null
+++ b/bin/tests/system/include-multiplecfg/ns2/zone2.com.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA dns1.zone2.com. hostmaster.zone2.com. (
+ 2001062501 ; serial
+ 21600 ; refresh after 6 hours
+ 3600 ; retry after 1 hour
+ 604800 ; expire after 1 week
+ 86400 ) ; minimum TTL of 1 day
+
+ IN NS dns1.zone2.com.
+
+ IN A 10.53.0.1
+
+dns1 IN A 10.53.0.1
diff --git a/bin/tests/system/include-multiplecfg/ns2/zone2.conf b/bin/tests/system/include-multiplecfg/ns2/zone2.conf
new file mode 100644
index 0000000..b122b0f
--- /dev/null
+++ b/bin/tests/system/include-multiplecfg/ns2/zone2.conf
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "zone2.com" {
+ type primary;
+ file "zone2.com.db";
+};
+
diff --git a/bin/tests/system/include-multiplecfg/setup.sh b/bin/tests/system/include-multiplecfg/setup.sh
new file mode 100644
index 0000000..064fb01
--- /dev/null
+++ b/bin/tests/system/include-multiplecfg/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns2/named.conf.in ns2/named.conf
diff --git a/bin/tests/system/include-multiplecfg/tests.sh b/bin/tests/system/include-multiplecfg/tests.sh
new file mode 100644
index 0000000..65b4001
--- /dev/null
+++ b/bin/tests/system/include-multiplecfg/tests.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Test of include statement with glob expression.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +nosea +nostat +nocmd +norec +noques +noadd +nostats -p ${PORT}"
+
+status=0
+n=0
+
+# Test 1 - check if zone1 was loaded.
+n=$((n + 1))
+echo_i "checking glob include of zone1 config ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 zone1.com. a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^zone1.com.' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 2 - check if zone2 was loaded.
+n=$((n + 1))
+echo_i "checking glob include of zone2 config ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 zone2.com. a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^zone2.com.' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 3 - check if standard file path (no magic chars) works.
+n=$((n + 1))
+echo_i "checking include of standard file path config ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 mars.com. a > dig.out.ns2.$n || ret=1
+grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1
+grep '^mars.com.' dig.out.ns2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Test 4: named-checkconf correctly parses glob includes.
+n=$((n + 1))
+echo_i "checking named-checkconf with glob include ($n)"
+ret=0
+(cd ns2; $CHECKCONF named.conf) || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/include-multiplecfg/tests_sh_include_multiplecfg.py b/bin/tests/system/include-multiplecfg/tests_sh_include_multiplecfg.py
new file mode 100644
index 0000000..e767c1d
--- /dev/null
+++ b/bin/tests/system/include-multiplecfg/tests_sh_include_multiplecfg.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_include_multiplecfg(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/inline/clean.sh b/bin/tests/system/inline/clean.sh
new file mode 100644
index 0000000..79f3774
--- /dev/null
+++ b/bin/tests/system/inline/clean.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -rf ./*/*.jbk \
+ ./*/*.nzd ./*/*.nzd-lock ./*/*.nzf \
+ ./*/named.conf ./*/named.memstats ./*/named.run* ./*/named.lock \
+ ./*/trusted.conf \
+ ./K* ./*/K* \
+ ./checkecdsa \
+ ./freeze.test* thaw.test* \
+ ./import.key \
+ ././ns*/managed-keys.bind* ./ns*/*.mkeys* \
+ ./*/dsset-* ./*/nzf-* \
+ ./*/*.db ./*/*.db.signed ./*/*.db.jnl ./*/*.db.signed.jnl \
+ ./*.out ./*.out* ./*/*.out ./*/*.out* \
+ ./*/*.bk ./*/*.bk.jnl ./*/*.bk.signed ./*/*.bk.signed.jnl \
+ ns3/a-file ns3/removedkeys
diff --git a/bin/tests/system/inline/ns1/named.conf.in b/bin/tests/system/inline/ns1/named.conf.in
new file mode 100644
index 0000000..da27c58
--- /dev/null
+++ b/bin/tests/system/inline/ns1/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+controls { /* empty */ };
+
+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;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/inline/ns1/root.db.in b/bin/tests/system/inline/ns1/root.db.in
new file mode 100644
index 0000000..abc7370
--- /dev/null
+++ b/bin/tests/system/inline/ns1/root.db.in
@@ -0,0 +1,59 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+bits. NS ns3.bits.
+bits. NS ns4.bits.
+ns3.bits. A 10.53.0.3
+ns4.bits. A 10.53.0.4
+
+noixfr. NS ns3.noixfr.
+ns3.noixfr. A 10.53.0.3
+
+primary. NS ns3.primary.
+ns3.primary. A 10.53.0.3
+
+dynamic. NS ns3.dynamic.
+ns3.dynamic. A 10.53.0.3
+
+updated. NS ns3.updated.
+ns3.updated. A 10.53.0.3
+
+expired. NS ns3.expired.
+ns3.expired. A 10.53.0.3
+
+retransfer. NS ns3.retransfer.
+ns3.retransfer. A 10.53.0.3
+
+nsec3. NS ns3.nsec3.
+ns3.nsec3. A 10.53.0.3
+
+externalkey. NS ns3.externalkey.
+ns3.externalkey. A 10.53.0.3
+
+retransfer3. NS ns3.retransfer.
+ns3.retransfer3. A 10.53.0.3
+
+inactiveksk. NS ns3.inactiveksk.
+ns3.inactiveksk. A 10.53.0.3
+
+inactivezsk. NS ns3.inactivezsk.
+ns3.inactivezsk. A 10.53.0.3
diff --git a/bin/tests/system/inline/ns1/sign.sh b/bin/tests/system/inline/ns1/sign.sh
new file mode 100644
index 0000000..c231713
--- /dev/null
+++ b/bin/tests/system/inline/ns1/sign.sh
@@ -0,0 +1,25 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=.
+rm -f K.+*+*.key
+rm -f K.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+$SIGNER -S -x -T 1200 -o ${zone} root.db > signer.out
+[ $? = 0 ] || cat signer.out
+
+keyfile_to_static_ds $keyname > trusted.conf
+cp trusted.conf ../ns6/trusted.conf
diff --git a/bin/tests/system/inline/ns2/bits.db.in b/bin/tests/system/inline/ns2/bits.db.in
new file mode 100644
index 0000000..2652047
--- /dev/null
+++ b/bin/tests/system/inline/ns2/bits.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns2 . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/inline/ns2/named.conf.in b/bin/tests/system/inline/ns2/named.conf.in
new file mode 100644
index 0000000..38e6e90
--- /dev/null
+++ b/bin/tests/system/inline/ns2/named.conf.in
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ notify-delay 0;
+ allow-new-zones yes;
+ dnssec-validation no;
+};
+
+zone "bits" {
+ type primary;
+ file "bits.db";
+ allow-update { any; };
+};
+
+zone "retransfer" {
+ type primary;
+ file "retransfer.db";
+ allow-update { any; };
+ notify no;
+};
+
+zone "retransfer3" {
+ type primary;
+ file "retransfer3.db";
+ allow-update { any; };
+ allow-transfer { none; }; // changed dynamically by tests.sh
+ notify no;
+};
+
+zone "nsec3-loop" {
+ type primary;
+ file "nsec3-loop.db";
+ notify no;
+};
+
+zone "inactiveksk" {
+ type primary;
+ file "inactiveksk.db";
+ allow-update { any; };
+};
+
+zone "inactivezsk" {
+ type primary;
+ file "inactivezsk.db";
+ allow-update { any; };
+};
+
+zone "nokeys" {
+ type primary;
+ file "nokeys.db";
+ allow-update { any; };
+};
+
+zone "removedkeys-secondary" {
+ type primary;
+ file "removedkeys-secondary.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/inline/ns2/nsec3-loop.db.in b/bin/tests/system/inline/ns2/nsec3-loop.db.in
new file mode 100644
index 0000000..d12af8d
--- /dev/null
+++ b/bin/tests/system/inline/ns2/nsec3-loop.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; NOTE: This zone's data has been crafted in order to reproduce a very specific
+; scenario (see ns7/named.conf for more details). Please do not modify this
+; file.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns2 . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
diff --git a/bin/tests/system/inline/ns3/include.db.in b/bin/tests/system/inline/ns3/include.db.in
new file mode 100644
index 0000000..c46a6a8
--- /dev/null
+++ b/bin/tests/system/inline/ns3/include.db.in
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+f A 10.0.0.7
diff --git a/bin/tests/system/inline/ns3/named.conf.in b/bin/tests/system/inline/ns3/named.conf.in
new file mode 100644
index 0000000..6b3b3cd
--- /dev/null
+++ b/bin/tests/system/inline/ns3/named.conf.in
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 no;
+ notify yes;
+ try-tcp-refresh no;
+ notify-delay 0;
+ allow-new-zones yes;
+ dnssec-validation no;
+};
+
+zone "bits" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update-forwarding { any; };
+ file "bits.bk";
+ sig-signing-signatures 1; // force incremental processing
+};
+
+server 10.53.0.4 { request-ixfr no; };
+
+zone "noixfr" {
+ type secondary;
+ primaries { 10.53.0.4; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update-forwarding { any; };
+ file "noixfr.bk";
+};
+
+zone "primary" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "primary.db";
+ notify explicit;
+ also-notify {
+ 10.53.0.3;
+ };
+};
+
+zone "dynamic" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update { any; };
+ file "dynamic.db";
+};
+
+zone "updated" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update { none; };
+ file "updated.db";
+};
+
+zone "expired" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update { any; };
+ file "expired.db";
+};
+
+zone "retransfer" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "retransfer.bk";
+};
+
+zone "nsec3" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update { any; };
+ file "nsec3.db";
+};
+
+zone "externalkey" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ dnssec-dnskey-kskonly no;
+ allow-update { any; };
+ file "externalkey.db";
+};
+
+zone "retransfer3" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "retransfer3.bk";
+};
+
+zone "inactiveksk" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ dnssec-dnskey-kskonly yes;
+ file "inactiveksk.bk";
+};
+
+zone "inactivezsk" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "inactivezsk.bk";
+};
+
+zone "nokeys" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "nokeys.bk";
+};
+
+zone "delayedkeys" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "delayedkeys.db";
+};
+
+zone "removedkeys-primary" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ file "removedkeys-primary.db";
+};
+
+zone "removedkeys-secondary" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "removedkeys-secondary.bk";
+};
+
+zone "unsupported" {
+ type primary;
+ file "unsupported.db";
+ inline-signing yes;
+ auto-dnssec maintain;
+};
diff --git a/bin/tests/system/inline/ns3/primary.db.in b/bin/tests/system/inline/ns3/primary.db.in
new file mode 100644
index 0000000..4d30cf6
--- /dev/null
+++ b/bin/tests/system/inline/ns3/primary.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns3 . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/inline/ns3/primary2.db.in b/bin/tests/system/inline/ns3/primary2.db.in
new file mode 100644
index 0000000..24a0666
--- /dev/null
+++ b/bin/tests/system/inline/ns3/primary2.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns3 . (
+ 2000042408 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns3 A 10.53.0.3
+
+e A 10.0.0.5
diff --git a/bin/tests/system/inline/ns3/primary3.db.in b/bin/tests/system/inline/ns3/primary3.db.in
new file mode 100644
index 0000000..f3062c3
--- /dev/null
+++ b/bin/tests/system/inline/ns3/primary3.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns3 . (
+ 2000042409 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns3 A 10.53.0.3
+
+c A 10.0.0.3
+e A 10.0.0.5
diff --git a/bin/tests/system/inline/ns3/primary4.db.in b/bin/tests/system/inline/ns3/primary4.db.in
new file mode 100644
index 0000000..737e2e2
--- /dev/null
+++ b/bin/tests/system/inline/ns3/primary4.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns3 hostmaster. (
+ 2000042410 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns3 A 10.53.0.3
+
+c A 10.0.0.3
+e A 10.0.0.5
diff --git a/bin/tests/system/inline/ns3/primary5.db.in b/bin/tests/system/inline/ns3/primary5.db.in
new file mode 100644
index 0000000..a1e1300
--- /dev/null
+++ b/bin/tests/system/inline/ns3/primary5.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns3 . (
+ 2000042411 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns3 A 10.53.0.3
+
+c A 10.0.0.3
+e A 10.0.0.5
diff --git a/bin/tests/system/inline/ns3/primary6.db.in b/bin/tests/system/inline/ns3/primary6.db.in
new file mode 100644
index 0000000..de3e651
--- /dev/null
+++ b/bin/tests/system/inline/ns3/primary6.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns3 . (
+ 2000042412 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns3 A 10.53.0.3
+
+c A 10.0.0.3
+e A 10.0.0.5
+
+$INCLUDE missingfile.db
diff --git a/bin/tests/system/inline/ns3/primary7.db.in b/bin/tests/system/inline/ns3/primary7.db.in
new file mode 100644
index 0000000..a3e33e7
--- /dev/null
+++ b/bin/tests/system/inline/ns3/primary7.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns3 . (
+ 2000042412 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns3 A 10.53.0.3
+
+c A 10.0.0.3
+e A 10.0.0.5
+
+$INCLUDE include.db
diff --git a/bin/tests/system/inline/ns3/sign.sh b/bin/tests/system/inline/ns3/sign.sh
new file mode 100755
index 0000000..f17a8ad
--- /dev/null
+++ b/bin/tests/system/inline/ns3/sign.sh
@@ -0,0 +1,159 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+# Fake an unsupported key
+unsupportedkey=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone unsupported)
+awk '$3 == "DNSKEY" { $6 = 255 } { print }' ${unsupportedkey}.key > ${unsupportedkey}.tmp
+mv ${unsupportedkey}.tmp ${unsupportedkey}.key
+
+zone=bits
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+
+zone=noixfr
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+
+zone=primary
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+
+zone=dynamic
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+
+zone=updated
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+$SIGNER -S -O raw -L 2000042407 -o ${zone} ${zone}.db > /dev/null
+cp primary2.db.in updated.db
+
+# signatures are expired and should be regenerated on startup
+zone=expired
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+$SIGNER -PS -s 20100101000000 -e 20110101000000 -O raw -L 2000042407 -o ${zone} ${zone}.db > /dev/null
+
+zone=retransfer
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+
+zone=nsec3
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+
+zone=retransfer3
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+
+zone=inactiveksk
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -P now -A now+3600 -f KSK $zone)
+keyname=$($KEYGEN -q -a ${ALTERNATIVE_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${ALTERNATIVE_ALGORITHM} -n zone -f KSK $zone)
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+
+zone=inactivezsk
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -P now -A now+3600 $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+keyname=$($KEYGEN -q -a ${ALTERNATIVE_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${ALTERNATIVE_ALGORITHM} -n zone -f KSK $zone)
+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
+
+zone=delayedkeys
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+# Keys for the "delayedkeys" zone should not be initially accessible.
+mv K${zone}.+*+*.* ../
+
+zone=removedkeys-primary
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+
+zone=removedkeys-secondary
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+
+for s in a c d h k l m q z
+do
+ zone=test-$s
+ keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+done
+
+for s in b f i o p t v
+do
+ zone=test-$s
+ keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+ keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+done
+
+zone=externalkey
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+
+for alg in ${DEFAULT_ALGORITHM} ${ALTERNATIVE_ALGORITHM}
+do
+ k1=$($KEYGEN -q -a $alg -n zone -f KSK $zone)
+ k2=$($KEYGEN -q -a $alg -n zone $zone)
+ k3=$($KEYGEN -q -a $alg -n zone $zone)
+ k4=$($KEYGEN -q -a $alg -n zone -f KSK $zone)
+ $DSFROMKEY -T 1200 $k4 >> ../ns1/root.db
+
+ # Convert k1 and k2 in to External Keys.
+ rm -f $k1.private
+ mv $k1.key a-file
+ $IMPORTKEY -P now -D now+3600 -f a-file $zone > /dev/null 2>&1 ||
+ ( echo_i "importkey failed: $alg" )
+ rm -f $k2.private
+ mv $k2.key a-file
+ $IMPORTKEY -f a-file $zone > /dev/null 2>&1 ||
+ ( echo_i "importkey failed: $alg" )
+done
diff --git a/bin/tests/system/inline/ns4/named.conf.in b/bin/tests/system/inline/ns4/named.conf.in
new file mode 100644
index 0000000..c0745f4
--- /dev/null
+++ b/bin/tests/system/inline/ns4/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 no;
+ notify yes;
+ notify-delay 0;
+ dnssec-validation no;
+};
+
+zone "noixfr" {
+ type primary;
+ file "noixfr.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/inline/ns4/noixfr.db.in b/bin/tests/system/inline/ns4/noixfr.db.in
new file mode 100644
index 0000000..c40f011
--- /dev/null
+++ b/bin/tests/system/inline/ns4/noixfr.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns4 . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns4 A 10.53.0.4
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/inline/ns5/named.conf.post b/bin/tests/system/inline/ns5/named.conf.post
new file mode 100644
index 0000000..f454b35
--- /dev/null
+++ b/bin/tests/system/inline/ns5/named.conf.post
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 no;
+ notify yes;
+ notify-delay 0;
+ servfail-ttl 0;
+};
+
+zone "bits" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "bits.bk";
+ auto-dnssec maintain;
+ inline-signing yes;
+};
diff --git a/bin/tests/system/inline/ns5/named.conf.pre b/bin/tests/system/inline/ns5/named.conf.pre
new file mode 100644
index 0000000..91844ac
--- /dev/null
+++ b/bin/tests/system/inline/ns5/named.conf.pre
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 no;
+ notify yes;
+ notify-delay 0;
+};
+
+zone "bits" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "bits.bk";
+};
diff --git a/bin/tests/system/inline/ns6/named.conf.in b/bin/tests/system/inline/ns6/named.conf.in
new file mode 100644
index 0000000..8237f31
--- /dev/null
+++ b/bin/tests/system/inline/ns6/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS6
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ 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.6; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ notify-delay 0;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/inline/ns7/named.conf.in b/bin/tests/system/inline/ns7/named.conf.in
new file mode 100644
index 0000000..3a0cf86
--- /dev/null
+++ b/bin/tests/system/inline/ns7/named.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * NS7
+ *
+ * NOTE: This named instance is used to reproduce a scenario which involves a
+ * number of functions getting called in a very specific order which results in
+ * an infinite loop while iterating over NSEC3 red-black tree. Ensuring this
+ * happens requires carefully setting the number of signing keys, NSEC3
+ * parameters (number of iterations and salt value), zone data and named
+ * configuration. Changing any of these and/or influencing this instance's
+ * behavior (e.g. by sending extra queries to it) might render this test moot
+ * as it will no longer be able to reproduce the exact scenario it attempts to.
+ *
+ * Given the above, please do not use this instance for any other test than the
+ * one it was meant for.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ 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.7; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ try-tcp-refresh no;
+ allow-new-zones yes;
+ sig-signing-nodes 100;
+ sig-signing-signatures 10;
+};
diff --git a/bin/tests/system/inline/ns7/sign.sh b/bin/tests/system/inline/ns7/sign.sh
new file mode 100755
index 0000000..8ab8288
--- /dev/null
+++ b/bin/tests/system/inline/ns7/sign.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+# NOTE: The number of signing keys generated below is not coincidental. More
+# details can be found in the comment inside ns7/named.conf.
+
+zone=nsec3-loop
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
diff --git a/bin/tests/system/inline/ns8/example.com.db.in b/bin/tests/system/inline/ns8/example.com.db.in
new file mode 100644
index 0000000..dfc7630
--- /dev/null
+++ b/bin/tests/system/inline/ns8/example.com.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns8 . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns8
+ns8 A 10.53.0.8
diff --git a/bin/tests/system/inline/ns8/example.db.in b/bin/tests/system/inline/ns8/example.db.in
new file mode 100644
index 0000000..3ebf398
--- /dev/null
+++ b/bin/tests/system/inline/ns8/example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns8
+ns8 A 10.53.0.8
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
diff --git a/bin/tests/system/inline/ns8/example2.db.in b/bin/tests/system/inline/ns8/example2.db.in
new file mode 100644
index 0000000..1f42c3a
--- /dev/null
+++ b/bin/tests/system/inline/ns8/example2.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns8
+ns8 A 10.53.0.8
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
diff --git a/bin/tests/system/inline/ns8/example3.db.in b/bin/tests/system/inline/ns8/example3.db.in
new file mode 100644
index 0000000..a9e3daa
--- /dev/null
+++ b/bin/tests/system/inline/ns8/example3.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 400
+@ IN SOA mname1. . (
+ 3 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns8
+ns8 A 10.53.0.8
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
diff --git a/bin/tests/system/inline/ns8/named.conf.in b/bin/tests/system/inline/ns8/named.conf.in
new file mode 100644
index 0000000..47bb991
--- /dev/null
+++ b/bin/tests/system/inline/ns8/named.conf.in
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS8
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.8;
+ notify-source 10.53.0.8;
+ transfer-source 10.53.0.8;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.8; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ try-tcp-refresh no;
+ notify-delay 0;
+ allow-new-zones yes;
+ dnssec-validation no;
+};
+
+zone "example01.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example01.com.db";
+};
+
+zone "example02.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example02.com.db";
+};
+
+zone "example03.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example03.com.db";
+};
+
+zone "example04.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example04.com.db";
+};
+
+zone "example05.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example05.com.db";
+};
+
+zone "example06.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example06.com.db";
+};
+
+zone "example07.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example07.com.db";
+};
+
+zone "example08.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example08.com.db";
+};
+
+zone "example09.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example09.com.db";
+};
+
+zone "example10.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example10.com.db";
+};
+
+zone "example11.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example11.com.db";
+};
+
+zone "example12.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example12.com.db";
+};
+
+zone "example13.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example13.com.db";
+};
+
+zone "example14.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example14.com.db";
+};
+
+zone "example15.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example15.com.db";
+};
+
+zone "example16.com" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example16.com.db";
+};
+
+zone example {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example.db";
+};
+
+zone "unsigned-serial-test" {
+ type primary;
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "unsigned-serial-test.db";
+};
diff --git a/bin/tests/system/inline/ns8/sign.sh b/bin/tests/system/inline/ns8/sign.sh
new file mode 100755
index 0000000..d9b95e4
--- /dev/null
+++ b/bin/tests/system/inline/ns8/sign.sh
@@ -0,0 +1,35 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+for zone in example01.com example02.com example03.com example04.com \
+ example05.com example06.com example07.com example08.com \
+ example09.com example10.com example11.com example12.com \
+ example13.com example14.com example15.com example16.com
+do
+ rm -f K${zone}.+*+*.key
+ rm -f K${zone}.+*+*.private
+ keyname=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone)
+ keyname=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone -f KSK $zone)
+ cp example.com.db.in ${zone}.db
+ $SIGNER -S -T 3600 -O raw -L 2000042407 -o ${zone} ${zone}.db > /dev/null 2>&1
+done
+
+for zone in example unsigned-serial-test; do
+ rm -f K${zone}.+*+*.key
+ rm -f K${zone}.+*+*.private
+ keyname=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone)
+ keyname=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone -f KSK $zone)
+ cp example.db.in ${zone}.db
+done
diff --git a/bin/tests/system/inline/setup.sh b/bin/tests/system/inline/setup.sh
new file mode 100644
index 0000000..84233c8
--- /dev/null
+++ b/bin/tests/system/inline/setup.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+cp ns1/root.db.in ns1/root.db
+
+touch ns2/trusted.conf
+cp ns2/nsec3-loop.db.in ns2/nsec3-loop.db
+cp ns2/bits.db.in ns2/bits.db
+cp ns2/bits.db.in ns2/inactiveksk.db
+cp ns2/bits.db.in ns2/inactivezsk.db
+cp ns2/bits.db.in ns2/nokeys.db
+cp ns2/bits.db.in ns2/removedkeys-secondary.db
+cp ns2/bits.db.in ns2/retransfer.db
+cp ns2/bits.db.in ns2/retransfer3.db
+
+cp ns3/primary.db.in ns3/primary.db
+cp ns3/primary.db.in ns3/dynamic.db
+cp ns3/primary.db.in ns3/updated.db
+cp ns3/primary.db.in ns3/unsupported.db
+cp ns3/primary.db.in ns3/expired.db
+cp ns3/primary.db.in ns3/nsec3.db
+cp ns3/primary.db.in ns3/externalkey.db
+cp ns3/primary.db.in ns3/delayedkeys.db
+cp ns3/primary.db.in ns3/removedkeys-primary.db
+cp ns3/include.db.in ns3/include.db
+
+mkdir ns3/removedkeys
+
+touch ns4/trusted.conf
+cp ns4/noixfr.db.in ns4/noixfr.db
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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.pre ns5/named.conf
+copy_setports ns6/named.conf.in ns6/named.conf
+copy_setports ns7/named.conf.in ns7/named.conf
+copy_setports ns8/named.conf.in ns8/named.conf
+
+(cd ns3; $SHELL -e sign.sh)
+(cd ns1; $SHELL -e sign.sh)
+(cd ns7; $SHELL -e sign.sh)
+(cd ns8; $SHELL -e sign.sh)
diff --git a/bin/tests/system/inline/tests.sh b/bin/tests/system/inline/tests.sh
new file mode 100755
index 0000000..e9c4554
--- /dev/null
+++ b/bin/tests/system/inline/tests.sh
@@ -0,0 +1,1501 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +dnssec -p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+dig_with_opts() {
+ $DIG $DIGOPTS "$@"
+}
+
+rndccmd() {
+ $RNDCCMD "$@"
+}
+
+wait_for_serial() (
+ $DIG $DIGOPTS "@$1" "$2" SOA > "$4"
+ serial=$(awk '$4 == "SOA" { print $7 }' "$4")
+ [ "$3" -eq "${serial:--1}" ]
+)
+
+status=0
+n=0
+ret=0
+
+$RNDCCMD 10.53.0.3 signing -nsec3param 1 0 0 - nsec3 > /dev/null 2>&1 || ret=1
+
+for i in 1 2 3 4 5 6 7 8 9 0
+do
+ nsec3param=$($DIG $DIGOPTS +nodnssec +short @10.53.0.3 nsec3param nsec3.) || ret=1
+ test "$nsec3param" = "1 0 0 -" && break
+ sleep 1
+done
+
+if [ $ret != 0 ]; then echo_i "pre-condition failed, test aborted"; exit 1; fi
+
+n=$((n + 1))
+echo_i "checking that an unsupported algorithm is not used for signing ($n)"
+ret=0
+grep -q "algorithm is unsupported" ns3/named.run || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that rrsigs are replaced with ksk only ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 axfr nsec3. |
+ awk '/RRSIG NSEC3/ {a[$1]++} END { for (i in a) {if (a[i] != 1) exit (1)}}' || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that the zone is signed on initial transfer ($n)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $RNDCCMD 10.53.0.3 signing -list bits > signing.out.test$n 2>&1 || ret=1
+ keys=$(grep '^Done signing' signing.out.test$n | wc -l)
+ [ $keys = 2 ] || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking expired signatures are updated on load ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 +noall +answer +dnssec expired SOA > dig.out.ns3.test$n || ret=1
+expiry=$(awk '$4 == "RRSIG" { print $9 }' dig.out.ns3.test$n)
+[ "$expiry" = "20110101000000" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking removal of private type record via 'rndc signing -clear' ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 signing -list bits > signing.out.test$n 2>&1 || ret=1
+keys=$(sed -n -e 's/Done signing with key \(.*\)$/\1/p' signing.out.test$n)
+for key in $keys; do
+ $RNDCCMD 10.53.0.3 signing -clear ${key} bits > /dev/null || ret=1
+ break; # We only want to remove 1 record for now.
+done 2>&1 |sed 's/^/ns3 /' | cat_i
+
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ans=0
+ $RNDCCMD 10.53.0.3 signing -list bits > signing.out.test$n 2>&1 || ret=1
+ num=$(grep "Done signing with" signing.out.test$n | wc -l)
+ [ $num = 1 ] && break
+ sleep 1
+done
+[ $ans = 0 ] || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking private type was properly signed ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.6 bits TYPE65534 > dig.out.ns6.test$n || ret=1
+grep "ANSWER: 2," dig.out.ns6.test$n > /dev/null || ret=1
+grep "flags:.* ad[ ;]" dig.out.ns6.test$n > /dev/null || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking removal of remaining private type record via 'rndc signing -clear all' ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 signing -clear all bits > /dev/null || ret=1
+
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ans=0
+ $RNDCCMD 10.53.0.3 signing -list bits > signing.out.test$n 2>&1 || ret=1
+ grep "No signing records found" signing.out.test$n > /dev/null || ans=1
+ [ $ans = 1 ] || break
+ sleep 1
+done
+[ $ans = 0 ] || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking negative private type response was properly signed ($n)"
+ret=0
+sleep 1
+$DIG $DIGOPTS @10.53.0.6 bits TYPE65534 > dig.out.ns6.test$n || ret=1
+grep "status: NOERROR" dig.out.ns6.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns6.test$n > /dev/null || ret=1
+grep "flags:.* ad[ ;]" dig.out.ns6.test$n > /dev/null || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that the record is added on the hidden primary ($n)"
+ret=0
+
+$NSUPDATE << EOF || ret=1
+zone bits
+server 10.53.0.2 ${PORT}
+update add added.bits 0 A 1.2.3.4
+send
+EOF
+
+$DIG $DIGOPTS @10.53.0.2 added.bits A > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that update has been transferred and has been signed ($n)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 added.bits A > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking YYYYMMDDVV (2011072400) serial on hidden primary ($n)"
+ret=0
+
+$NSUPDATE << EOF || ret=1
+zone bits
+server 10.53.0.2 ${PORT}
+update add bits 0 SOA ns2.bits. . 2011072400 20 20 1814400 3600
+send
+EOF
+
+$DIG $DIGOPTS @10.53.0.2 bits SOA > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2011072400" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking YYYYMMDDVV (2011072400) serial in signed zone ($n)"
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 bits SOA > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+ grep "2011072400" dig.out.ns3.test$n > /dev/null || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that the zone is signed on initial transfer, noixfr ($n)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $RNDCCMD 10.53.0.3 signing -list noixfr > signing.out.test$n 2>&1 || ret=1
+ keys=$(grep '^Done signing' signing.out.test$n | wc -l)
+ [ $keys = 2 ] || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that the record is added on the hidden primary, noixfr ($n)"
+ret=0
+
+$NSUPDATE << EOF || ret=1
+zone noixfr
+server 10.53.0.4 ${PORT}
+update add added.noixfr 0 A 1.2.3.4
+send
+EOF
+
+$DIG $DIGOPTS @10.53.0.4 added.noixfr A > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that update has been transferred and has been signed, noixfr ($n)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 added.noixfr A > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking YYYYMMDDVV (2011072400) serial on hidden primary, noixfr ($n)"
+ret=0
+
+$NSUPDATE << EOF || ret=1
+zone noixfr
+server 10.53.0.4 ${PORT}
+update add noixfr 0 SOA ns4.noixfr. . 2011072400 20 20 1814400 3600
+send
+EOF
+
+$DIG $DIGOPTS @10.53.0.4 noixfr SOA > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
+grep "2011072400" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking YYYYMMDDVV (2011072400) serial in signed zone, noixfr ($n)"
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 noixfr SOA > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+ grep "2011072400" dig.out.ns3.test$n > /dev/null || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that the primary zone signed on initial load ($n)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $RNDCCMD 10.53.0.3 signing -list primary > signing.out.test$n 2>&1 || ret=1
+ keys=$(grep '^Done signing' signing.out.test$n | wc -l)
+ [ $keys = 2 ] || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking removal of private type record via 'rndc signing -clear' (primary) ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 signing -list primary > signing.out.test$n 2>&1 || ret=1
+keys=$(sed -n -e 's/Done signing with key \(.*\)$/\1/p' signing.out.test$n)
+for key in $keys; do
+ $RNDCCMD 10.53.0.3 signing -clear ${key} primary > /dev/null || ret=1
+ break; # We only want to remove 1 record for now.
+done 2>&1 |sed 's/^/ns3 /' | cat_i
+
+for i in 1 2 3 4 5 6 7 8 9
+do
+ ans=0
+ $RNDCCMD 10.53.0.3 signing -list primary > signing.out.test$n 2>&1 || ret=1
+ num=$(grep "Done signing with" signing.out.test$n | wc -l)
+ [ $num = 1 ] && break
+ sleep 1
+done
+[ $ans = 0 ] || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking private type was properly signed (primary) ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.6 primary TYPE65534 > dig.out.ns6.test$n || ret=1
+grep "ANSWER: 2," dig.out.ns6.test$n > /dev/null || ret=1
+grep "flags:.* ad[ ;]" dig.out.ns6.test$n > /dev/null || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking removal of remaining private type record via 'rndc signing -clear' (primary) ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 signing -clear all primary > /dev/null || ret=1
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ans=0
+ $RNDCCMD 10.53.0.3 signing -list primary > signing.out.test$n 2>&1 || ret=1
+ grep "No signing records found" signing.out.test$n > /dev/null || ans=1
+ [ $ans = 1 ] || break
+ sleep 1
+done
+[ $ans = 0 ] || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check adding of record to unsigned primary ($n)"
+ret=0
+cp ns3/primary2.db.in ns3/primary.db
+rndc_reload ns3 10.53.0.3 primary
+for i in 1 2 3 4 5 6 7 8 9
+do
+ ans=0
+ $DIG $DIGOPTS @10.53.0.3 e.primary A > dig.out.ns3.test$n || ret=1
+ grep "10.0.0.5" dig.out.ns3.test$n > /dev/null || ans=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ans=1
+ [ $ans = 1 ] || break
+ sleep 1
+done
+[ $ans = 0 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check adding record fails when SOA serial not changed ($n)"
+ret=0
+echo "c A 10.0.0.3" >> ns3/primary.db
+rndc_reload ns3 10.53.0.3
+sleep 1
+$DIG $DIGOPTS @10.53.0.3 c.primary A > dig.out.ns3.test$n || ret=1
+grep "NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check adding record works after updating SOA serial ($n)"
+ret=0
+cp ns3/primary3.db.in ns3/primary.db
+$RNDCCMD 10.53.0.3 reload primary 2>&1 | sed 's/^/ns3 /' | cat_i
+for i in 1 2 3 4 5 6 7 8 9
+do
+ ans=0
+ $DIG $DIGOPTS @10.53.0.3 c.primary A > dig.out.ns3.test$n || ret=1
+ grep "10.0.0.3" dig.out.ns3.test$n > /dev/null || ans=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ans=1
+ [ $ans = 1 ] || break
+ sleep 1
+done
+[ $ans = 0 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check the added record was properly signed ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 e.primary A > dig.out.ns6.test$n || ret=1
+grep "10.0.0.5" dig.out.ns6.test$n > /dev/null || ans=1
+grep "ANSWER: 2," dig.out.ns6.test$n > /dev/null || ans=1
+grep "flags:.* ad[ ;]" dig.out.ns6.test$n > /dev/null || ans=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that the dynamic primary zone signed on initial load ($n)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $RNDCCMD 10.53.0.3 signing -list dynamic > signing.out.test$n 2>&1 || ret=1
+ keys=$(grep '^Done signing' signing.out.test$n | wc -l)
+ [ $keys = 2 ] || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking primary zone that was updated while offline is correct ($n)"
+ret=0
+$DIG $DIGOPTS +nodnssec +short @10.53.0.3 updated SOA >dig.out.ns2.soa.test$n || ret=1
+serial=$(awk '{print $3}' dig.out.ns2.soa.test$n)
+# serial should have changed
+[ "$serial" = "2000042407" ] && ret=1
+# e.updated should exist and should be signed
+$DIG $DIGOPTS @10.53.0.3 e.updated A > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+# updated.db.signed.jnl should exist, should have the source serial
+# of primary2.db, and should show a minimal diff: no more than 8 added
+# records (SOA/RRSIG, 2 x NSEC/RRSIG, A/RRSIG), and 4 removed records
+# (SOA/RRSIG, NSEC/RRSIG).
+$JOURNALPRINT ns3/updated.db.signed.jnl >journalprint.out.test$n || ret=1
+serial=$(awk '/Source serial =/ {print $4}' journalprint.out.test$n)
+[ "$serial" = "2000042408" ] || ret=1
+diffsize=$(wc -l < journalprint.out.test$n)
+[ "$diffsize" -le 13 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking adding of record to unsigned primary using UPDATE ($n)"
+ret=0
+
+[ -f ns3/dynamic.db.jnl ] && { ret=1 ; echo_i "journal exists (pretest)" ; }
+
+$NSUPDATE << EOF || ret=1
+zone dynamic
+server 10.53.0.3 ${PORT}
+update add e.dynamic 0 A 1.2.3.4
+send
+EOF
+
+[ -f ns3/dynamic.db.jnl ] || { ret=1 ; echo_i "journal does not exist (posttest)" ; }
+
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ans=0
+ $DIG $DIGOPTS @10.53.0.3 e.dynamic > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ans=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ans=1
+ grep "1.2.3.4" dig.out.ns3.test$n > /dev/null || ans=1
+ [ $ans = 0 ] && break
+ sleep 1
+done
+[ $ans = 0 ] || { ret=1; echo_i "signed record not found"; cat dig.out.ns3.test$n ; }
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "stop bump in the wire signer server ($n)"
+ret=0
+stop_server ns3 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "restart bump in the wire signer server ($n)"
+ret=0
+start_server --noclean --restart --port ${PORT} ns3 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking YYYYMMDDVV (2011072450) serial on hidden primary ($n)"
+ret=0
+
+$NSUPDATE << EOF || ret=1
+zone bits
+server 10.53.0.2 ${PORT}
+update add bits 0 SOA ns2.bits. . 2011072450 20 20 1814400 3600
+send
+EOF
+
+$DIG $DIGOPTS @10.53.0.2 bits SOA > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2011072450" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking YYYYMMDDVV (2011072450) serial in signed zone ($n)"
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 bits SOA > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+ grep "2011072450" dig.out.ns3.test$n > /dev/null || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking YYYYMMDDVV (2011072450) serial on hidden primary, noixfr ($n)"
+ret=0
+
+$NSUPDATE << EOF || ret=1
+zone noixfr
+server 10.53.0.4 ${PORT}
+update add noixfr 0 SOA ns4.noixfr. . 2011072450 20 20 1814400 3600
+send
+EOF
+
+$DIG $DIGOPTS @10.53.0.4 noixfr SOA > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
+grep "2011072450" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking YYYYMMDDVV (2011072450) serial in signed zone, noixfr ($n)"
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 noixfr SOA > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+ grep "2011072450" dig.out.ns3.test$n > /dev/null || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking forwarded update on hidden primary ($n)"
+ret=0
+
+$NSUPDATE << EOF || ret=1
+zone bits
+server 10.53.0.3 ${PORT}
+update add bits 0 SOA ns2.bits. . 2011072460 20 20 1814400 3600
+send
+EOF
+
+$DIG $DIGOPTS @10.53.0.2 bits SOA > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+grep "2011072460" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking forwarded update on signed zone ($n)"
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 bits SOA > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+ grep "2011072460" dig.out.ns3.test$n > /dev/null || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking forwarded update on hidden primary, noixfr ($n)"
+ret=0
+
+$NSUPDATE << EOF || ret=1
+zone noixfr
+server 10.53.0.3 ${PORT}
+update add noixfr 0 SOA ns4.noixfr. . 2011072460 20 20 1814400 3600
+send
+EOF
+
+$DIG $DIGOPTS @10.53.0.4 noixfr SOA > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
+grep "2011072460" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking forwarded update on signed zone, noixfr ($n)"
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 noixfr SOA > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+ grep "2011072460" dig.out.ns3.test$n > /dev/null || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+ret=0
+n=$((n + 1))
+echo_i "checking turning on of inline signing in a secondary zone via reload ($n)"
+$DIG $DIGOPTS @10.53.0.5 +dnssec bits SOA > dig.out.ns5.test$n || ret=1
+grep "status: NOERROR" dig.out.ns5.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns5.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "setup broken"; fi
+status=$((status + ret))
+copy_setports ns5/named.conf.post ns5/named.conf
+(cd ns5; $KEYGEN -q -a ${DEFAULT_ALGORITHM} bits) > /dev/null 2>&1
+(cd ns5; $KEYGEN -q -a ${DEFAULT_ALGORITHM} -f KSK bits) > /dev/null 2>&1
+rndc_reload ns5 10.53.0.5
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.5 bits SOA > dig.out.ns5.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns5.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns5.test$n > /dev/null || ret=1
+ if [ $ret = 0 ]; then break; fi
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking rndc freeze/thaw of dynamic inline zone no change ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 freeze dynamic > freeze.test$n 2>&1 || { echo_i "/' < freeze.test$n"; ret=1; }
+sleep 1
+$RNDCCMD 10.53.0.3 thaw dynamic > thaw.test$n 2>&1 || { echo_i "rndc thaw dynamic failed" ; ret=1; }
+sleep 1
+grep "zone dynamic/IN (unsigned): ixfr-from-differences: unchanged" ns3/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+
+n=$((n + 1))
+echo_i "checking rndc freeze/thaw of dynamic inline zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 freeze dynamic > freeze.test$n 2>&1 || ret=1
+sleep 1
+awk '$2 == ";" && $3 ~ /serial/ { printf("%d %s %s\n", $1 + 1, $2, $3); next; }
+ { print; }
+ END { print "freeze1.dynamic. 0 TXT freeze1"; } ' ns3/dynamic.db > ns3/dynamic.db.new
+mv ns3/dynamic.db.new ns3/dynamic.db
+$RNDCCMD 10.53.0.3 thaw dynamic > thaw.test$n 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check added record freeze1.dynamic ($n)"
+for i in 1 2 3 4 5 6 7 8 9
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 freeze1.dynamic TXT > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+ test $ret = 0 && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# allow 1 second so that file time stamps change
+sleep 1
+
+n=$((n + 1))
+echo_i "checking rndc freeze/thaw of server ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 freeze > freeze.test$n 2>&1 || ret=1
+sleep 1
+awk '$2 == ";" && $3 ~ /serial/ { printf("%d %s %s\n", $1 + 1, $2, $3); next; }
+ { print; }
+ END { print "freeze2.dynamic. 0 TXT freeze2"; } ' ns3/dynamic.db > ns3/dynamic.db.new
+mv ns3/dynamic.db.new ns3/dynamic.db
+$RNDCCMD 10.53.0.3 thaw > thaw.test$n 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check added record freeze2.dynamic ($n)"
+for i in 1 2 3 4 5 6 7 8 9
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 freeze2.dynamic TXT > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+ test $ret = 0 && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check rndc reload allows reuse of inline-signing zones ($n)"
+ret=0
+{ $RNDCCMD 10.53.0.3 reload 2>&1 || ret=1 ; } | sed 's/^/ns3 /' | cat_i
+grep "not reusable" ns3/named.run > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check rndc sync removes both signed and unsigned journals ($n)"
+ret=0
+[ -f ns3/dynamic.db.jnl ] || ret=1
+[ -f ns3/dynamic.db.signed.jnl ] || ret=1
+$RNDCCMD 10.53.0.3 sync -clean dynamic 2>&1 || ret=1
+[ -f ns3/dynamic.db.jnl ] && ret=1
+[ -f ns3/dynamic.db.signed.jnl ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that the retransfer record is added on the hidden primary ($n)"
+ret=0
+
+$NSUPDATE << EOF || ret=1
+zone retransfer
+server 10.53.0.2 ${PORT}
+update add added.retransfer 0 A 1.2.3.4
+send
+
+EOF
+
+$DIG $DIGOPTS @10.53.0.2 added.retransfer A > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that the change has not been transferred due to notify ($n)"
+ret=0
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ ans=0
+ $DIG $DIGOPTS @10.53.0.3 added.retransfer A > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ans=1
+ [ $ans = 0 ] && break
+ sleep 1
+done
+if [ $ans != 1 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check rndc retransfer of a inline secondary zone works ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 retransfer retransfer 2>&1 || ret=1
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ ans=0
+ $DIG $DIGOPTS @10.53.0.3 added.retransfer A > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ans=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ans=1
+ [ $ans = 0 ] && break
+ sleep 1
+done
+[ $ans = 1 ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check 'rndc signing -nsec3param' requests are queued for zones which are not loaded ($n)"
+ret=0
+# The "retransfer3" zone is configured with "allow-transfer { none; };" on ns2,
+# which means it should not yet be available on ns3.
+$DIG $DIGOPTS @10.53.0.3 retransfer3 SOA > dig.out.ns3.pre.test$n || ret=1
+grep "status: SERVFAIL" dig.out.ns3.pre.test$n > /dev/null || ret=1
+# Switch the zone to NSEC3. An "NSEC3 -> NSEC -> NSEC3" sequence is used purely
+# to test that multiple queued "rndc signing -nsec3param" requests are handled
+# properly.
+$RNDCCMD 10.53.0.3 signing -nsec3param 1 0 0 - retransfer3 > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.3 signing -nsec3param none retransfer3 > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.3 signing -nsec3param 1 0 0 - retransfer3 > /dev/null 2>&1 || ret=1
+# Reconfigure ns2 to allow outgoing transfers for the "retransfer3" zone.
+sed "s|\(allow-transfer { none; };.*\)|// \1|;" ns2/named.conf > ns2/named.conf.new
+mv ns2/named.conf.new ns2/named.conf
+$RNDCCMD 10.53.0.2 reconfig || ret=1
+# Request ns3 to retransfer the "retransfer3" zone.
+$RNDCCMD 10.53.0.3 retransfer retransfer3 || ret=1
+# Check whether "retransfer3" uses NSEC3 as requested.
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.3 nonexist.retransfer3 A > dig.out.ns3.post.test$n.$i || ret=1
+ grep "status: NXDOMAIN" dig.out.ns3.post.test$n.$i > /dev/null || ret=1
+ grep "NSEC3" dig.out.ns3.post.test$n.$i > /dev/null || ret=1
+ test $ret -eq 0 && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check rndc retransfer of a inline nsec3 secondary retains nsec3 ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 signing -nsec3param 1 0 0 - retransfer3 > /dev/null 2>&1 || ret=1
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ ans=0
+ $DIG $DIGOPTS @10.53.0.3 nonexist.retransfer3 A > dig.out.ns3.pre.test$n || ret=1
+ grep "status: NXDOMAIN" dig.out.ns3.pre.test$n > /dev/null || ans=1
+ grep "NSEC3" dig.out.ns3.pre.test$n > /dev/null || ans=1
+ [ $ans = 0 ] && break
+ sleep 1
+done
+$RNDCCMD 10.53.0.3 retransfer retransfer3 2>&1 || ret=1
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ ans=0
+ $DIG $DIGOPTS @10.53.0.3 nonexist.retransfer3 A > dig.out.ns3.post.test$n || ret=1
+ grep "status: NXDOMAIN" dig.out.ns3.post.test$n > /dev/null || ans=1
+ grep "NSEC3" dig.out.ns3.post.test$n > /dev/null || ans=1
+ [ $ans = 0 ] && break
+ sleep 1
+done
+[ $ans = 1 ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# NOTE: The test below should be considered fragile. More details can be found
+# in the comment inside ns7/named.conf.
+n=$((n + 1))
+echo_i "check rndc retransfer of a inline nsec3 secondary does not trigger an infinite loop ($n)"
+ret=0
+zone=nsec3-loop
+# Add secondary zone using rndc
+$RNDCCMD 10.53.0.7 addzone $zone \
+ '{ type secondary; primaries { 10.53.0.2; }; file "'$zone'.db"; inline-signing yes; auto-dnssec maintain; };' || ret=1
+# Wait until secondary zone is fully signed using NSEC
+for i in 1 2 3 4 5 6 7 8 9 0
+do
+ ret=1
+ $RNDCCMD 10.53.0.7 signing -list $zone > signing.out.test$n 2>&1 || ret=1
+ keys=$(grep '^Done signing' signing.out.test$n | wc -l)
+ [ $keys -eq 3 ] && ret=0 && break
+ sleep 1
+done
+# Switch secondary zone to NSEC3
+$RNDCCMD 10.53.0.7 signing -nsec3param 1 0 2 12345678 $zone > /dev/null 2>&1 || ret=1
+# Wait until secondary zone is fully signed using NSEC3
+for i in 1 2 3 4 5 6 7 8 9 0
+do
+ ret=1
+ nsec3param=$($DIG $DIGOPTS +nodnssec +short @10.53.0.7 nsec3param $zone) || ret=1
+ test "$nsec3param" = "1 0 2 12345678" && ret=0 && break
+ sleep 1
+done
+# Attempt to retransfer the secondary zone from primary
+$RNDCCMD 10.53.0.7 retransfer $zone || ret=1
+# Check whether the signer managed to fully sign the retransferred zone by
+# waiting for a specific SOA serial number to appear in the logs; if this
+# specific SOA serial number does not appear in the logs, it means the signer
+# has either ran into an infinite loop or crashed; note that we check the logs
+# instead of sending SOA queries to the signer as these may influence its
+# behavior in a way which may prevent the desired scenario from being
+# reproduced (see comment in ns7/named.conf)
+for i in 1 2 3 4 5 6 7 8 9 0
+do
+ ret=1
+ { grep "ns2.$zone. . 10 20 20 1814400 3600" ns7/named.run > /dev/null 2>&1; rc=$?; } || true
+ [ $rc -eq 0 ] && ret=0 && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "stop bump in the wire signer server ($n)"
+ret=0
+stop_server ns3 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "update SOA record while stopped"
+cp ns3/primary4.db.in ns3/primary.db
+rm -f ns3/primary.db.jnl
+
+n=$((n + 1))
+echo_i "restart bump in the wire signer server ($n)"
+ret=0
+start_server --noclean --restart --port ${PORT} ns3 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "updates to SOA parameters other than serial while stopped are reflected in signed zone ($n)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9
+do
+ ans=0
+ $DIG $DIGOPTS @10.53.0.3 primary SOA > dig.out.ns3.test$n || ret=1
+ grep "hostmaster" dig.out.ns3.test$n > /dev/null || ans=1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ans=1
+ [ $ans = 1 ] || break
+ sleep 1
+done
+[ $ans = 0 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that reloading all zones does not cause zone maintenance to cease for inline-signed zones ($n)"
+ret=1
+# Ensure "rndc reload" attempts to load ns3/primary.db by waiting 1 second so
+# that the file modification time has no possibility of being equal to
+# the one stored during server startup.
+sleep 1
+nextpart ns3/named.run > /dev/null
+cp ns3/primary5.db.in ns3/primary.db
+rndc_reload ns3 10.53.0.3
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ if nextpart ns3/named.run | grep "zone primary.*sending notifies" > /dev/null; then
+ ret=0
+ break
+ fi
+ sleep 1
+done
+# Sanity check: file updates should be reflected in the signed zone,
+# i.e. SOA RNAME should no longer be set to "hostmaster".
+$DIG $DIGOPTS @10.53.0.3 primary SOA > dig.out.ns3.test$n || ret=1
+grep "hostmaster" dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that reloading errors prevent synchronization ($n)"
+ret=1
+$DIG $DIGOPTS +short @10.53.0.3 primary SOA > dig.out.ns3.test$n.1 || ret=1
+sleep 1
+nextpart ns3/named.run > /dev/null
+cp ns3/primary6.db.in ns3/primary.db
+rndc_reload ns3 10.53.0.3
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ if nextpart ns3/named.run | grep "not loaded due to errors" > /dev/null
+ then
+ ret=0
+ break
+ fi
+ sleep 1
+done
+# Sanity check: the SOA record should be unchanged
+$DIG $DIGOPTS +short @10.53.0.3 primary SOA | grep -v '^;' > dig.out.ns3.test$n.2
+diff dig.out.ns3.test$n.1 dig.out.ns3.test$n.2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check inline-signing with an include file ($n)"
+ret=0
+$DIG $DIGOPTS +short @10.53.0.3 primary SOA > dig.out.ns3.test$n.1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+sleep 1
+nextpart ns3/named.run > /dev/null
+cp ns3/primary7.db.in ns3/primary.db
+rndc_reload ns3 10.53.0.3
+_includefile_loaded() {
+ $DIG $DIGOPTS @10.53.0.3 f.primary A > dig.out.ns3.test$n || return 1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || return 1
+ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || return 1
+ grep "10\.0\.0\.7" dig.out.ns3.test$n > /dev/null || return 1
+ return 0
+}
+retry_quiet 10 _includefile_loaded
+# Sanity check: the SOA record should be changed
+$DIG $DIGOPTS +short @10.53.0.3 primary SOA | grep -v '^;' > dig.out.ns3.test$n.2
+diff dig.out.ns3.test$n.1 dig.out.ns3.test$n.2 > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "test add/del zone combinations ($n)"
+ret=0
+for zone in 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
+do
+$RNDCCMD 10.53.0.2 addzone test-$zone \
+ '{ type primary; file "bits.db.in"; allow-transfer { any; }; };' || ret=1
+$DIG $DIGOPTS @10.53.0.2 test-$zone SOA > dig.out.ns2.$zone.test$n || ret=1
+grep "status: NOERROR," dig.out.ns2.$zone.test$n > /dev/null || { ret=1; cat dig.out.ns2.$zone.test$n; }
+$RNDCCMD 10.53.0.3 addzone test-$zone \
+ '{ type secondary; primaries { 10.53.0.2; }; file "'test-$zone.bk'"; inline-signing yes; auto-dnssec maintain; allow-transfer { any; }; };' || ret=1
+$RNDCCMD 10.53.0.3 delzone test-$zone > /dev/null 2>&1 || ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing adding external keys to a inline zone ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 dnskey externalkey > dig.out.ns3.test$n || ret=1
+for alg in ${DEFAULT_ALGORITHM_NUMBER} ${ALTERNATIVE_ALGORITHM_NUMBER}
+do
+ [ $alg = 13 -a ! -f checkecdsa ] && continue;
+
+ case $alg in
+ 7) echo_i "checking NSEC3RSASHA1";;
+ 8) echo_i "checking RSASHA256";;
+ 13) echo_i "checking ECDSAP256SHA256";;
+ *) echo_i "checking $alg";;
+ esac
+
+ dnskeys=$(grep "IN.DNSKEY.25[67] [0-9]* $alg " dig.out.ns3.test$n | wc -l)
+ rrsigs=$(grep "RRSIG.DNSKEY $alg " dig.out.ns3.test$n | wc -l)
+ test ${dnskeys:-0} -eq 3 || { echo_i "failed $alg (dnskeys ${dnskeys:-0})"; ret=1; }
+ test ${rrsigs:-0} -eq 2 || { echo_i "failed $alg (rrsigs ${rrsigs:-0})"; ret=1; }
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing imported key won't overwrite a private key ($n)"
+ret=0
+key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} import.example)
+cp ${key}.key import.key
+# import should fail
+$IMPORTKEY -f import.key import.example > /dev/null 2>&1 && ret=1
+rm -f ${key}.private
+# private key removed; import should now succeed
+$IMPORTKEY -f import.key import.example > /dev/null 2>&1 || ret=1
+# now that it's an external key, re-import should succeed
+$IMPORTKEY -f import.key import.example > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing updating inline secure serial via 'rndc signing -serial' ($n)"
+ret=0
+$DIG $DIGOPTS nsec3. SOA @10.53.0.3 > dig.out.n3.pre.test$n || ret=1
+newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] + 10) if ($field[3] eq "SOA"); }' < dig.out.n3.pre.test$n)
+$RNDCCMD 10.53.0.3 signing -serial ${newserial:-0} nsec3 > /dev/null 2>&1 || ret=1
+retry_quiet 5 wait_for_serial 10.53.0.3 nsec3. "${newserial:-0}" dig.out.ns3.post.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing updating inline secure serial via 'rndc signing -serial' with negative change ($n)"
+ret=0
+$DIG $DIGOPTS nsec3. SOA @10.53.0.3 > dig.out.n3.pre.test$n || ret=1
+oldserial=$(awk '$4 == "SOA" { print $7 }' dig.out.n3.pre.test$n)
+newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] - 10) if ($field[3] eq "SOA"); }' < dig.out.n3.pre.test$n)
+$RNDCCMD 10.53.0.3 signing -serial ${newserial:-0} nsec3 > /dev/null 2>&1 || ret=1
+sleep 1
+$DIG $DIGOPTS nsec3. SOA @10.53.0.3 > dig.out.ns3.post.test$n || ret=1
+serial=$(awk '$4 == "SOA" { print $7 }' dig.out.ns3.post.test$n)
+[ ${oldserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#
+# Freezing only operates on the raw zone.
+#
+n=$((n + 1))
+echo_i "testing updating inline secure serial via 'rndc signing -serial' when frozen ($n)"
+ret=0
+$DIG $DIGOPTS nsec3. SOA @10.53.0.3 > dig.out.n3.pre.test$n || ret=1
+oldserial=$(awk '$4 == "SOA" { print $7 }' dig.out.n3.pre.test$n)
+newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] + 10) if ($field[3] eq "SOA"); }' < dig.out.n3.pre.test$n)
+$RNDCCMD 10.53.0.3 freeze nsec3 > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.3 signing -serial ${newserial:-0} nsec3 > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.3 thaw nsec3 > /dev/null 2>&1 || ret=1
+retry_quiet 5 wait_for_serial 10.53.0.3 nsec3. "${newserial:-0}" dig.out.ns3.post1.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing updating dynamic serial via 'rndc signing -serial' ($n)"
+ret=0
+$DIG $DIGOPTS bits. SOA @10.53.0.2 > dig.out.ns2.pre.test$n || ret=1
+newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] + 10) if ($field[3] eq "SOA"); }' < dig.out.ns2.pre.test$n)
+$RNDCCMD 10.53.0.2 signing -serial ${newserial:-0} bits > /dev/null 2>&1 || ret=1
+retry_quiet 5 wait_for_serial 10.53.0.2 bits. "${newserial:-0}" dig.out.ns2.post.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing updating dynamic serial via 'rndc signing -serial' with negative change ($n)"
+ret=0
+$DIG $DIGOPTS bits. SOA @10.53.0.2 > dig.out.ns2.pre.test$n || ret=1
+oldserial=$(awk '$4 == "SOA" { print $7 }' dig.out.ns2.pre.test$n)
+newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] - 10) if ($field[3] eq "SOA"); }' < dig.out.ns2.pre.test$n)
+$RNDCCMD 10.53.0.2 signing -serial ${newserial:-0} bits > /dev/null 2>&1 || ret=1
+retry_quiet 5 wait_for_serial 10.53.0.2 bits. "${newserial:-1}" dig.out.ns2.post1.test$n && ret=1
+retry_quiet 5 wait_for_serial 10.53.0.2 bits. "${oldserial:-1}" dig.out.ns2.post2.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing updating dynamic serial via 'rndc signing -serial' when frozen ($n)"
+ret=0
+$DIG $DIGOPTS bits. SOA @10.53.0.2 > dig.out.ns2.pre.test$n || ret=1
+oldserial=$(awk '$4 == "SOA" { print $7 }' dig.out.ns2.pre.test$n)
+newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] + 10) if ($field[3] eq "SOA"); }' < dig.out.ns2.pre.test$n)
+$RNDCCMD 10.53.0.2 freeze bits > /dev/null 2>&1 || ret=1
+$RNDCCMD 10.53.0.2 signing -serial ${newserial:-0} bits > /dev/null 2>&1 && ret=1
+$RNDCCMD 10.53.0.2 thaw bits > /dev/null 2>&1 || ret=1
+retry_quiet 5 wait_for_serial 10.53.0.2 bits. "${newserial:-1}" dig.out.ns2.post1.test$n && ret=1
+retry_quiet 5 wait_for_serial 10.53.0.2 bits. "${oldserial:-1}" dig.out.ns2.post2.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing that inline signing works with inactive ZSK and active KSK ($n)"
+ret=0
+
+$DIG $DIGOPTS @10.53.0.3 soa inactivezsk > dig.out.ns3.pre.test$n || ret=1
+soa1=$(awk '$4 == "SOA" { print $7 }' dig.out.ns3.pre.test$n)
+
+$NSUPDATE << EOF || ret=1
+server 10.53.0.2 ${PORT}
+update add added.inactivezsk 0 IN TXT added record
+send
+EOF
+
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ $DIG $DIGOPTS @10.53.0.3 soa inactivezsk > dig.out.ns3.post.test$n || ret=1
+ soa2=$(awk '$4 == "SOA" { print $7 }' dig.out.ns3.post.test$n)
+ test ${soa1:-0} -ne ${soa2:-0} && break
+ sleep 1
+done
+test ${soa1:-0} -ne ${soa2:-0} || ret=1
+
+$DIG $DIGOPTS @10.53.0.3 txt added.inactivezsk > dig.out.ns3.test$n || ret=1
+grep "ANSWER: 3," dig.out.ns3.test$n > /dev/null || ret=1
+grep "RRSIG" dig.out.ns3.test$n > /dev/null || ret=1
+grep "TXT ${DEFAULT_ALGORITHM_NUMBER} 2" dig.out.ns3.test$n > /dev/null || ret=1
+grep "TXT ${ALTERNATIVE_ALGORITHM_NUMBER} 2" dig.out.ns3.test$n > /dev/null || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "testing that inline signing works with inactive KSK and active ZSK ($n)"
+ret=0
+
+$DIG $DIGOPTS @10.53.0.3 axfr inactiveksk > dig.out.ns3.test$n || ret=1
+
+#
+# check that DNSKEY is signed with ZSK for default algorithm
+#
+awk='$4 == "DNSKEY" && $5 == 256 && $7 == alg { print }'
+zskid=$(awk -v alg=${DEFAULT_ALGORITHM_NUMBER} "${awk}" dig.out.ns3.test$n |
+ $DSFROMKEY -A -2 -f - inactiveksk | awk '{ print $4}' )
+grep "DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 1 [0-9]* [0-9]* [0-9]* ${zskid} " dig.out.ns3.test$n > /dev/null || ret=1
+awk='$4 == "DNSKEY" && $5 == 257 && $7 == alg { print }'
+kskid=$(awk -v alg=${DEFAULT_ALGORITHM_NUMBER} "${awk}" dig.out.ns3.test$n |
+ $DSFROMKEY -2 -f - inactiveksk | awk '{ print $4}' )
+grep "DNSKEY ${DEFAULT_ALGORITHM_NUMBER} 1 [0-9]* [0-9]* [0-9]* ${kskid} " dig.out.ns3.test$n > /dev/null && ret=1
+
+#
+# check that DNSKEY is signed with KSK for alternative algorithm
+#
+awk='$4 == "DNSKEY" && $5 == 256 && $7 == alg { print }'
+zskid=$(awk -v alg=${ALTERNATIVE_ALGORITHM_NUMBER} "${awk}" dig.out.ns3.test$n |
+ $DSFROMKEY -A -2 -f - inactiveksk | awk '{ print $4}' )
+grep "DNSKEY ${ALTERNATIVE_ALGORITHM_NUMBER} 1 [0-9]* [0-9]* [0-9]* ${zskid} " dig.out.ns3.test$n > /dev/null && ret=1
+awk='$4 == "DNSKEY" && $5 == 257 && $7 == alg { print }'
+kskid=$(awk -v alg=${ALTERNATIVE_ALGORITHM_NUMBER} "${awk}" dig.out.ns3.test$n |
+ $DSFROMKEY -2 -f - inactiveksk | awk '{ print $4}' )
+grep "DNSKEY ${ALTERNATIVE_ALGORITHM_NUMBER} 1 [0-9]* [0-9]* [0-9]* ${kskid} " dig.out.ns3.test$n > /dev/null || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Wait until an update to the raw part of a given inline signed zone is fully
+# processed. As waiting for a fixed amount of time is suboptimal and there is
+# no single message that would signify both a successful modification and an
+# error in a race-free manner, instead wait until either notifies are sent
+# (which means the secure zone was modified) or a receive_secure_serial() error
+# is logged (which means the zone was not modified and will not be modified any
+# further in response to the relevant raw zone update).
+wait_until_raw_zone_update_is_processed() {
+ zone="$1"
+ for i in 1 2 3 4 5 6 7 8 9 10
+ do
+ if nextpart ns3/named.run | grep -E "zone ${zone}.*(sending notifies|receive_secure_serial)" > /dev/null; then
+ return
+ fi
+ sleep 1
+ done
+}
+
+n=$((n + 1))
+echo_i "checking that changes to raw zone are applied to a previously unsigned secure zone ($n)"
+ret=0
+# Query for bar.nokeys/A and ensure the response is negative. As this zone
+# does not have any signing keys set up, the response must be unsigned.
+$DIG $DIGOPTS @10.53.0.3 bar.nokeys. A > dig.out.ns3.pre.test$n 2>&1 || ret=1
+grep "status: NOERROR" dig.out.ns3.pre.test$n > /dev/null && ret=1
+grep "RRSIG" dig.out.ns3.pre.test$n > /dev/null && ret=1
+# Ensure the wait_until_raw_zone_update_is_processed() call below will ignore
+# log messages generated before the raw zone is updated.
+nextpart ns3/named.run > /dev/null
+# Add a record to the raw zone on the primary.
+$NSUPDATE << EOF || ret=1
+zone nokeys.
+server 10.53.0.2 ${PORT}
+update add bar.nokeys. 0 A 127.0.0.1
+send
+EOF
+wait_until_raw_zone_update_is_processed "nokeys"
+# Query for bar.nokeys/A again and ensure the signer now returns a positive,
+# yet still unsigned response.
+$DIG $DIGOPTS @10.53.0.3 bar.nokeys. A > dig.out.ns3.post.test$n 2>&1 || ret=1
+grep "status: NOERROR" dig.out.ns3.post.test$n > /dev/null || ret=1
+grep "RRSIG" dig.out.ns3.pre.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that changes to raw zone are not applied to a previously signed secure zone with no keys available (primary) ($n)"
+ret=0
+# Query for bar.removedkeys-primary/A and ensure the response is negative. As
+# this zone has signing keys set up, the response must be signed.
+$DIG $DIGOPTS @10.53.0.3 bar.removedkeys-primary. A > dig.out.ns3.pre.test$n 2>&1 || ret=1
+grep "status: NOERROR" dig.out.ns3.pre.test$n > /dev/null && ret=1
+grep "RRSIG" dig.out.ns3.pre.test$n > /dev/null || ret=1
+# Remove the signing keys for this zone.
+mv -f ns3/Kremovedkeys-primary* ns3/removedkeys
+# Ensure the wait_until_raw_zone_update_is_processed() call below will ignore
+# log messages generated before the raw zone is updated.
+nextpart ns3/named.run > /dev/null
+# Add a record to the raw zone on the primary.
+$NSUPDATE << EOF || ret=1
+zone removedkeys-primary.
+server 10.53.0.3 ${PORT}
+update add bar.removedkeys-primary. 0 A 127.0.0.1
+send
+EOF
+wait_until_raw_zone_update_is_processed "removedkeys-primary"
+# Query for bar.removedkeys-primary/A again and ensure the signer still returns
+# a negative, signed response.
+$DIG $DIGOPTS @10.53.0.3 bar.removedkeys-primary. A > dig.out.ns3.post.test$n 2>&1 || ret=1
+grep "status: NOERROR" dig.out.ns3.post.test$n > /dev/null && ret=1
+grep "RRSIG" dig.out.ns3.pre.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that backlogged changes to raw zone are applied after keys become available (primary) ($n)"
+ret=0
+# Restore the signing keys for this zone.
+mv ns3/removedkeys/Kremovedkeys-primary* ns3
+$RNDCCMD 10.53.0.3 loadkeys removedkeys-primary > /dev/null 2>&1 || ret=1
+# Determine what a SOA record with a bumped serial number should look like.
+BUMPED_SOA=$(sed -n 's/.*\(add removedkeys-primary.*IN.*SOA\)/\1/p;' ns3/named.run | tail -1 | awk '{$8 += 1; print $0}')
+# Ensure the wait_until_raw_zone_update_is_processed() call below will ignore
+# log messages generated before the raw zone is updated.
+nextpart ns3/named.run > /dev/null
+# Bump the SOA serial number of the raw zone.
+$NSUPDATE << EOF || ret=1
+zone removedkeys-primary.
+server 10.53.0.3 ${PORT}
+update del removedkeys-primary. SOA
+update ${BUMPED_SOA}
+send
+EOF
+wait_until_raw_zone_update_is_processed "removedkeys-primary"
+# Query for bar.removedkeys-primary/A again and ensure the signer now returns a
+# positive, signed response.
+$DIG $DIGOPTS @10.53.0.3 bar.removedkeys-primary. A > dig.out.ns3.test$n 2>&1 || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "RRSIG" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that changes to raw zone are not applied to a previously signed secure zone with no keys available (secondary) ($n)"
+ret=0
+# Query for bar.removedkeys-secondary/A and ensure the response is negative. As this
+# zone does have signing keys set up, the response must be signed.
+$DIG $DIGOPTS @10.53.0.3 bar.removedkeys-secondary. A > dig.out.ns3.pre.test$n 2>&1 || ret=1
+grep "status: NOERROR" dig.out.ns3.pre.test$n > /dev/null && ret=1
+grep "RRSIG" dig.out.ns3.pre.test$n > /dev/null || ret=1
+# Remove the signing keys for this zone.
+mv -f ns3/Kremovedkeys-secondary* ns3/removedkeys
+# Ensure the wait_until_raw_zone_update_is_processed() call below will ignore
+# log messages generated before the raw zone is updated.
+nextpart ns3/named.run > /dev/null
+# Add a record to the raw zone on the primary.
+$NSUPDATE << EOF || ret=1
+zone removedkeys-secondary.
+server 10.53.0.2 ${PORT}
+update add bar.removedkeys-secondary. 0 A 127.0.0.1
+send
+EOF
+wait_until_raw_zone_update_is_processed "removedkeys-secondary"
+# Query for bar.removedkeys-secondary/A again and ensure the signer still returns a
+# negative, signed response.
+$DIG $DIGOPTS @10.53.0.3 bar.removedkeys-secondary. A > dig.out.ns3.post.test$n 2>&1 || ret=1
+grep "status: NOERROR" dig.out.ns3.post.test$n > /dev/null && ret=1
+grep "RRSIG" dig.out.ns3.pre.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that backlogged changes to raw zone are applied after keys become available (secondary) ($n)"
+ret=0
+# Restore the signing keys for this zone.
+mv ns3/removedkeys/Kremovedkeys-secondary* ns3
+$RNDCCMD 10.53.0.3 loadkeys removedkeys-secondary > /dev/null 2>&1 || ret=1
+# Determine what a SOA record with a bumped serial number should look like.
+BUMPED_SOA=$(sed -n 's/.*\(add removedkeys-secondary.*IN.*SOA\)/\1/p;' ns2/named.run | tail -1 | awk '{$8 += 1; print $0}')
+# Ensure the wait_until_raw_zone_update_is_processed() call below will ignore
+# log messages generated before the raw zone is updated.
+nextpart ns3/named.run > /dev/null
+# Bump the SOA serial number of the raw zone on the primary.
+$NSUPDATE << EOF || ret=1
+zone removedkeys-secondary.
+server 10.53.0.2 ${PORT}
+update del removedkeys-secondary. SOA
+update ${BUMPED_SOA}
+send
+EOF
+wait_until_raw_zone_update_is_processed "removedkeys-secondary"
+# Query for bar.removedkeys-secondary/A again and ensure the signer now returns
+# a positive, signed response.
+$DIG $DIGOPTS @10.53.0.3 bar.removedkeys-secondary. A > dig.out.ns3.test$n 2>&1 || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "RRSIG" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check that the file $2 for zone $1 does not contain RRSIG records
+# while the journal file for that zone does contain them.
+ensure_sigs_only_in_journal() {
+ origin="$1"
+ masterfile="$2"
+ $CHECKZONE -i none -f raw -D -o - "$origin" "$masterfile" 2>&1 | grep -w RRSIG > /dev/null && ret=1
+ $CHECKZONE -j -i none -f raw -D -o - "$origin" "$masterfile" 2>&1 | grep -w RRSIG > /dev/null || ret=1
+}
+
+n=$((n + 1))
+echo_i "checking that records added from a journal are scheduled to be resigned ($n)"
+ret=0
+# Signing keys for the "delayedkeys" zone are not yet accessible. Thus, the
+# zone file for the signed version of the zone will contain no DNSSEC records.
+# Move keys into place now and load them, which will cause DNSSEC records to
+# only be present in the journal for the signed version of the zone.
+mv Kdelayedkeys* ns3/
+$RNDCCMD 10.53.0.3 loadkeys delayedkeys > rndc.out.ns3.pre.test$n 2>&1 || ret=1
+# Wait until the zone is signed.
+check_done_signing () (
+ $RNDCCMD 10.53.0.3 signing -list delayedkeys > signing.out.test$n 2>&1 || true
+ num=$(grep "Done signing with" signing.out.test$n | wc -l)
+ [ $num -eq 2 ]
+)
+retry_quiet 10 check_done_signing || ret=1
+# Halt rather than stopping the server to prevent the file from being
+# flushed upon shutdown since we specifically want to avoid it.
+stop_server --use-rndc --halt --port ${CONTROLPORT} ns3 || ret=1
+ensure_sigs_only_in_journal delayedkeys ns3/delayedkeys.db.signed
+start_server --noclean --restart --port ${PORT} ns3 || ret=1
+# At this point, the raw zone journal will not have a source serial set. Upon
+# server startup, receive_secure_serial() will rectify that, update SOA, resign
+# it, and schedule its future resign. This will cause "rndc zonestatus" to
+# return delayedkeys/SOA as the next node to resign, so we restart the server
+# once again; with the raw zone journal now having a source serial set,
+# receive_secure_serial() should refrain from introducing any zone changes.
+stop_server --use-rndc --halt --port ${CONTROLPORT} ns3 || ret=1
+ensure_sigs_only_in_journal delayedkeys ns3/delayedkeys.db.signed
+nextpart ns3/named.run > /dev/null
+start_server --noclean --restart --port ${PORT} ns3 || ret=1
+# We can now test whether the secure zone journal was correctly processed:
+# unless the records contained in it were scheduled for resigning, no resigning
+# event will be scheduled at all since the secure zone file contains no
+# DNSSEC records.
+wait_for_log 20 "all zones loaded" ns3/named.run || ret=1
+$RNDCCMD 10.53.0.3 zonestatus delayedkeys > rndc.out.ns3.post.test$n 2>&1 || ret=1
+grep "next resign node:" rndc.out.ns3.post.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that zonestatus reports 'type: primary' for an inline primary zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 zonestatus primary > rndc.out.ns3.test$n || ret=1
+grep "type: primary" rndc.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that zonestatus reports 'type: secondary' for an inline secondary zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 zonestatus bits > rndc.out.ns3.test$n || ret=1
+grep "type: secondary" rndc.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking reload of touched inline zones ($n)"
+ret=0
+echo_ic "pre-reload 'next key event'"
+nextpart ns8/named.run > nextpart.pre$n.out
+count=$(grep "zone example[0-9][0-9].com/IN (signed): next key event:" nextpart.pre$n.out | wc -l)
+echo_ic "found: $count/16"
+[ $count -eq 16 ] || ret=1
+echo_ic "touch and reload"
+touch ns8/example??.com.db
+$RNDCCMD 10.53.0.8 reload 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 5
+echo_ic "post-reload 'next key event'"
+nextpart ns8/named.run > nextpart.post$n.out
+count=$(grep "zone example[0-9][0-9].com/IN (signed): next key event:" nextpart.post$n.out | wc -l)
+echo_ic "found: $count/16"
+[ $count -eq 16 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking second reload of touched inline zones ($n)"
+ret=0
+nextpart ns8/named.run > nextpart.pre$n.out
+$RNDCCMD 10.53.0.8 reload 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 5
+nextpart ns8/named.run > nextpart.post$n.out
+grep "ixfr-from-differences: unchanged" nextpart.post$n.out && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "Check that 'rndc reload' of just the serial updates the signed instance ($n)"
+ret=0
+dig_with_opts @10.53.0.8 example SOA > dig.out.ns8.test$n.soa1 || ret=1
+cp ns8/example2.db.in ns8/example.db || ret=1
+nextpart ns8/named.run > /dev/null
+rndccmd 10.53.0.8 reload || ret=1
+wait_for_log 3 "all zones loaded" ns8/named.run
+sleep 1
+dig_with_opts @10.53.0.8 example SOA > dig.out.ns8.test$n.soa2 || ret=1
+soa1=$(awk '$4 == "SOA" { print $7 }' dig.out.ns8.test$n.soa1)
+soa2=$(awk '$4 == "SOA" { print $7 }' dig.out.ns8.test$n.soa2)
+ttl1=$(awk '$4 == "SOA" { print $2 }' dig.out.ns8.test$n.soa1)
+ttl2=$(awk '$4 == "SOA" { print $2 }' dig.out.ns8.test$n.soa2)
+test ${soa1:-1000} -lt ${soa2:-0} || ret=1
+test ${ttl1:-0} -eq 300 || ret=1
+test ${ttl2:-0} -eq 300 || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check that restart with zone changes and deleted journal works ($n)"
+TSIG=
+ret=0
+dig_with_opts @10.53.0.8 example SOA > dig.out.ns8.test$n.soa1 || ret=1
+stop_server --use-rndc --port ${CONTROLPORT} ns8 || ret=1
+# TTL of all records change from 300 to 400
+cp ns8/example3.db.in ns8/example.db || ret=1
+rm -f ns8/example.db.jnl
+nextpart ns8/named.run > /dev/null
+start_server --noclean --restart --port ${PORT} ns8 || ret=1
+wait_for_log 3 "all zones loaded" ns8/named.run
+sleep 1
+dig_with_opts @10.53.0.8 example SOA > dig.out.ns8.test$n.soa2 || ret=1
+soa1=$(awk '$4 == "SOA" { print $7 }' dig.out.ns8.test$n.soa1)
+soa2=$(awk '$4 == "SOA" { print $7 }' dig.out.ns8.test$n.soa2)
+ttl1=$(awk '$4 == "SOA" { print $2 }' dig.out.ns8.test$n.soa1)
+ttl2=$(awk '$4 == "SOA" { print $2 }' dig.out.ns8.test$n.soa2)
+test ${soa1:-1000} -lt ${soa2:-0} || ret=1
+test ${ttl1:-0} -eq 300 || ret=1
+test ${ttl2:-0} -eq 400 || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/inline/tests_sh_inline.py b/bin/tests/system/inline/tests_sh_inline.py
new file mode 100644
index 0000000..f7520b8
--- /dev/null
+++ b/bin/tests/system/inline/tests_sh_inline.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_inline(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/inline/tests_signed_zone_files.py b/bin/tests/system/inline/tests_signed_zone_files.py
new file mode 100755
index 0000000..596b756
--- /dev/null
+++ b/bin/tests/system/inline/tests_signed_zone_files.py
@@ -0,0 +1,67 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import glob
+import struct
+
+
+class RawFormatHeader(dict):
+ """
+ A dictionary of raw-format header fields read from a zone file.
+ """
+
+ fields = [
+ "format",
+ "version",
+ "dumptime",
+ "flags",
+ "sourceserial",
+ "lastxfrin",
+ ]
+
+ def __init__(self, file_name):
+ header = struct.Struct(">IIIIII")
+ with open(file_name, "rb") as data:
+ header_data = data.read(header.size)
+ super().__init__(zip(self.fields, header.unpack_from(header_data)))
+
+
+def test_unsigned_serial_number():
+ """
+ Check whether all signed zone files in the "ns8" subdirectory contain the
+ serial number of the unsigned version of the zone in the raw-format header.
+ The test assumes that all "*.signed" files in the "ns8" subdirectory are in
+ raw format.
+
+ Notes:
+
+ - The actual zone signing and dumping happens while the tests.sh phase of
+ the "inline" system test is set up and run. This check only verifies
+ the outcome of those events; it does not initiate any signing or
+ dumping itself.
+
+ - example[0-9][0-9].com.db.signed files are initially signed by
+ dnssec-signzone while the others - by named.
+ """
+
+ zones_with_unsigned_serial_missing = []
+
+ for signed_zone in sorted(glob.glob("ns8/*.signed")):
+ raw_header = RawFormatHeader(signed_zone)
+ # Ensure the unsigned serial number is placed where it is expected.
+ assert raw_header["format"] == 2
+ assert raw_header["version"] == 1
+ # Check whether the header flags indicate that the unsigned serial
+ # number is set and that the latter is indeed set.
+ if raw_header["flags"] & 0x02 == 0 or raw_header["sourceserial"] == 0:
+ zones_with_unsigned_serial_missing.append(signed_zone)
+
+ assert not zones_with_unsigned_serial_missing
diff --git a/bin/tests/system/integrity/clean.sh b/bin/tests/system/integrity/clean.sh
new file mode 100644
index 0000000..941fccf
--- /dev/null
+++ b/bin/tests/system/integrity/clean.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.test*
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/integrity/ns1/mx-cname.db b/bin/tests/system/integrity/ns1/mx-cname.db
new file mode 100644
index 0000000..a700269
--- /dev/null
+++ b/bin/tests/system/integrity/ns1/mx-cname.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns1 hostmaster 0 0 0 0 0
+@ NS ns1
+@ MX 0 cname
+ns1 A 10.53.0.1
+cname CNAME ns1
diff --git a/bin/tests/system/integrity/ns1/named.conf.in b/bin/tests/system/integrity/ns1/named.conf.in
new file mode 100644
index 0000000..00d9dba
--- /dev/null
+++ b/bin/tests/system/integrity/ns1/named.conf.in
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "mx-cname-fail" {
+ type primary;
+ check-integrity yes;
+ check-mx-cname fail;
+ file "mx-cname.db";
+};
+
+zone "mx-cname-warn" {
+ type primary;
+ check-integrity yes;
+ check-mx-cname warn;
+ file "mx-cname.db";
+};
+
+zone "mx-cname-ignore" {
+ type primary;
+ check-integrity yes;
+ check-mx-cname ignore;
+ file "mx-cname.db";
+};
+
+zone "no-mx-cname-fail" {
+ type primary;
+ check-integrity no;
+ check-mx-cname fail;
+ file "mx-cname.db";
+};
+
+zone "no-mx-cname-warn" {
+ type primary;
+ check-integrity no;
+ check-mx-cname warn;
+ file "mx-cname.db";
+};
+
+zone "no-mx-cname-ignore" {
+ type primary;
+ check-integrity no;
+ check-mx-cname ignore;
+ file "mx-cname.db";
+};
+
+zone "srv-cname-fail" {
+ type primary;
+ check-integrity yes;
+ check-srv-cname fail;
+ file "srv-cname.db";
+};
+
+zone "srv-cname-warn" {
+ type primary;
+ check-integrity yes;
+ check-srv-cname warn;
+ file "srv-cname.db";
+};
+
+zone "srv-cname-ignore" {
+ type primary;
+ check-integrity yes;
+ check-srv-cname ignore;
+ file "srv-cname.db";
+};
+zone "no-srv-cname-fail" {
+ type primary;
+ check-integrity no;
+ check-srv-cname fail;
+ file "srv-cname.db";
+};
+
+zone "no-srv-cname-warn" {
+ type primary;
+ check-integrity no;
+ check-srv-cname warn;
+ file "srv-cname.db";
+};
+
+zone "no-srv-cname-ignore" {
+ type primary;
+ check-integrity no;
+ check-srv-cname ignore;
+ file "srv-cname.db";
+};
diff --git a/bin/tests/system/integrity/ns1/srv-cname.db b/bin/tests/system/integrity/ns1/srv-cname.db
new file mode 100644
index 0000000..d6ae603
--- /dev/null
+++ b/bin/tests/system/integrity/ns1/srv-cname.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns1 hostmaster 0 0 0 0 0
+@ NS ns1
+@ SRV 0 0 0 cname
+ns1 A 10.53.0.1
+cname CNAME ns1
diff --git a/bin/tests/system/integrity/setup.sh b/bin/tests/system/integrity/setup.sh
new file mode 100644
index 0000000..82240a7
--- /dev/null
+++ b/bin/tests/system/integrity/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/integrity/tests.sh b/bin/tests/system/integrity/tests.sh
new file mode 100644
index 0000000..65648b4
--- /dev/null
+++ b/bin/tests/system/integrity/tests.sh
@@ -0,0 +1,132 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+
+status=0
+n=1
+
+echo_i "check that 'check-integrity yes; check-mx-cname fail;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 mx mx-cname-fail > dig.out.test$n || ret=1
+grep "status: SERVFAIL," dig.out.test$n > /dev/null || ret=1
+grep "zone mx-cname-fail/IN: mx-cname-fail/MX 'cname.mx-cname-fail' is a CNAME (illegal)" ns1/named.run > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'check-integrity yes; check-mx-cname warn;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 mx mx-cname-warn > dig.out.test$n || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+grep "zone mx-cname-warn/IN: mx-cname-warn/MX 'cname.mx-cname-warn' is a CNAME (illegal)" ns1/named.run > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'check-integrity yes; check-mx-cname ignore;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 mx mx-cname-ignore > dig.out.test$n || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+grep "zone mx-cname-ignore/IN: mx-cname-ignore/MX 'cname.mx-cname-ignore' is a CNAME (illegal)" ns1/named.run > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'check-integrity no; check-mx-cname fail;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 mx no-mx-cname-fail > dig.out.test$n || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+grep "zone no-mx-cname-fail/IN: no-mx-cname-fail/MX 'cname.no-mx-cname-fail' is a CNAME (illegal)" ns1/named.run > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'check-integrity no; check-mx-cname warn;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 mx no-mx-cname-warn > dig.out.test$n || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+grep "zone no-mx-cname-warn/IN: no-mx-cname-warn/MX 'cname.no-mx-cname-warn' is a CNAME (illegal)" ns1/named.run > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'check-integrity no; check-mx-cname ignore;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 mx no-mx-cname-ignore > dig.out.test$n || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+grep "zone no-mx-cname-ignore/IN: no-mx-cname-ignore/MX 'cname.no-mx-cname-ignore' is a CNAME (illegal)" ns1/named.run > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'check-integrity yes; check-srv-cname fail;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 srv srv-cname-fail > dig.out.test$n || ret=1
+grep "status: SERVFAIL," dig.out.test$n > /dev/null || ret=1
+grep "zone srv-cname-fail/IN: srv-cname-fail/SRV 'cname.srv-cname-fail' is a CNAME (illegal)" ns1/named.run > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'check-integrity yes; check-srv-cname warn;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 srv srv-cname-warn > dig.out.test$n || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+grep "zone srv-cname-warn/IN: srv-cname-warn/SRV 'cname.srv-cname-warn' is a CNAME (illegal)" ns1/named.run > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'check-integrity yes; check-srv-cname ignore;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 srv srv-cname-ignore > dig.out.test$n || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+grep "zone srv-cname-ignore/IN: srv-cname-ignore/SRV 'cname.srv-cname-ignore' is a CNAME (illegal)" ns1/named.run > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'check-integrity no; check-srv-cname fail;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 srv no-srv-cname-fail > dig.out.test$n || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+grep "zone no-srv-cname-fail/IN: no-srv-cname-fail/SRV 'cname.no-srv-cname-fail' is a CNAME (illegal)" ns1/named.run > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'check-integrity no; check-srv-cname warn;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 srv no-srv-cname-warn > dig.out.test$n || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+grep "zone no-srv-cname-warn/IN: no-srv-cname-warn/SRV 'cname.no-srv-cname-warn' is a CNAME (illegal)" ns1/named.run > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check that 'check-integrity no; check-srv-cname ignore;' works ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 srv no-srv-cname-ignore > dig.out.test$n || ret=1
+grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
+grep "zone no-srv-cname-ignore/IN: no-srv-cname-ignore/SRV 'cname.no-srv-cname-ignore' is a CNAME (illegal)" ns1/named.run > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+test $status -eq 0 || exit 1
diff --git a/bin/tests/system/integrity/tests_sh_integrity.py b/bin/tests/system/integrity/tests_sh_integrity.py
new file mode 100644
index 0000000..7316af3
--- /dev/null
+++ b/bin/tests/system/integrity/tests_sh_integrity.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_integrity(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/ixfr/ans2/startme b/bin/tests/system/ixfr/ans2/startme
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin/tests/system/ixfr/ans2/startme
diff --git a/bin/tests/system/ixfr/clean.sh b/bin/tests/system/ixfr/clean.sh
new file mode 100644
index 0000000..eb78363
--- /dev/null
+++ b/bin/tests/system/ixfr/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f stats.*
+rm -f ns1/*.db ns1/*.jnl
+rm -f ns3/*.jnl ns3/mytest*.db ns3/subtest*.db
+rm -f ns4/*.jnl ns4/*.db
+rm -f ns5/*.jnl ns5/*.db
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run */named.run.prev
+rm -f */ans.run
+rm -f dig.out.test* dig.out1.test* dig.out2.test* dig.out3.test*
+rm -f ns3/large.db
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind* ns*/*.mkeys
diff --git a/bin/tests/system/ixfr/ixfr-stats.good b/bin/tests/system/ixfr/ixfr-stats.good
new file mode 100644
index 0000000..3d0d2dd
--- /dev/null
+++ b/bin/tests/system/ixfr/ixfr-stats.good
@@ -0,0 +1,3 @@
+messages=1
+records=5
+bytes=204
diff --git a/bin/tests/system/ixfr/ns1/named.conf.in b/bin/tests/system/ixfr/ns1/named.conf.in
new file mode 100644
index 0000000..48fc1cd
--- /dev/null
+++ b/bin/tests/system/ixfr/ns1/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/ixfr/ns3/named.conf.in b/bin/tests/system/ixfr/ns3/named.conf.in
new file mode 100644
index 0000000..40af324
--- /dev/null
+++ b/bin/tests/system/ixfr/ns3/named.conf.in
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ allow-transfer { any; };
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view "primary" {
+ ixfr-from-differences yes;
+ request-ixfr yes;
+ zone "test" IN {
+ type primary;
+ file "mytest.db";
+ max-ixfr-ratio 75%;
+ };
+ zone "sub.test" IN {
+ type primary;
+ file "subtest.db";
+ };
+ zone "large" IN {
+ type primary;
+ file "large.db";
+ };
+};
diff --git a/bin/tests/system/ixfr/ns4/named.conf.in b/bin/tests/system/ixfr/ns4/named.conf.in
new file mode 100644
index 0000000..ae6657e
--- /dev/null
+++ b/bin/tests/system/ixfr/ns4/named.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view "primary" {
+ ixfr-from-differences yes;
+ request-ixfr yes;
+ zone "test" IN {
+ type secondary;
+ file "mytest.db";
+ primaries { 10.53.0.3; };
+ max-ixfr-ratio unlimited;
+ };
+ zone "sub.test" IN {
+ type secondary;
+ file "subtest.db";
+ request-ixfr no;
+ primaries { 10.53.0.3; };
+ };
+};
diff --git a/bin/tests/system/ixfr/ns5/named.conf.in b/bin/tests/system/ixfr/ns5/named.conf.in
new file mode 100644
index 0000000..e1056fc
--- /dev/null
+++ b/bin/tests/system/ixfr/ns5/named.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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 no;
+ notify yes;
+ provide-ixfr no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view "primary" {
+ ixfr-from-differences yes;
+ request-ixfr yes;
+ zone "test" IN {
+ type secondary;
+ file "mytest.db";
+ primaries { 10.53.0.3; };
+ };
+ zone "sub.test" IN {
+ type secondary;
+ file "subtest.db";
+ request-ixfr no;
+ primaries { 10.53.0.3; };
+ };
+};
diff --git a/bin/tests/system/ixfr/setup.sh b/bin/tests/system/ixfr/setup.sh
new file mode 100644
index 0000000..65aedf6
--- /dev/null
+++ b/bin/tests/system/ixfr/setup.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$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
+
+# Set up db files for zone "test" - this is a series of four
+# versions of the zone, the second and third having small changes
+# and the fourth having a large one.
+
+testdb () {
+ cat << EOF
+\$ORIGIN $1
+\$TTL 15
+@ 15 IN SOA ns1.test. hostmaster.test. (
+ $2 ; serial
+ 3H ; refresh
+ 15 ; retry
+ 1w ; expire
+ 3h ; minimum
+ )
+ IN NS ns1.test.
+ IN NS ns2.test.
+ IN NS ns5.test.
+ns1 IN A 10.53.0.3
+ns2 IN A 10.53.0.4
+ns5 IN A 10.53.0.5
+EOF
+
+ i=0
+ while [ $i -lt $3 ]; do
+ echo "host$i IN A 192.0.2.$i"
+ i=$((i+1))
+ done
+}
+
+testdb test. 1 60 > ns3/mytest.db
+testdb test. 2 61 > ns3/mytest1.db
+testdb test. 3 62 > ns3/mytest2.db
+testdb test. 4 0 > ns3/mytest3.db
+
+# Set up similar db files for sub.test, which will have IXFR disabled
+testdb sub.test. 1 60 > ns3/subtest.db
+testdb sub.test. 3 61 > ns3/subtest1.db
+
+# Set up a large zone
+i=0
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 3 > ns3/large.db
+while [ $i -lt 10000 ]; do
+ echo "record$i 10 IN TXT this is record %i" >> ns3/large.db
+ i=$((i+1))
+done
diff --git a/bin/tests/system/ixfr/tests.sh b/bin/tests/system/ixfr/tests.sh
new file mode 100644
index 0000000..f1e3b62
--- /dev/null
+++ b/bin/tests/system/ixfr/tests.sh
@@ -0,0 +1,443 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# WARNING: The test labelled "testing request-ixfr option in view vs zone"
+# is fragile because it depends upon counting instances of records
+# in the log file - need a better approach <sdm> - until then,
+# if you add any tests above that point, you will break the test.
+
+set -e
+
+. ../conf.sh
+
+wait_for_serial() (
+ $DIG $DIGOPTS "@$1" "$2" SOA > "$4"
+ serial=$(awk '$4 == "SOA" { print $7 }' "$4")
+ [ "$3" -eq "${serial:--1}" ]
+)
+
+status=0
+n=0
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../common/rndc.conf -s"
+
+sendcmd() {
+ send 10.53.0.2 "${EXTRAPORT1}"
+}
+
+
+n=$((n+1))
+echo_i "testing initial AXFR ($n)"
+ret=0
+
+sendcmd <<EOF
+/SOA/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+/AXFR/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+/AXFR/
+nil. 300 NS ns.nil.
+nil. 300 TXT "initial AXFR"
+a.nil. 60 A 10.0.0.61
+b.nil. 60 A 10.0.0.62
+/AXFR/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+EOF
+
+sleep 1
+
+# Initially, ns1 is not authoritative for anything (see setup.sh).
+# Now that ans is up and running with the right data, we make it
+# a secondary for nil.
+
+cat <<EOF >>ns1/named.conf
+zone "nil" {
+ type secondary;
+ file "myftp.db";
+ primaries { 10.53.0.2; };
+};
+EOF
+
+rndc_reload ns1 10.53.0.1
+
+retry_quiet 10 wait_for_serial 10.53.0.1 nil. 1 dig.out.test$n || ret=1
+
+$DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'initial AXFR' >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing successful IXFR ($n)"
+ret=0
+
+# We change the IP address of a.nil., and the TXT record at the apex.
+# Then we do a SOA-only update.
+
+sendcmd <<EOF
+/SOA/
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+/IXFR/
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+a.nil. 60 A 10.0.0.61
+nil. 300 TXT "initial AXFR"
+nil. 300 SOA ns.nil. root.nil. 2 300 300 604800 300
+nil. 300 TXT "successful IXFR"
+a.nil. 60 A 10.0.1.61
+nil. 300 SOA ns.nil. root.nil. 2 300 300 604800 300
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+EOF
+
+sleep 1
+
+$RNDCCMD 10.53.0.1 refresh nil | sed 's/^/ns1 /' | cat_i
+
+sleep 2
+
+$DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'successful IXFR' >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing AXFR fallback after IXFR failure (not exact error) ($n)"
+ret=0
+
+# Provide a broken IXFR response and a working fallback AXFR response
+
+sendcmd <<EOF
+/SOA/
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+/IXFR/
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+nil. 300 TXT "delete-nonexistent-txt-record"
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+nil. 300 TXT "this-txt-record-would-be-added"
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+/AXFR/
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+/AXFR/
+nil. 300 NS ns.nil.
+nil. 300 TXT "fallback AXFR"
+/AXFR/
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+EOF
+
+sleep 1
+
+$RNDCCMD 10.53.0.1 refresh nil | sed 's/^/ns1 /' | cat_i
+
+sleep 2
+
+$DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'fallback AXFR' >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing AXFR fallback after IXFR failure (bad SOA owner) ($n)"
+ret=0
+
+# Prepare for checking the logs later on.
+nextpart ns1/named.run >/dev/null
+
+# Provide a broken IXFR response and a working fallback AXFR response.
+sendcmd <<EOF
+/SOA/
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+/IXFR/
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+bad-owner. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+test.nil. 300 TXT "serial 4, malformed IXFR"
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+/AXFR/
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+/AXFR/
+nil. 300 NS ns.nil.
+test.nil. 300 TXT "serial 4, fallback AXFR"
+/AXFR/
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+EOF
+$RNDCCMD 10.53.0.1 refresh nil | sed 's/^/ns1 /' | cat_i
+
+# A broken server would accept the malformed IXFR and apply its contents to the
+# zone. A fixed one would reject the IXFR and fall back to AXFR. Both IXFR and
+# AXFR above bring the nil. zone up to serial 4, but we cannot reliably query
+# for the SOA record to check whether the transfer was finished because a broken
+# server would send back SERVFAIL responses to SOA queries after accepting the
+# malformed IXFR. Instead, check transfer progress by querying for a TXT record
+# at test.nil. which is present in both IXFR and AXFR (with different contents).
+_wait_until_transfer_is_finished() {
+ $DIG $DIGOPTS +tries=1 +time=1 @10.53.0.1 test.nil. TXT > dig.out.test$n.1 &&
+ grep -q -F "serial 4" dig.out.test$n.1
+}
+if ! retry_quiet 10 _wait_until_transfer_is_finished; then
+ echo_i "timed out waiting for version 4 of zone nil. to be transferred"
+ ret=1
+fi
+
+# At this point a broken server would be serving a zone with no SOA records.
+# Try crashing it by triggering a SOA refresh query.
+$RNDCCMD 10.53.0.1 refresh nil | sed 's/^/ns1 /' | cat_i
+
+# Do not wait until the zone refresh completes - even if a crash has not
+# happened by now, a broken server would never serve the record which is only
+# present in the fallback AXFR, so checking for that is enough to verify if a
+# server is broken or not; if it is, it is bound to crash shortly anyway.
+$DIG $DIGOPTS test.nil. TXT @10.53.0.1 > dig.out.test$n.2 || ret=1
+grep -q -F "serial 4, fallback AXFR" dig.out.test$n.2 || ret=1
+
+# Ensure the expected error is logged.
+nextpart ns1/named.run | grep -q -F "SOA name mismatch" || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing ixfr-from-differences option ($n)"
+# ns3 is primary; ns4 is secondary
+{ $CHECKZONE test. ns3/mytest.db > /dev/null 2>&1; rc=$?; } || true
+if [ $rc -ne 0 ]
+then
+ echo_i "named-checkzone returned failure on ns3/mytest.db"
+fi
+
+retry_quiet 10 wait_for_serial 10.53.0.4 test. 1 dig.out.test$n || ret=1
+
+nextpart ns4/named.run > /dev/null
+
+# modify the primary
+sleep 1
+cp ns3/mytest1.db ns3/mytest.db
+$RNDCCMD 10.53.0.3 reload | sed 's/^/ns3 /' | cat_i
+
+# wait for primary to reload
+retry_quiet 10 wait_for_serial 10.53.0.3 test. 2 dig.out.test$n || ret=1
+
+# wait for secondary to reload
+tret=0
+retry_quiet 5 wait_for_serial 10.53.0.4 test. 2 dig.out.test$n || tret=1
+if [ $tret -eq 1 ]; then
+ # re-noitfy after 5 seconds, then wait another 10
+ $RNDCCMD 10.53.0.3 notify test | set 's/^/ns3 /' | cat_i
+ retry_quiet 10 wait_for_serial 10.53.0.4 test. 2 dig.out.test$n || ret=1
+fi
+
+wait_for_log 10 'got incremental' ns4/named.run || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing 'request-ixfr no' option inheritance from view ($n)"
+ret=0
+# There's a view with 2 zones. In the view, "request-ixfr yes"
+# but in the zone "sub.test", request-ixfr no"
+# we want to make sure that a change to sub.test results in AXFR, while
+# changes to test. result in IXFR
+
+sleep 1
+cp ns3/subtest1.db ns3/subtest.db # change to sub.test zone, should be AXFR
+nextpart ns4/named.run > /dev/null
+$RNDCCMD 10.53.0.3 reload | sed 's/^/ns3 /' | cat_i
+
+# wait for primary to reload
+retry_quiet 10 wait_for_serial 10.53.0.3 sub.test. 3 dig.out.test$n || ret=1
+
+# wait for secondary to reload
+tret=0
+retry_quiet 5 wait_for_serial 10.53.0.4 sub.test. 3 dig.out.test$n || tret=1
+if [ $tret -eq 1 ]; then
+ # re-noitfy after 5 seconds, then wait another 10
+ $RNDCCMD 10.53.0.3 notify sub.test | set 's/^/ns3 /' | cat_i
+ retry_quiet 10 wait_for_serial 10.53.0.4 sub.test. 3 dig.out.test$n || ret=1
+fi
+
+wait_for_log 10 'got nonincremental response' ns4/named.run || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing 'request-ixfr yes' option inheritance from view ($n)"
+ret=0
+sleep 1
+cp ns3/mytest2.db ns3/mytest.db # change to test zone, should be IXFR
+nextpart ns4/named.run > /dev/null
+$RNDCCMD 10.53.0.3 reload | sed 's/^/ns3 /' | cat_i
+
+# wait for primary to reload
+retry_quiet 10 wait_for_serial 10.53.0.3 test. 3 dig.out.test$n || ret=1
+
+# wait for secondary to reload
+tret=0
+retry_quiet 5 wait_for_serial 10.53.0.4 test. 3 dig.out.test$n || tret=1
+if [ $tret -eq 1 ]; then
+ # re-noitfy after 5 seconds, then wait another 10
+ $RNDCCMD 10.53.0.3 notify test | set 's/^/ns3 /' | cat_i
+ retry_quiet 10 wait_for_serial 10.53.0.4 test. 3 dig.out.test$n || ret=1
+fi
+
+wait_for_log 10 'got incremental response' ns4/named.run || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "testing DiG's handling of a multi message AXFR style IXFR response ($n)"
+(
+(sleep 10 && kill $$) 2>/dev/null &
+sub=$!
+$DIG -p ${PORT} ixfr=0 large @10.53.0.3 > dig.out.test$n
+kill $sub
+)
+lines=$(grep hostmaster.large dig.out.test$n | wc -l)
+test ${lines:-0} -eq 2 || ret=1
+messages=$(sed -n 's/^;;.*messages \([0-9]*\),.*/\1/p' dig.out.test$n)
+test ${messages:-0} -gt 1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "test 'dig +notcp ixfr=<value>' vs 'dig ixfr=<value> +notcp' vs 'dig ixfr=<value>' ($n)"
+ret=0
+# Should be "switch to TCP" response
+$DIG $DIGOPTS +notcp ixfr=1 test @10.53.0.4 > dig.out1.test$n || ret=1
+$DIG $DIGOPTS ixfr=1 +notcp test @10.53.0.4 > dig.out2.test$n || ret=1
+digcomp dig.out1.test$n dig.out2.test$n || ret=1
+awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out1.test$n || ret=1
+awk '$4 == "SOA" { if ($7 == 3) exit(0); else exit(1);}' dig.out1.test$n || ret=1
+#
+nextpart ns4/named.run > /dev/null
+# Should be incremental transfer.
+$DIG $DIGOPTS ixfr=1 test @10.53.0.4 > dig.out3.test$n || ret=1
+awk '$4 == "SOA" { soacnt++} END { if (soacnt == 6) exit(0); else exit(1);}' dig.out3.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check estimated IXFR size ($n)"
+ret=0
+# note IXFR delta size will be slightly bigger with version 1 transaction
+# headers as there is no correction for the overall record length storage.
+# Ver1 = 4 * (6 + 10 + 10 + 17 + 5 * 4) + 2 * (13 + 10 + 4) + (6 * 4) = 330
+# Ver2 = 4 * (6 + 10 + 10 + 17 + 5 * 4) + 2 * (13 + 10 + 4) = 306
+nextpart ns4/named.run | grep "IXFR delta size (306 bytes)" > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# make sure ns5 has transfered the zone
+# wait for secondary to reload
+tret=0
+retry_quiet 5 wait_for_serial 10.53.0.5 test. 4 dig.out.test$n || tret=1
+if [ $tret -eq 1 ]; then
+ # re-noitfy after 5 seconds, then wait another 10
+ $RNDCCMD 10.53.0.3 notify test | set 's/^/ns3 /' | cat_i
+ retry_quiet 10 wait_for_serial 10.53.0.5 test. 3 dig.out.test$n || ret=1
+fi
+
+n=$((n+1))
+echo_i "test 'provide-ixfr no;' (serial < current) ($n)"
+ret=0
+nextpart ns5/named.run > /dev/null
+# Should be "AXFR style" response
+$DIG $DIGOPTS ixfr=1 test @10.53.0.5 > dig.out1.test$n || ret=1
+# Should be "switch to TCP" response
+$DIG $DIGOPTS ixfr=1 +notcp test @10.53.0.5 > dig.out2.test$n || ret=1
+awk '$4 == "SOA" { soacnt++} END {if (soacnt == 2) exit(0); else exit(1);}' dig.out1.test$n || ret=1
+awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out2.test$n || ret=1
+msg="IXFR delta response disabled due to 'provide-ixfr no;' being set"
+nextpart ns5/named.run | grep "$msg" > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "test 'provide-ixfr no;' (serial = current) ($n)"
+ret=0
+# Should be "AXFR style" response
+$DIG $DIGOPTS ixfr=3 test @10.53.0.5 > dig.out1.test$n || ret=1
+# Should be "switch to TCP" response
+$DIG $DIGOPTS ixfr=3 +notcp test @10.53.0.5 > dig.out2.test$n || ret=1
+awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out1.test$n || ret=1
+awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out2.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "test 'provide-ixfr no;' (serial > current) ($n)"
+ret=0
+# Should be "AXFR style" response
+$DIG $DIGOPTS ixfr=4 test @10.53.0.5 > dig.out1.test$n || ret=1
+# Should be "switch to TCP" response
+$DIG $DIGOPTS ixfr=4 +notcp test @10.53.0.5 > dig.out2.test$n || ret=1
+awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out1.test$n || ret=1
+awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out2.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking whether dig calculates IXFR statistics correctly ($n)"
+ret=0
+$DIG $DIGOPTS +noedns +stat -b 10.53.0.4 @10.53.0.4 test. ixfr=2 > dig.out1.test$n
+get_dig_xfer_stats dig.out1.test$n > stats.dig
+diff ixfr-stats.good stats.dig > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Note: in the next two tests, we use ns4 logs for checking both incoming and
+# outgoing transfer statistics as ns4 is both a secondary server (for ns3) and a
+# primary server (for dig queries from the previous test) for "test".
+
+_wait_for_stats () {
+ get_named_xfer_stats ns4/named.run "$1" test "$2" > "$3"
+ diff ixfr-stats.good "$3" > /dev/null || return 1
+ return 0
+}
+
+n=$((n+1))
+echo_i "checking whether named calculates incoming IXFR statistics correctly ($n)"
+ret=0
+retry_quiet 10 _wait_for_stats 10.53.0.3 "Transfer completed" stats.incoming || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking whether named calculates outgoing IXFR statistics correctly ($n)"
+retry_quiet 10 _wait_for_stats 10.53.0.4 "IXFR ended" stats.outgoing || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "testing fallback to AXFR when max-ixfr-ratio is exceeded ($n)"
+nextpart ns4/named.run > /dev/null
+
+sleep 1
+cp ns3/mytest3.db ns3/mytest.db # change to test zone, too big for IXFR
+$RNDCCMD 10.53.0.3 reload | sed 's/^/ns3 /' | cat_i
+
+# wait for secondary to reload
+tret=0
+retry_quiet 5 wait_for_serial 10.53.0.4 test. 4 dig.out.test$n || tret=1
+if [ $tret -eq 1 ]; then
+ # re-noitfy after 5 seconds, then wait another 10
+ $RNDCCMD 10.53.0.3 notify test | set 's/^/ns3 /' | cat_i
+ retry_quiet 10 wait_for_serial 10.53.0.4 test. 4 dig.out.test$n || ret=1
+fi
+
+wait_for_log 10 'got nonincremental response' ns4/named.run || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/ixfr/tests_sh_ixfr.py b/bin/tests/system/ixfr/tests_sh_ixfr.py
new file mode 100644
index 0000000..2c7fc28
--- /dev/null
+++ b/bin/tests/system/ixfr/tests_sh_ixfr.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_ixfr(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/journal/clean.sh b/bin/tests/system/journal/clean.sh
new file mode 100644
index 0000000..adab870
--- /dev/null
+++ b/bin/tests/system/journal/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */*.db */*.jnl
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f dig.out*
+rm -f journalprint.out.*
+rm -f ns1/managed-keys.bind
+rm -f ns2/managed-keys.bind
+rm -f tmp.jnl
diff --git a/bin/tests/system/journal/ns1/changed.ver1.jnl.saved b/bin/tests/system/journal/ns1/changed.ver1.jnl.saved
new file mode 100644
index 0000000..b449a7d
--- /dev/null
+++ b/bin/tests/system/journal/ns1/changed.ver1.jnl.saved
Binary files differ
diff --git a/bin/tests/system/journal/ns1/changed.ver2.jnl.saved b/bin/tests/system/journal/ns1/changed.ver2.jnl.saved
new file mode 100644
index 0000000..d2fa199
--- /dev/null
+++ b/bin/tests/system/journal/ns1/changed.ver2.jnl.saved
Binary files differ
diff --git a/bin/tests/system/journal/ns1/d1212.jnl.saved b/bin/tests/system/journal/ns1/d1212.jnl.saved
new file mode 100644
index 0000000..57c1497
--- /dev/null
+++ b/bin/tests/system/journal/ns1/d1212.jnl.saved
Binary files differ
diff --git a/bin/tests/system/journal/ns1/d2121.jnl.saved b/bin/tests/system/journal/ns1/d2121.jnl.saved
new file mode 100644
index 0000000..ec21372
--- /dev/null
+++ b/bin/tests/system/journal/ns1/d2121.jnl.saved
Binary files differ
diff --git a/bin/tests/system/journal/ns1/generic.db.in b/bin/tests/system/journal/ns1/generic.db.in
new file mode 100644
index 0000000..55669d7
--- /dev/null
+++ b/bin/tests/system/journal/ns1/generic.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2012010901 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+addr1 A 10.53.0.1
diff --git a/bin/tests/system/journal/ns1/ixfr.db.in b/bin/tests/system/journal/ns1/ixfr.db.in
new file mode 100644
index 0000000..0cb1184
--- /dev/null
+++ b/bin/tests/system/journal/ns1/ixfr.db.in
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ SOA ns hostmaster 2012010902 3600 1200 604800 1200
+ NS ns
+ns A 192.0.2.1
+
+addr1 A 10.53.0.1
+addr2 A 10.53.0.2
diff --git a/bin/tests/system/journal/ns1/ixfr.ver1.jnl.saved b/bin/tests/system/journal/ns1/ixfr.ver1.jnl.saved
new file mode 100644
index 0000000..10b5116
--- /dev/null
+++ b/bin/tests/system/journal/ns1/ixfr.ver1.jnl.saved
Binary files differ
diff --git a/bin/tests/system/journal/ns1/managed-keys.bind.in b/bin/tests/system/journal/ns1/managed-keys.bind.in
new file mode 100644
index 0000000..923e98b
--- /dev/null
+++ b/bin/tests/system/journal/ns1/managed-keys.bind.in
@@ -0,0 +1,2 @@
+. 0 IN SOA . . 3297 0 0 0 0
+. 0 IN TYPE65533 \# 276 60621140598E0A83000000000101030803010001ACFFB409BCC939F8 31F7A1E5EC88F7A59255EC53040BE432027390A4CE896D6F9086F3C5 E177FBFE118163AAEC7AF1462C47945944C4E2C026BE5E98BBCDED25 978272E1E3E079C5094D573F0E83C92F02B32D3513B1550B826929C8 0DD0F92CAC966D17769FD5867B647C3F38029ABDC48152EB8F207159 ECC5D232C7C1537C79F4B7AC28FF11682F21681BF6D6ABA555032BF6 F9F036BEB2AAA5B3778D6EEBFBA6BF9EA191BE4AB0CAEA759E2F773A 1F9029C73ECB8D5735B9321DB085F1B8E2D8038FE2941992548CEE0D 67DD4547E11DD63AF9C9FC1C5466FB684CF009D7197C2CF79E792AB5 01E6A8A1CA519AF2CB9B5F6367E94C0D47502451357BE1B5
diff --git a/bin/tests/system/journal/ns1/managed-keys.bind.jnl.in b/bin/tests/system/journal/ns1/managed-keys.bind.jnl.in
new file mode 100644
index 0000000..a63f91c
--- /dev/null
+++ b/bin/tests/system/journal/ns1/managed-keys.bind.jnl.in
@@ -0,0 +1,704 @@
+3b42494e44204c4f472056390a000000
+00000cd20000020000000ce200002bf8
+00000038000000000000000000000000
+00000000000000000000000000000000
+00000cd20000020000000cd30000049c
+00000cd40000073800000cd5000009d8
+00000cd600000c7800000cd700000f18
+00000cd8000011b800000cd900001458
+00000cda000016f800000cdb00001998
+00000cdc00001c3800000cdd00001ed8
+00000cde0000217800000cdf00002418
+00000ce0000026b800000ce100002958
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+00000000000000000000000000000000
+0000029000000cd200000cd300000021
+0000060001000000000016000000000c
+d2000000000000000000000000000000
+000000011f00fffd0001000000000114
+6058a4c2598e0a830000000001010308
+03010001acffb409bcc939f831f7a1e5
+ec88f7a59255ec53040be432027390a4
+ce896d6f9086f3c5e177fbfe118163aa
+ec7af1462c47945944c4e2c026be5e98
+bbcded25978272e1e3e079c5094d573f
+0e83c92f02b32d3513b1550b826929c8
+0dd0f92cac966d17769fd5867b647c3f
+38029abdc48152eb8f207159ecc5d232
+c7c1537c79f4b7ac28ff11682f21681b
+f6d6aba555032bf6f9f036beb2aaa5b3
+778d6eebfba6bf9ea191be4ab0caea75
+9e2f773a1f9029c73ecb8d5735b9321d
+b085f1b8e2d8038fe2941992548cee0d
+67dd4547e11dd63af9c9fc1c5466fb68
+4cf009d7197c2cf79e792ab501e6a8a1
+ca519af2cb9b5f6367e94c0d47502451
+357be1b5000000210000060001000000
+000016000000000cd300000000000000
+0000000000000000000000011f00fffd
+00010000000001146058e4a0598e0a83
+000000000101030803010001acffb409
+bcc939f831f7a1e5ec88f7a59255ec53
+040be432027390a4ce896d6f9086f3c5
+e177fbfe118163aaec7af1462c479459
+44c4e2c026be5e98bbcded25978272e1
+e3e079c5094d573f0e83c92f02b32d35
+13b1550b826929c80dd0f92cac966d17
+769fd5867b647c3f38029abdc48152eb
+8f207159ecc5d232c7c1537c79f4b7ac
+28ff11682f21681bf6d6aba555032bf6
+f9f036beb2aaa5b3778d6eebfba6bf9e
+a191be4ab0caea759e2f773a1f9029c7
+3ecb8d5735b9321db085f1b8e2d8038f
+e2941992548cee0d67dd4547e11dd63a
+f9c9fc1c5466fb684cf009d7197c2cf7
+9e792ab501e6a8a1ca519af2cb9b5f63
+67e94c0d47502451357be1b500000290
+00000cd300000cd40000002100000600
+01000000000016000000000cd3000000
+00000000000000000000000000000001
+1f00fffd00010000000001146058e4a0
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cd40000000000000000000000
+00000000000000011f00fffd00010000
+000001146059f642598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cd4
+00000cd5000000000000002100000600
+01000000000016000000000cd4000000
+00000000000000000000000000000001
+1f00fffd00010000000001146059f642
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cd50000000000000000000000
+00000000000000011f00fffd00010000
+00000114605a283e598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cd5
+00000cd6000000000000002100000600
+01000000000016000000000cd5000000
+00000000000000000000000000000001
+1f00fffd0001000000000114605a283e
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cd60000000000000000000000
+00000000000000011f00fffd00010000
+00000114605b47c2598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cd6
+00000cd7000000000000002100000600
+01000000000016000000000cd6000000
+00000000000000000000000000000001
+1f00fffd0001000000000114605b47c2
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cd70000000000000000000000
+00000000000000011f00fffd00010000
+00000114605b79bf598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cd7
+00000cd8000000000000002100000600
+01000000000016000000000cd7000000
+00000000000000000000000000000001
+1f00fffd0001000000000114605b79bf
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cd80000000000000000000000
+00000000000000011f00fffd00010000
+00000114605c9943598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cd8
+00000cd9000000000000002100000600
+01000000000016000000000cd8000000
+00000000000000000000000000000001
+1f00fffd0001000000000114605c9943
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cd90000000000000000000000
+00000000000000011f00fffd00010000
+00000114605ccb40598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cd9
+00000cda000000000000002100000600
+01000000000016000000000cd9000000
+00000000000000000000000000000001
+1f00fffd0001000000000114605ccb40
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cda0000000000000000000000
+00000000000000011f00fffd00010000
+00000114605deac4598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cda
+00000cdb000000000000002100000600
+01000000000016000000000cda000000
+00000000000000000000000000000001
+1f00fffd0001000000000114605deac4
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cdb0000000000000000000000
+00000000000000011f00fffd00010000
+00000114605e1cc0598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cdb
+00000cdc000000000000002100000600
+01000000000016000000000cdb000000
+00000000000000000000000000000001
+1f00fffd0001000000000114605e1cc0
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cdc0000000000000000000000
+00000000000000011f00fffd00010000
+00000114605efb3a598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cdc
+00000cdd000000000000002100000600
+01000000000016000000000cdc000000
+00000000000000000000000000000001
+1f00fffd0001000000000114605efb3a
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cdd0000000000000000000000
+00000000000000011f00fffd00010000
+00000114605f6e40598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cdd
+00000cde000000000000002100000600
+01000000000016000000000cdd000000
+00000000000000000000000000000001
+1f00fffd0001000000000114605f6e40
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cde0000000000000000000000
+00000000000000011f00fffd00010000
+0000011460604cbb598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cde
+00000cdf000000000000002100000600
+01000000000016000000000cde000000
+00000000000000000000000000000001
+1f00fffd000100000000011460604cbb
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000cdf0000000000000000000000
+00000000000000011f00fffd00010000
+000001146060bfc0598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000cdf
+00000ce0000000000000002100000600
+01000000000016000000000cdf000000
+00000000000000000000000000000001
+1f00fffd00010000000001146060bfc0
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000ce00000000000000000000000
+00000000000000011f00fffd00010000
+0000011460619e3b598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000ce0
+00000ce1000000000000002100000600
+01000000000016000000000ce0000000
+00000000000000000000000000000001
+1f00fffd000100000000011460619e3b
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000ce10000000000000000000000
+00000000000000011f00fffd00010000
+0000011460621140598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b50000029000000ce1
+00000ce2000000000000002100000600
+01000000000016000000000ce1000000
+00000000000000000000000000000001
+1f00fffd000100000000011460621140
+598e0a83000000000101030803010001
+acffb409bcc939f831f7a1e5ec88f7a5
+9255ec53040be432027390a4ce896d6f
+9086f3c5e177fbfe118163aaec7af146
+2c47945944c4e2c026be5e98bbcded25
+978272e1e3e079c5094d573f0e83c92f
+02b32d3513b1550b826929c80dd0f92c
+ac966d17769fd5867b647c3f38029abd
+c48152eb8f207159ecc5d232c7c1537c
+79f4b7ac28ff11682f21681bf6d6aba5
+55032bf6f9f036beb2aaa5b3778d6eeb
+fba6bf9ea191be4ab0caea759e2f773a
+1f9029c73ecb8d5735b9321db085f1b8
+e2d8038fe2941992548cee0d67dd4547
+e11dd63af9c9fc1c5466fb684cf009d7
+197c2cf79e792ab501e6a8a1ca519af2
+cb9b5f6367e94c0d47502451357be1b5
+00000021000006000100000000001600
+0000000ce20000000000000000000000
+00000000000000011f00fffd00010000
+000001146062efbb598e0a8300000000
+0101030803010001acffb409bcc939f8
+31f7a1e5ec88f7a59255ec53040be432
+027390a4ce896d6f9086f3c5e177fbfe
+118163aaec7af1462c47945944c4e2c0
+26be5e98bbcded25978272e1e3e079c5
+094d573f0e83c92f02b32d3513b1550b
+826929c80dd0f92cac966d17769fd586
+7b647c3f38029abdc48152eb8f207159
+ecc5d232c7c1537c79f4b7ac28ff1168
+2f21681bf6d6aba555032bf6f9f036be
+b2aaa5b3778d6eebfba6bf9ea191be4a
+b0caea759e2f773a1f9029c73ecb8d57
+35b9321db085f1b8e2d8038fe2941992
+548cee0d67dd4547e11dd63af9c9fc1c
+5466fb684cf009d7197c2cf79e792ab5
+01e6a8a1ca519af2cb9b5f6367e94c0d
+47502451357be1b5
diff --git a/bin/tests/system/journal/ns1/maxjournal.jnl.saved b/bin/tests/system/journal/ns1/maxjournal.jnl.saved
new file mode 100644
index 0000000..7c79e5c
--- /dev/null
+++ b/bin/tests/system/journal/ns1/maxjournal.jnl.saved
Binary files differ
diff --git a/bin/tests/system/journal/ns1/maxjournal2.jnl.saved b/bin/tests/system/journal/ns1/maxjournal2.jnl.saved
new file mode 100644
index 0000000..e200905
--- /dev/null
+++ b/bin/tests/system/journal/ns1/maxjournal2.jnl.saved
Binary files differ
diff --git a/bin/tests/system/journal/ns1/named.conf.in b/bin/tests/system/journal/ns1/named.conf.in
new file mode 100644
index 0000000..55753f6
--- /dev/null
+++ b/bin/tests/system/journal/ns1/named.conf.in
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation yes;
+ minimal-responses no;
+ recursion no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone changed {
+ type primary;
+ update-policy local;
+ file "changed.db";
+};
+
+zone unchanged {
+ type primary;
+ update-policy local;
+ file "unchanged.db";
+};
+
+zone changed2 {
+ type primary;
+ update-policy local;
+ file "changed2.db";
+};
+
+zone unchanged2 {
+ type primary;
+ update-policy local;
+ file "unchanged2.db";
+};
+
+zone hdr1d1d2d1d2 {
+ type primary;
+ update-policy local;
+ file "d1212.db";
+};
+
+zone hdr1d2d1d2d1 {
+ type primary;
+ update-policy local;
+ file "d2121.db";
+};
+
+zone ixfr {
+ type primary;
+ ixfr-from-differences yes;
+ file "ixfr.db";
+};
+
+zone maxjournal {
+ type primary;
+ max-journal-size 1k;
+ update-policy local;
+ file "maxjournal.db";
+};
+
+zone maxjournal2 {
+ type primary;
+ max-journal-size 1k;
+ update-policy local;
+ file "maxjournal2.db";
+};
diff --git a/bin/tests/system/journal/ns1/unchanged.ver1.jnl.saved b/bin/tests/system/journal/ns1/unchanged.ver1.jnl.saved
new file mode 100644
index 0000000..f7885d9
--- /dev/null
+++ b/bin/tests/system/journal/ns1/unchanged.ver1.jnl.saved
Binary files differ
diff --git a/bin/tests/system/journal/ns1/unchanged.ver2.jnl.saved b/bin/tests/system/journal/ns1/unchanged.ver2.jnl.saved
new file mode 100644
index 0000000..d974be4
--- /dev/null
+++ b/bin/tests/system/journal/ns1/unchanged.ver2.jnl.saved
Binary files differ
diff --git a/bin/tests/system/journal/ns2/managed-keys.bind.in b/bin/tests/system/journal/ns2/managed-keys.bind.in
new file mode 100644
index 0000000..2139706
--- /dev/null
+++ b/bin/tests/system/journal/ns2/managed-keys.bind.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 0 ; 0 seconds
+@ IN SOA . . (
+ 29 ; serial
+ 0 ; refresh (0 seconds)
+ 0 ; retry (0 seconds)
+ 0 ; expire (0 seconds)
+ 0 ; minimum (0 seconds)
+ )
+ KEYDATA 20210611104535 19700101000000 19700101000000 0 0 0 (
+
+ ) ; ZSK; alg = 0; key id = 0
+ ; next refresh: Fri, 11 Jun 2021 10:45:35 GMT
+ ; no trust
diff --git a/bin/tests/system/journal/ns2/managed-keys.bind.jnl.in b/bin/tests/system/journal/ns2/managed-keys.bind.jnl.in
new file mode 100644
index 0000000..01c1d47
--- /dev/null
+++ b/bin/tests/system/journal/ns2/managed-keys.bind.jnl.in
Binary files differ
diff --git a/bin/tests/system/journal/ns2/named.conf.in b/bin/tests/system/journal/ns2/named.conf.in
new file mode 100644
index 0000000..a24774a
--- /dev/null
+++ b/bin/tests/system/journal/ns2/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ dnssec-validation yes;
+ minimal-responses no;
+ recursion no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/journal/setup.sh b/bin/tests/system/journal/setup.sh
new file mode 100644
index 0000000..e9b0072
--- /dev/null
+++ b/bin/tests/system/journal/setup.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+cp ns1/generic.db.in ns1/changed.db
+cp ns1/changed.ver1.jnl.saved ns1/changed.db.jnl
+
+cp ns1/generic.db.in ns1/unchanged.db
+cp ns1/unchanged.ver1.jnl.saved ns1/unchanged.db.jnl
+
+cp ns1/generic.db.in ns1/changed2.db
+cp ns1/changed.ver2.jnl.saved ns1/changed2.db.jnl
+
+cp ns1/generic.db.in ns1/unchanged2.db
+cp ns1/unchanged.ver2.jnl.saved ns1/unchanged2.db.jnl
+
+cp ns1/ixfr.db.in ns1/ixfr.db
+cp ns1/ixfr.ver1.jnl.saved ns1/ixfr.db.jnl
+
+cp ns1/generic.db.in ns1/d1212.db
+cp ns1/d1212.jnl.saved ns1/d1212.db.jnl
+
+cp ns1/generic.db.in ns1/d2121.db
+cp ns1/d2121.jnl.saved ns1/d2121.db.jnl
+
+cp ns1/generic.db.in ns1/maxjournal.db
+cp ns1/maxjournal.jnl.saved ns1/maxjournal.db.jnl
+
+cp ns1/generic.db.in ns1/maxjournal2.db
+cp ns1/maxjournal2.jnl.saved ns1/maxjournal2.db.jnl
+
+cp ns1/managed-keys.bind.in ns1/managed-keys.bind
+$PERL ../fromhex.pl < ns1/managed-keys.bind.jnl.in > ns1/managed-keys.bind.jnl
+
+copy_setports ns2/named.conf.in ns2/named.conf
+cp ns2/managed-keys.bind.in ns2/managed-keys.bind
+cp ns2/managed-keys.bind.jnl.in ns2/managed-keys.bind.jnl
diff --git a/bin/tests/system/journal/tests.sh b/bin/tests/system/journal/tests.sh
new file mode 100644
index 0000000..5dbceb8
--- /dev/null
+++ b/bin/tests/system/journal/tests.sh
@@ -0,0 +1,257 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+dig_with_opts() {
+ "$DIG" @10.53.0.1 -p "$PORT" +tcp "$@"
+}
+
+rndc_with_opts() {
+ "$RNDC" -c ../common/rndc.conf -p "$CONTROLPORT" -s "$@"
+}
+
+status=0
+n=0
+
+n=$((n + 1))
+echo_i "check outdated journal rolled forward (dynamic) ($n)"
+ret=0
+dig_with_opts changed soa > dig.out.test$n
+grep 'status: NOERROR' dig.out.test$n > /dev/null || ret=1
+grep '2012010902' dig.out.test$n > /dev/null || ret=1
+grep 'zone changed/IN: journal rollforward completed successfully using old journal format' ns1/named.run > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check outdated empty journal did not cause an error (dynamic) ($n)"
+ret=0
+dig_with_opts unchanged soa > dig.out.test$n
+grep 'status: NOERROR' dig.out.test$n > /dev/null || ret=1
+grep '2012010901' dig.out.test$n > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check outdated journals were updated or removed (dynamic) ($n)"
+ret=0
+cat -v ns1/changed.db.jnl | grep "BIND LOG V9.2" > /dev/null || ret=1
+[ -f ns1/unchanged.db.jnl ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check updated journal has correct RR count (dynamic) ($n)"
+ret=0
+$JOURNALPRINT -x ns1/changed.db.jnl | grep "rrcount 3 " > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check new-format journal rolled forward (dynamic) ($n)"
+ret=0
+dig_with_opts changed2 soa > dig.out.test$n
+grep 'status: NOERROR' dig.out.test$n > /dev/null || ret=1
+grep '2012010902' dig.out.test$n > /dev/null || ret=1
+grep 'zone changed2/IN: journal rollforward completed successfully: success' ns1/named.run > /dev/null || ret=1
+grep 'zone changed2/IN: journal rollforward completed successfully using old journal format' ns1/named.run > /dev/null && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check new-format empty journal did not cause error (dynamic) ($n)"
+ret=0
+dig_with_opts unchanged2 soa > dig.out.test$n
+grep 'status: NOERROR' dig.out.test$n > /dev/null || ret=1
+grep '2012010901' dig.out.test$n > /dev/null || ret=1
+grep 'zone unchanged2/IN: journal rollforward completed successfully' ns1/named.run > /dev/null && ret=1
+grep 'zone unchanged2/IN: journal rollforward completed successfully using old journal format' ns1/named.run > /dev/null && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check new-format journals were updated or removed (dynamic) ($n)"
+ret=0
+cat -v ns1/changed2.db.jnl | grep "BIND LOG V9.2" > /dev/null || ret=1
+[ -f ns1/unchanged2.db.jnl ] && ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check outdated up-to-date journal succeeded (ixfr-from-differences) ($n)"
+ret=0
+dig_with_opts -t soa ixfr > dig.out.test$n
+grep 'status: NOERROR' dig.out.test$n > /dev/null || ret=1
+grep '2012010902' dig.out.test$n > /dev/null || ret=1
+grep 'zone ixfr/IN: journal rollforward completed successfully using old journal format: up to date' ns1/named.run > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check outdated journal was updated (ixfr-from-differences) ($n)"
+ret=0
+cat -v ns1/ixfr.db.jnl | grep "BIND LOG V9.2" > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check journal with mixed headers succeeded (version 1,2,1,2) ($n)"
+ret=0
+dig_with_opts -t soa hdr1d1d2d1d2 > dig.out.test$n
+grep 'status: NOERROR' dig.out.test$n > /dev/null || ret=1
+grep '2012010905' dig.out.test$n > /dev/null || ret=1
+grep 'zone hdr1d1d2d1d2/IN: journal rollforward completed successfully using old journal format: success' ns1/named.run > /dev/null || ret=1
+grep 'zone_journal_compact: zone hdr1d1d2d1d2/IN: repair full journal' ns1/named.run > /dev/null || ret=1
+grep 'hdr1d1d2d1d2/IN: dns_journal_compact: success' ns1/named.run > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check journal with mixed headers was updated (version 1,2,1,2) ($n)"
+ret=0
+[ $($JOURNALPRINT -x ns1/d1212.jnl.saved | grep -c "version 1") -eq 2 ] || ret=1
+[ $($JOURNALPRINT -x ns1/d1212.jnl.saved | grep -c "version 2") -eq 2 ] || ret=1
+[ $($JOURNALPRINT -x ns1/d1212.db.jnl | grep -c "version 1") -eq 0 ] || ret=1
+[ $($JOURNALPRINT -x ns1/d1212.db.jnl | grep -c "version 2") -eq 4 ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check journal with mixed headers succeeded (version 2,1,2,1) ($n)"
+ret=0
+dig_with_opts -t soa hdr1d2d1d2d1 > dig.out.test$n
+grep 'status: NOERROR' dig.out.test$n > /dev/null || ret=1
+grep '2012010905' dig.out.test$n > /dev/null || ret=1
+grep 'zone hdr1d2d1d2d1/IN: journal rollforward completed successfully using old journal format: success' ns1/named.run > /dev/null || ret=1
+grep 'zone_journal_compact: zone hdr1d2d1d2d1/IN: repair full journal' ns1/named.run > /dev/null || ret=1
+grep 'zone hdr1d2d1d2d1/IN: dns_journal_compact: success' ns1/named.run > /dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check journal with mixed headers was updated (version 2,1,2,1) ($n)"
+ret=0
+[ $($JOURNALPRINT -x ns1/d2121.jnl.saved | grep -c "version 1") -eq 2 ] || ret=1
+[ $($JOURNALPRINT -x ns1/d2121.jnl.saved | grep -c "version 2") -eq 2 ] || ret=1
+[ $($JOURNALPRINT -x ns1/d2121.db.jnl | grep -c "version 1") -eq 0 ] || ret=1
+[ $($JOURNALPRINT -x ns1/d2121.db.jnl | grep -c "version 2") -eq 4 ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check there are no journals left un-updated ($n)"
+ret=0
+c1=$(cat -v ns1/*.jnl | grep -c "BIND LOG V9")
+c2=$(cat -v ns1/*.jnl | grep -c "BIND LOG V9.2")
+[ ${c1} -eq ${c2} ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "Check that journal with mixed headers can be compacted (version 1,2,1,2) ($n)"
+ret=0
+journal=ns1/d1212.jnl.saved
+seriallist=$($JOURNALPRINT -x $journal | awk '$1 == "Transaction:" { print $11 }')
+for serial in $seriallist
+do
+ cp $journal tmp.jnl
+ $JOURNALPRINT -c $serial tmp.jnl || ret=1
+done
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "Check that journal with mixed headers can be compacted (version 2,1,2,1) ($n)"
+ret=0
+journal=ns1/d2121.jnl.saved
+seriallist=$($JOURNALPRINT -x $journal | awk '$1 == "Transaction:" { print $11 }')
+for serial in $seriallist
+do
+ cp ns1/d1212.jnl.saved tmp.jnl
+ $JOURNALPRINT -c $serial tmp.jnl || ret=1
+done
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check upgrade of managed-keys.bind.jnl succeeded($n)"
+ret=0
+$JOURNALPRINT ns1/managed-keys.bind.jnl > journalprint.out.test$n
+lines=$(awk '$1 == "add" && $5 == "SOA" && $8 == "3297" { print }' journalprint.out.test$n | wc -l)
+test $lines -eq 1 || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check journal downgrade/upgrade ($n)"
+ret=0
+cp ns1/changed.db.jnl ns1/temp.jnl
+$JOURNALPRINT -d ns1/temp.jnl
+[ $($JOURNALPRINT -x ns1/temp.jnl | grep -c "version 1") -eq 1 ] || ret=1
+$JOURNALPRINT -x ns1/temp.jnl | grep -q "Header version = 1" || ret=1
+$JOURNALPRINT -u ns1/temp.jnl
+$JOURNALPRINT -x ns1/temp.jnl | grep -q "Header version = 2" || ret=1
+[ $($JOURNALPRINT -x ns1/temp.jnl | grep -c "version 2") -eq 1 ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check max-journal-size works after journal update ($n)"
+ret=0
+# journal was repaired, it should still be big
+[ $(wc -c < ns1/maxjournal.db.jnl) -gt 12000 ] || ret=1
+# the zone hasn't been dumped yet, so 'rndc sync' should work without
+# needing a zone update first.
+rndc_with_opts 10.53.0.1 sync maxjournal
+check_size() (
+ [ $(wc -c < ns1/maxjournal.db.jnl) -lt 4000 ]
+)
+retry_quiet 10 check_size || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check max-journal-size works with non-updated journals ($n)"
+ret=0
+# journal was not repaired, so it should still be big
+[ $(wc -c < ns1/maxjournal2.db.jnl) -gt 12000 ] || ret=1
+# the zone hasn't been dumped yet, so 'rndc sync' should work without
+# needing a zone update first.
+rndc_with_opts 10.53.0.1 sync maxjournal2
+check_size() (
+ [ $(wc -c < ns1/maxjournal2.db.jnl) -lt 4000 ]
+)
+retry_quiet 10 check_size || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check journal index consistency ($n)"
+ret=0
+for jnl in ns1/*.jnl; do
+ $JOURNALPRINT -x $jnl 2>&1 | grep -q "Offset mismatch" && ret=1
+done
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check that journal is applied to zone with keydata placeholder record"
+ret=0
+grep 'managed-keys-zone: journal rollforward completed successfully: up to date' ns2/named.run > /dev/null 2>&1 || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/journal/tests_sh_journal.py b/bin/tests/system/journal/tests_sh_journal.py
new file mode 100644
index 0000000..e492e12
--- /dev/null
+++ b/bin/tests/system/journal/tests_sh_journal.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_journal(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/kasp.sh b/bin/tests/system/kasp.sh
new file mode 100644
index 0000000..4c44ac9
--- /dev/null
+++ b/bin/tests/system/kasp.sh
@@ -0,0 +1,1244 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Common configuration data for kasp system tests, to be sourced into
+# other shell scripts.
+#
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+###############################################################################
+# Constants #
+###############################################################################
+DEFAULT_TTL=300
+
+###############################################################################
+# Query properties #
+###############################################################################
+TSIG=""
+SHA1="FrSt77yPTFx6hTs4i2tKLB9LmE0="
+SHA224="hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA=="
+SHA256="R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY="
+VIEW1="YPfMoAk6h+3iN8MDRQC004iSNHY="
+VIEW2="4xILSZQnuO1UKubXHkYUsvBRPu8="
+VIEW3="C1Azf+gGPMmxrUg/WQINP6eV9Y0="
+
+###############################################################################
+# Key properties #
+###############################################################################
+# ID
+# BASEFILE
+# EXPECT
+# ROLE
+# KSK
+# ZSK
+# FLAGS
+# LIFETIME
+# ALG_NUM
+# ALG_STR
+# ALG_LEN
+# CREATED
+# PUBLISHED
+# ACTIVE
+# RETIRED
+# REVOKED
+# REMOVED
+# GOAL
+# STATE_DNSKEY
+# STATE_ZRRSIG
+# STATE_KRRSIG
+# STATE_DS
+# EXPECT_ZRRSIG
+# EXPECT_KRRSIG
+# LEGACY
+# PRIVATE
+# PRIVKEY_STAT
+# PUBKEY_STAT
+# STATE_STAT
+
+key_key() {
+ echo "${1}__${2}"
+}
+
+key_get() {
+ eval "echo \${$(key_key "$1" "$2")}"
+}
+
+key_set() {
+ eval "$(key_key "$1" "$2")='$3'"
+}
+
+key_stat() {
+ $PERL -e 'print((stat @ARGV[0])[9] . "\n");' "$1"
+}
+
+# Save certain values in the KEY array.
+key_save()
+{
+ # Save key id.
+ key_set "$1" ID "$KEY_ID"
+ # Save base filename.
+ key_set "$1" BASEFILE "$BASE_FILE"
+ # Save creation date.
+ key_set "$1" CREATED "${KEY_CREATED}"
+ # Save key change time.
+ key_set "$1" PRIVKEY_STAT $(key_stat "${BASE_FILE}.private")
+ key_set "$1" PUBKEY_STAT $(key_stat "${BASE_FILE}.key")
+ key_set "$1" STATE_STAT $(key_stat "${BASE_FILE}.state")
+}
+
+# Clear key state.
+#
+# This will update either the KEY1, KEY2, or KEY3 array.
+key_clear() {
+ key_set "$1" "ID" 'no'
+ key_set "$1" "IDPAD" 'no'
+ key_set "$1" "EXPECT" 'no'
+ key_set "$1" "ROLE" 'none'
+ key_set "$1" "KSK" 'no'
+ key_set "$1" "ZSK" 'no'
+ key_set "$1" "FLAGS" '0'
+ key_set "$1" "LIFETIME" 'none'
+ key_set "$1" "ALG_NUM" '0'
+ key_set "$1" "ALG_STR" 'none'
+ key_set "$1" "ALG_LEN" '0'
+ key_set "$1" "CREATED" '0'
+ key_set "$1" "PUBLISHED" 'none'
+ key_set "$1" "SYNCPUBLISH" 'none'
+ key_set "$1" "ACTIVE" 'none'
+ key_set "$1" "RETIRED" 'none'
+ key_set "$1" "REVOKED" 'none'
+ key_set "$1" "REMOVED" 'none'
+ key_set "$1" "GOAL" 'none'
+ key_set "$1" "STATE_DNSKEY" 'none'
+ key_set "$1" "STATE_KRRSIG" 'none'
+ key_set "$1" "STATE_ZRRSIG" 'none'
+ key_set "$1" "STATE_DS" 'none'
+ key_set "$1" "EXPECT_ZRRSIG" 'no'
+ key_set "$1" "EXPECT_KRRSIG" 'no'
+ key_set "$1" "LEGACY" 'no'
+ key_set "$1" "PRIVATE" 'yes'
+ key_set "$1" "PRIVKEY_STAT" '0'
+ key_set "$1" "PUBKEY_STAT" '0'
+ key_set "$1" "STATE_STAT" '0'
+}
+
+# Start clear.
+# There can be at most 4 keys at the same time during a rollover:
+# 2x KSK, 2x ZSK
+key_clear "KEY1"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+###############################################################################
+# Utilities #
+###############################################################################
+
+# Call dig with default options.
+_dig_with_opts() {
+
+ if [ -n "$TSIG" ]; then
+ "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" -y "$TSIG" "$@"
+ else
+ "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
+ fi
+}
+
+# RNDC.
+_rndccmd() {
+ "$RNDC" -c ../common/rndc.conf -p "$CONTROLPORT" -s "$@"
+}
+
+# Print IDs of keys used for generating RRSIG records for RRsets of type $1
+# found in dig output file $2.
+get_keys_which_signed() {
+ _qtype=$1
+ _output=$2
+ # The key ID is the 11th column of the RRSIG record line.
+ awk -v qt="$_qtype" '$4 == "RRSIG" && $5 == qt {print $11}' < "$_output"
+}
+
+# Get the key ids from key files for zone $2 in directory $1.
+get_keyids() {
+ _dir=$1
+ _zone=$2
+ _regex="K${_zone}.+*+*.key"
+
+ find "${_dir}" -mindepth 1 -maxdepth 1 -name "${_regex}" | sed "s,$_dir/K${_zone}.+\([0-9]\{3\}\)+\([0-9]\{5\}\).key,\2,"
+}
+
+# By default log errors and don't quit immediately.
+_log=1
+_log_error() {
+ test $_log -eq 1 && echo_i "error: $1"
+ ret=$((ret+1))
+}
+disable_logerror() {
+ _log=0
+}
+enable_logerror() {
+ _log=1
+}
+
+# Set server key-directory ($1) and address ($2) for testing keys.
+set_server() {
+ DIR=$1
+ SERVER=$2
+}
+# Set zone name for testing keys.
+set_zone() {
+ ZONE=$1
+ DYNAMIC="no"
+}
+# By default zones are considered static.
+# When testing dynamic zones, call 'set_dynamic' after 'set_zone'.
+set_dynamic() {
+ DYNAMIC="yes"
+}
+
+# Set policy settings (name $1, number of keys $2, dnskey ttl $3) for testing keys.
+set_policy() {
+ POLICY=$1
+ NUM_KEYS=$2
+ DNSKEY_TTL=$3
+ CDS_DELETE="no"
+}
+# By default policies are considered to be secure.
+# If a zone sets its policy to "insecure", call 'set_cdsdelete' to tell the
+# system test to expect a CDS and CDNSKEY Delete record.
+set_cdsdelete() {
+ CDS_DELETE="yes"
+}
+
+# Set key properties for testing keys.
+# $1: Key to update (KEY1, KEY2, ...)
+# $2: Value
+set_keyrole() {
+ key_set "$1" "EXPECT" "yes"
+ key_set "$1" "ROLE" "$2"
+ key_set "$1" "KSK" "no"
+ key_set "$1" "ZSK" "no"
+ key_set "$1" "FLAGS" "0"
+
+ test "$2" = "ksk" && key_set "$1" "KSK" "yes"
+ test "$2" = "ksk" && key_set "$1" "FLAGS" "257"
+
+ test "$2" = "zsk" && key_set "$1" "ZSK" "yes"
+ test "$2" = "zsk" && key_set "$1" "FLAGS" "256"
+
+ test "$2" = "csk" && key_set "$1" "KSK" "yes"
+ test "$2" = "csk" && key_set "$1" "ZSK" "yes"
+ test "$2" = "csk" && key_set "$1" "FLAGS" "257"
+
+ return 0
+}
+set_keylifetime() {
+ key_set "$1" "EXPECT" "yes"
+ key_set "$1" "LIFETIME" "$2"
+}
+# The algorithm value consists of three parts:
+# $2: Algorithm (number)
+# $3: Algorithm (string-format)
+# $4: Algorithm length
+set_keyalgorithm() {
+ key_set "$1" "EXPECT" "yes"
+ key_set "$1" "ALG_NUM" "$2"
+ key_set "$1" "ALG_STR" "$3"
+ key_set "$1" "ALG_LEN" "$4"
+}
+set_keysigning() {
+ key_set "$1" "EXPECT" "yes"
+ key_set "$1" "EXPECT_KRRSIG" "$2"
+}
+set_zonesigning() {
+ key_set "$1" "EXPECT" "yes"
+ key_set "$1" "EXPECT_ZRRSIG" "$2"
+}
+
+# Set key timing metadata. Set to "none" to unset.
+# $1: Key to update (KEY1, KEY2, ...)
+# $2: Time to update (PUBLISHED, SYNCPUBLISH, ACTIVE, RETIRED, REVOKED, or REMOVED).
+# $3: Value
+set_keytime() {
+ key_set "$1" "EXPECT" "yes"
+ key_set "$1" "$2" "$3"
+}
+
+# Set key timing metadata to a value plus additional time.
+# $1: Key to update (KEY1, KEY2, ...)
+# $2: Time to update (PUBLISHED, SYNCPUBLISH, ACTIVE, RETIRED, REVOKED, or REMOVED).
+# $3: Value
+# $4: Additional time.
+set_addkeytime() {
+ if [ -x "$PYTHON" ]; then
+ # Convert "%Y%m%d%H%M%S" format to epoch seconds.
+ # Then, add the additional time (can be negative).
+ _value=$3
+ _plus=$4
+ $PYTHON > python.out.$ZONE.$1.$2 <<EOF
+from datetime import datetime
+from datetime import timedelta
+_now = datetime.strptime("$_value", "%Y%m%d%H%M%S")
+_delta = timedelta(seconds=$_plus)
+_then = _now + _delta
+print(_then.strftime("%Y%m%d%H%M%S"));
+EOF
+ # Set the expected timing metadata.
+ key_set "$1" "$2" $(cat python.out.$ZONE.$1.$2)
+ fi
+}
+
+# Set key state metadata. Set to "none" to unset.
+# $1: Key to update (KEY1, KEY2, ...)
+# $2: Key state to update (GOAL, STATE_DNSKEY, STATE_ZRRSIG, STATE_KRRSIG, or STATE_DS)
+# $3: Value
+set_keystate() {
+ key_set "$1" "EXPECT" "yes"
+ key_set "$1" "$2" "$3"
+}
+
+# Check the key $1 with id $2.
+# This requires environment variables to be set.
+#
+# This will set the following environment variables for testing:
+# BASE_FILE="${_dir}/K${_zone}.+${_alg_numpad}+${_key_idpad}"
+# KEY_FILE="${BASE_FILE}.key"
+# PRIVATE_FILE="${BASE_FILE}.private"
+# STATE_FILE="${BASE_FILE}.state"
+# KEY_ID=$(echo $1 | sed 's/^0\{0,4\}//')
+# KEY_CREATED (from the KEY_FILE)
+check_key() {
+ _dir="$DIR"
+ _zone="$ZONE"
+ _role=$(key_get "$1" ROLE)
+ _key_idpad="$2"
+ _key_id=$(echo "$_key_idpad" | sed 's/^0\{0,4\}//')
+ _alg_num=$(key_get "$1" ALG_NUM)
+ _alg_numpad=$(printf "%03d" "$_alg_num")
+ _alg_string=$(key_get "$1" ALG_STR)
+ _length=$(key_get "$1" "ALG_LEN")
+ _dnskey_ttl="$DNSKEY_TTL"
+ _lifetime=$(key_get "$1" LIFETIME)
+ _legacy=$(key_get "$1" LEGACY)
+ _private=$(key_get "$1" PRIVATE)
+ _flags=$(key_get "$1" FLAGS)
+
+ _published=$(key_get "$1" PUBLISHED)
+ _active=$(key_get "$1" ACTIVE)
+ _retired=$(key_get "$1" RETIRED)
+ _revoked=$(key_get "$1" REVOKED)
+ _removed=$(key_get "$1" REMOVED)
+
+ _goal=$(key_get "$1" GOAL)
+ _state_dnskey=$(key_get "$1" STATE_DNSKEY)
+ _state_zrrsig=$(key_get "$1" STATE_ZRRSIG)
+ _state_krrsig=$(key_get "$1" STATE_KRRSIG)
+ _state_ds=$(key_get "$1" STATE_DS)
+
+ _ksk="no"
+ _zsk="no"
+ if [ "$_role" = "ksk" ]; then
+ _ksk="yes"
+ elif [ "$_role" = "zsk" ]; then
+ _zsk="yes"
+ elif [ "$_role" = "csk" ]; then
+ _zsk="yes"
+ _ksk="yes"
+ fi
+
+ _role2="none"
+ if [ "$_flags" = "257" ]; then
+ _role2="key-signing"
+ elif [ "$_flags" = "256" ]; then
+ _role2="zone-signing"
+ fi
+
+ BASE_FILE="${_dir}/K${_zone}.+${_alg_numpad}+${_key_idpad}"
+ KEY_FILE="${BASE_FILE}.key"
+ PRIVATE_FILE="${BASE_FILE}.private"
+ STATE_FILE="${BASE_FILE}.state"
+ KEY_ID="${_key_id}"
+
+ # Check file existence.
+ [ -s "$KEY_FILE" ] || ret=1
+ if [ "$_private" = "yes" ]; then
+ [ -s "$PRIVATE_FILE" ] || ret=1
+ fi
+ if [ "$_legacy" = "no" ]; then
+ [ -s "$STATE_FILE" ] || ret=1
+ fi
+ [ "$ret" -eq 0 ] || _log_error "${BASE_FILE} files missing"
+ [ "$ret" -eq 0 ] || return 0
+
+ # Retrieve creation date.
+ grep "; Created:" "$KEY_FILE" > "${ZONE}.${KEY_ID}.${_alg_num}.created" || _log_error "mismatch created comment in $KEY_FILE"
+ KEY_CREATED=$(awk '{print $3}' < "${ZONE}.${KEY_ID}.${_alg_num}.created")
+
+ if [ "$_private" = "yes" ]; then
+ grep "Created: ${KEY_CREATED}" "$PRIVATE_FILE" > /dev/null || _log_error "mismatch created in $PRIVATE_FILE"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "Generated: ${KEY_CREATED}" "$STATE_FILE" > /dev/null || _log_error "mismatch generated in $STATE_FILE"
+ fi
+
+ test $_log -eq 1 && echo_i "check key file $BASE_FILE"
+
+ # Check the public key file.
+ grep "This is a ${_role2} key, keyid ${_key_id}, for ${_zone}." "$KEY_FILE" > /dev/null || _log_error "mismatch top comment in $KEY_FILE"
+ grep "${_zone}\. ${_dnskey_ttl} IN DNSKEY ${_flags} 3 ${_alg_num}" "$KEY_FILE" > /dev/null || _log_error "mismatch DNSKEY record in $KEY_FILE"
+ # Now check the private key file.
+ if [ "$_private" = "yes" ]; then
+ grep "Private-key-format: v1.3" "$PRIVATE_FILE" > /dev/null || _log_error "mismatch private key format in $PRIVATE_FILE"
+ grep "Algorithm: ${_alg_num} (${_alg_string})" "$PRIVATE_FILE" > /dev/null || _log_error "mismatch algorithm in $PRIVATE_FILE"
+ fi
+ # Now check the key state file.
+ if [ "$_legacy" = "no" ]; then
+ grep "This is the state of key ${_key_id}, for ${_zone}." "$STATE_FILE" > /dev/null || _log_error "mismatch top comment in $STATE_FILE"
+ if [ "$_lifetime" = "none" ]; then
+ grep "Lifetime: " "$STATE_FILE" > /dev/null && _log_error "unexpected lifetime in $STATE_FILE"
+ else
+ grep "Lifetime: ${_lifetime}" "$STATE_FILE" > /dev/null || _log_error "mismatch lifetime in $STATE_FILE"
+ fi
+ grep "Algorithm: ${_alg_num}" "$STATE_FILE" > /dev/null || _log_error "mismatch algorithm in $STATE_FILE"
+ grep "Length: ${_length}" "$STATE_FILE" > /dev/null || _log_error "mismatch length in $STATE_FILE"
+ grep "KSK: ${_ksk}" "$STATE_FILE" > /dev/null || _log_error "mismatch ksk in $STATE_FILE"
+ grep "ZSK: ${_zsk}" "$STATE_FILE" > /dev/null || _log_error "mismatch zsk in $STATE_FILE"
+
+ # Check key states.
+ if [ "$_goal" = "none" ]; then
+ grep "GoalState: " "$STATE_FILE" > /dev/null && _log_error "unexpected goal state in $STATE_FILE"
+ else
+ grep "GoalState: ${_goal}" "$STATE_FILE" > /dev/null || _log_error "mismatch goal state in $STATE_FILE"
+ fi
+
+ if [ "$_state_dnskey" = "none" ]; then
+ grep "DNSKEYState: " "$STATE_FILE" > /dev/null && _log_error "unexpected dnskey state in $STATE_FILE"
+ grep "DNSKEYChange: " "$STATE_FILE" > /dev/null && _log_error "unexpected dnskey change in $STATE_FILE"
+ else
+ grep "DNSKEYState: ${_state_dnskey}" "$STATE_FILE" > /dev/null || _log_error "mismatch dnskey state in $STATE_FILE"
+ grep "DNSKEYChange: " "$STATE_FILE" > /dev/null || _log_error "mismatch dnskey change in $STATE_FILE"
+ fi
+
+ if [ "$_state_zrrsig" = "none" ]; then
+ grep "ZRRSIGState: " "$STATE_FILE" > /dev/null && _log_error "unexpected zrrsig state in $STATE_FILE"
+ grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null && _log_error "unexpected zrrsig change in $STATE_FILE"
+ else
+ grep "ZRRSIGState: ${_state_zrrsig}" "$STATE_FILE" > /dev/null || _log_error "mismatch zrrsig state in $STATE_FILE"
+ grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null || _log_error "mismatch zrrsig change in $STATE_FILE"
+ fi
+
+ if [ "$_state_krrsig" = "none" ]; then
+ grep "KRRSIGState: " "$STATE_FILE" > /dev/null && _log_error "unexpected krrsig state in $STATE_FILE"
+ grep "KRRSIGChange: " "$STATE_FILE" > /dev/null && _log_error "unexpected krrsig change in $STATE_FILE"
+ else
+ grep "KRRSIGState: ${_state_krrsig}" "$STATE_FILE" > /dev/null || _log_error "mismatch krrsig state in $STATE_FILE"
+ grep "KRRSIGChange: " "$STATE_FILE" > /dev/null || _log_error "mismatch krrsig change in $STATE_FILE"
+ fi
+
+ if [ "$_state_ds" = "none" ]; then
+ grep "DSState: " "$STATE_FILE" > /dev/null && _log_error "unexpected ds state in $STATE_FILE"
+ grep "DSChange: " "$STATE_FILE" > /dev/null && _log_error "unexpected ds change in $STATE_FILE"
+ else
+ grep "DSState: ${_state_ds}" "$STATE_FILE" > /dev/null || _log_error "mismatch ds state in $STATE_FILE"
+ grep "DSChange: " "$STATE_FILE" > /dev/null || _log_error "mismatch ds change in $STATE_FILE"
+ fi
+ fi
+
+ return 0
+}
+
+# Check the key timing metadata for key $1.
+check_timingmetadata() {
+ _dir="$DIR"
+ _zone="$ZONE"
+ _key_idpad=$(key_get "$1" ID)
+ _key_id=$(echo "$_key_idpad" | sed 's/^0\{0,4\}//')
+ _alg_num=$(key_get "$1" ALG_NUM)
+ _alg_numpad=$(printf "%03d" "$_alg_num")
+
+ _published=$(key_get "$1" PUBLISHED)
+ _active=$(key_get "$1" ACTIVE)
+ _retired=$(key_get "$1" RETIRED)
+ _revoked=$(key_get "$1" REVOKED)
+ _removed=$(key_get "$1" REMOVED)
+
+ _goal=$(key_get "$1" GOAL)
+ _state_dnskey=$(key_get "$1" STATE_DNSKEY)
+ _state_zrrsig=$(key_get "$1" STATE_ZRRSIG)
+ _state_krrsig=$(key_get "$1" STATE_KRRSIG)
+ _state_ds=$(key_get "$1" STATE_DS)
+
+ _base_file=$(key_get "$1" BASEFILE)
+ _key_file="${_base_file}.key"
+ _private_file="${_base_file}.private"
+ _state_file="${_base_file}.state"
+ _legacy=$(key_get "$1" LEGACY)
+ _private=$(key_get "$1" PRIVATE)
+
+ _published=$(key_get "$1" PUBLISHED)
+ _syncpublish=$(key_get "$1" SYNCPUBLISH)
+ _active=$(key_get "$1" ACTIVE)
+ _retired=$(key_get "$1" RETIRED)
+ _revoked=$(key_get "$1" REVOKED)
+ _removed=$(key_get "$1" REMOVED)
+
+ # Check timing metadata.
+ n=$((n+1))
+ echo_i "check key timing metadata for key $1 id ${_key_id} zone ${ZONE} ($n)"
+ ret=0
+
+ if [ "$_published" = "none" ]; then
+ grep "; Publish:" "${_key_file}" > /dev/null && _log_error "unexpected publish comment in ${_key_file}"
+ if [ "$_private" = "yes" ]; then
+ grep "Publish:" "${_private_file}" > /dev/null && _log_error "unexpected publish in ${_private_file}"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "Published: " "${_state_file}" > /dev/null && _log_error "unexpected publish in ${_state_file}"
+ fi
+ else
+ grep "; Publish: $_published" "${_key_file}" > /dev/null || _log_error "mismatch publish comment in ${_key_file} (expected ${_published})"
+ if [ "$_private" = "yes" ]; then
+ grep "Publish: $_published" "${_private_file}" > /dev/null || _log_error "mismatch publish in ${_private_file} (expected ${_published})"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "Published: $_published" "${_state_file}" > /dev/null || _log_error "mismatch publish in ${_state_file} (expected ${_published})"
+ fi
+ fi
+
+ if [ "$_syncpublish" = "none" ]; then
+ grep "; SyncPublish:" "${_key_file}" > /dev/null && _log_error "unexpected syncpublish comment in ${_key_file}"
+ if [ "$_private" = "yes" ]; then
+ grep "SyncPublish:" "${_private_file}" > /dev/null && _log_error "unexpected syncpublish in ${_private_file}"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "PublishCDS: " "${_state_file}" > /dev/null && _log_error "unexpected syncpublish in ${_state_file}"
+ fi
+ else
+ grep "; SyncPublish: $_syncpublish" "${_key_file}" > /dev/null || _log_error "mismatch syncpublish comment in ${_key_file} (expected ${_syncpublish})"
+ if [ "$_private" = "yes" ]; then
+ grep "SyncPublish: $_syncpublish" "${_private_file}" > /dev/null || _log_error "mismatch syncpublish in ${_private_file} (expected ${_syncpublish})"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "PublishCDS: $_syncpublish" "${_state_file}" > /dev/null || _log_error "mismatch syncpublish in ${_state_file} (expected ${_syncpublish})"
+ fi
+ fi
+
+ if [ "$_active" = "none" ]; then
+ grep "; Activate:" "${_key_file}" > /dev/null && _log_error "unexpected active comment in ${_key_file}"
+ if [ "$_private" = "yes" ]; then
+ grep "Activate:" "${_private_file}" > /dev/null && _log_error "unexpected active in ${_private_file}"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "Active: " "${_state_file}" > /dev/null && _log_error "unexpected active in ${_state_file}"
+ fi
+ else
+ grep "; Activate: $_active" "${_key_file}" > /dev/null || _log_error "mismatch active comment in ${_key_file} (expected ${_active})"
+ if [ "$_private" = "yes" ]; then
+ grep "Activate: $_active" "${_private_file}" > /dev/null || _log_error "mismatch active in ${_private_file} (expected ${_active})"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "Active: $_active" "${_state_file}" > /dev/null || _log_error "mismatch active in ${_state_file} (expected ${_active})"
+ fi
+ fi
+
+ if [ "$_retired" = "none" ]; then
+ grep "; Inactive:" "${_key_file}" > /dev/null && _log_error "unexpected retired comment in ${_key_file}"
+ if [ "$_private" = "yes" ]; then
+ grep "Inactive:" "${_private_file}" > /dev/null && _log_error "unexpected retired in ${_private_file}"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "Retired: " "${_state_file}" > /dev/null && _log_error "unexpected retired in ${_state_file}"
+ fi
+ else
+ grep "; Inactive: $_retired" "${_key_file}" > /dev/null || _log_error "mismatch retired comment in ${_key_file} (expected ${_retired})"
+ if [ "$_private" = "yes" ]; then
+ grep "Inactive: $_retired" "${_private_file}" > /dev/null || _log_error "mismatch retired in ${_private_file} (expected ${_retired})"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "Retired: $_retired" "${_state_file}" > /dev/null || _log_error "mismatch retired in ${_state_file} (expected ${_retired})"
+ fi
+ fi
+
+ if [ "$_revoked" = "none" ]; then
+ grep "; Revoke:" "${_key_file}" > /dev/null && _log_error "unexpected revoked comment in ${_key_file}"
+ if [ "$_private" = "yes" ]; then
+ grep "Revoke:" "${_private_file}" > /dev/null && _log_error "unexpected revoked in ${_private_file}"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "Revoked: " "${_state_file}" > /dev/null && _log_error "unexpected revoked in ${_state_file}"
+ fi
+ else
+ grep "; Revoke: $_revoked" "${_key_file}" > /dev/null || _log_error "mismatch revoked comment in ${_key_file} (expected ${_revoked})"
+ if [ "$_private" = "yes" ]; then
+ grep "Revoke: $_revoked" "${_private_file}" > /dev/null || _log_error "mismatch revoked in ${_private_file} (expected ${_revoked})"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "Revoked: $_revoked" "${_state_file}" > /dev/null || _log_error "mismatch revoked in ${_state_file} (expected ${_revoked})"
+ fi
+ fi
+
+ if [ "$_removed" = "none" ]; then
+ grep "; Delete:" "${_key_file}" > /dev/null && _log_error "unexpected removed comment in ${_key_file}"
+ if [ "$_private" = "yes" ]; then
+ grep "Delete:" "${_private_file}" > /dev/null && _log_error "unexpected removed in ${_private_file}"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "Removed: " "${_state_file}" > /dev/null && _log_error "unexpected removed in ${_state_file}"
+ fi
+ else
+ grep "; Delete: $_removed" "${_key_file}" > /dev/null || _log_error "mismatch removed comment in ${_key_file} (expected ${_removed})"
+ if [ "$_private" = "yes" ]; then
+ grep "Delete: $_removed" "${_private_file}" > /dev/null || _log_error "mismatch removed in ${_private_file} (expected ${_removed})"
+ fi
+ if [ "$_legacy" = "no" ]; then
+ grep "Removed: $_removed" "${_state_file}" > /dev/null || _log_error "mismatch removed in ${_state_file} (expected ${_removed})"
+ fi
+ fi
+
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+check_keytimes() {
+ # The script relies on Python to set keytimes.
+ if [ -x "$PYTHON" ]; then
+
+ if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
+ check_timingmetadata "KEY1"
+ fi
+ if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
+ check_timingmetadata "KEY2"
+ fi
+ if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
+ check_timingmetadata "KEY3"
+ fi
+ if [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
+ check_timingmetadata "KEY4"
+ fi
+ fi
+}
+
+# Check the key with key id $1 and see if it is unused.
+# This requires environment variables to be set.
+#
+# This will set the following environment variables for testing:
+# BASE_FILE="${_dir}/K${_zone}.+${_alg_numpad}+${_key_idpad}"
+# KEY_FILE="${BASE_FILE}.key"
+# PRIVATE_FILE="${BASE_FILE}.private"
+# STATE_FILE="${BASE_FILE}.state"
+# KEY_ID=$(echo $1 | sed 's/^0\{0,4\}//')
+key_unused() {
+ _dir=$DIR
+ _zone=$ZONE
+ _key_idpad=$1
+ _key_id=$(echo "$_key_idpad" | sed 's/^0\{0,4\}//')
+ _alg_num=$2
+ _alg_numpad=$(printf "%03d" "$_alg_num")
+
+ BASE_FILE="${_dir}/K${_zone}.+${_alg_numpad}+${_key_idpad}"
+ KEY_FILE="${BASE_FILE}.key"
+ PRIVATE_FILE="${BASE_FILE}.private"
+ STATE_FILE="${BASE_FILE}.state"
+ KEY_ID="${_key_id}"
+
+ test $_log -eq 1 && echo_i "key unused $KEY_ID?"
+
+ # Check file existence.
+ [ -s "$KEY_FILE" ] || ret=1
+ [ -s "$PRIVATE_FILE" ] || ret=1
+ [ -s "$STATE_FILE" ] || ret=1
+ [ "$ret" -eq 0 ] || return 0
+
+ # Treat keys that have been removed from the zone as unused.
+ _check_removed=1
+ grep "; Created:" "$KEY_FILE" > created.key-${KEY_ID}.test${n} || _check_removed=0
+ grep "; Delete:" "$KEY_FILE" > unused.key-${KEY_ID}.test${n} || _check_removed=0
+ if [ "$_check_removed" -eq 1 ]; then
+ _created=$(awk '{print $3}' < created.key-${KEY_ID}.test${n})
+ _removed=$(awk '{print $3}' < unused.key-${KEY_ID}.test${n})
+ [ "$_removed" -le "$_created" ] && return
+ fi
+
+ # If no timing metadata is set, this key is unused.
+ grep "; Publish:" "$KEY_FILE" > /dev/null && _log_error "unexpected publish comment in $KEY_FILE"
+ grep "; Activate:" "$KEY_FILE" > /dev/null && _log_error "unexpected active comment in $KEY_FILE"
+ grep "; Inactive:" "$KEY_FILE" > /dev/null && _log_error "unexpected retired comment in $KEY_FILE"
+ grep "; Revoke:" "$KEY_FILE" > /dev/null && _log_error "unexpected revoked comment in $KEY_FILE"
+ grep "; Delete:" "$KEY_FILE" > /dev/null && _log_error "unexpected removed comment in $KEY_FILE"
+
+ grep "Publish:" "$PRIVATE_FILE" > /dev/null && _log_error "unexpected publish in $PRIVATE_FILE"
+ grep "Activate:" "$PRIVATE_FILE" > /dev/null && _log_error "unexpected active in $PRIVATE_FILE"
+ grep "Inactive:" "$PRIVATE_FILE" > /dev/null && _log_error "unexpected retired in $PRIVATE_FILE"
+ grep "Revoke:" "$PRIVATE_FILE" > /dev/null && _log_error "unexpected revoked in $PRIVATE_FILE"
+ grep "Delete:" "$PRIVATE_FILE" > /dev/null && _log_error "unexpected removed in $PRIVATE_FILE"
+
+ grep "Published: " "$STATE_FILE" > /dev/null && _log_error "unexpected publish in $STATE_FILE"
+ grep "Active: " "$STATE_FILE" > /dev/null && _log_error "unexpected active in $STATE_FILE"
+ grep "Retired: " "$STATE_FILE" > /dev/null && _log_error "unexpected retired in $STATE_FILE"
+ grep "Revoked: " "$STATE_FILE" > /dev/null && _log_error "unexpected revoked in $STATE_FILE"
+ grep "Removed: " "$STATE_FILE" > /dev/null && _log_error "unexpected removed in $STATE_FILE"
+
+ return 0
+}
+
+# Test: dnssec-verify zone $1.
+dnssec_verify()
+{
+ n=$((n+1))
+ echo_i "dnssec-verify zone ${ZONE} ($n)"
+ ret=0
+ _dig_with_opts "$ZONE" "@${SERVER}" AXFR > dig.out.axfr.test$n || _log_error "dig ${ZONE} AXFR failed"
+ $VERIFY -z -o "$ZONE" dig.out.axfr.test$n > verify.out.$ZONE.test$n || _log_error "dnssec verify zone $ZONE failed"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+# Wait for the zone to be signed.
+# The apex NSEC record indicates that it is signed.
+_wait_for_nsec() {
+ _dig_with_opts "@${SERVER}" "$ZONE" NSEC > "dig.out.nsec.test$n" || return 1
+ grep "NS SOA" "dig.out.nsec.test$n" > /dev/null || return 1
+ grep "${ZONE}\..*IN.*RRSIG" "dig.out.nsec.test$n" > /dev/null || return 1
+ return 0
+}
+wait_for_nsec() {
+ n=$((n+1))
+ ret=0
+ echo_i "wait for ${ZONE} to be signed ($n)"
+ retry_quiet 10 _wait_for_nsec || _log_error "wait for ${ZONE} to be signed failed"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+check_numkeys() {
+ _numkeys=$(get_keyids "$DIR" "$ZONE" | wc -l)
+ test "$_numkeys" -eq "$NUM_KEYS" || return 1
+ return 0
+}
+
+_check_keys() {
+ ret=0
+ _ret=0
+
+ # Clear key ids.
+ key_set KEY1 ID "no"
+ key_set KEY2 ID "no"
+ key_set KEY3 ID "no"
+ key_set KEY4 ID "no"
+
+ # Check key files.
+ _ids=$(get_keyids "$DIR" "$ZONE")
+ for _id in $_ids; do
+ # There are multiple key files with the same algorithm.
+ # Check them until a match is found.
+ ret=0
+ echo_i "check key id $_id"
+
+ if [ "no" = "$(key_get KEY1 ID)" ] && [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
+ ret=0
+ check_key "KEY1" "$_id"
+ test "$ret" -eq 0 && key_save KEY1 && continue
+ fi
+ if [ "no" = "$(key_get KEY2 ID)" ] && [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
+ ret=0
+ check_key "KEY2" "$_id"
+ test "$ret" -eq 0 && key_save KEY2 && continue
+ fi
+ if [ "no" = "$(key_get KEY3 ID)" ] && [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
+ ret=0
+ check_key "KEY3" "$_id"
+ test "$ret" -eq 0 && key_save KEY3 && continue
+ fi
+ if [ "no" = "$(key_get KEY4 ID)" ] && [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
+ ret=0
+ check_key "KEY4" "$_id"
+ test "$ret" -eq 0 && key_save KEY4 && continue
+ fi
+
+ # This may be an unused key. Assume algorithm of KEY1.
+ ret=0 && key_unused "$_id" "$(key_get KEY1 ALG_NUM)"
+ test "$ret" -eq 0 && continue
+
+ # If ret is still non-zero, none of the files matched.
+ echo_i "failed"
+ _ret=1
+ done
+
+ return $_ret
+}
+
+# Check keys for a configured zone. This verifies:
+# 1. The right number of keys exist in the key pool ($1).
+# 2. The right number of keys is active. Checks KEY1, KEY2, KEY3, and KEY4.
+#
+# It is expected that KEY1, KEY2, KEY3, and KEY4 arrays are set correctly.
+# Found key identifiers are stored in the right key array.
+check_keys() {
+ n=$((n+1))
+ echo_i "check keys are created for zone ${ZONE} ($n)"
+ ret=0
+
+ echo_i "check number of keys for zone ${ZONE} in dir ${DIR} ($n)"
+ retry_quiet 10 check_numkeys || ret=1
+ if [ $ret -ne 0 ]; then
+ _numkeys=$(get_keyids "$DIR" "$ZONE" | wc -l)
+ _log_error "bad number of key files ($_numkeys) for zone $ZONE (expected $NUM_KEYS)"
+ status=$((status+ret))
+ fi
+
+ # Temporarily don't log errors because we are searching multiple files.
+ disable_logerror
+
+ retry_quiet 3 _check_keys || ret=1
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+ # Turn error logs on again.
+ enable_logerror
+
+ ret=0
+ if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
+ echo_i "KEY1 ID $(key_get KEY1 ID)"
+ test "no" = "$(key_get KEY1 ID)" && _log_error "No KEY1 found for zone ${ZONE}"
+ fi
+ if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
+ echo_i "KEY2 ID $(key_get KEY2 ID)"
+ test "no" = "$(key_get KEY2 ID)" && _log_error "No KEY2 found for zone ${ZONE}"
+ fi
+ if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
+ echo_i "KEY3 ID $(key_get KEY3 ID)"
+ test "no" = "$(key_get KEY3 ID)" && _log_error "No KEY3 found for zone ${ZONE}"
+ fi
+ if [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
+ echo_i "KEY4 ID $(key_get KEY4 ID)"
+ test "no" = "$(key_get KEY4 ID)" && _log_error "No KEY4 found for zone ${ZONE}"
+ fi
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+# Call rndc dnssec -status on server $1 for zone $3 in view $4 with policy $2
+# and check output. This is a loose verification, it just tests if the right
+# policy name is returned, and if all expected keys are listed. The rndc
+# dnssec -status output also lists whether a key is published,
+# used for signing, is retired, or is removed, and if not when
+# it is scheduled to do so, and it shows the states for the various
+# DNSSEC records.
+check_dnssecstatus() {
+ _server=$1
+ _policy=$2
+ _zone=$3
+ _view=$4
+
+ n=$((n+1))
+ echo_i "check rndc dnssec -status output for ${_zone} (policy: $_policy) ($n)"
+ ret=0
+
+ _rndccmd $_server dnssec -status $_zone in $_view > rndc.dnssec.status.out.$_zone.$n || _log_error "rndc dnssec -status zone ${_zone} failed"
+
+ if [ "$_policy" = "none" ]; then
+ grep "Zone does not have dnssec-policy" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "bad dnssec status for unsigned zone ${_zone}"
+ else
+ grep "dnssec-policy: ${_policy}" rndc.dnssec.status.out.$_zone.$n > /dev/null || _log_error "bad dnssec status for signed zone ${_zone}"
+ if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
+ grep "key: $(key_get KEY1 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || _log_error "missing key $(key_get KEY1 ID) from dnssec status"
+ fi
+ if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
+ grep "key: $(key_get KEY2 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || _log_error "missing key $(key_get KEY2 ID) from dnssec status"
+ fi
+ if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
+ grep "key: $(key_get KEY3 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || _log_error "missing key $(key_get KEY3 ID) from dnssec status"
+ fi
+ if [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
+ grep "key: $(key_get KEY4 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || _log_error "missing key $(key_get KEY4 ID) from dnssec status"
+ fi
+ fi
+
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+# Call rndc zonestatus on server $1 for zone $2 in view $3 and check output if
+# inline-signing is enabled.
+check_inlinesigning() {
+ _server=$1
+ _zone=$2
+ _view=$3
+
+ _rndccmd $_server zonestatus $_zone in $_view > rndc.zonestatus.out.$_zone.$n || return 1
+ grep "inline signing: yes" rndc.zonestatus.out.$_zone.$n > /dev/null || return 1
+}
+
+# Call rndc zonestatus on server $1 for zone $2 in view $3 and check output if
+# the zone is dynamic.
+check_isdynamic() {
+ _server=$1
+ _zone=$2
+ _view=$3
+
+ _rndccmd $_server zonestatus $_zone in $_view > rndc.zonestatus.out.$_zone.$n || return 1
+ grep "dynamic: yes" rndc.zonestatus.out.$_zone.$n > /dev/null || return 1
+}
+
+# Check if RRset of type $1 in file $2 is signed with the right keys.
+# The right keys are the ones that expect a signature and matches the role $3.
+_check_signatures() {
+ _qtype=$1
+ _file=$2
+ _role=$3
+
+ numsigs=0
+
+ if [ "$_role" = "KSK" ]; then
+ _expect_type=EXPECT_KRRSIG
+ elif [ "$_role" = "ZSK" ]; then
+ _expect_type=EXPECT_ZRRSIG
+ fi
+
+ if [ "$(key_get KEY1 "$_expect_type")" = "yes" ] && [ "$(key_get KEY1 "$_role")" = "yes" ]; then
+ get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY1 ID)$" > /dev/null || return 1
+ numsigs=$((numsigs+1))
+ elif [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
+ get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY1 ID)$" > /dev/null && return 1
+ fi
+
+ if [ "$(key_get KEY2 "$_expect_type")" = "yes" ] && [ "$(key_get KEY2 "$_role")" = "yes" ]; then
+ get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY2 ID)$" > /dev/null || return 1
+ numsigs=$((numsigs+1))
+ elif [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
+ get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY2 ID)$" > /dev/null && return 1
+ fi
+
+ if [ "$(key_get KEY3 "$_expect_type")" = "yes" ] && [ "$(key_get KEY3 "$_role")" = "yes" ]; then
+ get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY3 ID)$" > /dev/null || return 1
+ numsigs=$((numsigs+1))
+ elif [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
+ get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY3 ID)$" > /dev/null && return 1
+ fi
+
+ if [ "$(key_get KEY4 "$_expect_type")" = "yes" ] && [ "$(key_get KEY4 "$_role")" = "yes" ]; then
+ get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY4 ID)$" > /dev/null || return 1
+ numsigs=$((numsigs+1))
+ elif [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
+ get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY4 ID)$" > /dev/null && return 1
+ fi
+
+ lines=$(get_keys_which_signed "${_qtype}" "${_file}" | wc -l)
+ test "$lines" -eq "$numsigs" || echo_i "bad number of signatures for $_qtype (got $lines, expected $numsigs)"
+ test "$lines" -eq "$numsigs" || return 1
+
+ return 0
+}
+check_signatures() {
+ retry_quiet 3 _check_signatures $1 $2 $3 || _log_error "RRset $1 in zone $ZONE incorrectly signed"
+}
+
+response_has_cds_for_key() (
+ awk -v zone="${ZONE%%.}." \
+ -v ttl="${DNSKEY_TTL}" \
+ -v qtype="CDS" \
+ -v keyid="$(key_get "${1}" ID)" \
+ -v keyalg="$(key_get "${1}" ALG_NUM)" \
+ -v hashalg="2" \
+ 'BEGIN { ret=1; }
+ $1 == zone && $2 == ttl && $4 == qtype && $5 == keyid && $6 == keyalg && $7 == hashalg { ret=0; exit; }
+ END { exit ret; }' \
+ "$2"
+)
+
+response_has_cdnskey_for_key() (
+
+ awk -v zone="${ZONE%%.}." \
+ -v ttl="${DNSKEY_TTL}" \
+ -v qtype="CDNSKEY" \
+ -v flags="$(key_get "${1}" FLAGS)" \
+ -v keyalg="$(key_get "${1}" ALG_NUM)" \
+ 'BEGIN { ret=1; }
+ $1 == zone && $2 == ttl && $4 == qtype && $5 == flags && $7 == keyalg { ret=0; exit; }
+ END { exit ret; }' \
+ "$2"
+)
+
+# Test CDS and CDNSKEY publication.
+check_cds() {
+
+ n=$((n+1))
+ echo_i "check CDS and CDNSKEY rrset are signed correctly for zone ${ZONE} ($n)"
+ ret=0
+
+ _checksig=0
+
+ _dig_with_opts "$ZONE" "@${SERVER}" "CDS" > "dig.out.$DIR.test$n.cds" || _log_error "dig ${ZONE} CDS failed"
+ grep "status: NOERROR" "dig.out.$DIR.test$n.cds" > /dev/null || _log_error "mismatch status in DNS response"
+
+ _dig_with_opts "$ZONE" "@${SERVER}" "CDNSKEY" > "dig.out.$DIR.test$n.cdnskey" || _log_error "dig ${ZONE} CDNSKEY failed"
+ grep "status: NOERROR" "dig.out.$DIR.test$n.cdnskey" > /dev/null || _log_error "mismatch status in DNS response"
+
+ if [ "$CDS_DELETE" = "no" ]; then
+ grep "CDS.*0 0 0 00" "dig.out.$DIR.test$n.cds" > /dev/null && _log_error "unexpected CDS DELETE record in DNS response"
+ grep "CDNSKEY.*0 3 0 AA==" "dig.out.$DIR.test$n.cdnskey" > /dev/null && _log_error "unexpected CDNSKEY DELETE record in DNS response"
+ else
+ grep "CDS.*0 0 0 00" "dig.out.$DIR.test$n.cds" > /dev/null || _log_error "missing CDS DELETE record in DNS response"
+ grep "CDNSKEY.*0 3 0 AA==" "dig.out.$DIR.test$n.cdnskey" > /dev/null || _log_error "missing CDNSKEY DELETE record in DNS response"
+ _checksig=1
+ fi
+
+ if [ "$(key_get KEY1 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY1 STATE_DS)" = "omnipresent" ]; then
+ response_has_cds_for_key KEY1 "dig.out.$DIR.test$n.cds" || _log_error "missing CDS record in response for key $(key_get KEY1 ID)"
+ response_has_cdnskey_for_key KEY1 "dig.out.$DIR.test$n.cdnskey" || _log_error "missing CDNSKEY record in response for key $(key_get KEY1 ID)"
+ _checksig=1
+ elif [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
+ response_has_cds_for_key KEY1 "dig.out.$DIR.test$n.cds" && _log_error "unexpected CDS record in response for key $(key_get KEY1 ID)"
+ # KEY1 should not have an associated CDNSKEY, but there may be
+ # one for another key. Since the CDNSKEY has no field for key
+ # id, it is hard to check what key the CDNSKEY may belong to
+ # so let's skip this check for now.
+ fi
+
+ if [ "$(key_get KEY2 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY2 STATE_DS)" = "omnipresent" ]; then
+ response_has_cds_for_key KEY2 "dig.out.$DIR.test$n.cds" || _log_error "missing CDS record in response for key $(key_get KEY2 ID)"
+ response_has_cdnskey_for_key KEY2 "dig.out.$DIR.test$n.cdnskey" || _log_error "missing CDNSKEY record in response for key $(key_get KEY2 ID)"
+ _checksig=1
+ elif [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
+ response_has_cds_for_key KEY2 "dig.out.$DIR.test$n.cds" && _log_error "unexpected CDS record in response for key $(key_get KEY2 ID)"
+ # KEY2 should not have an associated CDNSKEY, but there may be
+ # one for another key. Since the CDNSKEY has no field for key
+ # id, it is hard to check what key the CDNSKEY may belong to
+ # so let's skip this check for now.
+ fi
+
+ if [ "$(key_get KEY3 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY3 STATE_DS)" = "omnipresent" ]; then
+ response_has_cds_for_key KEY3 "dig.out.$DIR.test$n.cds" || _log_error "missing CDS record in response for key $(key_get KEY3 ID)"
+ response_has_cdnskey_for_key KEY3 "dig.out.$DIR.test$n.cdnskey" || _log_error "missing CDNSKEY record in response for key $(key_get KEY3 ID)"
+ _checksig=1
+ elif [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
+ response_has_cds_for_key KEY3 "dig.out.$DIR.test$n.cds" && _log_error "unexpected CDS record in response for key $(key_get KEY3 ID)"
+ # KEY3 should not have an associated CDNSKEY, but there may be
+ # one for another key. Since the CDNSKEY has no field for key
+ # id, it is hard to check what key the CDNSKEY may belong to
+ # so let's skip this check for now.
+ fi
+
+ if [ "$(key_get KEY4 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY4 STATE_DS)" = "omnipresent" ]; then
+ response_has_cds_for_key KEY4 "dig.out.$DIR.test$n.cds" || _log_error "missing CDS record in response for key $(key_get KEY4 ID)"
+ response_has_cdnskey_for_key KEY4 "dig.out.$DIR.test$n.cdnskey" || _log_error "missing CDNSKEY record in response for key $(key_get KEY4 ID)"
+ _checksig=1
+ elif [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
+ response_has_cds_for_key KEY4 "dig.out.$DIR.test$n.cds" && _log_error "unexpected CDS record in response for key $(key_get KEY4 ID)"
+ # KEY4 should not have an associated CDNSKEY, but there may be
+ # one for another key. Since the CDNSKEY has no field for key
+ # id, it is hard to check what key the CDNSKEY may belong to
+ # so let's skip this check for now.
+ fi
+
+ test "$_checksig" -eq 0 || check_signatures "CDS" "dig.out.$DIR.test$n.cds" "KSK"
+ test "$_checksig" -eq 0 || check_signatures "CDNSKEY" "dig.out.$DIR.test$n.cdnskey" "KSK"
+
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+_find_dnskey() {
+ _owner="${ZONE}."
+ _alg="$(key_get $1 ALG_NUM)"
+ _flags="$(key_get $1 FLAGS)"
+ _key_file="$(key_get $1 BASEFILE).key"
+
+ awk '$1 == "'"$_owner"'" && $2 == "'"$DNSKEY_TTL"'" && $3 == "IN" && $4 == "DNSKEY" && $5 == "'"$_flags"'" && $6 == "3" && $7 == "'"$_alg"'" { print $8 }' < "$_key_file"
+}
+
+
+# Test DNSKEY query.
+_check_apex_dnskey() {
+ _dig_with_opts "$ZONE" "@${SERVER}" "DNSKEY" > "dig.out.$DIR.test$n" || return 1
+ grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || return 1
+
+ _checksig=0
+
+ if [ "$(key_get KEY1 STATE_DNSKEY)" = "rumoured" ] || [ "$(key_get KEY1 STATE_DNSKEY)" = "omnipresent" ]; then
+ _pubkey=$(_find_dnskey KEY1)
+ test -z "$_pubkey" && return 1
+ grep -F "$_pubkey" "dig.out.$DIR.test$n" > /dev/null || return 1
+ _checksig=1
+ elif [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
+ _pubkey=$(_find_dnskey KEY1)
+ test -z "$_pubkey" && return 1
+ grep -F "$_pubkey" "dig.out.$DIR.test$n" > /dev/null && return 1
+ fi
+
+ if [ "$(key_get KEY2 STATE_DNSKEY)" = "rumoured" ] || [ "$(key_get KEY2 STATE_DNSKEY)" = "omnipresent" ]; then
+ _pubkey=$(_find_dnskey KEY2)
+ test -z "$_pubkey" && return 1
+ grep -F "$_pubkey" "dig.out.$DIR.test$n" > /dev/null || return 1
+ _checksig=1
+ elif [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
+ _pubkey=$(_find_dnskey KEY2)
+ test -z "$_pubkey" && return 1
+ grep -F "$_pubkey" "dig.out.$DIR.test$n" > /dev/null && return 1
+ fi
+
+ if [ "$(key_get KEY3 STATE_DNSKEY)" = "rumoured" ] || [ "$(key_get KEY3 STATE_DNSKEY)" = "omnipresent" ]; then
+ _pubkey=$(_find_dnskey KEY3)
+ test -z "$_pubkey" && return 1
+ grep -F "$_pubkey" "dig.out.$DIR.test$n" > /dev/null || return 1
+ _checksig=1
+ elif [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
+ _pubkey=$(_find_dnskey KEY3)
+ test -z "$_pubkey" && return 1
+ grep -F "$_pubkey" "dig.out.$DIR.test$n" > /dev/null && return 1
+ fi
+
+ if [ "$(key_get KEY4 STATE_DNSKEY)" = "rumoured" ] || [ "$(key_get KEY4 STATE_DNSKEY)" = "omnipresent" ]; then
+ _pubkey=$(_find_dnskey KEY4)
+ test -z "$_pubkey" && return 1
+ grep -F "$_pubkey" "dig.out.$DIR.test$n" > /dev/null || return 1
+ _checksig=1
+ elif [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
+ _pubkey=$(_find_dnskey KEY4)
+ test -z "$_pubkey" && return 1
+ grep -F "$_pubkey" "dig.out.$DIR.test$n" > /dev/null && return 1
+ fi
+
+ test "$_checksig" -eq 0 && return 0
+
+ _check_signatures "DNSKEY" "dig.out.$DIR.test$n" "KSK" || return 1
+
+ return 0
+}
+
+# Test the apex of a configured zone. This checks that the SOA and DNSKEY
+# RRsets are signed correctly and with the appropriate keys.
+check_apex() {
+
+ # Test DNSKEY query.
+ n=$((n+1))
+ echo_i "check DNSKEY rrset is signed correctly for zone ${ZONE} ($n)"
+ ret=0
+ retry_quiet 10 _check_apex_dnskey || ret=1
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+ # We retry the DNSKEY query for at most ten seconds to avoid test
+ # failures due to timing issues. If the DNSKEY query check passes this
+ # means the zone is resigned and further apex checks (SOA, CDS, CDNSKEY)
+ # don't need to be retried quietly.
+
+ # Test SOA query.
+ n=$((n+1))
+ echo_i "check SOA rrset is signed correctly for zone ${ZONE} ($n)"
+ ret=0
+ _dig_with_opts "$ZONE" "@${SERVER}" "SOA" > "dig.out.$DIR.test$n" || _log_error "dig ${ZONE} SOA failed"
+ grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || _log_error "mismatch status in DNS response"
+ grep "${ZONE}\..*${DEFAULT_TTL}.*IN.*SOA.*" "dig.out.$DIR.test$n" > /dev/null || _log_error "missing SOA record in response"
+ check_signatures "SOA" "dig.out.$DIR.test$n" "ZSK"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+ # Test CDS and CDNSKEY publication.
+ check_cds
+}
+
+# Test an RRset below the apex and verify it is signed correctly.
+check_subdomain() {
+ _qtype="A"
+ n=$((n+1))
+ echo_i "check ${_qtype} a.${ZONE} rrset is signed correctly for zone ${ZONE} ($n)"
+ ret=0
+ _dig_with_opts "a.$ZONE" "@${SERVER}" $_qtype > "dig.out.$DIR.test$n" || _log_error "dig a.${ZONE} ${_qtype} failed"
+ grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || _log_error "mismatch status in DNS response"
+ grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*${_qtype}.*10\.0\.0\.1" "dig.out.$DIR.test$n" > /dev/null || _log_error "missing a.${ZONE} ${_qtype} record in response"
+ lines=$(get_keys_which_signed $_qtype "dig.out.$DIR.test$n" | wc -l)
+ check_signatures $_qtype "dig.out.$DIR.test$n" "ZSK"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+# Check if "CDS/CDNSKEY Published" is logged.
+check_cdslog() {
+ _dir=$1
+ _zone=$2
+ _key=$3
+
+ _alg=$(key_get $_key ALG_STR)
+ _id=$(key_get $_key ID)
+
+ n=$((n+1))
+ echo_i "check CDS/CDNSKEY publication is logged in ${_dir}/named.run for key ${_zone}/${_alg}/${_id} ($n)"
+ ret=0
+
+ grep "CDS for key ${_zone}/${_alg}/${_id} is now published" "${_dir}/named.run" > /dev/null || ret=1
+ grep "CDNSKEY for key ${_zone}/${_alg}/${_id} is now published" "${_dir}/named.run" > /dev/null || ret=1
+
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+# Tell named that the DS for the key in given zone has been seen in the
+# parent (this does not actually has to be true, we just issue the command
+# to make named believe it can continue with the rollover).
+rndc_checkds() {
+ _server=$1
+ _dir=$2
+ _key=$3
+ _when=$4
+ _what=$5
+ _zone=$6
+ _view=$7
+
+ _keycmd=""
+ if [ "${_key}" != "-" ]; then
+ _keyid=$(key_get $_key ID)
+ _keycmd=" -key ${_keyid}"
+ fi
+
+ _whencmd=""
+ if [ "${_when}" != "now" ]; then
+ _whencmd=" -when ${_when}"
+ fi
+
+ n=$((n+1))
+ echo_i "calling rndc dnssec -checkds${_keycmd}${_whencmd} ${_what} zone ${_zone} in ${_view} ($n)"
+ ret=0
+
+ _rndccmd $_server dnssec -checkds $_keycmd $_whencmd $_what $_zone in $_view > rndc.dnssec.checkds.out.$_zone.$n || _log_error "rndc dnssec -checkds${_keycmd}${_whencmd} ${_what} zone ${_zone} failed"
+
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+# Tell named to schedule a key rollover.
+rndc_rollover() {
+ _server=$1
+ _dir=$2
+ _keyid=$3
+ _when=$4
+ _zone=$5
+ _view=$6
+
+ _whencmd=""
+ if [ "${_when}" != "now" ]; then
+ _whencmd="-when ${_when}"
+ fi
+
+ n=$((n+1))
+ echo_i "calling rndc dnssec -rollover key ${_keyid} ${_whencmd} zone ${_zone} ($n)"
+ ret=0
+
+ _rndccmd $_server dnssec -rollover -key $_keyid $_whencmd $_zone in $_view > rndc.dnssec.rollover.out.$_zone.$n || _log_error "rndc dnssec -rollover (key ${_keyid} when ${_when}) zone ${_zone} failed"
+
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
diff --git a/bin/tests/system/kasp/README b/bin/tests/system/kasp/README
new file mode 100644
index 0000000..96b0ef7
--- /dev/null
+++ b/bin/tests/system/kasp/README
@@ -0,0 +1,23 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+The test setup for the KASP tests.
+
+ns1 is reserved for the root server.
+
+ns2 is running primary service for ns3.
+
+ns3 is an authoritative server for the various test domains.
+
+ns4 and ns5 are authoritative servers for various test domains related to views.
+
+ns6 is an authoritative server that tests changes in dnssec-policy (algorithm
+rollover).
diff --git a/bin/tests/system/kasp/clean.sh b/bin/tests/system/kasp/clean.sh
new file mode 100644
index 0000000..db264c2
--- /dev/null
+++ b/bin/tests/system/kasp/clean.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f ./keygen.*
+rm -f ./K*.private ./K*.key ./K*.state ./K*.cmp
+rm -rf ./keys/
+rm -f dig.out* rrsig.out.* keyevent.out.* verify.out.* zone.out.*
+rm -f ns*/named.conf ns*/named.memstats ns*/named.run*
+rm -f ns*/named-fips.conf
+rm -f ns*/policies/*.conf
+rm -f ns*/*.jnl ns*/*.jbk
+rm -f ns*/K*.private ns*/K*.key ns*/K*.state
+rm -f ns*/dsset-* ns*/*.db ns*/*.db.signed
+rm -f ns*/keygen.out.* ns*/settime.out.* ns*/signer.out.*
+rm -f ns*/managed-keys.bind
+rm -f ns*/*.mkeys
+rm -f ns*/zones ns*/*.db.infile
+rm -f ns*/*.zsk1 ns*/*.zsk2
+rm -f ns3/legacy-keys.*
+rm -f *.created published.test* retired.test*
+rm -f rndc.dnssec.*.out.* rndc.zonestatus.out.*
+rm -f python.out.*
+rm -f *-supported.file
+rm -f created.key-* unused.key-*
diff --git a/bin/tests/system/kasp/kasp.conf b/bin/tests/system/kasp/kasp.conf
new file mode 100644
index 0000000..e7a2eab
--- /dev/null
+++ b/bin/tests/system/kasp/kasp.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * This is just a random selection of configuration options.
+ */
+
+dnssec-policy "kasp" {
+ dnskey-ttl 200;
+
+ keys {
+ csk key-directory lifetime P1Y algorithm 13;
+ ksk key-directory lifetime P1Y algorithm 8;
+ zsk key-directory lifetime P30D algorithm 8 2048;
+ zsk key-directory lifetime P6M algorithm 8 3072;
+ };
+};
diff --git a/bin/tests/system/kasp/ns2/named.conf.in b/bin/tests/system/kasp/ns2/named.conf.in
new file mode 100644
index 0000000..bdbacc2
--- /dev/null
+++ b/bin/tests/system/kasp/ns2/named.conf.in
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ allow-transfer { any; };
+ recursion no;
+ dnssec-policy "none";
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+/* Inherit dnssec-policy (which is none) */
+
+zone "unsigned.tld" {
+ type primary;
+ file "unsigned.tld.db";
+};
+
+/* Override dnssec-policy */
+
+zone "signed.tld" {
+ type primary;
+ file "signed.tld.db";
+ dnssec-policy "default";
+ inline-signing yes;
+};
+
+/* Primary service for ns3 */
+
+zone "secondary.kasp" {
+ type primary;
+ file "secondary.kasp.db";
+ allow-transfer { 10.53.0.3; };
+ notify yes;
+};
diff --git a/bin/tests/system/kasp/ns2/secondary.kasp.db.in b/bin/tests/system/kasp/ns2/secondary.kasp.db.in
new file mode 100644
index 0000000..3c8d124
--- /dev/null
+++ b/bin/tests/system/kasp/ns2/secondary.kasp.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA secondary.kasp. hostmaster.kasp. (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+
diff --git a/bin/tests/system/kasp/ns2/secondary.kasp.db.in2 b/bin/tests/system/kasp/ns2/secondary.kasp.db.in2
new file mode 100644
index 0000000..9289831
--- /dev/null
+++ b/bin/tests/system/kasp/ns2/secondary.kasp.db.in2
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA secondary.kasp. hostmaster.kasp. (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.11
+b A 10.0.0.2
+c A 10.0.0.3
+d A 10.0.0.4
+
diff --git a/bin/tests/system/kasp/ns2/setup.sh b/bin/tests/system/kasp/ns2/setup.sh
new file mode 100644
index 0000000..cdf0f26
--- /dev/null
+++ b/bin/tests/system/kasp/ns2/setup.sh
@@ -0,0 +1,35 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns2/setup.sh"
+
+zone="secondary.kasp"
+echo_i "setting up zone: $zone"
+zonefile="${zone}.db"
+infile="${zonefile}.in"
+cp $infile $zonefile
+
+zone="signed.tld"
+echo_i "setting up zone: $zone"
+zonefile="${zone}.db"
+infile="template.tld.db.in"
+cp $infile $zonefile
+
+zone="unsigned.tld"
+echo_i "setting up zone: $zone"
+zonefile="${zone}.db"
+infile="template.tld.db.in"
+cp $infile $zonefile
diff --git a/bin/tests/system/kasp/ns2/template.tld.db.in b/bin/tests/system/kasp/ns2/template.tld.db.in
new file mode 100644
index 0000000..400dc34
--- /dev/null
+++ b/bin/tests/system/kasp/ns2/template.tld.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA secondary.kasp. hostmaster.kasp. (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns2
+ns2 A 10.53.0.2
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+
diff --git a/bin/tests/system/kasp/ns3/ed25519.conf b/bin/tests/system/kasp/ns3/ed25519.conf
new file mode 100644
index 0000000..999fa2f
--- /dev/null
+++ b/bin/tests/system/kasp/ns3/ed25519.conf
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "ed25519" {
+ dnskey-ttl 1234;
+
+ keys {
+ ksk key-directory lifetime P10Y algorithm 15;
+ zsk key-directory lifetime P5Y algorithm 15;
+ zsk key-directory lifetime P1Y algorithm 15 256;
+ };
+};
+
+zone "ed25519.kasp" {
+ type primary;
+ file "ed25519.kasp.db";
+ inline-signing yes;
+ dnssec-policy "ed25519";
+};
diff --git a/bin/tests/system/kasp/ns3/ed448.conf b/bin/tests/system/kasp/ns3/ed448.conf
new file mode 100644
index 0000000..e9c8312
--- /dev/null
+++ b/bin/tests/system/kasp/ns3/ed448.conf
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "ed448" {
+ dnskey-ttl 1234;
+
+ keys {
+ ksk key-directory lifetime P10Y algorithm 16;
+ zsk key-directory lifetime P5Y algorithm 16;
+ zsk key-directory lifetime P1Y algorithm 16 456;
+ };
+};
+
+zone "ed448.kasp" {
+ type primary;
+ file "ed448.kasp.db";
+ inline-signing yes;
+ dnssec-policy "ed448";
+};
diff --git a/bin/tests/system/kasp/ns3/named-fips.conf.in b/bin/tests/system/kasp/ns3/named-fips.conf.in
new file mode 100644
index 0000000..a6e8b3a
--- /dev/null
+++ b/bin/tests/system/kasp/ns3/named-fips.conf.in
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+include "policies/kasp.conf";
+include "policies/autosign.conf";
+
+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; };
+ allow-transfer { any; };
+ recursion no;
+ dnssec-policy "rsasha256";
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+/* Zones that are getting initially signed */
+
+/* The default case: No keys created, using default policy. */
+zone "default.kasp" {
+ type primary;
+ file "default.kasp.db";
+ inline-signing yes;
+ dnssec-policy "default";
+};
+
+/* checkds: Zone with one KSK. */
+zone "checkds-ksk.kasp" {
+ type primary;
+ file "checkds-ksk.kasp.db";
+ inline-signing yes;
+ dnssec-policy "checkds-ksk";
+};
+
+/* checkds: Zone with two KSKs. */
+zone "checkds-doubleksk.kasp" {
+ type primary;
+ file "checkds-doubleksk.kasp.db";
+ inline-signing yes;
+ dnssec-policy "checkds-doubleksk";
+};
+
+/* checkds: Zone with one CSK. */
+zone "checkds-csk.kasp" {
+ type primary;
+ file "checkds-csk.kasp.db";
+ inline-signing yes;
+ dnssec-policy "checkds-csk";
+};
+
+/* Key lifetime unlimited. */
+zone "unlimited.kasp" {
+ type primary;
+ file "unlimited.kasp.db";
+ inline-signing yes;
+ dnssec-policy "unlimited";
+};
+
+/* Manual rollover. */
+zone "manual-rollover.kasp" {
+ type primary;
+ file "manual-rollover.kasp.db";
+ inline-signing yes;
+ dnssec-policy "manual-rollover";
+};
+
+/* A zone that inherits dnssec-policy. */
+zone "inherit.kasp" {
+ type primary;
+ inline-signing yes;
+ file "inherit.kasp.db";
+};
+
+/* A zone that overrides dnssec-policy. */
+zone "unsigned.kasp" {
+ type primary;
+ file "unsigned.kasp.db";
+ inline-signing yes;
+ dnssec-policy "none";
+};
+
+/* A zone that is initially set to insecure. */
+zone "insecure.kasp" {
+ type primary;
+ file "insecure.kasp.db";
+ inline-signing yes;
+ dnssec-policy "insecure";
+};
+
+/* A primary zone with dnssec-policy but keys already created. */
+zone "dnssec-keygen.kasp" {
+ type primary;
+ file "dnssec-keygen.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha256";
+};
+
+/* A secondary zone with dnssec-policy. */
+zone "secondary.kasp" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "secondary.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha256";
+};
+
+/* A dynamic zone with dnssec-policy. */
+zone "dynamic.kasp" {
+ type primary;
+ file "dynamic.kasp.db";
+ dnssec-policy "default";
+ allow-update { any; };
+};
+
+/* A dynamic inline-signed zone with dnssec-policy. */
+zone "dynamic-inline-signing.kasp" {
+ type primary;
+ file "dynamic-inline-signing.kasp.db";
+ dnssec-policy "default";
+ allow-update { any; };
+ inline-signing yes;
+};
+
+/* An inline-signed zone with dnssec-policy. */
+zone "inline-signing.kasp" {
+ type primary;
+ file "inline-signing.kasp.db";
+ dnssec-policy "default";
+ inline-signing yes;
+};
+
+/*
+ * A configured dnssec-policy but some keys already created.
+ */
+zone "some-keys.kasp" {
+ type primary;
+ file "some-keys.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha256";
+};
+
+/*
+ * A configured dnssec-policy but some keys already in use.
+ */
+zone "legacy-keys.kasp" {
+ type primary;
+ file "legacy-keys.kasp.db";
+ inline-signing yes;
+ dnssec-policy "migrate-to-dnssec-policy";
+};
+
+/*
+ * A configured dnssec-policy with (too) many keys pregenerated.
+ */
+zone "pregenerated.kasp" {
+ type primary;
+ file "pregenerated.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha256";
+};
+
+/*
+ * A configured dnssec-policy with one rumoured key.
+ * Bugfix case for GL #1593.
+ */
+zone "rumoured.kasp" {
+ type primary;
+ file "rumoured.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha256";
+};
+
+/* RFC 8901 Multi-signer Model 2. */
+zone "multisigner-model2.kasp" {
+ type primary;
+ file "multisigner-model2.kasp.db";
+ dnssec-policy "multisigner-model2";
+ allow-update { any; };
+};
+
+/*
+ * Different algorithms.
+ */
+zone "rsasha256.kasp" {
+ type primary;
+ file "rsasha256.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha256";
+};
+zone "rsasha512.kasp" {
+ type primary;
+ file "rsasha512.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha512";
+};
+zone "ecdsa256.kasp" {
+ type primary;
+ file "ecdsa256.kasp.db";
+ inline-signing yes;
+ dnssec-policy "ecdsa256";
+};
+zone "ecdsa384.kasp" {
+ type primary;
+ file "ecdsa384.kasp.db";
+ inline-signing yes;
+ dnssec-policy "ecdsa384";
+};
+
+/*
+ * Zone with too high TTL.
+ */
+zone "max-zone-ttl.kasp" {
+ type primary;
+ file "max-zone-ttl.kasp.db";
+ inline-signing yes;
+ dnssec-policy "ttl";
+};
+
+/*
+ * Zone for testing GL #2375: Three is a crowd.
+ */
+zone "three-is-a-crowd.kasp" {
+ type primary;
+ file "three-is-a-crowd.kasp.db";
+ inline-signing yes;
+ /* Use same policy as KSK rollover test zones. */
+ dnssec-policy "ksk-doubleksk";
+};
+
+/*
+ * Zones in different signing states.
+ */
+
+/*
+ * Zone that has expired signatures.
+ */
+zone "expired-sigs.autosign" {
+ type primary;
+ file "expired-sigs.autosign.db";
+ inline-signing yes;
+ dnssec-policy "autosign";
+};
+
+/*
+ * Zone that has valid, fresh signatures.
+ */
+zone "fresh-sigs.autosign" {
+ type primary;
+ file "fresh-sigs.autosign.db";
+ inline-signing yes;
+ dnssec-policy "autosign";
+};
+
+/*
+ * Zone that has unfresh signatures.
+ */
+zone "unfresh-sigs.autosign" {
+ type primary;
+ file "unfresh-sigs.autosign.db";
+ inline-signing yes;
+ dnssec-policy "autosign";
+};
+
+/*
+ * Zone that has missing private KSK.
+ */
+zone "ksk-missing.autosign" {
+ type primary;
+ file "ksk-missing.autosign.db";
+ inline-signing yes;
+ dnssec-policy "autosign";
+};
+
+/*
+ * Zone that has missing private ZSK.
+ */
+zone "zsk-missing.autosign" {
+ type primary;
+ file "zsk-missing.autosign.db";
+ inline-signing yes;
+ dnssec-policy "autosign";
+};
+
+/*
+ * Zone that has inactive ZSK.
+ */
+zone "zsk-retired.autosign" {
+ type primary;
+ file "zsk-retired.autosign.db";
+ inline-signing yes;
+ dnssec-policy "autosign";
+};
+
+/*
+ * Zones for testing enabling DNSSEC.
+ */
+zone "step1.enable-dnssec.autosign" {
+ type primary;
+ file "step1.enable-dnssec.autosign.db";
+ inline-signing yes;
+ dnssec-policy "enable-dnssec";
+};
+zone "step2.enable-dnssec.autosign" {
+ type primary;
+ file "step2.enable-dnssec.autosign.db";
+ inline-signing yes;
+ dnssec-policy "enable-dnssec";
+};
+zone "step3.enable-dnssec.autosign" {
+ type primary;
+ file "step3.enable-dnssec.autosign.db";
+ inline-signing yes;
+ dnssec-policy "enable-dnssec";
+};
+zone "step4.enable-dnssec.autosign" {
+ type primary;
+ file "step4.enable-dnssec.autosign.db";
+ inline-signing yes;
+ dnssec-policy "enable-dnssec";
+};
+
+/*
+ * Zones for testing ZSK Pre-Publication steps.
+ */
+zone "step1.zsk-prepub.autosign" {
+ type primary;
+ file "step1.zsk-prepub.autosign.db";
+ inline-signing yes;
+ dnssec-policy "zsk-prepub";
+};
+zone "step2.zsk-prepub.autosign" {
+ type primary;
+ file "step2.zsk-prepub.autosign.db";
+ inline-signing yes;
+ dnssec-policy "zsk-prepub";
+};
+zone "step3.zsk-prepub.autosign" {
+ type primary;
+ file "step3.zsk-prepub.autosign.db";
+ inline-signing yes;
+ dnssec-policy "zsk-prepub";
+};
+zone "step4.zsk-prepub.autosign" {
+ type primary;
+ file "step4.zsk-prepub.autosign.db";
+ inline-signing yes;
+ dnssec-policy "zsk-prepub";
+};
+zone "step5.zsk-prepub.autosign" {
+ type primary;
+ file "step5.zsk-prepub.autosign.db";
+ inline-signing yes;
+ dnssec-policy "zsk-prepub";
+};
+zone "step6.zsk-prepub.autosign" {
+ type primary;
+ file "step6.zsk-prepub.autosign.db";
+ inline-signing yes;
+ dnssec-policy "zsk-prepub";
+};
+
+/*
+ * Zones for testing KSK Double-KSK steps.
+ */
+zone "step1.ksk-doubleksk.autosign" {
+ type primary;
+ file "step1.ksk-doubleksk.autosign.db";
+ inline-signing yes;
+ dnssec-policy "ksk-doubleksk";
+};
+zone "step2.ksk-doubleksk.autosign" {
+ type primary;
+ file "step2.ksk-doubleksk.autosign.db";
+ inline-signing yes;
+ dnssec-policy "ksk-doubleksk";
+};
+zone "step3.ksk-doubleksk.autosign" {
+ type primary;
+ file "step3.ksk-doubleksk.autosign.db";
+ inline-signing yes;
+ dnssec-policy "ksk-doubleksk";
+};
+zone "step4.ksk-doubleksk.autosign" {
+ type primary;
+ file "step4.ksk-doubleksk.autosign.db";
+ inline-signing yes;
+ dnssec-policy "ksk-doubleksk";
+};
+zone "step5.ksk-doubleksk.autosign" {
+ type primary;
+ file "step5.ksk-doubleksk.autosign.db";
+ inline-signing yes;
+ dnssec-policy "ksk-doubleksk";
+};
+zone "step6.ksk-doubleksk.autosign" {
+ type primary;
+ file "step6.ksk-doubleksk.autosign.db";
+ inline-signing yes;
+ dnssec-policy "ksk-doubleksk";
+};
+
+/*
+ * Zones for testing CSK rollover steps.
+ */
+zone "step1.csk-roll.autosign" {
+ type primary;
+ file "step1.csk-roll.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll";
+};
+zone "step2.csk-roll.autosign" {
+ type primary;
+ file "step2.csk-roll.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll";
+};
+zone "step3.csk-roll.autosign" {
+ type primary;
+ file "step3.csk-roll.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll";
+};
+zone "step4.csk-roll.autosign" {
+ type primary;
+ file "step4.csk-roll.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll";
+};
+zone "step5.csk-roll.autosign" {
+ type primary;
+ file "step5.csk-roll.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll";
+};
+zone "step6.csk-roll.autosign" {
+ type primary;
+ file "step6.csk-roll.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll";
+};
+zone "step7.csk-roll.autosign" {
+ type primary;
+ file "step7.csk-roll.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll";
+};
+zone "step8.csk-roll.autosign" {
+ type primary;
+ file "step8.csk-roll.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll";
+};
+
+zone "step1.csk-roll2.autosign" {
+ type primary;
+ file "step1.csk-roll2.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll2";
+};
+zone "step2.csk-roll2.autosign" {
+ type primary;
+ file "step2.csk-roll2.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll2";
+};
+zone "step3.csk-roll2.autosign" {
+ type primary;
+ file "step3.csk-roll2.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll2";
+};
+zone "step4.csk-roll2.autosign" {
+ type primary;
+ file "step4.csk-roll2.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll2";
+};
+zone "step5.csk-roll2.autosign" {
+ type primary;
+ file "step5.csk-roll2.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll2";
+};
+zone "step6.csk-roll2.autosign" {
+ type primary;
+ file "step6.csk-roll2.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll2";
+};
+zone "step7.csk-roll2.autosign" {
+ type primary;
+ file "step7.csk-roll2.autosign.db";
+ inline-signing yes;
+ dnssec-policy "csk-roll2";
+};
diff --git a/bin/tests/system/kasp/ns3/named.conf.in b/bin/tests/system/kasp/ns3/named.conf.in
new file mode 100644
index 0000000..92e007d
--- /dev/null
+++ b/bin/tests/system/kasp/ns3/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+include "named-fips.conf";
+
+zone "rsasha1.kasp" {
+ type primary;
+ file "rsasha1.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha1";
+};
+
+zone "rsasha1-nsec3.kasp" {
+ type primary;
+ file "rsasha1-nsec3.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha1-nsec3";
+};
diff --git a/bin/tests/system/kasp/ns3/policies/autosign.conf.in b/bin/tests/system/kasp/ns3/policies/autosign.conf.in
new file mode 100644
index 0000000..5564ec5
--- /dev/null
+++ b/bin/tests/system/kasp/ns3/policies/autosign.conf.in
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "autosign" {
+
+ signatures-refresh P1W;
+ signatures-validity P2W;
+ signatures-validity-dnskey P2W;
+
+ dnskey-ttl 300;
+
+ keys {
+ ksk key-directory lifetime P2Y algorithm @DEFAULT_ALGORITHM@;
+ zsk key-directory lifetime P1Y algorithm @DEFAULT_ALGORITHM@;
+ };
+};
+
+dnssec-policy "enable-dnssec" {
+
+ signatures-refresh P1W;
+ signatures-validity P2W;
+ signatures-validity-dnskey P2W;
+
+ dnskey-ttl 300;
+ max-zone-ttl PT12H;
+ zone-propagation-delay PT5M;
+ retire-safety PT20M;
+ publish-safety PT5M;
+
+ parent-propagation-delay 1h;
+ parent-ds-ttl 2h;
+
+ keys {
+ csk lifetime unlimited algorithm @DEFAULT_ALGORITHM_NUMBER@;
+ };
+};
+
+dnssec-policy "zsk-prepub" {
+
+ signatures-refresh P1W;
+ signatures-validity P2W;
+ signatures-validity-dnskey P2W;
+
+ dnskey-ttl 3600;
+ publish-safety P1D;
+ retire-safety P2D;
+ purge-keys PT1H;
+
+ keys {
+ ksk key-directory lifetime P2Y algorithm @DEFAULT_ALGORITHM@;
+ zsk key-directory lifetime P30D algorithm @DEFAULT_ALGORITHM@;
+ };
+
+ zone-propagation-delay PT1H;
+ max-zone-ttl 1d;
+};
+
+dnssec-policy "ksk-doubleksk" {
+
+ signatures-refresh P1W;
+ signatures-validity P2W;
+ signatures-validity-dnskey P2W;
+
+ dnskey-ttl 2h;
+ publish-safety P1D;
+ retire-safety P2D;
+ purge-keys PT1H;
+
+ keys {
+ ksk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@;
+ zsk key-directory lifetime P1Y algorithm @DEFAULT_ALGORITHM@;
+ };
+
+ zone-propagation-delay PT1H;
+ max-zone-ttl 1d;
+
+ parent-ds-ttl 3600;
+ parent-propagation-delay PT1H;
+};
+
+dnssec-policy "csk-roll" {
+
+ signatures-refresh P5D;
+ signatures-validity 30d;
+ signatures-validity-dnskey 30d;
+
+ dnskey-ttl 1h;
+ publish-safety PT1H;
+ retire-safety 2h;
+ purge-keys PT1H;
+
+ keys {
+ csk key-directory lifetime P6M algorithm @DEFAULT_ALGORITHM@;
+ };
+
+ zone-propagation-delay 1h;
+ max-zone-ttl P1D;
+
+ parent-ds-ttl 1h;
+ parent-propagation-delay 1h;
+};
+
+dnssec-policy "csk-roll2" {
+
+ signatures-refresh 12h;
+ signatures-validity P1D;
+ signatures-validity-dnskey P1D;
+
+ dnskey-ttl 1h;
+ publish-safety PT1H;
+ retire-safety 1h;
+ purge-keys 0;
+
+ keys {
+ csk key-directory lifetime P6M algorithm @DEFAULT_ALGORITHM@;
+ };
+
+ zone-propagation-delay PT1H;
+ max-zone-ttl 1d;
+
+ parent-ds-ttl PT1H;
+ parent-propagation-delay P1W;
+};
diff --git a/bin/tests/system/kasp/ns3/policies/kasp-fips.conf.in b/bin/tests/system/kasp/ns3/policies/kasp-fips.conf.in
new file mode 100644
index 0000000..90a92a2
--- /dev/null
+++ b/bin/tests/system/kasp/ns3/policies/kasp-fips.conf.in
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "unlimited" {
+ dnskey-ttl 1234;
+
+ keys {
+ csk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ };
+};
+
+dnssec-policy "manual-rollover" {
+ dnskey-ttl 3600;
+
+ keys {
+ ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ };
+};
+
+dnssec-policy "multisigner-model2" {
+ dnskey-ttl 3600;
+
+ keys {
+ ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ };
+};
+
+dnssec-policy "migrate-to-dnssec-policy" {
+ dnskey-ttl 1234;
+
+ keys {
+ ksk key-directory lifetime P6M algorithm 8;
+ zsk key-directory lifetime P6M algorithm 8;
+ };
+};
+
+dnssec-policy "rsasha256" {
+ dnskey-ttl 1234;
+
+ keys {
+ ksk key-directory lifetime P10Y algorithm 8;
+ zsk key-directory lifetime P5Y algorithm 8;
+ zsk key-directory lifetime P1Y algorithm 8 3072;
+ };
+};
+
+dnssec-policy "rsasha512" {
+ dnskey-ttl 1234;
+
+ keys {
+ ksk key-directory lifetime P10Y algorithm 10;
+ zsk key-directory lifetime P5Y algorithm 10;
+ zsk key-directory lifetime P1Y algorithm 10 3072;
+ };
+};
+
+dnssec-policy "ecdsa256" {
+ dnskey-ttl 1234;
+
+ keys {
+ ksk key-directory lifetime P10Y algorithm 13;
+ zsk key-directory lifetime P5Y algorithm 13;
+ zsk key-directory lifetime P1Y algorithm 13 256;
+ };
+};
+
+dnssec-policy "ecdsa384" {
+ dnskey-ttl 1234;
+
+ keys {
+ ksk key-directory lifetime P10Y algorithm 14;
+ zsk key-directory lifetime P5Y algorithm 14;
+ zsk key-directory lifetime P1Y algorithm 14 384;
+ };
+};
+
+dnssec-policy "checkds-ksk" {
+ dnskey-ttl 303;
+
+ keys {
+ ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ };
+};
+
+dnssec-policy "checkds-doubleksk" {
+ dnskey-ttl 303;
+
+ keys {
+ ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ };
+};
+
+dnssec-policy "checkds-csk" {
+ dnskey-ttl 303;
+
+ keys {
+ csk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ };
+};
+
+dnssec-policy "ttl" {
+ max-zone-ttl 299;
+};
diff --git a/bin/tests/system/kasp/ns3/policies/kasp.conf.in b/bin/tests/system/kasp/ns3/policies/kasp.conf.in
new file mode 100644
index 0000000..cb045bc
--- /dev/null
+++ b/bin/tests/system/kasp/ns3/policies/kasp.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "policies/kasp-fips.conf";
+
+dnssec-policy "rsasha1" {
+ dnskey-ttl 1234;
+
+ keys {
+ ksk key-directory lifetime P10Y algorithm 5;
+ zsk key-directory lifetime P5Y algorithm 5;
+ zsk key-directory lifetime P1Y algorithm 5 2000;
+ };
+};
+
+dnssec-policy "rsasha1-nsec3" {
+ dnskey-ttl 1234;
+
+ keys {
+ ksk key-directory lifetime P10Y algorithm 7;
+ zsk key-directory lifetime P5Y algorithm 7;
+ zsk key-directory lifetime P1Y algorithm 7 2000;
+ };
+};
diff --git a/bin/tests/system/kasp/ns3/setup.sh b/bin/tests/system/kasp/ns3/setup.sh
new file mode 100644
index 0000000..8af40ed
--- /dev/null
+++ b/bin/tests/system/kasp/ns3/setup.sh
@@ -0,0 +1,1470 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns3/setup.sh"
+
+setup() {
+ zone="$1"
+ echo_i "setting up zone: $zone"
+ zonefile="${zone}.db"
+ infile="${zone}.db.infile"
+ echo "$zone" >> zones
+}
+
+# Set in the key state files the Predecessor/Successor fields.
+# Key $1 is the predecessor of key $2.
+key_successor() {
+ id1=$(keyfile_to_key_id "$1")
+ id2=$(keyfile_to_key_id "$2")
+ echo "Predecessor: ${id1}" >> "${2}.state"
+ echo "Successor: ${id2}" >> "${1}.state"
+}
+
+# Make lines shorter by storing key states in environment variables.
+H="HIDDEN"
+R="RUMOURED"
+O="OMNIPRESENT"
+U="UNRETENTIVE"
+
+#
+# Set up zones that will be initially signed.
+#
+for zn in default dnssec-keygen some-keys legacy-keys pregenerated \
+ rumoured rsasha256 rsasha512 ecdsa256 ecdsa384 \
+ dynamic dynamic-inline-signing inline-signing \
+ checkds-ksk checkds-doubleksk checkds-csk inherit unlimited \
+ manual-rollover multisigner-model2
+do
+ setup "${zn}.kasp"
+ cp template.db.in "$zonefile"
+done
+
+#
+# Set up RSASHA1 based zones
+#
+for zn in rsasha1 rsasha1-nsec3
+do
+ if (cd ..; $SHELL ../testcrypto.sh -q RSASHA1)
+ then
+ setup "${zn}.kasp"
+ cp template.db.in "$zonefile"
+ else
+ # don't add to zones.
+ echo_i "setting up zone: ${zn}.kasp"
+ cp template.db.in "${zn}.kasp.db"
+ fi
+done
+
+if [ -f ../ed25519-supported.file ]; then
+ setup "ed25519.kasp"
+ cp template.db.in "$zonefile"
+ cat ed25519.conf >> named.conf
+fi
+
+if [ -f ../ed448-supported.file ]; then
+ setup "ed448.kasp"
+ cp template.db.in "$zonefile"
+ cat ed448.conf >> named.conf
+fi
+
+# Set up zones that stay unsigned.
+for zn in unsigned insecure max-zone-ttl
+do
+ zone="${zn}.kasp"
+ echo_i "setting up zone: $zone"
+ zonefile="${zone}.db"
+ infile="${zone}.db.infile"
+ cp template.db.in $infile
+ cp template.db.in $zonefile
+done
+
+# Some of these zones already have keys.
+zone="dnssec-keygen.kasp"
+echo_i "setting up zone: $zone"
+$KEYGEN -k rsasha256 -l policies/kasp.conf $zone > keygen.out.$zone.1 2>&1
+
+zone="some-keys.kasp"
+echo_i "setting up zone: $zone"
+$KEYGEN -G -a RSASHA256 -b 2048 -L 1234 $zone > keygen.out.$zone.1 2>&1
+$KEYGEN -G -a RSASHA256 -f KSK -L 1234 $zone > keygen.out.$zone.2 2>&1
+
+zone="legacy-keys.kasp"
+echo_i "setting up zone: $zone"
+ZSK=$($KEYGEN -a RSASHA256 -b 2048 -L 1234 $zone 2> keygen.out.$zone.1)
+KSK=$($KEYGEN -a RSASHA256 -f KSK -L 1234 $zone 2> keygen.out.$zone.2)
+echo $ZSK > legacy-keys.kasp.zsk
+echo $KSK > legacy-keys.kasp.ksk
+# Predecessor keys:
+Tact="now-9mo"
+Tret="now-3mo"
+ZSK=$($KEYGEN -a RSASHA256 -b 2048 -L 1234 $zone 2> keygen.out.$zone.3)
+KSK=$($KEYGEN -a RSASHA256 -f KSK -L 1234 $zone 2> keygen.out.$zone.4)
+$SETTIME -P $Tact -A $Tact -I $Tret -D $Tret "$ZSK" > settime.out.$zone.1 2>&1
+$SETTIME -P $Tact -A $Tact -I $Tret -D $Tret "$KSK" > settime.out.$zone.2 2>&1
+
+zone="pregenerated.kasp"
+echo_i "setting up zone: $zone"
+$KEYGEN -G -k rsasha256 -l policies/kasp.conf $zone > keygen.out.$zone.1 2>&1
+$KEYGEN -G -k rsasha256 -l policies/kasp.conf $zone > keygen.out.$zone.2 2>&1
+
+zone="multisigner-model2.kasp"
+echo_i "setting up zone: $zone"
+# Import the ZSK sets of the other providers into their DNSKEY RRset.
+ZSK1=$($KEYGEN -K ../ -a $DEFAULT_ALGORITHM -L 3600 $zone 2> keygen.out.$zone.1)
+ZSK2=$($KEYGEN -K ../ -a $DEFAULT_ALGORITHM -L 3600 $zone 2> keygen.out.$zone.2)
+# ZSK1 will be added to the unsigned zonefile.
+cat "../${ZSK1}.key" | grep -v ";.*" >> "${zone}.db"
+cat "../${ZSK1}.key" | grep -v ";.*" > "${zone}.zsk1"
+rm -f "../${ZSK1}.*"
+# ZSK2 will be used with a Dynamic Update.
+cat "../${ZSK2}.key" | grep -v ";.*" > "${zone}.zsk2"
+rm -f "../${ZSK2}.*"
+
+zone="rumoured.kasp"
+echo_i "setting up zone: $zone"
+Tpub="now"
+Tact="now+1d"
+keytimes="-P ${Tpub} -A ${Tact}"
+KSK=$($KEYGEN -a RSASHA256 -f KSK -L 1234 $keytimes $zone 2> keygen.out.$zone.1)
+ZSK1=$($KEYGEN -a RSASHA256 -b 3072 -L 1234 $keytimes $zone 2> keygen.out.$zone.2)
+ZSK2=$($KEYGEN -a RSASHA256 -L 1234 $keytimes $zone 2> keygen.out.$zone.3)
+$SETTIME -s -g $O -k $R $Tpub -r $R $Tpub -d $H $Tpub "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $R $Tpub -z $R $Tpub "$ZSK1" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $R $Tpub -z $R $Tpub "$ZSK2" > settime.out.$zone.2 2>&1
+
+#
+# Set up zones that are already signed.
+#
+
+# Zone to test manual rollover.
+setup manual-rollover.kasp
+T="now-1d"
+ksktimes="-P $T -A $T -P sync $T"
+zsktimes="-P $T -A $T"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -PS -x -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# These signatures are set to expire long in the past, update immediately.
+setup expired-sigs.autosign
+T="now-6mo"
+ksktimes="-P $T -A $T -P sync $T"
+zsktimes="-P $T -A $T"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -PS -x -s now-2mo -e now-1mo -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# These signatures are still good, and can be reused.
+setup fresh-sigs.autosign
+T="now-6mo"
+ksktimes="-P $T -A $T -P sync $T"
+zsktimes="-P $T -A $T"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# These signatures are still good, but not fresh enough, update immediately.
+setup unfresh-sigs.autosign
+T="now-6mo"
+ksktimes="-P $T -A $T -P sync $T"
+zsktimes="-P $T -A $T"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1w -e now+1w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# These signatures are still good, but the private KSK is missing.
+setup ksk-missing.autosign
+T="now-6mo"
+ksktimes="-P $T -A $T -P sync $T"
+zsktimes="-P $T -A $T"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1w -e now+1w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+echo "KSK: yes" >> "${KSK}".state
+echo "ZSK: no" >> "${KSK}".state
+echo "Lifetime: 63072000" >> "${KSK}".state # PT2Y
+rm -f "${KSK}".private
+
+# These signatures are still good, but the private ZSK is missing.
+setup zsk-missing.autosign
+T="now-6mo"
+ksktimes="-P $T -A $T -P sync $T"
+zsktimes="-P $T -A $T"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1w -e now+1w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+echo "KSK: no" >> "${ZSK}".state
+echo "ZSK: yes" >> "${ZSK}".state
+echo "Lifetime: 31536000" >> "${ZSK}".state # PT1Y
+rm -f "${ZSK}".private
+
+# These signatures are already expired, and the private ZSK is retired.
+setup zsk-retired.autosign
+T="now-6mo"
+ksktimes="-P $T -A $T -P sync $T"
+zsktimes="-P $T -A $T -I now"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -PS -x -s now-2w -e now-1mi -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SETTIME -s -g HIDDEN "$ZSK" > settime.out.$zone.3 2>&1
+
+#
+# The zones at enable-dnssec.autosign represent the various steps of the
+# initial signing of a zone.
+#
+
+# Step 1:
+# This is an unsigned zone and named should perform the initial steps of
+# introducing the DNSSEC records in the right order.
+setup step1.enable-dnssec.autosign
+cp template.db.in $zonefile
+
+# Step 2:
+# The DNSKEY has been published long enough to become OMNIPRESENT.
+setup step2.enable-dnssec.autosign
+# DNSKEY TTL: 300 seconds
+# zone-propagation-delay: 5 minutes (300 seconds)
+# publish-safety: 5 minutes (300 seconds)
+# Total: 900 seconds
+TpubN="now-900s"
+# RRSIG TTL: 12 hour (43200 seconds)
+# zone-propagation-delay: 5 minutes (300 seconds)
+# retire-safety: 20 minutes (1200 seconds)
+# Already passed time: -900 seconds
+# Total: 43800 seconds
+TsbmN="now+43800s"
+keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}"
+CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2> keygen.out.$zone.1)
+$SETTIME -s -g $O -k $R $TpubN -r $R $TpubN -d $H $TpubN -z $R $TpubN "$CSK" > settime.out.$zone.1 2>&1
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 3:
+# The zone signatures have been published long enough to become OMNIPRESENT.
+setup step3.enable-dnssec.autosign
+# Passed time since publications: 43800 + 900 = 44700 seconds.
+TpubN="now-44700s"
+# The key is secure for using in chain of trust when the DNSKEY is OMNIPRESENT.
+TcotN="now-43800s"
+# We can submit the DS now.
+TsbmN="now"
+keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}"
+CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2> keygen.out.$zone.1)
+$SETTIME -s -g $O -k $O $TcotN -r $O $TcotN -d $H $TpubN -z $R $TpubN "$CSK" > settime.out.$zone.1 2>&1
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 4:
+# The DS has been submitted long enough ago to become OMNIPRESENT.
+setup step4.enable-dnssec.autosign
+# DS TTL: 2 hour (7200 seconds)
+# parent-propagation-delay: 1 hour (3600 seconds)
+# retire-safety: 20 minutes (1200 seconds)
+# Total aditional time: 12000 seconds
+# 44700 + 12000 = 56700
+TpubN="now-56700s"
+# 43800 + 12000 = 55800
+TcotN="now-55800s"
+TsbmN="now-12000s"
+keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}"
+CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2> keygen.out.$zone.1)
+$SETTIME -s -g $O -P ds $TsbmN -k $O $TcotN -r $O $TcotN -d $R $TsbmN -z $O $TsbmN "$CSK" > settime.out.$zone.1 2>&1
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+setup step4.enable-dnssec.autosign
+
+#
+# The zones at zsk-prepub.autosign represent the various steps of a ZSK
+# Pre-Publication rollover.
+#
+
+# Step 1:
+# Introduce the first key. This will immediately be active.
+setup step1.zsk-prepub.autosign
+TactN="now"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
+zsktimes="-P ${TactN} -A ${TactN}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 2:
+# It is time to pre-publish the successor ZSK.
+setup step2.zsk-prepub.autosign
+# According to RFC 7583:
+#
+# Tpub(N+1) <= Tact(N) + Lzsk - Ipub
+# Ipub = Dprp + TTLkey (+publish-safety)
+#
+# |3| |4| |5| |6|
+# | | | |
+# Key N |<-------Lzsk------>|
+# | | | |
+# Key N+1 | |<-Ipub->|<-->|
+# | | | |
+# Key N Tact
+# Key N+1 Tpub Trdy Tact
+#
+# Tnow
+#
+# Lzsk: 30d
+# Dprp: 1h
+# TTLkey: 1h
+# publish-safety: 1d
+# Ipub: 26h
+#
+# Tact(N) = Tnow + Ipub - Lzsk = now + 26h - 30d
+# = now + 26h - 30d = now − 694h
+TactN="now-694h"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
+zsktimes="-P ${TactN} -A ${TactN}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 3:
+# After the publication interval has passed the DNSKEY of the successor ZSK
+# is OMNIPRESENT and the zone can thus be signed with the successor ZSK.
+setup step3.zsk-prepub.autosign
+# According to RFC 7583:
+#
+# Tpub(N+1) <= Tact(N) + Lzsk - Ipub
+# Tret(N) = Tact(N+1) = Tact(N) + Lzsk
+# Trem(N) = Tret(N) + Iret
+# Iret = Dsgn + Dprp + TTLsig (+retire-safety)
+#
+# |3| |4| |5| |6| |7| |8|
+# | | | | | |
+# Key N |<-------Lzsk------>|<-Iret->|<--->|
+# | | | | | |
+# Key N+1 | |<-Ipub->|<-->|<---Lzsk---- - -
+# | | | | | |
+# Key N Tact Tret Tdea Trem
+# Key N+1 Tpub Trdy Tact
+#
+# Tnow
+#
+# Lzsk: 30d
+# Ipub: 26h
+# Dsgn: 1w
+# Dprp: 1h
+# TTLsig: 1d
+# retire-safety: 2d
+# Iret: 10d1h = 241h
+#
+# Tact(N) = Tnow - Lzsk = now - 30d
+# Tret(N) = now
+# Trem(N) = Tnow + Iret = now + 241h
+# Tpub(N+1) = Tnow - Ipub = now - 26h
+# Tret(N+1) = Tnow + Lzsk = now + 30d
+# Trem(N+1) = Tnow + Lzsk + Iret = now + 30d + 241h
+# = now + 961h
+TactN="now-30d"
+TretN="now"
+TremN="now+241h"
+TpubN1="now-26h"
+TactN1="now"
+TretN1="now+30d"
+TremN1="now+961h"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
+zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
+ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2> keygen.out.$zone.3)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $R $TpubN1 -z $H $TpubN1 "$ZSK2" > settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $ZSK1 $ZSK2
+# Sign zone.
+cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 4:
+# After the retire interval has passed the predecessor DNSKEY can be
+# removed from the zone.
+setup step4.zsk-prepub.autosign
+# According to RFC 7583:
+#
+# Tret(N) = Tact(N) + Lzsk
+# Tdea(N) = Tret(N) + Iret
+#
+# |3| |4| |5| |6| |7| |8|
+# | | | | | |
+# Key N |<-------Lzsk------>|<-Iret->|<--->|
+# | | | | | |
+# Key N+1 | |<-Ipub->|<-->|<---Lzsk---- - -
+# | | | | | |
+# Key N Tact Tret Tdea Trem
+# Key N+1 Tpub Trdy Tact
+#
+# Tnow
+#
+# Lzsk: 30d
+# Ipub: 26h
+# Iret: 241h
+#
+# Tact(N) = Tnow - Iret - Lzsk
+# = now - 241h - 30d = now - 241h - 720h
+# = now - 961h
+# Tret(N) = Tnow - Iret = now - 241h
+# Trem(N) = Tnow
+# Tpub(N+1) = Tnow - Iret - Ipub
+# = now - 241h - 26h
+# = now - 267h
+# Tact(N+1) = Tnow - Iret = Tret(N)
+# Tret(N+1) = Tnow - Iret + Lzsk
+# = now - 241h + 30d = now - 241h + 720h
+# = now + 479h
+# Trem(N+1) = Tnow + Lzsk = now + 30d
+TactN="now-961h"
+TretN="now-241h"
+TremN="now"
+TpubN1="now-267h"
+TactN1="${TretN}"
+TretN1="now+479h"
+TremN1="now+30d"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
+zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
+ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2> keygen.out.$zone.3)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $H -k $O $TactN -z $U $TretN "$ZSK1" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -z $R $TactN1 "$ZSK2" > settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $ZSK1 $ZSK2
+# Sign zone.
+cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" > "$infile"
+cp $infile $zonefile
+$SIGNER -PS -x -s now-2w -e now-1mi -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 5:
+# The predecessor DNSKEY is removed long enough that is has become HIDDEN.
+setup step5.zsk-prepub.autosign
+# Subtract DNSKEY TTL from all the times (1h).
+# Tact(N) = now - 961h - 1h = now - 962h
+# Tret(N) = now - 241h - 1h = now - 242h
+# Tdea(N) = now - 2d - 1h = now - 49h
+# Trem(N) = now - 1h
+# Tpub(N+1) = now - 267h - 1h = now - 268h
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = now + 479h - 1h = now + 478h
+# Trem(N+1) = now + 30d - 1h = now + 719h
+TactN="now-962h"
+TretN="now-242h"
+TremN="now-1h"
+TdeaN="now-49h"
+TpubN1="now-268h"
+TactN1="${TretN}"
+TretN1="now+478h"
+TremN1="now+719h"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
+zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
+ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2> keygen.out.$zone.3)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $H -k $U $TdeaN -z $H $TdeaN "$ZSK1" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -z $O $TdeaN "$ZSK2" > settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $ZSK1 $ZSK2
+# Sign zone.
+cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 6:
+# The predecessor DNSKEY can be purged.
+setup step6.zsk-prepub.autosign
+# Subtract purge-keys interval from all the times (1h).
+# Tact(N) = now - 962h - 1h = now - 963h
+# Tret(N) = now - 242h - 1h = now - 243h
+# Tdea(N) = now - 49h - 1h = now - 50h
+# Trem(N) = now - 1h - 1h = now - 2h
+# Tpub(N+1) = now - 268h - 1h = now - 269h
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = now + 478h - 1h = now + 477h
+# Trem(N+1) = now + 719h - 1h = now + 718h
+TactN="now-963h"
+TretN="now-243h"
+TremN="now-2h"
+TdeaN="now-50h"
+TpubN1="now-269h"
+TactN1="${TretN}"
+TretN1="now+477h"
+TremN1="now+718h"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
+zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
+ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2> keygen.out.$zone.3)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $H -k $H $TdeaN -z $H $TdeaN "$ZSK1" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -z $O $TdeaN "$ZSK2" > settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $ZSK1 $ZSK2
+# Sign zone.
+cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+#
+# The zones at ksk-doubleksk.autosign represent the various steps of a KSK
+# Double-KSK rollover.
+#
+
+# Step 1:
+# Introduce the first key. This will immediately be active.
+setup step1.ksk-doubleksk.autosign
+TactN="now"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
+zsktimes="-P ${TactN} -A ${TactN}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 2:
+# It is time to submit the introduce the new KSK.
+setup step2.ksk-doubleksk.autosign
+# According to RFC 7583:
+#
+# Tpub(N+1) <= Tact(N) + Lksk - Dreg - IpubC
+# IpubC = DprpC + TTLkey (+publish-safety)
+#
+# |1| |2| |3| |4|
+# | | | |
+# Key N |<-IpubC->|<--->|<-Dreg->|<-----Lksk--- - -
+# | | | |
+# Key N+1 | | | |
+# | | | |
+# Key N Tpub Trdy Tsbm Tact
+# Key N+1
+#
+# (continued ...)
+#
+# |5| |6| |7| |8| |9| |10|
+# | | | | | |
+# Key N - - --------------Lksk------->|<-Iret->|<----->|
+# | | | | | |
+# Key N+1 |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - -
+# | | | | | |
+# Key N Tret Tdea Trem
+# Key N+1 Tpub Trdy Tsbm Tact
+#
+# Tnow
+#
+# Lksk: 60d
+# Dreg: 1d
+# DprpC: 1h
+# TTLkey: 2h
+# publish-safety: 1d
+# IpubC: 27h
+#
+# Tact(N) = Tnow - Lksk + Dreg + IpubC = now - 60d + 27h
+# = now - 1440h + 27h = now - 1413h
+TactN="now-1413h"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
+zsktimes="-P ${TactN} -A ${TactN}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 3:
+# It is time to submit the DS.
+setup step3.ksk-doubleksk.autosign
+# According to RFC 7583:
+#
+# Tsbm(N+1) >= Trdy(N+1)
+# Tact(N+1) = Tsbm(N+1) + Dreg
+# Iret = DprpP + TTLds (+retire-safety)
+#
+# |5| |6| |7| |8| |9| |10|
+# | | | | | |
+# Key N - - --------------Lksk------->|<-Iret->|<----->|
+# | | | | | |
+# Key N+1 |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - -
+# | | | | | |
+# Key N Tret Tdea Trem
+# Key N+1 Tpub Trdy Tsbm Tact
+#
+# Tnow
+#
+# Lksk: 60d
+# Dreg: N/A
+# DprpP: 1h
+# TTLds: 1h
+# retire-safety: 2d
+# Iret: 50h
+# DprpC: 1h
+# TTLkey: 2h
+# publish-safety: 1d
+# IpubC: 27h
+#
+# Tact(N) = Tnow + Lksk = now - 60d = now - 60d
+# Tret(N) = now
+# Trem(N) = Tnow + Iret = now + 50h
+# Tpub(N+1) = Tnow - IpubC = now - 27h
+# Tsbm(N+1) = now
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = Tnow + Lksk = now + 60d
+# Trem(N+1) = Tnow + Lksk + Iret = now + 60d + 50h
+# = now + 1440h + 50h = 1490h
+TactN="now-60d"
+TretN="now"
+TremN="now+50h"
+TpubN1="now-27h"
+TsbmN1="now"
+TactN1="${TretN}"
+TretN1="now+60d"
+TremN1="now+1490h"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}"
+zsktimes="-P ${TactN} -A ${TactN}"
+KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2> keygen.out.$zone.2)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.3)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" > settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $KSK1 $KSK2
+# Sign zone.
+cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 4:
+# The DS should be swapped now.
+setup step4.ksk-doubleksk.autosign
+# According to RFC 7583:
+#
+# Tret(N) = Tsbm(N+1)
+# Tdea(N) = Tret(N) + Iret
+# Tact(N+1) = Tret(N)
+#
+# |5| |6| |7| |8| |9| |10|
+# | | | | | |
+# Key N - - --------------Lksk------->|<-Iret->|<----->|
+# | | | | | |
+# Key N+1 |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - -
+# | | | | | |
+# Key N Tret Tdea Trem
+# Key N+1 Tpub Trdy Tsbm Tact
+#
+# Tnow
+#
+# Lksk: 60d
+# Dreg: N/A
+# Iret: 50h
+#
+# Tact(N) = Tnow - Lksk - Iret = now - 60d - 50h
+# = now - 1440h - 50h = now - 1490h
+# Tret(N) = Tnow - Iret = now - 50h
+# Trem(N) = Tnow
+# Tpub(N+1) = Tnow - Iret - IpubC = now - 50h - 27h
+# = now - 77h
+# Tsbm(N+1) = Tnow - Iret = now - 50h
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = Tnow + Lksk - Iret = now + 60d - 50h = now + 1390h
+# Trem(N+1) = Tnow + Lksk = now + 60d
+TactN="now-1490h"
+TretN="now-50h"
+TremN="now"
+TpubN1="now-77h"
+TsbmN1="now-50h"
+TactN1="${TretN}"
+TretN1="now+1390h"
+TremN1="now+60d"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}"
+zsktimes="-P ${TactN} -A ${TactN}"
+KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2> keygen.out.$zone.2)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.3)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TsbmN1 -D ds $TsbmN1 "$KSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $R $TsbmN1 -P ds $TsbmN1 "$KSK2" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" > settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $KSK1 $KSK2
+# Sign zone.
+cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 5:
+# The predecessor DNSKEY is removed long enough that is has become HIDDEN.
+setup step5.ksk-doubleksk.autosign
+# Subtract DNSKEY TTL from all the times (2h).
+# Tact(N) = now - 1490h - 2h = now - 1492h
+# Tret(N) = now - 50h - 2h = now - 52h
+# Trem(N) = now - 2h
+# Tpub(N+1) = now - 77h - 2h = now - 79h
+# Tsbm(N+1) = now - 50h - 2h = now - 52h
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = now + 1390h - 2h = now + 1388h
+# Trem(N+1) = now + 60d - 2h = now + 1442h
+TactN="now-1492h"
+TretN="now-52h"
+TremN="now-2h"
+TpubN1="now-79h"
+TsbmN1="now-52h"
+TactN1="${TretN}"
+TretN1="now+1388h"
+TremN1="now+1442h"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}"
+zsktimes="-P ${TactN} -A ${TactN}"
+KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2> keygen.out.$zone.2)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.3)
+$SETTIME -s -g $H -k $U $TretN -r $U $TretN -d $H $TretN "$KSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" > settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $KSK1 $KSK2
+# Sign zone.
+cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 6:
+# The predecessor DNSKEY can be purged.
+setup step6.ksk-doubleksk.autosign
+# Subtract purge-keys interval from all the times (1h).
+# Tact(N) = now - 1492h - 1h = now - 1493h
+# Tret(N) = now - 52h - 1h = now - 53h
+# Trem(N) = now - 2h - 1h = now - 3h
+# Tpub(N+1) = now - 79h - 1h = now - 80h
+# Tsbm(N+1) = now - 52h - 1h = now - 53h
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = now + 1388h - 1h = now + 1387h
+# Trem(N+1) = now + 1442h - 1h = now + 1441h
+TactN="now-1493h"
+TretN="now-53h"
+TremN="now-3h"
+TpubN1="now-80h"
+TsbmN1="now-53h"
+TactN1="${TretN}"
+TretN1="now+1387h"
+TremN1="now+1441h"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}"
+zsktimes="-P ${TactN} -A ${TactN}"
+KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2> keygen.out.$zone.2)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.3)
+$SETTIME -s -g $H -k $H $TretN -r $H $TretN -d $H $TretN "$KSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" > settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $KSK1 $KSK2
+# Sign zone.
+cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+#
+# The zones at csk-roll.autosign represent the various steps of a CSK rollover
+# (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover).
+#
+
+# Step 1:
+# Introduce the first key. This will immediately be active.
+setup step1.csk-roll.autosign
+TactN="now"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN}"
+CSK=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" > settime.out.$zone.1 2>&1
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 2:
+# It is time to introduce the new CSK.
+setup step2.csk-roll.autosign
+# According to RFC 7583:
+# KSK: Tpub(N+1) <= Tact(N) + Lksk - IpubC
+# ZSK: Tpub(N+1) <= Tact(N) + Lzsk - Ipub
+# IpubC = DprpC + TTLkey (+publish-safety)
+# Ipub = IpubC
+# Lcsk = Lksk = Lzsk
+#
+# Lcsk: 6mo (186d, 4464h)
+# Dreg: N/A
+# DprpC: 1h
+# TTLkey: 1h
+# publish-safety: 1h
+# Ipub: 3h
+#
+# Tact(N) = Tnow - Lcsk + Ipub = now - 186d + 3h
+# = now - 4464h + 3h = now - 4461h
+TactN="now-4461h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN}"
+CSK=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" > settime.out.$zone.1 2>&1
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 3:
+# It is time to submit the DS and to roll signatures.
+setup step3.csk-roll.autosign
+# According to RFC 7583:
+#
+# Tsbm(N+1) >= Trdy(N+1)
+# KSK: Tact(N+1) = Tsbm(N+1)
+# ZSK: Tact(N+1) = Tpub(N+1) + Ipub = Tsbm(N+1)
+# KSK: Iret = DprpP + TTLds (+retire-safety)
+# ZSK: IretZ = Dsgn + Dprp + TTLsig (+retire-safety)
+#
+# Lcsk: 186d
+# Dprp: 1h
+# DprpP: 1h
+# Dreg: N/A
+# Dsgn: 25d
+# TTLds: 1h
+# TTLsig: 1d
+# retire-safety: 2h
+# Iret: 4h
+# IretZ: 26d3h
+# Ipub: 3h
+#
+# Tact(N) = Tnow - Lcsk = now - 186d
+# Tret(N) = now
+# Trem(N) = Tnow + IretZ = now + 26d3h = now + 627h
+# Tpub(N+1) = Tnow - Ipub = now - 3h
+# Tsbm(N+1) = Tret(N)
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = Tnow + Lcsk = now + 186d = now + 186d
+# Trem(N+1) = Tnow + Lcsk + IretZ = now + 186d + 26d3h =
+# = now + 5091h
+TactN="now-186d"
+TretN="now"
+TremN="now+627h"
+TpubN1="now-3h"
+TsbmN1="now"
+TactN1="${TretN}"
+TretN1="now+186d"
+TremN1="now+5091h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 -z $H $TpubN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Set key rollover relationship.
+key_successor $CSK1 $CSK2
+# Sign zone.
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 4:
+# Some time later all the ZRRSIG records should be from the new CSK, and the
+# DS should be swapped. The ZRRSIG records are all replaced after IretZ
+# (which is 26d3h). The DS is swapped after Iret (which is 4h).
+# In other words, the DS is swapped before all zone signatures are replaced.
+setup step4.csk-roll.autosign
+# According to RFC 7583:
+# Trem(N) = Tret(N) - Iret + IretZ
+# Tnow = Tsbm(N+1) + Iret
+#
+# Lcsk: 186d
+# Iret: 4h
+# IretZ: 26d3h
+#
+# Tact(N) = Tnow - Iret - Lcsk = now - 4h - 186d = now - 4468h
+# Tret(N) = Tnow - Iret = now - 4h = now - 4h
+# Trem(N) = Tnow - Iret + IretZ = now - 4h + 26d3h
+# = now + 623h
+# Tpub(N+1) = Tnow - Iret - IpubC = now - 4h - 3h = now - 7h
+# Tsbm(N+1) = Tret(N)
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = Tnow - Iret + Lcsk = now - 4h + 186d = now + 4460h
+# Trem(N+1) = Tnow - Iret + Lcsk + IretZ = now - 4h + 186d + 26d3h
+# = now + 5087h
+TactN="now-4468h"
+TretN="now-4h"
+TremN="now+623h"
+TpubN1="now-7h"
+TsbmN1="${TretN}"
+TactN1="${TretN}"
+TretN1="now+4460h"
+TremN1="now+5087h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TsbmN1 -z $U $TsbmN1 -D ds $TsbmN1 "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $R $TsbmN1 -z $R $TsbmN1 -P ds $TsbmN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Set key rollover relationship.
+key_successor $CSK1 $CSK2
+# Sign zone.
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 5:
+# After the DS is swapped in step 4, also the KRRSIG records can be removed.
+# At this time these have all become hidden.
+setup step5.csk-roll.autosign
+# Subtract DNSKEY TTL plus zone propagation delay from all the times (2h).
+# Tact(N) = now - 4468h - 2h = now - 4470h
+# Tret(N) = now - 4h - 2h = now - 6h
+# Trem(N) = now + 623h - 2h = now + 621h
+# Tpub(N+1) = now - 7h - 2h = now - 9h
+# Tsbm(N+1) = Tret(N)
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = now + 4460h - 2h = now + 4458h
+# Trem(N+1) = now + 5087h - 2h = now + 5085h
+TactN="now-4470h"
+TretN="now-6h"
+TremN="now+621h"
+TpubN1="now-9h"
+TsbmN1="${TretN}"
+TactN1="${TretN}"
+TretN1="now+4458h"
+TremN1="now+5085h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $O $TactN -r $U now-2h -d $H now-2h -z $U $TactN1 "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O now-2h -z $R $TactN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Set key rollover relationship.
+key_successor $CSK1 $CSK2
+# Sign zone.
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 6:
+# After the retire interval has passed the predecessor DNSKEY can be
+# removed from the zone.
+setup step6.csk-roll.autosign
+# According to RFC 7583:
+# Trem(N) = Tret(N) + IretZ
+# Tret(N) = Tact(N) + Lcsk
+#
+# Lcsk: 186d
+# Iret: 4h
+# IretZ: 26d3h
+#
+# Tact(N) = Tnow - IretZ - Lcsk = now - 627h - 186d
+# = now - 627h - 4464h = now - 5091h
+# Tret(N) = Tnow - IretZ = now - 627h
+# Trem(N) = Tnow
+# Tpub(N+1) = Tnow - IretZ - Ipub = now - 627h - 3h = now - 630h
+# Tsbm(N+1) = Tret(N)
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = Tnow - IretZ + Lcsk = now - 627h + 186d = now + 3837h
+# Trem(N+1) = Tnow + Lcsk = now + 186d
+TactN="now-5091h"
+TretN="now-627h"
+TremN="now"
+TpubN1="now-630h"
+TsbmN1="${TretN}"
+TactN1="${TretN}"
+TretN1="now+3837h"
+TremN1="now+186d"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $O $TactN -r $H $TremN -d $H $TremN -z $U $TsbmN1 "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O $TremN -z $R $TsbmN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Set key rollover relationship.
+key_successor $CSK1 $CSK2
+# Sign zone.
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 7:
+# Some time later the predecessor DNSKEY enters the HIDDEN state.
+setup step7.csk-roll.autosign
+# Subtract DNSKEY TTL plus zone propagation delay from all the times (2h).
+# Tact(N) = now - 5091h - 2h = now - 5093h
+# Tret(N) = now - 627h - 2h = now - 629h
+# Trem(N) = now - 2h
+# Tpub(N+1) = now - 630h - 2h = now - 632h
+# Tsbm(N+1) = Tret(N)
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = now + 3837h - 2h = now + 3835h
+# Trem(N+1) = now + 186d - 2h = now + 4462h
+TactN="now-5093h"
+TretN="now-629h"
+TremN="now-2h"
+TpubN1="now-632h"
+TsbmN1="${TretN}"
+TactN1="${TretN}"
+TretN1="now+3835h"
+TremN1="now+4462h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $U $TremN -r $H $TremN -d $H $TremN -z $H $TactN1 "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O $TactN1 -z $O $TactN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Set key rollover relationship.
+key_successor $CSK1 $CSK2
+# Sign zone.
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 8:
+# The predecessor DNSKEY can be purged.
+setup step8.csk-roll.autosign
+# Subtract purge-keys interval from all the times (1h).
+# Tact(N) = now - 5093h - 1h = now - 5094h
+# Tret(N) = now - 629h - 1h = now - 630h
+# Trem(N) = now - 2h - 1h = now - 3h
+# Tpub(N+1) = now - 632h - 1h = now - 633h
+# Tsbm(N+1) = Tret(N)
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = now + 3835h - 1h = now + 3834h
+# Trem(N+1) = now + 4462h - 1h = now + 4461h
+TactN="now-5094h"
+TretN="now-630h"
+TremN="now-3h"
+TpubN1="now-633h"
+TsbmN1="${TretN}"
+TactN1="${TretN}"
+TretN1="now+3834h"
+TremN1="now+4461h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $H $TremN -r $H $TremN -d $H $TremN -z $H $TactN1 "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O $TactN1 -z $O $TactN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Set key rollover relationship.
+key_successor $CSK1 $CSK2
+# Sign zone.
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+#
+# The zones at csk-roll2.autosign represent the various steps of a CSK rollover
+# (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover).
+# This scenario differs from the above one because the zone signatures (ZRRSIG)
+# are replaced with the new key sooner than the DS is swapped.
+#
+
+# Step 1:
+# Introduce the first key. This will immediately be active.
+setup step1.csk-roll2.autosign
+TactN="now"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN}"
+CSK=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" > settime.out.$zone.1 2>&1
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 2:
+# It is time to introduce the new CSK.
+setup step2.csk-roll2.autosign
+# According to RFC 7583:
+# KSK: Tpub(N+1) <= Tact(N) + Lksk - IpubC
+# ZSK: Tpub(N+1) <= Tact(N) + Lzsk - Ipub
+# IpubC = DprpC + TTLkey (+publish-safety)
+# Ipub = IpubC
+# Lcsk = Lksk = Lzsk
+#
+# Lcsk: 6mo (186d, 4464h)
+# Dreg: N/A
+# DprpC: 1h
+# TTLkey: 1h
+# publish-safety: 1h
+# Ipub: 3h
+#
+# Tact(N) = Tnow - Lcsk + Ipub = now - 186d + 3h
+# = now - 4464h + 3h = now - 4461h
+TactN="now-4461h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN}"
+CSK=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" > settime.out.$zone.1 2>&1
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 3:
+# It is time to submit the DS and to roll signatures.
+setup step3.csk-roll2.autosign
+# According to RFC 7583:
+#
+# Tsbm(N+1) >= Trdy(N+1)
+# KSK: Tact(N+1) = Tsbm(N+1)
+# ZSK: Tact(N+1) = Tpub(N+1) + Ipub = Tsbm(N+1)
+# KSK: Iret = DprpP + TTLds (+retire-safety)
+# ZSK: IretZ = Dsgn + Dprp + TTLsig (+retire-safety)
+#
+# Lcsk: 186d
+# Dprp: 1h
+# DprpP: 1w
+# Dreg: N/A
+# Dsgn: 12h
+# TTLds: 1h
+# TTLsig: 1d
+# retire-safety: 1h
+# Iret: 170h
+# IretZ: 38h
+# Ipub: 3h
+#
+# Tact(N) = Tnow - Lcsk = now - 186d
+# Tret(N) = now
+# Trem(N) = Tnow + Iret = now + 170h
+# Tpub(N+1) = Tnow - Ipub = now - 3h
+# Tsbm(N+1) = Tret(N)
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = Tnow + Lcsk = now + 186d
+# Trem(N+1) = Tnow + Lcsk + Iret = now + 186d + 170h =
+# = now + 4464h + 170h = now + 4634h
+TactN="now-186d"
+TretN="now"
+TremN="now+170h"
+TpubN1="now-3h"
+TsbmN1="${TretN}"
+TactN1="${TretN}"
+TretN1="now+186d"
+TremN1="now+4634h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+CSK1=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 -z $H $TpubN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Set key rollover relationship.
+key_successor $CSK1 $CSK2
+# Sign zone.
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 4:
+# Some time later all the ZRRSIG records should be from the new CSK, and the
+# DS should be swapped. The ZRRSIG records are all replaced after IretZ (38h).
+# The DS is swapped after Dreg + Iret (1w3h). In other words, the zone
+# signatures are replaced before the DS is swapped.
+setup step4.csk-roll2.autosign
+# According to RFC 7583:
+# Trem(N) = Tret(N) + IretZ
+#
+# Lcsk: 186d
+# Dreg: N/A
+# Iret: 170h
+# IretZ: 38h
+#
+# Tact(N) = Tnow - IretZ = Lcsk = now - 38h - 186d
+# = now - 38h - 4464h = now - 4502h
+# Tret(N) = Tnow - IretZ = now - 38h
+# Trem(N) = Tnow - IretZ + Iret = now - 38h + 170h = now + 132h
+# Tpub(N+1) = Tnow - IretZ - IpubC = now - 38h - 3h = now - 41h
+# Tsbm(N+1) = Tret(N)
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = Tnow - IretZ + Lcsk = now - 38h + 186d
+# = now + 4426h
+# Trem(N+1) = Tnow - IretZ + Lcsk + Iret
+# = now + 4426h + 3h = now + 4429h
+TactN="now-4502h"
+TretN="now-38h"
+TremN="now+132h"
+TpubN1="now-41h"
+TsbmN1="${TretN}"
+TactN1="${TretN}"
+TretN1="now+4426h"
+TremN1="now+4429h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+CSK1=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $U $TretN -d $U $TsbmN1 -D ds $TsbmN1 "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -z $R $TactN1 -d $R $TsbmN1 -P ds $TsbmN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Set key rollover relationship.
+key_successor $CSK1 $CSK2
+# Sign zone.
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 5:
+# Some time later the DS can be swapped and the old DNSKEY can be removed from
+# the zone.
+setup step5.csk-roll2.autosign
+# Subtract Iret (170h) - IretZ (38h) = 132h.
+#
+# Tact(N) = now - 4502h - 132h = now - 4634h
+# Tret(N) = now - 38h - 132h = now - 170h
+# Trem(N) = now + 132h - 132h = now
+# Tpub(N+1) = now - 41h - 132h = now - 173h
+# Tsbm(N+1) = Tret(N)
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = now + 4426h - 132h = now + 4294h
+# Trem(N+1) = now + 4492h - 132h = now + 4360h
+TactN="now-4634h"
+TretN="now-170h"
+TremN="now"
+TpubN1="now-173h"
+TsbmN1="${TretN}"
+TactN1="${TretN}"
+TretN1="now+4294h"
+TremN1="now+4360h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+CSK1=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $H now-133h -d $U $TsbmN1 -D ds $TsbmN1 "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -z $O now-133h -d $R $TsbmN1 -P ds $TsbmN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Set key rollover relationship.
+key_successor $CSK1 $CSK2
+# Sign zone.
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 6:
+# Some time later the predecessor DNSKEY enters the HIDDEN state.
+setup step6.csk-roll2.autosign
+# Subtract DNSKEY TTL plus zone propagation delay (2h).
+#
+# Tact(N) = now - 4634h - 2h = now - 4636h
+# Tret(N) = now - 170h - 2h = now - 172h
+# Trem(N) = now - 2h
+# Tpub(N+1) = now - 173h - 2h = now - 175h
+# Tsbm(N+1) = Tret(N)
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = now + 4294h - 2h = now + 4292h
+# Trem(N+1) = now + 4360h - 2h = now + 4358h
+TactN="now-4636h"
+TretN="now-172h"
+TremN="now-2h"
+TpubN1="now-175h"
+TsbmN1="${TretN}"
+TactN1="${TretN}"
+TretN1="now+4292h"
+TremN1="now+4358h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+CSK1=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $U $TremN -r $U $TremN -d $H $TremN -z $H now-135h "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O $TremN -z $O now-135h "$CSK2" > settime.out.$zone.2 2>&1
+# Set key rollover relationship.
+key_successor $CSK1 $CSK2
+# Sign zone.
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 7:
+# The predecessor DNSKEY can be purged, but purge-keys is disabled.
+setup step7.csk-roll2.autosign
+# Subtract 90 days (default, 2160h) from all the times.
+# Tact(N) = now - 4636h - 2160h = now - 6796h
+# Tret(N) = now - 172h - 2160h = now - 2332h
+# Trem(N) = now - 2h - 2160h = now - 2162h
+# Tpub(N+1) = now - 175h - 2160h = now - 2335h
+# Tsbm(N+1) = Tret(N)
+# Tact(N+1) = Tret(N)
+# Tret(N+1) = now + 4294h - 2160h = now + 2134h
+# Trem(N+1) = now + 4360h - 2160h = now + 2200h
+TactN="now-6796h"
+TretN="now-2332h"
+TremN="now-2162h"
+TpubN1="now-2335h"
+TsbmN1="${TretN}"
+TactN1="${TretN}"
+TretN1="now+2134h"
+TremN1="now+2200h"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}"
+CSK1=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $U $TremN -r $U $TremN -d $H $TremN -z $H now-135h "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O $TremN -z $O now-135h "$CSK2" > settime.out.$zone.2 2>&1
+# Set key rollover relationship.
+key_successor $CSK1 $CSK2
+# Sign zone.
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Test #2375, the "three is a crowd" bug, where a new key is introduced but the
+# previous rollover has not finished yet. In other words, we have a key KEY2
+# that is the successor of key KEY1, and we introduce a new key KEY3 that is
+# the successor of key KEY2:
+#
+# KEY1 < KEY2 < KEY3.
+#
+# The expected behavior is that all three keys remain in the zone, and not
+# the bug behavior where KEY2 is removed and immediately replaced with KEY3.
+#
+# Set up a zone that has a KSK (KEY1) and have the successor key (KEY2)
+# published as well.
+setup three-is-a-crowd.kasp
+# These times are the same as step3.ksk-doubleksk.autosign.
+TactN="now-60d"
+TretN="now"
+TremN="now+50h"
+TpubN1="now-27h"
+TsbmN1="now"
+TactN1="${TretN}"
+TretN1="now+60d"
+TremN1="now+1490h"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}"
+newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}"
+zsktimes="-P ${TactN} -A ${TactN}"
+KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2> keygen.out.$zone.2)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.3)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" > settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $KSK1 $KSK2
+# Sign zone.
+cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
diff --git a/bin/tests/system/kasp/ns3/template.db.in b/bin/tests/system/kasp/ns3/template.db.in
new file mode 100644
index 0000000..010b05b
--- /dev/null
+++ b/bin/tests/system/kasp/ns3/template.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns3
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+
diff --git a/bin/tests/system/kasp/ns3/template2.db.in b/bin/tests/system/kasp/ns3/template2.db.in
new file mode 100644
index 0000000..7b94ace
--- /dev/null
+++ b/bin/tests/system/kasp/ns3/template2.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns3
+ns3 A 10.53.0.3
+
+a A 10.0.0.11
+b A 10.0.0.22
+c A 10.0.0.33
+d A 10.0.0.44
diff --git a/bin/tests/system/kasp/ns4/example1.db.in b/bin/tests/system/kasp/ns4/example1.db.in
new file mode 100644
index 0000000..c9e537f
--- /dev/null
+++ b/bin/tests/system/kasp/ns4/example1.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns4
+ns4 A 10.53.0.4
+
+view TXT "view1"
diff --git a/bin/tests/system/kasp/ns4/example2.db.in b/bin/tests/system/kasp/ns4/example2.db.in
new file mode 100644
index 0000000..c1f16a2
--- /dev/null
+++ b/bin/tests/system/kasp/ns4/example2.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns4
+ns4 A 10.53.0.4
+
+view TXT "view2"
diff --git a/bin/tests/system/kasp/ns4/named.conf.in b/bin/tests/system/kasp/ns4/named.conf.in
new file mode 100644
index 0000000..459ea73
--- /dev/null
+++ b/bin/tests/system/kasp/ns4/named.conf.in
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS4
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key "sha1" {
+ algorithm "hmac-sha1";
+ secret "FrSt77yPTFx6hTs4i2tKLB9LmE0=";
+};
+
+key "sha224" {
+ algorithm "hmac-sha224";
+ secret "hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA==";
+};
+
+key "sha256" {
+ algorithm "hmac-sha256";
+ secret "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY=";
+};
+
+key "keyforview1" {
+ algorithm @DEFAULT_HMAC@;
+ secret "YPfMoAk6h+3iN8MDRQC004iSNHY=";
+};
+
+key "keyforview2" {
+ algorithm @DEFAULT_HMAC@;
+ secret "4xILSZQnuO1UKubXHkYUsvBRPu8=";
+};
+
+key "keyforview3" {
+ algorithm @DEFAULT_HMAC@;
+ secret "C1Azf+gGPMmxrUg/WQINP6eV9Y0=";
+};
+
+dnssec-policy "test" {
+ keys {
+ csk key-directory lifetime 0 algorithm 14;
+ };
+};
+
+options {
+ query-source address 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-policy "test";
+ dnssec-validation no;
+};
+
+view "inherit" {
+ match-clients { key "sha1"; };
+
+ /* Inherit dnssec-policy 'test' */
+ zone "inherit.inherit.signed" {
+ type primary;
+ file "inherit.inherit.signed.db";
+ inline-signing yes;
+ };
+
+ /* Override dnssec-policy */
+ zone "override.inherit.signed" {
+ type primary;
+ file "override.inherit.signed.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ };
+
+ /* Unset dnssec-policy */
+ zone "none.inherit.signed" {
+ type primary;
+ file "none.inherit.signed.db";
+ dnssec-policy "none";
+ };
+};
+
+view "override" {
+ match-clients { key "sha224"; };
+ dnssec-policy "default";
+
+ /* Inherit dnssec-policy 'test' */
+ zone "inherit.override.signed" {
+ type primary;
+ file "inherit.override.signed.db";
+ inline-signing yes;
+ };
+
+ /* Override dnssec-policy */
+ zone "override.override.signed" {
+ type primary;
+ file "override.override.signed.db";
+ inline-signing yes;
+ dnssec-policy "test";
+ };
+
+ /* Unset dnssec-policy */
+ zone "none.override.signed" {
+ type primary;
+ file "none.override.signed.db";
+ dnssec-policy "none";
+ };
+};
+
+view "none" {
+ match-clients { key "sha256"; };
+ dnssec-policy "none";
+
+ /* Inherit dnssec-policy 'none' */
+ zone "inherit.none.signed" {
+ type primary;
+ file "inherit.none.signed.db";
+ };
+
+ /* Override dnssec-policy */
+ zone "override.none.signed" {
+ type primary;
+ file "override.none.signed.db";
+ inline-signing yes;
+ dnssec-policy "test";
+ };
+
+ /* Unset dnssec-policy */
+ zone "none.none.signed" {
+ type primary;
+ file "none.none.signed.db";
+ dnssec-policy "none";
+ };
+};
+
+view "example1" {
+ match-clients { key "keyforview1"; };
+
+ allow-update { any; };
+
+ zone "example.net" {
+ type primary;
+ file "example1.db";
+ };
+};
+
+view "example2" {
+ match-clients { key "keyforview2"; };
+
+ zone "example.net" {
+ type primary;
+ file "example2.db";
+ inline-signing yes;
+ };
+};
+
+view "example3" {
+ match-clients { key "keyforview3"; };
+ zone "example.net" {
+ in-view example2;
+ };
+};
diff --git a/bin/tests/system/kasp/ns4/setup.sh b/bin/tests/system/kasp/ns4/setup.sh
new file mode 100644
index 0000000..61b049d
--- /dev/null
+++ b/bin/tests/system/kasp/ns4/setup.sh
@@ -0,0 +1,33 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns4/setup.sh"
+
+#
+# Set up zones that potentially will be initially signed.
+#
+for zn in inherit.inherit override.inherit none.inherit \
+ inherit.override override.override none.override \
+ inherit.none override.none none.none
+do
+ zone="$zn.signed"
+ echo_i "setting up zone: $zone"
+ zonefile="${zone}.db"
+ cp template.db.in $zonefile
+done
+
+cp example1.db.in example1.db
+cp example2.db.in example2.db
diff --git a/bin/tests/system/kasp/ns4/template.db.in b/bin/tests/system/kasp/ns4/template.db.in
new file mode 100644
index 0000000..0f72e9c
--- /dev/null
+++ b/bin/tests/system/kasp/ns4/template.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns4
+ns4 A 10.53.0.4
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+
diff --git a/bin/tests/system/kasp/ns5/named.conf.in b/bin/tests/system/kasp/ns5/named.conf.in
new file mode 100644
index 0000000..44855b9
--- /dev/null
+++ b/bin/tests/system/kasp/ns5/named.conf.in
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key "sha1" {
+ algorithm "hmac-sha1";
+ secret "FrSt77yPTFx6hTs4i2tKLB9LmE0=";
+};
+
+key "sha224" {
+ algorithm "hmac-sha224";
+ secret "hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA==";
+};
+
+key "sha256" {
+ algorithm "hmac-sha256";
+ secret "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY=";
+};
+
+dnssec-policy "test" {
+ keys {
+ csk key-directory lifetime 0 algorithm 14;
+ };
+};
+
+options {
+ query-source address 10.53.0.5;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-policy "none";
+ dnssec-validation no;
+};
+
+view "inherit" {
+ match-clients { key "sha1"; };
+
+ /* Inherit dnssec-policy 'none' */
+ zone "inherit.inherit.unsigned" {
+ type primary;
+ file "inherit.inherit.unsigned.db";
+ };
+
+ /* Override dnssec-policy */
+ zone "override.inherit.unsigned" {
+ type primary;
+ file "override.inherit.unsigned.db";
+ inline-signing yes;
+ dnssec-policy "default";
+ };
+
+ /* Unset dnssec-policy */
+ zone "none.inherit.unsigned" {
+ type primary;
+ file "none.inherit.unsigned.db";
+ dnssec-policy "none";
+ };
+};
+
+view "override" {
+ match-clients { key "sha224"; };
+ dnssec-policy "default";
+
+ /* Inherit dnssec-policy 'default' */
+ zone "inherit.override.unsigned" {
+ type primary;
+ file "inherit.override.unsigned.db";
+ inline-signing yes;
+ };
+
+ /* Override dnssec-policy */
+ zone "override.override.unsigned" {
+ type primary;
+ file "override.override.unsigned.db";
+ inline-signing yes;
+ dnssec-policy "test";
+ };
+
+ /* Unset dnssec-policy */
+ zone "none.override.unsigned" {
+ type primary;
+ file "none.override.unsigned.db";
+ dnssec-policy "none";
+ };
+};
+
+view "none" {
+ match-clients { key "sha256"; };
+ dnssec-policy "none";
+
+ /* Inherit dnssec-policy 'none' */
+ zone "inherit.none.unsigned" {
+ type primary;
+ file "inherit.none.unsigned.db";
+ };
+
+ /* Override dnssec-policy */
+ zone "override.none.unsigned" {
+ type primary;
+ file "override.none.unsigned.db";
+ inline-signing yes;
+ dnssec-policy "test";
+ };
+
+ /* Unset dnssec-policy */
+ zone "none.none.unsigned" {
+ type primary;
+ file "none.none.unsigned.db";
+ dnssec-policy "none";
+ };
+};
diff --git a/bin/tests/system/kasp/ns5/setup.sh b/bin/tests/system/kasp/ns5/setup.sh
new file mode 100644
index 0000000..59c7a41
--- /dev/null
+++ b/bin/tests/system/kasp/ns5/setup.sh
@@ -0,0 +1,30 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns5/setup.sh"
+
+#
+# Set up zones that potentially will be initially signed.
+#
+for zn in inherit.inherit override.inherit none.inherit \
+ inherit.override override.override none.override \
+ inherit.none override.none none.none
+do
+ zone="$zn.unsigned"
+ echo_i "setting up zone: $zone"
+ zonefile="${zone}.db"
+ cp template.db.in $zonefile
+done
diff --git a/bin/tests/system/kasp/ns5/template.db.in b/bin/tests/system/kasp/ns5/template.db.in
new file mode 100644
index 0000000..6cb07a4
--- /dev/null
+++ b/bin/tests/system/kasp/ns5/template.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns5
+ns5 A 10.53.0.5
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+
diff --git a/bin/tests/system/kasp/ns6/example.db.in b/bin/tests/system/kasp/ns6/example.db.in
new file mode 100644
index 0000000..d6b912c
--- /dev/null
+++ b/bin/tests/system/kasp/ns6/example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns6
+ns6 A 10.53.0.6
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
diff --git a/bin/tests/system/kasp/ns6/example2.db.in b/bin/tests/system/kasp/ns6/example2.db.in
new file mode 100644
index 0000000..46aed9b
--- /dev/null
+++ b/bin/tests/system/kasp/ns6/example2.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns6
+ns6 A 10.53.0.6
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
diff --git a/bin/tests/system/kasp/ns6/example3.db.in b/bin/tests/system/kasp/ns6/example3.db.in
new file mode 100644
index 0000000..ccbd96a
--- /dev/null
+++ b/bin/tests/system/kasp/ns6/example3.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 400
+@ IN SOA mname1. . (
+ 3 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns6
+ns6 A 10.53.0.6
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
diff --git a/bin/tests/system/kasp/ns6/named.conf.in b/bin/tests/system/kasp/ns6/named.conf.in
new file mode 100644
index 0000000..c339c44
--- /dev/null
+++ b/bin/tests/system/kasp/ns6/named.conf.in
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS6
+
+include "policies/kasp.conf";
+include "policies/csk1.conf";
+
+options {
+ 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.6; };
+ listen-on-v6 { none; };
+ allow-transfer { any; };
+ recursion no;
+ key-directory ".";
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+/* This zone switch from dynamic to inline-signing. */
+zone "dynamic2inline.kasp" {
+ type primary;
+ file "dynamic2inline.kasp.db";
+ allow-update { any; };
+ dnssec-policy "default";
+};
+
+/* These zones are going insecure. */
+zone "step1.going-insecure.kasp" {
+ type primary;
+ file "step1.going-insecure.kasp.db";
+ inline-signing yes;
+ dnssec-policy "unsigning";
+};
+
+zone "step1.going-insecure-dynamic.kasp" {
+ type primary;
+ file "step1.going-insecure-dynamic.kasp.db";
+ dnssec-policy "unsigning";
+ allow-update { any; };
+};
+
+zone "step1.going-straight-to-none.kasp" {
+ type primary;
+ file "step1.going-straight-to-none.kasp.db";
+ inline-signing yes;
+ dnssec-policy "default";
+};
+
+/* These are alorithm rollover test zones. */
+zone "step1.algorithm-roll.kasp" {
+ type primary;
+ file "step1.algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha256";
+};
+
+zone "step1.csk-algorithm-roll.kasp" {
+ type primary;
+ file "step1.csk-algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "csk-algoroll";
+};
+
+dnssec-policy "modified" {
+ keys {
+ csk lifetime unlimited algorithm rsasha256 2048;
+ };
+};
+
+zone example {
+ type primary;
+ file "example.db";
+ inline-signing yes;
+ dnssec-policy modified;
+};
diff --git a/bin/tests/system/kasp/ns6/named2.conf.in b/bin/tests/system/kasp/ns6/named2.conf.in
new file mode 100644
index 0000000..4d48fd9
--- /dev/null
+++ b/bin/tests/system/kasp/ns6/named2.conf.in
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS6
+
+include "policies/kasp.conf";
+include "policies/csk2.conf";
+
+options {
+ 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.6; };
+ listen-on-v6 { none; };
+ allow-transfer { any; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+/* This zone switch from dynamic to inline-signing. */
+zone "dynamic2inline.kasp" {
+ type primary;
+ file "dynamic2inline.kasp.db";
+ allow-update { any; };
+ inline-signing yes;
+ dnssec-policy "default";
+};
+
+/* Zones for testing going insecure. */
+zone "step1.going-insecure.kasp" {
+ type primary;
+ file "step1.going-insecure.kasp.db";
+ inline-signing yes;
+ dnssec-policy "insecure";
+};
+
+zone "step2.going-insecure.kasp" {
+ type primary;
+ file "step2.going-insecure.kasp.db";
+ inline-signing yes;
+ dnssec-policy "insecure";
+};
+
+zone "step1.going-insecure-dynamic.kasp" {
+ type primary;
+ file "step1.going-insecure-dynamic.kasp.db";
+ dnssec-policy "insecure";
+ allow-update { any; };
+};
+
+zone "step2.going-insecure-dynamic.kasp" {
+ type primary;
+ file "step2.going-insecure-dynamic.kasp.db";
+ dnssec-policy "insecure";
+ allow-update { any; };
+};
+
+zone "step1.going-straight-to-none.kasp" {
+ type primary;
+ file "step1.going-straight-to-none.kasp.db";
+ dnssec-policy "none";
+};
+
+/*
+ * Zones for testing KSK/ZSK algorithm roll.
+ */
+zone "step1.algorithm-roll.kasp" {
+ type primary;
+ file "step1.algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "ecdsa256";
+};
+
+zone "step2.algorithm-roll.kasp" {
+ type primary;
+ file "step2.algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "ecdsa256";
+};
+
+zone "step3.algorithm-roll.kasp" {
+ type primary;
+ file "step3.algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "ecdsa256";
+};
+
+zone "step4.algorithm-roll.kasp" {
+ type primary;
+ file "step4.algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "ecdsa256";
+};
+
+zone "step5.algorithm-roll.kasp" {
+ type primary;
+ file "step5.algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "ecdsa256";
+};
+
+zone "step6.algorithm-roll.kasp" {
+ type primary;
+ file "step6.algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "ecdsa256";
+};
+
+/*
+ * Zones for testing CSK algorithm roll.
+ */
+zone "step1.csk-algorithm-roll.kasp" {
+ type primary;
+ file "step1.csk-algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "csk-algoroll";
+};
+
+zone "step2.csk-algorithm-roll.kasp" {
+ type primary;
+ file "step2.csk-algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "csk-algoroll";
+};
+
+zone "step3.csk-algorithm-roll.kasp" {
+ type primary;
+ file "step3.csk-algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "csk-algoroll";
+};
+
+zone "step4.csk-algorithm-roll.kasp" {
+ type primary;
+ file "step4.csk-algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "csk-algoroll";
+};
+
+zone "step5.csk-algorithm-roll.kasp" {
+ type primary;
+ file "step5.csk-algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "csk-algoroll";
+};
+
+zone "step6.csk-algorithm-roll.kasp" {
+ type primary;
+ file "step6.csk-algorithm-roll.kasp.db";
+ inline-signing yes;
+ dnssec-policy "csk-algoroll";
+};
+
+dnssec-policy "modified" {
+ keys {
+ csk lifetime unlimited algorithm rsasha256 2048;
+ };
+};
+
+zone example {
+ type primary;
+ file "example.db";
+ inline-signing yes;
+ dnssec-policy modified;
+};
diff --git a/bin/tests/system/kasp/ns6/policies/csk1.conf.in b/bin/tests/system/kasp/ns6/policies/csk1.conf.in
new file mode 100644
index 0000000..a5ff042
--- /dev/null
+++ b/bin/tests/system/kasp/ns6/policies/csk1.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "csk-algoroll" {
+ signatures-refresh P5D;
+ signatures-validity 30d;
+ signatures-validity-dnskey 30d;
+
+ keys {
+ csk lifetime unlimited algorithm rsasha256;
+ };
+
+ dnskey-ttl 1h;
+ publish-safety PT1H;
+ retire-safety 2h;
+ zone-propagation-delay 3600;
+ max-zone-ttl 6h;
+ parent-propagation-delay pt1h;
+ parent-ds-ttl 7200;
+};
diff --git a/bin/tests/system/kasp/ns6/policies/csk2.conf.in b/bin/tests/system/kasp/ns6/policies/csk2.conf.in
new file mode 100644
index 0000000..6d290c3
--- /dev/null
+++ b/bin/tests/system/kasp/ns6/policies/csk2.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "csk-algoroll" {
+ signatures-refresh P5D;
+ signatures-validity 30d;
+ signatures-validity-dnskey 30d;
+
+ keys {
+ csk lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ };
+
+ dnskey-ttl 1h;
+ publish-safety PT1H;
+ retire-safety 2h;
+ zone-propagation-delay 3600;
+ max-zone-ttl 6h;
+ parent-propagation-delay pt1h;
+ parent-ds-ttl 7200;
+};
diff --git a/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in b/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in
new file mode 100644
index 0000000..810b91d
--- /dev/null
+++ b/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "unsigning" {
+ dnskey-ttl 7200;
+
+ keys {
+ ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ zsk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@;
+ };
+};
+
+dnssec-policy "nsec3" {
+ nsec3param iterations 0 optout no salt-length 0;
+};
+
+dnssec-policy "rsasha256" {
+ signatures-refresh P5D;
+ signatures-validity 30d;
+ signatures-validity-dnskey 30d;
+
+ keys {
+ ksk lifetime unlimited algorithm rsasha256;
+ zsk lifetime unlimited algorithm rsasha256;
+ };
+
+ dnskey-ttl 1h;
+ publish-safety PT1H;
+ retire-safety 2h;
+ zone-propagation-delay 3600;
+ max-zone-ttl 6h;
+ parent-propagation-delay pt1h;
+ parent-ds-ttl 7200;
+};
+
+dnssec-policy "ecdsa256" {
+ signatures-refresh P5D;
+ signatures-validity 30d;
+ signatures-validity-dnskey 30d;
+
+ keys {
+ ksk lifetime unlimited algorithm ecdsa256;
+ zsk lifetime unlimited algorithm ecdsa256;
+ };
+
+ dnskey-ttl 1h;
+ publish-safety PT1H;
+ retire-safety 2h;
+ zone-propagation-delay 3600;
+ max-zone-ttl 6h;
+ parent-propagation-delay pt1h;
+ parent-ds-ttl 7200;
+};
diff --git a/bin/tests/system/kasp/ns6/policies/kasp.conf.in b/bin/tests/system/kasp/ns6/policies/kasp.conf.in
new file mode 100644
index 0000000..d634b76
--- /dev/null
+++ b/bin/tests/system/kasp/ns6/policies/kasp.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "policies/kasp-fips.conf";
+
+dnssec-policy "rsasha1" {
+ signatures-refresh P5D;
+ signatures-validity 30d;
+ signatures-validity-dnskey 30d;
+
+ keys {
+ ksk lifetime unlimited algorithm rsasha1;
+ zsk lifetime unlimited algorithm rsasha1;
+ };
+
+ dnskey-ttl 1h;
+ publish-safety PT1H;
+ retire-safety 2h;
+ zone-propagation-delay 3600;
+ max-zone-ttl 6h;
+ parent-propagation-delay pt1h;
+ parent-ds-ttl 7200;
+};
diff --git a/bin/tests/system/kasp/ns6/setup.sh b/bin/tests/system/kasp/ns6/setup.sh
new file mode 100644
index 0000000..6764f1b
--- /dev/null
+++ b/bin/tests/system/kasp/ns6/setup.sh
@@ -0,0 +1,409 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns6/setup.sh"
+
+setup() {
+ zone="$1"
+ echo_i "setting up zone: $zone"
+ zonefile="${zone}.db"
+ infile="${zone}.db.infile"
+}
+
+# Make lines shorter by storing key states in environment variables.
+H="HIDDEN"
+R="RUMOURED"
+O="OMNIPRESENT"
+U="UNRETENTIVE"
+
+# The child zones (step1, step2) beneath these zones represent the various
+# steps of unsigning a zone.
+for zn in going-insecure.kasp going-insecure-dynamic.kasp
+do
+ # Step 1:
+ # Set up a zone with dnssec-policy that is going insecure.
+ setup step1.$zn
+ echo "$zone" >> zones
+ T="now-10d"
+ ksktimes="-P $T -A $T -P sync $T"
+ zsktimes="-P $T -A $T"
+ KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.2)
+ cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+ cp $infile $zonefile
+ $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+ # Step 2:
+ # Set up a zone with dnssec-policy that is going insecure. Don't add
+ # this zone to the zones file, because this zone is no longer expected
+ # to be fully signed.
+ setup step2.$zn
+ # The DS was withdrawn from the parent zone 26 hours ago.
+ Trem="now-26h"
+ ksktimes="-P $T -A $T -P sync $T"
+ zsktimes="-P $T -A $T"
+ KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.2)
+ $SETTIME -s -g $H -k $O $T -r $O $T -d $U $Trem -D ds $Trem "$KSK" > settime.out.$zone.1 2>&1
+ $SETTIME -s -g $H -k $O $T -z $O $T "$ZSK" > settime.out.$zone.2 2>&1
+ # Fake lifetime of old algorithm keys.
+ echo "Lifetime: 0" >> "${KSK}.state"
+ echo "Lifetime: 5184000" >> "${ZSK}.state"
+ cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+ cp $infile $zonefile
+ $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+done
+
+# This zone is going straight to "none" policy. This is undefined behavior.
+setup step1.going-straight-to-none.kasp
+echo "$zone" >> zones
+TactN="now"
+csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
+CSK=$($KEYGEN -k default $csktimes $zone 2> keygen.out.$zone.1)
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN -r $O $TactN -d $O $TactN "$CSK" > settime.out.$zone.1 2>&1
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -z -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+#
+# The zones at algorithm-roll.kasp represent the various steps of a ZSK/KSK
+# algorithm rollover.
+#
+
+# Step 1:
+# Introduce the first key. This will immediately be active.
+setup step1.algorithm-roll.kasp
+echo "$zone" >> zones
+TactN="now"
+ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}"
+zsktimes="-P ${TactN} -A ${TactN}"
+KSK=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a RSASHA256 -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" > settime.out.$zone.2 2>&1
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone 8 "$KSK" >> "$infile"
+private_type_record $zone 8 "$ZSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 2:
+# After the publication interval has passed the DNSKEY is OMNIPRESENT.
+setup step2.algorithm-roll.kasp
+# The time passed since the new algorithm keys have been introduced is 3 hours.
+TactN="now-3h"
+TpubN1="now-3h"
+# Tsbm(N+1) = TpubN1 + Ipub = now + TTLsig + Dprp + publish-safety =
+# now - 3h + 6h + 1h + 1h = now + 5h
+TsbmN1="now+5h"
+ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I now"
+zsk1times="-P ${TactN} -A ${TactN} -I now"
+ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
+zsk2times="-P ${TpubN1} -A ${TpubN1}"
+KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2> keygen.out.$zone.1)
+ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2> keygen.out.$zone.2)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2> keygen.out.$zone.3)
+ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2> keygen.out.$zone.4)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" > settime.out.$zone.3 2>&1
+$SETTIME -s -g $O -k $R $TpubN1 -z $R $TpubN1 "$ZSK2" > settime.out.$zone.4 2>&1
+# Fake lifetime of old algorithm keys.
+echo "Lifetime: 0" >> "${KSK1}.state"
+echo "Lifetime: 0" >> "${ZSK1}.state"
+cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" > "$infile"
+private_type_record $zone 8 "$KSK1" >> "$infile"
+private_type_record $zone 8 "$ZSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 3:
+# The zone signatures are also OMNIPRESENT.
+setup step3.algorithm-roll.kasp
+# The time passed since the new algorithm keys have been introduced is 9 hours.
+TactN="now-9h"
+TretN="now-6h"
+TpubN1="now-9h"
+TsbmN1="now-1h"
+ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
+zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
+ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
+zsk2times="-P ${TpubN1} -A ${TpubN1}"
+KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2> keygen.out.$zone.1)
+ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2> keygen.out.$zone.2)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2> keygen.out.$zone.3)
+ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2> keygen.out.$zone.4)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $H $TpubN1 "$KSK2" > settime.out.$zone.3 2>&1
+$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" > settime.out.$zone.4 2>&1
+# Fake lifetime of old algorithm keys.
+echo "Lifetime: 0" >> "${KSK1}.state"
+echo "Lifetime: 0" >> "${ZSK1}.state"
+cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" > "$infile"
+private_type_record $zone 8 "$KSK1" >> "$infile"
+private_type_record $zone 8 "$ZSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 4:
+# The DS is swapped and can become OMNIPRESENT.
+setup step4.algorithm-roll.kasp
+# The time passed since the DS has been swapped is 29 hours.
+TactN="now-38h"
+TretN="now-35h"
+TpubN1="now-38h"
+TsbmN1="now-30h"
+TactN1="now-29h"
+ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
+zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
+ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
+zsk2times="-P ${TpubN1} -A ${TpubN1}"
+KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2> keygen.out.$zone.1)
+ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2> keygen.out.$zone.2)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2> keygen.out.$zone.3)
+ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2> keygen.out.$zone.4)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TactN1 -D ds $TactN1 "$KSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $R $TactN1 -P ds $TactN1 "$KSK2" > settime.out.$zone.3 2>&1
+$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" > settime.out.$zone.4 2>&1
+# Fake lifetime of old algorithm keys.
+echo "Lifetime: 0" >> "${KSK1}.state"
+echo "Lifetime: 0" >> "${ZSK1}.state"
+cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" > "$infile"
+private_type_record $zone 8 "$KSK1" >> "$infile"
+private_type_record $zone 8 "$ZSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 5:
+# The DNSKEY is removed long enough to be HIDDEN.
+setup step5.algorithm-roll.kasp
+# The time passed since the DNSKEY has been removed is 2 hours.
+TactN="now-40h"
+TretN="now-37h"
+TremN="now-2h"
+TpubN1="now-40h"
+TsbmN1="now-32h"
+TactN1="now-31h"
+ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
+zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
+ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
+zsk2times="-P ${TpubN1} -A ${TpubN1}"
+KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2> keygen.out.$zone.1)
+ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2> keygen.out.$zone.2)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2> keygen.out.$zone.3)
+ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2> keygen.out.$zone.4)
+$SETTIME -s -g $H -k $U $TremN -r $U $TremN -d $H $TactN1 "$KSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $H -k $U $TremN -z $U $TremN "$ZSK1" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $O $TactN1 "$KSK2" > settime.out.$zone.3 2>&1
+$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" > settime.out.$zone.4 2>&1
+# Fake lifetime of old algorithm keys.
+echo "Lifetime: 0" >> "${KSK1}.state"
+echo "Lifetime: 0" >> "${ZSK1}.state"
+cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" > "$infile"
+private_type_record $zone 8 "$KSK1" >> "$infile"
+private_type_record $zone 8 "$ZSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 6:
+# The RRSIGs have been removed long enough to be HIDDEN.
+setup step6.algorithm-roll.kasp
+# Additional time passed: 7h.
+TactN="now-47h"
+TretN="now-44h"
+TremN="now-7h"
+TpubN1="now-47h"
+TsbmN1="now-39h"
+TactN1="now-38h"
+TdeaN="now-9h"
+ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
+zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
+ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
+zsk2times="-P ${TpubN1} -A ${TpubN1}"
+KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2> keygen.out.$zone.1)
+ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2> keygen.out.$zone.2)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2> keygen.out.$zone.3)
+ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2> keygen.out.$zone.4)
+$SETTIME -s -g $H -k $H $TremN -r $U $TdeaN -d $H $TactN1 "$KSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $H -k $H $TremN -z $U $TdeaN "$ZSK1" > settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $O $TactN1 "$KSK2" > settime.out.$zone.3 2>&1
+$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" > settime.out.$zone.4 2>&1
+# Fake lifetime of old algorithm keys.
+echo "Lifetime: 0" >> "${KSK1}.state"
+echo "Lifetime: 0" >> "${ZSK1}.state"
+cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" > "$infile"
+private_type_record $zone 8 "$KSK1" >> "$infile"
+private_type_record $zone 8 "$ZSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+#
+# The zones at csk-algorithm-roll.kasp represent the various steps of a CSK
+# algorithm rollover.
+#
+
+# Step 1:
+# Introduce the first key. This will immediately be active.
+setup step1.csk-algorithm-roll.kasp
+echo "$zone" >> zones
+TactN="now"
+csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN}"
+CSK=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2> keygen.out.$zone.1)
+$SETTIME -s -g $O -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK" > settime.out.$zone.1 2>&1
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone 5 "$CSK" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 2:
+# After the publication interval has passed the DNSKEY is OMNIPRESENT.
+setup step2.csk-algorithm-roll.kasp
+# The time passed since the new algorithm keys have been introduced is 3 hours.
+TactN="now-3h"
+TpubN1="now-3h"
+csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I now"
+newtimes="-P ${TpubN1} -A ${TpubN1}"
+CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -z $R $TpubN1 -d $H $TpubN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Fake lifetime of old algorithm keys.
+echo "Lifetime: 0" >> "${CSK1}.state"
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone 5 "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 3:
+# The zone signatures are also OMNIPRESENT.
+setup step3.csk-algorithm-roll.kasp
+# The time passed since the new algorithm keys have been introduced is 9 hours.
+TactN="now-9h"
+TretN="now-6h"
+TpubN1="now-9h"
+TactN1="now-6h"
+csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
+newtimes="-P ${TpubN1} -A ${TpubN1}"
+CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $R $TpubN1 -d $H $TpubN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Fake lifetime of old algorithm keys.
+echo "Lifetime: 0" >> "${CSK1}.state"
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone 5 "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 4:
+# The DS is swapped and can become OMNIPRESENT.
+setup step4.csk-algorithm-roll.kasp
+# The time passed since the DS has been swapped is 29 hours.
+TactN="now-38h"
+TretN="now-35h"
+TpubN1="now-38h"
+TactN1="now-35h"
+TsubN1="now-29h"
+csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
+newtimes="-P ${TpubN1} -A ${TpubN1}"
+CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TactN -d $U $TactN1 -D ds $TactN1 "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $O $TsubN1 -d $R $TsubN1 -P ds $TsubN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Fake lifetime of old algorithm keys.
+echo "Lifetime: 0" >> "${CSK1}.state"
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone 5 "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 5:
+# The DNSKEY is removed long enough to be HIDDEN.
+setup step5.csk-algorithm-roll.kasp
+# The time passed since the DNSKEY has been removed is 2 hours.
+TactN="now-40h"
+TretN="now-37h"
+TremN="now-2h"
+TpubN1="now-40h"
+TactN1="now-37h"
+TsubN1="now-31h"
+csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
+newtimes="-P ${TpubN1} -A ${TpubN1}"
+CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $U $TremN -r $U $TremN -z $U $TremN -d $H $TremN "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $O $TsubN1 -d $O $TremN "$CSK2" > settime.out.$zone.2 2>&1
+# Fake lifetime of old algorithm keys.
+echo "Lifetime: 0" >> "${CSK1}.state"
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone 5 "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+# Step 6:
+# The RRSIGs have been removed long enough to be HIDDEN.
+setup step6.csk-algorithm-roll.kasp
+# Additional time passed: 7h.
+TactN="now-47h"
+TretN="now-44h"
+TdeaN="now-9h"
+TremN="now-7h"
+TpubN1="now-47h"
+TactN1="now-44h"
+TsubN1="now-38h"
+csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
+newtimes="-P ${TpubN1} -A ${TpubN1}"
+CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2> keygen.out.$zone.1)
+CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2> keygen.out.$zone.2)
+$SETTIME -s -g $H -k $H $TremN -r $U $TdeaN -z $U $TdeaN -d $H $TactN1 "$CSK1" > settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $O $TsubN1 -d $O $TactN1 "$CSK2" > settime.out.$zone.2 2>&1
+# Fake lifetime of old algorithm keys.
+echo "Lifetime: 0" >> "${CSK1}.state"
+cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
+private_type_record $zone 5 "$CSK1" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
+cp $infile $zonefile
+$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+#
+# Reload testing
+#
+echo "example" >> zones
+cp example.db.in example.db
+
+setup "dynamic2inline.kasp"
+cp template.db.in $zonefile
diff --git a/bin/tests/system/kasp/ns6/template.db.in b/bin/tests/system/kasp/ns6/template.db.in
new file mode 100644
index 0000000..f1d8b94
--- /dev/null
+++ b/bin/tests/system/kasp/ns6/template.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns6
+ns6 A 10.53.0.6
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+
diff --git a/bin/tests/system/kasp/setup.sh b/bin/tests/system/kasp/setup.sh
new file mode 100644
index 0000000..67cfa92
--- /dev/null
+++ b/bin/tests/system/kasp/setup.sh
@@ -0,0 +1,80 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+$SHELL clean.sh
+
+mkdir keys
+
+copy_setports ns2/named.conf.in ns2/named.conf
+if ! $SHELL ../testcrypto.sh -q RSASHA1
+then
+ copy_setports ns3/named-fips.conf.in ns3/named.conf
+else
+ copy_setports ns3/named-fips.conf.in ns3/named-fips.conf
+ copy_setports ns3/named.conf.in ns3/named.conf
+fi
+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
+
+if $SHELL ../testcrypto.sh ed25519; then
+ echo "yes" > ed25519-supported.file
+fi
+
+if $SHELL ../testcrypto.sh ed448; then
+ echo "yes" > ed448-supported.file
+fi
+
+copy_setports ns3/policies/autosign.conf.in ns3/policies/autosign.conf
+copy_setports ns3/policies/kasp-fips.conf.in ns3/policies/kasp-fips.conf
+copy_setports ns3/policies/kasp.conf.in ns3/policies/kasp.conf
+if ! $SHELL ../testcrypto.sh -q RSASHA1
+then
+ cp ns3/policies/kasp-fips.conf ns3/policies/kasp.conf
+fi
+
+copy_setports ns6/policies/csk1.conf.in ns6/policies/csk1.conf
+copy_setports ns6/policies/csk2.conf.in ns6/policies/csk2.conf
+copy_setports ns6/policies/kasp-fips.conf.in ns6/policies/kasp-fips.conf
+copy_setports ns6/policies/kasp.conf.in ns6/policies/kasp.conf
+if ! $SHELL ../testcrypto.sh -q RSASHA1
+then
+ cp ns6/policies/kasp-fips.conf ns6/policies/kasp.conf
+fi
+
+# Setup zones
+(
+ cd ns2
+ $SHELL setup.sh
+)
+(
+ cd ns3
+ $SHELL setup.sh
+)
+(
+ cd ns4
+ $SHELL setup.sh
+)
+(
+ cd ns5
+ $SHELL setup.sh
+)
+(
+ cd ns6
+ $SHELL setup.sh
+)
diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh
new file mode 100644
index 0000000..ddbbd32
--- /dev/null
+++ b/bin/tests/system/kasp/tests.sh
@@ -0,0 +1,4883 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+# shellcheck source=kasp.sh
+. ../kasp.sh
+
+start_time="$(TZ=UTC date +%s)"
+status=0
+n=0
+
+###############################################################################
+# Utilities #
+###############################################################################
+
+# Call dig with default options.
+dig_with_opts() {
+
+ if [ -n "$TSIG" ]; then
+ "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" -y "$TSIG" "$@"
+ else
+ "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
+ fi
+}
+
+# RNDC.
+rndccmd() {
+ "$RNDC" -c ../common/rndc.conf -p "$CONTROLPORT" -s "$@"
+}
+
+# Log error and increment failure rate.
+log_error() {
+ echo_i "error: $1"
+ ret=$((ret+1))
+}
+
+# Default next key event threshold. May be extended by wait periods.
+next_key_event_threshold=100
+
+###############################################################################
+# Tests #
+###############################################################################
+
+#
+# dnssec-keygen
+#
+set_zone "kasp"
+set_policy "kasp" "4" "200"
+set_server "keys" "10.53.0.1"
+
+n=$((n+1))
+echo_i "check that 'dnssec-keygen -k' (configured policy) creates valid files ($n)"
+ret=0
+$KEYGEN -K keys -k "$POLICY" -l kasp.conf "$ZONE" > "keygen.out.$POLICY.test$n" 2>/dev/null || ret=1
+lines=$(wc -l < "keygen.out.$POLICY.test$n")
+test "$lines" -eq $NUM_KEYS || log_error "wrong number of keys created for policy kasp: $lines"
+# Temporarily don't log errors because we are searching multiple files.
+disable_logerror
+
+# Key properties.
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "31536000"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+
+set_keyrole "KEY2" "ksk"
+set_keylifetime "KEY2" "31536000"
+set_keyalgorithm "KEY2" "8" "RSASHA256" "2048"
+set_keysigning "KEY2" "yes"
+set_zonesigning "KEY2" "no"
+
+set_keyrole "KEY3" "zsk"
+set_keylifetime "KEY3" "2592000"
+set_keyalgorithm "KEY3" "8" "RSASHA256" "2048"
+set_keysigning "KEY3" "no"
+set_zonesigning "KEY3" "yes"
+
+set_keyrole "KEY4" "zsk"
+set_keylifetime "KEY4" "16070400"
+set_keyalgorithm "KEY4" "8" "RSASHA256" "3072"
+set_keysigning "KEY4" "no"
+set_zonesigning "KEY4" "yes"
+
+lines=$(get_keyids "$DIR" "$ZONE" | wc -l)
+test "$lines" -eq $NUM_KEYS || log_error "bad number of key ids"
+
+ids=$(get_keyids "$DIR" "$ZONE")
+for id in $ids; do
+ # There are four key files with the same algorithm.
+ # Check them until a match is found.
+ ret=0 && check_key "KEY1" "$id"
+ test "$ret" -eq 0 && continue
+
+ ret=0 && check_key "KEY2" "$id"
+ test "$ret" -eq 0 && continue
+
+ ret=0 && check_key "KEY3" "$id"
+ test "$ret" -eq 0 && continue
+
+ ret=0 && check_key "KEY4" "$id"
+
+ # If ret is still non-zero, non of the files matched.
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+done
+# Turn error logs on again.
+enable_logerror
+
+n=$((n+1))
+echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
+ret=0
+set_zone "kasp"
+set_policy "default" "1" "3600"
+set_server "." "10.53.0.1"
+# Key properties.
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+$KEYGEN -G -k "$POLICY" "$ZONE" > "keygen.out.$POLICY.test$n" 2>/dev/null || ret=1
+lines=$(wc -l < "keygen.out.$POLICY.test$n")
+test "$lines" -eq $NUM_KEYS || log_error "wrong number of keys created for policy default: $lines"
+ids=$(get_keyids "$DIR" "$ZONE")
+for id in $ids; do
+ check_key "KEY1" "$id"
+ test "$ret" -eq 0 && key_save KEY1
+ check_keytimes
+done
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# dnssec-settime
+#
+
+# These test builds upon the latest created key with dnssec-keygen and uses the
+# environment variables BASE_FILE, KEY_FILE, PRIVATE_FILE and STATE_FILE.
+CMP_FILE="${BASE_FILE}.cmp"
+n=$((n+1))
+echo_i "check that 'dnssec-settime' by default does not edit key state file ($n)"
+ret=0
+cp "$STATE_FILE" "$CMP_FILE"
+$SETTIME -P +3600 "$BASE_FILE" > /dev/null || log_error "settime failed"
+grep "; Publish: " "$KEY_FILE" > /dev/null || log_error "mismatch published in $KEY_FILE"
+grep "Publish: " "$PRIVATE_FILE" > /dev/null || log_error "mismatch published in $PRIVATE_FILE"
+diff "$CMP_FILE" "$STATE_FILE" || log_error "unexpected file change in $STATE_FILE"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check that 'dnssec-settime -s' also sets publish time metadata and states in key state file ($n)"
+ret=0
+cp "$STATE_FILE" "$CMP_FILE"
+now=$(date +%Y%m%d%H%M%S)
+$SETTIME -s -P "$now" -g "omnipresent" -k "rumoured" "$now" -z "omnipresent" "$now" -r "rumoured" "$now" -d "hidden" "$now" "$BASE_FILE" > /dev/null || log_error "settime failed"
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "hidden"
+check_key "KEY1" "$id"
+test "$ret" -eq 0 && key_save KEY1
+set_keytime "KEY1" "PUBLISHED" "${now}"
+check_keytimes
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check that 'dnssec-settime -s' also unsets publish time metadata and states in key state file ($n)"
+ret=0
+cp "$STATE_FILE" "$CMP_FILE"
+$SETTIME -s -P "none" -g "none" -k "none" "$now" -z "none" "$now" -r "none" "$now" -d "none" "$now" "$BASE_FILE" > /dev/null || log_error "settime failed"
+set_keystate "KEY1" "GOAL" "none"
+set_keystate "KEY1" "STATE_DNSKEY" "none"
+set_keystate "KEY1" "STATE_KRRSIG" "none"
+set_keystate "KEY1" "STATE_ZRRSIG" "none"
+set_keystate "KEY1" "STATE_DS" "none"
+check_key "KEY1" "$id"
+test "$ret" -eq 0 && key_save KEY1
+set_keytime "KEY1" "PUBLISHED" "none"
+check_keytimes
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check that 'dnssec-settime -s' also sets active time metadata and states in key state file (uppercase) ($n)"
+ret=0
+cp "$STATE_FILE" "$CMP_FILE"
+now=$(date +%Y%m%d%H%M%S)
+$SETTIME -s -A "$now" -g "HIDDEN" -k "UNRETENTIVE" "$now" -z "UNRETENTIVE" "$now" -r "OMNIPRESENT" "$now" -d "OMNIPRESENT" "$now" "$BASE_FILE" > /dev/null || log_error "settime failed"
+set_keystate "KEY1" "GOAL" "hidden"
+set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_ZRRSIG" "unretentive"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+check_key "KEY1" "$id"
+test "$ret" -eq 0 && key_save KEY1
+set_keytime "KEY1" "ACTIVE" "${now}"
+check_keytimes
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# named
+#
+
+# The NSEC record at the apex of the zone and its RRSIG records are
+# added as part of the last step in signing a zone. We wait for the
+# NSEC records to appear before proceeding with a counter to prevent
+# infinite loops if there is an error.
+n=$((n+1))
+echo_i "waiting for kasp signing changes to take effect ($n)"
+
+_wait_for_done_apexnsec() {
+ while read -r zone
+ do
+ dig_with_opts "$zone" @10.53.0.3 nsec > "dig.out.ns3.test$n.$zone" || return 1
+ grep "NS SOA" "dig.out.ns3.test$n.$zone" > /dev/null || return 1
+ grep "$zone\..*IN.*RRSIG" "dig.out.ns3.test$n.$zone" > /dev/null || return 1
+ done < ns3/zones
+
+ while read -r zone
+ do
+ dig_with_opts "$zone" @10.53.0.6 nsec > "dig.out.ns6.test$n.$zone" || return 1
+ grep "NS SOA" "dig.out.ns6.test$n.$zone" > /dev/null || return 1
+ grep "$zone\..*IN.*RRSIG" "dig.out.ns6.test$n.$zone" > /dev/null || return 1
+ done < ns6/zones
+
+ return 0
+}
+retry_quiet 30 _wait_for_done_apexnsec || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Test max-zone-ttl rejects zones with too high TTL.
+n=$((n+1))
+echo_i "check that max-zone-ttl rejects zones with too high TTL ($n)"
+ret=0
+set_zone "max-zone-ttl.kasp"
+grep "loading from master file ${ZONE}.db failed: out of range" "ns3/named.run" > /dev/null || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Zone: default.kasp.
+#
+set_keytimes_csk_policy() {
+ # The first key is immediately published and activated.
+ created=$(key_get KEY1 CREATED)
+ set_keytime "KEY1" "PUBLISHED" "${created}"
+ set_keytime "KEY1" "ACTIVE" "${created}"
+ # The DS can be published if the DNSKEY and RRSIG records are
+ # OMNIPRESENT. This happens after max-zone-ttl (1d) plus
+ # publish-safety (1h) plus zone-propagation-delay (300s) =
+ # 86400 + 3600 + 300 = 90300.
+ set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 90300
+ # Key lifetime is unlimited, so not setting RETIRED and REMOVED.
+}
+
+# Check the zone with default kasp policy has loaded and is signed.
+set_zone "default.kasp"
+set_policy "default" "1" "3600"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Trigger a keymgr run. Make sure the key files are not touched if there are
+# no modifications to the key metadata.
+n=$((n+1))
+echo_i "make sure key files are untouched if metadata does not change ($n)"
+ret=0
+basefile=$(key_get KEY1 BASEFILE)
+privkey_stat=$(key_get KEY1 PRIVKEY_STAT)
+pubkey_stat=$(key_get KEY1 PUBKEY_STAT)
+state_stat=$(key_get KEY1 STATE_STAT)
+
+nextpart $DIR/named.run > /dev/null
+rndccmd 10.53.0.3 loadkeys "$ZONE" > /dev/null || log_error "rndc loadkeys zone ${ZONE} failed"
+wait_for_log 3 "keymgr: $ZONE done" $DIR/named.run
+privkey_stat2=$(key_stat "${basefile}.private")
+pubkey_stat2=$(key_stat "${basefile}.key")
+state_stat2=$(key_stat "${basefile}.state")
+test "$privkey_stat" = "$privkey_stat2" || log_error "wrong private key file stat (expected $privkey_stat got $privkey_stat2)"
+test "$pubkey_stat" = "$pubkey_stat2" || log_error "wrong public key file stat (expected $pubkey_stat got $pubkey_stat2)"
+test "$state_stat" = "$state_stat2" || log_error "wrong state file stat (expected $state_stat got $state_stat2)"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "again ($n)"
+ret=0
+
+nextpart $DIR/named.run > /dev/null
+rndccmd 10.53.0.3 loadkeys "$ZONE" > /dev/null || log_error "rndc loadkeys zone ${ZONE} failed"
+wait_for_log 3 "keymgr: $ZONE done" $DIR/named.run
+privkey_stat2=$(key_stat "${basefile}.private")
+pubkey_stat2=$(key_stat "${basefile}.key")
+state_stat2=$(key_stat "${basefile}.state")
+test "$privkey_stat" = "$privkey_stat2" || log_error "wrong private key file stat (expected $privkey_stat got $privkey_stat2)"
+test "$pubkey_stat" = "$pubkey_stat2" || log_error "wrong public key file stat (expected $pubkey_stat got $pubkey_stat2)"
+test "$state_stat" = "$state_stat2" || log_error "wrong state file stat (expected $state_stat got $state_stat2)"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Update zone.
+n=$((n+1))
+echo_i "modify unsigned zone file and check that new record is signed for zone ${ZONE} ($n)"
+ret=0
+cp "${DIR}/template2.db.in" "${DIR}/${ZONE}.db"
+rndccmd 10.53.0.3 reload "$ZONE" > /dev/null || log_error "rndc reload zone ${ZONE} failed"
+
+update_is_signed() {
+ ip_a=$1
+ ip_d=$2
+
+ if [ "$ip_a" != "-" ]; then
+ dig_with_opts "a.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n.a" || return 1
+ grep "status: NOERROR" "dig.out.$DIR.test$n.a" > /dev/null || return 1
+ grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*${ip_a}" "dig.out.$DIR.test$n.a" > /dev/null || return 1
+ lines=$(get_keys_which_signed A "dig.out.$DIR.test$n.a" | wc -l)
+ test "$lines" -eq 1 || return 1
+ get_keys_which_signed A "dig.out.$DIR.test$n.a" | grep "^${KEY_ID}$" > /dev/null || return 1
+ fi
+
+ if [ "$ip_d" != "-" ]; then
+ dig_with_opts "d.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n".d || return 1
+ grep "status: NOERROR" "dig.out.$DIR.test$n".d > /dev/null || return 1
+ grep "d.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*${ip_d}" "dig.out.$DIR.test$n".d > /dev/null || return 1
+ lines=$(get_keys_which_signed A "dig.out.$DIR.test$n".d | wc -l)
+ test "$lines" -eq 1 || return 1
+ get_keys_which_signed A "dig.out.$DIR.test$n".d | grep "^${KEY_ID}$" > /dev/null || return 1
+ fi
+}
+
+retry_quiet 10 update_is_signed "10.0.0.11" "10.0.0.44" || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Move the private key file, a rekey event should not introduce replacement
+# keys.
+ret=0
+echo_i "test that if private key files are inaccessible this doesn't trigger a rollover ($n)"
+basefile=$(key_get KEY1 BASEFILE)
+mv "${basefile}.private" "${basefile}.offline"
+rndccmd 10.53.0.3 loadkeys "$ZONE" > /dev/null || log_error "rndc loadkeys zone ${ZONE} failed"
+wait_for_log 3 "offline, policy default" $DIR/named.run || ret=1
+mv "${basefile}.offline" "${basefile}.private"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Nothing has changed.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: dynamic.kasp
+#
+set_zone "dynamic.kasp"
+set_dynamic
+set_policy "default" "1" "3600"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Update zone with nsupdate.
+n=$((n+1))
+echo_i "nsupdate zone and check that new record is signed for zone ${ZONE} ($n)"
+ret=0
+(
+echo zone ${ZONE}
+echo server 10.53.0.3 "$PORT"
+echo update del "a.${ZONE}" 300 A 10.0.0.1
+echo update add "a.${ZONE}" 300 A 10.0.0.101
+echo update add "d.${ZONE}" 300 A 10.0.0.4
+echo send
+) | $NSUPDATE
+
+retry_quiet 10 update_is_signed "10.0.0.101" "10.0.0.4" || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Update zone with nsupdate (reverting the above change).
+n=$((n+1))
+echo_i "nsupdate zone and check that new record is signed for zone ${ZONE} ($n)"
+ret=0
+(
+echo zone ${ZONE}
+echo server 10.53.0.3 "$PORT"
+echo update add "a.${ZONE}" 300 A 10.0.0.1
+echo update del "a.${ZONE}" 300 A 10.0.0.101
+echo update del "d.${ZONE}" 300 A 10.0.0.4
+echo send
+) | $NSUPDATE
+
+retry_quiet 10 update_is_signed "10.0.0.1" "-" || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Update zone with freeze/thaw.
+n=$((n+1))
+echo_i "modify zone file and check that new record is signed for zone ${ZONE} ($n)"
+ret=0
+rndccmd 10.53.0.3 freeze "$ZONE" > /dev/null || log_error "rndc freeze zone ${ZONE} failed"
+sleep 1
+echo "d.${ZONE}. 300 A 10.0.0.44" >> "${DIR}/${ZONE}.db"
+rndccmd 10.53.0.3 thaw "$ZONE" > /dev/null || log_error "rndc thaw zone ${ZONE} failed"
+
+retry_quiet 10 update_is_signed "10.0.0.1" "10.0.0.44" || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Zone: dynamic-inline-signing.kasp
+#
+set_zone "dynamic-inline-signing.kasp"
+set_dynamic
+set_policy "default" "1" "3600"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Update zone with freeze/thaw.
+n=$((n+1))
+echo_i "modify unsigned zone file and check that new record is signed for zone ${ZONE} ($n)"
+ret=0
+rndccmd 10.53.0.3 freeze "$ZONE" > /dev/null || log_error "rndc freeze zone ${ZONE} failed"
+sleep 1
+cp "${DIR}/template2.db.in" "${DIR}/${ZONE}.db"
+rndccmd 10.53.0.3 thaw "$ZONE" > /dev/null || log_error "rndc thaw zone ${ZONE} failed"
+
+retry_quiet 10 update_is_signed || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Zone: inline-signing.kasp
+#
+set_zone "inline-signing.kasp"
+set_policy "default" "1" "3600"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: checkds-ksk.kasp.
+#
+key_clear "KEY1"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+set_zone "checkds-ksk.kasp"
+set_policy "checkds-ksk" "2" "303"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+set_keyrole "KEY2" "zsk"
+set_keylifetime "KEY2" "0"
+set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY2" "no"
+set_zonesigning "KEY2" "yes"
+# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+basefile=$(key_get KEY1 BASEFILE)
+
+_wait_for_metadata() {
+ _expr=$1
+ _file=$2
+ grep "$_expr" $_file > /dev/null || return 1
+ return 0
+}
+
+n=$((n+1))
+echo_i "checkds publish correctly sets DSPublish for zone $ZONE ($n)"
+now=$(date +%Y%m%d%H%M%S)
+rndc_checkds "$SERVER" "$DIR" "-" "$now" "published" "$ZONE"
+retry_quiet 3 _wait_for_metadata "DSPublish: $now" "${basefile}.state" || log_error "bad DSPublish in ${basefile}.state"
+# DS State should be forced into RUMOURED.
+set_keystate "KEY1" "STATE_DS" "rumoured"
+check_keys
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checkds withdraw correctly sets DSRemoved for zone $ZONE ($n)"
+now=$(date +%Y%m%d%H%M%S)
+rndc_checkds "$SERVER" "$DIR" "-" "$now" "withdrawn" "$ZONE"
+retry_quiet 3 _wait_for_metadata "DSRemoved: $now" "${basefile}.state" || log_error "bad DSRemoved in ${basefile}.state"
+# DS State should be forced into UNRETENTIVE.
+set_keystate "KEY1" "STATE_DS" "unretentive"
+check_keys
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Zone: checkds-doubleksk.kasp.
+#
+key_clear "KEY1"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+set_zone "checkds-doubleksk.kasp"
+set_policy "checkds-doubleksk" "3" "303"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+set_keyrole "KEY2" "ksk"
+set_keylifetime "KEY2" "0"
+set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY2" "yes"
+set_zonesigning "KEY2" "no"
+
+set_keyrole "KEY3" "zsk"
+set_keylifetime "KEY3" "0"
+set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY3" "no"
+set_zonesigning "KEY3" "yes"
+# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY2" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY2" "STATE_DS" "hidden"
+
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_ZRRSIG" "rumoured"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+basefile1=$(key_get KEY1 BASEFILE)
+basefile2=$(key_get KEY2 BASEFILE)
+
+n=$((n+1))
+echo_i "checkds published does not set DSPublish for zone $ZONE (multiple KSK) ($n)"
+rndc_checkds "$SERVER" "$DIR" "-" "20200102121314" "published" "$ZONE"
+grep "DSPublish:" "${basefile1}.state" > /dev/null && log_error "DSPublish incorrectly set in ${basefile1}"
+grep "DSPublish:" "${basefile2}.state" > /dev/null && log_error "DSPublish incorrectly set in ${basefile2}"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checkds withdrawn does not set DSRemoved for zone $ZONE (multiple KSK) ($n)"
+rndc_checkds "$SERVER" "$DIR" "-" "20190102121314" "withdrawn" "$ZONE"
+grep "DSRemoved:" "${basefile1}.state" > /dev/null && log_error "DSRemoved incorrectly set in ${basefile1}"
+grep "DSRemoved:" "${basefile2}.state" > /dev/null && log_error "DSRemoved incorrectly set in ${basefile2}"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checkds published does not set DSPublish for zone $ZONE (wrong algorithm) ($n)"
+rndccmd "$SERVER" dnssec -checkds -key $(key_get KEY1 ID) -alg 8 "published" "$ZONE" > rndc.dnssec.checkds.out.$ZONE.$n
+grep "DSPublish:" "${basefile1}.state" > /dev/null && log_error "DSPublish incorrectly set in ${basefile1}"
+grep "DSPublish:" "${basefile2}.state" > /dev/null && log_error "DSPublish incorrectly set in ${basefile2}"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checkds withdrawn does not set DSRemoved for zone $ZONE (wrong algorithm) ($n)"
+rndccmd "$SERVER" dnssec -checkds -key $(key_get KEY1 ID) -alg RSASHA256 "withdrawn" "$ZONE" > rndc.dnssec.checkds.out.$ZONE.$n
+grep "DSRemoved:" "${basefile1}.state" > /dev/null && log_error "DSRemoved incorrectly set in ${basefile1}"
+grep "DSRemoved:" "${basefile2}.state" > /dev/null && log_error "DSRemoved incorrectly set in ${basefile2}"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checkds published -key correctly sets DSPublish for key $(key_get KEY1 ID) zone $ZONE (multiple KSK) ($n)"
+rndc_checkds "$SERVER" "$DIR" KEY1 "20190102121314" "published" "$ZONE"
+retry_quiet 3 _wait_for_metadata "DSPublish: 20190102121314" "${basefile1}.state" || log_error "bad DSPublish in ${basefile1}.state"
+grep "DSPublish:" "${basefile2}.state" > /dev/null && log_error "DSPublish incorrectly set in ${basefile2}"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checkds withdrawn -key correctly sets DSRemoved for key $(key_get KEY2 ID) zone $ZONE (multiple KSK) ($n)"
+rndc_checkds "$SERVER" "$DIR" KEY2 "20200102121314" "withdrawn" "$ZONE"
+grep "DSRemoved:" "${basefile1}.state" > /dev/null && log_error "DSPublish incorrectly set in ${basefile1}"
+retry_quiet 3 _wait_for_metadata "DSRemoved: 20200102121314" "${basefile2}.state" || log_error "bad DSRemoved in ${basefile2}.state"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Zone: checkds-csk.kasp.
+#
+key_clear "KEY1"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+set_zone "checkds-csk.kasp"
+set_policy "checkds-csk" "1" "303"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+basefile=$(key_get KEY1 BASEFILE)
+
+n=$((n+1))
+echo_i "checkds publish correctly sets DSPublish for zone $ZONE ($n)"
+rndc_checkds "$SERVER" "$DIR" "-" "20190102121314" "published" "$ZONE"
+retry_quiet 3 _wait_for_metadata "DSPublish: 20190102121314" "${basefile}.state" || log_error "bad DSPublish in ${basefile}.state"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checkds withdraw correctly sets DSRemoved for zone $ZONE ($n)"
+rndc_checkds "$SERVER" "$DIR" "-" "20200102121314" "withdrawn" "$ZONE"
+retry_quiet 3 _wait_for_metadata "DSRemoved: 20200102121314" "${basefile}.state" || log_error "bad DSRemoved in ${basefile}.state"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Set keytimes for dnssec-policy with various algorithms.
+# These all use the same time values.
+set_keytimes_algorithm_policy() {
+ # The first KSK is immediately published and activated.
+ created=$(key_get KEY1 CREATED)
+ set_keytime "KEY1" "PUBLISHED" "${created}"
+ set_keytime "KEY1" "ACTIVE" "${created}"
+ # Key was pregenerated.
+ if [ "$1" = "pregenerated" ]; then
+ keyfile=$(key_get KEY1 BASEFILE)
+ grep "; Publish:" "${keyfile}.key" > published.test${n}.key1
+ published=$(awk '{print $3}' < published.test${n}.key1)
+ set_keytime "KEY1" "PUBLISHED" "${published}"
+ set_keytime "KEY1" "ACTIVE" "${published}"
+ fi
+ published=$(key_get KEY1 PUBLISHED)
+
+ # The DS can be published if the DNSKEY and RRSIG records are
+ # OMNIPRESENT. This happens after max-zone-ttl (1d) plus
+ # publish-safety (1h) plus zone-propagation-delay (300s) =
+ # 86400 + 3600 + 300 = 90300.
+ set_addkeytime "KEY1" "SYNCPUBLISH" "${published}" 90300
+ # Key lifetime is 10 years, 315360000 seconds.
+ set_addkeytime "KEY1" "RETIRED" "${published}" 315360000
+ # The key is removed after the retire time plus DS TTL (1d),
+ # parent propagation delay (1h), and retire safety (1h) =
+ # 86400 + 3600 + 3600 = 93600.
+ retired=$(key_get KEY1 RETIRED)
+ set_addkeytime "KEY1" "REMOVED" "${retired}" 93600
+
+ # The first ZSKs are immediately published and activated.
+ created=$(key_get KEY2 CREATED)
+ set_keytime "KEY2" "PUBLISHED" "${created}"
+ set_keytime "KEY2" "ACTIVE" "${created}"
+ # Key was pregenerated.
+ if [ "$1" = "pregenerated" ]; then
+ keyfile=$(key_get KEY2 BASEFILE)
+ grep "; Publish:" "${keyfile}.key" > published.test${n}.key2
+ published=$(awk '{print $3}' < published.test${n}.key2)
+ set_keytime "KEY2" "PUBLISHED" "${published}"
+ set_keytime "KEY2" "ACTIVE" "${published}"
+ fi
+ published=$(key_get KEY2 PUBLISHED)
+
+ # Key lifetime for KSK2 is 5 years, 157680000 seconds.
+ set_addkeytime "KEY2" "RETIRED" "${published}" 157680000
+ # The key is removed after the retire time plus max zone ttl (1d), zone
+ # propagation delay (300s), retire safety (1h), and sign delay
+ # (signature validity minus refresh, 9d) =
+ # 86400 + 300 + 3600 + 777600 = 867900.
+ retired=$(key_get KEY2 RETIRED)
+ set_addkeytime "KEY2" "REMOVED" "${retired}" 867900
+
+ # Second ZSK (KEY3).
+ created=$(key_get KEY3 CREATED)
+ set_keytime "KEY3" "PUBLISHED" "${created}"
+ set_keytime "KEY3" "ACTIVE" "${created}"
+ # Key was pregenerated.
+ if [ "$1" = "pregenerated" ]; then
+ keyfile=$(key_get KEY3 BASEFILE)
+ grep "; Publish:" "${keyfile}.key" > published.test${n}.key3
+ published=$(awk '{print $3}' < published.test${n}.key3)
+ set_keytime "KEY3" "PUBLISHED" "${published}"
+ set_keytime "KEY3" "ACTIVE" "${published}"
+ fi
+ published=$(key_get KEY3 PUBLISHED)
+
+ # Key lifetime for KSK3 is 1 year, 31536000 seconds.
+ set_addkeytime "KEY3" "RETIRED" "${published}" 31536000
+ retired=$(key_get KEY3 RETIRED)
+ set_addkeytime "KEY3" "REMOVED" "${retired}" 867900
+}
+
+#
+# Zone: rsasha1.kasp.
+#
+if $SHELL ../testcrypto.sh -q RSASHA1
+then
+ set_zone "rsasha1.kasp"
+ set_policy "rsasha1" "3" "1234"
+ set_server "ns3" "10.53.0.3"
+ # Key properties.
+ key_clear "KEY1"
+ set_keyrole "KEY1" "ksk"
+ set_keylifetime "KEY1" "315360000"
+ set_keyalgorithm "KEY1" "5" "RSASHA1" "2048"
+ set_keysigning "KEY1" "yes"
+ set_zonesigning "KEY1" "no"
+
+ key_clear "KEY2"
+ set_keyrole "KEY2" "zsk"
+ set_keylifetime "KEY2" "157680000"
+ set_keyalgorithm "KEY2" "5" "RSASHA1" "2048"
+ set_keysigning "KEY2" "no"
+ set_zonesigning "KEY2" "yes"
+
+ key_clear "KEY3"
+ set_keyrole "KEY3" "zsk"
+ set_keylifetime "KEY3" "31536000"
+ set_keyalgorithm "KEY3" "5" "RSASHA1" "2000"
+ set_keysigning "KEY3" "no"
+ set_zonesigning "KEY3" "yes"
+
+ # KSK: DNSKEY, RRSIG (ksk) published. DS needs to wait.
+ # ZSK: DNSKEY, RRSIG (zsk) published.
+ set_keystate "KEY1" "GOAL" "omnipresent"
+ set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+ set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+ set_keystate "KEY1" "STATE_DS" "hidden"
+
+ set_keystate "KEY2" "GOAL" "omnipresent"
+ set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+ set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
+
+ set_keystate "KEY3" "GOAL" "omnipresent"
+ set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+ set_keystate "KEY3" "STATE_ZRRSIG" "rumoured"
+ # Three keys only.
+ key_clear "KEY4"
+
+ check_keys
+ check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+ set_keytimes_algorithm_policy
+ check_keytimes
+ check_apex
+ check_subdomain
+ dnssec_verify
+fi
+
+#
+# Zone: unsigned.kasp.
+#
+set_zone "unsigned.kasp"
+set_policy "none" "0" "0"
+set_server "ns3" "10.53.0.3"
+
+key_clear "KEY1"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+# Make sure the zone file is untouched.
+n=$((n+1))
+echo_i "Make sure the zonefile for zone ${ZONE} is not edited ($n)"
+ret=0
+diff "${DIR}/${ZONE}.db.infile" "${DIR}/${ZONE}.db" || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Zone: insecure.kasp.
+#
+set_zone "insecure.kasp"
+set_policy "insecure" "0" "0"
+set_server "ns3" "10.53.0.3"
+
+key_clear "KEY1"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+#
+# Zone: unlimited.kasp.
+#
+set_zone "unlimited.kasp"
+set_policy "unlimited" "1" "1234"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: inherit.kasp.
+#
+set_zone "inherit.kasp"
+set_policy "rsasha256" "3" "1234"
+set_server "ns3" "10.53.0.3"
+
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "315360000"
+set_keyalgorithm "KEY1" "8" "RSASHA256" "2048"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+key_clear "KEY2"
+set_keyrole "KEY2" "zsk"
+set_keylifetime "KEY2" "157680000"
+set_keyalgorithm "KEY2" "8" "RSASHA256" "2048"
+set_keysigning "KEY2" "no"
+set_zonesigning "KEY2" "yes"
+
+key_clear "KEY3"
+set_keyrole "KEY3" "zsk"
+set_keylifetime "KEY3" "31536000"
+set_keyalgorithm "KEY3" "8" "RSASHA256" "3072"
+set_keysigning "KEY3" "no"
+set_zonesigning "KEY3" "yes"
+# KSK: DNSKEY, RRSIG (ksk) published. DS needs to wait.
+# ZSK: DNSKEY, RRSIG (zsk) published.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
+
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_ZRRSIG" "rumoured"
+# Three keys only.
+key_clear "KEY4"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_algorithm_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: dnssec-keygen.kasp.
+#
+set_zone "dnssec-keygen.kasp"
+set_policy "rsasha256" "3" "1234"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_algorithm_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: some-keys.kasp.
+#
+set_zone "some-keys.kasp"
+set_policy "rsasha256" "3" "1234"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_algorithm_policy "pregenerated"
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: pregenerated.kasp.
+#
+# There are more pregenerated keys than needed, hence the number of keys is
+# six, not three.
+set_zone "pregenerated.kasp"
+set_policy "rsasha256" "6" "1234"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_algorithm_policy "pregenerated"
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: rumoured.kasp.
+#
+# There are three keys in rumoured state.
+set_zone "rumoured.kasp"
+set_policy "rsasha256" "3" "1234"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_algorithm_policy
+# Activation date is a day later.
+set_addkeytime "KEY1" "ACTIVE" $(key_get KEY1 ACTIVE) 86400
+set_addkeytime "KEY1" "RETIRED" $(key_get KEY1 RETIRED) 86400
+set_addkeytime "KEY1" "REMOVED" $(key_get KEY1 REMOVED) 86400
+set_addkeytime "KEY2" "ACTIVE" $(key_get KEY2 ACTIVE) 86400
+set_addkeytime "KEY2" "RETIRED" $(key_get KEY2 RETIRED) 86400
+set_addkeytime "KEY2" "REMOVED" $(key_get KEY2 REMOVED) 86400
+set_addkeytime "KEY3" "ACTIVE" $(key_get KEY3 ACTIVE) 86400
+set_addkeytime "KEY3" "RETIRED" $(key_get KEY3 RETIRED) 86400
+set_addkeytime "KEY3" "REMOVED" $(key_get KEY3 REMOVED) 86400
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: secondary.kasp.
+#
+set_zone "secondary.kasp"
+set_policy "rsasha256" "3" "1234"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_algorithm_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Update zone.
+n=$((n+1))
+echo_i "check that we correctly sign the zone after IXFR for zone ${ZONE} ($n)"
+ret=0
+cp ns2/secondary.kasp.db.in2 ns2/secondary.kasp.db
+rndccmd 10.53.0.2 reload "$ZONE" > /dev/null || log_error "rndc reload zone ${ZONE} failed"
+
+_wait_for_done_subdomains() {
+ ret=0
+ dig_with_opts "a.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n.a" || return 1
+ grep "status: NOERROR" "dig.out.$DIR.test$n.a" > /dev/null || return 1
+ grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.11" "dig.out.$DIR.test$n.a" > /dev/null || return 1
+ check_signatures $_qtype "dig.out.$DIR.test$n.a" "ZSK"
+ if [ $ret -gt 0 ]; then return $ret; fi
+
+ dig_with_opts "d.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n.d" || return 1
+ grep "status: NOERROR" "dig.out.$DIR.test$n.d" > /dev/null || return 1
+ grep "d.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.4" "dig.out.$DIR.test$n.d" > /dev/null || return 1
+ check_signatures $_qtype "dig.out.$DIR.test$n.d" "ZSK"
+ return $ret
+}
+retry_quiet 5 _wait_for_done_subdomains || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# TODO: we might want to test:
+# - configuring a zone with too many active keys (should trigger retire).
+# - configuring a zone with keys not matching the policy.
+
+#
+# Zone: rsasha1-nsec3.kasp.
+#
+if $SHELL ../testcrypto.sh -q RSASHA1
+then
+ set_zone "rsasha1-nsec3.kasp"
+ set_policy "rsasha1-nsec3" "3" "1234"
+ set_server "ns3" "10.53.0.3"
+ # Key properties.
+ set_keyalgorithm "KEY1" "7" "NSEC3RSASHA1" "2048"
+ set_keyalgorithm "KEY2" "7" "NSEC3RSASHA1" "2048"
+ set_keyalgorithm "KEY3" "7" "NSEC3RSASHA1" "2000"
+ # Key timings and states same as above.
+
+ check_keys
+ check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+ set_keytimes_algorithm_policy
+ check_keytimes
+ check_apex
+ check_subdomain
+ dnssec_verify
+fi
+
+#
+# Zone: rsasha256.kasp.
+#
+set_zone "rsasha256.kasp"
+set_policy "rsasha256" "3" "1234"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+set_keyalgorithm "KEY1" "8" "RSASHA256" "2048"
+set_keyalgorithm "KEY2" "8" "RSASHA256" "2048"
+set_keyalgorithm "KEY3" "8" "RSASHA256" "3072"
+# Key timings and states same as above.
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_algorithm_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: rsasha512.kasp.
+#
+set_zone "rsasha512.kasp"
+set_policy "rsasha512" "3" "1234"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+set_keyalgorithm "KEY1" "10" "RSASHA512" "2048"
+set_keyalgorithm "KEY2" "10" "RSASHA512" "2048"
+set_keyalgorithm "KEY3" "10" "RSASHA512" "3072"
+# Key timings and states same as above.
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_algorithm_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: ecdsa256.kasp.
+#
+set_zone "ecdsa256.kasp"
+set_policy "ecdsa256" "3" "1234"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
+set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256"
+# Key timings and states same as above.
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_algorithm_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: ecdsa512.kasp.
+#
+set_zone "ecdsa384.kasp"
+set_policy "ecdsa384" "3" "1234"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+set_keyalgorithm "KEY1" "14" "ECDSAP384SHA384" "384"
+set_keyalgorithm "KEY2" "14" "ECDSAP384SHA384" "384"
+set_keyalgorithm "KEY3" "14" "ECDSAP384SHA384" "384"
+# Key timings and states same as above.
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_algorithm_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: ed25519.kasp.
+#
+if [ -f ed25519-supported.file ]; then
+ set_zone "ed25519.kasp"
+ set_policy "ed25519" "3" "1234"
+ set_server "ns3" "10.53.0.3"
+ # Key properties.
+ set_keyalgorithm "KEY1" "15" "ED25519" "256"
+ set_keyalgorithm "KEY2" "15" "ED25519" "256"
+ set_keyalgorithm "KEY3" "15" "ED25519" "256"
+ # Key timings and states same as above.
+
+ check_keys
+ check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+ set_keytimes_algorithm_policy
+ check_keytimes
+ check_apex
+ check_subdomain
+ dnssec_verify
+fi
+
+#
+# Zone: ed448.kasp.
+#
+if [ -f ed448-supported.file ]; then
+ set_zone "ed448.kasp"
+ set_policy "ed448" "3" "1234"
+ set_server "ns3" "10.53.0.3"
+ # Key properties.
+ set_keyalgorithm "KEY1" "16" "ED448" "456"
+ set_keyalgorithm "KEY2" "16" "ED448" "456"
+ set_keyalgorithm "KEY3" "16" "ED448" "456"
+ # Key timings and states same as above.
+
+ check_keys
+ check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+ set_keytimes_algorithm_policy
+ check_keytimes
+ check_apex
+ check_subdomain
+ dnssec_verify
+fi
+
+# Set key times for 'autosign' policy.
+set_keytimes_autosign_policy() {
+ # The KSK was published six months ago (with settime).
+ created=$(key_get KEY1 CREATED)
+ set_addkeytime "KEY1" "PUBLISHED" "${created}" -15552000
+ set_addkeytime "KEY1" "ACTIVE" "${created}" -15552000
+ set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -15552000
+ # Key lifetime is 2 years, 63072000 seconds.
+ active=$(key_get KEY1 ACTIVE)
+ set_addkeytime "KEY1" "RETIRED" "${active}" 63072000
+ # The key is removed after the retire time plus DS TTL (1d),
+ # parent propagation delay (1h), retire safety (1h) =
+ # 86400 + 3600 + 3600 = 93600
+ retired=$(key_get KEY1 RETIRED)
+ set_addkeytime "KEY1" "REMOVED" "${retired}" 93600
+
+ # The ZSK was published six months ago (with settime).
+ created=$(key_get KEY2 CREATED)
+ set_addkeytime "KEY2" "PUBLISHED" "${created}" -15552000
+ set_addkeytime "KEY2" "ACTIVE" "${created}" -15552000
+ # Key lifetime for KSK2 is 1 year, 31536000 seconds.
+ active=$(key_get KEY2 ACTIVE)
+ set_addkeytime "KEY2" "RETIRED" "${active}" 31536000
+ # The key is removed after the retire time plus:
+ # TTLsig (RRSIG TTL): 1 day (86400 seconds)
+ # Dprp (propagation delay): 5 minutes (300 seconds)
+ # retire-safety: 1 hour (3600 seconds)
+ # Dsgn (sign delay): 7 days (604800 seconds)
+ # Iret: 695100 seconds.
+ retired=$(key_get KEY2 RETIRED)
+ set_addkeytime "KEY2" "REMOVED" "${retired}" 695100
+}
+
+#
+# Zone: expired-sigs.autosign.
+#
+set_zone "expired-sigs.autosign"
+set_policy "autosign" "2" "300"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "63072000"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+key_clear "KEY2"
+set_keyrole "KEY2" "zsk"
+set_keylifetime "KEY2" "31536000"
+set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY2" "no"
+set_zonesigning "KEY2" "yes"
+
+# Both KSK and ZSK stay OMNIPRESENT.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+# Expect only two keys.
+key_clear "KEY3"
+key_clear "KEY4"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_autosign_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Verify all signatures have been refreshed.
+check_rrsig_refresh() {
+ # Apex.
+ _qtypes="DNSKEY SOA NS NSEC"
+ for _qtype in $_qtypes
+ do
+ n=$((n+1))
+ echo_i "check ${_qtype} rrsig is refreshed correctly for zone ${ZONE} ($n)"
+ ret=0
+ dig_with_opts "$ZONE" "@${SERVER}" "$_qtype" > "dig.out.$DIR.test$n" || log_error "dig ${ZONE} ${_qtype} failed"
+ grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
+ grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" "dig.out.$DIR.test$n" > "rrsig.out.$ZONE.$_qtype" || log_error "missing RRSIG (${_qtype}) record in response"
+ # If this exact RRSIG is also in the zone file it is not refreshed.
+ _rrsig=$(cat "rrsig.out.$ZONE.$_qtype")
+ grep "${_rrsig}" "${DIR}/${ZONE}.db" > /dev/null && log_error "RRSIG (${_qtype}) not refreshed in zone ${ZONE}"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+ done
+
+ # Below apex.
+ _labels="a b c ns3"
+ for _label in $_labels;
+ do
+ _qtypes="A NSEC"
+ for _qtype in $_qtypes
+ do
+ n=$((n+1))
+ echo_i "check ${_label} ${_qtype} rrsig is refreshed correctly for zone ${ZONE} ($n)"
+ ret=0
+ dig_with_opts "${_label}.${ZONE}" "@${SERVER}" "$_qtype" > "dig.out.$DIR.test$n" || log_error "dig ${_label}.${ZONE} ${_qtype} failed"
+ grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
+ grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" "dig.out.$DIR.test$n" > "rrsig.out.$ZONE.$_qtype" || log_error "missing RRSIG (${_qtype}) record in response"
+ _rrsig=$(cat "rrsig.out.$ZONE.$_qtype")
+ grep "${_rrsig}" "${DIR}/${ZONE}.db" > /dev/null && log_error "RRSIG (${_qtype}) not refreshed in zone ${ZONE}"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+ done
+ done
+}
+
+check_rrsig_refresh
+
+#
+# Zone: fresh-sigs.autosign.
+#
+set_zone "fresh-sigs.autosign"
+set_policy "autosign" "2" "300"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_autosign_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Verify signature reuse.
+check_rrsig_reuse() {
+ # Apex.
+ _qtypes="NS NSEC"
+ for _qtype in $_qtypes
+ do
+ n=$((n+1))
+ echo_i "check ${_qtype} rrsig is reused correctly for zone ${ZONE} ($n)"
+ ret=0
+ dig_with_opts "$ZONE" "@${SERVER}" "$_qtype" > "dig.out.$DIR.test$n" || log_error "dig ${ZONE} ${_qtype} failed"
+ grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
+ grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" "dig.out.$DIR.test$n" > "rrsig.out.$ZONE.$_qtype" || log_error "missing RRSIG (${_qtype}) record in response"
+ # If this exact RRSIG is also in the signed zone file it is not refreshed.
+ _rrsig=$(awk '{print $5, $6, $7, $8, $9, $10, $11, $12, $13, $14;}' < "rrsig.out.$ZONE.$_qtype")
+ $CHECKZONE -f raw -F text -s full -o zone.out.${ZONE}.test$n "${ZONE}" "${DIR}/${ZONE}.db.signed" > /dev/null
+ grep "${_rrsig}" zone.out.${ZONE}.test$n > /dev/null || log_error "RRSIG (${_qtype}) not reused in zone ${ZONE}"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+ done
+
+ # Below apex.
+ _labels="a b c ns3"
+ for _label in $_labels;
+ do
+ _qtypes="A NSEC"
+ for _qtype in $_qtypes
+ do
+ n=$((n+1))
+ echo_i "check ${_label} ${_qtype} rrsig is reused correctly for zone ${ZONE} ($n)"
+ ret=0
+ dig_with_opts "${_label}.${ZONE}" "@${SERVER}" "$_qtype" > "dig.out.$DIR.test$n" || log_error "dig ${_label}.${ZONE} ${_qtype} failed"
+ grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
+ grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" "dig.out.$DIR.test$n" > "rrsig.out.$ZONE.$_qtype" || log_error "missing RRSIG (${_qtype}) record in response"
+ # If this exact RRSIG is also in the signed zone file it is not refreshed.
+ _rrsig=$(awk '{print $5, $6, $7, $8, $9, $10, $11, $12, $13, $14;}' < "rrsig.out.$ZONE.$_qtype")
+ $CHECKZONE -f raw -F text -s full -o zone.out.${ZONE}.test$n "${ZONE}" "${DIR}/${ZONE}.db.signed" > /dev/null
+ grep "${_rrsig}" zone.out.${ZONE}.test$n > /dev/null || log_error "RRSIG (${_qtype}) not reused in zone ${ZONE}"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+ done
+ done
+}
+
+check_rrsig_reuse
+
+#
+# Zone: unfresh-sigs.autosign.
+#
+set_zone "unfresh-sigs.autosign"
+set_policy "autosign" "2" "300"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_autosign_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+check_rrsig_refresh
+
+#
+# Zone: ksk-missing.autosign.
+#
+set_zone "ksk-missing.autosign"
+set_policy "autosign" "2" "300"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+# Skip checking the private file, because it is missing.
+key_set "KEY1" "PRIVATE" "no"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+# Restore the PRIVATE variable.
+key_set "KEY1" "PRIVATE" "yes"
+
+#
+# Zone: zsk-missing.autosign.
+#
+set_zone "zsk-missing.autosign"
+set_policy "autosign" "2" "300"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+# Skip checking the private file, because it is missing.
+key_set "KEY2" "PRIVATE" "no"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# For the apex, we expect the SOA to be signed with the KSK because the ZSK is
+# offline. Temporary treat KEY1 as a zone signing key too.
+set_keyrole "KEY1" "csk"
+set_zonesigning "KEY1" "yes"
+set_zonesigning "KEY2" "no"
+check_apex
+set_keyrole "KEY1" "ksk"
+set_zonesigning "KEY1" "no"
+set_zonesigning "KEY2" "yes"
+check_subdomain
+dnssec_verify
+
+# Restore the PRIVATE variable.
+key_set "KEY2" "PRIVATE" "yes"
+
+#
+# Zone: zsk-retired.autosign.
+#
+set_zone "zsk-retired.autosign"
+set_policy "autosign" "3" "300"
+set_server "ns3" "10.53.0.3"
+# The third key is not yet expected to be signing.
+set_keyrole "KEY3" "zsk"
+set_keylifetime "KEY3" "31536000"
+set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY3" "no"
+set_zonesigning "KEY3" "no"
+# The ZSK goal is set to HIDDEN but records stay OMNIPRESENT until the new ZSK
+# is active.
+set_keystate "KEY2" "GOAL" "hidden"
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+# A new ZSK should be introduced, so expect a key with goal OMNIPRESENT,
+# the DNSKEY introduced (RUMOURED) and the signatures HIDDEN.
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_ZRRSIG" "hidden"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_autosign_policy
+
+# The old ZSK is retired.
+created=$(key_get KEY2 CREATED)
+set_keytime "KEY2" "RETIRED" "${created}"
+set_addkeytime "KEY2" "REMOVED" "${created}" 695100
+# The new ZSK is immediately published.
+created=$(key_get KEY3 CREATED)
+set_keytime "KEY3" "PUBLISHED" "${created}"
+# And becomes active after Ipub:
+# DNSKEY TTL: 300 seconds
+# zone-propagation-delay 5 minutes (300 seconds)
+# publish-safety: 1 hour (3600 seconds)
+# Ipub: 4200 seconds
+published=$(key_get KEY3 PUBLISHED)
+set_addkeytime "KEY3" "ACTIVE" "${published}" 4200
+# Lzsk: 1 year (31536000 seconds)
+active=$(key_get KEY3 ACTIVE)
+set_addkeytime "KEY3" "RETIRED" "${active}" 31536000
+# Iret: 695100 seconds.
+retired=$(key_get KEY3 RETIRED)
+set_addkeytime "KEY3" "REMOVED" "${retired}" 695100
+
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+check_rrsig_refresh
+
+#
+# Zone: legacy-keys.kasp.
+#
+set_zone "legacy-keys.kasp"
+# This zone has two active keys and two old keys left in key directory, so
+# expect 4 key files.
+set_policy "migrate-to-dnssec-policy" "4" "1234"
+set_server "ns3" "10.53.0.3"
+
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "16070400"
+set_keyalgorithm "KEY1" "8" "RSASHA256" "2048"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+key_clear "KEY2"
+set_keyrole "KEY2" "zsk"
+set_keylifetime "KEY2" "16070400"
+set_keyalgorithm "KEY2" "8" "RSASHA256" "2048"
+set_keysigning "KEY2" "no"
+set_zonesigning "KEY2" "yes"
+# KSK: DNSKEY, RRSIG (ksk) published. DS needs to wait.
+# ZSK: DNSKEY, RRSIG (zsk) published.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
+# Two keys only.
+key_clear "KEY3"
+key_clear "KEY4"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Make sure the correct legacy keys were used (and not the removed predecessor
+# keys).
+n=$((n+1))
+echo_i "check correct keys were used when migrating zone ${ZONE} to dnssec-policy ($n)"
+ret=0
+kskfile=$(cat ns3/legacy-keys.kasp.ksk)
+basefile=$(key_get KEY1 BASEFILE)
+echo_i "filename: $basefile (expect $kskfile)"
+test "$DIR/$kskfile" = "$basefile" || ret=1
+zskfile=$(cat ns3/legacy-keys.kasp.zsk)
+basefile=$(key_get KEY2 BASEFILE)
+echo_i "filename: $basefile (expect $zskfile)"
+test "$DIR/$zskfile" = "$basefile" || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# KSK times.
+created=$(key_get KEY1 CREATED)
+keyfile=$(key_get KEY1 BASEFILE)
+grep "; Publish:" "${keyfile}.key" > published.test${n}.key1
+published=$(awk '{print $3}' < published.test${n}.key1)
+set_keytime "KEY1" "PUBLISHED" "${published}"
+set_keytime "KEY1" "ACTIVE" "${published}"
+published=$(key_get KEY1 PUBLISHED)
+# The DS can be published if the DNSKEY and RRSIG records are OMNIPRESENT.
+# This happens after max-zone-ttl (1d) plus publish-safety (1h) plus
+# zone-propagation-delay (300s) = 86400 + 3600 + 300 = 90300.
+set_addkeytime "KEY1" "SYNCPUBLISH" "${published}" 90300
+# Key lifetime is 6 months, 315360000 seconds.
+set_addkeytime "KEY1" "RETIRED" "${published}" 16070400
+# The key is removed after the retire time plus DS TTL (1d), parent
+# propagation delay (1h), and retire safety (1h) = 86400 + 3600 + 3600 = 93600.
+retired=$(key_get KEY1 RETIRED)
+set_addkeytime "KEY1" "REMOVED" "${retired}" 93600
+
+# ZSK times.
+created=$(key_get KEY2 CREATED)
+keyfile=$(key_get KEY2 BASEFILE)
+grep "; Publish:" "${keyfile}.key" > published.test${n}.key2
+published=$(awk '{print $3}' < published.test${n}.key2)
+set_keytime "KEY2" "PUBLISHED" "${published}"
+set_keytime "KEY2" "ACTIVE" "${published}"
+published=$(key_get KEY2 PUBLISHED)
+# Key lifetime is 6 months, 315360000 seconds.
+set_addkeytime "KEY2" "RETIRED" "${published}" 16070400
+# The key is removed after the retire time plus max zone ttl (1d), zone
+# propagation delay (300s), retire safety (1h), and sign delay (signature
+# validity minus refresh, 9d) = 86400 + 300 + 3600 + 777600 = 867900.
+retired=$(key_get KEY2 RETIRED)
+set_addkeytime "KEY2" "REMOVED" "${retired}" 867900
+
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Test dnssec-policy inheritance.
+#
+
+# These zones should be unsigned:
+# ns2/unsigned.tld
+# ns4/none.inherit.signed
+# ns4/none.override.signed
+# ns4/inherit.none.signed
+# ns4/none.none.signed
+# ns5/inherit.inherit.unsigned
+# ns5/none.inherit.unsigned
+# ns5/none.override.unsigned
+# ns5/inherit.none.unsigned
+# ns5/none.none.unsigned
+key_clear "KEY1"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+set_zone "unsigned.tld"
+set_policy "none" "0" "0"
+set_server "ns2" "10.53.0.2"
+TSIG=""
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+set_zone "none.inherit.signed"
+set_policy "none" "0" "0"
+set_server "ns4" "10.53.0.4"
+TSIG="hmac-sha1:sha1:$SHA1"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+set_zone "none.override.signed"
+set_policy "none" "0" "0"
+set_server "ns4" "10.53.0.4"
+TSIG="hmac-sha224:sha224:$SHA224"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+set_zone "inherit.none.signed"
+set_policy "none" "0" "0"
+set_server "ns4" "10.53.0.4"
+TSIG="hmac-sha256:sha256:$SHA256"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+set_zone "none.none.signed"
+set_policy "none" "0" "0"
+set_server "ns4" "10.53.0.4"
+TSIG="hmac-sha256:sha256:$SHA256"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+set_zone "inherit.inherit.unsigned"
+set_policy "none" "0" "0"
+set_server "ns5" "10.53.0.5"
+TSIG="hmac-sha1:sha1:$SHA1"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+set_zone "none.inherit.unsigned"
+set_policy "none" "0" "0"
+set_server "ns5" "10.53.0.5"
+TSIG="hmac-sha1:sha1:$SHA1"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+set_zone "none.override.unsigned"
+set_policy "none" "0" "0"
+set_server "ns5" "10.53.0.5"
+TSIG="hmac-sha224:sha224:$SHA224"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+set_zone "inherit.none.unsigned"
+set_policy "none" "0" "0"
+set_server "ns5" "10.53.0.5"
+TSIG="hmac-sha256:sha256:$SHA256"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+set_zone "none.none.unsigned"
+set_policy "none" "0" "0"
+set_server "ns5" "10.53.0.5"
+TSIG="hmac-sha256:sha256:$SHA256"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+# These zones should be signed with the default policy:
+# ns2/signed.tld
+# ns4/override.inherit.signed
+# ns4/inherit.override.signed
+# ns5/override.inherit.signed
+# ns5/inherit.override.signed
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+
+set_zone "signed.tld"
+set_policy "default" "1" "3600"
+set_server "ns2" "10.53.0.2"
+TSIG=""
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+set_zone "override.inherit.signed"
+set_policy "default" "1" "3600"
+set_server "ns4" "10.53.0.4"
+TSIG="hmac-sha1:sha1:$SHA1"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+set_zone "inherit.override.signed"
+set_policy "default" "1" "3600"
+set_server "ns4" "10.53.0.4"
+TSIG="hmac-sha224:sha224:$SHA224"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+set_zone "override.inherit.unsigned"
+set_policy "default" "1" "3600"
+set_server "ns5" "10.53.0.5"
+TSIG="hmac-sha1:sha1:$SHA1"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+set_zone "inherit.override.unsigned"
+set_policy "default" "1" "3600"
+set_server "ns5" "10.53.0.5"
+TSIG="hmac-sha224:sha224:$SHA224"
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# These zones should be signed with the test policy:
+# ns4/inherit.inherit.signed
+# ns4/override.override.signed
+# ns4/override.none.signed
+# ns5/override.override.unsigned
+# ns5/override.none.unsigned
+# ns4/example.net (both views)
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "14" "ECDSAP384SHA384" "384"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+
+set_zone "inherit.inherit.signed"
+set_policy "test" "1" "3600"
+set_server "ns4" "10.53.0.4"
+TSIG="hmac-sha1:sha1:$SHA1"
+wait_for_nsec
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+set_zone "override.override.signed"
+set_policy "test" "1" "3600"
+set_server "ns4" "10.53.0.4"
+TSIG="hmac-sha224:sha224:$SHA224"
+wait_for_nsec
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+set_zone "override.none.signed"
+set_policy "test" "1" "3600"
+set_server "ns4" "10.53.0.4"
+TSIG="hmac-sha256:sha256:$SHA256"
+wait_for_nsec
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+set_zone "override.override.unsigned"
+set_policy "test" "1" "3600"
+set_server "ns5" "10.53.0.5"
+TSIG="hmac-sha224:sha224:$SHA224"
+wait_for_nsec
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+set_zone "override.none.unsigned"
+set_policy "test" "1" "3600"
+set_server "ns5" "10.53.0.5"
+TSIG="hmac-sha256:sha256:$SHA256"
+wait_for_nsec
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Test with views.
+set_zone "example.net"
+set_server "ns4" "10.53.0.4"
+TSIG="$DEFAULT_HMAC:keyforview1:$VIEW1"
+wait_for_nsec
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" "example1"
+set_keytimes_csk_policy
+check_keytimes
+check_apex
+dnssec_verify
+# check zonestatus
+n=$((n+1))
+echo_i "check $ZONE (view example1) zonestatus ($n)"
+ret=0
+check_isdynamic "$SERVER" "$ZONE" "example1" || log_error "zone not dynamic"
+check_inlinesigning "$SERVER" "$ZONE" "example1" && log_error "inline-signing enabled, expected disabled"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+# check subdomain
+n=$((n+1))
+echo_i "check TXT example.net (view example1) rrset is signed correctly ($n)"
+ret=0
+dig_with_opts "view.${ZONE}" "@${SERVER}" TXT > "dig.out.$DIR.test$n.txt" || log_error "dig view.${ZONE} TXT failed"
+grep "status: NOERROR" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "mismatch status in DNS response"
+grep "view.${ZONE}\..*${DEFAULT_TTL}.*IN.*TXT.*view1" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "missing view.${ZONE} TXT record in response"
+check_signatures TXT "dig.out.$DIR.test$n.txt" "ZSK"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+TSIG="$DEFAULT_HMAC:keyforview2:$VIEW2"
+wait_for_nsec
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" "example2"
+check_apex
+dnssec_verify
+# check zonestatus
+n=$((n+1))
+echo_i "check $ZONE (view example2) zonestatus ($n)"
+ret=0
+check_isdynamic "$SERVER" "$ZONE" "example2" && log_error "zone dynamic, but not expected"
+check_inlinesigning "$SERVER" "$ZONE" "example2" || log_error "inline-signing disabled, expected enabled"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+# check subdomain
+n=$((n+1))
+echo_i "check TXT example.net (view example2) rrset is signed correctly ($n)"
+ret=0
+dig_with_opts "view.${ZONE}" "@${SERVER}" TXT > "dig.out.$DIR.test$n.txt" || log_error "dig view.${ZONE} TXT failed"
+grep "status: NOERROR" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "mismatch status in DNS response"
+grep "view.${ZONE}\..*${DEFAULT_TTL}.*IN.*TXT.*view2" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "missing view.${ZONE} TXT record in response"
+check_signatures TXT "dig.out.$DIR.test$n.txt" "ZSK"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+TSIG="$DEFAULT_HMAC:keyforview3:$VIEW3"
+wait_for_nsec
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" "example3"
+check_apex
+dnssec_verify
+# check zonestatus
+n=$((n+1))
+echo_i "check $ZONE (view example3) zonestatus ($n)"
+ret=0
+check_isdynamic "$SERVER" "$ZONE" "example3" && log_error "zone dynamic, but not expected"
+check_inlinesigning "$SERVER" "$ZONE" "example3" || log_error "inline-signing disabled, expected enabled"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+# check subdomain
+n=$((n+1))
+echo_i "check TXT example.net (view example3) rrset is signed correctly ($n)"
+ret=0
+dig_with_opts "view.${ZONE}" "@${SERVER}" TXT > "dig.out.$DIR.test$n.txt" || log_error "dig view.${ZONE} TXT failed"
+grep "status: NOERROR" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "mismatch status in DNS response"
+grep "view.${ZONE}\..*${DEFAULT_TTL}.*IN.*TXT.*view2" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "missing view.${ZONE} TXT record in response"
+check_signatures TXT "dig.out.$DIR.test$n.txt" "ZSK"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Clear TSIG.
+TSIG=""
+
+#
+# Testing RFC 8901 Multi-Signer Model 2.
+#
+set_zone "multisigner-model2.kasp"
+set_policy "multisigner-model2" "2" "3600"
+set_server "ns3" "10.53.0.3"
+key_clear "KEY1"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# Key properties.
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+set_keyrole "KEY2" "zsk"
+set_keylifetime "KEY2" "0"
+set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY2" "no"
+set_zonesigning "KEY2" "yes"
+
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+# Check that the ZSKs from the other provider are published.
+zsks_are_published() {
+ dig_with_opts +short "$ZONE" "@${SERVER}" DNSKEY > "dig.out.$DIR.test$n" || return 1
+ # We should have three ZSKs.
+ lines=$(grep "256 3 13" dig.out.$DIR.test$n | wc -l)
+ test "$lines" -eq 3 || return 1
+ # And one KSK.
+ lines=$(grep "257 3 13" dig.out.$DIR.test$n | wc -l)
+ test "$lines" -eq 1 || return 1
+}
+
+n=$((n+1))
+echo_i "update zone with ZSK from another provider for zone ${ZONE} ($n)"
+ret=0
+(
+echo zone ${ZONE}
+echo server 10.53.0.3 "$PORT"
+echo update add $(cat "${DIR}/${ZONE}.zsk2")
+echo send
+) | $NSUPDATE
+retry_quiet 10 zsks_are_published || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Testing manual rollover.
+#
+set_zone "manual-rollover.kasp"
+set_policy "manual-rollover" "2" "3600"
+set_server "ns3" "10.53.0.3"
+key_clear "KEY1"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+# Key properties.
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+set_keyrole "KEY2" "zsk"
+set_keylifetime "KEY2" "0"
+set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY2" "no"
+set_zonesigning "KEY2" "yes"
+# During set up everything was set to OMNIPRESENT.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# The first keys were published and activated a day ago.
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -86400
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -86400
+set_addkeytime "KEY1" "ACTIVE" "${created}" -86400
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -86400
+set_addkeytime "KEY2" "ACTIVE" "${created}" -86400
+# Key lifetimes are unlimited, so not setting RETIRED and REMOVED.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Schedule KSK rollover in six months (15552000 seconds).
+active=$(key_get KEY1 ACTIVE)
+set_addkeytime "KEY1" "RETIRED" "${active}" 15552000
+retired=$(key_get KEY1 RETIRED)
+rndc_rollover "$SERVER" "$DIR" $(key_get KEY1 ID) "${retired}" "$ZONE"
+# Rollover starts in six months, but lifetime is set to six months plus
+# prepublication duration = 15552000 + 7500 = 15559500 seconds.
+set_keylifetime "KEY1" "15559500"
+set_addkeytime "KEY1" "RETIRED" "${active}" 15559500
+retired=$(key_get KEY1 RETIRED)
+# Retire interval of this policy is 26h (93600 seconds).
+set_addkeytime "KEY1" "REMOVED" "${retired}" 93600
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Schedule KSK rollover now.
+set_policy "manual-rollover" "3" "3600"
+set_keystate "KEY1" "GOAL" "hidden"
+# This key was activated one day ago, so lifetime is set to 1d plus
+# prepublication duration (7500 seconds) = 93900 seconds.
+set_keylifetime "KEY1" "93900"
+created=$(key_get KEY1 CREATED)
+set_keytime "KEY1" "RETIRED" "${created}"
+rndc_rollover "$SERVER" "$DIR" $(key_get KEY1 ID) "${created}" "$ZONE"
+# New key is introduced.
+set_keyrole "KEY3" "ksk"
+set_keylifetime "KEY3" "0"
+set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY3" "yes"
+set_zonesigning "KEY3" "no"
+
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY3" "STATE_DS" "hidden"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+# Schedule ZSK rollover now.
+set_policy "manual-rollover" "4" "3600"
+set_keystate "KEY2" "GOAL" "hidden"
+# This key was activated one day ago, so lifetime is set to 1d plus
+# prepublication duration (7500 seconds) = 93900 seconds.
+set_keylifetime "KEY2" "93900"
+created=$(key_get KEY2 CREATED)
+set_keytime "KEY2" "RETIRED" "${created}"
+rndc_rollover "$SERVER" "$DIR" $(key_get KEY2 ID) "${created}" "$ZONE"
+# New key is introduced.
+set_keyrole "KEY4" "zsk"
+set_keylifetime "KEY4" "0"
+set_keyalgorithm "KEY4" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY4" "no"
+set_zonesigning "KEY4" "no" # not yet, first prepublish DNSKEY.
+
+set_keystate "KEY4" "GOAL" "omnipresent"
+set_keystate "KEY4" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY4" "STATE_ZRRSIG" "hidden"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+# Try to schedule a ZSK rollover for an inactive key (should fail).
+n=$((n+1))
+echo_i "check that rndc dnssec -rollover fails if key is inactive ($n)"
+ret=0
+rndccmd "$SERVER" dnssec -rollover -key $(key_get KEY4 ID) "$ZONE" > rndc.dnssec.rollover.out.$ZONE.$n || ret=1
+grep "key is not actively signing" rndc.dnssec.rollover.out.$ZONE.$n > /dev/null || log_error "bad error message"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Testing DNSSEC introduction.
+#
+
+#
+# Zone: step1.enable-dnssec.autosign.
+#
+set_zone "step1.enable-dnssec.autosign"
+set_policy "enable-dnssec" "1" "300"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+# The DNSKEY and signatures are introduced first, the DS remains hidden.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+# This policy lists only one key (CSK).
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The first key is immediately published and activated.
+created=$(key_get KEY1 CREATED)
+set_keytime "KEY1" "PUBLISHED" "${created}"
+set_keytime "KEY1" "ACTIVE" "${created}"
+# - The DS can be published if the DNSKEY and RRSIG records are
+# OMNIPRESENT. This happens after max-zone-ttl (12h) plus
+# publish-safety (5m) plus zone-propagation-delay (5m) =
+# 43200 + 300 + 300 = 43800.
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 43800
+# - Key lifetime is unlimited, so not setting RETIRED and REMOVED.
+
+# Various signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+_check_next_key_event() {
+ _expect=$1
+
+ grep "zone ${ZONE}.*: next key event in .* seconds" "${DIR}/named.run" > "keyevent.out.$ZONE.test$n" || return 1
+
+ # Get the latest next key event.
+ if [ "${DYNAMIC}" = "yes" ]; then
+ _time=$(awk '{print $9}' < "keyevent.out.$ZONE.test$n" | tail -1)
+ else
+ # inline-signing zone adds "(signed)"
+ _time=$(awk '{print $10}' < "keyevent.out.$ZONE.test$n" | tail -1)
+ fi
+
+ # The next key event time must within threshold of the
+ # expected time.
+ _expectmin=$((_expect-next_key_event_threshold))
+ _expectmax=$((_expect+next_key_event_threshold))
+
+ test $_expectmin -le "$_time" || return 1
+ test $_expectmax -ge "$_time" || return 1
+
+ return 0
+}
+
+check_next_key_event() {
+ n=$((n+1))
+ echo_i "check next key event for zone ${ZONE} ($n)"
+ ret=0
+
+ retry_quiet 3 _check_next_key_event $1 || log_error "bad next key event time for zone ${ZONE} (expect ${_expect})"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+}
+
+# Next key event is when the DNSKEY RRset becomes OMNIPRESENT: DNSKEY TTL plus
+# publish safety plus the zone propagation delay: 900 seconds.
+check_next_key_event 900
+
+#
+# Zone: step2.enable-dnssec.autosign.
+#
+set_zone "step2.enable-dnssec.autosign"
+set_policy "enable-dnssec" "1" "300"
+set_server "ns3" "10.53.0.3"
+# The DNSKEY is omnipresent, but the zone signatures not yet.
+# Thus, the DS remains hidden.
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The key was published and activated 900 seconds ago (with settime).
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -900
+set_addkeytime "KEY1" "ACTIVE" "${created}" -900
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 43800
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the zone signatures become OMNIPRESENT: max-zone-ttl
+# plus zone propagation delay plus retire safety minus the already elapsed
+# 900 seconds: 12h + 300s + 20m - 900 = 44700 - 900 = 43800 seconds
+check_next_key_event 43800
+
+#
+# Zone: step3.enable-dnssec.autosign.
+#
+set_zone "step3.enable-dnssec.autosign"
+set_policy "enable-dnssec" "1" "300"
+set_server "ns3" "10.53.0.3"
+# All signatures should be omnipresent, so the DS can be submitted.
+set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "rumoured"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The key was published and activated 44700 seconds ago (with settime).
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -44700
+set_addkeytime "KEY1" "ACTIVE" "${created}" -44700
+set_keytime "KEY1" "SYNCPUBLISH" "${created}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+# Check that CDS publication is logged.
+check_cdslog "$DIR" "$ZONE" KEY1
+
+# The DS can be introduced. We ignore any parent registration delay, so set
+# the DS publish time to now.
+rndc_checkds "$SERVER" "$DIR" KEY1 "now" "published" "$ZONE"
+# Next key event is when the DS can move to the OMNIPRESENT state. This occurs
+# when the parent propagation delay have passed, plus the DS TTL and retire
+# safety delay: 1h + 2h + 20m = 3h20m = 12000 seconds
+check_next_key_event 12000
+
+#
+# Zone: step4.enable-dnssec.autosign.
+#
+set_zone "step4.enable-dnssec.autosign"
+set_policy "enable-dnssec" "1" "300"
+set_server "ns3" "10.53.0.3"
+# The DS is omnipresent.
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The key was published and activated 56700 seconds ago (with settime).
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -56700
+set_addkeytime "KEY1" "ACTIVE" "${created}" -56700
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -12000
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is never, the zone dnssec-policy has been established. So we
+# fall back to the default loadkeys interval.
+check_next_key_event 3600
+
+#
+# Testing ZSK Pre-Publication rollover.
+#
+
+# Policy parameters.
+# Lksk: 2 years (63072000 seconds)
+# Lzsk: 30 days (2592000 seconds)
+# Iret(KSK): DS TTL (1d) + DprpP (1h) + retire-safety (2d)
+# Iret(KSK): 3d1h (262800 seconds)
+# Iret(ZSK): RRSIG TTL (1d) + Dprp (1h) + Dsgn (1w) + retire-safety (2d)
+# Iret(ZSK): 10d1h (867600 seconds)
+Lksk=63072000
+Lzsk=2592000
+IretKSK=262800
+IretZSK=867600
+
+#
+# Zone: step1.zsk-prepub.autosign.
+#
+set_zone "step1.zsk-prepub.autosign"
+set_policy "zsk-prepub" "2" "3600"
+set_server "ns3" "10.53.0.3"
+
+set_retired_removed() {
+ _Lkey=$2
+ _Iret=$3
+
+ _active=$(key_get $1 ACTIVE)
+ set_addkeytime "${1}" "RETIRED" "${_active}" "${_Lkey}"
+ _retired=$(key_get $1 RETIRED)
+ set_addkeytime "${1}" "REMOVED" "${_retired}" "${_Iret}"
+}
+
+rollover_predecessor_keytimes() {
+ _addtime=$1
+
+ _created=$(key_get KEY1 CREATED)
+ set_addkeytime "KEY1" "PUBLISHED" "${_created}" "${_addtime}"
+ set_addkeytime "KEY1" "SYNCPUBLISH" "${_created}" "${_addtime}"
+ set_addkeytime "KEY1" "ACTIVE" "${_created}" "${_addtime}"
+ [ "$Lksk" = 0 ] || set_retired_removed "KEY1" "${Lksk}" "${IretKSK}"
+
+ _created=$(key_get KEY2 CREATED)
+ set_addkeytime "KEY2" "PUBLISHED" "${_created}" "${_addtime}"
+ set_addkeytime "KEY2" "ACTIVE" "${_created}" "${_addtime}"
+ [ "$Lzsk" = 0 ] || set_retired_removed "KEY2" "${Lzsk}" "${IretZSK}"
+}
+
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "${Lksk}"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+key_clear "KEY2"
+set_keyrole "KEY2" "zsk"
+set_keylifetime "KEY2" "${Lzsk}"
+set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY2" "no"
+set_zonesigning "KEY2" "yes"
+# Both KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+# Initially only two keys.
+key_clear "KEY3"
+key_clear "KEY4"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# These keys are immediately published and activated.
+rollover_predecessor_keytimes 0
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the successor ZSK needs to be published. That is
+# the ZSK lifetime - prepublication time. The prepublication time is DNSKEY
+# TTL plus publish safety plus the zone propagation delay. For the
+# zsk-prepub policy that means: 30d - 3600s + 1d + 1h = 2498400 seconds.
+check_next_key_event 2498400
+
+#
+# Zone: step2.zsk-prepub.autosign.
+#
+set_zone "step2.zsk-prepub.autosign"
+set_policy "zsk-prepub" "3" "3600"
+set_server "ns3" "10.53.0.3"
+# New ZSK (KEY3) is prepublished, but not yet signing.
+key_clear "KEY3"
+set_keyrole "KEY3" "zsk"
+set_keylifetime "KEY3" "${Lzsk}"
+set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY3" "no"
+set_zonesigning "KEY3" "no"
+# Key states.
+set_keystate "KEY2" "GOAL" "hidden"
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_ZRRSIG" "hidden"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys were activated 694 hours ago (2498400 seconds).
+rollover_predecessor_keytimes -2498400
+# - The new ZSK is published now.
+created=$(key_get KEY3 CREATED)
+set_keytime "KEY3" "PUBLISHED" "${created}"
+# - The new ZSK becomes active when the DNSKEY is OMNIPRESENT.
+# Ipub: TTLkey (1h) + Dprp (1h) + publish-safety (1d)
+# Ipub: 26 hour (93600 seconds).
+IpubZSK=93600
+set_addkeytime "KEY3" "ACTIVE" "${created}" "${IpubZSK}"
+set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the successor ZSK becomes OMNIPRESENT. That is the
+# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For
+# the zsk-prepub policy, this means: 3600s + 1h + 1d = 93600 seconds.
+check_next_key_event 93600
+
+#
+# Zone: step3.zsk-prepub.autosign.
+#
+set_zone "step3.zsk-prepub.autosign"
+set_policy "zsk-prepub" "3" "3600"
+set_server "ns3" "10.53.0.3"
+# ZSK (KEY2) no longer is actively signing, RRSIG state in UNRETENTIVE.
+# New ZSK (KEY3) is now actively signing, RRSIG state in RUMOURED.
+set_zonesigning "KEY2" "no"
+set_keystate "KEY2" "STATE_ZRRSIG" "unretentive"
+set_zonesigning "KEY3" "yes"
+set_keystate "KEY3" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY3" "STATE_ZRRSIG" "rumoured"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys are activated 30 days ago (2592000 seconds).
+rollover_predecessor_keytimes -2592000
+# - The new ZSK is published 26 hours ago (93600 seconds).
+created=$(key_get KEY3 CREATED)
+set_addkeytime "KEY3" "PUBLISHED" "${created}" -93600
+set_keytime "KEY3" "ACTIVE" "${created}"
+set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+# Subdomain still has good signatures of ZSK (KEY2).
+# Set expected zone signing on for KEY2 and off for KEY3,
+# testing whether signatures which are still valid are being reused.
+set_zonesigning "KEY2" "yes"
+set_zonesigning "KEY3" "no"
+check_subdomain
+# Restore the expected zone signing properties.
+set_zonesigning "KEY2" "no"
+set_zonesigning "KEY3" "yes"
+dnssec_verify
+
+# Next key event is when all the RRSIG records have been replaced with
+# signatures of the new ZSK, in other words when ZRRSIG becomes OMNIPRESENT.
+# That is Dsgn plus the maximum zone TTL plus the zone propagation delay plus
+# retire-safety. For the zsk-prepub policy that means: 1w (because 2w validity
+# and refresh within a week) + 1d + 1h + 2d = 10d1h = 867600 seconds.
+check_next_key_event 867600
+
+#
+# Zone: step4.zsk-prepub.autosign.
+#
+set_zone "step4.zsk-prepub.autosign"
+set_policy "zsk-prepub" "3" "3600"
+set_server "ns3" "10.53.0.3"
+# ZSK (KEY2) DNSKEY is no longer needed.
+# ZSK (KEY3) is now actively signing, RRSIG state in RUMOURED.
+set_keystate "KEY2" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY2" "STATE_ZRRSIG" "hidden"
+set_keystate "KEY3" "STATE_ZRRSIG" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys are activated 961 hours ago (3459600 seconds).
+rollover_predecessor_keytimes -3459600
+# - The new ZSK is published 267 hours ago (961200 seconds).
+created=$(key_get KEY3 CREATED)
+set_addkeytime "KEY3" "PUBLISHED" "${created}" -961200
+published=$(key_get KEY3 PUBLISHED)
+set_addkeytime "KEY3" "ACTIVE" "${published}" "${IpubZSK}"
+set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the DNSKEY enters the HIDDEN state. This is the
+# DNSKEY TTL plus zone propagation delay. For the zsk-prepub policy this is:
+# 3600s + 1h = 7200s
+check_next_key_event 7200
+
+#
+# Zone: step5.zsk-prepub.autosign.
+#
+set_zone "step5.zsk-prepub.autosign"
+set_policy "zsk-prepub" "3" "3600"
+set_server "ns3" "10.53.0.3"
+# ZSK (KEY2) DNSKEY is now completely HIDDEN and removed.
+set_keystate "KEY2" "STATE_DNSKEY" "hidden"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys are activated 962 hours ago (3463200 seconds).
+rollover_predecessor_keytimes -3463200
+# - The new ZSK is published 268 hours ago (964800 seconds).
+created=$(key_get KEY3 CREATED)
+set_addkeytime "KEY3" "PUBLISHED" "${created}" -964800
+published=$(key_get KEY3 PUBLISHED)
+set_addkeytime "KEY3" "ACTIVE" "${published}" "${IpubZSK}"
+set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the new successor needs to be published. This is the
+# ZSK lifetime minus Iret minus Ipub minus DNSKEY TTL. For the zsk-prepub
+# policy this is: 30d - 867600s - 93600s - 3600s = 1627200 seconds.
+check_next_key_event 1627200
+
+#
+# Zone: step6.zsk-prepub.autosign.
+#
+set_zone "step6.zsk-prepub.autosign"
+set_policy "zsk-prepub" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# ZSK (KEY2) DNSKEY is purged.
+key_clear "KEY2"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Testing KSK Double-KSK rollover.
+#
+
+# Policy parameters.
+# Lksk: 60 days (16070400 seconds)
+# Lzsk: 1 year (31536000 seconds)
+# Iret(KSK): DS TTL (1h) + DprpP (1h) + retire-safety (2d)
+# Iret(KSK): 50h (180000 seconds)
+# Iret(ZSK): RRSIG TTL (1d) + Dprp (1h) + Dsgn (1w) + retire-safety (2d)
+# Iret(ZSK): 10d1h (867600 seconds)
+Lksk=5184000
+Lzsk=31536000
+IretKSK=180000
+IretZSK=867600
+
+#
+# Zone: step1.ksk-doubleksk.autosign.
+#
+set_zone "step1.ksk-doubleksk.autosign"
+set_policy "ksk-doubleksk" "2" "7200"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "${Lksk}"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+key_clear "KEY2"
+set_keyrole "KEY2" "zsk"
+set_keylifetime "KEY2" "${Lzsk}"
+set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY2" "no"
+set_zonesigning "KEY2" "yes"
+# Both KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+# Initially only two keys.
+key_clear "KEY3"
+key_clear "KEY4"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# These keys are immediately published and activated.
+rollover_predecessor_keytimes 0
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the successor KSK needs to be published. That is
+# the KSK lifetime - prepublication time. The prepublication time is
+# DNSKEY TTL plus publish safety plus the zone propagation delay.
+# For the ksk-doubleksk policy that means: 60d - (1d3h) = 5086800 seconds.
+check_next_key_event 5086800
+
+#
+# Zone: step2.ksk-doubleksk.autosign.
+#
+set_zone "step2.ksk-doubleksk.autosign"
+set_policy "ksk-doubleksk" "3" "7200"
+set_server "ns3" "10.53.0.3"
+# New KSK (KEY3) is prepublished (and signs DNSKEY RRset).
+key_clear "KEY3"
+set_keyrole "KEY3" "ksk"
+set_keylifetime "KEY3" "${Lksk}"
+set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY3" "yes"
+set_zonesigning "KEY3" "no"
+# Key states.
+set_keystate "KEY1" "GOAL" "hidden"
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY3" "STATE_DS" "hidden"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys were activated 1413 hours ago (5086800 seconds).
+rollover_predecessor_keytimes -5086800
+# - The new KSK is published now.
+created=$(key_get KEY3 CREATED)
+set_keytime "KEY3" "PUBLISHED" "${created}"
+# The new KSK should publish the CDS after the prepublication time.
+# TTLkey: 2h
+# DprpC: 1h
+# publish-safety: 1d
+# IpubC: 27h (97200 seconds)
+IpubC=97200
+set_addkeytime "KEY3" "SYNCPUBLISH" "${created}" "${IpubC}"
+set_addkeytime "KEY3" "ACTIVE" "${created}" "${IpubC}"
+set_retired_removed "KEY3" "${Lksk}" "${IretKSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the successor KSK becomes OMNIPRESENT. That is the
+# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For
+# the ksk-doubleksk policy, this means: 7200s + 1h + 1d = 97200 seconds.
+check_next_key_event 97200
+
+#
+# Zone: step3.ksk-doubleksk.autosign.
+#
+set_zone "step3.ksk-doubleksk.autosign"
+set_policy "ksk-doubleksk" "3" "7200"
+set_server "ns3" "10.53.0.3"
+
+# The DNSKEY RRset has become omnipresent.
+# Check keys before we tell named that we saw the DS has been replaced.
+set_keystate "KEY3" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY3" "STATE_KRRSIG" "omnipresent"
+# The old DS (KEY1) can be withdrawn and the new DS (KEY3) can be introduced.
+set_keystate "KEY1" "STATE_DS" "unretentive"
+set_keystate "KEY3" "STATE_DS" "rumoured"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# Check that CDS publication is logged.
+check_cdslog "$DIR" "$ZONE" KEY3
+
+# Set expected key times:
+# - The old keys were activated 60 days ago (5184000 seconds).
+rollover_predecessor_keytimes -5184000
+# - The new KSK is published 27 hours ago (97200 seconds).
+created=$(key_get KEY3 CREATED)
+set_addkeytime "KEY3" "PUBLISHED" "${created}" -97200
+# - The new KSK CDS is published now.
+set_keytime "KEY3" "SYNCPUBLISH" "${created}"
+syncpub=$(key_get KEY3 SYNCPUBLISH)
+set_keytime "KEY3" "ACTIVE" "${syncpub}"
+set_retired_removed "KEY3" "${Lksk}" "${IretKSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# We ignore any parent registration delay, so set the DS publish time to now.
+rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE"
+rndc_checkds "$SERVER" "$DIR" KEY3 "now" "published" "$ZONE"
+# Next key event is when the predecessor DS has been replaced with the
+# successor DS and enough time has passed such that the all validators that
+# have this DS RRset cached only know about the successor DS. This is the
+# the retire interval, which is the parent propagation delay plus the DS TTL
+# plus the retire-safety. For the ksk-double-ksk policy this means:
+# 1h + 3600s + 2d = 2d2h = 180000 seconds.
+check_next_key_event 180000
+
+#
+# Zone: step4.ksk-doubleksk.autosign.
+#
+set_zone "step4.ksk-doubleksk.autosign"
+set_policy "ksk-doubleksk" "3" "7200"
+set_server "ns3" "10.53.0.3"
+# KSK (KEY1) DNSKEY can be removed.
+set_keysigning "KEY1" "no"
+set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY1" "STATE_KRRSIG" "unretentive"
+set_keystate "KEY1" "STATE_DS" "hidden"
+# New KSK (KEY3) DS is now OMNIPRESENT.
+set_keystate "KEY3" "STATE_DS" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys were activated 1490 hours ago (5364000 seconds).
+rollover_predecessor_keytimes -5364000
+# - The new KSK is published 77 hours ago (277200 seconds).
+created=$(key_get KEY3 CREATED)
+set_addkeytime "KEY3" "PUBLISHED" "${created}" -277200
+published=$(key_get KEY3 PUBLISHED)
+set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" "${IpubC}"
+syncpub=$(key_get KEY3 SYNCPUBLISH)
+set_keytime "KEY3" "ACTIVE" "${syncpub}"
+set_retired_removed "KEY3" "${Lksk}" "${IretKSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the DNSKEY enters the HIDDEN state. This is the
+# DNSKEY TTL plus zone propagation delay. For the ksk-doubleksk policy this is:
+# 7200s + 1h = 10800s
+check_next_key_event 10800
+
+#
+# Zone: step5.ksk-doubleksk.autosign.
+#
+set_zone "step5.ksk-doubleksk.autosign"
+set_policy "ksk-doubleksk" "3" "7200"
+set_server "ns3" "10.53.0.3"
+# KSK (KEY1) DNSKEY is now HIDDEN.
+set_keystate "KEY1" "STATE_DNSKEY" "hidden"
+set_keystate "KEY1" "STATE_KRRSIG" "hidden"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old KSK is activated 1492 hours ago (5371200 seconds).
+rollover_predecessor_keytimes -5371200
+# - The new KSK is published 79 hours ago (284400 seconds).
+created=$(key_get KEY3 CREATED)
+set_addkeytime "KEY3" "PUBLISHED" "${created}" -284400
+published=$(key_get KEY3 PUBLISHED)
+set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" "${IpubC}"
+syncpub=$(key_get KEY3 SYNCPUBLISH)
+set_keytime "KEY3" "ACTIVE" "${syncpub}"
+set_retired_removed "KEY3" "${Lksk}" "${IretKSK}"
+
+# Various signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the new successor needs to be published. This is the
+# KSK lifetime minus Ipub minus Iret minus DNSKEY TTL. For the
+# ksk-doubleksk this is: 60d - 1d3h - 1d - 2d2h - 2h =
+# 5184000 - 97200 - 180000 - 7200 = 4813200 seconds.
+check_next_key_event 4899600
+
+#
+# Zone: step6.ksk-doubleksk.autosign.
+#
+set_zone "step6.ksk-doubleksk.autosign"
+set_policy "ksk-doubleksk" "2" "7200"
+set_server "ns3" "10.53.0.3"
+# KSK (KEY1) DNSKEY is purged.
+key_clear "KEY1"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Testing CSK key rollover (1).
+#
+
+# Policy parameters.
+# Lcsk: 186 days (5184000 seconds)
+# Iret(KSK): DS TTL (1h) + DprpP (1h) + retire-safety (2h)
+# Iret(KSK): 4h (14400 seconds)
+# Iret(ZSK): RRSIG TTL (1d) + Dprp (1h) + Dsgn (25d) + retire-safety (2h)
+# Iret(ZSK): 26d3h (2257200 seconds)
+Lcsk=16070400
+IretKSK=14400
+IretZSK=2257200
+IretCSK=$IretZSK
+
+csk_rollover_predecessor_keytimes() {
+ _addtime=$1
+
+ _created=$(key_get KEY1 CREATED)
+ set_addkeytime "KEY1" "PUBLISHED" "${_created}" "${_addtime}"
+ set_addkeytime "KEY1" "SYNCPUBLISH" "${_created}" "${_addtime}"
+ set_addkeytime "KEY1" "ACTIVE" "${_created}" "${_addtime}"
+ [ "$Lcsk" = 0 ] || set_retired_removed "KEY1" "${Lcsk}" "${IretCSK}"
+}
+
+#
+# Zone: step1.csk-roll.autosign.
+#
+set_zone "step1.csk-roll.autosign"
+set_policy "csk-roll" "1" "3600"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "${Lcsk}"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+# The CSK (KEY1) starts in OMNIPRESENT.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+# Initially only one key.
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# This key is immediately published and activated.
+csk_rollover_predecessor_keytimes 0
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the successor CSK needs to be published.
+# This is Lcsk - Ipub - Dreg.
+# Lcsk: 186d (16070400 seconds)
+# Ipub: 3h (10800 seconds)
+check_next_key_event 16059600
+
+#
+# Zone: step2.csk-roll.autosign.
+#
+set_zone "step2.csk-roll.autosign"
+set_policy "csk-roll" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# New CSK (KEY2) is prepublished (signs DNSKEY RRset, but not yet other RRsets).
+key_clear "KEY2"
+set_keyrole "KEY2" "csk"
+set_keylifetime "KEY2" "16070400"
+set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY2" "yes"
+set_zonesigning "KEY2" "no"
+# Key states.
+set_keystate "KEY1" "GOAL" "hidden"
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY2" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY2" "STATE_ZRRSIG" "hidden"
+set_keystate "KEY2" "STATE_DS" "hidden"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - This key was activated 4461 hours ago (16059600 seconds).
+csk_rollover_predecessor_keytimes -16059600
+# - The new CSK is published now.
+created=$(key_get KEY2 CREATED)
+set_keytime "KEY2" "PUBLISHED" "${created}"
+# - The new CSK should publish the CDS after the prepublication time.
+# Ipub: 3 hour (10800 seconds)
+Ipub="10800"
+set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" "${Ipub}"
+set_addkeytime "KEY2" "ACTIVE" "${created}" "${Ipub}"
+set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the successor CSK becomes OMNIPRESENT. That is the
+# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For
+# the csk-roll policy, this means 3 hours = 10800 seconds.
+check_next_key_event 10800
+
+#
+# Zone: step3.csk-roll.autosign.
+#
+set_zone "step3.csk-roll.autosign"
+set_policy "csk-roll" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# Swap zone signing role.
+set_zonesigning "KEY1" "no"
+set_zonesigning "KEY2" "yes"
+# CSK (KEY1) will be removed, so moving to UNRETENTIVE.
+set_keystate "KEY1" "STATE_ZRRSIG" "unretentive"
+# New CSK (KEY2) DNSKEY is OMNIPRESENT, so moving ZRRSIG to RUMOURED.
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
+# The old DS (KEY1) can be withdrawn and the new DS (KEY2) can be introduced.
+set_keystate "KEY1" "STATE_DS" "unretentive"
+set_keystate "KEY2" "STATE_DS" "rumoured"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# Check that CDS publication is logged.
+check_cdslog "$DIR" "$ZONE" KEY2
+
+# Set expected key times:
+# - This key was activated 186 days ago (16070400 seconds).
+csk_rollover_predecessor_keytimes -16070400
+# - The new CSK is published three hours ago, CDS must be published now.
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" "-${Ipub}"
+set_keytime "KEY2" "SYNCPUBLISH" "${created}"
+# - Also signatures are being introduced now.
+set_keytime "KEY2" "ACTIVE" "${created}"
+set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+# Subdomain still has good signatures of old CSK (KEY1).
+# Set expected zone signing on for KEY1 and off for KEY2,
+# testing whether signatures which are still valid are being reused.
+set_zonesigning "KEY1" "yes"
+set_zonesigning "KEY2" "no"
+check_subdomain
+# Restore the expected zone signing properties.
+set_zonesigning "KEY1" "no"
+set_zonesigning "KEY2" "yes"
+dnssec_verify
+
+# We ignore any parent registration delay, so set the DS publish time to now.
+rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE"
+rndc_checkds "$SERVER" "$DIR" KEY2 "now" "published" "$ZONE"
+# Next key event is when the predecessor DS has been replaced with the
+# successor DS and enough time has passed such that the all validators that
+# have this DS RRset cached only know about the successor DS. This is the
+# the retire interval, which is the parent propagation delay plus the DS TTL
+# plus the retire-safety. For the csk-roll policy this means:
+# 1h + 1h + 2h = 4h = 14400 seconds.
+check_next_key_event 14400
+
+#
+# Zone: step4.csk-roll.autosign.
+#
+set_zone "step4.csk-roll.autosign"
+set_policy "csk-roll" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# The old CSK (KEY1) is no longer signing the DNSKEY RRset.
+set_keysigning "KEY1" "no"
+# The old CSK (KEY1) DS is hidden. We still need to keep the DNSKEY public
+# but can remove the KRRSIG records.
+set_keystate "KEY1" "STATE_KRRSIG" "unretentive"
+set_keystate "KEY1" "STATE_DS" "hidden"
+# The new CSK (KEY2) DS is now OMNIPRESENT.
+set_keystate "KEY2" "STATE_DS" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - This key was activated 4468 hours ago (16084800 seconds).
+csk_rollover_predecessor_keytimes -16084800
+# - The new CSK started signing 4h ago (14400 seconds).
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "ACTIVE" "${created}" -14400
+set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" -14400
+syncpub=$(key_get KEY2 SYNCPUBLISH)
+set_addkeytime "KEY2" "PUBLISHED" "${syncpub}" "-${Ipub}"
+set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the KRRSIG enters the HIDDEN state. This is the
+# DNSKEY TTL plus zone propagation delay. For the csk-roll policy this is:
+# 1h + 1h = 7200 seconds.
+check_next_key_event 7200
+
+#
+# Zone: step5.csk-roll.autosign.
+#
+set_zone "step5.csk-roll.autosign"
+set_policy "csk-roll" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# The old CSK (KEY1) KRRSIG records are now all hidden.
+set_keystate "KEY1" "STATE_KRRSIG" "hidden"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - This key was activated 4470 hours ago (16092000 seconds).
+csk_rollover_predecessor_keytimes -16092000
+# - The new CSK started signing 6h ago (21600 seconds).
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "ACTIVE" "${created}" -21600
+set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" -21600
+syncpub=$(key_get KEY2 SYNCPUBLISH)
+set_addkeytime "KEY2" "PUBLISHED" "${syncpub}" "-${Ipub}"
+set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the DNSKEY can be removed. This is when all ZRRSIG
+# records have been replaced with signatures of the new CSK. We have
+# calculated the interval to be 26d3h of which 4h (Iret(KSK)) plus
+# 2h (DNSKEY TTL + Dprp) have already passed. So next key event is in
+# 26d3h - 4h - 2h = 621h = 2235600 seconds.
+check_next_key_event 2235600
+
+#
+# Zone: step6.csk-roll.autosign.
+#
+set_zone "step6.csk-roll.autosign"
+set_policy "csk-roll" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# The old CSK (KEY1) ZRRSIG records are now all hidden (so the DNSKEY can
+# be removed).
+set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY1" "STATE_ZRRSIG" "hidden"
+# The new CSK (KEY2) is now fully OMNIPRESENT.
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times
+# - This key was activated 5091 hours ago (18327600 seconds).
+csk_rollover_predecessor_keytimes -18327600
+# - The new CSK is activated 627 hours ago (2257200 seconds).
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "ACTIVE" "${created}" -2257200
+set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" -2257200
+syncpub=$(key_get KEY2 SYNCPUBLISH)
+set_addkeytime "KEY2" "PUBLISHED" "${syncpub}" "-${Ipub}"
+set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the DNSKEY enters the HIDDEN state. This is the
+# DNSKEY TTL plus zone propagation delay. For the csk-roll policy this is:
+# 1h + 1h = 7200 seconds.
+check_next_key_event 7200
+
+#
+# Zone: step7.csk-roll.autosign.
+#
+set_zone "step7.csk-roll.autosign"
+set_policy "csk-roll" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# The old CSK (KEY1) is now completely HIDDEN.
+set_keystate "KEY1" "STATE_DNSKEY" "hidden"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - This key was activated 5093 hours ago (18334800 seconds).
+csk_rollover_predecessor_keytimes -18334800
+# - The new CSK is activated 629 hours ago (2264400 seconds).
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "ACTIVE" "${created}" -2264400
+set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" -2264400
+syncpub=$(key_get KEY2 SYNCPUBLISH)
+set_addkeytime "KEY2" "PUBLISHED" "${syncpub}" "-${Ipub}"
+set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the new successor needs to be published.
+# This is the Lcsk, minus time passed since the key started signing,
+# minus the prepublication time.
+# Lcsk: 186d (16070400 seconds)
+# Time passed: 629h (2264400 seconds)
+# Ipub: 3h (10800 seconds)
+check_next_key_event 13795200
+
+#
+# Zone: step8.csk-roll.autosign.
+#
+set_zone "step8.csk-roll.autosign"
+set_policy "csk-roll" "1" "3600"
+set_server "ns3" "10.53.0.3"
+# The old CSK (KEY1) is purged.
+key_clear "KEY1"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Testing CSK key rollover (2).
+#
+
+# Policy parameters.
+# Lcsk: 186 days (16070400 seconds)
+# Dreg: N/A
+# Iret(KSK): DS TTL (1h) + DprpP (1w) + retire-safety (1h)
+# Iret(KSK): 170h (61200 seconds)
+# Iret(ZSK): RRSIG TTL (1d) + Dprp (1h) + Dsgn (12h) + retire-safety (1h)
+# Iret(ZSK): 38h (136800 seconds)
+Lcsk=16070400
+IretKSK=612000
+IretZSK=136800
+IretCSK=$IretKSK
+
+#
+# Zone: step1.csk-roll2.autosign.
+#
+set_zone "step1.csk-roll2.autosign"
+set_policy "csk-roll2" "1" "3600"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "16070400"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+# The CSK (KEY1) starts in OMNIPRESENT.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+# Initially only one key.
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# This key is immediately published and activated.
+csk_rollover_predecessor_keytimes 0
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the successor CSK needs to be published.
+# This is Lcsk - Ipub.
+# Lcsk: 186d (16070400 seconds)
+# Ipub: 3h (10800 seconds)
+# Total: 186d3h (16059600 seconds)
+check_next_key_event 16059600
+
+#
+# Zone: step2.csk-roll2.autosign.
+#
+set_zone "step2.csk-roll2.autosign"
+set_policy "csk-roll2" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# New CSK (KEY2) is prepublished (signs DNSKEY RRset, but not yet other RRsets).
+key_clear "KEY2"
+set_keyrole "KEY2" "csk"
+set_keylifetime "KEY2" "16070400"
+set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY2" "yes"
+set_zonesigning "KEY2" "no"
+# Key states.
+set_keystate "KEY1" "GOAL" "hidden"
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY2" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY2" "STATE_ZRRSIG" "hidden"
+set_keystate "KEY2" "STATE_DS" "hidden"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - This key was activated 4461 hours ago (16059600 seconds).
+csk_rollover_predecessor_keytimes -16059600
+# - The new CSK is published now.
+created=$(key_get KEY2 CREATED)
+set_keytime "KEY2" "PUBLISHED" "${created}"
+# - The new CSK should publish the CDS after the prepublication time.
+# - Ipub: 3 hour (10800 seconds)
+Ipub="10800"
+set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" "${Ipub}"
+set_addkeytime "KEY2" "ACTIVE" "${created}" "${Ipub}"
+set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}"
+
+# Continue signing policy checks.
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the successor CSK becomes OMNIPRESENT. That is the
+# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For
+# the csk-roll2 policy, this means 3h hours = 10800 seconds.
+check_next_key_event 10800
+
+#
+# Zone: step3.csk-roll2.autosign.
+#
+set_zone "step3.csk-roll2.autosign"
+set_policy "csk-roll2" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# CSK (KEY1) can be removed, so move to UNRETENTIVE.
+set_zonesigning "KEY1" "no"
+set_keystate "KEY1" "STATE_ZRRSIG" "unretentive"
+# New CSK (KEY2) DNSKEY is OMNIPRESENT, so move ZRRSIG to RUMOURED state.
+set_zonesigning "KEY2" "yes"
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
+# The old DS (KEY1) can be withdrawn and the new DS (KEY2) can be introduced.
+set_keystate "KEY1" "STATE_DS" "unretentive"
+set_keystate "KEY2" "STATE_DS" "rumoured"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# Check that CDS publication is logged.
+check_cdslog "$DIR" "$ZONE" KEY2
+
+# Set expected key times:
+# - This key was activated 186 days ago (16070400 seconds).
+csk_rollover_predecessor_keytimes -16070400
+# - The new CSK is published three hours ago, CDS must be published now.
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" "-${Ipub}"
+set_keytime "KEY2" "SYNCPUBLISH" "${created}"
+# - Also signatures are being introduced now.
+set_keytime "KEY2" "ACTIVE" "${created}"
+set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+# Subdomain still has good signatures of old CSK (KEY1).
+# Set expected zone signing on for KEY1 and off for KEY2,
+# testing whether signatures which are still valid are being reused.
+set_zonesigning "KEY1" "yes"
+set_zonesigning "KEY2" "no"
+check_subdomain
+# Restore the expected zone signing properties.
+set_zonesigning "KEY1" "no"
+set_zonesigning "KEY2" "yes"
+dnssec_verify
+
+# We ignore any parent registration delay, so set the DS publish time to now.
+rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE"
+rndc_checkds "$SERVER" "$DIR" KEY2 "now" "published" "$ZONE"
+# Next key event is when the predecessor ZRRSIG records have been replaced
+# with that of the successor and enough time has passed such that the all
+# validators that have such signed RRsets in cache only know about the
+# successor signatures. This is the retire interval: Dsgn plus the
+# maximum zone TTL plus the zone propagation delay plus retire-safety. For the
+# csk-roll2 policy that means: 12h (because 1d validity and refresh within
+# 12 hours) + 1d + 1h + 1h = 38h = 136800 seconds. Prevent intermittent false
+# positives on slow platforms by subtracting the number of seconds which
+# passed between key creation and invoking 'rndc dnssec -checkds'.
+now="$(TZ=UTC date +%s)"
+time_passed=$((now-start_time))
+next_time=$((136800-time_passed))
+check_next_key_event $next_time
+
+#
+# Zone: step4.csk-roll2.autosign.
+#
+set_zone "step4.csk-roll2.autosign"
+set_policy "csk-roll2" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# The old CSK (KEY1) ZRRSIG is now HIDDEN.
+set_keystate "KEY1" "STATE_ZRRSIG" "hidden"
+# The new CSK (KEY2) ZRRSIG is now OMNIPRESENT.
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - This key was activated 4502 hours ago (16207200 seconds).
+csk_rollover_predecessor_keytimes -16207200
+# - The new CSK was published 41 hours (147600 seconds) ago.
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -147600
+published=$(key_get KEY2 PUBLISHED)
+set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" "${Ipub}"
+set_addkeytime "KEY2" "ACTIVE" "${published}" "${Ipub}"
+set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the predecessor DS has been replaced with the
+# successor DS and enough time has passed such that the all validators that
+# have this DS RRset cached only know about the successor DS. This is the
+# registration delay plus the retire interval, which is the parent
+# propagation delay plus the DS TTL plus the retire-safety. For the
+# csk-roll2 policy this means: 1w + 1h + 1h = 170h = 612000 seconds.
+# However, 136800 seconds have passed already, so 478800 seconds left.
+check_next_key_event 475200
+
+#
+# Zone: step5.csk-roll2.autosign.
+#
+set_zone "step5.csk-roll2.autosign"
+set_policy "csk-roll2" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# The old CSK (KEY1) DNSKEY can be removed.
+set_keysigning "KEY1" "no"
+set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY1" "STATE_KRRSIG" "unretentive"
+set_keystate "KEY1" "STATE_DS" "hidden"
+# The new CSK (KEY2) is now fully OMNIPRESENT.
+set_keystate "KEY2" "STATE_DS" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - This key was activated 4634 hours ago (16682400 seconds).
+csk_rollover_predecessor_keytimes -16682400
+# - The new CSK was published 173 hours (622800 seconds) ago.
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -622800
+published=$(key_get KEY2 PUBLISHED)
+set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" "${Ipub}"
+set_addkeytime "KEY2" "ACTIVE" "${published}" "${Ipub}"
+set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the DNSKEY enters the HIDDEN state. This is the
+# DNSKEY TTL plus zone propagation delay. For the csk-roll policy this is:
+# 1h + 1h = 7200 seconds.
+check_next_key_event 7200
+
+#
+# Zone: step6.csk-roll2.autosign.
+#
+set_zone "step6.csk-roll2.autosign"
+set_policy "csk-roll2" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# The old CSK (KEY1) is now completely HIDDEN.
+set_keystate "KEY1" "STATE_DNSKEY" "hidden"
+set_keystate "KEY1" "STATE_KRRSIG" "hidden"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - This key was activated 4636 hours ago (16689600 seconds).
+csk_rollover_predecessor_keytimes -16689600
+# - The new CSK was published 175 hours (630000 seconds) ago.
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -630000
+published=$(key_get KEY2 PUBLISHED)
+set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" "${Ipub}"
+set_addkeytime "KEY2" "ACTIVE" "${published}" "${Ipub}"
+set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the new successor needs to be published.
+# This is the Lcsk, minus time passed since the key was published.
+# Lcsk: 186d (16070400 seconds)
+# Time passed: 175h (630000 seconds)
+check_next_key_event 15440400
+
+#
+# Zone: step7.csk-roll2.autosign.
+#
+set_zone "step7.csk-roll2.autosign"
+set_policy "csk-roll2" "2" "3600"
+set_server "ns3" "10.53.0.3"
+# The old CSK (KEY1) could have been purged, but purge-keys is disabled.
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Test #2375: Scheduled rollovers are happening faster than they can finish
+#
+set_zone "three-is-a-crowd.kasp"
+set_policy "ksk-doubleksk" "3" "7200"
+set_server "ns3" "10.53.0.3"
+CDNSKEY="no"
+# These are the same time values as calculated for ksk-doubleksk.
+Lksk=5184000
+Lzsk=31536000
+IretKSK=180000
+IretZSK=867600
+# KSK (KEY1) is outgoing.
+key_clear "KEY1"
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "${Lksk}"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+set_keystate "KEY1" "GOAL" "hidden"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "unretentive"
+# KSK (KEY2) is incoming.
+key_clear "KEY2"
+set_keyrole "KEY2" "ksk"
+set_keylifetime "KEY2" "${Lksk}"
+set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY2" "yes"
+set_zonesigning "KEY2" "no"
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY2" "STATE_DS" "rumoured"
+# We will introduce the third KSK shortly.
+key_clear "KEY3"
+# ZSK (KEY4).
+key_clear "KEY4"
+set_keyrole "KEY4" "zsk"
+set_keylifetime "KEY4" "${Lzsk}"
+set_keyalgorithm "KEY4" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY4" "no"
+set_zonesigning "KEY4" "yes"
+set_keystate "KEY4" "GOAL" "omnipresent"
+set_keystate "KEY4" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY4" "STATE_ZRRSIG" "omnipresent"
+# Run preliminary tests.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+# Roll over KEY2.
+# Set expected key lifetime, which is DNSKEY TTL plus the zone propagation delay,
+# plus the publish-safety: 7200s + 1h + 1d = 97200 seconds.
+set_keylifetime "KEY2" "97200"
+created=$(key_get KEY2 CREATED)
+rndc_rollover "$SERVER" "$DIR" $(key_get KEY2 ID) "${created}" "$ZONE"
+# Update expected number of keys and key states.
+set_keystate "KEY2" "GOAL" "hidden"
+set_policy "ksk-doubleksk" "4" "7200"
+CDNSKEY="no"
+# New KSK (KEY3) is introduced.
+set_keyrole "KEY3" "ksk"
+set_keylifetime "KEY3" "${Lksk}"
+set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY3" "yes"
+set_zonesigning "KEY3" "no"
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY3" "STATE_DS" "hidden"
+# Run tests again. We now expect four keys (3x KSK, 1x ZSK).
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+# Test dynamic zones that switch to inline-signing.
+set_zone "dynamic2inline.kasp"
+set_policy "default" "1" "3600"
+set_server "ns6" "10.53.0.6"
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# The CSK is rumoured.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Testing algorithm rollover.
+#
+Lksk=0
+Lzsk=0
+IretKSK=0
+IretZSK=0
+
+#
+# Zone: step1.algorithm-roll.kasp
+#
+set_zone "step1.algorithm-roll.kasp"
+set_policy "rsasha256" "2" "3600"
+set_server "ns6" "10.53.0.6"
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "8" "RSASHA256" "2048"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+key_clear "KEY2"
+set_keyrole "KEY2" "zsk"
+set_keylifetime "KEY2" "0"
+set_keyalgorithm "KEY2" "8" "RSASHA256" "2048"
+set_keysigning "KEY2" "no"
+set_zonesigning "KEY2" "yes"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# The KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# These keys are immediately published and activated.
+rollover_predecessor_keytimes 0
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the successor keys need to be published.
+# Since the lifetime of the keys are unlimited, so default to loadkeys
+# interval.
+check_next_key_event 3600
+
+#
+# Zone: step1.csk-algorithm-roll.kasp
+#
+set_zone "step1.csk-algorithm-roll.kasp"
+set_policy "csk-algoroll" "1" "3600"
+set_server "ns6" "10.53.0.6"
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "8" "RSASHA256" "2048"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+# The CSK (KEY1) starts in OMNIPRESENT.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# This key is immediately published and activated.
+Lcsk=0
+IretCSK=0
+csk_rollover_predecessor_keytimes 0
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the successor keys need to be published.
+# Since the lifetime of the keys are unlimited, so default to loadkeys
+# interval.
+check_next_key_event 3600
+
+#
+# Testing going insecure.
+#
+
+#
+# Zone step1.going-insecure.kasp
+#
+set_zone "step1.going-insecure.kasp"
+set_policy "unsigning" "2" "7200"
+set_server "ns6" "10.53.0.6"
+
+# Policy parameters.
+# Lksk: 0
+# Lzsk: 60 days (5184000 seconds)
+# Iret(KSK): DS TTL (1d) + DprpP (1h) + retire-safety (1h)
+# Iret(KSK): 1d2h (93600 seconds)
+# Iret(ZSK): RRSIG TTL (1d) + Dprp (5m) + Dsgn (9d) + retire-safety (1h)
+# Iret(ZSK): 10d1h5m (867900 seconds)
+Lksk=0
+Lzsk=5184000
+IretKSK=93600
+IretZSK=867900
+
+init_migration_insecure() {
+ key_clear "KEY1"
+ set_keyrole "KEY1" "ksk"
+ set_keylifetime "KEY1" "${Lksk}"
+ set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+ set_keysigning "KEY1" "yes"
+ set_zonesigning "KEY1" "no"
+
+ set_keystate "KEY1" "GOAL" "omnipresent"
+ set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+ set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+ set_keystate "KEY1" "STATE_DS" "omnipresent"
+
+ key_clear "KEY2"
+ set_keyrole "KEY2" "zsk"
+ set_keylifetime "KEY2" "${Lzsk}"
+ set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+ set_keysigning "KEY2" "no"
+ set_zonesigning "KEY2" "yes"
+
+ set_keystate "KEY2" "GOAL" "omnipresent"
+ set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+ set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+
+ key_clear "KEY3"
+ key_clear "KEY4"
+}
+init_migration_insecure
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# We have set the timing metadata to now - 10 days (864000 seconds).
+rollover_predecessor_keytimes -864000
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone step1.going-insecure-dynamic.kasp
+#
+
+set_zone "step1.going-insecure-dynamic.kasp"
+set_dynamic
+set_policy "unsigning" "2" "7200"
+set_server "ns6" "10.53.0.6"
+init_migration_insecure
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# We have set the timing metadata to now - 10 days (864000 seconds).
+rollover_predecessor_keytimes -864000
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone step1.going-straight-to-none.kasp
+#
+set_zone "step1.going-straight-to-none.kasp"
+set_policy "default" "1" "3600"
+set_server "ns6" "10.53.0.6"
+# Key properties.
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+# This policy only has one key.
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# The first key is immediately published and activated.
+created=$(key_get KEY1 CREATED)
+set_keytime "KEY1" "PUBLISHED" "${created}"
+set_keytime "KEY1" "ACTIVE" "${created}"
+set_keytime "KEY1" "SYNCPUBLISH" "${created}"
+# Key lifetime is unlimited, so not setting RETIRED and REMOVED.
+check_keytimes
+
+check_apex
+check_subdomain
+dnssec_verify
+
+# Reconfig dnssec-policy (triggering algorithm roll and other dnssec-policy
+# changes).
+echo_i "reconfig dnssec-policy to trigger algorithm rollover"
+copy_setports ns6/named2.conf.in ns6/named.conf
+rndc_reconfig ns6 10.53.0.6
+
+# Calculate time passed to correctly check for next key events.
+now="$(TZ=UTC date +%s)"
+time_passed=$((now-start_time))
+echo_i "${time_passed} seconds passed between start of tests and reconfig"
+
+# Wait until we have seen "zone_rekey done:" message for this key.
+_wait_for_done_signing() {
+ _zone=$1
+
+ _ksk=$(key_get $2 KSK)
+ _zsk=$(key_get $2 ZSK)
+ if [ "$_ksk" = "yes" ]; then
+ _role="KSK"
+ _expect_type=EXPECT_KRRSIG
+ elif [ "$_zsk" = "yes" ]; then
+ _role="ZSK"
+ _expect_type=EXPECT_ZRRSIG
+ fi
+
+ if [ "$(key_get ${2} $_expect_type)" = "yes" ] && [ "$(key_get $2 $_role)" = "yes" ]; then
+ _keyid=$(key_get $2 ID)
+ _keyalg=$(key_get $2 ALG_STR)
+ echo_i "wait for zone ${_zone} is done signing with $2 ${_zone}/${_keyalg}/${_keyid}"
+ grep "zone_rekey done: key ${_keyid}/${_keyalg}" "${DIR}/named.run" > /dev/null || return 1
+ fi
+
+ return 0
+}
+
+wait_for_done_signing() {
+ n=$((n+1))
+ echo_i "wait for zone ${ZONE} is done signing ($n)"
+ ret=0
+
+ retry_quiet 30 _wait_for_done_signing ${ZONE} KEY1 || ret=1
+ retry_quiet 30 _wait_for_done_signing ${ZONE} KEY2 || ret=1
+ retry_quiet 30 _wait_for_done_signing ${ZONE} KEY3 || ret=1
+ retry_quiet 30 _wait_for_done_signing ${ZONE} KEY4 || ret=1
+
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+# Test dynamic zones that switch to inline-signing.
+set_zone "dynamic2inline.kasp"
+set_policy "default" "1" "3600"
+set_server "ns6" "10.53.0.6"
+# Key properties.
+key_clear "KEY1"
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# The CSK is rumoured.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "hidden"
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Testing going insecure.
+#
+
+#
+# Zone: step1.going-insecure.kasp
+#
+set_zone "step1.going-insecure.kasp"
+set_policy "insecure" "2" "7200"
+set_server "ns6" "10.53.0.6"
+# Expect a CDS/CDNSKEY Delete Record.
+set_cdsdelete
+
+# Key goal states should be HIDDEN.
+init_migration_insecure
+set_keystate "KEY1" "GOAL" "hidden"
+set_keystate "KEY2" "GOAL" "hidden"
+# The DS may be removed if we are going insecure.
+set_keystate "KEY1" "STATE_DS" "unretentive"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+# Tell named that the DS has been removed.
+rndc_checkds "$SERVER" "$DIR" "KEY1" "now" "withdrawn" "$ZONE"
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the DS becomes HIDDEN. This happens after the
+# parent propagation delay, retire safety delay, and DS TTL:
+# 1h + 1h + 1d = 26h = 93600 seconds.
+check_next_key_event 93600
+
+#
+# Zone: step2.going-insecure.kasp
+#
+set_zone "step2.going-insecure.kasp"
+set_policy "insecure" "2" "7200"
+set_server "ns6" "10.53.0.6"
+
+# The DS is long enough removed from the zone to be considered HIDDEN.
+# This means the DNSKEY and the KSK signatures can be removed.
+set_keystate "KEY1" "STATE_DS" "hidden"
+set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY1" "STATE_KRRSIG" "unretentive"
+set_keysigning "KEY1" "no"
+
+set_keystate "KEY2" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY2" "STATE_ZRRSIG" "unretentive"
+set_zonesigning "KEY2" "no"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+# Next key event is when the DNSKEY becomes HIDDEN. This happens after the
+# propagation delay, plus DNSKEY TTL:
+# 5m + 2h = 125m = 7500 seconds.
+check_next_key_event 7500
+
+#
+# Zone: step1.going-insecure-dynamic.kasp
+#
+set_zone "step1.going-insecure-dynamic.kasp"
+set_dynamic
+set_policy "insecure" "2" "7200"
+set_server "ns6" "10.53.0.6"
+# Expect a CDS/CDNSKEY Delete Record.
+set_cdsdelete
+
+# Key goal states should be HIDDEN.
+init_migration_insecure
+set_keystate "KEY1" "GOAL" "hidden"
+set_keystate "KEY2" "GOAL" "hidden"
+# The DS may be removed if we are going insecure.
+set_keystate "KEY1" "STATE_DS" "unretentive"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+# Tell named that the DS has been removed.
+rndc_checkds "$SERVER" "$DIR" "KEY1" "now" "withdrawn" "$ZONE"
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the DS becomes HIDDEN. This happens after the
+# parent propagation delay, retire safety delay, and DS TTL:
+# 1h + 1h + 1d = 26h = 93600 seconds.
+check_next_key_event 93600
+
+#
+# Zone: step2.going-insecure-dynamic.kasp
+#
+set_zone "step2.going-insecure-dynamic.kasp"
+set_dynamic
+set_policy "insecure" "2" "7200"
+set_server "ns6" "10.53.0.6"
+
+# The DS is long enough removed from the zone to be considered HIDDEN.
+# This means the DNSKEY and the KSK signatures can be removed.
+set_keystate "KEY1" "STATE_DS" "hidden"
+set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY1" "STATE_KRRSIG" "unretentive"
+set_keysigning "KEY1" "no"
+
+set_keystate "KEY2" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY2" "STATE_ZRRSIG" "unretentive"
+set_zonesigning "KEY2" "no"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+
+# Next key event is when the DNSKEY becomes HIDDEN. This happens after the
+# propagation delay, plus DNSKEY TTL:
+# 5m + 2h = 125m = 7500 seconds.
+check_next_key_event 7500
+
+#
+# Zone: step1.going-straight-to-none.kasp
+#
+set_zone "step1.going-straight-to-none.kasp"
+set_policy "none" "1" "3600"
+set_server "ns6" "10.53.0.6"
+
+# The zone will go bogus after signatures expire, but remains validly signed for now.
+
+# Key properties.
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+# This policy only has one key.
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# Various signing policy checks.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+dnssec_verify
+
+#
+# Testing KSK/ZSK algorithm rollover.
+#
+
+# Policy parameters.
+# Lksk: unlimited
+# Lzsk: unlimited
+Lksk=0
+Lzsk=0
+
+#
+# Zone: step1.algorithm-roll.kasp
+#
+set_zone "step1.algorithm-roll.kasp"
+set_policy "ecdsa256" "4" "3600"
+set_server "ns6" "10.53.0.6"
+# Old RSASHA1 keys.
+key_clear "KEY1"
+set_keyrole "KEY1" "ksk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "8" "RSASHA256" "2048"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "no"
+
+key_clear "KEY2"
+set_keyrole "KEY2" "zsk"
+set_keylifetime "KEY2" "0"
+set_keyalgorithm "KEY2" "8" "RSASHA256" "2048"
+set_keysigning "KEY2" "no"
+set_zonesigning "KEY2" "yes"
+# New ECDSAP256SHA256 keys.
+key_clear "KEY3"
+set_keyrole "KEY3" "ksk"
+set_keylifetime "KEY3" "0"
+set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY3" "yes"
+set_zonesigning "KEY3" "no"
+
+key_clear "KEY4"
+set_keyrole "KEY4" "zsk"
+set_keylifetime "KEY4" "0"
+set_keyalgorithm "KEY4" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY4" "no"
+set_zonesigning "KEY4" "yes"
+# The RSAHSHA1 keys are outroducing.
+set_keystate "KEY1" "GOAL" "hidden"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+set_keystate "KEY2" "GOAL" "hidden"
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+# The ECDSAP256SHA256 keys are introducing.
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY3" "STATE_DS" "hidden"
+set_keystate "KEY4" "GOAL" "omnipresent"
+set_keystate "KEY4" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY4" "STATE_ZRRSIG" "rumoured"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys are published and activated.
+rollover_predecessor_keytimes 0
+# - KSK must be retired since it no longer matches the policy.
+keyfile=$(key_get KEY1 BASEFILE)
+grep "; Inactive:" "${keyfile}.key" > retired.test${n}.ksk
+retired=$(awk '{print $3}' < retired.test${n}.ksk)
+set_keytime "KEY1" "RETIRED" "${retired}"
+# - The key is removed after the retire interval:
+# IretKSK = TTLds + DprpP + retire-safety
+# TTLds: 2h (7200 seconds)
+# DprpP: 1h (3600 seconds)
+# retire-safety: 2h (7200 seconds)
+# IretKSK: 5h (18000 seconds)
+IretKSK=18000
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
+# - ZSK must be retired since it no longer matches the policy.
+keyfile=$(key_get KEY2 BASEFILE)
+grep "; Inactive:" "${keyfile}.key" > retired.test${n}.zsk
+retired=$(awk '{print $3}' < retired.test${n}.zsk)
+set_keytime "KEY2" "RETIRED" "${retired}"
+# - The key is removed after the retire interval:
+# IretZSK = TTLsig + Dprp + Dsgn + retire-safety
+# TTLsig: 6h (21600 seconds)
+# Dprp: 1h (3600 seconds)
+# Dsgn: 25d (2160000 seconds)
+# retire-safety: 2h (7200 seconds)
+# IretZSK: 25d9h (2192400 seconds)
+IretZSK=2192400
+set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
+# - The new KSK is published and activated.
+created=$(key_get KEY3 CREATED)
+set_keytime "KEY3" "PUBLISHED" "${created}"
+set_keytime "KEY3" "ACTIVE" "${created}"
+# - It takes TTLsig + Dprp + publish-safety hours to propagate the zone.
+# TTLsig: 6h (39600 seconds)
+# Dprp: 1h (3600 seconds)
+# publish-safety: 1h (3600 seconds)
+# Ipub: 8h (28800 seconds)
+Ipub=28800
+set_addkeytime "KEY3" "SYNCPUBLISH" "${created}" "${Ipub}"
+# - The new ZSK is published and activated.
+created=$(key_get KEY4 CREATED)
+set_keytime "KEY4" "PUBLISHED" "${created}"
+set_keytime "KEY4" "ACTIVE" "${created}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the ecdsa256 keys have been propagated.
+# This is the DNSKEY TTL plus publish safety plus zone propagation delay:
+# 3 times an hour: 10800 seconds.
+check_next_key_event 10800
+
+#
+# Zone: step2.algorithm-roll.kasp
+#
+set_zone "step2.algorithm-roll.kasp"
+set_policy "ecdsa256" "4" "3600"
+set_server "ns6" "10.53.0.6"
+# The RSAHSHA1 keys are outroducing, but need to stay present until the new
+# algorithm chain of trust has been established. Thus the properties, timings
+# and states of the KEY1 and KEY2 are the same as above.
+
+# The ECDSAP256SHA256 keys are introducing. The DNSKEY RRset is omnipresent,
+# but the zone signatures are not.
+set_keystate "KEY3" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY3" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY4" "STATE_DNSKEY" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys were activated three hours ago (10800 seconds).
+rollover_predecessor_keytimes -10800
+# - KSK must be retired since it no longer matches the policy.
+created=$(key_get KEY1 CREATED)
+set_keytime "KEY1" "RETIRED" "${created}"
+set_addkeytime "KEY1" "REMOVED" "${created}" "${IretKSK}"
+# - ZSK must be retired since it no longer matches the policy.
+created=$(key_get KEY2 CREATED)
+set_keytime "KEY2" "RETIRED" "${created}"
+set_addkeytime "KEY2" "REMOVED" "${created}" "${IretZSK}"
+# - The new keys are published 3 hours ago.
+created=$(key_get KEY3 CREATED)
+set_addkeytime "KEY3" "PUBLISHED" "${created}" -10800
+set_addkeytime "KEY3" "ACTIVE" "${created}" -10800
+published=$(key_get KEY3 PUBLISHED)
+set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" "${Ipub}"
+
+created=$(key_get KEY4 CREATED)
+set_addkeytime "KEY4" "PUBLISHED" "${created}" -10800
+set_addkeytime "KEY4" "ACTIVE" "${created}" -10800
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when all zone signatures are signed with the new
+# algorithm. This is the max-zone-ttl plus zone propagation delay
+# plus retire safety: 6h + 1h + 2h. But three hours have already passed
+# (the time it took to make the DNSKEY omnipresent), so the next event
+# should be scheduled in 6 hour: 21600 seconds. Prevent intermittent
+# false positives on slow platforms by subtracting the number of seconds
+# which passed between key creation and invoking 'rndc reconfig'.
+next_time=$((21600-time_passed))
+check_next_key_event $next_time
+
+#
+# Zone: step3.algorithm-roll.kasp
+#
+set_zone "step3.algorithm-roll.kasp"
+set_policy "ecdsa256" "4" "3600"
+set_server "ns6" "10.53.0.6"
+# The ECDSAP256SHA256 keys are introducing.
+set_keystate "KEY4" "STATE_ZRRSIG" "omnipresent"
+# The DS can be swapped.
+set_keystate "KEY1" "STATE_DS" "unretentive"
+set_keystate "KEY3" "STATE_DS" "rumoured"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# Check that CDS publication is logged.
+check_cdslog "$DIR" "$ZONE" KEY3
+
+# Set expected key times:
+# - The old keys were activated 9 hours ago (32400 seconds).
+rollover_predecessor_keytimes -32400
+# - And retired 6 hours ago (21600 seconds).
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "RETIRED" "${created}" -21600
+retired=$(key_get KEY1 RETIRED)
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
+
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "RETIRED" "${created}" -21600
+retired=$(key_get KEY2 RETIRED)
+set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
+# - The new keys are published 9 hours ago.
+created=$(key_get KEY3 CREATED)
+set_addkeytime "KEY3" "PUBLISHED" "${created}" -32400
+set_addkeytime "KEY3" "ACTIVE" "${created}" -32400
+published=$(key_get KEY3 PUBLISHED)
+set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
+
+created=$(key_get KEY4 CREATED)
+set_addkeytime "KEY4" "PUBLISHED" "${created}" -32400
+set_addkeytime "KEY4" "ACTIVE" "${created}" -32400
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Tell named we "saw" the parent swap the DS and see if the next key event is
+# scheduled at the correct time.
+rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE"
+rndc_checkds "$SERVER" "$DIR" KEY3 "now" "published" "$ZONE"
+# Next key event is when the DS becomes OMNIPRESENT. This happens after the
+# parent propagation delay, retire safety delay, and DS TTL:
+# 1h + 2h + 2h = 5h = 18000 seconds.
+check_next_key_event 18000
+
+#
+# Zone: step4.algorithm-roll.kasp
+#
+set_zone "step4.algorithm-roll.kasp"
+set_policy "ecdsa256" "4" "3600"
+set_server "ns6" "10.53.0.6"
+# The old DS is HIDDEN, we can remove the old algorithm DNSKEY/RRSIG records.
+set_keysigning "KEY1" "no"
+set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY1" "STATE_KRRSIG" "unretentive"
+set_keystate "KEY1" "STATE_DS" "hidden"
+
+set_zonesigning "KEY2" "no"
+set_keystate "KEY2" "GOAL" "hidden"
+set_keystate "KEY2" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY2" "STATE_ZRRSIG" "unretentive"
+# The ECDSAP256SHA256 DS is now OMNIPRESENT.
+set_keystate "KEY3" "STATE_DS" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys were activated 38 hours ago (136800 seconds).
+rollover_predecessor_keytimes -136800
+# - And retired 35 hours ago (126000 seconds).
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "RETIRED" "${created}" -126000
+retired=$(key_get KEY1 RETIRED)
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
+
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "RETIRED" "${created}" -126000
+retired=$(key_get KEY2 RETIRED)
+set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
+
+# - The new keys are published 38 hours ago.
+created=$(key_get KEY3 CREATED)
+set_addkeytime "KEY3" "PUBLISHED" "${created}" -136800
+set_addkeytime "KEY3" "ACTIVE" "${created}" -136800
+published=$(key_get KEY3 PUBLISHED)
+set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
+
+created=$(key_get KEY4 CREATED)
+set_addkeytime "KEY4" "PUBLISHED" "${created}" -136800
+set_addkeytime "KEY4" "ACTIVE" "${created}" -136800
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the old DNSKEY becomes HIDDEN. This happens after the
+# DNSKEY TTL plus zone propagation delay (2h).
+check_next_key_event 7200
+
+#
+# Zone: step5.algorithm-roll.kasp
+#
+set_zone "step5.algorithm-roll.kasp"
+set_policy "ecdsa256" "4" "3600"
+set_server "ns6" "10.53.0.6"
+# The DNSKEY becomes HIDDEN.
+set_keystate "KEY1" "STATE_DNSKEY" "hidden"
+set_keystate "KEY1" "STATE_KRRSIG" "hidden"
+set_keystate "KEY2" "STATE_DNSKEY" "hidden"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys were activated 40 hours ago (144000 seconds)
+rollover_predecessor_keytimes -144000
+# - And retired 37 hours ago (133200 seconds).
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "RETIRED" "${created}" -133200
+retired=$(key_get KEY1 RETIRED)
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
+
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "RETIRED" "${created}" -133200
+retired=$(key_get KEY2 RETIRED)
+set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
+
+# The new keys are published 40 hours ago.
+created=$(key_get KEY3 CREATED)
+set_addkeytime "KEY3" "PUBLISHED" "${created}" -144000
+set_addkeytime "KEY3" "ACTIVE" "${created}" -144000
+published=$(key_get KEY3 PUBLISHED)
+set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
+
+created=$(key_get KEY4 CREATED)
+set_addkeytime "KEY4" "PUBLISHED" "${created}" -144000
+set_addkeytime "KEY4" "ACTIVE" "${created}" -144000
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the RSASHA1 signatures become HIDDEN. This happens
+# after the max-zone-ttl plus zone propagation delay plus retire safety
+# (6h + 1h + 2h) minus the time already passed since the UNRETENTIVE state has
+# been reached (2h): 9h - 2h = 7h = 25200 seconds. Prevent intermittent
+# false positives on slow platforms by subtracting the number of seconds
+# which passed between key creation and invoking 'rndc reconfig'.
+next_time=$((25200-time_passed))
+check_next_key_event $next_time
+
+#
+# Zone: step6.algorithm-roll.kasp
+#
+set_zone "step6.algorithm-roll.kasp"
+set_policy "ecdsa256" "4" "3600"
+set_server "ns6" "10.53.0.6"
+# The old zone signatures (KEY2) should now also be HIDDEN.
+set_keystate "KEY2" "STATE_ZRRSIG" "hidden"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys were activated 47 hours ago (169200 seconds)
+rollover_predecessor_keytimes -169200
+# - And retired 44 hours ago (158400 seconds).
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "RETIRED" "${created}" -158400
+retired=$(key_get KEY1 RETIRED)
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
+
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "RETIRED" "${created}" -158400
+retired=$(key_get KEY2 RETIRED)
+set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
+
+# The new keys are published 47 hours ago.
+created=$(key_get KEY3 CREATED)
+set_addkeytime "KEY3" "PUBLISHED" "${created}" -169200
+set_addkeytime "KEY3" "ACTIVE" "${created}" -169200
+published=$(key_get KEY3 PUBLISHED)
+set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
+
+created=$(key_get KEY4 CREATED)
+set_addkeytime "KEY4" "PUBLISHED" "${created}" -169200
+set_addkeytime "KEY4" "ACTIVE" "${created}" -169200
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is never since we established the policy and the keys have
+# an unlimited lifetime. Fallback to the default loadkeys interval.
+check_next_key_event 3600
+
+#
+# Testing CSK algorithm rollover.
+#
+
+# Policy parameters.
+# Lcsk: unlimited
+Lcksk=0
+
+#
+# Zone: step1.csk-algorithm-roll.kasp
+#
+set_zone "step1.csk-algorithm-roll.kasp"
+set_policy "csk-algoroll" "2" "3600"
+set_server "ns6" "10.53.0.6"
+# Old RSASHA1 key.
+key_clear "KEY1"
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "8" "RSASHA256" "2048"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+# New ECDSAP256SHA256 key.
+key_clear "KEY2"
+set_keyrole "KEY2" "csk"
+set_keylifetime "KEY2" "0"
+set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY2" "yes"
+set_zonesigning "KEY2" "yes"
+key_clear "KEY3"
+key_clear "KEY4"
+# The RSAHSHA1 key is outroducing.
+set_keystate "KEY1" "GOAL" "hidden"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+# The ECDSAP256SHA256 key is introducing.
+set_keystate "KEY2" "GOAL" "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY2" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY2" "STATE_DS" "hidden"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - CSK must be retired since it no longer matches the policy.
+csk_rollover_predecessor_keytimes 0
+keyfile=$(key_get KEY1 BASEFILE)
+grep "; Inactive:" "${keyfile}.key" > retired.test${n}.ksk
+retired=$(awk '{print $3}' < retired.test${n}.ksk)
+set_keytime "KEY1" "RETIRED" "${retired}"
+# - The key is removed after the retire interval:
+# IretZSK = TTLsig + Dprp + Dsgn + retire-safety
+# TTLsig: 6h (21600 seconds)
+# Dprp: 1h (3600 seconds)
+# Dsgn: 25d (2160000 seconds)
+# retire-safety: 2h (7200 seconds)
+# IretZSK: 25d9h (2192400 seconds)
+IretCSK=2192400
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
+# - The new CSK is published and activated.
+created=$(key_get KEY2 CREATED)
+set_keytime "KEY2" "PUBLISHED" "${created}"
+set_keytime "KEY2" "ACTIVE" "${created}"
+# - It takes TTLsig + Dprp + publish-safety hours to propagate the zone.
+# TTLsig: 6h (39600 seconds)
+# Dprp: 1h (3600 seconds)
+# publish-safety: 1h (3600 seconds)
+# Ipub: 8h (28800 seconds)
+Ipub=28800
+set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" "${Ipub}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the new key has been propagated.
+# This is the DNSKEY TTL plus publish safety plus zone propagation delay:
+# 3 times an hour: 10800 seconds.
+check_next_key_event 10800
+
+#
+# Zone: step2.csk-algorithm-roll.kasp
+#
+set_zone "step2.csk-algorithm-roll.kasp"
+set_policy "csk-algoroll" "2" "3600"
+set_server "ns6" "10.53.0.6"
+# The RSAHSHA1 key is outroducing, but need to stay present until the new
+# algorithm chain of trust has been established. Thus the properties, timings
+# and states of KEY1 is the same as above.
+#
+# The ECDSAP256SHA256 keys are introducing. The DNSKEY RRset is omnipresent,
+# but the zone signatures are not.
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_KRRSIG" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old key was activated three hours ago (10800 seconds).
+csk_rollover_predecessor_keytimes -10800
+# - CSK must be retired since it no longer matches the policy.
+created=$(key_get KEY1 CREATED)
+set_keytime "KEY1" "RETIRED" "${created}"
+set_addkeytime "KEY1" "REMOVED" "${created}" "${IretCSK}"
+# - The new key was published 3 hours ago.
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -10800
+set_addkeytime "KEY2" "ACTIVE" "${created}" -10800
+published=$(key_get KEY2 PUBLISHED)
+set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" "${Ipub}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when all zone signatures are signed with the new
+# algorithm. This is the max-zone-ttl plus zone propagation delay
+# plus retire safety: 6h + 1h + 2h. But three hours have already passed
+# (the time it took to make the DNSKEY omnipresent), so the next event
+# should be scheduled in 6 hour: 21600 seconds. Prevent intermittent
+# false positives on slow platforms by subtracting the number of seconds
+# which passed between key creation and invoking 'rndc reconfig'.
+next_time=$((21600-time_passed))
+check_next_key_event $next_time
+
+#
+# Zone: step3.csk-algorithm-roll.kasp
+#
+set_zone "step3.csk-algorithm-roll.kasp"
+set_policy "csk-algoroll" "2" "3600"
+set_server "ns6" "10.53.0.6"
+# The RSAHSHA1 key is outroducing, and it is time to swap the DS.
+# The ECDSAP256SHA256 key is introducing. The DNSKEY RRset and all signatures
+# are now omnipresent, so the DS can be introduced.
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+# The old DS (KEY1) can be withdrawn and the new DS (KEY2) can be introduced.
+set_keystate "KEY1" "STATE_DS" "unretentive"
+set_keystate "KEY2" "STATE_DS" "rumoured"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# Check that CDS publication is logged.
+check_cdslog "$DIR" "$ZONE" KEY2
+
+# Set expected key times:
+# - The old key was activated 9 hours ago (32400 seconds).
+csk_rollover_predecessor_keytimes -32400
+# - And was retired 6 hours ago (21600 seconds).
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "RETIRED" "${created}" -21600
+retired=$(key_get KEY1 RETIRED)
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
+# - The new key was published 9 hours ago.
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -32400
+set_addkeytime "KEY2" "ACTIVE" "${created}" -32400
+published=$(key_get KEY2 PUBLISHED)
+set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" "${Ipub}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# We ignore any parent registration delay, so set the DS publish time to now.
+rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE"
+rndc_checkds "$SERVER" "$DIR" KEY2 "now" "published" "$ZONE"
+# Next key event is when the DS becomes OMNIPRESENT. This happens after the
+# parent propagation delay, retire safety delay, and DS TTL:
+# 1h + 2h + 2h = 5h = 18000 seconds.
+check_next_key_event 18000
+
+#
+# Zone: step4.csk-algorithm-roll.kasp
+#
+set_zone "step4.csk-algorithm-roll.kasp"
+set_policy "csk-algoroll" "2" "3600"
+set_server "ns6" "10.53.0.6"
+# The old DS is HIDDEN, we can remove the old algorithm DNSKEY/RRSIG records.
+set_keysigning "KEY1" "no"
+set_zonesigning "KEY1" "no"
+set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
+set_keystate "KEY1" "STATE_KRRSIG" "unretentive"
+set_keystate "KEY1" "STATE_ZRRSIG" "unretentive"
+set_keystate "KEY1" "STATE_DS" "hidden"
+# The ECDSAP256SHA256 DS is now OMNIPRESENT.
+set_keystate "KEY2" "STATE_DS" "omnipresent"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old key was activated 38 hours ago (136800 seconds)
+csk_rollover_predecessor_keytimes -136800
+# - And retired 35 hours ago (126000 seconds).
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "RETIRED" "${created}" -126000
+retired=$(key_get KEY1 RETIRED)
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
+# - The new key was published 38 hours ago.
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -136800
+set_addkeytime "KEY2" "ACTIVE" "${created}" -136800
+published=$(key_get KEY2 PUBLISHED)
+set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub}
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the old DNSKEY becomes HIDDEN. This happens after the
+# DNSKEY TTL plus zone propagation delay (2h).
+check_next_key_event 7200
+
+#
+# Zone: step5.csk-algorithm-roll.kasp
+#
+set_zone "step5.csk-algorithm-roll.kasp"
+set_policy "csk-algoroll" "2" "3600"
+set_server "ns6" "10.53.0.6"
+# The DNSKEY becomes HIDDEN.
+set_keystate "KEY1" "STATE_DNSKEY" "hidden"
+set_keystate "KEY1" "STATE_KRRSIG" "hidden"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old key was activated 40 hours ago (144000 seconds)
+csk_rollover_predecessor_keytimes -144000
+# - And retired 37 hours ago (133200 seconds).
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "RETIRED" "${created}" -133200
+retired=$(key_get KEY1 RETIRED)
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
+# - The new key was published 40 hours ago.
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -144000
+set_addkeytime "KEY2" "ACTIVE" "${created}" -144000
+published=$(key_get KEY2 PUBLISHED)
+set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub}
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is when the RSASHA1 signatures become HIDDEN. This happens
+# after the max-zone-ttl plus zone propagation delay plus retire safety
+# (6h + 1h + 2h) minus the time already passed since the UNRETENTIVE state has
+# been reached (2h): 9h - 2h = 7h = 25200 seconds. Prevent intermittent
+# false positives on slow platforms by subtracting the number of seconds
+# which passed between key creation and invoking 'rndc reconfig'.
+next_time=$((25200-time_passed))
+check_next_key_event $next_time
+
+#
+# Zone: step6.csk-algorithm-roll.kasp
+#
+set_zone "step6.csk-algorithm-roll.kasp"
+set_policy "csk-algoroll" "2" "3600"
+set_server "ns6" "10.53.0.6"
+# The zone signatures should now also be HIDDEN.
+set_keystate "KEY1" "STATE_ZRRSIG" "hidden"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The old keys were activated 47 hours ago (169200 seconds)
+csk_rollover_predecessor_keytimes -169200
+# - And retired 44 hours ago (158400 seconds).
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "RETIRED" "${created}" -158400
+retired=$(key_get KEY1 RETIRED)
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
+# - The new key was published 47 hours ago.
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -169200
+set_addkeytime "KEY2" "ACTIVE" "${created}" -169200
+published=$(key_get KEY2 PUBLISHED)
+set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub}
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Next key event is never since we established the policy and the keys have
+# an unlimited lifetime. Fallback to the default loadkeys interval.
+check_next_key_event 3600
+
+_check_soa_ttl() {
+ dig_with_opts @10.53.0.6 example SOA > dig.out.ns6.test$n.soa2 || return 1
+ soa1=$(awk '$4 == "SOA" { print $7 }' dig.out.ns6.test$n.soa1)
+ soa2=$(awk '$4 == "SOA" { print $7 }' dig.out.ns6.test$n.soa2)
+ ttl1=$(awk '$4 == "SOA" { print $2 }' dig.out.ns6.test$n.soa1)
+ ttl2=$(awk '$4 == "SOA" { print $2 }' dig.out.ns6.test$n.soa2)
+ test ${soa1:-1000} -lt ${soa2:-0} || return 1
+ test ${ttl1:-0} -eq $1 || return 1
+ test ${ttl2:-0} -eq $2 || return 1
+}
+
+n=$((n+1))
+echo_i "Check that 'rndc reload' of just the serial updates the signed instance ($n)"
+TSIG=
+ret=0
+dig_with_opts @10.53.0.6 example SOA > dig.out.ns6.test$n.soa1 || ret=1
+cp ns6/example2.db.in ns6/example.db || ret=1
+nextpart ns6/named.run > /dev/null
+rndccmd 10.53.0.6 reload || ret=1
+wait_for_log 3 "all zones loaded" ns6/named.run
+# Check that the SOA SERIAL increases and check the TTLs (should be 300 as
+# defined in ns6/example2.db.in).
+retry_quiet 10 _check_soa_ttl 300 300 || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check that restart with zone changes and deleted journal works ($n)"
+TSIG=
+ret=0
+dig_with_opts @10.53.0.6 example SOA > dig.out.ns6.test$n.soa1 || ret=1
+stop_server --use-rndc --port ${CONTROLPORT} ns6
+# TTL of all records change from 300 to 400
+cp ns6/example3.db.in ns6/example.db || ret=1
+rm ns6/example.db.jnl
+nextpart ns6/named.run > /dev/null
+start_server --noclean --restart --port ${PORT} ns6
+wait_for_log 3 "all zones loaded" ns6/named.run
+# Check that the SOA SERIAL increases and check the TTLs (should be changed
+# from 300 to 400 as defined in ns6/example3.db.in).
+retry_quiet 10 _check_soa_ttl 300 400 || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/kasp/tests_sh_kasp.py b/bin/tests/system/kasp/tests_sh_kasp.py
new file mode 100644
index 0000000..d01125d
--- /dev/null
+++ b/bin/tests/system/kasp/tests_sh_kasp.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_kasp(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/keepalive/clean.sh b/bin/tests/system/keepalive/clean.sh
new file mode 100644
index 0000000..9ccbd12
--- /dev/null
+++ b/bin/tests/system/keepalive/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.*
+rm -f output
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/named.conf
+rm -f ns*/named.stats
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/keepalive/expected b/bin/tests/system/keepalive/expected
new file mode 100644
index 0000000..e498db7
--- /dev/null
+++ b/bin/tests/system/keepalive/expected
@@ -0,0 +1,4 @@
+tcp-initial-timeout=300
+tcp-idle-timeout=300
+tcp-keepalive-timeout=300
+tcp-advertised-timeout=200
diff --git a/bin/tests/system/keepalive/ns1/named.conf.in b/bin/tests/system/keepalive/ns1/named.conf.in
new file mode 100644
index 0000000..32dbf90
--- /dev/null
+++ b/bin/tests/system/keepalive/ns1/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/keepalive/ns1/root.db b/bin/tests/system/keepalive/ns1/root.db
new file mode 100644
index 0000000..17780d1
--- /dev/null
+++ b/bin/tests/system/keepalive/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/keepalive/ns2/example.db b/bin/tests/system/keepalive/ns2/example.db
new file mode 100644
index 0000000..ccc6ef9
--- /dev/null
+++ b/bin/tests/system/keepalive/ns2/example.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA ns2 hostmaster.isc.org. 1 600 600 1200 600
+@ NS ns2
+ns2 A 10.53.0.2
+foo A 10.53.1.1
+bar A 10.53.2.2
diff --git a/bin/tests/system/keepalive/ns2/named.conf.in b/bin/tests/system/keepalive/ns2/named.conf.in
new file mode 100644
index 0000000..8ccf1c4
--- /dev/null
+++ b/bin/tests/system/keepalive/ns2/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ send-cookie yes;
+ tcp-advertised-timeout 150;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/keepalive/ns3/named.conf.in b/bin/tests/system/keepalive/ns3/named.conf.in
new file mode 100644
index 0000000..3713f13
--- /dev/null
+++ b/bin/tests/system/keepalive/ns3/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation no;
+};
+
+server 10.53.0.2 {
+ tcp-only yes;
+ tcp-keepalive yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/keepalive/setup.sh b/bin/tests/system/keepalive/setup.sh
new file mode 100644
index 0000000..7ffda55
--- /dev/null
+++ b/bin/tests/system/keepalive/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
diff --git a/bin/tests/system/keepalive/tests.sh b/bin/tests/system/keepalive/tests.sh
new file mode 100644
index 0000000..7314a9e
--- /dev/null
+++ b/bin/tests/system/keepalive/tests.sh
@@ -0,0 +1,99 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT}"
+
+n=0
+status=0
+
+echo_i "checking that dig handles TCP keepalive ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +qr +keepalive foo.example @10.53.0.2 > dig.out.test$n
+grep "; TCP KEEPALIVE" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that dig added TCP keepalive ($n)"
+ret=0
+n=$((n + 1))
+$RNDCCMD stats
+grep "EDNS TCP keepalive option received" ns2/named.stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that TCP keepalive is added for TCP responses ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +vc +keepalive foo.example @10.53.0.2 > dig.out.test$n
+grep "; TCP KEEPALIVE" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that TCP keepalive requires TCP ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +keepalive foo.example @10.53.0.2 > dig.out.test$n
+grep "; TCP KEEPALIVE" dig.out.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking default value ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +vc +keepalive foo.example @10.53.0.3 > dig.out.test$n
+grep "; TCP KEEPALIVE: 30.0 secs" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking configured value ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +vc +keepalive foo.example @10.53.0.2 > dig.out.test$n
+grep "; TCP KEEPALIVE: 15.0 secs" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking re-configured value ($n)"
+ret=0
+n=$((n + 1))
+$RNDCCMD tcp-timeouts 300 300 300 200 > output
+diff -b output expected || ret=1
+$DIG $DIGOPTS +vc +keepalive foo.example @10.53.0.2 > dig.out.test$n
+grep "; TCP KEEPALIVE: 20.0 secs" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking server config entry ($n)"
+ret=0
+n=$((n + 1))
+$RNDCCMD stats
+oka=$(grep "EDNS TCP keepalive option received" ns2/named.stats | \
+ tail -1 | awk '{ print $1}')
+$DIG $DIGOPTS bar.example @10.53.0.3 > dig.out.test$n
+$RNDCCMD stats
+nka=$(grep "EDNS TCP keepalive option received" ns2/named.stats | \
+ tail -1 | awk '{ print $1}')
+#echo oka ':' $oka
+#echo nka ':' $nka
+if [ "$oka" -eq "$nka" ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/keepalive/tests_sh_keepalive.py b/bin/tests/system/keepalive/tests_sh_keepalive.py
new file mode 100644
index 0000000..a2433c4
--- /dev/null
+++ b/bin/tests/system/keepalive/tests_sh_keepalive.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_keepalive(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/keyfromlabel/clean.sh b/bin/tests/system/keyfromlabel/clean.sh
new file mode 100644
index 0000000..bce2099
--- /dev/null
+++ b/bin/tests/system/keyfromlabel/clean.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+rm -f K*
+rm -f pin
+rm -f dsset-*
+rm -f *.example.db *.example.db.signed
+rm -f keyfromlabel.out.*
+rm -f pkcs11-tool.out.*
+rm -f signer.out.*
+
+softhsm2-util --delete-token --token "softhsm2-keyfromlabel" >/dev/null 2>&1 || echo_i "softhsm2-keyfromlabel token not found for cleaning"
diff --git a/bin/tests/system/keyfromlabel/prereq.sh b/bin/tests/system/keyfromlabel/prereq.sh
new file mode 100644
index 0000000..2002c2a
--- /dev/null
+++ b/bin/tests/system/keyfromlabel/prereq.sh
@@ -0,0 +1,21 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+if [ -n "${SOFTHSM2_MODULE}" ] && command -v pkcs11-tool >/dev/null && command -v softhsm2-util >/dev/null; then
+ exit 0
+fi
+
+echo_i "skip: softhsm2-util or pkcs11-tool not available"
+exit 255
diff --git a/bin/tests/system/keyfromlabel/setup.sh b/bin/tests/system/keyfromlabel/setup.sh
new file mode 100644
index 0000000..703814d
--- /dev/null
+++ b/bin/tests/system/keyfromlabel/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+softhsm2-util --init-token --free --pin 1234 --so-pin 1234 --label "softhsm2-keyfromlabel" | awk '/^The token has been initialized and is reassigned to slot/ { print $NF }'
+
+printf '%s' "${HSMPIN:-1234}" > pin
+PWD=$(pwd)
diff --git a/bin/tests/system/keyfromlabel/template.db.in b/bin/tests/system/keyfromlabel/template.db.in
new file mode 100644
index 0000000..7941903
--- /dev/null
+++ b/bin/tests/system/keyfromlabel/template.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "test"
+
diff --git a/bin/tests/system/keyfromlabel/tests.sh b/bin/tests/system/keyfromlabel/tests.sh
new file mode 100644
index 0000000..5cedbf9
--- /dev/null
+++ b/bin/tests/system/keyfromlabel/tests.sh
@@ -0,0 +1,93 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+PWD=$(pwd)
+
+keygen() {
+ type="$1"
+ bits="$2"
+ zone="$3"
+ id="$4"
+
+ label="${id}-${zone}"
+ p11id=$(echo "${label}" | openssl sha1 -r | awk '{print $1}')
+ pkcs11-tool --module $SOFTHSM2_MODULE --token-label "softhsm2-keyfromlabel" -l -k --key-type $type:$bits --label "${label}" --id "${p11id}" --pin $(cat $PWD/pin) > pkcs11-tool.out.$zone.$id || return 1
+}
+
+keyfromlabel() {
+ alg="$1"
+ zone="$2"
+ id="$3"
+ shift 3
+
+ $KEYFRLAB -E pkcs11 -a $alg -l "token=softhsm2-keyfromlabel;object=${id}-${zone};pin-source=$PWD/pin" "$@" $zone >> keyfromlabel.out.$zone.$id 2>> /dev/null || return 1
+ cat keyfromlabel.out.$zone.$id
+}
+
+infile="template.db.in"
+for algtypebits in rsasha256:rsa:2048 rsasha512:rsa:2048 \
+ ecdsap256sha256:EC:prime256v1 ecdsap384sha384:EC:prime384v1
+ # Edwards curves are not yet supported by OpenSC
+ # ed25519:EC:edwards25519 ed448:EC:edwards448
+do
+ alg=$(echo "$algtypebits" | cut -f 1 -d :)
+ type=$(echo "$algtypebits" | cut -f 2 -d :)
+ bits=$(echo "$algtypebits" | cut -f 3 -d :)
+
+ if $SHELL ../testcrypto.sh $alg; then
+ zone="$alg.example"
+ zonefile="zone.$alg.example.db"
+ ret=0
+
+ echo_i "Generate keys $alg $type:$bits for zone $zone"
+ keygen $type $bits $zone keyfromlabel-zsk || ret=1
+ keygen $type $bits $zone keyfromlabel-ksk || ret=1
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+ # Skip dnssec-keyfromlabel if key generation failed.
+ test $ret -eq 0 || continue
+
+ echo_i "Get ZSK $alg $zone $type:$bits"
+ ret=0
+ zsk=$(keyfromlabel $alg $zone keyfromlabel-zsk)
+ test -z "$zsk" && ret=1
+ test "$ret" -eq 0 || echo_i "failed (zsk=$zsk)"
+ status=$((status+ret))
+
+ echo_i "Get KSK $alg $zone $type:$bits"
+ ret=0
+ ksk=$(keyfromlabel $alg $zone keyfromlabel-ksk -f KSK)
+ test -z "$ksk" && ret=1
+ test "$ret" -eq 0 || echo_i "failed (ksk=$ksk)"
+ status=$((status+ret))
+
+ # Skip signing if dnssec-keyfromlabel failed.
+ test $ret -eq 0 || continue
+
+ echo_i "Sign zone with $ksk $zsk"
+ ret=0
+ cat "$infile" "$ksk.key" "$zsk.key" > "$zonefile"
+ $SIGNER -E pkcs11 -S -a -g -o "$zone" "$zonefile" > signer.out.$zone || ret=1
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+ fi
+done
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/keyfromlabel/tests_sh_keyfromlabel.py b/bin/tests/system/keyfromlabel/tests_sh_keyfromlabel.py
new file mode 100644
index 0000000..9cbf56e
--- /dev/null
+++ b/bin/tests/system/keyfromlabel/tests_sh_keyfromlabel.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_keyfromlabel(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/keymgr2kasp/README b/bin/tests/system/keymgr2kasp/README
new file mode 100644
index 0000000..f941209
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/README
@@ -0,0 +1,17 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+The test setup for migrating to KASP tests.
+
+ns3 is an authoritative server for the various test domains.
+
+ns4 is an authoritative server that tests a specific case where zones
+using views migrate to dnssec-policy.
diff --git a/bin/tests/system/keymgr2kasp/clean.sh b/bin/tests/system/keymgr2kasp/clean.sh
new file mode 100644
index 0000000..1fe2bb9
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/clean.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f ns*/K*.private ns*/K*.key ns*/K*.state
+rm -f ns*/named.conf ns*/kasp.conf
+rm -f ns*/named.memstats ns*/named.run
+rm -f ns*/keygen.out* ns*/signer.out*
+rm -f ns*/zones
+rm -f ns*/dsset-*
+rm -f ns*/*.db ns*/*.db.jnl ns*/*.db.jbk
+rm -f ns*/*.db.signed* ns*/*.db.infile
+rm -f ns*/managed-keys.bind*
+rm -f ns*/*.mkeys*
+rm -f ./*.created
+rm -f ./created.key-*
+rm -f ./dig.out*
+rm -f ./python.out.*
+rm -f ./retired.*
+rm -f ./rndc.dnssec.*
+rm -f ./unused.key*
+rm -f ./verify.out.*
+
diff --git a/bin/tests/system/keymgr2kasp/ns3/kasp.conf.in b/bin/tests/system/keymgr2kasp/ns3/kasp.conf.in
new file mode 100644
index 0000000..55a827b
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/ns3/kasp.conf.in
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "migrate" {
+ dnskey-ttl 7200;
+
+ keys {
+ ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ zsk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@;
+ };
+};
+
+dnssec-policy "timing-metadata" {
+ dnskey-ttl 300;
+
+ signatures-refresh P1W;
+ signatures-validity P2W;
+ signatures-validity-dnskey P2W;
+
+ keys {
+ ksk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@;
+ zsk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@;
+ };
+
+ // Together 12h
+ zone-propagation-delay 3600;
+ max-zone-ttl 11h;
+
+ // Together 3h
+ parent-propagation-delay pt1h;
+ parent-ds-ttl 7200;
+};
+
+/*
+ * This policy tests migration from existing keys with 1024 bits RSASHA1 keys
+ * to ECDSAP256SHA256 keys.
+ */
+dnssec-policy "migrate-nomatch-algnum" {
+ dnskey-ttl 300;
+
+ keys {
+ ksk key-directory lifetime unlimited algorithm ecdsa256;
+ zsk key-directory lifetime P60D algorithm ecdsa256;
+ };
+
+ // Together 12h
+ zone-propagation-delay 3600;
+ max-zone-ttl 11h;
+
+ // Together 3h
+ parent-propagation-delay pt1h;
+ parent-ds-ttl 7200;
+};
+
+/*
+ * This policy tests migration from existing keys with 2048 bits RSASHA256 keys
+ * to 3072 bits RSASHA256 keys.
+ */
+dnssec-policy "migrate-nomatch-alglen" {
+ dnskey-ttl 300;
+
+ keys {
+ ksk key-directory lifetime unlimited algorithm rsasha256 3072;
+ zsk key-directory lifetime P60D algorithm rsasha256 3072;
+ };
+
+ // Together 12h
+ zone-propagation-delay 3600;
+ max-zone-ttl 11h;
+
+ // Together 3h
+ parent-propagation-delay pt1h;
+ parent-ds-ttl 7200;
+};
+
+/*
+ * This policy tests migration from existing KSK and ZSK to CSK.
+ * The keys clause matches the default policy.
+ */
+dnssec-policy "migrate-nomatch-kzc" {
+ dnskey-ttl 300;
+
+ keys {
+ csk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ };
+
+ // Together 12h
+ zone-propagation-delay 3600;
+ max-zone-ttl 11h;
+
+ // Together 3h
+ parent-propagation-delay pt1h;
+ parent-ds-ttl 7200;
+};
diff --git a/bin/tests/system/keymgr2kasp/ns3/named.conf.in b/bin/tests/system/keymgr2kasp/ns3/named.conf.in
new file mode 100644
index 0000000..40104c1
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/ns3/named.conf.in
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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; };
+ allow-transfer { any; };
+ recursion no;
+ key-directory ".";
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+/* These are zones that migrate to dnssec-policy. */
+zone "migrate.kasp" {
+ type primary;
+ file "migrate.kasp.db";
+ auto-dnssec maintain;
+ allow-update { any; };
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+};
+
+zone "csk.kasp" {
+ type primary;
+ file "csk.kasp.db";
+ auto-dnssec maintain;
+ allow-update { any; };
+ dnssec-dnskey-kskonly no;
+};
+
+zone "csk-nosep.kasp" {
+ type primary;
+ file "csk-nosep.kasp.db";
+ auto-dnssec maintain;
+ allow-update { any; };
+ dnssec-dnskey-kskonly no;
+};
+
+zone "rumoured.kasp" {
+ type primary;
+ file "rumoured.kasp.db";
+ auto-dnssec maintain;
+ allow-update { any; };
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+};
+
+zone "omnipresent.kasp" {
+ type primary;
+ file "omnipresent.kasp.db";
+ auto-dnssec maintain;
+ allow-update { any; };
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+};
+
+zone "migrate-nomatch-algnum.kasp" {
+ type primary;
+ file "migrate-nomatch-algnum.kasp.db";
+ auto-dnssec maintain;
+ allow-update { any; };
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+};
+
+zone "migrate-nomatch-alglen.kasp" {
+ type primary;
+ file "migrate-nomatch-alglen.kasp.db";
+ auto-dnssec maintain;
+ allow-update { any; };
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+};
+
+zone "migrate-nomatch-kzc.kasp" {
+ type primary;
+ file "migrate-nomatch-kzc.kasp.db";
+ auto-dnssec maintain;
+ inline-signing yes;
+};
diff --git a/bin/tests/system/keymgr2kasp/ns3/named2.conf.in b/bin/tests/system/keymgr2kasp/ns3/named2.conf.in
new file mode 100644
index 0000000..3eb1adf
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/ns3/named2.conf.in
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+include "kasp.conf";
+
+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; };
+ allow-transfer { any; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+/* These are zones that migrate to dnssec-policy. */
+zone "migrate.kasp" {
+ type primary;
+ file "migrate.kasp.db";
+ allow-update { any; };
+ dnssec-policy "migrate";
+};
+
+zone "csk.kasp" {
+ type primary;
+ file "csk.kasp.db";
+ allow-update { any; };
+ dnssec-policy "default";
+};
+
+zone "csk-nosep.kasp" {
+ type primary;
+ file "csk-nosep.kasp.db";
+ allow-update { any; };
+ dnssec-policy "default";
+};
+
+zone "rumoured.kasp" {
+ type primary;
+ file "rumoured.kasp.db";
+ allow-update { any; };
+ dnssec-policy "timing-metadata";
+};
+
+zone "omnipresent.kasp" {
+ type primary;
+ file "omnipresent.kasp.db";
+ allow-update { any; };
+ dnssec-policy "timing-metadata";
+};
+
+zone "migrate-nomatch-algnum.kasp" {
+ type primary;
+ file "migrate-nomatch-algnum.kasp.db";
+ allow-update { any; };
+ dnssec-policy "migrate-nomatch-algnum";
+};
+
+zone "migrate-nomatch-alglen.kasp" {
+ type primary;
+ file "migrate-nomatch-alglen.kasp.db";
+ allow-update { any; };
+ dnssec-policy "migrate-nomatch-alglen";
+};
+
+zone "migrate-nomatch-kzc.kasp" {
+ type primary;
+ file "migrate-nomatch-kzc.kasp.db";
+ inline-signing yes;
+ dnssec-policy "migrate-nomatch-kzc";
+};
diff --git a/bin/tests/system/keymgr2kasp/ns3/setup.sh b/bin/tests/system/keymgr2kasp/ns3/setup.sh
new file mode 100644
index 0000000..9f53851
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/ns3/setup.sh
@@ -0,0 +1,148 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns3/setup.sh"
+
+setup() {
+ zone="$1"
+ echo_i "setting up zone: $zone"
+ zonefile="${zone}.db"
+ infile="${zone}.db.infile"
+}
+
+# Make lines shorter by storing key states in environment variables.
+H="HIDDEN"
+R="RUMOURED"
+O="OMNIPRESENT"
+U="UNRETENTIVE"
+
+# Set up a zone with auto-dnssec maintain to migrate to dnssec-policy.
+setup migrate.kasp
+echo "$zone" >> zones
+ksktimes="-P now -A now -P sync now"
+zsktimes="-P now -A now"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.2)
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
+
+# Set up Single-Type Signing Scheme zones with auto-dnssec maintain to
+# migrate to dnssec-policy. This is a zone that has 'update-check-ksk no;'
+# configured, meaning the zone is signed with a single CSK.
+setup csk.kasp
+echo "$zone" >> zones
+csktimes="-P now -A now -P sync now"
+CSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $csktimes $zone 2> keygen.out.$zone.1)
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+$SIGNER -S -z -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
+
+setup csk-nosep.kasp
+echo "$zone" >> zones
+csktimes="-P now -A now -P sync now"
+CSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $csktimes $zone 2> keygen.out.$zone.1)
+cat template.db.in "${CSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
+$SIGNER -S -z -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
+
+# Set up a zone with auto-dnssec maintain to migrate to dnssec-policy, but this
+# time the existing keys do not match the policy. The existing keys are
+# RSASHA256 keys, and will be migrated to a dnssec-policy that dictates
+# ECDSAP256SHA256 keys.
+setup migrate-nomatch-algnum.kasp
+echo "$zone" >> zones
+Tds="now-3h" # Time according to dnssec-policy that DS will be OMNIPRESENT
+Tkey="now-3900s" # DNSKEY TTL + propagation delay
+Tsig="now-12h" # Zone's maximum TTL + propagation delay
+ksktimes="-P ${Tkey} -A ${Tkey} -P sync ${Tds}"
+zsktimes="-P ${Tkey} -A ${Tsig}"
+KSK=$($KEYGEN -a RSASHA256 -b 2048 -L 300 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a RSASHA256 -b 2048 -L 300 $zsktimes $zone 2> keygen.out.$zone.2)
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone 5 "$KSK" >> "$infile"
+private_type_record $zone 5 "$ZSK" >> "$infile"
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
+
+# Set up a zone with auto-dnssec maintain to migrate to dnssec-policy, but this
+# time the existing keys do not match the policy. The existing keys are
+# 2048 bits RSASHA256 keys, and will be migrated to a dnssec-policy that
+# dictates 3072 bits RSASHA256 keys.
+setup migrate-nomatch-alglen.kasp
+echo "$zone" >> zones
+Tds="now-3h" # Time according to dnssec-policy that DS will be OMNIPRESENT
+Tkey="now-3900s" # DNSKEY TTL + propagation delay
+Tsig="now-12h" # Zone's maximum TTL + propagation delay
+ksktimes="-P ${Tkey} -A ${Tkey} -P sync ${Tds}"
+zsktimes="-P ${Tkey} -A ${Tsig}"
+KSK=$($KEYGEN -a RSASHA256 -b 2048 -L 300 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a RSASHA256 -b 2048 -L 300 $zsktimes $zone 2> keygen.out.$zone.2)
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone 5 "$KSK" >> "$infile"
+private_type_record $zone 5 "$ZSK" >> "$infile"
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
+
+# Set up a zone with auto-dnssec maintain to migrate to default dnssec-policy.
+# The zone is signed with KSK/ZSK split, but the dnssec-policy uses CSK.
+setup migrate-nomatch-kzc.kasp
+echo "$zone" >> zones
+Tds="now-3h" # Time according to dnssec-policy that DS will be OMNIPRESENT
+Tkey="now-3900s" # DNSKEY TTL + propagation delay
+Tsig="now-12h" # Zone's maximum TTL + propagation delay
+ksktimes="-P ${Tkey} -A ${Tkey} -P sync ${Tds}"
+zsktimes="-P ${Tkey} -A ${Tsig}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2> keygen.out.$zone.2)
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+cp $infile $zonefile
+private_type_record $zone 5 "$KSK" >> "$infile"
+private_type_record $zone 5 "$ZSK" >> "$infile"
+$SIGNER -PS -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+
+#
+# Set up zones to test time metadata correctly sets state.
+#
+
+# Key states expected to be rumoured after migration.
+setup rumoured.kasp
+echo "$zone" >> zones
+Tds="now-2h"
+Tkey="now-300s"
+Tsig="now-11h"
+ksktimes="-P ${Tkey} -A ${Tkey} -P sync ${Tds}"
+zsktimes="-P ${Tkey} -A ${Tsig}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2> keygen.out.$zone.2)
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
+
+# Key states expected to be omnipresent after migration.
+setup omnipresent.kasp
+echo "$zone" >> zones
+Tds="now-3h" # Time according to dnssec-policy that DS will be OMNIPRESENT
+Tkey="now-3900s" # DNSKEY TTL + propagation delay
+Tsig="now-12h" # Zone's maximum TTL + propagation delay
+ksktimes="-P ${Tkey} -A ${Tkey} -P sync ${Tds}"
+zsktimes="-P ${Tkey} -A ${Tsig}"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2> keygen.out.$zone.2)
+cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
+$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
diff --git a/bin/tests/system/keymgr2kasp/ns3/template.db.in b/bin/tests/system/keymgr2kasp/ns3/template.db.in
new file mode 100644
index 0000000..010b05b
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/ns3/template.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns3
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+
diff --git a/bin/tests/system/keymgr2kasp/ns4/named.conf.in b/bin/tests/system/keymgr2kasp/ns4/named.conf.in
new file mode 100644
index 0000000..ac25806
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/ns4/named.conf.in
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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; };
+ allow-transfer { any; };
+ recursion no;
+ key-directory ".";
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key "external" {
+ algorithm @DEFAULT_HMAC@;
+ secret "YPfMoAk6h+3iN8MDRQC004iSNHY=";
+};
+
+key "internal" {
+ algorithm @DEFAULT_HMAC@;
+ secret "4xILSZQnuO1UKubXHkYUsvBRPu8=";
+};
+
+view "ext" {
+ match-clients { key "external"; };
+
+ zone "view-rsasha256.kasp" {
+ type primary;
+ file "view-rsasha256.kasp.ext.db";
+ auto-dnssec maintain;
+ inline-signing yes;
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+ };
+};
+
+view "int" {
+ match-clients { key "internal"; };
+
+ zone "view-rsasha256.kasp" {
+ type primary;
+ file "view-rsasha256.kasp.int.db";
+ auto-dnssec maintain;
+ inline-signing yes;
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+ };
+};
diff --git a/bin/tests/system/keymgr2kasp/ns4/named2.conf.in b/bin/tests/system/keymgr2kasp/ns4/named2.conf.in
new file mode 100644
index 0000000..fb533f9
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/ns4/named2.conf.in
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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; };
+ allow-transfer { any; };
+ recursion no;
+ key-directory ".";
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+dnssec-policy "rsasha256" {
+ keys {
+ zsk key-directory lifetime P3M algorithm 8 2048;
+ ksk key-directory lifetime P1Y algorithm 8 2048;
+ };
+
+ dnskey-ttl 300;
+ publish-safety 1h;
+ retire-safety 1h;
+
+ signatures-refresh 5d;
+ signatures-validity 14d;
+ signatures-validity-dnskey 14d;
+
+ max-zone-ttl 1d;
+ zone-propagation-delay 300;
+
+ parent-ds-ttl 86400;
+ parent-propagation-delay 3h;
+};
+
+key "external" {
+ algorithm @DEFAULT_HMAC@;
+ secret "YPfMoAk6h+3iN8MDRQC004iSNHY=";
+};
+
+key "internal" {
+ algorithm @DEFAULT_HMAC@;
+ secret "4xILSZQnuO1UKubXHkYUsvBRPu8=";
+};
+
+view "ext" {
+ match-clients { key "external"; };
+
+ zone "view-rsasha256.kasp" {
+ type primary;
+ file "view-rsasha256.kasp.ext.db";
+ inline-signing yes;
+ dnssec-policy "rsasha256";
+ };
+};
+
+view "int" {
+ match-clients { key "internal"; };
+
+ zone "view-rsasha256.kasp" {
+ type primary;
+ file "view-rsasha256.kasp.int.db";
+ inline-signing yes;
+ dnssec-policy "rsasha256";
+ };
+};
diff --git a/bin/tests/system/keymgr2kasp/ns4/setup.sh b/bin/tests/system/keymgr2kasp/ns4/setup.sh
new file mode 100644
index 0000000..63121a0
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/ns4/setup.sh
@@ -0,0 +1,46 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns4/setup.sh"
+
+# Make lines shorter by storing key states in environment variables.
+H="HIDDEN"
+R="RUMOURED"
+O="OMNIPRESENT"
+U="UNRETENTIVE"
+
+zone="view-rsasha256.kasp"
+algo="RSASHA256"
+num="8"
+echo "$zone" >> zones
+
+# Set up zones in views with auto-dnssec maintain to migrate to dnssec-policy.
+# The keys for these zones are in use long enough that they should start a
+# rollover for the ZSK (P3M), but not long enough to initiate a KSK rollover (P1Y).
+ksktimes="-P -186d -A -186d -P sync -186d"
+zsktimes="-P -186d -A -186d"
+KSK=$($KEYGEN -a $algo -L 300 -b 2048 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $algo -L 300 -b 2048 $zsktimes $zone 2> keygen.out.$zone.2)
+
+echo_i "setting up zone $zone (external)"
+view="ext"
+zonefile="${zone}.${view}.db"
+cat template.$view.db.in "${KSK}.key" "${ZSK}.key" > "$zonefile"
+
+echo_i "setting up zone $zone (internal)"
+view="int"
+zonefile="${zone}.${view}.db"
+cat template.$view.db.in "${KSK}.key" "${ZSK}.key" > "$zonefile"
diff --git a/bin/tests/system/keymgr2kasp/ns4/template.ext.db.in b/bin/tests/system/keymgr2kasp/ns4/template.ext.db.in
new file mode 100644
index 0000000..eecda2f
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/ns4/template.ext.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns4
+ns4 A 10.53.0.4
+
+view TXT "external"
diff --git a/bin/tests/system/keymgr2kasp/ns4/template.int.db.in b/bin/tests/system/keymgr2kasp/ns4/template.int.db.in
new file mode 100644
index 0000000..3783d64
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/ns4/template.int.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns4
+ns4 A 10.53.0.4
+
+view TXT "internal"
diff --git a/bin/tests/system/keymgr2kasp/setup.sh b/bin/tests/system/keymgr2kasp/setup.sh
new file mode 100644
index 0000000..e43f798
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/setup.sh
@@ -0,0 +1,34 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+$SHELL clean.sh
+
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
+
+copy_setports ns3/kasp.conf.in ns3/kasp.conf
+
+# Setup zones
+(
+ cd ns3
+ $SHELL setup.sh
+)
+(
+ cd ns4
+ $SHELL setup.sh
+)
diff --git a/bin/tests/system/keymgr2kasp/tests.sh b/bin/tests/system/keymgr2kasp/tests.sh
new file mode 100644
index 0000000..6f9caae
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/tests.sh
@@ -0,0 +1,1276 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+# shellcheck source=kasp.sh
+. ../kasp.sh
+
+start_time="$(TZ=UTC date +%s)"
+status=0
+n=0
+
+###############################################################################
+# Utilities #
+###############################################################################
+
+# Call dig with default options.
+dig_with_opts() {
+
+ if [ -n "$TSIG" ]; then
+ "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" -y "$TSIG" "$@"
+ else
+ "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
+ fi
+}
+
+# Log error and increment failure rate.
+log_error() {
+ echo_i "error: $1"
+ ret=$((ret+1))
+}
+
+# Default next key event threshold. May be extended by wait periods.
+next_key_event_threshold=100
+
+###############################################################################
+# Tests #
+###############################################################################
+
+set_retired_removed() {
+ _Lkey=$2
+ _Iret=$3
+
+ _active=$(key_get $1 ACTIVE)
+ set_addkeytime "${1}" "RETIRED" "${_active}" "${_Lkey}"
+ _retired=$(key_get $1 RETIRED)
+ set_addkeytime "${1}" "REMOVED" "${_retired}" "${_Iret}"
+}
+
+rollover_predecessor_keytimes() {
+ _addtime=$1
+
+ _created=$(key_get KEY1 CREATED)
+
+ set_addkeytime "KEY1" "PUBLISHED" "${_created}" "${_addtime}"
+ set_addkeytime "KEY1" "SYNCPUBLISH" "${_created}" "${_addtime}"
+ set_addkeytime "KEY1" "ACTIVE" "${_created}" "${_addtime}"
+ [ "$Lksk" = 0 ] || set_retired_removed "KEY1" "${Lksk}" "${IretKSK}"
+
+ _created=$(key_get KEY2 CREATED)
+ set_addkeytime "KEY2" "PUBLISHED" "${_created}" "${_addtime}"
+ set_addkeytime "KEY2" "ACTIVE" "${_created}" "${_addtime}"
+ [ "$Lzsk" = 0 ] || set_retired_removed "KEY2" "${Lzsk}" "${IretZSK}"
+}
+
+# Policy parameters.
+# Lksk: unlimited
+# Lzsk: unlimited
+Lksk=0
+Lzsk=0
+
+
+#################################################
+# Test state before switching to dnssec-policy. #
+#################################################
+
+# Set expected key properties for migration tests.
+# $1 $2: Algorithm number and string.
+# $3 $4: KSK and ZSK size.
+init_migration_keys() {
+ key_clear "KEY1"
+ key_set "KEY1" "LEGACY" "yes"
+ set_keyrole "KEY1" "ksk"
+ set_keylifetime "KEY1" "none"
+ set_keyalgorithm "KEY1" "$1" "$2" "$3"
+ set_keysigning "KEY1" "yes"
+ set_zonesigning "KEY1" "no"
+
+ key_clear "KEY2"
+ key_set "KEY2" "LEGACY" "yes"
+ set_keyrole "KEY2" "zsk"
+ set_keylifetime "KEY2" "none"
+ set_keyalgorithm "KEY2" "$1" "$2" "$4"
+ set_keysigning "KEY2" "no"
+ set_zonesigning "KEY2" "yes"
+
+ key_clear "KEY3"
+ key_clear "KEY4"
+}
+
+# Set expected key states for migration tests.
+# $1: Goal
+# $2: States
+init_migration_states() {
+ set_keystate "KEY1" "GOAL" "$1"
+ set_keystate "KEY1" "STATE_DNSKEY" "$2"
+ set_keystate "KEY1" "STATE_KRRSIG" "$2"
+ set_keystate "KEY1" "STATE_DS" "$2"
+
+ set_keystate "KEY2" "GOAL" "$1"
+ set_keystate "KEY2" "STATE_DNSKEY" "$2"
+ set_keystate "KEY2" "STATE_ZRRSIG" "$2"
+}
+
+#
+# Testing a good migration.
+#
+set_zone "migrate.kasp"
+set_policy "none" "2" "7200"
+set_server "ns3" "10.53.0.3"
+
+init_migration_keys "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+init_migration_states "omnipresent" "rumoured"
+
+# Make sure the zone is signed with legacy keys.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# These keys are immediately published and activated.
+rollover_predecessor_keytimes 0
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+# Remember legacy key tags.
+_migrate_ksk=$(key_get KEY1 ID)
+_migrate_zsk=$(key_get KEY2 ID)
+
+#
+# Testing a good migration (CSK).
+#
+set_zone "csk.kasp"
+set_policy "none" "1" "7200"
+set_server "ns3" "10.53.0.3"
+
+key_clear "KEY1"
+key_set "KEY1" "LEGACY" "yes"
+set_keyrole "KEY1" "ksk"
+# This key also acts as a ZSK.
+key_set "KEY1" "ZSK" "yes"
+set_keylifetime "KEY1" "none"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "rumoured"
+
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# Make sure the zone is signed with legacy key.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# The key is immediately published and activated.
+_created=$(key_get KEY1 CREATED)
+set_keytime "KEY1" "PUBLISHED" "${_created}"
+set_keytime "KEY1" "SYNCPUBLISH" "${_created}"
+set_keytime "KEY1" "ACTIVE" "${_created}"
+
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+# Remember legacy key tags.
+_migrate_csk=$(key_get KEY1 ID)
+
+#
+# Testing a good migration (CSK, no SEP).
+#
+set_zone "csk-nosep.kasp"
+set_policy "none" "1" "7200"
+set_server "ns3" "10.53.0.3"
+
+key_clear "KEY1"
+key_set "KEY1" "LEGACY" "yes"
+set_keyrole "KEY1" "zsk"
+# Despite the missing SEP bit, this key also acts as a KSK.
+key_set "KEY1" "KSK" "yes"
+set_keylifetime "KEY1" "none"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "rumoured"
+
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# Make sure the zone is signed with legacy key.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+# The key is immediately published and activated.
+_created=$(key_get KEY1 CREATED)
+set_keytime "KEY1" "PUBLISHED" "${_created}"
+set_keytime "KEY1" "SYNCPUBLISH" "${_created}"
+set_keytime "KEY1" "ACTIVE" "${_created}"
+
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+# Remember legacy key tags.
+_migrate_csk_nosep=$(key_get KEY1 ID)
+
+#
+# Testing key states derived from key timing metadata (rumoured).
+#
+set_zone "rumoured.kasp"
+set_policy "none" "2" "300"
+set_server "ns3" "10.53.0.3"
+
+init_migration_keys "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+init_migration_states "omnipresent" "rumoured"
+
+# Make sure the zone is signed with legacy keys.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+# Remember legacy key tags.
+_rumoured_ksk=$(key_get KEY1 ID)
+_rumoured_zsk=$(key_get KEY2 ID)
+
+#
+# Testing key states derived from key timing metadata (omnipresent).
+#
+set_zone "omnipresent.kasp"
+set_policy "none" "2" "300"
+set_server "ns3" "10.53.0.3"
+
+init_migration_keys "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+init_migration_states "omnipresent" "omnipresent"
+
+# Make sure the zone is signed with legacy keys.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+check_apex
+check_subdomain
+dnssec_verify
+# Remember legacy key tags.
+_omnipresent_ksk=$(key_get KEY1 ID)
+_omnipresent_zsk=$(key_get KEY2 ID)
+
+#
+# Testing migration with unmatched existing keys (different algorithm).
+#
+set_zone "migrate-nomatch-algnum.kasp"
+set_policy "none" "2" "300"
+set_server "ns3" "10.53.0.3"
+
+init_migration_keys "8" "RSASHA256" "2048" "2048"
+init_migration_states "omnipresent" "omnipresent"
+
+# Make sure the zone is signed with legacy keys.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# The KSK is immediately published and activated.
+# -P : now-3900s
+# -P sync: now-3h
+# -A : now-3900s
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY1" "ACTIVE" "${created}" -3900
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -10800
+# The ZSK is immediately published and activated.
+# -P: now-3900s
+# -A: now-12h
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY2" "ACTIVE" "${created}" -43200
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Remember legacy key tags.
+_migratenomatch_algnum_ksk=$(key_get KEY1 ID)
+_migratenomatch_algnum_zsk=$(key_get KEY2 ID)
+
+#
+# Testing migration with unmatched existing keys (different length).
+#
+set_zone "migrate-nomatch-alglen.kasp"
+set_policy "none" "2" "300"
+set_server "ns3" "10.53.0.3"
+
+init_migration_keys "8" "RSASHA256" "2048" "2048"
+init_migration_states "omnipresent" "omnipresent"
+
+# Make sure the zone is signed with legacy keys.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The KSK is immediately published and activated.
+# P : now-3900s
+# P sync: now-3h
+# A : now-3900s
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY1" "ACTIVE" "${created}" -3900
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -10800
+# - The ZSK is immediately published and activated.
+# P: now-3900s
+# A: now-12h
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY2" "ACTIVE" "${created}" -43200
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Remember legacy key tags.
+_migratenomatch_alglen_ksk=$(key_get KEY1 ID)
+_migratenomatch_alglen_zsk=$(key_get KEY2 ID)
+
+#
+# Testing migration with unmatched existing keys (different roles KSK/ZSK -> CSK).
+#
+set_zone "migrate-nomatch-kzc.kasp"
+set_policy "none" "2" "300"
+set_server "ns3" "10.53.0.3"
+
+init_migration_keys "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+init_migration_states "omnipresent" "omnipresent"
+
+# Make sure the zone is signed with legacy keys.
+check_keys
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - The KSK is immediately published and activated.
+# P : now-3900s
+# P sync: now-3h
+# A : now-3900s
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY1" "ACTIVE" "${created}" -3900
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -10800
+# - The ZSK is immediately published and activated.
+# P: now-3900s
+# A: now-12h
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY2" "ACTIVE" "${created}" -43200
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Remember legacy key tags.
+_migratenomatch_kzc_ksk=$(key_get KEY1 ID)
+_migratenomatch_kzc_zsk=$(key_get KEY2 ID)
+
+#############
+# Reconfig. #
+#############
+echo_i "reconfig (migration to dnssec-policy)"
+copy_setports ns3/named2.conf.in ns3/named.conf
+rndc_reconfig ns3 10.53.0.3
+
+# Calculate time passed to correctly check for next key events.
+now="$(TZ=UTC date +%s)"
+time_passed=$((now-start_time))
+echo_i "${time_passed} seconds passed between start of tests and reconfig"
+
+# Wait until we have seen "zone_rekey done:" message for this key.
+_wait_for_done_signing() {
+ _zone=$1
+
+ _ksk=$(key_get $2 KSK)
+ _zsk=$(key_get $2 ZSK)
+ if [ "$_ksk" = "yes" ]; then
+ _role="KSK"
+ _expect_type=EXPECT_KRRSIG
+ elif [ "$_zsk" = "yes" ]; then
+ _role="ZSK"
+ _expect_type=EXPECT_ZRRSIG
+ fi
+
+ if [ "$(key_get ${2} $_expect_type)" = "yes" ] && [ "$(key_get $2 $_role)" = "yes" ]; then
+ _keyid=$(key_get $2 ID)
+ _keyalg=$(key_get $2 ALG_STR)
+ echo_i "wait for zone ${_zone} is done signing with $2 ${_zone}/${_keyalg}/${_keyid}"
+ grep "zone_rekey done: key ${_keyid}/${_keyalg}" "${DIR}/named.run" > /dev/null || return 1
+ fi
+
+ return 0
+}
+wait_for_done_signing() {
+ n=$((n+1))
+ echo_i "wait for zone ${ZONE} is done signing ($n)"
+ ret=0
+
+ retry_quiet 30 _wait_for_done_signing ${ZONE} KEY1 || ret=1
+ retry_quiet 30 _wait_for_done_signing ${ZONE} KEY2 || ret=1
+ retry_quiet 30 _wait_for_done_signing ${ZONE} KEY3 || ret=1
+ retry_quiet 30 _wait_for_done_signing ${ZONE} KEY4 || ret=1
+
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+
+################################################
+# Test state after switching to dnssec-policy. #
+################################################
+
+# Policy parameters.
+# ZSK now has lifetime of 60 days (5184000 seconds).
+# The key is removed after Iret = TTLsig + Dprp + Dsgn + retire-safety.
+Lzsk=5184000
+IretZSK=867900
+
+#
+# Testing good migration.
+#
+set_zone "migrate.kasp"
+set_policy "migrate" "2" "7200"
+set_server "ns3" "10.53.0.3"
+
+# Key properties, timings and metadata should be the same as legacy keys above.
+# However, because the zsk has a lifetime, kasp will set the retired time.
+init_migration_keys "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+init_migration_states "omnipresent" "rumoured"
+key_set "KEY1" "LEGACY" "no"
+key_set "KEY2" "LEGACY" "no"
+set_keylifetime "KEY1" "${Lksk}"
+set_keylifetime "KEY2" "${Lzsk}"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+rollover_predecessor_keytimes 0
+
+# - Key now has lifetime of 60 days (5184000 seconds).
+# The key is removed after Iret = TTLsig + Dprp + Dsgn + retire-safety.
+# TTLsig: 1d (86400 seconds)
+# Dprp: 5m (300 seconds)
+# Dsgn: 9d (777600 seconds)
+# retire-safety: 1h (3600 seconds)
+# IretZSK: 10d65m (867900 seconds)
+active=$(key_get KEY2 ACTIVE)
+set_addkeytime "KEY2" "RETIRED" "${active}" "${Lzsk}"
+retired=$(key_get KEY2 RETIRED)
+set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Check key tags, should be the same.
+n=$((n+1))
+echo_i "check that of zone ${ZONE} migration to dnssec-policy uses the same keys ($n)"
+ret=0
+[ $_migrate_ksk = $(key_get KEY1 ID) ] || log_error "mismatch ksk tag"
+[ $_migrate_zsk = $(key_get KEY2 ID) ] || log_error "mismatch zsk tag"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Testing a good migration (CSK).
+#
+set_zone "csk.kasp"
+set_policy "default" "1" "7200"
+set_server "ns3" "10.53.0.3"
+
+key_clear "KEY1"
+key_set "KEY1" "LEGACY" "no"
+set_keyrole "KEY1" "csk"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "rumoured"
+
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# The key was immediately published and activated.
+_created=$(key_get KEY1 CREATED)
+set_keytime "KEY1" "PUBLISHED" "${_created}"
+set_keytime "KEY1" "SYNCPUBLISH" "${_created}"
+set_keytime "KEY1" "ACTIVE" "${_created}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Check key tags, should be the same.
+n=$((n+1))
+echo_i "check that of zone ${ZONE} migration to dnssec-policy uses the same key ($n)"
+ret=0
+[ $_migrate_csk = $(key_get KEY1 ID) ] || log_error "mismatch csk tag"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Testing a good migration (CSK, no SEP).
+#
+set_zone "csk-nosep.kasp"
+set_policy "default" "1" "7200"
+set_server "ns3" "10.53.0.3"
+
+key_clear "KEY1"
+key_set "KEY1" "LEGACY" "no"
+set_keyrole "KEY1" "csk"
+key_set "KEY1" "FLAGS" "256"
+set_keylifetime "KEY1" "0"
+set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+set_keysigning "KEY1" "yes"
+set_zonesigning "KEY1" "yes"
+
+set_keystate "KEY1" "GOAL" "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS" "rumoured"
+
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# The key was immediately published and activated.
+_created=$(key_get KEY1 CREATED)
+set_keytime "KEY1" "PUBLISHED" "${_created}"
+set_keytime "KEY1" "SYNCPUBLISH" "${_created}"
+set_keytime "KEY1" "ACTIVE" "${_created}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Check key tags, should be the same.
+n=$((n+1))
+echo_i "check that of zone ${ZONE} migration to dnssec-policy uses the same key ($n)"
+ret=0
+[ $_migrate_csk_nosep = $(key_get KEY1 ID) ] || log_error "mismatch csk tag"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Test migration to dnssec-policy, existing keys do not match key algorithm.
+#
+set_zone "migrate-nomatch-algnum.kasp"
+set_policy "migrate-nomatch-algnum" "4" "300"
+set_server "ns3" "10.53.0.3"
+# The legacy keys need to be retired, but otherwise stay present until the
+# new keys are omnipresent, and can be used to construct a chain of trust.
+init_migration_keys "8" "RSASHA256" "2048" "2048"
+init_migration_states "hidden" "omnipresent"
+key_set "KEY1" "LEGACY" "no"
+key_set "KEY2" "LEGACY" "no"
+
+set_keyrole "KEY3" "ksk"
+set_keylifetime "KEY3" "0"
+set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY3" "yes"
+set_zonesigning "KEY3" "no"
+
+set_keyrole "KEY4" "zsk"
+set_keylifetime "KEY4" "5184000"
+set_keyalgorithm "KEY4" "13" "ECDSAP256SHA256" "256"
+set_keysigning "KEY4" "no"
+set_zonesigning "KEY4" "yes"
+
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY3" "STATE_DS" "hidden"
+
+set_keystate "KEY4" "GOAL" "omnipresent"
+set_keystate "KEY4" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY4" "STATE_ZRRSIG" "rumoured"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - KSK must be retired since it no longer matches the policy.
+# P : now-3900s
+# P sync: now-3h
+# A : now-3900s
+# - The key is removed after the retire interval:
+# IretKSK = TTLds + DprpP + retire_safety.
+# TTLds: 2h (7200 seconds)
+# Dprp: 1h (3600 seconds)
+# retire-safety: 1h (3600 seconds)
+# IretKSK: 4h (14400 seconds)
+IretKSK=14400
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY1" "ACTIVE" "${created}" -3900
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -10800
+keyfile=$(key_get KEY1 BASEFILE)
+grep "; Inactive:" "${keyfile}.key" > retired.test${n}.ksk
+retired=$(awk '{print $3}' < retired.test${n}.ksk)
+set_keytime "KEY1" "RETIRED" "${retired}"
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
+# - ZSK must be retired since it no longer matches the policy.
+# P: now-3900s
+# A: now-12h
+# - The key is removed after the retire interval:
+# IretZSK = TTLsig + Dprp + Dsgn + retire-safety.
+# TTLsig: 11h (39600 seconds)
+# Dprp: 1h (3600 seconds)
+# Dsgn: 9d (777600 seconds)
+# retire-safety: 1h (3600 seconds)
+# IretZSK: 9d13h (824400 seconds)
+IretZSK=824400
+Lzsk=5184000
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY2" "ACTIVE" "${created}" -43200
+keyfile=$(key_get KEY2 BASEFILE)
+grep "; Inactive:" "${keyfile}.key" > retired.test${n}.zsk
+retired=$(awk '{print $3}' < retired.test${n}.zsk)
+set_keytime "KEY2" "RETIRED" "${retired}"
+set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
+# - The new KSK is immediately published and activated.
+created=$(key_get KEY3 CREATED)
+set_keytime "KEY3" "PUBLISHED" "${created}"
+set_keytime "KEY3" "ACTIVE" "${created}"
+# - It takes TTLsig + Dprp + publish-safety hours to propagate the zone.
+# TTLsig: 11h (39600 seconds)
+# Dprp: 1h (3600 seconds)
+# publish-safety: 1h (3600 seconds)
+# Ipub: 13h (46800 seconds)
+Ipub=46800
+set_addkeytime "KEY3" "SYNCPUBLISH" "${created}" "${Ipub}"
+# - The ZSK is immediately published and activated.
+created=$(key_get KEY4 CREATED)
+set_keytime "KEY4" "PUBLISHED" "${created}"
+set_keytime "KEY4" "ACTIVE" "${created}"
+active=$(key_get KEY4 ACTIVE)
+set_addkeytime "KEY4" "RETIRED" "${active}" "${Lzsk}"
+retired=$(key_get KEY4 RETIRED)
+set_addkeytime "KEY4" "REMOVED" "${retired}" "${IretZSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Check key tags, should be the same.
+n=$((n+1))
+echo_i "check that of zone ${ZONE} migration to dnssec-policy keeps existing keys ($n)"
+ret=0
+[ $_migratenomatch_algnum_ksk = $(key_get KEY1 ID) ] || log_error "mismatch ksk tag"
+[ $_migratenomatch_algnum_zsk = $(key_get KEY2 ID) ] || log_error "mismatch zsk tag"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Test migration to dnssec-policy, existing keys do not match key length.
+#
+set_zone "migrate-nomatch-alglen.kasp"
+set_policy "migrate-nomatch-alglen" "4" "300"
+set_server "ns3" "10.53.0.3"
+
+# The legacy keys need to be retired, but otherwise stay present until the
+# new keys are omnipresent, and can be used to construct a chain of trust.
+init_migration_keys "8" "RSASHA256" "2048" "2048"
+init_migration_states "hidden" "omnipresent"
+key_set "KEY1" "LEGACY" "no"
+key_set "KEY2" "LEGACY" "no"
+
+set_keyrole "KEY3" "ksk"
+set_keylifetime "KEY3" "0"
+set_keyalgorithm "KEY3" "8" "RSASHA256" "3072"
+set_keysigning "KEY3" "yes"
+set_zonesigning "KEY3" "no"
+
+set_keyrole "KEY4" "zsk"
+set_keylifetime "KEY4" "5184000"
+set_keyalgorithm "KEY4" "8" "RSASHA256" "3072"
+set_keysigning "KEY4" "no"
+# This key is considered to be prepublished, so it is not yet signing.
+set_zonesigning "KEY4" "no"
+
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY3" "STATE_DS" "hidden"
+
+set_keystate "KEY4" "GOAL" "omnipresent"
+set_keystate "KEY4" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY4" "STATE_ZRRSIG" "hidden"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - KSK must be retired since it no longer matches the policy.
+# P : now-3900s
+# P sync: now-3h
+# A : now-3900s
+# - The key is removed after the retire interval:
+# IretKSK = TTLds + DprpP + retire_safety.
+# TTLds: 2h (7200 seconds)
+# Dprp: 1h (3600 seconds)
+# retire-safety: 1h (3600 seconds)
+# IretKSK: 4h (14400 seconds)
+IretKSK=14400
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY1" "ACTIVE" "${created}" -3900
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -10800
+keyfile=$(key_get KEY1 BASEFILE)
+grep "; Inactive:" "${keyfile}.key" > retired.test${n}.ksk
+retired=$(awk '{print $3}' < retired.test${n}.ksk)
+set_keytime "KEY1" "RETIRED" "${retired}"
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
+# - ZSK must be retired since it no longer matches the policy.
+# P: now-3900s
+# A: now-12h
+# - The key is removed after the retire interval:
+# IretZSK = TTLsig + Dprp + Dsgn + retire-safety.
+# TTLsig: 11h (39600 seconds)
+# Dprp: 1h (3600 seconds)
+# Dsgn: 9d (777600 seconds)
+# publish-safety: 1h (3600 seconds)
+# IretZSK: 9d13h (824400 seconds)
+IretZSK=824400
+Lzsk=5184000
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY2" "ACTIVE" "${created}" -43200
+keyfile=$(key_get KEY2 BASEFILE)
+grep "; Inactive:" "${keyfile}.key" > retired.test${n}.zsk
+retired=$(awk '{print $3}' < retired.test${n}.zsk)
+set_keytime "KEY2" "RETIRED" "${retired}"
+set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
+# - The new KSK is immediately published and activated.
+created=$(key_get KEY3 CREATED)
+set_keytime "KEY3" "PUBLISHED" "${created}"
+set_keytime "KEY3" "ACTIVE" "${created}"
+# - It takes TTLsig + Dprp + publish-safety hours to propagate the zone.
+# TTLsig: 11h (39600 seconds)
+# Dprp: 1h (3600 seconds)
+# publish-safety: 1h (3600 seconds)
+# Ipub: 13h (46800 seconds)
+Ipub=46800
+set_addkeytime "KEY3" "SYNCPUBLISH" "${created}" "${Ipub}"
+# - The ZSK is immediately published and activated.
+created=$(key_get KEY4 CREATED)
+set_keytime "KEY4" "PUBLISHED" "${created}"
+set_keytime "KEY4" "ACTIVE" "${created}"
+active=$(key_get KEY4 ACTIVE)
+set_addkeytime "KEY4" "RETIRED" "${active}" "${Lzsk}"
+retired=$(key_get KEY4 RETIRED)
+set_addkeytime "KEY4" "REMOVED" "${retired}" "${IretZSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Check key tags, should be the same.
+n=$((n+1))
+echo_i "check that of zone ${ZONE} migration to dnssec-policy keeps existing keys ($n)"
+ret=0
+[ $_migratenomatch_alglen_ksk = $(key_get KEY1 ID) ] || log_error "mismatch ksk tag"
+[ $_migratenomatch_alglen_zsk = $(key_get KEY2 ID) ] || log_error "mismatch zsk tag"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Test migration to dnssec-policy, existing keys do not match role (KSK/ZSK -> CSK).
+#
+set_zone "migrate-nomatch-kzc.kasp"
+set_policy "migrate-nomatch-kzc" "3" "300"
+set_server "ns3" "10.53.0.3"
+
+# The legacy keys need to be retired, but otherwise stay present until the
+# new keys are omnipresent, and can be used to construct a chain of trust.
+init_migration_keys "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+init_migration_states "hidden" "omnipresent"
+key_set "KEY1" "LEGACY" "no"
+key_set "KEY2" "LEGACY" "no"
+
+set_keyrole "KEY3" "csk"
+set_keylifetime "KEY3" "0"
+set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
+set_keysigning "KEY3" "yes"
+set_zonesigning "KEY3" "no"
+
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_KRRSIG" "rumoured"
+# This key is considered to be prepublished, so it is not yet signing.
+set_keystate "KEY3" "STATE_ZRRSIG" "hidden"
+set_keystate "KEY3" "STATE_DS" "hidden"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+# - KSK must be retired since it no longer matches the policy.
+# P : now-3900s
+# P sync: now-3h
+# A : now-3900s
+# - The key is removed after the retire interval:
+# IretKSK = TTLds + DprpP + retire_safety.
+# TTLds: 2h (7200 seconds)
+# Dprp: 1h (3600 seconds)
+# retire-safety: 1h (3600 seconds)
+# IretKSK: 4h (14400 seconds)
+IretKSK=14400
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY1" "ACTIVE" "${created}" -3900
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -10800
+keyfile=$(key_get KEY1 BASEFILE)
+grep "; Inactive:" "${keyfile}.key" > retired.test${n}.ksk
+retired=$(awk '{print $3}' < retired.test${n}.ksk)
+set_keytime "KEY1" "RETIRED" "${retired}"
+set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
+# - ZSK must be retired since it no longer matches the policy.
+# P: now-3900s
+# A: now-12h
+# - The key is removed after the retire interval:
+# IretZSK = TTLsig + Dprp + Dsgn + retire-safety.
+# TTLsig: 11h (39600 seconds)
+# Dprp: 1h (3600 seconds)
+# Dsgn: 9d (777600 seconds)
+# publish-safety: 1h (3600 seconds)
+# IretZSK: 9d13h (824400 seconds)
+IretZSK=824400
+Lzsk=5184000
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY2" "ACTIVE" "${created}" -43200
+keyfile=$(key_get KEY2 BASEFILE)
+grep "; Inactive:" "${keyfile}.key" > retired.test${n}.zsk
+retired=$(awk '{print $3}' < retired.test${n}.zsk)
+set_keytime "KEY2" "RETIRED" "${retired}"
+set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
+# - The new KSK is immediately published and activated.
+created=$(key_get KEY3 CREATED)
+set_keytime "KEY3" "PUBLISHED" "${created}"
+set_keytime "KEY3" "ACTIVE" "${created}"
+# - It takes TTLsig + Dprp + publish-safety hours to propagate the zone.
+# TTLsig: 11h (39600 seconds)
+# Dprp: 1h (3600 seconds)
+# publish-safety: 1h (3600 seconds)
+# Ipub: 13h (46800 seconds)
+Ipub=46800
+set_addkeytime "KEY3" "SYNCPUBLISH" "${created}" "${Ipub}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Check key tags, should be the same.
+n=$((n+1))
+echo_i "check that of zone ${ZONE} migration to dnssec-policy keeps existing keys ($n)"
+ret=0
+[ $_migratenomatch_kzc_ksk = $(key_get KEY1 ID) ] || log_error "mismatch ksk tag"
+[ $_migratenomatch_kzc_zsk = $(key_get KEY2 ID) ] || log_error "mismatch zsk tag"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+########################################################
+# Testing key states derived from key timing metadata. #
+########################################################
+
+# Policy parameters.
+# KSK has lifetime of 60 days (5184000 seconds).
+# The KSK is removed after Iret = DprpP + TTLds + retire-safety =
+# 4h = 14400 seconds.
+Lksk=5184000
+IretKSK=14400
+# ZSK has lifetime of 60 days (5184000 seconds).
+# The ZSK is removed after Iret = TTLsig + Dprp + Dsgn + retire-safety =
+# 181h = 651600 seconds.
+Lzsk=5184000
+IretZSK=651600
+
+#
+# Testing rumoured state.
+#
+set_zone "rumoured.kasp"
+set_policy "timing-metadata" "2" "300"
+set_server "ns3" "10.53.0.3"
+
+# Key properties, timings and metadata should be the same as legacy keys above.
+init_migration_keys "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+init_migration_states "omnipresent" "rumoured"
+key_set "KEY1" "LEGACY" "no"
+key_set "KEY2" "LEGACY" "no"
+set_keylifetime "KEY1" "${Lksk}"
+set_keylifetime "KEY2" "${Lzsk}"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+#
+# Tds="now-2h" (7200)
+# Tkey="now-300s" (300)
+# Tsig="now-11h" (39600)
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -300
+set_addkeytime "KEY1" "ACTIVE" "${created}" -300
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -7200
+set_retired_removed "KEY1" "${Lksk}" "${IretKSK}"
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -300
+set_addkeytime "KEY2" "ACTIVE" "${created}" -39600
+set_retired_removed "KEY2" "${Lzsk}" "${IretZSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Check key tags, should be the same.
+n=$((n+1))
+echo_i "check that of zone ${ZONE} migration to dnssec-policy uses the same keys ($n)"
+ret=0
+[ $_rumoured_ksk = $(key_get KEY1 ID) ] || log_error "mismatch ksk tag"
+[ $_rumoured_zsk = $(key_get KEY2 ID) ] || log_error "mismatch zsk tag"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Testing omnipresent state.
+#
+set_zone "omnipresent.kasp"
+set_policy "timing-metadata" "2" "300"
+set_server "ns3" "10.53.0.3"
+
+# Key properties, timings and metadata should be the same as legacy keys above.
+init_migration_keys "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" "$DEFAULT_BITS"
+init_migration_states "omnipresent" "omnipresent"
+key_set "KEY1" "LEGACY" "no"
+key_set "KEY2" "LEGACY" "no"
+set_keylifetime "KEY1" "${Lksk}"
+set_keylifetime "KEY2" "${Lzsk}"
+
+# Various signing policy checks.
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
+
+# Set expected key times:
+#
+# Tds="now-3h" (10800)
+# Tkey="now-3900s" (3900)
+# Tsig="now-12h" (43200)
+created=$(key_get KEY1 CREATED)
+set_addkeytime "KEY1" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY1" "ACTIVE" "${created}" -3900
+set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -10800
+set_retired_removed "KEY1" "${Lksk}" "${IretKSK}"
+created=$(key_get KEY2 CREATED)
+set_addkeytime "KEY2" "PUBLISHED" "${created}" -3900
+set_addkeytime "KEY2" "ACTIVE" "${created}" -43200
+set_retired_removed "KEY2" "${Lzsk}" "${IretZSK}"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+check_subdomain
+dnssec_verify
+
+# Check key tags, should be the same.
+n=$((n+1))
+echo_i "check that of zone ${ZONE} migration to dnssec-policy uses the same keys ($n)"
+ret=0
+[ $_omnipresent_ksk = $(key_get KEY1 ID) ] || log_error "mismatch ksk tag"
+[ $_omnipresent_zsk = $(key_get KEY2 ID) ] || log_error "mismatch zsk tag"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+
+######################################
+# Testing good migration with views. #
+######################################
+init_view_migration() {
+ key_clear "KEY1"
+ key_set "KEY1" "LEGACY" "yes"
+ set_keyrole "KEY1" "ksk"
+ set_keylifetime "KEY1" "0"
+ set_keysigning "KEY1" "yes"
+ set_zonesigning "KEY1" "no"
+
+ key_clear "KEY2"
+ key_set "KEY2" "LEGACY" "yes"
+ set_keyrole "KEY2" "zsk"
+ set_keylifetime "KEY2" "0"
+ set_keysigning "KEY2" "no"
+ set_zonesigning "KEY2" "yes"
+
+ key_clear "KEY3"
+ key_clear "KEY4"
+
+ set_keystate "KEY1" "GOAL" "omnipresent"
+ set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+ set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+ set_keystate "KEY1" "STATE_DS" "rumoured"
+
+ set_keystate "KEY2" "GOAL" "omnipresent"
+ set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+ set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
+}
+
+set_keytimes_view_migration() {
+ # Key is six months in use.
+ created=$(key_get KEY1 CREATED)
+ set_addkeytime "KEY1" "PUBLISHED" "${created}" -16070400
+ set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -16070400
+ set_addkeytime "KEY1" "ACTIVE" "${created}" -16070400
+ created=$(key_get KEY2 CREATED)
+ set_addkeytime "KEY2" "PUBLISHED" "${created}" -16070400
+ set_addkeytime "KEY2" "ACTIVE" "${created}" -16070400
+}
+
+# Zone view.rsasha256.kasp (external)
+set_zone "view-rsasha256.kasp"
+set_policy "rsasha256" "2" "300"
+set_server "ns4" "10.53.0.4"
+init_view_migration
+set_keyalgorithm "KEY1" "8" "RSASHA256" "2048"
+set_keyalgorithm "KEY2" "8" "RSASHA256" "2048"
+TSIG="$DEFAULT_HMAC:external:$VIEW1"
+wait_for_nsec
+# Make sure the zone is signed with legacy keys.
+check_keys
+set_keytimes_view_migration
+check_keytimes
+dnssec_verify
+
+n=$((n+1))
+# check subdomain
+echo_i "check TXT $ZONE (view ext) rrset is signed correctly ($n)"
+ret=0
+dig_with_opts "view.${ZONE}" "@${SERVER}" TXT > "dig.out.$DIR.test$n.txt" || log_error "dig view.${ZONE} TXT failed"
+grep "status: NOERROR" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "mismatch status in DNS response"
+grep "view.${ZONE}\..*${DEFAULT_TTL}.*IN.*TXT.*external" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "missing view.${ZONE} TXT record in response"
+check_signatures TXT "dig.out.$DIR.test$n.txt" "ZSK"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Remember legacy key tags.
+_migrate_ext8_ksk=$(key_get KEY1 ID)
+_migrate_ext8_zsk=$(key_get KEY2 ID)
+
+# Zone view.rsasha256.kasp (internal)
+set_zone "view-rsasha256.kasp"
+set_policy "rsasha256" "2" "300"
+set_server "ns4" "10.53.0.4"
+init_view_migration
+set_keyalgorithm "KEY1" "8" "RSASHA256" "2048"
+set_keyalgorithm "KEY2" "8" "RSASHA256" "2048"
+TSIG="$DEFAULT_HMAC:internal:$VIEW2"
+wait_for_nsec
+# Make sure the zone is signed with legacy keys.
+check_keys
+set_keytimes_view_migration
+check_keytimes
+dnssec_verify
+
+n=$((n+1))
+# check subdomain
+echo_i "check TXT $ZONE (view int) rrset is signed correctly ($n)"
+ret=0
+dig_with_opts "view.${ZONE}" "@${SERVER}" TXT > "dig.out.$DIR.test$n.txt" || log_error "dig view.${ZONE} TXT failed"
+grep "status: NOERROR" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "mismatch status in DNS response"
+grep "view.${ZONE}\..*${DEFAULT_TTL}.*IN.*TXT.*internal" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "missing view.${ZONE} TXT record in response"
+check_signatures TXT "dig.out.$DIR.test$n.txt" "ZSK"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+# Remember legacy key tags.
+_migrate_int8_ksk=$(key_get KEY1 ID)
+_migrate_int8_zsk=$(key_get KEY2 ID)
+
+# Reconfig dnssec-policy.
+echo_i "reconfig to switch to dnssec-policy"
+copy_setports ns4/named2.conf.in ns4/named.conf
+rndc_reconfig ns4 10.53.0.4
+
+# Calculate time passed to correctly check for next key events.
+now="$(TZ=UTC date +%s)"
+time_passed=$((now-start_time))
+echo_i "${time_passed} seconds passed between start of tests and reconfig"
+
+#
+# Testing migration (RSASHA256, views).
+#
+set_zone "view-rsasha256.kasp"
+set_policy "rsasha256" "3" "300"
+set_server "ns4" "10.53.0.4"
+init_migration_keys "8" "RSASHA256" "2048" "2048"
+init_migration_states "omnipresent" "rumoured"
+# Key properties, timings and metadata should be the same as legacy keys above.
+# However, because the keys have a lifetime, kasp will set the retired time.
+key_set "KEY1" "LEGACY" "no"
+set_keylifetime "KEY1" "31536000"
+set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
+set_keystate "KEY1" "STATE_DS" "omnipresent"
+
+key_set "KEY2" "LEGACY" "no"
+set_keylifetime "KEY2" "8035200"
+set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
+set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
+# The ZSK needs to be replaced.
+set_keystate "KEY2" "GOAL" "hidden"
+set_keystate "KEY3" "GOAL" "omnipresent"
+set_keyrole "KEY3" "zsk"
+set_keylifetime "KEY3" "8035200"
+set_keyalgorithm "KEY3" "8" "RSASHA256" "2048"
+set_keysigning "KEY3" "no"
+set_zonesigning "KEY3" "no" # not yet
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_ZRRSIG" "hidden"
+
+# Various signing policy checks (external).
+TSIG="$DEFAULT_HMAC:external:$VIEW1"
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" "ext"
+set_keytimes_view_migration
+
+# Set expected key times:
+published=$(key_get KEY1 PUBLISHED)
+set_keytime "KEY1" "ACTIVE" "${published}"
+set_keytime "KEY1" "SYNCPUBLISH" "${published}"
+# Lifetime: 1 year (8035200 seconds)
+active=$(key_get KEY1 ACTIVE)
+set_addkeytime "KEY1" "RETIRED" "${active}" "31536000"
+# Retire interval:
+# DS TTL: 1d
+# Parent zone propagation: 3h
+# Retire safety: 1h
+# Total: 100800 seconds
+retired=$(key_get KEY1 RETIRED)
+set_addkeytime "KEY1" "REMOVED" "${retired}" "100800"
+
+published=$(key_get KEY2 PUBLISHED)
+set_keytime "KEY2" "ACTIVE" "${published}"
+# Lifetime: 3 months (8035200 seconds)
+active=$(key_get KEY2 ACTIVE)
+set_addkeytime "KEY2" "RETIRED" "${active}" "8035200"
+# Retire interval:
+# Sign delay: 9d (14-5)
+# Max zone TTL: 1d
+# Retire safety: 1h
+# Zone propagation delay: 300s
+# Total: 867900 seconds
+retired=$(key_get KEY2 RETIRED)
+set_addkeytime "KEY2" "REMOVED" "${retired}" "867900"
+
+created=$(key_get KEY3 CREATED)
+set_keytime "KEY3" "PUBLISHED" "${created}"
+# Publication interval:
+# DNSKEY TTL: 300s
+# Publish safety: 1h
+# Zone propagation delay: 300s
+# Total: 4200 seconds
+set_addkeytime "KEY3" "ACTIVE" "${created}" "4200"
+# Lifetime: 3 months (8035200 seconds)
+active=$(key_get KEY3 ACTIVE)
+set_addkeytime "KEY3" "RETIRED" "${active}" "8035200"
+# Retire interval:
+# Sign delay: 9d (14-5)
+# Max zone TTL: 1d
+# Retire safety: 1h
+# Zone propagation delay: 300s
+# Total: 867900 seconds
+retired=$(key_get KEY3 RETIRED)
+set_addkeytime "KEY3" "REMOVED" "${retired}" "867900"
+
+# Continue signing policy checks.
+check_keytimes
+check_apex
+dnssec_verify
+
+# Various signing policy checks (internal).
+TSIG="$DEFAULT_HMAC:internal:$VIEW2"
+check_keys
+wait_for_done_signing
+check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" "int"
+set_keytimes_view_migration
+check_keytimes
+check_apex
+dnssec_verify
+
+# Check key tags, should be the same.
+n=$((n+1))
+echo_i "check that of zone ${ZONE} migration to dnssec-policy uses the same keys ($n)"
+ret=0
+[ $_migrate_ext8_ksk = $_migrate_int8_ksk ] || log_error "mismatch ksk tag"
+[ $_migrate_ext8_zsk = $_migrate_int8_zsk ] || log_error "mismatch zsk tag"
+[ $_migrate_ext8_ksk = $(key_get KEY1 ID) ] || log_error "mismatch ksk tag"
+[ $_migrate_ext8_zsk = $(key_get KEY2 ID) ] || log_error "mismatch zsk tag"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/keymgr2kasp/tests_sh_keymgr2kasp.py b/bin/tests/system/keymgr2kasp/tests_sh_keymgr2kasp.py
new file mode 100644
index 0000000..ba9b667
--- /dev/null
+++ b/bin/tests/system/keymgr2kasp/tests_sh_keymgr2kasp.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_keymgr2kasp(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/legacy.run.sh.in b/bin/tests/system/legacy.run.sh.in
new file mode 100644
index 0000000..b523637
--- /dev/null
+++ b/bin/tests/system/legacy.run.sh.in
@@ -0,0 +1,311 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Run a system test.
+#
+
+top_builddir=@top_builddir@
+builddir=@abs_builddir@
+srcdir=@abs_srcdir@
+
+# shellcheck source=conf.sh
+. ${builddir}/conf.sh
+
+if [ "$CI_SERVER" != "yes" ] && [ "$(id -u)" -eq "0" ] && [ "@DEVELOPER_MODE@" != "yes" ]; then
+ echofail "Refusing to run test as root. Build with --enable-developer to override." >&2
+ exit 1
+fi
+
+export builddir
+export srcdir
+
+date_with_args() (
+ date "+%Y-%m-%dT%T%z"
+)
+
+stopservers=true
+# baseport == 0 means random
+baseport=0
+
+if [ "${SYSTEMTEST_NO_CLEAN:-0}" -eq 1 ]; then
+ clean=false
+else
+ clean=true
+fi
+
+do_run=false
+restart=false
+log_flags="-r"
+while getopts "sknp:r-:t" OPT; do
+ log_flags="$log_flags -$OPT$OPTARG"
+ if [ "$OPT" = "-" ] && [ -n "$OPTARG" ]; then
+ OPT="${OPTARG%%=*}"
+ OPTARG="${OPTARG#$OPT}"
+ OPTARG="${OPTARG#=}"
+ fi
+
+ # shellcheck disable=SC2214
+ case "$OPT" in
+ k | keep) stopservers=false ;;
+ n | noclean) clean=false ;;
+ p | port) baseport=$OPTARG ;;
+ r | run) do_run=true ;;
+ s | skip) exit 77 ;;
+ t | restart) restart=true ;;
+ -) break ;;
+ *) echo "invalid option" >&2; exit 1 ;;
+ esac
+done
+
+shift $((OPTIND-1))
+
+if ! $do_run; then
+ if [ "$baseport" -eq 0 ]; then
+ log_flags="$log_flags -p 5300"
+ fi
+ env - \
+ CYGWIN="$CYGWIN" \
+ SYSTEMTEST_FORCE_COLOR="$SYSTEMTEST_FORCE_COLOR" \
+ SYSTEMTEST_NO_CLEAN="$SYSTEMTEST_NO_CLEAN" \
+ SLOT="$SLOT" \
+ OPENSSL_CONF="$OPENSSL_CONF" \
+ SOFTHSM2_CONF="$SOFTHSM2_CONF" \
+ SOFTHSM2_MODULE="$SOFTHSM2_MODULE" \
+ PATH="$PATH" \
+ ${LD_LIBRARY_PATH:+"LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"} \
+ TESTS="$*" \
+ TEST_SUITE_LOG=run.log \
+ LOG_DRIVER_FLAGS="--verbose yes --color-tests yes" \
+ LOG_FLAGS="$log_flags" \
+ TEST_LARGE_MAP="${TEST_LARGE_MAP}" \
+ CI_ENABLE_ALL_TESTS="${CI_ENABLE_ALL_TESTS}" \
+ ${VIRTUAL_ENV:+"VIRTUAL_ENV=${VIRTUAL_ENV}"} \
+ ${PERL5LIB:+"PERL5LIB=${PERL5LIB}"} \
+ make -e check
+ exit $?
+fi
+
+if [ $# -eq 0 ]; then
+ echofail "Usage: $0 [-k] [-n] [-p <PORT>] test-directory [test-options]" >&2;
+ exit 1
+fi
+
+systest=$(basename "${1%%/}")
+shift
+
+if [ ! -d "${srcdir}/$systest" ]; then
+ echofail "$0: $systest: no such test" >&2
+ exit 1
+fi
+
+if [ "${srcdir}" != "${builddir}" ]; then
+ if [ ! -d common ] || [ ! -r common/.prepared ]; then
+ cp -a "${srcdir}/common" "${builddir}"
+ fi
+ # Some tests require additional files to work for out-of-tree test runs.
+ for file in ckdnsrps.sh conftest.py digcomp.pl ditch.pl fromhex.pl get_core_dumps.sh kasp.sh packet.pl pytest_custom_markers.py start.pl stop.pl testcrypto.sh; do
+ if [ ! -r "${file}" ]; then
+ cp -a "${srcdir}/${file}" "${builddir}"
+ fi
+ done
+ if [ ! -d "$systest" ] || [ ! -r "$systest/.prepared" ]; then
+ mkdir -p "${builddir}/$systest"
+ cp -a "${srcdir}/$systest" "${builddir}/"
+ touch "$systest/.prepared"
+ fi
+fi
+
+if [ ! -d "${systest}" ]; then
+ echofail "$0: $systest: no such test" >&2
+ exit 1
+fi
+
+
+# Determine which ports to use for this system test.
+eval "$(cd "${srcdir}" && ./get_ports.sh -p "$baseport" -t "$systest")"
+
+# Start all servers used by the system test. Ensure all log files written
+# during a system test (tests.sh + potentially multiple *.py scripts) are
+# retained for each run by calling start.pl with the --restart command-line
+# option for all invocations except the first one.
+start_servers() {
+ echoinfo "I:$systest:starting servers"
+ if $restart || [ "$run" -gt 0 ]; then
+ restart_opt="--restart"
+ fi
+ if ! $PERL start.pl ${restart_opt} --port "$PORT" "$systest"; then
+ echoinfo "I:$systest:starting servers failed"
+ return 1
+ fi
+}
+
+stop_servers() {
+ if $stopservers; then
+ echoinfo "I:$systest:stopping servers"
+ if ! $PERL stop.pl "$systest"; then
+ echoinfo "I:$systest:stopping servers failed"
+ return 1
+ fi
+ fi
+}
+
+echostart "S:$systest:$(date_with_args)"
+echoinfo "T:$systest:1:A"
+echoinfo "A:$systest:System test $systest"
+echoinfo "I:$systest:PORTS:${PORT},${TLSPORT},${HTTPPORT},${HTTPSPORT},${EXTRAPORT1},${EXTRAPORT2},${EXTRAPORT3},${EXTRAPORT4},${EXTRAPORT5},${EXTRAPORT6},${EXTRAPORT7},${EXTRAPORT8},${CONTROLPORT}"
+
+$PERL ${srcdir}/testsock.pl -p "$PORT" || {
+ echowarn "I:$systest:Network interface aliases not set up. Skipping test."
+ echowarn "R:$systest:FAIL"
+ echoend "E:$systest:$(date_with_args)"
+ exit 1;
+}
+
+# Check for test-specific prerequisites.
+test ! -f "$systest/prereq.sh" || ( cd "${systest}" && $SHELL prereq.sh "$@" )
+result=$?
+
+if [ $result -eq 0 ]; then
+ : prereqs ok
+else
+ echowarn "I:$systest:Prerequisites missing, skipping test."
+ echowarn "R:$systest:SKIPPED";
+ echoend "E:$systest:$(date_with_args)"
+ exit 77
+fi
+
+# Clean up files left from any potential previous runs except when
+# started with the --restart option.
+if ! $restart; then
+ if test -f "$systest/clean.sh"; then
+ if ! ( cd "${systest}" && $SHELL clean.sh "$@" ); then
+ echowarn "I:$systest:clean.sh script failed"
+ echofail "R:$systest:FAIL"
+ echoend "E:$systest:$(date_with_args)"
+ exit 1
+ fi
+ fi
+fi
+
+# Set up any dynamically generated test data
+if test -f "$systest/setup.sh"
+then
+ if ! ( cd "${systest}" && $SHELL setup.sh "$@" ); then
+ echowarn "I:$systest:setup.sh script failed"
+ echofail "R:$systest:FAIL"
+ echoend "E:$systest:$(date_with_args)"
+ exit 1
+ fi
+fi
+
+status=0
+run=0
+# Run the tests
+if [ -r "$systest/tests.sh" ]; then
+ if start_servers; then
+ ( cd "$systest" && $SHELL tests.sh "$@" )
+ status=$?
+ run=$((run+1))
+ stop_servers || status=1
+ else
+ status=1
+ fi
+fi
+
+if [ $status -eq 0 ]; then
+ if [ -n "$PYTEST" ]; then
+ for test in $(cd "${systest}" && find . -name "tests*.py" ! -name "tests_sh_*.py"); do
+ rm -f "$systest/$test.status"
+ if start_servers; then
+ run=$((run+1))
+ test_status=0
+ (cd "$systest" && LEGACY_TEST_RUNNER=1 "$PYTEST" -rsxX -v "$test" "$@" || echo "$?" > "$test.status") | SYSTESTDIR="$systest" cat_d
+ if [ -f "$systest/$test.status" ]; then
+ if [ "$(cat "$systest/$test.status")" = "5" ]; then
+ echowarn "R:$systest:SKIPPED"
+ else
+ echo_i "FAILED"
+ test_status=$(cat "$systest/$test.status")
+ fi
+ fi
+ status=$((status+test_status))
+ stop_servers || status=1
+ else
+ status=1
+ fi
+ if [ $status -ne 0 ]; then
+ break
+ fi
+ done
+ rm -f "$systest/$test.status"
+ else
+ echoinfo "I:$systest:pytest not installed, skipping python tests"
+ fi
+fi
+
+if [ "$run" -eq "0" ]; then
+ echoinfo "I:$systest:No tests were found and run"
+ status=255
+fi
+
+if $stopservers
+then
+ :
+else
+ exit $status
+fi
+
+$SHELL get_core_dumps.sh "$systest" || status=1
+
+print_outstanding_files() {
+ if test -d ${srcdir}/../../../.git; then
+ git status -su --ignored "${systest}/" 2>/dev/null | \
+ sed -n -e 's|^?? \(.*\)|I:'"${systest}"':file \1 not removed|p' \
+ -e 's|^!! \(.*/named.run\)$|I:'"${systest}"':file \1 not removed|p' \
+ -e 's|^!! \(.*/named.memstats\)$|I:'"${systest}"':file \1 not removed|p'
+ fi
+}
+
+print_outstanding_files_oot() {
+ if test -d ${srcdir}/../../../.git; then
+ git -C "${srcdir}/${systest}" ls-files | sed "s|^|${systest}/|" > gitfiles.txt
+ find "${systest}/" -type f ! -name .prepared ! -name Makefile > testfiles.txt
+ grep -F -x -v -f gitfiles.txt testfiles.txt
+ rm -f gitfiles.txt testfiles.txt
+ fi
+}
+
+if [ $status -ne 0 ]; then
+ echofail "R:$systest:FAIL"
+else
+ echopass "R:$systest:PASS"
+ if $clean && ! $restart; then
+ ( cd "${systest}" && $SHELL clean.sh "$@" )
+ if [ "${srcdir}" = "${builddir}" ]; then
+ print_outstanding_files
+ else
+ print_outstanding_files_oot | xargs rm -f
+ find "${systest}/" \( -type d -empty \) -delete 2>/dev/null
+ fi
+ fi
+fi
+
+NAMED_RUN_LINES_THRESHOLD=200000
+find "${systest}" -type f -name "named.run" -exec wc -l {} \; | awk "\$1 > ${NAMED_RUN_LINES_THRESHOLD} { print \$2 }" | sort | while read -r LOG_FILE; do
+ echowarn "I:${systest}:${LOG_FILE} contains more than ${NAMED_RUN_LINES_THRESHOLD} lines, consider tweaking the test to limit disk I/O"
+done
+
+echoend "E:$systest:$(date_with_args)"
+
+exit $status
diff --git a/bin/tests/system/legacy/build.sh b/bin/tests/system/legacy/build.sh
new file mode 100644
index 0000000..fcde4e1
--- /dev/null
+++ b/bin/tests/system/legacy/build.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+(cd ns6 && $SHELL -e sign.sh)
+(cd ns7 && $SHELL -e sign.sh)
+
+$SHELL clean.sh
diff --git a/bin/tests/system/legacy/clean.sh b/bin/tests/system/legacy/clean.sh
new file mode 100644
index 0000000..4c65a2d
--- /dev/null
+++ b/bin/tests/system/legacy/clean.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.*
+rm -f ns*/named.conf
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/named.lock
+
+# build.sh
+rm -f ns1/named_dump.db*
+rm -f ns6/K*
+rm -f ns6/dsset-*
+rm -f ns6/edns512.db
+rm -f ns6/signer.err
+rm -f ns7/K*
+rm -f ns7/dsset-*
+rm -f ns7/edns512-notcp.db
+rm -f ns7/signer.err
+rm -f ns7/trusted.conf
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/legacy/ns1/named1.conf.in b/bin/tests/system/legacy/ns1/named1.conf.in
new file mode 100644
index 0000000..5c4b1c4
--- /dev/null
+++ b/bin/tests/system/legacy/ns1/named1.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/legacy/ns1/named2.conf.in b/bin/tests/system/legacy/ns1/named2.conf.in
new file mode 100644
index 0000000..239e58f
--- /dev/null
+++ b/bin/tests/system/legacy/ns1/named2.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/legacy/ns1/root.db b/bin/tests/system/legacy/ns1/root.db
new file mode 100644
index 0000000..175847a
--- /dev/null
+++ b/bin/tests/system/legacy/ns1/root.db
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+. SOA ns1. marka.isc.org 1 0 0 0 0
+. NS ns1.
+ns1. A 10.53.0.1
+dropedns. NS ns.dropedns.
+ns.dropedns. A 10.53.0.2
+dropedns-notcp. NS ns.dropedns-notcp.
+ns.dropedns-notcp. A 10.53.0.3
+plain. NS ns.plain.
+ns.plain. A 10.53.0.4
+plain-notcp. NS ns.plain-notcp.
+ns.plain-notcp. A 10.53.0.5
+edns512. NS ns.edns512.
+ns.edns512. A 10.53.0.6
+edns512-notcp. NS ns.edns512-notcp.
+ns.edns512-notcp. A 10.53.0.7
+ednsformerr. NS ns.ednsformerr.
+ns.ednsformerr. A 10.53.0.8
+ednsnotimp. NS ns.ednsnotimp.
+ns.ednsnotimp. A 10.53.0.9
+ednsrefused. NS ns.ednsrefused.
+ns.ednsrefused. A 10.53.0.10
diff --git a/bin/tests/system/legacy/ns1/trusted.conf b/bin/tests/system/legacy/ns1/trusted.conf
new file mode 100644
index 0000000..a54b6aa
--- /dev/null
+++ b/bin/tests/system/legacy/ns1/trusted.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+trust-anchors {
+ "edns512-notcp." static-ds 8161 10 2 "19147C5BF59BED075AC26CE73DDA875438FB5AC61BCF31F081AD5BDA1AA7C236";
+};
diff --git a/bin/tests/system/legacy/ns10/ednsrefused.db b/bin/tests/system/legacy/ns10/ednsrefused.db
new file mode 100644
index 0000000..9aa3a4a
--- /dev/null
+++ b/bin/tests/system/legacy/ns10/ednsrefused.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 60 SOA ns marka.isc.org. 1 0 0 0 0
+@ 60 NS ns
+ns 60 A 10.53.0.8
diff --git a/bin/tests/system/legacy/ns10/named.conf.in b/bin/tests/system/legacy/ns10/named.conf.in
new file mode 100644
index 0000000..628c51a
--- /dev/null
+++ b/bin/tests/system/legacy/ns10/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.10;
+ notify-source 10.53.0.10;
+ transfer-source 10.53.0.10;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.10; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "ednsrefused" {
+ type primary;
+ file "ednsrefused.db";
+};
diff --git a/bin/tests/system/legacy/ns10/named.ednsrefused b/bin/tests/system/legacy/ns10/named.ednsrefused
new file mode 100644
index 0000000..6b43ac0
--- /dev/null
+++ b/bin/tests/system/legacy/ns10/named.ednsrefused
@@ -0,0 +1 @@
+ednsrefused
diff --git a/bin/tests/system/legacy/ns2/dropedns.db b/bin/tests/system/legacy/ns2/dropedns.db
new file mode 100644
index 0000000..06c023c
--- /dev/null
+++ b/bin/tests/system/legacy/ns2/dropedns.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 60 SOA ns marka.isc.org. 1 0 0 0 0
+@ 60 NS ns
+ns 60 A 10.53.0.2
diff --git a/bin/tests/system/legacy/ns2/named.conf.in b/bin/tests/system/legacy/ns2/named.conf.in
new file mode 100644
index 0000000..e570ffe
--- /dev/null
+++ b/bin/tests/system/legacy/ns2/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "dropedns" {
+ type primary;
+ file "dropedns.db";
+};
diff --git a/bin/tests/system/legacy/ns2/named.dropedns b/bin/tests/system/legacy/ns2/named.dropedns
new file mode 100644
index 0000000..37dd9cf
--- /dev/null
+++ b/bin/tests/system/legacy/ns2/named.dropedns
@@ -0,0 +1 @@
+dropedns
diff --git a/bin/tests/system/legacy/ns3/dropedns-notcp.db b/bin/tests/system/legacy/ns3/dropedns-notcp.db
new file mode 100644
index 0000000..0ac44bc
--- /dev/null
+++ b/bin/tests/system/legacy/ns3/dropedns-notcp.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 60 SOA ns marka.isc.org. 1 0 0 0 0
+@ 60 NS ns
+ns 60 A 10.53.0.3
diff --git a/bin/tests/system/legacy/ns3/named.conf.in b/bin/tests/system/legacy/ns3/named.conf.in
new file mode 100644
index 0000000..3d89554
--- /dev/null
+++ b/bin/tests/system/legacy/ns3/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "dropedns-notcp" {
+ type primary;
+ file "dropedns-notcp.db";
+};
diff --git a/bin/tests/system/legacy/ns3/named.dropedns b/bin/tests/system/legacy/ns3/named.dropedns
new file mode 100644
index 0000000..37dd9cf
--- /dev/null
+++ b/bin/tests/system/legacy/ns3/named.dropedns
@@ -0,0 +1 @@
+dropedns
diff --git a/bin/tests/system/legacy/ns3/named.notcp b/bin/tests/system/legacy/ns3/named.notcp
new file mode 100644
index 0000000..e25c3a8
--- /dev/null
+++ b/bin/tests/system/legacy/ns3/named.notcp
@@ -0,0 +1 @@
+notcp
diff --git a/bin/tests/system/legacy/ns4/named.args b/bin/tests/system/legacy/ns4/named.args
new file mode 100644
index 0000000..4ccb648
--- /dev/null
+++ b/bin/tests/system/legacy/ns4/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 99 -D legacy-ns4 -X named.lock -g -U 4 -T maxcachesize=2097152 -T noedns
diff --git a/bin/tests/system/legacy/ns4/named.conf.in b/bin/tests/system/legacy/ns4/named.conf.in
new file mode 100644
index 0000000..32bdb05
--- /dev/null
+++ b/bin/tests/system/legacy/ns4/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "plain" {
+ type primary;
+ file "plain.db";
+};
diff --git a/bin/tests/system/legacy/ns4/plain.db b/bin/tests/system/legacy/ns4/plain.db
new file mode 100644
index 0000000..2c20a70
--- /dev/null
+++ b/bin/tests/system/legacy/ns4/plain.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 60 SOA ns marka.isc.org. 1 0 0 0 0
+@ 60 NS ns
+ns 60 A 10.53.0.4
diff --git a/bin/tests/system/legacy/ns5/named.args b/bin/tests/system/legacy/ns5/named.args
new file mode 100644
index 0000000..0c5e17a
--- /dev/null
+++ b/bin/tests/system/legacy/ns5/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 99 -D legacy-ns5 -X named.lock -g -U 4 -T maxcachesize=2097152 -T noedns
diff --git a/bin/tests/system/legacy/ns5/named.conf.in b/bin/tests/system/legacy/ns5/named.conf.in
new file mode 100644
index 0000000..92e754f
--- /dev/null
+++ b/bin/tests/system/legacy/ns5/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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 no;
+ dnssec-validation no;
+};
+
+zone "plain-notcp" {
+ type primary;
+ file "plain-notcp.db";
+};
diff --git a/bin/tests/system/legacy/ns5/named.notcp b/bin/tests/system/legacy/ns5/named.notcp
new file mode 100644
index 0000000..e25c3a8
--- /dev/null
+++ b/bin/tests/system/legacy/ns5/named.notcp
@@ -0,0 +1 @@
+notcp
diff --git a/bin/tests/system/legacy/ns5/plain-notcp.db b/bin/tests/system/legacy/ns5/plain-notcp.db
new file mode 100644
index 0000000..9c1a96b
--- /dev/null
+++ b/bin/tests/system/legacy/ns5/plain-notcp.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 60 SOA ns marka.isc.org. 1 0 0 0 0
+@ 60 NS ns
+ns 60 A 10.53.0.5
diff --git a/bin/tests/system/legacy/ns6/edns512.db.in b/bin/tests/system/legacy/ns6/edns512.db.in
new file mode 100644
index 0000000..485ec8e
--- /dev/null
+++ b/bin/tests/system/legacy/ns6/edns512.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 60 SOA ns marka.isc.org. 1 0 0 0 0
+@ 60 NS ns
+@ 60 TXT a txt record
+ns 60 A 10.53.0.6
diff --git a/bin/tests/system/legacy/ns6/edns512.db.signed b/bin/tests/system/legacy/ns6/edns512.db.signed
new file mode 100644
index 0000000..f193a09
--- /dev/null
+++ b/bin/tests/system/legacy/ns6/edns512.db.signed
@@ -0,0 +1,226 @@
+; File written on Fri Oct 23 13:08:55 2020
+; dnssec_signzone version 9.17.6
+edns512. 60 IN SOA ns.edns512. marka.isc.org. (
+ 1 ; serial
+ 0 ; refresh (0 seconds)
+ 0 ; retry (0 seconds)
+ 0 ; expire (0 seconds)
+ 0 ; minimum (0 seconds)
+ )
+ 60 RRSIG SOA 10 1 60 (
+ 20501016010855 20201023010855 53333 edns512.
+ De3f+wPXopHUPSD2z6Ak5oWhk7AOqqCGU/Z7
+ iCHR+9SCTaDRyGQarIGoCrlc2hhrkxOsYWB1
+ X01E0Zx+iKrzjbK8aJi1JoigvWvi+XogBfWR
+ g7P2LnRnriJfBtsFdKEQSHFo3dmVX4XCqyJX
+ xkJZG2+if+HedaYkrW2izH6PRUsXf3sQWdm4
+ +k1jy+4m4m6bVM/QeHbX/u6KwEZlNuWy64lL
+ 2CXtRpjc2W0oX5Fqoz5GWKI6T038IEawLhP3
+ g/SnC021ub89U5sWRY3s3c1vNrZBjtdnGkOr
+ V5xqBkVwl9RVJwmrMZ4Sa4JaPbd6eV25d+R+
+ +yoCJu3mLwL3q7zBT/Du5N23sTeVeIQmmrj/
+ PxaaX8YIsGH8cCDaverEAJsveuzpYuZjy8G8
+ ZiZagWrA5DQwwy4t+XrhZkUYjxX51t6l367V
+ 8stKcY/SGEmuEpOuYlaTV0/EikZyWQFoq/iv
+ 2eyt/CS+vbD9Bz6v/EXI30rNIdSrYlA1/Vnb
+ hJmb/k13Nlf6ZeybSWLFDYYSXz//FObZ81Zi
+ 7mUB8nZaMtadOnaf7cmsEDUeDbOd9JkiMsmY
+ XDnJPN04hOlCpnwVs8gfLPexD+iDwGLc8rkB
+ hGcAOQRXw22QI7OkBlyaXCHwPpniahmK2wtB
+ Pb7wmdlIVz2lcbtdNz1e2Jfp2rlxcz7e74w= )
+ 60 NS ns.edns512.
+ 60 RRSIG NS 10 1 60 (
+ 20501016010855 20201023010855 53333 edns512.
+ n0ZPbouoYSPJO35aT4qUr9dwiHDwpf7tyCKn
+ 18v9b2UXSGloo5ojUkyA7aJf16vuTrcRR3/b
+ NFHE+qdUsyquHAqjzfPg6O6wL/1CFtZM4Be9
+ SPoaMi1/qYJ51ixep07etIFeQamdSTdwFEFb
+ 2mowRZ5/6TP2GlQZuO56kLTNZSPzUOSh/keN
+ W/sqMludYPJ4JUSI/tyXaadyu/oTLxHvqmFg
+ IHGIVsZs4QGyJax75YKL/tQgpMV8A5w56J5V
+ 2N+8wcLArfwqSduDE0LCU9BfFt4FZf5Hxdqx
+ Vh30cQkNzvK+k2Em+dV7NyNUtyeQO+szkMdL
+ Rkwx9bLGaBExDQZZUvXaAmGcrFPGHgYxBEyN
+ YCpPETeTyvI/Hlt5ldKFLhBuy5h84VNpZ1et
+ T4YBoc/v+SLK+QygJTESvS86v3eSnKtTpr7Z
+ z6MaB0jU5rYc1GsVU/W/Hbw8N4EHtsA4PxP+
+ CVHBqRCNT3VZuASJuGRYo5g/JFeoA1MFfvIK
+ gPR7JEAL9TXxgeCWPpyeF0uLabgusPfbcSaH
+ H90smjebOP5aN5F31oDyJdT0dj4VJybjkIkq
+ /DKh4gMUTDLe7XSz7E0V56W5TMjnh6qvJCNr
+ Lrt3M3su6iCTogCXnGqIyqd0udDjryMr6RX8
+ QHdOfb8n9CE2cgbgB3lZ2yTo+wTElCK+QQ8= )
+ 60 TXT "a" "txt" "record"
+ 60 RRSIG TXT 10 1 60 (
+ 20501016010855 20201023010855 53333 edns512.
+ MFRZbRqXwWAL5FivjxPsq02Zn6GGO+v0PKAe
+ 2FCMrCzIFXqxAuiX3aUg3OXdtSgYKTsgS5X+
+ GfTPAGrdH3hsdanqJbnD/pSjSIOuyrwTR4p5
+ QS6nLReu6HgYqw38gJXzOL596s5N5PPIz0T2
+ 6FmbUsVo0x+PNikUQe6rR68Wfs4T/C689aT7
+ ws5e/NHvG/EfyxyAENQHLWjuXG0iyU61xmB9
+ b8mzdUwT0TupyE75gBDEMLosbBOqSKp8Etjo
+ hVzjYkXkIRjp1+KceauOIIi8HnpJWkFDbgst
+ EFhEydCpf2cfCSooE/ddvjKCgsykL7H3iFBl
+ 6b1mgQ91mouK+qrJTtF9Vjbtz49Q8x/aPyw5
+ YL37y7pXTcELJjE4QDk26OShxnUZYxV7rnp+
+ u7AHaGjPpRHG+Tv+/Ovp7LP33ZFK05jCr2jl
+ KMfi6lPpivY7wF8Eyg+gNlf4Je+7jARYQ6/n
+ Gk4dD0IHg1Q9f9f9Zuus6EqBY+Hw4tMDrhvq
+ MFNdgNArN6MgQKpTqcl3RPsW5UmDQh4cyqZm
+ OsxxCSzwKggTsDSAHCemJp2HhiagRMEE5Jk3
+ 8kiBA9CUSgMHu2hh3MeC/+mUWXO7rBl6f+4v
+ IwlJ5Lc5W+F7acJqpbhVRIW7SsTxC3unJXEu
+ ZJoIy8/VRRK5sW3y3lPh+kY3M+ibAaweGIc= )
+ 0 NSEC ns.edns512. NS SOA TXT RRSIG NSEC DNSKEY
+ 0 RRSIG NSEC 10 1 0 (
+ 20501016010855 20201023010855 53333 edns512.
+ uUXcf0YI0zxGIGCSoRCC5sY6PqaeiZMkMyEw
+ RaOmshO0ylGgjSdXDq8aYyfX0Yqk3cNlNws+
+ pxc93SHjS5y5AouUJyAmp/DcuWTbb6HI5rUu
+ Vl5MBU4SaQc2mfNDbJVvkPFSG8L5KddL8AOo
+ 1C/n4xxtQXmBvxD26lm3Is4V8F0ka5s6Gsx6
+ wa+wk/x4tIUXjPs31i9Rm6INMJrjTr0KEpEE
+ N4NDsiCd8udcQhSDXYSfJ6mL2T4oLBkI2rTb
+ 63YimpBl0tThlO852iXmGz42LiO4e/7OHEfi
+ qVbeLo66PAOW50dqxBchTydaUl1ODDbkaT06
+ YXrIyO5epPOZcHnKnU+WtXzVGhx1WFYamK+d
+ YeFxIFT9FH3Ka0CutimVjziMoYzPZZTSBCER
+ e2Lat4VY3tlKIREo21k83q86KuuEmJsnn3mO
+ E4h29sJAbqPlJ81/iOPBM6mZOJKQRUYkd3xo
+ 9VdYMmLc0BPRH8YxbpqQ/2bZwE676/Z5TlzY
+ Zs4RgG7nxddzwrroD52MfKDvb7TelF0q1hwU
+ ay481qZkCRFEziRt0veUMTlp8u8tRJbSTOwn
+ KsgF2hadtzGwNPMcsx03cO6rkGlZXlJPvj2a
+ A8720jM+1xIKUH1ClDnIM3DLjwBAquJpstO0
+ 6GccRya3pRDf/H+1kBodXMylIw7QF/1L91Q= )
+ 60 DNSKEY 256 3 10 (
+ AwEAAb6wC1T1oWvZUHHTf5er1NKQRzGyu/Rb
+ r2HgRcnOwqUh4Bv8jCN8zXCKRZ0t2uFFvRrX
+ HE/NvhxJnZNtwGyfJNNVCQ4jkbPoD/lPYCCc
+ 8LWeZ9ZLgN7XZpUk3F1EnGkHQCM7WoXe03UA
+ OCHo6hriB96pgFJV+tCSCIubB99Fyk+dN1gG
+ dfjbRRYSYi7fgQEEVicmbP1u8Bd/6HZQXE7o
+ aFdGs1gAkvNNVY+AkFQVdhv5gbDew1vFg9lY
+ C3wWWdRdJtOpHMYY4Q9LBPSKJe4/C/Qr9JJg
+ jl/OgfeMPPPw2O50W7j5DVqPAPJaeflJbpCp
+ EjBhIJAgp2nekWlN2WGqFuQLMfsm8HWftafY
+ WdGXQpGB+gG4yJTRC6aoAGLQ7Ah2xzwodRYx
+ 6Hu3VMBOjmbiNeubFmZHtOjND6VAexbuGf4Y
+ CiRfGbxY2+nQtDU3DPF1s0k6TcIw3HuukFuv
+ yaK9zjx//YD/+AprMHhvrsXjZwLUYwERe6Ax
+ CTKtbhPFoYb/Sx9spjMG/yWTJw/cLCen0K3t
+ JHoDKzmRuCldnCk5ff9ZVoOUvZrOfBicuVW4
+ vy1eYdfugDf8Y0Gix00DpA6h0xEVh/pCd7VC
+ 2N5mi0m9ZX5gaH3Rz8AZy9c3iFG+36kUu7By
+ kSCAwVUEryxS1uuR4a3a3FTPgIYZAOAEif6Y
+ 0eFD
+ ) ; ZSK; alg = RSASHA512 ; key id = 53333
+ 60 DNSKEY 257 3 10 (
+ AwEAAZVmIZdDKaEpBYzRNZ8sCXLdPBkWvH1l
+ hRMwYtqQuwvKahA1+m0xHWczNV1m04e2MrI9
+ AR2yYFCKi+znm9MS3WPo6fShbKzbzCu04G16
+ 334WcmxiFfiKWd71NJoM/Oe7pcWJPiGlm0+z
+ SE93DD1681/GCJxolquJizZH3N9c9erK4Fzv
+ v8jSbEiVen89bkdUw8ulAmX/Eeb9x39A7fs+
+ acO4BuTrL4vsKZ96D9+qbDnUkDn967jFeKGw
+ RCDUMa+UGABkkNjmic8WTVITwI84xEcaFEl5
+ GQBYLJ/qfou1tPicCQxup/EllF4xgFsTvtgG
+ BjN+uJXaE6rs171pzIbDcwZVuq0JZfWXCnrp
+ JZUQbtpwr1nFwT4prg4riDCzmiA3gnXCOLFR
+ pvqx7iOhS77+7miNqBEBthfu6kEdChOlNWpO
+ TX1Df77HbLyGHPWpExcg11j1jxH1PUB/ijpL
+ gUFRORuE6Y8NxUvN8ooQWHIYjd8AEIGlAssy
+ 9dv91KlyOSfZfZftGelCvm5Hha4PoMXUF1of
+ 4rqVy346UhVRKIu29ML+Os4+HPTPhXY1/wco
+ 2q3fvKqix8sI997SOrjYeX39MJ2WImzWZVoc
+ U2X0sbZlYU0I6yq2zDh4oN98s2r1U4TJPf4G
+ Kc2A3107n5WHsavLF6DfV9bDU4/ozVE920/5
+ KocD
+ ) ; KSK; alg = RSASHA512 ; key id = 21624
+ 60 RRSIG DNSKEY 10 1 60 (
+ 20501016010855 20201023010855 53333 edns512.
+ VFBtgMd79vb3EKirSuX5adFdCVMCQQrQ6ANM
+ iAMhKSxo9Ic8ICZGANm7jvpg+IEG13+2ehyt
+ 3EpBIHQYp+Apa1j6lGUDbdmcqP0E34eVy8jJ
+ brP94Bpo0hP1E0P6pPuIqWrnWYG60bXNztc1
+ nJ0ACg7mbcbbnFKHwOcD+js74jGAQdCKpwo3
+ SCfjApUMQwLhHVa0MKcxKCtbCz0WJJwGoXOV
+ U4l0DY/wD/aXTXjguiycjrHEP1dT23JPICFl
+ ZsaVE/+ra999p8fCZ5Vqy3PRFGqUirrwj8hG
+ 93dK4R5GxY0OLfIxYVX5Nt1w6qDmpXbVtryU
+ wgzdO3ZO6+Fz7hltPB19bfCQZQIkqypaPkXT
+ ltk23Jax9EU1nQ1CXLPgMDd3jjlF/46R/CD0
+ H/69/ftwCUdmfX2TZmIWEca4sdj5Za1U1AY4
+ pby4uPUncEw4T4WtRxKmrXjd9H2Ml8KRCIPe
+ Iz/21cUoxdLzlomjnP967H/TR6UFxayQziv/
+ LL2R7LIQwQlz9ZCHHhedptCaK+0FUicWHqW4
+ SW7Y/AKavvFGkMO3KXkXto2oZQLRL4m1Auv7
+ M8rlStuEFBJ5/K0JIp4NCDKTayhXwwvf9jtn
+ WrsCaLRBJH2nCIO2/1w16G3D5mQdvt0QskM2
+ FRtEhi3a7TpwRvCGKw9PuVilH7qXIYpHF54= )
+ 60 RRSIG DNSKEY 10 1 60 (
+ 20501016010855 20201023010855 21624 edns512.
+ Nv7YHuTniNFoFtEeF53VG5ERUEBzKY6wTzUe
+ 34+5hD/GwdxqKq0qQ8VflACrP/JYonCejgj7
+ 6K4EWLBnZYk1K53NTetO19CCP9X7uQC5+av9
+ D5TMLZUC+nQKzHqvJvR6E9UsaH8/wTfOPf1y
+ Li0CzNUpIQ1dKiDu4nJV15Vb8maxjsSxSMwB
+ 8bq6d7sNaa97KIqhhlQp1uJBtS26yp+vP7oJ
+ dYYuJJDeim3GyS/5SN1uMi0r+k9ZL5ajCcyh
+ IACupyTdGLmQKVR1QwF+UlLhY66TGuLKvvJB
+ ygg8W5nguqz8mu9uEmwnVta82itKTKWeXwDm
+ TvEsmW3otxkllRTnHUGDD5mYQBojblFvd27K
+ qf5ALNjAsDwqgrp3EkX7wSOjUNa14ndPLvlO
+ oaeI+ak914WeWrX4s3Pq14BOgeY2dkPX7+MN
+ J3cVkZF3UHsUzzI8vDu68Lnrr36Io5LLlbx6
+ ZzVceeOGvFDz3F949LjYdfBPmIRaC1sKlhEf
+ VrHILfDQFKd3XUK9aRehj3coARu7Aovve1qO
+ nBTQKwxBFamDaNLlJOaTSaXF8qolIaaEx5Nf
+ ymlTsUEkhkB2R1E4LOg1GYziysJSuTYNK5vJ
+ k4kNVn4H/I+sFcxphy2bpZeVHeyNW7JEzQLy
+ JibBoojBRlVtYCmxqYMtGggHsG+C/YYF0QA= )
+ns.edns512. 60 IN A 10.53.0.6
+ 60 RRSIG A 10 2 60 (
+ 20501016010855 20201023010855 53333 edns512.
+ XL9RRX33pcjPE9x6705G/ztksGQbJ/y7tT+k
+ Ojr/hVxfm16IppAjqUnQawbpHTak9NQssa8w
+ 0+edKW5DDMnU6Cnk7rnD2JRNNoXCsQ+HI1oe
+ I7DAgxPvloELwqKnRFmViTCued13oTbzYYOF
+ w28oRXC+elYoeK5ee953hm298WJjOwaVFzub
+ YUf5Tf3DlVLtDeylnokPGTOHMo55IS1h+xni
+ 0V8+jPLXARA9L4fI590J83XPyDPwNgjt0Imv
+ ySZJ2WopQf16RLPJAHbqz+xQK/kO61TBzk6x
+ bqe2o5izwKmg46/5ekOvntjXebvxaC9PnSKw
+ e0fPlXBs5gwbSRFitRHxFzVS2m9eWLMtcYXP
+ XW7cVKLiBmlci0gzWkhOlGUSCAF5ZaUX/6EK
+ 4nHsDthtHa2Y4TGkCOeRZNDLGeO4fdfLSS+o
+ qR70HuhxYp+FqwYxJFtePx7PeJpSwc6FaWTs
+ Ol41GBSDVFNomOcUawMdstqj2QRWoi4o8Q4m
+ SwTdyIBd0gekzkyKheVzfFJxUlE524idgNL2
+ fCF/y8G/GGwU8DZ2mXLRTbE+7eZV/BG0m9ih
+ hs/wqqY6o7ClTDWgWJOQ7bbzZBvy3QEmkMZc
+ TcuWRhVzbS64QlWlFOVD5EpQO5YM3UNKBgVX
+ ynqTaHEjDZ8P43szTvel8Og2LLdw13qNBYA= )
+ 0 NSEC edns512. A RRSIG NSEC
+ 0 RRSIG NSEC 10 2 0 (
+ 20501016010855 20201023010855 53333 edns512.
+ FuLjgUgFvqjd7KVC5Qli4TueVtHpJlWul+VT
+ fSWFW8V+730HaPqo2TvZr9pbU7TKFqNWm1mK
+ cqlxTg9iYviabIZO7cq5tDvX++CiVBaqbjnC
+ UM7PHl36mj/+WPkQHxSo+TpOC3zd1uSGoF4h
+ sg8HjMUuQ9dRpsYWPwGM9dwkcgzfHSrCs/zQ
+ kW4Ari8JgBLAQ7mqRzAEzZPWG90lFgsElvXu
+ YeSyeP8nSwRvzxjzfgg9YnWOY/zSqUup2HUm
+ jf4CSFqyOzJm+o0BhVs7qumFl6Z6DRibWece
+ 0cV7xdLqeBvHZdmBW1uWNio/7YnK1uF2UCBC
+ bwtzZKrwmCRWaj5HuhJ4DaftFje/7nPz0Kxl
+ VXWYqTDW+OFO9yJLc3+NPrZdNxuADnrW0MrR
+ OgJwd1vTpHAwf14ipOitzf4PyBWE5EyL2VIV
+ QM8oB3+xgZqG2QwAaGe4ZOrrDXQotQ5BmS1d
+ Y8SebfcylVUWKJK4kJzAvGjLddZ/1pq2bO2w
+ awj2UarfydJvH+JnX44cykGZeT3x7Y26jEzn
+ DL5/2NNPVU3jTl/HKdeyMG2INPxWr6z/+PXs
+ Wn0IjTRpVrKjoTIl2/hUctsldNgZ/kjKhP+U
+ VrI3O0cBhUM4BPV01mAU8Cq0nhrkRt0ESgo3
+ Bulleb0NLQlhBgo0aiZYQLIA8cDLeAi/dIE= )
diff --git a/bin/tests/system/legacy/ns6/named.args b/bin/tests/system/legacy/ns6/named.args
new file mode 100644
index 0000000..3475121
--- /dev/null
+++ b/bin/tests/system/legacy/ns6/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 99 -D legacy-ns6 -X named.lock -g -U 4 -T maxcachesize=2097152 -T maxudp512
diff --git a/bin/tests/system/legacy/ns6/named.conf.in b/bin/tests/system/legacy/ns6/named.conf.in
new file mode 100644
index 0000000..17f19d9
--- /dev/null
+++ b/bin/tests/system/legacy/ns6/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.6;
+ notify-source 10.53.0.6;
+ transfer-source 10.53.0.6;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.6; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "edns512" {
+ type primary;
+ file "edns512.db.signed";
+};
diff --git a/bin/tests/system/legacy/ns6/sign.sh b/bin/tests/system/legacy/ns6/sign.sh
new file mode 100755
index 0000000..f76b3c2
--- /dev/null
+++ b/bin/tests/system/legacy/ns6/sign.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+SYSTESTDIR=legacy
+
+echo_i "sign edns512"
+
+zone=edns512
+infile=edns512.db.in
+zonefile=edns512.db
+outfile=edns512.db.signed
+
+keyname1=$($KEYGEN -a RSASHA512 -b 4096 -n zone $zone 2> /dev/null)
+keyname2=$($KEYGEN -f KSK -a RSASHA512 -b 4096 -n zone $zone 2> /dev/null)
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -o $zone -f $outfile -e +30y $zonefile > /dev/null 2> signer.err || cat signer.err
diff --git a/bin/tests/system/legacy/ns7/edns512-notcp.db.in b/bin/tests/system/legacy/ns7/edns512-notcp.db.in
new file mode 100644
index 0000000..e181ca4
--- /dev/null
+++ b/bin/tests/system/legacy/ns7/edns512-notcp.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 60 SOA ns marka.isc.org. 1 0 0 0 0
+@ 60 NS ns
+@ 60 TXT a txt record
+ns 60 A 10.53.0.7
diff --git a/bin/tests/system/legacy/ns7/edns512-notcp.db.signed b/bin/tests/system/legacy/ns7/edns512-notcp.db.signed
new file mode 100644
index 0000000..495d098
--- /dev/null
+++ b/bin/tests/system/legacy/ns7/edns512-notcp.db.signed
@@ -0,0 +1,226 @@
+; File written on Fri Oct 23 13:08:56 2020
+; dnssec_signzone version 9.17.6
+edns512-notcp. 60 IN SOA ns.edns512-notcp. marka.isc.org. (
+ 1 ; serial
+ 0 ; refresh (0 seconds)
+ 0 ; retry (0 seconds)
+ 0 ; expire (0 seconds)
+ 0 ; minimum (0 seconds)
+ )
+ 60 RRSIG SOA 10 1 60 (
+ 20501016010856 20201023010856 22916 edns512-notcp.
+ oLYJAlTUS8D9FSdgdL+wQVNbWZamSxv+vTx1
+ 3zAfTgMV/n3RclAtFfFENe+bNxW5vkt4ADEg
+ j5ys/MFnLA0pgw3fjziIzR2OwEQpuw76A8S/
+ ecLVvon5VcEOvKRhUbDJoAS2PatPPqnGxVyE
+ bs+fBCqeorUl/noU/6TfiISIeVcOmEgZX9I7
+ 9LN//CmDpGeZGMm3q6S3LlmsXnBoaMb6g1SN
+ xH/aA/xstiHXvwRLy1YwtImJa92WIZPaA9tb
+ zCX9vVXaVtnLxUVz7PyJOAW/+jsg4IfVmpbz
+ GboD0FdgENC4KuIHjjA93opAOI3iOuREmGEw
+ 7kBPAgaVB8EzypYxgKoEuargmw+3TymHipZE
+ e0/0JeXFdRbaiUQWXtKtYfPcmHcnrY5JO1eo
+ KjNbAakpDkd1wt5EtMc16TO7+00cY4VtUZNJ
+ IOLtzXByCy2a5FRWzar1InYhicUIvM6VoP5b
+ tj9QcYLWT3e1E0aXeBia2Qy+hS/Ut4X+vYvp
+ gedVySBjk8tSDyAkm7ALDiI1gPjdZfCWO+E3
+ 8XI4RbCvaGNlZ4rRH17SKyjxJrgiAPN562bg
+ NAA2F/S5dzLOQn3wwXgHEwu77WisvMV5yrG+
+ 3ef8eVEapJgNGzz1YlPTolpYn9EbAtRMxBcK
+ 6/CFz0Qf6cfBrHS3lxHj78Dcj53O0+zKenY= )
+ 60 NS ns.edns512-notcp.
+ 60 RRSIG NS 10 1 60 (
+ 20501016010856 20201023010856 22916 edns512-notcp.
+ r+WNvwHqzInk8Q/8bDkT4gUbgtc/ArysbpOC
+ Cw7LGnAREt4W6sZ3okkeXb8fnN/t8bsgE9IU
+ Hy7/IuhFu9eMzBYYuc4tzELXVswlCRpUvlVA
+ 0zUJpNmyAcUuCyesy/pu67X0H7mUJX6Z1MKc
+ /o9F21lGkbXxSPSEgRYp6Kmr0s6oGxUqfPL8
+ KDM6yuLBn9YtXzZl5W95aHFGHSlJrCmOeW8P
+ 8Y+5PAWN3fqA8Djgxy1EOMswFVZqmdM0K9oE
+ +oDjTKtj87YmrwdPsUlJLUQTJuoGIpAZxSj8
+ 4Vgs0sdfdo0w0ZyqljYnlrNUlj214FdbXBec
+ CCTSgGcacg7GTW/0yWWeP/cvvVh0MkXWVO37
+ SUecD9jeMwyjFLfVFpzxkgbHO3AiBG8Y9rTk
+ ma18D/hAagbTLGlDhnjz0B/2loVCkRmvWyQp
+ 4Kgpt807cX5w/mR4a/M+//OUTm4xtdq/Ym6f
+ VXLK+JOX8Z+RsDfMWBNodT+JgefnfvdfMaiK
+ FA65Sgq2TIhe75v7ttoN0FaPmIv/g1lgKSxA
+ sLg9syXSUp6Z08wWy3V0jYhs89s4ZJmjezYc
+ bZKvszSqmoCm3KXAkrRUyYooPpNVaMK8taQ1
+ v9vIiC7bFCap8eAogMrfjz1MImIQ/lsH0SC4
+ T+OLiqKK0/uXrqO13FW9EKj5NyBeioURx/k= )
+ 60 TXT "a" "txt" "record"
+ 60 RRSIG TXT 10 1 60 (
+ 20501016010856 20201023010856 22916 edns512-notcp.
+ 06INKYbKaphZUY5Nyc/FuiZolDsQBWnkMB0+
+ pwW/nUhCfXbZR+6wFuvmZHwDRUVvBGsLgPMs
+ WvUw313CsRB35vCb0ncGtFxaKdUahbf/9N2w
+ 600wINuoRSTdxkuGlFbF2Rm0IjuATXkK0QFJ
+ /eSuATu2PfmMyy2MVtjTWCNIEcCJNXm6HjKj
+ KokuKB5YJWdR7pI/ofJD0v8L9Y1uM6uOMSEm
+ MW3jnrqnItg0CzpdAoJNDKCdv0lVz2SYAMIm
+ fbbYGbfhjGJnHvU+PZmgX4OI0F0QKXT+AAe1
+ fJaMBPFU5vvQo+Q/UYcWW+tc9jUiSMTwCOjW
+ j+cPJypLx7U3Hx3knUscYsikohQv9gqMTQsB
+ ylqpwJVbofgR62DWqlUUbgoEnILM18SvZ54A
+ nOcjfz6wLw3/jG/ONsXqLuyYiqetXGhhQLz3
+ DxzQrCts1vXWGCnjWdqHeDGZoPWK9RMcsK46
+ nGd+jHlOBvCgpgb0KEwKYBIdwnYgoLXqldVM
+ VEjJ4yJa0Lt9FDFEjdJmI9pcDkE/zAZSfKHF
+ cf0U/hHy303QpiL9c+2zzEeYpZzDltZfv1/g
+ oyVFPFxPxp8iNj2W4B1hYTYCgS3M/S75ylgQ
+ np/QyDv4PX6nIsVPvZUhslm62LfkRnANpqBe
+ y/VfZDrEHxsd6/4kpqFVhlCgmnCfvwT1PgU= )
+ 0 NSEC ns.edns512-notcp. NS SOA TXT RRSIG NSEC DNSKEY
+ 0 RRSIG NSEC 10 1 0 (
+ 20501016010856 20201023010856 22916 edns512-notcp.
+ ZuI5yl2PzNehPw4HKsR3G/mN2LWtAr+7xWkE
+ 2pm/Zr8LhnecYz0wbZkve5EDjLe7/93TH7y6
+ n7RD4N4W/jtK80J82Xpjy7xOZ3UX4PVoX/0s
+ IvJFHCPEmlzuzHiVZglMZS9HQl9aY6J5KIde
+ T4xRnY8YzhvraHi2E2T7HPIGZLZVccWU1dFe
+ qAxaIhmVYAbLNixd2TbKr6SeWfLQRvn4aM3H
+ 90k5kSMwePOieyMtvfapmCsOIOxjG2KpibIX
+ VWnQrXGig5IQ0nOPkamKde5eTYH+cxkx2AHA
+ gjHutcrbrvwtW4HomW65BNZzyyknX8kC5eo9
+ RdAOWTpEXhDDxoU9QxsI6U8zRIwDEuet63N8
+ oESfik7AXDST1kJjLeY9QyX8FYKOQoCjxfIA
+ o06MTKN5OjtRquQUiCHNyOo3ySwaabEHVsbG
+ a28Laelo8oaPxEFZpVC02N9c2TW6H4gHijzm
+ WuyrlTV5T2FEQiWLlizVrDDKfNSbbF5DMw1A
+ AqYIiWUHTa5FAXT+DwBQaN1rd0FJXXMM4Uk+
+ a9Mquw9whK5TOe0BSHOsctPz3rAXVmQ/C6Tk
+ U0tZAmxEsPQDPiM29VdTx2CfTiTqYDsLVCl5
+ HUwHMYj9z5uVTZ8pD5zqI3NFH6KrqPlTB/je
+ ksrzOGaJrtnyj5oGExNWriYVsZx8FoyPNv0= )
+ 60 DNSKEY 256 3 10 (
+ AwEAAdnQArhgG2vUoiAvs8zH8Z/+RTBxYUnv
+ /J3Vd9ierGFvvWonU1Ao/WWspZggXe3I6ZmK
+ +NCSuVlWb1HmemTobib6jdKWpNOMn8OcJHSE
+ 4TsbOB0+sOknDdU/C8akwegHG2zgQG5dSKRC
+ oLVqlsnV27lFQrmpVm+cm0IruorTWJRC2W5t
+ iXnblVQ0ouR54SYG8+k18UqJDVfg1YBfDkzM
+ eMvz/wJjFy156yPul982VaRHT/xU+Ol5S/+c
+ yy91W22Q9ktlIjiIu5NLeH6TTwwfGu0YY+h7
+ rMFImDkwPeTX+K28BRdjYY2htH8O+ZfbmYE7
+ Ft8+qF9P7Df7YUPBiREs350NVuDMeqcJmbsi
+ yOFBZ+J/QJU7nM5VHCFeUIDZ873/o2bJN0W2
+ MaI+v+WsTmHN+W42EmejonGZqlC4ct9j8KO5
+ Z73y1+jdzqDOJfIctxRyqK6cF6PBz0Y1QoLI
+ Z3fmX4IsdIaiFH7h73R4s3uXYTx8BUzY369p
+ 95jxpMBqMPeFvOaYzeHc4hSqcXIehGwIIUj2
+ XQxZU1wf8ijaDXOBM+Ccei147Njd/VOjhJ0F
+ MG/5EjCkrVLC2IVUO8VMuvpBtji5RNSal6b8
+ 0pIZTgEposeT8dbNP8ojzAG15HclFgzjY/Q8
+ 90DErfB8UsCtcOz060UKMYKx+zcoYU9KRo2u
+ 77b9
+ ) ; ZSK; alg = RSASHA512 ; key id = 22916
+ 60 DNSKEY 257 3 10 (
+ AwEAAZ4bc3CnvoIGDpDOW2+afYCU7pSIFNzW
+ ueXVOjPRolnxUaJYwLyCIHngpm+9/9stMh+E
+ LBFozA785zPhfqnRaZz1xWMP1D5bHu6SXmpF
+ V88BOnSznEbam/kqzQTrowH2hs3SClFI2wFD
+ QsKytzgnRDFEkysgfbjx8rOQZLRV3HN56z39
+ DgWWC4kz++0FQtp4rZRr0TKgpIXDYJbBxgWn
+ em43xdlCv8qErE2jRfE+gto6bS3Uw71qfFTn
+ XBuvoI2Tfy/cxCa4oeamWYwrfFKbSC0fEykG
+ 3YnTrYIqJCEnD8h5191h6GZ0OZ0XGWKD14N3
+ NjXYSjjorqbqUSU01vDxS/8UvCKknmLCTTpN
+ Jm3RvpWM9EIghF3qDDgMgFd/hFlJsBGg1MxQ
+ vGskBg+PdsPDLQZRbpWy+5umLCZ//3Djmok4
+ YnvnaFLeMnRlu0x4vTFtpuEdkwTrGUacOkJu
+ 53vH1pofl3WqC4PrPVwsQXNHTJcZTiHnyAN5
+ wM4h6kD47+VKS2888SP49Bi36ypSnZp5bfM9
+ wW3zOgh1oFUKTyknQWOX8Saxr+g3sVBZot7V
+ EpTEeJOWOwdSSRj/K/2UiXI5QJEX4+4aJYxA
+ ak8OJCmixLmcSVsY4MYsK2m9I0Sl6brGn0xG
+ qUa0SBTVw+X3zyybLlsqJV8LX9W7sLeM3OgY
+ st7t
+ ) ; KSK; alg = RSASHA512 ; key id = 8161
+ 60 RRSIG DNSKEY 10 1 60 (
+ 20501016010856 20201023010856 22916 edns512-notcp.
+ klMRNVbs52XfLa1AZNHlAiQWqzjNjNQ7yuVG
+ 9o8sxcAqzrxvdcnISC9CNz867Sw2JKs9dMZi
+ Vv07Jm/f85wN/B9OO63NbxQHgtMAv3lT5isN
+ 4xC7NJtDQCPIEKrgPjnznJG1/XiWZudPemv0
+ dpTIMR9fiQHC5Z0I+xqUsRJjlBc4x1tPrPNC
+ 9r+YEaQlwKT59pWHTLPpBYZE+0jjNY9wMrhX
+ 1uP7gS8z0s0iyldhIgIicccjdRrCCc6EoNnc
+ ToEfWsLMN2HTNCtAAxCHSNTPrC2wriKl4CHi
+ Pqy2AsztfLLkyT+dR/gBLFbjHasp/5O1Y5M+
+ 60WywgNr/tbsNzzuSSfcIZ4RM3JhS7cgoZpP
+ MEsumXOyJdTLF9oIZK3QKVjT07eai/KA+Vjt
+ bbkVBvagosE+uCCXhpM4nn0oTfZCZiIoUADr
+ wQ2PuvujEzPbky2BuX7iQGV90G1bcidpS1B8
+ Hm7zrpOjO0mwNyF29YTcJkgelvVOmEaAH3X4
+ +Enmji13kQmWkkc0sUYq9tyX0gTiXjZtz/4I
+ Yl/JOng3/CKS7/In20p1Oea4Sa0GDqtlmK+f
+ YsgaAkCaN1RbZslNDpphgEIKUF8M9YZVaAlE
+ XNqj5HFeqzOAoGNN/rUKKgNWcRynJdHP13gd
+ AoUxJa5FxdxZB4AAk6vfojOFjU7kQyeJlh8= )
+ 60 RRSIG DNSKEY 10 1 60 (
+ 20501016010856 20201023010856 8161 edns512-notcp.
+ Y27v9t6VkOZzuEdGZIr33RTGJ+L4QfWkoCvj
+ 9VGdOsj3dWVATqwYoGmlfRqlm6m2L7yhJVTC
+ pI8ihj/Tl7aoROTBnJGO9CkuvXKeGt16LIpi
+ ZBz9FbZ6MPwwjn7uPlm4RR51mscTWdu1Y45e
+ zs/uPxc2qpafl3NnBwcAw9l1VM9f11Ah7+tu
+ WA58niT+GMwKVSB2B0+cDQoP5covZmU3DjgE
+ 8CmqwBUF4cElQ4DcGGy6LkWdO2+Yj8ANCsUS
+ DTeE8j7XLVGGurwgwL0TNPA1yntibvl+U+ti
+ vznWlvsV7Mww16j83BrJvEeTVOGthINdtL4P
+ 7Pm6U6NUSMJNK2lGB3VucJyLDuuUN3CNNfsb
+ IO+6vBrA/T6UtXaRfv5c5Xnq9dcrbiYW1ar3
+ Ysw6cpGi2Ti2YO5EfG8OfGmHeZXK+OqrTNEn
+ T14ELewVKVEWv4lGiVbddDUq7YmltoYog2Zp
+ DsyahxOgfFLYj32pYIdNRr5HE9c1FwOZXmnz
+ wPp/rB1baf5eNddRxJtDaEo/ek5v+CtWC6Y+
+ eRwBKWN/ozmc5JnNpoJtKSvRlTuGYlKElct0
+ 1cS9BmZsu/zAt4kGuNC71758XnVSd1CcwhwA
+ WYEAvrJV2+wr7jpjHvq1tGrCEPppBaelrwut
+ CGfenY08YE/dDMmbFPXMFUHbhtz1qvFiMjU= )
+ns.edns512-notcp. 60 IN A 10.53.0.7
+ 60 RRSIG A 10 2 60 (
+ 20501016010856 20201023010856 22916 edns512-notcp.
+ tFjfl9DvT60ko1h9p55T2s5hU4CmmHEYrMUg
+ 9Iv+tvW9YoCiHESBC7TkDmdVT8YwzaLDjlTf
+ YxgA5KLhV+04M9m7vUgxK5T4vjiE43VnTq7x
+ L+hM9cvjQ4sKTBJLHmTrKjrcE5fyd0/F3jvF
+ MiomX/8p7PLq2fzZWwygjiOrkd0s7ypFEuoX
+ AjRoxo60q2oV9/8jiKkgiD4+UEIqU/fxURP+
+ 1MpNVqks/PXSFVQcyGrQKddiRpp53yYlgcDv
+ /0ulXnxK53dQ3CqymOflJrf7B5H0rq8LQHjK
+ ZO3ys54sWq80jxtxRWNMBvygmHl+LFCes5mL
+ GuB1pFYJq7z026GC6QHbVmOQu5P2pLOr13jW
+ KBwRisr0/BN/no3goGVAP7hJD47r2fr0E8WL
+ K1GJZI2McrHgQW12NnZm43AI2z7xjapbRquB
+ HMeJR8bPfjxEhy555AE0B1AXZobiuZHtycox
+ XBS+A9URAYx78OWAgAENF94rnkKIoSAmMENJ
+ KX29TEHrNLG3MCWxX9mRnMzON+5oTZjOxV8R
+ KIc6Qw/hE93Bho1+3Vdlq8X2Gwu8RswwLBgH
+ e3AnKRHWGTbv6uUwKCVrTyZOQft+yiKxooBr
+ Wz0AgEosnuwenxjw4Tim/Z5NhLnzrJBaSyjo
+ Pt+wguhDW1boaCf/4RYOAZtSNNalGnJNV4k= )
+ 0 NSEC edns512-notcp. A RRSIG NSEC
+ 0 RRSIG NSEC 10 2 0 (
+ 20501016010856 20201023010856 22916 edns512-notcp.
+ hwvmKC/yVOUavH1cty6pg1EyTNBo+MAz+KjY
+ UmodFwGPv2EuRY/6TcujLTMHdeSbi71e+JQU
+ +ij6TXcXNZl7CpZbBEfVZd8xvTPYykhO3rr8
+ cckPre1p8pGx56x7nVjRA1P/+oyjjr6j1nVZ
+ RewWOrSo/LPah4WY2iyEJH0JF5H/SVrF2Z86
+ XT4YrLqe+1vpeRw0C8VNAJGZbd6H90Qu/Cnd
+ Xdyj1OOl+RQbvJCVpcw6/fFmcNRy5zbQJFA6
+ nsGyCL62OfptdByQKJhSU6gQcaWcMnYeqSgT
+ I3yBye1whQ/2fdgyKUFAESbPRp7WpzXzNabf
+ ZNeLRZT8RGsjHD4i0OqCL+R6axXl53wUn7sa
+ pXWTRBWIKshnTJrzntIkdXLq1qQtxnw7zA6h
+ kUCVzf1FzjP64cHh928CQBbnfT1MSdJuQe1G
+ /RGCn0RwOcn+n06O2uiCBmwkGnrZB/+Yytzp
+ apdULCyUmvByozvKYp73GOK4eTAqNF6igEAc
+ pSz8oXZy+wmVG1l72yli1Eyunm010Skb3oxe
+ 23htSPq1MIqETzAWtMJM082F9vAEjTJNSnSo
+ RFpPnlq6LDjtr7Z6/mRcqVXx5OC1nj4Svaxo
+ JOebR0igOJcAKG9gCGz6ffDy/1VeUHCnzvKR
+ vgJZjbvXDuHkOzNB6KYc3N2BglMIxajwVcQ= )
diff --git a/bin/tests/system/legacy/ns7/named.args b/bin/tests/system/legacy/ns7/named.args
new file mode 100644
index 0000000..1da4980
--- /dev/null
+++ b/bin/tests/system/legacy/ns7/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 99 -D legacy-ns7 -X named.lock -g -U 4 -T maxcachesize=2097152 -T maxudp512
diff --git a/bin/tests/system/legacy/ns7/named.conf.in b/bin/tests/system/legacy/ns7/named.conf.in
new file mode 100644
index 0000000..30f3ea2
--- /dev/null
+++ b/bin/tests/system/legacy/ns7/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.7;
+ notify-source 10.53.0.7;
+ transfer-source 10.53.0.7;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.7; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "edns512-notcp" {
+ type primary;
+ file "edns512-notcp.db.signed";
+};
diff --git a/bin/tests/system/legacy/ns7/named.notcp b/bin/tests/system/legacy/ns7/named.notcp
new file mode 100644
index 0000000..e25c3a8
--- /dev/null
+++ b/bin/tests/system/legacy/ns7/named.notcp
@@ -0,0 +1 @@
+notcp
diff --git a/bin/tests/system/legacy/ns7/sign.sh b/bin/tests/system/legacy/ns7/sign.sh
new file mode 100755
index 0000000..c2153f9
--- /dev/null
+++ b/bin/tests/system/legacy/ns7/sign.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+SYSTESTDIR=legacy
+
+echo_i "sign edns512-notcp"
+
+zone=edns512-notcp
+infile=edns512-notcp.db.in
+zonefile=edns512-notcp.db
+outfile=edns512-notcp.db.signed
+
+keyname1=$($KEYGEN -a RSASHA512 -b 4096 -n zone $zone 2> /dev/null)
+keyname2=$($KEYGEN -f KSK -a RSASHA512 -b 4096 -n zone $zone 2> /dev/null)
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -o $zone -f $outfile -e +30y $zonefile > /dev/null 2> signer.err || cat signer.err
+
+keyfile_to_static_ds $keyname2 > trusted.conf
+cp trusted.conf ../ns1
diff --git a/bin/tests/system/legacy/ns8/ednsformerr.db b/bin/tests/system/legacy/ns8/ednsformerr.db
new file mode 100644
index 0000000..9aa3a4a
--- /dev/null
+++ b/bin/tests/system/legacy/ns8/ednsformerr.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 60 SOA ns marka.isc.org. 1 0 0 0 0
+@ 60 NS ns
+ns 60 A 10.53.0.8
diff --git a/bin/tests/system/legacy/ns8/named.conf.in b/bin/tests/system/legacy/ns8/named.conf.in
new file mode 100644
index 0000000..7431cf8
--- /dev/null
+++ b/bin/tests/system/legacy/ns8/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.8;
+ notify-source 10.53.0.8;
+ transfer-source 10.53.0.8;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.8; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "ednsformerr" {
+ type primary;
+ file "ednsformerr.db";
+};
diff --git a/bin/tests/system/legacy/ns8/named.ednsformerr b/bin/tests/system/legacy/ns8/named.ednsformerr
new file mode 100644
index 0000000..e35cb02
--- /dev/null
+++ b/bin/tests/system/legacy/ns8/named.ednsformerr
@@ -0,0 +1 @@
+ednsformerr
diff --git a/bin/tests/system/legacy/ns9/ednsnotimp.db b/bin/tests/system/legacy/ns9/ednsnotimp.db
new file mode 100644
index 0000000..9aa3a4a
--- /dev/null
+++ b/bin/tests/system/legacy/ns9/ednsnotimp.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 60 SOA ns marka.isc.org. 1 0 0 0 0
+@ 60 NS ns
+ns 60 A 10.53.0.8
diff --git a/bin/tests/system/legacy/ns9/named.conf.in b/bin/tests/system/legacy/ns9/named.conf.in
new file mode 100644
index 0000000..385fbfd
--- /dev/null
+++ b/bin/tests/system/legacy/ns9/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "ednsnotimp" {
+ type primary;
+ file "ednsnotimp.db";
+};
diff --git a/bin/tests/system/legacy/ns9/named.ednsnotimp b/bin/tests/system/legacy/ns9/named.ednsnotimp
new file mode 100644
index 0000000..4e6424d
--- /dev/null
+++ b/bin/tests/system/legacy/ns9/named.ednsnotimp
@@ -0,0 +1 @@
+ednsnotimp
diff --git a/bin/tests/system/legacy/setup.sh b/bin/tests/system/legacy/setup.sh
new file mode 100644
index 0000000..d2a53bb
--- /dev/null
+++ b/bin/tests/system/legacy/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named1.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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
+copy_setports ns8/named.conf.in ns8/named.conf
+copy_setports ns9/named.conf.in ns9/named.conf
+copy_setports ns10/named.conf.in ns10/named.conf
diff --git a/bin/tests/system/legacy/tests.sh b/bin/tests/system/legacy/tests.sh
new file mode 100755
index 0000000..44d3b11
--- /dev/null
+++ b/bin/tests/system/legacy/tests.sh
@@ -0,0 +1,269 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT} +tries=1 +time=2"
+
+# Check whether the SOA record for the name provided in $1 can be resolved by
+# ns1. Return 0 if resolution succeeds as expected; return 1 otherwise.
+resolution_succeeds() {
+ _ret=0
+ $DIG $DIGOPTS +tcp +tries=3 +time=5 @10.53.0.1 ${1} SOA > dig.out.test$n || _ret=1
+ grep "status: NOERROR" dig.out.test$n > /dev/null || _ret=1
+ return $_ret
+}
+
+# Check whether the SOA record for the name provided in $1 can be resolved by
+# ns1. Return 0 if resolution fails as expected; return 1 otherwise. Note that
+# both a SERVFAIL response and timing out mean resolution failed, so the exit
+# code of dig does not influence the result (the exit code for a SERVFAIL
+# response is 0 while the exit code for not getting a response at all is not 0).
+resolution_fails() {
+ _servfail=0
+ _timeout=0
+ $DIG $DIGOPTS +tcp +time=5 @10.53.0.1 ${1} TXT > dig.out.test$n
+ grep -F "status: SERVFAIL" dig.out.test$n > /dev/null && _servfail=1
+ grep -F "timed out" dig.out.test$n > /dev/null && _timeout=1
+ if [ $_servfail -eq 1 ] || [ $_timeout -eq 1 ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+status=0
+n=0
+
+n=$((n + 1))
+echo_i "checking formerr edns server setup ($n)"
+ret=0
+$DIG $DIGOPTS +edns @10.53.0.8 ednsformerr soa > dig.out.1.test$n || ret=1
+grep "status: FORMERR" dig.out.1.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.1.test$n > /dev/null && ret=1
+$DIG $DIGOPTS +noedns @10.53.0.8 ednsformerr soa > dig.out.2.test$n || ret=1
+grep "status: NOERROR" dig.out.2.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking recursive lookup to formerr edns server succeeds ($n)"
+ret=0
+resolution_succeeds ednsformerr. || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking notimp edns server setup ($n)"
+ret=0
+$DIG $DIGOPTS +edns @10.53.0.9 ednsnotimp soa > dig.out.1.test$n || ret=1
+grep "status: NOTIMP" dig.out.1.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.1.test$n > /dev/null && ret=1
+$DIG $DIGOPTS +noedns @10.53.0.9 ednsnotimp soa > dig.out.2.test$n || ret=1
+grep "status: NOERROR" dig.out.2.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking recursive lookup to notimp edns server fails ($n)"
+ret=0
+resolution_fails ednsnotimp. || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking refused edns server setup ($n)"
+ret=0
+$DIG $DIGOPTS +edns @10.53.0.10 ednsrefused soa > dig.out.1.test$n || ret=1
+grep "status: REFUSED" dig.out.1.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.1.test$n > /dev/null && ret=1
+$DIG $DIGOPTS +noedns @10.53.0.10 ednsrefused soa > dig.out.2.test$n || ret=1
+grep "status: NOERROR" dig.out.2.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking recursive lookup to refused edns server fails ($n)"
+ret=0
+resolution_fails ednsrefused. || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking drop edns server setup ($n)"
+ret=0
+$DIG $DIGOPTS +edns @10.53.0.2 dropedns soa > dig.out.1.test$n && ret=1
+grep "timed out" dig.out.1.test$n > /dev/null || ret=1
+grep ";; no servers could be reached" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +noedns @10.53.0.2 dropedns soa > dig.out.2.test$n || ret=1
+grep "status: NOERROR" dig.out.2.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.2.test$n > /dev/null && ret=1
+$DIG $DIGOPTS +noedns +tcp @10.53.0.2 dropedns soa > dig.out.3.test$n || ret=1
+grep "status: NOERROR" dig.out.3.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.3.test$n > /dev/null && ret=1
+$DIG $DIGOPTS +edns +tcp @10.53.0.2 dropedns soa > dig.out.4.test$n && ret=1
+grep "timed out" dig.out.4.test$n > /dev/null || ret=1
+grep ";; no servers could be reached" dig.out.4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking recursive lookup to drop edns server fails ($n)"
+ret=0
+resolution_fails dropedns. || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking drop edns + no tcp server setup ($n)"
+ret=0
+$DIG $DIGOPTS +edns @10.53.0.3 dropedns-notcp soa > dig.out.1.test$n && ret=1
+grep "timed out" dig.out.1.test$n > /dev/null || ret=1
+grep ";; no servers could be reached" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +noedns +tcp @10.53.0.3 dropedns-notcp soa > dig.out.2.test$n && ret=1
+grep "connection refused" dig.out.2.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +noedns @10.53.0.3 dropedns-notcp soa > dig.out.3.test$n || ret=1
+grep "status: NOERROR" dig.out.3.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking recursive lookup to drop edns + no tcp server fails ($n)"
+ret=0
+resolution_fails dropedns-notcp. || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking plain dns server setup ($n)"
+ret=0
+$DIG $DIGOPTS +edns @10.53.0.4 plain soa > dig.out.1.test$n || ret=1
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.1.test$n > /dev/null && ret=1
+$DIG $DIGOPTS +edns +tcp @10.53.0.4 plain soa > dig.out.2.test$n
+grep "status: NOERROR" dig.out.2.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking recursive lookup to plain dns server succeeds ($n)"
+ret=0
+resolution_succeeds plain. || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking plain dns + no tcp server setup ($n)"
+ret=0
+$DIG $DIGOPTS +edns @10.53.0.5 plain-notcp soa > dig.out.1.test$n || ret=1
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.1.test$n > /dev/null && ret=1
+$DIG $DIGOPTS +edns +tcp @10.53.0.5 plain-notcp soa > dig.out.2.test$n && ret=1
+grep "connection refused" dig.out.2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking recursive lookup to plain dns + no tcp server succeeds ($n)"
+ret=0
+resolution_succeeds plain-notcp. || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "checking edns 512 server setup ($n)"
+ret=0
+$DIG $DIGOPTS +edns @10.53.0.6 edns512 txt > dig.out.1.test$n || ret=1
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +edns +tcp @10.53.0.6 edns512 txt > dig.out.2.test$n || ret=1
+grep "status: NOERROR" dig.out.2.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.2.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +edns +dnssec @10.53.0.6 edns512 txt > dig.out.3.test$n && ret=1
+grep "timed out" dig.out.3.test$n > /dev/null || ret=1
+grep ";; no servers could be reached" dig.out.3.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +edns +dnssec +bufsize=512 +ignore @10.53.0.6 edns512 soa > dig.out.4.test$n || ret=1
+grep "status: NOERROR" dig.out.4.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.4.test$n > /dev/null || ret=1
+grep "flags:.* tc[ ;]" dig.out.4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking recursive lookup to edns 512 server succeeds ($n)"
+ret=0
+retry_quiet 3 resolution_succeeds edns512. || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking edns 512 + no tcp server setup ($n)"
+ret=0
+$DIG $DIGOPTS +edns @10.53.0.7 edns512-notcp soa > dig.out.1.test$n || ret=1
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +edns +tcp @10.53.0.7 edns512-notcp soa > dig.out.2.test$n && ret=1
+grep "connection refused" dig.out.2.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +edns +dnssec @10.53.0.7 edns512-notcp soa > dig.out.3.test$n && ret=1
+grep "timed out" dig.out.3.test$n > /dev/null || ret=1
+grep ";; no servers could be reached" dig.out.3.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +edns +dnssec +bufsize=512 +ignore @10.53.0.7 edns512-notcp soa > dig.out.4.test$n || ret=1
+grep "status: NOERROR" dig.out.4.test$n > /dev/null || ret=1
+grep "EDNS: version:" dig.out.4.test$n > /dev/null || ret=1
+grep "flags:.* tc[ ;]" dig.out.4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking recursive lookup to edns 512 + no tcp server fails ($n)"
+ret=0
+resolution_fails edns512-notcp. || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking recursive lookup to edns 512 + no tcp server does not cause query loops ($n)"
+ret=0
+sent=$(grep -c -F "sending packet to 10.53.0.7" ns1/named.run)
+if [ $sent -ge 10 ]; then
+ echo_i "ns1 sent $sent queries to ns7, expected less than 10"
+ ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+stop_server --use-rndc --port ${CONTROLPORT} ns1
+copy_setports ns1/named2.conf.in ns1/named.conf
+start_server --noclean --restart --port ${PORT} ns1
+
+n=$((n + 1))
+echo_i "checking recursive lookup to edns 512 + no tcp + trust anchor fails ($n)"
+# retry loop in case the server restart above causes transient failure
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ ret=0
+ resolution_fails edns512-notcp. || ret=1
+ [ "$ret" -eq 0 ] && break
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/legacy/tests_sh_legacy.py b/bin/tests/system/legacy/tests_sh_legacy.py
new file mode 100644
index 0000000..ded36f0
--- /dev/null
+++ b/bin/tests/system/legacy/tests_sh_legacy.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_legacy(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/limits/clean.sh b/bin/tests/system/limits/clean.sh
new file mode 100644
index 0000000..b69c695
--- /dev/null
+++ b/bin/tests/system/limits/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after limits tests.
+#
+rm -f dig.out.*
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/limits/knowngood.dig.out.1000 b/bin/tests/system/limits/knowngood.dig.out.1000
new file mode 100644
index 0000000..3b7e01a
--- /dev/null
+++ b/bin/tests/system/limits/knowngood.dig.out.1000
@@ -0,0 +1,1023 @@
+
+; <<>> DiG 8.2 <<>> 1000.example. @10.53.0.1 a -p
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr aa rd ad; QUERY: 1, ANSWER: 1000, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; 1000.example, type = A, class = IN
+
+;; ANSWER SECTION:
+1000.example. 5M IN A 10.0.0.0
+1000.example. 5M IN A 10.0.0.1
+1000.example. 5M IN A 10.0.0.2
+1000.example. 5M IN A 10.0.0.3
+1000.example. 5M IN A 10.0.0.4
+1000.example. 5M IN A 10.0.0.5
+1000.example. 5M IN A 10.0.0.6
+1000.example. 5M IN A 10.0.0.7
+1000.example. 5M IN A 10.0.0.8
+1000.example. 5M IN A 10.0.0.9
+1000.example. 5M IN A 10.0.0.10
+1000.example. 5M IN A 10.0.0.11
+1000.example. 5M IN A 10.0.0.12
+1000.example. 5M IN A 10.0.0.13
+1000.example. 5M IN A 10.0.0.14
+1000.example. 5M IN A 10.0.0.15
+1000.example. 5M IN A 10.0.0.16
+1000.example. 5M IN A 10.0.0.17
+1000.example. 5M IN A 10.0.0.18
+1000.example. 5M IN A 10.0.0.19
+1000.example. 5M IN A 10.0.0.20
+1000.example. 5M IN A 10.0.0.21
+1000.example. 5M IN A 10.0.0.22
+1000.example. 5M IN A 10.0.0.23
+1000.example. 5M IN A 10.0.0.24
+1000.example. 5M IN A 10.0.0.25
+1000.example. 5M IN A 10.0.0.26
+1000.example. 5M IN A 10.0.0.27
+1000.example. 5M IN A 10.0.0.28
+1000.example. 5M IN A 10.0.0.29
+1000.example. 5M IN A 10.0.0.30
+1000.example. 5M IN A 10.0.0.31
+1000.example. 5M IN A 10.0.0.32
+1000.example. 5M IN A 10.0.0.33
+1000.example. 5M IN A 10.0.0.34
+1000.example. 5M IN A 10.0.0.35
+1000.example. 5M IN A 10.0.0.36
+1000.example. 5M IN A 10.0.0.37
+1000.example. 5M IN A 10.0.0.38
+1000.example. 5M IN A 10.0.0.39
+1000.example. 5M IN A 10.0.0.40
+1000.example. 5M IN A 10.0.0.41
+1000.example. 5M IN A 10.0.0.42
+1000.example. 5M IN A 10.0.0.43
+1000.example. 5M IN A 10.0.0.44
+1000.example. 5M IN A 10.0.0.45
+1000.example. 5M IN A 10.0.0.46
+1000.example. 5M IN A 10.0.0.47
+1000.example. 5M IN A 10.0.0.48
+1000.example. 5M IN A 10.0.0.49
+1000.example. 5M IN A 10.0.0.50
+1000.example. 5M IN A 10.0.0.51
+1000.example. 5M IN A 10.0.0.52
+1000.example. 5M IN A 10.0.0.53
+1000.example. 5M IN A 10.0.0.54
+1000.example. 5M IN A 10.0.0.55
+1000.example. 5M IN A 10.0.0.56
+1000.example. 5M IN A 10.0.0.57
+1000.example. 5M IN A 10.0.0.58
+1000.example. 5M IN A 10.0.0.59
+1000.example. 5M IN A 10.0.0.60
+1000.example. 5M IN A 10.0.0.61
+1000.example. 5M IN A 10.0.0.62
+1000.example. 5M IN A 10.0.0.63
+1000.example. 5M IN A 10.0.0.64
+1000.example. 5M IN A 10.0.0.65
+1000.example. 5M IN A 10.0.0.66
+1000.example. 5M IN A 10.0.0.67
+1000.example. 5M IN A 10.0.0.68
+1000.example. 5M IN A 10.0.0.69
+1000.example. 5M IN A 10.0.0.70
+1000.example. 5M IN A 10.0.0.71
+1000.example. 5M IN A 10.0.0.72
+1000.example. 5M IN A 10.0.0.73
+1000.example. 5M IN A 10.0.0.74
+1000.example. 5M IN A 10.0.0.75
+1000.example. 5M IN A 10.0.0.76
+1000.example. 5M IN A 10.0.0.77
+1000.example. 5M IN A 10.0.0.78
+1000.example. 5M IN A 10.0.0.79
+1000.example. 5M IN A 10.0.0.80
+1000.example. 5M IN A 10.0.0.81
+1000.example. 5M IN A 10.0.0.82
+1000.example. 5M IN A 10.0.0.83
+1000.example. 5M IN A 10.0.0.84
+1000.example. 5M IN A 10.0.0.85
+1000.example. 5M IN A 10.0.0.86
+1000.example. 5M IN A 10.0.0.87
+1000.example. 5M IN A 10.0.0.88
+1000.example. 5M IN A 10.0.0.89
+1000.example. 5M IN A 10.0.0.90
+1000.example. 5M IN A 10.0.0.91
+1000.example. 5M IN A 10.0.0.92
+1000.example. 5M IN A 10.0.0.93
+1000.example. 5M IN A 10.0.0.94
+1000.example. 5M IN A 10.0.0.95
+1000.example. 5M IN A 10.0.0.96
+1000.example. 5M IN A 10.0.0.97
+1000.example. 5M IN A 10.0.0.98
+1000.example. 5M IN A 10.0.0.99
+1000.example. 5M IN A 10.0.0.100
+1000.example. 5M IN A 10.0.0.101
+1000.example. 5M IN A 10.0.0.102
+1000.example. 5M IN A 10.0.0.103
+1000.example. 5M IN A 10.0.0.104
+1000.example. 5M IN A 10.0.0.105
+1000.example. 5M IN A 10.0.0.106
+1000.example. 5M IN A 10.0.0.107
+1000.example. 5M IN A 10.0.0.108
+1000.example. 5M IN A 10.0.0.109
+1000.example. 5M IN A 10.0.0.110
+1000.example. 5M IN A 10.0.0.111
+1000.example. 5M IN A 10.0.0.112
+1000.example. 5M IN A 10.0.0.113
+1000.example. 5M IN A 10.0.0.114
+1000.example. 5M IN A 10.0.0.115
+1000.example. 5M IN A 10.0.0.116
+1000.example. 5M IN A 10.0.0.117
+1000.example. 5M IN A 10.0.0.118
+1000.example. 5M IN A 10.0.0.119
+1000.example. 5M IN A 10.0.0.120
+1000.example. 5M IN A 10.0.0.121
+1000.example. 5M IN A 10.0.0.122
+1000.example. 5M IN A 10.0.0.123
+1000.example. 5M IN A 10.0.0.124
+1000.example. 5M IN A 10.0.0.125
+1000.example. 5M IN A 10.0.0.126
+1000.example. 5M IN A 10.0.0.127
+1000.example. 5M IN A 10.0.0.128
+1000.example. 5M IN A 10.0.0.129
+1000.example. 5M IN A 10.0.0.130
+1000.example. 5M IN A 10.0.0.131
+1000.example. 5M IN A 10.0.0.132
+1000.example. 5M IN A 10.0.0.133
+1000.example. 5M IN A 10.0.0.134
+1000.example. 5M IN A 10.0.0.135
+1000.example. 5M IN A 10.0.0.136
+1000.example. 5M IN A 10.0.0.137
+1000.example. 5M IN A 10.0.0.138
+1000.example. 5M IN A 10.0.0.139
+1000.example. 5M IN A 10.0.0.140
+1000.example. 5M IN A 10.0.0.141
+1000.example. 5M IN A 10.0.0.142
+1000.example. 5M IN A 10.0.0.143
+1000.example. 5M IN A 10.0.0.144
+1000.example. 5M IN A 10.0.0.145
+1000.example. 5M IN A 10.0.0.146
+1000.example. 5M IN A 10.0.0.147
+1000.example. 5M IN A 10.0.0.148
+1000.example. 5M IN A 10.0.0.149
+1000.example. 5M IN A 10.0.0.150
+1000.example. 5M IN A 10.0.0.151
+1000.example. 5M IN A 10.0.0.152
+1000.example. 5M IN A 10.0.0.153
+1000.example. 5M IN A 10.0.0.154
+1000.example. 5M IN A 10.0.0.155
+1000.example. 5M IN A 10.0.0.156
+1000.example. 5M IN A 10.0.0.157
+1000.example. 5M IN A 10.0.0.158
+1000.example. 5M IN A 10.0.0.159
+1000.example. 5M IN A 10.0.0.160
+1000.example. 5M IN A 10.0.0.161
+1000.example. 5M IN A 10.0.0.162
+1000.example. 5M IN A 10.0.0.163
+1000.example. 5M IN A 10.0.0.164
+1000.example. 5M IN A 10.0.0.165
+1000.example. 5M IN A 10.0.0.166
+1000.example. 5M IN A 10.0.0.167
+1000.example. 5M IN A 10.0.0.168
+1000.example. 5M IN A 10.0.0.169
+1000.example. 5M IN A 10.0.0.170
+1000.example. 5M IN A 10.0.0.171
+1000.example. 5M IN A 10.0.0.172
+1000.example. 5M IN A 10.0.0.173
+1000.example. 5M IN A 10.0.0.174
+1000.example. 5M IN A 10.0.0.175
+1000.example. 5M IN A 10.0.0.176
+1000.example. 5M IN A 10.0.0.177
+1000.example. 5M IN A 10.0.0.178
+1000.example. 5M IN A 10.0.0.179
+1000.example. 5M IN A 10.0.0.180
+1000.example. 5M IN A 10.0.0.181
+1000.example. 5M IN A 10.0.0.182
+1000.example. 5M IN A 10.0.0.183
+1000.example. 5M IN A 10.0.0.184
+1000.example. 5M IN A 10.0.0.185
+1000.example. 5M IN A 10.0.0.186
+1000.example. 5M IN A 10.0.0.187
+1000.example. 5M IN A 10.0.0.188
+1000.example. 5M IN A 10.0.0.189
+1000.example. 5M IN A 10.0.0.190
+1000.example. 5M IN A 10.0.0.191
+1000.example. 5M IN A 10.0.0.192
+1000.example. 5M IN A 10.0.0.193
+1000.example. 5M IN A 10.0.0.194
+1000.example. 5M IN A 10.0.0.195
+1000.example. 5M IN A 10.0.0.196
+1000.example. 5M IN A 10.0.0.197
+1000.example. 5M IN A 10.0.0.198
+1000.example. 5M IN A 10.0.0.199
+1000.example. 5M IN A 10.0.0.200
+1000.example. 5M IN A 10.0.0.201
+1000.example. 5M IN A 10.0.0.202
+1000.example. 5M IN A 10.0.0.203
+1000.example. 5M IN A 10.0.0.204
+1000.example. 5M IN A 10.0.0.205
+1000.example. 5M IN A 10.0.0.206
+1000.example. 5M IN A 10.0.0.207
+1000.example. 5M IN A 10.0.0.208
+1000.example. 5M IN A 10.0.0.209
+1000.example. 5M IN A 10.0.0.210
+1000.example. 5M IN A 10.0.0.211
+1000.example. 5M IN A 10.0.0.212
+1000.example. 5M IN A 10.0.0.213
+1000.example. 5M IN A 10.0.0.214
+1000.example. 5M IN A 10.0.0.215
+1000.example. 5M IN A 10.0.0.216
+1000.example. 5M IN A 10.0.0.217
+1000.example. 5M IN A 10.0.0.218
+1000.example. 5M IN A 10.0.0.219
+1000.example. 5M IN A 10.0.0.220
+1000.example. 5M IN A 10.0.0.221
+1000.example. 5M IN A 10.0.0.222
+1000.example. 5M IN A 10.0.0.223
+1000.example. 5M IN A 10.0.0.224
+1000.example. 5M IN A 10.0.0.225
+1000.example. 5M IN A 10.0.0.226
+1000.example. 5M IN A 10.0.0.227
+1000.example. 5M IN A 10.0.0.228
+1000.example. 5M IN A 10.0.0.229
+1000.example. 5M IN A 10.0.0.230
+1000.example. 5M IN A 10.0.0.231
+1000.example. 5M IN A 10.0.0.232
+1000.example. 5M IN A 10.0.0.233
+1000.example. 5M IN A 10.0.0.234
+1000.example. 5M IN A 10.0.0.235
+1000.example. 5M IN A 10.0.0.236
+1000.example. 5M IN A 10.0.0.237
+1000.example. 5M IN A 10.0.0.238
+1000.example. 5M IN A 10.0.0.239
+1000.example. 5M IN A 10.0.0.240
+1000.example. 5M IN A 10.0.0.241
+1000.example. 5M IN A 10.0.0.242
+1000.example. 5M IN A 10.0.0.243
+1000.example. 5M IN A 10.0.0.244
+1000.example. 5M IN A 10.0.0.245
+1000.example. 5M IN A 10.0.0.246
+1000.example. 5M IN A 10.0.0.247
+1000.example. 5M IN A 10.0.0.248
+1000.example. 5M IN A 10.0.0.249
+1000.example. 5M IN A 10.0.0.250
+1000.example. 5M IN A 10.0.0.251
+1000.example. 5M IN A 10.0.0.252
+1000.example. 5M IN A 10.0.0.253
+1000.example. 5M IN A 10.0.0.254
+1000.example. 5M IN A 10.0.0.255
+1000.example. 5M IN A 10.0.1.0
+1000.example. 5M IN A 10.0.1.1
+1000.example. 5M IN A 10.0.1.2
+1000.example. 5M IN A 10.0.1.3
+1000.example. 5M IN A 10.0.1.4
+1000.example. 5M IN A 10.0.1.5
+1000.example. 5M IN A 10.0.1.6
+1000.example. 5M IN A 10.0.1.7
+1000.example. 5M IN A 10.0.1.8
+1000.example. 5M IN A 10.0.1.9
+1000.example. 5M IN A 10.0.1.10
+1000.example. 5M IN A 10.0.1.11
+1000.example. 5M IN A 10.0.1.12
+1000.example. 5M IN A 10.0.1.13
+1000.example. 5M IN A 10.0.1.14
+1000.example. 5M IN A 10.0.1.15
+1000.example. 5M IN A 10.0.1.16
+1000.example. 5M IN A 10.0.1.17
+1000.example. 5M IN A 10.0.1.18
+1000.example. 5M IN A 10.0.1.19
+1000.example. 5M IN A 10.0.1.20
+1000.example. 5M IN A 10.0.1.21
+1000.example. 5M IN A 10.0.1.22
+1000.example. 5M IN A 10.0.1.23
+1000.example. 5M IN A 10.0.1.24
+1000.example. 5M IN A 10.0.1.25
+1000.example. 5M IN A 10.0.1.26
+1000.example. 5M IN A 10.0.1.27
+1000.example. 5M IN A 10.0.1.28
+1000.example. 5M IN A 10.0.1.29
+1000.example. 5M IN A 10.0.1.30
+1000.example. 5M IN A 10.0.1.31
+1000.example. 5M IN A 10.0.1.32
+1000.example. 5M IN A 10.0.1.33
+1000.example. 5M IN A 10.0.1.34
+1000.example. 5M IN A 10.0.1.35
+1000.example. 5M IN A 10.0.1.36
+1000.example. 5M IN A 10.0.1.37
+1000.example. 5M IN A 10.0.1.38
+1000.example. 5M IN A 10.0.1.39
+1000.example. 5M IN A 10.0.1.40
+1000.example. 5M IN A 10.0.1.41
+1000.example. 5M IN A 10.0.1.42
+1000.example. 5M IN A 10.0.1.43
+1000.example. 5M IN A 10.0.1.44
+1000.example. 5M IN A 10.0.1.45
+1000.example. 5M IN A 10.0.1.46
+1000.example. 5M IN A 10.0.1.47
+1000.example. 5M IN A 10.0.1.48
+1000.example. 5M IN A 10.0.1.49
+1000.example. 5M IN A 10.0.1.50
+1000.example. 5M IN A 10.0.1.51
+1000.example. 5M IN A 10.0.1.52
+1000.example. 5M IN A 10.0.1.53
+1000.example. 5M IN A 10.0.1.54
+1000.example. 5M IN A 10.0.1.55
+1000.example. 5M IN A 10.0.1.56
+1000.example. 5M IN A 10.0.1.57
+1000.example. 5M IN A 10.0.1.58
+1000.example. 5M IN A 10.0.1.59
+1000.example. 5M IN A 10.0.1.60
+1000.example. 5M IN A 10.0.1.61
+1000.example. 5M IN A 10.0.1.62
+1000.example. 5M IN A 10.0.1.63
+1000.example. 5M IN A 10.0.1.64
+1000.example. 5M IN A 10.0.1.65
+1000.example. 5M IN A 10.0.1.66
+1000.example. 5M IN A 10.0.1.67
+1000.example. 5M IN A 10.0.1.68
+1000.example. 5M IN A 10.0.1.69
+1000.example. 5M IN A 10.0.1.70
+1000.example. 5M IN A 10.0.1.71
+1000.example. 5M IN A 10.0.1.72
+1000.example. 5M IN A 10.0.1.73
+1000.example. 5M IN A 10.0.1.74
+1000.example. 5M IN A 10.0.1.75
+1000.example. 5M IN A 10.0.1.76
+1000.example. 5M IN A 10.0.1.77
+1000.example. 5M IN A 10.0.1.78
+1000.example. 5M IN A 10.0.1.79
+1000.example. 5M IN A 10.0.1.80
+1000.example. 5M IN A 10.0.1.81
+1000.example. 5M IN A 10.0.1.82
+1000.example. 5M IN A 10.0.1.83
+1000.example. 5M IN A 10.0.1.84
+1000.example. 5M IN A 10.0.1.85
+1000.example. 5M IN A 10.0.1.86
+1000.example. 5M IN A 10.0.1.87
+1000.example. 5M IN A 10.0.1.88
+1000.example. 5M IN A 10.0.1.89
+1000.example. 5M IN A 10.0.1.90
+1000.example. 5M IN A 10.0.1.91
+1000.example. 5M IN A 10.0.1.92
+1000.example. 5M IN A 10.0.1.93
+1000.example. 5M IN A 10.0.1.94
+1000.example. 5M IN A 10.0.1.95
+1000.example. 5M IN A 10.0.1.96
+1000.example. 5M IN A 10.0.1.97
+1000.example. 5M IN A 10.0.1.98
+1000.example. 5M IN A 10.0.1.99
+1000.example. 5M IN A 10.0.1.100
+1000.example. 5M IN A 10.0.1.101
+1000.example. 5M IN A 10.0.1.102
+1000.example. 5M IN A 10.0.1.103
+1000.example. 5M IN A 10.0.1.104
+1000.example. 5M IN A 10.0.1.105
+1000.example. 5M IN A 10.0.1.106
+1000.example. 5M IN A 10.0.1.107
+1000.example. 5M IN A 10.0.1.108
+1000.example. 5M IN A 10.0.1.109
+1000.example. 5M IN A 10.0.1.110
+1000.example. 5M IN A 10.0.1.111
+1000.example. 5M IN A 10.0.1.112
+1000.example. 5M IN A 10.0.1.113
+1000.example. 5M IN A 10.0.1.114
+1000.example. 5M IN A 10.0.1.115
+1000.example. 5M IN A 10.0.1.116
+1000.example. 5M IN A 10.0.1.117
+1000.example. 5M IN A 10.0.1.118
+1000.example. 5M IN A 10.0.1.119
+1000.example. 5M IN A 10.0.1.120
+1000.example. 5M IN A 10.0.1.121
+1000.example. 5M IN A 10.0.1.122
+1000.example. 5M IN A 10.0.1.123
+1000.example. 5M IN A 10.0.1.124
+1000.example. 5M IN A 10.0.1.125
+1000.example. 5M IN A 10.0.1.126
+1000.example. 5M IN A 10.0.1.127
+1000.example. 5M IN A 10.0.1.128
+1000.example. 5M IN A 10.0.1.129
+1000.example. 5M IN A 10.0.1.130
+1000.example. 5M IN A 10.0.1.131
+1000.example. 5M IN A 10.0.1.132
+1000.example. 5M IN A 10.0.1.133
+1000.example. 5M IN A 10.0.1.134
+1000.example. 5M IN A 10.0.1.135
+1000.example. 5M IN A 10.0.1.136
+1000.example. 5M IN A 10.0.1.137
+1000.example. 5M IN A 10.0.1.138
+1000.example. 5M IN A 10.0.1.139
+1000.example. 5M IN A 10.0.1.140
+1000.example. 5M IN A 10.0.1.141
+1000.example. 5M IN A 10.0.1.142
+1000.example. 5M IN A 10.0.1.143
+1000.example. 5M IN A 10.0.1.144
+1000.example. 5M IN A 10.0.1.145
+1000.example. 5M IN A 10.0.1.146
+1000.example. 5M IN A 10.0.1.147
+1000.example. 5M IN A 10.0.1.148
+1000.example. 5M IN A 10.0.1.149
+1000.example. 5M IN A 10.0.1.150
+1000.example. 5M IN A 10.0.1.151
+1000.example. 5M IN A 10.0.1.152
+1000.example. 5M IN A 10.0.1.153
+1000.example. 5M IN A 10.0.1.154
+1000.example. 5M IN A 10.0.1.155
+1000.example. 5M IN A 10.0.1.156
+1000.example. 5M IN A 10.0.1.157
+1000.example. 5M IN A 10.0.1.158
+1000.example. 5M IN A 10.0.1.159
+1000.example. 5M IN A 10.0.1.160
+1000.example. 5M IN A 10.0.1.161
+1000.example. 5M IN A 10.0.1.162
+1000.example. 5M IN A 10.0.1.163
+1000.example. 5M IN A 10.0.1.164
+1000.example. 5M IN A 10.0.1.165
+1000.example. 5M IN A 10.0.1.166
+1000.example. 5M IN A 10.0.1.167
+1000.example. 5M IN A 10.0.1.168
+1000.example. 5M IN A 10.0.1.169
+1000.example. 5M IN A 10.0.1.170
+1000.example. 5M IN A 10.0.1.171
+1000.example. 5M IN A 10.0.1.172
+1000.example. 5M IN A 10.0.1.173
+1000.example. 5M IN A 10.0.1.174
+1000.example. 5M IN A 10.0.1.175
+1000.example. 5M IN A 10.0.1.176
+1000.example. 5M IN A 10.0.1.177
+1000.example. 5M IN A 10.0.1.178
+1000.example. 5M IN A 10.0.1.179
+1000.example. 5M IN A 10.0.1.180
+1000.example. 5M IN A 10.0.1.181
+1000.example. 5M IN A 10.0.1.182
+1000.example. 5M IN A 10.0.1.183
+1000.example. 5M IN A 10.0.1.184
+1000.example. 5M IN A 10.0.1.185
+1000.example. 5M IN A 10.0.1.186
+1000.example. 5M IN A 10.0.1.187
+1000.example. 5M IN A 10.0.1.188
+1000.example. 5M IN A 10.0.1.189
+1000.example. 5M IN A 10.0.1.190
+1000.example. 5M IN A 10.0.1.191
+1000.example. 5M IN A 10.0.1.192
+1000.example. 5M IN A 10.0.1.193
+1000.example. 5M IN A 10.0.1.194
+1000.example. 5M IN A 10.0.1.195
+1000.example. 5M IN A 10.0.1.196
+1000.example. 5M IN A 10.0.1.197
+1000.example. 5M IN A 10.0.1.198
+1000.example. 5M IN A 10.0.1.199
+1000.example. 5M IN A 10.0.1.200
+1000.example. 5M IN A 10.0.1.201
+1000.example. 5M IN A 10.0.1.202
+1000.example. 5M IN A 10.0.1.203
+1000.example. 5M IN A 10.0.1.204
+1000.example. 5M IN A 10.0.1.205
+1000.example. 5M IN A 10.0.1.206
+1000.example. 5M IN A 10.0.1.207
+1000.example. 5M IN A 10.0.1.208
+1000.example. 5M IN A 10.0.1.209
+1000.example. 5M IN A 10.0.1.210
+1000.example. 5M IN A 10.0.1.211
+1000.example. 5M IN A 10.0.1.212
+1000.example. 5M IN A 10.0.1.213
+1000.example. 5M IN A 10.0.1.214
+1000.example. 5M IN A 10.0.1.215
+1000.example. 5M IN A 10.0.1.216
+1000.example. 5M IN A 10.0.1.217
+1000.example. 5M IN A 10.0.1.218
+1000.example. 5M IN A 10.0.1.219
+1000.example. 5M IN A 10.0.1.220
+1000.example. 5M IN A 10.0.1.221
+1000.example. 5M IN A 10.0.1.222
+1000.example. 5M IN A 10.0.1.223
+1000.example. 5M IN A 10.0.1.224
+1000.example. 5M IN A 10.0.1.225
+1000.example. 5M IN A 10.0.1.226
+1000.example. 5M IN A 10.0.1.227
+1000.example. 5M IN A 10.0.1.228
+1000.example. 5M IN A 10.0.1.229
+1000.example. 5M IN A 10.0.1.230
+1000.example. 5M IN A 10.0.1.231
+1000.example. 5M IN A 10.0.1.232
+1000.example. 5M IN A 10.0.1.233
+1000.example. 5M IN A 10.0.1.234
+1000.example. 5M IN A 10.0.1.235
+1000.example. 5M IN A 10.0.1.236
+1000.example. 5M IN A 10.0.1.237
+1000.example. 5M IN A 10.0.1.238
+1000.example. 5M IN A 10.0.1.239
+1000.example. 5M IN A 10.0.1.240
+1000.example. 5M IN A 10.0.1.241
+1000.example. 5M IN A 10.0.1.242
+1000.example. 5M IN A 10.0.1.243
+1000.example. 5M IN A 10.0.1.244
+1000.example. 5M IN A 10.0.1.245
+1000.example. 5M IN A 10.0.1.246
+1000.example. 5M IN A 10.0.1.247
+1000.example. 5M IN A 10.0.1.248
+1000.example. 5M IN A 10.0.1.249
+1000.example. 5M IN A 10.0.1.250
+1000.example. 5M IN A 10.0.1.251
+1000.example. 5M IN A 10.0.1.252
+1000.example. 5M IN A 10.0.1.253
+1000.example. 5M IN A 10.0.1.254
+1000.example. 5M IN A 10.0.1.255
+1000.example. 5M IN A 10.0.2.0
+1000.example. 5M IN A 10.0.2.1
+1000.example. 5M IN A 10.0.2.2
+1000.example. 5M IN A 10.0.2.3
+1000.example. 5M IN A 10.0.2.4
+1000.example. 5M IN A 10.0.2.5
+1000.example. 5M IN A 10.0.2.6
+1000.example. 5M IN A 10.0.2.7
+1000.example. 5M IN A 10.0.2.8
+1000.example. 5M IN A 10.0.2.9
+1000.example. 5M IN A 10.0.2.10
+1000.example. 5M IN A 10.0.2.11
+1000.example. 5M IN A 10.0.2.12
+1000.example. 5M IN A 10.0.2.13
+1000.example. 5M IN A 10.0.2.14
+1000.example. 5M IN A 10.0.2.15
+1000.example. 5M IN A 10.0.2.16
+1000.example. 5M IN A 10.0.2.17
+1000.example. 5M IN A 10.0.2.18
+1000.example. 5M IN A 10.0.2.19
+1000.example. 5M IN A 10.0.2.20
+1000.example. 5M IN A 10.0.2.21
+1000.example. 5M IN A 10.0.2.22
+1000.example. 5M IN A 10.0.2.23
+1000.example. 5M IN A 10.0.2.24
+1000.example. 5M IN A 10.0.2.25
+1000.example. 5M IN A 10.0.2.26
+1000.example. 5M IN A 10.0.2.27
+1000.example. 5M IN A 10.0.2.28
+1000.example. 5M IN A 10.0.2.29
+1000.example. 5M IN A 10.0.2.30
+1000.example. 5M IN A 10.0.2.31
+1000.example. 5M IN A 10.0.2.32
+1000.example. 5M IN A 10.0.2.33
+1000.example. 5M IN A 10.0.2.34
+1000.example. 5M IN A 10.0.2.35
+1000.example. 5M IN A 10.0.2.36
+1000.example. 5M IN A 10.0.2.37
+1000.example. 5M IN A 10.0.2.38
+1000.example. 5M IN A 10.0.2.39
+1000.example. 5M IN A 10.0.2.40
+1000.example. 5M IN A 10.0.2.41
+1000.example. 5M IN A 10.0.2.42
+1000.example. 5M IN A 10.0.2.43
+1000.example. 5M IN A 10.0.2.44
+1000.example. 5M IN A 10.0.2.45
+1000.example. 5M IN A 10.0.2.46
+1000.example. 5M IN A 10.0.2.47
+1000.example. 5M IN A 10.0.2.48
+1000.example. 5M IN A 10.0.2.49
+1000.example. 5M IN A 10.0.2.50
+1000.example. 5M IN A 10.0.2.51
+1000.example. 5M IN A 10.0.2.52
+1000.example. 5M IN A 10.0.2.53
+1000.example. 5M IN A 10.0.2.54
+1000.example. 5M IN A 10.0.2.55
+1000.example. 5M IN A 10.0.2.56
+1000.example. 5M IN A 10.0.2.57
+1000.example. 5M IN A 10.0.2.58
+1000.example. 5M IN A 10.0.2.59
+1000.example. 5M IN A 10.0.2.60
+1000.example. 5M IN A 10.0.2.61
+1000.example. 5M IN A 10.0.2.62
+1000.example. 5M IN A 10.0.2.63
+1000.example. 5M IN A 10.0.2.64
+1000.example. 5M IN A 10.0.2.65
+1000.example. 5M IN A 10.0.2.66
+1000.example. 5M IN A 10.0.2.67
+1000.example. 5M IN A 10.0.2.68
+1000.example. 5M IN A 10.0.2.69
+1000.example. 5M IN A 10.0.2.70
+1000.example. 5M IN A 10.0.2.71
+1000.example. 5M IN A 10.0.2.72
+1000.example. 5M IN A 10.0.2.73
+1000.example. 5M IN A 10.0.2.74
+1000.example. 5M IN A 10.0.2.75
+1000.example. 5M IN A 10.0.2.76
+1000.example. 5M IN A 10.0.2.77
+1000.example. 5M IN A 10.0.2.78
+1000.example. 5M IN A 10.0.2.79
+1000.example. 5M IN A 10.0.2.80
+1000.example. 5M IN A 10.0.2.81
+1000.example. 5M IN A 10.0.2.82
+1000.example. 5M IN A 10.0.2.83
+1000.example. 5M IN A 10.0.2.84
+1000.example. 5M IN A 10.0.2.85
+1000.example. 5M IN A 10.0.2.86
+1000.example. 5M IN A 10.0.2.87
+1000.example. 5M IN A 10.0.2.88
+1000.example. 5M IN A 10.0.2.89
+1000.example. 5M IN A 10.0.2.90
+1000.example. 5M IN A 10.0.2.91
+1000.example. 5M IN A 10.0.2.92
+1000.example. 5M IN A 10.0.2.93
+1000.example. 5M IN A 10.0.2.94
+1000.example. 5M IN A 10.0.2.95
+1000.example. 5M IN A 10.0.2.96
+1000.example. 5M IN A 10.0.2.97
+1000.example. 5M IN A 10.0.2.98
+1000.example. 5M IN A 10.0.2.99
+1000.example. 5M IN A 10.0.2.100
+1000.example. 5M IN A 10.0.2.101
+1000.example. 5M IN A 10.0.2.102
+1000.example. 5M IN A 10.0.2.103
+1000.example. 5M IN A 10.0.2.104
+1000.example. 5M IN A 10.0.2.105
+1000.example. 5M IN A 10.0.2.106
+1000.example. 5M IN A 10.0.2.107
+1000.example. 5M IN A 10.0.2.108
+1000.example. 5M IN A 10.0.2.109
+1000.example. 5M IN A 10.0.2.110
+1000.example. 5M IN A 10.0.2.111
+1000.example. 5M IN A 10.0.2.112
+1000.example. 5M IN A 10.0.2.113
+1000.example. 5M IN A 10.0.2.114
+1000.example. 5M IN A 10.0.2.115
+1000.example. 5M IN A 10.0.2.116
+1000.example. 5M IN A 10.0.2.117
+1000.example. 5M IN A 10.0.2.118
+1000.example. 5M IN A 10.0.2.119
+1000.example. 5M IN A 10.0.2.120
+1000.example. 5M IN A 10.0.2.121
+1000.example. 5M IN A 10.0.2.122
+1000.example. 5M IN A 10.0.2.123
+1000.example. 5M IN A 10.0.2.124
+1000.example. 5M IN A 10.0.2.125
+1000.example. 5M IN A 10.0.2.126
+1000.example. 5M IN A 10.0.2.127
+1000.example. 5M IN A 10.0.2.128
+1000.example. 5M IN A 10.0.2.129
+1000.example. 5M IN A 10.0.2.130
+1000.example. 5M IN A 10.0.2.131
+1000.example. 5M IN A 10.0.2.132
+1000.example. 5M IN A 10.0.2.133
+1000.example. 5M IN A 10.0.2.134
+1000.example. 5M IN A 10.0.2.135
+1000.example. 5M IN A 10.0.2.136
+1000.example. 5M IN A 10.0.2.137
+1000.example. 5M IN A 10.0.2.138
+1000.example. 5M IN A 10.0.2.139
+1000.example. 5M IN A 10.0.2.140
+1000.example. 5M IN A 10.0.2.141
+1000.example. 5M IN A 10.0.2.142
+1000.example. 5M IN A 10.0.2.143
+1000.example. 5M IN A 10.0.2.144
+1000.example. 5M IN A 10.0.2.145
+1000.example. 5M IN A 10.0.2.146
+1000.example. 5M IN A 10.0.2.147
+1000.example. 5M IN A 10.0.2.148
+1000.example. 5M IN A 10.0.2.149
+1000.example. 5M IN A 10.0.2.150
+1000.example. 5M IN A 10.0.2.151
+1000.example. 5M IN A 10.0.2.152
+1000.example. 5M IN A 10.0.2.153
+1000.example. 5M IN A 10.0.2.154
+1000.example. 5M IN A 10.0.2.155
+1000.example. 5M IN A 10.0.2.156
+1000.example. 5M IN A 10.0.2.157
+1000.example. 5M IN A 10.0.2.158
+1000.example. 5M IN A 10.0.2.159
+1000.example. 5M IN A 10.0.2.160
+1000.example. 5M IN A 10.0.2.161
+1000.example. 5M IN A 10.0.2.162
+1000.example. 5M IN A 10.0.2.163
+1000.example. 5M IN A 10.0.2.164
+1000.example. 5M IN A 10.0.2.165
+1000.example. 5M IN A 10.0.2.166
+1000.example. 5M IN A 10.0.2.167
+1000.example. 5M IN A 10.0.2.168
+1000.example. 5M IN A 10.0.2.169
+1000.example. 5M IN A 10.0.2.170
+1000.example. 5M IN A 10.0.2.171
+1000.example. 5M IN A 10.0.2.172
+1000.example. 5M IN A 10.0.2.173
+1000.example. 5M IN A 10.0.2.174
+1000.example. 5M IN A 10.0.2.175
+1000.example. 5M IN A 10.0.2.176
+1000.example. 5M IN A 10.0.2.177
+1000.example. 5M IN A 10.0.2.178
+1000.example. 5M IN A 10.0.2.179
+1000.example. 5M IN A 10.0.2.180
+1000.example. 5M IN A 10.0.2.181
+1000.example. 5M IN A 10.0.2.182
+1000.example. 5M IN A 10.0.2.183
+1000.example. 5M IN A 10.0.2.184
+1000.example. 5M IN A 10.0.2.185
+1000.example. 5M IN A 10.0.2.186
+1000.example. 5M IN A 10.0.2.187
+1000.example. 5M IN A 10.0.2.188
+1000.example. 5M IN A 10.0.2.189
+1000.example. 5M IN A 10.0.2.190
+1000.example. 5M IN A 10.0.2.191
+1000.example. 5M IN A 10.0.2.192
+1000.example. 5M IN A 10.0.2.193
+1000.example. 5M IN A 10.0.2.194
+1000.example. 5M IN A 10.0.2.195
+1000.example. 5M IN A 10.0.2.196
+1000.example. 5M IN A 10.0.2.197
+1000.example. 5M IN A 10.0.2.198
+1000.example. 5M IN A 10.0.2.199
+1000.example. 5M IN A 10.0.2.200
+1000.example. 5M IN A 10.0.2.201
+1000.example. 5M IN A 10.0.2.202
+1000.example. 5M IN A 10.0.2.203
+1000.example. 5M IN A 10.0.2.204
+1000.example. 5M IN A 10.0.2.205
+1000.example. 5M IN A 10.0.2.206
+1000.example. 5M IN A 10.0.2.207
+1000.example. 5M IN A 10.0.2.208
+1000.example. 5M IN A 10.0.2.209
+1000.example. 5M IN A 10.0.2.210
+1000.example. 5M IN A 10.0.2.211
+1000.example. 5M IN A 10.0.2.212
+1000.example. 5M IN A 10.0.2.213
+1000.example. 5M IN A 10.0.2.214
+1000.example. 5M IN A 10.0.2.215
+1000.example. 5M IN A 10.0.2.216
+1000.example. 5M IN A 10.0.2.217
+1000.example. 5M IN A 10.0.2.218
+1000.example. 5M IN A 10.0.2.219
+1000.example. 5M IN A 10.0.2.220
+1000.example. 5M IN A 10.0.2.221
+1000.example. 5M IN A 10.0.2.222
+1000.example. 5M IN A 10.0.2.223
+1000.example. 5M IN A 10.0.2.224
+1000.example. 5M IN A 10.0.2.225
+1000.example. 5M IN A 10.0.2.226
+1000.example. 5M IN A 10.0.2.227
+1000.example. 5M IN A 10.0.2.228
+1000.example. 5M IN A 10.0.2.229
+1000.example. 5M IN A 10.0.2.230
+1000.example. 5M IN A 10.0.2.231
+1000.example. 5M IN A 10.0.2.232
+1000.example. 5M IN A 10.0.2.233
+1000.example. 5M IN A 10.0.2.234
+1000.example. 5M IN A 10.0.2.235
+1000.example. 5M IN A 10.0.2.236
+1000.example. 5M IN A 10.0.2.237
+1000.example. 5M IN A 10.0.2.238
+1000.example. 5M IN A 10.0.2.239
+1000.example. 5M IN A 10.0.2.240
+1000.example. 5M IN A 10.0.2.241
+1000.example. 5M IN A 10.0.2.242
+1000.example. 5M IN A 10.0.2.243
+1000.example. 5M IN A 10.0.2.244
+1000.example. 5M IN A 10.0.2.245
+1000.example. 5M IN A 10.0.2.246
+1000.example. 5M IN A 10.0.2.247
+1000.example. 5M IN A 10.0.2.248
+1000.example. 5M IN A 10.0.2.249
+1000.example. 5M IN A 10.0.2.250
+1000.example. 5M IN A 10.0.2.251
+1000.example. 5M IN A 10.0.2.252
+1000.example. 5M IN A 10.0.2.253
+1000.example. 5M IN A 10.0.2.254
+1000.example. 5M IN A 10.0.2.255
+1000.example. 5M IN A 10.0.3.0
+1000.example. 5M IN A 10.0.3.1
+1000.example. 5M IN A 10.0.3.2
+1000.example. 5M IN A 10.0.3.3
+1000.example. 5M IN A 10.0.3.4
+1000.example. 5M IN A 10.0.3.5
+1000.example. 5M IN A 10.0.3.6
+1000.example. 5M IN A 10.0.3.7
+1000.example. 5M IN A 10.0.3.8
+1000.example. 5M IN A 10.0.3.9
+1000.example. 5M IN A 10.0.3.10
+1000.example. 5M IN A 10.0.3.11
+1000.example. 5M IN A 10.0.3.12
+1000.example. 5M IN A 10.0.3.13
+1000.example. 5M IN A 10.0.3.14
+1000.example. 5M IN A 10.0.3.15
+1000.example. 5M IN A 10.0.3.16
+1000.example. 5M IN A 10.0.3.17
+1000.example. 5M IN A 10.0.3.18
+1000.example. 5M IN A 10.0.3.19
+1000.example. 5M IN A 10.0.3.20
+1000.example. 5M IN A 10.0.3.21
+1000.example. 5M IN A 10.0.3.22
+1000.example. 5M IN A 10.0.3.23
+1000.example. 5M IN A 10.0.3.24
+1000.example. 5M IN A 10.0.3.25
+1000.example. 5M IN A 10.0.3.26
+1000.example. 5M IN A 10.0.3.27
+1000.example. 5M IN A 10.0.3.28
+1000.example. 5M IN A 10.0.3.29
+1000.example. 5M IN A 10.0.3.30
+1000.example. 5M IN A 10.0.3.31
+1000.example. 5M IN A 10.0.3.32
+1000.example. 5M IN A 10.0.3.33
+1000.example. 5M IN A 10.0.3.34
+1000.example. 5M IN A 10.0.3.35
+1000.example. 5M IN A 10.0.3.36
+1000.example. 5M IN A 10.0.3.37
+1000.example. 5M IN A 10.0.3.38
+1000.example. 5M IN A 10.0.3.39
+1000.example. 5M IN A 10.0.3.40
+1000.example. 5M IN A 10.0.3.41
+1000.example. 5M IN A 10.0.3.42
+1000.example. 5M IN A 10.0.3.43
+1000.example. 5M IN A 10.0.3.44
+1000.example. 5M IN A 10.0.3.45
+1000.example. 5M IN A 10.0.3.46
+1000.example. 5M IN A 10.0.3.47
+1000.example. 5M IN A 10.0.3.48
+1000.example. 5M IN A 10.0.3.49
+1000.example. 5M IN A 10.0.3.50
+1000.example. 5M IN A 10.0.3.51
+1000.example. 5M IN A 10.0.3.52
+1000.example. 5M IN A 10.0.3.53
+1000.example. 5M IN A 10.0.3.54
+1000.example. 5M IN A 10.0.3.55
+1000.example. 5M IN A 10.0.3.56
+1000.example. 5M IN A 10.0.3.57
+1000.example. 5M IN A 10.0.3.58
+1000.example. 5M IN A 10.0.3.59
+1000.example. 5M IN A 10.0.3.60
+1000.example. 5M IN A 10.0.3.61
+1000.example. 5M IN A 10.0.3.62
+1000.example. 5M IN A 10.0.3.63
+1000.example. 5M IN A 10.0.3.64
+1000.example. 5M IN A 10.0.3.65
+1000.example. 5M IN A 10.0.3.66
+1000.example. 5M IN A 10.0.3.67
+1000.example. 5M IN A 10.0.3.68
+1000.example. 5M IN A 10.0.3.69
+1000.example. 5M IN A 10.0.3.70
+1000.example. 5M IN A 10.0.3.71
+1000.example. 5M IN A 10.0.3.72
+1000.example. 5M IN A 10.0.3.73
+1000.example. 5M IN A 10.0.3.74
+1000.example. 5M IN A 10.0.3.75
+1000.example. 5M IN A 10.0.3.76
+1000.example. 5M IN A 10.0.3.77
+1000.example. 5M IN A 10.0.3.78
+1000.example. 5M IN A 10.0.3.79
+1000.example. 5M IN A 10.0.3.80
+1000.example. 5M IN A 10.0.3.81
+1000.example. 5M IN A 10.0.3.82
+1000.example. 5M IN A 10.0.3.83
+1000.example. 5M IN A 10.0.3.84
+1000.example. 5M IN A 10.0.3.85
+1000.example. 5M IN A 10.0.3.86
+1000.example. 5M IN A 10.0.3.87
+1000.example. 5M IN A 10.0.3.88
+1000.example. 5M IN A 10.0.3.89
+1000.example. 5M IN A 10.0.3.90
+1000.example. 5M IN A 10.0.3.91
+1000.example. 5M IN A 10.0.3.92
+1000.example. 5M IN A 10.0.3.93
+1000.example. 5M IN A 10.0.3.94
+1000.example. 5M IN A 10.0.3.95
+1000.example. 5M IN A 10.0.3.96
+1000.example. 5M IN A 10.0.3.97
+1000.example. 5M IN A 10.0.3.98
+1000.example. 5M IN A 10.0.3.99
+1000.example. 5M IN A 10.0.3.100
+1000.example. 5M IN A 10.0.3.101
+1000.example. 5M IN A 10.0.3.102
+1000.example. 5M IN A 10.0.3.103
+1000.example. 5M IN A 10.0.3.104
+1000.example. 5M IN A 10.0.3.105
+1000.example. 5M IN A 10.0.3.106
+1000.example. 5M IN A 10.0.3.107
+1000.example. 5M IN A 10.0.3.108
+1000.example. 5M IN A 10.0.3.109
+1000.example. 5M IN A 10.0.3.110
+1000.example. 5M IN A 10.0.3.111
+1000.example. 5M IN A 10.0.3.112
+1000.example. 5M IN A 10.0.3.113
+1000.example. 5M IN A 10.0.3.114
+1000.example. 5M IN A 10.0.3.115
+1000.example. 5M IN A 10.0.3.116
+1000.example. 5M IN A 10.0.3.117
+1000.example. 5M IN A 10.0.3.118
+1000.example. 5M IN A 10.0.3.119
+1000.example. 5M IN A 10.0.3.120
+1000.example. 5M IN A 10.0.3.121
+1000.example. 5M IN A 10.0.3.122
+1000.example. 5M IN A 10.0.3.123
+1000.example. 5M IN A 10.0.3.124
+1000.example. 5M IN A 10.0.3.125
+1000.example. 5M IN A 10.0.3.126
+1000.example. 5M IN A 10.0.3.127
+1000.example. 5M IN A 10.0.3.128
+1000.example. 5M IN A 10.0.3.129
+1000.example. 5M IN A 10.0.3.130
+1000.example. 5M IN A 10.0.3.131
+1000.example. 5M IN A 10.0.3.132
+1000.example. 5M IN A 10.0.3.133
+1000.example. 5M IN A 10.0.3.134
+1000.example. 5M IN A 10.0.3.135
+1000.example. 5M IN A 10.0.3.136
+1000.example. 5M IN A 10.0.3.137
+1000.example. 5M IN A 10.0.3.138
+1000.example. 5M IN A 10.0.3.139
+1000.example. 5M IN A 10.0.3.140
+1000.example. 5M IN A 10.0.3.141
+1000.example. 5M IN A 10.0.3.142
+1000.example. 5M IN A 10.0.3.143
+1000.example. 5M IN A 10.0.3.144
+1000.example. 5M IN A 10.0.3.145
+1000.example. 5M IN A 10.0.3.146
+1000.example. 5M IN A 10.0.3.147
+1000.example. 5M IN A 10.0.3.148
+1000.example. 5M IN A 10.0.3.149
+1000.example. 5M IN A 10.0.3.150
+1000.example. 5M IN A 10.0.3.151
+1000.example. 5M IN A 10.0.3.152
+1000.example. 5M IN A 10.0.3.153
+1000.example. 5M IN A 10.0.3.154
+1000.example. 5M IN A 10.0.3.155
+1000.example. 5M IN A 10.0.3.156
+1000.example. 5M IN A 10.0.3.157
+1000.example. 5M IN A 10.0.3.158
+1000.example. 5M IN A 10.0.3.159
+1000.example. 5M IN A 10.0.3.160
+1000.example. 5M IN A 10.0.3.161
+1000.example. 5M IN A 10.0.3.162
+1000.example. 5M IN A 10.0.3.163
+1000.example. 5M IN A 10.0.3.164
+1000.example. 5M IN A 10.0.3.165
+1000.example. 5M IN A 10.0.3.166
+1000.example. 5M IN A 10.0.3.167
+1000.example. 5M IN A 10.0.3.168
+1000.example. 5M IN A 10.0.3.169
+1000.example. 5M IN A 10.0.3.170
+1000.example. 5M IN A 10.0.3.171
+1000.example. 5M IN A 10.0.3.172
+1000.example. 5M IN A 10.0.3.173
+1000.example. 5M IN A 10.0.3.174
+1000.example. 5M IN A 10.0.3.175
+1000.example. 5M IN A 10.0.3.176
+1000.example. 5M IN A 10.0.3.177
+1000.example. 5M IN A 10.0.3.178
+1000.example. 5M IN A 10.0.3.179
+1000.example. 5M IN A 10.0.3.180
+1000.example. 5M IN A 10.0.3.181
+1000.example. 5M IN A 10.0.3.182
+1000.example. 5M IN A 10.0.3.183
+1000.example. 5M IN A 10.0.3.184
+1000.example. 5M IN A 10.0.3.185
+1000.example. 5M IN A 10.0.3.186
+1000.example. 5M IN A 10.0.3.187
+1000.example. 5M IN A 10.0.3.188
+1000.example. 5M IN A 10.0.3.189
+1000.example. 5M IN A 10.0.3.190
+1000.example. 5M IN A 10.0.3.191
+1000.example. 5M IN A 10.0.3.192
+1000.example. 5M IN A 10.0.3.193
+1000.example. 5M IN A 10.0.3.194
+1000.example. 5M IN A 10.0.3.195
+1000.example. 5M IN A 10.0.3.196
+1000.example. 5M IN A 10.0.3.197
+1000.example. 5M IN A 10.0.3.198
+1000.example. 5M IN A 10.0.3.199
+1000.example. 5M IN A 10.0.3.200
+1000.example. 5M IN A 10.0.3.201
+1000.example. 5M IN A 10.0.3.202
+1000.example. 5M IN A 10.0.3.203
+1000.example. 5M IN A 10.0.3.204
+1000.example. 5M IN A 10.0.3.205
+1000.example. 5M IN A 10.0.3.206
+1000.example. 5M IN A 10.0.3.207
+1000.example. 5M IN A 10.0.3.208
+1000.example. 5M IN A 10.0.3.209
+1000.example. 5M IN A 10.0.3.210
+1000.example. 5M IN A 10.0.3.211
+1000.example. 5M IN A 10.0.3.212
+1000.example. 5M IN A 10.0.3.213
+1000.example. 5M IN A 10.0.3.214
+1000.example. 5M IN A 10.0.3.215
+1000.example. 5M IN A 10.0.3.216
+1000.example. 5M IN A 10.0.3.217
+1000.example. 5M IN A 10.0.3.218
+1000.example. 5M IN A 10.0.3.219
+1000.example. 5M IN A 10.0.3.220
+1000.example. 5M IN A 10.0.3.221
+1000.example. 5M IN A 10.0.3.222
+1000.example. 5M IN A 10.0.3.223
+1000.example. 5M IN A 10.0.3.224
+1000.example. 5M IN A 10.0.3.225
+1000.example. 5M IN A 10.0.3.226
+1000.example. 5M IN A 10.0.3.227
+1000.example. 5M IN A 10.0.3.228
+1000.example. 5M IN A 10.0.3.229
+1000.example. 5M IN A 10.0.3.230
+1000.example. 5M IN A 10.0.3.231
+
+;; AUTHORITY SECTION:
+example. 5M IN NS ns1.example.
+
+;; ADDITIONAL SECTION:
+ns1.example. 5M IN A 10.53.0.1
+
+;; Total query time: 69 msec
+;; FROM: draco to SERVER: 10.53.0.1
+;; WHEN: Fri Jun 23 12:58:14 2000
+;; MSG SIZE sent: 30 rcvd: 16064
+
diff --git a/bin/tests/system/limits/knowngood.dig.out.2000 b/bin/tests/system/limits/knowngood.dig.out.2000
new file mode 100644
index 0000000..96c9181
--- /dev/null
+++ b/bin/tests/system/limits/knowngood.dig.out.2000
@@ -0,0 +1,2023 @@
+
+; <<>> DiG 8.2 <<>> 2000.example. @10.53.0.1 a -p
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr aa rd ad; QUERY: 1, ANSWER: 2000, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; 2000.example, type = A, class = IN
+
+;; ANSWER SECTION:
+2000.example. 5M IN A 10.0.0.0
+2000.example. 5M IN A 10.0.0.1
+2000.example. 5M IN A 10.0.0.2
+2000.example. 5M IN A 10.0.0.3
+2000.example. 5M IN A 10.0.0.4
+2000.example. 5M IN A 10.0.0.5
+2000.example. 5M IN A 10.0.0.6
+2000.example. 5M IN A 10.0.0.7
+2000.example. 5M IN A 10.0.0.8
+2000.example. 5M IN A 10.0.0.9
+2000.example. 5M IN A 10.0.0.10
+2000.example. 5M IN A 10.0.0.11
+2000.example. 5M IN A 10.0.0.12
+2000.example. 5M IN A 10.0.0.13
+2000.example. 5M IN A 10.0.0.14
+2000.example. 5M IN A 10.0.0.15
+2000.example. 5M IN A 10.0.0.16
+2000.example. 5M IN A 10.0.0.17
+2000.example. 5M IN A 10.0.0.18
+2000.example. 5M IN A 10.0.0.19
+2000.example. 5M IN A 10.0.0.20
+2000.example. 5M IN A 10.0.0.21
+2000.example. 5M IN A 10.0.0.22
+2000.example. 5M IN A 10.0.0.23
+2000.example. 5M IN A 10.0.0.24
+2000.example. 5M IN A 10.0.0.25
+2000.example. 5M IN A 10.0.0.26
+2000.example. 5M IN A 10.0.0.27
+2000.example. 5M IN A 10.0.0.28
+2000.example. 5M IN A 10.0.0.29
+2000.example. 5M IN A 10.0.0.30
+2000.example. 5M IN A 10.0.0.31
+2000.example. 5M IN A 10.0.0.32
+2000.example. 5M IN A 10.0.0.33
+2000.example. 5M IN A 10.0.0.34
+2000.example. 5M IN A 10.0.0.35
+2000.example. 5M IN A 10.0.0.36
+2000.example. 5M IN A 10.0.0.37
+2000.example. 5M IN A 10.0.0.38
+2000.example. 5M IN A 10.0.0.39
+2000.example. 5M IN A 10.0.0.40
+2000.example. 5M IN A 10.0.0.41
+2000.example. 5M IN A 10.0.0.42
+2000.example. 5M IN A 10.0.0.43
+2000.example. 5M IN A 10.0.0.44
+2000.example. 5M IN A 10.0.0.45
+2000.example. 5M IN A 10.0.0.46
+2000.example. 5M IN A 10.0.0.47
+2000.example. 5M IN A 10.0.0.48
+2000.example. 5M IN A 10.0.0.49
+2000.example. 5M IN A 10.0.0.50
+2000.example. 5M IN A 10.0.0.51
+2000.example. 5M IN A 10.0.0.52
+2000.example. 5M IN A 10.0.0.53
+2000.example. 5M IN A 10.0.0.54
+2000.example. 5M IN A 10.0.0.55
+2000.example. 5M IN A 10.0.0.56
+2000.example. 5M IN A 10.0.0.57
+2000.example. 5M IN A 10.0.0.58
+2000.example. 5M IN A 10.0.0.59
+2000.example. 5M IN A 10.0.0.60
+2000.example. 5M IN A 10.0.0.61
+2000.example. 5M IN A 10.0.0.62
+2000.example. 5M IN A 10.0.0.63
+2000.example. 5M IN A 10.0.0.64
+2000.example. 5M IN A 10.0.0.65
+2000.example. 5M IN A 10.0.0.66
+2000.example. 5M IN A 10.0.0.67
+2000.example. 5M IN A 10.0.0.68
+2000.example. 5M IN A 10.0.0.69
+2000.example. 5M IN A 10.0.0.70
+2000.example. 5M IN A 10.0.0.71
+2000.example. 5M IN A 10.0.0.72
+2000.example. 5M IN A 10.0.0.73
+2000.example. 5M IN A 10.0.0.74
+2000.example. 5M IN A 10.0.0.75
+2000.example. 5M IN A 10.0.0.76
+2000.example. 5M IN A 10.0.0.77
+2000.example. 5M IN A 10.0.0.78
+2000.example. 5M IN A 10.0.0.79
+2000.example. 5M IN A 10.0.0.80
+2000.example. 5M IN A 10.0.0.81
+2000.example. 5M IN A 10.0.0.82
+2000.example. 5M IN A 10.0.0.83
+2000.example. 5M IN A 10.0.0.84
+2000.example. 5M IN A 10.0.0.85
+2000.example. 5M IN A 10.0.0.86
+2000.example. 5M IN A 10.0.0.87
+2000.example. 5M IN A 10.0.0.88
+2000.example. 5M IN A 10.0.0.89
+2000.example. 5M IN A 10.0.0.90
+2000.example. 5M IN A 10.0.0.91
+2000.example. 5M IN A 10.0.0.92
+2000.example. 5M IN A 10.0.0.93
+2000.example. 5M IN A 10.0.0.94
+2000.example. 5M IN A 10.0.0.95
+2000.example. 5M IN A 10.0.0.96
+2000.example. 5M IN A 10.0.0.97
+2000.example. 5M IN A 10.0.0.98
+2000.example. 5M IN A 10.0.0.99
+2000.example. 5M IN A 10.0.0.100
+2000.example. 5M IN A 10.0.0.101
+2000.example. 5M IN A 10.0.0.102
+2000.example. 5M IN A 10.0.0.103
+2000.example. 5M IN A 10.0.0.104
+2000.example. 5M IN A 10.0.0.105
+2000.example. 5M IN A 10.0.0.106
+2000.example. 5M IN A 10.0.0.107
+2000.example. 5M IN A 10.0.0.108
+2000.example. 5M IN A 10.0.0.109
+2000.example. 5M IN A 10.0.0.110
+2000.example. 5M IN A 10.0.0.111
+2000.example. 5M IN A 10.0.0.112
+2000.example. 5M IN A 10.0.0.113
+2000.example. 5M IN A 10.0.0.114
+2000.example. 5M IN A 10.0.0.115
+2000.example. 5M IN A 10.0.0.116
+2000.example. 5M IN A 10.0.0.117
+2000.example. 5M IN A 10.0.0.118
+2000.example. 5M IN A 10.0.0.119
+2000.example. 5M IN A 10.0.0.120
+2000.example. 5M IN A 10.0.0.121
+2000.example. 5M IN A 10.0.0.122
+2000.example. 5M IN A 10.0.0.123
+2000.example. 5M IN A 10.0.0.124
+2000.example. 5M IN A 10.0.0.125
+2000.example. 5M IN A 10.0.0.126
+2000.example. 5M IN A 10.0.0.127
+2000.example. 5M IN A 10.0.0.128
+2000.example. 5M IN A 10.0.0.129
+2000.example. 5M IN A 10.0.0.130
+2000.example. 5M IN A 10.0.0.131
+2000.example. 5M IN A 10.0.0.132
+2000.example. 5M IN A 10.0.0.133
+2000.example. 5M IN A 10.0.0.134
+2000.example. 5M IN A 10.0.0.135
+2000.example. 5M IN A 10.0.0.136
+2000.example. 5M IN A 10.0.0.137
+2000.example. 5M IN A 10.0.0.138
+2000.example. 5M IN A 10.0.0.139
+2000.example. 5M IN A 10.0.0.140
+2000.example. 5M IN A 10.0.0.141
+2000.example. 5M IN A 10.0.0.142
+2000.example. 5M IN A 10.0.0.143
+2000.example. 5M IN A 10.0.0.144
+2000.example. 5M IN A 10.0.0.145
+2000.example. 5M IN A 10.0.0.146
+2000.example. 5M IN A 10.0.0.147
+2000.example. 5M IN A 10.0.0.148
+2000.example. 5M IN A 10.0.0.149
+2000.example. 5M IN A 10.0.0.150
+2000.example. 5M IN A 10.0.0.151
+2000.example. 5M IN A 10.0.0.152
+2000.example. 5M IN A 10.0.0.153
+2000.example. 5M IN A 10.0.0.154
+2000.example. 5M IN A 10.0.0.155
+2000.example. 5M IN A 10.0.0.156
+2000.example. 5M IN A 10.0.0.157
+2000.example. 5M IN A 10.0.0.158
+2000.example. 5M IN A 10.0.0.159
+2000.example. 5M IN A 10.0.0.160
+2000.example. 5M IN A 10.0.0.161
+2000.example. 5M IN A 10.0.0.162
+2000.example. 5M IN A 10.0.0.163
+2000.example. 5M IN A 10.0.0.164
+2000.example. 5M IN A 10.0.0.165
+2000.example. 5M IN A 10.0.0.166
+2000.example. 5M IN A 10.0.0.167
+2000.example. 5M IN A 10.0.0.168
+2000.example. 5M IN A 10.0.0.169
+2000.example. 5M IN A 10.0.0.170
+2000.example. 5M IN A 10.0.0.171
+2000.example. 5M IN A 10.0.0.172
+2000.example. 5M IN A 10.0.0.173
+2000.example. 5M IN A 10.0.0.174
+2000.example. 5M IN A 10.0.0.175
+2000.example. 5M IN A 10.0.0.176
+2000.example. 5M IN A 10.0.0.177
+2000.example. 5M IN A 10.0.0.178
+2000.example. 5M IN A 10.0.0.179
+2000.example. 5M IN A 10.0.0.180
+2000.example. 5M IN A 10.0.0.181
+2000.example. 5M IN A 10.0.0.182
+2000.example. 5M IN A 10.0.0.183
+2000.example. 5M IN A 10.0.0.184
+2000.example. 5M IN A 10.0.0.185
+2000.example. 5M IN A 10.0.0.186
+2000.example. 5M IN A 10.0.0.187
+2000.example. 5M IN A 10.0.0.188
+2000.example. 5M IN A 10.0.0.189
+2000.example. 5M IN A 10.0.0.190
+2000.example. 5M IN A 10.0.0.191
+2000.example. 5M IN A 10.0.0.192
+2000.example. 5M IN A 10.0.0.193
+2000.example. 5M IN A 10.0.0.194
+2000.example. 5M IN A 10.0.0.195
+2000.example. 5M IN A 10.0.0.196
+2000.example. 5M IN A 10.0.0.197
+2000.example. 5M IN A 10.0.0.198
+2000.example. 5M IN A 10.0.0.199
+2000.example. 5M IN A 10.0.0.200
+2000.example. 5M IN A 10.0.0.201
+2000.example. 5M IN A 10.0.0.202
+2000.example. 5M IN A 10.0.0.203
+2000.example. 5M IN A 10.0.0.204
+2000.example. 5M IN A 10.0.0.205
+2000.example. 5M IN A 10.0.0.206
+2000.example. 5M IN A 10.0.0.207
+2000.example. 5M IN A 10.0.0.208
+2000.example. 5M IN A 10.0.0.209
+2000.example. 5M IN A 10.0.0.210
+2000.example. 5M IN A 10.0.0.211
+2000.example. 5M IN A 10.0.0.212
+2000.example. 5M IN A 10.0.0.213
+2000.example. 5M IN A 10.0.0.214
+2000.example. 5M IN A 10.0.0.215
+2000.example. 5M IN A 10.0.0.216
+2000.example. 5M IN A 10.0.0.217
+2000.example. 5M IN A 10.0.0.218
+2000.example. 5M IN A 10.0.0.219
+2000.example. 5M IN A 10.0.0.220
+2000.example. 5M IN A 10.0.0.221
+2000.example. 5M IN A 10.0.0.222
+2000.example. 5M IN A 10.0.0.223
+2000.example. 5M IN A 10.0.0.224
+2000.example. 5M IN A 10.0.0.225
+2000.example. 5M IN A 10.0.0.226
+2000.example. 5M IN A 10.0.0.227
+2000.example. 5M IN A 10.0.0.228
+2000.example. 5M IN A 10.0.0.229
+2000.example. 5M IN A 10.0.0.230
+2000.example. 5M IN A 10.0.0.231
+2000.example. 5M IN A 10.0.0.232
+2000.example. 5M IN A 10.0.0.233
+2000.example. 5M IN A 10.0.0.234
+2000.example. 5M IN A 10.0.0.235
+2000.example. 5M IN A 10.0.0.236
+2000.example. 5M IN A 10.0.0.237
+2000.example. 5M IN A 10.0.0.238
+2000.example. 5M IN A 10.0.0.239
+2000.example. 5M IN A 10.0.0.240
+2000.example. 5M IN A 10.0.0.241
+2000.example. 5M IN A 10.0.0.242
+2000.example. 5M IN A 10.0.0.243
+2000.example. 5M IN A 10.0.0.244
+2000.example. 5M IN A 10.0.0.245
+2000.example. 5M IN A 10.0.0.246
+2000.example. 5M IN A 10.0.0.247
+2000.example. 5M IN A 10.0.0.248
+2000.example. 5M IN A 10.0.0.249
+2000.example. 5M IN A 10.0.0.250
+2000.example. 5M IN A 10.0.0.251
+2000.example. 5M IN A 10.0.0.252
+2000.example. 5M IN A 10.0.0.253
+2000.example. 5M IN A 10.0.0.254
+2000.example. 5M IN A 10.0.0.255
+2000.example. 5M IN A 10.0.1.0
+2000.example. 5M IN A 10.0.1.1
+2000.example. 5M IN A 10.0.1.2
+2000.example. 5M IN A 10.0.1.3
+2000.example. 5M IN A 10.0.1.4
+2000.example. 5M IN A 10.0.1.5
+2000.example. 5M IN A 10.0.1.6
+2000.example. 5M IN A 10.0.1.7
+2000.example. 5M IN A 10.0.1.8
+2000.example. 5M IN A 10.0.1.9
+2000.example. 5M IN A 10.0.1.10
+2000.example. 5M IN A 10.0.1.11
+2000.example. 5M IN A 10.0.1.12
+2000.example. 5M IN A 10.0.1.13
+2000.example. 5M IN A 10.0.1.14
+2000.example. 5M IN A 10.0.1.15
+2000.example. 5M IN A 10.0.1.16
+2000.example. 5M IN A 10.0.1.17
+2000.example. 5M IN A 10.0.1.18
+2000.example. 5M IN A 10.0.1.19
+2000.example. 5M IN A 10.0.1.20
+2000.example. 5M IN A 10.0.1.21
+2000.example. 5M IN A 10.0.1.22
+2000.example. 5M IN A 10.0.1.23
+2000.example. 5M IN A 10.0.1.24
+2000.example. 5M IN A 10.0.1.25
+2000.example. 5M IN A 10.0.1.26
+2000.example. 5M IN A 10.0.1.27
+2000.example. 5M IN A 10.0.1.28
+2000.example. 5M IN A 10.0.1.29
+2000.example. 5M IN A 10.0.1.30
+2000.example. 5M IN A 10.0.1.31
+2000.example. 5M IN A 10.0.1.32
+2000.example. 5M IN A 10.0.1.33
+2000.example. 5M IN A 10.0.1.34
+2000.example. 5M IN A 10.0.1.35
+2000.example. 5M IN A 10.0.1.36
+2000.example. 5M IN A 10.0.1.37
+2000.example. 5M IN A 10.0.1.38
+2000.example. 5M IN A 10.0.1.39
+2000.example. 5M IN A 10.0.1.40
+2000.example. 5M IN A 10.0.1.41
+2000.example. 5M IN A 10.0.1.42
+2000.example. 5M IN A 10.0.1.43
+2000.example. 5M IN A 10.0.1.44
+2000.example. 5M IN A 10.0.1.45
+2000.example. 5M IN A 10.0.1.46
+2000.example. 5M IN A 10.0.1.47
+2000.example. 5M IN A 10.0.1.48
+2000.example. 5M IN A 10.0.1.49
+2000.example. 5M IN A 10.0.1.50
+2000.example. 5M IN A 10.0.1.51
+2000.example. 5M IN A 10.0.1.52
+2000.example. 5M IN A 10.0.1.53
+2000.example. 5M IN A 10.0.1.54
+2000.example. 5M IN A 10.0.1.55
+2000.example. 5M IN A 10.0.1.56
+2000.example. 5M IN A 10.0.1.57
+2000.example. 5M IN A 10.0.1.58
+2000.example. 5M IN A 10.0.1.59
+2000.example. 5M IN A 10.0.1.60
+2000.example. 5M IN A 10.0.1.61
+2000.example. 5M IN A 10.0.1.62
+2000.example. 5M IN A 10.0.1.63
+2000.example. 5M IN A 10.0.1.64
+2000.example. 5M IN A 10.0.1.65
+2000.example. 5M IN A 10.0.1.66
+2000.example. 5M IN A 10.0.1.67
+2000.example. 5M IN A 10.0.1.68
+2000.example. 5M IN A 10.0.1.69
+2000.example. 5M IN A 10.0.1.70
+2000.example. 5M IN A 10.0.1.71
+2000.example. 5M IN A 10.0.1.72
+2000.example. 5M IN A 10.0.1.73
+2000.example. 5M IN A 10.0.1.74
+2000.example. 5M IN A 10.0.1.75
+2000.example. 5M IN A 10.0.1.76
+2000.example. 5M IN A 10.0.1.77
+2000.example. 5M IN A 10.0.1.78
+2000.example. 5M IN A 10.0.1.79
+2000.example. 5M IN A 10.0.1.80
+2000.example. 5M IN A 10.0.1.81
+2000.example. 5M IN A 10.0.1.82
+2000.example. 5M IN A 10.0.1.83
+2000.example. 5M IN A 10.0.1.84
+2000.example. 5M IN A 10.0.1.85
+2000.example. 5M IN A 10.0.1.86
+2000.example. 5M IN A 10.0.1.87
+2000.example. 5M IN A 10.0.1.88
+2000.example. 5M IN A 10.0.1.89
+2000.example. 5M IN A 10.0.1.90
+2000.example. 5M IN A 10.0.1.91
+2000.example. 5M IN A 10.0.1.92
+2000.example. 5M IN A 10.0.1.93
+2000.example. 5M IN A 10.0.1.94
+2000.example. 5M IN A 10.0.1.95
+2000.example. 5M IN A 10.0.1.96
+2000.example. 5M IN A 10.0.1.97
+2000.example. 5M IN A 10.0.1.98
+2000.example. 5M IN A 10.0.1.99
+2000.example. 5M IN A 10.0.1.100
+2000.example. 5M IN A 10.0.1.101
+2000.example. 5M IN A 10.0.1.102
+2000.example. 5M IN A 10.0.1.103
+2000.example. 5M IN A 10.0.1.104
+2000.example. 5M IN A 10.0.1.105
+2000.example. 5M IN A 10.0.1.106
+2000.example. 5M IN A 10.0.1.107
+2000.example. 5M IN A 10.0.1.108
+2000.example. 5M IN A 10.0.1.109
+2000.example. 5M IN A 10.0.1.110
+2000.example. 5M IN A 10.0.1.111
+2000.example. 5M IN A 10.0.1.112
+2000.example. 5M IN A 10.0.1.113
+2000.example. 5M IN A 10.0.1.114
+2000.example. 5M IN A 10.0.1.115
+2000.example. 5M IN A 10.0.1.116
+2000.example. 5M IN A 10.0.1.117
+2000.example. 5M IN A 10.0.1.118
+2000.example. 5M IN A 10.0.1.119
+2000.example. 5M IN A 10.0.1.120
+2000.example. 5M IN A 10.0.1.121
+2000.example. 5M IN A 10.0.1.122
+2000.example. 5M IN A 10.0.1.123
+2000.example. 5M IN A 10.0.1.124
+2000.example. 5M IN A 10.0.1.125
+2000.example. 5M IN A 10.0.1.126
+2000.example. 5M IN A 10.0.1.127
+2000.example. 5M IN A 10.0.1.128
+2000.example. 5M IN A 10.0.1.129
+2000.example. 5M IN A 10.0.1.130
+2000.example. 5M IN A 10.0.1.131
+2000.example. 5M IN A 10.0.1.132
+2000.example. 5M IN A 10.0.1.133
+2000.example. 5M IN A 10.0.1.134
+2000.example. 5M IN A 10.0.1.135
+2000.example. 5M IN A 10.0.1.136
+2000.example. 5M IN A 10.0.1.137
+2000.example. 5M IN A 10.0.1.138
+2000.example. 5M IN A 10.0.1.139
+2000.example. 5M IN A 10.0.1.140
+2000.example. 5M IN A 10.0.1.141
+2000.example. 5M IN A 10.0.1.142
+2000.example. 5M IN A 10.0.1.143
+2000.example. 5M IN A 10.0.1.144
+2000.example. 5M IN A 10.0.1.145
+2000.example. 5M IN A 10.0.1.146
+2000.example. 5M IN A 10.0.1.147
+2000.example. 5M IN A 10.0.1.148
+2000.example. 5M IN A 10.0.1.149
+2000.example. 5M IN A 10.0.1.150
+2000.example. 5M IN A 10.0.1.151
+2000.example. 5M IN A 10.0.1.152
+2000.example. 5M IN A 10.0.1.153
+2000.example. 5M IN A 10.0.1.154
+2000.example. 5M IN A 10.0.1.155
+2000.example. 5M IN A 10.0.1.156
+2000.example. 5M IN A 10.0.1.157
+2000.example. 5M IN A 10.0.1.158
+2000.example. 5M IN A 10.0.1.159
+2000.example. 5M IN A 10.0.1.160
+2000.example. 5M IN A 10.0.1.161
+2000.example. 5M IN A 10.0.1.162
+2000.example. 5M IN A 10.0.1.163
+2000.example. 5M IN A 10.0.1.164
+2000.example. 5M IN A 10.0.1.165
+2000.example. 5M IN A 10.0.1.166
+2000.example. 5M IN A 10.0.1.167
+2000.example. 5M IN A 10.0.1.168
+2000.example. 5M IN A 10.0.1.169
+2000.example. 5M IN A 10.0.1.170
+2000.example. 5M IN A 10.0.1.171
+2000.example. 5M IN A 10.0.1.172
+2000.example. 5M IN A 10.0.1.173
+2000.example. 5M IN A 10.0.1.174
+2000.example. 5M IN A 10.0.1.175
+2000.example. 5M IN A 10.0.1.176
+2000.example. 5M IN A 10.0.1.177
+2000.example. 5M IN A 10.0.1.178
+2000.example. 5M IN A 10.0.1.179
+2000.example. 5M IN A 10.0.1.180
+2000.example. 5M IN A 10.0.1.181
+2000.example. 5M IN A 10.0.1.182
+2000.example. 5M IN A 10.0.1.183
+2000.example. 5M IN A 10.0.1.184
+2000.example. 5M IN A 10.0.1.185
+2000.example. 5M IN A 10.0.1.186
+2000.example. 5M IN A 10.0.1.187
+2000.example. 5M IN A 10.0.1.188
+2000.example. 5M IN A 10.0.1.189
+2000.example. 5M IN A 10.0.1.190
+2000.example. 5M IN A 10.0.1.191
+2000.example. 5M IN A 10.0.1.192
+2000.example. 5M IN A 10.0.1.193
+2000.example. 5M IN A 10.0.1.194
+2000.example. 5M IN A 10.0.1.195
+2000.example. 5M IN A 10.0.1.196
+2000.example. 5M IN A 10.0.1.197
+2000.example. 5M IN A 10.0.1.198
+2000.example. 5M IN A 10.0.1.199
+2000.example. 5M IN A 10.0.1.200
+2000.example. 5M IN A 10.0.1.201
+2000.example. 5M IN A 10.0.1.202
+2000.example. 5M IN A 10.0.1.203
+2000.example. 5M IN A 10.0.1.204
+2000.example. 5M IN A 10.0.1.205
+2000.example. 5M IN A 10.0.1.206
+2000.example. 5M IN A 10.0.1.207
+2000.example. 5M IN A 10.0.1.208
+2000.example. 5M IN A 10.0.1.209
+2000.example. 5M IN A 10.0.1.210
+2000.example. 5M IN A 10.0.1.211
+2000.example. 5M IN A 10.0.1.212
+2000.example. 5M IN A 10.0.1.213
+2000.example. 5M IN A 10.0.1.214
+2000.example. 5M IN A 10.0.1.215
+2000.example. 5M IN A 10.0.1.216
+2000.example. 5M IN A 10.0.1.217
+2000.example. 5M IN A 10.0.1.218
+2000.example. 5M IN A 10.0.1.219
+2000.example. 5M IN A 10.0.1.220
+2000.example. 5M IN A 10.0.1.221
+2000.example. 5M IN A 10.0.1.222
+2000.example. 5M IN A 10.0.1.223
+2000.example. 5M IN A 10.0.1.224
+2000.example. 5M IN A 10.0.1.225
+2000.example. 5M IN A 10.0.1.226
+2000.example. 5M IN A 10.0.1.227
+2000.example. 5M IN A 10.0.1.228
+2000.example. 5M IN A 10.0.1.229
+2000.example. 5M IN A 10.0.1.230
+2000.example. 5M IN A 10.0.1.231
+2000.example. 5M IN A 10.0.1.232
+2000.example. 5M IN A 10.0.1.233
+2000.example. 5M IN A 10.0.1.234
+2000.example. 5M IN A 10.0.1.235
+2000.example. 5M IN A 10.0.1.236
+2000.example. 5M IN A 10.0.1.237
+2000.example. 5M IN A 10.0.1.238
+2000.example. 5M IN A 10.0.1.239
+2000.example. 5M IN A 10.0.1.240
+2000.example. 5M IN A 10.0.1.241
+2000.example. 5M IN A 10.0.1.242
+2000.example. 5M IN A 10.0.1.243
+2000.example. 5M IN A 10.0.1.244
+2000.example. 5M IN A 10.0.1.245
+2000.example. 5M IN A 10.0.1.246
+2000.example. 5M IN A 10.0.1.247
+2000.example. 5M IN A 10.0.1.248
+2000.example. 5M IN A 10.0.1.249
+2000.example. 5M IN A 10.0.1.250
+2000.example. 5M IN A 10.0.1.251
+2000.example. 5M IN A 10.0.1.252
+2000.example. 5M IN A 10.0.1.253
+2000.example. 5M IN A 10.0.1.254
+2000.example. 5M IN A 10.0.1.255
+2000.example. 5M IN A 10.0.2.0
+2000.example. 5M IN A 10.0.2.1
+2000.example. 5M IN A 10.0.2.2
+2000.example. 5M IN A 10.0.2.3
+2000.example. 5M IN A 10.0.2.4
+2000.example. 5M IN A 10.0.2.5
+2000.example. 5M IN A 10.0.2.6
+2000.example. 5M IN A 10.0.2.7
+2000.example. 5M IN A 10.0.2.8
+2000.example. 5M IN A 10.0.2.9
+2000.example. 5M IN A 10.0.2.10
+2000.example. 5M IN A 10.0.2.11
+2000.example. 5M IN A 10.0.2.12
+2000.example. 5M IN A 10.0.2.13
+2000.example. 5M IN A 10.0.2.14
+2000.example. 5M IN A 10.0.2.15
+2000.example. 5M IN A 10.0.2.16
+2000.example. 5M IN A 10.0.2.17
+2000.example. 5M IN A 10.0.2.18
+2000.example. 5M IN A 10.0.2.19
+2000.example. 5M IN A 10.0.2.20
+2000.example. 5M IN A 10.0.2.21
+2000.example. 5M IN A 10.0.2.22
+2000.example. 5M IN A 10.0.2.23
+2000.example. 5M IN A 10.0.2.24
+2000.example. 5M IN A 10.0.2.25
+2000.example. 5M IN A 10.0.2.26
+2000.example. 5M IN A 10.0.2.27
+2000.example. 5M IN A 10.0.2.28
+2000.example. 5M IN A 10.0.2.29
+2000.example. 5M IN A 10.0.2.30
+2000.example. 5M IN A 10.0.2.31
+2000.example. 5M IN A 10.0.2.32
+2000.example. 5M IN A 10.0.2.33
+2000.example. 5M IN A 10.0.2.34
+2000.example. 5M IN A 10.0.2.35
+2000.example. 5M IN A 10.0.2.36
+2000.example. 5M IN A 10.0.2.37
+2000.example. 5M IN A 10.0.2.38
+2000.example. 5M IN A 10.0.2.39
+2000.example. 5M IN A 10.0.2.40
+2000.example. 5M IN A 10.0.2.41
+2000.example. 5M IN A 10.0.2.42
+2000.example. 5M IN A 10.0.2.43
+2000.example. 5M IN A 10.0.2.44
+2000.example. 5M IN A 10.0.2.45
+2000.example. 5M IN A 10.0.2.46
+2000.example. 5M IN A 10.0.2.47
+2000.example. 5M IN A 10.0.2.48
+2000.example. 5M IN A 10.0.2.49
+2000.example. 5M IN A 10.0.2.50
+2000.example. 5M IN A 10.0.2.51
+2000.example. 5M IN A 10.0.2.52
+2000.example. 5M IN A 10.0.2.53
+2000.example. 5M IN A 10.0.2.54
+2000.example. 5M IN A 10.0.2.55
+2000.example. 5M IN A 10.0.2.56
+2000.example. 5M IN A 10.0.2.57
+2000.example. 5M IN A 10.0.2.58
+2000.example. 5M IN A 10.0.2.59
+2000.example. 5M IN A 10.0.2.60
+2000.example. 5M IN A 10.0.2.61
+2000.example. 5M IN A 10.0.2.62
+2000.example. 5M IN A 10.0.2.63
+2000.example. 5M IN A 10.0.2.64
+2000.example. 5M IN A 10.0.2.65
+2000.example. 5M IN A 10.0.2.66
+2000.example. 5M IN A 10.0.2.67
+2000.example. 5M IN A 10.0.2.68
+2000.example. 5M IN A 10.0.2.69
+2000.example. 5M IN A 10.0.2.70
+2000.example. 5M IN A 10.0.2.71
+2000.example. 5M IN A 10.0.2.72
+2000.example. 5M IN A 10.0.2.73
+2000.example. 5M IN A 10.0.2.74
+2000.example. 5M IN A 10.0.2.75
+2000.example. 5M IN A 10.0.2.76
+2000.example. 5M IN A 10.0.2.77
+2000.example. 5M IN A 10.0.2.78
+2000.example. 5M IN A 10.0.2.79
+2000.example. 5M IN A 10.0.2.80
+2000.example. 5M IN A 10.0.2.81
+2000.example. 5M IN A 10.0.2.82
+2000.example. 5M IN A 10.0.2.83
+2000.example. 5M IN A 10.0.2.84
+2000.example. 5M IN A 10.0.2.85
+2000.example. 5M IN A 10.0.2.86
+2000.example. 5M IN A 10.0.2.87
+2000.example. 5M IN A 10.0.2.88
+2000.example. 5M IN A 10.0.2.89
+2000.example. 5M IN A 10.0.2.90
+2000.example. 5M IN A 10.0.2.91
+2000.example. 5M IN A 10.0.2.92
+2000.example. 5M IN A 10.0.2.93
+2000.example. 5M IN A 10.0.2.94
+2000.example. 5M IN A 10.0.2.95
+2000.example. 5M IN A 10.0.2.96
+2000.example. 5M IN A 10.0.2.97
+2000.example. 5M IN A 10.0.2.98
+2000.example. 5M IN A 10.0.2.99
+2000.example. 5M IN A 10.0.2.100
+2000.example. 5M IN A 10.0.2.101
+2000.example. 5M IN A 10.0.2.102
+2000.example. 5M IN A 10.0.2.103
+2000.example. 5M IN A 10.0.2.104
+2000.example. 5M IN A 10.0.2.105
+2000.example. 5M IN A 10.0.2.106
+2000.example. 5M IN A 10.0.2.107
+2000.example. 5M IN A 10.0.2.108
+2000.example. 5M IN A 10.0.2.109
+2000.example. 5M IN A 10.0.2.110
+2000.example. 5M IN A 10.0.2.111
+2000.example. 5M IN A 10.0.2.112
+2000.example. 5M IN A 10.0.2.113
+2000.example. 5M IN A 10.0.2.114
+2000.example. 5M IN A 10.0.2.115
+2000.example. 5M IN A 10.0.2.116
+2000.example. 5M IN A 10.0.2.117
+2000.example. 5M IN A 10.0.2.118
+2000.example. 5M IN A 10.0.2.119
+2000.example. 5M IN A 10.0.2.120
+2000.example. 5M IN A 10.0.2.121
+2000.example. 5M IN A 10.0.2.122
+2000.example. 5M IN A 10.0.2.123
+2000.example. 5M IN A 10.0.2.124
+2000.example. 5M IN A 10.0.2.125
+2000.example. 5M IN A 10.0.2.126
+2000.example. 5M IN A 10.0.2.127
+2000.example. 5M IN A 10.0.2.128
+2000.example. 5M IN A 10.0.2.129
+2000.example. 5M IN A 10.0.2.130
+2000.example. 5M IN A 10.0.2.131
+2000.example. 5M IN A 10.0.2.132
+2000.example. 5M IN A 10.0.2.133
+2000.example. 5M IN A 10.0.2.134
+2000.example. 5M IN A 10.0.2.135
+2000.example. 5M IN A 10.0.2.136
+2000.example. 5M IN A 10.0.2.137
+2000.example. 5M IN A 10.0.2.138
+2000.example. 5M IN A 10.0.2.139
+2000.example. 5M IN A 10.0.2.140
+2000.example. 5M IN A 10.0.2.141
+2000.example. 5M IN A 10.0.2.142
+2000.example. 5M IN A 10.0.2.143
+2000.example. 5M IN A 10.0.2.144
+2000.example. 5M IN A 10.0.2.145
+2000.example. 5M IN A 10.0.2.146
+2000.example. 5M IN A 10.0.2.147
+2000.example. 5M IN A 10.0.2.148
+2000.example. 5M IN A 10.0.2.149
+2000.example. 5M IN A 10.0.2.150
+2000.example. 5M IN A 10.0.2.151
+2000.example. 5M IN A 10.0.2.152
+2000.example. 5M IN A 10.0.2.153
+2000.example. 5M IN A 10.0.2.154
+2000.example. 5M IN A 10.0.2.155
+2000.example. 5M IN A 10.0.2.156
+2000.example. 5M IN A 10.0.2.157
+2000.example. 5M IN A 10.0.2.158
+2000.example. 5M IN A 10.0.2.159
+2000.example. 5M IN A 10.0.2.160
+2000.example. 5M IN A 10.0.2.161
+2000.example. 5M IN A 10.0.2.162
+2000.example. 5M IN A 10.0.2.163
+2000.example. 5M IN A 10.0.2.164
+2000.example. 5M IN A 10.0.2.165
+2000.example. 5M IN A 10.0.2.166
+2000.example. 5M IN A 10.0.2.167
+2000.example. 5M IN A 10.0.2.168
+2000.example. 5M IN A 10.0.2.169
+2000.example. 5M IN A 10.0.2.170
+2000.example. 5M IN A 10.0.2.171
+2000.example. 5M IN A 10.0.2.172
+2000.example. 5M IN A 10.0.2.173
+2000.example. 5M IN A 10.0.2.174
+2000.example. 5M IN A 10.0.2.175
+2000.example. 5M IN A 10.0.2.176
+2000.example. 5M IN A 10.0.2.177
+2000.example. 5M IN A 10.0.2.178
+2000.example. 5M IN A 10.0.2.179
+2000.example. 5M IN A 10.0.2.180
+2000.example. 5M IN A 10.0.2.181
+2000.example. 5M IN A 10.0.2.182
+2000.example. 5M IN A 10.0.2.183
+2000.example. 5M IN A 10.0.2.184
+2000.example. 5M IN A 10.0.2.185
+2000.example. 5M IN A 10.0.2.186
+2000.example. 5M IN A 10.0.2.187
+2000.example. 5M IN A 10.0.2.188
+2000.example. 5M IN A 10.0.2.189
+2000.example. 5M IN A 10.0.2.190
+2000.example. 5M IN A 10.0.2.191
+2000.example. 5M IN A 10.0.2.192
+2000.example. 5M IN A 10.0.2.193
+2000.example. 5M IN A 10.0.2.194
+2000.example. 5M IN A 10.0.2.195
+2000.example. 5M IN A 10.0.2.196
+2000.example. 5M IN A 10.0.2.197
+2000.example. 5M IN A 10.0.2.198
+2000.example. 5M IN A 10.0.2.199
+2000.example. 5M IN A 10.0.2.200
+2000.example. 5M IN A 10.0.2.201
+2000.example. 5M IN A 10.0.2.202
+2000.example. 5M IN A 10.0.2.203
+2000.example. 5M IN A 10.0.2.204
+2000.example. 5M IN A 10.0.2.205
+2000.example. 5M IN A 10.0.2.206
+2000.example. 5M IN A 10.0.2.207
+2000.example. 5M IN A 10.0.2.208
+2000.example. 5M IN A 10.0.2.209
+2000.example. 5M IN A 10.0.2.210
+2000.example. 5M IN A 10.0.2.211
+2000.example. 5M IN A 10.0.2.212
+2000.example. 5M IN A 10.0.2.213
+2000.example. 5M IN A 10.0.2.214
+2000.example. 5M IN A 10.0.2.215
+2000.example. 5M IN A 10.0.2.216
+2000.example. 5M IN A 10.0.2.217
+2000.example. 5M IN A 10.0.2.218
+2000.example. 5M IN A 10.0.2.219
+2000.example. 5M IN A 10.0.2.220
+2000.example. 5M IN A 10.0.2.221
+2000.example. 5M IN A 10.0.2.222
+2000.example. 5M IN A 10.0.2.223
+2000.example. 5M IN A 10.0.2.224
+2000.example. 5M IN A 10.0.2.225
+2000.example. 5M IN A 10.0.2.226
+2000.example. 5M IN A 10.0.2.227
+2000.example. 5M IN A 10.0.2.228
+2000.example. 5M IN A 10.0.2.229
+2000.example. 5M IN A 10.0.2.230
+2000.example. 5M IN A 10.0.2.231
+2000.example. 5M IN A 10.0.2.232
+2000.example. 5M IN A 10.0.2.233
+2000.example. 5M IN A 10.0.2.234
+2000.example. 5M IN A 10.0.2.235
+2000.example. 5M IN A 10.0.2.236
+2000.example. 5M IN A 10.0.2.237
+2000.example. 5M IN A 10.0.2.238
+2000.example. 5M IN A 10.0.2.239
+2000.example. 5M IN A 10.0.2.240
+2000.example. 5M IN A 10.0.2.241
+2000.example. 5M IN A 10.0.2.242
+2000.example. 5M IN A 10.0.2.243
+2000.example. 5M IN A 10.0.2.244
+2000.example. 5M IN A 10.0.2.245
+2000.example. 5M IN A 10.0.2.246
+2000.example. 5M IN A 10.0.2.247
+2000.example. 5M IN A 10.0.2.248
+2000.example. 5M IN A 10.0.2.249
+2000.example. 5M IN A 10.0.2.250
+2000.example. 5M IN A 10.0.2.251
+2000.example. 5M IN A 10.0.2.252
+2000.example. 5M IN A 10.0.2.253
+2000.example. 5M IN A 10.0.2.254
+2000.example. 5M IN A 10.0.2.255
+2000.example. 5M IN A 10.0.3.0
+2000.example. 5M IN A 10.0.3.1
+2000.example. 5M IN A 10.0.3.2
+2000.example. 5M IN A 10.0.3.3
+2000.example. 5M IN A 10.0.3.4
+2000.example. 5M IN A 10.0.3.5
+2000.example. 5M IN A 10.0.3.6
+2000.example. 5M IN A 10.0.3.7
+2000.example. 5M IN A 10.0.3.8
+2000.example. 5M IN A 10.0.3.9
+2000.example. 5M IN A 10.0.3.10
+2000.example. 5M IN A 10.0.3.11
+2000.example. 5M IN A 10.0.3.12
+2000.example. 5M IN A 10.0.3.13
+2000.example. 5M IN A 10.0.3.14
+2000.example. 5M IN A 10.0.3.15
+2000.example. 5M IN A 10.0.3.16
+2000.example. 5M IN A 10.0.3.17
+2000.example. 5M IN A 10.0.3.18
+2000.example. 5M IN A 10.0.3.19
+2000.example. 5M IN A 10.0.3.20
+2000.example. 5M IN A 10.0.3.21
+2000.example. 5M IN A 10.0.3.22
+2000.example. 5M IN A 10.0.3.23
+2000.example. 5M IN A 10.0.3.24
+2000.example. 5M IN A 10.0.3.25
+2000.example. 5M IN A 10.0.3.26
+2000.example. 5M IN A 10.0.3.27
+2000.example. 5M IN A 10.0.3.28
+2000.example. 5M IN A 10.0.3.29
+2000.example. 5M IN A 10.0.3.30
+2000.example. 5M IN A 10.0.3.31
+2000.example. 5M IN A 10.0.3.32
+2000.example. 5M IN A 10.0.3.33
+2000.example. 5M IN A 10.0.3.34
+2000.example. 5M IN A 10.0.3.35
+2000.example. 5M IN A 10.0.3.36
+2000.example. 5M IN A 10.0.3.37
+2000.example. 5M IN A 10.0.3.38
+2000.example. 5M IN A 10.0.3.39
+2000.example. 5M IN A 10.0.3.40
+2000.example. 5M IN A 10.0.3.41
+2000.example. 5M IN A 10.0.3.42
+2000.example. 5M IN A 10.0.3.43
+2000.example. 5M IN A 10.0.3.44
+2000.example. 5M IN A 10.0.3.45
+2000.example. 5M IN A 10.0.3.46
+2000.example. 5M IN A 10.0.3.47
+2000.example. 5M IN A 10.0.3.48
+2000.example. 5M IN A 10.0.3.49
+2000.example. 5M IN A 10.0.3.50
+2000.example. 5M IN A 10.0.3.51
+2000.example. 5M IN A 10.0.3.52
+2000.example. 5M IN A 10.0.3.53
+2000.example. 5M IN A 10.0.3.54
+2000.example. 5M IN A 10.0.3.55
+2000.example. 5M IN A 10.0.3.56
+2000.example. 5M IN A 10.0.3.57
+2000.example. 5M IN A 10.0.3.58
+2000.example. 5M IN A 10.0.3.59
+2000.example. 5M IN A 10.0.3.60
+2000.example. 5M IN A 10.0.3.61
+2000.example. 5M IN A 10.0.3.62
+2000.example. 5M IN A 10.0.3.63
+2000.example. 5M IN A 10.0.3.64
+2000.example. 5M IN A 10.0.3.65
+2000.example. 5M IN A 10.0.3.66
+2000.example. 5M IN A 10.0.3.67
+2000.example. 5M IN A 10.0.3.68
+2000.example. 5M IN A 10.0.3.69
+2000.example. 5M IN A 10.0.3.70
+2000.example. 5M IN A 10.0.3.71
+2000.example. 5M IN A 10.0.3.72
+2000.example. 5M IN A 10.0.3.73
+2000.example. 5M IN A 10.0.3.74
+2000.example. 5M IN A 10.0.3.75
+2000.example. 5M IN A 10.0.3.76
+2000.example. 5M IN A 10.0.3.77
+2000.example. 5M IN A 10.0.3.78
+2000.example. 5M IN A 10.0.3.79
+2000.example. 5M IN A 10.0.3.80
+2000.example. 5M IN A 10.0.3.81
+2000.example. 5M IN A 10.0.3.82
+2000.example. 5M IN A 10.0.3.83
+2000.example. 5M IN A 10.0.3.84
+2000.example. 5M IN A 10.0.3.85
+2000.example. 5M IN A 10.0.3.86
+2000.example. 5M IN A 10.0.3.87
+2000.example. 5M IN A 10.0.3.88
+2000.example. 5M IN A 10.0.3.89
+2000.example. 5M IN A 10.0.3.90
+2000.example. 5M IN A 10.0.3.91
+2000.example. 5M IN A 10.0.3.92
+2000.example. 5M IN A 10.0.3.93
+2000.example. 5M IN A 10.0.3.94
+2000.example. 5M IN A 10.0.3.95
+2000.example. 5M IN A 10.0.3.96
+2000.example. 5M IN A 10.0.3.97
+2000.example. 5M IN A 10.0.3.98
+2000.example. 5M IN A 10.0.3.99
+2000.example. 5M IN A 10.0.3.100
+2000.example. 5M IN A 10.0.3.101
+2000.example. 5M IN A 10.0.3.102
+2000.example. 5M IN A 10.0.3.103
+2000.example. 5M IN A 10.0.3.104
+2000.example. 5M IN A 10.0.3.105
+2000.example. 5M IN A 10.0.3.106
+2000.example. 5M IN A 10.0.3.107
+2000.example. 5M IN A 10.0.3.108
+2000.example. 5M IN A 10.0.3.109
+2000.example. 5M IN A 10.0.3.110
+2000.example. 5M IN A 10.0.3.111
+2000.example. 5M IN A 10.0.3.112
+2000.example. 5M IN A 10.0.3.113
+2000.example. 5M IN A 10.0.3.114
+2000.example. 5M IN A 10.0.3.115
+2000.example. 5M IN A 10.0.3.116
+2000.example. 5M IN A 10.0.3.117
+2000.example. 5M IN A 10.0.3.118
+2000.example. 5M IN A 10.0.3.119
+2000.example. 5M IN A 10.0.3.120
+2000.example. 5M IN A 10.0.3.121
+2000.example. 5M IN A 10.0.3.122
+2000.example. 5M IN A 10.0.3.123
+2000.example. 5M IN A 10.0.3.124
+2000.example. 5M IN A 10.0.3.125
+2000.example. 5M IN A 10.0.3.126
+2000.example. 5M IN A 10.0.3.127
+2000.example. 5M IN A 10.0.3.128
+2000.example. 5M IN A 10.0.3.129
+2000.example. 5M IN A 10.0.3.130
+2000.example. 5M IN A 10.0.3.131
+2000.example. 5M IN A 10.0.3.132
+2000.example. 5M IN A 10.0.3.133
+2000.example. 5M IN A 10.0.3.134
+2000.example. 5M IN A 10.0.3.135
+2000.example. 5M IN A 10.0.3.136
+2000.example. 5M IN A 10.0.3.137
+2000.example. 5M IN A 10.0.3.138
+2000.example. 5M IN A 10.0.3.139
+2000.example. 5M IN A 10.0.3.140
+2000.example. 5M IN A 10.0.3.141
+2000.example. 5M IN A 10.0.3.142
+2000.example. 5M IN A 10.0.3.143
+2000.example. 5M IN A 10.0.3.144
+2000.example. 5M IN A 10.0.3.145
+2000.example. 5M IN A 10.0.3.146
+2000.example. 5M IN A 10.0.3.147
+2000.example. 5M IN A 10.0.3.148
+2000.example. 5M IN A 10.0.3.149
+2000.example. 5M IN A 10.0.3.150
+2000.example. 5M IN A 10.0.3.151
+2000.example. 5M IN A 10.0.3.152
+2000.example. 5M IN A 10.0.3.153
+2000.example. 5M IN A 10.0.3.154
+2000.example. 5M IN A 10.0.3.155
+2000.example. 5M IN A 10.0.3.156
+2000.example. 5M IN A 10.0.3.157
+2000.example. 5M IN A 10.0.3.158
+2000.example. 5M IN A 10.0.3.159
+2000.example. 5M IN A 10.0.3.160
+2000.example. 5M IN A 10.0.3.161
+2000.example. 5M IN A 10.0.3.162
+2000.example. 5M IN A 10.0.3.163
+2000.example. 5M IN A 10.0.3.164
+2000.example. 5M IN A 10.0.3.165
+2000.example. 5M IN A 10.0.3.166
+2000.example. 5M IN A 10.0.3.167
+2000.example. 5M IN A 10.0.3.168
+2000.example. 5M IN A 10.0.3.169
+2000.example. 5M IN A 10.0.3.170
+2000.example. 5M IN A 10.0.3.171
+2000.example. 5M IN A 10.0.3.172
+2000.example. 5M IN A 10.0.3.173
+2000.example. 5M IN A 10.0.3.174
+2000.example. 5M IN A 10.0.3.175
+2000.example. 5M IN A 10.0.3.176
+2000.example. 5M IN A 10.0.3.177
+2000.example. 5M IN A 10.0.3.178
+2000.example. 5M IN A 10.0.3.179
+2000.example. 5M IN A 10.0.3.180
+2000.example. 5M IN A 10.0.3.181
+2000.example. 5M IN A 10.0.3.182
+2000.example. 5M IN A 10.0.3.183
+2000.example. 5M IN A 10.0.3.184
+2000.example. 5M IN A 10.0.3.185
+2000.example. 5M IN A 10.0.3.186
+2000.example. 5M IN A 10.0.3.187
+2000.example. 5M IN A 10.0.3.188
+2000.example. 5M IN A 10.0.3.189
+2000.example. 5M IN A 10.0.3.190
+2000.example. 5M IN A 10.0.3.191
+2000.example. 5M IN A 10.0.3.192
+2000.example. 5M IN A 10.0.3.193
+2000.example. 5M IN A 10.0.3.194
+2000.example. 5M IN A 10.0.3.195
+2000.example. 5M IN A 10.0.3.196
+2000.example. 5M IN A 10.0.3.197
+2000.example. 5M IN A 10.0.3.198
+2000.example. 5M IN A 10.0.3.199
+2000.example. 5M IN A 10.0.3.200
+2000.example. 5M IN A 10.0.3.201
+2000.example. 5M IN A 10.0.3.202
+2000.example. 5M IN A 10.0.3.203
+2000.example. 5M IN A 10.0.3.204
+2000.example. 5M IN A 10.0.3.205
+2000.example. 5M IN A 10.0.3.206
+2000.example. 5M IN A 10.0.3.207
+2000.example. 5M IN A 10.0.3.208
+2000.example. 5M IN A 10.0.3.209
+2000.example. 5M IN A 10.0.3.210
+2000.example. 5M IN A 10.0.3.211
+2000.example. 5M IN A 10.0.3.212
+2000.example. 5M IN A 10.0.3.213
+2000.example. 5M IN A 10.0.3.214
+2000.example. 5M IN A 10.0.3.215
+2000.example. 5M IN A 10.0.3.216
+2000.example. 5M IN A 10.0.3.217
+2000.example. 5M IN A 10.0.3.218
+2000.example. 5M IN A 10.0.3.219
+2000.example. 5M IN A 10.0.3.220
+2000.example. 5M IN A 10.0.3.221
+2000.example. 5M IN A 10.0.3.222
+2000.example. 5M IN A 10.0.3.223
+2000.example. 5M IN A 10.0.3.224
+2000.example. 5M IN A 10.0.3.225
+2000.example. 5M IN A 10.0.3.226
+2000.example. 5M IN A 10.0.3.227
+2000.example. 5M IN A 10.0.3.228
+2000.example. 5M IN A 10.0.3.229
+2000.example. 5M IN A 10.0.3.230
+2000.example. 5M IN A 10.0.3.231
+2000.example. 5M IN A 10.0.3.232
+2000.example. 5M IN A 10.0.3.233
+2000.example. 5M IN A 10.0.3.234
+2000.example. 5M IN A 10.0.3.235
+2000.example. 5M IN A 10.0.3.236
+2000.example. 5M IN A 10.0.3.237
+2000.example. 5M IN A 10.0.3.238
+2000.example. 5M IN A 10.0.3.239
+2000.example. 5M IN A 10.0.3.240
+2000.example. 5M IN A 10.0.3.241
+2000.example. 5M IN A 10.0.3.242
+2000.example. 5M IN A 10.0.3.243
+2000.example. 5M IN A 10.0.3.244
+2000.example. 5M IN A 10.0.3.245
+2000.example. 5M IN A 10.0.3.246
+2000.example. 5M IN A 10.0.3.247
+2000.example. 5M IN A 10.0.3.248
+2000.example. 5M IN A 10.0.3.249
+2000.example. 5M IN A 10.0.3.250
+2000.example. 5M IN A 10.0.3.251
+2000.example. 5M IN A 10.0.3.252
+2000.example. 5M IN A 10.0.3.253
+2000.example. 5M IN A 10.0.3.254
+2000.example. 5M IN A 10.0.3.255
+2000.example. 5M IN A 10.0.4.0
+2000.example. 5M IN A 10.0.4.1
+2000.example. 5M IN A 10.0.4.2
+2000.example. 5M IN A 10.0.4.3
+2000.example. 5M IN A 10.0.4.4
+2000.example. 5M IN A 10.0.4.5
+2000.example. 5M IN A 10.0.4.6
+2000.example. 5M IN A 10.0.4.7
+2000.example. 5M IN A 10.0.4.8
+2000.example. 5M IN A 10.0.4.9
+2000.example. 5M IN A 10.0.4.10
+2000.example. 5M IN A 10.0.4.11
+2000.example. 5M IN A 10.0.4.12
+2000.example. 5M IN A 10.0.4.13
+2000.example. 5M IN A 10.0.4.14
+2000.example. 5M IN A 10.0.4.15
+2000.example. 5M IN A 10.0.4.16
+2000.example. 5M IN A 10.0.4.17
+2000.example. 5M IN A 10.0.4.18
+2000.example. 5M IN A 10.0.4.19
+2000.example. 5M IN A 10.0.4.20
+2000.example. 5M IN A 10.0.4.21
+2000.example. 5M IN A 10.0.4.22
+2000.example. 5M IN A 10.0.4.23
+2000.example. 5M IN A 10.0.4.24
+2000.example. 5M IN A 10.0.4.25
+2000.example. 5M IN A 10.0.4.26
+2000.example. 5M IN A 10.0.4.27
+2000.example. 5M IN A 10.0.4.28
+2000.example. 5M IN A 10.0.4.29
+2000.example. 5M IN A 10.0.4.30
+2000.example. 5M IN A 10.0.4.31
+2000.example. 5M IN A 10.0.4.32
+2000.example. 5M IN A 10.0.4.33
+2000.example. 5M IN A 10.0.4.34
+2000.example. 5M IN A 10.0.4.35
+2000.example. 5M IN A 10.0.4.36
+2000.example. 5M IN A 10.0.4.37
+2000.example. 5M IN A 10.0.4.38
+2000.example. 5M IN A 10.0.4.39
+2000.example. 5M IN A 10.0.4.40
+2000.example. 5M IN A 10.0.4.41
+2000.example. 5M IN A 10.0.4.42
+2000.example. 5M IN A 10.0.4.43
+2000.example. 5M IN A 10.0.4.44
+2000.example. 5M IN A 10.0.4.45
+2000.example. 5M IN A 10.0.4.46
+2000.example. 5M IN A 10.0.4.47
+2000.example. 5M IN A 10.0.4.48
+2000.example. 5M IN A 10.0.4.49
+2000.example. 5M IN A 10.0.4.50
+2000.example. 5M IN A 10.0.4.51
+2000.example. 5M IN A 10.0.4.52
+2000.example. 5M IN A 10.0.4.53
+2000.example. 5M IN A 10.0.4.54
+2000.example. 5M IN A 10.0.4.55
+2000.example. 5M IN A 10.0.4.56
+2000.example. 5M IN A 10.0.4.57
+2000.example. 5M IN A 10.0.4.58
+2000.example. 5M IN A 10.0.4.59
+2000.example. 5M IN A 10.0.4.60
+2000.example. 5M IN A 10.0.4.61
+2000.example. 5M IN A 10.0.4.62
+2000.example. 5M IN A 10.0.4.63
+2000.example. 5M IN A 10.0.4.64
+2000.example. 5M IN A 10.0.4.65
+2000.example. 5M IN A 10.0.4.66
+2000.example. 5M IN A 10.0.4.67
+2000.example. 5M IN A 10.0.4.68
+2000.example. 5M IN A 10.0.4.69
+2000.example. 5M IN A 10.0.4.70
+2000.example. 5M IN A 10.0.4.71
+2000.example. 5M IN A 10.0.4.72
+2000.example. 5M IN A 10.0.4.73
+2000.example. 5M IN A 10.0.4.74
+2000.example. 5M IN A 10.0.4.75
+2000.example. 5M IN A 10.0.4.76
+2000.example. 5M IN A 10.0.4.77
+2000.example. 5M IN A 10.0.4.78
+2000.example. 5M IN A 10.0.4.79
+2000.example. 5M IN A 10.0.4.80
+2000.example. 5M IN A 10.0.4.81
+2000.example. 5M IN A 10.0.4.82
+2000.example. 5M IN A 10.0.4.83
+2000.example. 5M IN A 10.0.4.84
+2000.example. 5M IN A 10.0.4.85
+2000.example. 5M IN A 10.0.4.86
+2000.example. 5M IN A 10.0.4.87
+2000.example. 5M IN A 10.0.4.88
+2000.example. 5M IN A 10.0.4.89
+2000.example. 5M IN A 10.0.4.90
+2000.example. 5M IN A 10.0.4.91
+2000.example. 5M IN A 10.0.4.92
+2000.example. 5M IN A 10.0.4.93
+2000.example. 5M IN A 10.0.4.94
+2000.example. 5M IN A 10.0.4.95
+2000.example. 5M IN A 10.0.4.96
+2000.example. 5M IN A 10.0.4.97
+2000.example. 5M IN A 10.0.4.98
+2000.example. 5M IN A 10.0.4.99
+2000.example. 5M IN A 10.0.4.100
+2000.example. 5M IN A 10.0.4.101
+2000.example. 5M IN A 10.0.4.102
+2000.example. 5M IN A 10.0.4.103
+2000.example. 5M IN A 10.0.4.104
+2000.example. 5M IN A 10.0.4.105
+2000.example. 5M IN A 10.0.4.106
+2000.example. 5M IN A 10.0.4.107
+2000.example. 5M IN A 10.0.4.108
+2000.example. 5M IN A 10.0.4.109
+2000.example. 5M IN A 10.0.4.110
+2000.example. 5M IN A 10.0.4.111
+2000.example. 5M IN A 10.0.4.112
+2000.example. 5M IN A 10.0.4.113
+2000.example. 5M IN A 10.0.4.114
+2000.example. 5M IN A 10.0.4.115
+2000.example. 5M IN A 10.0.4.116
+2000.example. 5M IN A 10.0.4.117
+2000.example. 5M IN A 10.0.4.118
+2000.example. 5M IN A 10.0.4.119
+2000.example. 5M IN A 10.0.4.120
+2000.example. 5M IN A 10.0.4.121
+2000.example. 5M IN A 10.0.4.122
+2000.example. 5M IN A 10.0.4.123
+2000.example. 5M IN A 10.0.4.124
+2000.example. 5M IN A 10.0.4.125
+2000.example. 5M IN A 10.0.4.126
+2000.example. 5M IN A 10.0.4.127
+2000.example. 5M IN A 10.0.4.128
+2000.example. 5M IN A 10.0.4.129
+2000.example. 5M IN A 10.0.4.130
+2000.example. 5M IN A 10.0.4.131
+2000.example. 5M IN A 10.0.4.132
+2000.example. 5M IN A 10.0.4.133
+2000.example. 5M IN A 10.0.4.134
+2000.example. 5M IN A 10.0.4.135
+2000.example. 5M IN A 10.0.4.136
+2000.example. 5M IN A 10.0.4.137
+2000.example. 5M IN A 10.0.4.138
+2000.example. 5M IN A 10.0.4.139
+2000.example. 5M IN A 10.0.4.140
+2000.example. 5M IN A 10.0.4.141
+2000.example. 5M IN A 10.0.4.142
+2000.example. 5M IN A 10.0.4.143
+2000.example. 5M IN A 10.0.4.144
+2000.example. 5M IN A 10.0.4.145
+2000.example. 5M IN A 10.0.4.146
+2000.example. 5M IN A 10.0.4.147
+2000.example. 5M IN A 10.0.4.148
+2000.example. 5M IN A 10.0.4.149
+2000.example. 5M IN A 10.0.4.150
+2000.example. 5M IN A 10.0.4.151
+2000.example. 5M IN A 10.0.4.152
+2000.example. 5M IN A 10.0.4.153
+2000.example. 5M IN A 10.0.4.154
+2000.example. 5M IN A 10.0.4.155
+2000.example. 5M IN A 10.0.4.156
+2000.example. 5M IN A 10.0.4.157
+2000.example. 5M IN A 10.0.4.158
+2000.example. 5M IN A 10.0.4.159
+2000.example. 5M IN A 10.0.4.160
+2000.example. 5M IN A 10.0.4.161
+2000.example. 5M IN A 10.0.4.162
+2000.example. 5M IN A 10.0.4.163
+2000.example. 5M IN A 10.0.4.164
+2000.example. 5M IN A 10.0.4.165
+2000.example. 5M IN A 10.0.4.166
+2000.example. 5M IN A 10.0.4.167
+2000.example. 5M IN A 10.0.4.168
+2000.example. 5M IN A 10.0.4.169
+2000.example. 5M IN A 10.0.4.170
+2000.example. 5M IN A 10.0.4.171
+2000.example. 5M IN A 10.0.4.172
+2000.example. 5M IN A 10.0.4.173
+2000.example. 5M IN A 10.0.4.174
+2000.example. 5M IN A 10.0.4.175
+2000.example. 5M IN A 10.0.4.176
+2000.example. 5M IN A 10.0.4.177
+2000.example. 5M IN A 10.0.4.178
+2000.example. 5M IN A 10.0.4.179
+2000.example. 5M IN A 10.0.4.180
+2000.example. 5M IN A 10.0.4.181
+2000.example. 5M IN A 10.0.4.182
+2000.example. 5M IN A 10.0.4.183
+2000.example. 5M IN A 10.0.4.184
+2000.example. 5M IN A 10.0.4.185
+2000.example. 5M IN A 10.0.4.186
+2000.example. 5M IN A 10.0.4.187
+2000.example. 5M IN A 10.0.4.188
+2000.example. 5M IN A 10.0.4.189
+2000.example. 5M IN A 10.0.4.190
+2000.example. 5M IN A 10.0.4.191
+2000.example. 5M IN A 10.0.4.192
+2000.example. 5M IN A 10.0.4.193
+2000.example. 5M IN A 10.0.4.194
+2000.example. 5M IN A 10.0.4.195
+2000.example. 5M IN A 10.0.4.196
+2000.example. 5M IN A 10.0.4.197
+2000.example. 5M IN A 10.0.4.198
+2000.example. 5M IN A 10.0.4.199
+2000.example. 5M IN A 10.0.4.200
+2000.example. 5M IN A 10.0.4.201
+2000.example. 5M IN A 10.0.4.202
+2000.example. 5M IN A 10.0.4.203
+2000.example. 5M IN A 10.0.4.204
+2000.example. 5M IN A 10.0.4.205
+2000.example. 5M IN A 10.0.4.206
+2000.example. 5M IN A 10.0.4.207
+2000.example. 5M IN A 10.0.4.208
+2000.example. 5M IN A 10.0.4.209
+2000.example. 5M IN A 10.0.4.210
+2000.example. 5M IN A 10.0.4.211
+2000.example. 5M IN A 10.0.4.212
+2000.example. 5M IN A 10.0.4.213
+2000.example. 5M IN A 10.0.4.214
+2000.example. 5M IN A 10.0.4.215
+2000.example. 5M IN A 10.0.4.216
+2000.example. 5M IN A 10.0.4.217
+2000.example. 5M IN A 10.0.4.218
+2000.example. 5M IN A 10.0.4.219
+2000.example. 5M IN A 10.0.4.220
+2000.example. 5M IN A 10.0.4.221
+2000.example. 5M IN A 10.0.4.222
+2000.example. 5M IN A 10.0.4.223
+2000.example. 5M IN A 10.0.4.224
+2000.example. 5M IN A 10.0.4.225
+2000.example. 5M IN A 10.0.4.226
+2000.example. 5M IN A 10.0.4.227
+2000.example. 5M IN A 10.0.4.228
+2000.example. 5M IN A 10.0.4.229
+2000.example. 5M IN A 10.0.4.230
+2000.example. 5M IN A 10.0.4.231
+2000.example. 5M IN A 10.0.4.232
+2000.example. 5M IN A 10.0.4.233
+2000.example. 5M IN A 10.0.4.234
+2000.example. 5M IN A 10.0.4.235
+2000.example. 5M IN A 10.0.4.236
+2000.example. 5M IN A 10.0.4.237
+2000.example. 5M IN A 10.0.4.238
+2000.example. 5M IN A 10.0.4.239
+2000.example. 5M IN A 10.0.4.240
+2000.example. 5M IN A 10.0.4.241
+2000.example. 5M IN A 10.0.4.242
+2000.example. 5M IN A 10.0.4.243
+2000.example. 5M IN A 10.0.4.244
+2000.example. 5M IN A 10.0.4.245
+2000.example. 5M IN A 10.0.4.246
+2000.example. 5M IN A 10.0.4.247
+2000.example. 5M IN A 10.0.4.248
+2000.example. 5M IN A 10.0.4.249
+2000.example. 5M IN A 10.0.4.250
+2000.example. 5M IN A 10.0.4.251
+2000.example. 5M IN A 10.0.4.252
+2000.example. 5M IN A 10.0.4.253
+2000.example. 5M IN A 10.0.4.254
+2000.example. 5M IN A 10.0.4.255
+2000.example. 5M IN A 10.0.5.0
+2000.example. 5M IN A 10.0.5.1
+2000.example. 5M IN A 10.0.5.2
+2000.example. 5M IN A 10.0.5.3
+2000.example. 5M IN A 10.0.5.4
+2000.example. 5M IN A 10.0.5.5
+2000.example. 5M IN A 10.0.5.6
+2000.example. 5M IN A 10.0.5.7
+2000.example. 5M IN A 10.0.5.8
+2000.example. 5M IN A 10.0.5.9
+2000.example. 5M IN A 10.0.5.10
+2000.example. 5M IN A 10.0.5.11
+2000.example. 5M IN A 10.0.5.12
+2000.example. 5M IN A 10.0.5.13
+2000.example. 5M IN A 10.0.5.14
+2000.example. 5M IN A 10.0.5.15
+2000.example. 5M IN A 10.0.5.16
+2000.example. 5M IN A 10.0.5.17
+2000.example. 5M IN A 10.0.5.18
+2000.example. 5M IN A 10.0.5.19
+2000.example. 5M IN A 10.0.5.20
+2000.example. 5M IN A 10.0.5.21
+2000.example. 5M IN A 10.0.5.22
+2000.example. 5M IN A 10.0.5.23
+2000.example. 5M IN A 10.0.5.24
+2000.example. 5M IN A 10.0.5.25
+2000.example. 5M IN A 10.0.5.26
+2000.example. 5M IN A 10.0.5.27
+2000.example. 5M IN A 10.0.5.28
+2000.example. 5M IN A 10.0.5.29
+2000.example. 5M IN A 10.0.5.30
+2000.example. 5M IN A 10.0.5.31
+2000.example. 5M IN A 10.0.5.32
+2000.example. 5M IN A 10.0.5.33
+2000.example. 5M IN A 10.0.5.34
+2000.example. 5M IN A 10.0.5.35
+2000.example. 5M IN A 10.0.5.36
+2000.example. 5M IN A 10.0.5.37
+2000.example. 5M IN A 10.0.5.38
+2000.example. 5M IN A 10.0.5.39
+2000.example. 5M IN A 10.0.5.40
+2000.example. 5M IN A 10.0.5.41
+2000.example. 5M IN A 10.0.5.42
+2000.example. 5M IN A 10.0.5.43
+2000.example. 5M IN A 10.0.5.44
+2000.example. 5M IN A 10.0.5.45
+2000.example. 5M IN A 10.0.5.46
+2000.example. 5M IN A 10.0.5.47
+2000.example. 5M IN A 10.0.5.48
+2000.example. 5M IN A 10.0.5.49
+2000.example. 5M IN A 10.0.5.50
+2000.example. 5M IN A 10.0.5.51
+2000.example. 5M IN A 10.0.5.52
+2000.example. 5M IN A 10.0.5.53
+2000.example. 5M IN A 10.0.5.54
+2000.example. 5M IN A 10.0.5.55
+2000.example. 5M IN A 10.0.5.56
+2000.example. 5M IN A 10.0.5.57
+2000.example. 5M IN A 10.0.5.58
+2000.example. 5M IN A 10.0.5.59
+2000.example. 5M IN A 10.0.5.60
+2000.example. 5M IN A 10.0.5.61
+2000.example. 5M IN A 10.0.5.62
+2000.example. 5M IN A 10.0.5.63
+2000.example. 5M IN A 10.0.5.64
+2000.example. 5M IN A 10.0.5.65
+2000.example. 5M IN A 10.0.5.66
+2000.example. 5M IN A 10.0.5.67
+2000.example. 5M IN A 10.0.5.68
+2000.example. 5M IN A 10.0.5.69
+2000.example. 5M IN A 10.0.5.70
+2000.example. 5M IN A 10.0.5.71
+2000.example. 5M IN A 10.0.5.72
+2000.example. 5M IN A 10.0.5.73
+2000.example. 5M IN A 10.0.5.74
+2000.example. 5M IN A 10.0.5.75
+2000.example. 5M IN A 10.0.5.76
+2000.example. 5M IN A 10.0.5.77
+2000.example. 5M IN A 10.0.5.78
+2000.example. 5M IN A 10.0.5.79
+2000.example. 5M IN A 10.0.5.80
+2000.example. 5M IN A 10.0.5.81
+2000.example. 5M IN A 10.0.5.82
+2000.example. 5M IN A 10.0.5.83
+2000.example. 5M IN A 10.0.5.84
+2000.example. 5M IN A 10.0.5.85
+2000.example. 5M IN A 10.0.5.86
+2000.example. 5M IN A 10.0.5.87
+2000.example. 5M IN A 10.0.5.88
+2000.example. 5M IN A 10.0.5.89
+2000.example. 5M IN A 10.0.5.90
+2000.example. 5M IN A 10.0.5.91
+2000.example. 5M IN A 10.0.5.92
+2000.example. 5M IN A 10.0.5.93
+2000.example. 5M IN A 10.0.5.94
+2000.example. 5M IN A 10.0.5.95
+2000.example. 5M IN A 10.0.5.96
+2000.example. 5M IN A 10.0.5.97
+2000.example. 5M IN A 10.0.5.98
+2000.example. 5M IN A 10.0.5.99
+2000.example. 5M IN A 10.0.5.100
+2000.example. 5M IN A 10.0.5.101
+2000.example. 5M IN A 10.0.5.102
+2000.example. 5M IN A 10.0.5.103
+2000.example. 5M IN A 10.0.5.104
+2000.example. 5M IN A 10.0.5.105
+2000.example. 5M IN A 10.0.5.106
+2000.example. 5M IN A 10.0.5.107
+2000.example. 5M IN A 10.0.5.108
+2000.example. 5M IN A 10.0.5.109
+2000.example. 5M IN A 10.0.5.110
+2000.example. 5M IN A 10.0.5.111
+2000.example. 5M IN A 10.0.5.112
+2000.example. 5M IN A 10.0.5.113
+2000.example. 5M IN A 10.0.5.114
+2000.example. 5M IN A 10.0.5.115
+2000.example. 5M IN A 10.0.5.116
+2000.example. 5M IN A 10.0.5.117
+2000.example. 5M IN A 10.0.5.118
+2000.example. 5M IN A 10.0.5.119
+2000.example. 5M IN A 10.0.5.120
+2000.example. 5M IN A 10.0.5.121
+2000.example. 5M IN A 10.0.5.122
+2000.example. 5M IN A 10.0.5.123
+2000.example. 5M IN A 10.0.5.124
+2000.example. 5M IN A 10.0.5.125
+2000.example. 5M IN A 10.0.5.126
+2000.example. 5M IN A 10.0.5.127
+2000.example. 5M IN A 10.0.5.128
+2000.example. 5M IN A 10.0.5.129
+2000.example. 5M IN A 10.0.5.130
+2000.example. 5M IN A 10.0.5.131
+2000.example. 5M IN A 10.0.5.132
+2000.example. 5M IN A 10.0.5.133
+2000.example. 5M IN A 10.0.5.134
+2000.example. 5M IN A 10.0.5.135
+2000.example. 5M IN A 10.0.5.136
+2000.example. 5M IN A 10.0.5.137
+2000.example. 5M IN A 10.0.5.138
+2000.example. 5M IN A 10.0.5.139
+2000.example. 5M IN A 10.0.5.140
+2000.example. 5M IN A 10.0.5.141
+2000.example. 5M IN A 10.0.5.142
+2000.example. 5M IN A 10.0.5.143
+2000.example. 5M IN A 10.0.5.144
+2000.example. 5M IN A 10.0.5.145
+2000.example. 5M IN A 10.0.5.146
+2000.example. 5M IN A 10.0.5.147
+2000.example. 5M IN A 10.0.5.148
+2000.example. 5M IN A 10.0.5.149
+2000.example. 5M IN A 10.0.5.150
+2000.example. 5M IN A 10.0.5.151
+2000.example. 5M IN A 10.0.5.152
+2000.example. 5M IN A 10.0.5.153
+2000.example. 5M IN A 10.0.5.154
+2000.example. 5M IN A 10.0.5.155
+2000.example. 5M IN A 10.0.5.156
+2000.example. 5M IN A 10.0.5.157
+2000.example. 5M IN A 10.0.5.158
+2000.example. 5M IN A 10.0.5.159
+2000.example. 5M IN A 10.0.5.160
+2000.example. 5M IN A 10.0.5.161
+2000.example. 5M IN A 10.0.5.162
+2000.example. 5M IN A 10.0.5.163
+2000.example. 5M IN A 10.0.5.164
+2000.example. 5M IN A 10.0.5.165
+2000.example. 5M IN A 10.0.5.166
+2000.example. 5M IN A 10.0.5.167
+2000.example. 5M IN A 10.0.5.168
+2000.example. 5M IN A 10.0.5.169
+2000.example. 5M IN A 10.0.5.170
+2000.example. 5M IN A 10.0.5.171
+2000.example. 5M IN A 10.0.5.172
+2000.example. 5M IN A 10.0.5.173
+2000.example. 5M IN A 10.0.5.174
+2000.example. 5M IN A 10.0.5.175
+2000.example. 5M IN A 10.0.5.176
+2000.example. 5M IN A 10.0.5.177
+2000.example. 5M IN A 10.0.5.178
+2000.example. 5M IN A 10.0.5.179
+2000.example. 5M IN A 10.0.5.180
+2000.example. 5M IN A 10.0.5.181
+2000.example. 5M IN A 10.0.5.182
+2000.example. 5M IN A 10.0.5.183
+2000.example. 5M IN A 10.0.5.184
+2000.example. 5M IN A 10.0.5.185
+2000.example. 5M IN A 10.0.5.186
+2000.example. 5M IN A 10.0.5.187
+2000.example. 5M IN A 10.0.5.188
+2000.example. 5M IN A 10.0.5.189
+2000.example. 5M IN A 10.0.5.190
+2000.example. 5M IN A 10.0.5.191
+2000.example. 5M IN A 10.0.5.192
+2000.example. 5M IN A 10.0.5.193
+2000.example. 5M IN A 10.0.5.194
+2000.example. 5M IN A 10.0.5.195
+2000.example. 5M IN A 10.0.5.196
+2000.example. 5M IN A 10.0.5.197
+2000.example. 5M IN A 10.0.5.198
+2000.example. 5M IN A 10.0.5.199
+2000.example. 5M IN A 10.0.5.200
+2000.example. 5M IN A 10.0.5.201
+2000.example. 5M IN A 10.0.5.202
+2000.example. 5M IN A 10.0.5.203
+2000.example. 5M IN A 10.0.5.204
+2000.example. 5M IN A 10.0.5.205
+2000.example. 5M IN A 10.0.5.206
+2000.example. 5M IN A 10.0.5.207
+2000.example. 5M IN A 10.0.5.208
+2000.example. 5M IN A 10.0.5.209
+2000.example. 5M IN A 10.0.5.210
+2000.example. 5M IN A 10.0.5.211
+2000.example. 5M IN A 10.0.5.212
+2000.example. 5M IN A 10.0.5.213
+2000.example. 5M IN A 10.0.5.214
+2000.example. 5M IN A 10.0.5.215
+2000.example. 5M IN A 10.0.5.216
+2000.example. 5M IN A 10.0.5.217
+2000.example. 5M IN A 10.0.5.218
+2000.example. 5M IN A 10.0.5.219
+2000.example. 5M IN A 10.0.5.220
+2000.example. 5M IN A 10.0.5.221
+2000.example. 5M IN A 10.0.5.222
+2000.example. 5M IN A 10.0.5.223
+2000.example. 5M IN A 10.0.5.224
+2000.example. 5M IN A 10.0.5.225
+2000.example. 5M IN A 10.0.5.226
+2000.example. 5M IN A 10.0.5.227
+2000.example. 5M IN A 10.0.5.228
+2000.example. 5M IN A 10.0.5.229
+2000.example. 5M IN A 10.0.5.230
+2000.example. 5M IN A 10.0.5.231
+2000.example. 5M IN A 10.0.5.232
+2000.example. 5M IN A 10.0.5.233
+2000.example. 5M IN A 10.0.5.234
+2000.example. 5M IN A 10.0.5.235
+2000.example. 5M IN A 10.0.5.236
+2000.example. 5M IN A 10.0.5.237
+2000.example. 5M IN A 10.0.5.238
+2000.example. 5M IN A 10.0.5.239
+2000.example. 5M IN A 10.0.5.240
+2000.example. 5M IN A 10.0.5.241
+2000.example. 5M IN A 10.0.5.242
+2000.example. 5M IN A 10.0.5.243
+2000.example. 5M IN A 10.0.5.244
+2000.example. 5M IN A 10.0.5.245
+2000.example. 5M IN A 10.0.5.246
+2000.example. 5M IN A 10.0.5.247
+2000.example. 5M IN A 10.0.5.248
+2000.example. 5M IN A 10.0.5.249
+2000.example. 5M IN A 10.0.5.250
+2000.example. 5M IN A 10.0.5.251
+2000.example. 5M IN A 10.0.5.252
+2000.example. 5M IN A 10.0.5.253
+2000.example. 5M IN A 10.0.5.254
+2000.example. 5M IN A 10.0.5.255
+2000.example. 5M IN A 10.0.6.0
+2000.example. 5M IN A 10.0.6.1
+2000.example. 5M IN A 10.0.6.2
+2000.example. 5M IN A 10.0.6.3
+2000.example. 5M IN A 10.0.6.4
+2000.example. 5M IN A 10.0.6.5
+2000.example. 5M IN A 10.0.6.6
+2000.example. 5M IN A 10.0.6.7
+2000.example. 5M IN A 10.0.6.8
+2000.example. 5M IN A 10.0.6.9
+2000.example. 5M IN A 10.0.6.10
+2000.example. 5M IN A 10.0.6.11
+2000.example. 5M IN A 10.0.6.12
+2000.example. 5M IN A 10.0.6.13
+2000.example. 5M IN A 10.0.6.14
+2000.example. 5M IN A 10.0.6.15
+2000.example. 5M IN A 10.0.6.16
+2000.example. 5M IN A 10.0.6.17
+2000.example. 5M IN A 10.0.6.18
+2000.example. 5M IN A 10.0.6.19
+2000.example. 5M IN A 10.0.6.20
+2000.example. 5M IN A 10.0.6.21
+2000.example. 5M IN A 10.0.6.22
+2000.example. 5M IN A 10.0.6.23
+2000.example. 5M IN A 10.0.6.24
+2000.example. 5M IN A 10.0.6.25
+2000.example. 5M IN A 10.0.6.26
+2000.example. 5M IN A 10.0.6.27
+2000.example. 5M IN A 10.0.6.28
+2000.example. 5M IN A 10.0.6.29
+2000.example. 5M IN A 10.0.6.30
+2000.example. 5M IN A 10.0.6.31
+2000.example. 5M IN A 10.0.6.32
+2000.example. 5M IN A 10.0.6.33
+2000.example. 5M IN A 10.0.6.34
+2000.example. 5M IN A 10.0.6.35
+2000.example. 5M IN A 10.0.6.36
+2000.example. 5M IN A 10.0.6.37
+2000.example. 5M IN A 10.0.6.38
+2000.example. 5M IN A 10.0.6.39
+2000.example. 5M IN A 10.0.6.40
+2000.example. 5M IN A 10.0.6.41
+2000.example. 5M IN A 10.0.6.42
+2000.example. 5M IN A 10.0.6.43
+2000.example. 5M IN A 10.0.6.44
+2000.example. 5M IN A 10.0.6.45
+2000.example. 5M IN A 10.0.6.46
+2000.example. 5M IN A 10.0.6.47
+2000.example. 5M IN A 10.0.6.48
+2000.example. 5M IN A 10.0.6.49
+2000.example. 5M IN A 10.0.6.50
+2000.example. 5M IN A 10.0.6.51
+2000.example. 5M IN A 10.0.6.52
+2000.example. 5M IN A 10.0.6.53
+2000.example. 5M IN A 10.0.6.54
+2000.example. 5M IN A 10.0.6.55
+2000.example. 5M IN A 10.0.6.56
+2000.example. 5M IN A 10.0.6.57
+2000.example. 5M IN A 10.0.6.58
+2000.example. 5M IN A 10.0.6.59
+2000.example. 5M IN A 10.0.6.60
+2000.example. 5M IN A 10.0.6.61
+2000.example. 5M IN A 10.0.6.62
+2000.example. 5M IN A 10.0.6.63
+2000.example. 5M IN A 10.0.6.64
+2000.example. 5M IN A 10.0.6.65
+2000.example. 5M IN A 10.0.6.66
+2000.example. 5M IN A 10.0.6.67
+2000.example. 5M IN A 10.0.6.68
+2000.example. 5M IN A 10.0.6.69
+2000.example. 5M IN A 10.0.6.70
+2000.example. 5M IN A 10.0.6.71
+2000.example. 5M IN A 10.0.6.72
+2000.example. 5M IN A 10.0.6.73
+2000.example. 5M IN A 10.0.6.74
+2000.example. 5M IN A 10.0.6.75
+2000.example. 5M IN A 10.0.6.76
+2000.example. 5M IN A 10.0.6.77
+2000.example. 5M IN A 10.0.6.78
+2000.example. 5M IN A 10.0.6.79
+2000.example. 5M IN A 10.0.6.80
+2000.example. 5M IN A 10.0.6.81
+2000.example. 5M IN A 10.0.6.82
+2000.example. 5M IN A 10.0.6.83
+2000.example. 5M IN A 10.0.6.84
+2000.example. 5M IN A 10.0.6.85
+2000.example. 5M IN A 10.0.6.86
+2000.example. 5M IN A 10.0.6.87
+2000.example. 5M IN A 10.0.6.88
+2000.example. 5M IN A 10.0.6.89
+2000.example. 5M IN A 10.0.6.90
+2000.example. 5M IN A 10.0.6.91
+2000.example. 5M IN A 10.0.6.92
+2000.example. 5M IN A 10.0.6.93
+2000.example. 5M IN A 10.0.6.94
+2000.example. 5M IN A 10.0.6.95
+2000.example. 5M IN A 10.0.6.96
+2000.example. 5M IN A 10.0.6.97
+2000.example. 5M IN A 10.0.6.98
+2000.example. 5M IN A 10.0.6.99
+2000.example. 5M IN A 10.0.6.100
+2000.example. 5M IN A 10.0.6.101
+2000.example. 5M IN A 10.0.6.102
+2000.example. 5M IN A 10.0.6.103
+2000.example. 5M IN A 10.0.6.104
+2000.example. 5M IN A 10.0.6.105
+2000.example. 5M IN A 10.0.6.106
+2000.example. 5M IN A 10.0.6.107
+2000.example. 5M IN A 10.0.6.108
+2000.example. 5M IN A 10.0.6.109
+2000.example. 5M IN A 10.0.6.110
+2000.example. 5M IN A 10.0.6.111
+2000.example. 5M IN A 10.0.6.112
+2000.example. 5M IN A 10.0.6.113
+2000.example. 5M IN A 10.0.6.114
+2000.example. 5M IN A 10.0.6.115
+2000.example. 5M IN A 10.0.6.116
+2000.example. 5M IN A 10.0.6.117
+2000.example. 5M IN A 10.0.6.118
+2000.example. 5M IN A 10.0.6.119
+2000.example. 5M IN A 10.0.6.120
+2000.example. 5M IN A 10.0.6.121
+2000.example. 5M IN A 10.0.6.122
+2000.example. 5M IN A 10.0.6.123
+2000.example. 5M IN A 10.0.6.124
+2000.example. 5M IN A 10.0.6.125
+2000.example. 5M IN A 10.0.6.126
+2000.example. 5M IN A 10.0.6.127
+2000.example. 5M IN A 10.0.6.128
+2000.example. 5M IN A 10.0.6.129
+2000.example. 5M IN A 10.0.6.130
+2000.example. 5M IN A 10.0.6.131
+2000.example. 5M IN A 10.0.6.132
+2000.example. 5M IN A 10.0.6.133
+2000.example. 5M IN A 10.0.6.134
+2000.example. 5M IN A 10.0.6.135
+2000.example. 5M IN A 10.0.6.136
+2000.example. 5M IN A 10.0.6.137
+2000.example. 5M IN A 10.0.6.138
+2000.example. 5M IN A 10.0.6.139
+2000.example. 5M IN A 10.0.6.140
+2000.example. 5M IN A 10.0.6.141
+2000.example. 5M IN A 10.0.6.142
+2000.example. 5M IN A 10.0.6.143
+2000.example. 5M IN A 10.0.6.144
+2000.example. 5M IN A 10.0.6.145
+2000.example. 5M IN A 10.0.6.146
+2000.example. 5M IN A 10.0.6.147
+2000.example. 5M IN A 10.0.6.148
+2000.example. 5M IN A 10.0.6.149
+2000.example. 5M IN A 10.0.6.150
+2000.example. 5M IN A 10.0.6.151
+2000.example. 5M IN A 10.0.6.152
+2000.example. 5M IN A 10.0.6.153
+2000.example. 5M IN A 10.0.6.154
+2000.example. 5M IN A 10.0.6.155
+2000.example. 5M IN A 10.0.6.156
+2000.example. 5M IN A 10.0.6.157
+2000.example. 5M IN A 10.0.6.158
+2000.example. 5M IN A 10.0.6.159
+2000.example. 5M IN A 10.0.6.160
+2000.example. 5M IN A 10.0.6.161
+2000.example. 5M IN A 10.0.6.162
+2000.example. 5M IN A 10.0.6.163
+2000.example. 5M IN A 10.0.6.164
+2000.example. 5M IN A 10.0.6.165
+2000.example. 5M IN A 10.0.6.166
+2000.example. 5M IN A 10.0.6.167
+2000.example. 5M IN A 10.0.6.168
+2000.example. 5M IN A 10.0.6.169
+2000.example. 5M IN A 10.0.6.170
+2000.example. 5M IN A 10.0.6.171
+2000.example. 5M IN A 10.0.6.172
+2000.example. 5M IN A 10.0.6.173
+2000.example. 5M IN A 10.0.6.174
+2000.example. 5M IN A 10.0.6.175
+2000.example. 5M IN A 10.0.6.176
+2000.example. 5M IN A 10.0.6.177
+2000.example. 5M IN A 10.0.6.178
+2000.example. 5M IN A 10.0.6.179
+2000.example. 5M IN A 10.0.6.180
+2000.example. 5M IN A 10.0.6.181
+2000.example. 5M IN A 10.0.6.182
+2000.example. 5M IN A 10.0.6.183
+2000.example. 5M IN A 10.0.6.184
+2000.example. 5M IN A 10.0.6.185
+2000.example. 5M IN A 10.0.6.186
+2000.example. 5M IN A 10.0.6.187
+2000.example. 5M IN A 10.0.6.188
+2000.example. 5M IN A 10.0.6.189
+2000.example. 5M IN A 10.0.6.190
+2000.example. 5M IN A 10.0.6.191
+2000.example. 5M IN A 10.0.6.192
+2000.example. 5M IN A 10.0.6.193
+2000.example. 5M IN A 10.0.6.194
+2000.example. 5M IN A 10.0.6.195
+2000.example. 5M IN A 10.0.6.196
+2000.example. 5M IN A 10.0.6.197
+2000.example. 5M IN A 10.0.6.198
+2000.example. 5M IN A 10.0.6.199
+2000.example. 5M IN A 10.0.6.200
+2000.example. 5M IN A 10.0.6.201
+2000.example. 5M IN A 10.0.6.202
+2000.example. 5M IN A 10.0.6.203
+2000.example. 5M IN A 10.0.6.204
+2000.example. 5M IN A 10.0.6.205
+2000.example. 5M IN A 10.0.6.206
+2000.example. 5M IN A 10.0.6.207
+2000.example. 5M IN A 10.0.6.208
+2000.example. 5M IN A 10.0.6.209
+2000.example. 5M IN A 10.0.6.210
+2000.example. 5M IN A 10.0.6.211
+2000.example. 5M IN A 10.0.6.212
+2000.example. 5M IN A 10.0.6.213
+2000.example. 5M IN A 10.0.6.214
+2000.example. 5M IN A 10.0.6.215
+2000.example. 5M IN A 10.0.6.216
+2000.example. 5M IN A 10.0.6.217
+2000.example. 5M IN A 10.0.6.218
+2000.example. 5M IN A 10.0.6.219
+2000.example. 5M IN A 10.0.6.220
+2000.example. 5M IN A 10.0.6.221
+2000.example. 5M IN A 10.0.6.222
+2000.example. 5M IN A 10.0.6.223
+2000.example. 5M IN A 10.0.6.224
+2000.example. 5M IN A 10.0.6.225
+2000.example. 5M IN A 10.0.6.226
+2000.example. 5M IN A 10.0.6.227
+2000.example. 5M IN A 10.0.6.228
+2000.example. 5M IN A 10.0.6.229
+2000.example. 5M IN A 10.0.6.230
+2000.example. 5M IN A 10.0.6.231
+2000.example. 5M IN A 10.0.6.232
+2000.example. 5M IN A 10.0.6.233
+2000.example. 5M IN A 10.0.6.234
+2000.example. 5M IN A 10.0.6.235
+2000.example. 5M IN A 10.0.6.236
+2000.example. 5M IN A 10.0.6.237
+2000.example. 5M IN A 10.0.6.238
+2000.example. 5M IN A 10.0.6.239
+2000.example. 5M IN A 10.0.6.240
+2000.example. 5M IN A 10.0.6.241
+2000.example. 5M IN A 10.0.6.242
+2000.example. 5M IN A 10.0.6.243
+2000.example. 5M IN A 10.0.6.244
+2000.example. 5M IN A 10.0.6.245
+2000.example. 5M IN A 10.0.6.246
+2000.example. 5M IN A 10.0.6.247
+2000.example. 5M IN A 10.0.6.248
+2000.example. 5M IN A 10.0.6.249
+2000.example. 5M IN A 10.0.6.250
+2000.example. 5M IN A 10.0.6.251
+2000.example. 5M IN A 10.0.6.252
+2000.example. 5M IN A 10.0.6.253
+2000.example. 5M IN A 10.0.6.254
+2000.example. 5M IN A 10.0.6.255
+2000.example. 5M IN A 10.0.7.0
+2000.example. 5M IN A 10.0.7.1
+2000.example. 5M IN A 10.0.7.2
+2000.example. 5M IN A 10.0.7.3
+2000.example. 5M IN A 10.0.7.4
+2000.example. 5M IN A 10.0.7.5
+2000.example. 5M IN A 10.0.7.6
+2000.example. 5M IN A 10.0.7.7
+2000.example. 5M IN A 10.0.7.8
+2000.example. 5M IN A 10.0.7.9
+2000.example. 5M IN A 10.0.7.10
+2000.example. 5M IN A 10.0.7.11
+2000.example. 5M IN A 10.0.7.12
+2000.example. 5M IN A 10.0.7.13
+2000.example. 5M IN A 10.0.7.14
+2000.example. 5M IN A 10.0.7.15
+2000.example. 5M IN A 10.0.7.16
+2000.example. 5M IN A 10.0.7.17
+2000.example. 5M IN A 10.0.7.18
+2000.example. 5M IN A 10.0.7.19
+2000.example. 5M IN A 10.0.7.20
+2000.example. 5M IN A 10.0.7.21
+2000.example. 5M IN A 10.0.7.22
+2000.example. 5M IN A 10.0.7.23
+2000.example. 5M IN A 10.0.7.24
+2000.example. 5M IN A 10.0.7.25
+2000.example. 5M IN A 10.0.7.26
+2000.example. 5M IN A 10.0.7.27
+2000.example. 5M IN A 10.0.7.28
+2000.example. 5M IN A 10.0.7.29
+2000.example. 5M IN A 10.0.7.30
+2000.example. 5M IN A 10.0.7.31
+2000.example. 5M IN A 10.0.7.32
+2000.example. 5M IN A 10.0.7.33
+2000.example. 5M IN A 10.0.7.34
+2000.example. 5M IN A 10.0.7.35
+2000.example. 5M IN A 10.0.7.36
+2000.example. 5M IN A 10.0.7.37
+2000.example. 5M IN A 10.0.7.38
+2000.example. 5M IN A 10.0.7.39
+2000.example. 5M IN A 10.0.7.40
+2000.example. 5M IN A 10.0.7.41
+2000.example. 5M IN A 10.0.7.42
+2000.example. 5M IN A 10.0.7.43
+2000.example. 5M IN A 10.0.7.44
+2000.example. 5M IN A 10.0.7.45
+2000.example. 5M IN A 10.0.7.46
+2000.example. 5M IN A 10.0.7.47
+2000.example. 5M IN A 10.0.7.48
+2000.example. 5M IN A 10.0.7.49
+2000.example. 5M IN A 10.0.7.50
+2000.example. 5M IN A 10.0.7.51
+2000.example. 5M IN A 10.0.7.52
+2000.example. 5M IN A 10.0.7.53
+2000.example. 5M IN A 10.0.7.54
+2000.example. 5M IN A 10.0.7.55
+2000.example. 5M IN A 10.0.7.56
+2000.example. 5M IN A 10.0.7.57
+2000.example. 5M IN A 10.0.7.58
+2000.example. 5M IN A 10.0.7.59
+2000.example. 5M IN A 10.0.7.60
+2000.example. 5M IN A 10.0.7.61
+2000.example. 5M IN A 10.0.7.62
+2000.example. 5M IN A 10.0.7.63
+2000.example. 5M IN A 10.0.7.64
+2000.example. 5M IN A 10.0.7.65
+2000.example. 5M IN A 10.0.7.66
+2000.example. 5M IN A 10.0.7.67
+2000.example. 5M IN A 10.0.7.68
+2000.example. 5M IN A 10.0.7.69
+2000.example. 5M IN A 10.0.7.70
+2000.example. 5M IN A 10.0.7.71
+2000.example. 5M IN A 10.0.7.72
+2000.example. 5M IN A 10.0.7.73
+2000.example. 5M IN A 10.0.7.74
+2000.example. 5M IN A 10.0.7.75
+2000.example. 5M IN A 10.0.7.76
+2000.example. 5M IN A 10.0.7.77
+2000.example. 5M IN A 10.0.7.78
+2000.example. 5M IN A 10.0.7.79
+2000.example. 5M IN A 10.0.7.80
+2000.example. 5M IN A 10.0.7.81
+2000.example. 5M IN A 10.0.7.82
+2000.example. 5M IN A 10.0.7.83
+2000.example. 5M IN A 10.0.7.84
+2000.example. 5M IN A 10.0.7.85
+2000.example. 5M IN A 10.0.7.86
+2000.example. 5M IN A 10.0.7.87
+2000.example. 5M IN A 10.0.7.88
+2000.example. 5M IN A 10.0.7.89
+2000.example. 5M IN A 10.0.7.90
+2000.example. 5M IN A 10.0.7.91
+2000.example. 5M IN A 10.0.7.92
+2000.example. 5M IN A 10.0.7.93
+2000.example. 5M IN A 10.0.7.94
+2000.example. 5M IN A 10.0.7.95
+2000.example. 5M IN A 10.0.7.96
+2000.example. 5M IN A 10.0.7.97
+2000.example. 5M IN A 10.0.7.98
+2000.example. 5M IN A 10.0.7.99
+2000.example. 5M IN A 10.0.7.100
+2000.example. 5M IN A 10.0.7.101
+2000.example. 5M IN A 10.0.7.102
+2000.example. 5M IN A 10.0.7.103
+2000.example. 5M IN A 10.0.7.104
+2000.example. 5M IN A 10.0.7.105
+2000.example. 5M IN A 10.0.7.106
+2000.example. 5M IN A 10.0.7.107
+2000.example. 5M IN A 10.0.7.108
+2000.example. 5M IN A 10.0.7.109
+2000.example. 5M IN A 10.0.7.110
+2000.example. 5M IN A 10.0.7.111
+2000.example. 5M IN A 10.0.7.112
+2000.example. 5M IN A 10.0.7.113
+2000.example. 5M IN A 10.0.7.114
+2000.example. 5M IN A 10.0.7.115
+2000.example. 5M IN A 10.0.7.116
+2000.example. 5M IN A 10.0.7.117
+2000.example. 5M IN A 10.0.7.118
+2000.example. 5M IN A 10.0.7.119
+2000.example. 5M IN A 10.0.7.120
+2000.example. 5M IN A 10.0.7.121
+2000.example. 5M IN A 10.0.7.122
+2000.example. 5M IN A 10.0.7.123
+2000.example. 5M IN A 10.0.7.124
+2000.example. 5M IN A 10.0.7.125
+2000.example. 5M IN A 10.0.7.126
+2000.example. 5M IN A 10.0.7.127
+2000.example. 5M IN A 10.0.7.128
+2000.example. 5M IN A 10.0.7.129
+2000.example. 5M IN A 10.0.7.130
+2000.example. 5M IN A 10.0.7.131
+2000.example. 5M IN A 10.0.7.132
+2000.example. 5M IN A 10.0.7.133
+2000.example. 5M IN A 10.0.7.134
+2000.example. 5M IN A 10.0.7.135
+2000.example. 5M IN A 10.0.7.136
+2000.example. 5M IN A 10.0.7.137
+2000.example. 5M IN A 10.0.7.138
+2000.example. 5M IN A 10.0.7.139
+2000.example. 5M IN A 10.0.7.140
+2000.example. 5M IN A 10.0.7.141
+2000.example. 5M IN A 10.0.7.142
+2000.example. 5M IN A 10.0.7.143
+2000.example. 5M IN A 10.0.7.144
+2000.example. 5M IN A 10.0.7.145
+2000.example. 5M IN A 10.0.7.146
+2000.example. 5M IN A 10.0.7.147
+2000.example. 5M IN A 10.0.7.148
+2000.example. 5M IN A 10.0.7.149
+2000.example. 5M IN A 10.0.7.150
+2000.example. 5M IN A 10.0.7.151
+2000.example. 5M IN A 10.0.7.152
+2000.example. 5M IN A 10.0.7.153
+2000.example. 5M IN A 10.0.7.154
+2000.example. 5M IN A 10.0.7.155
+2000.example. 5M IN A 10.0.7.156
+2000.example. 5M IN A 10.0.7.157
+2000.example. 5M IN A 10.0.7.158
+2000.example. 5M IN A 10.0.7.159
+2000.example. 5M IN A 10.0.7.160
+2000.example. 5M IN A 10.0.7.161
+2000.example. 5M IN A 10.0.7.162
+2000.example. 5M IN A 10.0.7.163
+2000.example. 5M IN A 10.0.7.164
+2000.example. 5M IN A 10.0.7.165
+2000.example. 5M IN A 10.0.7.166
+2000.example. 5M IN A 10.0.7.167
+2000.example. 5M IN A 10.0.7.168
+2000.example. 5M IN A 10.0.7.169
+2000.example. 5M IN A 10.0.7.170
+2000.example. 5M IN A 10.0.7.171
+2000.example. 5M IN A 10.0.7.172
+2000.example. 5M IN A 10.0.7.173
+2000.example. 5M IN A 10.0.7.174
+2000.example. 5M IN A 10.0.7.175
+2000.example. 5M IN A 10.0.7.176
+2000.example. 5M IN A 10.0.7.177
+2000.example. 5M IN A 10.0.7.178
+2000.example. 5M IN A 10.0.7.179
+2000.example. 5M IN A 10.0.7.180
+2000.example. 5M IN A 10.0.7.181
+2000.example. 5M IN A 10.0.7.182
+2000.example. 5M IN A 10.0.7.183
+2000.example. 5M IN A 10.0.7.184
+2000.example. 5M IN A 10.0.7.185
+2000.example. 5M IN A 10.0.7.186
+2000.example. 5M IN A 10.0.7.187
+2000.example. 5M IN A 10.0.7.188
+2000.example. 5M IN A 10.0.7.189
+2000.example. 5M IN A 10.0.7.190
+2000.example. 5M IN A 10.0.7.191
+2000.example. 5M IN A 10.0.7.192
+2000.example. 5M IN A 10.0.7.193
+2000.example. 5M IN A 10.0.7.194
+2000.example. 5M IN A 10.0.7.195
+2000.example. 5M IN A 10.0.7.196
+2000.example. 5M IN A 10.0.7.197
+2000.example. 5M IN A 10.0.7.198
+2000.example. 5M IN A 10.0.7.199
+2000.example. 5M IN A 10.0.7.200
+2000.example. 5M IN A 10.0.7.201
+2000.example. 5M IN A 10.0.7.202
+2000.example. 5M IN A 10.0.7.203
+2000.example. 5M IN A 10.0.7.204
+2000.example. 5M IN A 10.0.7.205
+2000.example. 5M IN A 10.0.7.206
+2000.example. 5M IN A 10.0.7.207
+
+;; AUTHORITY SECTION:
+example. 5M IN NS ns1.example.
+
+;; ADDITIONAL SECTION:
+ns1.example. 5M IN A 10.53.0.1
+
+;; Total query time: 121 msec
+;; FROM: draco to SERVER: 10.53.0.1
+;; WHEN: Fri Jun 23 12:58:14 2000
+;; MSG SIZE sent: 30 rcvd: 32068
+
diff --git a/bin/tests/system/limits/knowngood.dig.out.3000 b/bin/tests/system/limits/knowngood.dig.out.3000
new file mode 100644
index 0000000..1932475
--- /dev/null
+++ b/bin/tests/system/limits/knowngood.dig.out.3000
@@ -0,0 +1,3023 @@
+
+; <<>> DiG 8.2 <<>> 3000.example. @10.53.0.1 a -p
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr aa rd ad; QUERY: 1, ANSWER: 3000, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; 3000.example, type = A, class = IN
+
+;; ANSWER SECTION:
+3000.example. 5M IN A 10.0.0.0
+3000.example. 5M IN A 10.0.0.1
+3000.example. 5M IN A 10.0.0.2
+3000.example. 5M IN A 10.0.0.3
+3000.example. 5M IN A 10.0.0.4
+3000.example. 5M IN A 10.0.0.5
+3000.example. 5M IN A 10.0.0.6
+3000.example. 5M IN A 10.0.0.7
+3000.example. 5M IN A 10.0.0.8
+3000.example. 5M IN A 10.0.0.9
+3000.example. 5M IN A 10.0.0.10
+3000.example. 5M IN A 10.0.0.11
+3000.example. 5M IN A 10.0.0.12
+3000.example. 5M IN A 10.0.0.13
+3000.example. 5M IN A 10.0.0.14
+3000.example. 5M IN A 10.0.0.15
+3000.example. 5M IN A 10.0.0.16
+3000.example. 5M IN A 10.0.0.17
+3000.example. 5M IN A 10.0.0.18
+3000.example. 5M IN A 10.0.0.19
+3000.example. 5M IN A 10.0.0.20
+3000.example. 5M IN A 10.0.0.21
+3000.example. 5M IN A 10.0.0.22
+3000.example. 5M IN A 10.0.0.23
+3000.example. 5M IN A 10.0.0.24
+3000.example. 5M IN A 10.0.0.25
+3000.example. 5M IN A 10.0.0.26
+3000.example. 5M IN A 10.0.0.27
+3000.example. 5M IN A 10.0.0.28
+3000.example. 5M IN A 10.0.0.29
+3000.example. 5M IN A 10.0.0.30
+3000.example. 5M IN A 10.0.0.31
+3000.example. 5M IN A 10.0.0.32
+3000.example. 5M IN A 10.0.0.33
+3000.example. 5M IN A 10.0.0.34
+3000.example. 5M IN A 10.0.0.35
+3000.example. 5M IN A 10.0.0.36
+3000.example. 5M IN A 10.0.0.37
+3000.example. 5M IN A 10.0.0.38
+3000.example. 5M IN A 10.0.0.39
+3000.example. 5M IN A 10.0.0.40
+3000.example. 5M IN A 10.0.0.41
+3000.example. 5M IN A 10.0.0.42
+3000.example. 5M IN A 10.0.0.43
+3000.example. 5M IN A 10.0.0.44
+3000.example. 5M IN A 10.0.0.45
+3000.example. 5M IN A 10.0.0.46
+3000.example. 5M IN A 10.0.0.47
+3000.example. 5M IN A 10.0.0.48
+3000.example. 5M IN A 10.0.0.49
+3000.example. 5M IN A 10.0.0.50
+3000.example. 5M IN A 10.0.0.51
+3000.example. 5M IN A 10.0.0.52
+3000.example. 5M IN A 10.0.0.53
+3000.example. 5M IN A 10.0.0.54
+3000.example. 5M IN A 10.0.0.55
+3000.example. 5M IN A 10.0.0.56
+3000.example. 5M IN A 10.0.0.57
+3000.example. 5M IN A 10.0.0.58
+3000.example. 5M IN A 10.0.0.59
+3000.example. 5M IN A 10.0.0.60
+3000.example. 5M IN A 10.0.0.61
+3000.example. 5M IN A 10.0.0.62
+3000.example. 5M IN A 10.0.0.63
+3000.example. 5M IN A 10.0.0.64
+3000.example. 5M IN A 10.0.0.65
+3000.example. 5M IN A 10.0.0.66
+3000.example. 5M IN A 10.0.0.67
+3000.example. 5M IN A 10.0.0.68
+3000.example. 5M IN A 10.0.0.69
+3000.example. 5M IN A 10.0.0.70
+3000.example. 5M IN A 10.0.0.71
+3000.example. 5M IN A 10.0.0.72
+3000.example. 5M IN A 10.0.0.73
+3000.example. 5M IN A 10.0.0.74
+3000.example. 5M IN A 10.0.0.75
+3000.example. 5M IN A 10.0.0.76
+3000.example. 5M IN A 10.0.0.77
+3000.example. 5M IN A 10.0.0.78
+3000.example. 5M IN A 10.0.0.79
+3000.example. 5M IN A 10.0.0.80
+3000.example. 5M IN A 10.0.0.81
+3000.example. 5M IN A 10.0.0.82
+3000.example. 5M IN A 10.0.0.83
+3000.example. 5M IN A 10.0.0.84
+3000.example. 5M IN A 10.0.0.85
+3000.example. 5M IN A 10.0.0.86
+3000.example. 5M IN A 10.0.0.87
+3000.example. 5M IN A 10.0.0.88
+3000.example. 5M IN A 10.0.0.89
+3000.example. 5M IN A 10.0.0.90
+3000.example. 5M IN A 10.0.0.91
+3000.example. 5M IN A 10.0.0.92
+3000.example. 5M IN A 10.0.0.93
+3000.example. 5M IN A 10.0.0.94
+3000.example. 5M IN A 10.0.0.95
+3000.example. 5M IN A 10.0.0.96
+3000.example. 5M IN A 10.0.0.97
+3000.example. 5M IN A 10.0.0.98
+3000.example. 5M IN A 10.0.0.99
+3000.example. 5M IN A 10.0.0.100
+3000.example. 5M IN A 10.0.0.101
+3000.example. 5M IN A 10.0.0.102
+3000.example. 5M IN A 10.0.0.103
+3000.example. 5M IN A 10.0.0.104
+3000.example. 5M IN A 10.0.0.105
+3000.example. 5M IN A 10.0.0.106
+3000.example. 5M IN A 10.0.0.107
+3000.example. 5M IN A 10.0.0.108
+3000.example. 5M IN A 10.0.0.109
+3000.example. 5M IN A 10.0.0.110
+3000.example. 5M IN A 10.0.0.111
+3000.example. 5M IN A 10.0.0.112
+3000.example. 5M IN A 10.0.0.113
+3000.example. 5M IN A 10.0.0.114
+3000.example. 5M IN A 10.0.0.115
+3000.example. 5M IN A 10.0.0.116
+3000.example. 5M IN A 10.0.0.117
+3000.example. 5M IN A 10.0.0.118
+3000.example. 5M IN A 10.0.0.119
+3000.example. 5M IN A 10.0.0.120
+3000.example. 5M IN A 10.0.0.121
+3000.example. 5M IN A 10.0.0.122
+3000.example. 5M IN A 10.0.0.123
+3000.example. 5M IN A 10.0.0.124
+3000.example. 5M IN A 10.0.0.125
+3000.example. 5M IN A 10.0.0.126
+3000.example. 5M IN A 10.0.0.127
+3000.example. 5M IN A 10.0.0.128
+3000.example. 5M IN A 10.0.0.129
+3000.example. 5M IN A 10.0.0.130
+3000.example. 5M IN A 10.0.0.131
+3000.example. 5M IN A 10.0.0.132
+3000.example. 5M IN A 10.0.0.133
+3000.example. 5M IN A 10.0.0.134
+3000.example. 5M IN A 10.0.0.135
+3000.example. 5M IN A 10.0.0.136
+3000.example. 5M IN A 10.0.0.137
+3000.example. 5M IN A 10.0.0.138
+3000.example. 5M IN A 10.0.0.139
+3000.example. 5M IN A 10.0.0.140
+3000.example. 5M IN A 10.0.0.141
+3000.example. 5M IN A 10.0.0.142
+3000.example. 5M IN A 10.0.0.143
+3000.example. 5M IN A 10.0.0.144
+3000.example. 5M IN A 10.0.0.145
+3000.example. 5M IN A 10.0.0.146
+3000.example. 5M IN A 10.0.0.147
+3000.example. 5M IN A 10.0.0.148
+3000.example. 5M IN A 10.0.0.149
+3000.example. 5M IN A 10.0.0.150
+3000.example. 5M IN A 10.0.0.151
+3000.example. 5M IN A 10.0.0.152
+3000.example. 5M IN A 10.0.0.153
+3000.example. 5M IN A 10.0.0.154
+3000.example. 5M IN A 10.0.0.155
+3000.example. 5M IN A 10.0.0.156
+3000.example. 5M IN A 10.0.0.157
+3000.example. 5M IN A 10.0.0.158
+3000.example. 5M IN A 10.0.0.159
+3000.example. 5M IN A 10.0.0.160
+3000.example. 5M IN A 10.0.0.161
+3000.example. 5M IN A 10.0.0.162
+3000.example. 5M IN A 10.0.0.163
+3000.example. 5M IN A 10.0.0.164
+3000.example. 5M IN A 10.0.0.165
+3000.example. 5M IN A 10.0.0.166
+3000.example. 5M IN A 10.0.0.167
+3000.example. 5M IN A 10.0.0.168
+3000.example. 5M IN A 10.0.0.169
+3000.example. 5M IN A 10.0.0.170
+3000.example. 5M IN A 10.0.0.171
+3000.example. 5M IN A 10.0.0.172
+3000.example. 5M IN A 10.0.0.173
+3000.example. 5M IN A 10.0.0.174
+3000.example. 5M IN A 10.0.0.175
+3000.example. 5M IN A 10.0.0.176
+3000.example. 5M IN A 10.0.0.177
+3000.example. 5M IN A 10.0.0.178
+3000.example. 5M IN A 10.0.0.179
+3000.example. 5M IN A 10.0.0.180
+3000.example. 5M IN A 10.0.0.181
+3000.example. 5M IN A 10.0.0.182
+3000.example. 5M IN A 10.0.0.183
+3000.example. 5M IN A 10.0.0.184
+3000.example. 5M IN A 10.0.0.185
+3000.example. 5M IN A 10.0.0.186
+3000.example. 5M IN A 10.0.0.187
+3000.example. 5M IN A 10.0.0.188
+3000.example. 5M IN A 10.0.0.189
+3000.example. 5M IN A 10.0.0.190
+3000.example. 5M IN A 10.0.0.191
+3000.example. 5M IN A 10.0.0.192
+3000.example. 5M IN A 10.0.0.193
+3000.example. 5M IN A 10.0.0.194
+3000.example. 5M IN A 10.0.0.195
+3000.example. 5M IN A 10.0.0.196
+3000.example. 5M IN A 10.0.0.197
+3000.example. 5M IN A 10.0.0.198
+3000.example. 5M IN A 10.0.0.199
+3000.example. 5M IN A 10.0.0.200
+3000.example. 5M IN A 10.0.0.201
+3000.example. 5M IN A 10.0.0.202
+3000.example. 5M IN A 10.0.0.203
+3000.example. 5M IN A 10.0.0.204
+3000.example. 5M IN A 10.0.0.205
+3000.example. 5M IN A 10.0.0.206
+3000.example. 5M IN A 10.0.0.207
+3000.example. 5M IN A 10.0.0.208
+3000.example. 5M IN A 10.0.0.209
+3000.example. 5M IN A 10.0.0.210
+3000.example. 5M IN A 10.0.0.211
+3000.example. 5M IN A 10.0.0.212
+3000.example. 5M IN A 10.0.0.213
+3000.example. 5M IN A 10.0.0.214
+3000.example. 5M IN A 10.0.0.215
+3000.example. 5M IN A 10.0.0.216
+3000.example. 5M IN A 10.0.0.217
+3000.example. 5M IN A 10.0.0.218
+3000.example. 5M IN A 10.0.0.219
+3000.example. 5M IN A 10.0.0.220
+3000.example. 5M IN A 10.0.0.221
+3000.example. 5M IN A 10.0.0.222
+3000.example. 5M IN A 10.0.0.223
+3000.example. 5M IN A 10.0.0.224
+3000.example. 5M IN A 10.0.0.225
+3000.example. 5M IN A 10.0.0.226
+3000.example. 5M IN A 10.0.0.227
+3000.example. 5M IN A 10.0.0.228
+3000.example. 5M IN A 10.0.0.229
+3000.example. 5M IN A 10.0.0.230
+3000.example. 5M IN A 10.0.0.231
+3000.example. 5M IN A 10.0.0.232
+3000.example. 5M IN A 10.0.0.233
+3000.example. 5M IN A 10.0.0.234
+3000.example. 5M IN A 10.0.0.235
+3000.example. 5M IN A 10.0.0.236
+3000.example. 5M IN A 10.0.0.237
+3000.example. 5M IN A 10.0.0.238
+3000.example. 5M IN A 10.0.0.239
+3000.example. 5M IN A 10.0.0.240
+3000.example. 5M IN A 10.0.0.241
+3000.example. 5M IN A 10.0.0.242
+3000.example. 5M IN A 10.0.0.243
+3000.example. 5M IN A 10.0.0.244
+3000.example. 5M IN A 10.0.0.245
+3000.example. 5M IN A 10.0.0.246
+3000.example. 5M IN A 10.0.0.247
+3000.example. 5M IN A 10.0.0.248
+3000.example. 5M IN A 10.0.0.249
+3000.example. 5M IN A 10.0.0.250
+3000.example. 5M IN A 10.0.0.251
+3000.example. 5M IN A 10.0.0.252
+3000.example. 5M IN A 10.0.0.253
+3000.example. 5M IN A 10.0.0.254
+3000.example. 5M IN A 10.0.0.255
+3000.example. 5M IN A 10.0.1.0
+3000.example. 5M IN A 10.0.1.1
+3000.example. 5M IN A 10.0.1.2
+3000.example. 5M IN A 10.0.1.3
+3000.example. 5M IN A 10.0.1.4
+3000.example. 5M IN A 10.0.1.5
+3000.example. 5M IN A 10.0.1.6
+3000.example. 5M IN A 10.0.1.7
+3000.example. 5M IN A 10.0.1.8
+3000.example. 5M IN A 10.0.1.9
+3000.example. 5M IN A 10.0.1.10
+3000.example. 5M IN A 10.0.1.11
+3000.example. 5M IN A 10.0.1.12
+3000.example. 5M IN A 10.0.1.13
+3000.example. 5M IN A 10.0.1.14
+3000.example. 5M IN A 10.0.1.15
+3000.example. 5M IN A 10.0.1.16
+3000.example. 5M IN A 10.0.1.17
+3000.example. 5M IN A 10.0.1.18
+3000.example. 5M IN A 10.0.1.19
+3000.example. 5M IN A 10.0.1.20
+3000.example. 5M IN A 10.0.1.21
+3000.example. 5M IN A 10.0.1.22
+3000.example. 5M IN A 10.0.1.23
+3000.example. 5M IN A 10.0.1.24
+3000.example. 5M IN A 10.0.1.25
+3000.example. 5M IN A 10.0.1.26
+3000.example. 5M IN A 10.0.1.27
+3000.example. 5M IN A 10.0.1.28
+3000.example. 5M IN A 10.0.1.29
+3000.example. 5M IN A 10.0.1.30
+3000.example. 5M IN A 10.0.1.31
+3000.example. 5M IN A 10.0.1.32
+3000.example. 5M IN A 10.0.1.33
+3000.example. 5M IN A 10.0.1.34
+3000.example. 5M IN A 10.0.1.35
+3000.example. 5M IN A 10.0.1.36
+3000.example. 5M IN A 10.0.1.37
+3000.example. 5M IN A 10.0.1.38
+3000.example. 5M IN A 10.0.1.39
+3000.example. 5M IN A 10.0.1.40
+3000.example. 5M IN A 10.0.1.41
+3000.example. 5M IN A 10.0.1.42
+3000.example. 5M IN A 10.0.1.43
+3000.example. 5M IN A 10.0.1.44
+3000.example. 5M IN A 10.0.1.45
+3000.example. 5M IN A 10.0.1.46
+3000.example. 5M IN A 10.0.1.47
+3000.example. 5M IN A 10.0.1.48
+3000.example. 5M IN A 10.0.1.49
+3000.example. 5M IN A 10.0.1.50
+3000.example. 5M IN A 10.0.1.51
+3000.example. 5M IN A 10.0.1.52
+3000.example. 5M IN A 10.0.1.53
+3000.example. 5M IN A 10.0.1.54
+3000.example. 5M IN A 10.0.1.55
+3000.example. 5M IN A 10.0.1.56
+3000.example. 5M IN A 10.0.1.57
+3000.example. 5M IN A 10.0.1.58
+3000.example. 5M IN A 10.0.1.59
+3000.example. 5M IN A 10.0.1.60
+3000.example. 5M IN A 10.0.1.61
+3000.example. 5M IN A 10.0.1.62
+3000.example. 5M IN A 10.0.1.63
+3000.example. 5M IN A 10.0.1.64
+3000.example. 5M IN A 10.0.1.65
+3000.example. 5M IN A 10.0.1.66
+3000.example. 5M IN A 10.0.1.67
+3000.example. 5M IN A 10.0.1.68
+3000.example. 5M IN A 10.0.1.69
+3000.example. 5M IN A 10.0.1.70
+3000.example. 5M IN A 10.0.1.71
+3000.example. 5M IN A 10.0.1.72
+3000.example. 5M IN A 10.0.1.73
+3000.example. 5M IN A 10.0.1.74
+3000.example. 5M IN A 10.0.1.75
+3000.example. 5M IN A 10.0.1.76
+3000.example. 5M IN A 10.0.1.77
+3000.example. 5M IN A 10.0.1.78
+3000.example. 5M IN A 10.0.1.79
+3000.example. 5M IN A 10.0.1.80
+3000.example. 5M IN A 10.0.1.81
+3000.example. 5M IN A 10.0.1.82
+3000.example. 5M IN A 10.0.1.83
+3000.example. 5M IN A 10.0.1.84
+3000.example. 5M IN A 10.0.1.85
+3000.example. 5M IN A 10.0.1.86
+3000.example. 5M IN A 10.0.1.87
+3000.example. 5M IN A 10.0.1.88
+3000.example. 5M IN A 10.0.1.89
+3000.example. 5M IN A 10.0.1.90
+3000.example. 5M IN A 10.0.1.91
+3000.example. 5M IN A 10.0.1.92
+3000.example. 5M IN A 10.0.1.93
+3000.example. 5M IN A 10.0.1.94
+3000.example. 5M IN A 10.0.1.95
+3000.example. 5M IN A 10.0.1.96
+3000.example. 5M IN A 10.0.1.97
+3000.example. 5M IN A 10.0.1.98
+3000.example. 5M IN A 10.0.1.99
+3000.example. 5M IN A 10.0.1.100
+3000.example. 5M IN A 10.0.1.101
+3000.example. 5M IN A 10.0.1.102
+3000.example. 5M IN A 10.0.1.103
+3000.example. 5M IN A 10.0.1.104
+3000.example. 5M IN A 10.0.1.105
+3000.example. 5M IN A 10.0.1.106
+3000.example. 5M IN A 10.0.1.107
+3000.example. 5M IN A 10.0.1.108
+3000.example. 5M IN A 10.0.1.109
+3000.example. 5M IN A 10.0.1.110
+3000.example. 5M IN A 10.0.1.111
+3000.example. 5M IN A 10.0.1.112
+3000.example. 5M IN A 10.0.1.113
+3000.example. 5M IN A 10.0.1.114
+3000.example. 5M IN A 10.0.1.115
+3000.example. 5M IN A 10.0.1.116
+3000.example. 5M IN A 10.0.1.117
+3000.example. 5M IN A 10.0.1.118
+3000.example. 5M IN A 10.0.1.119
+3000.example. 5M IN A 10.0.1.120
+3000.example. 5M IN A 10.0.1.121
+3000.example. 5M IN A 10.0.1.122
+3000.example. 5M IN A 10.0.1.123
+3000.example. 5M IN A 10.0.1.124
+3000.example. 5M IN A 10.0.1.125
+3000.example. 5M IN A 10.0.1.126
+3000.example. 5M IN A 10.0.1.127
+3000.example. 5M IN A 10.0.1.128
+3000.example. 5M IN A 10.0.1.129
+3000.example. 5M IN A 10.0.1.130
+3000.example. 5M IN A 10.0.1.131
+3000.example. 5M IN A 10.0.1.132
+3000.example. 5M IN A 10.0.1.133
+3000.example. 5M IN A 10.0.1.134
+3000.example. 5M IN A 10.0.1.135
+3000.example. 5M IN A 10.0.1.136
+3000.example. 5M IN A 10.0.1.137
+3000.example. 5M IN A 10.0.1.138
+3000.example. 5M IN A 10.0.1.139
+3000.example. 5M IN A 10.0.1.140
+3000.example. 5M IN A 10.0.1.141
+3000.example. 5M IN A 10.0.1.142
+3000.example. 5M IN A 10.0.1.143
+3000.example. 5M IN A 10.0.1.144
+3000.example. 5M IN A 10.0.1.145
+3000.example. 5M IN A 10.0.1.146
+3000.example. 5M IN A 10.0.1.147
+3000.example. 5M IN A 10.0.1.148
+3000.example. 5M IN A 10.0.1.149
+3000.example. 5M IN A 10.0.1.150
+3000.example. 5M IN A 10.0.1.151
+3000.example. 5M IN A 10.0.1.152
+3000.example. 5M IN A 10.0.1.153
+3000.example. 5M IN A 10.0.1.154
+3000.example. 5M IN A 10.0.1.155
+3000.example. 5M IN A 10.0.1.156
+3000.example. 5M IN A 10.0.1.157
+3000.example. 5M IN A 10.0.1.158
+3000.example. 5M IN A 10.0.1.159
+3000.example. 5M IN A 10.0.1.160
+3000.example. 5M IN A 10.0.1.161
+3000.example. 5M IN A 10.0.1.162
+3000.example. 5M IN A 10.0.1.163
+3000.example. 5M IN A 10.0.1.164
+3000.example. 5M IN A 10.0.1.165
+3000.example. 5M IN A 10.0.1.166
+3000.example. 5M IN A 10.0.1.167
+3000.example. 5M IN A 10.0.1.168
+3000.example. 5M IN A 10.0.1.169
+3000.example. 5M IN A 10.0.1.170
+3000.example. 5M IN A 10.0.1.171
+3000.example. 5M IN A 10.0.1.172
+3000.example. 5M IN A 10.0.1.173
+3000.example. 5M IN A 10.0.1.174
+3000.example. 5M IN A 10.0.1.175
+3000.example. 5M IN A 10.0.1.176
+3000.example. 5M IN A 10.0.1.177
+3000.example. 5M IN A 10.0.1.178
+3000.example. 5M IN A 10.0.1.179
+3000.example. 5M IN A 10.0.1.180
+3000.example. 5M IN A 10.0.1.181
+3000.example. 5M IN A 10.0.1.182
+3000.example. 5M IN A 10.0.1.183
+3000.example. 5M IN A 10.0.1.184
+3000.example. 5M IN A 10.0.1.185
+3000.example. 5M IN A 10.0.1.186
+3000.example. 5M IN A 10.0.1.187
+3000.example. 5M IN A 10.0.1.188
+3000.example. 5M IN A 10.0.1.189
+3000.example. 5M IN A 10.0.1.190
+3000.example. 5M IN A 10.0.1.191
+3000.example. 5M IN A 10.0.1.192
+3000.example. 5M IN A 10.0.1.193
+3000.example. 5M IN A 10.0.1.194
+3000.example. 5M IN A 10.0.1.195
+3000.example. 5M IN A 10.0.1.196
+3000.example. 5M IN A 10.0.1.197
+3000.example. 5M IN A 10.0.1.198
+3000.example. 5M IN A 10.0.1.199
+3000.example. 5M IN A 10.0.1.200
+3000.example. 5M IN A 10.0.1.201
+3000.example. 5M IN A 10.0.1.202
+3000.example. 5M IN A 10.0.1.203
+3000.example. 5M IN A 10.0.1.204
+3000.example. 5M IN A 10.0.1.205
+3000.example. 5M IN A 10.0.1.206
+3000.example. 5M IN A 10.0.1.207
+3000.example. 5M IN A 10.0.1.208
+3000.example. 5M IN A 10.0.1.209
+3000.example. 5M IN A 10.0.1.210
+3000.example. 5M IN A 10.0.1.211
+3000.example. 5M IN A 10.0.1.212
+3000.example. 5M IN A 10.0.1.213
+3000.example. 5M IN A 10.0.1.214
+3000.example. 5M IN A 10.0.1.215
+3000.example. 5M IN A 10.0.1.216
+3000.example. 5M IN A 10.0.1.217
+3000.example. 5M IN A 10.0.1.218
+3000.example. 5M IN A 10.0.1.219
+3000.example. 5M IN A 10.0.1.220
+3000.example. 5M IN A 10.0.1.221
+3000.example. 5M IN A 10.0.1.222
+3000.example. 5M IN A 10.0.1.223
+3000.example. 5M IN A 10.0.1.224
+3000.example. 5M IN A 10.0.1.225
+3000.example. 5M IN A 10.0.1.226
+3000.example. 5M IN A 10.0.1.227
+3000.example. 5M IN A 10.0.1.228
+3000.example. 5M IN A 10.0.1.229
+3000.example. 5M IN A 10.0.1.230
+3000.example. 5M IN A 10.0.1.231
+3000.example. 5M IN A 10.0.1.232
+3000.example. 5M IN A 10.0.1.233
+3000.example. 5M IN A 10.0.1.234
+3000.example. 5M IN A 10.0.1.235
+3000.example. 5M IN A 10.0.1.236
+3000.example. 5M IN A 10.0.1.237
+3000.example. 5M IN A 10.0.1.238
+3000.example. 5M IN A 10.0.1.239
+3000.example. 5M IN A 10.0.1.240
+3000.example. 5M IN A 10.0.1.241
+3000.example. 5M IN A 10.0.1.242
+3000.example. 5M IN A 10.0.1.243
+3000.example. 5M IN A 10.0.1.244
+3000.example. 5M IN A 10.0.1.245
+3000.example. 5M IN A 10.0.1.246
+3000.example. 5M IN A 10.0.1.247
+3000.example. 5M IN A 10.0.1.248
+3000.example. 5M IN A 10.0.1.249
+3000.example. 5M IN A 10.0.1.250
+3000.example. 5M IN A 10.0.1.251
+3000.example. 5M IN A 10.0.1.252
+3000.example. 5M IN A 10.0.1.253
+3000.example. 5M IN A 10.0.1.254
+3000.example. 5M IN A 10.0.1.255
+3000.example. 5M IN A 10.0.2.0
+3000.example. 5M IN A 10.0.2.1
+3000.example. 5M IN A 10.0.2.2
+3000.example. 5M IN A 10.0.2.3
+3000.example. 5M IN A 10.0.2.4
+3000.example. 5M IN A 10.0.2.5
+3000.example. 5M IN A 10.0.2.6
+3000.example. 5M IN A 10.0.2.7
+3000.example. 5M IN A 10.0.2.8
+3000.example. 5M IN A 10.0.2.9
+3000.example. 5M IN A 10.0.2.10
+3000.example. 5M IN A 10.0.2.11
+3000.example. 5M IN A 10.0.2.12
+3000.example. 5M IN A 10.0.2.13
+3000.example. 5M IN A 10.0.2.14
+3000.example. 5M IN A 10.0.2.15
+3000.example. 5M IN A 10.0.2.16
+3000.example. 5M IN A 10.0.2.17
+3000.example. 5M IN A 10.0.2.18
+3000.example. 5M IN A 10.0.2.19
+3000.example. 5M IN A 10.0.2.20
+3000.example. 5M IN A 10.0.2.21
+3000.example. 5M IN A 10.0.2.22
+3000.example. 5M IN A 10.0.2.23
+3000.example. 5M IN A 10.0.2.24
+3000.example. 5M IN A 10.0.2.25
+3000.example. 5M IN A 10.0.2.26
+3000.example. 5M IN A 10.0.2.27
+3000.example. 5M IN A 10.0.2.28
+3000.example. 5M IN A 10.0.2.29
+3000.example. 5M IN A 10.0.2.30
+3000.example. 5M IN A 10.0.2.31
+3000.example. 5M IN A 10.0.2.32
+3000.example. 5M IN A 10.0.2.33
+3000.example. 5M IN A 10.0.2.34
+3000.example. 5M IN A 10.0.2.35
+3000.example. 5M IN A 10.0.2.36
+3000.example. 5M IN A 10.0.2.37
+3000.example. 5M IN A 10.0.2.38
+3000.example. 5M IN A 10.0.2.39
+3000.example. 5M IN A 10.0.2.40
+3000.example. 5M IN A 10.0.2.41
+3000.example. 5M IN A 10.0.2.42
+3000.example. 5M IN A 10.0.2.43
+3000.example. 5M IN A 10.0.2.44
+3000.example. 5M IN A 10.0.2.45
+3000.example. 5M IN A 10.0.2.46
+3000.example. 5M IN A 10.0.2.47
+3000.example. 5M IN A 10.0.2.48
+3000.example. 5M IN A 10.0.2.49
+3000.example. 5M IN A 10.0.2.50
+3000.example. 5M IN A 10.0.2.51
+3000.example. 5M IN A 10.0.2.52
+3000.example. 5M IN A 10.0.2.53
+3000.example. 5M IN A 10.0.2.54
+3000.example. 5M IN A 10.0.2.55
+3000.example. 5M IN A 10.0.2.56
+3000.example. 5M IN A 10.0.2.57
+3000.example. 5M IN A 10.0.2.58
+3000.example. 5M IN A 10.0.2.59
+3000.example. 5M IN A 10.0.2.60
+3000.example. 5M IN A 10.0.2.61
+3000.example. 5M IN A 10.0.2.62
+3000.example. 5M IN A 10.0.2.63
+3000.example. 5M IN A 10.0.2.64
+3000.example. 5M IN A 10.0.2.65
+3000.example. 5M IN A 10.0.2.66
+3000.example. 5M IN A 10.0.2.67
+3000.example. 5M IN A 10.0.2.68
+3000.example. 5M IN A 10.0.2.69
+3000.example. 5M IN A 10.0.2.70
+3000.example. 5M IN A 10.0.2.71
+3000.example. 5M IN A 10.0.2.72
+3000.example. 5M IN A 10.0.2.73
+3000.example. 5M IN A 10.0.2.74
+3000.example. 5M IN A 10.0.2.75
+3000.example. 5M IN A 10.0.2.76
+3000.example. 5M IN A 10.0.2.77
+3000.example. 5M IN A 10.0.2.78
+3000.example. 5M IN A 10.0.2.79
+3000.example. 5M IN A 10.0.2.80
+3000.example. 5M IN A 10.0.2.81
+3000.example. 5M IN A 10.0.2.82
+3000.example. 5M IN A 10.0.2.83
+3000.example. 5M IN A 10.0.2.84
+3000.example. 5M IN A 10.0.2.85
+3000.example. 5M IN A 10.0.2.86
+3000.example. 5M IN A 10.0.2.87
+3000.example. 5M IN A 10.0.2.88
+3000.example. 5M IN A 10.0.2.89
+3000.example. 5M IN A 10.0.2.90
+3000.example. 5M IN A 10.0.2.91
+3000.example. 5M IN A 10.0.2.92
+3000.example. 5M IN A 10.0.2.93
+3000.example. 5M IN A 10.0.2.94
+3000.example. 5M IN A 10.0.2.95
+3000.example. 5M IN A 10.0.2.96
+3000.example. 5M IN A 10.0.2.97
+3000.example. 5M IN A 10.0.2.98
+3000.example. 5M IN A 10.0.2.99
+3000.example. 5M IN A 10.0.2.100
+3000.example. 5M IN A 10.0.2.101
+3000.example. 5M IN A 10.0.2.102
+3000.example. 5M IN A 10.0.2.103
+3000.example. 5M IN A 10.0.2.104
+3000.example. 5M IN A 10.0.2.105
+3000.example. 5M IN A 10.0.2.106
+3000.example. 5M IN A 10.0.2.107
+3000.example. 5M IN A 10.0.2.108
+3000.example. 5M IN A 10.0.2.109
+3000.example. 5M IN A 10.0.2.110
+3000.example. 5M IN A 10.0.2.111
+3000.example. 5M IN A 10.0.2.112
+3000.example. 5M IN A 10.0.2.113
+3000.example. 5M IN A 10.0.2.114
+3000.example. 5M IN A 10.0.2.115
+3000.example. 5M IN A 10.0.2.116
+3000.example. 5M IN A 10.0.2.117
+3000.example. 5M IN A 10.0.2.118
+3000.example. 5M IN A 10.0.2.119
+3000.example. 5M IN A 10.0.2.120
+3000.example. 5M IN A 10.0.2.121
+3000.example. 5M IN A 10.0.2.122
+3000.example. 5M IN A 10.0.2.123
+3000.example. 5M IN A 10.0.2.124
+3000.example. 5M IN A 10.0.2.125
+3000.example. 5M IN A 10.0.2.126
+3000.example. 5M IN A 10.0.2.127
+3000.example. 5M IN A 10.0.2.128
+3000.example. 5M IN A 10.0.2.129
+3000.example. 5M IN A 10.0.2.130
+3000.example. 5M IN A 10.0.2.131
+3000.example. 5M IN A 10.0.2.132
+3000.example. 5M IN A 10.0.2.133
+3000.example. 5M IN A 10.0.2.134
+3000.example. 5M IN A 10.0.2.135
+3000.example. 5M IN A 10.0.2.136
+3000.example. 5M IN A 10.0.2.137
+3000.example. 5M IN A 10.0.2.138
+3000.example. 5M IN A 10.0.2.139
+3000.example. 5M IN A 10.0.2.140
+3000.example. 5M IN A 10.0.2.141
+3000.example. 5M IN A 10.0.2.142
+3000.example. 5M IN A 10.0.2.143
+3000.example. 5M IN A 10.0.2.144
+3000.example. 5M IN A 10.0.2.145
+3000.example. 5M IN A 10.0.2.146
+3000.example. 5M IN A 10.0.2.147
+3000.example. 5M IN A 10.0.2.148
+3000.example. 5M IN A 10.0.2.149
+3000.example. 5M IN A 10.0.2.150
+3000.example. 5M IN A 10.0.2.151
+3000.example. 5M IN A 10.0.2.152
+3000.example. 5M IN A 10.0.2.153
+3000.example. 5M IN A 10.0.2.154
+3000.example. 5M IN A 10.0.2.155
+3000.example. 5M IN A 10.0.2.156
+3000.example. 5M IN A 10.0.2.157
+3000.example. 5M IN A 10.0.2.158
+3000.example. 5M IN A 10.0.2.159
+3000.example. 5M IN A 10.0.2.160
+3000.example. 5M IN A 10.0.2.161
+3000.example. 5M IN A 10.0.2.162
+3000.example. 5M IN A 10.0.2.163
+3000.example. 5M IN A 10.0.2.164
+3000.example. 5M IN A 10.0.2.165
+3000.example. 5M IN A 10.0.2.166
+3000.example. 5M IN A 10.0.2.167
+3000.example. 5M IN A 10.0.2.168
+3000.example. 5M IN A 10.0.2.169
+3000.example. 5M IN A 10.0.2.170
+3000.example. 5M IN A 10.0.2.171
+3000.example. 5M IN A 10.0.2.172
+3000.example. 5M IN A 10.0.2.173
+3000.example. 5M IN A 10.0.2.174
+3000.example. 5M IN A 10.0.2.175
+3000.example. 5M IN A 10.0.2.176
+3000.example. 5M IN A 10.0.2.177
+3000.example. 5M IN A 10.0.2.178
+3000.example. 5M IN A 10.0.2.179
+3000.example. 5M IN A 10.0.2.180
+3000.example. 5M IN A 10.0.2.181
+3000.example. 5M IN A 10.0.2.182
+3000.example. 5M IN A 10.0.2.183
+3000.example. 5M IN A 10.0.2.184
+3000.example. 5M IN A 10.0.2.185
+3000.example. 5M IN A 10.0.2.186
+3000.example. 5M IN A 10.0.2.187
+3000.example. 5M IN A 10.0.2.188
+3000.example. 5M IN A 10.0.2.189
+3000.example. 5M IN A 10.0.2.190
+3000.example. 5M IN A 10.0.2.191
+3000.example. 5M IN A 10.0.2.192
+3000.example. 5M IN A 10.0.2.193
+3000.example. 5M IN A 10.0.2.194
+3000.example. 5M IN A 10.0.2.195
+3000.example. 5M IN A 10.0.2.196
+3000.example. 5M IN A 10.0.2.197
+3000.example. 5M IN A 10.0.2.198
+3000.example. 5M IN A 10.0.2.199
+3000.example. 5M IN A 10.0.2.200
+3000.example. 5M IN A 10.0.2.201
+3000.example. 5M IN A 10.0.2.202
+3000.example. 5M IN A 10.0.2.203
+3000.example. 5M IN A 10.0.2.204
+3000.example. 5M IN A 10.0.2.205
+3000.example. 5M IN A 10.0.2.206
+3000.example. 5M IN A 10.0.2.207
+3000.example. 5M IN A 10.0.2.208
+3000.example. 5M IN A 10.0.2.209
+3000.example. 5M IN A 10.0.2.210
+3000.example. 5M IN A 10.0.2.211
+3000.example. 5M IN A 10.0.2.212
+3000.example. 5M IN A 10.0.2.213
+3000.example. 5M IN A 10.0.2.214
+3000.example. 5M IN A 10.0.2.215
+3000.example. 5M IN A 10.0.2.216
+3000.example. 5M IN A 10.0.2.217
+3000.example. 5M IN A 10.0.2.218
+3000.example. 5M IN A 10.0.2.219
+3000.example. 5M IN A 10.0.2.220
+3000.example. 5M IN A 10.0.2.221
+3000.example. 5M IN A 10.0.2.222
+3000.example. 5M IN A 10.0.2.223
+3000.example. 5M IN A 10.0.2.224
+3000.example. 5M IN A 10.0.2.225
+3000.example. 5M IN A 10.0.2.226
+3000.example. 5M IN A 10.0.2.227
+3000.example. 5M IN A 10.0.2.228
+3000.example. 5M IN A 10.0.2.229
+3000.example. 5M IN A 10.0.2.230
+3000.example. 5M IN A 10.0.2.231
+3000.example. 5M IN A 10.0.2.232
+3000.example. 5M IN A 10.0.2.233
+3000.example. 5M IN A 10.0.2.234
+3000.example. 5M IN A 10.0.2.235
+3000.example. 5M IN A 10.0.2.236
+3000.example. 5M IN A 10.0.2.237
+3000.example. 5M IN A 10.0.2.238
+3000.example. 5M IN A 10.0.2.239
+3000.example. 5M IN A 10.0.2.240
+3000.example. 5M IN A 10.0.2.241
+3000.example. 5M IN A 10.0.2.242
+3000.example. 5M IN A 10.0.2.243
+3000.example. 5M IN A 10.0.2.244
+3000.example. 5M IN A 10.0.2.245
+3000.example. 5M IN A 10.0.2.246
+3000.example. 5M IN A 10.0.2.247
+3000.example. 5M IN A 10.0.2.248
+3000.example. 5M IN A 10.0.2.249
+3000.example. 5M IN A 10.0.2.250
+3000.example. 5M IN A 10.0.2.251
+3000.example. 5M IN A 10.0.2.252
+3000.example. 5M IN A 10.0.2.253
+3000.example. 5M IN A 10.0.2.254
+3000.example. 5M IN A 10.0.2.255
+3000.example. 5M IN A 10.0.3.0
+3000.example. 5M IN A 10.0.3.1
+3000.example. 5M IN A 10.0.3.2
+3000.example. 5M IN A 10.0.3.3
+3000.example. 5M IN A 10.0.3.4
+3000.example. 5M IN A 10.0.3.5
+3000.example. 5M IN A 10.0.3.6
+3000.example. 5M IN A 10.0.3.7
+3000.example. 5M IN A 10.0.3.8
+3000.example. 5M IN A 10.0.3.9
+3000.example. 5M IN A 10.0.3.10
+3000.example. 5M IN A 10.0.3.11
+3000.example. 5M IN A 10.0.3.12
+3000.example. 5M IN A 10.0.3.13
+3000.example. 5M IN A 10.0.3.14
+3000.example. 5M IN A 10.0.3.15
+3000.example. 5M IN A 10.0.3.16
+3000.example. 5M IN A 10.0.3.17
+3000.example. 5M IN A 10.0.3.18
+3000.example. 5M IN A 10.0.3.19
+3000.example. 5M IN A 10.0.3.20
+3000.example. 5M IN A 10.0.3.21
+3000.example. 5M IN A 10.0.3.22
+3000.example. 5M IN A 10.0.3.23
+3000.example. 5M IN A 10.0.3.24
+3000.example. 5M IN A 10.0.3.25
+3000.example. 5M IN A 10.0.3.26
+3000.example. 5M IN A 10.0.3.27
+3000.example. 5M IN A 10.0.3.28
+3000.example. 5M IN A 10.0.3.29
+3000.example. 5M IN A 10.0.3.30
+3000.example. 5M IN A 10.0.3.31
+3000.example. 5M IN A 10.0.3.32
+3000.example. 5M IN A 10.0.3.33
+3000.example. 5M IN A 10.0.3.34
+3000.example. 5M IN A 10.0.3.35
+3000.example. 5M IN A 10.0.3.36
+3000.example. 5M IN A 10.0.3.37
+3000.example. 5M IN A 10.0.3.38
+3000.example. 5M IN A 10.0.3.39
+3000.example. 5M IN A 10.0.3.40
+3000.example. 5M IN A 10.0.3.41
+3000.example. 5M IN A 10.0.3.42
+3000.example. 5M IN A 10.0.3.43
+3000.example. 5M IN A 10.0.3.44
+3000.example. 5M IN A 10.0.3.45
+3000.example. 5M IN A 10.0.3.46
+3000.example. 5M IN A 10.0.3.47
+3000.example. 5M IN A 10.0.3.48
+3000.example. 5M IN A 10.0.3.49
+3000.example. 5M IN A 10.0.3.50
+3000.example. 5M IN A 10.0.3.51
+3000.example. 5M IN A 10.0.3.52
+3000.example. 5M IN A 10.0.3.53
+3000.example. 5M IN A 10.0.3.54
+3000.example. 5M IN A 10.0.3.55
+3000.example. 5M IN A 10.0.3.56
+3000.example. 5M IN A 10.0.3.57
+3000.example. 5M IN A 10.0.3.58
+3000.example. 5M IN A 10.0.3.59
+3000.example. 5M IN A 10.0.3.60
+3000.example. 5M IN A 10.0.3.61
+3000.example. 5M IN A 10.0.3.62
+3000.example. 5M IN A 10.0.3.63
+3000.example. 5M IN A 10.0.3.64
+3000.example. 5M IN A 10.0.3.65
+3000.example. 5M IN A 10.0.3.66
+3000.example. 5M IN A 10.0.3.67
+3000.example. 5M IN A 10.0.3.68
+3000.example. 5M IN A 10.0.3.69
+3000.example. 5M IN A 10.0.3.70
+3000.example. 5M IN A 10.0.3.71
+3000.example. 5M IN A 10.0.3.72
+3000.example. 5M IN A 10.0.3.73
+3000.example. 5M IN A 10.0.3.74
+3000.example. 5M IN A 10.0.3.75
+3000.example. 5M IN A 10.0.3.76
+3000.example. 5M IN A 10.0.3.77
+3000.example. 5M IN A 10.0.3.78
+3000.example. 5M IN A 10.0.3.79
+3000.example. 5M IN A 10.0.3.80
+3000.example. 5M IN A 10.0.3.81
+3000.example. 5M IN A 10.0.3.82
+3000.example. 5M IN A 10.0.3.83
+3000.example. 5M IN A 10.0.3.84
+3000.example. 5M IN A 10.0.3.85
+3000.example. 5M IN A 10.0.3.86
+3000.example. 5M IN A 10.0.3.87
+3000.example. 5M IN A 10.0.3.88
+3000.example. 5M IN A 10.0.3.89
+3000.example. 5M IN A 10.0.3.90
+3000.example. 5M IN A 10.0.3.91
+3000.example. 5M IN A 10.0.3.92
+3000.example. 5M IN A 10.0.3.93
+3000.example. 5M IN A 10.0.3.94
+3000.example. 5M IN A 10.0.3.95
+3000.example. 5M IN A 10.0.3.96
+3000.example. 5M IN A 10.0.3.97
+3000.example. 5M IN A 10.0.3.98
+3000.example. 5M IN A 10.0.3.99
+3000.example. 5M IN A 10.0.3.100
+3000.example. 5M IN A 10.0.3.101
+3000.example. 5M IN A 10.0.3.102
+3000.example. 5M IN A 10.0.3.103
+3000.example. 5M IN A 10.0.3.104
+3000.example. 5M IN A 10.0.3.105
+3000.example. 5M IN A 10.0.3.106
+3000.example. 5M IN A 10.0.3.107
+3000.example. 5M IN A 10.0.3.108
+3000.example. 5M IN A 10.0.3.109
+3000.example. 5M IN A 10.0.3.110
+3000.example. 5M IN A 10.0.3.111
+3000.example. 5M IN A 10.0.3.112
+3000.example. 5M IN A 10.0.3.113
+3000.example. 5M IN A 10.0.3.114
+3000.example. 5M IN A 10.0.3.115
+3000.example. 5M IN A 10.0.3.116
+3000.example. 5M IN A 10.0.3.117
+3000.example. 5M IN A 10.0.3.118
+3000.example. 5M IN A 10.0.3.119
+3000.example. 5M IN A 10.0.3.120
+3000.example. 5M IN A 10.0.3.121
+3000.example. 5M IN A 10.0.3.122
+3000.example. 5M IN A 10.0.3.123
+3000.example. 5M IN A 10.0.3.124
+3000.example. 5M IN A 10.0.3.125
+3000.example. 5M IN A 10.0.3.126
+3000.example. 5M IN A 10.0.3.127
+3000.example. 5M IN A 10.0.3.128
+3000.example. 5M IN A 10.0.3.129
+3000.example. 5M IN A 10.0.3.130
+3000.example. 5M IN A 10.0.3.131
+3000.example. 5M IN A 10.0.3.132
+3000.example. 5M IN A 10.0.3.133
+3000.example. 5M IN A 10.0.3.134
+3000.example. 5M IN A 10.0.3.135
+3000.example. 5M IN A 10.0.3.136
+3000.example. 5M IN A 10.0.3.137
+3000.example. 5M IN A 10.0.3.138
+3000.example. 5M IN A 10.0.3.139
+3000.example. 5M IN A 10.0.3.140
+3000.example. 5M IN A 10.0.3.141
+3000.example. 5M IN A 10.0.3.142
+3000.example. 5M IN A 10.0.3.143
+3000.example. 5M IN A 10.0.3.144
+3000.example. 5M IN A 10.0.3.145
+3000.example. 5M IN A 10.0.3.146
+3000.example. 5M IN A 10.0.3.147
+3000.example. 5M IN A 10.0.3.148
+3000.example. 5M IN A 10.0.3.149
+3000.example. 5M IN A 10.0.3.150
+3000.example. 5M IN A 10.0.3.151
+3000.example. 5M IN A 10.0.3.152
+3000.example. 5M IN A 10.0.3.153
+3000.example. 5M IN A 10.0.3.154
+3000.example. 5M IN A 10.0.3.155
+3000.example. 5M IN A 10.0.3.156
+3000.example. 5M IN A 10.0.3.157
+3000.example. 5M IN A 10.0.3.158
+3000.example. 5M IN A 10.0.3.159
+3000.example. 5M IN A 10.0.3.160
+3000.example. 5M IN A 10.0.3.161
+3000.example. 5M IN A 10.0.3.162
+3000.example. 5M IN A 10.0.3.163
+3000.example. 5M IN A 10.0.3.164
+3000.example. 5M IN A 10.0.3.165
+3000.example. 5M IN A 10.0.3.166
+3000.example. 5M IN A 10.0.3.167
+3000.example. 5M IN A 10.0.3.168
+3000.example. 5M IN A 10.0.3.169
+3000.example. 5M IN A 10.0.3.170
+3000.example. 5M IN A 10.0.3.171
+3000.example. 5M IN A 10.0.3.172
+3000.example. 5M IN A 10.0.3.173
+3000.example. 5M IN A 10.0.3.174
+3000.example. 5M IN A 10.0.3.175
+3000.example. 5M IN A 10.0.3.176
+3000.example. 5M IN A 10.0.3.177
+3000.example. 5M IN A 10.0.3.178
+3000.example. 5M IN A 10.0.3.179
+3000.example. 5M IN A 10.0.3.180
+3000.example. 5M IN A 10.0.3.181
+3000.example. 5M IN A 10.0.3.182
+3000.example. 5M IN A 10.0.3.183
+3000.example. 5M IN A 10.0.3.184
+3000.example. 5M IN A 10.0.3.185
+3000.example. 5M IN A 10.0.3.186
+3000.example. 5M IN A 10.0.3.187
+3000.example. 5M IN A 10.0.3.188
+3000.example. 5M IN A 10.0.3.189
+3000.example. 5M IN A 10.0.3.190
+3000.example. 5M IN A 10.0.3.191
+3000.example. 5M IN A 10.0.3.192
+3000.example. 5M IN A 10.0.3.193
+3000.example. 5M IN A 10.0.3.194
+3000.example. 5M IN A 10.0.3.195
+3000.example. 5M IN A 10.0.3.196
+3000.example. 5M IN A 10.0.3.197
+3000.example. 5M IN A 10.0.3.198
+3000.example. 5M IN A 10.0.3.199
+3000.example. 5M IN A 10.0.3.200
+3000.example. 5M IN A 10.0.3.201
+3000.example. 5M IN A 10.0.3.202
+3000.example. 5M IN A 10.0.3.203
+3000.example. 5M IN A 10.0.3.204
+3000.example. 5M IN A 10.0.3.205
+3000.example. 5M IN A 10.0.3.206
+3000.example. 5M IN A 10.0.3.207
+3000.example. 5M IN A 10.0.3.208
+3000.example. 5M IN A 10.0.3.209
+3000.example. 5M IN A 10.0.3.210
+3000.example. 5M IN A 10.0.3.211
+3000.example. 5M IN A 10.0.3.212
+3000.example. 5M IN A 10.0.3.213
+3000.example. 5M IN A 10.0.3.214
+3000.example. 5M IN A 10.0.3.215
+3000.example. 5M IN A 10.0.3.216
+3000.example. 5M IN A 10.0.3.217
+3000.example. 5M IN A 10.0.3.218
+3000.example. 5M IN A 10.0.3.219
+3000.example. 5M IN A 10.0.3.220
+3000.example. 5M IN A 10.0.3.221
+3000.example. 5M IN A 10.0.3.222
+3000.example. 5M IN A 10.0.3.223
+3000.example. 5M IN A 10.0.3.224
+3000.example. 5M IN A 10.0.3.225
+3000.example. 5M IN A 10.0.3.226
+3000.example. 5M IN A 10.0.3.227
+3000.example. 5M IN A 10.0.3.228
+3000.example. 5M IN A 10.0.3.229
+3000.example. 5M IN A 10.0.3.230
+3000.example. 5M IN A 10.0.3.231
+3000.example. 5M IN A 10.0.3.232
+3000.example. 5M IN A 10.0.3.233
+3000.example. 5M IN A 10.0.3.234
+3000.example. 5M IN A 10.0.3.235
+3000.example. 5M IN A 10.0.3.236
+3000.example. 5M IN A 10.0.3.237
+3000.example. 5M IN A 10.0.3.238
+3000.example. 5M IN A 10.0.3.239
+3000.example. 5M IN A 10.0.3.240
+3000.example. 5M IN A 10.0.3.241
+3000.example. 5M IN A 10.0.3.242
+3000.example. 5M IN A 10.0.3.243
+3000.example. 5M IN A 10.0.3.244
+3000.example. 5M IN A 10.0.3.245
+3000.example. 5M IN A 10.0.3.246
+3000.example. 5M IN A 10.0.3.247
+3000.example. 5M IN A 10.0.3.248
+3000.example. 5M IN A 10.0.3.249
+3000.example. 5M IN A 10.0.3.250
+3000.example. 5M IN A 10.0.3.251
+3000.example. 5M IN A 10.0.3.252
+3000.example. 5M IN A 10.0.3.253
+3000.example. 5M IN A 10.0.3.254
+3000.example. 5M IN A 10.0.3.255
+3000.example. 5M IN A 10.0.4.0
+3000.example. 5M IN A 10.0.4.1
+3000.example. 5M IN A 10.0.4.2
+3000.example. 5M IN A 10.0.4.3
+3000.example. 5M IN A 10.0.4.4
+3000.example. 5M IN A 10.0.4.5
+3000.example. 5M IN A 10.0.4.6
+3000.example. 5M IN A 10.0.4.7
+3000.example. 5M IN A 10.0.4.8
+3000.example. 5M IN A 10.0.4.9
+3000.example. 5M IN A 10.0.4.10
+3000.example. 5M IN A 10.0.4.11
+3000.example. 5M IN A 10.0.4.12
+3000.example. 5M IN A 10.0.4.13
+3000.example. 5M IN A 10.0.4.14
+3000.example. 5M IN A 10.0.4.15
+3000.example. 5M IN A 10.0.4.16
+3000.example. 5M IN A 10.0.4.17
+3000.example. 5M IN A 10.0.4.18
+3000.example. 5M IN A 10.0.4.19
+3000.example. 5M IN A 10.0.4.20
+3000.example. 5M IN A 10.0.4.21
+3000.example. 5M IN A 10.0.4.22
+3000.example. 5M IN A 10.0.4.23
+3000.example. 5M IN A 10.0.4.24
+3000.example. 5M IN A 10.0.4.25
+3000.example. 5M IN A 10.0.4.26
+3000.example. 5M IN A 10.0.4.27
+3000.example. 5M IN A 10.0.4.28
+3000.example. 5M IN A 10.0.4.29
+3000.example. 5M IN A 10.0.4.30
+3000.example. 5M IN A 10.0.4.31
+3000.example. 5M IN A 10.0.4.32
+3000.example. 5M IN A 10.0.4.33
+3000.example. 5M IN A 10.0.4.34
+3000.example. 5M IN A 10.0.4.35
+3000.example. 5M IN A 10.0.4.36
+3000.example. 5M IN A 10.0.4.37
+3000.example. 5M IN A 10.0.4.38
+3000.example. 5M IN A 10.0.4.39
+3000.example. 5M IN A 10.0.4.40
+3000.example. 5M IN A 10.0.4.41
+3000.example. 5M IN A 10.0.4.42
+3000.example. 5M IN A 10.0.4.43
+3000.example. 5M IN A 10.0.4.44
+3000.example. 5M IN A 10.0.4.45
+3000.example. 5M IN A 10.0.4.46
+3000.example. 5M IN A 10.0.4.47
+3000.example. 5M IN A 10.0.4.48
+3000.example. 5M IN A 10.0.4.49
+3000.example. 5M IN A 10.0.4.50
+3000.example. 5M IN A 10.0.4.51
+3000.example. 5M IN A 10.0.4.52
+3000.example. 5M IN A 10.0.4.53
+3000.example. 5M IN A 10.0.4.54
+3000.example. 5M IN A 10.0.4.55
+3000.example. 5M IN A 10.0.4.56
+3000.example. 5M IN A 10.0.4.57
+3000.example. 5M IN A 10.0.4.58
+3000.example. 5M IN A 10.0.4.59
+3000.example. 5M IN A 10.0.4.60
+3000.example. 5M IN A 10.0.4.61
+3000.example. 5M IN A 10.0.4.62
+3000.example. 5M IN A 10.0.4.63
+3000.example. 5M IN A 10.0.4.64
+3000.example. 5M IN A 10.0.4.65
+3000.example. 5M IN A 10.0.4.66
+3000.example. 5M IN A 10.0.4.67
+3000.example. 5M IN A 10.0.4.68
+3000.example. 5M IN A 10.0.4.69
+3000.example. 5M IN A 10.0.4.70
+3000.example. 5M IN A 10.0.4.71
+3000.example. 5M IN A 10.0.4.72
+3000.example. 5M IN A 10.0.4.73
+3000.example. 5M IN A 10.0.4.74
+3000.example. 5M IN A 10.0.4.75
+3000.example. 5M IN A 10.0.4.76
+3000.example. 5M IN A 10.0.4.77
+3000.example. 5M IN A 10.0.4.78
+3000.example. 5M IN A 10.0.4.79
+3000.example. 5M IN A 10.0.4.80
+3000.example. 5M IN A 10.0.4.81
+3000.example. 5M IN A 10.0.4.82
+3000.example. 5M IN A 10.0.4.83
+3000.example. 5M IN A 10.0.4.84
+3000.example. 5M IN A 10.0.4.85
+3000.example. 5M IN A 10.0.4.86
+3000.example. 5M IN A 10.0.4.87
+3000.example. 5M IN A 10.0.4.88
+3000.example. 5M IN A 10.0.4.89
+3000.example. 5M IN A 10.0.4.90
+3000.example. 5M IN A 10.0.4.91
+3000.example. 5M IN A 10.0.4.92
+3000.example. 5M IN A 10.0.4.93
+3000.example. 5M IN A 10.0.4.94
+3000.example. 5M IN A 10.0.4.95
+3000.example. 5M IN A 10.0.4.96
+3000.example. 5M IN A 10.0.4.97
+3000.example. 5M IN A 10.0.4.98
+3000.example. 5M IN A 10.0.4.99
+3000.example. 5M IN A 10.0.4.100
+3000.example. 5M IN A 10.0.4.101
+3000.example. 5M IN A 10.0.4.102
+3000.example. 5M IN A 10.0.4.103
+3000.example. 5M IN A 10.0.4.104
+3000.example. 5M IN A 10.0.4.105
+3000.example. 5M IN A 10.0.4.106
+3000.example. 5M IN A 10.0.4.107
+3000.example. 5M IN A 10.0.4.108
+3000.example. 5M IN A 10.0.4.109
+3000.example. 5M IN A 10.0.4.110
+3000.example. 5M IN A 10.0.4.111
+3000.example. 5M IN A 10.0.4.112
+3000.example. 5M IN A 10.0.4.113
+3000.example. 5M IN A 10.0.4.114
+3000.example. 5M IN A 10.0.4.115
+3000.example. 5M IN A 10.0.4.116
+3000.example. 5M IN A 10.0.4.117
+3000.example. 5M IN A 10.0.4.118
+3000.example. 5M IN A 10.0.4.119
+3000.example. 5M IN A 10.0.4.120
+3000.example. 5M IN A 10.0.4.121
+3000.example. 5M IN A 10.0.4.122
+3000.example. 5M IN A 10.0.4.123
+3000.example. 5M IN A 10.0.4.124
+3000.example. 5M IN A 10.0.4.125
+3000.example. 5M IN A 10.0.4.126
+3000.example. 5M IN A 10.0.4.127
+3000.example. 5M IN A 10.0.4.128
+3000.example. 5M IN A 10.0.4.129
+3000.example. 5M IN A 10.0.4.130
+3000.example. 5M IN A 10.0.4.131
+3000.example. 5M IN A 10.0.4.132
+3000.example. 5M IN A 10.0.4.133
+3000.example. 5M IN A 10.0.4.134
+3000.example. 5M IN A 10.0.4.135
+3000.example. 5M IN A 10.0.4.136
+3000.example. 5M IN A 10.0.4.137
+3000.example. 5M IN A 10.0.4.138
+3000.example. 5M IN A 10.0.4.139
+3000.example. 5M IN A 10.0.4.140
+3000.example. 5M IN A 10.0.4.141
+3000.example. 5M IN A 10.0.4.142
+3000.example. 5M IN A 10.0.4.143
+3000.example. 5M IN A 10.0.4.144
+3000.example. 5M IN A 10.0.4.145
+3000.example. 5M IN A 10.0.4.146
+3000.example. 5M IN A 10.0.4.147
+3000.example. 5M IN A 10.0.4.148
+3000.example. 5M IN A 10.0.4.149
+3000.example. 5M IN A 10.0.4.150
+3000.example. 5M IN A 10.0.4.151
+3000.example. 5M IN A 10.0.4.152
+3000.example. 5M IN A 10.0.4.153
+3000.example. 5M IN A 10.0.4.154
+3000.example. 5M IN A 10.0.4.155
+3000.example. 5M IN A 10.0.4.156
+3000.example. 5M IN A 10.0.4.157
+3000.example. 5M IN A 10.0.4.158
+3000.example. 5M IN A 10.0.4.159
+3000.example. 5M IN A 10.0.4.160
+3000.example. 5M IN A 10.0.4.161
+3000.example. 5M IN A 10.0.4.162
+3000.example. 5M IN A 10.0.4.163
+3000.example. 5M IN A 10.0.4.164
+3000.example. 5M IN A 10.0.4.165
+3000.example. 5M IN A 10.0.4.166
+3000.example. 5M IN A 10.0.4.167
+3000.example. 5M IN A 10.0.4.168
+3000.example. 5M IN A 10.0.4.169
+3000.example. 5M IN A 10.0.4.170
+3000.example. 5M IN A 10.0.4.171
+3000.example. 5M IN A 10.0.4.172
+3000.example. 5M IN A 10.0.4.173
+3000.example. 5M IN A 10.0.4.174
+3000.example. 5M IN A 10.0.4.175
+3000.example. 5M IN A 10.0.4.176
+3000.example. 5M IN A 10.0.4.177
+3000.example. 5M IN A 10.0.4.178
+3000.example. 5M IN A 10.0.4.179
+3000.example. 5M IN A 10.0.4.180
+3000.example. 5M IN A 10.0.4.181
+3000.example. 5M IN A 10.0.4.182
+3000.example. 5M IN A 10.0.4.183
+3000.example. 5M IN A 10.0.4.184
+3000.example. 5M IN A 10.0.4.185
+3000.example. 5M IN A 10.0.4.186
+3000.example. 5M IN A 10.0.4.187
+3000.example. 5M IN A 10.0.4.188
+3000.example. 5M IN A 10.0.4.189
+3000.example. 5M IN A 10.0.4.190
+3000.example. 5M IN A 10.0.4.191
+3000.example. 5M IN A 10.0.4.192
+3000.example. 5M IN A 10.0.4.193
+3000.example. 5M IN A 10.0.4.194
+3000.example. 5M IN A 10.0.4.195
+3000.example. 5M IN A 10.0.4.196
+3000.example. 5M IN A 10.0.4.197
+3000.example. 5M IN A 10.0.4.198
+3000.example. 5M IN A 10.0.4.199
+3000.example. 5M IN A 10.0.4.200
+3000.example. 5M IN A 10.0.4.201
+3000.example. 5M IN A 10.0.4.202
+3000.example. 5M IN A 10.0.4.203
+3000.example. 5M IN A 10.0.4.204
+3000.example. 5M IN A 10.0.4.205
+3000.example. 5M IN A 10.0.4.206
+3000.example. 5M IN A 10.0.4.207
+3000.example. 5M IN A 10.0.4.208
+3000.example. 5M IN A 10.0.4.209
+3000.example. 5M IN A 10.0.4.210
+3000.example. 5M IN A 10.0.4.211
+3000.example. 5M IN A 10.0.4.212
+3000.example. 5M IN A 10.0.4.213
+3000.example. 5M IN A 10.0.4.214
+3000.example. 5M IN A 10.0.4.215
+3000.example. 5M IN A 10.0.4.216
+3000.example. 5M IN A 10.0.4.217
+3000.example. 5M IN A 10.0.4.218
+3000.example. 5M IN A 10.0.4.219
+3000.example. 5M IN A 10.0.4.220
+3000.example. 5M IN A 10.0.4.221
+3000.example. 5M IN A 10.0.4.222
+3000.example. 5M IN A 10.0.4.223
+3000.example. 5M IN A 10.0.4.224
+3000.example. 5M IN A 10.0.4.225
+3000.example. 5M IN A 10.0.4.226
+3000.example. 5M IN A 10.0.4.227
+3000.example. 5M IN A 10.0.4.228
+3000.example. 5M IN A 10.0.4.229
+3000.example. 5M IN A 10.0.4.230
+3000.example. 5M IN A 10.0.4.231
+3000.example. 5M IN A 10.0.4.232
+3000.example. 5M IN A 10.0.4.233
+3000.example. 5M IN A 10.0.4.234
+3000.example. 5M IN A 10.0.4.235
+3000.example. 5M IN A 10.0.4.236
+3000.example. 5M IN A 10.0.4.237
+3000.example. 5M IN A 10.0.4.238
+3000.example. 5M IN A 10.0.4.239
+3000.example. 5M IN A 10.0.4.240
+3000.example. 5M IN A 10.0.4.241
+3000.example. 5M IN A 10.0.4.242
+3000.example. 5M IN A 10.0.4.243
+3000.example. 5M IN A 10.0.4.244
+3000.example. 5M IN A 10.0.4.245
+3000.example. 5M IN A 10.0.4.246
+3000.example. 5M IN A 10.0.4.247
+3000.example. 5M IN A 10.0.4.248
+3000.example. 5M IN A 10.0.4.249
+3000.example. 5M IN A 10.0.4.250
+3000.example. 5M IN A 10.0.4.251
+3000.example. 5M IN A 10.0.4.252
+3000.example. 5M IN A 10.0.4.253
+3000.example. 5M IN A 10.0.4.254
+3000.example. 5M IN A 10.0.4.255
+3000.example. 5M IN A 10.0.5.0
+3000.example. 5M IN A 10.0.5.1
+3000.example. 5M IN A 10.0.5.2
+3000.example. 5M IN A 10.0.5.3
+3000.example. 5M IN A 10.0.5.4
+3000.example. 5M IN A 10.0.5.5
+3000.example. 5M IN A 10.0.5.6
+3000.example. 5M IN A 10.0.5.7
+3000.example. 5M IN A 10.0.5.8
+3000.example. 5M IN A 10.0.5.9
+3000.example. 5M IN A 10.0.5.10
+3000.example. 5M IN A 10.0.5.11
+3000.example. 5M IN A 10.0.5.12
+3000.example. 5M IN A 10.0.5.13
+3000.example. 5M IN A 10.0.5.14
+3000.example. 5M IN A 10.0.5.15
+3000.example. 5M IN A 10.0.5.16
+3000.example. 5M IN A 10.0.5.17
+3000.example. 5M IN A 10.0.5.18
+3000.example. 5M IN A 10.0.5.19
+3000.example. 5M IN A 10.0.5.20
+3000.example. 5M IN A 10.0.5.21
+3000.example. 5M IN A 10.0.5.22
+3000.example. 5M IN A 10.0.5.23
+3000.example. 5M IN A 10.0.5.24
+3000.example. 5M IN A 10.0.5.25
+3000.example. 5M IN A 10.0.5.26
+3000.example. 5M IN A 10.0.5.27
+3000.example. 5M IN A 10.0.5.28
+3000.example. 5M IN A 10.0.5.29
+3000.example. 5M IN A 10.0.5.30
+3000.example. 5M IN A 10.0.5.31
+3000.example. 5M IN A 10.0.5.32
+3000.example. 5M IN A 10.0.5.33
+3000.example. 5M IN A 10.0.5.34
+3000.example. 5M IN A 10.0.5.35
+3000.example. 5M IN A 10.0.5.36
+3000.example. 5M IN A 10.0.5.37
+3000.example. 5M IN A 10.0.5.38
+3000.example. 5M IN A 10.0.5.39
+3000.example. 5M IN A 10.0.5.40
+3000.example. 5M IN A 10.0.5.41
+3000.example. 5M IN A 10.0.5.42
+3000.example. 5M IN A 10.0.5.43
+3000.example. 5M IN A 10.0.5.44
+3000.example. 5M IN A 10.0.5.45
+3000.example. 5M IN A 10.0.5.46
+3000.example. 5M IN A 10.0.5.47
+3000.example. 5M IN A 10.0.5.48
+3000.example. 5M IN A 10.0.5.49
+3000.example. 5M IN A 10.0.5.50
+3000.example. 5M IN A 10.0.5.51
+3000.example. 5M IN A 10.0.5.52
+3000.example. 5M IN A 10.0.5.53
+3000.example. 5M IN A 10.0.5.54
+3000.example. 5M IN A 10.0.5.55
+3000.example. 5M IN A 10.0.5.56
+3000.example. 5M IN A 10.0.5.57
+3000.example. 5M IN A 10.0.5.58
+3000.example. 5M IN A 10.0.5.59
+3000.example. 5M IN A 10.0.5.60
+3000.example. 5M IN A 10.0.5.61
+3000.example. 5M IN A 10.0.5.62
+3000.example. 5M IN A 10.0.5.63
+3000.example. 5M IN A 10.0.5.64
+3000.example. 5M IN A 10.0.5.65
+3000.example. 5M IN A 10.0.5.66
+3000.example. 5M IN A 10.0.5.67
+3000.example. 5M IN A 10.0.5.68
+3000.example. 5M IN A 10.0.5.69
+3000.example. 5M IN A 10.0.5.70
+3000.example. 5M IN A 10.0.5.71
+3000.example. 5M IN A 10.0.5.72
+3000.example. 5M IN A 10.0.5.73
+3000.example. 5M IN A 10.0.5.74
+3000.example. 5M IN A 10.0.5.75
+3000.example. 5M IN A 10.0.5.76
+3000.example. 5M IN A 10.0.5.77
+3000.example. 5M IN A 10.0.5.78
+3000.example. 5M IN A 10.0.5.79
+3000.example. 5M IN A 10.0.5.80
+3000.example. 5M IN A 10.0.5.81
+3000.example. 5M IN A 10.0.5.82
+3000.example. 5M IN A 10.0.5.83
+3000.example. 5M IN A 10.0.5.84
+3000.example. 5M IN A 10.0.5.85
+3000.example. 5M IN A 10.0.5.86
+3000.example. 5M IN A 10.0.5.87
+3000.example. 5M IN A 10.0.5.88
+3000.example. 5M IN A 10.0.5.89
+3000.example. 5M IN A 10.0.5.90
+3000.example. 5M IN A 10.0.5.91
+3000.example. 5M IN A 10.0.5.92
+3000.example. 5M IN A 10.0.5.93
+3000.example. 5M IN A 10.0.5.94
+3000.example. 5M IN A 10.0.5.95
+3000.example. 5M IN A 10.0.5.96
+3000.example. 5M IN A 10.0.5.97
+3000.example. 5M IN A 10.0.5.98
+3000.example. 5M IN A 10.0.5.99
+3000.example. 5M IN A 10.0.5.100
+3000.example. 5M IN A 10.0.5.101
+3000.example. 5M IN A 10.0.5.102
+3000.example. 5M IN A 10.0.5.103
+3000.example. 5M IN A 10.0.5.104
+3000.example. 5M IN A 10.0.5.105
+3000.example. 5M IN A 10.0.5.106
+3000.example. 5M IN A 10.0.5.107
+3000.example. 5M IN A 10.0.5.108
+3000.example. 5M IN A 10.0.5.109
+3000.example. 5M IN A 10.0.5.110
+3000.example. 5M IN A 10.0.5.111
+3000.example. 5M IN A 10.0.5.112
+3000.example. 5M IN A 10.0.5.113
+3000.example. 5M IN A 10.0.5.114
+3000.example. 5M IN A 10.0.5.115
+3000.example. 5M IN A 10.0.5.116
+3000.example. 5M IN A 10.0.5.117
+3000.example. 5M IN A 10.0.5.118
+3000.example. 5M IN A 10.0.5.119
+3000.example. 5M IN A 10.0.5.120
+3000.example. 5M IN A 10.0.5.121
+3000.example. 5M IN A 10.0.5.122
+3000.example. 5M IN A 10.0.5.123
+3000.example. 5M IN A 10.0.5.124
+3000.example. 5M IN A 10.0.5.125
+3000.example. 5M IN A 10.0.5.126
+3000.example. 5M IN A 10.0.5.127
+3000.example. 5M IN A 10.0.5.128
+3000.example. 5M IN A 10.0.5.129
+3000.example. 5M IN A 10.0.5.130
+3000.example. 5M IN A 10.0.5.131
+3000.example. 5M IN A 10.0.5.132
+3000.example. 5M IN A 10.0.5.133
+3000.example. 5M IN A 10.0.5.134
+3000.example. 5M IN A 10.0.5.135
+3000.example. 5M IN A 10.0.5.136
+3000.example. 5M IN A 10.0.5.137
+3000.example. 5M IN A 10.0.5.138
+3000.example. 5M IN A 10.0.5.139
+3000.example. 5M IN A 10.0.5.140
+3000.example. 5M IN A 10.0.5.141
+3000.example. 5M IN A 10.0.5.142
+3000.example. 5M IN A 10.0.5.143
+3000.example. 5M IN A 10.0.5.144
+3000.example. 5M IN A 10.0.5.145
+3000.example. 5M IN A 10.0.5.146
+3000.example. 5M IN A 10.0.5.147
+3000.example. 5M IN A 10.0.5.148
+3000.example. 5M IN A 10.0.5.149
+3000.example. 5M IN A 10.0.5.150
+3000.example. 5M IN A 10.0.5.151
+3000.example. 5M IN A 10.0.5.152
+3000.example. 5M IN A 10.0.5.153
+3000.example. 5M IN A 10.0.5.154
+3000.example. 5M IN A 10.0.5.155
+3000.example. 5M IN A 10.0.5.156
+3000.example. 5M IN A 10.0.5.157
+3000.example. 5M IN A 10.0.5.158
+3000.example. 5M IN A 10.0.5.159
+3000.example. 5M IN A 10.0.5.160
+3000.example. 5M IN A 10.0.5.161
+3000.example. 5M IN A 10.0.5.162
+3000.example. 5M IN A 10.0.5.163
+3000.example. 5M IN A 10.0.5.164
+3000.example. 5M IN A 10.0.5.165
+3000.example. 5M IN A 10.0.5.166
+3000.example. 5M IN A 10.0.5.167
+3000.example. 5M IN A 10.0.5.168
+3000.example. 5M IN A 10.0.5.169
+3000.example. 5M IN A 10.0.5.170
+3000.example. 5M IN A 10.0.5.171
+3000.example. 5M IN A 10.0.5.172
+3000.example. 5M IN A 10.0.5.173
+3000.example. 5M IN A 10.0.5.174
+3000.example. 5M IN A 10.0.5.175
+3000.example. 5M IN A 10.0.5.176
+3000.example. 5M IN A 10.0.5.177
+3000.example. 5M IN A 10.0.5.178
+3000.example. 5M IN A 10.0.5.179
+3000.example. 5M IN A 10.0.5.180
+3000.example. 5M IN A 10.0.5.181
+3000.example. 5M IN A 10.0.5.182
+3000.example. 5M IN A 10.0.5.183
+3000.example. 5M IN A 10.0.5.184
+3000.example. 5M IN A 10.0.5.185
+3000.example. 5M IN A 10.0.5.186
+3000.example. 5M IN A 10.0.5.187
+3000.example. 5M IN A 10.0.5.188
+3000.example. 5M IN A 10.0.5.189
+3000.example. 5M IN A 10.0.5.190
+3000.example. 5M IN A 10.0.5.191
+3000.example. 5M IN A 10.0.5.192
+3000.example. 5M IN A 10.0.5.193
+3000.example. 5M IN A 10.0.5.194
+3000.example. 5M IN A 10.0.5.195
+3000.example. 5M IN A 10.0.5.196
+3000.example. 5M IN A 10.0.5.197
+3000.example. 5M IN A 10.0.5.198
+3000.example. 5M IN A 10.0.5.199
+3000.example. 5M IN A 10.0.5.200
+3000.example. 5M IN A 10.0.5.201
+3000.example. 5M IN A 10.0.5.202
+3000.example. 5M IN A 10.0.5.203
+3000.example. 5M IN A 10.0.5.204
+3000.example. 5M IN A 10.0.5.205
+3000.example. 5M IN A 10.0.5.206
+3000.example. 5M IN A 10.0.5.207
+3000.example. 5M IN A 10.0.5.208
+3000.example. 5M IN A 10.0.5.209
+3000.example. 5M IN A 10.0.5.210
+3000.example. 5M IN A 10.0.5.211
+3000.example. 5M IN A 10.0.5.212
+3000.example. 5M IN A 10.0.5.213
+3000.example. 5M IN A 10.0.5.214
+3000.example. 5M IN A 10.0.5.215
+3000.example. 5M IN A 10.0.5.216
+3000.example. 5M IN A 10.0.5.217
+3000.example. 5M IN A 10.0.5.218
+3000.example. 5M IN A 10.0.5.219
+3000.example. 5M IN A 10.0.5.220
+3000.example. 5M IN A 10.0.5.221
+3000.example. 5M IN A 10.0.5.222
+3000.example. 5M IN A 10.0.5.223
+3000.example. 5M IN A 10.0.5.224
+3000.example. 5M IN A 10.0.5.225
+3000.example. 5M IN A 10.0.5.226
+3000.example. 5M IN A 10.0.5.227
+3000.example. 5M IN A 10.0.5.228
+3000.example. 5M IN A 10.0.5.229
+3000.example. 5M IN A 10.0.5.230
+3000.example. 5M IN A 10.0.5.231
+3000.example. 5M IN A 10.0.5.232
+3000.example. 5M IN A 10.0.5.233
+3000.example. 5M IN A 10.0.5.234
+3000.example. 5M IN A 10.0.5.235
+3000.example. 5M IN A 10.0.5.236
+3000.example. 5M IN A 10.0.5.237
+3000.example. 5M IN A 10.0.5.238
+3000.example. 5M IN A 10.0.5.239
+3000.example. 5M IN A 10.0.5.240
+3000.example. 5M IN A 10.0.5.241
+3000.example. 5M IN A 10.0.5.242
+3000.example. 5M IN A 10.0.5.243
+3000.example. 5M IN A 10.0.5.244
+3000.example. 5M IN A 10.0.5.245
+3000.example. 5M IN A 10.0.5.246
+3000.example. 5M IN A 10.0.5.247
+3000.example. 5M IN A 10.0.5.248
+3000.example. 5M IN A 10.0.5.249
+3000.example. 5M IN A 10.0.5.250
+3000.example. 5M IN A 10.0.5.251
+3000.example. 5M IN A 10.0.5.252
+3000.example. 5M IN A 10.0.5.253
+3000.example. 5M IN A 10.0.5.254
+3000.example. 5M IN A 10.0.5.255
+3000.example. 5M IN A 10.0.6.0
+3000.example. 5M IN A 10.0.6.1
+3000.example. 5M IN A 10.0.6.2
+3000.example. 5M IN A 10.0.6.3
+3000.example. 5M IN A 10.0.6.4
+3000.example. 5M IN A 10.0.6.5
+3000.example. 5M IN A 10.0.6.6
+3000.example. 5M IN A 10.0.6.7
+3000.example. 5M IN A 10.0.6.8
+3000.example. 5M IN A 10.0.6.9
+3000.example. 5M IN A 10.0.6.10
+3000.example. 5M IN A 10.0.6.11
+3000.example. 5M IN A 10.0.6.12
+3000.example. 5M IN A 10.0.6.13
+3000.example. 5M IN A 10.0.6.14
+3000.example. 5M IN A 10.0.6.15
+3000.example. 5M IN A 10.0.6.16
+3000.example. 5M IN A 10.0.6.17
+3000.example. 5M IN A 10.0.6.18
+3000.example. 5M IN A 10.0.6.19
+3000.example. 5M IN A 10.0.6.20
+3000.example. 5M IN A 10.0.6.21
+3000.example. 5M IN A 10.0.6.22
+3000.example. 5M IN A 10.0.6.23
+3000.example. 5M IN A 10.0.6.24
+3000.example. 5M IN A 10.0.6.25
+3000.example. 5M IN A 10.0.6.26
+3000.example. 5M IN A 10.0.6.27
+3000.example. 5M IN A 10.0.6.28
+3000.example. 5M IN A 10.0.6.29
+3000.example. 5M IN A 10.0.6.30
+3000.example. 5M IN A 10.0.6.31
+3000.example. 5M IN A 10.0.6.32
+3000.example. 5M IN A 10.0.6.33
+3000.example. 5M IN A 10.0.6.34
+3000.example. 5M IN A 10.0.6.35
+3000.example. 5M IN A 10.0.6.36
+3000.example. 5M IN A 10.0.6.37
+3000.example. 5M IN A 10.0.6.38
+3000.example. 5M IN A 10.0.6.39
+3000.example. 5M IN A 10.0.6.40
+3000.example. 5M IN A 10.0.6.41
+3000.example. 5M IN A 10.0.6.42
+3000.example. 5M IN A 10.0.6.43
+3000.example. 5M IN A 10.0.6.44
+3000.example. 5M IN A 10.0.6.45
+3000.example. 5M IN A 10.0.6.46
+3000.example. 5M IN A 10.0.6.47
+3000.example. 5M IN A 10.0.6.48
+3000.example. 5M IN A 10.0.6.49
+3000.example. 5M IN A 10.0.6.50
+3000.example. 5M IN A 10.0.6.51
+3000.example. 5M IN A 10.0.6.52
+3000.example. 5M IN A 10.0.6.53
+3000.example. 5M IN A 10.0.6.54
+3000.example. 5M IN A 10.0.6.55
+3000.example. 5M IN A 10.0.6.56
+3000.example. 5M IN A 10.0.6.57
+3000.example. 5M IN A 10.0.6.58
+3000.example. 5M IN A 10.0.6.59
+3000.example. 5M IN A 10.0.6.60
+3000.example. 5M IN A 10.0.6.61
+3000.example. 5M IN A 10.0.6.62
+3000.example. 5M IN A 10.0.6.63
+3000.example. 5M IN A 10.0.6.64
+3000.example. 5M IN A 10.0.6.65
+3000.example. 5M IN A 10.0.6.66
+3000.example. 5M IN A 10.0.6.67
+3000.example. 5M IN A 10.0.6.68
+3000.example. 5M IN A 10.0.6.69
+3000.example. 5M IN A 10.0.6.70
+3000.example. 5M IN A 10.0.6.71
+3000.example. 5M IN A 10.0.6.72
+3000.example. 5M IN A 10.0.6.73
+3000.example. 5M IN A 10.0.6.74
+3000.example. 5M IN A 10.0.6.75
+3000.example. 5M IN A 10.0.6.76
+3000.example. 5M IN A 10.0.6.77
+3000.example. 5M IN A 10.0.6.78
+3000.example. 5M IN A 10.0.6.79
+3000.example. 5M IN A 10.0.6.80
+3000.example. 5M IN A 10.0.6.81
+3000.example. 5M IN A 10.0.6.82
+3000.example. 5M IN A 10.0.6.83
+3000.example. 5M IN A 10.0.6.84
+3000.example. 5M IN A 10.0.6.85
+3000.example. 5M IN A 10.0.6.86
+3000.example. 5M IN A 10.0.6.87
+3000.example. 5M IN A 10.0.6.88
+3000.example. 5M IN A 10.0.6.89
+3000.example. 5M IN A 10.0.6.90
+3000.example. 5M IN A 10.0.6.91
+3000.example. 5M IN A 10.0.6.92
+3000.example. 5M IN A 10.0.6.93
+3000.example. 5M IN A 10.0.6.94
+3000.example. 5M IN A 10.0.6.95
+3000.example. 5M IN A 10.0.6.96
+3000.example. 5M IN A 10.0.6.97
+3000.example. 5M IN A 10.0.6.98
+3000.example. 5M IN A 10.0.6.99
+3000.example. 5M IN A 10.0.6.100
+3000.example. 5M IN A 10.0.6.101
+3000.example. 5M IN A 10.0.6.102
+3000.example. 5M IN A 10.0.6.103
+3000.example. 5M IN A 10.0.6.104
+3000.example. 5M IN A 10.0.6.105
+3000.example. 5M IN A 10.0.6.106
+3000.example. 5M IN A 10.0.6.107
+3000.example. 5M IN A 10.0.6.108
+3000.example. 5M IN A 10.0.6.109
+3000.example. 5M IN A 10.0.6.110
+3000.example. 5M IN A 10.0.6.111
+3000.example. 5M IN A 10.0.6.112
+3000.example. 5M IN A 10.0.6.113
+3000.example. 5M IN A 10.0.6.114
+3000.example. 5M IN A 10.0.6.115
+3000.example. 5M IN A 10.0.6.116
+3000.example. 5M IN A 10.0.6.117
+3000.example. 5M IN A 10.0.6.118
+3000.example. 5M IN A 10.0.6.119
+3000.example. 5M IN A 10.0.6.120
+3000.example. 5M IN A 10.0.6.121
+3000.example. 5M IN A 10.0.6.122
+3000.example. 5M IN A 10.0.6.123
+3000.example. 5M IN A 10.0.6.124
+3000.example. 5M IN A 10.0.6.125
+3000.example. 5M IN A 10.0.6.126
+3000.example. 5M IN A 10.0.6.127
+3000.example. 5M IN A 10.0.6.128
+3000.example. 5M IN A 10.0.6.129
+3000.example. 5M IN A 10.0.6.130
+3000.example. 5M IN A 10.0.6.131
+3000.example. 5M IN A 10.0.6.132
+3000.example. 5M IN A 10.0.6.133
+3000.example. 5M IN A 10.0.6.134
+3000.example. 5M IN A 10.0.6.135
+3000.example. 5M IN A 10.0.6.136
+3000.example. 5M IN A 10.0.6.137
+3000.example. 5M IN A 10.0.6.138
+3000.example. 5M IN A 10.0.6.139
+3000.example. 5M IN A 10.0.6.140
+3000.example. 5M IN A 10.0.6.141
+3000.example. 5M IN A 10.0.6.142
+3000.example. 5M IN A 10.0.6.143
+3000.example. 5M IN A 10.0.6.144
+3000.example. 5M IN A 10.0.6.145
+3000.example. 5M IN A 10.0.6.146
+3000.example. 5M IN A 10.0.6.147
+3000.example. 5M IN A 10.0.6.148
+3000.example. 5M IN A 10.0.6.149
+3000.example. 5M IN A 10.0.6.150
+3000.example. 5M IN A 10.0.6.151
+3000.example. 5M IN A 10.0.6.152
+3000.example. 5M IN A 10.0.6.153
+3000.example. 5M IN A 10.0.6.154
+3000.example. 5M IN A 10.0.6.155
+3000.example. 5M IN A 10.0.6.156
+3000.example. 5M IN A 10.0.6.157
+3000.example. 5M IN A 10.0.6.158
+3000.example. 5M IN A 10.0.6.159
+3000.example. 5M IN A 10.0.6.160
+3000.example. 5M IN A 10.0.6.161
+3000.example. 5M IN A 10.0.6.162
+3000.example. 5M IN A 10.0.6.163
+3000.example. 5M IN A 10.0.6.164
+3000.example. 5M IN A 10.0.6.165
+3000.example. 5M IN A 10.0.6.166
+3000.example. 5M IN A 10.0.6.167
+3000.example. 5M IN A 10.0.6.168
+3000.example. 5M IN A 10.0.6.169
+3000.example. 5M IN A 10.0.6.170
+3000.example. 5M IN A 10.0.6.171
+3000.example. 5M IN A 10.0.6.172
+3000.example. 5M IN A 10.0.6.173
+3000.example. 5M IN A 10.0.6.174
+3000.example. 5M IN A 10.0.6.175
+3000.example. 5M IN A 10.0.6.176
+3000.example. 5M IN A 10.0.6.177
+3000.example. 5M IN A 10.0.6.178
+3000.example. 5M IN A 10.0.6.179
+3000.example. 5M IN A 10.0.6.180
+3000.example. 5M IN A 10.0.6.181
+3000.example. 5M IN A 10.0.6.182
+3000.example. 5M IN A 10.0.6.183
+3000.example. 5M IN A 10.0.6.184
+3000.example. 5M IN A 10.0.6.185
+3000.example. 5M IN A 10.0.6.186
+3000.example. 5M IN A 10.0.6.187
+3000.example. 5M IN A 10.0.6.188
+3000.example. 5M IN A 10.0.6.189
+3000.example. 5M IN A 10.0.6.190
+3000.example. 5M IN A 10.0.6.191
+3000.example. 5M IN A 10.0.6.192
+3000.example. 5M IN A 10.0.6.193
+3000.example. 5M IN A 10.0.6.194
+3000.example. 5M IN A 10.0.6.195
+3000.example. 5M IN A 10.0.6.196
+3000.example. 5M IN A 10.0.6.197
+3000.example. 5M IN A 10.0.6.198
+3000.example. 5M IN A 10.0.6.199
+3000.example. 5M IN A 10.0.6.200
+3000.example. 5M IN A 10.0.6.201
+3000.example. 5M IN A 10.0.6.202
+3000.example. 5M IN A 10.0.6.203
+3000.example. 5M IN A 10.0.6.204
+3000.example. 5M IN A 10.0.6.205
+3000.example. 5M IN A 10.0.6.206
+3000.example. 5M IN A 10.0.6.207
+3000.example. 5M IN A 10.0.6.208
+3000.example. 5M IN A 10.0.6.209
+3000.example. 5M IN A 10.0.6.210
+3000.example. 5M IN A 10.0.6.211
+3000.example. 5M IN A 10.0.6.212
+3000.example. 5M IN A 10.0.6.213
+3000.example. 5M IN A 10.0.6.214
+3000.example. 5M IN A 10.0.6.215
+3000.example. 5M IN A 10.0.6.216
+3000.example. 5M IN A 10.0.6.217
+3000.example. 5M IN A 10.0.6.218
+3000.example. 5M IN A 10.0.6.219
+3000.example. 5M IN A 10.0.6.220
+3000.example. 5M IN A 10.0.6.221
+3000.example. 5M IN A 10.0.6.222
+3000.example. 5M IN A 10.0.6.223
+3000.example. 5M IN A 10.0.6.224
+3000.example. 5M IN A 10.0.6.225
+3000.example. 5M IN A 10.0.6.226
+3000.example. 5M IN A 10.0.6.227
+3000.example. 5M IN A 10.0.6.228
+3000.example. 5M IN A 10.0.6.229
+3000.example. 5M IN A 10.0.6.230
+3000.example. 5M IN A 10.0.6.231
+3000.example. 5M IN A 10.0.6.232
+3000.example. 5M IN A 10.0.6.233
+3000.example. 5M IN A 10.0.6.234
+3000.example. 5M IN A 10.0.6.235
+3000.example. 5M IN A 10.0.6.236
+3000.example. 5M IN A 10.0.6.237
+3000.example. 5M IN A 10.0.6.238
+3000.example. 5M IN A 10.0.6.239
+3000.example. 5M IN A 10.0.6.240
+3000.example. 5M IN A 10.0.6.241
+3000.example. 5M IN A 10.0.6.242
+3000.example. 5M IN A 10.0.6.243
+3000.example. 5M IN A 10.0.6.244
+3000.example. 5M IN A 10.0.6.245
+3000.example. 5M IN A 10.0.6.246
+3000.example. 5M IN A 10.0.6.247
+3000.example. 5M IN A 10.0.6.248
+3000.example. 5M IN A 10.0.6.249
+3000.example. 5M IN A 10.0.6.250
+3000.example. 5M IN A 10.0.6.251
+3000.example. 5M IN A 10.0.6.252
+3000.example. 5M IN A 10.0.6.253
+3000.example. 5M IN A 10.0.6.254
+3000.example. 5M IN A 10.0.6.255
+3000.example. 5M IN A 10.0.7.0
+3000.example. 5M IN A 10.0.7.1
+3000.example. 5M IN A 10.0.7.2
+3000.example. 5M IN A 10.0.7.3
+3000.example. 5M IN A 10.0.7.4
+3000.example. 5M IN A 10.0.7.5
+3000.example. 5M IN A 10.0.7.6
+3000.example. 5M IN A 10.0.7.7
+3000.example. 5M IN A 10.0.7.8
+3000.example. 5M IN A 10.0.7.9
+3000.example. 5M IN A 10.0.7.10
+3000.example. 5M IN A 10.0.7.11
+3000.example. 5M IN A 10.0.7.12
+3000.example. 5M IN A 10.0.7.13
+3000.example. 5M IN A 10.0.7.14
+3000.example. 5M IN A 10.0.7.15
+3000.example. 5M IN A 10.0.7.16
+3000.example. 5M IN A 10.0.7.17
+3000.example. 5M IN A 10.0.7.18
+3000.example. 5M IN A 10.0.7.19
+3000.example. 5M IN A 10.0.7.20
+3000.example. 5M IN A 10.0.7.21
+3000.example. 5M IN A 10.0.7.22
+3000.example. 5M IN A 10.0.7.23
+3000.example. 5M IN A 10.0.7.24
+3000.example. 5M IN A 10.0.7.25
+3000.example. 5M IN A 10.0.7.26
+3000.example. 5M IN A 10.0.7.27
+3000.example. 5M IN A 10.0.7.28
+3000.example. 5M IN A 10.0.7.29
+3000.example. 5M IN A 10.0.7.30
+3000.example. 5M IN A 10.0.7.31
+3000.example. 5M IN A 10.0.7.32
+3000.example. 5M IN A 10.0.7.33
+3000.example. 5M IN A 10.0.7.34
+3000.example. 5M IN A 10.0.7.35
+3000.example. 5M IN A 10.0.7.36
+3000.example. 5M IN A 10.0.7.37
+3000.example. 5M IN A 10.0.7.38
+3000.example. 5M IN A 10.0.7.39
+3000.example. 5M IN A 10.0.7.40
+3000.example. 5M IN A 10.0.7.41
+3000.example. 5M IN A 10.0.7.42
+3000.example. 5M IN A 10.0.7.43
+3000.example. 5M IN A 10.0.7.44
+3000.example. 5M IN A 10.0.7.45
+3000.example. 5M IN A 10.0.7.46
+3000.example. 5M IN A 10.0.7.47
+3000.example. 5M IN A 10.0.7.48
+3000.example. 5M IN A 10.0.7.49
+3000.example. 5M IN A 10.0.7.50
+3000.example. 5M IN A 10.0.7.51
+3000.example. 5M IN A 10.0.7.52
+3000.example. 5M IN A 10.0.7.53
+3000.example. 5M IN A 10.0.7.54
+3000.example. 5M IN A 10.0.7.55
+3000.example. 5M IN A 10.0.7.56
+3000.example. 5M IN A 10.0.7.57
+3000.example. 5M IN A 10.0.7.58
+3000.example. 5M IN A 10.0.7.59
+3000.example. 5M IN A 10.0.7.60
+3000.example. 5M IN A 10.0.7.61
+3000.example. 5M IN A 10.0.7.62
+3000.example. 5M IN A 10.0.7.63
+3000.example. 5M IN A 10.0.7.64
+3000.example. 5M IN A 10.0.7.65
+3000.example. 5M IN A 10.0.7.66
+3000.example. 5M IN A 10.0.7.67
+3000.example. 5M IN A 10.0.7.68
+3000.example. 5M IN A 10.0.7.69
+3000.example. 5M IN A 10.0.7.70
+3000.example. 5M IN A 10.0.7.71
+3000.example. 5M IN A 10.0.7.72
+3000.example. 5M IN A 10.0.7.73
+3000.example. 5M IN A 10.0.7.74
+3000.example. 5M IN A 10.0.7.75
+3000.example. 5M IN A 10.0.7.76
+3000.example. 5M IN A 10.0.7.77
+3000.example. 5M IN A 10.0.7.78
+3000.example. 5M IN A 10.0.7.79
+3000.example. 5M IN A 10.0.7.80
+3000.example. 5M IN A 10.0.7.81
+3000.example. 5M IN A 10.0.7.82
+3000.example. 5M IN A 10.0.7.83
+3000.example. 5M IN A 10.0.7.84
+3000.example. 5M IN A 10.0.7.85
+3000.example. 5M IN A 10.0.7.86
+3000.example. 5M IN A 10.0.7.87
+3000.example. 5M IN A 10.0.7.88
+3000.example. 5M IN A 10.0.7.89
+3000.example. 5M IN A 10.0.7.90
+3000.example. 5M IN A 10.0.7.91
+3000.example. 5M IN A 10.0.7.92
+3000.example. 5M IN A 10.0.7.93
+3000.example. 5M IN A 10.0.7.94
+3000.example. 5M IN A 10.0.7.95
+3000.example. 5M IN A 10.0.7.96
+3000.example. 5M IN A 10.0.7.97
+3000.example. 5M IN A 10.0.7.98
+3000.example. 5M IN A 10.0.7.99
+3000.example. 5M IN A 10.0.7.100
+3000.example. 5M IN A 10.0.7.101
+3000.example. 5M IN A 10.0.7.102
+3000.example. 5M IN A 10.0.7.103
+3000.example. 5M IN A 10.0.7.104
+3000.example. 5M IN A 10.0.7.105
+3000.example. 5M IN A 10.0.7.106
+3000.example. 5M IN A 10.0.7.107
+3000.example. 5M IN A 10.0.7.108
+3000.example. 5M IN A 10.0.7.109
+3000.example. 5M IN A 10.0.7.110
+3000.example. 5M IN A 10.0.7.111
+3000.example. 5M IN A 10.0.7.112
+3000.example. 5M IN A 10.0.7.113
+3000.example. 5M IN A 10.0.7.114
+3000.example. 5M IN A 10.0.7.115
+3000.example. 5M IN A 10.0.7.116
+3000.example. 5M IN A 10.0.7.117
+3000.example. 5M IN A 10.0.7.118
+3000.example. 5M IN A 10.0.7.119
+3000.example. 5M IN A 10.0.7.120
+3000.example. 5M IN A 10.0.7.121
+3000.example. 5M IN A 10.0.7.122
+3000.example. 5M IN A 10.0.7.123
+3000.example. 5M IN A 10.0.7.124
+3000.example. 5M IN A 10.0.7.125
+3000.example. 5M IN A 10.0.7.126
+3000.example. 5M IN A 10.0.7.127
+3000.example. 5M IN A 10.0.7.128
+3000.example. 5M IN A 10.0.7.129
+3000.example. 5M IN A 10.0.7.130
+3000.example. 5M IN A 10.0.7.131
+3000.example. 5M IN A 10.0.7.132
+3000.example. 5M IN A 10.0.7.133
+3000.example. 5M IN A 10.0.7.134
+3000.example. 5M IN A 10.0.7.135
+3000.example. 5M IN A 10.0.7.136
+3000.example. 5M IN A 10.0.7.137
+3000.example. 5M IN A 10.0.7.138
+3000.example. 5M IN A 10.0.7.139
+3000.example. 5M IN A 10.0.7.140
+3000.example. 5M IN A 10.0.7.141
+3000.example. 5M IN A 10.0.7.142
+3000.example. 5M IN A 10.0.7.143
+3000.example. 5M IN A 10.0.7.144
+3000.example. 5M IN A 10.0.7.145
+3000.example. 5M IN A 10.0.7.146
+3000.example. 5M IN A 10.0.7.147
+3000.example. 5M IN A 10.0.7.148
+3000.example. 5M IN A 10.0.7.149
+3000.example. 5M IN A 10.0.7.150
+3000.example. 5M IN A 10.0.7.151
+3000.example. 5M IN A 10.0.7.152
+3000.example. 5M IN A 10.0.7.153
+3000.example. 5M IN A 10.0.7.154
+3000.example. 5M IN A 10.0.7.155
+3000.example. 5M IN A 10.0.7.156
+3000.example. 5M IN A 10.0.7.157
+3000.example. 5M IN A 10.0.7.158
+3000.example. 5M IN A 10.0.7.159
+3000.example. 5M IN A 10.0.7.160
+3000.example. 5M IN A 10.0.7.161
+3000.example. 5M IN A 10.0.7.162
+3000.example. 5M IN A 10.0.7.163
+3000.example. 5M IN A 10.0.7.164
+3000.example. 5M IN A 10.0.7.165
+3000.example. 5M IN A 10.0.7.166
+3000.example. 5M IN A 10.0.7.167
+3000.example. 5M IN A 10.0.7.168
+3000.example. 5M IN A 10.0.7.169
+3000.example. 5M IN A 10.0.7.170
+3000.example. 5M IN A 10.0.7.171
+3000.example. 5M IN A 10.0.7.172
+3000.example. 5M IN A 10.0.7.173
+3000.example. 5M IN A 10.0.7.174
+3000.example. 5M IN A 10.0.7.175
+3000.example. 5M IN A 10.0.7.176
+3000.example. 5M IN A 10.0.7.177
+3000.example. 5M IN A 10.0.7.178
+3000.example. 5M IN A 10.0.7.179
+3000.example. 5M IN A 10.0.7.180
+3000.example. 5M IN A 10.0.7.181
+3000.example. 5M IN A 10.0.7.182
+3000.example. 5M IN A 10.0.7.183
+3000.example. 5M IN A 10.0.7.184
+3000.example. 5M IN A 10.0.7.185
+3000.example. 5M IN A 10.0.7.186
+3000.example. 5M IN A 10.0.7.187
+3000.example. 5M IN A 10.0.7.188
+3000.example. 5M IN A 10.0.7.189
+3000.example. 5M IN A 10.0.7.190
+3000.example. 5M IN A 10.0.7.191
+3000.example. 5M IN A 10.0.7.192
+3000.example. 5M IN A 10.0.7.193
+3000.example. 5M IN A 10.0.7.194
+3000.example. 5M IN A 10.0.7.195
+3000.example. 5M IN A 10.0.7.196
+3000.example. 5M IN A 10.0.7.197
+3000.example. 5M IN A 10.0.7.198
+3000.example. 5M IN A 10.0.7.199
+3000.example. 5M IN A 10.0.7.200
+3000.example. 5M IN A 10.0.7.201
+3000.example. 5M IN A 10.0.7.202
+3000.example. 5M IN A 10.0.7.203
+3000.example. 5M IN A 10.0.7.204
+3000.example. 5M IN A 10.0.7.205
+3000.example. 5M IN A 10.0.7.206
+3000.example. 5M IN A 10.0.7.207
+3000.example. 5M IN A 10.0.7.208
+3000.example. 5M IN A 10.0.7.209
+3000.example. 5M IN A 10.0.7.210
+3000.example. 5M IN A 10.0.7.211
+3000.example. 5M IN A 10.0.7.212
+3000.example. 5M IN A 10.0.7.213
+3000.example. 5M IN A 10.0.7.214
+3000.example. 5M IN A 10.0.7.215
+3000.example. 5M IN A 10.0.7.216
+3000.example. 5M IN A 10.0.7.217
+3000.example. 5M IN A 10.0.7.218
+3000.example. 5M IN A 10.0.7.219
+3000.example. 5M IN A 10.0.7.220
+3000.example. 5M IN A 10.0.7.221
+3000.example. 5M IN A 10.0.7.222
+3000.example. 5M IN A 10.0.7.223
+3000.example. 5M IN A 10.0.7.224
+3000.example. 5M IN A 10.0.7.225
+3000.example. 5M IN A 10.0.7.226
+3000.example. 5M IN A 10.0.7.227
+3000.example. 5M IN A 10.0.7.228
+3000.example. 5M IN A 10.0.7.229
+3000.example. 5M IN A 10.0.7.230
+3000.example. 5M IN A 10.0.7.231
+3000.example. 5M IN A 10.0.7.232
+3000.example. 5M IN A 10.0.7.233
+3000.example. 5M IN A 10.0.7.234
+3000.example. 5M IN A 10.0.7.235
+3000.example. 5M IN A 10.0.7.236
+3000.example. 5M IN A 10.0.7.237
+3000.example. 5M IN A 10.0.7.238
+3000.example. 5M IN A 10.0.7.239
+3000.example. 5M IN A 10.0.7.240
+3000.example. 5M IN A 10.0.7.241
+3000.example. 5M IN A 10.0.7.242
+3000.example. 5M IN A 10.0.7.243
+3000.example. 5M IN A 10.0.7.244
+3000.example. 5M IN A 10.0.7.245
+3000.example. 5M IN A 10.0.7.246
+3000.example. 5M IN A 10.0.7.247
+3000.example. 5M IN A 10.0.7.248
+3000.example. 5M IN A 10.0.7.249
+3000.example. 5M IN A 10.0.7.250
+3000.example. 5M IN A 10.0.7.251
+3000.example. 5M IN A 10.0.7.252
+3000.example. 5M IN A 10.0.7.253
+3000.example. 5M IN A 10.0.7.254
+3000.example. 5M IN A 10.0.7.255
+3000.example. 5M IN A 10.0.8.0
+3000.example. 5M IN A 10.0.8.1
+3000.example. 5M IN A 10.0.8.2
+3000.example. 5M IN A 10.0.8.3
+3000.example. 5M IN A 10.0.8.4
+3000.example. 5M IN A 10.0.8.5
+3000.example. 5M IN A 10.0.8.6
+3000.example. 5M IN A 10.0.8.7
+3000.example. 5M IN A 10.0.8.8
+3000.example. 5M IN A 10.0.8.9
+3000.example. 5M IN A 10.0.8.10
+3000.example. 5M IN A 10.0.8.11
+3000.example. 5M IN A 10.0.8.12
+3000.example. 5M IN A 10.0.8.13
+3000.example. 5M IN A 10.0.8.14
+3000.example. 5M IN A 10.0.8.15
+3000.example. 5M IN A 10.0.8.16
+3000.example. 5M IN A 10.0.8.17
+3000.example. 5M IN A 10.0.8.18
+3000.example. 5M IN A 10.0.8.19
+3000.example. 5M IN A 10.0.8.20
+3000.example. 5M IN A 10.0.8.21
+3000.example. 5M IN A 10.0.8.22
+3000.example. 5M IN A 10.0.8.23
+3000.example. 5M IN A 10.0.8.24
+3000.example. 5M IN A 10.0.8.25
+3000.example. 5M IN A 10.0.8.26
+3000.example. 5M IN A 10.0.8.27
+3000.example. 5M IN A 10.0.8.28
+3000.example. 5M IN A 10.0.8.29
+3000.example. 5M IN A 10.0.8.30
+3000.example. 5M IN A 10.0.8.31
+3000.example. 5M IN A 10.0.8.32
+3000.example. 5M IN A 10.0.8.33
+3000.example. 5M IN A 10.0.8.34
+3000.example. 5M IN A 10.0.8.35
+3000.example. 5M IN A 10.0.8.36
+3000.example. 5M IN A 10.0.8.37
+3000.example. 5M IN A 10.0.8.38
+3000.example. 5M IN A 10.0.8.39
+3000.example. 5M IN A 10.0.8.40
+3000.example. 5M IN A 10.0.8.41
+3000.example. 5M IN A 10.0.8.42
+3000.example. 5M IN A 10.0.8.43
+3000.example. 5M IN A 10.0.8.44
+3000.example. 5M IN A 10.0.8.45
+3000.example. 5M IN A 10.0.8.46
+3000.example. 5M IN A 10.0.8.47
+3000.example. 5M IN A 10.0.8.48
+3000.example. 5M IN A 10.0.8.49
+3000.example. 5M IN A 10.0.8.50
+3000.example. 5M IN A 10.0.8.51
+3000.example. 5M IN A 10.0.8.52
+3000.example. 5M IN A 10.0.8.53
+3000.example. 5M IN A 10.0.8.54
+3000.example. 5M IN A 10.0.8.55
+3000.example. 5M IN A 10.0.8.56
+3000.example. 5M IN A 10.0.8.57
+3000.example. 5M IN A 10.0.8.58
+3000.example. 5M IN A 10.0.8.59
+3000.example. 5M IN A 10.0.8.60
+3000.example. 5M IN A 10.0.8.61
+3000.example. 5M IN A 10.0.8.62
+3000.example. 5M IN A 10.0.8.63
+3000.example. 5M IN A 10.0.8.64
+3000.example. 5M IN A 10.0.8.65
+3000.example. 5M IN A 10.0.8.66
+3000.example. 5M IN A 10.0.8.67
+3000.example. 5M IN A 10.0.8.68
+3000.example. 5M IN A 10.0.8.69
+3000.example. 5M IN A 10.0.8.70
+3000.example. 5M IN A 10.0.8.71
+3000.example. 5M IN A 10.0.8.72
+3000.example. 5M IN A 10.0.8.73
+3000.example. 5M IN A 10.0.8.74
+3000.example. 5M IN A 10.0.8.75
+3000.example. 5M IN A 10.0.8.76
+3000.example. 5M IN A 10.0.8.77
+3000.example. 5M IN A 10.0.8.78
+3000.example. 5M IN A 10.0.8.79
+3000.example. 5M IN A 10.0.8.80
+3000.example. 5M IN A 10.0.8.81
+3000.example. 5M IN A 10.0.8.82
+3000.example. 5M IN A 10.0.8.83
+3000.example. 5M IN A 10.0.8.84
+3000.example. 5M IN A 10.0.8.85
+3000.example. 5M IN A 10.0.8.86
+3000.example. 5M IN A 10.0.8.87
+3000.example. 5M IN A 10.0.8.88
+3000.example. 5M IN A 10.0.8.89
+3000.example. 5M IN A 10.0.8.90
+3000.example. 5M IN A 10.0.8.91
+3000.example. 5M IN A 10.0.8.92
+3000.example. 5M IN A 10.0.8.93
+3000.example. 5M IN A 10.0.8.94
+3000.example. 5M IN A 10.0.8.95
+3000.example. 5M IN A 10.0.8.96
+3000.example. 5M IN A 10.0.8.97
+3000.example. 5M IN A 10.0.8.98
+3000.example. 5M IN A 10.0.8.99
+3000.example. 5M IN A 10.0.8.100
+3000.example. 5M IN A 10.0.8.101
+3000.example. 5M IN A 10.0.8.102
+3000.example. 5M IN A 10.0.8.103
+3000.example. 5M IN A 10.0.8.104
+3000.example. 5M IN A 10.0.8.105
+3000.example. 5M IN A 10.0.8.106
+3000.example. 5M IN A 10.0.8.107
+3000.example. 5M IN A 10.0.8.108
+3000.example. 5M IN A 10.0.8.109
+3000.example. 5M IN A 10.0.8.110
+3000.example. 5M IN A 10.0.8.111
+3000.example. 5M IN A 10.0.8.112
+3000.example. 5M IN A 10.0.8.113
+3000.example. 5M IN A 10.0.8.114
+3000.example. 5M IN A 10.0.8.115
+3000.example. 5M IN A 10.0.8.116
+3000.example. 5M IN A 10.0.8.117
+3000.example. 5M IN A 10.0.8.118
+3000.example. 5M IN A 10.0.8.119
+3000.example. 5M IN A 10.0.8.120
+3000.example. 5M IN A 10.0.8.121
+3000.example. 5M IN A 10.0.8.122
+3000.example. 5M IN A 10.0.8.123
+3000.example. 5M IN A 10.0.8.124
+3000.example. 5M IN A 10.0.8.125
+3000.example. 5M IN A 10.0.8.126
+3000.example. 5M IN A 10.0.8.127
+3000.example. 5M IN A 10.0.8.128
+3000.example. 5M IN A 10.0.8.129
+3000.example. 5M IN A 10.0.8.130
+3000.example. 5M IN A 10.0.8.131
+3000.example. 5M IN A 10.0.8.132
+3000.example. 5M IN A 10.0.8.133
+3000.example. 5M IN A 10.0.8.134
+3000.example. 5M IN A 10.0.8.135
+3000.example. 5M IN A 10.0.8.136
+3000.example. 5M IN A 10.0.8.137
+3000.example. 5M IN A 10.0.8.138
+3000.example. 5M IN A 10.0.8.139
+3000.example. 5M IN A 10.0.8.140
+3000.example. 5M IN A 10.0.8.141
+3000.example. 5M IN A 10.0.8.142
+3000.example. 5M IN A 10.0.8.143
+3000.example. 5M IN A 10.0.8.144
+3000.example. 5M IN A 10.0.8.145
+3000.example. 5M IN A 10.0.8.146
+3000.example. 5M IN A 10.0.8.147
+3000.example. 5M IN A 10.0.8.148
+3000.example. 5M IN A 10.0.8.149
+3000.example. 5M IN A 10.0.8.150
+3000.example. 5M IN A 10.0.8.151
+3000.example. 5M IN A 10.0.8.152
+3000.example. 5M IN A 10.0.8.153
+3000.example. 5M IN A 10.0.8.154
+3000.example. 5M IN A 10.0.8.155
+3000.example. 5M IN A 10.0.8.156
+3000.example. 5M IN A 10.0.8.157
+3000.example. 5M IN A 10.0.8.158
+3000.example. 5M IN A 10.0.8.159
+3000.example. 5M IN A 10.0.8.160
+3000.example. 5M IN A 10.0.8.161
+3000.example. 5M IN A 10.0.8.162
+3000.example. 5M IN A 10.0.8.163
+3000.example. 5M IN A 10.0.8.164
+3000.example. 5M IN A 10.0.8.165
+3000.example. 5M IN A 10.0.8.166
+3000.example. 5M IN A 10.0.8.167
+3000.example. 5M IN A 10.0.8.168
+3000.example. 5M IN A 10.0.8.169
+3000.example. 5M IN A 10.0.8.170
+3000.example. 5M IN A 10.0.8.171
+3000.example. 5M IN A 10.0.8.172
+3000.example. 5M IN A 10.0.8.173
+3000.example. 5M IN A 10.0.8.174
+3000.example. 5M IN A 10.0.8.175
+3000.example. 5M IN A 10.0.8.176
+3000.example. 5M IN A 10.0.8.177
+3000.example. 5M IN A 10.0.8.178
+3000.example. 5M IN A 10.0.8.179
+3000.example. 5M IN A 10.0.8.180
+3000.example. 5M IN A 10.0.8.181
+3000.example. 5M IN A 10.0.8.182
+3000.example. 5M IN A 10.0.8.183
+3000.example. 5M IN A 10.0.8.184
+3000.example. 5M IN A 10.0.8.185
+3000.example. 5M IN A 10.0.8.186
+3000.example. 5M IN A 10.0.8.187
+3000.example. 5M IN A 10.0.8.188
+3000.example. 5M IN A 10.0.8.189
+3000.example. 5M IN A 10.0.8.190
+3000.example. 5M IN A 10.0.8.191
+3000.example. 5M IN A 10.0.8.192
+3000.example. 5M IN A 10.0.8.193
+3000.example. 5M IN A 10.0.8.194
+3000.example. 5M IN A 10.0.8.195
+3000.example. 5M IN A 10.0.8.196
+3000.example. 5M IN A 10.0.8.197
+3000.example. 5M IN A 10.0.8.198
+3000.example. 5M IN A 10.0.8.199
+3000.example. 5M IN A 10.0.8.200
+3000.example. 5M IN A 10.0.8.201
+3000.example. 5M IN A 10.0.8.202
+3000.example. 5M IN A 10.0.8.203
+3000.example. 5M IN A 10.0.8.204
+3000.example. 5M IN A 10.0.8.205
+3000.example. 5M IN A 10.0.8.206
+3000.example. 5M IN A 10.0.8.207
+3000.example. 5M IN A 10.0.8.208
+3000.example. 5M IN A 10.0.8.209
+3000.example. 5M IN A 10.0.8.210
+3000.example. 5M IN A 10.0.8.211
+3000.example. 5M IN A 10.0.8.212
+3000.example. 5M IN A 10.0.8.213
+3000.example. 5M IN A 10.0.8.214
+3000.example. 5M IN A 10.0.8.215
+3000.example. 5M IN A 10.0.8.216
+3000.example. 5M IN A 10.0.8.217
+3000.example. 5M IN A 10.0.8.218
+3000.example. 5M IN A 10.0.8.219
+3000.example. 5M IN A 10.0.8.220
+3000.example. 5M IN A 10.0.8.221
+3000.example. 5M IN A 10.0.8.222
+3000.example. 5M IN A 10.0.8.223
+3000.example. 5M IN A 10.0.8.224
+3000.example. 5M IN A 10.0.8.225
+3000.example. 5M IN A 10.0.8.226
+3000.example. 5M IN A 10.0.8.227
+3000.example. 5M IN A 10.0.8.228
+3000.example. 5M IN A 10.0.8.229
+3000.example. 5M IN A 10.0.8.230
+3000.example. 5M IN A 10.0.8.231
+3000.example. 5M IN A 10.0.8.232
+3000.example. 5M IN A 10.0.8.233
+3000.example. 5M IN A 10.0.8.234
+3000.example. 5M IN A 10.0.8.235
+3000.example. 5M IN A 10.0.8.236
+3000.example. 5M IN A 10.0.8.237
+3000.example. 5M IN A 10.0.8.238
+3000.example. 5M IN A 10.0.8.239
+3000.example. 5M IN A 10.0.8.240
+3000.example. 5M IN A 10.0.8.241
+3000.example. 5M IN A 10.0.8.242
+3000.example. 5M IN A 10.0.8.243
+3000.example. 5M IN A 10.0.8.244
+3000.example. 5M IN A 10.0.8.245
+3000.example. 5M IN A 10.0.8.246
+3000.example. 5M IN A 10.0.8.247
+3000.example. 5M IN A 10.0.8.248
+3000.example. 5M IN A 10.0.8.249
+3000.example. 5M IN A 10.0.8.250
+3000.example. 5M IN A 10.0.8.251
+3000.example. 5M IN A 10.0.8.252
+3000.example. 5M IN A 10.0.8.253
+3000.example. 5M IN A 10.0.8.254
+3000.example. 5M IN A 10.0.8.255
+3000.example. 5M IN A 10.0.9.0
+3000.example. 5M IN A 10.0.9.1
+3000.example. 5M IN A 10.0.9.2
+3000.example. 5M IN A 10.0.9.3
+3000.example. 5M IN A 10.0.9.4
+3000.example. 5M IN A 10.0.9.5
+3000.example. 5M IN A 10.0.9.6
+3000.example. 5M IN A 10.0.9.7
+3000.example. 5M IN A 10.0.9.8
+3000.example. 5M IN A 10.0.9.9
+3000.example. 5M IN A 10.0.9.10
+3000.example. 5M IN A 10.0.9.11
+3000.example. 5M IN A 10.0.9.12
+3000.example. 5M IN A 10.0.9.13
+3000.example. 5M IN A 10.0.9.14
+3000.example. 5M IN A 10.0.9.15
+3000.example. 5M IN A 10.0.9.16
+3000.example. 5M IN A 10.0.9.17
+3000.example. 5M IN A 10.0.9.18
+3000.example. 5M IN A 10.0.9.19
+3000.example. 5M IN A 10.0.9.20
+3000.example. 5M IN A 10.0.9.21
+3000.example. 5M IN A 10.0.9.22
+3000.example. 5M IN A 10.0.9.23
+3000.example. 5M IN A 10.0.9.24
+3000.example. 5M IN A 10.0.9.25
+3000.example. 5M IN A 10.0.9.26
+3000.example. 5M IN A 10.0.9.27
+3000.example. 5M IN A 10.0.9.28
+3000.example. 5M IN A 10.0.9.29
+3000.example. 5M IN A 10.0.9.30
+3000.example. 5M IN A 10.0.9.31
+3000.example. 5M IN A 10.0.9.32
+3000.example. 5M IN A 10.0.9.33
+3000.example. 5M IN A 10.0.9.34
+3000.example. 5M IN A 10.0.9.35
+3000.example. 5M IN A 10.0.9.36
+3000.example. 5M IN A 10.0.9.37
+3000.example. 5M IN A 10.0.9.38
+3000.example. 5M IN A 10.0.9.39
+3000.example. 5M IN A 10.0.9.40
+3000.example. 5M IN A 10.0.9.41
+3000.example. 5M IN A 10.0.9.42
+3000.example. 5M IN A 10.0.9.43
+3000.example. 5M IN A 10.0.9.44
+3000.example. 5M IN A 10.0.9.45
+3000.example. 5M IN A 10.0.9.46
+3000.example. 5M IN A 10.0.9.47
+3000.example. 5M IN A 10.0.9.48
+3000.example. 5M IN A 10.0.9.49
+3000.example. 5M IN A 10.0.9.50
+3000.example. 5M IN A 10.0.9.51
+3000.example. 5M IN A 10.0.9.52
+3000.example. 5M IN A 10.0.9.53
+3000.example. 5M IN A 10.0.9.54
+3000.example. 5M IN A 10.0.9.55
+3000.example. 5M IN A 10.0.9.56
+3000.example. 5M IN A 10.0.9.57
+3000.example. 5M IN A 10.0.9.58
+3000.example. 5M IN A 10.0.9.59
+3000.example. 5M IN A 10.0.9.60
+3000.example. 5M IN A 10.0.9.61
+3000.example. 5M IN A 10.0.9.62
+3000.example. 5M IN A 10.0.9.63
+3000.example. 5M IN A 10.0.9.64
+3000.example. 5M IN A 10.0.9.65
+3000.example. 5M IN A 10.0.9.66
+3000.example. 5M IN A 10.0.9.67
+3000.example. 5M IN A 10.0.9.68
+3000.example. 5M IN A 10.0.9.69
+3000.example. 5M IN A 10.0.9.70
+3000.example. 5M IN A 10.0.9.71
+3000.example. 5M IN A 10.0.9.72
+3000.example. 5M IN A 10.0.9.73
+3000.example. 5M IN A 10.0.9.74
+3000.example. 5M IN A 10.0.9.75
+3000.example. 5M IN A 10.0.9.76
+3000.example. 5M IN A 10.0.9.77
+3000.example. 5M IN A 10.0.9.78
+3000.example. 5M IN A 10.0.9.79
+3000.example. 5M IN A 10.0.9.80
+3000.example. 5M IN A 10.0.9.81
+3000.example. 5M IN A 10.0.9.82
+3000.example. 5M IN A 10.0.9.83
+3000.example. 5M IN A 10.0.9.84
+3000.example. 5M IN A 10.0.9.85
+3000.example. 5M IN A 10.0.9.86
+3000.example. 5M IN A 10.0.9.87
+3000.example. 5M IN A 10.0.9.88
+3000.example. 5M IN A 10.0.9.89
+3000.example. 5M IN A 10.0.9.90
+3000.example. 5M IN A 10.0.9.91
+3000.example. 5M IN A 10.0.9.92
+3000.example. 5M IN A 10.0.9.93
+3000.example. 5M IN A 10.0.9.94
+3000.example. 5M IN A 10.0.9.95
+3000.example. 5M IN A 10.0.9.96
+3000.example. 5M IN A 10.0.9.97
+3000.example. 5M IN A 10.0.9.98
+3000.example. 5M IN A 10.0.9.99
+3000.example. 5M IN A 10.0.9.100
+3000.example. 5M IN A 10.0.9.101
+3000.example. 5M IN A 10.0.9.102
+3000.example. 5M IN A 10.0.9.103
+3000.example. 5M IN A 10.0.9.104
+3000.example. 5M IN A 10.0.9.105
+3000.example. 5M IN A 10.0.9.106
+3000.example. 5M IN A 10.0.9.107
+3000.example. 5M IN A 10.0.9.108
+3000.example. 5M IN A 10.0.9.109
+3000.example. 5M IN A 10.0.9.110
+3000.example. 5M IN A 10.0.9.111
+3000.example. 5M IN A 10.0.9.112
+3000.example. 5M IN A 10.0.9.113
+3000.example. 5M IN A 10.0.9.114
+3000.example. 5M IN A 10.0.9.115
+3000.example. 5M IN A 10.0.9.116
+3000.example. 5M IN A 10.0.9.117
+3000.example. 5M IN A 10.0.9.118
+3000.example. 5M IN A 10.0.9.119
+3000.example. 5M IN A 10.0.9.120
+3000.example. 5M IN A 10.0.9.121
+3000.example. 5M IN A 10.0.9.122
+3000.example. 5M IN A 10.0.9.123
+3000.example. 5M IN A 10.0.9.124
+3000.example. 5M IN A 10.0.9.125
+3000.example. 5M IN A 10.0.9.126
+3000.example. 5M IN A 10.0.9.127
+3000.example. 5M IN A 10.0.9.128
+3000.example. 5M IN A 10.0.9.129
+3000.example. 5M IN A 10.0.9.130
+3000.example. 5M IN A 10.0.9.131
+3000.example. 5M IN A 10.0.9.132
+3000.example. 5M IN A 10.0.9.133
+3000.example. 5M IN A 10.0.9.134
+3000.example. 5M IN A 10.0.9.135
+3000.example. 5M IN A 10.0.9.136
+3000.example. 5M IN A 10.0.9.137
+3000.example. 5M IN A 10.0.9.138
+3000.example. 5M IN A 10.0.9.139
+3000.example. 5M IN A 10.0.9.140
+3000.example. 5M IN A 10.0.9.141
+3000.example. 5M IN A 10.0.9.142
+3000.example. 5M IN A 10.0.9.143
+3000.example. 5M IN A 10.0.9.144
+3000.example. 5M IN A 10.0.9.145
+3000.example. 5M IN A 10.0.9.146
+3000.example. 5M IN A 10.0.9.147
+3000.example. 5M IN A 10.0.9.148
+3000.example. 5M IN A 10.0.9.149
+3000.example. 5M IN A 10.0.9.150
+3000.example. 5M IN A 10.0.9.151
+3000.example. 5M IN A 10.0.9.152
+3000.example. 5M IN A 10.0.9.153
+3000.example. 5M IN A 10.0.9.154
+3000.example. 5M IN A 10.0.9.155
+3000.example. 5M IN A 10.0.9.156
+3000.example. 5M IN A 10.0.9.157
+3000.example. 5M IN A 10.0.9.158
+3000.example. 5M IN A 10.0.9.159
+3000.example. 5M IN A 10.0.9.160
+3000.example. 5M IN A 10.0.9.161
+3000.example. 5M IN A 10.0.9.162
+3000.example. 5M IN A 10.0.9.163
+3000.example. 5M IN A 10.0.9.164
+3000.example. 5M IN A 10.0.9.165
+3000.example. 5M IN A 10.0.9.166
+3000.example. 5M IN A 10.0.9.167
+3000.example. 5M IN A 10.0.9.168
+3000.example. 5M IN A 10.0.9.169
+3000.example. 5M IN A 10.0.9.170
+3000.example. 5M IN A 10.0.9.171
+3000.example. 5M IN A 10.0.9.172
+3000.example. 5M IN A 10.0.9.173
+3000.example. 5M IN A 10.0.9.174
+3000.example. 5M IN A 10.0.9.175
+3000.example. 5M IN A 10.0.9.176
+3000.example. 5M IN A 10.0.9.177
+3000.example. 5M IN A 10.0.9.178
+3000.example. 5M IN A 10.0.9.179
+3000.example. 5M IN A 10.0.9.180
+3000.example. 5M IN A 10.0.9.181
+3000.example. 5M IN A 10.0.9.182
+3000.example. 5M IN A 10.0.9.183
+3000.example. 5M IN A 10.0.9.184
+3000.example. 5M IN A 10.0.9.185
+3000.example. 5M IN A 10.0.9.186
+3000.example. 5M IN A 10.0.9.187
+3000.example. 5M IN A 10.0.9.188
+3000.example. 5M IN A 10.0.9.189
+3000.example. 5M IN A 10.0.9.190
+3000.example. 5M IN A 10.0.9.191
+3000.example. 5M IN A 10.0.9.192
+3000.example. 5M IN A 10.0.9.193
+3000.example. 5M IN A 10.0.9.194
+3000.example. 5M IN A 10.0.9.195
+3000.example. 5M IN A 10.0.9.196
+3000.example. 5M IN A 10.0.9.197
+3000.example. 5M IN A 10.0.9.198
+3000.example. 5M IN A 10.0.9.199
+3000.example. 5M IN A 10.0.9.200
+3000.example. 5M IN A 10.0.9.201
+3000.example. 5M IN A 10.0.9.202
+3000.example. 5M IN A 10.0.9.203
+3000.example. 5M IN A 10.0.9.204
+3000.example. 5M IN A 10.0.9.205
+3000.example. 5M IN A 10.0.9.206
+3000.example. 5M IN A 10.0.9.207
+3000.example. 5M IN A 10.0.9.208
+3000.example. 5M IN A 10.0.9.209
+3000.example. 5M IN A 10.0.9.210
+3000.example. 5M IN A 10.0.9.211
+3000.example. 5M IN A 10.0.9.212
+3000.example. 5M IN A 10.0.9.213
+3000.example. 5M IN A 10.0.9.214
+3000.example. 5M IN A 10.0.9.215
+3000.example. 5M IN A 10.0.9.216
+3000.example. 5M IN A 10.0.9.217
+3000.example. 5M IN A 10.0.9.218
+3000.example. 5M IN A 10.0.9.219
+3000.example. 5M IN A 10.0.9.220
+3000.example. 5M IN A 10.0.9.221
+3000.example. 5M IN A 10.0.9.222
+3000.example. 5M IN A 10.0.9.223
+3000.example. 5M IN A 10.0.9.224
+3000.example. 5M IN A 10.0.9.225
+3000.example. 5M IN A 10.0.9.226
+3000.example. 5M IN A 10.0.9.227
+3000.example. 5M IN A 10.0.9.228
+3000.example. 5M IN A 10.0.9.229
+3000.example. 5M IN A 10.0.9.230
+3000.example. 5M IN A 10.0.9.231
+3000.example. 5M IN A 10.0.9.232
+3000.example. 5M IN A 10.0.9.233
+3000.example. 5M IN A 10.0.9.234
+3000.example. 5M IN A 10.0.9.235
+3000.example. 5M IN A 10.0.9.236
+3000.example. 5M IN A 10.0.9.237
+3000.example. 5M IN A 10.0.9.238
+3000.example. 5M IN A 10.0.9.239
+3000.example. 5M IN A 10.0.9.240
+3000.example. 5M IN A 10.0.9.241
+3000.example. 5M IN A 10.0.9.242
+3000.example. 5M IN A 10.0.9.243
+3000.example. 5M IN A 10.0.9.244
+3000.example. 5M IN A 10.0.9.245
+3000.example. 5M IN A 10.0.9.246
+3000.example. 5M IN A 10.0.9.247
+3000.example. 5M IN A 10.0.9.248
+3000.example. 5M IN A 10.0.9.249
+3000.example. 5M IN A 10.0.9.250
+3000.example. 5M IN A 10.0.9.251
+3000.example. 5M IN A 10.0.9.252
+3000.example. 5M IN A 10.0.9.253
+3000.example. 5M IN A 10.0.9.254
+3000.example. 5M IN A 10.0.9.255
+3000.example. 5M IN A 10.0.10.0
+3000.example. 5M IN A 10.0.10.1
+3000.example. 5M IN A 10.0.10.2
+3000.example. 5M IN A 10.0.10.3
+3000.example. 5M IN A 10.0.10.4
+3000.example. 5M IN A 10.0.10.5
+3000.example. 5M IN A 10.0.10.6
+3000.example. 5M IN A 10.0.10.7
+3000.example. 5M IN A 10.0.10.8
+3000.example. 5M IN A 10.0.10.9
+3000.example. 5M IN A 10.0.10.10
+3000.example. 5M IN A 10.0.10.11
+3000.example. 5M IN A 10.0.10.12
+3000.example. 5M IN A 10.0.10.13
+3000.example. 5M IN A 10.0.10.14
+3000.example. 5M IN A 10.0.10.15
+3000.example. 5M IN A 10.0.10.16
+3000.example. 5M IN A 10.0.10.17
+3000.example. 5M IN A 10.0.10.18
+3000.example. 5M IN A 10.0.10.19
+3000.example. 5M IN A 10.0.10.20
+3000.example. 5M IN A 10.0.10.21
+3000.example. 5M IN A 10.0.10.22
+3000.example. 5M IN A 10.0.10.23
+3000.example. 5M IN A 10.0.10.24
+3000.example. 5M IN A 10.0.10.25
+3000.example. 5M IN A 10.0.10.26
+3000.example. 5M IN A 10.0.10.27
+3000.example. 5M IN A 10.0.10.28
+3000.example. 5M IN A 10.0.10.29
+3000.example. 5M IN A 10.0.10.30
+3000.example. 5M IN A 10.0.10.31
+3000.example. 5M IN A 10.0.10.32
+3000.example. 5M IN A 10.0.10.33
+3000.example. 5M IN A 10.0.10.34
+3000.example. 5M IN A 10.0.10.35
+3000.example. 5M IN A 10.0.10.36
+3000.example. 5M IN A 10.0.10.37
+3000.example. 5M IN A 10.0.10.38
+3000.example. 5M IN A 10.0.10.39
+3000.example. 5M IN A 10.0.10.40
+3000.example. 5M IN A 10.0.10.41
+3000.example. 5M IN A 10.0.10.42
+3000.example. 5M IN A 10.0.10.43
+3000.example. 5M IN A 10.0.10.44
+3000.example. 5M IN A 10.0.10.45
+3000.example. 5M IN A 10.0.10.46
+3000.example. 5M IN A 10.0.10.47
+3000.example. 5M IN A 10.0.10.48
+3000.example. 5M IN A 10.0.10.49
+3000.example. 5M IN A 10.0.10.50
+3000.example. 5M IN A 10.0.10.51
+3000.example. 5M IN A 10.0.10.52
+3000.example. 5M IN A 10.0.10.53
+3000.example. 5M IN A 10.0.10.54
+3000.example. 5M IN A 10.0.10.55
+3000.example. 5M IN A 10.0.10.56
+3000.example. 5M IN A 10.0.10.57
+3000.example. 5M IN A 10.0.10.58
+3000.example. 5M IN A 10.0.10.59
+3000.example. 5M IN A 10.0.10.60
+3000.example. 5M IN A 10.0.10.61
+3000.example. 5M IN A 10.0.10.62
+3000.example. 5M IN A 10.0.10.63
+3000.example. 5M IN A 10.0.10.64
+3000.example. 5M IN A 10.0.10.65
+3000.example. 5M IN A 10.0.10.66
+3000.example. 5M IN A 10.0.10.67
+3000.example. 5M IN A 10.0.10.68
+3000.example. 5M IN A 10.0.10.69
+3000.example. 5M IN A 10.0.10.70
+3000.example. 5M IN A 10.0.10.71
+3000.example. 5M IN A 10.0.10.72
+3000.example. 5M IN A 10.0.10.73
+3000.example. 5M IN A 10.0.10.74
+3000.example. 5M IN A 10.0.10.75
+3000.example. 5M IN A 10.0.10.76
+3000.example. 5M IN A 10.0.10.77
+3000.example. 5M IN A 10.0.10.78
+3000.example. 5M IN A 10.0.10.79
+3000.example. 5M IN A 10.0.10.80
+3000.example. 5M IN A 10.0.10.81
+3000.example. 5M IN A 10.0.10.82
+3000.example. 5M IN A 10.0.10.83
+3000.example. 5M IN A 10.0.10.84
+3000.example. 5M IN A 10.0.10.85
+3000.example. 5M IN A 10.0.10.86
+3000.example. 5M IN A 10.0.10.87
+3000.example. 5M IN A 10.0.10.88
+3000.example. 5M IN A 10.0.10.89
+3000.example. 5M IN A 10.0.10.90
+3000.example. 5M IN A 10.0.10.91
+3000.example. 5M IN A 10.0.10.92
+3000.example. 5M IN A 10.0.10.93
+3000.example. 5M IN A 10.0.10.94
+3000.example. 5M IN A 10.0.10.95
+3000.example. 5M IN A 10.0.10.96
+3000.example. 5M IN A 10.0.10.97
+3000.example. 5M IN A 10.0.10.98
+3000.example. 5M IN A 10.0.10.99
+3000.example. 5M IN A 10.0.10.100
+3000.example. 5M IN A 10.0.10.101
+3000.example. 5M IN A 10.0.10.102
+3000.example. 5M IN A 10.0.10.103
+3000.example. 5M IN A 10.0.10.104
+3000.example. 5M IN A 10.0.10.105
+3000.example. 5M IN A 10.0.10.106
+3000.example. 5M IN A 10.0.10.107
+3000.example. 5M IN A 10.0.10.108
+3000.example. 5M IN A 10.0.10.109
+3000.example. 5M IN A 10.0.10.110
+3000.example. 5M IN A 10.0.10.111
+3000.example. 5M IN A 10.0.10.112
+3000.example. 5M IN A 10.0.10.113
+3000.example. 5M IN A 10.0.10.114
+3000.example. 5M IN A 10.0.10.115
+3000.example. 5M IN A 10.0.10.116
+3000.example. 5M IN A 10.0.10.117
+3000.example. 5M IN A 10.0.10.118
+3000.example. 5M IN A 10.0.10.119
+3000.example. 5M IN A 10.0.10.120
+3000.example. 5M IN A 10.0.10.121
+3000.example. 5M IN A 10.0.10.122
+3000.example. 5M IN A 10.0.10.123
+3000.example. 5M IN A 10.0.10.124
+3000.example. 5M IN A 10.0.10.125
+3000.example. 5M IN A 10.0.10.126
+3000.example. 5M IN A 10.0.10.127
+3000.example. 5M IN A 10.0.10.128
+3000.example. 5M IN A 10.0.10.129
+3000.example. 5M IN A 10.0.10.130
+3000.example. 5M IN A 10.0.10.131
+3000.example. 5M IN A 10.0.10.132
+3000.example. 5M IN A 10.0.10.133
+3000.example. 5M IN A 10.0.10.134
+3000.example. 5M IN A 10.0.10.135
+3000.example. 5M IN A 10.0.10.136
+3000.example. 5M IN A 10.0.10.137
+3000.example. 5M IN A 10.0.10.138
+3000.example. 5M IN A 10.0.10.139
+3000.example. 5M IN A 10.0.10.140
+3000.example. 5M IN A 10.0.10.141
+3000.example. 5M IN A 10.0.10.142
+3000.example. 5M IN A 10.0.10.143
+3000.example. 5M IN A 10.0.10.144
+3000.example. 5M IN A 10.0.10.145
+3000.example. 5M IN A 10.0.10.146
+3000.example. 5M IN A 10.0.10.147
+3000.example. 5M IN A 10.0.10.148
+3000.example. 5M IN A 10.0.10.149
+3000.example. 5M IN A 10.0.10.150
+3000.example. 5M IN A 10.0.10.151
+3000.example. 5M IN A 10.0.10.152
+3000.example. 5M IN A 10.0.10.153
+3000.example. 5M IN A 10.0.10.154
+3000.example. 5M IN A 10.0.10.155
+3000.example. 5M IN A 10.0.10.156
+3000.example. 5M IN A 10.0.10.157
+3000.example. 5M IN A 10.0.10.158
+3000.example. 5M IN A 10.0.10.159
+3000.example. 5M IN A 10.0.10.160
+3000.example. 5M IN A 10.0.10.161
+3000.example. 5M IN A 10.0.10.162
+3000.example. 5M IN A 10.0.10.163
+3000.example. 5M IN A 10.0.10.164
+3000.example. 5M IN A 10.0.10.165
+3000.example. 5M IN A 10.0.10.166
+3000.example. 5M IN A 10.0.10.167
+3000.example. 5M IN A 10.0.10.168
+3000.example. 5M IN A 10.0.10.169
+3000.example. 5M IN A 10.0.10.170
+3000.example. 5M IN A 10.0.10.171
+3000.example. 5M IN A 10.0.10.172
+3000.example. 5M IN A 10.0.10.173
+3000.example. 5M IN A 10.0.10.174
+3000.example. 5M IN A 10.0.10.175
+3000.example. 5M IN A 10.0.10.176
+3000.example. 5M IN A 10.0.10.177
+3000.example. 5M IN A 10.0.10.178
+3000.example. 5M IN A 10.0.10.179
+3000.example. 5M IN A 10.0.10.180
+3000.example. 5M IN A 10.0.10.181
+3000.example. 5M IN A 10.0.10.182
+3000.example. 5M IN A 10.0.10.183
+3000.example. 5M IN A 10.0.10.184
+3000.example. 5M IN A 10.0.10.185
+3000.example. 5M IN A 10.0.10.186
+3000.example. 5M IN A 10.0.10.187
+3000.example. 5M IN A 10.0.10.188
+3000.example. 5M IN A 10.0.10.189
+3000.example. 5M IN A 10.0.10.190
+3000.example. 5M IN A 10.0.10.191
+3000.example. 5M IN A 10.0.10.192
+3000.example. 5M IN A 10.0.10.193
+3000.example. 5M IN A 10.0.10.194
+3000.example. 5M IN A 10.0.10.195
+3000.example. 5M IN A 10.0.10.196
+3000.example. 5M IN A 10.0.10.197
+3000.example. 5M IN A 10.0.10.198
+3000.example. 5M IN A 10.0.10.199
+3000.example. 5M IN A 10.0.10.200
+3000.example. 5M IN A 10.0.10.201
+3000.example. 5M IN A 10.0.10.202
+3000.example. 5M IN A 10.0.10.203
+3000.example. 5M IN A 10.0.10.204
+3000.example. 5M IN A 10.0.10.205
+3000.example. 5M IN A 10.0.10.206
+3000.example. 5M IN A 10.0.10.207
+3000.example. 5M IN A 10.0.10.208
+3000.example. 5M IN A 10.0.10.209
+3000.example. 5M IN A 10.0.10.210
+3000.example. 5M IN A 10.0.10.211
+3000.example. 5M IN A 10.0.10.212
+3000.example. 5M IN A 10.0.10.213
+3000.example. 5M IN A 10.0.10.214
+3000.example. 5M IN A 10.0.10.215
+3000.example. 5M IN A 10.0.10.216
+3000.example. 5M IN A 10.0.10.217
+3000.example. 5M IN A 10.0.10.218
+3000.example. 5M IN A 10.0.10.219
+3000.example. 5M IN A 10.0.10.220
+3000.example. 5M IN A 10.0.10.221
+3000.example. 5M IN A 10.0.10.222
+3000.example. 5M IN A 10.0.10.223
+3000.example. 5M IN A 10.0.10.224
+3000.example. 5M IN A 10.0.10.225
+3000.example. 5M IN A 10.0.10.226
+3000.example. 5M IN A 10.0.10.227
+3000.example. 5M IN A 10.0.10.228
+3000.example. 5M IN A 10.0.10.229
+3000.example. 5M IN A 10.0.10.230
+3000.example. 5M IN A 10.0.10.231
+3000.example. 5M IN A 10.0.10.232
+3000.example. 5M IN A 10.0.10.233
+3000.example. 5M IN A 10.0.10.234
+3000.example. 5M IN A 10.0.10.235
+3000.example. 5M IN A 10.0.10.236
+3000.example. 5M IN A 10.0.10.237
+3000.example. 5M IN A 10.0.10.238
+3000.example. 5M IN A 10.0.10.239
+3000.example. 5M IN A 10.0.10.240
+3000.example. 5M IN A 10.0.10.241
+3000.example. 5M IN A 10.0.10.242
+3000.example. 5M IN A 10.0.10.243
+3000.example. 5M IN A 10.0.10.244
+3000.example. 5M IN A 10.0.10.245
+3000.example. 5M IN A 10.0.10.246
+3000.example. 5M IN A 10.0.10.247
+3000.example. 5M IN A 10.0.10.248
+3000.example. 5M IN A 10.0.10.249
+3000.example. 5M IN A 10.0.10.250
+3000.example. 5M IN A 10.0.10.251
+3000.example. 5M IN A 10.0.10.252
+3000.example. 5M IN A 10.0.10.253
+3000.example. 5M IN A 10.0.10.254
+3000.example. 5M IN A 10.0.10.255
+3000.example. 5M IN A 10.0.11.0
+3000.example. 5M IN A 10.0.11.1
+3000.example. 5M IN A 10.0.11.2
+3000.example. 5M IN A 10.0.11.3
+3000.example. 5M IN A 10.0.11.4
+3000.example. 5M IN A 10.0.11.5
+3000.example. 5M IN A 10.0.11.6
+3000.example. 5M IN A 10.0.11.7
+3000.example. 5M IN A 10.0.11.8
+3000.example. 5M IN A 10.0.11.9
+3000.example. 5M IN A 10.0.11.10
+3000.example. 5M IN A 10.0.11.11
+3000.example. 5M IN A 10.0.11.12
+3000.example. 5M IN A 10.0.11.13
+3000.example. 5M IN A 10.0.11.14
+3000.example. 5M IN A 10.0.11.15
+3000.example. 5M IN A 10.0.11.16
+3000.example. 5M IN A 10.0.11.17
+3000.example. 5M IN A 10.0.11.18
+3000.example. 5M IN A 10.0.11.19
+3000.example. 5M IN A 10.0.11.20
+3000.example. 5M IN A 10.0.11.21
+3000.example. 5M IN A 10.0.11.22
+3000.example. 5M IN A 10.0.11.23
+3000.example. 5M IN A 10.0.11.24
+3000.example. 5M IN A 10.0.11.25
+3000.example. 5M IN A 10.0.11.26
+3000.example. 5M IN A 10.0.11.27
+3000.example. 5M IN A 10.0.11.28
+3000.example. 5M IN A 10.0.11.29
+3000.example. 5M IN A 10.0.11.30
+3000.example. 5M IN A 10.0.11.31
+3000.example. 5M IN A 10.0.11.32
+3000.example. 5M IN A 10.0.11.33
+3000.example. 5M IN A 10.0.11.34
+3000.example. 5M IN A 10.0.11.35
+3000.example. 5M IN A 10.0.11.36
+3000.example. 5M IN A 10.0.11.37
+3000.example. 5M IN A 10.0.11.38
+3000.example. 5M IN A 10.0.11.39
+3000.example. 5M IN A 10.0.11.40
+3000.example. 5M IN A 10.0.11.41
+3000.example. 5M IN A 10.0.11.42
+3000.example. 5M IN A 10.0.11.43
+3000.example. 5M IN A 10.0.11.44
+3000.example. 5M IN A 10.0.11.45
+3000.example. 5M IN A 10.0.11.46
+3000.example. 5M IN A 10.0.11.47
+3000.example. 5M IN A 10.0.11.48
+3000.example. 5M IN A 10.0.11.49
+3000.example. 5M IN A 10.0.11.50
+3000.example. 5M IN A 10.0.11.51
+3000.example. 5M IN A 10.0.11.52
+3000.example. 5M IN A 10.0.11.53
+3000.example. 5M IN A 10.0.11.54
+3000.example. 5M IN A 10.0.11.55
+3000.example. 5M IN A 10.0.11.56
+3000.example. 5M IN A 10.0.11.57
+3000.example. 5M IN A 10.0.11.58
+3000.example. 5M IN A 10.0.11.59
+3000.example. 5M IN A 10.0.11.60
+3000.example. 5M IN A 10.0.11.61
+3000.example. 5M IN A 10.0.11.62
+3000.example. 5M IN A 10.0.11.63
+3000.example. 5M IN A 10.0.11.64
+3000.example. 5M IN A 10.0.11.65
+3000.example. 5M IN A 10.0.11.66
+3000.example. 5M IN A 10.0.11.67
+3000.example. 5M IN A 10.0.11.68
+3000.example. 5M IN A 10.0.11.69
+3000.example. 5M IN A 10.0.11.70
+3000.example. 5M IN A 10.0.11.71
+3000.example. 5M IN A 10.0.11.72
+3000.example. 5M IN A 10.0.11.73
+3000.example. 5M IN A 10.0.11.74
+3000.example. 5M IN A 10.0.11.75
+3000.example. 5M IN A 10.0.11.76
+3000.example. 5M IN A 10.0.11.77
+3000.example. 5M IN A 10.0.11.78
+3000.example. 5M IN A 10.0.11.79
+3000.example. 5M IN A 10.0.11.80
+3000.example. 5M IN A 10.0.11.81
+3000.example. 5M IN A 10.0.11.82
+3000.example. 5M IN A 10.0.11.83
+3000.example. 5M IN A 10.0.11.84
+3000.example. 5M IN A 10.0.11.85
+3000.example. 5M IN A 10.0.11.86
+3000.example. 5M IN A 10.0.11.87
+3000.example. 5M IN A 10.0.11.88
+3000.example. 5M IN A 10.0.11.89
+3000.example. 5M IN A 10.0.11.90
+3000.example. 5M IN A 10.0.11.91
+3000.example. 5M IN A 10.0.11.92
+3000.example. 5M IN A 10.0.11.93
+3000.example. 5M IN A 10.0.11.94
+3000.example. 5M IN A 10.0.11.95
+3000.example. 5M IN A 10.0.11.96
+3000.example. 5M IN A 10.0.11.97
+3000.example. 5M IN A 10.0.11.98
+3000.example. 5M IN A 10.0.11.99
+3000.example. 5M IN A 10.0.11.100
+3000.example. 5M IN A 10.0.11.101
+3000.example. 5M IN A 10.0.11.102
+3000.example. 5M IN A 10.0.11.103
+3000.example. 5M IN A 10.0.11.104
+3000.example. 5M IN A 10.0.11.105
+3000.example. 5M IN A 10.0.11.106
+3000.example. 5M IN A 10.0.11.107
+3000.example. 5M IN A 10.0.11.108
+3000.example. 5M IN A 10.0.11.109
+3000.example. 5M IN A 10.0.11.110
+3000.example. 5M IN A 10.0.11.111
+3000.example. 5M IN A 10.0.11.112
+3000.example. 5M IN A 10.0.11.113
+3000.example. 5M IN A 10.0.11.114
+3000.example. 5M IN A 10.0.11.115
+3000.example. 5M IN A 10.0.11.116
+3000.example. 5M IN A 10.0.11.117
+3000.example. 5M IN A 10.0.11.118
+3000.example. 5M IN A 10.0.11.119
+3000.example. 5M IN A 10.0.11.120
+3000.example. 5M IN A 10.0.11.121
+3000.example. 5M IN A 10.0.11.122
+3000.example. 5M IN A 10.0.11.123
+3000.example. 5M IN A 10.0.11.124
+3000.example. 5M IN A 10.0.11.125
+3000.example. 5M IN A 10.0.11.126
+3000.example. 5M IN A 10.0.11.127
+3000.example. 5M IN A 10.0.11.128
+3000.example. 5M IN A 10.0.11.129
+3000.example. 5M IN A 10.0.11.130
+3000.example. 5M IN A 10.0.11.131
+3000.example. 5M IN A 10.0.11.132
+3000.example. 5M IN A 10.0.11.133
+3000.example. 5M IN A 10.0.11.134
+3000.example. 5M IN A 10.0.11.135
+3000.example. 5M IN A 10.0.11.136
+3000.example. 5M IN A 10.0.11.137
+3000.example. 5M IN A 10.0.11.138
+3000.example. 5M IN A 10.0.11.139
+3000.example. 5M IN A 10.0.11.140
+3000.example. 5M IN A 10.0.11.141
+3000.example. 5M IN A 10.0.11.142
+3000.example. 5M IN A 10.0.11.143
+3000.example. 5M IN A 10.0.11.144
+3000.example. 5M IN A 10.0.11.145
+3000.example. 5M IN A 10.0.11.146
+3000.example. 5M IN A 10.0.11.147
+3000.example. 5M IN A 10.0.11.148
+3000.example. 5M IN A 10.0.11.149
+3000.example. 5M IN A 10.0.11.150
+3000.example. 5M IN A 10.0.11.151
+3000.example. 5M IN A 10.0.11.152
+3000.example. 5M IN A 10.0.11.153
+3000.example. 5M IN A 10.0.11.154
+3000.example. 5M IN A 10.0.11.155
+3000.example. 5M IN A 10.0.11.156
+3000.example. 5M IN A 10.0.11.157
+3000.example. 5M IN A 10.0.11.158
+3000.example. 5M IN A 10.0.11.159
+3000.example. 5M IN A 10.0.11.160
+3000.example. 5M IN A 10.0.11.161
+3000.example. 5M IN A 10.0.11.162
+3000.example. 5M IN A 10.0.11.163
+3000.example. 5M IN A 10.0.11.164
+3000.example. 5M IN A 10.0.11.165
+3000.example. 5M IN A 10.0.11.166
+3000.example. 5M IN A 10.0.11.167
+3000.example. 5M IN A 10.0.11.168
+3000.example. 5M IN A 10.0.11.169
+3000.example. 5M IN A 10.0.11.170
+3000.example. 5M IN A 10.0.11.171
+3000.example. 5M IN A 10.0.11.172
+3000.example. 5M IN A 10.0.11.173
+3000.example. 5M IN A 10.0.11.174
+3000.example. 5M IN A 10.0.11.175
+3000.example. 5M IN A 10.0.11.176
+3000.example. 5M IN A 10.0.11.177
+3000.example. 5M IN A 10.0.11.178
+3000.example. 5M IN A 10.0.11.179
+3000.example. 5M IN A 10.0.11.180
+3000.example. 5M IN A 10.0.11.181
+3000.example. 5M IN A 10.0.11.182
+3000.example. 5M IN A 10.0.11.183
+
+;; AUTHORITY SECTION:
+example. 5M IN NS ns1.example.
+
+;; ADDITIONAL SECTION:
+ns1.example. 5M IN A 10.53.0.1
+
+;; Total query time: 211 msec
+;; FROM: draco to SERVER: 10.53.0.1
+;; WHEN: Fri Jun 23 12:58:17 2000
+;; MSG SIZE sent: 30 rcvd: 48068
+
diff --git a/bin/tests/system/limits/knowngood.dig.out.4000 b/bin/tests/system/limits/knowngood.dig.out.4000
new file mode 100644
index 0000000..8b109c8
--- /dev/null
+++ b/bin/tests/system/limits/knowngood.dig.out.4000
@@ -0,0 +1,4023 @@
+
+; <<>> DiG 8.2 <<>> 4000.example. @10.53.0.1 a -p
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr aa rd ad; QUERY: 1, ANSWER: 4000, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; 4000.example, type = A, class = IN
+
+;; ANSWER SECTION:
+4000.example. 5M IN A 10.0.0.0
+4000.example. 5M IN A 10.0.0.1
+4000.example. 5M IN A 10.0.0.2
+4000.example. 5M IN A 10.0.0.3
+4000.example. 5M IN A 10.0.0.4
+4000.example. 5M IN A 10.0.0.5
+4000.example. 5M IN A 10.0.0.6
+4000.example. 5M IN A 10.0.0.7
+4000.example. 5M IN A 10.0.0.8
+4000.example. 5M IN A 10.0.0.9
+4000.example. 5M IN A 10.0.0.10
+4000.example. 5M IN A 10.0.0.11
+4000.example. 5M IN A 10.0.0.12
+4000.example. 5M IN A 10.0.0.13
+4000.example. 5M IN A 10.0.0.14
+4000.example. 5M IN A 10.0.0.15
+4000.example. 5M IN A 10.0.0.16
+4000.example. 5M IN A 10.0.0.17
+4000.example. 5M IN A 10.0.0.18
+4000.example. 5M IN A 10.0.0.19
+4000.example. 5M IN A 10.0.0.20
+4000.example. 5M IN A 10.0.0.21
+4000.example. 5M IN A 10.0.0.22
+4000.example. 5M IN A 10.0.0.23
+4000.example. 5M IN A 10.0.0.24
+4000.example. 5M IN A 10.0.0.25
+4000.example. 5M IN A 10.0.0.26
+4000.example. 5M IN A 10.0.0.27
+4000.example. 5M IN A 10.0.0.28
+4000.example. 5M IN A 10.0.0.29
+4000.example. 5M IN A 10.0.0.30
+4000.example. 5M IN A 10.0.0.31
+4000.example. 5M IN A 10.0.0.32
+4000.example. 5M IN A 10.0.0.33
+4000.example. 5M IN A 10.0.0.34
+4000.example. 5M IN A 10.0.0.35
+4000.example. 5M IN A 10.0.0.36
+4000.example. 5M IN A 10.0.0.37
+4000.example. 5M IN A 10.0.0.38
+4000.example. 5M IN A 10.0.0.39
+4000.example. 5M IN A 10.0.0.40
+4000.example. 5M IN A 10.0.0.41
+4000.example. 5M IN A 10.0.0.42
+4000.example. 5M IN A 10.0.0.43
+4000.example. 5M IN A 10.0.0.44
+4000.example. 5M IN A 10.0.0.45
+4000.example. 5M IN A 10.0.0.46
+4000.example. 5M IN A 10.0.0.47
+4000.example. 5M IN A 10.0.0.48
+4000.example. 5M IN A 10.0.0.49
+4000.example. 5M IN A 10.0.0.50
+4000.example. 5M IN A 10.0.0.51
+4000.example. 5M IN A 10.0.0.52
+4000.example. 5M IN A 10.0.0.53
+4000.example. 5M IN A 10.0.0.54
+4000.example. 5M IN A 10.0.0.55
+4000.example. 5M IN A 10.0.0.56
+4000.example. 5M IN A 10.0.0.57
+4000.example. 5M IN A 10.0.0.58
+4000.example. 5M IN A 10.0.0.59
+4000.example. 5M IN A 10.0.0.60
+4000.example. 5M IN A 10.0.0.61
+4000.example. 5M IN A 10.0.0.62
+4000.example. 5M IN A 10.0.0.63
+4000.example. 5M IN A 10.0.0.64
+4000.example. 5M IN A 10.0.0.65
+4000.example. 5M IN A 10.0.0.66
+4000.example. 5M IN A 10.0.0.67
+4000.example. 5M IN A 10.0.0.68
+4000.example. 5M IN A 10.0.0.69
+4000.example. 5M IN A 10.0.0.70
+4000.example. 5M IN A 10.0.0.71
+4000.example. 5M IN A 10.0.0.72
+4000.example. 5M IN A 10.0.0.73
+4000.example. 5M IN A 10.0.0.74
+4000.example. 5M IN A 10.0.0.75
+4000.example. 5M IN A 10.0.0.76
+4000.example. 5M IN A 10.0.0.77
+4000.example. 5M IN A 10.0.0.78
+4000.example. 5M IN A 10.0.0.79
+4000.example. 5M IN A 10.0.0.80
+4000.example. 5M IN A 10.0.0.81
+4000.example. 5M IN A 10.0.0.82
+4000.example. 5M IN A 10.0.0.83
+4000.example. 5M IN A 10.0.0.84
+4000.example. 5M IN A 10.0.0.85
+4000.example. 5M IN A 10.0.0.86
+4000.example. 5M IN A 10.0.0.87
+4000.example. 5M IN A 10.0.0.88
+4000.example. 5M IN A 10.0.0.89
+4000.example. 5M IN A 10.0.0.90
+4000.example. 5M IN A 10.0.0.91
+4000.example. 5M IN A 10.0.0.92
+4000.example. 5M IN A 10.0.0.93
+4000.example. 5M IN A 10.0.0.94
+4000.example. 5M IN A 10.0.0.95
+4000.example. 5M IN A 10.0.0.96
+4000.example. 5M IN A 10.0.0.97
+4000.example. 5M IN A 10.0.0.98
+4000.example. 5M IN A 10.0.0.99
+4000.example. 5M IN A 10.0.0.100
+4000.example. 5M IN A 10.0.0.101
+4000.example. 5M IN A 10.0.0.102
+4000.example. 5M IN A 10.0.0.103
+4000.example. 5M IN A 10.0.0.104
+4000.example. 5M IN A 10.0.0.105
+4000.example. 5M IN A 10.0.0.106
+4000.example. 5M IN A 10.0.0.107
+4000.example. 5M IN A 10.0.0.108
+4000.example. 5M IN A 10.0.0.109
+4000.example. 5M IN A 10.0.0.110
+4000.example. 5M IN A 10.0.0.111
+4000.example. 5M IN A 10.0.0.112
+4000.example. 5M IN A 10.0.0.113
+4000.example. 5M IN A 10.0.0.114
+4000.example. 5M IN A 10.0.0.115
+4000.example. 5M IN A 10.0.0.116
+4000.example. 5M IN A 10.0.0.117
+4000.example. 5M IN A 10.0.0.118
+4000.example. 5M IN A 10.0.0.119
+4000.example. 5M IN A 10.0.0.120
+4000.example. 5M IN A 10.0.0.121
+4000.example. 5M IN A 10.0.0.122
+4000.example. 5M IN A 10.0.0.123
+4000.example. 5M IN A 10.0.0.124
+4000.example. 5M IN A 10.0.0.125
+4000.example. 5M IN A 10.0.0.126
+4000.example. 5M IN A 10.0.0.127
+4000.example. 5M IN A 10.0.0.128
+4000.example. 5M IN A 10.0.0.129
+4000.example. 5M IN A 10.0.0.130
+4000.example. 5M IN A 10.0.0.131
+4000.example. 5M IN A 10.0.0.132
+4000.example. 5M IN A 10.0.0.133
+4000.example. 5M IN A 10.0.0.134
+4000.example. 5M IN A 10.0.0.135
+4000.example. 5M IN A 10.0.0.136
+4000.example. 5M IN A 10.0.0.137
+4000.example. 5M IN A 10.0.0.138
+4000.example. 5M IN A 10.0.0.139
+4000.example. 5M IN A 10.0.0.140
+4000.example. 5M IN A 10.0.0.141
+4000.example. 5M IN A 10.0.0.142
+4000.example. 5M IN A 10.0.0.143
+4000.example. 5M IN A 10.0.0.144
+4000.example. 5M IN A 10.0.0.145
+4000.example. 5M IN A 10.0.0.146
+4000.example. 5M IN A 10.0.0.147
+4000.example. 5M IN A 10.0.0.148
+4000.example. 5M IN A 10.0.0.149
+4000.example. 5M IN A 10.0.0.150
+4000.example. 5M IN A 10.0.0.151
+4000.example. 5M IN A 10.0.0.152
+4000.example. 5M IN A 10.0.0.153
+4000.example. 5M IN A 10.0.0.154
+4000.example. 5M IN A 10.0.0.155
+4000.example. 5M IN A 10.0.0.156
+4000.example. 5M IN A 10.0.0.157
+4000.example. 5M IN A 10.0.0.158
+4000.example. 5M IN A 10.0.0.159
+4000.example. 5M IN A 10.0.0.160
+4000.example. 5M IN A 10.0.0.161
+4000.example. 5M IN A 10.0.0.162
+4000.example. 5M IN A 10.0.0.163
+4000.example. 5M IN A 10.0.0.164
+4000.example. 5M IN A 10.0.0.165
+4000.example. 5M IN A 10.0.0.166
+4000.example. 5M IN A 10.0.0.167
+4000.example. 5M IN A 10.0.0.168
+4000.example. 5M IN A 10.0.0.169
+4000.example. 5M IN A 10.0.0.170
+4000.example. 5M IN A 10.0.0.171
+4000.example. 5M IN A 10.0.0.172
+4000.example. 5M IN A 10.0.0.173
+4000.example. 5M IN A 10.0.0.174
+4000.example. 5M IN A 10.0.0.175
+4000.example. 5M IN A 10.0.0.176
+4000.example. 5M IN A 10.0.0.177
+4000.example. 5M IN A 10.0.0.178
+4000.example. 5M IN A 10.0.0.179
+4000.example. 5M IN A 10.0.0.180
+4000.example. 5M IN A 10.0.0.181
+4000.example. 5M IN A 10.0.0.182
+4000.example. 5M IN A 10.0.0.183
+4000.example. 5M IN A 10.0.0.184
+4000.example. 5M IN A 10.0.0.185
+4000.example. 5M IN A 10.0.0.186
+4000.example. 5M IN A 10.0.0.187
+4000.example. 5M IN A 10.0.0.188
+4000.example. 5M IN A 10.0.0.189
+4000.example. 5M IN A 10.0.0.190
+4000.example. 5M IN A 10.0.0.191
+4000.example. 5M IN A 10.0.0.192
+4000.example. 5M IN A 10.0.0.193
+4000.example. 5M IN A 10.0.0.194
+4000.example. 5M IN A 10.0.0.195
+4000.example. 5M IN A 10.0.0.196
+4000.example. 5M IN A 10.0.0.197
+4000.example. 5M IN A 10.0.0.198
+4000.example. 5M IN A 10.0.0.199
+4000.example. 5M IN A 10.0.0.200
+4000.example. 5M IN A 10.0.0.201
+4000.example. 5M IN A 10.0.0.202
+4000.example. 5M IN A 10.0.0.203
+4000.example. 5M IN A 10.0.0.204
+4000.example. 5M IN A 10.0.0.205
+4000.example. 5M IN A 10.0.0.206
+4000.example. 5M IN A 10.0.0.207
+4000.example. 5M IN A 10.0.0.208
+4000.example. 5M IN A 10.0.0.209
+4000.example. 5M IN A 10.0.0.210
+4000.example. 5M IN A 10.0.0.211
+4000.example. 5M IN A 10.0.0.212
+4000.example. 5M IN A 10.0.0.213
+4000.example. 5M IN A 10.0.0.214
+4000.example. 5M IN A 10.0.0.215
+4000.example. 5M IN A 10.0.0.216
+4000.example. 5M IN A 10.0.0.217
+4000.example. 5M IN A 10.0.0.218
+4000.example. 5M IN A 10.0.0.219
+4000.example. 5M IN A 10.0.0.220
+4000.example. 5M IN A 10.0.0.221
+4000.example. 5M IN A 10.0.0.222
+4000.example. 5M IN A 10.0.0.223
+4000.example. 5M IN A 10.0.0.224
+4000.example. 5M IN A 10.0.0.225
+4000.example. 5M IN A 10.0.0.226
+4000.example. 5M IN A 10.0.0.227
+4000.example. 5M IN A 10.0.0.228
+4000.example. 5M IN A 10.0.0.229
+4000.example. 5M IN A 10.0.0.230
+4000.example. 5M IN A 10.0.0.231
+4000.example. 5M IN A 10.0.0.232
+4000.example. 5M IN A 10.0.0.233
+4000.example. 5M IN A 10.0.0.234
+4000.example. 5M IN A 10.0.0.235
+4000.example. 5M IN A 10.0.0.236
+4000.example. 5M IN A 10.0.0.237
+4000.example. 5M IN A 10.0.0.238
+4000.example. 5M IN A 10.0.0.239
+4000.example. 5M IN A 10.0.0.240
+4000.example. 5M IN A 10.0.0.241
+4000.example. 5M IN A 10.0.0.242
+4000.example. 5M IN A 10.0.0.243
+4000.example. 5M IN A 10.0.0.244
+4000.example. 5M IN A 10.0.0.245
+4000.example. 5M IN A 10.0.0.246
+4000.example. 5M IN A 10.0.0.247
+4000.example. 5M IN A 10.0.0.248
+4000.example. 5M IN A 10.0.0.249
+4000.example. 5M IN A 10.0.0.250
+4000.example. 5M IN A 10.0.0.251
+4000.example. 5M IN A 10.0.0.252
+4000.example. 5M IN A 10.0.0.253
+4000.example. 5M IN A 10.0.0.254
+4000.example. 5M IN A 10.0.0.255
+4000.example. 5M IN A 10.0.1.0
+4000.example. 5M IN A 10.0.1.1
+4000.example. 5M IN A 10.0.1.2
+4000.example. 5M IN A 10.0.1.3
+4000.example. 5M IN A 10.0.1.4
+4000.example. 5M IN A 10.0.1.5
+4000.example. 5M IN A 10.0.1.6
+4000.example. 5M IN A 10.0.1.7
+4000.example. 5M IN A 10.0.1.8
+4000.example. 5M IN A 10.0.1.9
+4000.example. 5M IN A 10.0.1.10
+4000.example. 5M IN A 10.0.1.11
+4000.example. 5M IN A 10.0.1.12
+4000.example. 5M IN A 10.0.1.13
+4000.example. 5M IN A 10.0.1.14
+4000.example. 5M IN A 10.0.1.15
+4000.example. 5M IN A 10.0.1.16
+4000.example. 5M IN A 10.0.1.17
+4000.example. 5M IN A 10.0.1.18
+4000.example. 5M IN A 10.0.1.19
+4000.example. 5M IN A 10.0.1.20
+4000.example. 5M IN A 10.0.1.21
+4000.example. 5M IN A 10.0.1.22
+4000.example. 5M IN A 10.0.1.23
+4000.example. 5M IN A 10.0.1.24
+4000.example. 5M IN A 10.0.1.25
+4000.example. 5M IN A 10.0.1.26
+4000.example. 5M IN A 10.0.1.27
+4000.example. 5M IN A 10.0.1.28
+4000.example. 5M IN A 10.0.1.29
+4000.example. 5M IN A 10.0.1.30
+4000.example. 5M IN A 10.0.1.31
+4000.example. 5M IN A 10.0.1.32
+4000.example. 5M IN A 10.0.1.33
+4000.example. 5M IN A 10.0.1.34
+4000.example. 5M IN A 10.0.1.35
+4000.example. 5M IN A 10.0.1.36
+4000.example. 5M IN A 10.0.1.37
+4000.example. 5M IN A 10.0.1.38
+4000.example. 5M IN A 10.0.1.39
+4000.example. 5M IN A 10.0.1.40
+4000.example. 5M IN A 10.0.1.41
+4000.example. 5M IN A 10.0.1.42
+4000.example. 5M IN A 10.0.1.43
+4000.example. 5M IN A 10.0.1.44
+4000.example. 5M IN A 10.0.1.45
+4000.example. 5M IN A 10.0.1.46
+4000.example. 5M IN A 10.0.1.47
+4000.example. 5M IN A 10.0.1.48
+4000.example. 5M IN A 10.0.1.49
+4000.example. 5M IN A 10.0.1.50
+4000.example. 5M IN A 10.0.1.51
+4000.example. 5M IN A 10.0.1.52
+4000.example. 5M IN A 10.0.1.53
+4000.example. 5M IN A 10.0.1.54
+4000.example. 5M IN A 10.0.1.55
+4000.example. 5M IN A 10.0.1.56
+4000.example. 5M IN A 10.0.1.57
+4000.example. 5M IN A 10.0.1.58
+4000.example. 5M IN A 10.0.1.59
+4000.example. 5M IN A 10.0.1.60
+4000.example. 5M IN A 10.0.1.61
+4000.example. 5M IN A 10.0.1.62
+4000.example. 5M IN A 10.0.1.63
+4000.example. 5M IN A 10.0.1.64
+4000.example. 5M IN A 10.0.1.65
+4000.example. 5M IN A 10.0.1.66
+4000.example. 5M IN A 10.0.1.67
+4000.example. 5M IN A 10.0.1.68
+4000.example. 5M IN A 10.0.1.69
+4000.example. 5M IN A 10.0.1.70
+4000.example. 5M IN A 10.0.1.71
+4000.example. 5M IN A 10.0.1.72
+4000.example. 5M IN A 10.0.1.73
+4000.example. 5M IN A 10.0.1.74
+4000.example. 5M IN A 10.0.1.75
+4000.example. 5M IN A 10.0.1.76
+4000.example. 5M IN A 10.0.1.77
+4000.example. 5M IN A 10.0.1.78
+4000.example. 5M IN A 10.0.1.79
+4000.example. 5M IN A 10.0.1.80
+4000.example. 5M IN A 10.0.1.81
+4000.example. 5M IN A 10.0.1.82
+4000.example. 5M IN A 10.0.1.83
+4000.example. 5M IN A 10.0.1.84
+4000.example. 5M IN A 10.0.1.85
+4000.example. 5M IN A 10.0.1.86
+4000.example. 5M IN A 10.0.1.87
+4000.example. 5M IN A 10.0.1.88
+4000.example. 5M IN A 10.0.1.89
+4000.example. 5M IN A 10.0.1.90
+4000.example. 5M IN A 10.0.1.91
+4000.example. 5M IN A 10.0.1.92
+4000.example. 5M IN A 10.0.1.93
+4000.example. 5M IN A 10.0.1.94
+4000.example. 5M IN A 10.0.1.95
+4000.example. 5M IN A 10.0.1.96
+4000.example. 5M IN A 10.0.1.97
+4000.example. 5M IN A 10.0.1.98
+4000.example. 5M IN A 10.0.1.99
+4000.example. 5M IN A 10.0.1.100
+4000.example. 5M IN A 10.0.1.101
+4000.example. 5M IN A 10.0.1.102
+4000.example. 5M IN A 10.0.1.103
+4000.example. 5M IN A 10.0.1.104
+4000.example. 5M IN A 10.0.1.105
+4000.example. 5M IN A 10.0.1.106
+4000.example. 5M IN A 10.0.1.107
+4000.example. 5M IN A 10.0.1.108
+4000.example. 5M IN A 10.0.1.109
+4000.example. 5M IN A 10.0.1.110
+4000.example. 5M IN A 10.0.1.111
+4000.example. 5M IN A 10.0.1.112
+4000.example. 5M IN A 10.0.1.113
+4000.example. 5M IN A 10.0.1.114
+4000.example. 5M IN A 10.0.1.115
+4000.example. 5M IN A 10.0.1.116
+4000.example. 5M IN A 10.0.1.117
+4000.example. 5M IN A 10.0.1.118
+4000.example. 5M IN A 10.0.1.119
+4000.example. 5M IN A 10.0.1.120
+4000.example. 5M IN A 10.0.1.121
+4000.example. 5M IN A 10.0.1.122
+4000.example. 5M IN A 10.0.1.123
+4000.example. 5M IN A 10.0.1.124
+4000.example. 5M IN A 10.0.1.125
+4000.example. 5M IN A 10.0.1.126
+4000.example. 5M IN A 10.0.1.127
+4000.example. 5M IN A 10.0.1.128
+4000.example. 5M IN A 10.0.1.129
+4000.example. 5M IN A 10.0.1.130
+4000.example. 5M IN A 10.0.1.131
+4000.example. 5M IN A 10.0.1.132
+4000.example. 5M IN A 10.0.1.133
+4000.example. 5M IN A 10.0.1.134
+4000.example. 5M IN A 10.0.1.135
+4000.example. 5M IN A 10.0.1.136
+4000.example. 5M IN A 10.0.1.137
+4000.example. 5M IN A 10.0.1.138
+4000.example. 5M IN A 10.0.1.139
+4000.example. 5M IN A 10.0.1.140
+4000.example. 5M IN A 10.0.1.141
+4000.example. 5M IN A 10.0.1.142
+4000.example. 5M IN A 10.0.1.143
+4000.example. 5M IN A 10.0.1.144
+4000.example. 5M IN A 10.0.1.145
+4000.example. 5M IN A 10.0.1.146
+4000.example. 5M IN A 10.0.1.147
+4000.example. 5M IN A 10.0.1.148
+4000.example. 5M IN A 10.0.1.149
+4000.example. 5M IN A 10.0.1.150
+4000.example. 5M IN A 10.0.1.151
+4000.example. 5M IN A 10.0.1.152
+4000.example. 5M IN A 10.0.1.153
+4000.example. 5M IN A 10.0.1.154
+4000.example. 5M IN A 10.0.1.155
+4000.example. 5M IN A 10.0.1.156
+4000.example. 5M IN A 10.0.1.157
+4000.example. 5M IN A 10.0.1.158
+4000.example. 5M IN A 10.0.1.159
+4000.example. 5M IN A 10.0.1.160
+4000.example. 5M IN A 10.0.1.161
+4000.example. 5M IN A 10.0.1.162
+4000.example. 5M IN A 10.0.1.163
+4000.example. 5M IN A 10.0.1.164
+4000.example. 5M IN A 10.0.1.165
+4000.example. 5M IN A 10.0.1.166
+4000.example. 5M IN A 10.0.1.167
+4000.example. 5M IN A 10.0.1.168
+4000.example. 5M IN A 10.0.1.169
+4000.example. 5M IN A 10.0.1.170
+4000.example. 5M IN A 10.0.1.171
+4000.example. 5M IN A 10.0.1.172
+4000.example. 5M IN A 10.0.1.173
+4000.example. 5M IN A 10.0.1.174
+4000.example. 5M IN A 10.0.1.175
+4000.example. 5M IN A 10.0.1.176
+4000.example. 5M IN A 10.0.1.177
+4000.example. 5M IN A 10.0.1.178
+4000.example. 5M IN A 10.0.1.179
+4000.example. 5M IN A 10.0.1.180
+4000.example. 5M IN A 10.0.1.181
+4000.example. 5M IN A 10.0.1.182
+4000.example. 5M IN A 10.0.1.183
+4000.example. 5M IN A 10.0.1.184
+4000.example. 5M IN A 10.0.1.185
+4000.example. 5M IN A 10.0.1.186
+4000.example. 5M IN A 10.0.1.187
+4000.example. 5M IN A 10.0.1.188
+4000.example. 5M IN A 10.0.1.189
+4000.example. 5M IN A 10.0.1.190
+4000.example. 5M IN A 10.0.1.191
+4000.example. 5M IN A 10.0.1.192
+4000.example. 5M IN A 10.0.1.193
+4000.example. 5M IN A 10.0.1.194
+4000.example. 5M IN A 10.0.1.195
+4000.example. 5M IN A 10.0.1.196
+4000.example. 5M IN A 10.0.1.197
+4000.example. 5M IN A 10.0.1.198
+4000.example. 5M IN A 10.0.1.199
+4000.example. 5M IN A 10.0.1.200
+4000.example. 5M IN A 10.0.1.201
+4000.example. 5M IN A 10.0.1.202
+4000.example. 5M IN A 10.0.1.203
+4000.example. 5M IN A 10.0.1.204
+4000.example. 5M IN A 10.0.1.205
+4000.example. 5M IN A 10.0.1.206
+4000.example. 5M IN A 10.0.1.207
+4000.example. 5M IN A 10.0.1.208
+4000.example. 5M IN A 10.0.1.209
+4000.example. 5M IN A 10.0.1.210
+4000.example. 5M IN A 10.0.1.211
+4000.example. 5M IN A 10.0.1.212
+4000.example. 5M IN A 10.0.1.213
+4000.example. 5M IN A 10.0.1.214
+4000.example. 5M IN A 10.0.1.215
+4000.example. 5M IN A 10.0.1.216
+4000.example. 5M IN A 10.0.1.217
+4000.example. 5M IN A 10.0.1.218
+4000.example. 5M IN A 10.0.1.219
+4000.example. 5M IN A 10.0.1.220
+4000.example. 5M IN A 10.0.1.221
+4000.example. 5M IN A 10.0.1.222
+4000.example. 5M IN A 10.0.1.223
+4000.example. 5M IN A 10.0.1.224
+4000.example. 5M IN A 10.0.1.225
+4000.example. 5M IN A 10.0.1.226
+4000.example. 5M IN A 10.0.1.227
+4000.example. 5M IN A 10.0.1.228
+4000.example. 5M IN A 10.0.1.229
+4000.example. 5M IN A 10.0.1.230
+4000.example. 5M IN A 10.0.1.231
+4000.example. 5M IN A 10.0.1.232
+4000.example. 5M IN A 10.0.1.233
+4000.example. 5M IN A 10.0.1.234
+4000.example. 5M IN A 10.0.1.235
+4000.example. 5M IN A 10.0.1.236
+4000.example. 5M IN A 10.0.1.237
+4000.example. 5M IN A 10.0.1.238
+4000.example. 5M IN A 10.0.1.239
+4000.example. 5M IN A 10.0.1.240
+4000.example. 5M IN A 10.0.1.241
+4000.example. 5M IN A 10.0.1.242
+4000.example. 5M IN A 10.0.1.243
+4000.example. 5M IN A 10.0.1.244
+4000.example. 5M IN A 10.0.1.245
+4000.example. 5M IN A 10.0.1.246
+4000.example. 5M IN A 10.0.1.247
+4000.example. 5M IN A 10.0.1.248
+4000.example. 5M IN A 10.0.1.249
+4000.example. 5M IN A 10.0.1.250
+4000.example. 5M IN A 10.0.1.251
+4000.example. 5M IN A 10.0.1.252
+4000.example. 5M IN A 10.0.1.253
+4000.example. 5M IN A 10.0.1.254
+4000.example. 5M IN A 10.0.1.255
+4000.example. 5M IN A 10.0.2.0
+4000.example. 5M IN A 10.0.2.1
+4000.example. 5M IN A 10.0.2.2
+4000.example. 5M IN A 10.0.2.3
+4000.example. 5M IN A 10.0.2.4
+4000.example. 5M IN A 10.0.2.5
+4000.example. 5M IN A 10.0.2.6
+4000.example. 5M IN A 10.0.2.7
+4000.example. 5M IN A 10.0.2.8
+4000.example. 5M IN A 10.0.2.9
+4000.example. 5M IN A 10.0.2.10
+4000.example. 5M IN A 10.0.2.11
+4000.example. 5M IN A 10.0.2.12
+4000.example. 5M IN A 10.0.2.13
+4000.example. 5M IN A 10.0.2.14
+4000.example. 5M IN A 10.0.2.15
+4000.example. 5M IN A 10.0.2.16
+4000.example. 5M IN A 10.0.2.17
+4000.example. 5M IN A 10.0.2.18
+4000.example. 5M IN A 10.0.2.19
+4000.example. 5M IN A 10.0.2.20
+4000.example. 5M IN A 10.0.2.21
+4000.example. 5M IN A 10.0.2.22
+4000.example. 5M IN A 10.0.2.23
+4000.example. 5M IN A 10.0.2.24
+4000.example. 5M IN A 10.0.2.25
+4000.example. 5M IN A 10.0.2.26
+4000.example. 5M IN A 10.0.2.27
+4000.example. 5M IN A 10.0.2.28
+4000.example. 5M IN A 10.0.2.29
+4000.example. 5M IN A 10.0.2.30
+4000.example. 5M IN A 10.0.2.31
+4000.example. 5M IN A 10.0.2.32
+4000.example. 5M IN A 10.0.2.33
+4000.example. 5M IN A 10.0.2.34
+4000.example. 5M IN A 10.0.2.35
+4000.example. 5M IN A 10.0.2.36
+4000.example. 5M IN A 10.0.2.37
+4000.example. 5M IN A 10.0.2.38
+4000.example. 5M IN A 10.0.2.39
+4000.example. 5M IN A 10.0.2.40
+4000.example. 5M IN A 10.0.2.41
+4000.example. 5M IN A 10.0.2.42
+4000.example. 5M IN A 10.0.2.43
+4000.example. 5M IN A 10.0.2.44
+4000.example. 5M IN A 10.0.2.45
+4000.example. 5M IN A 10.0.2.46
+4000.example. 5M IN A 10.0.2.47
+4000.example. 5M IN A 10.0.2.48
+4000.example. 5M IN A 10.0.2.49
+4000.example. 5M IN A 10.0.2.50
+4000.example. 5M IN A 10.0.2.51
+4000.example. 5M IN A 10.0.2.52
+4000.example. 5M IN A 10.0.2.53
+4000.example. 5M IN A 10.0.2.54
+4000.example. 5M IN A 10.0.2.55
+4000.example. 5M IN A 10.0.2.56
+4000.example. 5M IN A 10.0.2.57
+4000.example. 5M IN A 10.0.2.58
+4000.example. 5M IN A 10.0.2.59
+4000.example. 5M IN A 10.0.2.60
+4000.example. 5M IN A 10.0.2.61
+4000.example. 5M IN A 10.0.2.62
+4000.example. 5M IN A 10.0.2.63
+4000.example. 5M IN A 10.0.2.64
+4000.example. 5M IN A 10.0.2.65
+4000.example. 5M IN A 10.0.2.66
+4000.example. 5M IN A 10.0.2.67
+4000.example. 5M IN A 10.0.2.68
+4000.example. 5M IN A 10.0.2.69
+4000.example. 5M IN A 10.0.2.70
+4000.example. 5M IN A 10.0.2.71
+4000.example. 5M IN A 10.0.2.72
+4000.example. 5M IN A 10.0.2.73
+4000.example. 5M IN A 10.0.2.74
+4000.example. 5M IN A 10.0.2.75
+4000.example. 5M IN A 10.0.2.76
+4000.example. 5M IN A 10.0.2.77
+4000.example. 5M IN A 10.0.2.78
+4000.example. 5M IN A 10.0.2.79
+4000.example. 5M IN A 10.0.2.80
+4000.example. 5M IN A 10.0.2.81
+4000.example. 5M IN A 10.0.2.82
+4000.example. 5M IN A 10.0.2.83
+4000.example. 5M IN A 10.0.2.84
+4000.example. 5M IN A 10.0.2.85
+4000.example. 5M IN A 10.0.2.86
+4000.example. 5M IN A 10.0.2.87
+4000.example. 5M IN A 10.0.2.88
+4000.example. 5M IN A 10.0.2.89
+4000.example. 5M IN A 10.0.2.90
+4000.example. 5M IN A 10.0.2.91
+4000.example. 5M IN A 10.0.2.92
+4000.example. 5M IN A 10.0.2.93
+4000.example. 5M IN A 10.0.2.94
+4000.example. 5M IN A 10.0.2.95
+4000.example. 5M IN A 10.0.2.96
+4000.example. 5M IN A 10.0.2.97
+4000.example. 5M IN A 10.0.2.98
+4000.example. 5M IN A 10.0.2.99
+4000.example. 5M IN A 10.0.2.100
+4000.example. 5M IN A 10.0.2.101
+4000.example. 5M IN A 10.0.2.102
+4000.example. 5M IN A 10.0.2.103
+4000.example. 5M IN A 10.0.2.104
+4000.example. 5M IN A 10.0.2.105
+4000.example. 5M IN A 10.0.2.106
+4000.example. 5M IN A 10.0.2.107
+4000.example. 5M IN A 10.0.2.108
+4000.example. 5M IN A 10.0.2.109
+4000.example. 5M IN A 10.0.2.110
+4000.example. 5M IN A 10.0.2.111
+4000.example. 5M IN A 10.0.2.112
+4000.example. 5M IN A 10.0.2.113
+4000.example. 5M IN A 10.0.2.114
+4000.example. 5M IN A 10.0.2.115
+4000.example. 5M IN A 10.0.2.116
+4000.example. 5M IN A 10.0.2.117
+4000.example. 5M IN A 10.0.2.118
+4000.example. 5M IN A 10.0.2.119
+4000.example. 5M IN A 10.0.2.120
+4000.example. 5M IN A 10.0.2.121
+4000.example. 5M IN A 10.0.2.122
+4000.example. 5M IN A 10.0.2.123
+4000.example. 5M IN A 10.0.2.124
+4000.example. 5M IN A 10.0.2.125
+4000.example. 5M IN A 10.0.2.126
+4000.example. 5M IN A 10.0.2.127
+4000.example. 5M IN A 10.0.2.128
+4000.example. 5M IN A 10.0.2.129
+4000.example. 5M IN A 10.0.2.130
+4000.example. 5M IN A 10.0.2.131
+4000.example. 5M IN A 10.0.2.132
+4000.example. 5M IN A 10.0.2.133
+4000.example. 5M IN A 10.0.2.134
+4000.example. 5M IN A 10.0.2.135
+4000.example. 5M IN A 10.0.2.136
+4000.example. 5M IN A 10.0.2.137
+4000.example. 5M IN A 10.0.2.138
+4000.example. 5M IN A 10.0.2.139
+4000.example. 5M IN A 10.0.2.140
+4000.example. 5M IN A 10.0.2.141
+4000.example. 5M IN A 10.0.2.142
+4000.example. 5M IN A 10.0.2.143
+4000.example. 5M IN A 10.0.2.144
+4000.example. 5M IN A 10.0.2.145
+4000.example. 5M IN A 10.0.2.146
+4000.example. 5M IN A 10.0.2.147
+4000.example. 5M IN A 10.0.2.148
+4000.example. 5M IN A 10.0.2.149
+4000.example. 5M IN A 10.0.2.150
+4000.example. 5M IN A 10.0.2.151
+4000.example. 5M IN A 10.0.2.152
+4000.example. 5M IN A 10.0.2.153
+4000.example. 5M IN A 10.0.2.154
+4000.example. 5M IN A 10.0.2.155
+4000.example. 5M IN A 10.0.2.156
+4000.example. 5M IN A 10.0.2.157
+4000.example. 5M IN A 10.0.2.158
+4000.example. 5M IN A 10.0.2.159
+4000.example. 5M IN A 10.0.2.160
+4000.example. 5M IN A 10.0.2.161
+4000.example. 5M IN A 10.0.2.162
+4000.example. 5M IN A 10.0.2.163
+4000.example. 5M IN A 10.0.2.164
+4000.example. 5M IN A 10.0.2.165
+4000.example. 5M IN A 10.0.2.166
+4000.example. 5M IN A 10.0.2.167
+4000.example. 5M IN A 10.0.2.168
+4000.example. 5M IN A 10.0.2.169
+4000.example. 5M IN A 10.0.2.170
+4000.example. 5M IN A 10.0.2.171
+4000.example. 5M IN A 10.0.2.172
+4000.example. 5M IN A 10.0.2.173
+4000.example. 5M IN A 10.0.2.174
+4000.example. 5M IN A 10.0.2.175
+4000.example. 5M IN A 10.0.2.176
+4000.example. 5M IN A 10.0.2.177
+4000.example. 5M IN A 10.0.2.178
+4000.example. 5M IN A 10.0.2.179
+4000.example. 5M IN A 10.0.2.180
+4000.example. 5M IN A 10.0.2.181
+4000.example. 5M IN A 10.0.2.182
+4000.example. 5M IN A 10.0.2.183
+4000.example. 5M IN A 10.0.2.184
+4000.example. 5M IN A 10.0.2.185
+4000.example. 5M IN A 10.0.2.186
+4000.example. 5M IN A 10.0.2.187
+4000.example. 5M IN A 10.0.2.188
+4000.example. 5M IN A 10.0.2.189
+4000.example. 5M IN A 10.0.2.190
+4000.example. 5M IN A 10.0.2.191
+4000.example. 5M IN A 10.0.2.192
+4000.example. 5M IN A 10.0.2.193
+4000.example. 5M IN A 10.0.2.194
+4000.example. 5M IN A 10.0.2.195
+4000.example. 5M IN A 10.0.2.196
+4000.example. 5M IN A 10.0.2.197
+4000.example. 5M IN A 10.0.2.198
+4000.example. 5M IN A 10.0.2.199
+4000.example. 5M IN A 10.0.2.200
+4000.example. 5M IN A 10.0.2.201
+4000.example. 5M IN A 10.0.2.202
+4000.example. 5M IN A 10.0.2.203
+4000.example. 5M IN A 10.0.2.204
+4000.example. 5M IN A 10.0.2.205
+4000.example. 5M IN A 10.0.2.206
+4000.example. 5M IN A 10.0.2.207
+4000.example. 5M IN A 10.0.2.208
+4000.example. 5M IN A 10.0.2.209
+4000.example. 5M IN A 10.0.2.210
+4000.example. 5M IN A 10.0.2.211
+4000.example. 5M IN A 10.0.2.212
+4000.example. 5M IN A 10.0.2.213
+4000.example. 5M IN A 10.0.2.214
+4000.example. 5M IN A 10.0.2.215
+4000.example. 5M IN A 10.0.2.216
+4000.example. 5M IN A 10.0.2.217
+4000.example. 5M IN A 10.0.2.218
+4000.example. 5M IN A 10.0.2.219
+4000.example. 5M IN A 10.0.2.220
+4000.example. 5M IN A 10.0.2.221
+4000.example. 5M IN A 10.0.2.222
+4000.example. 5M IN A 10.0.2.223
+4000.example. 5M IN A 10.0.2.224
+4000.example. 5M IN A 10.0.2.225
+4000.example. 5M IN A 10.0.2.226
+4000.example. 5M IN A 10.0.2.227
+4000.example. 5M IN A 10.0.2.228
+4000.example. 5M IN A 10.0.2.229
+4000.example. 5M IN A 10.0.2.230
+4000.example. 5M IN A 10.0.2.231
+4000.example. 5M IN A 10.0.2.232
+4000.example. 5M IN A 10.0.2.233
+4000.example. 5M IN A 10.0.2.234
+4000.example. 5M IN A 10.0.2.235
+4000.example. 5M IN A 10.0.2.236
+4000.example. 5M IN A 10.0.2.237
+4000.example. 5M IN A 10.0.2.238
+4000.example. 5M IN A 10.0.2.239
+4000.example. 5M IN A 10.0.2.240
+4000.example. 5M IN A 10.0.2.241
+4000.example. 5M IN A 10.0.2.242
+4000.example. 5M IN A 10.0.2.243
+4000.example. 5M IN A 10.0.2.244
+4000.example. 5M IN A 10.0.2.245
+4000.example. 5M IN A 10.0.2.246
+4000.example. 5M IN A 10.0.2.247
+4000.example. 5M IN A 10.0.2.248
+4000.example. 5M IN A 10.0.2.249
+4000.example. 5M IN A 10.0.2.250
+4000.example. 5M IN A 10.0.2.251
+4000.example. 5M IN A 10.0.2.252
+4000.example. 5M IN A 10.0.2.253
+4000.example. 5M IN A 10.0.2.254
+4000.example. 5M IN A 10.0.2.255
+4000.example. 5M IN A 10.0.3.0
+4000.example. 5M IN A 10.0.3.1
+4000.example. 5M IN A 10.0.3.2
+4000.example. 5M IN A 10.0.3.3
+4000.example. 5M IN A 10.0.3.4
+4000.example. 5M IN A 10.0.3.5
+4000.example. 5M IN A 10.0.3.6
+4000.example. 5M IN A 10.0.3.7
+4000.example. 5M IN A 10.0.3.8
+4000.example. 5M IN A 10.0.3.9
+4000.example. 5M IN A 10.0.3.10
+4000.example. 5M IN A 10.0.3.11
+4000.example. 5M IN A 10.0.3.12
+4000.example. 5M IN A 10.0.3.13
+4000.example. 5M IN A 10.0.3.14
+4000.example. 5M IN A 10.0.3.15
+4000.example. 5M IN A 10.0.3.16
+4000.example. 5M IN A 10.0.3.17
+4000.example. 5M IN A 10.0.3.18
+4000.example. 5M IN A 10.0.3.19
+4000.example. 5M IN A 10.0.3.20
+4000.example. 5M IN A 10.0.3.21
+4000.example. 5M IN A 10.0.3.22
+4000.example. 5M IN A 10.0.3.23
+4000.example. 5M IN A 10.0.3.24
+4000.example. 5M IN A 10.0.3.25
+4000.example. 5M IN A 10.0.3.26
+4000.example. 5M IN A 10.0.3.27
+4000.example. 5M IN A 10.0.3.28
+4000.example. 5M IN A 10.0.3.29
+4000.example. 5M IN A 10.0.3.30
+4000.example. 5M IN A 10.0.3.31
+4000.example. 5M IN A 10.0.3.32
+4000.example. 5M IN A 10.0.3.33
+4000.example. 5M IN A 10.0.3.34
+4000.example. 5M IN A 10.0.3.35
+4000.example. 5M IN A 10.0.3.36
+4000.example. 5M IN A 10.0.3.37
+4000.example. 5M IN A 10.0.3.38
+4000.example. 5M IN A 10.0.3.39
+4000.example. 5M IN A 10.0.3.40
+4000.example. 5M IN A 10.0.3.41
+4000.example. 5M IN A 10.0.3.42
+4000.example. 5M IN A 10.0.3.43
+4000.example. 5M IN A 10.0.3.44
+4000.example. 5M IN A 10.0.3.45
+4000.example. 5M IN A 10.0.3.46
+4000.example. 5M IN A 10.0.3.47
+4000.example. 5M IN A 10.0.3.48
+4000.example. 5M IN A 10.0.3.49
+4000.example. 5M IN A 10.0.3.50
+4000.example. 5M IN A 10.0.3.51
+4000.example. 5M IN A 10.0.3.52
+4000.example. 5M IN A 10.0.3.53
+4000.example. 5M IN A 10.0.3.54
+4000.example. 5M IN A 10.0.3.55
+4000.example. 5M IN A 10.0.3.56
+4000.example. 5M IN A 10.0.3.57
+4000.example. 5M IN A 10.0.3.58
+4000.example. 5M IN A 10.0.3.59
+4000.example. 5M IN A 10.0.3.60
+4000.example. 5M IN A 10.0.3.61
+4000.example. 5M IN A 10.0.3.62
+4000.example. 5M IN A 10.0.3.63
+4000.example. 5M IN A 10.0.3.64
+4000.example. 5M IN A 10.0.3.65
+4000.example. 5M IN A 10.0.3.66
+4000.example. 5M IN A 10.0.3.67
+4000.example. 5M IN A 10.0.3.68
+4000.example. 5M IN A 10.0.3.69
+4000.example. 5M IN A 10.0.3.70
+4000.example. 5M IN A 10.0.3.71
+4000.example. 5M IN A 10.0.3.72
+4000.example. 5M IN A 10.0.3.73
+4000.example. 5M IN A 10.0.3.74
+4000.example. 5M IN A 10.0.3.75
+4000.example. 5M IN A 10.0.3.76
+4000.example. 5M IN A 10.0.3.77
+4000.example. 5M IN A 10.0.3.78
+4000.example. 5M IN A 10.0.3.79
+4000.example. 5M IN A 10.0.3.80
+4000.example. 5M IN A 10.0.3.81
+4000.example. 5M IN A 10.0.3.82
+4000.example. 5M IN A 10.0.3.83
+4000.example. 5M IN A 10.0.3.84
+4000.example. 5M IN A 10.0.3.85
+4000.example. 5M IN A 10.0.3.86
+4000.example. 5M IN A 10.0.3.87
+4000.example. 5M IN A 10.0.3.88
+4000.example. 5M IN A 10.0.3.89
+4000.example. 5M IN A 10.0.3.90
+4000.example. 5M IN A 10.0.3.91
+4000.example. 5M IN A 10.0.3.92
+4000.example. 5M IN A 10.0.3.93
+4000.example. 5M IN A 10.0.3.94
+4000.example. 5M IN A 10.0.3.95
+4000.example. 5M IN A 10.0.3.96
+4000.example. 5M IN A 10.0.3.97
+4000.example. 5M IN A 10.0.3.98
+4000.example. 5M IN A 10.0.3.99
+4000.example. 5M IN A 10.0.3.100
+4000.example. 5M IN A 10.0.3.101
+4000.example. 5M IN A 10.0.3.102
+4000.example. 5M IN A 10.0.3.103
+4000.example. 5M IN A 10.0.3.104
+4000.example. 5M IN A 10.0.3.105
+4000.example. 5M IN A 10.0.3.106
+4000.example. 5M IN A 10.0.3.107
+4000.example. 5M IN A 10.0.3.108
+4000.example. 5M IN A 10.0.3.109
+4000.example. 5M IN A 10.0.3.110
+4000.example. 5M IN A 10.0.3.111
+4000.example. 5M IN A 10.0.3.112
+4000.example. 5M IN A 10.0.3.113
+4000.example. 5M IN A 10.0.3.114
+4000.example. 5M IN A 10.0.3.115
+4000.example. 5M IN A 10.0.3.116
+4000.example. 5M IN A 10.0.3.117
+4000.example. 5M IN A 10.0.3.118
+4000.example. 5M IN A 10.0.3.119
+4000.example. 5M IN A 10.0.3.120
+4000.example. 5M IN A 10.0.3.121
+4000.example. 5M IN A 10.0.3.122
+4000.example. 5M IN A 10.0.3.123
+4000.example. 5M IN A 10.0.3.124
+4000.example. 5M IN A 10.0.3.125
+4000.example. 5M IN A 10.0.3.126
+4000.example. 5M IN A 10.0.3.127
+4000.example. 5M IN A 10.0.3.128
+4000.example. 5M IN A 10.0.3.129
+4000.example. 5M IN A 10.0.3.130
+4000.example. 5M IN A 10.0.3.131
+4000.example. 5M IN A 10.0.3.132
+4000.example. 5M IN A 10.0.3.133
+4000.example. 5M IN A 10.0.3.134
+4000.example. 5M IN A 10.0.3.135
+4000.example. 5M IN A 10.0.3.136
+4000.example. 5M IN A 10.0.3.137
+4000.example. 5M IN A 10.0.3.138
+4000.example. 5M IN A 10.0.3.139
+4000.example. 5M IN A 10.0.3.140
+4000.example. 5M IN A 10.0.3.141
+4000.example. 5M IN A 10.0.3.142
+4000.example. 5M IN A 10.0.3.143
+4000.example. 5M IN A 10.0.3.144
+4000.example. 5M IN A 10.0.3.145
+4000.example. 5M IN A 10.0.3.146
+4000.example. 5M IN A 10.0.3.147
+4000.example. 5M IN A 10.0.3.148
+4000.example. 5M IN A 10.0.3.149
+4000.example. 5M IN A 10.0.3.150
+4000.example. 5M IN A 10.0.3.151
+4000.example. 5M IN A 10.0.3.152
+4000.example. 5M IN A 10.0.3.153
+4000.example. 5M IN A 10.0.3.154
+4000.example. 5M IN A 10.0.3.155
+4000.example. 5M IN A 10.0.3.156
+4000.example. 5M IN A 10.0.3.157
+4000.example. 5M IN A 10.0.3.158
+4000.example. 5M IN A 10.0.3.159
+4000.example. 5M IN A 10.0.3.160
+4000.example. 5M IN A 10.0.3.161
+4000.example. 5M IN A 10.0.3.162
+4000.example. 5M IN A 10.0.3.163
+4000.example. 5M IN A 10.0.3.164
+4000.example. 5M IN A 10.0.3.165
+4000.example. 5M IN A 10.0.3.166
+4000.example. 5M IN A 10.0.3.167
+4000.example. 5M IN A 10.0.3.168
+4000.example. 5M IN A 10.0.3.169
+4000.example. 5M IN A 10.0.3.170
+4000.example. 5M IN A 10.0.3.171
+4000.example. 5M IN A 10.0.3.172
+4000.example. 5M IN A 10.0.3.173
+4000.example. 5M IN A 10.0.3.174
+4000.example. 5M IN A 10.0.3.175
+4000.example. 5M IN A 10.0.3.176
+4000.example. 5M IN A 10.0.3.177
+4000.example. 5M IN A 10.0.3.178
+4000.example. 5M IN A 10.0.3.179
+4000.example. 5M IN A 10.0.3.180
+4000.example. 5M IN A 10.0.3.181
+4000.example. 5M IN A 10.0.3.182
+4000.example. 5M IN A 10.0.3.183
+4000.example. 5M IN A 10.0.3.184
+4000.example. 5M IN A 10.0.3.185
+4000.example. 5M IN A 10.0.3.186
+4000.example. 5M IN A 10.0.3.187
+4000.example. 5M IN A 10.0.3.188
+4000.example. 5M IN A 10.0.3.189
+4000.example. 5M IN A 10.0.3.190
+4000.example. 5M IN A 10.0.3.191
+4000.example. 5M IN A 10.0.3.192
+4000.example. 5M IN A 10.0.3.193
+4000.example. 5M IN A 10.0.3.194
+4000.example. 5M IN A 10.0.3.195
+4000.example. 5M IN A 10.0.3.196
+4000.example. 5M IN A 10.0.3.197
+4000.example. 5M IN A 10.0.3.198
+4000.example. 5M IN A 10.0.3.199
+4000.example. 5M IN A 10.0.3.200
+4000.example. 5M IN A 10.0.3.201
+4000.example. 5M IN A 10.0.3.202
+4000.example. 5M IN A 10.0.3.203
+4000.example. 5M IN A 10.0.3.204
+4000.example. 5M IN A 10.0.3.205
+4000.example. 5M IN A 10.0.3.206
+4000.example. 5M IN A 10.0.3.207
+4000.example. 5M IN A 10.0.3.208
+4000.example. 5M IN A 10.0.3.209
+4000.example. 5M IN A 10.0.3.210
+4000.example. 5M IN A 10.0.3.211
+4000.example. 5M IN A 10.0.3.212
+4000.example. 5M IN A 10.0.3.213
+4000.example. 5M IN A 10.0.3.214
+4000.example. 5M IN A 10.0.3.215
+4000.example. 5M IN A 10.0.3.216
+4000.example. 5M IN A 10.0.3.217
+4000.example. 5M IN A 10.0.3.218
+4000.example. 5M IN A 10.0.3.219
+4000.example. 5M IN A 10.0.3.220
+4000.example. 5M IN A 10.0.3.221
+4000.example. 5M IN A 10.0.3.222
+4000.example. 5M IN A 10.0.3.223
+4000.example. 5M IN A 10.0.3.224
+4000.example. 5M IN A 10.0.3.225
+4000.example. 5M IN A 10.0.3.226
+4000.example. 5M IN A 10.0.3.227
+4000.example. 5M IN A 10.0.3.228
+4000.example. 5M IN A 10.0.3.229
+4000.example. 5M IN A 10.0.3.230
+4000.example. 5M IN A 10.0.3.231
+4000.example. 5M IN A 10.0.3.232
+4000.example. 5M IN A 10.0.3.233
+4000.example. 5M IN A 10.0.3.234
+4000.example. 5M IN A 10.0.3.235
+4000.example. 5M IN A 10.0.3.236
+4000.example. 5M IN A 10.0.3.237
+4000.example. 5M IN A 10.0.3.238
+4000.example. 5M IN A 10.0.3.239
+4000.example. 5M IN A 10.0.3.240
+4000.example. 5M IN A 10.0.3.241
+4000.example. 5M IN A 10.0.3.242
+4000.example. 5M IN A 10.0.3.243
+4000.example. 5M IN A 10.0.3.244
+4000.example. 5M IN A 10.0.3.245
+4000.example. 5M IN A 10.0.3.246
+4000.example. 5M IN A 10.0.3.247
+4000.example. 5M IN A 10.0.3.248
+4000.example. 5M IN A 10.0.3.249
+4000.example. 5M IN A 10.0.3.250
+4000.example. 5M IN A 10.0.3.251
+4000.example. 5M IN A 10.0.3.252
+4000.example. 5M IN A 10.0.3.253
+4000.example. 5M IN A 10.0.3.254
+4000.example. 5M IN A 10.0.3.255
+4000.example. 5M IN A 10.0.4.0
+4000.example. 5M IN A 10.0.4.1
+4000.example. 5M IN A 10.0.4.2
+4000.example. 5M IN A 10.0.4.3
+4000.example. 5M IN A 10.0.4.4
+4000.example. 5M IN A 10.0.4.5
+4000.example. 5M IN A 10.0.4.6
+4000.example. 5M IN A 10.0.4.7
+4000.example. 5M IN A 10.0.4.8
+4000.example. 5M IN A 10.0.4.9
+4000.example. 5M IN A 10.0.4.10
+4000.example. 5M IN A 10.0.4.11
+4000.example. 5M IN A 10.0.4.12
+4000.example. 5M IN A 10.0.4.13
+4000.example. 5M IN A 10.0.4.14
+4000.example. 5M IN A 10.0.4.15
+4000.example. 5M IN A 10.0.4.16
+4000.example. 5M IN A 10.0.4.17
+4000.example. 5M IN A 10.0.4.18
+4000.example. 5M IN A 10.0.4.19
+4000.example. 5M IN A 10.0.4.20
+4000.example. 5M IN A 10.0.4.21
+4000.example. 5M IN A 10.0.4.22
+4000.example. 5M IN A 10.0.4.23
+4000.example. 5M IN A 10.0.4.24
+4000.example. 5M IN A 10.0.4.25
+4000.example. 5M IN A 10.0.4.26
+4000.example. 5M IN A 10.0.4.27
+4000.example. 5M IN A 10.0.4.28
+4000.example. 5M IN A 10.0.4.29
+4000.example. 5M IN A 10.0.4.30
+4000.example. 5M IN A 10.0.4.31
+4000.example. 5M IN A 10.0.4.32
+4000.example. 5M IN A 10.0.4.33
+4000.example. 5M IN A 10.0.4.34
+4000.example. 5M IN A 10.0.4.35
+4000.example. 5M IN A 10.0.4.36
+4000.example. 5M IN A 10.0.4.37
+4000.example. 5M IN A 10.0.4.38
+4000.example. 5M IN A 10.0.4.39
+4000.example. 5M IN A 10.0.4.40
+4000.example. 5M IN A 10.0.4.41
+4000.example. 5M IN A 10.0.4.42
+4000.example. 5M IN A 10.0.4.43
+4000.example. 5M IN A 10.0.4.44
+4000.example. 5M IN A 10.0.4.45
+4000.example. 5M IN A 10.0.4.46
+4000.example. 5M IN A 10.0.4.47
+4000.example. 5M IN A 10.0.4.48
+4000.example. 5M IN A 10.0.4.49
+4000.example. 5M IN A 10.0.4.50
+4000.example. 5M IN A 10.0.4.51
+4000.example. 5M IN A 10.0.4.52
+4000.example. 5M IN A 10.0.4.53
+4000.example. 5M IN A 10.0.4.54
+4000.example. 5M IN A 10.0.4.55
+4000.example. 5M IN A 10.0.4.56
+4000.example. 5M IN A 10.0.4.57
+4000.example. 5M IN A 10.0.4.58
+4000.example. 5M IN A 10.0.4.59
+4000.example. 5M IN A 10.0.4.60
+4000.example. 5M IN A 10.0.4.61
+4000.example. 5M IN A 10.0.4.62
+4000.example. 5M IN A 10.0.4.63
+4000.example. 5M IN A 10.0.4.64
+4000.example. 5M IN A 10.0.4.65
+4000.example. 5M IN A 10.0.4.66
+4000.example. 5M IN A 10.0.4.67
+4000.example. 5M IN A 10.0.4.68
+4000.example. 5M IN A 10.0.4.69
+4000.example. 5M IN A 10.0.4.70
+4000.example. 5M IN A 10.0.4.71
+4000.example. 5M IN A 10.0.4.72
+4000.example. 5M IN A 10.0.4.73
+4000.example. 5M IN A 10.0.4.74
+4000.example. 5M IN A 10.0.4.75
+4000.example. 5M IN A 10.0.4.76
+4000.example. 5M IN A 10.0.4.77
+4000.example. 5M IN A 10.0.4.78
+4000.example. 5M IN A 10.0.4.79
+4000.example. 5M IN A 10.0.4.80
+4000.example. 5M IN A 10.0.4.81
+4000.example. 5M IN A 10.0.4.82
+4000.example. 5M IN A 10.0.4.83
+4000.example. 5M IN A 10.0.4.84
+4000.example. 5M IN A 10.0.4.85
+4000.example. 5M IN A 10.0.4.86
+4000.example. 5M IN A 10.0.4.87
+4000.example. 5M IN A 10.0.4.88
+4000.example. 5M IN A 10.0.4.89
+4000.example. 5M IN A 10.0.4.90
+4000.example. 5M IN A 10.0.4.91
+4000.example. 5M IN A 10.0.4.92
+4000.example. 5M IN A 10.0.4.93
+4000.example. 5M IN A 10.0.4.94
+4000.example. 5M IN A 10.0.4.95
+4000.example. 5M IN A 10.0.4.96
+4000.example. 5M IN A 10.0.4.97
+4000.example. 5M IN A 10.0.4.98
+4000.example. 5M IN A 10.0.4.99
+4000.example. 5M IN A 10.0.4.100
+4000.example. 5M IN A 10.0.4.101
+4000.example. 5M IN A 10.0.4.102
+4000.example. 5M IN A 10.0.4.103
+4000.example. 5M IN A 10.0.4.104
+4000.example. 5M IN A 10.0.4.105
+4000.example. 5M IN A 10.0.4.106
+4000.example. 5M IN A 10.0.4.107
+4000.example. 5M IN A 10.0.4.108
+4000.example. 5M IN A 10.0.4.109
+4000.example. 5M IN A 10.0.4.110
+4000.example. 5M IN A 10.0.4.111
+4000.example. 5M IN A 10.0.4.112
+4000.example. 5M IN A 10.0.4.113
+4000.example. 5M IN A 10.0.4.114
+4000.example. 5M IN A 10.0.4.115
+4000.example. 5M IN A 10.0.4.116
+4000.example. 5M IN A 10.0.4.117
+4000.example. 5M IN A 10.0.4.118
+4000.example. 5M IN A 10.0.4.119
+4000.example. 5M IN A 10.0.4.120
+4000.example. 5M IN A 10.0.4.121
+4000.example. 5M IN A 10.0.4.122
+4000.example. 5M IN A 10.0.4.123
+4000.example. 5M IN A 10.0.4.124
+4000.example. 5M IN A 10.0.4.125
+4000.example. 5M IN A 10.0.4.126
+4000.example. 5M IN A 10.0.4.127
+4000.example. 5M IN A 10.0.4.128
+4000.example. 5M IN A 10.0.4.129
+4000.example. 5M IN A 10.0.4.130
+4000.example. 5M IN A 10.0.4.131
+4000.example. 5M IN A 10.0.4.132
+4000.example. 5M IN A 10.0.4.133
+4000.example. 5M IN A 10.0.4.134
+4000.example. 5M IN A 10.0.4.135
+4000.example. 5M IN A 10.0.4.136
+4000.example. 5M IN A 10.0.4.137
+4000.example. 5M IN A 10.0.4.138
+4000.example. 5M IN A 10.0.4.139
+4000.example. 5M IN A 10.0.4.140
+4000.example. 5M IN A 10.0.4.141
+4000.example. 5M IN A 10.0.4.142
+4000.example. 5M IN A 10.0.4.143
+4000.example. 5M IN A 10.0.4.144
+4000.example. 5M IN A 10.0.4.145
+4000.example. 5M IN A 10.0.4.146
+4000.example. 5M IN A 10.0.4.147
+4000.example. 5M IN A 10.0.4.148
+4000.example. 5M IN A 10.0.4.149
+4000.example. 5M IN A 10.0.4.150
+4000.example. 5M IN A 10.0.4.151
+4000.example. 5M IN A 10.0.4.152
+4000.example. 5M IN A 10.0.4.153
+4000.example. 5M IN A 10.0.4.154
+4000.example. 5M IN A 10.0.4.155
+4000.example. 5M IN A 10.0.4.156
+4000.example. 5M IN A 10.0.4.157
+4000.example. 5M IN A 10.0.4.158
+4000.example. 5M IN A 10.0.4.159
+4000.example. 5M IN A 10.0.4.160
+4000.example. 5M IN A 10.0.4.161
+4000.example. 5M IN A 10.0.4.162
+4000.example. 5M IN A 10.0.4.163
+4000.example. 5M IN A 10.0.4.164
+4000.example. 5M IN A 10.0.4.165
+4000.example. 5M IN A 10.0.4.166
+4000.example. 5M IN A 10.0.4.167
+4000.example. 5M IN A 10.0.4.168
+4000.example. 5M IN A 10.0.4.169
+4000.example. 5M IN A 10.0.4.170
+4000.example. 5M IN A 10.0.4.171
+4000.example. 5M IN A 10.0.4.172
+4000.example. 5M IN A 10.0.4.173
+4000.example. 5M IN A 10.0.4.174
+4000.example. 5M IN A 10.0.4.175
+4000.example. 5M IN A 10.0.4.176
+4000.example. 5M IN A 10.0.4.177
+4000.example. 5M IN A 10.0.4.178
+4000.example. 5M IN A 10.0.4.179
+4000.example. 5M IN A 10.0.4.180
+4000.example. 5M IN A 10.0.4.181
+4000.example. 5M IN A 10.0.4.182
+4000.example. 5M IN A 10.0.4.183
+4000.example. 5M IN A 10.0.4.184
+4000.example. 5M IN A 10.0.4.185
+4000.example. 5M IN A 10.0.4.186
+4000.example. 5M IN A 10.0.4.187
+4000.example. 5M IN A 10.0.4.188
+4000.example. 5M IN A 10.0.4.189
+4000.example. 5M IN A 10.0.4.190
+4000.example. 5M IN A 10.0.4.191
+4000.example. 5M IN A 10.0.4.192
+4000.example. 5M IN A 10.0.4.193
+4000.example. 5M IN A 10.0.4.194
+4000.example. 5M IN A 10.0.4.195
+4000.example. 5M IN A 10.0.4.196
+4000.example. 5M IN A 10.0.4.197
+4000.example. 5M IN A 10.0.4.198
+4000.example. 5M IN A 10.0.4.199
+4000.example. 5M IN A 10.0.4.200
+4000.example. 5M IN A 10.0.4.201
+4000.example. 5M IN A 10.0.4.202
+4000.example. 5M IN A 10.0.4.203
+4000.example. 5M IN A 10.0.4.204
+4000.example. 5M IN A 10.0.4.205
+4000.example. 5M IN A 10.0.4.206
+4000.example. 5M IN A 10.0.4.207
+4000.example. 5M IN A 10.0.4.208
+4000.example. 5M IN A 10.0.4.209
+4000.example. 5M IN A 10.0.4.210
+4000.example. 5M IN A 10.0.4.211
+4000.example. 5M IN A 10.0.4.212
+4000.example. 5M IN A 10.0.4.213
+4000.example. 5M IN A 10.0.4.214
+4000.example. 5M IN A 10.0.4.215
+4000.example. 5M IN A 10.0.4.216
+4000.example. 5M IN A 10.0.4.217
+4000.example. 5M IN A 10.0.4.218
+4000.example. 5M IN A 10.0.4.219
+4000.example. 5M IN A 10.0.4.220
+4000.example. 5M IN A 10.0.4.221
+4000.example. 5M IN A 10.0.4.222
+4000.example. 5M IN A 10.0.4.223
+4000.example. 5M IN A 10.0.4.224
+4000.example. 5M IN A 10.0.4.225
+4000.example. 5M IN A 10.0.4.226
+4000.example. 5M IN A 10.0.4.227
+4000.example. 5M IN A 10.0.4.228
+4000.example. 5M IN A 10.0.4.229
+4000.example. 5M IN A 10.0.4.230
+4000.example. 5M IN A 10.0.4.231
+4000.example. 5M IN A 10.0.4.232
+4000.example. 5M IN A 10.0.4.233
+4000.example. 5M IN A 10.0.4.234
+4000.example. 5M IN A 10.0.4.235
+4000.example. 5M IN A 10.0.4.236
+4000.example. 5M IN A 10.0.4.237
+4000.example. 5M IN A 10.0.4.238
+4000.example. 5M IN A 10.0.4.239
+4000.example. 5M IN A 10.0.4.240
+4000.example. 5M IN A 10.0.4.241
+4000.example. 5M IN A 10.0.4.242
+4000.example. 5M IN A 10.0.4.243
+4000.example. 5M IN A 10.0.4.244
+4000.example. 5M IN A 10.0.4.245
+4000.example. 5M IN A 10.0.4.246
+4000.example. 5M IN A 10.0.4.247
+4000.example. 5M IN A 10.0.4.248
+4000.example. 5M IN A 10.0.4.249
+4000.example. 5M IN A 10.0.4.250
+4000.example. 5M IN A 10.0.4.251
+4000.example. 5M IN A 10.0.4.252
+4000.example. 5M IN A 10.0.4.253
+4000.example. 5M IN A 10.0.4.254
+4000.example. 5M IN A 10.0.4.255
+4000.example. 5M IN A 10.0.5.0
+4000.example. 5M IN A 10.0.5.1
+4000.example. 5M IN A 10.0.5.2
+4000.example. 5M IN A 10.0.5.3
+4000.example. 5M IN A 10.0.5.4
+4000.example. 5M IN A 10.0.5.5
+4000.example. 5M IN A 10.0.5.6
+4000.example. 5M IN A 10.0.5.7
+4000.example. 5M IN A 10.0.5.8
+4000.example. 5M IN A 10.0.5.9
+4000.example. 5M IN A 10.0.5.10
+4000.example. 5M IN A 10.0.5.11
+4000.example. 5M IN A 10.0.5.12
+4000.example. 5M IN A 10.0.5.13
+4000.example. 5M IN A 10.0.5.14
+4000.example. 5M IN A 10.0.5.15
+4000.example. 5M IN A 10.0.5.16
+4000.example. 5M IN A 10.0.5.17
+4000.example. 5M IN A 10.0.5.18
+4000.example. 5M IN A 10.0.5.19
+4000.example. 5M IN A 10.0.5.20
+4000.example. 5M IN A 10.0.5.21
+4000.example. 5M IN A 10.0.5.22
+4000.example. 5M IN A 10.0.5.23
+4000.example. 5M IN A 10.0.5.24
+4000.example. 5M IN A 10.0.5.25
+4000.example. 5M IN A 10.0.5.26
+4000.example. 5M IN A 10.0.5.27
+4000.example. 5M IN A 10.0.5.28
+4000.example. 5M IN A 10.0.5.29
+4000.example. 5M IN A 10.0.5.30
+4000.example. 5M IN A 10.0.5.31
+4000.example. 5M IN A 10.0.5.32
+4000.example. 5M IN A 10.0.5.33
+4000.example. 5M IN A 10.0.5.34
+4000.example. 5M IN A 10.0.5.35
+4000.example. 5M IN A 10.0.5.36
+4000.example. 5M IN A 10.0.5.37
+4000.example. 5M IN A 10.0.5.38
+4000.example. 5M IN A 10.0.5.39
+4000.example. 5M IN A 10.0.5.40
+4000.example. 5M IN A 10.0.5.41
+4000.example. 5M IN A 10.0.5.42
+4000.example. 5M IN A 10.0.5.43
+4000.example. 5M IN A 10.0.5.44
+4000.example. 5M IN A 10.0.5.45
+4000.example. 5M IN A 10.0.5.46
+4000.example. 5M IN A 10.0.5.47
+4000.example. 5M IN A 10.0.5.48
+4000.example. 5M IN A 10.0.5.49
+4000.example. 5M IN A 10.0.5.50
+4000.example. 5M IN A 10.0.5.51
+4000.example. 5M IN A 10.0.5.52
+4000.example. 5M IN A 10.0.5.53
+4000.example. 5M IN A 10.0.5.54
+4000.example. 5M IN A 10.0.5.55
+4000.example. 5M IN A 10.0.5.56
+4000.example. 5M IN A 10.0.5.57
+4000.example. 5M IN A 10.0.5.58
+4000.example. 5M IN A 10.0.5.59
+4000.example. 5M IN A 10.0.5.60
+4000.example. 5M IN A 10.0.5.61
+4000.example. 5M IN A 10.0.5.62
+4000.example. 5M IN A 10.0.5.63
+4000.example. 5M IN A 10.0.5.64
+4000.example. 5M IN A 10.0.5.65
+4000.example. 5M IN A 10.0.5.66
+4000.example. 5M IN A 10.0.5.67
+4000.example. 5M IN A 10.0.5.68
+4000.example. 5M IN A 10.0.5.69
+4000.example. 5M IN A 10.0.5.70
+4000.example. 5M IN A 10.0.5.71
+4000.example. 5M IN A 10.0.5.72
+4000.example. 5M IN A 10.0.5.73
+4000.example. 5M IN A 10.0.5.74
+4000.example. 5M IN A 10.0.5.75
+4000.example. 5M IN A 10.0.5.76
+4000.example. 5M IN A 10.0.5.77
+4000.example. 5M IN A 10.0.5.78
+4000.example. 5M IN A 10.0.5.79
+4000.example. 5M IN A 10.0.5.80
+4000.example. 5M IN A 10.0.5.81
+4000.example. 5M IN A 10.0.5.82
+4000.example. 5M IN A 10.0.5.83
+4000.example. 5M IN A 10.0.5.84
+4000.example. 5M IN A 10.0.5.85
+4000.example. 5M IN A 10.0.5.86
+4000.example. 5M IN A 10.0.5.87
+4000.example. 5M IN A 10.0.5.88
+4000.example. 5M IN A 10.0.5.89
+4000.example. 5M IN A 10.0.5.90
+4000.example. 5M IN A 10.0.5.91
+4000.example. 5M IN A 10.0.5.92
+4000.example. 5M IN A 10.0.5.93
+4000.example. 5M IN A 10.0.5.94
+4000.example. 5M IN A 10.0.5.95
+4000.example. 5M IN A 10.0.5.96
+4000.example. 5M IN A 10.0.5.97
+4000.example. 5M IN A 10.0.5.98
+4000.example. 5M IN A 10.0.5.99
+4000.example. 5M IN A 10.0.5.100
+4000.example. 5M IN A 10.0.5.101
+4000.example. 5M IN A 10.0.5.102
+4000.example. 5M IN A 10.0.5.103
+4000.example. 5M IN A 10.0.5.104
+4000.example. 5M IN A 10.0.5.105
+4000.example. 5M IN A 10.0.5.106
+4000.example. 5M IN A 10.0.5.107
+4000.example. 5M IN A 10.0.5.108
+4000.example. 5M IN A 10.0.5.109
+4000.example. 5M IN A 10.0.5.110
+4000.example. 5M IN A 10.0.5.111
+4000.example. 5M IN A 10.0.5.112
+4000.example. 5M IN A 10.0.5.113
+4000.example. 5M IN A 10.0.5.114
+4000.example. 5M IN A 10.0.5.115
+4000.example. 5M IN A 10.0.5.116
+4000.example. 5M IN A 10.0.5.117
+4000.example. 5M IN A 10.0.5.118
+4000.example. 5M IN A 10.0.5.119
+4000.example. 5M IN A 10.0.5.120
+4000.example. 5M IN A 10.0.5.121
+4000.example. 5M IN A 10.0.5.122
+4000.example. 5M IN A 10.0.5.123
+4000.example. 5M IN A 10.0.5.124
+4000.example. 5M IN A 10.0.5.125
+4000.example. 5M IN A 10.0.5.126
+4000.example. 5M IN A 10.0.5.127
+4000.example. 5M IN A 10.0.5.128
+4000.example. 5M IN A 10.0.5.129
+4000.example. 5M IN A 10.0.5.130
+4000.example. 5M IN A 10.0.5.131
+4000.example. 5M IN A 10.0.5.132
+4000.example. 5M IN A 10.0.5.133
+4000.example. 5M IN A 10.0.5.134
+4000.example. 5M IN A 10.0.5.135
+4000.example. 5M IN A 10.0.5.136
+4000.example. 5M IN A 10.0.5.137
+4000.example. 5M IN A 10.0.5.138
+4000.example. 5M IN A 10.0.5.139
+4000.example. 5M IN A 10.0.5.140
+4000.example. 5M IN A 10.0.5.141
+4000.example. 5M IN A 10.0.5.142
+4000.example. 5M IN A 10.0.5.143
+4000.example. 5M IN A 10.0.5.144
+4000.example. 5M IN A 10.0.5.145
+4000.example. 5M IN A 10.0.5.146
+4000.example. 5M IN A 10.0.5.147
+4000.example. 5M IN A 10.0.5.148
+4000.example. 5M IN A 10.0.5.149
+4000.example. 5M IN A 10.0.5.150
+4000.example. 5M IN A 10.0.5.151
+4000.example. 5M IN A 10.0.5.152
+4000.example. 5M IN A 10.0.5.153
+4000.example. 5M IN A 10.0.5.154
+4000.example. 5M IN A 10.0.5.155
+4000.example. 5M IN A 10.0.5.156
+4000.example. 5M IN A 10.0.5.157
+4000.example. 5M IN A 10.0.5.158
+4000.example. 5M IN A 10.0.5.159
+4000.example. 5M IN A 10.0.5.160
+4000.example. 5M IN A 10.0.5.161
+4000.example. 5M IN A 10.0.5.162
+4000.example. 5M IN A 10.0.5.163
+4000.example. 5M IN A 10.0.5.164
+4000.example. 5M IN A 10.0.5.165
+4000.example. 5M IN A 10.0.5.166
+4000.example. 5M IN A 10.0.5.167
+4000.example. 5M IN A 10.0.5.168
+4000.example. 5M IN A 10.0.5.169
+4000.example. 5M IN A 10.0.5.170
+4000.example. 5M IN A 10.0.5.171
+4000.example. 5M IN A 10.0.5.172
+4000.example. 5M IN A 10.0.5.173
+4000.example. 5M IN A 10.0.5.174
+4000.example. 5M IN A 10.0.5.175
+4000.example. 5M IN A 10.0.5.176
+4000.example. 5M IN A 10.0.5.177
+4000.example. 5M IN A 10.0.5.178
+4000.example. 5M IN A 10.0.5.179
+4000.example. 5M IN A 10.0.5.180
+4000.example. 5M IN A 10.0.5.181
+4000.example. 5M IN A 10.0.5.182
+4000.example. 5M IN A 10.0.5.183
+4000.example. 5M IN A 10.0.5.184
+4000.example. 5M IN A 10.0.5.185
+4000.example. 5M IN A 10.0.5.186
+4000.example. 5M IN A 10.0.5.187
+4000.example. 5M IN A 10.0.5.188
+4000.example. 5M IN A 10.0.5.189
+4000.example. 5M IN A 10.0.5.190
+4000.example. 5M IN A 10.0.5.191
+4000.example. 5M IN A 10.0.5.192
+4000.example. 5M IN A 10.0.5.193
+4000.example. 5M IN A 10.0.5.194
+4000.example. 5M IN A 10.0.5.195
+4000.example. 5M IN A 10.0.5.196
+4000.example. 5M IN A 10.0.5.197
+4000.example. 5M IN A 10.0.5.198
+4000.example. 5M IN A 10.0.5.199
+4000.example. 5M IN A 10.0.5.200
+4000.example. 5M IN A 10.0.5.201
+4000.example. 5M IN A 10.0.5.202
+4000.example. 5M IN A 10.0.5.203
+4000.example. 5M IN A 10.0.5.204
+4000.example. 5M IN A 10.0.5.205
+4000.example. 5M IN A 10.0.5.206
+4000.example. 5M IN A 10.0.5.207
+4000.example. 5M IN A 10.0.5.208
+4000.example. 5M IN A 10.0.5.209
+4000.example. 5M IN A 10.0.5.210
+4000.example. 5M IN A 10.0.5.211
+4000.example. 5M IN A 10.0.5.212
+4000.example. 5M IN A 10.0.5.213
+4000.example. 5M IN A 10.0.5.214
+4000.example. 5M IN A 10.0.5.215
+4000.example. 5M IN A 10.0.5.216
+4000.example. 5M IN A 10.0.5.217
+4000.example. 5M IN A 10.0.5.218
+4000.example. 5M IN A 10.0.5.219
+4000.example. 5M IN A 10.0.5.220
+4000.example. 5M IN A 10.0.5.221
+4000.example. 5M IN A 10.0.5.222
+4000.example. 5M IN A 10.0.5.223
+4000.example. 5M IN A 10.0.5.224
+4000.example. 5M IN A 10.0.5.225
+4000.example. 5M IN A 10.0.5.226
+4000.example. 5M IN A 10.0.5.227
+4000.example. 5M IN A 10.0.5.228
+4000.example. 5M IN A 10.0.5.229
+4000.example. 5M IN A 10.0.5.230
+4000.example. 5M IN A 10.0.5.231
+4000.example. 5M IN A 10.0.5.232
+4000.example. 5M IN A 10.0.5.233
+4000.example. 5M IN A 10.0.5.234
+4000.example. 5M IN A 10.0.5.235
+4000.example. 5M IN A 10.0.5.236
+4000.example. 5M IN A 10.0.5.237
+4000.example. 5M IN A 10.0.5.238
+4000.example. 5M IN A 10.0.5.239
+4000.example. 5M IN A 10.0.5.240
+4000.example. 5M IN A 10.0.5.241
+4000.example. 5M IN A 10.0.5.242
+4000.example. 5M IN A 10.0.5.243
+4000.example. 5M IN A 10.0.5.244
+4000.example. 5M IN A 10.0.5.245
+4000.example. 5M IN A 10.0.5.246
+4000.example. 5M IN A 10.0.5.247
+4000.example. 5M IN A 10.0.5.248
+4000.example. 5M IN A 10.0.5.249
+4000.example. 5M IN A 10.0.5.250
+4000.example. 5M IN A 10.0.5.251
+4000.example. 5M IN A 10.0.5.252
+4000.example. 5M IN A 10.0.5.253
+4000.example. 5M IN A 10.0.5.254
+4000.example. 5M IN A 10.0.5.255
+4000.example. 5M IN A 10.0.6.0
+4000.example. 5M IN A 10.0.6.1
+4000.example. 5M IN A 10.0.6.2
+4000.example. 5M IN A 10.0.6.3
+4000.example. 5M IN A 10.0.6.4
+4000.example. 5M IN A 10.0.6.5
+4000.example. 5M IN A 10.0.6.6
+4000.example. 5M IN A 10.0.6.7
+4000.example. 5M IN A 10.0.6.8
+4000.example. 5M IN A 10.0.6.9
+4000.example. 5M IN A 10.0.6.10
+4000.example. 5M IN A 10.0.6.11
+4000.example. 5M IN A 10.0.6.12
+4000.example. 5M IN A 10.0.6.13
+4000.example. 5M IN A 10.0.6.14
+4000.example. 5M IN A 10.0.6.15
+4000.example. 5M IN A 10.0.6.16
+4000.example. 5M IN A 10.0.6.17
+4000.example. 5M IN A 10.0.6.18
+4000.example. 5M IN A 10.0.6.19
+4000.example. 5M IN A 10.0.6.20
+4000.example. 5M IN A 10.0.6.21
+4000.example. 5M IN A 10.0.6.22
+4000.example. 5M IN A 10.0.6.23
+4000.example. 5M IN A 10.0.6.24
+4000.example. 5M IN A 10.0.6.25
+4000.example. 5M IN A 10.0.6.26
+4000.example. 5M IN A 10.0.6.27
+4000.example. 5M IN A 10.0.6.28
+4000.example. 5M IN A 10.0.6.29
+4000.example. 5M IN A 10.0.6.30
+4000.example. 5M IN A 10.0.6.31
+4000.example. 5M IN A 10.0.6.32
+4000.example. 5M IN A 10.0.6.33
+4000.example. 5M IN A 10.0.6.34
+4000.example. 5M IN A 10.0.6.35
+4000.example. 5M IN A 10.0.6.36
+4000.example. 5M IN A 10.0.6.37
+4000.example. 5M IN A 10.0.6.38
+4000.example. 5M IN A 10.0.6.39
+4000.example. 5M IN A 10.0.6.40
+4000.example. 5M IN A 10.0.6.41
+4000.example. 5M IN A 10.0.6.42
+4000.example. 5M IN A 10.0.6.43
+4000.example. 5M IN A 10.0.6.44
+4000.example. 5M IN A 10.0.6.45
+4000.example. 5M IN A 10.0.6.46
+4000.example. 5M IN A 10.0.6.47
+4000.example. 5M IN A 10.0.6.48
+4000.example. 5M IN A 10.0.6.49
+4000.example. 5M IN A 10.0.6.50
+4000.example. 5M IN A 10.0.6.51
+4000.example. 5M IN A 10.0.6.52
+4000.example. 5M IN A 10.0.6.53
+4000.example. 5M IN A 10.0.6.54
+4000.example. 5M IN A 10.0.6.55
+4000.example. 5M IN A 10.0.6.56
+4000.example. 5M IN A 10.0.6.57
+4000.example. 5M IN A 10.0.6.58
+4000.example. 5M IN A 10.0.6.59
+4000.example. 5M IN A 10.0.6.60
+4000.example. 5M IN A 10.0.6.61
+4000.example. 5M IN A 10.0.6.62
+4000.example. 5M IN A 10.0.6.63
+4000.example. 5M IN A 10.0.6.64
+4000.example. 5M IN A 10.0.6.65
+4000.example. 5M IN A 10.0.6.66
+4000.example. 5M IN A 10.0.6.67
+4000.example. 5M IN A 10.0.6.68
+4000.example. 5M IN A 10.0.6.69
+4000.example. 5M IN A 10.0.6.70
+4000.example. 5M IN A 10.0.6.71
+4000.example. 5M IN A 10.0.6.72
+4000.example. 5M IN A 10.0.6.73
+4000.example. 5M IN A 10.0.6.74
+4000.example. 5M IN A 10.0.6.75
+4000.example. 5M IN A 10.0.6.76
+4000.example. 5M IN A 10.0.6.77
+4000.example. 5M IN A 10.0.6.78
+4000.example. 5M IN A 10.0.6.79
+4000.example. 5M IN A 10.0.6.80
+4000.example. 5M IN A 10.0.6.81
+4000.example. 5M IN A 10.0.6.82
+4000.example. 5M IN A 10.0.6.83
+4000.example. 5M IN A 10.0.6.84
+4000.example. 5M IN A 10.0.6.85
+4000.example. 5M IN A 10.0.6.86
+4000.example. 5M IN A 10.0.6.87
+4000.example. 5M IN A 10.0.6.88
+4000.example. 5M IN A 10.0.6.89
+4000.example. 5M IN A 10.0.6.90
+4000.example. 5M IN A 10.0.6.91
+4000.example. 5M IN A 10.0.6.92
+4000.example. 5M IN A 10.0.6.93
+4000.example. 5M IN A 10.0.6.94
+4000.example. 5M IN A 10.0.6.95
+4000.example. 5M IN A 10.0.6.96
+4000.example. 5M IN A 10.0.6.97
+4000.example. 5M IN A 10.0.6.98
+4000.example. 5M IN A 10.0.6.99
+4000.example. 5M IN A 10.0.6.100
+4000.example. 5M IN A 10.0.6.101
+4000.example. 5M IN A 10.0.6.102
+4000.example. 5M IN A 10.0.6.103
+4000.example. 5M IN A 10.0.6.104
+4000.example. 5M IN A 10.0.6.105
+4000.example. 5M IN A 10.0.6.106
+4000.example. 5M IN A 10.0.6.107
+4000.example. 5M IN A 10.0.6.108
+4000.example. 5M IN A 10.0.6.109
+4000.example. 5M IN A 10.0.6.110
+4000.example. 5M IN A 10.0.6.111
+4000.example. 5M IN A 10.0.6.112
+4000.example. 5M IN A 10.0.6.113
+4000.example. 5M IN A 10.0.6.114
+4000.example. 5M IN A 10.0.6.115
+4000.example. 5M IN A 10.0.6.116
+4000.example. 5M IN A 10.0.6.117
+4000.example. 5M IN A 10.0.6.118
+4000.example. 5M IN A 10.0.6.119
+4000.example. 5M IN A 10.0.6.120
+4000.example. 5M IN A 10.0.6.121
+4000.example. 5M IN A 10.0.6.122
+4000.example. 5M IN A 10.0.6.123
+4000.example. 5M IN A 10.0.6.124
+4000.example. 5M IN A 10.0.6.125
+4000.example. 5M IN A 10.0.6.126
+4000.example. 5M IN A 10.0.6.127
+4000.example. 5M IN A 10.0.6.128
+4000.example. 5M IN A 10.0.6.129
+4000.example. 5M IN A 10.0.6.130
+4000.example. 5M IN A 10.0.6.131
+4000.example. 5M IN A 10.0.6.132
+4000.example. 5M IN A 10.0.6.133
+4000.example. 5M IN A 10.0.6.134
+4000.example. 5M IN A 10.0.6.135
+4000.example. 5M IN A 10.0.6.136
+4000.example. 5M IN A 10.0.6.137
+4000.example. 5M IN A 10.0.6.138
+4000.example. 5M IN A 10.0.6.139
+4000.example. 5M IN A 10.0.6.140
+4000.example. 5M IN A 10.0.6.141
+4000.example. 5M IN A 10.0.6.142
+4000.example. 5M IN A 10.0.6.143
+4000.example. 5M IN A 10.0.6.144
+4000.example. 5M IN A 10.0.6.145
+4000.example. 5M IN A 10.0.6.146
+4000.example. 5M IN A 10.0.6.147
+4000.example. 5M IN A 10.0.6.148
+4000.example. 5M IN A 10.0.6.149
+4000.example. 5M IN A 10.0.6.150
+4000.example. 5M IN A 10.0.6.151
+4000.example. 5M IN A 10.0.6.152
+4000.example. 5M IN A 10.0.6.153
+4000.example. 5M IN A 10.0.6.154
+4000.example. 5M IN A 10.0.6.155
+4000.example. 5M IN A 10.0.6.156
+4000.example. 5M IN A 10.0.6.157
+4000.example. 5M IN A 10.0.6.158
+4000.example. 5M IN A 10.0.6.159
+4000.example. 5M IN A 10.0.6.160
+4000.example. 5M IN A 10.0.6.161
+4000.example. 5M IN A 10.0.6.162
+4000.example. 5M IN A 10.0.6.163
+4000.example. 5M IN A 10.0.6.164
+4000.example. 5M IN A 10.0.6.165
+4000.example. 5M IN A 10.0.6.166
+4000.example. 5M IN A 10.0.6.167
+4000.example. 5M IN A 10.0.6.168
+4000.example. 5M IN A 10.0.6.169
+4000.example. 5M IN A 10.0.6.170
+4000.example. 5M IN A 10.0.6.171
+4000.example. 5M IN A 10.0.6.172
+4000.example. 5M IN A 10.0.6.173
+4000.example. 5M IN A 10.0.6.174
+4000.example. 5M IN A 10.0.6.175
+4000.example. 5M IN A 10.0.6.176
+4000.example. 5M IN A 10.0.6.177
+4000.example. 5M IN A 10.0.6.178
+4000.example. 5M IN A 10.0.6.179
+4000.example. 5M IN A 10.0.6.180
+4000.example. 5M IN A 10.0.6.181
+4000.example. 5M IN A 10.0.6.182
+4000.example. 5M IN A 10.0.6.183
+4000.example. 5M IN A 10.0.6.184
+4000.example. 5M IN A 10.0.6.185
+4000.example. 5M IN A 10.0.6.186
+4000.example. 5M IN A 10.0.6.187
+4000.example. 5M IN A 10.0.6.188
+4000.example. 5M IN A 10.0.6.189
+4000.example. 5M IN A 10.0.6.190
+4000.example. 5M IN A 10.0.6.191
+4000.example. 5M IN A 10.0.6.192
+4000.example. 5M IN A 10.0.6.193
+4000.example. 5M IN A 10.0.6.194
+4000.example. 5M IN A 10.0.6.195
+4000.example. 5M IN A 10.0.6.196
+4000.example. 5M IN A 10.0.6.197
+4000.example. 5M IN A 10.0.6.198
+4000.example. 5M IN A 10.0.6.199
+4000.example. 5M IN A 10.0.6.200
+4000.example. 5M IN A 10.0.6.201
+4000.example. 5M IN A 10.0.6.202
+4000.example. 5M IN A 10.0.6.203
+4000.example. 5M IN A 10.0.6.204
+4000.example. 5M IN A 10.0.6.205
+4000.example. 5M IN A 10.0.6.206
+4000.example. 5M IN A 10.0.6.207
+4000.example. 5M IN A 10.0.6.208
+4000.example. 5M IN A 10.0.6.209
+4000.example. 5M IN A 10.0.6.210
+4000.example. 5M IN A 10.0.6.211
+4000.example. 5M IN A 10.0.6.212
+4000.example. 5M IN A 10.0.6.213
+4000.example. 5M IN A 10.0.6.214
+4000.example. 5M IN A 10.0.6.215
+4000.example. 5M IN A 10.0.6.216
+4000.example. 5M IN A 10.0.6.217
+4000.example. 5M IN A 10.0.6.218
+4000.example. 5M IN A 10.0.6.219
+4000.example. 5M IN A 10.0.6.220
+4000.example. 5M IN A 10.0.6.221
+4000.example. 5M IN A 10.0.6.222
+4000.example. 5M IN A 10.0.6.223
+4000.example. 5M IN A 10.0.6.224
+4000.example. 5M IN A 10.0.6.225
+4000.example. 5M IN A 10.0.6.226
+4000.example. 5M IN A 10.0.6.227
+4000.example. 5M IN A 10.0.6.228
+4000.example. 5M IN A 10.0.6.229
+4000.example. 5M IN A 10.0.6.230
+4000.example. 5M IN A 10.0.6.231
+4000.example. 5M IN A 10.0.6.232
+4000.example. 5M IN A 10.0.6.233
+4000.example. 5M IN A 10.0.6.234
+4000.example. 5M IN A 10.0.6.235
+4000.example. 5M IN A 10.0.6.236
+4000.example. 5M IN A 10.0.6.237
+4000.example. 5M IN A 10.0.6.238
+4000.example. 5M IN A 10.0.6.239
+4000.example. 5M IN A 10.0.6.240
+4000.example. 5M IN A 10.0.6.241
+4000.example. 5M IN A 10.0.6.242
+4000.example. 5M IN A 10.0.6.243
+4000.example. 5M IN A 10.0.6.244
+4000.example. 5M IN A 10.0.6.245
+4000.example. 5M IN A 10.0.6.246
+4000.example. 5M IN A 10.0.6.247
+4000.example. 5M IN A 10.0.6.248
+4000.example. 5M IN A 10.0.6.249
+4000.example. 5M IN A 10.0.6.250
+4000.example. 5M IN A 10.0.6.251
+4000.example. 5M IN A 10.0.6.252
+4000.example. 5M IN A 10.0.6.253
+4000.example. 5M IN A 10.0.6.254
+4000.example. 5M IN A 10.0.6.255
+4000.example. 5M IN A 10.0.7.0
+4000.example. 5M IN A 10.0.7.1
+4000.example. 5M IN A 10.0.7.2
+4000.example. 5M IN A 10.0.7.3
+4000.example. 5M IN A 10.0.7.4
+4000.example. 5M IN A 10.0.7.5
+4000.example. 5M IN A 10.0.7.6
+4000.example. 5M IN A 10.0.7.7
+4000.example. 5M IN A 10.0.7.8
+4000.example. 5M IN A 10.0.7.9
+4000.example. 5M IN A 10.0.7.10
+4000.example. 5M IN A 10.0.7.11
+4000.example. 5M IN A 10.0.7.12
+4000.example. 5M IN A 10.0.7.13
+4000.example. 5M IN A 10.0.7.14
+4000.example. 5M IN A 10.0.7.15
+4000.example. 5M IN A 10.0.7.16
+4000.example. 5M IN A 10.0.7.17
+4000.example. 5M IN A 10.0.7.18
+4000.example. 5M IN A 10.0.7.19
+4000.example. 5M IN A 10.0.7.20
+4000.example. 5M IN A 10.0.7.21
+4000.example. 5M IN A 10.0.7.22
+4000.example. 5M IN A 10.0.7.23
+4000.example. 5M IN A 10.0.7.24
+4000.example. 5M IN A 10.0.7.25
+4000.example. 5M IN A 10.0.7.26
+4000.example. 5M IN A 10.0.7.27
+4000.example. 5M IN A 10.0.7.28
+4000.example. 5M IN A 10.0.7.29
+4000.example. 5M IN A 10.0.7.30
+4000.example. 5M IN A 10.0.7.31
+4000.example. 5M IN A 10.0.7.32
+4000.example. 5M IN A 10.0.7.33
+4000.example. 5M IN A 10.0.7.34
+4000.example. 5M IN A 10.0.7.35
+4000.example. 5M IN A 10.0.7.36
+4000.example. 5M IN A 10.0.7.37
+4000.example. 5M IN A 10.0.7.38
+4000.example. 5M IN A 10.0.7.39
+4000.example. 5M IN A 10.0.7.40
+4000.example. 5M IN A 10.0.7.41
+4000.example. 5M IN A 10.0.7.42
+4000.example. 5M IN A 10.0.7.43
+4000.example. 5M IN A 10.0.7.44
+4000.example. 5M IN A 10.0.7.45
+4000.example. 5M IN A 10.0.7.46
+4000.example. 5M IN A 10.0.7.47
+4000.example. 5M IN A 10.0.7.48
+4000.example. 5M IN A 10.0.7.49
+4000.example. 5M IN A 10.0.7.50
+4000.example. 5M IN A 10.0.7.51
+4000.example. 5M IN A 10.0.7.52
+4000.example. 5M IN A 10.0.7.53
+4000.example. 5M IN A 10.0.7.54
+4000.example. 5M IN A 10.0.7.55
+4000.example. 5M IN A 10.0.7.56
+4000.example. 5M IN A 10.0.7.57
+4000.example. 5M IN A 10.0.7.58
+4000.example. 5M IN A 10.0.7.59
+4000.example. 5M IN A 10.0.7.60
+4000.example. 5M IN A 10.0.7.61
+4000.example. 5M IN A 10.0.7.62
+4000.example. 5M IN A 10.0.7.63
+4000.example. 5M IN A 10.0.7.64
+4000.example. 5M IN A 10.0.7.65
+4000.example. 5M IN A 10.0.7.66
+4000.example. 5M IN A 10.0.7.67
+4000.example. 5M IN A 10.0.7.68
+4000.example. 5M IN A 10.0.7.69
+4000.example. 5M IN A 10.0.7.70
+4000.example. 5M IN A 10.0.7.71
+4000.example. 5M IN A 10.0.7.72
+4000.example. 5M IN A 10.0.7.73
+4000.example. 5M IN A 10.0.7.74
+4000.example. 5M IN A 10.0.7.75
+4000.example. 5M IN A 10.0.7.76
+4000.example. 5M IN A 10.0.7.77
+4000.example. 5M IN A 10.0.7.78
+4000.example. 5M IN A 10.0.7.79
+4000.example. 5M IN A 10.0.7.80
+4000.example. 5M IN A 10.0.7.81
+4000.example. 5M IN A 10.0.7.82
+4000.example. 5M IN A 10.0.7.83
+4000.example. 5M IN A 10.0.7.84
+4000.example. 5M IN A 10.0.7.85
+4000.example. 5M IN A 10.0.7.86
+4000.example. 5M IN A 10.0.7.87
+4000.example. 5M IN A 10.0.7.88
+4000.example. 5M IN A 10.0.7.89
+4000.example. 5M IN A 10.0.7.90
+4000.example. 5M IN A 10.0.7.91
+4000.example. 5M IN A 10.0.7.92
+4000.example. 5M IN A 10.0.7.93
+4000.example. 5M IN A 10.0.7.94
+4000.example. 5M IN A 10.0.7.95
+4000.example. 5M IN A 10.0.7.96
+4000.example. 5M IN A 10.0.7.97
+4000.example. 5M IN A 10.0.7.98
+4000.example. 5M IN A 10.0.7.99
+4000.example. 5M IN A 10.0.7.100
+4000.example. 5M IN A 10.0.7.101
+4000.example. 5M IN A 10.0.7.102
+4000.example. 5M IN A 10.0.7.103
+4000.example. 5M IN A 10.0.7.104
+4000.example. 5M IN A 10.0.7.105
+4000.example. 5M IN A 10.0.7.106
+4000.example. 5M IN A 10.0.7.107
+4000.example. 5M IN A 10.0.7.108
+4000.example. 5M IN A 10.0.7.109
+4000.example. 5M IN A 10.0.7.110
+4000.example. 5M IN A 10.0.7.111
+4000.example. 5M IN A 10.0.7.112
+4000.example. 5M IN A 10.0.7.113
+4000.example. 5M IN A 10.0.7.114
+4000.example. 5M IN A 10.0.7.115
+4000.example. 5M IN A 10.0.7.116
+4000.example. 5M IN A 10.0.7.117
+4000.example. 5M IN A 10.0.7.118
+4000.example. 5M IN A 10.0.7.119
+4000.example. 5M IN A 10.0.7.120
+4000.example. 5M IN A 10.0.7.121
+4000.example. 5M IN A 10.0.7.122
+4000.example. 5M IN A 10.0.7.123
+4000.example. 5M IN A 10.0.7.124
+4000.example. 5M IN A 10.0.7.125
+4000.example. 5M IN A 10.0.7.126
+4000.example. 5M IN A 10.0.7.127
+4000.example. 5M IN A 10.0.7.128
+4000.example. 5M IN A 10.0.7.129
+4000.example. 5M IN A 10.0.7.130
+4000.example. 5M IN A 10.0.7.131
+4000.example. 5M IN A 10.0.7.132
+4000.example. 5M IN A 10.0.7.133
+4000.example. 5M IN A 10.0.7.134
+4000.example. 5M IN A 10.0.7.135
+4000.example. 5M IN A 10.0.7.136
+4000.example. 5M IN A 10.0.7.137
+4000.example. 5M IN A 10.0.7.138
+4000.example. 5M IN A 10.0.7.139
+4000.example. 5M IN A 10.0.7.140
+4000.example. 5M IN A 10.0.7.141
+4000.example. 5M IN A 10.0.7.142
+4000.example. 5M IN A 10.0.7.143
+4000.example. 5M IN A 10.0.7.144
+4000.example. 5M IN A 10.0.7.145
+4000.example. 5M IN A 10.0.7.146
+4000.example. 5M IN A 10.0.7.147
+4000.example. 5M IN A 10.0.7.148
+4000.example. 5M IN A 10.0.7.149
+4000.example. 5M IN A 10.0.7.150
+4000.example. 5M IN A 10.0.7.151
+4000.example. 5M IN A 10.0.7.152
+4000.example. 5M IN A 10.0.7.153
+4000.example. 5M IN A 10.0.7.154
+4000.example. 5M IN A 10.0.7.155
+4000.example. 5M IN A 10.0.7.156
+4000.example. 5M IN A 10.0.7.157
+4000.example. 5M IN A 10.0.7.158
+4000.example. 5M IN A 10.0.7.159
+4000.example. 5M IN A 10.0.7.160
+4000.example. 5M IN A 10.0.7.161
+4000.example. 5M IN A 10.0.7.162
+4000.example. 5M IN A 10.0.7.163
+4000.example. 5M IN A 10.0.7.164
+4000.example. 5M IN A 10.0.7.165
+4000.example. 5M IN A 10.0.7.166
+4000.example. 5M IN A 10.0.7.167
+4000.example. 5M IN A 10.0.7.168
+4000.example. 5M IN A 10.0.7.169
+4000.example. 5M IN A 10.0.7.170
+4000.example. 5M IN A 10.0.7.171
+4000.example. 5M IN A 10.0.7.172
+4000.example. 5M IN A 10.0.7.173
+4000.example. 5M IN A 10.0.7.174
+4000.example. 5M IN A 10.0.7.175
+4000.example. 5M IN A 10.0.7.176
+4000.example. 5M IN A 10.0.7.177
+4000.example. 5M IN A 10.0.7.178
+4000.example. 5M IN A 10.0.7.179
+4000.example. 5M IN A 10.0.7.180
+4000.example. 5M IN A 10.0.7.181
+4000.example. 5M IN A 10.0.7.182
+4000.example. 5M IN A 10.0.7.183
+4000.example. 5M IN A 10.0.7.184
+4000.example. 5M IN A 10.0.7.185
+4000.example. 5M IN A 10.0.7.186
+4000.example. 5M IN A 10.0.7.187
+4000.example. 5M IN A 10.0.7.188
+4000.example. 5M IN A 10.0.7.189
+4000.example. 5M IN A 10.0.7.190
+4000.example. 5M IN A 10.0.7.191
+4000.example. 5M IN A 10.0.7.192
+4000.example. 5M IN A 10.0.7.193
+4000.example. 5M IN A 10.0.7.194
+4000.example. 5M IN A 10.0.7.195
+4000.example. 5M IN A 10.0.7.196
+4000.example. 5M IN A 10.0.7.197
+4000.example. 5M IN A 10.0.7.198
+4000.example. 5M IN A 10.0.7.199
+4000.example. 5M IN A 10.0.7.200
+4000.example. 5M IN A 10.0.7.201
+4000.example. 5M IN A 10.0.7.202
+4000.example. 5M IN A 10.0.7.203
+4000.example. 5M IN A 10.0.7.204
+4000.example. 5M IN A 10.0.7.205
+4000.example. 5M IN A 10.0.7.206
+4000.example. 5M IN A 10.0.7.207
+4000.example. 5M IN A 10.0.7.208
+4000.example. 5M IN A 10.0.7.209
+4000.example. 5M IN A 10.0.7.210
+4000.example. 5M IN A 10.0.7.211
+4000.example. 5M IN A 10.0.7.212
+4000.example. 5M IN A 10.0.7.213
+4000.example. 5M IN A 10.0.7.214
+4000.example. 5M IN A 10.0.7.215
+4000.example. 5M IN A 10.0.7.216
+4000.example. 5M IN A 10.0.7.217
+4000.example. 5M IN A 10.0.7.218
+4000.example. 5M IN A 10.0.7.219
+4000.example. 5M IN A 10.0.7.220
+4000.example. 5M IN A 10.0.7.221
+4000.example. 5M IN A 10.0.7.222
+4000.example. 5M IN A 10.0.7.223
+4000.example. 5M IN A 10.0.7.224
+4000.example. 5M IN A 10.0.7.225
+4000.example. 5M IN A 10.0.7.226
+4000.example. 5M IN A 10.0.7.227
+4000.example. 5M IN A 10.0.7.228
+4000.example. 5M IN A 10.0.7.229
+4000.example. 5M IN A 10.0.7.230
+4000.example. 5M IN A 10.0.7.231
+4000.example. 5M IN A 10.0.7.232
+4000.example. 5M IN A 10.0.7.233
+4000.example. 5M IN A 10.0.7.234
+4000.example. 5M IN A 10.0.7.235
+4000.example. 5M IN A 10.0.7.236
+4000.example. 5M IN A 10.0.7.237
+4000.example. 5M IN A 10.0.7.238
+4000.example. 5M IN A 10.0.7.239
+4000.example. 5M IN A 10.0.7.240
+4000.example. 5M IN A 10.0.7.241
+4000.example. 5M IN A 10.0.7.242
+4000.example. 5M IN A 10.0.7.243
+4000.example. 5M IN A 10.0.7.244
+4000.example. 5M IN A 10.0.7.245
+4000.example. 5M IN A 10.0.7.246
+4000.example. 5M IN A 10.0.7.247
+4000.example. 5M IN A 10.0.7.248
+4000.example. 5M IN A 10.0.7.249
+4000.example. 5M IN A 10.0.7.250
+4000.example. 5M IN A 10.0.7.251
+4000.example. 5M IN A 10.0.7.252
+4000.example. 5M IN A 10.0.7.253
+4000.example. 5M IN A 10.0.7.254
+4000.example. 5M IN A 10.0.7.255
+4000.example. 5M IN A 10.0.8.0
+4000.example. 5M IN A 10.0.8.1
+4000.example. 5M IN A 10.0.8.2
+4000.example. 5M IN A 10.0.8.3
+4000.example. 5M IN A 10.0.8.4
+4000.example. 5M IN A 10.0.8.5
+4000.example. 5M IN A 10.0.8.6
+4000.example. 5M IN A 10.0.8.7
+4000.example. 5M IN A 10.0.8.8
+4000.example. 5M IN A 10.0.8.9
+4000.example. 5M IN A 10.0.8.10
+4000.example. 5M IN A 10.0.8.11
+4000.example. 5M IN A 10.0.8.12
+4000.example. 5M IN A 10.0.8.13
+4000.example. 5M IN A 10.0.8.14
+4000.example. 5M IN A 10.0.8.15
+4000.example. 5M IN A 10.0.8.16
+4000.example. 5M IN A 10.0.8.17
+4000.example. 5M IN A 10.0.8.18
+4000.example. 5M IN A 10.0.8.19
+4000.example. 5M IN A 10.0.8.20
+4000.example. 5M IN A 10.0.8.21
+4000.example. 5M IN A 10.0.8.22
+4000.example. 5M IN A 10.0.8.23
+4000.example. 5M IN A 10.0.8.24
+4000.example. 5M IN A 10.0.8.25
+4000.example. 5M IN A 10.0.8.26
+4000.example. 5M IN A 10.0.8.27
+4000.example. 5M IN A 10.0.8.28
+4000.example. 5M IN A 10.0.8.29
+4000.example. 5M IN A 10.0.8.30
+4000.example. 5M IN A 10.0.8.31
+4000.example. 5M IN A 10.0.8.32
+4000.example. 5M IN A 10.0.8.33
+4000.example. 5M IN A 10.0.8.34
+4000.example. 5M IN A 10.0.8.35
+4000.example. 5M IN A 10.0.8.36
+4000.example. 5M IN A 10.0.8.37
+4000.example. 5M IN A 10.0.8.38
+4000.example. 5M IN A 10.0.8.39
+4000.example. 5M IN A 10.0.8.40
+4000.example. 5M IN A 10.0.8.41
+4000.example. 5M IN A 10.0.8.42
+4000.example. 5M IN A 10.0.8.43
+4000.example. 5M IN A 10.0.8.44
+4000.example. 5M IN A 10.0.8.45
+4000.example. 5M IN A 10.0.8.46
+4000.example. 5M IN A 10.0.8.47
+4000.example. 5M IN A 10.0.8.48
+4000.example. 5M IN A 10.0.8.49
+4000.example. 5M IN A 10.0.8.50
+4000.example. 5M IN A 10.0.8.51
+4000.example. 5M IN A 10.0.8.52
+4000.example. 5M IN A 10.0.8.53
+4000.example. 5M IN A 10.0.8.54
+4000.example. 5M IN A 10.0.8.55
+4000.example. 5M IN A 10.0.8.56
+4000.example. 5M IN A 10.0.8.57
+4000.example. 5M IN A 10.0.8.58
+4000.example. 5M IN A 10.0.8.59
+4000.example. 5M IN A 10.0.8.60
+4000.example. 5M IN A 10.0.8.61
+4000.example. 5M IN A 10.0.8.62
+4000.example. 5M IN A 10.0.8.63
+4000.example. 5M IN A 10.0.8.64
+4000.example. 5M IN A 10.0.8.65
+4000.example. 5M IN A 10.0.8.66
+4000.example. 5M IN A 10.0.8.67
+4000.example. 5M IN A 10.0.8.68
+4000.example. 5M IN A 10.0.8.69
+4000.example. 5M IN A 10.0.8.70
+4000.example. 5M IN A 10.0.8.71
+4000.example. 5M IN A 10.0.8.72
+4000.example. 5M IN A 10.0.8.73
+4000.example. 5M IN A 10.0.8.74
+4000.example. 5M IN A 10.0.8.75
+4000.example. 5M IN A 10.0.8.76
+4000.example. 5M IN A 10.0.8.77
+4000.example. 5M IN A 10.0.8.78
+4000.example. 5M IN A 10.0.8.79
+4000.example. 5M IN A 10.0.8.80
+4000.example. 5M IN A 10.0.8.81
+4000.example. 5M IN A 10.0.8.82
+4000.example. 5M IN A 10.0.8.83
+4000.example. 5M IN A 10.0.8.84
+4000.example. 5M IN A 10.0.8.85
+4000.example. 5M IN A 10.0.8.86
+4000.example. 5M IN A 10.0.8.87
+4000.example. 5M IN A 10.0.8.88
+4000.example. 5M IN A 10.0.8.89
+4000.example. 5M IN A 10.0.8.90
+4000.example. 5M IN A 10.0.8.91
+4000.example. 5M IN A 10.0.8.92
+4000.example. 5M IN A 10.0.8.93
+4000.example. 5M IN A 10.0.8.94
+4000.example. 5M IN A 10.0.8.95
+4000.example. 5M IN A 10.0.8.96
+4000.example. 5M IN A 10.0.8.97
+4000.example. 5M IN A 10.0.8.98
+4000.example. 5M IN A 10.0.8.99
+4000.example. 5M IN A 10.0.8.100
+4000.example. 5M IN A 10.0.8.101
+4000.example. 5M IN A 10.0.8.102
+4000.example. 5M IN A 10.0.8.103
+4000.example. 5M IN A 10.0.8.104
+4000.example. 5M IN A 10.0.8.105
+4000.example. 5M IN A 10.0.8.106
+4000.example. 5M IN A 10.0.8.107
+4000.example. 5M IN A 10.0.8.108
+4000.example. 5M IN A 10.0.8.109
+4000.example. 5M IN A 10.0.8.110
+4000.example. 5M IN A 10.0.8.111
+4000.example. 5M IN A 10.0.8.112
+4000.example. 5M IN A 10.0.8.113
+4000.example. 5M IN A 10.0.8.114
+4000.example. 5M IN A 10.0.8.115
+4000.example. 5M IN A 10.0.8.116
+4000.example. 5M IN A 10.0.8.117
+4000.example. 5M IN A 10.0.8.118
+4000.example. 5M IN A 10.0.8.119
+4000.example. 5M IN A 10.0.8.120
+4000.example. 5M IN A 10.0.8.121
+4000.example. 5M IN A 10.0.8.122
+4000.example. 5M IN A 10.0.8.123
+4000.example. 5M IN A 10.0.8.124
+4000.example. 5M IN A 10.0.8.125
+4000.example. 5M IN A 10.0.8.126
+4000.example. 5M IN A 10.0.8.127
+4000.example. 5M IN A 10.0.8.128
+4000.example. 5M IN A 10.0.8.129
+4000.example. 5M IN A 10.0.8.130
+4000.example. 5M IN A 10.0.8.131
+4000.example. 5M IN A 10.0.8.132
+4000.example. 5M IN A 10.0.8.133
+4000.example. 5M IN A 10.0.8.134
+4000.example. 5M IN A 10.0.8.135
+4000.example. 5M IN A 10.0.8.136
+4000.example. 5M IN A 10.0.8.137
+4000.example. 5M IN A 10.0.8.138
+4000.example. 5M IN A 10.0.8.139
+4000.example. 5M IN A 10.0.8.140
+4000.example. 5M IN A 10.0.8.141
+4000.example. 5M IN A 10.0.8.142
+4000.example. 5M IN A 10.0.8.143
+4000.example. 5M IN A 10.0.8.144
+4000.example. 5M IN A 10.0.8.145
+4000.example. 5M IN A 10.0.8.146
+4000.example. 5M IN A 10.0.8.147
+4000.example. 5M IN A 10.0.8.148
+4000.example. 5M IN A 10.0.8.149
+4000.example. 5M IN A 10.0.8.150
+4000.example. 5M IN A 10.0.8.151
+4000.example. 5M IN A 10.0.8.152
+4000.example. 5M IN A 10.0.8.153
+4000.example. 5M IN A 10.0.8.154
+4000.example. 5M IN A 10.0.8.155
+4000.example. 5M IN A 10.0.8.156
+4000.example. 5M IN A 10.0.8.157
+4000.example. 5M IN A 10.0.8.158
+4000.example. 5M IN A 10.0.8.159
+4000.example. 5M IN A 10.0.8.160
+4000.example. 5M IN A 10.0.8.161
+4000.example. 5M IN A 10.0.8.162
+4000.example. 5M IN A 10.0.8.163
+4000.example. 5M IN A 10.0.8.164
+4000.example. 5M IN A 10.0.8.165
+4000.example. 5M IN A 10.0.8.166
+4000.example. 5M IN A 10.0.8.167
+4000.example. 5M IN A 10.0.8.168
+4000.example. 5M IN A 10.0.8.169
+4000.example. 5M IN A 10.0.8.170
+4000.example. 5M IN A 10.0.8.171
+4000.example. 5M IN A 10.0.8.172
+4000.example. 5M IN A 10.0.8.173
+4000.example. 5M IN A 10.0.8.174
+4000.example. 5M IN A 10.0.8.175
+4000.example. 5M IN A 10.0.8.176
+4000.example. 5M IN A 10.0.8.177
+4000.example. 5M IN A 10.0.8.178
+4000.example. 5M IN A 10.0.8.179
+4000.example. 5M IN A 10.0.8.180
+4000.example. 5M IN A 10.0.8.181
+4000.example. 5M IN A 10.0.8.182
+4000.example. 5M IN A 10.0.8.183
+4000.example. 5M IN A 10.0.8.184
+4000.example. 5M IN A 10.0.8.185
+4000.example. 5M IN A 10.0.8.186
+4000.example. 5M IN A 10.0.8.187
+4000.example. 5M IN A 10.0.8.188
+4000.example. 5M IN A 10.0.8.189
+4000.example. 5M IN A 10.0.8.190
+4000.example. 5M IN A 10.0.8.191
+4000.example. 5M IN A 10.0.8.192
+4000.example. 5M IN A 10.0.8.193
+4000.example. 5M IN A 10.0.8.194
+4000.example. 5M IN A 10.0.8.195
+4000.example. 5M IN A 10.0.8.196
+4000.example. 5M IN A 10.0.8.197
+4000.example. 5M IN A 10.0.8.198
+4000.example. 5M IN A 10.0.8.199
+4000.example. 5M IN A 10.0.8.200
+4000.example. 5M IN A 10.0.8.201
+4000.example. 5M IN A 10.0.8.202
+4000.example. 5M IN A 10.0.8.203
+4000.example. 5M IN A 10.0.8.204
+4000.example. 5M IN A 10.0.8.205
+4000.example. 5M IN A 10.0.8.206
+4000.example. 5M IN A 10.0.8.207
+4000.example. 5M IN A 10.0.8.208
+4000.example. 5M IN A 10.0.8.209
+4000.example. 5M IN A 10.0.8.210
+4000.example. 5M IN A 10.0.8.211
+4000.example. 5M IN A 10.0.8.212
+4000.example. 5M IN A 10.0.8.213
+4000.example. 5M IN A 10.0.8.214
+4000.example. 5M IN A 10.0.8.215
+4000.example. 5M IN A 10.0.8.216
+4000.example. 5M IN A 10.0.8.217
+4000.example. 5M IN A 10.0.8.218
+4000.example. 5M IN A 10.0.8.219
+4000.example. 5M IN A 10.0.8.220
+4000.example. 5M IN A 10.0.8.221
+4000.example. 5M IN A 10.0.8.222
+4000.example. 5M IN A 10.0.8.223
+4000.example. 5M IN A 10.0.8.224
+4000.example. 5M IN A 10.0.8.225
+4000.example. 5M IN A 10.0.8.226
+4000.example. 5M IN A 10.0.8.227
+4000.example. 5M IN A 10.0.8.228
+4000.example. 5M IN A 10.0.8.229
+4000.example. 5M IN A 10.0.8.230
+4000.example. 5M IN A 10.0.8.231
+4000.example. 5M IN A 10.0.8.232
+4000.example. 5M IN A 10.0.8.233
+4000.example. 5M IN A 10.0.8.234
+4000.example. 5M IN A 10.0.8.235
+4000.example. 5M IN A 10.0.8.236
+4000.example. 5M IN A 10.0.8.237
+4000.example. 5M IN A 10.0.8.238
+4000.example. 5M IN A 10.0.8.239
+4000.example. 5M IN A 10.0.8.240
+4000.example. 5M IN A 10.0.8.241
+4000.example. 5M IN A 10.0.8.242
+4000.example. 5M IN A 10.0.8.243
+4000.example. 5M IN A 10.0.8.244
+4000.example. 5M IN A 10.0.8.245
+4000.example. 5M IN A 10.0.8.246
+4000.example. 5M IN A 10.0.8.247
+4000.example. 5M IN A 10.0.8.248
+4000.example. 5M IN A 10.0.8.249
+4000.example. 5M IN A 10.0.8.250
+4000.example. 5M IN A 10.0.8.251
+4000.example. 5M IN A 10.0.8.252
+4000.example. 5M IN A 10.0.8.253
+4000.example. 5M IN A 10.0.8.254
+4000.example. 5M IN A 10.0.8.255
+4000.example. 5M IN A 10.0.9.0
+4000.example. 5M IN A 10.0.9.1
+4000.example. 5M IN A 10.0.9.2
+4000.example. 5M IN A 10.0.9.3
+4000.example. 5M IN A 10.0.9.4
+4000.example. 5M IN A 10.0.9.5
+4000.example. 5M IN A 10.0.9.6
+4000.example. 5M IN A 10.0.9.7
+4000.example. 5M IN A 10.0.9.8
+4000.example. 5M IN A 10.0.9.9
+4000.example. 5M IN A 10.0.9.10
+4000.example. 5M IN A 10.0.9.11
+4000.example. 5M IN A 10.0.9.12
+4000.example. 5M IN A 10.0.9.13
+4000.example. 5M IN A 10.0.9.14
+4000.example. 5M IN A 10.0.9.15
+4000.example. 5M IN A 10.0.9.16
+4000.example. 5M IN A 10.0.9.17
+4000.example. 5M IN A 10.0.9.18
+4000.example. 5M IN A 10.0.9.19
+4000.example. 5M IN A 10.0.9.20
+4000.example. 5M IN A 10.0.9.21
+4000.example. 5M IN A 10.0.9.22
+4000.example. 5M IN A 10.0.9.23
+4000.example. 5M IN A 10.0.9.24
+4000.example. 5M IN A 10.0.9.25
+4000.example. 5M IN A 10.0.9.26
+4000.example. 5M IN A 10.0.9.27
+4000.example. 5M IN A 10.0.9.28
+4000.example. 5M IN A 10.0.9.29
+4000.example. 5M IN A 10.0.9.30
+4000.example. 5M IN A 10.0.9.31
+4000.example. 5M IN A 10.0.9.32
+4000.example. 5M IN A 10.0.9.33
+4000.example. 5M IN A 10.0.9.34
+4000.example. 5M IN A 10.0.9.35
+4000.example. 5M IN A 10.0.9.36
+4000.example. 5M IN A 10.0.9.37
+4000.example. 5M IN A 10.0.9.38
+4000.example. 5M IN A 10.0.9.39
+4000.example. 5M IN A 10.0.9.40
+4000.example. 5M IN A 10.0.9.41
+4000.example. 5M IN A 10.0.9.42
+4000.example. 5M IN A 10.0.9.43
+4000.example. 5M IN A 10.0.9.44
+4000.example. 5M IN A 10.0.9.45
+4000.example. 5M IN A 10.0.9.46
+4000.example. 5M IN A 10.0.9.47
+4000.example. 5M IN A 10.0.9.48
+4000.example. 5M IN A 10.0.9.49
+4000.example. 5M IN A 10.0.9.50
+4000.example. 5M IN A 10.0.9.51
+4000.example. 5M IN A 10.0.9.52
+4000.example. 5M IN A 10.0.9.53
+4000.example. 5M IN A 10.0.9.54
+4000.example. 5M IN A 10.0.9.55
+4000.example. 5M IN A 10.0.9.56
+4000.example. 5M IN A 10.0.9.57
+4000.example. 5M IN A 10.0.9.58
+4000.example. 5M IN A 10.0.9.59
+4000.example. 5M IN A 10.0.9.60
+4000.example. 5M IN A 10.0.9.61
+4000.example. 5M IN A 10.0.9.62
+4000.example. 5M IN A 10.0.9.63
+4000.example. 5M IN A 10.0.9.64
+4000.example. 5M IN A 10.0.9.65
+4000.example. 5M IN A 10.0.9.66
+4000.example. 5M IN A 10.0.9.67
+4000.example. 5M IN A 10.0.9.68
+4000.example. 5M IN A 10.0.9.69
+4000.example. 5M IN A 10.0.9.70
+4000.example. 5M IN A 10.0.9.71
+4000.example. 5M IN A 10.0.9.72
+4000.example. 5M IN A 10.0.9.73
+4000.example. 5M IN A 10.0.9.74
+4000.example. 5M IN A 10.0.9.75
+4000.example. 5M IN A 10.0.9.76
+4000.example. 5M IN A 10.0.9.77
+4000.example. 5M IN A 10.0.9.78
+4000.example. 5M IN A 10.0.9.79
+4000.example. 5M IN A 10.0.9.80
+4000.example. 5M IN A 10.0.9.81
+4000.example. 5M IN A 10.0.9.82
+4000.example. 5M IN A 10.0.9.83
+4000.example. 5M IN A 10.0.9.84
+4000.example. 5M IN A 10.0.9.85
+4000.example. 5M IN A 10.0.9.86
+4000.example. 5M IN A 10.0.9.87
+4000.example. 5M IN A 10.0.9.88
+4000.example. 5M IN A 10.0.9.89
+4000.example. 5M IN A 10.0.9.90
+4000.example. 5M IN A 10.0.9.91
+4000.example. 5M IN A 10.0.9.92
+4000.example. 5M IN A 10.0.9.93
+4000.example. 5M IN A 10.0.9.94
+4000.example. 5M IN A 10.0.9.95
+4000.example. 5M IN A 10.0.9.96
+4000.example. 5M IN A 10.0.9.97
+4000.example. 5M IN A 10.0.9.98
+4000.example. 5M IN A 10.0.9.99
+4000.example. 5M IN A 10.0.9.100
+4000.example. 5M IN A 10.0.9.101
+4000.example. 5M IN A 10.0.9.102
+4000.example. 5M IN A 10.0.9.103
+4000.example. 5M IN A 10.0.9.104
+4000.example. 5M IN A 10.0.9.105
+4000.example. 5M IN A 10.0.9.106
+4000.example. 5M IN A 10.0.9.107
+4000.example. 5M IN A 10.0.9.108
+4000.example. 5M IN A 10.0.9.109
+4000.example. 5M IN A 10.0.9.110
+4000.example. 5M IN A 10.0.9.111
+4000.example. 5M IN A 10.0.9.112
+4000.example. 5M IN A 10.0.9.113
+4000.example. 5M IN A 10.0.9.114
+4000.example. 5M IN A 10.0.9.115
+4000.example. 5M IN A 10.0.9.116
+4000.example. 5M IN A 10.0.9.117
+4000.example. 5M IN A 10.0.9.118
+4000.example. 5M IN A 10.0.9.119
+4000.example. 5M IN A 10.0.9.120
+4000.example. 5M IN A 10.0.9.121
+4000.example. 5M IN A 10.0.9.122
+4000.example. 5M IN A 10.0.9.123
+4000.example. 5M IN A 10.0.9.124
+4000.example. 5M IN A 10.0.9.125
+4000.example. 5M IN A 10.0.9.126
+4000.example. 5M IN A 10.0.9.127
+4000.example. 5M IN A 10.0.9.128
+4000.example. 5M IN A 10.0.9.129
+4000.example. 5M IN A 10.0.9.130
+4000.example. 5M IN A 10.0.9.131
+4000.example. 5M IN A 10.0.9.132
+4000.example. 5M IN A 10.0.9.133
+4000.example. 5M IN A 10.0.9.134
+4000.example. 5M IN A 10.0.9.135
+4000.example. 5M IN A 10.0.9.136
+4000.example. 5M IN A 10.0.9.137
+4000.example. 5M IN A 10.0.9.138
+4000.example. 5M IN A 10.0.9.139
+4000.example. 5M IN A 10.0.9.140
+4000.example. 5M IN A 10.0.9.141
+4000.example. 5M IN A 10.0.9.142
+4000.example. 5M IN A 10.0.9.143
+4000.example. 5M IN A 10.0.9.144
+4000.example. 5M IN A 10.0.9.145
+4000.example. 5M IN A 10.0.9.146
+4000.example. 5M IN A 10.0.9.147
+4000.example. 5M IN A 10.0.9.148
+4000.example. 5M IN A 10.0.9.149
+4000.example. 5M IN A 10.0.9.150
+4000.example. 5M IN A 10.0.9.151
+4000.example. 5M IN A 10.0.9.152
+4000.example. 5M IN A 10.0.9.153
+4000.example. 5M IN A 10.0.9.154
+4000.example. 5M IN A 10.0.9.155
+4000.example. 5M IN A 10.0.9.156
+4000.example. 5M IN A 10.0.9.157
+4000.example. 5M IN A 10.0.9.158
+4000.example. 5M IN A 10.0.9.159
+4000.example. 5M IN A 10.0.9.160
+4000.example. 5M IN A 10.0.9.161
+4000.example. 5M IN A 10.0.9.162
+4000.example. 5M IN A 10.0.9.163
+4000.example. 5M IN A 10.0.9.164
+4000.example. 5M IN A 10.0.9.165
+4000.example. 5M IN A 10.0.9.166
+4000.example. 5M IN A 10.0.9.167
+4000.example. 5M IN A 10.0.9.168
+4000.example. 5M IN A 10.0.9.169
+4000.example. 5M IN A 10.0.9.170
+4000.example. 5M IN A 10.0.9.171
+4000.example. 5M IN A 10.0.9.172
+4000.example. 5M IN A 10.0.9.173
+4000.example. 5M IN A 10.0.9.174
+4000.example. 5M IN A 10.0.9.175
+4000.example. 5M IN A 10.0.9.176
+4000.example. 5M IN A 10.0.9.177
+4000.example. 5M IN A 10.0.9.178
+4000.example. 5M IN A 10.0.9.179
+4000.example. 5M IN A 10.0.9.180
+4000.example. 5M IN A 10.0.9.181
+4000.example. 5M IN A 10.0.9.182
+4000.example. 5M IN A 10.0.9.183
+4000.example. 5M IN A 10.0.9.184
+4000.example. 5M IN A 10.0.9.185
+4000.example. 5M IN A 10.0.9.186
+4000.example. 5M IN A 10.0.9.187
+4000.example. 5M IN A 10.0.9.188
+4000.example. 5M IN A 10.0.9.189
+4000.example. 5M IN A 10.0.9.190
+4000.example. 5M IN A 10.0.9.191
+4000.example. 5M IN A 10.0.9.192
+4000.example. 5M IN A 10.0.9.193
+4000.example. 5M IN A 10.0.9.194
+4000.example. 5M IN A 10.0.9.195
+4000.example. 5M IN A 10.0.9.196
+4000.example. 5M IN A 10.0.9.197
+4000.example. 5M IN A 10.0.9.198
+4000.example. 5M IN A 10.0.9.199
+4000.example. 5M IN A 10.0.9.200
+4000.example. 5M IN A 10.0.9.201
+4000.example. 5M IN A 10.0.9.202
+4000.example. 5M IN A 10.0.9.203
+4000.example. 5M IN A 10.0.9.204
+4000.example. 5M IN A 10.0.9.205
+4000.example. 5M IN A 10.0.9.206
+4000.example. 5M IN A 10.0.9.207
+4000.example. 5M IN A 10.0.9.208
+4000.example. 5M IN A 10.0.9.209
+4000.example. 5M IN A 10.0.9.210
+4000.example. 5M IN A 10.0.9.211
+4000.example. 5M IN A 10.0.9.212
+4000.example. 5M IN A 10.0.9.213
+4000.example. 5M IN A 10.0.9.214
+4000.example. 5M IN A 10.0.9.215
+4000.example. 5M IN A 10.0.9.216
+4000.example. 5M IN A 10.0.9.217
+4000.example. 5M IN A 10.0.9.218
+4000.example. 5M IN A 10.0.9.219
+4000.example. 5M IN A 10.0.9.220
+4000.example. 5M IN A 10.0.9.221
+4000.example. 5M IN A 10.0.9.222
+4000.example. 5M IN A 10.0.9.223
+4000.example. 5M IN A 10.0.9.224
+4000.example. 5M IN A 10.0.9.225
+4000.example. 5M IN A 10.0.9.226
+4000.example. 5M IN A 10.0.9.227
+4000.example. 5M IN A 10.0.9.228
+4000.example. 5M IN A 10.0.9.229
+4000.example. 5M IN A 10.0.9.230
+4000.example. 5M IN A 10.0.9.231
+4000.example. 5M IN A 10.0.9.232
+4000.example. 5M IN A 10.0.9.233
+4000.example. 5M IN A 10.0.9.234
+4000.example. 5M IN A 10.0.9.235
+4000.example. 5M IN A 10.0.9.236
+4000.example. 5M IN A 10.0.9.237
+4000.example. 5M IN A 10.0.9.238
+4000.example. 5M IN A 10.0.9.239
+4000.example. 5M IN A 10.0.9.240
+4000.example. 5M IN A 10.0.9.241
+4000.example. 5M IN A 10.0.9.242
+4000.example. 5M IN A 10.0.9.243
+4000.example. 5M IN A 10.0.9.244
+4000.example. 5M IN A 10.0.9.245
+4000.example. 5M IN A 10.0.9.246
+4000.example. 5M IN A 10.0.9.247
+4000.example. 5M IN A 10.0.9.248
+4000.example. 5M IN A 10.0.9.249
+4000.example. 5M IN A 10.0.9.250
+4000.example. 5M IN A 10.0.9.251
+4000.example. 5M IN A 10.0.9.252
+4000.example. 5M IN A 10.0.9.253
+4000.example. 5M IN A 10.0.9.254
+4000.example. 5M IN A 10.0.9.255
+4000.example. 5M IN A 10.0.10.0
+4000.example. 5M IN A 10.0.10.1
+4000.example. 5M IN A 10.0.10.2
+4000.example. 5M IN A 10.0.10.3
+4000.example. 5M IN A 10.0.10.4
+4000.example. 5M IN A 10.0.10.5
+4000.example. 5M IN A 10.0.10.6
+4000.example. 5M IN A 10.0.10.7
+4000.example. 5M IN A 10.0.10.8
+4000.example. 5M IN A 10.0.10.9
+4000.example. 5M IN A 10.0.10.10
+4000.example. 5M IN A 10.0.10.11
+4000.example. 5M IN A 10.0.10.12
+4000.example. 5M IN A 10.0.10.13
+4000.example. 5M IN A 10.0.10.14
+4000.example. 5M IN A 10.0.10.15
+4000.example. 5M IN A 10.0.10.16
+4000.example. 5M IN A 10.0.10.17
+4000.example. 5M IN A 10.0.10.18
+4000.example. 5M IN A 10.0.10.19
+4000.example. 5M IN A 10.0.10.20
+4000.example. 5M IN A 10.0.10.21
+4000.example. 5M IN A 10.0.10.22
+4000.example. 5M IN A 10.0.10.23
+4000.example. 5M IN A 10.0.10.24
+4000.example. 5M IN A 10.0.10.25
+4000.example. 5M IN A 10.0.10.26
+4000.example. 5M IN A 10.0.10.27
+4000.example. 5M IN A 10.0.10.28
+4000.example. 5M IN A 10.0.10.29
+4000.example. 5M IN A 10.0.10.30
+4000.example. 5M IN A 10.0.10.31
+4000.example. 5M IN A 10.0.10.32
+4000.example. 5M IN A 10.0.10.33
+4000.example. 5M IN A 10.0.10.34
+4000.example. 5M IN A 10.0.10.35
+4000.example. 5M IN A 10.0.10.36
+4000.example. 5M IN A 10.0.10.37
+4000.example. 5M IN A 10.0.10.38
+4000.example. 5M IN A 10.0.10.39
+4000.example. 5M IN A 10.0.10.40
+4000.example. 5M IN A 10.0.10.41
+4000.example. 5M IN A 10.0.10.42
+4000.example. 5M IN A 10.0.10.43
+4000.example. 5M IN A 10.0.10.44
+4000.example. 5M IN A 10.0.10.45
+4000.example. 5M IN A 10.0.10.46
+4000.example. 5M IN A 10.0.10.47
+4000.example. 5M IN A 10.0.10.48
+4000.example. 5M IN A 10.0.10.49
+4000.example. 5M IN A 10.0.10.50
+4000.example. 5M IN A 10.0.10.51
+4000.example. 5M IN A 10.0.10.52
+4000.example. 5M IN A 10.0.10.53
+4000.example. 5M IN A 10.0.10.54
+4000.example. 5M IN A 10.0.10.55
+4000.example. 5M IN A 10.0.10.56
+4000.example. 5M IN A 10.0.10.57
+4000.example. 5M IN A 10.0.10.58
+4000.example. 5M IN A 10.0.10.59
+4000.example. 5M IN A 10.0.10.60
+4000.example. 5M IN A 10.0.10.61
+4000.example. 5M IN A 10.0.10.62
+4000.example. 5M IN A 10.0.10.63
+4000.example. 5M IN A 10.0.10.64
+4000.example. 5M IN A 10.0.10.65
+4000.example. 5M IN A 10.0.10.66
+4000.example. 5M IN A 10.0.10.67
+4000.example. 5M IN A 10.0.10.68
+4000.example. 5M IN A 10.0.10.69
+4000.example. 5M IN A 10.0.10.70
+4000.example. 5M IN A 10.0.10.71
+4000.example. 5M IN A 10.0.10.72
+4000.example. 5M IN A 10.0.10.73
+4000.example. 5M IN A 10.0.10.74
+4000.example. 5M IN A 10.0.10.75
+4000.example. 5M IN A 10.0.10.76
+4000.example. 5M IN A 10.0.10.77
+4000.example. 5M IN A 10.0.10.78
+4000.example. 5M IN A 10.0.10.79
+4000.example. 5M IN A 10.0.10.80
+4000.example. 5M IN A 10.0.10.81
+4000.example. 5M IN A 10.0.10.82
+4000.example. 5M IN A 10.0.10.83
+4000.example. 5M IN A 10.0.10.84
+4000.example. 5M IN A 10.0.10.85
+4000.example. 5M IN A 10.0.10.86
+4000.example. 5M IN A 10.0.10.87
+4000.example. 5M IN A 10.0.10.88
+4000.example. 5M IN A 10.0.10.89
+4000.example. 5M IN A 10.0.10.90
+4000.example. 5M IN A 10.0.10.91
+4000.example. 5M IN A 10.0.10.92
+4000.example. 5M IN A 10.0.10.93
+4000.example. 5M IN A 10.0.10.94
+4000.example. 5M IN A 10.0.10.95
+4000.example. 5M IN A 10.0.10.96
+4000.example. 5M IN A 10.0.10.97
+4000.example. 5M IN A 10.0.10.98
+4000.example. 5M IN A 10.0.10.99
+4000.example. 5M IN A 10.0.10.100
+4000.example. 5M IN A 10.0.10.101
+4000.example. 5M IN A 10.0.10.102
+4000.example. 5M IN A 10.0.10.103
+4000.example. 5M IN A 10.0.10.104
+4000.example. 5M IN A 10.0.10.105
+4000.example. 5M IN A 10.0.10.106
+4000.example. 5M IN A 10.0.10.107
+4000.example. 5M IN A 10.0.10.108
+4000.example. 5M IN A 10.0.10.109
+4000.example. 5M IN A 10.0.10.110
+4000.example. 5M IN A 10.0.10.111
+4000.example. 5M IN A 10.0.10.112
+4000.example. 5M IN A 10.0.10.113
+4000.example. 5M IN A 10.0.10.114
+4000.example. 5M IN A 10.0.10.115
+4000.example. 5M IN A 10.0.10.116
+4000.example. 5M IN A 10.0.10.117
+4000.example. 5M IN A 10.0.10.118
+4000.example. 5M IN A 10.0.10.119
+4000.example. 5M IN A 10.0.10.120
+4000.example. 5M IN A 10.0.10.121
+4000.example. 5M IN A 10.0.10.122
+4000.example. 5M IN A 10.0.10.123
+4000.example. 5M IN A 10.0.10.124
+4000.example. 5M IN A 10.0.10.125
+4000.example. 5M IN A 10.0.10.126
+4000.example. 5M IN A 10.0.10.127
+4000.example. 5M IN A 10.0.10.128
+4000.example. 5M IN A 10.0.10.129
+4000.example. 5M IN A 10.0.10.130
+4000.example. 5M IN A 10.0.10.131
+4000.example. 5M IN A 10.0.10.132
+4000.example. 5M IN A 10.0.10.133
+4000.example. 5M IN A 10.0.10.134
+4000.example. 5M IN A 10.0.10.135
+4000.example. 5M IN A 10.0.10.136
+4000.example. 5M IN A 10.0.10.137
+4000.example. 5M IN A 10.0.10.138
+4000.example. 5M IN A 10.0.10.139
+4000.example. 5M IN A 10.0.10.140
+4000.example. 5M IN A 10.0.10.141
+4000.example. 5M IN A 10.0.10.142
+4000.example. 5M IN A 10.0.10.143
+4000.example. 5M IN A 10.0.10.144
+4000.example. 5M IN A 10.0.10.145
+4000.example. 5M IN A 10.0.10.146
+4000.example. 5M IN A 10.0.10.147
+4000.example. 5M IN A 10.0.10.148
+4000.example. 5M IN A 10.0.10.149
+4000.example. 5M IN A 10.0.10.150
+4000.example. 5M IN A 10.0.10.151
+4000.example. 5M IN A 10.0.10.152
+4000.example. 5M IN A 10.0.10.153
+4000.example. 5M IN A 10.0.10.154
+4000.example. 5M IN A 10.0.10.155
+4000.example. 5M IN A 10.0.10.156
+4000.example. 5M IN A 10.0.10.157
+4000.example. 5M IN A 10.0.10.158
+4000.example. 5M IN A 10.0.10.159
+4000.example. 5M IN A 10.0.10.160
+4000.example. 5M IN A 10.0.10.161
+4000.example. 5M IN A 10.0.10.162
+4000.example. 5M IN A 10.0.10.163
+4000.example. 5M IN A 10.0.10.164
+4000.example. 5M IN A 10.0.10.165
+4000.example. 5M IN A 10.0.10.166
+4000.example. 5M IN A 10.0.10.167
+4000.example. 5M IN A 10.0.10.168
+4000.example. 5M IN A 10.0.10.169
+4000.example. 5M IN A 10.0.10.170
+4000.example. 5M IN A 10.0.10.171
+4000.example. 5M IN A 10.0.10.172
+4000.example. 5M IN A 10.0.10.173
+4000.example. 5M IN A 10.0.10.174
+4000.example. 5M IN A 10.0.10.175
+4000.example. 5M IN A 10.0.10.176
+4000.example. 5M IN A 10.0.10.177
+4000.example. 5M IN A 10.0.10.178
+4000.example. 5M IN A 10.0.10.179
+4000.example. 5M IN A 10.0.10.180
+4000.example. 5M IN A 10.0.10.181
+4000.example. 5M IN A 10.0.10.182
+4000.example. 5M IN A 10.0.10.183
+4000.example. 5M IN A 10.0.10.184
+4000.example. 5M IN A 10.0.10.185
+4000.example. 5M IN A 10.0.10.186
+4000.example. 5M IN A 10.0.10.187
+4000.example. 5M IN A 10.0.10.188
+4000.example. 5M IN A 10.0.10.189
+4000.example. 5M IN A 10.0.10.190
+4000.example. 5M IN A 10.0.10.191
+4000.example. 5M IN A 10.0.10.192
+4000.example. 5M IN A 10.0.10.193
+4000.example. 5M IN A 10.0.10.194
+4000.example. 5M IN A 10.0.10.195
+4000.example. 5M IN A 10.0.10.196
+4000.example. 5M IN A 10.0.10.197
+4000.example. 5M IN A 10.0.10.198
+4000.example. 5M IN A 10.0.10.199
+4000.example. 5M IN A 10.0.10.200
+4000.example. 5M IN A 10.0.10.201
+4000.example. 5M IN A 10.0.10.202
+4000.example. 5M IN A 10.0.10.203
+4000.example. 5M IN A 10.0.10.204
+4000.example. 5M IN A 10.0.10.205
+4000.example. 5M IN A 10.0.10.206
+4000.example. 5M IN A 10.0.10.207
+4000.example. 5M IN A 10.0.10.208
+4000.example. 5M IN A 10.0.10.209
+4000.example. 5M IN A 10.0.10.210
+4000.example. 5M IN A 10.0.10.211
+4000.example. 5M IN A 10.0.10.212
+4000.example. 5M IN A 10.0.10.213
+4000.example. 5M IN A 10.0.10.214
+4000.example. 5M IN A 10.0.10.215
+4000.example. 5M IN A 10.0.10.216
+4000.example. 5M IN A 10.0.10.217
+4000.example. 5M IN A 10.0.10.218
+4000.example. 5M IN A 10.0.10.219
+4000.example. 5M IN A 10.0.10.220
+4000.example. 5M IN A 10.0.10.221
+4000.example. 5M IN A 10.0.10.222
+4000.example. 5M IN A 10.0.10.223
+4000.example. 5M IN A 10.0.10.224
+4000.example. 5M IN A 10.0.10.225
+4000.example. 5M IN A 10.0.10.226
+4000.example. 5M IN A 10.0.10.227
+4000.example. 5M IN A 10.0.10.228
+4000.example. 5M IN A 10.0.10.229
+4000.example. 5M IN A 10.0.10.230
+4000.example. 5M IN A 10.0.10.231
+4000.example. 5M IN A 10.0.10.232
+4000.example. 5M IN A 10.0.10.233
+4000.example. 5M IN A 10.0.10.234
+4000.example. 5M IN A 10.0.10.235
+4000.example. 5M IN A 10.0.10.236
+4000.example. 5M IN A 10.0.10.237
+4000.example. 5M IN A 10.0.10.238
+4000.example. 5M IN A 10.0.10.239
+4000.example. 5M IN A 10.0.10.240
+4000.example. 5M IN A 10.0.10.241
+4000.example. 5M IN A 10.0.10.242
+4000.example. 5M IN A 10.0.10.243
+4000.example. 5M IN A 10.0.10.244
+4000.example. 5M IN A 10.0.10.245
+4000.example. 5M IN A 10.0.10.246
+4000.example. 5M IN A 10.0.10.247
+4000.example. 5M IN A 10.0.10.248
+4000.example. 5M IN A 10.0.10.249
+4000.example. 5M IN A 10.0.10.250
+4000.example. 5M IN A 10.0.10.251
+4000.example. 5M IN A 10.0.10.252
+4000.example. 5M IN A 10.0.10.253
+4000.example. 5M IN A 10.0.10.254
+4000.example. 5M IN A 10.0.10.255
+4000.example. 5M IN A 10.0.11.0
+4000.example. 5M IN A 10.0.11.1
+4000.example. 5M IN A 10.0.11.2
+4000.example. 5M IN A 10.0.11.3
+4000.example. 5M IN A 10.0.11.4
+4000.example. 5M IN A 10.0.11.5
+4000.example. 5M IN A 10.0.11.6
+4000.example. 5M IN A 10.0.11.7
+4000.example. 5M IN A 10.0.11.8
+4000.example. 5M IN A 10.0.11.9
+4000.example. 5M IN A 10.0.11.10
+4000.example. 5M IN A 10.0.11.11
+4000.example. 5M IN A 10.0.11.12
+4000.example. 5M IN A 10.0.11.13
+4000.example. 5M IN A 10.0.11.14
+4000.example. 5M IN A 10.0.11.15
+4000.example. 5M IN A 10.0.11.16
+4000.example. 5M IN A 10.0.11.17
+4000.example. 5M IN A 10.0.11.18
+4000.example. 5M IN A 10.0.11.19
+4000.example. 5M IN A 10.0.11.20
+4000.example. 5M IN A 10.0.11.21
+4000.example. 5M IN A 10.0.11.22
+4000.example. 5M IN A 10.0.11.23
+4000.example. 5M IN A 10.0.11.24
+4000.example. 5M IN A 10.0.11.25
+4000.example. 5M IN A 10.0.11.26
+4000.example. 5M IN A 10.0.11.27
+4000.example. 5M IN A 10.0.11.28
+4000.example. 5M IN A 10.0.11.29
+4000.example. 5M IN A 10.0.11.30
+4000.example. 5M IN A 10.0.11.31
+4000.example. 5M IN A 10.0.11.32
+4000.example. 5M IN A 10.0.11.33
+4000.example. 5M IN A 10.0.11.34
+4000.example. 5M IN A 10.0.11.35
+4000.example. 5M IN A 10.0.11.36
+4000.example. 5M IN A 10.0.11.37
+4000.example. 5M IN A 10.0.11.38
+4000.example. 5M IN A 10.0.11.39
+4000.example. 5M IN A 10.0.11.40
+4000.example. 5M IN A 10.0.11.41
+4000.example. 5M IN A 10.0.11.42
+4000.example. 5M IN A 10.0.11.43
+4000.example. 5M IN A 10.0.11.44
+4000.example. 5M IN A 10.0.11.45
+4000.example. 5M IN A 10.0.11.46
+4000.example. 5M IN A 10.0.11.47
+4000.example. 5M IN A 10.0.11.48
+4000.example. 5M IN A 10.0.11.49
+4000.example. 5M IN A 10.0.11.50
+4000.example. 5M IN A 10.0.11.51
+4000.example. 5M IN A 10.0.11.52
+4000.example. 5M IN A 10.0.11.53
+4000.example. 5M IN A 10.0.11.54
+4000.example. 5M IN A 10.0.11.55
+4000.example. 5M IN A 10.0.11.56
+4000.example. 5M IN A 10.0.11.57
+4000.example. 5M IN A 10.0.11.58
+4000.example. 5M IN A 10.0.11.59
+4000.example. 5M IN A 10.0.11.60
+4000.example. 5M IN A 10.0.11.61
+4000.example. 5M IN A 10.0.11.62
+4000.example. 5M IN A 10.0.11.63
+4000.example. 5M IN A 10.0.11.64
+4000.example. 5M IN A 10.0.11.65
+4000.example. 5M IN A 10.0.11.66
+4000.example. 5M IN A 10.0.11.67
+4000.example. 5M IN A 10.0.11.68
+4000.example. 5M IN A 10.0.11.69
+4000.example. 5M IN A 10.0.11.70
+4000.example. 5M IN A 10.0.11.71
+4000.example. 5M IN A 10.0.11.72
+4000.example. 5M IN A 10.0.11.73
+4000.example. 5M IN A 10.0.11.74
+4000.example. 5M IN A 10.0.11.75
+4000.example. 5M IN A 10.0.11.76
+4000.example. 5M IN A 10.0.11.77
+4000.example. 5M IN A 10.0.11.78
+4000.example. 5M IN A 10.0.11.79
+4000.example. 5M IN A 10.0.11.80
+4000.example. 5M IN A 10.0.11.81
+4000.example. 5M IN A 10.0.11.82
+4000.example. 5M IN A 10.0.11.83
+4000.example. 5M IN A 10.0.11.84
+4000.example. 5M IN A 10.0.11.85
+4000.example. 5M IN A 10.0.11.86
+4000.example. 5M IN A 10.0.11.87
+4000.example. 5M IN A 10.0.11.88
+4000.example. 5M IN A 10.0.11.89
+4000.example. 5M IN A 10.0.11.90
+4000.example. 5M IN A 10.0.11.91
+4000.example. 5M IN A 10.0.11.92
+4000.example. 5M IN A 10.0.11.93
+4000.example. 5M IN A 10.0.11.94
+4000.example. 5M IN A 10.0.11.95
+4000.example. 5M IN A 10.0.11.96
+4000.example. 5M IN A 10.0.11.97
+4000.example. 5M IN A 10.0.11.98
+4000.example. 5M IN A 10.0.11.99
+4000.example. 5M IN A 10.0.11.100
+4000.example. 5M IN A 10.0.11.101
+4000.example. 5M IN A 10.0.11.102
+4000.example. 5M IN A 10.0.11.103
+4000.example. 5M IN A 10.0.11.104
+4000.example. 5M IN A 10.0.11.105
+4000.example. 5M IN A 10.0.11.106
+4000.example. 5M IN A 10.0.11.107
+4000.example. 5M IN A 10.0.11.108
+4000.example. 5M IN A 10.0.11.109
+4000.example. 5M IN A 10.0.11.110
+4000.example. 5M IN A 10.0.11.111
+4000.example. 5M IN A 10.0.11.112
+4000.example. 5M IN A 10.0.11.113
+4000.example. 5M IN A 10.0.11.114
+4000.example. 5M IN A 10.0.11.115
+4000.example. 5M IN A 10.0.11.116
+4000.example. 5M IN A 10.0.11.117
+4000.example. 5M IN A 10.0.11.118
+4000.example. 5M IN A 10.0.11.119
+4000.example. 5M IN A 10.0.11.120
+4000.example. 5M IN A 10.0.11.121
+4000.example. 5M IN A 10.0.11.122
+4000.example. 5M IN A 10.0.11.123
+4000.example. 5M IN A 10.0.11.124
+4000.example. 5M IN A 10.0.11.125
+4000.example. 5M IN A 10.0.11.126
+4000.example. 5M IN A 10.0.11.127
+4000.example. 5M IN A 10.0.11.128
+4000.example. 5M IN A 10.0.11.129
+4000.example. 5M IN A 10.0.11.130
+4000.example. 5M IN A 10.0.11.131
+4000.example. 5M IN A 10.0.11.132
+4000.example. 5M IN A 10.0.11.133
+4000.example. 5M IN A 10.0.11.134
+4000.example. 5M IN A 10.0.11.135
+4000.example. 5M IN A 10.0.11.136
+4000.example. 5M IN A 10.0.11.137
+4000.example. 5M IN A 10.0.11.138
+4000.example. 5M IN A 10.0.11.139
+4000.example. 5M IN A 10.0.11.140
+4000.example. 5M IN A 10.0.11.141
+4000.example. 5M IN A 10.0.11.142
+4000.example. 5M IN A 10.0.11.143
+4000.example. 5M IN A 10.0.11.144
+4000.example. 5M IN A 10.0.11.145
+4000.example. 5M IN A 10.0.11.146
+4000.example. 5M IN A 10.0.11.147
+4000.example. 5M IN A 10.0.11.148
+4000.example. 5M IN A 10.0.11.149
+4000.example. 5M IN A 10.0.11.150
+4000.example. 5M IN A 10.0.11.151
+4000.example. 5M IN A 10.0.11.152
+4000.example. 5M IN A 10.0.11.153
+4000.example. 5M IN A 10.0.11.154
+4000.example. 5M IN A 10.0.11.155
+4000.example. 5M IN A 10.0.11.156
+4000.example. 5M IN A 10.0.11.157
+4000.example. 5M IN A 10.0.11.158
+4000.example. 5M IN A 10.0.11.159
+4000.example. 5M IN A 10.0.11.160
+4000.example. 5M IN A 10.0.11.161
+4000.example. 5M IN A 10.0.11.162
+4000.example. 5M IN A 10.0.11.163
+4000.example. 5M IN A 10.0.11.164
+4000.example. 5M IN A 10.0.11.165
+4000.example. 5M IN A 10.0.11.166
+4000.example. 5M IN A 10.0.11.167
+4000.example. 5M IN A 10.0.11.168
+4000.example. 5M IN A 10.0.11.169
+4000.example. 5M IN A 10.0.11.170
+4000.example. 5M IN A 10.0.11.171
+4000.example. 5M IN A 10.0.11.172
+4000.example. 5M IN A 10.0.11.173
+4000.example. 5M IN A 10.0.11.174
+4000.example. 5M IN A 10.0.11.175
+4000.example. 5M IN A 10.0.11.176
+4000.example. 5M IN A 10.0.11.177
+4000.example. 5M IN A 10.0.11.178
+4000.example. 5M IN A 10.0.11.179
+4000.example. 5M IN A 10.0.11.180
+4000.example. 5M IN A 10.0.11.181
+4000.example. 5M IN A 10.0.11.182
+4000.example. 5M IN A 10.0.11.183
+4000.example. 5M IN A 10.0.11.184
+4000.example. 5M IN A 10.0.11.185
+4000.example. 5M IN A 10.0.11.186
+4000.example. 5M IN A 10.0.11.187
+4000.example. 5M IN A 10.0.11.188
+4000.example. 5M IN A 10.0.11.189
+4000.example. 5M IN A 10.0.11.190
+4000.example. 5M IN A 10.0.11.191
+4000.example. 5M IN A 10.0.11.192
+4000.example. 5M IN A 10.0.11.193
+4000.example. 5M IN A 10.0.11.194
+4000.example. 5M IN A 10.0.11.195
+4000.example. 5M IN A 10.0.11.196
+4000.example. 5M IN A 10.0.11.197
+4000.example. 5M IN A 10.0.11.198
+4000.example. 5M IN A 10.0.11.199
+4000.example. 5M IN A 10.0.11.200
+4000.example. 5M IN A 10.0.11.201
+4000.example. 5M IN A 10.0.11.202
+4000.example. 5M IN A 10.0.11.203
+4000.example. 5M IN A 10.0.11.204
+4000.example. 5M IN A 10.0.11.205
+4000.example. 5M IN A 10.0.11.206
+4000.example. 5M IN A 10.0.11.207
+4000.example. 5M IN A 10.0.11.208
+4000.example. 5M IN A 10.0.11.209
+4000.example. 5M IN A 10.0.11.210
+4000.example. 5M IN A 10.0.11.211
+4000.example. 5M IN A 10.0.11.212
+4000.example. 5M IN A 10.0.11.213
+4000.example. 5M IN A 10.0.11.214
+4000.example. 5M IN A 10.0.11.215
+4000.example. 5M IN A 10.0.11.216
+4000.example. 5M IN A 10.0.11.217
+4000.example. 5M IN A 10.0.11.218
+4000.example. 5M IN A 10.0.11.219
+4000.example. 5M IN A 10.0.11.220
+4000.example. 5M IN A 10.0.11.221
+4000.example. 5M IN A 10.0.11.222
+4000.example. 5M IN A 10.0.11.223
+4000.example. 5M IN A 10.0.11.224
+4000.example. 5M IN A 10.0.11.225
+4000.example. 5M IN A 10.0.11.226
+4000.example. 5M IN A 10.0.11.227
+4000.example. 5M IN A 10.0.11.228
+4000.example. 5M IN A 10.0.11.229
+4000.example. 5M IN A 10.0.11.230
+4000.example. 5M IN A 10.0.11.231
+4000.example. 5M IN A 10.0.11.232
+4000.example. 5M IN A 10.0.11.233
+4000.example. 5M IN A 10.0.11.234
+4000.example. 5M IN A 10.0.11.235
+4000.example. 5M IN A 10.0.11.236
+4000.example. 5M IN A 10.0.11.237
+4000.example. 5M IN A 10.0.11.238
+4000.example. 5M IN A 10.0.11.239
+4000.example. 5M IN A 10.0.11.240
+4000.example. 5M IN A 10.0.11.241
+4000.example. 5M IN A 10.0.11.242
+4000.example. 5M IN A 10.0.11.243
+4000.example. 5M IN A 10.0.11.244
+4000.example. 5M IN A 10.0.11.245
+4000.example. 5M IN A 10.0.11.246
+4000.example. 5M IN A 10.0.11.247
+4000.example. 5M IN A 10.0.11.248
+4000.example. 5M IN A 10.0.11.249
+4000.example. 5M IN A 10.0.11.250
+4000.example. 5M IN A 10.0.11.251
+4000.example. 5M IN A 10.0.11.252
+4000.example. 5M IN A 10.0.11.253
+4000.example. 5M IN A 10.0.11.254
+4000.example. 5M IN A 10.0.11.255
+4000.example. 5M IN A 10.0.12.0
+4000.example. 5M IN A 10.0.12.1
+4000.example. 5M IN A 10.0.12.2
+4000.example. 5M IN A 10.0.12.3
+4000.example. 5M IN A 10.0.12.4
+4000.example. 5M IN A 10.0.12.5
+4000.example. 5M IN A 10.0.12.6
+4000.example. 5M IN A 10.0.12.7
+4000.example. 5M IN A 10.0.12.8
+4000.example. 5M IN A 10.0.12.9
+4000.example. 5M IN A 10.0.12.10
+4000.example. 5M IN A 10.0.12.11
+4000.example. 5M IN A 10.0.12.12
+4000.example. 5M IN A 10.0.12.13
+4000.example. 5M IN A 10.0.12.14
+4000.example. 5M IN A 10.0.12.15
+4000.example. 5M IN A 10.0.12.16
+4000.example. 5M IN A 10.0.12.17
+4000.example. 5M IN A 10.0.12.18
+4000.example. 5M IN A 10.0.12.19
+4000.example. 5M IN A 10.0.12.20
+4000.example. 5M IN A 10.0.12.21
+4000.example. 5M IN A 10.0.12.22
+4000.example. 5M IN A 10.0.12.23
+4000.example. 5M IN A 10.0.12.24
+4000.example. 5M IN A 10.0.12.25
+4000.example. 5M IN A 10.0.12.26
+4000.example. 5M IN A 10.0.12.27
+4000.example. 5M IN A 10.0.12.28
+4000.example. 5M IN A 10.0.12.29
+4000.example. 5M IN A 10.0.12.30
+4000.example. 5M IN A 10.0.12.31
+4000.example. 5M IN A 10.0.12.32
+4000.example. 5M IN A 10.0.12.33
+4000.example. 5M IN A 10.0.12.34
+4000.example. 5M IN A 10.0.12.35
+4000.example. 5M IN A 10.0.12.36
+4000.example. 5M IN A 10.0.12.37
+4000.example. 5M IN A 10.0.12.38
+4000.example. 5M IN A 10.0.12.39
+4000.example. 5M IN A 10.0.12.40
+4000.example. 5M IN A 10.0.12.41
+4000.example. 5M IN A 10.0.12.42
+4000.example. 5M IN A 10.0.12.43
+4000.example. 5M IN A 10.0.12.44
+4000.example. 5M IN A 10.0.12.45
+4000.example. 5M IN A 10.0.12.46
+4000.example. 5M IN A 10.0.12.47
+4000.example. 5M IN A 10.0.12.48
+4000.example. 5M IN A 10.0.12.49
+4000.example. 5M IN A 10.0.12.50
+4000.example. 5M IN A 10.0.12.51
+4000.example. 5M IN A 10.0.12.52
+4000.example. 5M IN A 10.0.12.53
+4000.example. 5M IN A 10.0.12.54
+4000.example. 5M IN A 10.0.12.55
+4000.example. 5M IN A 10.0.12.56
+4000.example. 5M IN A 10.0.12.57
+4000.example. 5M IN A 10.0.12.58
+4000.example. 5M IN A 10.0.12.59
+4000.example. 5M IN A 10.0.12.60
+4000.example. 5M IN A 10.0.12.61
+4000.example. 5M IN A 10.0.12.62
+4000.example. 5M IN A 10.0.12.63
+4000.example. 5M IN A 10.0.12.64
+4000.example. 5M IN A 10.0.12.65
+4000.example. 5M IN A 10.0.12.66
+4000.example. 5M IN A 10.0.12.67
+4000.example. 5M IN A 10.0.12.68
+4000.example. 5M IN A 10.0.12.69
+4000.example. 5M IN A 10.0.12.70
+4000.example. 5M IN A 10.0.12.71
+4000.example. 5M IN A 10.0.12.72
+4000.example. 5M IN A 10.0.12.73
+4000.example. 5M IN A 10.0.12.74
+4000.example. 5M IN A 10.0.12.75
+4000.example. 5M IN A 10.0.12.76
+4000.example. 5M IN A 10.0.12.77
+4000.example. 5M IN A 10.0.12.78
+4000.example. 5M IN A 10.0.12.79
+4000.example. 5M IN A 10.0.12.80
+4000.example. 5M IN A 10.0.12.81
+4000.example. 5M IN A 10.0.12.82
+4000.example. 5M IN A 10.0.12.83
+4000.example. 5M IN A 10.0.12.84
+4000.example. 5M IN A 10.0.12.85
+4000.example. 5M IN A 10.0.12.86
+4000.example. 5M IN A 10.0.12.87
+4000.example. 5M IN A 10.0.12.88
+4000.example. 5M IN A 10.0.12.89
+4000.example. 5M IN A 10.0.12.90
+4000.example. 5M IN A 10.0.12.91
+4000.example. 5M IN A 10.0.12.92
+4000.example. 5M IN A 10.0.12.93
+4000.example. 5M IN A 10.0.12.94
+4000.example. 5M IN A 10.0.12.95
+4000.example. 5M IN A 10.0.12.96
+4000.example. 5M IN A 10.0.12.97
+4000.example. 5M IN A 10.0.12.98
+4000.example. 5M IN A 10.0.12.99
+4000.example. 5M IN A 10.0.12.100
+4000.example. 5M IN A 10.0.12.101
+4000.example. 5M IN A 10.0.12.102
+4000.example. 5M IN A 10.0.12.103
+4000.example. 5M IN A 10.0.12.104
+4000.example. 5M IN A 10.0.12.105
+4000.example. 5M IN A 10.0.12.106
+4000.example. 5M IN A 10.0.12.107
+4000.example. 5M IN A 10.0.12.108
+4000.example. 5M IN A 10.0.12.109
+4000.example. 5M IN A 10.0.12.110
+4000.example. 5M IN A 10.0.12.111
+4000.example. 5M IN A 10.0.12.112
+4000.example. 5M IN A 10.0.12.113
+4000.example. 5M IN A 10.0.12.114
+4000.example. 5M IN A 10.0.12.115
+4000.example. 5M IN A 10.0.12.116
+4000.example. 5M IN A 10.0.12.117
+4000.example. 5M IN A 10.0.12.118
+4000.example. 5M IN A 10.0.12.119
+4000.example. 5M IN A 10.0.12.120
+4000.example. 5M IN A 10.0.12.121
+4000.example. 5M IN A 10.0.12.122
+4000.example. 5M IN A 10.0.12.123
+4000.example. 5M IN A 10.0.12.124
+4000.example. 5M IN A 10.0.12.125
+4000.example. 5M IN A 10.0.12.126
+4000.example. 5M IN A 10.0.12.127
+4000.example. 5M IN A 10.0.12.128
+4000.example. 5M IN A 10.0.12.129
+4000.example. 5M IN A 10.0.12.130
+4000.example. 5M IN A 10.0.12.131
+4000.example. 5M IN A 10.0.12.132
+4000.example. 5M IN A 10.0.12.133
+4000.example. 5M IN A 10.0.12.134
+4000.example. 5M IN A 10.0.12.135
+4000.example. 5M IN A 10.0.12.136
+4000.example. 5M IN A 10.0.12.137
+4000.example. 5M IN A 10.0.12.138
+4000.example. 5M IN A 10.0.12.139
+4000.example. 5M IN A 10.0.12.140
+4000.example. 5M IN A 10.0.12.141
+4000.example. 5M IN A 10.0.12.142
+4000.example. 5M IN A 10.0.12.143
+4000.example. 5M IN A 10.0.12.144
+4000.example. 5M IN A 10.0.12.145
+4000.example. 5M IN A 10.0.12.146
+4000.example. 5M IN A 10.0.12.147
+4000.example. 5M IN A 10.0.12.148
+4000.example. 5M IN A 10.0.12.149
+4000.example. 5M IN A 10.0.12.150
+4000.example. 5M IN A 10.0.12.151
+4000.example. 5M IN A 10.0.12.152
+4000.example. 5M IN A 10.0.12.153
+4000.example. 5M IN A 10.0.12.154
+4000.example. 5M IN A 10.0.12.155
+4000.example. 5M IN A 10.0.12.156
+4000.example. 5M IN A 10.0.12.157
+4000.example. 5M IN A 10.0.12.158
+4000.example. 5M IN A 10.0.12.159
+4000.example. 5M IN A 10.0.12.160
+4000.example. 5M IN A 10.0.12.161
+4000.example. 5M IN A 10.0.12.162
+4000.example. 5M IN A 10.0.12.163
+4000.example. 5M IN A 10.0.12.164
+4000.example. 5M IN A 10.0.12.165
+4000.example. 5M IN A 10.0.12.166
+4000.example. 5M IN A 10.0.12.167
+4000.example. 5M IN A 10.0.12.168
+4000.example. 5M IN A 10.0.12.169
+4000.example. 5M IN A 10.0.12.170
+4000.example. 5M IN A 10.0.12.171
+4000.example. 5M IN A 10.0.12.172
+4000.example. 5M IN A 10.0.12.173
+4000.example. 5M IN A 10.0.12.174
+4000.example. 5M IN A 10.0.12.175
+4000.example. 5M IN A 10.0.12.176
+4000.example. 5M IN A 10.0.12.177
+4000.example. 5M IN A 10.0.12.178
+4000.example. 5M IN A 10.0.12.179
+4000.example. 5M IN A 10.0.12.180
+4000.example. 5M IN A 10.0.12.181
+4000.example. 5M IN A 10.0.12.182
+4000.example. 5M IN A 10.0.12.183
+4000.example. 5M IN A 10.0.12.184
+4000.example. 5M IN A 10.0.12.185
+4000.example. 5M IN A 10.0.12.186
+4000.example. 5M IN A 10.0.12.187
+4000.example. 5M IN A 10.0.12.188
+4000.example. 5M IN A 10.0.12.189
+4000.example. 5M IN A 10.0.12.190
+4000.example. 5M IN A 10.0.12.191
+4000.example. 5M IN A 10.0.12.192
+4000.example. 5M IN A 10.0.12.193
+4000.example. 5M IN A 10.0.12.194
+4000.example. 5M IN A 10.0.12.195
+4000.example. 5M IN A 10.0.12.196
+4000.example. 5M IN A 10.0.12.197
+4000.example. 5M IN A 10.0.12.198
+4000.example. 5M IN A 10.0.12.199
+4000.example. 5M IN A 10.0.12.200
+4000.example. 5M IN A 10.0.12.201
+4000.example. 5M IN A 10.0.12.202
+4000.example. 5M IN A 10.0.12.203
+4000.example. 5M IN A 10.0.12.204
+4000.example. 5M IN A 10.0.12.205
+4000.example. 5M IN A 10.0.12.206
+4000.example. 5M IN A 10.0.12.207
+4000.example. 5M IN A 10.0.12.208
+4000.example. 5M IN A 10.0.12.209
+4000.example. 5M IN A 10.0.12.210
+4000.example. 5M IN A 10.0.12.211
+4000.example. 5M IN A 10.0.12.212
+4000.example. 5M IN A 10.0.12.213
+4000.example. 5M IN A 10.0.12.214
+4000.example. 5M IN A 10.0.12.215
+4000.example. 5M IN A 10.0.12.216
+4000.example. 5M IN A 10.0.12.217
+4000.example. 5M IN A 10.0.12.218
+4000.example. 5M IN A 10.0.12.219
+4000.example. 5M IN A 10.0.12.220
+4000.example. 5M IN A 10.0.12.221
+4000.example. 5M IN A 10.0.12.222
+4000.example. 5M IN A 10.0.12.223
+4000.example. 5M IN A 10.0.12.224
+4000.example. 5M IN A 10.0.12.225
+4000.example. 5M IN A 10.0.12.226
+4000.example. 5M IN A 10.0.12.227
+4000.example. 5M IN A 10.0.12.228
+4000.example. 5M IN A 10.0.12.229
+4000.example. 5M IN A 10.0.12.230
+4000.example. 5M IN A 10.0.12.231
+4000.example. 5M IN A 10.0.12.232
+4000.example. 5M IN A 10.0.12.233
+4000.example. 5M IN A 10.0.12.234
+4000.example. 5M IN A 10.0.12.235
+4000.example. 5M IN A 10.0.12.236
+4000.example. 5M IN A 10.0.12.237
+4000.example. 5M IN A 10.0.12.238
+4000.example. 5M IN A 10.0.12.239
+4000.example. 5M IN A 10.0.12.240
+4000.example. 5M IN A 10.0.12.241
+4000.example. 5M IN A 10.0.12.242
+4000.example. 5M IN A 10.0.12.243
+4000.example. 5M IN A 10.0.12.244
+4000.example. 5M IN A 10.0.12.245
+4000.example. 5M IN A 10.0.12.246
+4000.example. 5M IN A 10.0.12.247
+4000.example. 5M IN A 10.0.12.248
+4000.example. 5M IN A 10.0.12.249
+4000.example. 5M IN A 10.0.12.250
+4000.example. 5M IN A 10.0.12.251
+4000.example. 5M IN A 10.0.12.252
+4000.example. 5M IN A 10.0.12.253
+4000.example. 5M IN A 10.0.12.254
+4000.example. 5M IN A 10.0.12.255
+4000.example. 5M IN A 10.0.13.0
+4000.example. 5M IN A 10.0.13.1
+4000.example. 5M IN A 10.0.13.2
+4000.example. 5M IN A 10.0.13.3
+4000.example. 5M IN A 10.0.13.4
+4000.example. 5M IN A 10.0.13.5
+4000.example. 5M IN A 10.0.13.6
+4000.example. 5M IN A 10.0.13.7
+4000.example. 5M IN A 10.0.13.8
+4000.example. 5M IN A 10.0.13.9
+4000.example. 5M IN A 10.0.13.10
+4000.example. 5M IN A 10.0.13.11
+4000.example. 5M IN A 10.0.13.12
+4000.example. 5M IN A 10.0.13.13
+4000.example. 5M IN A 10.0.13.14
+4000.example. 5M IN A 10.0.13.15
+4000.example. 5M IN A 10.0.13.16
+4000.example. 5M IN A 10.0.13.17
+4000.example. 5M IN A 10.0.13.18
+4000.example. 5M IN A 10.0.13.19
+4000.example. 5M IN A 10.0.13.20
+4000.example. 5M IN A 10.0.13.21
+4000.example. 5M IN A 10.0.13.22
+4000.example. 5M IN A 10.0.13.23
+4000.example. 5M IN A 10.0.13.24
+4000.example. 5M IN A 10.0.13.25
+4000.example. 5M IN A 10.0.13.26
+4000.example. 5M IN A 10.0.13.27
+4000.example. 5M IN A 10.0.13.28
+4000.example. 5M IN A 10.0.13.29
+4000.example. 5M IN A 10.0.13.30
+4000.example. 5M IN A 10.0.13.31
+4000.example. 5M IN A 10.0.13.32
+4000.example. 5M IN A 10.0.13.33
+4000.example. 5M IN A 10.0.13.34
+4000.example. 5M IN A 10.0.13.35
+4000.example. 5M IN A 10.0.13.36
+4000.example. 5M IN A 10.0.13.37
+4000.example. 5M IN A 10.0.13.38
+4000.example. 5M IN A 10.0.13.39
+4000.example. 5M IN A 10.0.13.40
+4000.example. 5M IN A 10.0.13.41
+4000.example. 5M IN A 10.0.13.42
+4000.example. 5M IN A 10.0.13.43
+4000.example. 5M IN A 10.0.13.44
+4000.example. 5M IN A 10.0.13.45
+4000.example. 5M IN A 10.0.13.46
+4000.example. 5M IN A 10.0.13.47
+4000.example. 5M IN A 10.0.13.48
+4000.example. 5M IN A 10.0.13.49
+4000.example. 5M IN A 10.0.13.50
+4000.example. 5M IN A 10.0.13.51
+4000.example. 5M IN A 10.0.13.52
+4000.example. 5M IN A 10.0.13.53
+4000.example. 5M IN A 10.0.13.54
+4000.example. 5M IN A 10.0.13.55
+4000.example. 5M IN A 10.0.13.56
+4000.example. 5M IN A 10.0.13.57
+4000.example. 5M IN A 10.0.13.58
+4000.example. 5M IN A 10.0.13.59
+4000.example. 5M IN A 10.0.13.60
+4000.example. 5M IN A 10.0.13.61
+4000.example. 5M IN A 10.0.13.62
+4000.example. 5M IN A 10.0.13.63
+4000.example. 5M IN A 10.0.13.64
+4000.example. 5M IN A 10.0.13.65
+4000.example. 5M IN A 10.0.13.66
+4000.example. 5M IN A 10.0.13.67
+4000.example. 5M IN A 10.0.13.68
+4000.example. 5M IN A 10.0.13.69
+4000.example. 5M IN A 10.0.13.70
+4000.example. 5M IN A 10.0.13.71
+4000.example. 5M IN A 10.0.13.72
+4000.example. 5M IN A 10.0.13.73
+4000.example. 5M IN A 10.0.13.74
+4000.example. 5M IN A 10.0.13.75
+4000.example. 5M IN A 10.0.13.76
+4000.example. 5M IN A 10.0.13.77
+4000.example. 5M IN A 10.0.13.78
+4000.example. 5M IN A 10.0.13.79
+4000.example. 5M IN A 10.0.13.80
+4000.example. 5M IN A 10.0.13.81
+4000.example. 5M IN A 10.0.13.82
+4000.example. 5M IN A 10.0.13.83
+4000.example. 5M IN A 10.0.13.84
+4000.example. 5M IN A 10.0.13.85
+4000.example. 5M IN A 10.0.13.86
+4000.example. 5M IN A 10.0.13.87
+4000.example. 5M IN A 10.0.13.88
+4000.example. 5M IN A 10.0.13.89
+4000.example. 5M IN A 10.0.13.90
+4000.example. 5M IN A 10.0.13.91
+4000.example. 5M IN A 10.0.13.92
+4000.example. 5M IN A 10.0.13.93
+4000.example. 5M IN A 10.0.13.94
+4000.example. 5M IN A 10.0.13.95
+4000.example. 5M IN A 10.0.13.96
+4000.example. 5M IN A 10.0.13.97
+4000.example. 5M IN A 10.0.13.98
+4000.example. 5M IN A 10.0.13.99
+4000.example. 5M IN A 10.0.13.100
+4000.example. 5M IN A 10.0.13.101
+4000.example. 5M IN A 10.0.13.102
+4000.example. 5M IN A 10.0.13.103
+4000.example. 5M IN A 10.0.13.104
+4000.example. 5M IN A 10.0.13.105
+4000.example. 5M IN A 10.0.13.106
+4000.example. 5M IN A 10.0.13.107
+4000.example. 5M IN A 10.0.13.108
+4000.example. 5M IN A 10.0.13.109
+4000.example. 5M IN A 10.0.13.110
+4000.example. 5M IN A 10.0.13.111
+4000.example. 5M IN A 10.0.13.112
+4000.example. 5M IN A 10.0.13.113
+4000.example. 5M IN A 10.0.13.114
+4000.example. 5M IN A 10.0.13.115
+4000.example. 5M IN A 10.0.13.116
+4000.example. 5M IN A 10.0.13.117
+4000.example. 5M IN A 10.0.13.118
+4000.example. 5M IN A 10.0.13.119
+4000.example. 5M IN A 10.0.13.120
+4000.example. 5M IN A 10.0.13.121
+4000.example. 5M IN A 10.0.13.122
+4000.example. 5M IN A 10.0.13.123
+4000.example. 5M IN A 10.0.13.124
+4000.example. 5M IN A 10.0.13.125
+4000.example. 5M IN A 10.0.13.126
+4000.example. 5M IN A 10.0.13.127
+4000.example. 5M IN A 10.0.13.128
+4000.example. 5M IN A 10.0.13.129
+4000.example. 5M IN A 10.0.13.130
+4000.example. 5M IN A 10.0.13.131
+4000.example. 5M IN A 10.0.13.132
+4000.example. 5M IN A 10.0.13.133
+4000.example. 5M IN A 10.0.13.134
+4000.example. 5M IN A 10.0.13.135
+4000.example. 5M IN A 10.0.13.136
+4000.example. 5M IN A 10.0.13.137
+4000.example. 5M IN A 10.0.13.138
+4000.example. 5M IN A 10.0.13.139
+4000.example. 5M IN A 10.0.13.140
+4000.example. 5M IN A 10.0.13.141
+4000.example. 5M IN A 10.0.13.142
+4000.example. 5M IN A 10.0.13.143
+4000.example. 5M IN A 10.0.13.144
+4000.example. 5M IN A 10.0.13.145
+4000.example. 5M IN A 10.0.13.146
+4000.example. 5M IN A 10.0.13.147
+4000.example. 5M IN A 10.0.13.148
+4000.example. 5M IN A 10.0.13.149
+4000.example. 5M IN A 10.0.13.150
+4000.example. 5M IN A 10.0.13.151
+4000.example. 5M IN A 10.0.13.152
+4000.example. 5M IN A 10.0.13.153
+4000.example. 5M IN A 10.0.13.154
+4000.example. 5M IN A 10.0.13.155
+4000.example. 5M IN A 10.0.13.156
+4000.example. 5M IN A 10.0.13.157
+4000.example. 5M IN A 10.0.13.158
+4000.example. 5M IN A 10.0.13.159
+4000.example. 5M IN A 10.0.13.160
+4000.example. 5M IN A 10.0.13.161
+4000.example. 5M IN A 10.0.13.162
+4000.example. 5M IN A 10.0.13.163
+4000.example. 5M IN A 10.0.13.164
+4000.example. 5M IN A 10.0.13.165
+4000.example. 5M IN A 10.0.13.166
+4000.example. 5M IN A 10.0.13.167
+4000.example. 5M IN A 10.0.13.168
+4000.example. 5M IN A 10.0.13.169
+4000.example. 5M IN A 10.0.13.170
+4000.example. 5M IN A 10.0.13.171
+4000.example. 5M IN A 10.0.13.172
+4000.example. 5M IN A 10.0.13.173
+4000.example. 5M IN A 10.0.13.174
+4000.example. 5M IN A 10.0.13.175
+4000.example. 5M IN A 10.0.13.176
+4000.example. 5M IN A 10.0.13.177
+4000.example. 5M IN A 10.0.13.178
+4000.example. 5M IN A 10.0.13.179
+4000.example. 5M IN A 10.0.13.180
+4000.example. 5M IN A 10.0.13.181
+4000.example. 5M IN A 10.0.13.182
+4000.example. 5M IN A 10.0.13.183
+4000.example. 5M IN A 10.0.13.184
+4000.example. 5M IN A 10.0.13.185
+4000.example. 5M IN A 10.0.13.186
+4000.example. 5M IN A 10.0.13.187
+4000.example. 5M IN A 10.0.13.188
+4000.example. 5M IN A 10.0.13.189
+4000.example. 5M IN A 10.0.13.190
+4000.example. 5M IN A 10.0.13.191
+4000.example. 5M IN A 10.0.13.192
+4000.example. 5M IN A 10.0.13.193
+4000.example. 5M IN A 10.0.13.194
+4000.example. 5M IN A 10.0.13.195
+4000.example. 5M IN A 10.0.13.196
+4000.example. 5M IN A 10.0.13.197
+4000.example. 5M IN A 10.0.13.198
+4000.example. 5M IN A 10.0.13.199
+4000.example. 5M IN A 10.0.13.200
+4000.example. 5M IN A 10.0.13.201
+4000.example. 5M IN A 10.0.13.202
+4000.example. 5M IN A 10.0.13.203
+4000.example. 5M IN A 10.0.13.204
+4000.example. 5M IN A 10.0.13.205
+4000.example. 5M IN A 10.0.13.206
+4000.example. 5M IN A 10.0.13.207
+4000.example. 5M IN A 10.0.13.208
+4000.example. 5M IN A 10.0.13.209
+4000.example. 5M IN A 10.0.13.210
+4000.example. 5M IN A 10.0.13.211
+4000.example. 5M IN A 10.0.13.212
+4000.example. 5M IN A 10.0.13.213
+4000.example. 5M IN A 10.0.13.214
+4000.example. 5M IN A 10.0.13.215
+4000.example. 5M IN A 10.0.13.216
+4000.example. 5M IN A 10.0.13.217
+4000.example. 5M IN A 10.0.13.218
+4000.example. 5M IN A 10.0.13.219
+4000.example. 5M IN A 10.0.13.220
+4000.example. 5M IN A 10.0.13.221
+4000.example. 5M IN A 10.0.13.222
+4000.example. 5M IN A 10.0.13.223
+4000.example. 5M IN A 10.0.13.224
+4000.example. 5M IN A 10.0.13.225
+4000.example. 5M IN A 10.0.13.226
+4000.example. 5M IN A 10.0.13.227
+4000.example. 5M IN A 10.0.13.228
+4000.example. 5M IN A 10.0.13.229
+4000.example. 5M IN A 10.0.13.230
+4000.example. 5M IN A 10.0.13.231
+4000.example. 5M IN A 10.0.13.232
+4000.example. 5M IN A 10.0.13.233
+4000.example. 5M IN A 10.0.13.234
+4000.example. 5M IN A 10.0.13.235
+4000.example. 5M IN A 10.0.13.236
+4000.example. 5M IN A 10.0.13.237
+4000.example. 5M IN A 10.0.13.238
+4000.example. 5M IN A 10.0.13.239
+4000.example. 5M IN A 10.0.13.240
+4000.example. 5M IN A 10.0.13.241
+4000.example. 5M IN A 10.0.13.242
+4000.example. 5M IN A 10.0.13.243
+4000.example. 5M IN A 10.0.13.244
+4000.example. 5M IN A 10.0.13.245
+4000.example. 5M IN A 10.0.13.246
+4000.example. 5M IN A 10.0.13.247
+4000.example. 5M IN A 10.0.13.248
+4000.example. 5M IN A 10.0.13.249
+4000.example. 5M IN A 10.0.13.250
+4000.example. 5M IN A 10.0.13.251
+4000.example. 5M IN A 10.0.13.252
+4000.example. 5M IN A 10.0.13.253
+4000.example. 5M IN A 10.0.13.254
+4000.example. 5M IN A 10.0.13.255
+4000.example. 5M IN A 10.0.14.0
+4000.example. 5M IN A 10.0.14.1
+4000.example. 5M IN A 10.0.14.2
+4000.example. 5M IN A 10.0.14.3
+4000.example. 5M IN A 10.0.14.4
+4000.example. 5M IN A 10.0.14.5
+4000.example. 5M IN A 10.0.14.6
+4000.example. 5M IN A 10.0.14.7
+4000.example. 5M IN A 10.0.14.8
+4000.example. 5M IN A 10.0.14.9
+4000.example. 5M IN A 10.0.14.10
+4000.example. 5M IN A 10.0.14.11
+4000.example. 5M IN A 10.0.14.12
+4000.example. 5M IN A 10.0.14.13
+4000.example. 5M IN A 10.0.14.14
+4000.example. 5M IN A 10.0.14.15
+4000.example. 5M IN A 10.0.14.16
+4000.example. 5M IN A 10.0.14.17
+4000.example. 5M IN A 10.0.14.18
+4000.example. 5M IN A 10.0.14.19
+4000.example. 5M IN A 10.0.14.20
+4000.example. 5M IN A 10.0.14.21
+4000.example. 5M IN A 10.0.14.22
+4000.example. 5M IN A 10.0.14.23
+4000.example. 5M IN A 10.0.14.24
+4000.example. 5M IN A 10.0.14.25
+4000.example. 5M IN A 10.0.14.26
+4000.example. 5M IN A 10.0.14.27
+4000.example. 5M IN A 10.0.14.28
+4000.example. 5M IN A 10.0.14.29
+4000.example. 5M IN A 10.0.14.30
+4000.example. 5M IN A 10.0.14.31
+4000.example. 5M IN A 10.0.14.32
+4000.example. 5M IN A 10.0.14.33
+4000.example. 5M IN A 10.0.14.34
+4000.example. 5M IN A 10.0.14.35
+4000.example. 5M IN A 10.0.14.36
+4000.example. 5M IN A 10.0.14.37
+4000.example. 5M IN A 10.0.14.38
+4000.example. 5M IN A 10.0.14.39
+4000.example. 5M IN A 10.0.14.40
+4000.example. 5M IN A 10.0.14.41
+4000.example. 5M IN A 10.0.14.42
+4000.example. 5M IN A 10.0.14.43
+4000.example. 5M IN A 10.0.14.44
+4000.example. 5M IN A 10.0.14.45
+4000.example. 5M IN A 10.0.14.46
+4000.example. 5M IN A 10.0.14.47
+4000.example. 5M IN A 10.0.14.48
+4000.example. 5M IN A 10.0.14.49
+4000.example. 5M IN A 10.0.14.50
+4000.example. 5M IN A 10.0.14.51
+4000.example. 5M IN A 10.0.14.52
+4000.example. 5M IN A 10.0.14.53
+4000.example. 5M IN A 10.0.14.54
+4000.example. 5M IN A 10.0.14.55
+4000.example. 5M IN A 10.0.14.56
+4000.example. 5M IN A 10.0.14.57
+4000.example. 5M IN A 10.0.14.58
+4000.example. 5M IN A 10.0.14.59
+4000.example. 5M IN A 10.0.14.60
+4000.example. 5M IN A 10.0.14.61
+4000.example. 5M IN A 10.0.14.62
+4000.example. 5M IN A 10.0.14.63
+4000.example. 5M IN A 10.0.14.64
+4000.example. 5M IN A 10.0.14.65
+4000.example. 5M IN A 10.0.14.66
+4000.example. 5M IN A 10.0.14.67
+4000.example. 5M IN A 10.0.14.68
+4000.example. 5M IN A 10.0.14.69
+4000.example. 5M IN A 10.0.14.70
+4000.example. 5M IN A 10.0.14.71
+4000.example. 5M IN A 10.0.14.72
+4000.example. 5M IN A 10.0.14.73
+4000.example. 5M IN A 10.0.14.74
+4000.example. 5M IN A 10.0.14.75
+4000.example. 5M IN A 10.0.14.76
+4000.example. 5M IN A 10.0.14.77
+4000.example. 5M IN A 10.0.14.78
+4000.example. 5M IN A 10.0.14.79
+4000.example. 5M IN A 10.0.14.80
+4000.example. 5M IN A 10.0.14.81
+4000.example. 5M IN A 10.0.14.82
+4000.example. 5M IN A 10.0.14.83
+4000.example. 5M IN A 10.0.14.84
+4000.example. 5M IN A 10.0.14.85
+4000.example. 5M IN A 10.0.14.86
+4000.example. 5M IN A 10.0.14.87
+4000.example. 5M IN A 10.0.14.88
+4000.example. 5M IN A 10.0.14.89
+4000.example. 5M IN A 10.0.14.90
+4000.example. 5M IN A 10.0.14.91
+4000.example. 5M IN A 10.0.14.92
+4000.example. 5M IN A 10.0.14.93
+4000.example. 5M IN A 10.0.14.94
+4000.example. 5M IN A 10.0.14.95
+4000.example. 5M IN A 10.0.14.96
+4000.example. 5M IN A 10.0.14.97
+4000.example. 5M IN A 10.0.14.98
+4000.example. 5M IN A 10.0.14.99
+4000.example. 5M IN A 10.0.14.100
+4000.example. 5M IN A 10.0.14.101
+4000.example. 5M IN A 10.0.14.102
+4000.example. 5M IN A 10.0.14.103
+4000.example. 5M IN A 10.0.14.104
+4000.example. 5M IN A 10.0.14.105
+4000.example. 5M IN A 10.0.14.106
+4000.example. 5M IN A 10.0.14.107
+4000.example. 5M IN A 10.0.14.108
+4000.example. 5M IN A 10.0.14.109
+4000.example. 5M IN A 10.0.14.110
+4000.example. 5M IN A 10.0.14.111
+4000.example. 5M IN A 10.0.14.112
+4000.example. 5M IN A 10.0.14.113
+4000.example. 5M IN A 10.0.14.114
+4000.example. 5M IN A 10.0.14.115
+4000.example. 5M IN A 10.0.14.116
+4000.example. 5M IN A 10.0.14.117
+4000.example. 5M IN A 10.0.14.118
+4000.example. 5M IN A 10.0.14.119
+4000.example. 5M IN A 10.0.14.120
+4000.example. 5M IN A 10.0.14.121
+4000.example. 5M IN A 10.0.14.122
+4000.example. 5M IN A 10.0.14.123
+4000.example. 5M IN A 10.0.14.124
+4000.example. 5M IN A 10.0.14.125
+4000.example. 5M IN A 10.0.14.126
+4000.example. 5M IN A 10.0.14.127
+4000.example. 5M IN A 10.0.14.128
+4000.example. 5M IN A 10.0.14.129
+4000.example. 5M IN A 10.0.14.130
+4000.example. 5M IN A 10.0.14.131
+4000.example. 5M IN A 10.0.14.132
+4000.example. 5M IN A 10.0.14.133
+4000.example. 5M IN A 10.0.14.134
+4000.example. 5M IN A 10.0.14.135
+4000.example. 5M IN A 10.0.14.136
+4000.example. 5M IN A 10.0.14.137
+4000.example. 5M IN A 10.0.14.138
+4000.example. 5M IN A 10.0.14.139
+4000.example. 5M IN A 10.0.14.140
+4000.example. 5M IN A 10.0.14.141
+4000.example. 5M IN A 10.0.14.142
+4000.example. 5M IN A 10.0.14.143
+4000.example. 5M IN A 10.0.14.144
+4000.example. 5M IN A 10.0.14.145
+4000.example. 5M IN A 10.0.14.146
+4000.example. 5M IN A 10.0.14.147
+4000.example. 5M IN A 10.0.14.148
+4000.example. 5M IN A 10.0.14.149
+4000.example. 5M IN A 10.0.14.150
+4000.example. 5M IN A 10.0.14.151
+4000.example. 5M IN A 10.0.14.152
+4000.example. 5M IN A 10.0.14.153
+4000.example. 5M IN A 10.0.14.154
+4000.example. 5M IN A 10.0.14.155
+4000.example. 5M IN A 10.0.14.156
+4000.example. 5M IN A 10.0.14.157
+4000.example. 5M IN A 10.0.14.158
+4000.example. 5M IN A 10.0.14.159
+4000.example. 5M IN A 10.0.14.160
+4000.example. 5M IN A 10.0.14.161
+4000.example. 5M IN A 10.0.14.162
+4000.example. 5M IN A 10.0.14.163
+4000.example. 5M IN A 10.0.14.164
+4000.example. 5M IN A 10.0.14.165
+4000.example. 5M IN A 10.0.14.166
+4000.example. 5M IN A 10.0.14.167
+4000.example. 5M IN A 10.0.14.168
+4000.example. 5M IN A 10.0.14.169
+4000.example. 5M IN A 10.0.14.170
+4000.example. 5M IN A 10.0.14.171
+4000.example. 5M IN A 10.0.14.172
+4000.example. 5M IN A 10.0.14.173
+4000.example. 5M IN A 10.0.14.174
+4000.example. 5M IN A 10.0.14.175
+4000.example. 5M IN A 10.0.14.176
+4000.example. 5M IN A 10.0.14.177
+4000.example. 5M IN A 10.0.14.178
+4000.example. 5M IN A 10.0.14.179
+4000.example. 5M IN A 10.0.14.180
+4000.example. 5M IN A 10.0.14.181
+4000.example. 5M IN A 10.0.14.182
+4000.example. 5M IN A 10.0.14.183
+4000.example. 5M IN A 10.0.14.184
+4000.example. 5M IN A 10.0.14.185
+4000.example. 5M IN A 10.0.14.186
+4000.example. 5M IN A 10.0.14.187
+4000.example. 5M IN A 10.0.14.188
+4000.example. 5M IN A 10.0.14.189
+4000.example. 5M IN A 10.0.14.190
+4000.example. 5M IN A 10.0.14.191
+4000.example. 5M IN A 10.0.14.192
+4000.example. 5M IN A 10.0.14.193
+4000.example. 5M IN A 10.0.14.194
+4000.example. 5M IN A 10.0.14.195
+4000.example. 5M IN A 10.0.14.196
+4000.example. 5M IN A 10.0.14.197
+4000.example. 5M IN A 10.0.14.198
+4000.example. 5M IN A 10.0.14.199
+4000.example. 5M IN A 10.0.14.200
+4000.example. 5M IN A 10.0.14.201
+4000.example. 5M IN A 10.0.14.202
+4000.example. 5M IN A 10.0.14.203
+4000.example. 5M IN A 10.0.14.204
+4000.example. 5M IN A 10.0.14.205
+4000.example. 5M IN A 10.0.14.206
+4000.example. 5M IN A 10.0.14.207
+4000.example. 5M IN A 10.0.14.208
+4000.example. 5M IN A 10.0.14.209
+4000.example. 5M IN A 10.0.14.210
+4000.example. 5M IN A 10.0.14.211
+4000.example. 5M IN A 10.0.14.212
+4000.example. 5M IN A 10.0.14.213
+4000.example. 5M IN A 10.0.14.214
+4000.example. 5M IN A 10.0.14.215
+4000.example. 5M IN A 10.0.14.216
+4000.example. 5M IN A 10.0.14.217
+4000.example. 5M IN A 10.0.14.218
+4000.example. 5M IN A 10.0.14.219
+4000.example. 5M IN A 10.0.14.220
+4000.example. 5M IN A 10.0.14.221
+4000.example. 5M IN A 10.0.14.222
+4000.example. 5M IN A 10.0.14.223
+4000.example. 5M IN A 10.0.14.224
+4000.example. 5M IN A 10.0.14.225
+4000.example. 5M IN A 10.0.14.226
+4000.example. 5M IN A 10.0.14.227
+4000.example. 5M IN A 10.0.14.228
+4000.example. 5M IN A 10.0.14.229
+4000.example. 5M IN A 10.0.14.230
+4000.example. 5M IN A 10.0.14.231
+4000.example. 5M IN A 10.0.14.232
+4000.example. 5M IN A 10.0.14.233
+4000.example. 5M IN A 10.0.14.234
+4000.example. 5M IN A 10.0.14.235
+4000.example. 5M IN A 10.0.14.236
+4000.example. 5M IN A 10.0.14.237
+4000.example. 5M IN A 10.0.14.238
+4000.example. 5M IN A 10.0.14.239
+4000.example. 5M IN A 10.0.14.240
+4000.example. 5M IN A 10.0.14.241
+4000.example. 5M IN A 10.0.14.242
+4000.example. 5M IN A 10.0.14.243
+4000.example. 5M IN A 10.0.14.244
+4000.example. 5M IN A 10.0.14.245
+4000.example. 5M IN A 10.0.14.246
+4000.example. 5M IN A 10.0.14.247
+4000.example. 5M IN A 10.0.14.248
+4000.example. 5M IN A 10.0.14.249
+4000.example. 5M IN A 10.0.14.250
+4000.example. 5M IN A 10.0.14.251
+4000.example. 5M IN A 10.0.14.252
+4000.example. 5M IN A 10.0.14.253
+4000.example. 5M IN A 10.0.14.254
+4000.example. 5M IN A 10.0.14.255
+4000.example. 5M IN A 10.0.15.0
+4000.example. 5M IN A 10.0.15.1
+4000.example. 5M IN A 10.0.15.2
+4000.example. 5M IN A 10.0.15.3
+4000.example. 5M IN A 10.0.15.4
+4000.example. 5M IN A 10.0.15.5
+4000.example. 5M IN A 10.0.15.6
+4000.example. 5M IN A 10.0.15.7
+4000.example. 5M IN A 10.0.15.8
+4000.example. 5M IN A 10.0.15.9
+4000.example. 5M IN A 10.0.15.10
+4000.example. 5M IN A 10.0.15.11
+4000.example. 5M IN A 10.0.15.12
+4000.example. 5M IN A 10.0.15.13
+4000.example. 5M IN A 10.0.15.14
+4000.example. 5M IN A 10.0.15.15
+4000.example. 5M IN A 10.0.15.16
+4000.example. 5M IN A 10.0.15.17
+4000.example. 5M IN A 10.0.15.18
+4000.example. 5M IN A 10.0.15.19
+4000.example. 5M IN A 10.0.15.20
+4000.example. 5M IN A 10.0.15.21
+4000.example. 5M IN A 10.0.15.22
+4000.example. 5M IN A 10.0.15.23
+4000.example. 5M IN A 10.0.15.24
+4000.example. 5M IN A 10.0.15.25
+4000.example. 5M IN A 10.0.15.26
+4000.example. 5M IN A 10.0.15.27
+4000.example. 5M IN A 10.0.15.28
+4000.example. 5M IN A 10.0.15.29
+4000.example. 5M IN A 10.0.15.30
+4000.example. 5M IN A 10.0.15.31
+4000.example. 5M IN A 10.0.15.32
+4000.example. 5M IN A 10.0.15.33
+4000.example. 5M IN A 10.0.15.34
+4000.example. 5M IN A 10.0.15.35
+4000.example. 5M IN A 10.0.15.36
+4000.example. 5M IN A 10.0.15.37
+4000.example. 5M IN A 10.0.15.38
+4000.example. 5M IN A 10.0.15.39
+4000.example. 5M IN A 10.0.15.40
+4000.example. 5M IN A 10.0.15.41
+4000.example. 5M IN A 10.0.15.42
+4000.example. 5M IN A 10.0.15.43
+4000.example. 5M IN A 10.0.15.44
+4000.example. 5M IN A 10.0.15.45
+4000.example. 5M IN A 10.0.15.46
+4000.example. 5M IN A 10.0.15.47
+4000.example. 5M IN A 10.0.15.48
+4000.example. 5M IN A 10.0.15.49
+4000.example. 5M IN A 10.0.15.50
+4000.example. 5M IN A 10.0.15.51
+4000.example. 5M IN A 10.0.15.52
+4000.example. 5M IN A 10.0.15.53
+4000.example. 5M IN A 10.0.15.54
+4000.example. 5M IN A 10.0.15.55
+4000.example. 5M IN A 10.0.15.56
+4000.example. 5M IN A 10.0.15.57
+4000.example. 5M IN A 10.0.15.58
+4000.example. 5M IN A 10.0.15.59
+4000.example. 5M IN A 10.0.15.60
+4000.example. 5M IN A 10.0.15.61
+4000.example. 5M IN A 10.0.15.62
+4000.example. 5M IN A 10.0.15.63
+4000.example. 5M IN A 10.0.15.64
+4000.example. 5M IN A 10.0.15.65
+4000.example. 5M IN A 10.0.15.66
+4000.example. 5M IN A 10.0.15.67
+4000.example. 5M IN A 10.0.15.68
+4000.example. 5M IN A 10.0.15.69
+4000.example. 5M IN A 10.0.15.70
+4000.example. 5M IN A 10.0.15.71
+4000.example. 5M IN A 10.0.15.72
+4000.example. 5M IN A 10.0.15.73
+4000.example. 5M IN A 10.0.15.74
+4000.example. 5M IN A 10.0.15.75
+4000.example. 5M IN A 10.0.15.76
+4000.example. 5M IN A 10.0.15.77
+4000.example. 5M IN A 10.0.15.78
+4000.example. 5M IN A 10.0.15.79
+4000.example. 5M IN A 10.0.15.80
+4000.example. 5M IN A 10.0.15.81
+4000.example. 5M IN A 10.0.15.82
+4000.example. 5M IN A 10.0.15.83
+4000.example. 5M IN A 10.0.15.84
+4000.example. 5M IN A 10.0.15.85
+4000.example. 5M IN A 10.0.15.86
+4000.example. 5M IN A 10.0.15.87
+4000.example. 5M IN A 10.0.15.88
+4000.example. 5M IN A 10.0.15.89
+4000.example. 5M IN A 10.0.15.90
+4000.example. 5M IN A 10.0.15.91
+4000.example. 5M IN A 10.0.15.92
+4000.example. 5M IN A 10.0.15.93
+4000.example. 5M IN A 10.0.15.94
+4000.example. 5M IN A 10.0.15.95
+4000.example. 5M IN A 10.0.15.96
+4000.example. 5M IN A 10.0.15.97
+4000.example. 5M IN A 10.0.15.98
+4000.example. 5M IN A 10.0.15.99
+4000.example. 5M IN A 10.0.15.100
+4000.example. 5M IN A 10.0.15.101
+4000.example. 5M IN A 10.0.15.102
+4000.example. 5M IN A 10.0.15.103
+4000.example. 5M IN A 10.0.15.104
+4000.example. 5M IN A 10.0.15.105
+4000.example. 5M IN A 10.0.15.106
+4000.example. 5M IN A 10.0.15.107
+4000.example. 5M IN A 10.0.15.108
+4000.example. 5M IN A 10.0.15.109
+4000.example. 5M IN A 10.0.15.110
+4000.example. 5M IN A 10.0.15.111
+4000.example. 5M IN A 10.0.15.112
+4000.example. 5M IN A 10.0.15.113
+4000.example. 5M IN A 10.0.15.114
+4000.example. 5M IN A 10.0.15.115
+4000.example. 5M IN A 10.0.15.116
+4000.example. 5M IN A 10.0.15.117
+4000.example. 5M IN A 10.0.15.118
+4000.example. 5M IN A 10.0.15.119
+4000.example. 5M IN A 10.0.15.120
+4000.example. 5M IN A 10.0.15.121
+4000.example. 5M IN A 10.0.15.122
+4000.example. 5M IN A 10.0.15.123
+4000.example. 5M IN A 10.0.15.124
+4000.example. 5M IN A 10.0.15.125
+4000.example. 5M IN A 10.0.15.126
+4000.example. 5M IN A 10.0.15.127
+4000.example. 5M IN A 10.0.15.128
+4000.example. 5M IN A 10.0.15.129
+4000.example. 5M IN A 10.0.15.130
+4000.example. 5M IN A 10.0.15.131
+4000.example. 5M IN A 10.0.15.132
+4000.example. 5M IN A 10.0.15.133
+4000.example. 5M IN A 10.0.15.134
+4000.example. 5M IN A 10.0.15.135
+4000.example. 5M IN A 10.0.15.136
+4000.example. 5M IN A 10.0.15.137
+4000.example. 5M IN A 10.0.15.138
+4000.example. 5M IN A 10.0.15.139
+4000.example. 5M IN A 10.0.15.140
+4000.example. 5M IN A 10.0.15.141
+4000.example. 5M IN A 10.0.15.142
+4000.example. 5M IN A 10.0.15.143
+4000.example. 5M IN A 10.0.15.144
+4000.example. 5M IN A 10.0.15.145
+4000.example. 5M IN A 10.0.15.146
+4000.example. 5M IN A 10.0.15.147
+4000.example. 5M IN A 10.0.15.148
+4000.example. 5M IN A 10.0.15.149
+4000.example. 5M IN A 10.0.15.150
+4000.example. 5M IN A 10.0.15.151
+4000.example. 5M IN A 10.0.15.152
+4000.example. 5M IN A 10.0.15.153
+4000.example. 5M IN A 10.0.15.154
+4000.example. 5M IN A 10.0.15.155
+4000.example. 5M IN A 10.0.15.156
+4000.example. 5M IN A 10.0.15.157
+4000.example. 5M IN A 10.0.15.158
+4000.example. 5M IN A 10.0.15.159
+
+;; AUTHORITY SECTION:
+example. 5M IN NS ns1.example.
+
+;; ADDITIONAL SECTION:
+ns1.example. 5M IN A 10.53.0.1
+
+;; Total query time: 279 msec
+;; FROM: draco to SERVER: 10.53.0.1
+;; WHEN: Fri Jun 23 12:58:20 2000
+;; MSG SIZE sent: 30 rcvd: 64068
+
diff --git a/bin/tests/system/limits/knowngood.dig.out.a-maximum-rrset b/bin/tests/system/limits/knowngood.dig.out.a-maximum-rrset
new file mode 100644
index 0000000..1688e83
--- /dev/null
+++ b/bin/tests/system/limits/knowngood.dig.out.a-maximum-rrset
@@ -0,0 +1,4114 @@
+
+; <<>> DiG 8.2 <<>> a-maximum-rrset.example. @10.53.0.1 a -p
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr aa rd ad; QUERY: 1, ANSWER: 4091, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; a-maximum-rrset.example, type = A, class = IN
+
+;; ANSWER SECTION:
+a-maximum-rrset.example. 5M IN A 10.0.0.0
+a-maximum-rrset.example. 5M IN A 10.0.0.1
+a-maximum-rrset.example. 5M IN A 10.0.0.2
+a-maximum-rrset.example. 5M IN A 10.0.0.3
+a-maximum-rrset.example. 5M IN A 10.0.0.4
+a-maximum-rrset.example. 5M IN A 10.0.0.5
+a-maximum-rrset.example. 5M IN A 10.0.0.6
+a-maximum-rrset.example. 5M IN A 10.0.0.7
+a-maximum-rrset.example. 5M IN A 10.0.0.8
+a-maximum-rrset.example. 5M IN A 10.0.0.9
+a-maximum-rrset.example. 5M IN A 10.0.0.10
+a-maximum-rrset.example. 5M IN A 10.0.0.11
+a-maximum-rrset.example. 5M IN A 10.0.0.12
+a-maximum-rrset.example. 5M IN A 10.0.0.13
+a-maximum-rrset.example. 5M IN A 10.0.0.14
+a-maximum-rrset.example. 5M IN A 10.0.0.15
+a-maximum-rrset.example. 5M IN A 10.0.0.16
+a-maximum-rrset.example. 5M IN A 10.0.0.17
+a-maximum-rrset.example. 5M IN A 10.0.0.18
+a-maximum-rrset.example. 5M IN A 10.0.0.19
+a-maximum-rrset.example. 5M IN A 10.0.0.20
+a-maximum-rrset.example. 5M IN A 10.0.0.21
+a-maximum-rrset.example. 5M IN A 10.0.0.22
+a-maximum-rrset.example. 5M IN A 10.0.0.23
+a-maximum-rrset.example. 5M IN A 10.0.0.24
+a-maximum-rrset.example. 5M IN A 10.0.0.25
+a-maximum-rrset.example. 5M IN A 10.0.0.26
+a-maximum-rrset.example. 5M IN A 10.0.0.27
+a-maximum-rrset.example. 5M IN A 10.0.0.28
+a-maximum-rrset.example. 5M IN A 10.0.0.29
+a-maximum-rrset.example. 5M IN A 10.0.0.30
+a-maximum-rrset.example. 5M IN A 10.0.0.31
+a-maximum-rrset.example. 5M IN A 10.0.0.32
+a-maximum-rrset.example. 5M IN A 10.0.0.33
+a-maximum-rrset.example. 5M IN A 10.0.0.34
+a-maximum-rrset.example. 5M IN A 10.0.0.35
+a-maximum-rrset.example. 5M IN A 10.0.0.36
+a-maximum-rrset.example. 5M IN A 10.0.0.37
+a-maximum-rrset.example. 5M IN A 10.0.0.38
+a-maximum-rrset.example. 5M IN A 10.0.0.39
+a-maximum-rrset.example. 5M IN A 10.0.0.40
+a-maximum-rrset.example. 5M IN A 10.0.0.41
+a-maximum-rrset.example. 5M IN A 10.0.0.42
+a-maximum-rrset.example. 5M IN A 10.0.0.43
+a-maximum-rrset.example. 5M IN A 10.0.0.44
+a-maximum-rrset.example. 5M IN A 10.0.0.45
+a-maximum-rrset.example. 5M IN A 10.0.0.46
+a-maximum-rrset.example. 5M IN A 10.0.0.47
+a-maximum-rrset.example. 5M IN A 10.0.0.48
+a-maximum-rrset.example. 5M IN A 10.0.0.49
+a-maximum-rrset.example. 5M IN A 10.0.0.50
+a-maximum-rrset.example. 5M IN A 10.0.0.51
+a-maximum-rrset.example. 5M IN A 10.0.0.52
+a-maximum-rrset.example. 5M IN A 10.0.0.53
+a-maximum-rrset.example. 5M IN A 10.0.0.54
+a-maximum-rrset.example. 5M IN A 10.0.0.55
+a-maximum-rrset.example. 5M IN A 10.0.0.56
+a-maximum-rrset.example. 5M IN A 10.0.0.57
+a-maximum-rrset.example. 5M IN A 10.0.0.58
+a-maximum-rrset.example. 5M IN A 10.0.0.59
+a-maximum-rrset.example. 5M IN A 10.0.0.60
+a-maximum-rrset.example. 5M IN A 10.0.0.61
+a-maximum-rrset.example. 5M IN A 10.0.0.62
+a-maximum-rrset.example. 5M IN A 10.0.0.63
+a-maximum-rrset.example. 5M IN A 10.0.0.64
+a-maximum-rrset.example. 5M IN A 10.0.0.65
+a-maximum-rrset.example. 5M IN A 10.0.0.66
+a-maximum-rrset.example. 5M IN A 10.0.0.67
+a-maximum-rrset.example. 5M IN A 10.0.0.68
+a-maximum-rrset.example. 5M IN A 10.0.0.69
+a-maximum-rrset.example. 5M IN A 10.0.0.70
+a-maximum-rrset.example. 5M IN A 10.0.0.71
+a-maximum-rrset.example. 5M IN A 10.0.0.72
+a-maximum-rrset.example. 5M IN A 10.0.0.73
+a-maximum-rrset.example. 5M IN A 10.0.0.74
+a-maximum-rrset.example. 5M IN A 10.0.0.75
+a-maximum-rrset.example. 5M IN A 10.0.0.76
+a-maximum-rrset.example. 5M IN A 10.0.0.77
+a-maximum-rrset.example. 5M IN A 10.0.0.78
+a-maximum-rrset.example. 5M IN A 10.0.0.79
+a-maximum-rrset.example. 5M IN A 10.0.0.80
+a-maximum-rrset.example. 5M IN A 10.0.0.81
+a-maximum-rrset.example. 5M IN A 10.0.0.82
+a-maximum-rrset.example. 5M IN A 10.0.0.83
+a-maximum-rrset.example. 5M IN A 10.0.0.84
+a-maximum-rrset.example. 5M IN A 10.0.0.85
+a-maximum-rrset.example. 5M IN A 10.0.0.86
+a-maximum-rrset.example. 5M IN A 10.0.0.87
+a-maximum-rrset.example. 5M IN A 10.0.0.88
+a-maximum-rrset.example. 5M IN A 10.0.0.89
+a-maximum-rrset.example. 5M IN A 10.0.0.90
+a-maximum-rrset.example. 5M IN A 10.0.0.91
+a-maximum-rrset.example. 5M IN A 10.0.0.92
+a-maximum-rrset.example. 5M IN A 10.0.0.93
+a-maximum-rrset.example. 5M IN A 10.0.0.94
+a-maximum-rrset.example. 5M IN A 10.0.0.95
+a-maximum-rrset.example. 5M IN A 10.0.0.96
+a-maximum-rrset.example. 5M IN A 10.0.0.97
+a-maximum-rrset.example. 5M IN A 10.0.0.98
+a-maximum-rrset.example. 5M IN A 10.0.0.99
+a-maximum-rrset.example. 5M IN A 10.0.0.100
+a-maximum-rrset.example. 5M IN A 10.0.0.101
+a-maximum-rrset.example. 5M IN A 10.0.0.102
+a-maximum-rrset.example. 5M IN A 10.0.0.103
+a-maximum-rrset.example. 5M IN A 10.0.0.104
+a-maximum-rrset.example. 5M IN A 10.0.0.105
+a-maximum-rrset.example. 5M IN A 10.0.0.106
+a-maximum-rrset.example. 5M IN A 10.0.0.107
+a-maximum-rrset.example. 5M IN A 10.0.0.108
+a-maximum-rrset.example. 5M IN A 10.0.0.109
+a-maximum-rrset.example. 5M IN A 10.0.0.110
+a-maximum-rrset.example. 5M IN A 10.0.0.111
+a-maximum-rrset.example. 5M IN A 10.0.0.112
+a-maximum-rrset.example. 5M IN A 10.0.0.113
+a-maximum-rrset.example. 5M IN A 10.0.0.114
+a-maximum-rrset.example. 5M IN A 10.0.0.115
+a-maximum-rrset.example. 5M IN A 10.0.0.116
+a-maximum-rrset.example. 5M IN A 10.0.0.117
+a-maximum-rrset.example. 5M IN A 10.0.0.118
+a-maximum-rrset.example. 5M IN A 10.0.0.119
+a-maximum-rrset.example. 5M IN A 10.0.0.120
+a-maximum-rrset.example. 5M IN A 10.0.0.121
+a-maximum-rrset.example. 5M IN A 10.0.0.122
+a-maximum-rrset.example. 5M IN A 10.0.0.123
+a-maximum-rrset.example. 5M IN A 10.0.0.124
+a-maximum-rrset.example. 5M IN A 10.0.0.125
+a-maximum-rrset.example. 5M IN A 10.0.0.126
+a-maximum-rrset.example. 5M IN A 10.0.0.127
+a-maximum-rrset.example. 5M IN A 10.0.0.128
+a-maximum-rrset.example. 5M IN A 10.0.0.129
+a-maximum-rrset.example. 5M IN A 10.0.0.130
+a-maximum-rrset.example. 5M IN A 10.0.0.131
+a-maximum-rrset.example. 5M IN A 10.0.0.132
+a-maximum-rrset.example. 5M IN A 10.0.0.133
+a-maximum-rrset.example. 5M IN A 10.0.0.134
+a-maximum-rrset.example. 5M IN A 10.0.0.135
+a-maximum-rrset.example. 5M IN A 10.0.0.136
+a-maximum-rrset.example. 5M IN A 10.0.0.137
+a-maximum-rrset.example. 5M IN A 10.0.0.138
+a-maximum-rrset.example. 5M IN A 10.0.0.139
+a-maximum-rrset.example. 5M IN A 10.0.0.140
+a-maximum-rrset.example. 5M IN A 10.0.0.141
+a-maximum-rrset.example. 5M IN A 10.0.0.142
+a-maximum-rrset.example. 5M IN A 10.0.0.143
+a-maximum-rrset.example. 5M IN A 10.0.0.144
+a-maximum-rrset.example. 5M IN A 10.0.0.145
+a-maximum-rrset.example. 5M IN A 10.0.0.146
+a-maximum-rrset.example. 5M IN A 10.0.0.147
+a-maximum-rrset.example. 5M IN A 10.0.0.148
+a-maximum-rrset.example. 5M IN A 10.0.0.149
+a-maximum-rrset.example. 5M IN A 10.0.0.150
+a-maximum-rrset.example. 5M IN A 10.0.0.151
+a-maximum-rrset.example. 5M IN A 10.0.0.152
+a-maximum-rrset.example. 5M IN A 10.0.0.153
+a-maximum-rrset.example. 5M IN A 10.0.0.154
+a-maximum-rrset.example. 5M IN A 10.0.0.155
+a-maximum-rrset.example. 5M IN A 10.0.0.156
+a-maximum-rrset.example. 5M IN A 10.0.0.157
+a-maximum-rrset.example. 5M IN A 10.0.0.158
+a-maximum-rrset.example. 5M IN A 10.0.0.159
+a-maximum-rrset.example. 5M IN A 10.0.0.160
+a-maximum-rrset.example. 5M IN A 10.0.0.161
+a-maximum-rrset.example. 5M IN A 10.0.0.162
+a-maximum-rrset.example. 5M IN A 10.0.0.163
+a-maximum-rrset.example. 5M IN A 10.0.0.164
+a-maximum-rrset.example. 5M IN A 10.0.0.165
+a-maximum-rrset.example. 5M IN A 10.0.0.166
+a-maximum-rrset.example. 5M IN A 10.0.0.167
+a-maximum-rrset.example. 5M IN A 10.0.0.168
+a-maximum-rrset.example. 5M IN A 10.0.0.169
+a-maximum-rrset.example. 5M IN A 10.0.0.170
+a-maximum-rrset.example. 5M IN A 10.0.0.171
+a-maximum-rrset.example. 5M IN A 10.0.0.172
+a-maximum-rrset.example. 5M IN A 10.0.0.173
+a-maximum-rrset.example. 5M IN A 10.0.0.174
+a-maximum-rrset.example. 5M IN A 10.0.0.175
+a-maximum-rrset.example. 5M IN A 10.0.0.176
+a-maximum-rrset.example. 5M IN A 10.0.0.177
+a-maximum-rrset.example. 5M IN A 10.0.0.178
+a-maximum-rrset.example. 5M IN A 10.0.0.179
+a-maximum-rrset.example. 5M IN A 10.0.0.180
+a-maximum-rrset.example. 5M IN A 10.0.0.181
+a-maximum-rrset.example. 5M IN A 10.0.0.182
+a-maximum-rrset.example. 5M IN A 10.0.0.183
+a-maximum-rrset.example. 5M IN A 10.0.0.184
+a-maximum-rrset.example. 5M IN A 10.0.0.185
+a-maximum-rrset.example. 5M IN A 10.0.0.186
+a-maximum-rrset.example. 5M IN A 10.0.0.187
+a-maximum-rrset.example. 5M IN A 10.0.0.188
+a-maximum-rrset.example. 5M IN A 10.0.0.189
+a-maximum-rrset.example. 5M IN A 10.0.0.190
+a-maximum-rrset.example. 5M IN A 10.0.0.191
+a-maximum-rrset.example. 5M IN A 10.0.0.192
+a-maximum-rrset.example. 5M IN A 10.0.0.193
+a-maximum-rrset.example. 5M IN A 10.0.0.194
+a-maximum-rrset.example. 5M IN A 10.0.0.195
+a-maximum-rrset.example. 5M IN A 10.0.0.196
+a-maximum-rrset.example. 5M IN A 10.0.0.197
+a-maximum-rrset.example. 5M IN A 10.0.0.198
+a-maximum-rrset.example. 5M IN A 10.0.0.199
+a-maximum-rrset.example. 5M IN A 10.0.0.200
+a-maximum-rrset.example. 5M IN A 10.0.0.201
+a-maximum-rrset.example. 5M IN A 10.0.0.202
+a-maximum-rrset.example. 5M IN A 10.0.0.203
+a-maximum-rrset.example. 5M IN A 10.0.0.204
+a-maximum-rrset.example. 5M IN A 10.0.0.205
+a-maximum-rrset.example. 5M IN A 10.0.0.206
+a-maximum-rrset.example. 5M IN A 10.0.0.207
+a-maximum-rrset.example. 5M IN A 10.0.0.208
+a-maximum-rrset.example. 5M IN A 10.0.0.209
+a-maximum-rrset.example. 5M IN A 10.0.0.210
+a-maximum-rrset.example. 5M IN A 10.0.0.211
+a-maximum-rrset.example. 5M IN A 10.0.0.212
+a-maximum-rrset.example. 5M IN A 10.0.0.213
+a-maximum-rrset.example. 5M IN A 10.0.0.214
+a-maximum-rrset.example. 5M IN A 10.0.0.215
+a-maximum-rrset.example. 5M IN A 10.0.0.216
+a-maximum-rrset.example. 5M IN A 10.0.0.217
+a-maximum-rrset.example. 5M IN A 10.0.0.218
+a-maximum-rrset.example. 5M IN A 10.0.0.219
+a-maximum-rrset.example. 5M IN A 10.0.0.220
+a-maximum-rrset.example. 5M IN A 10.0.0.221
+a-maximum-rrset.example. 5M IN A 10.0.0.222
+a-maximum-rrset.example. 5M IN A 10.0.0.223
+a-maximum-rrset.example. 5M IN A 10.0.0.224
+a-maximum-rrset.example. 5M IN A 10.0.0.225
+a-maximum-rrset.example. 5M IN A 10.0.0.226
+a-maximum-rrset.example. 5M IN A 10.0.0.227
+a-maximum-rrset.example. 5M IN A 10.0.0.228
+a-maximum-rrset.example. 5M IN A 10.0.0.229
+a-maximum-rrset.example. 5M IN A 10.0.0.230
+a-maximum-rrset.example. 5M IN A 10.0.0.231
+a-maximum-rrset.example. 5M IN A 10.0.0.232
+a-maximum-rrset.example. 5M IN A 10.0.0.233
+a-maximum-rrset.example. 5M IN A 10.0.0.234
+a-maximum-rrset.example. 5M IN A 10.0.0.235
+a-maximum-rrset.example. 5M IN A 10.0.0.236
+a-maximum-rrset.example. 5M IN A 10.0.0.237
+a-maximum-rrset.example. 5M IN A 10.0.0.238
+a-maximum-rrset.example. 5M IN A 10.0.0.239
+a-maximum-rrset.example. 5M IN A 10.0.0.240
+a-maximum-rrset.example. 5M IN A 10.0.0.241
+a-maximum-rrset.example. 5M IN A 10.0.0.242
+a-maximum-rrset.example. 5M IN A 10.0.0.243
+a-maximum-rrset.example. 5M IN A 10.0.0.244
+a-maximum-rrset.example. 5M IN A 10.0.0.245
+a-maximum-rrset.example. 5M IN A 10.0.0.246
+a-maximum-rrset.example. 5M IN A 10.0.0.247
+a-maximum-rrset.example. 5M IN A 10.0.0.248
+a-maximum-rrset.example. 5M IN A 10.0.0.249
+a-maximum-rrset.example. 5M IN A 10.0.0.250
+a-maximum-rrset.example. 5M IN A 10.0.0.251
+a-maximum-rrset.example. 5M IN A 10.0.0.252
+a-maximum-rrset.example. 5M IN A 10.0.0.253
+a-maximum-rrset.example. 5M IN A 10.0.0.254
+a-maximum-rrset.example. 5M IN A 10.0.0.255
+a-maximum-rrset.example. 5M IN A 10.0.1.0
+a-maximum-rrset.example. 5M IN A 10.0.1.1
+a-maximum-rrset.example. 5M IN A 10.0.1.2
+a-maximum-rrset.example. 5M IN A 10.0.1.3
+a-maximum-rrset.example. 5M IN A 10.0.1.4
+a-maximum-rrset.example. 5M IN A 10.0.1.5
+a-maximum-rrset.example. 5M IN A 10.0.1.6
+a-maximum-rrset.example. 5M IN A 10.0.1.7
+a-maximum-rrset.example. 5M IN A 10.0.1.8
+a-maximum-rrset.example. 5M IN A 10.0.1.9
+a-maximum-rrset.example. 5M IN A 10.0.1.10
+a-maximum-rrset.example. 5M IN A 10.0.1.11
+a-maximum-rrset.example. 5M IN A 10.0.1.12
+a-maximum-rrset.example. 5M IN A 10.0.1.13
+a-maximum-rrset.example. 5M IN A 10.0.1.14
+a-maximum-rrset.example. 5M IN A 10.0.1.15
+a-maximum-rrset.example. 5M IN A 10.0.1.16
+a-maximum-rrset.example. 5M IN A 10.0.1.17
+a-maximum-rrset.example. 5M IN A 10.0.1.18
+a-maximum-rrset.example. 5M IN A 10.0.1.19
+a-maximum-rrset.example. 5M IN A 10.0.1.20
+a-maximum-rrset.example. 5M IN A 10.0.1.21
+a-maximum-rrset.example. 5M IN A 10.0.1.22
+a-maximum-rrset.example. 5M IN A 10.0.1.23
+a-maximum-rrset.example. 5M IN A 10.0.1.24
+a-maximum-rrset.example. 5M IN A 10.0.1.25
+a-maximum-rrset.example. 5M IN A 10.0.1.26
+a-maximum-rrset.example. 5M IN A 10.0.1.27
+a-maximum-rrset.example. 5M IN A 10.0.1.28
+a-maximum-rrset.example. 5M IN A 10.0.1.29
+a-maximum-rrset.example. 5M IN A 10.0.1.30
+a-maximum-rrset.example. 5M IN A 10.0.1.31
+a-maximum-rrset.example. 5M IN A 10.0.1.32
+a-maximum-rrset.example. 5M IN A 10.0.1.33
+a-maximum-rrset.example. 5M IN A 10.0.1.34
+a-maximum-rrset.example. 5M IN A 10.0.1.35
+a-maximum-rrset.example. 5M IN A 10.0.1.36
+a-maximum-rrset.example. 5M IN A 10.0.1.37
+a-maximum-rrset.example. 5M IN A 10.0.1.38
+a-maximum-rrset.example. 5M IN A 10.0.1.39
+a-maximum-rrset.example. 5M IN A 10.0.1.40
+a-maximum-rrset.example. 5M IN A 10.0.1.41
+a-maximum-rrset.example. 5M IN A 10.0.1.42
+a-maximum-rrset.example. 5M IN A 10.0.1.43
+a-maximum-rrset.example. 5M IN A 10.0.1.44
+a-maximum-rrset.example. 5M IN A 10.0.1.45
+a-maximum-rrset.example. 5M IN A 10.0.1.46
+a-maximum-rrset.example. 5M IN A 10.0.1.47
+a-maximum-rrset.example. 5M IN A 10.0.1.48
+a-maximum-rrset.example. 5M IN A 10.0.1.49
+a-maximum-rrset.example. 5M IN A 10.0.1.50
+a-maximum-rrset.example. 5M IN A 10.0.1.51
+a-maximum-rrset.example. 5M IN A 10.0.1.52
+a-maximum-rrset.example. 5M IN A 10.0.1.53
+a-maximum-rrset.example. 5M IN A 10.0.1.54
+a-maximum-rrset.example. 5M IN A 10.0.1.55
+a-maximum-rrset.example. 5M IN A 10.0.1.56
+a-maximum-rrset.example. 5M IN A 10.0.1.57
+a-maximum-rrset.example. 5M IN A 10.0.1.58
+a-maximum-rrset.example. 5M IN A 10.0.1.59
+a-maximum-rrset.example. 5M IN A 10.0.1.60
+a-maximum-rrset.example. 5M IN A 10.0.1.61
+a-maximum-rrset.example. 5M IN A 10.0.1.62
+a-maximum-rrset.example. 5M IN A 10.0.1.63
+a-maximum-rrset.example. 5M IN A 10.0.1.64
+a-maximum-rrset.example. 5M IN A 10.0.1.65
+a-maximum-rrset.example. 5M IN A 10.0.1.66
+a-maximum-rrset.example. 5M IN A 10.0.1.67
+a-maximum-rrset.example. 5M IN A 10.0.1.68
+a-maximum-rrset.example. 5M IN A 10.0.1.69
+a-maximum-rrset.example. 5M IN A 10.0.1.70
+a-maximum-rrset.example. 5M IN A 10.0.1.71
+a-maximum-rrset.example. 5M IN A 10.0.1.72
+a-maximum-rrset.example. 5M IN A 10.0.1.73
+a-maximum-rrset.example. 5M IN A 10.0.1.74
+a-maximum-rrset.example. 5M IN A 10.0.1.75
+a-maximum-rrset.example. 5M IN A 10.0.1.76
+a-maximum-rrset.example. 5M IN A 10.0.1.77
+a-maximum-rrset.example. 5M IN A 10.0.1.78
+a-maximum-rrset.example. 5M IN A 10.0.1.79
+a-maximum-rrset.example. 5M IN A 10.0.1.80
+a-maximum-rrset.example. 5M IN A 10.0.1.81
+a-maximum-rrset.example. 5M IN A 10.0.1.82
+a-maximum-rrset.example. 5M IN A 10.0.1.83
+a-maximum-rrset.example. 5M IN A 10.0.1.84
+a-maximum-rrset.example. 5M IN A 10.0.1.85
+a-maximum-rrset.example. 5M IN A 10.0.1.86
+a-maximum-rrset.example. 5M IN A 10.0.1.87
+a-maximum-rrset.example. 5M IN A 10.0.1.88
+a-maximum-rrset.example. 5M IN A 10.0.1.89
+a-maximum-rrset.example. 5M IN A 10.0.1.90
+a-maximum-rrset.example. 5M IN A 10.0.1.91
+a-maximum-rrset.example. 5M IN A 10.0.1.92
+a-maximum-rrset.example. 5M IN A 10.0.1.93
+a-maximum-rrset.example. 5M IN A 10.0.1.94
+a-maximum-rrset.example. 5M IN A 10.0.1.95
+a-maximum-rrset.example. 5M IN A 10.0.1.96
+a-maximum-rrset.example. 5M IN A 10.0.1.97
+a-maximum-rrset.example. 5M IN A 10.0.1.98
+a-maximum-rrset.example. 5M IN A 10.0.1.99
+a-maximum-rrset.example. 5M IN A 10.0.1.100
+a-maximum-rrset.example. 5M IN A 10.0.1.101
+a-maximum-rrset.example. 5M IN A 10.0.1.102
+a-maximum-rrset.example. 5M IN A 10.0.1.103
+a-maximum-rrset.example. 5M IN A 10.0.1.104
+a-maximum-rrset.example. 5M IN A 10.0.1.105
+a-maximum-rrset.example. 5M IN A 10.0.1.106
+a-maximum-rrset.example. 5M IN A 10.0.1.107
+a-maximum-rrset.example. 5M IN A 10.0.1.108
+a-maximum-rrset.example. 5M IN A 10.0.1.109
+a-maximum-rrset.example. 5M IN A 10.0.1.110
+a-maximum-rrset.example. 5M IN A 10.0.1.111
+a-maximum-rrset.example. 5M IN A 10.0.1.112
+a-maximum-rrset.example. 5M IN A 10.0.1.113
+a-maximum-rrset.example. 5M IN A 10.0.1.114
+a-maximum-rrset.example. 5M IN A 10.0.1.115
+a-maximum-rrset.example. 5M IN A 10.0.1.116
+a-maximum-rrset.example. 5M IN A 10.0.1.117
+a-maximum-rrset.example. 5M IN A 10.0.1.118
+a-maximum-rrset.example. 5M IN A 10.0.1.119
+a-maximum-rrset.example. 5M IN A 10.0.1.120
+a-maximum-rrset.example. 5M IN A 10.0.1.121
+a-maximum-rrset.example. 5M IN A 10.0.1.122
+a-maximum-rrset.example. 5M IN A 10.0.1.123
+a-maximum-rrset.example. 5M IN A 10.0.1.124
+a-maximum-rrset.example. 5M IN A 10.0.1.125
+a-maximum-rrset.example. 5M IN A 10.0.1.126
+a-maximum-rrset.example. 5M IN A 10.0.1.127
+a-maximum-rrset.example. 5M IN A 10.0.1.128
+a-maximum-rrset.example. 5M IN A 10.0.1.129
+a-maximum-rrset.example. 5M IN A 10.0.1.130
+a-maximum-rrset.example. 5M IN A 10.0.1.131
+a-maximum-rrset.example. 5M IN A 10.0.1.132
+a-maximum-rrset.example. 5M IN A 10.0.1.133
+a-maximum-rrset.example. 5M IN A 10.0.1.134
+a-maximum-rrset.example. 5M IN A 10.0.1.135
+a-maximum-rrset.example. 5M IN A 10.0.1.136
+a-maximum-rrset.example. 5M IN A 10.0.1.137
+a-maximum-rrset.example. 5M IN A 10.0.1.138
+a-maximum-rrset.example. 5M IN A 10.0.1.139
+a-maximum-rrset.example. 5M IN A 10.0.1.140
+a-maximum-rrset.example. 5M IN A 10.0.1.141
+a-maximum-rrset.example. 5M IN A 10.0.1.142
+a-maximum-rrset.example. 5M IN A 10.0.1.143
+a-maximum-rrset.example. 5M IN A 10.0.1.144
+a-maximum-rrset.example. 5M IN A 10.0.1.145
+a-maximum-rrset.example. 5M IN A 10.0.1.146
+a-maximum-rrset.example. 5M IN A 10.0.1.147
+a-maximum-rrset.example. 5M IN A 10.0.1.148
+a-maximum-rrset.example. 5M IN A 10.0.1.149
+a-maximum-rrset.example. 5M IN A 10.0.1.150
+a-maximum-rrset.example. 5M IN A 10.0.1.151
+a-maximum-rrset.example. 5M IN A 10.0.1.152
+a-maximum-rrset.example. 5M IN A 10.0.1.153
+a-maximum-rrset.example. 5M IN A 10.0.1.154
+a-maximum-rrset.example. 5M IN A 10.0.1.155
+a-maximum-rrset.example. 5M IN A 10.0.1.156
+a-maximum-rrset.example. 5M IN A 10.0.1.157
+a-maximum-rrset.example. 5M IN A 10.0.1.158
+a-maximum-rrset.example. 5M IN A 10.0.1.159
+a-maximum-rrset.example. 5M IN A 10.0.1.160
+a-maximum-rrset.example. 5M IN A 10.0.1.161
+a-maximum-rrset.example. 5M IN A 10.0.1.162
+a-maximum-rrset.example. 5M IN A 10.0.1.163
+a-maximum-rrset.example. 5M IN A 10.0.1.164
+a-maximum-rrset.example. 5M IN A 10.0.1.165
+a-maximum-rrset.example. 5M IN A 10.0.1.166
+a-maximum-rrset.example. 5M IN A 10.0.1.167
+a-maximum-rrset.example. 5M IN A 10.0.1.168
+a-maximum-rrset.example. 5M IN A 10.0.1.169
+a-maximum-rrset.example. 5M IN A 10.0.1.170
+a-maximum-rrset.example. 5M IN A 10.0.1.171
+a-maximum-rrset.example. 5M IN A 10.0.1.172
+a-maximum-rrset.example. 5M IN A 10.0.1.173
+a-maximum-rrset.example. 5M IN A 10.0.1.174
+a-maximum-rrset.example. 5M IN A 10.0.1.175
+a-maximum-rrset.example. 5M IN A 10.0.1.176
+a-maximum-rrset.example. 5M IN A 10.0.1.177
+a-maximum-rrset.example. 5M IN A 10.0.1.178
+a-maximum-rrset.example. 5M IN A 10.0.1.179
+a-maximum-rrset.example. 5M IN A 10.0.1.180
+a-maximum-rrset.example. 5M IN A 10.0.1.181
+a-maximum-rrset.example. 5M IN A 10.0.1.182
+a-maximum-rrset.example. 5M IN A 10.0.1.183
+a-maximum-rrset.example. 5M IN A 10.0.1.184
+a-maximum-rrset.example. 5M IN A 10.0.1.185
+a-maximum-rrset.example. 5M IN A 10.0.1.186
+a-maximum-rrset.example. 5M IN A 10.0.1.187
+a-maximum-rrset.example. 5M IN A 10.0.1.188
+a-maximum-rrset.example. 5M IN A 10.0.1.189
+a-maximum-rrset.example. 5M IN A 10.0.1.190
+a-maximum-rrset.example. 5M IN A 10.0.1.191
+a-maximum-rrset.example. 5M IN A 10.0.1.192
+a-maximum-rrset.example. 5M IN A 10.0.1.193
+a-maximum-rrset.example. 5M IN A 10.0.1.194
+a-maximum-rrset.example. 5M IN A 10.0.1.195
+a-maximum-rrset.example. 5M IN A 10.0.1.196
+a-maximum-rrset.example. 5M IN A 10.0.1.197
+a-maximum-rrset.example. 5M IN A 10.0.1.198
+a-maximum-rrset.example. 5M IN A 10.0.1.199
+a-maximum-rrset.example. 5M IN A 10.0.1.200
+a-maximum-rrset.example. 5M IN A 10.0.1.201
+a-maximum-rrset.example. 5M IN A 10.0.1.202
+a-maximum-rrset.example. 5M IN A 10.0.1.203
+a-maximum-rrset.example. 5M IN A 10.0.1.204
+a-maximum-rrset.example. 5M IN A 10.0.1.205
+a-maximum-rrset.example. 5M IN A 10.0.1.206
+a-maximum-rrset.example. 5M IN A 10.0.1.207
+a-maximum-rrset.example. 5M IN A 10.0.1.208
+a-maximum-rrset.example. 5M IN A 10.0.1.209
+a-maximum-rrset.example. 5M IN A 10.0.1.210
+a-maximum-rrset.example. 5M IN A 10.0.1.211
+a-maximum-rrset.example. 5M IN A 10.0.1.212
+a-maximum-rrset.example. 5M IN A 10.0.1.213
+a-maximum-rrset.example. 5M IN A 10.0.1.214
+a-maximum-rrset.example. 5M IN A 10.0.1.215
+a-maximum-rrset.example. 5M IN A 10.0.1.216
+a-maximum-rrset.example. 5M IN A 10.0.1.217
+a-maximum-rrset.example. 5M IN A 10.0.1.218
+a-maximum-rrset.example. 5M IN A 10.0.1.219
+a-maximum-rrset.example. 5M IN A 10.0.1.220
+a-maximum-rrset.example. 5M IN A 10.0.1.221
+a-maximum-rrset.example. 5M IN A 10.0.1.222
+a-maximum-rrset.example. 5M IN A 10.0.1.223
+a-maximum-rrset.example. 5M IN A 10.0.1.224
+a-maximum-rrset.example. 5M IN A 10.0.1.225
+a-maximum-rrset.example. 5M IN A 10.0.1.226
+a-maximum-rrset.example. 5M IN A 10.0.1.227
+a-maximum-rrset.example. 5M IN A 10.0.1.228
+a-maximum-rrset.example. 5M IN A 10.0.1.229
+a-maximum-rrset.example. 5M IN A 10.0.1.230
+a-maximum-rrset.example. 5M IN A 10.0.1.231
+a-maximum-rrset.example. 5M IN A 10.0.1.232
+a-maximum-rrset.example. 5M IN A 10.0.1.233
+a-maximum-rrset.example. 5M IN A 10.0.1.234
+a-maximum-rrset.example. 5M IN A 10.0.1.235
+a-maximum-rrset.example. 5M IN A 10.0.1.236
+a-maximum-rrset.example. 5M IN A 10.0.1.237
+a-maximum-rrset.example. 5M IN A 10.0.1.238
+a-maximum-rrset.example. 5M IN A 10.0.1.239
+a-maximum-rrset.example. 5M IN A 10.0.1.240
+a-maximum-rrset.example. 5M IN A 10.0.1.241
+a-maximum-rrset.example. 5M IN A 10.0.1.242
+a-maximum-rrset.example. 5M IN A 10.0.1.243
+a-maximum-rrset.example. 5M IN A 10.0.1.244
+a-maximum-rrset.example. 5M IN A 10.0.1.245
+a-maximum-rrset.example. 5M IN A 10.0.1.246
+a-maximum-rrset.example. 5M IN A 10.0.1.247
+a-maximum-rrset.example. 5M IN A 10.0.1.248
+a-maximum-rrset.example. 5M IN A 10.0.1.249
+a-maximum-rrset.example. 5M IN A 10.0.1.250
+a-maximum-rrset.example. 5M IN A 10.0.1.251
+a-maximum-rrset.example. 5M IN A 10.0.1.252
+a-maximum-rrset.example. 5M IN A 10.0.1.253
+a-maximum-rrset.example. 5M IN A 10.0.1.254
+a-maximum-rrset.example. 5M IN A 10.0.1.255
+a-maximum-rrset.example. 5M IN A 10.0.2.0
+a-maximum-rrset.example. 5M IN A 10.0.2.1
+a-maximum-rrset.example. 5M IN A 10.0.2.2
+a-maximum-rrset.example. 5M IN A 10.0.2.3
+a-maximum-rrset.example. 5M IN A 10.0.2.4
+a-maximum-rrset.example. 5M IN A 10.0.2.5
+a-maximum-rrset.example. 5M IN A 10.0.2.6
+a-maximum-rrset.example. 5M IN A 10.0.2.7
+a-maximum-rrset.example. 5M IN A 10.0.2.8
+a-maximum-rrset.example. 5M IN A 10.0.2.9
+a-maximum-rrset.example. 5M IN A 10.0.2.10
+a-maximum-rrset.example. 5M IN A 10.0.2.11
+a-maximum-rrset.example. 5M IN A 10.0.2.12
+a-maximum-rrset.example. 5M IN A 10.0.2.13
+a-maximum-rrset.example. 5M IN A 10.0.2.14
+a-maximum-rrset.example. 5M IN A 10.0.2.15
+a-maximum-rrset.example. 5M IN A 10.0.2.16
+a-maximum-rrset.example. 5M IN A 10.0.2.17
+a-maximum-rrset.example. 5M IN A 10.0.2.18
+a-maximum-rrset.example. 5M IN A 10.0.2.19
+a-maximum-rrset.example. 5M IN A 10.0.2.20
+a-maximum-rrset.example. 5M IN A 10.0.2.21
+a-maximum-rrset.example. 5M IN A 10.0.2.22
+a-maximum-rrset.example. 5M IN A 10.0.2.23
+a-maximum-rrset.example. 5M IN A 10.0.2.24
+a-maximum-rrset.example. 5M IN A 10.0.2.25
+a-maximum-rrset.example. 5M IN A 10.0.2.26
+a-maximum-rrset.example. 5M IN A 10.0.2.27
+a-maximum-rrset.example. 5M IN A 10.0.2.28
+a-maximum-rrset.example. 5M IN A 10.0.2.29
+a-maximum-rrset.example. 5M IN A 10.0.2.30
+a-maximum-rrset.example. 5M IN A 10.0.2.31
+a-maximum-rrset.example. 5M IN A 10.0.2.32
+a-maximum-rrset.example. 5M IN A 10.0.2.33
+a-maximum-rrset.example. 5M IN A 10.0.2.34
+a-maximum-rrset.example. 5M IN A 10.0.2.35
+a-maximum-rrset.example. 5M IN A 10.0.2.36
+a-maximum-rrset.example. 5M IN A 10.0.2.37
+a-maximum-rrset.example. 5M IN A 10.0.2.38
+a-maximum-rrset.example. 5M IN A 10.0.2.39
+a-maximum-rrset.example. 5M IN A 10.0.2.40
+a-maximum-rrset.example. 5M IN A 10.0.2.41
+a-maximum-rrset.example. 5M IN A 10.0.2.42
+a-maximum-rrset.example. 5M IN A 10.0.2.43
+a-maximum-rrset.example. 5M IN A 10.0.2.44
+a-maximum-rrset.example. 5M IN A 10.0.2.45
+a-maximum-rrset.example. 5M IN A 10.0.2.46
+a-maximum-rrset.example. 5M IN A 10.0.2.47
+a-maximum-rrset.example. 5M IN A 10.0.2.48
+a-maximum-rrset.example. 5M IN A 10.0.2.49
+a-maximum-rrset.example. 5M IN A 10.0.2.50
+a-maximum-rrset.example. 5M IN A 10.0.2.51
+a-maximum-rrset.example. 5M IN A 10.0.2.52
+a-maximum-rrset.example. 5M IN A 10.0.2.53
+a-maximum-rrset.example. 5M IN A 10.0.2.54
+a-maximum-rrset.example. 5M IN A 10.0.2.55
+a-maximum-rrset.example. 5M IN A 10.0.2.56
+a-maximum-rrset.example. 5M IN A 10.0.2.57
+a-maximum-rrset.example. 5M IN A 10.0.2.58
+a-maximum-rrset.example. 5M IN A 10.0.2.59
+a-maximum-rrset.example. 5M IN A 10.0.2.60
+a-maximum-rrset.example. 5M IN A 10.0.2.61
+a-maximum-rrset.example. 5M IN A 10.0.2.62
+a-maximum-rrset.example. 5M IN A 10.0.2.63
+a-maximum-rrset.example. 5M IN A 10.0.2.64
+a-maximum-rrset.example. 5M IN A 10.0.2.65
+a-maximum-rrset.example. 5M IN A 10.0.2.66
+a-maximum-rrset.example. 5M IN A 10.0.2.67
+a-maximum-rrset.example. 5M IN A 10.0.2.68
+a-maximum-rrset.example. 5M IN A 10.0.2.69
+a-maximum-rrset.example. 5M IN A 10.0.2.70
+a-maximum-rrset.example. 5M IN A 10.0.2.71
+a-maximum-rrset.example. 5M IN A 10.0.2.72
+a-maximum-rrset.example. 5M IN A 10.0.2.73
+a-maximum-rrset.example. 5M IN A 10.0.2.74
+a-maximum-rrset.example. 5M IN A 10.0.2.75
+a-maximum-rrset.example. 5M IN A 10.0.2.76
+a-maximum-rrset.example. 5M IN A 10.0.2.77
+a-maximum-rrset.example. 5M IN A 10.0.2.78
+a-maximum-rrset.example. 5M IN A 10.0.2.79
+a-maximum-rrset.example. 5M IN A 10.0.2.80
+a-maximum-rrset.example. 5M IN A 10.0.2.81
+a-maximum-rrset.example. 5M IN A 10.0.2.82
+a-maximum-rrset.example. 5M IN A 10.0.2.83
+a-maximum-rrset.example. 5M IN A 10.0.2.84
+a-maximum-rrset.example. 5M IN A 10.0.2.85
+a-maximum-rrset.example. 5M IN A 10.0.2.86
+a-maximum-rrset.example. 5M IN A 10.0.2.87
+a-maximum-rrset.example. 5M IN A 10.0.2.88
+a-maximum-rrset.example. 5M IN A 10.0.2.89
+a-maximum-rrset.example. 5M IN A 10.0.2.90
+a-maximum-rrset.example. 5M IN A 10.0.2.91
+a-maximum-rrset.example. 5M IN A 10.0.2.92
+a-maximum-rrset.example. 5M IN A 10.0.2.93
+a-maximum-rrset.example. 5M IN A 10.0.2.94
+a-maximum-rrset.example. 5M IN A 10.0.2.95
+a-maximum-rrset.example. 5M IN A 10.0.2.96
+a-maximum-rrset.example. 5M IN A 10.0.2.97
+a-maximum-rrset.example. 5M IN A 10.0.2.98
+a-maximum-rrset.example. 5M IN A 10.0.2.99
+a-maximum-rrset.example. 5M IN A 10.0.2.100
+a-maximum-rrset.example. 5M IN A 10.0.2.101
+a-maximum-rrset.example. 5M IN A 10.0.2.102
+a-maximum-rrset.example. 5M IN A 10.0.2.103
+a-maximum-rrset.example. 5M IN A 10.0.2.104
+a-maximum-rrset.example. 5M IN A 10.0.2.105
+a-maximum-rrset.example. 5M IN A 10.0.2.106
+a-maximum-rrset.example. 5M IN A 10.0.2.107
+a-maximum-rrset.example. 5M IN A 10.0.2.108
+a-maximum-rrset.example. 5M IN A 10.0.2.109
+a-maximum-rrset.example. 5M IN A 10.0.2.110
+a-maximum-rrset.example. 5M IN A 10.0.2.111
+a-maximum-rrset.example. 5M IN A 10.0.2.112
+a-maximum-rrset.example. 5M IN A 10.0.2.113
+a-maximum-rrset.example. 5M IN A 10.0.2.114
+a-maximum-rrset.example. 5M IN A 10.0.2.115
+a-maximum-rrset.example. 5M IN A 10.0.2.116
+a-maximum-rrset.example. 5M IN A 10.0.2.117
+a-maximum-rrset.example. 5M IN A 10.0.2.118
+a-maximum-rrset.example. 5M IN A 10.0.2.119
+a-maximum-rrset.example. 5M IN A 10.0.2.120
+a-maximum-rrset.example. 5M IN A 10.0.2.121
+a-maximum-rrset.example. 5M IN A 10.0.2.122
+a-maximum-rrset.example. 5M IN A 10.0.2.123
+a-maximum-rrset.example. 5M IN A 10.0.2.124
+a-maximum-rrset.example. 5M IN A 10.0.2.125
+a-maximum-rrset.example. 5M IN A 10.0.2.126
+a-maximum-rrset.example. 5M IN A 10.0.2.127
+a-maximum-rrset.example. 5M IN A 10.0.2.128
+a-maximum-rrset.example. 5M IN A 10.0.2.129
+a-maximum-rrset.example. 5M IN A 10.0.2.130
+a-maximum-rrset.example. 5M IN A 10.0.2.131
+a-maximum-rrset.example. 5M IN A 10.0.2.132
+a-maximum-rrset.example. 5M IN A 10.0.2.133
+a-maximum-rrset.example. 5M IN A 10.0.2.134
+a-maximum-rrset.example. 5M IN A 10.0.2.135
+a-maximum-rrset.example. 5M IN A 10.0.2.136
+a-maximum-rrset.example. 5M IN A 10.0.2.137
+a-maximum-rrset.example. 5M IN A 10.0.2.138
+a-maximum-rrset.example. 5M IN A 10.0.2.139
+a-maximum-rrset.example. 5M IN A 10.0.2.140
+a-maximum-rrset.example. 5M IN A 10.0.2.141
+a-maximum-rrset.example. 5M IN A 10.0.2.142
+a-maximum-rrset.example. 5M IN A 10.0.2.143
+a-maximum-rrset.example. 5M IN A 10.0.2.144
+a-maximum-rrset.example. 5M IN A 10.0.2.145
+a-maximum-rrset.example. 5M IN A 10.0.2.146
+a-maximum-rrset.example. 5M IN A 10.0.2.147
+a-maximum-rrset.example. 5M IN A 10.0.2.148
+a-maximum-rrset.example. 5M IN A 10.0.2.149
+a-maximum-rrset.example. 5M IN A 10.0.2.150
+a-maximum-rrset.example. 5M IN A 10.0.2.151
+a-maximum-rrset.example. 5M IN A 10.0.2.152
+a-maximum-rrset.example. 5M IN A 10.0.2.153
+a-maximum-rrset.example. 5M IN A 10.0.2.154
+a-maximum-rrset.example. 5M IN A 10.0.2.155
+a-maximum-rrset.example. 5M IN A 10.0.2.156
+a-maximum-rrset.example. 5M IN A 10.0.2.157
+a-maximum-rrset.example. 5M IN A 10.0.2.158
+a-maximum-rrset.example. 5M IN A 10.0.2.159
+a-maximum-rrset.example. 5M IN A 10.0.2.160
+a-maximum-rrset.example. 5M IN A 10.0.2.161
+a-maximum-rrset.example. 5M IN A 10.0.2.162
+a-maximum-rrset.example. 5M IN A 10.0.2.163
+a-maximum-rrset.example. 5M IN A 10.0.2.164
+a-maximum-rrset.example. 5M IN A 10.0.2.165
+a-maximum-rrset.example. 5M IN A 10.0.2.166
+a-maximum-rrset.example. 5M IN A 10.0.2.167
+a-maximum-rrset.example. 5M IN A 10.0.2.168
+a-maximum-rrset.example. 5M IN A 10.0.2.169
+a-maximum-rrset.example. 5M IN A 10.0.2.170
+a-maximum-rrset.example. 5M IN A 10.0.2.171
+a-maximum-rrset.example. 5M IN A 10.0.2.172
+a-maximum-rrset.example. 5M IN A 10.0.2.173
+a-maximum-rrset.example. 5M IN A 10.0.2.174
+a-maximum-rrset.example. 5M IN A 10.0.2.175
+a-maximum-rrset.example. 5M IN A 10.0.2.176
+a-maximum-rrset.example. 5M IN A 10.0.2.177
+a-maximum-rrset.example. 5M IN A 10.0.2.178
+a-maximum-rrset.example. 5M IN A 10.0.2.179
+a-maximum-rrset.example. 5M IN A 10.0.2.180
+a-maximum-rrset.example. 5M IN A 10.0.2.181
+a-maximum-rrset.example. 5M IN A 10.0.2.182
+a-maximum-rrset.example. 5M IN A 10.0.2.183
+a-maximum-rrset.example. 5M IN A 10.0.2.184
+a-maximum-rrset.example. 5M IN A 10.0.2.185
+a-maximum-rrset.example. 5M IN A 10.0.2.186
+a-maximum-rrset.example. 5M IN A 10.0.2.187
+a-maximum-rrset.example. 5M IN A 10.0.2.188
+a-maximum-rrset.example. 5M IN A 10.0.2.189
+a-maximum-rrset.example. 5M IN A 10.0.2.190
+a-maximum-rrset.example. 5M IN A 10.0.2.191
+a-maximum-rrset.example. 5M IN A 10.0.2.192
+a-maximum-rrset.example. 5M IN A 10.0.2.193
+a-maximum-rrset.example. 5M IN A 10.0.2.194
+a-maximum-rrset.example. 5M IN A 10.0.2.195
+a-maximum-rrset.example. 5M IN A 10.0.2.196
+a-maximum-rrset.example. 5M IN A 10.0.2.197
+a-maximum-rrset.example. 5M IN A 10.0.2.198
+a-maximum-rrset.example. 5M IN A 10.0.2.199
+a-maximum-rrset.example. 5M IN A 10.0.2.200
+a-maximum-rrset.example. 5M IN A 10.0.2.201
+a-maximum-rrset.example. 5M IN A 10.0.2.202
+a-maximum-rrset.example. 5M IN A 10.0.2.203
+a-maximum-rrset.example. 5M IN A 10.0.2.204
+a-maximum-rrset.example. 5M IN A 10.0.2.205
+a-maximum-rrset.example. 5M IN A 10.0.2.206
+a-maximum-rrset.example. 5M IN A 10.0.2.207
+a-maximum-rrset.example. 5M IN A 10.0.2.208
+a-maximum-rrset.example. 5M IN A 10.0.2.209
+a-maximum-rrset.example. 5M IN A 10.0.2.210
+a-maximum-rrset.example. 5M IN A 10.0.2.211
+a-maximum-rrset.example. 5M IN A 10.0.2.212
+a-maximum-rrset.example. 5M IN A 10.0.2.213
+a-maximum-rrset.example. 5M IN A 10.0.2.214
+a-maximum-rrset.example. 5M IN A 10.0.2.215
+a-maximum-rrset.example. 5M IN A 10.0.2.216
+a-maximum-rrset.example. 5M IN A 10.0.2.217
+a-maximum-rrset.example. 5M IN A 10.0.2.218
+a-maximum-rrset.example. 5M IN A 10.0.2.219
+a-maximum-rrset.example. 5M IN A 10.0.2.220
+a-maximum-rrset.example. 5M IN A 10.0.2.221
+a-maximum-rrset.example. 5M IN A 10.0.2.222
+a-maximum-rrset.example. 5M IN A 10.0.2.223
+a-maximum-rrset.example. 5M IN A 10.0.2.224
+a-maximum-rrset.example. 5M IN A 10.0.2.225
+a-maximum-rrset.example. 5M IN A 10.0.2.226
+a-maximum-rrset.example. 5M IN A 10.0.2.227
+a-maximum-rrset.example. 5M IN A 10.0.2.228
+a-maximum-rrset.example. 5M IN A 10.0.2.229
+a-maximum-rrset.example. 5M IN A 10.0.2.230
+a-maximum-rrset.example. 5M IN A 10.0.2.231
+a-maximum-rrset.example. 5M IN A 10.0.2.232
+a-maximum-rrset.example. 5M IN A 10.0.2.233
+a-maximum-rrset.example. 5M IN A 10.0.2.234
+a-maximum-rrset.example. 5M IN A 10.0.2.235
+a-maximum-rrset.example. 5M IN A 10.0.2.236
+a-maximum-rrset.example. 5M IN A 10.0.2.237
+a-maximum-rrset.example. 5M IN A 10.0.2.238
+a-maximum-rrset.example. 5M IN A 10.0.2.239
+a-maximum-rrset.example. 5M IN A 10.0.2.240
+a-maximum-rrset.example. 5M IN A 10.0.2.241
+a-maximum-rrset.example. 5M IN A 10.0.2.242
+a-maximum-rrset.example. 5M IN A 10.0.2.243
+a-maximum-rrset.example. 5M IN A 10.0.2.244
+a-maximum-rrset.example. 5M IN A 10.0.2.245
+a-maximum-rrset.example. 5M IN A 10.0.2.246
+a-maximum-rrset.example. 5M IN A 10.0.2.247
+a-maximum-rrset.example. 5M IN A 10.0.2.248
+a-maximum-rrset.example. 5M IN A 10.0.2.249
+a-maximum-rrset.example. 5M IN A 10.0.2.250
+a-maximum-rrset.example. 5M IN A 10.0.2.251
+a-maximum-rrset.example. 5M IN A 10.0.2.252
+a-maximum-rrset.example. 5M IN A 10.0.2.253
+a-maximum-rrset.example. 5M IN A 10.0.2.254
+a-maximum-rrset.example. 5M IN A 10.0.2.255
+a-maximum-rrset.example. 5M IN A 10.0.3.0
+a-maximum-rrset.example. 5M IN A 10.0.3.1
+a-maximum-rrset.example. 5M IN A 10.0.3.2
+a-maximum-rrset.example. 5M IN A 10.0.3.3
+a-maximum-rrset.example. 5M IN A 10.0.3.4
+a-maximum-rrset.example. 5M IN A 10.0.3.5
+a-maximum-rrset.example. 5M IN A 10.0.3.6
+a-maximum-rrset.example. 5M IN A 10.0.3.7
+a-maximum-rrset.example. 5M IN A 10.0.3.8
+a-maximum-rrset.example. 5M IN A 10.0.3.9
+a-maximum-rrset.example. 5M IN A 10.0.3.10
+a-maximum-rrset.example. 5M IN A 10.0.3.11
+a-maximum-rrset.example. 5M IN A 10.0.3.12
+a-maximum-rrset.example. 5M IN A 10.0.3.13
+a-maximum-rrset.example. 5M IN A 10.0.3.14
+a-maximum-rrset.example. 5M IN A 10.0.3.15
+a-maximum-rrset.example. 5M IN A 10.0.3.16
+a-maximum-rrset.example. 5M IN A 10.0.3.17
+a-maximum-rrset.example. 5M IN A 10.0.3.18
+a-maximum-rrset.example. 5M IN A 10.0.3.19
+a-maximum-rrset.example. 5M IN A 10.0.3.20
+a-maximum-rrset.example. 5M IN A 10.0.3.21
+a-maximum-rrset.example. 5M IN A 10.0.3.22
+a-maximum-rrset.example. 5M IN A 10.0.3.23
+a-maximum-rrset.example. 5M IN A 10.0.3.24
+a-maximum-rrset.example. 5M IN A 10.0.3.25
+a-maximum-rrset.example. 5M IN A 10.0.3.26
+a-maximum-rrset.example. 5M IN A 10.0.3.27
+a-maximum-rrset.example. 5M IN A 10.0.3.28
+a-maximum-rrset.example. 5M IN A 10.0.3.29
+a-maximum-rrset.example. 5M IN A 10.0.3.30
+a-maximum-rrset.example. 5M IN A 10.0.3.31
+a-maximum-rrset.example. 5M IN A 10.0.3.32
+a-maximum-rrset.example. 5M IN A 10.0.3.33
+a-maximum-rrset.example. 5M IN A 10.0.3.34
+a-maximum-rrset.example. 5M IN A 10.0.3.35
+a-maximum-rrset.example. 5M IN A 10.0.3.36
+a-maximum-rrset.example. 5M IN A 10.0.3.37
+a-maximum-rrset.example. 5M IN A 10.0.3.38
+a-maximum-rrset.example. 5M IN A 10.0.3.39
+a-maximum-rrset.example. 5M IN A 10.0.3.40
+a-maximum-rrset.example. 5M IN A 10.0.3.41
+a-maximum-rrset.example. 5M IN A 10.0.3.42
+a-maximum-rrset.example. 5M IN A 10.0.3.43
+a-maximum-rrset.example. 5M IN A 10.0.3.44
+a-maximum-rrset.example. 5M IN A 10.0.3.45
+a-maximum-rrset.example. 5M IN A 10.0.3.46
+a-maximum-rrset.example. 5M IN A 10.0.3.47
+a-maximum-rrset.example. 5M IN A 10.0.3.48
+a-maximum-rrset.example. 5M IN A 10.0.3.49
+a-maximum-rrset.example. 5M IN A 10.0.3.50
+a-maximum-rrset.example. 5M IN A 10.0.3.51
+a-maximum-rrset.example. 5M IN A 10.0.3.52
+a-maximum-rrset.example. 5M IN A 10.0.3.53
+a-maximum-rrset.example. 5M IN A 10.0.3.54
+a-maximum-rrset.example. 5M IN A 10.0.3.55
+a-maximum-rrset.example. 5M IN A 10.0.3.56
+a-maximum-rrset.example. 5M IN A 10.0.3.57
+a-maximum-rrset.example. 5M IN A 10.0.3.58
+a-maximum-rrset.example. 5M IN A 10.0.3.59
+a-maximum-rrset.example. 5M IN A 10.0.3.60
+a-maximum-rrset.example. 5M IN A 10.0.3.61
+a-maximum-rrset.example. 5M IN A 10.0.3.62
+a-maximum-rrset.example. 5M IN A 10.0.3.63
+a-maximum-rrset.example. 5M IN A 10.0.3.64
+a-maximum-rrset.example. 5M IN A 10.0.3.65
+a-maximum-rrset.example. 5M IN A 10.0.3.66
+a-maximum-rrset.example. 5M IN A 10.0.3.67
+a-maximum-rrset.example. 5M IN A 10.0.3.68
+a-maximum-rrset.example. 5M IN A 10.0.3.69
+a-maximum-rrset.example. 5M IN A 10.0.3.70
+a-maximum-rrset.example. 5M IN A 10.0.3.71
+a-maximum-rrset.example. 5M IN A 10.0.3.72
+a-maximum-rrset.example. 5M IN A 10.0.3.73
+a-maximum-rrset.example. 5M IN A 10.0.3.74
+a-maximum-rrset.example. 5M IN A 10.0.3.75
+a-maximum-rrset.example. 5M IN A 10.0.3.76
+a-maximum-rrset.example. 5M IN A 10.0.3.77
+a-maximum-rrset.example. 5M IN A 10.0.3.78
+a-maximum-rrset.example. 5M IN A 10.0.3.79
+a-maximum-rrset.example. 5M IN A 10.0.3.80
+a-maximum-rrset.example. 5M IN A 10.0.3.81
+a-maximum-rrset.example. 5M IN A 10.0.3.82
+a-maximum-rrset.example. 5M IN A 10.0.3.83
+a-maximum-rrset.example. 5M IN A 10.0.3.84
+a-maximum-rrset.example. 5M IN A 10.0.3.85
+a-maximum-rrset.example. 5M IN A 10.0.3.86
+a-maximum-rrset.example. 5M IN A 10.0.3.87
+a-maximum-rrset.example. 5M IN A 10.0.3.88
+a-maximum-rrset.example. 5M IN A 10.0.3.89
+a-maximum-rrset.example. 5M IN A 10.0.3.90
+a-maximum-rrset.example. 5M IN A 10.0.3.91
+a-maximum-rrset.example. 5M IN A 10.0.3.92
+a-maximum-rrset.example. 5M IN A 10.0.3.93
+a-maximum-rrset.example. 5M IN A 10.0.3.94
+a-maximum-rrset.example. 5M IN A 10.0.3.95
+a-maximum-rrset.example. 5M IN A 10.0.3.96
+a-maximum-rrset.example. 5M IN A 10.0.3.97
+a-maximum-rrset.example. 5M IN A 10.0.3.98
+a-maximum-rrset.example. 5M IN A 10.0.3.99
+a-maximum-rrset.example. 5M IN A 10.0.3.100
+a-maximum-rrset.example. 5M IN A 10.0.3.101
+a-maximum-rrset.example. 5M IN A 10.0.3.102
+a-maximum-rrset.example. 5M IN A 10.0.3.103
+a-maximum-rrset.example. 5M IN A 10.0.3.104
+a-maximum-rrset.example. 5M IN A 10.0.3.105
+a-maximum-rrset.example. 5M IN A 10.0.3.106
+a-maximum-rrset.example. 5M IN A 10.0.3.107
+a-maximum-rrset.example. 5M IN A 10.0.3.108
+a-maximum-rrset.example. 5M IN A 10.0.3.109
+a-maximum-rrset.example. 5M IN A 10.0.3.110
+a-maximum-rrset.example. 5M IN A 10.0.3.111
+a-maximum-rrset.example. 5M IN A 10.0.3.112
+a-maximum-rrset.example. 5M IN A 10.0.3.113
+a-maximum-rrset.example. 5M IN A 10.0.3.114
+a-maximum-rrset.example. 5M IN A 10.0.3.115
+a-maximum-rrset.example. 5M IN A 10.0.3.116
+a-maximum-rrset.example. 5M IN A 10.0.3.117
+a-maximum-rrset.example. 5M IN A 10.0.3.118
+a-maximum-rrset.example. 5M IN A 10.0.3.119
+a-maximum-rrset.example. 5M IN A 10.0.3.120
+a-maximum-rrset.example. 5M IN A 10.0.3.121
+a-maximum-rrset.example. 5M IN A 10.0.3.122
+a-maximum-rrset.example. 5M IN A 10.0.3.123
+a-maximum-rrset.example. 5M IN A 10.0.3.124
+a-maximum-rrset.example. 5M IN A 10.0.3.125
+a-maximum-rrset.example. 5M IN A 10.0.3.126
+a-maximum-rrset.example. 5M IN A 10.0.3.127
+a-maximum-rrset.example. 5M IN A 10.0.3.128
+a-maximum-rrset.example. 5M IN A 10.0.3.129
+a-maximum-rrset.example. 5M IN A 10.0.3.130
+a-maximum-rrset.example. 5M IN A 10.0.3.131
+a-maximum-rrset.example. 5M IN A 10.0.3.132
+a-maximum-rrset.example. 5M IN A 10.0.3.133
+a-maximum-rrset.example. 5M IN A 10.0.3.134
+a-maximum-rrset.example. 5M IN A 10.0.3.135
+a-maximum-rrset.example. 5M IN A 10.0.3.136
+a-maximum-rrset.example. 5M IN A 10.0.3.137
+a-maximum-rrset.example. 5M IN A 10.0.3.138
+a-maximum-rrset.example. 5M IN A 10.0.3.139
+a-maximum-rrset.example. 5M IN A 10.0.3.140
+a-maximum-rrset.example. 5M IN A 10.0.3.141
+a-maximum-rrset.example. 5M IN A 10.0.3.142
+a-maximum-rrset.example. 5M IN A 10.0.3.143
+a-maximum-rrset.example. 5M IN A 10.0.3.144
+a-maximum-rrset.example. 5M IN A 10.0.3.145
+a-maximum-rrset.example. 5M IN A 10.0.3.146
+a-maximum-rrset.example. 5M IN A 10.0.3.147
+a-maximum-rrset.example. 5M IN A 10.0.3.148
+a-maximum-rrset.example. 5M IN A 10.0.3.149
+a-maximum-rrset.example. 5M IN A 10.0.3.150
+a-maximum-rrset.example. 5M IN A 10.0.3.151
+a-maximum-rrset.example. 5M IN A 10.0.3.152
+a-maximum-rrset.example. 5M IN A 10.0.3.153
+a-maximum-rrset.example. 5M IN A 10.0.3.154
+a-maximum-rrset.example. 5M IN A 10.0.3.155
+a-maximum-rrset.example. 5M IN A 10.0.3.156
+a-maximum-rrset.example. 5M IN A 10.0.3.157
+a-maximum-rrset.example. 5M IN A 10.0.3.158
+a-maximum-rrset.example. 5M IN A 10.0.3.159
+a-maximum-rrset.example. 5M IN A 10.0.3.160
+a-maximum-rrset.example. 5M IN A 10.0.3.161
+a-maximum-rrset.example. 5M IN A 10.0.3.162
+a-maximum-rrset.example. 5M IN A 10.0.3.163
+a-maximum-rrset.example. 5M IN A 10.0.3.164
+a-maximum-rrset.example. 5M IN A 10.0.3.165
+a-maximum-rrset.example. 5M IN A 10.0.3.166
+a-maximum-rrset.example. 5M IN A 10.0.3.167
+a-maximum-rrset.example. 5M IN A 10.0.3.168
+a-maximum-rrset.example. 5M IN A 10.0.3.169
+a-maximum-rrset.example. 5M IN A 10.0.3.170
+a-maximum-rrset.example. 5M IN A 10.0.3.171
+a-maximum-rrset.example. 5M IN A 10.0.3.172
+a-maximum-rrset.example. 5M IN A 10.0.3.173
+a-maximum-rrset.example. 5M IN A 10.0.3.174
+a-maximum-rrset.example. 5M IN A 10.0.3.175
+a-maximum-rrset.example. 5M IN A 10.0.3.176
+a-maximum-rrset.example. 5M IN A 10.0.3.177
+a-maximum-rrset.example. 5M IN A 10.0.3.178
+a-maximum-rrset.example. 5M IN A 10.0.3.179
+a-maximum-rrset.example. 5M IN A 10.0.3.180
+a-maximum-rrset.example. 5M IN A 10.0.3.181
+a-maximum-rrset.example. 5M IN A 10.0.3.182
+a-maximum-rrset.example. 5M IN A 10.0.3.183
+a-maximum-rrset.example. 5M IN A 10.0.3.184
+a-maximum-rrset.example. 5M IN A 10.0.3.185
+a-maximum-rrset.example. 5M IN A 10.0.3.186
+a-maximum-rrset.example. 5M IN A 10.0.3.187
+a-maximum-rrset.example. 5M IN A 10.0.3.188
+a-maximum-rrset.example. 5M IN A 10.0.3.189
+a-maximum-rrset.example. 5M IN A 10.0.3.190
+a-maximum-rrset.example. 5M IN A 10.0.3.191
+a-maximum-rrset.example. 5M IN A 10.0.3.192
+a-maximum-rrset.example. 5M IN A 10.0.3.193
+a-maximum-rrset.example. 5M IN A 10.0.3.194
+a-maximum-rrset.example. 5M IN A 10.0.3.195
+a-maximum-rrset.example. 5M IN A 10.0.3.196
+a-maximum-rrset.example. 5M IN A 10.0.3.197
+a-maximum-rrset.example. 5M IN A 10.0.3.198
+a-maximum-rrset.example. 5M IN A 10.0.3.199
+a-maximum-rrset.example. 5M IN A 10.0.3.200
+a-maximum-rrset.example. 5M IN A 10.0.3.201
+a-maximum-rrset.example. 5M IN A 10.0.3.202
+a-maximum-rrset.example. 5M IN A 10.0.3.203
+a-maximum-rrset.example. 5M IN A 10.0.3.204
+a-maximum-rrset.example. 5M IN A 10.0.3.205
+a-maximum-rrset.example. 5M IN A 10.0.3.206
+a-maximum-rrset.example. 5M IN A 10.0.3.207
+a-maximum-rrset.example. 5M IN A 10.0.3.208
+a-maximum-rrset.example. 5M IN A 10.0.3.209
+a-maximum-rrset.example. 5M IN A 10.0.3.210
+a-maximum-rrset.example. 5M IN A 10.0.3.211
+a-maximum-rrset.example. 5M IN A 10.0.3.212
+a-maximum-rrset.example. 5M IN A 10.0.3.213
+a-maximum-rrset.example. 5M IN A 10.0.3.214
+a-maximum-rrset.example. 5M IN A 10.0.3.215
+a-maximum-rrset.example. 5M IN A 10.0.3.216
+a-maximum-rrset.example. 5M IN A 10.0.3.217
+a-maximum-rrset.example. 5M IN A 10.0.3.218
+a-maximum-rrset.example. 5M IN A 10.0.3.219
+a-maximum-rrset.example. 5M IN A 10.0.3.220
+a-maximum-rrset.example. 5M IN A 10.0.3.221
+a-maximum-rrset.example. 5M IN A 10.0.3.222
+a-maximum-rrset.example. 5M IN A 10.0.3.223
+a-maximum-rrset.example. 5M IN A 10.0.3.224
+a-maximum-rrset.example. 5M IN A 10.0.3.225
+a-maximum-rrset.example. 5M IN A 10.0.3.226
+a-maximum-rrset.example. 5M IN A 10.0.3.227
+a-maximum-rrset.example. 5M IN A 10.0.3.228
+a-maximum-rrset.example. 5M IN A 10.0.3.229
+a-maximum-rrset.example. 5M IN A 10.0.3.230
+a-maximum-rrset.example. 5M IN A 10.0.3.231
+a-maximum-rrset.example. 5M IN A 10.0.3.232
+a-maximum-rrset.example. 5M IN A 10.0.3.233
+a-maximum-rrset.example. 5M IN A 10.0.3.234
+a-maximum-rrset.example. 5M IN A 10.0.3.235
+a-maximum-rrset.example. 5M IN A 10.0.3.236
+a-maximum-rrset.example. 5M IN A 10.0.3.237
+a-maximum-rrset.example. 5M IN A 10.0.3.238
+a-maximum-rrset.example. 5M IN A 10.0.3.239
+a-maximum-rrset.example. 5M IN A 10.0.3.240
+a-maximum-rrset.example. 5M IN A 10.0.3.241
+a-maximum-rrset.example. 5M IN A 10.0.3.242
+a-maximum-rrset.example. 5M IN A 10.0.3.243
+a-maximum-rrset.example. 5M IN A 10.0.3.244
+a-maximum-rrset.example. 5M IN A 10.0.3.245
+a-maximum-rrset.example. 5M IN A 10.0.3.246
+a-maximum-rrset.example. 5M IN A 10.0.3.247
+a-maximum-rrset.example. 5M IN A 10.0.3.248
+a-maximum-rrset.example. 5M IN A 10.0.3.249
+a-maximum-rrset.example. 5M IN A 10.0.3.250
+a-maximum-rrset.example. 5M IN A 10.0.3.251
+a-maximum-rrset.example. 5M IN A 10.0.3.252
+a-maximum-rrset.example. 5M IN A 10.0.3.253
+a-maximum-rrset.example. 5M IN A 10.0.3.254
+a-maximum-rrset.example. 5M IN A 10.0.3.255
+a-maximum-rrset.example. 5M IN A 10.0.4.0
+a-maximum-rrset.example. 5M IN A 10.0.4.1
+a-maximum-rrset.example. 5M IN A 10.0.4.2
+a-maximum-rrset.example. 5M IN A 10.0.4.3
+a-maximum-rrset.example. 5M IN A 10.0.4.4
+a-maximum-rrset.example. 5M IN A 10.0.4.5
+a-maximum-rrset.example. 5M IN A 10.0.4.6
+a-maximum-rrset.example. 5M IN A 10.0.4.7
+a-maximum-rrset.example. 5M IN A 10.0.4.8
+a-maximum-rrset.example. 5M IN A 10.0.4.9
+a-maximum-rrset.example. 5M IN A 10.0.4.10
+a-maximum-rrset.example. 5M IN A 10.0.4.11
+a-maximum-rrset.example. 5M IN A 10.0.4.12
+a-maximum-rrset.example. 5M IN A 10.0.4.13
+a-maximum-rrset.example. 5M IN A 10.0.4.14
+a-maximum-rrset.example. 5M IN A 10.0.4.15
+a-maximum-rrset.example. 5M IN A 10.0.4.16
+a-maximum-rrset.example. 5M IN A 10.0.4.17
+a-maximum-rrset.example. 5M IN A 10.0.4.18
+a-maximum-rrset.example. 5M IN A 10.0.4.19
+a-maximum-rrset.example. 5M IN A 10.0.4.20
+a-maximum-rrset.example. 5M IN A 10.0.4.21
+a-maximum-rrset.example. 5M IN A 10.0.4.22
+a-maximum-rrset.example. 5M IN A 10.0.4.23
+a-maximum-rrset.example. 5M IN A 10.0.4.24
+a-maximum-rrset.example. 5M IN A 10.0.4.25
+a-maximum-rrset.example. 5M IN A 10.0.4.26
+a-maximum-rrset.example. 5M IN A 10.0.4.27
+a-maximum-rrset.example. 5M IN A 10.0.4.28
+a-maximum-rrset.example. 5M IN A 10.0.4.29
+a-maximum-rrset.example. 5M IN A 10.0.4.30
+a-maximum-rrset.example. 5M IN A 10.0.4.31
+a-maximum-rrset.example. 5M IN A 10.0.4.32
+a-maximum-rrset.example. 5M IN A 10.0.4.33
+a-maximum-rrset.example. 5M IN A 10.0.4.34
+a-maximum-rrset.example. 5M IN A 10.0.4.35
+a-maximum-rrset.example. 5M IN A 10.0.4.36
+a-maximum-rrset.example. 5M IN A 10.0.4.37
+a-maximum-rrset.example. 5M IN A 10.0.4.38
+a-maximum-rrset.example. 5M IN A 10.0.4.39
+a-maximum-rrset.example. 5M IN A 10.0.4.40
+a-maximum-rrset.example. 5M IN A 10.0.4.41
+a-maximum-rrset.example. 5M IN A 10.0.4.42
+a-maximum-rrset.example. 5M IN A 10.0.4.43
+a-maximum-rrset.example. 5M IN A 10.0.4.44
+a-maximum-rrset.example. 5M IN A 10.0.4.45
+a-maximum-rrset.example. 5M IN A 10.0.4.46
+a-maximum-rrset.example. 5M IN A 10.0.4.47
+a-maximum-rrset.example. 5M IN A 10.0.4.48
+a-maximum-rrset.example. 5M IN A 10.0.4.49
+a-maximum-rrset.example. 5M IN A 10.0.4.50
+a-maximum-rrset.example. 5M IN A 10.0.4.51
+a-maximum-rrset.example. 5M IN A 10.0.4.52
+a-maximum-rrset.example. 5M IN A 10.0.4.53
+a-maximum-rrset.example. 5M IN A 10.0.4.54
+a-maximum-rrset.example. 5M IN A 10.0.4.55
+a-maximum-rrset.example. 5M IN A 10.0.4.56
+a-maximum-rrset.example. 5M IN A 10.0.4.57
+a-maximum-rrset.example. 5M IN A 10.0.4.58
+a-maximum-rrset.example. 5M IN A 10.0.4.59
+a-maximum-rrset.example. 5M IN A 10.0.4.60
+a-maximum-rrset.example. 5M IN A 10.0.4.61
+a-maximum-rrset.example. 5M IN A 10.0.4.62
+a-maximum-rrset.example. 5M IN A 10.0.4.63
+a-maximum-rrset.example. 5M IN A 10.0.4.64
+a-maximum-rrset.example. 5M IN A 10.0.4.65
+a-maximum-rrset.example. 5M IN A 10.0.4.66
+a-maximum-rrset.example. 5M IN A 10.0.4.67
+a-maximum-rrset.example. 5M IN A 10.0.4.68
+a-maximum-rrset.example. 5M IN A 10.0.4.69
+a-maximum-rrset.example. 5M IN A 10.0.4.70
+a-maximum-rrset.example. 5M IN A 10.0.4.71
+a-maximum-rrset.example. 5M IN A 10.0.4.72
+a-maximum-rrset.example. 5M IN A 10.0.4.73
+a-maximum-rrset.example. 5M IN A 10.0.4.74
+a-maximum-rrset.example. 5M IN A 10.0.4.75
+a-maximum-rrset.example. 5M IN A 10.0.4.76
+a-maximum-rrset.example. 5M IN A 10.0.4.77
+a-maximum-rrset.example. 5M IN A 10.0.4.78
+a-maximum-rrset.example. 5M IN A 10.0.4.79
+a-maximum-rrset.example. 5M IN A 10.0.4.80
+a-maximum-rrset.example. 5M IN A 10.0.4.81
+a-maximum-rrset.example. 5M IN A 10.0.4.82
+a-maximum-rrset.example. 5M IN A 10.0.4.83
+a-maximum-rrset.example. 5M IN A 10.0.4.84
+a-maximum-rrset.example. 5M IN A 10.0.4.85
+a-maximum-rrset.example. 5M IN A 10.0.4.86
+a-maximum-rrset.example. 5M IN A 10.0.4.87
+a-maximum-rrset.example. 5M IN A 10.0.4.88
+a-maximum-rrset.example. 5M IN A 10.0.4.89
+a-maximum-rrset.example. 5M IN A 10.0.4.90
+a-maximum-rrset.example. 5M IN A 10.0.4.91
+a-maximum-rrset.example. 5M IN A 10.0.4.92
+a-maximum-rrset.example. 5M IN A 10.0.4.93
+a-maximum-rrset.example. 5M IN A 10.0.4.94
+a-maximum-rrset.example. 5M IN A 10.0.4.95
+a-maximum-rrset.example. 5M IN A 10.0.4.96
+a-maximum-rrset.example. 5M IN A 10.0.4.97
+a-maximum-rrset.example. 5M IN A 10.0.4.98
+a-maximum-rrset.example. 5M IN A 10.0.4.99
+a-maximum-rrset.example. 5M IN A 10.0.4.100
+a-maximum-rrset.example. 5M IN A 10.0.4.101
+a-maximum-rrset.example. 5M IN A 10.0.4.102
+a-maximum-rrset.example. 5M IN A 10.0.4.103
+a-maximum-rrset.example. 5M IN A 10.0.4.104
+a-maximum-rrset.example. 5M IN A 10.0.4.105
+a-maximum-rrset.example. 5M IN A 10.0.4.106
+a-maximum-rrset.example. 5M IN A 10.0.4.107
+a-maximum-rrset.example. 5M IN A 10.0.4.108
+a-maximum-rrset.example. 5M IN A 10.0.4.109
+a-maximum-rrset.example. 5M IN A 10.0.4.110
+a-maximum-rrset.example. 5M IN A 10.0.4.111
+a-maximum-rrset.example. 5M IN A 10.0.4.112
+a-maximum-rrset.example. 5M IN A 10.0.4.113
+a-maximum-rrset.example. 5M IN A 10.0.4.114
+a-maximum-rrset.example. 5M IN A 10.0.4.115
+a-maximum-rrset.example. 5M IN A 10.0.4.116
+a-maximum-rrset.example. 5M IN A 10.0.4.117
+a-maximum-rrset.example. 5M IN A 10.0.4.118
+a-maximum-rrset.example. 5M IN A 10.0.4.119
+a-maximum-rrset.example. 5M IN A 10.0.4.120
+a-maximum-rrset.example. 5M IN A 10.0.4.121
+a-maximum-rrset.example. 5M IN A 10.0.4.122
+a-maximum-rrset.example. 5M IN A 10.0.4.123
+a-maximum-rrset.example. 5M IN A 10.0.4.124
+a-maximum-rrset.example. 5M IN A 10.0.4.125
+a-maximum-rrset.example. 5M IN A 10.0.4.126
+a-maximum-rrset.example. 5M IN A 10.0.4.127
+a-maximum-rrset.example. 5M IN A 10.0.4.128
+a-maximum-rrset.example. 5M IN A 10.0.4.129
+a-maximum-rrset.example. 5M IN A 10.0.4.130
+a-maximum-rrset.example. 5M IN A 10.0.4.131
+a-maximum-rrset.example. 5M IN A 10.0.4.132
+a-maximum-rrset.example. 5M IN A 10.0.4.133
+a-maximum-rrset.example. 5M IN A 10.0.4.134
+a-maximum-rrset.example. 5M IN A 10.0.4.135
+a-maximum-rrset.example. 5M IN A 10.0.4.136
+a-maximum-rrset.example. 5M IN A 10.0.4.137
+a-maximum-rrset.example. 5M IN A 10.0.4.138
+a-maximum-rrset.example. 5M IN A 10.0.4.139
+a-maximum-rrset.example. 5M IN A 10.0.4.140
+a-maximum-rrset.example. 5M IN A 10.0.4.141
+a-maximum-rrset.example. 5M IN A 10.0.4.142
+a-maximum-rrset.example. 5M IN A 10.0.4.143
+a-maximum-rrset.example. 5M IN A 10.0.4.144
+a-maximum-rrset.example. 5M IN A 10.0.4.145
+a-maximum-rrset.example. 5M IN A 10.0.4.146
+a-maximum-rrset.example. 5M IN A 10.0.4.147
+a-maximum-rrset.example. 5M IN A 10.0.4.148
+a-maximum-rrset.example. 5M IN A 10.0.4.149
+a-maximum-rrset.example. 5M IN A 10.0.4.150
+a-maximum-rrset.example. 5M IN A 10.0.4.151
+a-maximum-rrset.example. 5M IN A 10.0.4.152
+a-maximum-rrset.example. 5M IN A 10.0.4.153
+a-maximum-rrset.example. 5M IN A 10.0.4.154
+a-maximum-rrset.example. 5M IN A 10.0.4.155
+a-maximum-rrset.example. 5M IN A 10.0.4.156
+a-maximum-rrset.example. 5M IN A 10.0.4.157
+a-maximum-rrset.example. 5M IN A 10.0.4.158
+a-maximum-rrset.example. 5M IN A 10.0.4.159
+a-maximum-rrset.example. 5M IN A 10.0.4.160
+a-maximum-rrset.example. 5M IN A 10.0.4.161
+a-maximum-rrset.example. 5M IN A 10.0.4.162
+a-maximum-rrset.example. 5M IN A 10.0.4.163
+a-maximum-rrset.example. 5M IN A 10.0.4.164
+a-maximum-rrset.example. 5M IN A 10.0.4.165
+a-maximum-rrset.example. 5M IN A 10.0.4.166
+a-maximum-rrset.example. 5M IN A 10.0.4.167
+a-maximum-rrset.example. 5M IN A 10.0.4.168
+a-maximum-rrset.example. 5M IN A 10.0.4.169
+a-maximum-rrset.example. 5M IN A 10.0.4.170
+a-maximum-rrset.example. 5M IN A 10.0.4.171
+a-maximum-rrset.example. 5M IN A 10.0.4.172
+a-maximum-rrset.example. 5M IN A 10.0.4.173
+a-maximum-rrset.example. 5M IN A 10.0.4.174
+a-maximum-rrset.example. 5M IN A 10.0.4.175
+a-maximum-rrset.example. 5M IN A 10.0.4.176
+a-maximum-rrset.example. 5M IN A 10.0.4.177
+a-maximum-rrset.example. 5M IN A 10.0.4.178
+a-maximum-rrset.example. 5M IN A 10.0.4.179
+a-maximum-rrset.example. 5M IN A 10.0.4.180
+a-maximum-rrset.example. 5M IN A 10.0.4.181
+a-maximum-rrset.example. 5M IN A 10.0.4.182
+a-maximum-rrset.example. 5M IN A 10.0.4.183
+a-maximum-rrset.example. 5M IN A 10.0.4.184
+a-maximum-rrset.example. 5M IN A 10.0.4.185
+a-maximum-rrset.example. 5M IN A 10.0.4.186
+a-maximum-rrset.example. 5M IN A 10.0.4.187
+a-maximum-rrset.example. 5M IN A 10.0.4.188
+a-maximum-rrset.example. 5M IN A 10.0.4.189
+a-maximum-rrset.example. 5M IN A 10.0.4.190
+a-maximum-rrset.example. 5M IN A 10.0.4.191
+a-maximum-rrset.example. 5M IN A 10.0.4.192
+a-maximum-rrset.example. 5M IN A 10.0.4.193
+a-maximum-rrset.example. 5M IN A 10.0.4.194
+a-maximum-rrset.example. 5M IN A 10.0.4.195
+a-maximum-rrset.example. 5M IN A 10.0.4.196
+a-maximum-rrset.example. 5M IN A 10.0.4.197
+a-maximum-rrset.example. 5M IN A 10.0.4.198
+a-maximum-rrset.example. 5M IN A 10.0.4.199
+a-maximum-rrset.example. 5M IN A 10.0.4.200
+a-maximum-rrset.example. 5M IN A 10.0.4.201
+a-maximum-rrset.example. 5M IN A 10.0.4.202
+a-maximum-rrset.example. 5M IN A 10.0.4.203
+a-maximum-rrset.example. 5M IN A 10.0.4.204
+a-maximum-rrset.example. 5M IN A 10.0.4.205
+a-maximum-rrset.example. 5M IN A 10.0.4.206
+a-maximum-rrset.example. 5M IN A 10.0.4.207
+a-maximum-rrset.example. 5M IN A 10.0.4.208
+a-maximum-rrset.example. 5M IN A 10.0.4.209
+a-maximum-rrset.example. 5M IN A 10.0.4.210
+a-maximum-rrset.example. 5M IN A 10.0.4.211
+a-maximum-rrset.example. 5M IN A 10.0.4.212
+a-maximum-rrset.example. 5M IN A 10.0.4.213
+a-maximum-rrset.example. 5M IN A 10.0.4.214
+a-maximum-rrset.example. 5M IN A 10.0.4.215
+a-maximum-rrset.example. 5M IN A 10.0.4.216
+a-maximum-rrset.example. 5M IN A 10.0.4.217
+a-maximum-rrset.example. 5M IN A 10.0.4.218
+a-maximum-rrset.example. 5M IN A 10.0.4.219
+a-maximum-rrset.example. 5M IN A 10.0.4.220
+a-maximum-rrset.example. 5M IN A 10.0.4.221
+a-maximum-rrset.example. 5M IN A 10.0.4.222
+a-maximum-rrset.example. 5M IN A 10.0.4.223
+a-maximum-rrset.example. 5M IN A 10.0.4.224
+a-maximum-rrset.example. 5M IN A 10.0.4.225
+a-maximum-rrset.example. 5M IN A 10.0.4.226
+a-maximum-rrset.example. 5M IN A 10.0.4.227
+a-maximum-rrset.example. 5M IN A 10.0.4.228
+a-maximum-rrset.example. 5M IN A 10.0.4.229
+a-maximum-rrset.example. 5M IN A 10.0.4.230
+a-maximum-rrset.example. 5M IN A 10.0.4.231
+a-maximum-rrset.example. 5M IN A 10.0.4.232
+a-maximum-rrset.example. 5M IN A 10.0.4.233
+a-maximum-rrset.example. 5M IN A 10.0.4.234
+a-maximum-rrset.example. 5M IN A 10.0.4.235
+a-maximum-rrset.example. 5M IN A 10.0.4.236
+a-maximum-rrset.example. 5M IN A 10.0.4.237
+a-maximum-rrset.example. 5M IN A 10.0.4.238
+a-maximum-rrset.example. 5M IN A 10.0.4.239
+a-maximum-rrset.example. 5M IN A 10.0.4.240
+a-maximum-rrset.example. 5M IN A 10.0.4.241
+a-maximum-rrset.example. 5M IN A 10.0.4.242
+a-maximum-rrset.example. 5M IN A 10.0.4.243
+a-maximum-rrset.example. 5M IN A 10.0.4.244
+a-maximum-rrset.example. 5M IN A 10.0.4.245
+a-maximum-rrset.example. 5M IN A 10.0.4.246
+a-maximum-rrset.example. 5M IN A 10.0.4.247
+a-maximum-rrset.example. 5M IN A 10.0.4.248
+a-maximum-rrset.example. 5M IN A 10.0.4.249
+a-maximum-rrset.example. 5M IN A 10.0.4.250
+a-maximum-rrset.example. 5M IN A 10.0.4.251
+a-maximum-rrset.example. 5M IN A 10.0.4.252
+a-maximum-rrset.example. 5M IN A 10.0.4.253
+a-maximum-rrset.example. 5M IN A 10.0.4.254
+a-maximum-rrset.example. 5M IN A 10.0.4.255
+a-maximum-rrset.example. 5M IN A 10.0.5.0
+a-maximum-rrset.example. 5M IN A 10.0.5.1
+a-maximum-rrset.example. 5M IN A 10.0.5.2
+a-maximum-rrset.example. 5M IN A 10.0.5.3
+a-maximum-rrset.example. 5M IN A 10.0.5.4
+a-maximum-rrset.example. 5M IN A 10.0.5.5
+a-maximum-rrset.example. 5M IN A 10.0.5.6
+a-maximum-rrset.example. 5M IN A 10.0.5.7
+a-maximum-rrset.example. 5M IN A 10.0.5.8
+a-maximum-rrset.example. 5M IN A 10.0.5.9
+a-maximum-rrset.example. 5M IN A 10.0.5.10
+a-maximum-rrset.example. 5M IN A 10.0.5.11
+a-maximum-rrset.example. 5M IN A 10.0.5.12
+a-maximum-rrset.example. 5M IN A 10.0.5.13
+a-maximum-rrset.example. 5M IN A 10.0.5.14
+a-maximum-rrset.example. 5M IN A 10.0.5.15
+a-maximum-rrset.example. 5M IN A 10.0.5.16
+a-maximum-rrset.example. 5M IN A 10.0.5.17
+a-maximum-rrset.example. 5M IN A 10.0.5.18
+a-maximum-rrset.example. 5M IN A 10.0.5.19
+a-maximum-rrset.example. 5M IN A 10.0.5.20
+a-maximum-rrset.example. 5M IN A 10.0.5.21
+a-maximum-rrset.example. 5M IN A 10.0.5.22
+a-maximum-rrset.example. 5M IN A 10.0.5.23
+a-maximum-rrset.example. 5M IN A 10.0.5.24
+a-maximum-rrset.example. 5M IN A 10.0.5.25
+a-maximum-rrset.example. 5M IN A 10.0.5.26
+a-maximum-rrset.example. 5M IN A 10.0.5.27
+a-maximum-rrset.example. 5M IN A 10.0.5.28
+a-maximum-rrset.example. 5M IN A 10.0.5.29
+a-maximum-rrset.example. 5M IN A 10.0.5.30
+a-maximum-rrset.example. 5M IN A 10.0.5.31
+a-maximum-rrset.example. 5M IN A 10.0.5.32
+a-maximum-rrset.example. 5M IN A 10.0.5.33
+a-maximum-rrset.example. 5M IN A 10.0.5.34
+a-maximum-rrset.example. 5M IN A 10.0.5.35
+a-maximum-rrset.example. 5M IN A 10.0.5.36
+a-maximum-rrset.example. 5M IN A 10.0.5.37
+a-maximum-rrset.example. 5M IN A 10.0.5.38
+a-maximum-rrset.example. 5M IN A 10.0.5.39
+a-maximum-rrset.example. 5M IN A 10.0.5.40
+a-maximum-rrset.example. 5M IN A 10.0.5.41
+a-maximum-rrset.example. 5M IN A 10.0.5.42
+a-maximum-rrset.example. 5M IN A 10.0.5.43
+a-maximum-rrset.example. 5M IN A 10.0.5.44
+a-maximum-rrset.example. 5M IN A 10.0.5.45
+a-maximum-rrset.example. 5M IN A 10.0.5.46
+a-maximum-rrset.example. 5M IN A 10.0.5.47
+a-maximum-rrset.example. 5M IN A 10.0.5.48
+a-maximum-rrset.example. 5M IN A 10.0.5.49
+a-maximum-rrset.example. 5M IN A 10.0.5.50
+a-maximum-rrset.example. 5M IN A 10.0.5.51
+a-maximum-rrset.example. 5M IN A 10.0.5.52
+a-maximum-rrset.example. 5M IN A 10.0.5.53
+a-maximum-rrset.example. 5M IN A 10.0.5.54
+a-maximum-rrset.example. 5M IN A 10.0.5.55
+a-maximum-rrset.example. 5M IN A 10.0.5.56
+a-maximum-rrset.example. 5M IN A 10.0.5.57
+a-maximum-rrset.example. 5M IN A 10.0.5.58
+a-maximum-rrset.example. 5M IN A 10.0.5.59
+a-maximum-rrset.example. 5M IN A 10.0.5.60
+a-maximum-rrset.example. 5M IN A 10.0.5.61
+a-maximum-rrset.example. 5M IN A 10.0.5.62
+a-maximum-rrset.example. 5M IN A 10.0.5.63
+a-maximum-rrset.example. 5M IN A 10.0.5.64
+a-maximum-rrset.example. 5M IN A 10.0.5.65
+a-maximum-rrset.example. 5M IN A 10.0.5.66
+a-maximum-rrset.example. 5M IN A 10.0.5.67
+a-maximum-rrset.example. 5M IN A 10.0.5.68
+a-maximum-rrset.example. 5M IN A 10.0.5.69
+a-maximum-rrset.example. 5M IN A 10.0.5.70
+a-maximum-rrset.example. 5M IN A 10.0.5.71
+a-maximum-rrset.example. 5M IN A 10.0.5.72
+a-maximum-rrset.example. 5M IN A 10.0.5.73
+a-maximum-rrset.example. 5M IN A 10.0.5.74
+a-maximum-rrset.example. 5M IN A 10.0.5.75
+a-maximum-rrset.example. 5M IN A 10.0.5.76
+a-maximum-rrset.example. 5M IN A 10.0.5.77
+a-maximum-rrset.example. 5M IN A 10.0.5.78
+a-maximum-rrset.example. 5M IN A 10.0.5.79
+a-maximum-rrset.example. 5M IN A 10.0.5.80
+a-maximum-rrset.example. 5M IN A 10.0.5.81
+a-maximum-rrset.example. 5M IN A 10.0.5.82
+a-maximum-rrset.example. 5M IN A 10.0.5.83
+a-maximum-rrset.example. 5M IN A 10.0.5.84
+a-maximum-rrset.example. 5M IN A 10.0.5.85
+a-maximum-rrset.example. 5M IN A 10.0.5.86
+a-maximum-rrset.example. 5M IN A 10.0.5.87
+a-maximum-rrset.example. 5M IN A 10.0.5.88
+a-maximum-rrset.example. 5M IN A 10.0.5.89
+a-maximum-rrset.example. 5M IN A 10.0.5.90
+a-maximum-rrset.example. 5M IN A 10.0.5.91
+a-maximum-rrset.example. 5M IN A 10.0.5.92
+a-maximum-rrset.example. 5M IN A 10.0.5.93
+a-maximum-rrset.example. 5M IN A 10.0.5.94
+a-maximum-rrset.example. 5M IN A 10.0.5.95
+a-maximum-rrset.example. 5M IN A 10.0.5.96
+a-maximum-rrset.example. 5M IN A 10.0.5.97
+a-maximum-rrset.example. 5M IN A 10.0.5.98
+a-maximum-rrset.example. 5M IN A 10.0.5.99
+a-maximum-rrset.example. 5M IN A 10.0.5.100
+a-maximum-rrset.example. 5M IN A 10.0.5.101
+a-maximum-rrset.example. 5M IN A 10.0.5.102
+a-maximum-rrset.example. 5M IN A 10.0.5.103
+a-maximum-rrset.example. 5M IN A 10.0.5.104
+a-maximum-rrset.example. 5M IN A 10.0.5.105
+a-maximum-rrset.example. 5M IN A 10.0.5.106
+a-maximum-rrset.example. 5M IN A 10.0.5.107
+a-maximum-rrset.example. 5M IN A 10.0.5.108
+a-maximum-rrset.example. 5M IN A 10.0.5.109
+a-maximum-rrset.example. 5M IN A 10.0.5.110
+a-maximum-rrset.example. 5M IN A 10.0.5.111
+a-maximum-rrset.example. 5M IN A 10.0.5.112
+a-maximum-rrset.example. 5M IN A 10.0.5.113
+a-maximum-rrset.example. 5M IN A 10.0.5.114
+a-maximum-rrset.example. 5M IN A 10.0.5.115
+a-maximum-rrset.example. 5M IN A 10.0.5.116
+a-maximum-rrset.example. 5M IN A 10.0.5.117
+a-maximum-rrset.example. 5M IN A 10.0.5.118
+a-maximum-rrset.example. 5M IN A 10.0.5.119
+a-maximum-rrset.example. 5M IN A 10.0.5.120
+a-maximum-rrset.example. 5M IN A 10.0.5.121
+a-maximum-rrset.example. 5M IN A 10.0.5.122
+a-maximum-rrset.example. 5M IN A 10.0.5.123
+a-maximum-rrset.example. 5M IN A 10.0.5.124
+a-maximum-rrset.example. 5M IN A 10.0.5.125
+a-maximum-rrset.example. 5M IN A 10.0.5.126
+a-maximum-rrset.example. 5M IN A 10.0.5.127
+a-maximum-rrset.example. 5M IN A 10.0.5.128
+a-maximum-rrset.example. 5M IN A 10.0.5.129
+a-maximum-rrset.example. 5M IN A 10.0.5.130
+a-maximum-rrset.example. 5M IN A 10.0.5.131
+a-maximum-rrset.example. 5M IN A 10.0.5.132
+a-maximum-rrset.example. 5M IN A 10.0.5.133
+a-maximum-rrset.example. 5M IN A 10.0.5.134
+a-maximum-rrset.example. 5M IN A 10.0.5.135
+a-maximum-rrset.example. 5M IN A 10.0.5.136
+a-maximum-rrset.example. 5M IN A 10.0.5.137
+a-maximum-rrset.example. 5M IN A 10.0.5.138
+a-maximum-rrset.example. 5M IN A 10.0.5.139
+a-maximum-rrset.example. 5M IN A 10.0.5.140
+a-maximum-rrset.example. 5M IN A 10.0.5.141
+a-maximum-rrset.example. 5M IN A 10.0.5.142
+a-maximum-rrset.example. 5M IN A 10.0.5.143
+a-maximum-rrset.example. 5M IN A 10.0.5.144
+a-maximum-rrset.example. 5M IN A 10.0.5.145
+a-maximum-rrset.example. 5M IN A 10.0.5.146
+a-maximum-rrset.example. 5M IN A 10.0.5.147
+a-maximum-rrset.example. 5M IN A 10.0.5.148
+a-maximum-rrset.example. 5M IN A 10.0.5.149
+a-maximum-rrset.example. 5M IN A 10.0.5.150
+a-maximum-rrset.example. 5M IN A 10.0.5.151
+a-maximum-rrset.example. 5M IN A 10.0.5.152
+a-maximum-rrset.example. 5M IN A 10.0.5.153
+a-maximum-rrset.example. 5M IN A 10.0.5.154
+a-maximum-rrset.example. 5M IN A 10.0.5.155
+a-maximum-rrset.example. 5M IN A 10.0.5.156
+a-maximum-rrset.example. 5M IN A 10.0.5.157
+a-maximum-rrset.example. 5M IN A 10.0.5.158
+a-maximum-rrset.example. 5M IN A 10.0.5.159
+a-maximum-rrset.example. 5M IN A 10.0.5.160
+a-maximum-rrset.example. 5M IN A 10.0.5.161
+a-maximum-rrset.example. 5M IN A 10.0.5.162
+a-maximum-rrset.example. 5M IN A 10.0.5.163
+a-maximum-rrset.example. 5M IN A 10.0.5.164
+a-maximum-rrset.example. 5M IN A 10.0.5.165
+a-maximum-rrset.example. 5M IN A 10.0.5.166
+a-maximum-rrset.example. 5M IN A 10.0.5.167
+a-maximum-rrset.example. 5M IN A 10.0.5.168
+a-maximum-rrset.example. 5M IN A 10.0.5.169
+a-maximum-rrset.example. 5M IN A 10.0.5.170
+a-maximum-rrset.example. 5M IN A 10.0.5.171
+a-maximum-rrset.example. 5M IN A 10.0.5.172
+a-maximum-rrset.example. 5M IN A 10.0.5.173
+a-maximum-rrset.example. 5M IN A 10.0.5.174
+a-maximum-rrset.example. 5M IN A 10.0.5.175
+a-maximum-rrset.example. 5M IN A 10.0.5.176
+a-maximum-rrset.example. 5M IN A 10.0.5.177
+a-maximum-rrset.example. 5M IN A 10.0.5.178
+a-maximum-rrset.example. 5M IN A 10.0.5.179
+a-maximum-rrset.example. 5M IN A 10.0.5.180
+a-maximum-rrset.example. 5M IN A 10.0.5.181
+a-maximum-rrset.example. 5M IN A 10.0.5.182
+a-maximum-rrset.example. 5M IN A 10.0.5.183
+a-maximum-rrset.example. 5M IN A 10.0.5.184
+a-maximum-rrset.example. 5M IN A 10.0.5.185
+a-maximum-rrset.example. 5M IN A 10.0.5.186
+a-maximum-rrset.example. 5M IN A 10.0.5.187
+a-maximum-rrset.example. 5M IN A 10.0.5.188
+a-maximum-rrset.example. 5M IN A 10.0.5.189
+a-maximum-rrset.example. 5M IN A 10.0.5.190
+a-maximum-rrset.example. 5M IN A 10.0.5.191
+a-maximum-rrset.example. 5M IN A 10.0.5.192
+a-maximum-rrset.example. 5M IN A 10.0.5.193
+a-maximum-rrset.example. 5M IN A 10.0.5.194
+a-maximum-rrset.example. 5M IN A 10.0.5.195
+a-maximum-rrset.example. 5M IN A 10.0.5.196
+a-maximum-rrset.example. 5M IN A 10.0.5.197
+a-maximum-rrset.example. 5M IN A 10.0.5.198
+a-maximum-rrset.example. 5M IN A 10.0.5.199
+a-maximum-rrset.example. 5M IN A 10.0.5.200
+a-maximum-rrset.example. 5M IN A 10.0.5.201
+a-maximum-rrset.example. 5M IN A 10.0.5.202
+a-maximum-rrset.example. 5M IN A 10.0.5.203
+a-maximum-rrset.example. 5M IN A 10.0.5.204
+a-maximum-rrset.example. 5M IN A 10.0.5.205
+a-maximum-rrset.example. 5M IN A 10.0.5.206
+a-maximum-rrset.example. 5M IN A 10.0.5.207
+a-maximum-rrset.example. 5M IN A 10.0.5.208
+a-maximum-rrset.example. 5M IN A 10.0.5.209
+a-maximum-rrset.example. 5M IN A 10.0.5.210
+a-maximum-rrset.example. 5M IN A 10.0.5.211
+a-maximum-rrset.example. 5M IN A 10.0.5.212
+a-maximum-rrset.example. 5M IN A 10.0.5.213
+a-maximum-rrset.example. 5M IN A 10.0.5.214
+a-maximum-rrset.example. 5M IN A 10.0.5.215
+a-maximum-rrset.example. 5M IN A 10.0.5.216
+a-maximum-rrset.example. 5M IN A 10.0.5.217
+a-maximum-rrset.example. 5M IN A 10.0.5.218
+a-maximum-rrset.example. 5M IN A 10.0.5.219
+a-maximum-rrset.example. 5M IN A 10.0.5.220
+a-maximum-rrset.example. 5M IN A 10.0.5.221
+a-maximum-rrset.example. 5M IN A 10.0.5.222
+a-maximum-rrset.example. 5M IN A 10.0.5.223
+a-maximum-rrset.example. 5M IN A 10.0.5.224
+a-maximum-rrset.example. 5M IN A 10.0.5.225
+a-maximum-rrset.example. 5M IN A 10.0.5.226
+a-maximum-rrset.example. 5M IN A 10.0.5.227
+a-maximum-rrset.example. 5M IN A 10.0.5.228
+a-maximum-rrset.example. 5M IN A 10.0.5.229
+a-maximum-rrset.example. 5M IN A 10.0.5.230
+a-maximum-rrset.example. 5M IN A 10.0.5.231
+a-maximum-rrset.example. 5M IN A 10.0.5.232
+a-maximum-rrset.example. 5M IN A 10.0.5.233
+a-maximum-rrset.example. 5M IN A 10.0.5.234
+a-maximum-rrset.example. 5M IN A 10.0.5.235
+a-maximum-rrset.example. 5M IN A 10.0.5.236
+a-maximum-rrset.example. 5M IN A 10.0.5.237
+a-maximum-rrset.example. 5M IN A 10.0.5.238
+a-maximum-rrset.example. 5M IN A 10.0.5.239
+a-maximum-rrset.example. 5M IN A 10.0.5.240
+a-maximum-rrset.example. 5M IN A 10.0.5.241
+a-maximum-rrset.example. 5M IN A 10.0.5.242
+a-maximum-rrset.example. 5M IN A 10.0.5.243
+a-maximum-rrset.example. 5M IN A 10.0.5.244
+a-maximum-rrset.example. 5M IN A 10.0.5.245
+a-maximum-rrset.example. 5M IN A 10.0.5.246
+a-maximum-rrset.example. 5M IN A 10.0.5.247
+a-maximum-rrset.example. 5M IN A 10.0.5.248
+a-maximum-rrset.example. 5M IN A 10.0.5.249
+a-maximum-rrset.example. 5M IN A 10.0.5.250
+a-maximum-rrset.example. 5M IN A 10.0.5.251
+a-maximum-rrset.example. 5M IN A 10.0.5.252
+a-maximum-rrset.example. 5M IN A 10.0.5.253
+a-maximum-rrset.example. 5M IN A 10.0.5.254
+a-maximum-rrset.example. 5M IN A 10.0.5.255
+a-maximum-rrset.example. 5M IN A 10.0.6.0
+a-maximum-rrset.example. 5M IN A 10.0.6.1
+a-maximum-rrset.example. 5M IN A 10.0.6.2
+a-maximum-rrset.example. 5M IN A 10.0.6.3
+a-maximum-rrset.example. 5M IN A 10.0.6.4
+a-maximum-rrset.example. 5M IN A 10.0.6.5
+a-maximum-rrset.example. 5M IN A 10.0.6.6
+a-maximum-rrset.example. 5M IN A 10.0.6.7
+a-maximum-rrset.example. 5M IN A 10.0.6.8
+a-maximum-rrset.example. 5M IN A 10.0.6.9
+a-maximum-rrset.example. 5M IN A 10.0.6.10
+a-maximum-rrset.example. 5M IN A 10.0.6.11
+a-maximum-rrset.example. 5M IN A 10.0.6.12
+a-maximum-rrset.example. 5M IN A 10.0.6.13
+a-maximum-rrset.example. 5M IN A 10.0.6.14
+a-maximum-rrset.example. 5M IN A 10.0.6.15
+a-maximum-rrset.example. 5M IN A 10.0.6.16
+a-maximum-rrset.example. 5M IN A 10.0.6.17
+a-maximum-rrset.example. 5M IN A 10.0.6.18
+a-maximum-rrset.example. 5M IN A 10.0.6.19
+a-maximum-rrset.example. 5M IN A 10.0.6.20
+a-maximum-rrset.example. 5M IN A 10.0.6.21
+a-maximum-rrset.example. 5M IN A 10.0.6.22
+a-maximum-rrset.example. 5M IN A 10.0.6.23
+a-maximum-rrset.example. 5M IN A 10.0.6.24
+a-maximum-rrset.example. 5M IN A 10.0.6.25
+a-maximum-rrset.example. 5M IN A 10.0.6.26
+a-maximum-rrset.example. 5M IN A 10.0.6.27
+a-maximum-rrset.example. 5M IN A 10.0.6.28
+a-maximum-rrset.example. 5M IN A 10.0.6.29
+a-maximum-rrset.example. 5M IN A 10.0.6.30
+a-maximum-rrset.example. 5M IN A 10.0.6.31
+a-maximum-rrset.example. 5M IN A 10.0.6.32
+a-maximum-rrset.example. 5M IN A 10.0.6.33
+a-maximum-rrset.example. 5M IN A 10.0.6.34
+a-maximum-rrset.example. 5M IN A 10.0.6.35
+a-maximum-rrset.example. 5M IN A 10.0.6.36
+a-maximum-rrset.example. 5M IN A 10.0.6.37
+a-maximum-rrset.example. 5M IN A 10.0.6.38
+a-maximum-rrset.example. 5M IN A 10.0.6.39
+a-maximum-rrset.example. 5M IN A 10.0.6.40
+a-maximum-rrset.example. 5M IN A 10.0.6.41
+a-maximum-rrset.example. 5M IN A 10.0.6.42
+a-maximum-rrset.example. 5M IN A 10.0.6.43
+a-maximum-rrset.example. 5M IN A 10.0.6.44
+a-maximum-rrset.example. 5M IN A 10.0.6.45
+a-maximum-rrset.example. 5M IN A 10.0.6.46
+a-maximum-rrset.example. 5M IN A 10.0.6.47
+a-maximum-rrset.example. 5M IN A 10.0.6.48
+a-maximum-rrset.example. 5M IN A 10.0.6.49
+a-maximum-rrset.example. 5M IN A 10.0.6.50
+a-maximum-rrset.example. 5M IN A 10.0.6.51
+a-maximum-rrset.example. 5M IN A 10.0.6.52
+a-maximum-rrset.example. 5M IN A 10.0.6.53
+a-maximum-rrset.example. 5M IN A 10.0.6.54
+a-maximum-rrset.example. 5M IN A 10.0.6.55
+a-maximum-rrset.example. 5M IN A 10.0.6.56
+a-maximum-rrset.example. 5M IN A 10.0.6.57
+a-maximum-rrset.example. 5M IN A 10.0.6.58
+a-maximum-rrset.example. 5M IN A 10.0.6.59
+a-maximum-rrset.example. 5M IN A 10.0.6.60
+a-maximum-rrset.example. 5M IN A 10.0.6.61
+a-maximum-rrset.example. 5M IN A 10.0.6.62
+a-maximum-rrset.example. 5M IN A 10.0.6.63
+a-maximum-rrset.example. 5M IN A 10.0.6.64
+a-maximum-rrset.example. 5M IN A 10.0.6.65
+a-maximum-rrset.example. 5M IN A 10.0.6.66
+a-maximum-rrset.example. 5M IN A 10.0.6.67
+a-maximum-rrset.example. 5M IN A 10.0.6.68
+a-maximum-rrset.example. 5M IN A 10.0.6.69
+a-maximum-rrset.example. 5M IN A 10.0.6.70
+a-maximum-rrset.example. 5M IN A 10.0.6.71
+a-maximum-rrset.example. 5M IN A 10.0.6.72
+a-maximum-rrset.example. 5M IN A 10.0.6.73
+a-maximum-rrset.example. 5M IN A 10.0.6.74
+a-maximum-rrset.example. 5M IN A 10.0.6.75
+a-maximum-rrset.example. 5M IN A 10.0.6.76
+a-maximum-rrset.example. 5M IN A 10.0.6.77
+a-maximum-rrset.example. 5M IN A 10.0.6.78
+a-maximum-rrset.example. 5M IN A 10.0.6.79
+a-maximum-rrset.example. 5M IN A 10.0.6.80
+a-maximum-rrset.example. 5M IN A 10.0.6.81
+a-maximum-rrset.example. 5M IN A 10.0.6.82
+a-maximum-rrset.example. 5M IN A 10.0.6.83
+a-maximum-rrset.example. 5M IN A 10.0.6.84
+a-maximum-rrset.example. 5M IN A 10.0.6.85
+a-maximum-rrset.example. 5M IN A 10.0.6.86
+a-maximum-rrset.example. 5M IN A 10.0.6.87
+a-maximum-rrset.example. 5M IN A 10.0.6.88
+a-maximum-rrset.example. 5M IN A 10.0.6.89
+a-maximum-rrset.example. 5M IN A 10.0.6.90
+a-maximum-rrset.example. 5M IN A 10.0.6.91
+a-maximum-rrset.example. 5M IN A 10.0.6.92
+a-maximum-rrset.example. 5M IN A 10.0.6.93
+a-maximum-rrset.example. 5M IN A 10.0.6.94
+a-maximum-rrset.example. 5M IN A 10.0.6.95
+a-maximum-rrset.example. 5M IN A 10.0.6.96
+a-maximum-rrset.example. 5M IN A 10.0.6.97
+a-maximum-rrset.example. 5M IN A 10.0.6.98
+a-maximum-rrset.example. 5M IN A 10.0.6.99
+a-maximum-rrset.example. 5M IN A 10.0.6.100
+a-maximum-rrset.example. 5M IN A 10.0.6.101
+a-maximum-rrset.example. 5M IN A 10.0.6.102
+a-maximum-rrset.example. 5M IN A 10.0.6.103
+a-maximum-rrset.example. 5M IN A 10.0.6.104
+a-maximum-rrset.example. 5M IN A 10.0.6.105
+a-maximum-rrset.example. 5M IN A 10.0.6.106
+a-maximum-rrset.example. 5M IN A 10.0.6.107
+a-maximum-rrset.example. 5M IN A 10.0.6.108
+a-maximum-rrset.example. 5M IN A 10.0.6.109
+a-maximum-rrset.example. 5M IN A 10.0.6.110
+a-maximum-rrset.example. 5M IN A 10.0.6.111
+a-maximum-rrset.example. 5M IN A 10.0.6.112
+a-maximum-rrset.example. 5M IN A 10.0.6.113
+a-maximum-rrset.example. 5M IN A 10.0.6.114
+a-maximum-rrset.example. 5M IN A 10.0.6.115
+a-maximum-rrset.example. 5M IN A 10.0.6.116
+a-maximum-rrset.example. 5M IN A 10.0.6.117
+a-maximum-rrset.example. 5M IN A 10.0.6.118
+a-maximum-rrset.example. 5M IN A 10.0.6.119
+a-maximum-rrset.example. 5M IN A 10.0.6.120
+a-maximum-rrset.example. 5M IN A 10.0.6.121
+a-maximum-rrset.example. 5M IN A 10.0.6.122
+a-maximum-rrset.example. 5M IN A 10.0.6.123
+a-maximum-rrset.example. 5M IN A 10.0.6.124
+a-maximum-rrset.example. 5M IN A 10.0.6.125
+a-maximum-rrset.example. 5M IN A 10.0.6.126
+a-maximum-rrset.example. 5M IN A 10.0.6.127
+a-maximum-rrset.example. 5M IN A 10.0.6.128
+a-maximum-rrset.example. 5M IN A 10.0.6.129
+a-maximum-rrset.example. 5M IN A 10.0.6.130
+a-maximum-rrset.example. 5M IN A 10.0.6.131
+a-maximum-rrset.example. 5M IN A 10.0.6.132
+a-maximum-rrset.example. 5M IN A 10.0.6.133
+a-maximum-rrset.example. 5M IN A 10.0.6.134
+a-maximum-rrset.example. 5M IN A 10.0.6.135
+a-maximum-rrset.example. 5M IN A 10.0.6.136
+a-maximum-rrset.example. 5M IN A 10.0.6.137
+a-maximum-rrset.example. 5M IN A 10.0.6.138
+a-maximum-rrset.example. 5M IN A 10.0.6.139
+a-maximum-rrset.example. 5M IN A 10.0.6.140
+a-maximum-rrset.example. 5M IN A 10.0.6.141
+a-maximum-rrset.example. 5M IN A 10.0.6.142
+a-maximum-rrset.example. 5M IN A 10.0.6.143
+a-maximum-rrset.example. 5M IN A 10.0.6.144
+a-maximum-rrset.example. 5M IN A 10.0.6.145
+a-maximum-rrset.example. 5M IN A 10.0.6.146
+a-maximum-rrset.example. 5M IN A 10.0.6.147
+a-maximum-rrset.example. 5M IN A 10.0.6.148
+a-maximum-rrset.example. 5M IN A 10.0.6.149
+a-maximum-rrset.example. 5M IN A 10.0.6.150
+a-maximum-rrset.example. 5M IN A 10.0.6.151
+a-maximum-rrset.example. 5M IN A 10.0.6.152
+a-maximum-rrset.example. 5M IN A 10.0.6.153
+a-maximum-rrset.example. 5M IN A 10.0.6.154
+a-maximum-rrset.example. 5M IN A 10.0.6.155
+a-maximum-rrset.example. 5M IN A 10.0.6.156
+a-maximum-rrset.example. 5M IN A 10.0.6.157
+a-maximum-rrset.example. 5M IN A 10.0.6.158
+a-maximum-rrset.example. 5M IN A 10.0.6.159
+a-maximum-rrset.example. 5M IN A 10.0.6.160
+a-maximum-rrset.example. 5M IN A 10.0.6.161
+a-maximum-rrset.example. 5M IN A 10.0.6.162
+a-maximum-rrset.example. 5M IN A 10.0.6.163
+a-maximum-rrset.example. 5M IN A 10.0.6.164
+a-maximum-rrset.example. 5M IN A 10.0.6.165
+a-maximum-rrset.example. 5M IN A 10.0.6.166
+a-maximum-rrset.example. 5M IN A 10.0.6.167
+a-maximum-rrset.example. 5M IN A 10.0.6.168
+a-maximum-rrset.example. 5M IN A 10.0.6.169
+a-maximum-rrset.example. 5M IN A 10.0.6.170
+a-maximum-rrset.example. 5M IN A 10.0.6.171
+a-maximum-rrset.example. 5M IN A 10.0.6.172
+a-maximum-rrset.example. 5M IN A 10.0.6.173
+a-maximum-rrset.example. 5M IN A 10.0.6.174
+a-maximum-rrset.example. 5M IN A 10.0.6.175
+a-maximum-rrset.example. 5M IN A 10.0.6.176
+a-maximum-rrset.example. 5M IN A 10.0.6.177
+a-maximum-rrset.example. 5M IN A 10.0.6.178
+a-maximum-rrset.example. 5M IN A 10.0.6.179
+a-maximum-rrset.example. 5M IN A 10.0.6.180
+a-maximum-rrset.example. 5M IN A 10.0.6.181
+a-maximum-rrset.example. 5M IN A 10.0.6.182
+a-maximum-rrset.example. 5M IN A 10.0.6.183
+a-maximum-rrset.example. 5M IN A 10.0.6.184
+a-maximum-rrset.example. 5M IN A 10.0.6.185
+a-maximum-rrset.example. 5M IN A 10.0.6.186
+a-maximum-rrset.example. 5M IN A 10.0.6.187
+a-maximum-rrset.example. 5M IN A 10.0.6.188
+a-maximum-rrset.example. 5M IN A 10.0.6.189
+a-maximum-rrset.example. 5M IN A 10.0.6.190
+a-maximum-rrset.example. 5M IN A 10.0.6.191
+a-maximum-rrset.example. 5M IN A 10.0.6.192
+a-maximum-rrset.example. 5M IN A 10.0.6.193
+a-maximum-rrset.example. 5M IN A 10.0.6.194
+a-maximum-rrset.example. 5M IN A 10.0.6.195
+a-maximum-rrset.example. 5M IN A 10.0.6.196
+a-maximum-rrset.example. 5M IN A 10.0.6.197
+a-maximum-rrset.example. 5M IN A 10.0.6.198
+a-maximum-rrset.example. 5M IN A 10.0.6.199
+a-maximum-rrset.example. 5M IN A 10.0.6.200
+a-maximum-rrset.example. 5M IN A 10.0.6.201
+a-maximum-rrset.example. 5M IN A 10.0.6.202
+a-maximum-rrset.example. 5M IN A 10.0.6.203
+a-maximum-rrset.example. 5M IN A 10.0.6.204
+a-maximum-rrset.example. 5M IN A 10.0.6.205
+a-maximum-rrset.example. 5M IN A 10.0.6.206
+a-maximum-rrset.example. 5M IN A 10.0.6.207
+a-maximum-rrset.example. 5M IN A 10.0.6.208
+a-maximum-rrset.example. 5M IN A 10.0.6.209
+a-maximum-rrset.example. 5M IN A 10.0.6.210
+a-maximum-rrset.example. 5M IN A 10.0.6.211
+a-maximum-rrset.example. 5M IN A 10.0.6.212
+a-maximum-rrset.example. 5M IN A 10.0.6.213
+a-maximum-rrset.example. 5M IN A 10.0.6.214
+a-maximum-rrset.example. 5M IN A 10.0.6.215
+a-maximum-rrset.example. 5M IN A 10.0.6.216
+a-maximum-rrset.example. 5M IN A 10.0.6.217
+a-maximum-rrset.example. 5M IN A 10.0.6.218
+a-maximum-rrset.example. 5M IN A 10.0.6.219
+a-maximum-rrset.example. 5M IN A 10.0.6.220
+a-maximum-rrset.example. 5M IN A 10.0.6.221
+a-maximum-rrset.example. 5M IN A 10.0.6.222
+a-maximum-rrset.example. 5M IN A 10.0.6.223
+a-maximum-rrset.example. 5M IN A 10.0.6.224
+a-maximum-rrset.example. 5M IN A 10.0.6.225
+a-maximum-rrset.example. 5M IN A 10.0.6.226
+a-maximum-rrset.example. 5M IN A 10.0.6.227
+a-maximum-rrset.example. 5M IN A 10.0.6.228
+a-maximum-rrset.example. 5M IN A 10.0.6.229
+a-maximum-rrset.example. 5M IN A 10.0.6.230
+a-maximum-rrset.example. 5M IN A 10.0.6.231
+a-maximum-rrset.example. 5M IN A 10.0.6.232
+a-maximum-rrset.example. 5M IN A 10.0.6.233
+a-maximum-rrset.example. 5M IN A 10.0.6.234
+a-maximum-rrset.example. 5M IN A 10.0.6.235
+a-maximum-rrset.example. 5M IN A 10.0.6.236
+a-maximum-rrset.example. 5M IN A 10.0.6.237
+a-maximum-rrset.example. 5M IN A 10.0.6.238
+a-maximum-rrset.example. 5M IN A 10.0.6.239
+a-maximum-rrset.example. 5M IN A 10.0.6.240
+a-maximum-rrset.example. 5M IN A 10.0.6.241
+a-maximum-rrset.example. 5M IN A 10.0.6.242
+a-maximum-rrset.example. 5M IN A 10.0.6.243
+a-maximum-rrset.example. 5M IN A 10.0.6.244
+a-maximum-rrset.example. 5M IN A 10.0.6.245
+a-maximum-rrset.example. 5M IN A 10.0.6.246
+a-maximum-rrset.example. 5M IN A 10.0.6.247
+a-maximum-rrset.example. 5M IN A 10.0.6.248
+a-maximum-rrset.example. 5M IN A 10.0.6.249
+a-maximum-rrset.example. 5M IN A 10.0.6.250
+a-maximum-rrset.example. 5M IN A 10.0.6.251
+a-maximum-rrset.example. 5M IN A 10.0.6.252
+a-maximum-rrset.example. 5M IN A 10.0.6.253
+a-maximum-rrset.example. 5M IN A 10.0.6.254
+a-maximum-rrset.example. 5M IN A 10.0.6.255
+a-maximum-rrset.example. 5M IN A 10.0.7.0
+a-maximum-rrset.example. 5M IN A 10.0.7.1
+a-maximum-rrset.example. 5M IN A 10.0.7.2
+a-maximum-rrset.example. 5M IN A 10.0.7.3
+a-maximum-rrset.example. 5M IN A 10.0.7.4
+a-maximum-rrset.example. 5M IN A 10.0.7.5
+a-maximum-rrset.example. 5M IN A 10.0.7.6
+a-maximum-rrset.example. 5M IN A 10.0.7.7
+a-maximum-rrset.example. 5M IN A 10.0.7.8
+a-maximum-rrset.example. 5M IN A 10.0.7.9
+a-maximum-rrset.example. 5M IN A 10.0.7.10
+a-maximum-rrset.example. 5M IN A 10.0.7.11
+a-maximum-rrset.example. 5M IN A 10.0.7.12
+a-maximum-rrset.example. 5M IN A 10.0.7.13
+a-maximum-rrset.example. 5M IN A 10.0.7.14
+a-maximum-rrset.example. 5M IN A 10.0.7.15
+a-maximum-rrset.example. 5M IN A 10.0.7.16
+a-maximum-rrset.example. 5M IN A 10.0.7.17
+a-maximum-rrset.example. 5M IN A 10.0.7.18
+a-maximum-rrset.example. 5M IN A 10.0.7.19
+a-maximum-rrset.example. 5M IN A 10.0.7.20
+a-maximum-rrset.example. 5M IN A 10.0.7.21
+a-maximum-rrset.example. 5M IN A 10.0.7.22
+a-maximum-rrset.example. 5M IN A 10.0.7.23
+a-maximum-rrset.example. 5M IN A 10.0.7.24
+a-maximum-rrset.example. 5M IN A 10.0.7.25
+a-maximum-rrset.example. 5M IN A 10.0.7.26
+a-maximum-rrset.example. 5M IN A 10.0.7.27
+a-maximum-rrset.example. 5M IN A 10.0.7.28
+a-maximum-rrset.example. 5M IN A 10.0.7.29
+a-maximum-rrset.example. 5M IN A 10.0.7.30
+a-maximum-rrset.example. 5M IN A 10.0.7.31
+a-maximum-rrset.example. 5M IN A 10.0.7.32
+a-maximum-rrset.example. 5M IN A 10.0.7.33
+a-maximum-rrset.example. 5M IN A 10.0.7.34
+a-maximum-rrset.example. 5M IN A 10.0.7.35
+a-maximum-rrset.example. 5M IN A 10.0.7.36
+a-maximum-rrset.example. 5M IN A 10.0.7.37
+a-maximum-rrset.example. 5M IN A 10.0.7.38
+a-maximum-rrset.example. 5M IN A 10.0.7.39
+a-maximum-rrset.example. 5M IN A 10.0.7.40
+a-maximum-rrset.example. 5M IN A 10.0.7.41
+a-maximum-rrset.example. 5M IN A 10.0.7.42
+a-maximum-rrset.example. 5M IN A 10.0.7.43
+a-maximum-rrset.example. 5M IN A 10.0.7.44
+a-maximum-rrset.example. 5M IN A 10.0.7.45
+a-maximum-rrset.example. 5M IN A 10.0.7.46
+a-maximum-rrset.example. 5M IN A 10.0.7.47
+a-maximum-rrset.example. 5M IN A 10.0.7.48
+a-maximum-rrset.example. 5M IN A 10.0.7.49
+a-maximum-rrset.example. 5M IN A 10.0.7.50
+a-maximum-rrset.example. 5M IN A 10.0.7.51
+a-maximum-rrset.example. 5M IN A 10.0.7.52
+a-maximum-rrset.example. 5M IN A 10.0.7.53
+a-maximum-rrset.example. 5M IN A 10.0.7.54
+a-maximum-rrset.example. 5M IN A 10.0.7.55
+a-maximum-rrset.example. 5M IN A 10.0.7.56
+a-maximum-rrset.example. 5M IN A 10.0.7.57
+a-maximum-rrset.example. 5M IN A 10.0.7.58
+a-maximum-rrset.example. 5M IN A 10.0.7.59
+a-maximum-rrset.example. 5M IN A 10.0.7.60
+a-maximum-rrset.example. 5M IN A 10.0.7.61
+a-maximum-rrset.example. 5M IN A 10.0.7.62
+a-maximum-rrset.example. 5M IN A 10.0.7.63
+a-maximum-rrset.example. 5M IN A 10.0.7.64
+a-maximum-rrset.example. 5M IN A 10.0.7.65
+a-maximum-rrset.example. 5M IN A 10.0.7.66
+a-maximum-rrset.example. 5M IN A 10.0.7.67
+a-maximum-rrset.example. 5M IN A 10.0.7.68
+a-maximum-rrset.example. 5M IN A 10.0.7.69
+a-maximum-rrset.example. 5M IN A 10.0.7.70
+a-maximum-rrset.example. 5M IN A 10.0.7.71
+a-maximum-rrset.example. 5M IN A 10.0.7.72
+a-maximum-rrset.example. 5M IN A 10.0.7.73
+a-maximum-rrset.example. 5M IN A 10.0.7.74
+a-maximum-rrset.example. 5M IN A 10.0.7.75
+a-maximum-rrset.example. 5M IN A 10.0.7.76
+a-maximum-rrset.example. 5M IN A 10.0.7.77
+a-maximum-rrset.example. 5M IN A 10.0.7.78
+a-maximum-rrset.example. 5M IN A 10.0.7.79
+a-maximum-rrset.example. 5M IN A 10.0.7.80
+a-maximum-rrset.example. 5M IN A 10.0.7.81
+a-maximum-rrset.example. 5M IN A 10.0.7.82
+a-maximum-rrset.example. 5M IN A 10.0.7.83
+a-maximum-rrset.example. 5M IN A 10.0.7.84
+a-maximum-rrset.example. 5M IN A 10.0.7.85
+a-maximum-rrset.example. 5M IN A 10.0.7.86
+a-maximum-rrset.example. 5M IN A 10.0.7.87
+a-maximum-rrset.example. 5M IN A 10.0.7.88
+a-maximum-rrset.example. 5M IN A 10.0.7.89
+a-maximum-rrset.example. 5M IN A 10.0.7.90
+a-maximum-rrset.example. 5M IN A 10.0.7.91
+a-maximum-rrset.example. 5M IN A 10.0.7.92
+a-maximum-rrset.example. 5M IN A 10.0.7.93
+a-maximum-rrset.example. 5M IN A 10.0.7.94
+a-maximum-rrset.example. 5M IN A 10.0.7.95
+a-maximum-rrset.example. 5M IN A 10.0.7.96
+a-maximum-rrset.example. 5M IN A 10.0.7.97
+a-maximum-rrset.example. 5M IN A 10.0.7.98
+a-maximum-rrset.example. 5M IN A 10.0.7.99
+a-maximum-rrset.example. 5M IN A 10.0.7.100
+a-maximum-rrset.example. 5M IN A 10.0.7.101
+a-maximum-rrset.example. 5M IN A 10.0.7.102
+a-maximum-rrset.example. 5M IN A 10.0.7.103
+a-maximum-rrset.example. 5M IN A 10.0.7.104
+a-maximum-rrset.example. 5M IN A 10.0.7.105
+a-maximum-rrset.example. 5M IN A 10.0.7.106
+a-maximum-rrset.example. 5M IN A 10.0.7.107
+a-maximum-rrset.example. 5M IN A 10.0.7.108
+a-maximum-rrset.example. 5M IN A 10.0.7.109
+a-maximum-rrset.example. 5M IN A 10.0.7.110
+a-maximum-rrset.example. 5M IN A 10.0.7.111
+a-maximum-rrset.example. 5M IN A 10.0.7.112
+a-maximum-rrset.example. 5M IN A 10.0.7.113
+a-maximum-rrset.example. 5M IN A 10.0.7.114
+a-maximum-rrset.example. 5M IN A 10.0.7.115
+a-maximum-rrset.example. 5M IN A 10.0.7.116
+a-maximum-rrset.example. 5M IN A 10.0.7.117
+a-maximum-rrset.example. 5M IN A 10.0.7.118
+a-maximum-rrset.example. 5M IN A 10.0.7.119
+a-maximum-rrset.example. 5M IN A 10.0.7.120
+a-maximum-rrset.example. 5M IN A 10.0.7.121
+a-maximum-rrset.example. 5M IN A 10.0.7.122
+a-maximum-rrset.example. 5M IN A 10.0.7.123
+a-maximum-rrset.example. 5M IN A 10.0.7.124
+a-maximum-rrset.example. 5M IN A 10.0.7.125
+a-maximum-rrset.example. 5M IN A 10.0.7.126
+a-maximum-rrset.example. 5M IN A 10.0.7.127
+a-maximum-rrset.example. 5M IN A 10.0.7.128
+a-maximum-rrset.example. 5M IN A 10.0.7.129
+a-maximum-rrset.example. 5M IN A 10.0.7.130
+a-maximum-rrset.example. 5M IN A 10.0.7.131
+a-maximum-rrset.example. 5M IN A 10.0.7.132
+a-maximum-rrset.example. 5M IN A 10.0.7.133
+a-maximum-rrset.example. 5M IN A 10.0.7.134
+a-maximum-rrset.example. 5M IN A 10.0.7.135
+a-maximum-rrset.example. 5M IN A 10.0.7.136
+a-maximum-rrset.example. 5M IN A 10.0.7.137
+a-maximum-rrset.example. 5M IN A 10.0.7.138
+a-maximum-rrset.example. 5M IN A 10.0.7.139
+a-maximum-rrset.example. 5M IN A 10.0.7.140
+a-maximum-rrset.example. 5M IN A 10.0.7.141
+a-maximum-rrset.example. 5M IN A 10.0.7.142
+a-maximum-rrset.example. 5M IN A 10.0.7.143
+a-maximum-rrset.example. 5M IN A 10.0.7.144
+a-maximum-rrset.example. 5M IN A 10.0.7.145
+a-maximum-rrset.example. 5M IN A 10.0.7.146
+a-maximum-rrset.example. 5M IN A 10.0.7.147
+a-maximum-rrset.example. 5M IN A 10.0.7.148
+a-maximum-rrset.example. 5M IN A 10.0.7.149
+a-maximum-rrset.example. 5M IN A 10.0.7.150
+a-maximum-rrset.example. 5M IN A 10.0.7.151
+a-maximum-rrset.example. 5M IN A 10.0.7.152
+a-maximum-rrset.example. 5M IN A 10.0.7.153
+a-maximum-rrset.example. 5M IN A 10.0.7.154
+a-maximum-rrset.example. 5M IN A 10.0.7.155
+a-maximum-rrset.example. 5M IN A 10.0.7.156
+a-maximum-rrset.example. 5M IN A 10.0.7.157
+a-maximum-rrset.example. 5M IN A 10.0.7.158
+a-maximum-rrset.example. 5M IN A 10.0.7.159
+a-maximum-rrset.example. 5M IN A 10.0.7.160
+a-maximum-rrset.example. 5M IN A 10.0.7.161
+a-maximum-rrset.example. 5M IN A 10.0.7.162
+a-maximum-rrset.example. 5M IN A 10.0.7.163
+a-maximum-rrset.example. 5M IN A 10.0.7.164
+a-maximum-rrset.example. 5M IN A 10.0.7.165
+a-maximum-rrset.example. 5M IN A 10.0.7.166
+a-maximum-rrset.example. 5M IN A 10.0.7.167
+a-maximum-rrset.example. 5M IN A 10.0.7.168
+a-maximum-rrset.example. 5M IN A 10.0.7.169
+a-maximum-rrset.example. 5M IN A 10.0.7.170
+a-maximum-rrset.example. 5M IN A 10.0.7.171
+a-maximum-rrset.example. 5M IN A 10.0.7.172
+a-maximum-rrset.example. 5M IN A 10.0.7.173
+a-maximum-rrset.example. 5M IN A 10.0.7.174
+a-maximum-rrset.example. 5M IN A 10.0.7.175
+a-maximum-rrset.example. 5M IN A 10.0.7.176
+a-maximum-rrset.example. 5M IN A 10.0.7.177
+a-maximum-rrset.example. 5M IN A 10.0.7.178
+a-maximum-rrset.example. 5M IN A 10.0.7.179
+a-maximum-rrset.example. 5M IN A 10.0.7.180
+a-maximum-rrset.example. 5M IN A 10.0.7.181
+a-maximum-rrset.example. 5M IN A 10.0.7.182
+a-maximum-rrset.example. 5M IN A 10.0.7.183
+a-maximum-rrset.example. 5M IN A 10.0.7.184
+a-maximum-rrset.example. 5M IN A 10.0.7.185
+a-maximum-rrset.example. 5M IN A 10.0.7.186
+a-maximum-rrset.example. 5M IN A 10.0.7.187
+a-maximum-rrset.example. 5M IN A 10.0.7.188
+a-maximum-rrset.example. 5M IN A 10.0.7.189
+a-maximum-rrset.example. 5M IN A 10.0.7.190
+a-maximum-rrset.example. 5M IN A 10.0.7.191
+a-maximum-rrset.example. 5M IN A 10.0.7.192
+a-maximum-rrset.example. 5M IN A 10.0.7.193
+a-maximum-rrset.example. 5M IN A 10.0.7.194
+a-maximum-rrset.example. 5M IN A 10.0.7.195
+a-maximum-rrset.example. 5M IN A 10.0.7.196
+a-maximum-rrset.example. 5M IN A 10.0.7.197
+a-maximum-rrset.example. 5M IN A 10.0.7.198
+a-maximum-rrset.example. 5M IN A 10.0.7.199
+a-maximum-rrset.example. 5M IN A 10.0.7.200
+a-maximum-rrset.example. 5M IN A 10.0.7.201
+a-maximum-rrset.example. 5M IN A 10.0.7.202
+a-maximum-rrset.example. 5M IN A 10.0.7.203
+a-maximum-rrset.example. 5M IN A 10.0.7.204
+a-maximum-rrset.example. 5M IN A 10.0.7.205
+a-maximum-rrset.example. 5M IN A 10.0.7.206
+a-maximum-rrset.example. 5M IN A 10.0.7.207
+a-maximum-rrset.example. 5M IN A 10.0.7.208
+a-maximum-rrset.example. 5M IN A 10.0.7.209
+a-maximum-rrset.example. 5M IN A 10.0.7.210
+a-maximum-rrset.example. 5M IN A 10.0.7.211
+a-maximum-rrset.example. 5M IN A 10.0.7.212
+a-maximum-rrset.example. 5M IN A 10.0.7.213
+a-maximum-rrset.example. 5M IN A 10.0.7.214
+a-maximum-rrset.example. 5M IN A 10.0.7.215
+a-maximum-rrset.example. 5M IN A 10.0.7.216
+a-maximum-rrset.example. 5M IN A 10.0.7.217
+a-maximum-rrset.example. 5M IN A 10.0.7.218
+a-maximum-rrset.example. 5M IN A 10.0.7.219
+a-maximum-rrset.example. 5M IN A 10.0.7.220
+a-maximum-rrset.example. 5M IN A 10.0.7.221
+a-maximum-rrset.example. 5M IN A 10.0.7.222
+a-maximum-rrset.example. 5M IN A 10.0.7.223
+a-maximum-rrset.example. 5M IN A 10.0.7.224
+a-maximum-rrset.example. 5M IN A 10.0.7.225
+a-maximum-rrset.example. 5M IN A 10.0.7.226
+a-maximum-rrset.example. 5M IN A 10.0.7.227
+a-maximum-rrset.example. 5M IN A 10.0.7.228
+a-maximum-rrset.example. 5M IN A 10.0.7.229
+a-maximum-rrset.example. 5M IN A 10.0.7.230
+a-maximum-rrset.example. 5M IN A 10.0.7.231
+a-maximum-rrset.example. 5M IN A 10.0.7.232
+a-maximum-rrset.example. 5M IN A 10.0.7.233
+a-maximum-rrset.example. 5M IN A 10.0.7.234
+a-maximum-rrset.example. 5M IN A 10.0.7.235
+a-maximum-rrset.example. 5M IN A 10.0.7.236
+a-maximum-rrset.example. 5M IN A 10.0.7.237
+a-maximum-rrset.example. 5M IN A 10.0.7.238
+a-maximum-rrset.example. 5M IN A 10.0.7.239
+a-maximum-rrset.example. 5M IN A 10.0.7.240
+a-maximum-rrset.example. 5M IN A 10.0.7.241
+a-maximum-rrset.example. 5M IN A 10.0.7.242
+a-maximum-rrset.example. 5M IN A 10.0.7.243
+a-maximum-rrset.example. 5M IN A 10.0.7.244
+a-maximum-rrset.example. 5M IN A 10.0.7.245
+a-maximum-rrset.example. 5M IN A 10.0.7.246
+a-maximum-rrset.example. 5M IN A 10.0.7.247
+a-maximum-rrset.example. 5M IN A 10.0.7.248
+a-maximum-rrset.example. 5M IN A 10.0.7.249
+a-maximum-rrset.example. 5M IN A 10.0.7.250
+a-maximum-rrset.example. 5M IN A 10.0.7.251
+a-maximum-rrset.example. 5M IN A 10.0.7.252
+a-maximum-rrset.example. 5M IN A 10.0.7.253
+a-maximum-rrset.example. 5M IN A 10.0.7.254
+a-maximum-rrset.example. 5M IN A 10.0.7.255
+a-maximum-rrset.example. 5M IN A 10.0.8.0
+a-maximum-rrset.example. 5M IN A 10.0.8.1
+a-maximum-rrset.example. 5M IN A 10.0.8.2
+a-maximum-rrset.example. 5M IN A 10.0.8.3
+a-maximum-rrset.example. 5M IN A 10.0.8.4
+a-maximum-rrset.example. 5M IN A 10.0.8.5
+a-maximum-rrset.example. 5M IN A 10.0.8.6
+a-maximum-rrset.example. 5M IN A 10.0.8.7
+a-maximum-rrset.example. 5M IN A 10.0.8.8
+a-maximum-rrset.example. 5M IN A 10.0.8.9
+a-maximum-rrset.example. 5M IN A 10.0.8.10
+a-maximum-rrset.example. 5M IN A 10.0.8.11
+a-maximum-rrset.example. 5M IN A 10.0.8.12
+a-maximum-rrset.example. 5M IN A 10.0.8.13
+a-maximum-rrset.example. 5M IN A 10.0.8.14
+a-maximum-rrset.example. 5M IN A 10.0.8.15
+a-maximum-rrset.example. 5M IN A 10.0.8.16
+a-maximum-rrset.example. 5M IN A 10.0.8.17
+a-maximum-rrset.example. 5M IN A 10.0.8.18
+a-maximum-rrset.example. 5M IN A 10.0.8.19
+a-maximum-rrset.example. 5M IN A 10.0.8.20
+a-maximum-rrset.example. 5M IN A 10.0.8.21
+a-maximum-rrset.example. 5M IN A 10.0.8.22
+a-maximum-rrset.example. 5M IN A 10.0.8.23
+a-maximum-rrset.example. 5M IN A 10.0.8.24
+a-maximum-rrset.example. 5M IN A 10.0.8.25
+a-maximum-rrset.example. 5M IN A 10.0.8.26
+a-maximum-rrset.example. 5M IN A 10.0.8.27
+a-maximum-rrset.example. 5M IN A 10.0.8.28
+a-maximum-rrset.example. 5M IN A 10.0.8.29
+a-maximum-rrset.example. 5M IN A 10.0.8.30
+a-maximum-rrset.example. 5M IN A 10.0.8.31
+a-maximum-rrset.example. 5M IN A 10.0.8.32
+a-maximum-rrset.example. 5M IN A 10.0.8.33
+a-maximum-rrset.example. 5M IN A 10.0.8.34
+a-maximum-rrset.example. 5M IN A 10.0.8.35
+a-maximum-rrset.example. 5M IN A 10.0.8.36
+a-maximum-rrset.example. 5M IN A 10.0.8.37
+a-maximum-rrset.example. 5M IN A 10.0.8.38
+a-maximum-rrset.example. 5M IN A 10.0.8.39
+a-maximum-rrset.example. 5M IN A 10.0.8.40
+a-maximum-rrset.example. 5M IN A 10.0.8.41
+a-maximum-rrset.example. 5M IN A 10.0.8.42
+a-maximum-rrset.example. 5M IN A 10.0.8.43
+a-maximum-rrset.example. 5M IN A 10.0.8.44
+a-maximum-rrset.example. 5M IN A 10.0.8.45
+a-maximum-rrset.example. 5M IN A 10.0.8.46
+a-maximum-rrset.example. 5M IN A 10.0.8.47
+a-maximum-rrset.example. 5M IN A 10.0.8.48
+a-maximum-rrset.example. 5M IN A 10.0.8.49
+a-maximum-rrset.example. 5M IN A 10.0.8.50
+a-maximum-rrset.example. 5M IN A 10.0.8.51
+a-maximum-rrset.example. 5M IN A 10.0.8.52
+a-maximum-rrset.example. 5M IN A 10.0.8.53
+a-maximum-rrset.example. 5M IN A 10.0.8.54
+a-maximum-rrset.example. 5M IN A 10.0.8.55
+a-maximum-rrset.example. 5M IN A 10.0.8.56
+a-maximum-rrset.example. 5M IN A 10.0.8.57
+a-maximum-rrset.example. 5M IN A 10.0.8.58
+a-maximum-rrset.example. 5M IN A 10.0.8.59
+a-maximum-rrset.example. 5M IN A 10.0.8.60
+a-maximum-rrset.example. 5M IN A 10.0.8.61
+a-maximum-rrset.example. 5M IN A 10.0.8.62
+a-maximum-rrset.example. 5M IN A 10.0.8.63
+a-maximum-rrset.example. 5M IN A 10.0.8.64
+a-maximum-rrset.example. 5M IN A 10.0.8.65
+a-maximum-rrset.example. 5M IN A 10.0.8.66
+a-maximum-rrset.example. 5M IN A 10.0.8.67
+a-maximum-rrset.example. 5M IN A 10.0.8.68
+a-maximum-rrset.example. 5M IN A 10.0.8.69
+a-maximum-rrset.example. 5M IN A 10.0.8.70
+a-maximum-rrset.example. 5M IN A 10.0.8.71
+a-maximum-rrset.example. 5M IN A 10.0.8.72
+a-maximum-rrset.example. 5M IN A 10.0.8.73
+a-maximum-rrset.example. 5M IN A 10.0.8.74
+a-maximum-rrset.example. 5M IN A 10.0.8.75
+a-maximum-rrset.example. 5M IN A 10.0.8.76
+a-maximum-rrset.example. 5M IN A 10.0.8.77
+a-maximum-rrset.example. 5M IN A 10.0.8.78
+a-maximum-rrset.example. 5M IN A 10.0.8.79
+a-maximum-rrset.example. 5M IN A 10.0.8.80
+a-maximum-rrset.example. 5M IN A 10.0.8.81
+a-maximum-rrset.example. 5M IN A 10.0.8.82
+a-maximum-rrset.example. 5M IN A 10.0.8.83
+a-maximum-rrset.example. 5M IN A 10.0.8.84
+a-maximum-rrset.example. 5M IN A 10.0.8.85
+a-maximum-rrset.example. 5M IN A 10.0.8.86
+a-maximum-rrset.example. 5M IN A 10.0.8.87
+a-maximum-rrset.example. 5M IN A 10.0.8.88
+a-maximum-rrset.example. 5M IN A 10.0.8.89
+a-maximum-rrset.example. 5M IN A 10.0.8.90
+a-maximum-rrset.example. 5M IN A 10.0.8.91
+a-maximum-rrset.example. 5M IN A 10.0.8.92
+a-maximum-rrset.example. 5M IN A 10.0.8.93
+a-maximum-rrset.example. 5M IN A 10.0.8.94
+a-maximum-rrset.example. 5M IN A 10.0.8.95
+a-maximum-rrset.example. 5M IN A 10.0.8.96
+a-maximum-rrset.example. 5M IN A 10.0.8.97
+a-maximum-rrset.example. 5M IN A 10.0.8.98
+a-maximum-rrset.example. 5M IN A 10.0.8.99
+a-maximum-rrset.example. 5M IN A 10.0.8.100
+a-maximum-rrset.example. 5M IN A 10.0.8.101
+a-maximum-rrset.example. 5M IN A 10.0.8.102
+a-maximum-rrset.example. 5M IN A 10.0.8.103
+a-maximum-rrset.example. 5M IN A 10.0.8.104
+a-maximum-rrset.example. 5M IN A 10.0.8.105
+a-maximum-rrset.example. 5M IN A 10.0.8.106
+a-maximum-rrset.example. 5M IN A 10.0.8.107
+a-maximum-rrset.example. 5M IN A 10.0.8.108
+a-maximum-rrset.example. 5M IN A 10.0.8.109
+a-maximum-rrset.example. 5M IN A 10.0.8.110
+a-maximum-rrset.example. 5M IN A 10.0.8.111
+a-maximum-rrset.example. 5M IN A 10.0.8.112
+a-maximum-rrset.example. 5M IN A 10.0.8.113
+a-maximum-rrset.example. 5M IN A 10.0.8.114
+a-maximum-rrset.example. 5M IN A 10.0.8.115
+a-maximum-rrset.example. 5M IN A 10.0.8.116
+a-maximum-rrset.example. 5M IN A 10.0.8.117
+a-maximum-rrset.example. 5M IN A 10.0.8.118
+a-maximum-rrset.example. 5M IN A 10.0.8.119
+a-maximum-rrset.example. 5M IN A 10.0.8.120
+a-maximum-rrset.example. 5M IN A 10.0.8.121
+a-maximum-rrset.example. 5M IN A 10.0.8.122
+a-maximum-rrset.example. 5M IN A 10.0.8.123
+a-maximum-rrset.example. 5M IN A 10.0.8.124
+a-maximum-rrset.example. 5M IN A 10.0.8.125
+a-maximum-rrset.example. 5M IN A 10.0.8.126
+a-maximum-rrset.example. 5M IN A 10.0.8.127
+a-maximum-rrset.example. 5M IN A 10.0.8.128
+a-maximum-rrset.example. 5M IN A 10.0.8.129
+a-maximum-rrset.example. 5M IN A 10.0.8.130
+a-maximum-rrset.example. 5M IN A 10.0.8.131
+a-maximum-rrset.example. 5M IN A 10.0.8.132
+a-maximum-rrset.example. 5M IN A 10.0.8.133
+a-maximum-rrset.example. 5M IN A 10.0.8.134
+a-maximum-rrset.example. 5M IN A 10.0.8.135
+a-maximum-rrset.example. 5M IN A 10.0.8.136
+a-maximum-rrset.example. 5M IN A 10.0.8.137
+a-maximum-rrset.example. 5M IN A 10.0.8.138
+a-maximum-rrset.example. 5M IN A 10.0.8.139
+a-maximum-rrset.example. 5M IN A 10.0.8.140
+a-maximum-rrset.example. 5M IN A 10.0.8.141
+a-maximum-rrset.example. 5M IN A 10.0.8.142
+a-maximum-rrset.example. 5M IN A 10.0.8.143
+a-maximum-rrset.example. 5M IN A 10.0.8.144
+a-maximum-rrset.example. 5M IN A 10.0.8.145
+a-maximum-rrset.example. 5M IN A 10.0.8.146
+a-maximum-rrset.example. 5M IN A 10.0.8.147
+a-maximum-rrset.example. 5M IN A 10.0.8.148
+a-maximum-rrset.example. 5M IN A 10.0.8.149
+a-maximum-rrset.example. 5M IN A 10.0.8.150
+a-maximum-rrset.example. 5M IN A 10.0.8.151
+a-maximum-rrset.example. 5M IN A 10.0.8.152
+a-maximum-rrset.example. 5M IN A 10.0.8.153
+a-maximum-rrset.example. 5M IN A 10.0.8.154
+a-maximum-rrset.example. 5M IN A 10.0.8.155
+a-maximum-rrset.example. 5M IN A 10.0.8.156
+a-maximum-rrset.example. 5M IN A 10.0.8.157
+a-maximum-rrset.example. 5M IN A 10.0.8.158
+a-maximum-rrset.example. 5M IN A 10.0.8.159
+a-maximum-rrset.example. 5M IN A 10.0.8.160
+a-maximum-rrset.example. 5M IN A 10.0.8.161
+a-maximum-rrset.example. 5M IN A 10.0.8.162
+a-maximum-rrset.example. 5M IN A 10.0.8.163
+a-maximum-rrset.example. 5M IN A 10.0.8.164
+a-maximum-rrset.example. 5M IN A 10.0.8.165
+a-maximum-rrset.example. 5M IN A 10.0.8.166
+a-maximum-rrset.example. 5M IN A 10.0.8.167
+a-maximum-rrset.example. 5M IN A 10.0.8.168
+a-maximum-rrset.example. 5M IN A 10.0.8.169
+a-maximum-rrset.example. 5M IN A 10.0.8.170
+a-maximum-rrset.example. 5M IN A 10.0.8.171
+a-maximum-rrset.example. 5M IN A 10.0.8.172
+a-maximum-rrset.example. 5M IN A 10.0.8.173
+a-maximum-rrset.example. 5M IN A 10.0.8.174
+a-maximum-rrset.example. 5M IN A 10.0.8.175
+a-maximum-rrset.example. 5M IN A 10.0.8.176
+a-maximum-rrset.example. 5M IN A 10.0.8.177
+a-maximum-rrset.example. 5M IN A 10.0.8.178
+a-maximum-rrset.example. 5M IN A 10.0.8.179
+a-maximum-rrset.example. 5M IN A 10.0.8.180
+a-maximum-rrset.example. 5M IN A 10.0.8.181
+a-maximum-rrset.example. 5M IN A 10.0.8.182
+a-maximum-rrset.example. 5M IN A 10.0.8.183
+a-maximum-rrset.example. 5M IN A 10.0.8.184
+a-maximum-rrset.example. 5M IN A 10.0.8.185
+a-maximum-rrset.example. 5M IN A 10.0.8.186
+a-maximum-rrset.example. 5M IN A 10.0.8.187
+a-maximum-rrset.example. 5M IN A 10.0.8.188
+a-maximum-rrset.example. 5M IN A 10.0.8.189
+a-maximum-rrset.example. 5M IN A 10.0.8.190
+a-maximum-rrset.example. 5M IN A 10.0.8.191
+a-maximum-rrset.example. 5M IN A 10.0.8.192
+a-maximum-rrset.example. 5M IN A 10.0.8.193
+a-maximum-rrset.example. 5M IN A 10.0.8.194
+a-maximum-rrset.example. 5M IN A 10.0.8.195
+a-maximum-rrset.example. 5M IN A 10.0.8.196
+a-maximum-rrset.example. 5M IN A 10.0.8.197
+a-maximum-rrset.example. 5M IN A 10.0.8.198
+a-maximum-rrset.example. 5M IN A 10.0.8.199
+a-maximum-rrset.example. 5M IN A 10.0.8.200
+a-maximum-rrset.example. 5M IN A 10.0.8.201
+a-maximum-rrset.example. 5M IN A 10.0.8.202
+a-maximum-rrset.example. 5M IN A 10.0.8.203
+a-maximum-rrset.example. 5M IN A 10.0.8.204
+a-maximum-rrset.example. 5M IN A 10.0.8.205
+a-maximum-rrset.example. 5M IN A 10.0.8.206
+a-maximum-rrset.example. 5M IN A 10.0.8.207
+a-maximum-rrset.example. 5M IN A 10.0.8.208
+a-maximum-rrset.example. 5M IN A 10.0.8.209
+a-maximum-rrset.example. 5M IN A 10.0.8.210
+a-maximum-rrset.example. 5M IN A 10.0.8.211
+a-maximum-rrset.example. 5M IN A 10.0.8.212
+a-maximum-rrset.example. 5M IN A 10.0.8.213
+a-maximum-rrset.example. 5M IN A 10.0.8.214
+a-maximum-rrset.example. 5M IN A 10.0.8.215
+a-maximum-rrset.example. 5M IN A 10.0.8.216
+a-maximum-rrset.example. 5M IN A 10.0.8.217
+a-maximum-rrset.example. 5M IN A 10.0.8.218
+a-maximum-rrset.example. 5M IN A 10.0.8.219
+a-maximum-rrset.example. 5M IN A 10.0.8.220
+a-maximum-rrset.example. 5M IN A 10.0.8.221
+a-maximum-rrset.example. 5M IN A 10.0.8.222
+a-maximum-rrset.example. 5M IN A 10.0.8.223
+a-maximum-rrset.example. 5M IN A 10.0.8.224
+a-maximum-rrset.example. 5M IN A 10.0.8.225
+a-maximum-rrset.example. 5M IN A 10.0.8.226
+a-maximum-rrset.example. 5M IN A 10.0.8.227
+a-maximum-rrset.example. 5M IN A 10.0.8.228
+a-maximum-rrset.example. 5M IN A 10.0.8.229
+a-maximum-rrset.example. 5M IN A 10.0.8.230
+a-maximum-rrset.example. 5M IN A 10.0.8.231
+a-maximum-rrset.example. 5M IN A 10.0.8.232
+a-maximum-rrset.example. 5M IN A 10.0.8.233
+a-maximum-rrset.example. 5M IN A 10.0.8.234
+a-maximum-rrset.example. 5M IN A 10.0.8.235
+a-maximum-rrset.example. 5M IN A 10.0.8.236
+a-maximum-rrset.example. 5M IN A 10.0.8.237
+a-maximum-rrset.example. 5M IN A 10.0.8.238
+a-maximum-rrset.example. 5M IN A 10.0.8.239
+a-maximum-rrset.example. 5M IN A 10.0.8.240
+a-maximum-rrset.example. 5M IN A 10.0.8.241
+a-maximum-rrset.example. 5M IN A 10.0.8.242
+a-maximum-rrset.example. 5M IN A 10.0.8.243
+a-maximum-rrset.example. 5M IN A 10.0.8.244
+a-maximum-rrset.example. 5M IN A 10.0.8.245
+a-maximum-rrset.example. 5M IN A 10.0.8.246
+a-maximum-rrset.example. 5M IN A 10.0.8.247
+a-maximum-rrset.example. 5M IN A 10.0.8.248
+a-maximum-rrset.example. 5M IN A 10.0.8.249
+a-maximum-rrset.example. 5M IN A 10.0.8.250
+a-maximum-rrset.example. 5M IN A 10.0.8.251
+a-maximum-rrset.example. 5M IN A 10.0.8.252
+a-maximum-rrset.example. 5M IN A 10.0.8.253
+a-maximum-rrset.example. 5M IN A 10.0.8.254
+a-maximum-rrset.example. 5M IN A 10.0.8.255
+a-maximum-rrset.example. 5M IN A 10.0.9.0
+a-maximum-rrset.example. 5M IN A 10.0.9.1
+a-maximum-rrset.example. 5M IN A 10.0.9.2
+a-maximum-rrset.example. 5M IN A 10.0.9.3
+a-maximum-rrset.example. 5M IN A 10.0.9.4
+a-maximum-rrset.example. 5M IN A 10.0.9.5
+a-maximum-rrset.example. 5M IN A 10.0.9.6
+a-maximum-rrset.example. 5M IN A 10.0.9.7
+a-maximum-rrset.example. 5M IN A 10.0.9.8
+a-maximum-rrset.example. 5M IN A 10.0.9.9
+a-maximum-rrset.example. 5M IN A 10.0.9.10
+a-maximum-rrset.example. 5M IN A 10.0.9.11
+a-maximum-rrset.example. 5M IN A 10.0.9.12
+a-maximum-rrset.example. 5M IN A 10.0.9.13
+a-maximum-rrset.example. 5M IN A 10.0.9.14
+a-maximum-rrset.example. 5M IN A 10.0.9.15
+a-maximum-rrset.example. 5M IN A 10.0.9.16
+a-maximum-rrset.example. 5M IN A 10.0.9.17
+a-maximum-rrset.example. 5M IN A 10.0.9.18
+a-maximum-rrset.example. 5M IN A 10.0.9.19
+a-maximum-rrset.example. 5M IN A 10.0.9.20
+a-maximum-rrset.example. 5M IN A 10.0.9.21
+a-maximum-rrset.example. 5M IN A 10.0.9.22
+a-maximum-rrset.example. 5M IN A 10.0.9.23
+a-maximum-rrset.example. 5M IN A 10.0.9.24
+a-maximum-rrset.example. 5M IN A 10.0.9.25
+a-maximum-rrset.example. 5M IN A 10.0.9.26
+a-maximum-rrset.example. 5M IN A 10.0.9.27
+a-maximum-rrset.example. 5M IN A 10.0.9.28
+a-maximum-rrset.example. 5M IN A 10.0.9.29
+a-maximum-rrset.example. 5M IN A 10.0.9.30
+a-maximum-rrset.example. 5M IN A 10.0.9.31
+a-maximum-rrset.example. 5M IN A 10.0.9.32
+a-maximum-rrset.example. 5M IN A 10.0.9.33
+a-maximum-rrset.example. 5M IN A 10.0.9.34
+a-maximum-rrset.example. 5M IN A 10.0.9.35
+a-maximum-rrset.example. 5M IN A 10.0.9.36
+a-maximum-rrset.example. 5M IN A 10.0.9.37
+a-maximum-rrset.example. 5M IN A 10.0.9.38
+a-maximum-rrset.example. 5M IN A 10.0.9.39
+a-maximum-rrset.example. 5M IN A 10.0.9.40
+a-maximum-rrset.example. 5M IN A 10.0.9.41
+a-maximum-rrset.example. 5M IN A 10.0.9.42
+a-maximum-rrset.example. 5M IN A 10.0.9.43
+a-maximum-rrset.example. 5M IN A 10.0.9.44
+a-maximum-rrset.example. 5M IN A 10.0.9.45
+a-maximum-rrset.example. 5M IN A 10.0.9.46
+a-maximum-rrset.example. 5M IN A 10.0.9.47
+a-maximum-rrset.example. 5M IN A 10.0.9.48
+a-maximum-rrset.example. 5M IN A 10.0.9.49
+a-maximum-rrset.example. 5M IN A 10.0.9.50
+a-maximum-rrset.example. 5M IN A 10.0.9.51
+a-maximum-rrset.example. 5M IN A 10.0.9.52
+a-maximum-rrset.example. 5M IN A 10.0.9.53
+a-maximum-rrset.example. 5M IN A 10.0.9.54
+a-maximum-rrset.example. 5M IN A 10.0.9.55
+a-maximum-rrset.example. 5M IN A 10.0.9.56
+a-maximum-rrset.example. 5M IN A 10.0.9.57
+a-maximum-rrset.example. 5M IN A 10.0.9.58
+a-maximum-rrset.example. 5M IN A 10.0.9.59
+a-maximum-rrset.example. 5M IN A 10.0.9.60
+a-maximum-rrset.example. 5M IN A 10.0.9.61
+a-maximum-rrset.example. 5M IN A 10.0.9.62
+a-maximum-rrset.example. 5M IN A 10.0.9.63
+a-maximum-rrset.example. 5M IN A 10.0.9.64
+a-maximum-rrset.example. 5M IN A 10.0.9.65
+a-maximum-rrset.example. 5M IN A 10.0.9.66
+a-maximum-rrset.example. 5M IN A 10.0.9.67
+a-maximum-rrset.example. 5M IN A 10.0.9.68
+a-maximum-rrset.example. 5M IN A 10.0.9.69
+a-maximum-rrset.example. 5M IN A 10.0.9.70
+a-maximum-rrset.example. 5M IN A 10.0.9.71
+a-maximum-rrset.example. 5M IN A 10.0.9.72
+a-maximum-rrset.example. 5M IN A 10.0.9.73
+a-maximum-rrset.example. 5M IN A 10.0.9.74
+a-maximum-rrset.example. 5M IN A 10.0.9.75
+a-maximum-rrset.example. 5M IN A 10.0.9.76
+a-maximum-rrset.example. 5M IN A 10.0.9.77
+a-maximum-rrset.example. 5M IN A 10.0.9.78
+a-maximum-rrset.example. 5M IN A 10.0.9.79
+a-maximum-rrset.example. 5M IN A 10.0.9.80
+a-maximum-rrset.example. 5M IN A 10.0.9.81
+a-maximum-rrset.example. 5M IN A 10.0.9.82
+a-maximum-rrset.example. 5M IN A 10.0.9.83
+a-maximum-rrset.example. 5M IN A 10.0.9.84
+a-maximum-rrset.example. 5M IN A 10.0.9.85
+a-maximum-rrset.example. 5M IN A 10.0.9.86
+a-maximum-rrset.example. 5M IN A 10.0.9.87
+a-maximum-rrset.example. 5M IN A 10.0.9.88
+a-maximum-rrset.example. 5M IN A 10.0.9.89
+a-maximum-rrset.example. 5M IN A 10.0.9.90
+a-maximum-rrset.example. 5M IN A 10.0.9.91
+a-maximum-rrset.example. 5M IN A 10.0.9.92
+a-maximum-rrset.example. 5M IN A 10.0.9.93
+a-maximum-rrset.example. 5M IN A 10.0.9.94
+a-maximum-rrset.example. 5M IN A 10.0.9.95
+a-maximum-rrset.example. 5M IN A 10.0.9.96
+a-maximum-rrset.example. 5M IN A 10.0.9.97
+a-maximum-rrset.example. 5M IN A 10.0.9.98
+a-maximum-rrset.example. 5M IN A 10.0.9.99
+a-maximum-rrset.example. 5M IN A 10.0.9.100
+a-maximum-rrset.example. 5M IN A 10.0.9.101
+a-maximum-rrset.example. 5M IN A 10.0.9.102
+a-maximum-rrset.example. 5M IN A 10.0.9.103
+a-maximum-rrset.example. 5M IN A 10.0.9.104
+a-maximum-rrset.example. 5M IN A 10.0.9.105
+a-maximum-rrset.example. 5M IN A 10.0.9.106
+a-maximum-rrset.example. 5M IN A 10.0.9.107
+a-maximum-rrset.example. 5M IN A 10.0.9.108
+a-maximum-rrset.example. 5M IN A 10.0.9.109
+a-maximum-rrset.example. 5M IN A 10.0.9.110
+a-maximum-rrset.example. 5M IN A 10.0.9.111
+a-maximum-rrset.example. 5M IN A 10.0.9.112
+a-maximum-rrset.example. 5M IN A 10.0.9.113
+a-maximum-rrset.example. 5M IN A 10.0.9.114
+a-maximum-rrset.example. 5M IN A 10.0.9.115
+a-maximum-rrset.example. 5M IN A 10.0.9.116
+a-maximum-rrset.example. 5M IN A 10.0.9.117
+a-maximum-rrset.example. 5M IN A 10.0.9.118
+a-maximum-rrset.example. 5M IN A 10.0.9.119
+a-maximum-rrset.example. 5M IN A 10.0.9.120
+a-maximum-rrset.example. 5M IN A 10.0.9.121
+a-maximum-rrset.example. 5M IN A 10.0.9.122
+a-maximum-rrset.example. 5M IN A 10.0.9.123
+a-maximum-rrset.example. 5M IN A 10.0.9.124
+a-maximum-rrset.example. 5M IN A 10.0.9.125
+a-maximum-rrset.example. 5M IN A 10.0.9.126
+a-maximum-rrset.example. 5M IN A 10.0.9.127
+a-maximum-rrset.example. 5M IN A 10.0.9.128
+a-maximum-rrset.example. 5M IN A 10.0.9.129
+a-maximum-rrset.example. 5M IN A 10.0.9.130
+a-maximum-rrset.example. 5M IN A 10.0.9.131
+a-maximum-rrset.example. 5M IN A 10.0.9.132
+a-maximum-rrset.example. 5M IN A 10.0.9.133
+a-maximum-rrset.example. 5M IN A 10.0.9.134
+a-maximum-rrset.example. 5M IN A 10.0.9.135
+a-maximum-rrset.example. 5M IN A 10.0.9.136
+a-maximum-rrset.example. 5M IN A 10.0.9.137
+a-maximum-rrset.example. 5M IN A 10.0.9.138
+a-maximum-rrset.example. 5M IN A 10.0.9.139
+a-maximum-rrset.example. 5M IN A 10.0.9.140
+a-maximum-rrset.example. 5M IN A 10.0.9.141
+a-maximum-rrset.example. 5M IN A 10.0.9.142
+a-maximum-rrset.example. 5M IN A 10.0.9.143
+a-maximum-rrset.example. 5M IN A 10.0.9.144
+a-maximum-rrset.example. 5M IN A 10.0.9.145
+a-maximum-rrset.example. 5M IN A 10.0.9.146
+a-maximum-rrset.example. 5M IN A 10.0.9.147
+a-maximum-rrset.example. 5M IN A 10.0.9.148
+a-maximum-rrset.example. 5M IN A 10.0.9.149
+a-maximum-rrset.example. 5M IN A 10.0.9.150
+a-maximum-rrset.example. 5M IN A 10.0.9.151
+a-maximum-rrset.example. 5M IN A 10.0.9.152
+a-maximum-rrset.example. 5M IN A 10.0.9.153
+a-maximum-rrset.example. 5M IN A 10.0.9.154
+a-maximum-rrset.example. 5M IN A 10.0.9.155
+a-maximum-rrset.example. 5M IN A 10.0.9.156
+a-maximum-rrset.example. 5M IN A 10.0.9.157
+a-maximum-rrset.example. 5M IN A 10.0.9.158
+a-maximum-rrset.example. 5M IN A 10.0.9.159
+a-maximum-rrset.example. 5M IN A 10.0.9.160
+a-maximum-rrset.example. 5M IN A 10.0.9.161
+a-maximum-rrset.example. 5M IN A 10.0.9.162
+a-maximum-rrset.example. 5M IN A 10.0.9.163
+a-maximum-rrset.example. 5M IN A 10.0.9.164
+a-maximum-rrset.example. 5M IN A 10.0.9.165
+a-maximum-rrset.example. 5M IN A 10.0.9.166
+a-maximum-rrset.example. 5M IN A 10.0.9.167
+a-maximum-rrset.example. 5M IN A 10.0.9.168
+a-maximum-rrset.example. 5M IN A 10.0.9.169
+a-maximum-rrset.example. 5M IN A 10.0.9.170
+a-maximum-rrset.example. 5M IN A 10.0.9.171
+a-maximum-rrset.example. 5M IN A 10.0.9.172
+a-maximum-rrset.example. 5M IN A 10.0.9.173
+a-maximum-rrset.example. 5M IN A 10.0.9.174
+a-maximum-rrset.example. 5M IN A 10.0.9.175
+a-maximum-rrset.example. 5M IN A 10.0.9.176
+a-maximum-rrset.example. 5M IN A 10.0.9.177
+a-maximum-rrset.example. 5M IN A 10.0.9.178
+a-maximum-rrset.example. 5M IN A 10.0.9.179
+a-maximum-rrset.example. 5M IN A 10.0.9.180
+a-maximum-rrset.example. 5M IN A 10.0.9.181
+a-maximum-rrset.example. 5M IN A 10.0.9.182
+a-maximum-rrset.example. 5M IN A 10.0.9.183
+a-maximum-rrset.example. 5M IN A 10.0.9.184
+a-maximum-rrset.example. 5M IN A 10.0.9.185
+a-maximum-rrset.example. 5M IN A 10.0.9.186
+a-maximum-rrset.example. 5M IN A 10.0.9.187
+a-maximum-rrset.example. 5M IN A 10.0.9.188
+a-maximum-rrset.example. 5M IN A 10.0.9.189
+a-maximum-rrset.example. 5M IN A 10.0.9.190
+a-maximum-rrset.example. 5M IN A 10.0.9.191
+a-maximum-rrset.example. 5M IN A 10.0.9.192
+a-maximum-rrset.example. 5M IN A 10.0.9.193
+a-maximum-rrset.example. 5M IN A 10.0.9.194
+a-maximum-rrset.example. 5M IN A 10.0.9.195
+a-maximum-rrset.example. 5M IN A 10.0.9.196
+a-maximum-rrset.example. 5M IN A 10.0.9.197
+a-maximum-rrset.example. 5M IN A 10.0.9.198
+a-maximum-rrset.example. 5M IN A 10.0.9.199
+a-maximum-rrset.example. 5M IN A 10.0.9.200
+a-maximum-rrset.example. 5M IN A 10.0.9.201
+a-maximum-rrset.example. 5M IN A 10.0.9.202
+a-maximum-rrset.example. 5M IN A 10.0.9.203
+a-maximum-rrset.example. 5M IN A 10.0.9.204
+a-maximum-rrset.example. 5M IN A 10.0.9.205
+a-maximum-rrset.example. 5M IN A 10.0.9.206
+a-maximum-rrset.example. 5M IN A 10.0.9.207
+a-maximum-rrset.example. 5M IN A 10.0.9.208
+a-maximum-rrset.example. 5M IN A 10.0.9.209
+a-maximum-rrset.example. 5M IN A 10.0.9.210
+a-maximum-rrset.example. 5M IN A 10.0.9.211
+a-maximum-rrset.example. 5M IN A 10.0.9.212
+a-maximum-rrset.example. 5M IN A 10.0.9.213
+a-maximum-rrset.example. 5M IN A 10.0.9.214
+a-maximum-rrset.example. 5M IN A 10.0.9.215
+a-maximum-rrset.example. 5M IN A 10.0.9.216
+a-maximum-rrset.example. 5M IN A 10.0.9.217
+a-maximum-rrset.example. 5M IN A 10.0.9.218
+a-maximum-rrset.example. 5M IN A 10.0.9.219
+a-maximum-rrset.example. 5M IN A 10.0.9.220
+a-maximum-rrset.example. 5M IN A 10.0.9.221
+a-maximum-rrset.example. 5M IN A 10.0.9.222
+a-maximum-rrset.example. 5M IN A 10.0.9.223
+a-maximum-rrset.example. 5M IN A 10.0.9.224
+a-maximum-rrset.example. 5M IN A 10.0.9.225
+a-maximum-rrset.example. 5M IN A 10.0.9.226
+a-maximum-rrset.example. 5M IN A 10.0.9.227
+a-maximum-rrset.example. 5M IN A 10.0.9.228
+a-maximum-rrset.example. 5M IN A 10.0.9.229
+a-maximum-rrset.example. 5M IN A 10.0.9.230
+a-maximum-rrset.example. 5M IN A 10.0.9.231
+a-maximum-rrset.example. 5M IN A 10.0.9.232
+a-maximum-rrset.example. 5M IN A 10.0.9.233
+a-maximum-rrset.example. 5M IN A 10.0.9.234
+a-maximum-rrset.example. 5M IN A 10.0.9.235
+a-maximum-rrset.example. 5M IN A 10.0.9.236
+a-maximum-rrset.example. 5M IN A 10.0.9.237
+a-maximum-rrset.example. 5M IN A 10.0.9.238
+a-maximum-rrset.example. 5M IN A 10.0.9.239
+a-maximum-rrset.example. 5M IN A 10.0.9.240
+a-maximum-rrset.example. 5M IN A 10.0.9.241
+a-maximum-rrset.example. 5M IN A 10.0.9.242
+a-maximum-rrset.example. 5M IN A 10.0.9.243
+a-maximum-rrset.example. 5M IN A 10.0.9.244
+a-maximum-rrset.example. 5M IN A 10.0.9.245
+a-maximum-rrset.example. 5M IN A 10.0.9.246
+a-maximum-rrset.example. 5M IN A 10.0.9.247
+a-maximum-rrset.example. 5M IN A 10.0.9.248
+a-maximum-rrset.example. 5M IN A 10.0.9.249
+a-maximum-rrset.example. 5M IN A 10.0.9.250
+a-maximum-rrset.example. 5M IN A 10.0.9.251
+a-maximum-rrset.example. 5M IN A 10.0.9.252
+a-maximum-rrset.example. 5M IN A 10.0.9.253
+a-maximum-rrset.example. 5M IN A 10.0.9.254
+a-maximum-rrset.example. 5M IN A 10.0.9.255
+a-maximum-rrset.example. 5M IN A 10.0.10.0
+a-maximum-rrset.example. 5M IN A 10.0.10.1
+a-maximum-rrset.example. 5M IN A 10.0.10.2
+a-maximum-rrset.example. 5M IN A 10.0.10.3
+a-maximum-rrset.example. 5M IN A 10.0.10.4
+a-maximum-rrset.example. 5M IN A 10.0.10.5
+a-maximum-rrset.example. 5M IN A 10.0.10.6
+a-maximum-rrset.example. 5M IN A 10.0.10.7
+a-maximum-rrset.example. 5M IN A 10.0.10.8
+a-maximum-rrset.example. 5M IN A 10.0.10.9
+a-maximum-rrset.example. 5M IN A 10.0.10.10
+a-maximum-rrset.example. 5M IN A 10.0.10.11
+a-maximum-rrset.example. 5M IN A 10.0.10.12
+a-maximum-rrset.example. 5M IN A 10.0.10.13
+a-maximum-rrset.example. 5M IN A 10.0.10.14
+a-maximum-rrset.example. 5M IN A 10.0.10.15
+a-maximum-rrset.example. 5M IN A 10.0.10.16
+a-maximum-rrset.example. 5M IN A 10.0.10.17
+a-maximum-rrset.example. 5M IN A 10.0.10.18
+a-maximum-rrset.example. 5M IN A 10.0.10.19
+a-maximum-rrset.example. 5M IN A 10.0.10.20
+a-maximum-rrset.example. 5M IN A 10.0.10.21
+a-maximum-rrset.example. 5M IN A 10.0.10.22
+a-maximum-rrset.example. 5M IN A 10.0.10.23
+a-maximum-rrset.example. 5M IN A 10.0.10.24
+a-maximum-rrset.example. 5M IN A 10.0.10.25
+a-maximum-rrset.example. 5M IN A 10.0.10.26
+a-maximum-rrset.example. 5M IN A 10.0.10.27
+a-maximum-rrset.example. 5M IN A 10.0.10.28
+a-maximum-rrset.example. 5M IN A 10.0.10.29
+a-maximum-rrset.example. 5M IN A 10.0.10.30
+a-maximum-rrset.example. 5M IN A 10.0.10.31
+a-maximum-rrset.example. 5M IN A 10.0.10.32
+a-maximum-rrset.example. 5M IN A 10.0.10.33
+a-maximum-rrset.example. 5M IN A 10.0.10.34
+a-maximum-rrset.example. 5M IN A 10.0.10.35
+a-maximum-rrset.example. 5M IN A 10.0.10.36
+a-maximum-rrset.example. 5M IN A 10.0.10.37
+a-maximum-rrset.example. 5M IN A 10.0.10.38
+a-maximum-rrset.example. 5M IN A 10.0.10.39
+a-maximum-rrset.example. 5M IN A 10.0.10.40
+a-maximum-rrset.example. 5M IN A 10.0.10.41
+a-maximum-rrset.example. 5M IN A 10.0.10.42
+a-maximum-rrset.example. 5M IN A 10.0.10.43
+a-maximum-rrset.example. 5M IN A 10.0.10.44
+a-maximum-rrset.example. 5M IN A 10.0.10.45
+a-maximum-rrset.example. 5M IN A 10.0.10.46
+a-maximum-rrset.example. 5M IN A 10.0.10.47
+a-maximum-rrset.example. 5M IN A 10.0.10.48
+a-maximum-rrset.example. 5M IN A 10.0.10.49
+a-maximum-rrset.example. 5M IN A 10.0.10.50
+a-maximum-rrset.example. 5M IN A 10.0.10.51
+a-maximum-rrset.example. 5M IN A 10.0.10.52
+a-maximum-rrset.example. 5M IN A 10.0.10.53
+a-maximum-rrset.example. 5M IN A 10.0.10.54
+a-maximum-rrset.example. 5M IN A 10.0.10.55
+a-maximum-rrset.example. 5M IN A 10.0.10.56
+a-maximum-rrset.example. 5M IN A 10.0.10.57
+a-maximum-rrset.example. 5M IN A 10.0.10.58
+a-maximum-rrset.example. 5M IN A 10.0.10.59
+a-maximum-rrset.example. 5M IN A 10.0.10.60
+a-maximum-rrset.example. 5M IN A 10.0.10.61
+a-maximum-rrset.example. 5M IN A 10.0.10.62
+a-maximum-rrset.example. 5M IN A 10.0.10.63
+a-maximum-rrset.example. 5M IN A 10.0.10.64
+a-maximum-rrset.example. 5M IN A 10.0.10.65
+a-maximum-rrset.example. 5M IN A 10.0.10.66
+a-maximum-rrset.example. 5M IN A 10.0.10.67
+a-maximum-rrset.example. 5M IN A 10.0.10.68
+a-maximum-rrset.example. 5M IN A 10.0.10.69
+a-maximum-rrset.example. 5M IN A 10.0.10.70
+a-maximum-rrset.example. 5M IN A 10.0.10.71
+a-maximum-rrset.example. 5M IN A 10.0.10.72
+a-maximum-rrset.example. 5M IN A 10.0.10.73
+a-maximum-rrset.example. 5M IN A 10.0.10.74
+a-maximum-rrset.example. 5M IN A 10.0.10.75
+a-maximum-rrset.example. 5M IN A 10.0.10.76
+a-maximum-rrset.example. 5M IN A 10.0.10.77
+a-maximum-rrset.example. 5M IN A 10.0.10.78
+a-maximum-rrset.example. 5M IN A 10.0.10.79
+a-maximum-rrset.example. 5M IN A 10.0.10.80
+a-maximum-rrset.example. 5M IN A 10.0.10.81
+a-maximum-rrset.example. 5M IN A 10.0.10.82
+a-maximum-rrset.example. 5M IN A 10.0.10.83
+a-maximum-rrset.example. 5M IN A 10.0.10.84
+a-maximum-rrset.example. 5M IN A 10.0.10.85
+a-maximum-rrset.example. 5M IN A 10.0.10.86
+a-maximum-rrset.example. 5M IN A 10.0.10.87
+a-maximum-rrset.example. 5M IN A 10.0.10.88
+a-maximum-rrset.example. 5M IN A 10.0.10.89
+a-maximum-rrset.example. 5M IN A 10.0.10.90
+a-maximum-rrset.example. 5M IN A 10.0.10.91
+a-maximum-rrset.example. 5M IN A 10.0.10.92
+a-maximum-rrset.example. 5M IN A 10.0.10.93
+a-maximum-rrset.example. 5M IN A 10.0.10.94
+a-maximum-rrset.example. 5M IN A 10.0.10.95
+a-maximum-rrset.example. 5M IN A 10.0.10.96
+a-maximum-rrset.example. 5M IN A 10.0.10.97
+a-maximum-rrset.example. 5M IN A 10.0.10.98
+a-maximum-rrset.example. 5M IN A 10.0.10.99
+a-maximum-rrset.example. 5M IN A 10.0.10.100
+a-maximum-rrset.example. 5M IN A 10.0.10.101
+a-maximum-rrset.example. 5M IN A 10.0.10.102
+a-maximum-rrset.example. 5M IN A 10.0.10.103
+a-maximum-rrset.example. 5M IN A 10.0.10.104
+a-maximum-rrset.example. 5M IN A 10.0.10.105
+a-maximum-rrset.example. 5M IN A 10.0.10.106
+a-maximum-rrset.example. 5M IN A 10.0.10.107
+a-maximum-rrset.example. 5M IN A 10.0.10.108
+a-maximum-rrset.example. 5M IN A 10.0.10.109
+a-maximum-rrset.example. 5M IN A 10.0.10.110
+a-maximum-rrset.example. 5M IN A 10.0.10.111
+a-maximum-rrset.example. 5M IN A 10.0.10.112
+a-maximum-rrset.example. 5M IN A 10.0.10.113
+a-maximum-rrset.example. 5M IN A 10.0.10.114
+a-maximum-rrset.example. 5M IN A 10.0.10.115
+a-maximum-rrset.example. 5M IN A 10.0.10.116
+a-maximum-rrset.example. 5M IN A 10.0.10.117
+a-maximum-rrset.example. 5M IN A 10.0.10.118
+a-maximum-rrset.example. 5M IN A 10.0.10.119
+a-maximum-rrset.example. 5M IN A 10.0.10.120
+a-maximum-rrset.example. 5M IN A 10.0.10.121
+a-maximum-rrset.example. 5M IN A 10.0.10.122
+a-maximum-rrset.example. 5M IN A 10.0.10.123
+a-maximum-rrset.example. 5M IN A 10.0.10.124
+a-maximum-rrset.example. 5M IN A 10.0.10.125
+a-maximum-rrset.example. 5M IN A 10.0.10.126
+a-maximum-rrset.example. 5M IN A 10.0.10.127
+a-maximum-rrset.example. 5M IN A 10.0.10.128
+a-maximum-rrset.example. 5M IN A 10.0.10.129
+a-maximum-rrset.example. 5M IN A 10.0.10.130
+a-maximum-rrset.example. 5M IN A 10.0.10.131
+a-maximum-rrset.example. 5M IN A 10.0.10.132
+a-maximum-rrset.example. 5M IN A 10.0.10.133
+a-maximum-rrset.example. 5M IN A 10.0.10.134
+a-maximum-rrset.example. 5M IN A 10.0.10.135
+a-maximum-rrset.example. 5M IN A 10.0.10.136
+a-maximum-rrset.example. 5M IN A 10.0.10.137
+a-maximum-rrset.example. 5M IN A 10.0.10.138
+a-maximum-rrset.example. 5M IN A 10.0.10.139
+a-maximum-rrset.example. 5M IN A 10.0.10.140
+a-maximum-rrset.example. 5M IN A 10.0.10.141
+a-maximum-rrset.example. 5M IN A 10.0.10.142
+a-maximum-rrset.example. 5M IN A 10.0.10.143
+a-maximum-rrset.example. 5M IN A 10.0.10.144
+a-maximum-rrset.example. 5M IN A 10.0.10.145
+a-maximum-rrset.example. 5M IN A 10.0.10.146
+a-maximum-rrset.example. 5M IN A 10.0.10.147
+a-maximum-rrset.example. 5M IN A 10.0.10.148
+a-maximum-rrset.example. 5M IN A 10.0.10.149
+a-maximum-rrset.example. 5M IN A 10.0.10.150
+a-maximum-rrset.example. 5M IN A 10.0.10.151
+a-maximum-rrset.example. 5M IN A 10.0.10.152
+a-maximum-rrset.example. 5M IN A 10.0.10.153
+a-maximum-rrset.example. 5M IN A 10.0.10.154
+a-maximum-rrset.example. 5M IN A 10.0.10.155
+a-maximum-rrset.example. 5M IN A 10.0.10.156
+a-maximum-rrset.example. 5M IN A 10.0.10.157
+a-maximum-rrset.example. 5M IN A 10.0.10.158
+a-maximum-rrset.example. 5M IN A 10.0.10.159
+a-maximum-rrset.example. 5M IN A 10.0.10.160
+a-maximum-rrset.example. 5M IN A 10.0.10.161
+a-maximum-rrset.example. 5M IN A 10.0.10.162
+a-maximum-rrset.example. 5M IN A 10.0.10.163
+a-maximum-rrset.example. 5M IN A 10.0.10.164
+a-maximum-rrset.example. 5M IN A 10.0.10.165
+a-maximum-rrset.example. 5M IN A 10.0.10.166
+a-maximum-rrset.example. 5M IN A 10.0.10.167
+a-maximum-rrset.example. 5M IN A 10.0.10.168
+a-maximum-rrset.example. 5M IN A 10.0.10.169
+a-maximum-rrset.example. 5M IN A 10.0.10.170
+a-maximum-rrset.example. 5M IN A 10.0.10.171
+a-maximum-rrset.example. 5M IN A 10.0.10.172
+a-maximum-rrset.example. 5M IN A 10.0.10.173
+a-maximum-rrset.example. 5M IN A 10.0.10.174
+a-maximum-rrset.example. 5M IN A 10.0.10.175
+a-maximum-rrset.example. 5M IN A 10.0.10.176
+a-maximum-rrset.example. 5M IN A 10.0.10.177
+a-maximum-rrset.example. 5M IN A 10.0.10.178
+a-maximum-rrset.example. 5M IN A 10.0.10.179
+a-maximum-rrset.example. 5M IN A 10.0.10.180
+a-maximum-rrset.example. 5M IN A 10.0.10.181
+a-maximum-rrset.example. 5M IN A 10.0.10.182
+a-maximum-rrset.example. 5M IN A 10.0.10.183
+a-maximum-rrset.example. 5M IN A 10.0.10.184
+a-maximum-rrset.example. 5M IN A 10.0.10.185
+a-maximum-rrset.example. 5M IN A 10.0.10.186
+a-maximum-rrset.example. 5M IN A 10.0.10.187
+a-maximum-rrset.example. 5M IN A 10.0.10.188
+a-maximum-rrset.example. 5M IN A 10.0.10.189
+a-maximum-rrset.example. 5M IN A 10.0.10.190
+a-maximum-rrset.example. 5M IN A 10.0.10.191
+a-maximum-rrset.example. 5M IN A 10.0.10.192
+a-maximum-rrset.example. 5M IN A 10.0.10.193
+a-maximum-rrset.example. 5M IN A 10.0.10.194
+a-maximum-rrset.example. 5M IN A 10.0.10.195
+a-maximum-rrset.example. 5M IN A 10.0.10.196
+a-maximum-rrset.example. 5M IN A 10.0.10.197
+a-maximum-rrset.example. 5M IN A 10.0.10.198
+a-maximum-rrset.example. 5M IN A 10.0.10.199
+a-maximum-rrset.example. 5M IN A 10.0.10.200
+a-maximum-rrset.example. 5M IN A 10.0.10.201
+a-maximum-rrset.example. 5M IN A 10.0.10.202
+a-maximum-rrset.example. 5M IN A 10.0.10.203
+a-maximum-rrset.example. 5M IN A 10.0.10.204
+a-maximum-rrset.example. 5M IN A 10.0.10.205
+a-maximum-rrset.example. 5M IN A 10.0.10.206
+a-maximum-rrset.example. 5M IN A 10.0.10.207
+a-maximum-rrset.example. 5M IN A 10.0.10.208
+a-maximum-rrset.example. 5M IN A 10.0.10.209
+a-maximum-rrset.example. 5M IN A 10.0.10.210
+a-maximum-rrset.example. 5M IN A 10.0.10.211
+a-maximum-rrset.example. 5M IN A 10.0.10.212
+a-maximum-rrset.example. 5M IN A 10.0.10.213
+a-maximum-rrset.example. 5M IN A 10.0.10.214
+a-maximum-rrset.example. 5M IN A 10.0.10.215
+a-maximum-rrset.example. 5M IN A 10.0.10.216
+a-maximum-rrset.example. 5M IN A 10.0.10.217
+a-maximum-rrset.example. 5M IN A 10.0.10.218
+a-maximum-rrset.example. 5M IN A 10.0.10.219
+a-maximum-rrset.example. 5M IN A 10.0.10.220
+a-maximum-rrset.example. 5M IN A 10.0.10.221
+a-maximum-rrset.example. 5M IN A 10.0.10.222
+a-maximum-rrset.example. 5M IN A 10.0.10.223
+a-maximum-rrset.example. 5M IN A 10.0.10.224
+a-maximum-rrset.example. 5M IN A 10.0.10.225
+a-maximum-rrset.example. 5M IN A 10.0.10.226
+a-maximum-rrset.example. 5M IN A 10.0.10.227
+a-maximum-rrset.example. 5M IN A 10.0.10.228
+a-maximum-rrset.example. 5M IN A 10.0.10.229
+a-maximum-rrset.example. 5M IN A 10.0.10.230
+a-maximum-rrset.example. 5M IN A 10.0.10.231
+a-maximum-rrset.example. 5M IN A 10.0.10.232
+a-maximum-rrset.example. 5M IN A 10.0.10.233
+a-maximum-rrset.example. 5M IN A 10.0.10.234
+a-maximum-rrset.example. 5M IN A 10.0.10.235
+a-maximum-rrset.example. 5M IN A 10.0.10.236
+a-maximum-rrset.example. 5M IN A 10.0.10.237
+a-maximum-rrset.example. 5M IN A 10.0.10.238
+a-maximum-rrset.example. 5M IN A 10.0.10.239
+a-maximum-rrset.example. 5M IN A 10.0.10.240
+a-maximum-rrset.example. 5M IN A 10.0.10.241
+a-maximum-rrset.example. 5M IN A 10.0.10.242
+a-maximum-rrset.example. 5M IN A 10.0.10.243
+a-maximum-rrset.example. 5M IN A 10.0.10.244
+a-maximum-rrset.example. 5M IN A 10.0.10.245
+a-maximum-rrset.example. 5M IN A 10.0.10.246
+a-maximum-rrset.example. 5M IN A 10.0.10.247
+a-maximum-rrset.example. 5M IN A 10.0.10.248
+a-maximum-rrset.example. 5M IN A 10.0.10.249
+a-maximum-rrset.example. 5M IN A 10.0.10.250
+a-maximum-rrset.example. 5M IN A 10.0.10.251
+a-maximum-rrset.example. 5M IN A 10.0.10.252
+a-maximum-rrset.example. 5M IN A 10.0.10.253
+a-maximum-rrset.example. 5M IN A 10.0.10.254
+a-maximum-rrset.example. 5M IN A 10.0.10.255
+a-maximum-rrset.example. 5M IN A 10.0.11.0
+a-maximum-rrset.example. 5M IN A 10.0.11.1
+a-maximum-rrset.example. 5M IN A 10.0.11.2
+a-maximum-rrset.example. 5M IN A 10.0.11.3
+a-maximum-rrset.example. 5M IN A 10.0.11.4
+a-maximum-rrset.example. 5M IN A 10.0.11.5
+a-maximum-rrset.example. 5M IN A 10.0.11.6
+a-maximum-rrset.example. 5M IN A 10.0.11.7
+a-maximum-rrset.example. 5M IN A 10.0.11.8
+a-maximum-rrset.example. 5M IN A 10.0.11.9
+a-maximum-rrset.example. 5M IN A 10.0.11.10
+a-maximum-rrset.example. 5M IN A 10.0.11.11
+a-maximum-rrset.example. 5M IN A 10.0.11.12
+a-maximum-rrset.example. 5M IN A 10.0.11.13
+a-maximum-rrset.example. 5M IN A 10.0.11.14
+a-maximum-rrset.example. 5M IN A 10.0.11.15
+a-maximum-rrset.example. 5M IN A 10.0.11.16
+a-maximum-rrset.example. 5M IN A 10.0.11.17
+a-maximum-rrset.example. 5M IN A 10.0.11.18
+a-maximum-rrset.example. 5M IN A 10.0.11.19
+a-maximum-rrset.example. 5M IN A 10.0.11.20
+a-maximum-rrset.example. 5M IN A 10.0.11.21
+a-maximum-rrset.example. 5M IN A 10.0.11.22
+a-maximum-rrset.example. 5M IN A 10.0.11.23
+a-maximum-rrset.example. 5M IN A 10.0.11.24
+a-maximum-rrset.example. 5M IN A 10.0.11.25
+a-maximum-rrset.example. 5M IN A 10.0.11.26
+a-maximum-rrset.example. 5M IN A 10.0.11.27
+a-maximum-rrset.example. 5M IN A 10.0.11.28
+a-maximum-rrset.example. 5M IN A 10.0.11.29
+a-maximum-rrset.example. 5M IN A 10.0.11.30
+a-maximum-rrset.example. 5M IN A 10.0.11.31
+a-maximum-rrset.example. 5M IN A 10.0.11.32
+a-maximum-rrset.example. 5M IN A 10.0.11.33
+a-maximum-rrset.example. 5M IN A 10.0.11.34
+a-maximum-rrset.example. 5M IN A 10.0.11.35
+a-maximum-rrset.example. 5M IN A 10.0.11.36
+a-maximum-rrset.example. 5M IN A 10.0.11.37
+a-maximum-rrset.example. 5M IN A 10.0.11.38
+a-maximum-rrset.example. 5M IN A 10.0.11.39
+a-maximum-rrset.example. 5M IN A 10.0.11.40
+a-maximum-rrset.example. 5M IN A 10.0.11.41
+a-maximum-rrset.example. 5M IN A 10.0.11.42
+a-maximum-rrset.example. 5M IN A 10.0.11.43
+a-maximum-rrset.example. 5M IN A 10.0.11.44
+a-maximum-rrset.example. 5M IN A 10.0.11.45
+a-maximum-rrset.example. 5M IN A 10.0.11.46
+a-maximum-rrset.example. 5M IN A 10.0.11.47
+a-maximum-rrset.example. 5M IN A 10.0.11.48
+a-maximum-rrset.example. 5M IN A 10.0.11.49
+a-maximum-rrset.example. 5M IN A 10.0.11.50
+a-maximum-rrset.example. 5M IN A 10.0.11.51
+a-maximum-rrset.example. 5M IN A 10.0.11.52
+a-maximum-rrset.example. 5M IN A 10.0.11.53
+a-maximum-rrset.example. 5M IN A 10.0.11.54
+a-maximum-rrset.example. 5M IN A 10.0.11.55
+a-maximum-rrset.example. 5M IN A 10.0.11.56
+a-maximum-rrset.example. 5M IN A 10.0.11.57
+a-maximum-rrset.example. 5M IN A 10.0.11.58
+a-maximum-rrset.example. 5M IN A 10.0.11.59
+a-maximum-rrset.example. 5M IN A 10.0.11.60
+a-maximum-rrset.example. 5M IN A 10.0.11.61
+a-maximum-rrset.example. 5M IN A 10.0.11.62
+a-maximum-rrset.example. 5M IN A 10.0.11.63
+a-maximum-rrset.example. 5M IN A 10.0.11.64
+a-maximum-rrset.example. 5M IN A 10.0.11.65
+a-maximum-rrset.example. 5M IN A 10.0.11.66
+a-maximum-rrset.example. 5M IN A 10.0.11.67
+a-maximum-rrset.example. 5M IN A 10.0.11.68
+a-maximum-rrset.example. 5M IN A 10.0.11.69
+a-maximum-rrset.example. 5M IN A 10.0.11.70
+a-maximum-rrset.example. 5M IN A 10.0.11.71
+a-maximum-rrset.example. 5M IN A 10.0.11.72
+a-maximum-rrset.example. 5M IN A 10.0.11.73
+a-maximum-rrset.example. 5M IN A 10.0.11.74
+a-maximum-rrset.example. 5M IN A 10.0.11.75
+a-maximum-rrset.example. 5M IN A 10.0.11.76
+a-maximum-rrset.example. 5M IN A 10.0.11.77
+a-maximum-rrset.example. 5M IN A 10.0.11.78
+a-maximum-rrset.example. 5M IN A 10.0.11.79
+a-maximum-rrset.example. 5M IN A 10.0.11.80
+a-maximum-rrset.example. 5M IN A 10.0.11.81
+a-maximum-rrset.example. 5M IN A 10.0.11.82
+a-maximum-rrset.example. 5M IN A 10.0.11.83
+a-maximum-rrset.example. 5M IN A 10.0.11.84
+a-maximum-rrset.example. 5M IN A 10.0.11.85
+a-maximum-rrset.example. 5M IN A 10.0.11.86
+a-maximum-rrset.example. 5M IN A 10.0.11.87
+a-maximum-rrset.example. 5M IN A 10.0.11.88
+a-maximum-rrset.example. 5M IN A 10.0.11.89
+a-maximum-rrset.example. 5M IN A 10.0.11.90
+a-maximum-rrset.example. 5M IN A 10.0.11.91
+a-maximum-rrset.example. 5M IN A 10.0.11.92
+a-maximum-rrset.example. 5M IN A 10.0.11.93
+a-maximum-rrset.example. 5M IN A 10.0.11.94
+a-maximum-rrset.example. 5M IN A 10.0.11.95
+a-maximum-rrset.example. 5M IN A 10.0.11.96
+a-maximum-rrset.example. 5M IN A 10.0.11.97
+a-maximum-rrset.example. 5M IN A 10.0.11.98
+a-maximum-rrset.example. 5M IN A 10.0.11.99
+a-maximum-rrset.example. 5M IN A 10.0.11.100
+a-maximum-rrset.example. 5M IN A 10.0.11.101
+a-maximum-rrset.example. 5M IN A 10.0.11.102
+a-maximum-rrset.example. 5M IN A 10.0.11.103
+a-maximum-rrset.example. 5M IN A 10.0.11.104
+a-maximum-rrset.example. 5M IN A 10.0.11.105
+a-maximum-rrset.example. 5M IN A 10.0.11.106
+a-maximum-rrset.example. 5M IN A 10.0.11.107
+a-maximum-rrset.example. 5M IN A 10.0.11.108
+a-maximum-rrset.example. 5M IN A 10.0.11.109
+a-maximum-rrset.example. 5M IN A 10.0.11.110
+a-maximum-rrset.example. 5M IN A 10.0.11.111
+a-maximum-rrset.example. 5M IN A 10.0.11.112
+a-maximum-rrset.example. 5M IN A 10.0.11.113
+a-maximum-rrset.example. 5M IN A 10.0.11.114
+a-maximum-rrset.example. 5M IN A 10.0.11.115
+a-maximum-rrset.example. 5M IN A 10.0.11.116
+a-maximum-rrset.example. 5M IN A 10.0.11.117
+a-maximum-rrset.example. 5M IN A 10.0.11.118
+a-maximum-rrset.example. 5M IN A 10.0.11.119
+a-maximum-rrset.example. 5M IN A 10.0.11.120
+a-maximum-rrset.example. 5M IN A 10.0.11.121
+a-maximum-rrset.example. 5M IN A 10.0.11.122
+a-maximum-rrset.example. 5M IN A 10.0.11.123
+a-maximum-rrset.example. 5M IN A 10.0.11.124
+a-maximum-rrset.example. 5M IN A 10.0.11.125
+a-maximum-rrset.example. 5M IN A 10.0.11.126
+a-maximum-rrset.example. 5M IN A 10.0.11.127
+a-maximum-rrset.example. 5M IN A 10.0.11.128
+a-maximum-rrset.example. 5M IN A 10.0.11.129
+a-maximum-rrset.example. 5M IN A 10.0.11.130
+a-maximum-rrset.example. 5M IN A 10.0.11.131
+a-maximum-rrset.example. 5M IN A 10.0.11.132
+a-maximum-rrset.example. 5M IN A 10.0.11.133
+a-maximum-rrset.example. 5M IN A 10.0.11.134
+a-maximum-rrset.example. 5M IN A 10.0.11.135
+a-maximum-rrset.example. 5M IN A 10.0.11.136
+a-maximum-rrset.example. 5M IN A 10.0.11.137
+a-maximum-rrset.example. 5M IN A 10.0.11.138
+a-maximum-rrset.example. 5M IN A 10.0.11.139
+a-maximum-rrset.example. 5M IN A 10.0.11.140
+a-maximum-rrset.example. 5M IN A 10.0.11.141
+a-maximum-rrset.example. 5M IN A 10.0.11.142
+a-maximum-rrset.example. 5M IN A 10.0.11.143
+a-maximum-rrset.example. 5M IN A 10.0.11.144
+a-maximum-rrset.example. 5M IN A 10.0.11.145
+a-maximum-rrset.example. 5M IN A 10.0.11.146
+a-maximum-rrset.example. 5M IN A 10.0.11.147
+a-maximum-rrset.example. 5M IN A 10.0.11.148
+a-maximum-rrset.example. 5M IN A 10.0.11.149
+a-maximum-rrset.example. 5M IN A 10.0.11.150
+a-maximum-rrset.example. 5M IN A 10.0.11.151
+a-maximum-rrset.example. 5M IN A 10.0.11.152
+a-maximum-rrset.example. 5M IN A 10.0.11.153
+a-maximum-rrset.example. 5M IN A 10.0.11.154
+a-maximum-rrset.example. 5M IN A 10.0.11.155
+a-maximum-rrset.example. 5M IN A 10.0.11.156
+a-maximum-rrset.example. 5M IN A 10.0.11.157
+a-maximum-rrset.example. 5M IN A 10.0.11.158
+a-maximum-rrset.example. 5M IN A 10.0.11.159
+a-maximum-rrset.example. 5M IN A 10.0.11.160
+a-maximum-rrset.example. 5M IN A 10.0.11.161
+a-maximum-rrset.example. 5M IN A 10.0.11.162
+a-maximum-rrset.example. 5M IN A 10.0.11.163
+a-maximum-rrset.example. 5M IN A 10.0.11.164
+a-maximum-rrset.example. 5M IN A 10.0.11.165
+a-maximum-rrset.example. 5M IN A 10.0.11.166
+a-maximum-rrset.example. 5M IN A 10.0.11.167
+a-maximum-rrset.example. 5M IN A 10.0.11.168
+a-maximum-rrset.example. 5M IN A 10.0.11.169
+a-maximum-rrset.example. 5M IN A 10.0.11.170
+a-maximum-rrset.example. 5M IN A 10.0.11.171
+a-maximum-rrset.example. 5M IN A 10.0.11.172
+a-maximum-rrset.example. 5M IN A 10.0.11.173
+a-maximum-rrset.example. 5M IN A 10.0.11.174
+a-maximum-rrset.example. 5M IN A 10.0.11.175
+a-maximum-rrset.example. 5M IN A 10.0.11.176
+a-maximum-rrset.example. 5M IN A 10.0.11.177
+a-maximum-rrset.example. 5M IN A 10.0.11.178
+a-maximum-rrset.example. 5M IN A 10.0.11.179
+a-maximum-rrset.example. 5M IN A 10.0.11.180
+a-maximum-rrset.example. 5M IN A 10.0.11.181
+a-maximum-rrset.example. 5M IN A 10.0.11.182
+a-maximum-rrset.example. 5M IN A 10.0.11.183
+a-maximum-rrset.example. 5M IN A 10.0.11.184
+a-maximum-rrset.example. 5M IN A 10.0.11.185
+a-maximum-rrset.example. 5M IN A 10.0.11.186
+a-maximum-rrset.example. 5M IN A 10.0.11.187
+a-maximum-rrset.example. 5M IN A 10.0.11.188
+a-maximum-rrset.example. 5M IN A 10.0.11.189
+a-maximum-rrset.example. 5M IN A 10.0.11.190
+a-maximum-rrset.example. 5M IN A 10.0.11.191
+a-maximum-rrset.example. 5M IN A 10.0.11.192
+a-maximum-rrset.example. 5M IN A 10.0.11.193
+a-maximum-rrset.example. 5M IN A 10.0.11.194
+a-maximum-rrset.example. 5M IN A 10.0.11.195
+a-maximum-rrset.example. 5M IN A 10.0.11.196
+a-maximum-rrset.example. 5M IN A 10.0.11.197
+a-maximum-rrset.example. 5M IN A 10.0.11.198
+a-maximum-rrset.example. 5M IN A 10.0.11.199
+a-maximum-rrset.example. 5M IN A 10.0.11.200
+a-maximum-rrset.example. 5M IN A 10.0.11.201
+a-maximum-rrset.example. 5M IN A 10.0.11.202
+a-maximum-rrset.example. 5M IN A 10.0.11.203
+a-maximum-rrset.example. 5M IN A 10.0.11.204
+a-maximum-rrset.example. 5M IN A 10.0.11.205
+a-maximum-rrset.example. 5M IN A 10.0.11.206
+a-maximum-rrset.example. 5M IN A 10.0.11.207
+a-maximum-rrset.example. 5M IN A 10.0.11.208
+a-maximum-rrset.example. 5M IN A 10.0.11.209
+a-maximum-rrset.example. 5M IN A 10.0.11.210
+a-maximum-rrset.example. 5M IN A 10.0.11.211
+a-maximum-rrset.example. 5M IN A 10.0.11.212
+a-maximum-rrset.example. 5M IN A 10.0.11.213
+a-maximum-rrset.example. 5M IN A 10.0.11.214
+a-maximum-rrset.example. 5M IN A 10.0.11.215
+a-maximum-rrset.example. 5M IN A 10.0.11.216
+a-maximum-rrset.example. 5M IN A 10.0.11.217
+a-maximum-rrset.example. 5M IN A 10.0.11.218
+a-maximum-rrset.example. 5M IN A 10.0.11.219
+a-maximum-rrset.example. 5M IN A 10.0.11.220
+a-maximum-rrset.example. 5M IN A 10.0.11.221
+a-maximum-rrset.example. 5M IN A 10.0.11.222
+a-maximum-rrset.example. 5M IN A 10.0.11.223
+a-maximum-rrset.example. 5M IN A 10.0.11.224
+a-maximum-rrset.example. 5M IN A 10.0.11.225
+a-maximum-rrset.example. 5M IN A 10.0.11.226
+a-maximum-rrset.example. 5M IN A 10.0.11.227
+a-maximum-rrset.example. 5M IN A 10.0.11.228
+a-maximum-rrset.example. 5M IN A 10.0.11.229
+a-maximum-rrset.example. 5M IN A 10.0.11.230
+a-maximum-rrset.example. 5M IN A 10.0.11.231
+a-maximum-rrset.example. 5M IN A 10.0.11.232
+a-maximum-rrset.example. 5M IN A 10.0.11.233
+a-maximum-rrset.example. 5M IN A 10.0.11.234
+a-maximum-rrset.example. 5M IN A 10.0.11.235
+a-maximum-rrset.example. 5M IN A 10.0.11.236
+a-maximum-rrset.example. 5M IN A 10.0.11.237
+a-maximum-rrset.example. 5M IN A 10.0.11.238
+a-maximum-rrset.example. 5M IN A 10.0.11.239
+a-maximum-rrset.example. 5M IN A 10.0.11.240
+a-maximum-rrset.example. 5M IN A 10.0.11.241
+a-maximum-rrset.example. 5M IN A 10.0.11.242
+a-maximum-rrset.example. 5M IN A 10.0.11.243
+a-maximum-rrset.example. 5M IN A 10.0.11.244
+a-maximum-rrset.example. 5M IN A 10.0.11.245
+a-maximum-rrset.example. 5M IN A 10.0.11.246
+a-maximum-rrset.example. 5M IN A 10.0.11.247
+a-maximum-rrset.example. 5M IN A 10.0.11.248
+a-maximum-rrset.example. 5M IN A 10.0.11.249
+a-maximum-rrset.example. 5M IN A 10.0.11.250
+a-maximum-rrset.example. 5M IN A 10.0.11.251
+a-maximum-rrset.example. 5M IN A 10.0.11.252
+a-maximum-rrset.example. 5M IN A 10.0.11.253
+a-maximum-rrset.example. 5M IN A 10.0.11.254
+a-maximum-rrset.example. 5M IN A 10.0.11.255
+a-maximum-rrset.example. 5M IN A 10.0.12.0
+a-maximum-rrset.example. 5M IN A 10.0.12.1
+a-maximum-rrset.example. 5M IN A 10.0.12.2
+a-maximum-rrset.example. 5M IN A 10.0.12.3
+a-maximum-rrset.example. 5M IN A 10.0.12.4
+a-maximum-rrset.example. 5M IN A 10.0.12.5
+a-maximum-rrset.example. 5M IN A 10.0.12.6
+a-maximum-rrset.example. 5M IN A 10.0.12.7
+a-maximum-rrset.example. 5M IN A 10.0.12.8
+a-maximum-rrset.example. 5M IN A 10.0.12.9
+a-maximum-rrset.example. 5M IN A 10.0.12.10
+a-maximum-rrset.example. 5M IN A 10.0.12.11
+a-maximum-rrset.example. 5M IN A 10.0.12.12
+a-maximum-rrset.example. 5M IN A 10.0.12.13
+a-maximum-rrset.example. 5M IN A 10.0.12.14
+a-maximum-rrset.example. 5M IN A 10.0.12.15
+a-maximum-rrset.example. 5M IN A 10.0.12.16
+a-maximum-rrset.example. 5M IN A 10.0.12.17
+a-maximum-rrset.example. 5M IN A 10.0.12.18
+a-maximum-rrset.example. 5M IN A 10.0.12.19
+a-maximum-rrset.example. 5M IN A 10.0.12.20
+a-maximum-rrset.example. 5M IN A 10.0.12.21
+a-maximum-rrset.example. 5M IN A 10.0.12.22
+a-maximum-rrset.example. 5M IN A 10.0.12.23
+a-maximum-rrset.example. 5M IN A 10.0.12.24
+a-maximum-rrset.example. 5M IN A 10.0.12.25
+a-maximum-rrset.example. 5M IN A 10.0.12.26
+a-maximum-rrset.example. 5M IN A 10.0.12.27
+a-maximum-rrset.example. 5M IN A 10.0.12.28
+a-maximum-rrset.example. 5M IN A 10.0.12.29
+a-maximum-rrset.example. 5M IN A 10.0.12.30
+a-maximum-rrset.example. 5M IN A 10.0.12.31
+a-maximum-rrset.example. 5M IN A 10.0.12.32
+a-maximum-rrset.example. 5M IN A 10.0.12.33
+a-maximum-rrset.example. 5M IN A 10.0.12.34
+a-maximum-rrset.example. 5M IN A 10.0.12.35
+a-maximum-rrset.example. 5M IN A 10.0.12.36
+a-maximum-rrset.example. 5M IN A 10.0.12.37
+a-maximum-rrset.example. 5M IN A 10.0.12.38
+a-maximum-rrset.example. 5M IN A 10.0.12.39
+a-maximum-rrset.example. 5M IN A 10.0.12.40
+a-maximum-rrset.example. 5M IN A 10.0.12.41
+a-maximum-rrset.example. 5M IN A 10.0.12.42
+a-maximum-rrset.example. 5M IN A 10.0.12.43
+a-maximum-rrset.example. 5M IN A 10.0.12.44
+a-maximum-rrset.example. 5M IN A 10.0.12.45
+a-maximum-rrset.example. 5M IN A 10.0.12.46
+a-maximum-rrset.example. 5M IN A 10.0.12.47
+a-maximum-rrset.example. 5M IN A 10.0.12.48
+a-maximum-rrset.example. 5M IN A 10.0.12.49
+a-maximum-rrset.example. 5M IN A 10.0.12.50
+a-maximum-rrset.example. 5M IN A 10.0.12.51
+a-maximum-rrset.example. 5M IN A 10.0.12.52
+a-maximum-rrset.example. 5M IN A 10.0.12.53
+a-maximum-rrset.example. 5M IN A 10.0.12.54
+a-maximum-rrset.example. 5M IN A 10.0.12.55
+a-maximum-rrset.example. 5M IN A 10.0.12.56
+a-maximum-rrset.example. 5M IN A 10.0.12.57
+a-maximum-rrset.example. 5M IN A 10.0.12.58
+a-maximum-rrset.example. 5M IN A 10.0.12.59
+a-maximum-rrset.example. 5M IN A 10.0.12.60
+a-maximum-rrset.example. 5M IN A 10.0.12.61
+a-maximum-rrset.example. 5M IN A 10.0.12.62
+a-maximum-rrset.example. 5M IN A 10.0.12.63
+a-maximum-rrset.example. 5M IN A 10.0.12.64
+a-maximum-rrset.example. 5M IN A 10.0.12.65
+a-maximum-rrset.example. 5M IN A 10.0.12.66
+a-maximum-rrset.example. 5M IN A 10.0.12.67
+a-maximum-rrset.example. 5M IN A 10.0.12.68
+a-maximum-rrset.example. 5M IN A 10.0.12.69
+a-maximum-rrset.example. 5M IN A 10.0.12.70
+a-maximum-rrset.example. 5M IN A 10.0.12.71
+a-maximum-rrset.example. 5M IN A 10.0.12.72
+a-maximum-rrset.example. 5M IN A 10.0.12.73
+a-maximum-rrset.example. 5M IN A 10.0.12.74
+a-maximum-rrset.example. 5M IN A 10.0.12.75
+a-maximum-rrset.example. 5M IN A 10.0.12.76
+a-maximum-rrset.example. 5M IN A 10.0.12.77
+a-maximum-rrset.example. 5M IN A 10.0.12.78
+a-maximum-rrset.example. 5M IN A 10.0.12.79
+a-maximum-rrset.example. 5M IN A 10.0.12.80
+a-maximum-rrset.example. 5M IN A 10.0.12.81
+a-maximum-rrset.example. 5M IN A 10.0.12.82
+a-maximum-rrset.example. 5M IN A 10.0.12.83
+a-maximum-rrset.example. 5M IN A 10.0.12.84
+a-maximum-rrset.example. 5M IN A 10.0.12.85
+a-maximum-rrset.example. 5M IN A 10.0.12.86
+a-maximum-rrset.example. 5M IN A 10.0.12.87
+a-maximum-rrset.example. 5M IN A 10.0.12.88
+a-maximum-rrset.example. 5M IN A 10.0.12.89
+a-maximum-rrset.example. 5M IN A 10.0.12.90
+a-maximum-rrset.example. 5M IN A 10.0.12.91
+a-maximum-rrset.example. 5M IN A 10.0.12.92
+a-maximum-rrset.example. 5M IN A 10.0.12.93
+a-maximum-rrset.example. 5M IN A 10.0.12.94
+a-maximum-rrset.example. 5M IN A 10.0.12.95
+a-maximum-rrset.example. 5M IN A 10.0.12.96
+a-maximum-rrset.example. 5M IN A 10.0.12.97
+a-maximum-rrset.example. 5M IN A 10.0.12.98
+a-maximum-rrset.example. 5M IN A 10.0.12.99
+a-maximum-rrset.example. 5M IN A 10.0.12.100
+a-maximum-rrset.example. 5M IN A 10.0.12.101
+a-maximum-rrset.example. 5M IN A 10.0.12.102
+a-maximum-rrset.example. 5M IN A 10.0.12.103
+a-maximum-rrset.example. 5M IN A 10.0.12.104
+a-maximum-rrset.example. 5M IN A 10.0.12.105
+a-maximum-rrset.example. 5M IN A 10.0.12.106
+a-maximum-rrset.example. 5M IN A 10.0.12.107
+a-maximum-rrset.example. 5M IN A 10.0.12.108
+a-maximum-rrset.example. 5M IN A 10.0.12.109
+a-maximum-rrset.example. 5M IN A 10.0.12.110
+a-maximum-rrset.example. 5M IN A 10.0.12.111
+a-maximum-rrset.example. 5M IN A 10.0.12.112
+a-maximum-rrset.example. 5M IN A 10.0.12.113
+a-maximum-rrset.example. 5M IN A 10.0.12.114
+a-maximum-rrset.example. 5M IN A 10.0.12.115
+a-maximum-rrset.example. 5M IN A 10.0.12.116
+a-maximum-rrset.example. 5M IN A 10.0.12.117
+a-maximum-rrset.example. 5M IN A 10.0.12.118
+a-maximum-rrset.example. 5M IN A 10.0.12.119
+a-maximum-rrset.example. 5M IN A 10.0.12.120
+a-maximum-rrset.example. 5M IN A 10.0.12.121
+a-maximum-rrset.example. 5M IN A 10.0.12.122
+a-maximum-rrset.example. 5M IN A 10.0.12.123
+a-maximum-rrset.example. 5M IN A 10.0.12.124
+a-maximum-rrset.example. 5M IN A 10.0.12.125
+a-maximum-rrset.example. 5M IN A 10.0.12.126
+a-maximum-rrset.example. 5M IN A 10.0.12.127
+a-maximum-rrset.example. 5M IN A 10.0.12.128
+a-maximum-rrset.example. 5M IN A 10.0.12.129
+a-maximum-rrset.example. 5M IN A 10.0.12.130
+a-maximum-rrset.example. 5M IN A 10.0.12.131
+a-maximum-rrset.example. 5M IN A 10.0.12.132
+a-maximum-rrset.example. 5M IN A 10.0.12.133
+a-maximum-rrset.example. 5M IN A 10.0.12.134
+a-maximum-rrset.example. 5M IN A 10.0.12.135
+a-maximum-rrset.example. 5M IN A 10.0.12.136
+a-maximum-rrset.example. 5M IN A 10.0.12.137
+a-maximum-rrset.example. 5M IN A 10.0.12.138
+a-maximum-rrset.example. 5M IN A 10.0.12.139
+a-maximum-rrset.example. 5M IN A 10.0.12.140
+a-maximum-rrset.example. 5M IN A 10.0.12.141
+a-maximum-rrset.example. 5M IN A 10.0.12.142
+a-maximum-rrset.example. 5M IN A 10.0.12.143
+a-maximum-rrset.example. 5M IN A 10.0.12.144
+a-maximum-rrset.example. 5M IN A 10.0.12.145
+a-maximum-rrset.example. 5M IN A 10.0.12.146
+a-maximum-rrset.example. 5M IN A 10.0.12.147
+a-maximum-rrset.example. 5M IN A 10.0.12.148
+a-maximum-rrset.example. 5M IN A 10.0.12.149
+a-maximum-rrset.example. 5M IN A 10.0.12.150
+a-maximum-rrset.example. 5M IN A 10.0.12.151
+a-maximum-rrset.example. 5M IN A 10.0.12.152
+a-maximum-rrset.example. 5M IN A 10.0.12.153
+a-maximum-rrset.example. 5M IN A 10.0.12.154
+a-maximum-rrset.example. 5M IN A 10.0.12.155
+a-maximum-rrset.example. 5M IN A 10.0.12.156
+a-maximum-rrset.example. 5M IN A 10.0.12.157
+a-maximum-rrset.example. 5M IN A 10.0.12.158
+a-maximum-rrset.example. 5M IN A 10.0.12.159
+a-maximum-rrset.example. 5M IN A 10.0.12.160
+a-maximum-rrset.example. 5M IN A 10.0.12.161
+a-maximum-rrset.example. 5M IN A 10.0.12.162
+a-maximum-rrset.example. 5M IN A 10.0.12.163
+a-maximum-rrset.example. 5M IN A 10.0.12.164
+a-maximum-rrset.example. 5M IN A 10.0.12.165
+a-maximum-rrset.example. 5M IN A 10.0.12.166
+a-maximum-rrset.example. 5M IN A 10.0.12.167
+a-maximum-rrset.example. 5M IN A 10.0.12.168
+a-maximum-rrset.example. 5M IN A 10.0.12.169
+a-maximum-rrset.example. 5M IN A 10.0.12.170
+a-maximum-rrset.example. 5M IN A 10.0.12.171
+a-maximum-rrset.example. 5M IN A 10.0.12.172
+a-maximum-rrset.example. 5M IN A 10.0.12.173
+a-maximum-rrset.example. 5M IN A 10.0.12.174
+a-maximum-rrset.example. 5M IN A 10.0.12.175
+a-maximum-rrset.example. 5M IN A 10.0.12.176
+a-maximum-rrset.example. 5M IN A 10.0.12.177
+a-maximum-rrset.example. 5M IN A 10.0.12.178
+a-maximum-rrset.example. 5M IN A 10.0.12.179
+a-maximum-rrset.example. 5M IN A 10.0.12.180
+a-maximum-rrset.example. 5M IN A 10.0.12.181
+a-maximum-rrset.example. 5M IN A 10.0.12.182
+a-maximum-rrset.example. 5M IN A 10.0.12.183
+a-maximum-rrset.example. 5M IN A 10.0.12.184
+a-maximum-rrset.example. 5M IN A 10.0.12.185
+a-maximum-rrset.example. 5M IN A 10.0.12.186
+a-maximum-rrset.example. 5M IN A 10.0.12.187
+a-maximum-rrset.example. 5M IN A 10.0.12.188
+a-maximum-rrset.example. 5M IN A 10.0.12.189
+a-maximum-rrset.example. 5M IN A 10.0.12.190
+a-maximum-rrset.example. 5M IN A 10.0.12.191
+a-maximum-rrset.example. 5M IN A 10.0.12.192
+a-maximum-rrset.example. 5M IN A 10.0.12.193
+a-maximum-rrset.example. 5M IN A 10.0.12.194
+a-maximum-rrset.example. 5M IN A 10.0.12.195
+a-maximum-rrset.example. 5M IN A 10.0.12.196
+a-maximum-rrset.example. 5M IN A 10.0.12.197
+a-maximum-rrset.example. 5M IN A 10.0.12.198
+a-maximum-rrset.example. 5M IN A 10.0.12.199
+a-maximum-rrset.example. 5M IN A 10.0.12.200
+a-maximum-rrset.example. 5M IN A 10.0.12.201
+a-maximum-rrset.example. 5M IN A 10.0.12.202
+a-maximum-rrset.example. 5M IN A 10.0.12.203
+a-maximum-rrset.example. 5M IN A 10.0.12.204
+a-maximum-rrset.example. 5M IN A 10.0.12.205
+a-maximum-rrset.example. 5M IN A 10.0.12.206
+a-maximum-rrset.example. 5M IN A 10.0.12.207
+a-maximum-rrset.example. 5M IN A 10.0.12.208
+a-maximum-rrset.example. 5M IN A 10.0.12.209
+a-maximum-rrset.example. 5M IN A 10.0.12.210
+a-maximum-rrset.example. 5M IN A 10.0.12.211
+a-maximum-rrset.example. 5M IN A 10.0.12.212
+a-maximum-rrset.example. 5M IN A 10.0.12.213
+a-maximum-rrset.example. 5M IN A 10.0.12.214
+a-maximum-rrset.example. 5M IN A 10.0.12.215
+a-maximum-rrset.example. 5M IN A 10.0.12.216
+a-maximum-rrset.example. 5M IN A 10.0.12.217
+a-maximum-rrset.example. 5M IN A 10.0.12.218
+a-maximum-rrset.example. 5M IN A 10.0.12.219
+a-maximum-rrset.example. 5M IN A 10.0.12.220
+a-maximum-rrset.example. 5M IN A 10.0.12.221
+a-maximum-rrset.example. 5M IN A 10.0.12.222
+a-maximum-rrset.example. 5M IN A 10.0.12.223
+a-maximum-rrset.example. 5M IN A 10.0.12.224
+a-maximum-rrset.example. 5M IN A 10.0.12.225
+a-maximum-rrset.example. 5M IN A 10.0.12.226
+a-maximum-rrset.example. 5M IN A 10.0.12.227
+a-maximum-rrset.example. 5M IN A 10.0.12.228
+a-maximum-rrset.example. 5M IN A 10.0.12.229
+a-maximum-rrset.example. 5M IN A 10.0.12.230
+a-maximum-rrset.example. 5M IN A 10.0.12.231
+a-maximum-rrset.example. 5M IN A 10.0.12.232
+a-maximum-rrset.example. 5M IN A 10.0.12.233
+a-maximum-rrset.example. 5M IN A 10.0.12.234
+a-maximum-rrset.example. 5M IN A 10.0.12.235
+a-maximum-rrset.example. 5M IN A 10.0.12.236
+a-maximum-rrset.example. 5M IN A 10.0.12.237
+a-maximum-rrset.example. 5M IN A 10.0.12.238
+a-maximum-rrset.example. 5M IN A 10.0.12.239
+a-maximum-rrset.example. 5M IN A 10.0.12.240
+a-maximum-rrset.example. 5M IN A 10.0.12.241
+a-maximum-rrset.example. 5M IN A 10.0.12.242
+a-maximum-rrset.example. 5M IN A 10.0.12.243
+a-maximum-rrset.example. 5M IN A 10.0.12.244
+a-maximum-rrset.example. 5M IN A 10.0.12.245
+a-maximum-rrset.example. 5M IN A 10.0.12.246
+a-maximum-rrset.example. 5M IN A 10.0.12.247
+a-maximum-rrset.example. 5M IN A 10.0.12.248
+a-maximum-rrset.example. 5M IN A 10.0.12.249
+a-maximum-rrset.example. 5M IN A 10.0.12.250
+a-maximum-rrset.example. 5M IN A 10.0.12.251
+a-maximum-rrset.example. 5M IN A 10.0.12.252
+a-maximum-rrset.example. 5M IN A 10.0.12.253
+a-maximum-rrset.example. 5M IN A 10.0.12.254
+a-maximum-rrset.example. 5M IN A 10.0.12.255
+a-maximum-rrset.example. 5M IN A 10.0.13.0
+a-maximum-rrset.example. 5M IN A 10.0.13.1
+a-maximum-rrset.example. 5M IN A 10.0.13.2
+a-maximum-rrset.example. 5M IN A 10.0.13.3
+a-maximum-rrset.example. 5M IN A 10.0.13.4
+a-maximum-rrset.example. 5M IN A 10.0.13.5
+a-maximum-rrset.example. 5M IN A 10.0.13.6
+a-maximum-rrset.example. 5M IN A 10.0.13.7
+a-maximum-rrset.example. 5M IN A 10.0.13.8
+a-maximum-rrset.example. 5M IN A 10.0.13.9
+a-maximum-rrset.example. 5M IN A 10.0.13.10
+a-maximum-rrset.example. 5M IN A 10.0.13.11
+a-maximum-rrset.example. 5M IN A 10.0.13.12
+a-maximum-rrset.example. 5M IN A 10.0.13.13
+a-maximum-rrset.example. 5M IN A 10.0.13.14
+a-maximum-rrset.example. 5M IN A 10.0.13.15
+a-maximum-rrset.example. 5M IN A 10.0.13.16
+a-maximum-rrset.example. 5M IN A 10.0.13.17
+a-maximum-rrset.example. 5M IN A 10.0.13.18
+a-maximum-rrset.example. 5M IN A 10.0.13.19
+a-maximum-rrset.example. 5M IN A 10.0.13.20
+a-maximum-rrset.example. 5M IN A 10.0.13.21
+a-maximum-rrset.example. 5M IN A 10.0.13.22
+a-maximum-rrset.example. 5M IN A 10.0.13.23
+a-maximum-rrset.example. 5M IN A 10.0.13.24
+a-maximum-rrset.example. 5M IN A 10.0.13.25
+a-maximum-rrset.example. 5M IN A 10.0.13.26
+a-maximum-rrset.example. 5M IN A 10.0.13.27
+a-maximum-rrset.example. 5M IN A 10.0.13.28
+a-maximum-rrset.example. 5M IN A 10.0.13.29
+a-maximum-rrset.example. 5M IN A 10.0.13.30
+a-maximum-rrset.example. 5M IN A 10.0.13.31
+a-maximum-rrset.example. 5M IN A 10.0.13.32
+a-maximum-rrset.example. 5M IN A 10.0.13.33
+a-maximum-rrset.example. 5M IN A 10.0.13.34
+a-maximum-rrset.example. 5M IN A 10.0.13.35
+a-maximum-rrset.example. 5M IN A 10.0.13.36
+a-maximum-rrset.example. 5M IN A 10.0.13.37
+a-maximum-rrset.example. 5M IN A 10.0.13.38
+a-maximum-rrset.example. 5M IN A 10.0.13.39
+a-maximum-rrset.example. 5M IN A 10.0.13.40
+a-maximum-rrset.example. 5M IN A 10.0.13.41
+a-maximum-rrset.example. 5M IN A 10.0.13.42
+a-maximum-rrset.example. 5M IN A 10.0.13.43
+a-maximum-rrset.example. 5M IN A 10.0.13.44
+a-maximum-rrset.example. 5M IN A 10.0.13.45
+a-maximum-rrset.example. 5M IN A 10.0.13.46
+a-maximum-rrset.example. 5M IN A 10.0.13.47
+a-maximum-rrset.example. 5M IN A 10.0.13.48
+a-maximum-rrset.example. 5M IN A 10.0.13.49
+a-maximum-rrset.example. 5M IN A 10.0.13.50
+a-maximum-rrset.example. 5M IN A 10.0.13.51
+a-maximum-rrset.example. 5M IN A 10.0.13.52
+a-maximum-rrset.example. 5M IN A 10.0.13.53
+a-maximum-rrset.example. 5M IN A 10.0.13.54
+a-maximum-rrset.example. 5M IN A 10.0.13.55
+a-maximum-rrset.example. 5M IN A 10.0.13.56
+a-maximum-rrset.example. 5M IN A 10.0.13.57
+a-maximum-rrset.example. 5M IN A 10.0.13.58
+a-maximum-rrset.example. 5M IN A 10.0.13.59
+a-maximum-rrset.example. 5M IN A 10.0.13.60
+a-maximum-rrset.example. 5M IN A 10.0.13.61
+a-maximum-rrset.example. 5M IN A 10.0.13.62
+a-maximum-rrset.example. 5M IN A 10.0.13.63
+a-maximum-rrset.example. 5M IN A 10.0.13.64
+a-maximum-rrset.example. 5M IN A 10.0.13.65
+a-maximum-rrset.example. 5M IN A 10.0.13.66
+a-maximum-rrset.example. 5M IN A 10.0.13.67
+a-maximum-rrset.example. 5M IN A 10.0.13.68
+a-maximum-rrset.example. 5M IN A 10.0.13.69
+a-maximum-rrset.example. 5M IN A 10.0.13.70
+a-maximum-rrset.example. 5M IN A 10.0.13.71
+a-maximum-rrset.example. 5M IN A 10.0.13.72
+a-maximum-rrset.example. 5M IN A 10.0.13.73
+a-maximum-rrset.example. 5M IN A 10.0.13.74
+a-maximum-rrset.example. 5M IN A 10.0.13.75
+a-maximum-rrset.example. 5M IN A 10.0.13.76
+a-maximum-rrset.example. 5M IN A 10.0.13.77
+a-maximum-rrset.example. 5M IN A 10.0.13.78
+a-maximum-rrset.example. 5M IN A 10.0.13.79
+a-maximum-rrset.example. 5M IN A 10.0.13.80
+a-maximum-rrset.example. 5M IN A 10.0.13.81
+a-maximum-rrset.example. 5M IN A 10.0.13.82
+a-maximum-rrset.example. 5M IN A 10.0.13.83
+a-maximum-rrset.example. 5M IN A 10.0.13.84
+a-maximum-rrset.example. 5M IN A 10.0.13.85
+a-maximum-rrset.example. 5M IN A 10.0.13.86
+a-maximum-rrset.example. 5M IN A 10.0.13.87
+a-maximum-rrset.example. 5M IN A 10.0.13.88
+a-maximum-rrset.example. 5M IN A 10.0.13.89
+a-maximum-rrset.example. 5M IN A 10.0.13.90
+a-maximum-rrset.example. 5M IN A 10.0.13.91
+a-maximum-rrset.example. 5M IN A 10.0.13.92
+a-maximum-rrset.example. 5M IN A 10.0.13.93
+a-maximum-rrset.example. 5M IN A 10.0.13.94
+a-maximum-rrset.example. 5M IN A 10.0.13.95
+a-maximum-rrset.example. 5M IN A 10.0.13.96
+a-maximum-rrset.example. 5M IN A 10.0.13.97
+a-maximum-rrset.example. 5M IN A 10.0.13.98
+a-maximum-rrset.example. 5M IN A 10.0.13.99
+a-maximum-rrset.example. 5M IN A 10.0.13.100
+a-maximum-rrset.example. 5M IN A 10.0.13.101
+a-maximum-rrset.example. 5M IN A 10.0.13.102
+a-maximum-rrset.example. 5M IN A 10.0.13.103
+a-maximum-rrset.example. 5M IN A 10.0.13.104
+a-maximum-rrset.example. 5M IN A 10.0.13.105
+a-maximum-rrset.example. 5M IN A 10.0.13.106
+a-maximum-rrset.example. 5M IN A 10.0.13.107
+a-maximum-rrset.example. 5M IN A 10.0.13.108
+a-maximum-rrset.example. 5M IN A 10.0.13.109
+a-maximum-rrset.example. 5M IN A 10.0.13.110
+a-maximum-rrset.example. 5M IN A 10.0.13.111
+a-maximum-rrset.example. 5M IN A 10.0.13.112
+a-maximum-rrset.example. 5M IN A 10.0.13.113
+a-maximum-rrset.example. 5M IN A 10.0.13.114
+a-maximum-rrset.example. 5M IN A 10.0.13.115
+a-maximum-rrset.example. 5M IN A 10.0.13.116
+a-maximum-rrset.example. 5M IN A 10.0.13.117
+a-maximum-rrset.example. 5M IN A 10.0.13.118
+a-maximum-rrset.example. 5M IN A 10.0.13.119
+a-maximum-rrset.example. 5M IN A 10.0.13.120
+a-maximum-rrset.example. 5M IN A 10.0.13.121
+a-maximum-rrset.example. 5M IN A 10.0.13.122
+a-maximum-rrset.example. 5M IN A 10.0.13.123
+a-maximum-rrset.example. 5M IN A 10.0.13.124
+a-maximum-rrset.example. 5M IN A 10.0.13.125
+a-maximum-rrset.example. 5M IN A 10.0.13.126
+a-maximum-rrset.example. 5M IN A 10.0.13.127
+a-maximum-rrset.example. 5M IN A 10.0.13.128
+a-maximum-rrset.example. 5M IN A 10.0.13.129
+a-maximum-rrset.example. 5M IN A 10.0.13.130
+a-maximum-rrset.example. 5M IN A 10.0.13.131
+a-maximum-rrset.example. 5M IN A 10.0.13.132
+a-maximum-rrset.example. 5M IN A 10.0.13.133
+a-maximum-rrset.example. 5M IN A 10.0.13.134
+a-maximum-rrset.example. 5M IN A 10.0.13.135
+a-maximum-rrset.example. 5M IN A 10.0.13.136
+a-maximum-rrset.example. 5M IN A 10.0.13.137
+a-maximum-rrset.example. 5M IN A 10.0.13.138
+a-maximum-rrset.example. 5M IN A 10.0.13.139
+a-maximum-rrset.example. 5M IN A 10.0.13.140
+a-maximum-rrset.example. 5M IN A 10.0.13.141
+a-maximum-rrset.example. 5M IN A 10.0.13.142
+a-maximum-rrset.example. 5M IN A 10.0.13.143
+a-maximum-rrset.example. 5M IN A 10.0.13.144
+a-maximum-rrset.example. 5M IN A 10.0.13.145
+a-maximum-rrset.example. 5M IN A 10.0.13.146
+a-maximum-rrset.example. 5M IN A 10.0.13.147
+a-maximum-rrset.example. 5M IN A 10.0.13.148
+a-maximum-rrset.example. 5M IN A 10.0.13.149
+a-maximum-rrset.example. 5M IN A 10.0.13.150
+a-maximum-rrset.example. 5M IN A 10.0.13.151
+a-maximum-rrset.example. 5M IN A 10.0.13.152
+a-maximum-rrset.example. 5M IN A 10.0.13.153
+a-maximum-rrset.example. 5M IN A 10.0.13.154
+a-maximum-rrset.example. 5M IN A 10.0.13.155
+a-maximum-rrset.example. 5M IN A 10.0.13.156
+a-maximum-rrset.example. 5M IN A 10.0.13.157
+a-maximum-rrset.example. 5M IN A 10.0.13.158
+a-maximum-rrset.example. 5M IN A 10.0.13.159
+a-maximum-rrset.example. 5M IN A 10.0.13.160
+a-maximum-rrset.example. 5M IN A 10.0.13.161
+a-maximum-rrset.example. 5M IN A 10.0.13.162
+a-maximum-rrset.example. 5M IN A 10.0.13.163
+a-maximum-rrset.example. 5M IN A 10.0.13.164
+a-maximum-rrset.example. 5M IN A 10.0.13.165
+a-maximum-rrset.example. 5M IN A 10.0.13.166
+a-maximum-rrset.example. 5M IN A 10.0.13.167
+a-maximum-rrset.example. 5M IN A 10.0.13.168
+a-maximum-rrset.example. 5M IN A 10.0.13.169
+a-maximum-rrset.example. 5M IN A 10.0.13.170
+a-maximum-rrset.example. 5M IN A 10.0.13.171
+a-maximum-rrset.example. 5M IN A 10.0.13.172
+a-maximum-rrset.example. 5M IN A 10.0.13.173
+a-maximum-rrset.example. 5M IN A 10.0.13.174
+a-maximum-rrset.example. 5M IN A 10.0.13.175
+a-maximum-rrset.example. 5M IN A 10.0.13.176
+a-maximum-rrset.example. 5M IN A 10.0.13.177
+a-maximum-rrset.example. 5M IN A 10.0.13.178
+a-maximum-rrset.example. 5M IN A 10.0.13.179
+a-maximum-rrset.example. 5M IN A 10.0.13.180
+a-maximum-rrset.example. 5M IN A 10.0.13.181
+a-maximum-rrset.example. 5M IN A 10.0.13.182
+a-maximum-rrset.example. 5M IN A 10.0.13.183
+a-maximum-rrset.example. 5M IN A 10.0.13.184
+a-maximum-rrset.example. 5M IN A 10.0.13.185
+a-maximum-rrset.example. 5M IN A 10.0.13.186
+a-maximum-rrset.example. 5M IN A 10.0.13.187
+a-maximum-rrset.example. 5M IN A 10.0.13.188
+a-maximum-rrset.example. 5M IN A 10.0.13.189
+a-maximum-rrset.example. 5M IN A 10.0.13.190
+a-maximum-rrset.example. 5M IN A 10.0.13.191
+a-maximum-rrset.example. 5M IN A 10.0.13.192
+a-maximum-rrset.example. 5M IN A 10.0.13.193
+a-maximum-rrset.example. 5M IN A 10.0.13.194
+a-maximum-rrset.example. 5M IN A 10.0.13.195
+a-maximum-rrset.example. 5M IN A 10.0.13.196
+a-maximum-rrset.example. 5M IN A 10.0.13.197
+a-maximum-rrset.example. 5M IN A 10.0.13.198
+a-maximum-rrset.example. 5M IN A 10.0.13.199
+a-maximum-rrset.example. 5M IN A 10.0.13.200
+a-maximum-rrset.example. 5M IN A 10.0.13.201
+a-maximum-rrset.example. 5M IN A 10.0.13.202
+a-maximum-rrset.example. 5M IN A 10.0.13.203
+a-maximum-rrset.example. 5M IN A 10.0.13.204
+a-maximum-rrset.example. 5M IN A 10.0.13.205
+a-maximum-rrset.example. 5M IN A 10.0.13.206
+a-maximum-rrset.example. 5M IN A 10.0.13.207
+a-maximum-rrset.example. 5M IN A 10.0.13.208
+a-maximum-rrset.example. 5M IN A 10.0.13.209
+a-maximum-rrset.example. 5M IN A 10.0.13.210
+a-maximum-rrset.example. 5M IN A 10.0.13.211
+a-maximum-rrset.example. 5M IN A 10.0.13.212
+a-maximum-rrset.example. 5M IN A 10.0.13.213
+a-maximum-rrset.example. 5M IN A 10.0.13.214
+a-maximum-rrset.example. 5M IN A 10.0.13.215
+a-maximum-rrset.example. 5M IN A 10.0.13.216
+a-maximum-rrset.example. 5M IN A 10.0.13.217
+a-maximum-rrset.example. 5M IN A 10.0.13.218
+a-maximum-rrset.example. 5M IN A 10.0.13.219
+a-maximum-rrset.example. 5M IN A 10.0.13.220
+a-maximum-rrset.example. 5M IN A 10.0.13.221
+a-maximum-rrset.example. 5M IN A 10.0.13.222
+a-maximum-rrset.example. 5M IN A 10.0.13.223
+a-maximum-rrset.example. 5M IN A 10.0.13.224
+a-maximum-rrset.example. 5M IN A 10.0.13.225
+a-maximum-rrset.example. 5M IN A 10.0.13.226
+a-maximum-rrset.example. 5M IN A 10.0.13.227
+a-maximum-rrset.example. 5M IN A 10.0.13.228
+a-maximum-rrset.example. 5M IN A 10.0.13.229
+a-maximum-rrset.example. 5M IN A 10.0.13.230
+a-maximum-rrset.example. 5M IN A 10.0.13.231
+a-maximum-rrset.example. 5M IN A 10.0.13.232
+a-maximum-rrset.example. 5M IN A 10.0.13.233
+a-maximum-rrset.example. 5M IN A 10.0.13.234
+a-maximum-rrset.example. 5M IN A 10.0.13.235
+a-maximum-rrset.example. 5M IN A 10.0.13.236
+a-maximum-rrset.example. 5M IN A 10.0.13.237
+a-maximum-rrset.example. 5M IN A 10.0.13.238
+a-maximum-rrset.example. 5M IN A 10.0.13.239
+a-maximum-rrset.example. 5M IN A 10.0.13.240
+a-maximum-rrset.example. 5M IN A 10.0.13.241
+a-maximum-rrset.example. 5M IN A 10.0.13.242
+a-maximum-rrset.example. 5M IN A 10.0.13.243
+a-maximum-rrset.example. 5M IN A 10.0.13.244
+a-maximum-rrset.example. 5M IN A 10.0.13.245
+a-maximum-rrset.example. 5M IN A 10.0.13.246
+a-maximum-rrset.example. 5M IN A 10.0.13.247
+a-maximum-rrset.example. 5M IN A 10.0.13.248
+a-maximum-rrset.example. 5M IN A 10.0.13.249
+a-maximum-rrset.example. 5M IN A 10.0.13.250
+a-maximum-rrset.example. 5M IN A 10.0.13.251
+a-maximum-rrset.example. 5M IN A 10.0.13.252
+a-maximum-rrset.example. 5M IN A 10.0.13.253
+a-maximum-rrset.example. 5M IN A 10.0.13.254
+a-maximum-rrset.example. 5M IN A 10.0.13.255
+a-maximum-rrset.example. 5M IN A 10.0.14.0
+a-maximum-rrset.example. 5M IN A 10.0.14.1
+a-maximum-rrset.example. 5M IN A 10.0.14.2
+a-maximum-rrset.example. 5M IN A 10.0.14.3
+a-maximum-rrset.example. 5M IN A 10.0.14.4
+a-maximum-rrset.example. 5M IN A 10.0.14.5
+a-maximum-rrset.example. 5M IN A 10.0.14.6
+a-maximum-rrset.example. 5M IN A 10.0.14.7
+a-maximum-rrset.example. 5M IN A 10.0.14.8
+a-maximum-rrset.example. 5M IN A 10.0.14.9
+a-maximum-rrset.example. 5M IN A 10.0.14.10
+a-maximum-rrset.example. 5M IN A 10.0.14.11
+a-maximum-rrset.example. 5M IN A 10.0.14.12
+a-maximum-rrset.example. 5M IN A 10.0.14.13
+a-maximum-rrset.example. 5M IN A 10.0.14.14
+a-maximum-rrset.example. 5M IN A 10.0.14.15
+a-maximum-rrset.example. 5M IN A 10.0.14.16
+a-maximum-rrset.example. 5M IN A 10.0.14.17
+a-maximum-rrset.example. 5M IN A 10.0.14.18
+a-maximum-rrset.example. 5M IN A 10.0.14.19
+a-maximum-rrset.example. 5M IN A 10.0.14.20
+a-maximum-rrset.example. 5M IN A 10.0.14.21
+a-maximum-rrset.example. 5M IN A 10.0.14.22
+a-maximum-rrset.example. 5M IN A 10.0.14.23
+a-maximum-rrset.example. 5M IN A 10.0.14.24
+a-maximum-rrset.example. 5M IN A 10.0.14.25
+a-maximum-rrset.example. 5M IN A 10.0.14.26
+a-maximum-rrset.example. 5M IN A 10.0.14.27
+a-maximum-rrset.example. 5M IN A 10.0.14.28
+a-maximum-rrset.example. 5M IN A 10.0.14.29
+a-maximum-rrset.example. 5M IN A 10.0.14.30
+a-maximum-rrset.example. 5M IN A 10.0.14.31
+a-maximum-rrset.example. 5M IN A 10.0.14.32
+a-maximum-rrset.example. 5M IN A 10.0.14.33
+a-maximum-rrset.example. 5M IN A 10.0.14.34
+a-maximum-rrset.example. 5M IN A 10.0.14.35
+a-maximum-rrset.example. 5M IN A 10.0.14.36
+a-maximum-rrset.example. 5M IN A 10.0.14.37
+a-maximum-rrset.example. 5M IN A 10.0.14.38
+a-maximum-rrset.example. 5M IN A 10.0.14.39
+a-maximum-rrset.example. 5M IN A 10.0.14.40
+a-maximum-rrset.example. 5M IN A 10.0.14.41
+a-maximum-rrset.example. 5M IN A 10.0.14.42
+a-maximum-rrset.example. 5M IN A 10.0.14.43
+a-maximum-rrset.example. 5M IN A 10.0.14.44
+a-maximum-rrset.example. 5M IN A 10.0.14.45
+a-maximum-rrset.example. 5M IN A 10.0.14.46
+a-maximum-rrset.example. 5M IN A 10.0.14.47
+a-maximum-rrset.example. 5M IN A 10.0.14.48
+a-maximum-rrset.example. 5M IN A 10.0.14.49
+a-maximum-rrset.example. 5M IN A 10.0.14.50
+a-maximum-rrset.example. 5M IN A 10.0.14.51
+a-maximum-rrset.example. 5M IN A 10.0.14.52
+a-maximum-rrset.example. 5M IN A 10.0.14.53
+a-maximum-rrset.example. 5M IN A 10.0.14.54
+a-maximum-rrset.example. 5M IN A 10.0.14.55
+a-maximum-rrset.example. 5M IN A 10.0.14.56
+a-maximum-rrset.example. 5M IN A 10.0.14.57
+a-maximum-rrset.example. 5M IN A 10.0.14.58
+a-maximum-rrset.example. 5M IN A 10.0.14.59
+a-maximum-rrset.example. 5M IN A 10.0.14.60
+a-maximum-rrset.example. 5M IN A 10.0.14.61
+a-maximum-rrset.example. 5M IN A 10.0.14.62
+a-maximum-rrset.example. 5M IN A 10.0.14.63
+a-maximum-rrset.example. 5M IN A 10.0.14.64
+a-maximum-rrset.example. 5M IN A 10.0.14.65
+a-maximum-rrset.example. 5M IN A 10.0.14.66
+a-maximum-rrset.example. 5M IN A 10.0.14.67
+a-maximum-rrset.example. 5M IN A 10.0.14.68
+a-maximum-rrset.example. 5M IN A 10.0.14.69
+a-maximum-rrset.example. 5M IN A 10.0.14.70
+a-maximum-rrset.example. 5M IN A 10.0.14.71
+a-maximum-rrset.example. 5M IN A 10.0.14.72
+a-maximum-rrset.example. 5M IN A 10.0.14.73
+a-maximum-rrset.example. 5M IN A 10.0.14.74
+a-maximum-rrset.example. 5M IN A 10.0.14.75
+a-maximum-rrset.example. 5M IN A 10.0.14.76
+a-maximum-rrset.example. 5M IN A 10.0.14.77
+a-maximum-rrset.example. 5M IN A 10.0.14.78
+a-maximum-rrset.example. 5M IN A 10.0.14.79
+a-maximum-rrset.example. 5M IN A 10.0.14.80
+a-maximum-rrset.example. 5M IN A 10.0.14.81
+a-maximum-rrset.example. 5M IN A 10.0.14.82
+a-maximum-rrset.example. 5M IN A 10.0.14.83
+a-maximum-rrset.example. 5M IN A 10.0.14.84
+a-maximum-rrset.example. 5M IN A 10.0.14.85
+a-maximum-rrset.example. 5M IN A 10.0.14.86
+a-maximum-rrset.example. 5M IN A 10.0.14.87
+a-maximum-rrset.example. 5M IN A 10.0.14.88
+a-maximum-rrset.example. 5M IN A 10.0.14.89
+a-maximum-rrset.example. 5M IN A 10.0.14.90
+a-maximum-rrset.example. 5M IN A 10.0.14.91
+a-maximum-rrset.example. 5M IN A 10.0.14.92
+a-maximum-rrset.example. 5M IN A 10.0.14.93
+a-maximum-rrset.example. 5M IN A 10.0.14.94
+a-maximum-rrset.example. 5M IN A 10.0.14.95
+a-maximum-rrset.example. 5M IN A 10.0.14.96
+a-maximum-rrset.example. 5M IN A 10.0.14.97
+a-maximum-rrset.example. 5M IN A 10.0.14.98
+a-maximum-rrset.example. 5M IN A 10.0.14.99
+a-maximum-rrset.example. 5M IN A 10.0.14.100
+a-maximum-rrset.example. 5M IN A 10.0.14.101
+a-maximum-rrset.example. 5M IN A 10.0.14.102
+a-maximum-rrset.example. 5M IN A 10.0.14.103
+a-maximum-rrset.example. 5M IN A 10.0.14.104
+a-maximum-rrset.example. 5M IN A 10.0.14.105
+a-maximum-rrset.example. 5M IN A 10.0.14.106
+a-maximum-rrset.example. 5M IN A 10.0.14.107
+a-maximum-rrset.example. 5M IN A 10.0.14.108
+a-maximum-rrset.example. 5M IN A 10.0.14.109
+a-maximum-rrset.example. 5M IN A 10.0.14.110
+a-maximum-rrset.example. 5M IN A 10.0.14.111
+a-maximum-rrset.example. 5M IN A 10.0.14.112
+a-maximum-rrset.example. 5M IN A 10.0.14.113
+a-maximum-rrset.example. 5M IN A 10.0.14.114
+a-maximum-rrset.example. 5M IN A 10.0.14.115
+a-maximum-rrset.example. 5M IN A 10.0.14.116
+a-maximum-rrset.example. 5M IN A 10.0.14.117
+a-maximum-rrset.example. 5M IN A 10.0.14.118
+a-maximum-rrset.example. 5M IN A 10.0.14.119
+a-maximum-rrset.example. 5M IN A 10.0.14.120
+a-maximum-rrset.example. 5M IN A 10.0.14.121
+a-maximum-rrset.example. 5M IN A 10.0.14.122
+a-maximum-rrset.example. 5M IN A 10.0.14.123
+a-maximum-rrset.example. 5M IN A 10.0.14.124
+a-maximum-rrset.example. 5M IN A 10.0.14.125
+a-maximum-rrset.example. 5M IN A 10.0.14.126
+a-maximum-rrset.example. 5M IN A 10.0.14.127
+a-maximum-rrset.example. 5M IN A 10.0.14.128
+a-maximum-rrset.example. 5M IN A 10.0.14.129
+a-maximum-rrset.example. 5M IN A 10.0.14.130
+a-maximum-rrset.example. 5M IN A 10.0.14.131
+a-maximum-rrset.example. 5M IN A 10.0.14.132
+a-maximum-rrset.example. 5M IN A 10.0.14.133
+a-maximum-rrset.example. 5M IN A 10.0.14.134
+a-maximum-rrset.example. 5M IN A 10.0.14.135
+a-maximum-rrset.example. 5M IN A 10.0.14.136
+a-maximum-rrset.example. 5M IN A 10.0.14.137
+a-maximum-rrset.example. 5M IN A 10.0.14.138
+a-maximum-rrset.example. 5M IN A 10.0.14.139
+a-maximum-rrset.example. 5M IN A 10.0.14.140
+a-maximum-rrset.example. 5M IN A 10.0.14.141
+a-maximum-rrset.example. 5M IN A 10.0.14.142
+a-maximum-rrset.example. 5M IN A 10.0.14.143
+a-maximum-rrset.example. 5M IN A 10.0.14.144
+a-maximum-rrset.example. 5M IN A 10.0.14.145
+a-maximum-rrset.example. 5M IN A 10.0.14.146
+a-maximum-rrset.example. 5M IN A 10.0.14.147
+a-maximum-rrset.example. 5M IN A 10.0.14.148
+a-maximum-rrset.example. 5M IN A 10.0.14.149
+a-maximum-rrset.example. 5M IN A 10.0.14.150
+a-maximum-rrset.example. 5M IN A 10.0.14.151
+a-maximum-rrset.example. 5M IN A 10.0.14.152
+a-maximum-rrset.example. 5M IN A 10.0.14.153
+a-maximum-rrset.example. 5M IN A 10.0.14.154
+a-maximum-rrset.example. 5M IN A 10.0.14.155
+a-maximum-rrset.example. 5M IN A 10.0.14.156
+a-maximum-rrset.example. 5M IN A 10.0.14.157
+a-maximum-rrset.example. 5M IN A 10.0.14.158
+a-maximum-rrset.example. 5M IN A 10.0.14.159
+a-maximum-rrset.example. 5M IN A 10.0.14.160
+a-maximum-rrset.example. 5M IN A 10.0.14.161
+a-maximum-rrset.example. 5M IN A 10.0.14.162
+a-maximum-rrset.example. 5M IN A 10.0.14.163
+a-maximum-rrset.example. 5M IN A 10.0.14.164
+a-maximum-rrset.example. 5M IN A 10.0.14.165
+a-maximum-rrset.example. 5M IN A 10.0.14.166
+a-maximum-rrset.example. 5M IN A 10.0.14.167
+a-maximum-rrset.example. 5M IN A 10.0.14.168
+a-maximum-rrset.example. 5M IN A 10.0.14.169
+a-maximum-rrset.example. 5M IN A 10.0.14.170
+a-maximum-rrset.example. 5M IN A 10.0.14.171
+a-maximum-rrset.example. 5M IN A 10.0.14.172
+a-maximum-rrset.example. 5M IN A 10.0.14.173
+a-maximum-rrset.example. 5M IN A 10.0.14.174
+a-maximum-rrset.example. 5M IN A 10.0.14.175
+a-maximum-rrset.example. 5M IN A 10.0.14.176
+a-maximum-rrset.example. 5M IN A 10.0.14.177
+a-maximum-rrset.example. 5M IN A 10.0.14.178
+a-maximum-rrset.example. 5M IN A 10.0.14.179
+a-maximum-rrset.example. 5M IN A 10.0.14.180
+a-maximum-rrset.example. 5M IN A 10.0.14.181
+a-maximum-rrset.example. 5M IN A 10.0.14.182
+a-maximum-rrset.example. 5M IN A 10.0.14.183
+a-maximum-rrset.example. 5M IN A 10.0.14.184
+a-maximum-rrset.example. 5M IN A 10.0.14.185
+a-maximum-rrset.example. 5M IN A 10.0.14.186
+a-maximum-rrset.example. 5M IN A 10.0.14.187
+a-maximum-rrset.example. 5M IN A 10.0.14.188
+a-maximum-rrset.example. 5M IN A 10.0.14.189
+a-maximum-rrset.example. 5M IN A 10.0.14.190
+a-maximum-rrset.example. 5M IN A 10.0.14.191
+a-maximum-rrset.example. 5M IN A 10.0.14.192
+a-maximum-rrset.example. 5M IN A 10.0.14.193
+a-maximum-rrset.example. 5M IN A 10.0.14.194
+a-maximum-rrset.example. 5M IN A 10.0.14.195
+a-maximum-rrset.example. 5M IN A 10.0.14.196
+a-maximum-rrset.example. 5M IN A 10.0.14.197
+a-maximum-rrset.example. 5M IN A 10.0.14.198
+a-maximum-rrset.example. 5M IN A 10.0.14.199
+a-maximum-rrset.example. 5M IN A 10.0.14.200
+a-maximum-rrset.example. 5M IN A 10.0.14.201
+a-maximum-rrset.example. 5M IN A 10.0.14.202
+a-maximum-rrset.example. 5M IN A 10.0.14.203
+a-maximum-rrset.example. 5M IN A 10.0.14.204
+a-maximum-rrset.example. 5M IN A 10.0.14.205
+a-maximum-rrset.example. 5M IN A 10.0.14.206
+a-maximum-rrset.example. 5M IN A 10.0.14.207
+a-maximum-rrset.example. 5M IN A 10.0.14.208
+a-maximum-rrset.example. 5M IN A 10.0.14.209
+a-maximum-rrset.example. 5M IN A 10.0.14.210
+a-maximum-rrset.example. 5M IN A 10.0.14.211
+a-maximum-rrset.example. 5M IN A 10.0.14.212
+a-maximum-rrset.example. 5M IN A 10.0.14.213
+a-maximum-rrset.example. 5M IN A 10.0.14.214
+a-maximum-rrset.example. 5M IN A 10.0.14.215
+a-maximum-rrset.example. 5M IN A 10.0.14.216
+a-maximum-rrset.example. 5M IN A 10.0.14.217
+a-maximum-rrset.example. 5M IN A 10.0.14.218
+a-maximum-rrset.example. 5M IN A 10.0.14.219
+a-maximum-rrset.example. 5M IN A 10.0.14.220
+a-maximum-rrset.example. 5M IN A 10.0.14.221
+a-maximum-rrset.example. 5M IN A 10.0.14.222
+a-maximum-rrset.example. 5M IN A 10.0.14.223
+a-maximum-rrset.example. 5M IN A 10.0.14.224
+a-maximum-rrset.example. 5M IN A 10.0.14.225
+a-maximum-rrset.example. 5M IN A 10.0.14.226
+a-maximum-rrset.example. 5M IN A 10.0.14.227
+a-maximum-rrset.example. 5M IN A 10.0.14.228
+a-maximum-rrset.example. 5M IN A 10.0.14.229
+a-maximum-rrset.example. 5M IN A 10.0.14.230
+a-maximum-rrset.example. 5M IN A 10.0.14.231
+a-maximum-rrset.example. 5M IN A 10.0.14.232
+a-maximum-rrset.example. 5M IN A 10.0.14.233
+a-maximum-rrset.example. 5M IN A 10.0.14.234
+a-maximum-rrset.example. 5M IN A 10.0.14.235
+a-maximum-rrset.example. 5M IN A 10.0.14.236
+a-maximum-rrset.example. 5M IN A 10.0.14.237
+a-maximum-rrset.example. 5M IN A 10.0.14.238
+a-maximum-rrset.example. 5M IN A 10.0.14.239
+a-maximum-rrset.example. 5M IN A 10.0.14.240
+a-maximum-rrset.example. 5M IN A 10.0.14.241
+a-maximum-rrset.example. 5M IN A 10.0.14.242
+a-maximum-rrset.example. 5M IN A 10.0.14.243
+a-maximum-rrset.example. 5M IN A 10.0.14.244
+a-maximum-rrset.example. 5M IN A 10.0.14.245
+a-maximum-rrset.example. 5M IN A 10.0.14.246
+a-maximum-rrset.example. 5M IN A 10.0.14.247
+a-maximum-rrset.example. 5M IN A 10.0.14.248
+a-maximum-rrset.example. 5M IN A 10.0.14.249
+a-maximum-rrset.example. 5M IN A 10.0.14.250
+a-maximum-rrset.example. 5M IN A 10.0.14.251
+a-maximum-rrset.example. 5M IN A 10.0.14.252
+a-maximum-rrset.example. 5M IN A 10.0.14.253
+a-maximum-rrset.example. 5M IN A 10.0.14.254
+a-maximum-rrset.example. 5M IN A 10.0.14.255
+a-maximum-rrset.example. 5M IN A 10.0.15.0
+a-maximum-rrset.example. 5M IN A 10.0.15.1
+a-maximum-rrset.example. 5M IN A 10.0.15.2
+a-maximum-rrset.example. 5M IN A 10.0.15.3
+a-maximum-rrset.example. 5M IN A 10.0.15.4
+a-maximum-rrset.example. 5M IN A 10.0.15.5
+a-maximum-rrset.example. 5M IN A 10.0.15.6
+a-maximum-rrset.example. 5M IN A 10.0.15.7
+a-maximum-rrset.example. 5M IN A 10.0.15.8
+a-maximum-rrset.example. 5M IN A 10.0.15.9
+a-maximum-rrset.example. 5M IN A 10.0.15.10
+a-maximum-rrset.example. 5M IN A 10.0.15.11
+a-maximum-rrset.example. 5M IN A 10.0.15.12
+a-maximum-rrset.example. 5M IN A 10.0.15.13
+a-maximum-rrset.example. 5M IN A 10.0.15.14
+a-maximum-rrset.example. 5M IN A 10.0.15.15
+a-maximum-rrset.example. 5M IN A 10.0.15.16
+a-maximum-rrset.example. 5M IN A 10.0.15.17
+a-maximum-rrset.example. 5M IN A 10.0.15.18
+a-maximum-rrset.example. 5M IN A 10.0.15.19
+a-maximum-rrset.example. 5M IN A 10.0.15.20
+a-maximum-rrset.example. 5M IN A 10.0.15.21
+a-maximum-rrset.example. 5M IN A 10.0.15.22
+a-maximum-rrset.example. 5M IN A 10.0.15.23
+a-maximum-rrset.example. 5M IN A 10.0.15.24
+a-maximum-rrset.example. 5M IN A 10.0.15.25
+a-maximum-rrset.example. 5M IN A 10.0.15.26
+a-maximum-rrset.example. 5M IN A 10.0.15.27
+a-maximum-rrset.example. 5M IN A 10.0.15.28
+a-maximum-rrset.example. 5M IN A 10.0.15.29
+a-maximum-rrset.example. 5M IN A 10.0.15.30
+a-maximum-rrset.example. 5M IN A 10.0.15.31
+a-maximum-rrset.example. 5M IN A 10.0.15.32
+a-maximum-rrset.example. 5M IN A 10.0.15.33
+a-maximum-rrset.example. 5M IN A 10.0.15.34
+a-maximum-rrset.example. 5M IN A 10.0.15.35
+a-maximum-rrset.example. 5M IN A 10.0.15.36
+a-maximum-rrset.example. 5M IN A 10.0.15.37
+a-maximum-rrset.example. 5M IN A 10.0.15.38
+a-maximum-rrset.example. 5M IN A 10.0.15.39
+a-maximum-rrset.example. 5M IN A 10.0.15.40
+a-maximum-rrset.example. 5M IN A 10.0.15.41
+a-maximum-rrset.example. 5M IN A 10.0.15.42
+a-maximum-rrset.example. 5M IN A 10.0.15.43
+a-maximum-rrset.example. 5M IN A 10.0.15.44
+a-maximum-rrset.example. 5M IN A 10.0.15.45
+a-maximum-rrset.example. 5M IN A 10.0.15.46
+a-maximum-rrset.example. 5M IN A 10.0.15.47
+a-maximum-rrset.example. 5M IN A 10.0.15.48
+a-maximum-rrset.example. 5M IN A 10.0.15.49
+a-maximum-rrset.example. 5M IN A 10.0.15.50
+a-maximum-rrset.example. 5M IN A 10.0.15.51
+a-maximum-rrset.example. 5M IN A 10.0.15.52
+a-maximum-rrset.example. 5M IN A 10.0.15.53
+a-maximum-rrset.example. 5M IN A 10.0.15.54
+a-maximum-rrset.example. 5M IN A 10.0.15.55
+a-maximum-rrset.example. 5M IN A 10.0.15.56
+a-maximum-rrset.example. 5M IN A 10.0.15.57
+a-maximum-rrset.example. 5M IN A 10.0.15.58
+a-maximum-rrset.example. 5M IN A 10.0.15.59
+a-maximum-rrset.example. 5M IN A 10.0.15.60
+a-maximum-rrset.example. 5M IN A 10.0.15.61
+a-maximum-rrset.example. 5M IN A 10.0.15.62
+a-maximum-rrset.example. 5M IN A 10.0.15.63
+a-maximum-rrset.example. 5M IN A 10.0.15.64
+a-maximum-rrset.example. 5M IN A 10.0.15.65
+a-maximum-rrset.example. 5M IN A 10.0.15.66
+a-maximum-rrset.example. 5M IN A 10.0.15.67
+a-maximum-rrset.example. 5M IN A 10.0.15.68
+a-maximum-rrset.example. 5M IN A 10.0.15.69
+a-maximum-rrset.example. 5M IN A 10.0.15.70
+a-maximum-rrset.example. 5M IN A 10.0.15.71
+a-maximum-rrset.example. 5M IN A 10.0.15.72
+a-maximum-rrset.example. 5M IN A 10.0.15.73
+a-maximum-rrset.example. 5M IN A 10.0.15.74
+a-maximum-rrset.example. 5M IN A 10.0.15.75
+a-maximum-rrset.example. 5M IN A 10.0.15.76
+a-maximum-rrset.example. 5M IN A 10.0.15.77
+a-maximum-rrset.example. 5M IN A 10.0.15.78
+a-maximum-rrset.example. 5M IN A 10.0.15.79
+a-maximum-rrset.example. 5M IN A 10.0.15.80
+a-maximum-rrset.example. 5M IN A 10.0.15.81
+a-maximum-rrset.example. 5M IN A 10.0.15.82
+a-maximum-rrset.example. 5M IN A 10.0.15.83
+a-maximum-rrset.example. 5M IN A 10.0.15.84
+a-maximum-rrset.example. 5M IN A 10.0.15.85
+a-maximum-rrset.example. 5M IN A 10.0.15.86
+a-maximum-rrset.example. 5M IN A 10.0.15.87
+a-maximum-rrset.example. 5M IN A 10.0.15.88
+a-maximum-rrset.example. 5M IN A 10.0.15.89
+a-maximum-rrset.example. 5M IN A 10.0.15.90
+a-maximum-rrset.example. 5M IN A 10.0.15.91
+a-maximum-rrset.example. 5M IN A 10.0.15.92
+a-maximum-rrset.example. 5M IN A 10.0.15.93
+a-maximum-rrset.example. 5M IN A 10.0.15.94
+a-maximum-rrset.example. 5M IN A 10.0.15.95
+a-maximum-rrset.example. 5M IN A 10.0.15.96
+a-maximum-rrset.example. 5M IN A 10.0.15.97
+a-maximum-rrset.example. 5M IN A 10.0.15.98
+a-maximum-rrset.example. 5M IN A 10.0.15.99
+a-maximum-rrset.example. 5M IN A 10.0.15.100
+a-maximum-rrset.example. 5M IN A 10.0.15.101
+a-maximum-rrset.example. 5M IN A 10.0.15.102
+a-maximum-rrset.example. 5M IN A 10.0.15.103
+a-maximum-rrset.example. 5M IN A 10.0.15.104
+a-maximum-rrset.example. 5M IN A 10.0.15.105
+a-maximum-rrset.example. 5M IN A 10.0.15.106
+a-maximum-rrset.example. 5M IN A 10.0.15.107
+a-maximum-rrset.example. 5M IN A 10.0.15.108
+a-maximum-rrset.example. 5M IN A 10.0.15.109
+a-maximum-rrset.example. 5M IN A 10.0.15.110
+a-maximum-rrset.example. 5M IN A 10.0.15.111
+a-maximum-rrset.example. 5M IN A 10.0.15.112
+a-maximum-rrset.example. 5M IN A 10.0.15.113
+a-maximum-rrset.example. 5M IN A 10.0.15.114
+a-maximum-rrset.example. 5M IN A 10.0.15.115
+a-maximum-rrset.example. 5M IN A 10.0.15.116
+a-maximum-rrset.example. 5M IN A 10.0.15.117
+a-maximum-rrset.example. 5M IN A 10.0.15.118
+a-maximum-rrset.example. 5M IN A 10.0.15.119
+a-maximum-rrset.example. 5M IN A 10.0.15.120
+a-maximum-rrset.example. 5M IN A 10.0.15.121
+a-maximum-rrset.example. 5M IN A 10.0.15.122
+a-maximum-rrset.example. 5M IN A 10.0.15.123
+a-maximum-rrset.example. 5M IN A 10.0.15.124
+a-maximum-rrset.example. 5M IN A 10.0.15.125
+a-maximum-rrset.example. 5M IN A 10.0.15.126
+a-maximum-rrset.example. 5M IN A 10.0.15.127
+a-maximum-rrset.example. 5M IN A 10.0.15.128
+a-maximum-rrset.example. 5M IN A 10.0.15.129
+a-maximum-rrset.example. 5M IN A 10.0.15.130
+a-maximum-rrset.example. 5M IN A 10.0.15.131
+a-maximum-rrset.example. 5M IN A 10.0.15.132
+a-maximum-rrset.example. 5M IN A 10.0.15.133
+a-maximum-rrset.example. 5M IN A 10.0.15.134
+a-maximum-rrset.example. 5M IN A 10.0.15.135
+a-maximum-rrset.example. 5M IN A 10.0.15.136
+a-maximum-rrset.example. 5M IN A 10.0.15.137
+a-maximum-rrset.example. 5M IN A 10.0.15.138
+a-maximum-rrset.example. 5M IN A 10.0.15.139
+a-maximum-rrset.example. 5M IN A 10.0.15.140
+a-maximum-rrset.example. 5M IN A 10.0.15.141
+a-maximum-rrset.example. 5M IN A 10.0.15.142
+a-maximum-rrset.example. 5M IN A 10.0.15.143
+a-maximum-rrset.example. 5M IN A 10.0.15.144
+a-maximum-rrset.example. 5M IN A 10.0.15.145
+a-maximum-rrset.example. 5M IN A 10.0.15.146
+a-maximum-rrset.example. 5M IN A 10.0.15.147
+a-maximum-rrset.example. 5M IN A 10.0.15.148
+a-maximum-rrset.example. 5M IN A 10.0.15.149
+a-maximum-rrset.example. 5M IN A 10.0.15.150
+a-maximum-rrset.example. 5M IN A 10.0.15.151
+a-maximum-rrset.example. 5M IN A 10.0.15.152
+a-maximum-rrset.example. 5M IN A 10.0.15.153
+a-maximum-rrset.example. 5M IN A 10.0.15.154
+a-maximum-rrset.example. 5M IN A 10.0.15.155
+a-maximum-rrset.example. 5M IN A 10.0.15.156
+a-maximum-rrset.example. 5M IN A 10.0.15.157
+a-maximum-rrset.example. 5M IN A 10.0.15.158
+a-maximum-rrset.example. 5M IN A 10.0.15.159
+a-maximum-rrset.example. 5M IN A 10.1.0.0
+a-maximum-rrset.example. 5M IN A 10.1.0.1
+a-maximum-rrset.example. 5M IN A 10.1.0.2
+a-maximum-rrset.example. 5M IN A 10.1.0.3
+a-maximum-rrset.example. 5M IN A 10.1.0.4
+a-maximum-rrset.example. 5M IN A 10.1.0.5
+a-maximum-rrset.example. 5M IN A 10.1.0.6
+a-maximum-rrset.example. 5M IN A 10.1.0.7
+a-maximum-rrset.example. 5M IN A 10.1.0.8
+a-maximum-rrset.example. 5M IN A 10.1.0.9
+a-maximum-rrset.example. 5M IN A 10.1.0.10
+a-maximum-rrset.example. 5M IN A 10.1.0.11
+a-maximum-rrset.example. 5M IN A 10.1.0.12
+a-maximum-rrset.example. 5M IN A 10.1.0.13
+a-maximum-rrset.example. 5M IN A 10.1.0.14
+a-maximum-rrset.example. 5M IN A 10.1.0.15
+a-maximum-rrset.example. 5M IN A 10.1.0.16
+a-maximum-rrset.example. 5M IN A 10.1.0.17
+a-maximum-rrset.example. 5M IN A 10.1.0.18
+a-maximum-rrset.example. 5M IN A 10.1.0.19
+a-maximum-rrset.example. 5M IN A 10.1.0.20
+a-maximum-rrset.example. 5M IN A 10.1.0.21
+a-maximum-rrset.example. 5M IN A 10.1.0.22
+a-maximum-rrset.example. 5M IN A 10.1.0.23
+a-maximum-rrset.example. 5M IN A 10.1.0.24
+a-maximum-rrset.example. 5M IN A 10.1.0.25
+a-maximum-rrset.example. 5M IN A 10.1.0.26
+a-maximum-rrset.example. 5M IN A 10.1.0.27
+a-maximum-rrset.example. 5M IN A 10.1.0.28
+a-maximum-rrset.example. 5M IN A 10.1.0.29
+a-maximum-rrset.example. 5M IN A 10.1.0.30
+a-maximum-rrset.example. 5M IN A 10.1.0.31
+a-maximum-rrset.example. 5M IN A 10.1.0.32
+a-maximum-rrset.example. 5M IN A 10.1.0.33
+a-maximum-rrset.example. 5M IN A 10.1.0.34
+a-maximum-rrset.example. 5M IN A 10.1.0.35
+a-maximum-rrset.example. 5M IN A 10.1.0.36
+a-maximum-rrset.example. 5M IN A 10.1.0.37
+a-maximum-rrset.example. 5M IN A 10.1.0.38
+a-maximum-rrset.example. 5M IN A 10.1.0.39
+a-maximum-rrset.example. 5M IN A 10.1.0.40
+a-maximum-rrset.example. 5M IN A 10.1.0.41
+a-maximum-rrset.example. 5M IN A 10.1.0.42
+a-maximum-rrset.example. 5M IN A 10.1.0.43
+a-maximum-rrset.example. 5M IN A 10.1.0.44
+a-maximum-rrset.example. 5M IN A 10.1.0.45
+a-maximum-rrset.example. 5M IN A 10.1.0.46
+a-maximum-rrset.example. 5M IN A 10.1.0.47
+a-maximum-rrset.example. 5M IN A 10.1.0.48
+a-maximum-rrset.example. 5M IN A 10.1.0.49
+a-maximum-rrset.example. 5M IN A 10.1.0.50
+a-maximum-rrset.example. 5M IN A 10.1.0.51
+a-maximum-rrset.example. 5M IN A 10.1.0.52
+a-maximum-rrset.example. 5M IN A 10.1.0.53
+a-maximum-rrset.example. 5M IN A 10.1.0.54
+a-maximum-rrset.example. 5M IN A 10.1.0.55
+a-maximum-rrset.example. 5M IN A 10.1.0.56
+a-maximum-rrset.example. 5M IN A 10.1.0.57
+a-maximum-rrset.example. 5M IN A 10.1.0.58
+a-maximum-rrset.example. 5M IN A 10.1.0.59
+a-maximum-rrset.example. 5M IN A 10.1.0.60
+a-maximum-rrset.example. 5M IN A 10.1.0.61
+a-maximum-rrset.example. 5M IN A 10.1.0.62
+a-maximum-rrset.example. 5M IN A 10.1.0.63
+a-maximum-rrset.example. 5M IN A 10.1.0.64
+a-maximum-rrset.example. 5M IN A 10.1.0.65
+a-maximum-rrset.example. 5M IN A 10.1.0.66
+a-maximum-rrset.example. 5M IN A 10.1.0.67
+a-maximum-rrset.example. 5M IN A 10.1.0.68
+a-maximum-rrset.example. 5M IN A 10.1.0.69
+a-maximum-rrset.example. 5M IN A 10.1.0.70
+a-maximum-rrset.example. 5M IN A 10.1.0.71
+a-maximum-rrset.example. 5M IN A 10.1.0.72
+a-maximum-rrset.example. 5M IN A 10.1.0.73
+a-maximum-rrset.example. 5M IN A 10.1.0.74
+a-maximum-rrset.example. 5M IN A 10.1.0.75
+a-maximum-rrset.example. 5M IN A 10.1.0.76
+a-maximum-rrset.example. 5M IN A 10.1.0.77
+a-maximum-rrset.example. 5M IN A 10.1.0.78
+a-maximum-rrset.example. 5M IN A 10.1.0.79
+a-maximum-rrset.example. 5M IN A 10.1.0.80
+a-maximum-rrset.example. 5M IN A 10.1.0.81
+a-maximum-rrset.example. 5M IN A 10.1.0.82
+a-maximum-rrset.example. 5M IN A 10.1.0.83
+a-maximum-rrset.example. 5M IN A 10.1.0.84
+a-maximum-rrset.example. 5M IN A 10.1.0.85
+a-maximum-rrset.example. 5M IN A 10.1.0.86
+a-maximum-rrset.example. 5M IN A 10.1.0.87
+a-maximum-rrset.example. 5M IN A 10.1.0.88
+a-maximum-rrset.example. 5M IN A 10.1.0.89
+a-maximum-rrset.example. 5M IN A 10.1.0.90
+
+;; AUTHORITY SECTION:
+example. 5M IN NS ns1.example.
+
+;; ADDITIONAL SECTION:
+ns1.example. 5M IN A 10.53.0.1
+
+;; Total query time: 308 msec
+;; FROM: draco to SERVER: 10.53.0.1
+;; WHEN: Fri Jun 23 12:58:22 2000
+;; MSG SIZE sent: 41 rcvd: 65535
+
diff --git a/bin/tests/system/limits/ns1/example.db b/bin/tests/system/limits/ns1/example.db
new file mode 100644
index 0000000..8998018
--- /dev/null
+++ b/bin/tests/system/limits/ns1/example.db
@@ -0,0 +1,19112 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns1.example. hostmaster.example. (
+ 2000042795 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS ns1.example.
+ns1 A 10.53.0.1
+1000 A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+2000 A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+ A 10.0.3.232
+ A 10.0.3.233
+ A 10.0.3.234
+ A 10.0.3.235
+ A 10.0.3.236
+ A 10.0.3.237
+ A 10.0.3.238
+ A 10.0.3.239
+ A 10.0.3.240
+ A 10.0.3.241
+ A 10.0.3.242
+ A 10.0.3.243
+ A 10.0.3.244
+ A 10.0.3.245
+ A 10.0.3.246
+ A 10.0.3.247
+ A 10.0.3.248
+ A 10.0.3.249
+ A 10.0.3.250
+ A 10.0.3.251
+ A 10.0.3.252
+ A 10.0.3.253
+ A 10.0.3.254
+ A 10.0.3.255
+ A 10.0.4.0
+ A 10.0.4.1
+ A 10.0.4.2
+ A 10.0.4.3
+ A 10.0.4.4
+ A 10.0.4.5
+ A 10.0.4.6
+ A 10.0.4.7
+ A 10.0.4.8
+ A 10.0.4.9
+ A 10.0.4.10
+ A 10.0.4.11
+ A 10.0.4.12
+ A 10.0.4.13
+ A 10.0.4.14
+ A 10.0.4.15
+ A 10.0.4.16
+ A 10.0.4.17
+ A 10.0.4.18
+ A 10.0.4.19
+ A 10.0.4.20
+ A 10.0.4.21
+ A 10.0.4.22
+ A 10.0.4.23
+ A 10.0.4.24
+ A 10.0.4.25
+ A 10.0.4.26
+ A 10.0.4.27
+ A 10.0.4.28
+ A 10.0.4.29
+ A 10.0.4.30
+ A 10.0.4.31
+ A 10.0.4.32
+ A 10.0.4.33
+ A 10.0.4.34
+ A 10.0.4.35
+ A 10.0.4.36
+ A 10.0.4.37
+ A 10.0.4.38
+ A 10.0.4.39
+ A 10.0.4.40
+ A 10.0.4.41
+ A 10.0.4.42
+ A 10.0.4.43
+ A 10.0.4.44
+ A 10.0.4.45
+ A 10.0.4.46
+ A 10.0.4.47
+ A 10.0.4.48
+ A 10.0.4.49
+ A 10.0.4.50
+ A 10.0.4.51
+ A 10.0.4.52
+ A 10.0.4.53
+ A 10.0.4.54
+ A 10.0.4.55
+ A 10.0.4.56
+ A 10.0.4.57
+ A 10.0.4.58
+ A 10.0.4.59
+ A 10.0.4.60
+ A 10.0.4.61
+ A 10.0.4.62
+ A 10.0.4.63
+ A 10.0.4.64
+ A 10.0.4.65
+ A 10.0.4.66
+ A 10.0.4.67
+ A 10.0.4.68
+ A 10.0.4.69
+ A 10.0.4.70
+ A 10.0.4.71
+ A 10.0.4.72
+ A 10.0.4.73
+ A 10.0.4.74
+ A 10.0.4.75
+ A 10.0.4.76
+ A 10.0.4.77
+ A 10.0.4.78
+ A 10.0.4.79
+ A 10.0.4.80
+ A 10.0.4.81
+ A 10.0.4.82
+ A 10.0.4.83
+ A 10.0.4.84
+ A 10.0.4.85
+ A 10.0.4.86
+ A 10.0.4.87
+ A 10.0.4.88
+ A 10.0.4.89
+ A 10.0.4.90
+ A 10.0.4.91
+ A 10.0.4.92
+ A 10.0.4.93
+ A 10.0.4.94
+ A 10.0.4.95
+ A 10.0.4.96
+ A 10.0.4.97
+ A 10.0.4.98
+ A 10.0.4.99
+ A 10.0.4.100
+ A 10.0.4.101
+ A 10.0.4.102
+ A 10.0.4.103
+ A 10.0.4.104
+ A 10.0.4.105
+ A 10.0.4.106
+ A 10.0.4.107
+ A 10.0.4.108
+ A 10.0.4.109
+ A 10.0.4.110
+ A 10.0.4.111
+ A 10.0.4.112
+ A 10.0.4.113
+ A 10.0.4.114
+ A 10.0.4.115
+ A 10.0.4.116
+ A 10.0.4.117
+ A 10.0.4.118
+ A 10.0.4.119
+ A 10.0.4.120
+ A 10.0.4.121
+ A 10.0.4.122
+ A 10.0.4.123
+ A 10.0.4.124
+ A 10.0.4.125
+ A 10.0.4.126
+ A 10.0.4.127
+ A 10.0.4.128
+ A 10.0.4.129
+ A 10.0.4.130
+ A 10.0.4.131
+ A 10.0.4.132
+ A 10.0.4.133
+ A 10.0.4.134
+ A 10.0.4.135
+ A 10.0.4.136
+ A 10.0.4.137
+ A 10.0.4.138
+ A 10.0.4.139
+ A 10.0.4.140
+ A 10.0.4.141
+ A 10.0.4.142
+ A 10.0.4.143
+ A 10.0.4.144
+ A 10.0.4.145
+ A 10.0.4.146
+ A 10.0.4.147
+ A 10.0.4.148
+ A 10.0.4.149
+ A 10.0.4.150
+ A 10.0.4.151
+ A 10.0.4.152
+ A 10.0.4.153
+ A 10.0.4.154
+ A 10.0.4.155
+ A 10.0.4.156
+ A 10.0.4.157
+ A 10.0.4.158
+ A 10.0.4.159
+ A 10.0.4.160
+ A 10.0.4.161
+ A 10.0.4.162
+ A 10.0.4.163
+ A 10.0.4.164
+ A 10.0.4.165
+ A 10.0.4.166
+ A 10.0.4.167
+ A 10.0.4.168
+ A 10.0.4.169
+ A 10.0.4.170
+ A 10.0.4.171
+ A 10.0.4.172
+ A 10.0.4.173
+ A 10.0.4.174
+ A 10.0.4.175
+ A 10.0.4.176
+ A 10.0.4.177
+ A 10.0.4.178
+ A 10.0.4.179
+ A 10.0.4.180
+ A 10.0.4.181
+ A 10.0.4.182
+ A 10.0.4.183
+ A 10.0.4.184
+ A 10.0.4.185
+ A 10.0.4.186
+ A 10.0.4.187
+ A 10.0.4.188
+ A 10.0.4.189
+ A 10.0.4.190
+ A 10.0.4.191
+ A 10.0.4.192
+ A 10.0.4.193
+ A 10.0.4.194
+ A 10.0.4.195
+ A 10.0.4.196
+ A 10.0.4.197
+ A 10.0.4.198
+ A 10.0.4.199
+ A 10.0.4.200
+ A 10.0.4.201
+ A 10.0.4.202
+ A 10.0.4.203
+ A 10.0.4.204
+ A 10.0.4.205
+ A 10.0.4.206
+ A 10.0.4.207
+ A 10.0.4.208
+ A 10.0.4.209
+ A 10.0.4.210
+ A 10.0.4.211
+ A 10.0.4.212
+ A 10.0.4.213
+ A 10.0.4.214
+ A 10.0.4.215
+ A 10.0.4.216
+ A 10.0.4.217
+ A 10.0.4.218
+ A 10.0.4.219
+ A 10.0.4.220
+ A 10.0.4.221
+ A 10.0.4.222
+ A 10.0.4.223
+ A 10.0.4.224
+ A 10.0.4.225
+ A 10.0.4.226
+ A 10.0.4.227
+ A 10.0.4.228
+ A 10.0.4.229
+ A 10.0.4.230
+ A 10.0.4.231
+ A 10.0.4.232
+ A 10.0.4.233
+ A 10.0.4.234
+ A 10.0.4.235
+ A 10.0.4.236
+ A 10.0.4.237
+ A 10.0.4.238
+ A 10.0.4.239
+ A 10.0.4.240
+ A 10.0.4.241
+ A 10.0.4.242
+ A 10.0.4.243
+ A 10.0.4.244
+ A 10.0.4.245
+ A 10.0.4.246
+ A 10.0.4.247
+ A 10.0.4.248
+ A 10.0.4.249
+ A 10.0.4.250
+ A 10.0.4.251
+ A 10.0.4.252
+ A 10.0.4.253
+ A 10.0.4.254
+ A 10.0.4.255
+ A 10.0.5.0
+ A 10.0.5.1
+ A 10.0.5.2
+ A 10.0.5.3
+ A 10.0.5.4
+ A 10.0.5.5
+ A 10.0.5.6
+ A 10.0.5.7
+ A 10.0.5.8
+ A 10.0.5.9
+ A 10.0.5.10
+ A 10.0.5.11
+ A 10.0.5.12
+ A 10.0.5.13
+ A 10.0.5.14
+ A 10.0.5.15
+ A 10.0.5.16
+ A 10.0.5.17
+ A 10.0.5.18
+ A 10.0.5.19
+ A 10.0.5.20
+ A 10.0.5.21
+ A 10.0.5.22
+ A 10.0.5.23
+ A 10.0.5.24
+ A 10.0.5.25
+ A 10.0.5.26
+ A 10.0.5.27
+ A 10.0.5.28
+ A 10.0.5.29
+ A 10.0.5.30
+ A 10.0.5.31
+ A 10.0.5.32
+ A 10.0.5.33
+ A 10.0.5.34
+ A 10.0.5.35
+ A 10.0.5.36
+ A 10.0.5.37
+ A 10.0.5.38
+ A 10.0.5.39
+ A 10.0.5.40
+ A 10.0.5.41
+ A 10.0.5.42
+ A 10.0.5.43
+ A 10.0.5.44
+ A 10.0.5.45
+ A 10.0.5.46
+ A 10.0.5.47
+ A 10.0.5.48
+ A 10.0.5.49
+ A 10.0.5.50
+ A 10.0.5.51
+ A 10.0.5.52
+ A 10.0.5.53
+ A 10.0.5.54
+ A 10.0.5.55
+ A 10.0.5.56
+ A 10.0.5.57
+ A 10.0.5.58
+ A 10.0.5.59
+ A 10.0.5.60
+ A 10.0.5.61
+ A 10.0.5.62
+ A 10.0.5.63
+ A 10.0.5.64
+ A 10.0.5.65
+ A 10.0.5.66
+ A 10.0.5.67
+ A 10.0.5.68
+ A 10.0.5.69
+ A 10.0.5.70
+ A 10.0.5.71
+ A 10.0.5.72
+ A 10.0.5.73
+ A 10.0.5.74
+ A 10.0.5.75
+ A 10.0.5.76
+ A 10.0.5.77
+ A 10.0.5.78
+ A 10.0.5.79
+ A 10.0.5.80
+ A 10.0.5.81
+ A 10.0.5.82
+ A 10.0.5.83
+ A 10.0.5.84
+ A 10.0.5.85
+ A 10.0.5.86
+ A 10.0.5.87
+ A 10.0.5.88
+ A 10.0.5.89
+ A 10.0.5.90
+ A 10.0.5.91
+ A 10.0.5.92
+ A 10.0.5.93
+ A 10.0.5.94
+ A 10.0.5.95
+ A 10.0.5.96
+ A 10.0.5.97
+ A 10.0.5.98
+ A 10.0.5.99
+ A 10.0.5.100
+ A 10.0.5.101
+ A 10.0.5.102
+ A 10.0.5.103
+ A 10.0.5.104
+ A 10.0.5.105
+ A 10.0.5.106
+ A 10.0.5.107
+ A 10.0.5.108
+ A 10.0.5.109
+ A 10.0.5.110
+ A 10.0.5.111
+ A 10.0.5.112
+ A 10.0.5.113
+ A 10.0.5.114
+ A 10.0.5.115
+ A 10.0.5.116
+ A 10.0.5.117
+ A 10.0.5.118
+ A 10.0.5.119
+ A 10.0.5.120
+ A 10.0.5.121
+ A 10.0.5.122
+ A 10.0.5.123
+ A 10.0.5.124
+ A 10.0.5.125
+ A 10.0.5.126
+ A 10.0.5.127
+ A 10.0.5.128
+ A 10.0.5.129
+ A 10.0.5.130
+ A 10.0.5.131
+ A 10.0.5.132
+ A 10.0.5.133
+ A 10.0.5.134
+ A 10.0.5.135
+ A 10.0.5.136
+ A 10.0.5.137
+ A 10.0.5.138
+ A 10.0.5.139
+ A 10.0.5.140
+ A 10.0.5.141
+ A 10.0.5.142
+ A 10.0.5.143
+ A 10.0.5.144
+ A 10.0.5.145
+ A 10.0.5.146
+ A 10.0.5.147
+ A 10.0.5.148
+ A 10.0.5.149
+ A 10.0.5.150
+ A 10.0.5.151
+ A 10.0.5.152
+ A 10.0.5.153
+ A 10.0.5.154
+ A 10.0.5.155
+ A 10.0.5.156
+ A 10.0.5.157
+ A 10.0.5.158
+ A 10.0.5.159
+ A 10.0.5.160
+ A 10.0.5.161
+ A 10.0.5.162
+ A 10.0.5.163
+ A 10.0.5.164
+ A 10.0.5.165
+ A 10.0.5.166
+ A 10.0.5.167
+ A 10.0.5.168
+ A 10.0.5.169
+ A 10.0.5.170
+ A 10.0.5.171
+ A 10.0.5.172
+ A 10.0.5.173
+ A 10.0.5.174
+ A 10.0.5.175
+ A 10.0.5.176
+ A 10.0.5.177
+ A 10.0.5.178
+ A 10.0.5.179
+ A 10.0.5.180
+ A 10.0.5.181
+ A 10.0.5.182
+ A 10.0.5.183
+ A 10.0.5.184
+ A 10.0.5.185
+ A 10.0.5.186
+ A 10.0.5.187
+ A 10.0.5.188
+ A 10.0.5.189
+ A 10.0.5.190
+ A 10.0.5.191
+ A 10.0.5.192
+ A 10.0.5.193
+ A 10.0.5.194
+ A 10.0.5.195
+ A 10.0.5.196
+ A 10.0.5.197
+ A 10.0.5.198
+ A 10.0.5.199
+ A 10.0.5.200
+ A 10.0.5.201
+ A 10.0.5.202
+ A 10.0.5.203
+ A 10.0.5.204
+ A 10.0.5.205
+ A 10.0.5.206
+ A 10.0.5.207
+ A 10.0.5.208
+ A 10.0.5.209
+ A 10.0.5.210
+ A 10.0.5.211
+ A 10.0.5.212
+ A 10.0.5.213
+ A 10.0.5.214
+ A 10.0.5.215
+ A 10.0.5.216
+ A 10.0.5.217
+ A 10.0.5.218
+ A 10.0.5.219
+ A 10.0.5.220
+ A 10.0.5.221
+ A 10.0.5.222
+ A 10.0.5.223
+ A 10.0.5.224
+ A 10.0.5.225
+ A 10.0.5.226
+ A 10.0.5.227
+ A 10.0.5.228
+ A 10.0.5.229
+ A 10.0.5.230
+ A 10.0.5.231
+ A 10.0.5.232
+ A 10.0.5.233
+ A 10.0.5.234
+ A 10.0.5.235
+ A 10.0.5.236
+ A 10.0.5.237
+ A 10.0.5.238
+ A 10.0.5.239
+ A 10.0.5.240
+ A 10.0.5.241
+ A 10.0.5.242
+ A 10.0.5.243
+ A 10.0.5.244
+ A 10.0.5.245
+ A 10.0.5.246
+ A 10.0.5.247
+ A 10.0.5.248
+ A 10.0.5.249
+ A 10.0.5.250
+ A 10.0.5.251
+ A 10.0.5.252
+ A 10.0.5.253
+ A 10.0.5.254
+ A 10.0.5.255
+ A 10.0.6.0
+ A 10.0.6.1
+ A 10.0.6.2
+ A 10.0.6.3
+ A 10.0.6.4
+ A 10.0.6.5
+ A 10.0.6.6
+ A 10.0.6.7
+ A 10.0.6.8
+ A 10.0.6.9
+ A 10.0.6.10
+ A 10.0.6.11
+ A 10.0.6.12
+ A 10.0.6.13
+ A 10.0.6.14
+ A 10.0.6.15
+ A 10.0.6.16
+ A 10.0.6.17
+ A 10.0.6.18
+ A 10.0.6.19
+ A 10.0.6.20
+ A 10.0.6.21
+ A 10.0.6.22
+ A 10.0.6.23
+ A 10.0.6.24
+ A 10.0.6.25
+ A 10.0.6.26
+ A 10.0.6.27
+ A 10.0.6.28
+ A 10.0.6.29
+ A 10.0.6.30
+ A 10.0.6.31
+ A 10.0.6.32
+ A 10.0.6.33
+ A 10.0.6.34
+ A 10.0.6.35
+ A 10.0.6.36
+ A 10.0.6.37
+ A 10.0.6.38
+ A 10.0.6.39
+ A 10.0.6.40
+ A 10.0.6.41
+ A 10.0.6.42
+ A 10.0.6.43
+ A 10.0.6.44
+ A 10.0.6.45
+ A 10.0.6.46
+ A 10.0.6.47
+ A 10.0.6.48
+ A 10.0.6.49
+ A 10.0.6.50
+ A 10.0.6.51
+ A 10.0.6.52
+ A 10.0.6.53
+ A 10.0.6.54
+ A 10.0.6.55
+ A 10.0.6.56
+ A 10.0.6.57
+ A 10.0.6.58
+ A 10.0.6.59
+ A 10.0.6.60
+ A 10.0.6.61
+ A 10.0.6.62
+ A 10.0.6.63
+ A 10.0.6.64
+ A 10.0.6.65
+ A 10.0.6.66
+ A 10.0.6.67
+ A 10.0.6.68
+ A 10.0.6.69
+ A 10.0.6.70
+ A 10.0.6.71
+ A 10.0.6.72
+ A 10.0.6.73
+ A 10.0.6.74
+ A 10.0.6.75
+ A 10.0.6.76
+ A 10.0.6.77
+ A 10.0.6.78
+ A 10.0.6.79
+ A 10.0.6.80
+ A 10.0.6.81
+ A 10.0.6.82
+ A 10.0.6.83
+ A 10.0.6.84
+ A 10.0.6.85
+ A 10.0.6.86
+ A 10.0.6.87
+ A 10.0.6.88
+ A 10.0.6.89
+ A 10.0.6.90
+ A 10.0.6.91
+ A 10.0.6.92
+ A 10.0.6.93
+ A 10.0.6.94
+ A 10.0.6.95
+ A 10.0.6.96
+ A 10.0.6.97
+ A 10.0.6.98
+ A 10.0.6.99
+ A 10.0.6.100
+ A 10.0.6.101
+ A 10.0.6.102
+ A 10.0.6.103
+ A 10.0.6.104
+ A 10.0.6.105
+ A 10.0.6.106
+ A 10.0.6.107
+ A 10.0.6.108
+ A 10.0.6.109
+ A 10.0.6.110
+ A 10.0.6.111
+ A 10.0.6.112
+ A 10.0.6.113
+ A 10.0.6.114
+ A 10.0.6.115
+ A 10.0.6.116
+ A 10.0.6.117
+ A 10.0.6.118
+ A 10.0.6.119
+ A 10.0.6.120
+ A 10.0.6.121
+ A 10.0.6.122
+ A 10.0.6.123
+ A 10.0.6.124
+ A 10.0.6.125
+ A 10.0.6.126
+ A 10.0.6.127
+ A 10.0.6.128
+ A 10.0.6.129
+ A 10.0.6.130
+ A 10.0.6.131
+ A 10.0.6.132
+ A 10.0.6.133
+ A 10.0.6.134
+ A 10.0.6.135
+ A 10.0.6.136
+ A 10.0.6.137
+ A 10.0.6.138
+ A 10.0.6.139
+ A 10.0.6.140
+ A 10.0.6.141
+ A 10.0.6.142
+ A 10.0.6.143
+ A 10.0.6.144
+ A 10.0.6.145
+ A 10.0.6.146
+ A 10.0.6.147
+ A 10.0.6.148
+ A 10.0.6.149
+ A 10.0.6.150
+ A 10.0.6.151
+ A 10.0.6.152
+ A 10.0.6.153
+ A 10.0.6.154
+ A 10.0.6.155
+ A 10.0.6.156
+ A 10.0.6.157
+ A 10.0.6.158
+ A 10.0.6.159
+ A 10.0.6.160
+ A 10.0.6.161
+ A 10.0.6.162
+ A 10.0.6.163
+ A 10.0.6.164
+ A 10.0.6.165
+ A 10.0.6.166
+ A 10.0.6.167
+ A 10.0.6.168
+ A 10.0.6.169
+ A 10.0.6.170
+ A 10.0.6.171
+ A 10.0.6.172
+ A 10.0.6.173
+ A 10.0.6.174
+ A 10.0.6.175
+ A 10.0.6.176
+ A 10.0.6.177
+ A 10.0.6.178
+ A 10.0.6.179
+ A 10.0.6.180
+ A 10.0.6.181
+ A 10.0.6.182
+ A 10.0.6.183
+ A 10.0.6.184
+ A 10.0.6.185
+ A 10.0.6.186
+ A 10.0.6.187
+ A 10.0.6.188
+ A 10.0.6.189
+ A 10.0.6.190
+ A 10.0.6.191
+ A 10.0.6.192
+ A 10.0.6.193
+ A 10.0.6.194
+ A 10.0.6.195
+ A 10.0.6.196
+ A 10.0.6.197
+ A 10.0.6.198
+ A 10.0.6.199
+ A 10.0.6.200
+ A 10.0.6.201
+ A 10.0.6.202
+ A 10.0.6.203
+ A 10.0.6.204
+ A 10.0.6.205
+ A 10.0.6.206
+ A 10.0.6.207
+ A 10.0.6.208
+ A 10.0.6.209
+ A 10.0.6.210
+ A 10.0.6.211
+ A 10.0.6.212
+ A 10.0.6.213
+ A 10.0.6.214
+ A 10.0.6.215
+ A 10.0.6.216
+ A 10.0.6.217
+ A 10.0.6.218
+ A 10.0.6.219
+ A 10.0.6.220
+ A 10.0.6.221
+ A 10.0.6.222
+ A 10.0.6.223
+ A 10.0.6.224
+ A 10.0.6.225
+ A 10.0.6.226
+ A 10.0.6.227
+ A 10.0.6.228
+ A 10.0.6.229
+ A 10.0.6.230
+ A 10.0.6.231
+ A 10.0.6.232
+ A 10.0.6.233
+ A 10.0.6.234
+ A 10.0.6.235
+ A 10.0.6.236
+ A 10.0.6.237
+ A 10.0.6.238
+ A 10.0.6.239
+ A 10.0.6.240
+ A 10.0.6.241
+ A 10.0.6.242
+ A 10.0.6.243
+ A 10.0.6.244
+ A 10.0.6.245
+ A 10.0.6.246
+ A 10.0.6.247
+ A 10.0.6.248
+ A 10.0.6.249
+ A 10.0.6.250
+ A 10.0.6.251
+ A 10.0.6.252
+ A 10.0.6.253
+ A 10.0.6.254
+ A 10.0.6.255
+ A 10.0.7.0
+ A 10.0.7.1
+ A 10.0.7.2
+ A 10.0.7.3
+ A 10.0.7.4
+ A 10.0.7.5
+ A 10.0.7.6
+ A 10.0.7.7
+ A 10.0.7.8
+ A 10.0.7.9
+ A 10.0.7.10
+ A 10.0.7.11
+ A 10.0.7.12
+ A 10.0.7.13
+ A 10.0.7.14
+ A 10.0.7.15
+ A 10.0.7.16
+ A 10.0.7.17
+ A 10.0.7.18
+ A 10.0.7.19
+ A 10.0.7.20
+ A 10.0.7.21
+ A 10.0.7.22
+ A 10.0.7.23
+ A 10.0.7.24
+ A 10.0.7.25
+ A 10.0.7.26
+ A 10.0.7.27
+ A 10.0.7.28
+ A 10.0.7.29
+ A 10.0.7.30
+ A 10.0.7.31
+ A 10.0.7.32
+ A 10.0.7.33
+ A 10.0.7.34
+ A 10.0.7.35
+ A 10.0.7.36
+ A 10.0.7.37
+ A 10.0.7.38
+ A 10.0.7.39
+ A 10.0.7.40
+ A 10.0.7.41
+ A 10.0.7.42
+ A 10.0.7.43
+ A 10.0.7.44
+ A 10.0.7.45
+ A 10.0.7.46
+ A 10.0.7.47
+ A 10.0.7.48
+ A 10.0.7.49
+ A 10.0.7.50
+ A 10.0.7.51
+ A 10.0.7.52
+ A 10.0.7.53
+ A 10.0.7.54
+ A 10.0.7.55
+ A 10.0.7.56
+ A 10.0.7.57
+ A 10.0.7.58
+ A 10.0.7.59
+ A 10.0.7.60
+ A 10.0.7.61
+ A 10.0.7.62
+ A 10.0.7.63
+ A 10.0.7.64
+ A 10.0.7.65
+ A 10.0.7.66
+ A 10.0.7.67
+ A 10.0.7.68
+ A 10.0.7.69
+ A 10.0.7.70
+ A 10.0.7.71
+ A 10.0.7.72
+ A 10.0.7.73
+ A 10.0.7.74
+ A 10.0.7.75
+ A 10.0.7.76
+ A 10.0.7.77
+ A 10.0.7.78
+ A 10.0.7.79
+ A 10.0.7.80
+ A 10.0.7.81
+ A 10.0.7.82
+ A 10.0.7.83
+ A 10.0.7.84
+ A 10.0.7.85
+ A 10.0.7.86
+ A 10.0.7.87
+ A 10.0.7.88
+ A 10.0.7.89
+ A 10.0.7.90
+ A 10.0.7.91
+ A 10.0.7.92
+ A 10.0.7.93
+ A 10.0.7.94
+ A 10.0.7.95
+ A 10.0.7.96
+ A 10.0.7.97
+ A 10.0.7.98
+ A 10.0.7.99
+ A 10.0.7.100
+ A 10.0.7.101
+ A 10.0.7.102
+ A 10.0.7.103
+ A 10.0.7.104
+ A 10.0.7.105
+ A 10.0.7.106
+ A 10.0.7.107
+ A 10.0.7.108
+ A 10.0.7.109
+ A 10.0.7.110
+ A 10.0.7.111
+ A 10.0.7.112
+ A 10.0.7.113
+ A 10.0.7.114
+ A 10.0.7.115
+ A 10.0.7.116
+ A 10.0.7.117
+ A 10.0.7.118
+ A 10.0.7.119
+ A 10.0.7.120
+ A 10.0.7.121
+ A 10.0.7.122
+ A 10.0.7.123
+ A 10.0.7.124
+ A 10.0.7.125
+ A 10.0.7.126
+ A 10.0.7.127
+ A 10.0.7.128
+ A 10.0.7.129
+ A 10.0.7.130
+ A 10.0.7.131
+ A 10.0.7.132
+ A 10.0.7.133
+ A 10.0.7.134
+ A 10.0.7.135
+ A 10.0.7.136
+ A 10.0.7.137
+ A 10.0.7.138
+ A 10.0.7.139
+ A 10.0.7.140
+ A 10.0.7.141
+ A 10.0.7.142
+ A 10.0.7.143
+ A 10.0.7.144
+ A 10.0.7.145
+ A 10.0.7.146
+ A 10.0.7.147
+ A 10.0.7.148
+ A 10.0.7.149
+ A 10.0.7.150
+ A 10.0.7.151
+ A 10.0.7.152
+ A 10.0.7.153
+ A 10.0.7.154
+ A 10.0.7.155
+ A 10.0.7.156
+ A 10.0.7.157
+ A 10.0.7.158
+ A 10.0.7.159
+ A 10.0.7.160
+ A 10.0.7.161
+ A 10.0.7.162
+ A 10.0.7.163
+ A 10.0.7.164
+ A 10.0.7.165
+ A 10.0.7.166
+ A 10.0.7.167
+ A 10.0.7.168
+ A 10.0.7.169
+ A 10.0.7.170
+ A 10.0.7.171
+ A 10.0.7.172
+ A 10.0.7.173
+ A 10.0.7.174
+ A 10.0.7.175
+ A 10.0.7.176
+ A 10.0.7.177
+ A 10.0.7.178
+ A 10.0.7.179
+ A 10.0.7.180
+ A 10.0.7.181
+ A 10.0.7.182
+ A 10.0.7.183
+ A 10.0.7.184
+ A 10.0.7.185
+ A 10.0.7.186
+ A 10.0.7.187
+ A 10.0.7.188
+ A 10.0.7.189
+ A 10.0.7.190
+ A 10.0.7.191
+ A 10.0.7.192
+ A 10.0.7.193
+ A 10.0.7.194
+ A 10.0.7.195
+ A 10.0.7.196
+ A 10.0.7.197
+ A 10.0.7.198
+ A 10.0.7.199
+ A 10.0.7.200
+ A 10.0.7.201
+ A 10.0.7.202
+ A 10.0.7.203
+ A 10.0.7.204
+ A 10.0.7.205
+ A 10.0.7.206
+ A 10.0.7.207
+3000 A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+ A 10.0.3.232
+ A 10.0.3.233
+ A 10.0.3.234
+ A 10.0.3.235
+ A 10.0.3.236
+ A 10.0.3.237
+ A 10.0.3.238
+ A 10.0.3.239
+ A 10.0.3.240
+ A 10.0.3.241
+ A 10.0.3.242
+ A 10.0.3.243
+ A 10.0.3.244
+ A 10.0.3.245
+ A 10.0.3.246
+ A 10.0.3.247
+ A 10.0.3.248
+ A 10.0.3.249
+ A 10.0.3.250
+ A 10.0.3.251
+ A 10.0.3.252
+ A 10.0.3.253
+ A 10.0.3.254
+ A 10.0.3.255
+ A 10.0.4.0
+ A 10.0.4.1
+ A 10.0.4.2
+ A 10.0.4.3
+ A 10.0.4.4
+ A 10.0.4.5
+ A 10.0.4.6
+ A 10.0.4.7
+ A 10.0.4.8
+ A 10.0.4.9
+ A 10.0.4.10
+ A 10.0.4.11
+ A 10.0.4.12
+ A 10.0.4.13
+ A 10.0.4.14
+ A 10.0.4.15
+ A 10.0.4.16
+ A 10.0.4.17
+ A 10.0.4.18
+ A 10.0.4.19
+ A 10.0.4.20
+ A 10.0.4.21
+ A 10.0.4.22
+ A 10.0.4.23
+ A 10.0.4.24
+ A 10.0.4.25
+ A 10.0.4.26
+ A 10.0.4.27
+ A 10.0.4.28
+ A 10.0.4.29
+ A 10.0.4.30
+ A 10.0.4.31
+ A 10.0.4.32
+ A 10.0.4.33
+ A 10.0.4.34
+ A 10.0.4.35
+ A 10.0.4.36
+ A 10.0.4.37
+ A 10.0.4.38
+ A 10.0.4.39
+ A 10.0.4.40
+ A 10.0.4.41
+ A 10.0.4.42
+ A 10.0.4.43
+ A 10.0.4.44
+ A 10.0.4.45
+ A 10.0.4.46
+ A 10.0.4.47
+ A 10.0.4.48
+ A 10.0.4.49
+ A 10.0.4.50
+ A 10.0.4.51
+ A 10.0.4.52
+ A 10.0.4.53
+ A 10.0.4.54
+ A 10.0.4.55
+ A 10.0.4.56
+ A 10.0.4.57
+ A 10.0.4.58
+ A 10.0.4.59
+ A 10.0.4.60
+ A 10.0.4.61
+ A 10.0.4.62
+ A 10.0.4.63
+ A 10.0.4.64
+ A 10.0.4.65
+ A 10.0.4.66
+ A 10.0.4.67
+ A 10.0.4.68
+ A 10.0.4.69
+ A 10.0.4.70
+ A 10.0.4.71
+ A 10.0.4.72
+ A 10.0.4.73
+ A 10.0.4.74
+ A 10.0.4.75
+ A 10.0.4.76
+ A 10.0.4.77
+ A 10.0.4.78
+ A 10.0.4.79
+ A 10.0.4.80
+ A 10.0.4.81
+ A 10.0.4.82
+ A 10.0.4.83
+ A 10.0.4.84
+ A 10.0.4.85
+ A 10.0.4.86
+ A 10.0.4.87
+ A 10.0.4.88
+ A 10.0.4.89
+ A 10.0.4.90
+ A 10.0.4.91
+ A 10.0.4.92
+ A 10.0.4.93
+ A 10.0.4.94
+ A 10.0.4.95
+ A 10.0.4.96
+ A 10.0.4.97
+ A 10.0.4.98
+ A 10.0.4.99
+ A 10.0.4.100
+ A 10.0.4.101
+ A 10.0.4.102
+ A 10.0.4.103
+ A 10.0.4.104
+ A 10.0.4.105
+ A 10.0.4.106
+ A 10.0.4.107
+ A 10.0.4.108
+ A 10.0.4.109
+ A 10.0.4.110
+ A 10.0.4.111
+ A 10.0.4.112
+ A 10.0.4.113
+ A 10.0.4.114
+ A 10.0.4.115
+ A 10.0.4.116
+ A 10.0.4.117
+ A 10.0.4.118
+ A 10.0.4.119
+ A 10.0.4.120
+ A 10.0.4.121
+ A 10.0.4.122
+ A 10.0.4.123
+ A 10.0.4.124
+ A 10.0.4.125
+ A 10.0.4.126
+ A 10.0.4.127
+ A 10.0.4.128
+ A 10.0.4.129
+ A 10.0.4.130
+ A 10.0.4.131
+ A 10.0.4.132
+ A 10.0.4.133
+ A 10.0.4.134
+ A 10.0.4.135
+ A 10.0.4.136
+ A 10.0.4.137
+ A 10.0.4.138
+ A 10.0.4.139
+ A 10.0.4.140
+ A 10.0.4.141
+ A 10.0.4.142
+ A 10.0.4.143
+ A 10.0.4.144
+ A 10.0.4.145
+ A 10.0.4.146
+ A 10.0.4.147
+ A 10.0.4.148
+ A 10.0.4.149
+ A 10.0.4.150
+ A 10.0.4.151
+ A 10.0.4.152
+ A 10.0.4.153
+ A 10.0.4.154
+ A 10.0.4.155
+ A 10.0.4.156
+ A 10.0.4.157
+ A 10.0.4.158
+ A 10.0.4.159
+ A 10.0.4.160
+ A 10.0.4.161
+ A 10.0.4.162
+ A 10.0.4.163
+ A 10.0.4.164
+ A 10.0.4.165
+ A 10.0.4.166
+ A 10.0.4.167
+ A 10.0.4.168
+ A 10.0.4.169
+ A 10.0.4.170
+ A 10.0.4.171
+ A 10.0.4.172
+ A 10.0.4.173
+ A 10.0.4.174
+ A 10.0.4.175
+ A 10.0.4.176
+ A 10.0.4.177
+ A 10.0.4.178
+ A 10.0.4.179
+ A 10.0.4.180
+ A 10.0.4.181
+ A 10.0.4.182
+ A 10.0.4.183
+ A 10.0.4.184
+ A 10.0.4.185
+ A 10.0.4.186
+ A 10.0.4.187
+ A 10.0.4.188
+ A 10.0.4.189
+ A 10.0.4.190
+ A 10.0.4.191
+ A 10.0.4.192
+ A 10.0.4.193
+ A 10.0.4.194
+ A 10.0.4.195
+ A 10.0.4.196
+ A 10.0.4.197
+ A 10.0.4.198
+ A 10.0.4.199
+ A 10.0.4.200
+ A 10.0.4.201
+ A 10.0.4.202
+ A 10.0.4.203
+ A 10.0.4.204
+ A 10.0.4.205
+ A 10.0.4.206
+ A 10.0.4.207
+ A 10.0.4.208
+ A 10.0.4.209
+ A 10.0.4.210
+ A 10.0.4.211
+ A 10.0.4.212
+ A 10.0.4.213
+ A 10.0.4.214
+ A 10.0.4.215
+ A 10.0.4.216
+ A 10.0.4.217
+ A 10.0.4.218
+ A 10.0.4.219
+ A 10.0.4.220
+ A 10.0.4.221
+ A 10.0.4.222
+ A 10.0.4.223
+ A 10.0.4.224
+ A 10.0.4.225
+ A 10.0.4.226
+ A 10.0.4.227
+ A 10.0.4.228
+ A 10.0.4.229
+ A 10.0.4.230
+ A 10.0.4.231
+ A 10.0.4.232
+ A 10.0.4.233
+ A 10.0.4.234
+ A 10.0.4.235
+ A 10.0.4.236
+ A 10.0.4.237
+ A 10.0.4.238
+ A 10.0.4.239
+ A 10.0.4.240
+ A 10.0.4.241
+ A 10.0.4.242
+ A 10.0.4.243
+ A 10.0.4.244
+ A 10.0.4.245
+ A 10.0.4.246
+ A 10.0.4.247
+ A 10.0.4.248
+ A 10.0.4.249
+ A 10.0.4.250
+ A 10.0.4.251
+ A 10.0.4.252
+ A 10.0.4.253
+ A 10.0.4.254
+ A 10.0.4.255
+ A 10.0.5.0
+ A 10.0.5.1
+ A 10.0.5.2
+ A 10.0.5.3
+ A 10.0.5.4
+ A 10.0.5.5
+ A 10.0.5.6
+ A 10.0.5.7
+ A 10.0.5.8
+ A 10.0.5.9
+ A 10.0.5.10
+ A 10.0.5.11
+ A 10.0.5.12
+ A 10.0.5.13
+ A 10.0.5.14
+ A 10.0.5.15
+ A 10.0.5.16
+ A 10.0.5.17
+ A 10.0.5.18
+ A 10.0.5.19
+ A 10.0.5.20
+ A 10.0.5.21
+ A 10.0.5.22
+ A 10.0.5.23
+ A 10.0.5.24
+ A 10.0.5.25
+ A 10.0.5.26
+ A 10.0.5.27
+ A 10.0.5.28
+ A 10.0.5.29
+ A 10.0.5.30
+ A 10.0.5.31
+ A 10.0.5.32
+ A 10.0.5.33
+ A 10.0.5.34
+ A 10.0.5.35
+ A 10.0.5.36
+ A 10.0.5.37
+ A 10.0.5.38
+ A 10.0.5.39
+ A 10.0.5.40
+ A 10.0.5.41
+ A 10.0.5.42
+ A 10.0.5.43
+ A 10.0.5.44
+ A 10.0.5.45
+ A 10.0.5.46
+ A 10.0.5.47
+ A 10.0.5.48
+ A 10.0.5.49
+ A 10.0.5.50
+ A 10.0.5.51
+ A 10.0.5.52
+ A 10.0.5.53
+ A 10.0.5.54
+ A 10.0.5.55
+ A 10.0.5.56
+ A 10.0.5.57
+ A 10.0.5.58
+ A 10.0.5.59
+ A 10.0.5.60
+ A 10.0.5.61
+ A 10.0.5.62
+ A 10.0.5.63
+ A 10.0.5.64
+ A 10.0.5.65
+ A 10.0.5.66
+ A 10.0.5.67
+ A 10.0.5.68
+ A 10.0.5.69
+ A 10.0.5.70
+ A 10.0.5.71
+ A 10.0.5.72
+ A 10.0.5.73
+ A 10.0.5.74
+ A 10.0.5.75
+ A 10.0.5.76
+ A 10.0.5.77
+ A 10.0.5.78
+ A 10.0.5.79
+ A 10.0.5.80
+ A 10.0.5.81
+ A 10.0.5.82
+ A 10.0.5.83
+ A 10.0.5.84
+ A 10.0.5.85
+ A 10.0.5.86
+ A 10.0.5.87
+ A 10.0.5.88
+ A 10.0.5.89
+ A 10.0.5.90
+ A 10.0.5.91
+ A 10.0.5.92
+ A 10.0.5.93
+ A 10.0.5.94
+ A 10.0.5.95
+ A 10.0.5.96
+ A 10.0.5.97
+ A 10.0.5.98
+ A 10.0.5.99
+ A 10.0.5.100
+ A 10.0.5.101
+ A 10.0.5.102
+ A 10.0.5.103
+ A 10.0.5.104
+ A 10.0.5.105
+ A 10.0.5.106
+ A 10.0.5.107
+ A 10.0.5.108
+ A 10.0.5.109
+ A 10.0.5.110
+ A 10.0.5.111
+ A 10.0.5.112
+ A 10.0.5.113
+ A 10.0.5.114
+ A 10.0.5.115
+ A 10.0.5.116
+ A 10.0.5.117
+ A 10.0.5.118
+ A 10.0.5.119
+ A 10.0.5.120
+ A 10.0.5.121
+ A 10.0.5.122
+ A 10.0.5.123
+ A 10.0.5.124
+ A 10.0.5.125
+ A 10.0.5.126
+ A 10.0.5.127
+ A 10.0.5.128
+ A 10.0.5.129
+ A 10.0.5.130
+ A 10.0.5.131
+ A 10.0.5.132
+ A 10.0.5.133
+ A 10.0.5.134
+ A 10.0.5.135
+ A 10.0.5.136
+ A 10.0.5.137
+ A 10.0.5.138
+ A 10.0.5.139
+ A 10.0.5.140
+ A 10.0.5.141
+ A 10.0.5.142
+ A 10.0.5.143
+ A 10.0.5.144
+ A 10.0.5.145
+ A 10.0.5.146
+ A 10.0.5.147
+ A 10.0.5.148
+ A 10.0.5.149
+ A 10.0.5.150
+ A 10.0.5.151
+ A 10.0.5.152
+ A 10.0.5.153
+ A 10.0.5.154
+ A 10.0.5.155
+ A 10.0.5.156
+ A 10.0.5.157
+ A 10.0.5.158
+ A 10.0.5.159
+ A 10.0.5.160
+ A 10.0.5.161
+ A 10.0.5.162
+ A 10.0.5.163
+ A 10.0.5.164
+ A 10.0.5.165
+ A 10.0.5.166
+ A 10.0.5.167
+ A 10.0.5.168
+ A 10.0.5.169
+ A 10.0.5.170
+ A 10.0.5.171
+ A 10.0.5.172
+ A 10.0.5.173
+ A 10.0.5.174
+ A 10.0.5.175
+ A 10.0.5.176
+ A 10.0.5.177
+ A 10.0.5.178
+ A 10.0.5.179
+ A 10.0.5.180
+ A 10.0.5.181
+ A 10.0.5.182
+ A 10.0.5.183
+ A 10.0.5.184
+ A 10.0.5.185
+ A 10.0.5.186
+ A 10.0.5.187
+ A 10.0.5.188
+ A 10.0.5.189
+ A 10.0.5.190
+ A 10.0.5.191
+ A 10.0.5.192
+ A 10.0.5.193
+ A 10.0.5.194
+ A 10.0.5.195
+ A 10.0.5.196
+ A 10.0.5.197
+ A 10.0.5.198
+ A 10.0.5.199
+ A 10.0.5.200
+ A 10.0.5.201
+ A 10.0.5.202
+ A 10.0.5.203
+ A 10.0.5.204
+ A 10.0.5.205
+ A 10.0.5.206
+ A 10.0.5.207
+ A 10.0.5.208
+ A 10.0.5.209
+ A 10.0.5.210
+ A 10.0.5.211
+ A 10.0.5.212
+ A 10.0.5.213
+ A 10.0.5.214
+ A 10.0.5.215
+ A 10.0.5.216
+ A 10.0.5.217
+ A 10.0.5.218
+ A 10.0.5.219
+ A 10.0.5.220
+ A 10.0.5.221
+ A 10.0.5.222
+ A 10.0.5.223
+ A 10.0.5.224
+ A 10.0.5.225
+ A 10.0.5.226
+ A 10.0.5.227
+ A 10.0.5.228
+ A 10.0.5.229
+ A 10.0.5.230
+ A 10.0.5.231
+ A 10.0.5.232
+ A 10.0.5.233
+ A 10.0.5.234
+ A 10.0.5.235
+ A 10.0.5.236
+ A 10.0.5.237
+ A 10.0.5.238
+ A 10.0.5.239
+ A 10.0.5.240
+ A 10.0.5.241
+ A 10.0.5.242
+ A 10.0.5.243
+ A 10.0.5.244
+ A 10.0.5.245
+ A 10.0.5.246
+ A 10.0.5.247
+ A 10.0.5.248
+ A 10.0.5.249
+ A 10.0.5.250
+ A 10.0.5.251
+ A 10.0.5.252
+ A 10.0.5.253
+ A 10.0.5.254
+ A 10.0.5.255
+ A 10.0.6.0
+ A 10.0.6.1
+ A 10.0.6.2
+ A 10.0.6.3
+ A 10.0.6.4
+ A 10.0.6.5
+ A 10.0.6.6
+ A 10.0.6.7
+ A 10.0.6.8
+ A 10.0.6.9
+ A 10.0.6.10
+ A 10.0.6.11
+ A 10.0.6.12
+ A 10.0.6.13
+ A 10.0.6.14
+ A 10.0.6.15
+ A 10.0.6.16
+ A 10.0.6.17
+ A 10.0.6.18
+ A 10.0.6.19
+ A 10.0.6.20
+ A 10.0.6.21
+ A 10.0.6.22
+ A 10.0.6.23
+ A 10.0.6.24
+ A 10.0.6.25
+ A 10.0.6.26
+ A 10.0.6.27
+ A 10.0.6.28
+ A 10.0.6.29
+ A 10.0.6.30
+ A 10.0.6.31
+ A 10.0.6.32
+ A 10.0.6.33
+ A 10.0.6.34
+ A 10.0.6.35
+ A 10.0.6.36
+ A 10.0.6.37
+ A 10.0.6.38
+ A 10.0.6.39
+ A 10.0.6.40
+ A 10.0.6.41
+ A 10.0.6.42
+ A 10.0.6.43
+ A 10.0.6.44
+ A 10.0.6.45
+ A 10.0.6.46
+ A 10.0.6.47
+ A 10.0.6.48
+ A 10.0.6.49
+ A 10.0.6.50
+ A 10.0.6.51
+ A 10.0.6.52
+ A 10.0.6.53
+ A 10.0.6.54
+ A 10.0.6.55
+ A 10.0.6.56
+ A 10.0.6.57
+ A 10.0.6.58
+ A 10.0.6.59
+ A 10.0.6.60
+ A 10.0.6.61
+ A 10.0.6.62
+ A 10.0.6.63
+ A 10.0.6.64
+ A 10.0.6.65
+ A 10.0.6.66
+ A 10.0.6.67
+ A 10.0.6.68
+ A 10.0.6.69
+ A 10.0.6.70
+ A 10.0.6.71
+ A 10.0.6.72
+ A 10.0.6.73
+ A 10.0.6.74
+ A 10.0.6.75
+ A 10.0.6.76
+ A 10.0.6.77
+ A 10.0.6.78
+ A 10.0.6.79
+ A 10.0.6.80
+ A 10.0.6.81
+ A 10.0.6.82
+ A 10.0.6.83
+ A 10.0.6.84
+ A 10.0.6.85
+ A 10.0.6.86
+ A 10.0.6.87
+ A 10.0.6.88
+ A 10.0.6.89
+ A 10.0.6.90
+ A 10.0.6.91
+ A 10.0.6.92
+ A 10.0.6.93
+ A 10.0.6.94
+ A 10.0.6.95
+ A 10.0.6.96
+ A 10.0.6.97
+ A 10.0.6.98
+ A 10.0.6.99
+ A 10.0.6.100
+ A 10.0.6.101
+ A 10.0.6.102
+ A 10.0.6.103
+ A 10.0.6.104
+ A 10.0.6.105
+ A 10.0.6.106
+ A 10.0.6.107
+ A 10.0.6.108
+ A 10.0.6.109
+ A 10.0.6.110
+ A 10.0.6.111
+ A 10.0.6.112
+ A 10.0.6.113
+ A 10.0.6.114
+ A 10.0.6.115
+ A 10.0.6.116
+ A 10.0.6.117
+ A 10.0.6.118
+ A 10.0.6.119
+ A 10.0.6.120
+ A 10.0.6.121
+ A 10.0.6.122
+ A 10.0.6.123
+ A 10.0.6.124
+ A 10.0.6.125
+ A 10.0.6.126
+ A 10.0.6.127
+ A 10.0.6.128
+ A 10.0.6.129
+ A 10.0.6.130
+ A 10.0.6.131
+ A 10.0.6.132
+ A 10.0.6.133
+ A 10.0.6.134
+ A 10.0.6.135
+ A 10.0.6.136
+ A 10.0.6.137
+ A 10.0.6.138
+ A 10.0.6.139
+ A 10.0.6.140
+ A 10.0.6.141
+ A 10.0.6.142
+ A 10.0.6.143
+ A 10.0.6.144
+ A 10.0.6.145
+ A 10.0.6.146
+ A 10.0.6.147
+ A 10.0.6.148
+ A 10.0.6.149
+ A 10.0.6.150
+ A 10.0.6.151
+ A 10.0.6.152
+ A 10.0.6.153
+ A 10.0.6.154
+ A 10.0.6.155
+ A 10.0.6.156
+ A 10.0.6.157
+ A 10.0.6.158
+ A 10.0.6.159
+ A 10.0.6.160
+ A 10.0.6.161
+ A 10.0.6.162
+ A 10.0.6.163
+ A 10.0.6.164
+ A 10.0.6.165
+ A 10.0.6.166
+ A 10.0.6.167
+ A 10.0.6.168
+ A 10.0.6.169
+ A 10.0.6.170
+ A 10.0.6.171
+ A 10.0.6.172
+ A 10.0.6.173
+ A 10.0.6.174
+ A 10.0.6.175
+ A 10.0.6.176
+ A 10.0.6.177
+ A 10.0.6.178
+ A 10.0.6.179
+ A 10.0.6.180
+ A 10.0.6.181
+ A 10.0.6.182
+ A 10.0.6.183
+ A 10.0.6.184
+ A 10.0.6.185
+ A 10.0.6.186
+ A 10.0.6.187
+ A 10.0.6.188
+ A 10.0.6.189
+ A 10.0.6.190
+ A 10.0.6.191
+ A 10.0.6.192
+ A 10.0.6.193
+ A 10.0.6.194
+ A 10.0.6.195
+ A 10.0.6.196
+ A 10.0.6.197
+ A 10.0.6.198
+ A 10.0.6.199
+ A 10.0.6.200
+ A 10.0.6.201
+ A 10.0.6.202
+ A 10.0.6.203
+ A 10.0.6.204
+ A 10.0.6.205
+ A 10.0.6.206
+ A 10.0.6.207
+ A 10.0.6.208
+ A 10.0.6.209
+ A 10.0.6.210
+ A 10.0.6.211
+ A 10.0.6.212
+ A 10.0.6.213
+ A 10.0.6.214
+ A 10.0.6.215
+ A 10.0.6.216
+ A 10.0.6.217
+ A 10.0.6.218
+ A 10.0.6.219
+ A 10.0.6.220
+ A 10.0.6.221
+ A 10.0.6.222
+ A 10.0.6.223
+ A 10.0.6.224
+ A 10.0.6.225
+ A 10.0.6.226
+ A 10.0.6.227
+ A 10.0.6.228
+ A 10.0.6.229
+ A 10.0.6.230
+ A 10.0.6.231
+ A 10.0.6.232
+ A 10.0.6.233
+ A 10.0.6.234
+ A 10.0.6.235
+ A 10.0.6.236
+ A 10.0.6.237
+ A 10.0.6.238
+ A 10.0.6.239
+ A 10.0.6.240
+ A 10.0.6.241
+ A 10.0.6.242
+ A 10.0.6.243
+ A 10.0.6.244
+ A 10.0.6.245
+ A 10.0.6.246
+ A 10.0.6.247
+ A 10.0.6.248
+ A 10.0.6.249
+ A 10.0.6.250
+ A 10.0.6.251
+ A 10.0.6.252
+ A 10.0.6.253
+ A 10.0.6.254
+ A 10.0.6.255
+ A 10.0.7.0
+ A 10.0.7.1
+ A 10.0.7.2
+ A 10.0.7.3
+ A 10.0.7.4
+ A 10.0.7.5
+ A 10.0.7.6
+ A 10.0.7.7
+ A 10.0.7.8
+ A 10.0.7.9
+ A 10.0.7.10
+ A 10.0.7.11
+ A 10.0.7.12
+ A 10.0.7.13
+ A 10.0.7.14
+ A 10.0.7.15
+ A 10.0.7.16
+ A 10.0.7.17
+ A 10.0.7.18
+ A 10.0.7.19
+ A 10.0.7.20
+ A 10.0.7.21
+ A 10.0.7.22
+ A 10.0.7.23
+ A 10.0.7.24
+ A 10.0.7.25
+ A 10.0.7.26
+ A 10.0.7.27
+ A 10.0.7.28
+ A 10.0.7.29
+ A 10.0.7.30
+ A 10.0.7.31
+ A 10.0.7.32
+ A 10.0.7.33
+ A 10.0.7.34
+ A 10.0.7.35
+ A 10.0.7.36
+ A 10.0.7.37
+ A 10.0.7.38
+ A 10.0.7.39
+ A 10.0.7.40
+ A 10.0.7.41
+ A 10.0.7.42
+ A 10.0.7.43
+ A 10.0.7.44
+ A 10.0.7.45
+ A 10.0.7.46
+ A 10.0.7.47
+ A 10.0.7.48
+ A 10.0.7.49
+ A 10.0.7.50
+ A 10.0.7.51
+ A 10.0.7.52
+ A 10.0.7.53
+ A 10.0.7.54
+ A 10.0.7.55
+ A 10.0.7.56
+ A 10.0.7.57
+ A 10.0.7.58
+ A 10.0.7.59
+ A 10.0.7.60
+ A 10.0.7.61
+ A 10.0.7.62
+ A 10.0.7.63
+ A 10.0.7.64
+ A 10.0.7.65
+ A 10.0.7.66
+ A 10.0.7.67
+ A 10.0.7.68
+ A 10.0.7.69
+ A 10.0.7.70
+ A 10.0.7.71
+ A 10.0.7.72
+ A 10.0.7.73
+ A 10.0.7.74
+ A 10.0.7.75
+ A 10.0.7.76
+ A 10.0.7.77
+ A 10.0.7.78
+ A 10.0.7.79
+ A 10.0.7.80
+ A 10.0.7.81
+ A 10.0.7.82
+ A 10.0.7.83
+ A 10.0.7.84
+ A 10.0.7.85
+ A 10.0.7.86
+ A 10.0.7.87
+ A 10.0.7.88
+ A 10.0.7.89
+ A 10.0.7.90
+ A 10.0.7.91
+ A 10.0.7.92
+ A 10.0.7.93
+ A 10.0.7.94
+ A 10.0.7.95
+ A 10.0.7.96
+ A 10.0.7.97
+ A 10.0.7.98
+ A 10.0.7.99
+ A 10.0.7.100
+ A 10.0.7.101
+ A 10.0.7.102
+ A 10.0.7.103
+ A 10.0.7.104
+ A 10.0.7.105
+ A 10.0.7.106
+ A 10.0.7.107
+ A 10.0.7.108
+ A 10.0.7.109
+ A 10.0.7.110
+ A 10.0.7.111
+ A 10.0.7.112
+ A 10.0.7.113
+ A 10.0.7.114
+ A 10.0.7.115
+ A 10.0.7.116
+ A 10.0.7.117
+ A 10.0.7.118
+ A 10.0.7.119
+ A 10.0.7.120
+ A 10.0.7.121
+ A 10.0.7.122
+ A 10.0.7.123
+ A 10.0.7.124
+ A 10.0.7.125
+ A 10.0.7.126
+ A 10.0.7.127
+ A 10.0.7.128
+ A 10.0.7.129
+ A 10.0.7.130
+ A 10.0.7.131
+ A 10.0.7.132
+ A 10.0.7.133
+ A 10.0.7.134
+ A 10.0.7.135
+ A 10.0.7.136
+ A 10.0.7.137
+ A 10.0.7.138
+ A 10.0.7.139
+ A 10.0.7.140
+ A 10.0.7.141
+ A 10.0.7.142
+ A 10.0.7.143
+ A 10.0.7.144
+ A 10.0.7.145
+ A 10.0.7.146
+ A 10.0.7.147
+ A 10.0.7.148
+ A 10.0.7.149
+ A 10.0.7.150
+ A 10.0.7.151
+ A 10.0.7.152
+ A 10.0.7.153
+ A 10.0.7.154
+ A 10.0.7.155
+ A 10.0.7.156
+ A 10.0.7.157
+ A 10.0.7.158
+ A 10.0.7.159
+ A 10.0.7.160
+ A 10.0.7.161
+ A 10.0.7.162
+ A 10.0.7.163
+ A 10.0.7.164
+ A 10.0.7.165
+ A 10.0.7.166
+ A 10.0.7.167
+ A 10.0.7.168
+ A 10.0.7.169
+ A 10.0.7.170
+ A 10.0.7.171
+ A 10.0.7.172
+ A 10.0.7.173
+ A 10.0.7.174
+ A 10.0.7.175
+ A 10.0.7.176
+ A 10.0.7.177
+ A 10.0.7.178
+ A 10.0.7.179
+ A 10.0.7.180
+ A 10.0.7.181
+ A 10.0.7.182
+ A 10.0.7.183
+ A 10.0.7.184
+ A 10.0.7.185
+ A 10.0.7.186
+ A 10.0.7.187
+ A 10.0.7.188
+ A 10.0.7.189
+ A 10.0.7.190
+ A 10.0.7.191
+ A 10.0.7.192
+ A 10.0.7.193
+ A 10.0.7.194
+ A 10.0.7.195
+ A 10.0.7.196
+ A 10.0.7.197
+ A 10.0.7.198
+ A 10.0.7.199
+ A 10.0.7.200
+ A 10.0.7.201
+ A 10.0.7.202
+ A 10.0.7.203
+ A 10.0.7.204
+ A 10.0.7.205
+ A 10.0.7.206
+ A 10.0.7.207
+ A 10.0.7.208
+ A 10.0.7.209
+ A 10.0.7.210
+ A 10.0.7.211
+ A 10.0.7.212
+ A 10.0.7.213
+ A 10.0.7.214
+ A 10.0.7.215
+ A 10.0.7.216
+ A 10.0.7.217
+ A 10.0.7.218
+ A 10.0.7.219
+ A 10.0.7.220
+ A 10.0.7.221
+ A 10.0.7.222
+ A 10.0.7.223
+ A 10.0.7.224
+ A 10.0.7.225
+ A 10.0.7.226
+ A 10.0.7.227
+ A 10.0.7.228
+ A 10.0.7.229
+ A 10.0.7.230
+ A 10.0.7.231
+ A 10.0.7.232
+ A 10.0.7.233
+ A 10.0.7.234
+ A 10.0.7.235
+ A 10.0.7.236
+ A 10.0.7.237
+ A 10.0.7.238
+ A 10.0.7.239
+ A 10.0.7.240
+ A 10.0.7.241
+ A 10.0.7.242
+ A 10.0.7.243
+ A 10.0.7.244
+ A 10.0.7.245
+ A 10.0.7.246
+ A 10.0.7.247
+ A 10.0.7.248
+ A 10.0.7.249
+ A 10.0.7.250
+ A 10.0.7.251
+ A 10.0.7.252
+ A 10.0.7.253
+ A 10.0.7.254
+ A 10.0.7.255
+ A 10.0.8.0
+ A 10.0.8.1
+ A 10.0.8.2
+ A 10.0.8.3
+ A 10.0.8.4
+ A 10.0.8.5
+ A 10.0.8.6
+ A 10.0.8.7
+ A 10.0.8.8
+ A 10.0.8.9
+ A 10.0.8.10
+ A 10.0.8.11
+ A 10.0.8.12
+ A 10.0.8.13
+ A 10.0.8.14
+ A 10.0.8.15
+ A 10.0.8.16
+ A 10.0.8.17
+ A 10.0.8.18
+ A 10.0.8.19
+ A 10.0.8.20
+ A 10.0.8.21
+ A 10.0.8.22
+ A 10.0.8.23
+ A 10.0.8.24
+ A 10.0.8.25
+ A 10.0.8.26
+ A 10.0.8.27
+ A 10.0.8.28
+ A 10.0.8.29
+ A 10.0.8.30
+ A 10.0.8.31
+ A 10.0.8.32
+ A 10.0.8.33
+ A 10.0.8.34
+ A 10.0.8.35
+ A 10.0.8.36
+ A 10.0.8.37
+ A 10.0.8.38
+ A 10.0.8.39
+ A 10.0.8.40
+ A 10.0.8.41
+ A 10.0.8.42
+ A 10.0.8.43
+ A 10.0.8.44
+ A 10.0.8.45
+ A 10.0.8.46
+ A 10.0.8.47
+ A 10.0.8.48
+ A 10.0.8.49
+ A 10.0.8.50
+ A 10.0.8.51
+ A 10.0.8.52
+ A 10.0.8.53
+ A 10.0.8.54
+ A 10.0.8.55
+ A 10.0.8.56
+ A 10.0.8.57
+ A 10.0.8.58
+ A 10.0.8.59
+ A 10.0.8.60
+ A 10.0.8.61
+ A 10.0.8.62
+ A 10.0.8.63
+ A 10.0.8.64
+ A 10.0.8.65
+ A 10.0.8.66
+ A 10.0.8.67
+ A 10.0.8.68
+ A 10.0.8.69
+ A 10.0.8.70
+ A 10.0.8.71
+ A 10.0.8.72
+ A 10.0.8.73
+ A 10.0.8.74
+ A 10.0.8.75
+ A 10.0.8.76
+ A 10.0.8.77
+ A 10.0.8.78
+ A 10.0.8.79
+ A 10.0.8.80
+ A 10.0.8.81
+ A 10.0.8.82
+ A 10.0.8.83
+ A 10.0.8.84
+ A 10.0.8.85
+ A 10.0.8.86
+ A 10.0.8.87
+ A 10.0.8.88
+ A 10.0.8.89
+ A 10.0.8.90
+ A 10.0.8.91
+ A 10.0.8.92
+ A 10.0.8.93
+ A 10.0.8.94
+ A 10.0.8.95
+ A 10.0.8.96
+ A 10.0.8.97
+ A 10.0.8.98
+ A 10.0.8.99
+ A 10.0.8.100
+ A 10.0.8.101
+ A 10.0.8.102
+ A 10.0.8.103
+ A 10.0.8.104
+ A 10.0.8.105
+ A 10.0.8.106
+ A 10.0.8.107
+ A 10.0.8.108
+ A 10.0.8.109
+ A 10.0.8.110
+ A 10.0.8.111
+ A 10.0.8.112
+ A 10.0.8.113
+ A 10.0.8.114
+ A 10.0.8.115
+ A 10.0.8.116
+ A 10.0.8.117
+ A 10.0.8.118
+ A 10.0.8.119
+ A 10.0.8.120
+ A 10.0.8.121
+ A 10.0.8.122
+ A 10.0.8.123
+ A 10.0.8.124
+ A 10.0.8.125
+ A 10.0.8.126
+ A 10.0.8.127
+ A 10.0.8.128
+ A 10.0.8.129
+ A 10.0.8.130
+ A 10.0.8.131
+ A 10.0.8.132
+ A 10.0.8.133
+ A 10.0.8.134
+ A 10.0.8.135
+ A 10.0.8.136
+ A 10.0.8.137
+ A 10.0.8.138
+ A 10.0.8.139
+ A 10.0.8.140
+ A 10.0.8.141
+ A 10.0.8.142
+ A 10.0.8.143
+ A 10.0.8.144
+ A 10.0.8.145
+ A 10.0.8.146
+ A 10.0.8.147
+ A 10.0.8.148
+ A 10.0.8.149
+ A 10.0.8.150
+ A 10.0.8.151
+ A 10.0.8.152
+ A 10.0.8.153
+ A 10.0.8.154
+ A 10.0.8.155
+ A 10.0.8.156
+ A 10.0.8.157
+ A 10.0.8.158
+ A 10.0.8.159
+ A 10.0.8.160
+ A 10.0.8.161
+ A 10.0.8.162
+ A 10.0.8.163
+ A 10.0.8.164
+ A 10.0.8.165
+ A 10.0.8.166
+ A 10.0.8.167
+ A 10.0.8.168
+ A 10.0.8.169
+ A 10.0.8.170
+ A 10.0.8.171
+ A 10.0.8.172
+ A 10.0.8.173
+ A 10.0.8.174
+ A 10.0.8.175
+ A 10.0.8.176
+ A 10.0.8.177
+ A 10.0.8.178
+ A 10.0.8.179
+ A 10.0.8.180
+ A 10.0.8.181
+ A 10.0.8.182
+ A 10.0.8.183
+ A 10.0.8.184
+ A 10.0.8.185
+ A 10.0.8.186
+ A 10.0.8.187
+ A 10.0.8.188
+ A 10.0.8.189
+ A 10.0.8.190
+ A 10.0.8.191
+ A 10.0.8.192
+ A 10.0.8.193
+ A 10.0.8.194
+ A 10.0.8.195
+ A 10.0.8.196
+ A 10.0.8.197
+ A 10.0.8.198
+ A 10.0.8.199
+ A 10.0.8.200
+ A 10.0.8.201
+ A 10.0.8.202
+ A 10.0.8.203
+ A 10.0.8.204
+ A 10.0.8.205
+ A 10.0.8.206
+ A 10.0.8.207
+ A 10.0.8.208
+ A 10.0.8.209
+ A 10.0.8.210
+ A 10.0.8.211
+ A 10.0.8.212
+ A 10.0.8.213
+ A 10.0.8.214
+ A 10.0.8.215
+ A 10.0.8.216
+ A 10.0.8.217
+ A 10.0.8.218
+ A 10.0.8.219
+ A 10.0.8.220
+ A 10.0.8.221
+ A 10.0.8.222
+ A 10.0.8.223
+ A 10.0.8.224
+ A 10.0.8.225
+ A 10.0.8.226
+ A 10.0.8.227
+ A 10.0.8.228
+ A 10.0.8.229
+ A 10.0.8.230
+ A 10.0.8.231
+ A 10.0.8.232
+ A 10.0.8.233
+ A 10.0.8.234
+ A 10.0.8.235
+ A 10.0.8.236
+ A 10.0.8.237
+ A 10.0.8.238
+ A 10.0.8.239
+ A 10.0.8.240
+ A 10.0.8.241
+ A 10.0.8.242
+ A 10.0.8.243
+ A 10.0.8.244
+ A 10.0.8.245
+ A 10.0.8.246
+ A 10.0.8.247
+ A 10.0.8.248
+ A 10.0.8.249
+ A 10.0.8.250
+ A 10.0.8.251
+ A 10.0.8.252
+ A 10.0.8.253
+ A 10.0.8.254
+ A 10.0.8.255
+ A 10.0.9.0
+ A 10.0.9.1
+ A 10.0.9.2
+ A 10.0.9.3
+ A 10.0.9.4
+ A 10.0.9.5
+ A 10.0.9.6
+ A 10.0.9.7
+ A 10.0.9.8
+ A 10.0.9.9
+ A 10.0.9.10
+ A 10.0.9.11
+ A 10.0.9.12
+ A 10.0.9.13
+ A 10.0.9.14
+ A 10.0.9.15
+ A 10.0.9.16
+ A 10.0.9.17
+ A 10.0.9.18
+ A 10.0.9.19
+ A 10.0.9.20
+ A 10.0.9.21
+ A 10.0.9.22
+ A 10.0.9.23
+ A 10.0.9.24
+ A 10.0.9.25
+ A 10.0.9.26
+ A 10.0.9.27
+ A 10.0.9.28
+ A 10.0.9.29
+ A 10.0.9.30
+ A 10.0.9.31
+ A 10.0.9.32
+ A 10.0.9.33
+ A 10.0.9.34
+ A 10.0.9.35
+ A 10.0.9.36
+ A 10.0.9.37
+ A 10.0.9.38
+ A 10.0.9.39
+ A 10.0.9.40
+ A 10.0.9.41
+ A 10.0.9.42
+ A 10.0.9.43
+ A 10.0.9.44
+ A 10.0.9.45
+ A 10.0.9.46
+ A 10.0.9.47
+ A 10.0.9.48
+ A 10.0.9.49
+ A 10.0.9.50
+ A 10.0.9.51
+ A 10.0.9.52
+ A 10.0.9.53
+ A 10.0.9.54
+ A 10.0.9.55
+ A 10.0.9.56
+ A 10.0.9.57
+ A 10.0.9.58
+ A 10.0.9.59
+ A 10.0.9.60
+ A 10.0.9.61
+ A 10.0.9.62
+ A 10.0.9.63
+ A 10.0.9.64
+ A 10.0.9.65
+ A 10.0.9.66
+ A 10.0.9.67
+ A 10.0.9.68
+ A 10.0.9.69
+ A 10.0.9.70
+ A 10.0.9.71
+ A 10.0.9.72
+ A 10.0.9.73
+ A 10.0.9.74
+ A 10.0.9.75
+ A 10.0.9.76
+ A 10.0.9.77
+ A 10.0.9.78
+ A 10.0.9.79
+ A 10.0.9.80
+ A 10.0.9.81
+ A 10.0.9.82
+ A 10.0.9.83
+ A 10.0.9.84
+ A 10.0.9.85
+ A 10.0.9.86
+ A 10.0.9.87
+ A 10.0.9.88
+ A 10.0.9.89
+ A 10.0.9.90
+ A 10.0.9.91
+ A 10.0.9.92
+ A 10.0.9.93
+ A 10.0.9.94
+ A 10.0.9.95
+ A 10.0.9.96
+ A 10.0.9.97
+ A 10.0.9.98
+ A 10.0.9.99
+ A 10.0.9.100
+ A 10.0.9.101
+ A 10.0.9.102
+ A 10.0.9.103
+ A 10.0.9.104
+ A 10.0.9.105
+ A 10.0.9.106
+ A 10.0.9.107
+ A 10.0.9.108
+ A 10.0.9.109
+ A 10.0.9.110
+ A 10.0.9.111
+ A 10.0.9.112
+ A 10.0.9.113
+ A 10.0.9.114
+ A 10.0.9.115
+ A 10.0.9.116
+ A 10.0.9.117
+ A 10.0.9.118
+ A 10.0.9.119
+ A 10.0.9.120
+ A 10.0.9.121
+ A 10.0.9.122
+ A 10.0.9.123
+ A 10.0.9.124
+ A 10.0.9.125
+ A 10.0.9.126
+ A 10.0.9.127
+ A 10.0.9.128
+ A 10.0.9.129
+ A 10.0.9.130
+ A 10.0.9.131
+ A 10.0.9.132
+ A 10.0.9.133
+ A 10.0.9.134
+ A 10.0.9.135
+ A 10.0.9.136
+ A 10.0.9.137
+ A 10.0.9.138
+ A 10.0.9.139
+ A 10.0.9.140
+ A 10.0.9.141
+ A 10.0.9.142
+ A 10.0.9.143
+ A 10.0.9.144
+ A 10.0.9.145
+ A 10.0.9.146
+ A 10.0.9.147
+ A 10.0.9.148
+ A 10.0.9.149
+ A 10.0.9.150
+ A 10.0.9.151
+ A 10.0.9.152
+ A 10.0.9.153
+ A 10.0.9.154
+ A 10.0.9.155
+ A 10.0.9.156
+ A 10.0.9.157
+ A 10.0.9.158
+ A 10.0.9.159
+ A 10.0.9.160
+ A 10.0.9.161
+ A 10.0.9.162
+ A 10.0.9.163
+ A 10.0.9.164
+ A 10.0.9.165
+ A 10.0.9.166
+ A 10.0.9.167
+ A 10.0.9.168
+ A 10.0.9.169
+ A 10.0.9.170
+ A 10.0.9.171
+ A 10.0.9.172
+ A 10.0.9.173
+ A 10.0.9.174
+ A 10.0.9.175
+ A 10.0.9.176
+ A 10.0.9.177
+ A 10.0.9.178
+ A 10.0.9.179
+ A 10.0.9.180
+ A 10.0.9.181
+ A 10.0.9.182
+ A 10.0.9.183
+ A 10.0.9.184
+ A 10.0.9.185
+ A 10.0.9.186
+ A 10.0.9.187
+ A 10.0.9.188
+ A 10.0.9.189
+ A 10.0.9.190
+ A 10.0.9.191
+ A 10.0.9.192
+ A 10.0.9.193
+ A 10.0.9.194
+ A 10.0.9.195
+ A 10.0.9.196
+ A 10.0.9.197
+ A 10.0.9.198
+ A 10.0.9.199
+ A 10.0.9.200
+ A 10.0.9.201
+ A 10.0.9.202
+ A 10.0.9.203
+ A 10.0.9.204
+ A 10.0.9.205
+ A 10.0.9.206
+ A 10.0.9.207
+ A 10.0.9.208
+ A 10.0.9.209
+ A 10.0.9.210
+ A 10.0.9.211
+ A 10.0.9.212
+ A 10.0.9.213
+ A 10.0.9.214
+ A 10.0.9.215
+ A 10.0.9.216
+ A 10.0.9.217
+ A 10.0.9.218
+ A 10.0.9.219
+ A 10.0.9.220
+ A 10.0.9.221
+ A 10.0.9.222
+ A 10.0.9.223
+ A 10.0.9.224
+ A 10.0.9.225
+ A 10.0.9.226
+ A 10.0.9.227
+ A 10.0.9.228
+ A 10.0.9.229
+ A 10.0.9.230
+ A 10.0.9.231
+ A 10.0.9.232
+ A 10.0.9.233
+ A 10.0.9.234
+ A 10.0.9.235
+ A 10.0.9.236
+ A 10.0.9.237
+ A 10.0.9.238
+ A 10.0.9.239
+ A 10.0.9.240
+ A 10.0.9.241
+ A 10.0.9.242
+ A 10.0.9.243
+ A 10.0.9.244
+ A 10.0.9.245
+ A 10.0.9.246
+ A 10.0.9.247
+ A 10.0.9.248
+ A 10.0.9.249
+ A 10.0.9.250
+ A 10.0.9.251
+ A 10.0.9.252
+ A 10.0.9.253
+ A 10.0.9.254
+ A 10.0.9.255
+ A 10.0.10.0
+ A 10.0.10.1
+ A 10.0.10.2
+ A 10.0.10.3
+ A 10.0.10.4
+ A 10.0.10.5
+ A 10.0.10.6
+ A 10.0.10.7
+ A 10.0.10.8
+ A 10.0.10.9
+ A 10.0.10.10
+ A 10.0.10.11
+ A 10.0.10.12
+ A 10.0.10.13
+ A 10.0.10.14
+ A 10.0.10.15
+ A 10.0.10.16
+ A 10.0.10.17
+ A 10.0.10.18
+ A 10.0.10.19
+ A 10.0.10.20
+ A 10.0.10.21
+ A 10.0.10.22
+ A 10.0.10.23
+ A 10.0.10.24
+ A 10.0.10.25
+ A 10.0.10.26
+ A 10.0.10.27
+ A 10.0.10.28
+ A 10.0.10.29
+ A 10.0.10.30
+ A 10.0.10.31
+ A 10.0.10.32
+ A 10.0.10.33
+ A 10.0.10.34
+ A 10.0.10.35
+ A 10.0.10.36
+ A 10.0.10.37
+ A 10.0.10.38
+ A 10.0.10.39
+ A 10.0.10.40
+ A 10.0.10.41
+ A 10.0.10.42
+ A 10.0.10.43
+ A 10.0.10.44
+ A 10.0.10.45
+ A 10.0.10.46
+ A 10.0.10.47
+ A 10.0.10.48
+ A 10.0.10.49
+ A 10.0.10.50
+ A 10.0.10.51
+ A 10.0.10.52
+ A 10.0.10.53
+ A 10.0.10.54
+ A 10.0.10.55
+ A 10.0.10.56
+ A 10.0.10.57
+ A 10.0.10.58
+ A 10.0.10.59
+ A 10.0.10.60
+ A 10.0.10.61
+ A 10.0.10.62
+ A 10.0.10.63
+ A 10.0.10.64
+ A 10.0.10.65
+ A 10.0.10.66
+ A 10.0.10.67
+ A 10.0.10.68
+ A 10.0.10.69
+ A 10.0.10.70
+ A 10.0.10.71
+ A 10.0.10.72
+ A 10.0.10.73
+ A 10.0.10.74
+ A 10.0.10.75
+ A 10.0.10.76
+ A 10.0.10.77
+ A 10.0.10.78
+ A 10.0.10.79
+ A 10.0.10.80
+ A 10.0.10.81
+ A 10.0.10.82
+ A 10.0.10.83
+ A 10.0.10.84
+ A 10.0.10.85
+ A 10.0.10.86
+ A 10.0.10.87
+ A 10.0.10.88
+ A 10.0.10.89
+ A 10.0.10.90
+ A 10.0.10.91
+ A 10.0.10.92
+ A 10.0.10.93
+ A 10.0.10.94
+ A 10.0.10.95
+ A 10.0.10.96
+ A 10.0.10.97
+ A 10.0.10.98
+ A 10.0.10.99
+ A 10.0.10.100
+ A 10.0.10.101
+ A 10.0.10.102
+ A 10.0.10.103
+ A 10.0.10.104
+ A 10.0.10.105
+ A 10.0.10.106
+ A 10.0.10.107
+ A 10.0.10.108
+ A 10.0.10.109
+ A 10.0.10.110
+ A 10.0.10.111
+ A 10.0.10.112
+ A 10.0.10.113
+ A 10.0.10.114
+ A 10.0.10.115
+ A 10.0.10.116
+ A 10.0.10.117
+ A 10.0.10.118
+ A 10.0.10.119
+ A 10.0.10.120
+ A 10.0.10.121
+ A 10.0.10.122
+ A 10.0.10.123
+ A 10.0.10.124
+ A 10.0.10.125
+ A 10.0.10.126
+ A 10.0.10.127
+ A 10.0.10.128
+ A 10.0.10.129
+ A 10.0.10.130
+ A 10.0.10.131
+ A 10.0.10.132
+ A 10.0.10.133
+ A 10.0.10.134
+ A 10.0.10.135
+ A 10.0.10.136
+ A 10.0.10.137
+ A 10.0.10.138
+ A 10.0.10.139
+ A 10.0.10.140
+ A 10.0.10.141
+ A 10.0.10.142
+ A 10.0.10.143
+ A 10.0.10.144
+ A 10.0.10.145
+ A 10.0.10.146
+ A 10.0.10.147
+ A 10.0.10.148
+ A 10.0.10.149
+ A 10.0.10.150
+ A 10.0.10.151
+ A 10.0.10.152
+ A 10.0.10.153
+ A 10.0.10.154
+ A 10.0.10.155
+ A 10.0.10.156
+ A 10.0.10.157
+ A 10.0.10.158
+ A 10.0.10.159
+ A 10.0.10.160
+ A 10.0.10.161
+ A 10.0.10.162
+ A 10.0.10.163
+ A 10.0.10.164
+ A 10.0.10.165
+ A 10.0.10.166
+ A 10.0.10.167
+ A 10.0.10.168
+ A 10.0.10.169
+ A 10.0.10.170
+ A 10.0.10.171
+ A 10.0.10.172
+ A 10.0.10.173
+ A 10.0.10.174
+ A 10.0.10.175
+ A 10.0.10.176
+ A 10.0.10.177
+ A 10.0.10.178
+ A 10.0.10.179
+ A 10.0.10.180
+ A 10.0.10.181
+ A 10.0.10.182
+ A 10.0.10.183
+ A 10.0.10.184
+ A 10.0.10.185
+ A 10.0.10.186
+ A 10.0.10.187
+ A 10.0.10.188
+ A 10.0.10.189
+ A 10.0.10.190
+ A 10.0.10.191
+ A 10.0.10.192
+ A 10.0.10.193
+ A 10.0.10.194
+ A 10.0.10.195
+ A 10.0.10.196
+ A 10.0.10.197
+ A 10.0.10.198
+ A 10.0.10.199
+ A 10.0.10.200
+ A 10.0.10.201
+ A 10.0.10.202
+ A 10.0.10.203
+ A 10.0.10.204
+ A 10.0.10.205
+ A 10.0.10.206
+ A 10.0.10.207
+ A 10.0.10.208
+ A 10.0.10.209
+ A 10.0.10.210
+ A 10.0.10.211
+ A 10.0.10.212
+ A 10.0.10.213
+ A 10.0.10.214
+ A 10.0.10.215
+ A 10.0.10.216
+ A 10.0.10.217
+ A 10.0.10.218
+ A 10.0.10.219
+ A 10.0.10.220
+ A 10.0.10.221
+ A 10.0.10.222
+ A 10.0.10.223
+ A 10.0.10.224
+ A 10.0.10.225
+ A 10.0.10.226
+ A 10.0.10.227
+ A 10.0.10.228
+ A 10.0.10.229
+ A 10.0.10.230
+ A 10.0.10.231
+ A 10.0.10.232
+ A 10.0.10.233
+ A 10.0.10.234
+ A 10.0.10.235
+ A 10.0.10.236
+ A 10.0.10.237
+ A 10.0.10.238
+ A 10.0.10.239
+ A 10.0.10.240
+ A 10.0.10.241
+ A 10.0.10.242
+ A 10.0.10.243
+ A 10.0.10.244
+ A 10.0.10.245
+ A 10.0.10.246
+ A 10.0.10.247
+ A 10.0.10.248
+ A 10.0.10.249
+ A 10.0.10.250
+ A 10.0.10.251
+ A 10.0.10.252
+ A 10.0.10.253
+ A 10.0.10.254
+ A 10.0.10.255
+ A 10.0.11.0
+ A 10.0.11.1
+ A 10.0.11.2
+ A 10.0.11.3
+ A 10.0.11.4
+ A 10.0.11.5
+ A 10.0.11.6
+ A 10.0.11.7
+ A 10.0.11.8
+ A 10.0.11.9
+ A 10.0.11.10
+ A 10.0.11.11
+ A 10.0.11.12
+ A 10.0.11.13
+ A 10.0.11.14
+ A 10.0.11.15
+ A 10.0.11.16
+ A 10.0.11.17
+ A 10.0.11.18
+ A 10.0.11.19
+ A 10.0.11.20
+ A 10.0.11.21
+ A 10.0.11.22
+ A 10.0.11.23
+ A 10.0.11.24
+ A 10.0.11.25
+ A 10.0.11.26
+ A 10.0.11.27
+ A 10.0.11.28
+ A 10.0.11.29
+ A 10.0.11.30
+ A 10.0.11.31
+ A 10.0.11.32
+ A 10.0.11.33
+ A 10.0.11.34
+ A 10.0.11.35
+ A 10.0.11.36
+ A 10.0.11.37
+ A 10.0.11.38
+ A 10.0.11.39
+ A 10.0.11.40
+ A 10.0.11.41
+ A 10.0.11.42
+ A 10.0.11.43
+ A 10.0.11.44
+ A 10.0.11.45
+ A 10.0.11.46
+ A 10.0.11.47
+ A 10.0.11.48
+ A 10.0.11.49
+ A 10.0.11.50
+ A 10.0.11.51
+ A 10.0.11.52
+ A 10.0.11.53
+ A 10.0.11.54
+ A 10.0.11.55
+ A 10.0.11.56
+ A 10.0.11.57
+ A 10.0.11.58
+ A 10.0.11.59
+ A 10.0.11.60
+ A 10.0.11.61
+ A 10.0.11.62
+ A 10.0.11.63
+ A 10.0.11.64
+ A 10.0.11.65
+ A 10.0.11.66
+ A 10.0.11.67
+ A 10.0.11.68
+ A 10.0.11.69
+ A 10.0.11.70
+ A 10.0.11.71
+ A 10.0.11.72
+ A 10.0.11.73
+ A 10.0.11.74
+ A 10.0.11.75
+ A 10.0.11.76
+ A 10.0.11.77
+ A 10.0.11.78
+ A 10.0.11.79
+ A 10.0.11.80
+ A 10.0.11.81
+ A 10.0.11.82
+ A 10.0.11.83
+ A 10.0.11.84
+ A 10.0.11.85
+ A 10.0.11.86
+ A 10.0.11.87
+ A 10.0.11.88
+ A 10.0.11.89
+ A 10.0.11.90
+ A 10.0.11.91
+ A 10.0.11.92
+ A 10.0.11.93
+ A 10.0.11.94
+ A 10.0.11.95
+ A 10.0.11.96
+ A 10.0.11.97
+ A 10.0.11.98
+ A 10.0.11.99
+ A 10.0.11.100
+ A 10.0.11.101
+ A 10.0.11.102
+ A 10.0.11.103
+ A 10.0.11.104
+ A 10.0.11.105
+ A 10.0.11.106
+ A 10.0.11.107
+ A 10.0.11.108
+ A 10.0.11.109
+ A 10.0.11.110
+ A 10.0.11.111
+ A 10.0.11.112
+ A 10.0.11.113
+ A 10.0.11.114
+ A 10.0.11.115
+ A 10.0.11.116
+ A 10.0.11.117
+ A 10.0.11.118
+ A 10.0.11.119
+ A 10.0.11.120
+ A 10.0.11.121
+ A 10.0.11.122
+ A 10.0.11.123
+ A 10.0.11.124
+ A 10.0.11.125
+ A 10.0.11.126
+ A 10.0.11.127
+ A 10.0.11.128
+ A 10.0.11.129
+ A 10.0.11.130
+ A 10.0.11.131
+ A 10.0.11.132
+ A 10.0.11.133
+ A 10.0.11.134
+ A 10.0.11.135
+ A 10.0.11.136
+ A 10.0.11.137
+ A 10.0.11.138
+ A 10.0.11.139
+ A 10.0.11.140
+ A 10.0.11.141
+ A 10.0.11.142
+ A 10.0.11.143
+ A 10.0.11.144
+ A 10.0.11.145
+ A 10.0.11.146
+ A 10.0.11.147
+ A 10.0.11.148
+ A 10.0.11.149
+ A 10.0.11.150
+ A 10.0.11.151
+ A 10.0.11.152
+ A 10.0.11.153
+ A 10.0.11.154
+ A 10.0.11.155
+ A 10.0.11.156
+ A 10.0.11.157
+ A 10.0.11.158
+ A 10.0.11.159
+ A 10.0.11.160
+ A 10.0.11.161
+ A 10.0.11.162
+ A 10.0.11.163
+ A 10.0.11.164
+ A 10.0.11.165
+ A 10.0.11.166
+ A 10.0.11.167
+ A 10.0.11.168
+ A 10.0.11.169
+ A 10.0.11.170
+ A 10.0.11.171
+ A 10.0.11.172
+ A 10.0.11.173
+ A 10.0.11.174
+ A 10.0.11.175
+ A 10.0.11.176
+ A 10.0.11.177
+ A 10.0.11.178
+ A 10.0.11.179
+ A 10.0.11.180
+ A 10.0.11.181
+ A 10.0.11.182
+ A 10.0.11.183
+4000 A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+ A 10.0.3.232
+ A 10.0.3.233
+ A 10.0.3.234
+ A 10.0.3.235
+ A 10.0.3.236
+ A 10.0.3.237
+ A 10.0.3.238
+ A 10.0.3.239
+ A 10.0.3.240
+ A 10.0.3.241
+ A 10.0.3.242
+ A 10.0.3.243
+ A 10.0.3.244
+ A 10.0.3.245
+ A 10.0.3.246
+ A 10.0.3.247
+ A 10.0.3.248
+ A 10.0.3.249
+ A 10.0.3.250
+ A 10.0.3.251
+ A 10.0.3.252
+ A 10.0.3.253
+ A 10.0.3.254
+ A 10.0.3.255
+ A 10.0.4.0
+ A 10.0.4.1
+ A 10.0.4.2
+ A 10.0.4.3
+ A 10.0.4.4
+ A 10.0.4.5
+ A 10.0.4.6
+ A 10.0.4.7
+ A 10.0.4.8
+ A 10.0.4.9
+ A 10.0.4.10
+ A 10.0.4.11
+ A 10.0.4.12
+ A 10.0.4.13
+ A 10.0.4.14
+ A 10.0.4.15
+ A 10.0.4.16
+ A 10.0.4.17
+ A 10.0.4.18
+ A 10.0.4.19
+ A 10.0.4.20
+ A 10.0.4.21
+ A 10.0.4.22
+ A 10.0.4.23
+ A 10.0.4.24
+ A 10.0.4.25
+ A 10.0.4.26
+ A 10.0.4.27
+ A 10.0.4.28
+ A 10.0.4.29
+ A 10.0.4.30
+ A 10.0.4.31
+ A 10.0.4.32
+ A 10.0.4.33
+ A 10.0.4.34
+ A 10.0.4.35
+ A 10.0.4.36
+ A 10.0.4.37
+ A 10.0.4.38
+ A 10.0.4.39
+ A 10.0.4.40
+ A 10.0.4.41
+ A 10.0.4.42
+ A 10.0.4.43
+ A 10.0.4.44
+ A 10.0.4.45
+ A 10.0.4.46
+ A 10.0.4.47
+ A 10.0.4.48
+ A 10.0.4.49
+ A 10.0.4.50
+ A 10.0.4.51
+ A 10.0.4.52
+ A 10.0.4.53
+ A 10.0.4.54
+ A 10.0.4.55
+ A 10.0.4.56
+ A 10.0.4.57
+ A 10.0.4.58
+ A 10.0.4.59
+ A 10.0.4.60
+ A 10.0.4.61
+ A 10.0.4.62
+ A 10.0.4.63
+ A 10.0.4.64
+ A 10.0.4.65
+ A 10.0.4.66
+ A 10.0.4.67
+ A 10.0.4.68
+ A 10.0.4.69
+ A 10.0.4.70
+ A 10.0.4.71
+ A 10.0.4.72
+ A 10.0.4.73
+ A 10.0.4.74
+ A 10.0.4.75
+ A 10.0.4.76
+ A 10.0.4.77
+ A 10.0.4.78
+ A 10.0.4.79
+ A 10.0.4.80
+ A 10.0.4.81
+ A 10.0.4.82
+ A 10.0.4.83
+ A 10.0.4.84
+ A 10.0.4.85
+ A 10.0.4.86
+ A 10.0.4.87
+ A 10.0.4.88
+ A 10.0.4.89
+ A 10.0.4.90
+ A 10.0.4.91
+ A 10.0.4.92
+ A 10.0.4.93
+ A 10.0.4.94
+ A 10.0.4.95
+ A 10.0.4.96
+ A 10.0.4.97
+ A 10.0.4.98
+ A 10.0.4.99
+ A 10.0.4.100
+ A 10.0.4.101
+ A 10.0.4.102
+ A 10.0.4.103
+ A 10.0.4.104
+ A 10.0.4.105
+ A 10.0.4.106
+ A 10.0.4.107
+ A 10.0.4.108
+ A 10.0.4.109
+ A 10.0.4.110
+ A 10.0.4.111
+ A 10.0.4.112
+ A 10.0.4.113
+ A 10.0.4.114
+ A 10.0.4.115
+ A 10.0.4.116
+ A 10.0.4.117
+ A 10.0.4.118
+ A 10.0.4.119
+ A 10.0.4.120
+ A 10.0.4.121
+ A 10.0.4.122
+ A 10.0.4.123
+ A 10.0.4.124
+ A 10.0.4.125
+ A 10.0.4.126
+ A 10.0.4.127
+ A 10.0.4.128
+ A 10.0.4.129
+ A 10.0.4.130
+ A 10.0.4.131
+ A 10.0.4.132
+ A 10.0.4.133
+ A 10.0.4.134
+ A 10.0.4.135
+ A 10.0.4.136
+ A 10.0.4.137
+ A 10.0.4.138
+ A 10.0.4.139
+ A 10.0.4.140
+ A 10.0.4.141
+ A 10.0.4.142
+ A 10.0.4.143
+ A 10.0.4.144
+ A 10.0.4.145
+ A 10.0.4.146
+ A 10.0.4.147
+ A 10.0.4.148
+ A 10.0.4.149
+ A 10.0.4.150
+ A 10.0.4.151
+ A 10.0.4.152
+ A 10.0.4.153
+ A 10.0.4.154
+ A 10.0.4.155
+ A 10.0.4.156
+ A 10.0.4.157
+ A 10.0.4.158
+ A 10.0.4.159
+ A 10.0.4.160
+ A 10.0.4.161
+ A 10.0.4.162
+ A 10.0.4.163
+ A 10.0.4.164
+ A 10.0.4.165
+ A 10.0.4.166
+ A 10.0.4.167
+ A 10.0.4.168
+ A 10.0.4.169
+ A 10.0.4.170
+ A 10.0.4.171
+ A 10.0.4.172
+ A 10.0.4.173
+ A 10.0.4.174
+ A 10.0.4.175
+ A 10.0.4.176
+ A 10.0.4.177
+ A 10.0.4.178
+ A 10.0.4.179
+ A 10.0.4.180
+ A 10.0.4.181
+ A 10.0.4.182
+ A 10.0.4.183
+ A 10.0.4.184
+ A 10.0.4.185
+ A 10.0.4.186
+ A 10.0.4.187
+ A 10.0.4.188
+ A 10.0.4.189
+ A 10.0.4.190
+ A 10.0.4.191
+ A 10.0.4.192
+ A 10.0.4.193
+ A 10.0.4.194
+ A 10.0.4.195
+ A 10.0.4.196
+ A 10.0.4.197
+ A 10.0.4.198
+ A 10.0.4.199
+ A 10.0.4.200
+ A 10.0.4.201
+ A 10.0.4.202
+ A 10.0.4.203
+ A 10.0.4.204
+ A 10.0.4.205
+ A 10.0.4.206
+ A 10.0.4.207
+ A 10.0.4.208
+ A 10.0.4.209
+ A 10.0.4.210
+ A 10.0.4.211
+ A 10.0.4.212
+ A 10.0.4.213
+ A 10.0.4.214
+ A 10.0.4.215
+ A 10.0.4.216
+ A 10.0.4.217
+ A 10.0.4.218
+ A 10.0.4.219
+ A 10.0.4.220
+ A 10.0.4.221
+ A 10.0.4.222
+ A 10.0.4.223
+ A 10.0.4.224
+ A 10.0.4.225
+ A 10.0.4.226
+ A 10.0.4.227
+ A 10.0.4.228
+ A 10.0.4.229
+ A 10.0.4.230
+ A 10.0.4.231
+ A 10.0.4.232
+ A 10.0.4.233
+ A 10.0.4.234
+ A 10.0.4.235
+ A 10.0.4.236
+ A 10.0.4.237
+ A 10.0.4.238
+ A 10.0.4.239
+ A 10.0.4.240
+ A 10.0.4.241
+ A 10.0.4.242
+ A 10.0.4.243
+ A 10.0.4.244
+ A 10.0.4.245
+ A 10.0.4.246
+ A 10.0.4.247
+ A 10.0.4.248
+ A 10.0.4.249
+ A 10.0.4.250
+ A 10.0.4.251
+ A 10.0.4.252
+ A 10.0.4.253
+ A 10.0.4.254
+ A 10.0.4.255
+ A 10.0.5.0
+ A 10.0.5.1
+ A 10.0.5.2
+ A 10.0.5.3
+ A 10.0.5.4
+ A 10.0.5.5
+ A 10.0.5.6
+ A 10.0.5.7
+ A 10.0.5.8
+ A 10.0.5.9
+ A 10.0.5.10
+ A 10.0.5.11
+ A 10.0.5.12
+ A 10.0.5.13
+ A 10.0.5.14
+ A 10.0.5.15
+ A 10.0.5.16
+ A 10.0.5.17
+ A 10.0.5.18
+ A 10.0.5.19
+ A 10.0.5.20
+ A 10.0.5.21
+ A 10.0.5.22
+ A 10.0.5.23
+ A 10.0.5.24
+ A 10.0.5.25
+ A 10.0.5.26
+ A 10.0.5.27
+ A 10.0.5.28
+ A 10.0.5.29
+ A 10.0.5.30
+ A 10.0.5.31
+ A 10.0.5.32
+ A 10.0.5.33
+ A 10.0.5.34
+ A 10.0.5.35
+ A 10.0.5.36
+ A 10.0.5.37
+ A 10.0.5.38
+ A 10.0.5.39
+ A 10.0.5.40
+ A 10.0.5.41
+ A 10.0.5.42
+ A 10.0.5.43
+ A 10.0.5.44
+ A 10.0.5.45
+ A 10.0.5.46
+ A 10.0.5.47
+ A 10.0.5.48
+ A 10.0.5.49
+ A 10.0.5.50
+ A 10.0.5.51
+ A 10.0.5.52
+ A 10.0.5.53
+ A 10.0.5.54
+ A 10.0.5.55
+ A 10.0.5.56
+ A 10.0.5.57
+ A 10.0.5.58
+ A 10.0.5.59
+ A 10.0.5.60
+ A 10.0.5.61
+ A 10.0.5.62
+ A 10.0.5.63
+ A 10.0.5.64
+ A 10.0.5.65
+ A 10.0.5.66
+ A 10.0.5.67
+ A 10.0.5.68
+ A 10.0.5.69
+ A 10.0.5.70
+ A 10.0.5.71
+ A 10.0.5.72
+ A 10.0.5.73
+ A 10.0.5.74
+ A 10.0.5.75
+ A 10.0.5.76
+ A 10.0.5.77
+ A 10.0.5.78
+ A 10.0.5.79
+ A 10.0.5.80
+ A 10.0.5.81
+ A 10.0.5.82
+ A 10.0.5.83
+ A 10.0.5.84
+ A 10.0.5.85
+ A 10.0.5.86
+ A 10.0.5.87
+ A 10.0.5.88
+ A 10.0.5.89
+ A 10.0.5.90
+ A 10.0.5.91
+ A 10.0.5.92
+ A 10.0.5.93
+ A 10.0.5.94
+ A 10.0.5.95
+ A 10.0.5.96
+ A 10.0.5.97
+ A 10.0.5.98
+ A 10.0.5.99
+ A 10.0.5.100
+ A 10.0.5.101
+ A 10.0.5.102
+ A 10.0.5.103
+ A 10.0.5.104
+ A 10.0.5.105
+ A 10.0.5.106
+ A 10.0.5.107
+ A 10.0.5.108
+ A 10.0.5.109
+ A 10.0.5.110
+ A 10.0.5.111
+ A 10.0.5.112
+ A 10.0.5.113
+ A 10.0.5.114
+ A 10.0.5.115
+ A 10.0.5.116
+ A 10.0.5.117
+ A 10.0.5.118
+ A 10.0.5.119
+ A 10.0.5.120
+ A 10.0.5.121
+ A 10.0.5.122
+ A 10.0.5.123
+ A 10.0.5.124
+ A 10.0.5.125
+ A 10.0.5.126
+ A 10.0.5.127
+ A 10.0.5.128
+ A 10.0.5.129
+ A 10.0.5.130
+ A 10.0.5.131
+ A 10.0.5.132
+ A 10.0.5.133
+ A 10.0.5.134
+ A 10.0.5.135
+ A 10.0.5.136
+ A 10.0.5.137
+ A 10.0.5.138
+ A 10.0.5.139
+ A 10.0.5.140
+ A 10.0.5.141
+ A 10.0.5.142
+ A 10.0.5.143
+ A 10.0.5.144
+ A 10.0.5.145
+ A 10.0.5.146
+ A 10.0.5.147
+ A 10.0.5.148
+ A 10.0.5.149
+ A 10.0.5.150
+ A 10.0.5.151
+ A 10.0.5.152
+ A 10.0.5.153
+ A 10.0.5.154
+ A 10.0.5.155
+ A 10.0.5.156
+ A 10.0.5.157
+ A 10.0.5.158
+ A 10.0.5.159
+ A 10.0.5.160
+ A 10.0.5.161
+ A 10.0.5.162
+ A 10.0.5.163
+ A 10.0.5.164
+ A 10.0.5.165
+ A 10.0.5.166
+ A 10.0.5.167
+ A 10.0.5.168
+ A 10.0.5.169
+ A 10.0.5.170
+ A 10.0.5.171
+ A 10.0.5.172
+ A 10.0.5.173
+ A 10.0.5.174
+ A 10.0.5.175
+ A 10.0.5.176
+ A 10.0.5.177
+ A 10.0.5.178
+ A 10.0.5.179
+ A 10.0.5.180
+ A 10.0.5.181
+ A 10.0.5.182
+ A 10.0.5.183
+ A 10.0.5.184
+ A 10.0.5.185
+ A 10.0.5.186
+ A 10.0.5.187
+ A 10.0.5.188
+ A 10.0.5.189
+ A 10.0.5.190
+ A 10.0.5.191
+ A 10.0.5.192
+ A 10.0.5.193
+ A 10.0.5.194
+ A 10.0.5.195
+ A 10.0.5.196
+ A 10.0.5.197
+ A 10.0.5.198
+ A 10.0.5.199
+ A 10.0.5.200
+ A 10.0.5.201
+ A 10.0.5.202
+ A 10.0.5.203
+ A 10.0.5.204
+ A 10.0.5.205
+ A 10.0.5.206
+ A 10.0.5.207
+ A 10.0.5.208
+ A 10.0.5.209
+ A 10.0.5.210
+ A 10.0.5.211
+ A 10.0.5.212
+ A 10.0.5.213
+ A 10.0.5.214
+ A 10.0.5.215
+ A 10.0.5.216
+ A 10.0.5.217
+ A 10.0.5.218
+ A 10.0.5.219
+ A 10.0.5.220
+ A 10.0.5.221
+ A 10.0.5.222
+ A 10.0.5.223
+ A 10.0.5.224
+ A 10.0.5.225
+ A 10.0.5.226
+ A 10.0.5.227
+ A 10.0.5.228
+ A 10.0.5.229
+ A 10.0.5.230
+ A 10.0.5.231
+ A 10.0.5.232
+ A 10.0.5.233
+ A 10.0.5.234
+ A 10.0.5.235
+ A 10.0.5.236
+ A 10.0.5.237
+ A 10.0.5.238
+ A 10.0.5.239
+ A 10.0.5.240
+ A 10.0.5.241
+ A 10.0.5.242
+ A 10.0.5.243
+ A 10.0.5.244
+ A 10.0.5.245
+ A 10.0.5.246
+ A 10.0.5.247
+ A 10.0.5.248
+ A 10.0.5.249
+ A 10.0.5.250
+ A 10.0.5.251
+ A 10.0.5.252
+ A 10.0.5.253
+ A 10.0.5.254
+ A 10.0.5.255
+ A 10.0.6.0
+ A 10.0.6.1
+ A 10.0.6.2
+ A 10.0.6.3
+ A 10.0.6.4
+ A 10.0.6.5
+ A 10.0.6.6
+ A 10.0.6.7
+ A 10.0.6.8
+ A 10.0.6.9
+ A 10.0.6.10
+ A 10.0.6.11
+ A 10.0.6.12
+ A 10.0.6.13
+ A 10.0.6.14
+ A 10.0.6.15
+ A 10.0.6.16
+ A 10.0.6.17
+ A 10.0.6.18
+ A 10.0.6.19
+ A 10.0.6.20
+ A 10.0.6.21
+ A 10.0.6.22
+ A 10.0.6.23
+ A 10.0.6.24
+ A 10.0.6.25
+ A 10.0.6.26
+ A 10.0.6.27
+ A 10.0.6.28
+ A 10.0.6.29
+ A 10.0.6.30
+ A 10.0.6.31
+ A 10.0.6.32
+ A 10.0.6.33
+ A 10.0.6.34
+ A 10.0.6.35
+ A 10.0.6.36
+ A 10.0.6.37
+ A 10.0.6.38
+ A 10.0.6.39
+ A 10.0.6.40
+ A 10.0.6.41
+ A 10.0.6.42
+ A 10.0.6.43
+ A 10.0.6.44
+ A 10.0.6.45
+ A 10.0.6.46
+ A 10.0.6.47
+ A 10.0.6.48
+ A 10.0.6.49
+ A 10.0.6.50
+ A 10.0.6.51
+ A 10.0.6.52
+ A 10.0.6.53
+ A 10.0.6.54
+ A 10.0.6.55
+ A 10.0.6.56
+ A 10.0.6.57
+ A 10.0.6.58
+ A 10.0.6.59
+ A 10.0.6.60
+ A 10.0.6.61
+ A 10.0.6.62
+ A 10.0.6.63
+ A 10.0.6.64
+ A 10.0.6.65
+ A 10.0.6.66
+ A 10.0.6.67
+ A 10.0.6.68
+ A 10.0.6.69
+ A 10.0.6.70
+ A 10.0.6.71
+ A 10.0.6.72
+ A 10.0.6.73
+ A 10.0.6.74
+ A 10.0.6.75
+ A 10.0.6.76
+ A 10.0.6.77
+ A 10.0.6.78
+ A 10.0.6.79
+ A 10.0.6.80
+ A 10.0.6.81
+ A 10.0.6.82
+ A 10.0.6.83
+ A 10.0.6.84
+ A 10.0.6.85
+ A 10.0.6.86
+ A 10.0.6.87
+ A 10.0.6.88
+ A 10.0.6.89
+ A 10.0.6.90
+ A 10.0.6.91
+ A 10.0.6.92
+ A 10.0.6.93
+ A 10.0.6.94
+ A 10.0.6.95
+ A 10.0.6.96
+ A 10.0.6.97
+ A 10.0.6.98
+ A 10.0.6.99
+ A 10.0.6.100
+ A 10.0.6.101
+ A 10.0.6.102
+ A 10.0.6.103
+ A 10.0.6.104
+ A 10.0.6.105
+ A 10.0.6.106
+ A 10.0.6.107
+ A 10.0.6.108
+ A 10.0.6.109
+ A 10.0.6.110
+ A 10.0.6.111
+ A 10.0.6.112
+ A 10.0.6.113
+ A 10.0.6.114
+ A 10.0.6.115
+ A 10.0.6.116
+ A 10.0.6.117
+ A 10.0.6.118
+ A 10.0.6.119
+ A 10.0.6.120
+ A 10.0.6.121
+ A 10.0.6.122
+ A 10.0.6.123
+ A 10.0.6.124
+ A 10.0.6.125
+ A 10.0.6.126
+ A 10.0.6.127
+ A 10.0.6.128
+ A 10.0.6.129
+ A 10.0.6.130
+ A 10.0.6.131
+ A 10.0.6.132
+ A 10.0.6.133
+ A 10.0.6.134
+ A 10.0.6.135
+ A 10.0.6.136
+ A 10.0.6.137
+ A 10.0.6.138
+ A 10.0.6.139
+ A 10.0.6.140
+ A 10.0.6.141
+ A 10.0.6.142
+ A 10.0.6.143
+ A 10.0.6.144
+ A 10.0.6.145
+ A 10.0.6.146
+ A 10.0.6.147
+ A 10.0.6.148
+ A 10.0.6.149
+ A 10.0.6.150
+ A 10.0.6.151
+ A 10.0.6.152
+ A 10.0.6.153
+ A 10.0.6.154
+ A 10.0.6.155
+ A 10.0.6.156
+ A 10.0.6.157
+ A 10.0.6.158
+ A 10.0.6.159
+ A 10.0.6.160
+ A 10.0.6.161
+ A 10.0.6.162
+ A 10.0.6.163
+ A 10.0.6.164
+ A 10.0.6.165
+ A 10.0.6.166
+ A 10.0.6.167
+ A 10.0.6.168
+ A 10.0.6.169
+ A 10.0.6.170
+ A 10.0.6.171
+ A 10.0.6.172
+ A 10.0.6.173
+ A 10.0.6.174
+ A 10.0.6.175
+ A 10.0.6.176
+ A 10.0.6.177
+ A 10.0.6.178
+ A 10.0.6.179
+ A 10.0.6.180
+ A 10.0.6.181
+ A 10.0.6.182
+ A 10.0.6.183
+ A 10.0.6.184
+ A 10.0.6.185
+ A 10.0.6.186
+ A 10.0.6.187
+ A 10.0.6.188
+ A 10.0.6.189
+ A 10.0.6.190
+ A 10.0.6.191
+ A 10.0.6.192
+ A 10.0.6.193
+ A 10.0.6.194
+ A 10.0.6.195
+ A 10.0.6.196
+ A 10.0.6.197
+ A 10.0.6.198
+ A 10.0.6.199
+ A 10.0.6.200
+ A 10.0.6.201
+ A 10.0.6.202
+ A 10.0.6.203
+ A 10.0.6.204
+ A 10.0.6.205
+ A 10.0.6.206
+ A 10.0.6.207
+ A 10.0.6.208
+ A 10.0.6.209
+ A 10.0.6.210
+ A 10.0.6.211
+ A 10.0.6.212
+ A 10.0.6.213
+ A 10.0.6.214
+ A 10.0.6.215
+ A 10.0.6.216
+ A 10.0.6.217
+ A 10.0.6.218
+ A 10.0.6.219
+ A 10.0.6.220
+ A 10.0.6.221
+ A 10.0.6.222
+ A 10.0.6.223
+ A 10.0.6.224
+ A 10.0.6.225
+ A 10.0.6.226
+ A 10.0.6.227
+ A 10.0.6.228
+ A 10.0.6.229
+ A 10.0.6.230
+ A 10.0.6.231
+ A 10.0.6.232
+ A 10.0.6.233
+ A 10.0.6.234
+ A 10.0.6.235
+ A 10.0.6.236
+ A 10.0.6.237
+ A 10.0.6.238
+ A 10.0.6.239
+ A 10.0.6.240
+ A 10.0.6.241
+ A 10.0.6.242
+ A 10.0.6.243
+ A 10.0.6.244
+ A 10.0.6.245
+ A 10.0.6.246
+ A 10.0.6.247
+ A 10.0.6.248
+ A 10.0.6.249
+ A 10.0.6.250
+ A 10.0.6.251
+ A 10.0.6.252
+ A 10.0.6.253
+ A 10.0.6.254
+ A 10.0.6.255
+ A 10.0.7.0
+ A 10.0.7.1
+ A 10.0.7.2
+ A 10.0.7.3
+ A 10.0.7.4
+ A 10.0.7.5
+ A 10.0.7.6
+ A 10.0.7.7
+ A 10.0.7.8
+ A 10.0.7.9
+ A 10.0.7.10
+ A 10.0.7.11
+ A 10.0.7.12
+ A 10.0.7.13
+ A 10.0.7.14
+ A 10.0.7.15
+ A 10.0.7.16
+ A 10.0.7.17
+ A 10.0.7.18
+ A 10.0.7.19
+ A 10.0.7.20
+ A 10.0.7.21
+ A 10.0.7.22
+ A 10.0.7.23
+ A 10.0.7.24
+ A 10.0.7.25
+ A 10.0.7.26
+ A 10.0.7.27
+ A 10.0.7.28
+ A 10.0.7.29
+ A 10.0.7.30
+ A 10.0.7.31
+ A 10.0.7.32
+ A 10.0.7.33
+ A 10.0.7.34
+ A 10.0.7.35
+ A 10.0.7.36
+ A 10.0.7.37
+ A 10.0.7.38
+ A 10.0.7.39
+ A 10.0.7.40
+ A 10.0.7.41
+ A 10.0.7.42
+ A 10.0.7.43
+ A 10.0.7.44
+ A 10.0.7.45
+ A 10.0.7.46
+ A 10.0.7.47
+ A 10.0.7.48
+ A 10.0.7.49
+ A 10.0.7.50
+ A 10.0.7.51
+ A 10.0.7.52
+ A 10.0.7.53
+ A 10.0.7.54
+ A 10.0.7.55
+ A 10.0.7.56
+ A 10.0.7.57
+ A 10.0.7.58
+ A 10.0.7.59
+ A 10.0.7.60
+ A 10.0.7.61
+ A 10.0.7.62
+ A 10.0.7.63
+ A 10.0.7.64
+ A 10.0.7.65
+ A 10.0.7.66
+ A 10.0.7.67
+ A 10.0.7.68
+ A 10.0.7.69
+ A 10.0.7.70
+ A 10.0.7.71
+ A 10.0.7.72
+ A 10.0.7.73
+ A 10.0.7.74
+ A 10.0.7.75
+ A 10.0.7.76
+ A 10.0.7.77
+ A 10.0.7.78
+ A 10.0.7.79
+ A 10.0.7.80
+ A 10.0.7.81
+ A 10.0.7.82
+ A 10.0.7.83
+ A 10.0.7.84
+ A 10.0.7.85
+ A 10.0.7.86
+ A 10.0.7.87
+ A 10.0.7.88
+ A 10.0.7.89
+ A 10.0.7.90
+ A 10.0.7.91
+ A 10.0.7.92
+ A 10.0.7.93
+ A 10.0.7.94
+ A 10.0.7.95
+ A 10.0.7.96
+ A 10.0.7.97
+ A 10.0.7.98
+ A 10.0.7.99
+ A 10.0.7.100
+ A 10.0.7.101
+ A 10.0.7.102
+ A 10.0.7.103
+ A 10.0.7.104
+ A 10.0.7.105
+ A 10.0.7.106
+ A 10.0.7.107
+ A 10.0.7.108
+ A 10.0.7.109
+ A 10.0.7.110
+ A 10.0.7.111
+ A 10.0.7.112
+ A 10.0.7.113
+ A 10.0.7.114
+ A 10.0.7.115
+ A 10.0.7.116
+ A 10.0.7.117
+ A 10.0.7.118
+ A 10.0.7.119
+ A 10.0.7.120
+ A 10.0.7.121
+ A 10.0.7.122
+ A 10.0.7.123
+ A 10.0.7.124
+ A 10.0.7.125
+ A 10.0.7.126
+ A 10.0.7.127
+ A 10.0.7.128
+ A 10.0.7.129
+ A 10.0.7.130
+ A 10.0.7.131
+ A 10.0.7.132
+ A 10.0.7.133
+ A 10.0.7.134
+ A 10.0.7.135
+ A 10.0.7.136
+ A 10.0.7.137
+ A 10.0.7.138
+ A 10.0.7.139
+ A 10.0.7.140
+ A 10.0.7.141
+ A 10.0.7.142
+ A 10.0.7.143
+ A 10.0.7.144
+ A 10.0.7.145
+ A 10.0.7.146
+ A 10.0.7.147
+ A 10.0.7.148
+ A 10.0.7.149
+ A 10.0.7.150
+ A 10.0.7.151
+ A 10.0.7.152
+ A 10.0.7.153
+ A 10.0.7.154
+ A 10.0.7.155
+ A 10.0.7.156
+ A 10.0.7.157
+ A 10.0.7.158
+ A 10.0.7.159
+ A 10.0.7.160
+ A 10.0.7.161
+ A 10.0.7.162
+ A 10.0.7.163
+ A 10.0.7.164
+ A 10.0.7.165
+ A 10.0.7.166
+ A 10.0.7.167
+ A 10.0.7.168
+ A 10.0.7.169
+ A 10.0.7.170
+ A 10.0.7.171
+ A 10.0.7.172
+ A 10.0.7.173
+ A 10.0.7.174
+ A 10.0.7.175
+ A 10.0.7.176
+ A 10.0.7.177
+ A 10.0.7.178
+ A 10.0.7.179
+ A 10.0.7.180
+ A 10.0.7.181
+ A 10.0.7.182
+ A 10.0.7.183
+ A 10.0.7.184
+ A 10.0.7.185
+ A 10.0.7.186
+ A 10.0.7.187
+ A 10.0.7.188
+ A 10.0.7.189
+ A 10.0.7.190
+ A 10.0.7.191
+ A 10.0.7.192
+ A 10.0.7.193
+ A 10.0.7.194
+ A 10.0.7.195
+ A 10.0.7.196
+ A 10.0.7.197
+ A 10.0.7.198
+ A 10.0.7.199
+ A 10.0.7.200
+ A 10.0.7.201
+ A 10.0.7.202
+ A 10.0.7.203
+ A 10.0.7.204
+ A 10.0.7.205
+ A 10.0.7.206
+ A 10.0.7.207
+ A 10.0.7.208
+ A 10.0.7.209
+ A 10.0.7.210
+ A 10.0.7.211
+ A 10.0.7.212
+ A 10.0.7.213
+ A 10.0.7.214
+ A 10.0.7.215
+ A 10.0.7.216
+ A 10.0.7.217
+ A 10.0.7.218
+ A 10.0.7.219
+ A 10.0.7.220
+ A 10.0.7.221
+ A 10.0.7.222
+ A 10.0.7.223
+ A 10.0.7.224
+ A 10.0.7.225
+ A 10.0.7.226
+ A 10.0.7.227
+ A 10.0.7.228
+ A 10.0.7.229
+ A 10.0.7.230
+ A 10.0.7.231
+ A 10.0.7.232
+ A 10.0.7.233
+ A 10.0.7.234
+ A 10.0.7.235
+ A 10.0.7.236
+ A 10.0.7.237
+ A 10.0.7.238
+ A 10.0.7.239
+ A 10.0.7.240
+ A 10.0.7.241
+ A 10.0.7.242
+ A 10.0.7.243
+ A 10.0.7.244
+ A 10.0.7.245
+ A 10.0.7.246
+ A 10.0.7.247
+ A 10.0.7.248
+ A 10.0.7.249
+ A 10.0.7.250
+ A 10.0.7.251
+ A 10.0.7.252
+ A 10.0.7.253
+ A 10.0.7.254
+ A 10.0.7.255
+ A 10.0.8.0
+ A 10.0.8.1
+ A 10.0.8.2
+ A 10.0.8.3
+ A 10.0.8.4
+ A 10.0.8.5
+ A 10.0.8.6
+ A 10.0.8.7
+ A 10.0.8.8
+ A 10.0.8.9
+ A 10.0.8.10
+ A 10.0.8.11
+ A 10.0.8.12
+ A 10.0.8.13
+ A 10.0.8.14
+ A 10.0.8.15
+ A 10.0.8.16
+ A 10.0.8.17
+ A 10.0.8.18
+ A 10.0.8.19
+ A 10.0.8.20
+ A 10.0.8.21
+ A 10.0.8.22
+ A 10.0.8.23
+ A 10.0.8.24
+ A 10.0.8.25
+ A 10.0.8.26
+ A 10.0.8.27
+ A 10.0.8.28
+ A 10.0.8.29
+ A 10.0.8.30
+ A 10.0.8.31
+ A 10.0.8.32
+ A 10.0.8.33
+ A 10.0.8.34
+ A 10.0.8.35
+ A 10.0.8.36
+ A 10.0.8.37
+ A 10.0.8.38
+ A 10.0.8.39
+ A 10.0.8.40
+ A 10.0.8.41
+ A 10.0.8.42
+ A 10.0.8.43
+ A 10.0.8.44
+ A 10.0.8.45
+ A 10.0.8.46
+ A 10.0.8.47
+ A 10.0.8.48
+ A 10.0.8.49
+ A 10.0.8.50
+ A 10.0.8.51
+ A 10.0.8.52
+ A 10.0.8.53
+ A 10.0.8.54
+ A 10.0.8.55
+ A 10.0.8.56
+ A 10.0.8.57
+ A 10.0.8.58
+ A 10.0.8.59
+ A 10.0.8.60
+ A 10.0.8.61
+ A 10.0.8.62
+ A 10.0.8.63
+ A 10.0.8.64
+ A 10.0.8.65
+ A 10.0.8.66
+ A 10.0.8.67
+ A 10.0.8.68
+ A 10.0.8.69
+ A 10.0.8.70
+ A 10.0.8.71
+ A 10.0.8.72
+ A 10.0.8.73
+ A 10.0.8.74
+ A 10.0.8.75
+ A 10.0.8.76
+ A 10.0.8.77
+ A 10.0.8.78
+ A 10.0.8.79
+ A 10.0.8.80
+ A 10.0.8.81
+ A 10.0.8.82
+ A 10.0.8.83
+ A 10.0.8.84
+ A 10.0.8.85
+ A 10.0.8.86
+ A 10.0.8.87
+ A 10.0.8.88
+ A 10.0.8.89
+ A 10.0.8.90
+ A 10.0.8.91
+ A 10.0.8.92
+ A 10.0.8.93
+ A 10.0.8.94
+ A 10.0.8.95
+ A 10.0.8.96
+ A 10.0.8.97
+ A 10.0.8.98
+ A 10.0.8.99
+ A 10.0.8.100
+ A 10.0.8.101
+ A 10.0.8.102
+ A 10.0.8.103
+ A 10.0.8.104
+ A 10.0.8.105
+ A 10.0.8.106
+ A 10.0.8.107
+ A 10.0.8.108
+ A 10.0.8.109
+ A 10.0.8.110
+ A 10.0.8.111
+ A 10.0.8.112
+ A 10.0.8.113
+ A 10.0.8.114
+ A 10.0.8.115
+ A 10.0.8.116
+ A 10.0.8.117
+ A 10.0.8.118
+ A 10.0.8.119
+ A 10.0.8.120
+ A 10.0.8.121
+ A 10.0.8.122
+ A 10.0.8.123
+ A 10.0.8.124
+ A 10.0.8.125
+ A 10.0.8.126
+ A 10.0.8.127
+ A 10.0.8.128
+ A 10.0.8.129
+ A 10.0.8.130
+ A 10.0.8.131
+ A 10.0.8.132
+ A 10.0.8.133
+ A 10.0.8.134
+ A 10.0.8.135
+ A 10.0.8.136
+ A 10.0.8.137
+ A 10.0.8.138
+ A 10.0.8.139
+ A 10.0.8.140
+ A 10.0.8.141
+ A 10.0.8.142
+ A 10.0.8.143
+ A 10.0.8.144
+ A 10.0.8.145
+ A 10.0.8.146
+ A 10.0.8.147
+ A 10.0.8.148
+ A 10.0.8.149
+ A 10.0.8.150
+ A 10.0.8.151
+ A 10.0.8.152
+ A 10.0.8.153
+ A 10.0.8.154
+ A 10.0.8.155
+ A 10.0.8.156
+ A 10.0.8.157
+ A 10.0.8.158
+ A 10.0.8.159
+ A 10.0.8.160
+ A 10.0.8.161
+ A 10.0.8.162
+ A 10.0.8.163
+ A 10.0.8.164
+ A 10.0.8.165
+ A 10.0.8.166
+ A 10.0.8.167
+ A 10.0.8.168
+ A 10.0.8.169
+ A 10.0.8.170
+ A 10.0.8.171
+ A 10.0.8.172
+ A 10.0.8.173
+ A 10.0.8.174
+ A 10.0.8.175
+ A 10.0.8.176
+ A 10.0.8.177
+ A 10.0.8.178
+ A 10.0.8.179
+ A 10.0.8.180
+ A 10.0.8.181
+ A 10.0.8.182
+ A 10.0.8.183
+ A 10.0.8.184
+ A 10.0.8.185
+ A 10.0.8.186
+ A 10.0.8.187
+ A 10.0.8.188
+ A 10.0.8.189
+ A 10.0.8.190
+ A 10.0.8.191
+ A 10.0.8.192
+ A 10.0.8.193
+ A 10.0.8.194
+ A 10.0.8.195
+ A 10.0.8.196
+ A 10.0.8.197
+ A 10.0.8.198
+ A 10.0.8.199
+ A 10.0.8.200
+ A 10.0.8.201
+ A 10.0.8.202
+ A 10.0.8.203
+ A 10.0.8.204
+ A 10.0.8.205
+ A 10.0.8.206
+ A 10.0.8.207
+ A 10.0.8.208
+ A 10.0.8.209
+ A 10.0.8.210
+ A 10.0.8.211
+ A 10.0.8.212
+ A 10.0.8.213
+ A 10.0.8.214
+ A 10.0.8.215
+ A 10.0.8.216
+ A 10.0.8.217
+ A 10.0.8.218
+ A 10.0.8.219
+ A 10.0.8.220
+ A 10.0.8.221
+ A 10.0.8.222
+ A 10.0.8.223
+ A 10.0.8.224
+ A 10.0.8.225
+ A 10.0.8.226
+ A 10.0.8.227
+ A 10.0.8.228
+ A 10.0.8.229
+ A 10.0.8.230
+ A 10.0.8.231
+ A 10.0.8.232
+ A 10.0.8.233
+ A 10.0.8.234
+ A 10.0.8.235
+ A 10.0.8.236
+ A 10.0.8.237
+ A 10.0.8.238
+ A 10.0.8.239
+ A 10.0.8.240
+ A 10.0.8.241
+ A 10.0.8.242
+ A 10.0.8.243
+ A 10.0.8.244
+ A 10.0.8.245
+ A 10.0.8.246
+ A 10.0.8.247
+ A 10.0.8.248
+ A 10.0.8.249
+ A 10.0.8.250
+ A 10.0.8.251
+ A 10.0.8.252
+ A 10.0.8.253
+ A 10.0.8.254
+ A 10.0.8.255
+ A 10.0.9.0
+ A 10.0.9.1
+ A 10.0.9.2
+ A 10.0.9.3
+ A 10.0.9.4
+ A 10.0.9.5
+ A 10.0.9.6
+ A 10.0.9.7
+ A 10.0.9.8
+ A 10.0.9.9
+ A 10.0.9.10
+ A 10.0.9.11
+ A 10.0.9.12
+ A 10.0.9.13
+ A 10.0.9.14
+ A 10.0.9.15
+ A 10.0.9.16
+ A 10.0.9.17
+ A 10.0.9.18
+ A 10.0.9.19
+ A 10.0.9.20
+ A 10.0.9.21
+ A 10.0.9.22
+ A 10.0.9.23
+ A 10.0.9.24
+ A 10.0.9.25
+ A 10.0.9.26
+ A 10.0.9.27
+ A 10.0.9.28
+ A 10.0.9.29
+ A 10.0.9.30
+ A 10.0.9.31
+ A 10.0.9.32
+ A 10.0.9.33
+ A 10.0.9.34
+ A 10.0.9.35
+ A 10.0.9.36
+ A 10.0.9.37
+ A 10.0.9.38
+ A 10.0.9.39
+ A 10.0.9.40
+ A 10.0.9.41
+ A 10.0.9.42
+ A 10.0.9.43
+ A 10.0.9.44
+ A 10.0.9.45
+ A 10.0.9.46
+ A 10.0.9.47
+ A 10.0.9.48
+ A 10.0.9.49
+ A 10.0.9.50
+ A 10.0.9.51
+ A 10.0.9.52
+ A 10.0.9.53
+ A 10.0.9.54
+ A 10.0.9.55
+ A 10.0.9.56
+ A 10.0.9.57
+ A 10.0.9.58
+ A 10.0.9.59
+ A 10.0.9.60
+ A 10.0.9.61
+ A 10.0.9.62
+ A 10.0.9.63
+ A 10.0.9.64
+ A 10.0.9.65
+ A 10.0.9.66
+ A 10.0.9.67
+ A 10.0.9.68
+ A 10.0.9.69
+ A 10.0.9.70
+ A 10.0.9.71
+ A 10.0.9.72
+ A 10.0.9.73
+ A 10.0.9.74
+ A 10.0.9.75
+ A 10.0.9.76
+ A 10.0.9.77
+ A 10.0.9.78
+ A 10.0.9.79
+ A 10.0.9.80
+ A 10.0.9.81
+ A 10.0.9.82
+ A 10.0.9.83
+ A 10.0.9.84
+ A 10.0.9.85
+ A 10.0.9.86
+ A 10.0.9.87
+ A 10.0.9.88
+ A 10.0.9.89
+ A 10.0.9.90
+ A 10.0.9.91
+ A 10.0.9.92
+ A 10.0.9.93
+ A 10.0.9.94
+ A 10.0.9.95
+ A 10.0.9.96
+ A 10.0.9.97
+ A 10.0.9.98
+ A 10.0.9.99
+ A 10.0.9.100
+ A 10.0.9.101
+ A 10.0.9.102
+ A 10.0.9.103
+ A 10.0.9.104
+ A 10.0.9.105
+ A 10.0.9.106
+ A 10.0.9.107
+ A 10.0.9.108
+ A 10.0.9.109
+ A 10.0.9.110
+ A 10.0.9.111
+ A 10.0.9.112
+ A 10.0.9.113
+ A 10.0.9.114
+ A 10.0.9.115
+ A 10.0.9.116
+ A 10.0.9.117
+ A 10.0.9.118
+ A 10.0.9.119
+ A 10.0.9.120
+ A 10.0.9.121
+ A 10.0.9.122
+ A 10.0.9.123
+ A 10.0.9.124
+ A 10.0.9.125
+ A 10.0.9.126
+ A 10.0.9.127
+ A 10.0.9.128
+ A 10.0.9.129
+ A 10.0.9.130
+ A 10.0.9.131
+ A 10.0.9.132
+ A 10.0.9.133
+ A 10.0.9.134
+ A 10.0.9.135
+ A 10.0.9.136
+ A 10.0.9.137
+ A 10.0.9.138
+ A 10.0.9.139
+ A 10.0.9.140
+ A 10.0.9.141
+ A 10.0.9.142
+ A 10.0.9.143
+ A 10.0.9.144
+ A 10.0.9.145
+ A 10.0.9.146
+ A 10.0.9.147
+ A 10.0.9.148
+ A 10.0.9.149
+ A 10.0.9.150
+ A 10.0.9.151
+ A 10.0.9.152
+ A 10.0.9.153
+ A 10.0.9.154
+ A 10.0.9.155
+ A 10.0.9.156
+ A 10.0.9.157
+ A 10.0.9.158
+ A 10.0.9.159
+ A 10.0.9.160
+ A 10.0.9.161
+ A 10.0.9.162
+ A 10.0.9.163
+ A 10.0.9.164
+ A 10.0.9.165
+ A 10.0.9.166
+ A 10.0.9.167
+ A 10.0.9.168
+ A 10.0.9.169
+ A 10.0.9.170
+ A 10.0.9.171
+ A 10.0.9.172
+ A 10.0.9.173
+ A 10.0.9.174
+ A 10.0.9.175
+ A 10.0.9.176
+ A 10.0.9.177
+ A 10.0.9.178
+ A 10.0.9.179
+ A 10.0.9.180
+ A 10.0.9.181
+ A 10.0.9.182
+ A 10.0.9.183
+ A 10.0.9.184
+ A 10.0.9.185
+ A 10.0.9.186
+ A 10.0.9.187
+ A 10.0.9.188
+ A 10.0.9.189
+ A 10.0.9.190
+ A 10.0.9.191
+ A 10.0.9.192
+ A 10.0.9.193
+ A 10.0.9.194
+ A 10.0.9.195
+ A 10.0.9.196
+ A 10.0.9.197
+ A 10.0.9.198
+ A 10.0.9.199
+ A 10.0.9.200
+ A 10.0.9.201
+ A 10.0.9.202
+ A 10.0.9.203
+ A 10.0.9.204
+ A 10.0.9.205
+ A 10.0.9.206
+ A 10.0.9.207
+ A 10.0.9.208
+ A 10.0.9.209
+ A 10.0.9.210
+ A 10.0.9.211
+ A 10.0.9.212
+ A 10.0.9.213
+ A 10.0.9.214
+ A 10.0.9.215
+ A 10.0.9.216
+ A 10.0.9.217
+ A 10.0.9.218
+ A 10.0.9.219
+ A 10.0.9.220
+ A 10.0.9.221
+ A 10.0.9.222
+ A 10.0.9.223
+ A 10.0.9.224
+ A 10.0.9.225
+ A 10.0.9.226
+ A 10.0.9.227
+ A 10.0.9.228
+ A 10.0.9.229
+ A 10.0.9.230
+ A 10.0.9.231
+ A 10.0.9.232
+ A 10.0.9.233
+ A 10.0.9.234
+ A 10.0.9.235
+ A 10.0.9.236
+ A 10.0.9.237
+ A 10.0.9.238
+ A 10.0.9.239
+ A 10.0.9.240
+ A 10.0.9.241
+ A 10.0.9.242
+ A 10.0.9.243
+ A 10.0.9.244
+ A 10.0.9.245
+ A 10.0.9.246
+ A 10.0.9.247
+ A 10.0.9.248
+ A 10.0.9.249
+ A 10.0.9.250
+ A 10.0.9.251
+ A 10.0.9.252
+ A 10.0.9.253
+ A 10.0.9.254
+ A 10.0.9.255
+ A 10.0.10.0
+ A 10.0.10.1
+ A 10.0.10.2
+ A 10.0.10.3
+ A 10.0.10.4
+ A 10.0.10.5
+ A 10.0.10.6
+ A 10.0.10.7
+ A 10.0.10.8
+ A 10.0.10.9
+ A 10.0.10.10
+ A 10.0.10.11
+ A 10.0.10.12
+ A 10.0.10.13
+ A 10.0.10.14
+ A 10.0.10.15
+ A 10.0.10.16
+ A 10.0.10.17
+ A 10.0.10.18
+ A 10.0.10.19
+ A 10.0.10.20
+ A 10.0.10.21
+ A 10.0.10.22
+ A 10.0.10.23
+ A 10.0.10.24
+ A 10.0.10.25
+ A 10.0.10.26
+ A 10.0.10.27
+ A 10.0.10.28
+ A 10.0.10.29
+ A 10.0.10.30
+ A 10.0.10.31
+ A 10.0.10.32
+ A 10.0.10.33
+ A 10.0.10.34
+ A 10.0.10.35
+ A 10.0.10.36
+ A 10.0.10.37
+ A 10.0.10.38
+ A 10.0.10.39
+ A 10.0.10.40
+ A 10.0.10.41
+ A 10.0.10.42
+ A 10.0.10.43
+ A 10.0.10.44
+ A 10.0.10.45
+ A 10.0.10.46
+ A 10.0.10.47
+ A 10.0.10.48
+ A 10.0.10.49
+ A 10.0.10.50
+ A 10.0.10.51
+ A 10.0.10.52
+ A 10.0.10.53
+ A 10.0.10.54
+ A 10.0.10.55
+ A 10.0.10.56
+ A 10.0.10.57
+ A 10.0.10.58
+ A 10.0.10.59
+ A 10.0.10.60
+ A 10.0.10.61
+ A 10.0.10.62
+ A 10.0.10.63
+ A 10.0.10.64
+ A 10.0.10.65
+ A 10.0.10.66
+ A 10.0.10.67
+ A 10.0.10.68
+ A 10.0.10.69
+ A 10.0.10.70
+ A 10.0.10.71
+ A 10.0.10.72
+ A 10.0.10.73
+ A 10.0.10.74
+ A 10.0.10.75
+ A 10.0.10.76
+ A 10.0.10.77
+ A 10.0.10.78
+ A 10.0.10.79
+ A 10.0.10.80
+ A 10.0.10.81
+ A 10.0.10.82
+ A 10.0.10.83
+ A 10.0.10.84
+ A 10.0.10.85
+ A 10.0.10.86
+ A 10.0.10.87
+ A 10.0.10.88
+ A 10.0.10.89
+ A 10.0.10.90
+ A 10.0.10.91
+ A 10.0.10.92
+ A 10.0.10.93
+ A 10.0.10.94
+ A 10.0.10.95
+ A 10.0.10.96
+ A 10.0.10.97
+ A 10.0.10.98
+ A 10.0.10.99
+ A 10.0.10.100
+ A 10.0.10.101
+ A 10.0.10.102
+ A 10.0.10.103
+ A 10.0.10.104
+ A 10.0.10.105
+ A 10.0.10.106
+ A 10.0.10.107
+ A 10.0.10.108
+ A 10.0.10.109
+ A 10.0.10.110
+ A 10.0.10.111
+ A 10.0.10.112
+ A 10.0.10.113
+ A 10.0.10.114
+ A 10.0.10.115
+ A 10.0.10.116
+ A 10.0.10.117
+ A 10.0.10.118
+ A 10.0.10.119
+ A 10.0.10.120
+ A 10.0.10.121
+ A 10.0.10.122
+ A 10.0.10.123
+ A 10.0.10.124
+ A 10.0.10.125
+ A 10.0.10.126
+ A 10.0.10.127
+ A 10.0.10.128
+ A 10.0.10.129
+ A 10.0.10.130
+ A 10.0.10.131
+ A 10.0.10.132
+ A 10.0.10.133
+ A 10.0.10.134
+ A 10.0.10.135
+ A 10.0.10.136
+ A 10.0.10.137
+ A 10.0.10.138
+ A 10.0.10.139
+ A 10.0.10.140
+ A 10.0.10.141
+ A 10.0.10.142
+ A 10.0.10.143
+ A 10.0.10.144
+ A 10.0.10.145
+ A 10.0.10.146
+ A 10.0.10.147
+ A 10.0.10.148
+ A 10.0.10.149
+ A 10.0.10.150
+ A 10.0.10.151
+ A 10.0.10.152
+ A 10.0.10.153
+ A 10.0.10.154
+ A 10.0.10.155
+ A 10.0.10.156
+ A 10.0.10.157
+ A 10.0.10.158
+ A 10.0.10.159
+ A 10.0.10.160
+ A 10.0.10.161
+ A 10.0.10.162
+ A 10.0.10.163
+ A 10.0.10.164
+ A 10.0.10.165
+ A 10.0.10.166
+ A 10.0.10.167
+ A 10.0.10.168
+ A 10.0.10.169
+ A 10.0.10.170
+ A 10.0.10.171
+ A 10.0.10.172
+ A 10.0.10.173
+ A 10.0.10.174
+ A 10.0.10.175
+ A 10.0.10.176
+ A 10.0.10.177
+ A 10.0.10.178
+ A 10.0.10.179
+ A 10.0.10.180
+ A 10.0.10.181
+ A 10.0.10.182
+ A 10.0.10.183
+ A 10.0.10.184
+ A 10.0.10.185
+ A 10.0.10.186
+ A 10.0.10.187
+ A 10.0.10.188
+ A 10.0.10.189
+ A 10.0.10.190
+ A 10.0.10.191
+ A 10.0.10.192
+ A 10.0.10.193
+ A 10.0.10.194
+ A 10.0.10.195
+ A 10.0.10.196
+ A 10.0.10.197
+ A 10.0.10.198
+ A 10.0.10.199
+ A 10.0.10.200
+ A 10.0.10.201
+ A 10.0.10.202
+ A 10.0.10.203
+ A 10.0.10.204
+ A 10.0.10.205
+ A 10.0.10.206
+ A 10.0.10.207
+ A 10.0.10.208
+ A 10.0.10.209
+ A 10.0.10.210
+ A 10.0.10.211
+ A 10.0.10.212
+ A 10.0.10.213
+ A 10.0.10.214
+ A 10.0.10.215
+ A 10.0.10.216
+ A 10.0.10.217
+ A 10.0.10.218
+ A 10.0.10.219
+ A 10.0.10.220
+ A 10.0.10.221
+ A 10.0.10.222
+ A 10.0.10.223
+ A 10.0.10.224
+ A 10.0.10.225
+ A 10.0.10.226
+ A 10.0.10.227
+ A 10.0.10.228
+ A 10.0.10.229
+ A 10.0.10.230
+ A 10.0.10.231
+ A 10.0.10.232
+ A 10.0.10.233
+ A 10.0.10.234
+ A 10.0.10.235
+ A 10.0.10.236
+ A 10.0.10.237
+ A 10.0.10.238
+ A 10.0.10.239
+ A 10.0.10.240
+ A 10.0.10.241
+ A 10.0.10.242
+ A 10.0.10.243
+ A 10.0.10.244
+ A 10.0.10.245
+ A 10.0.10.246
+ A 10.0.10.247
+ A 10.0.10.248
+ A 10.0.10.249
+ A 10.0.10.250
+ A 10.0.10.251
+ A 10.0.10.252
+ A 10.0.10.253
+ A 10.0.10.254
+ A 10.0.10.255
+ A 10.0.11.0
+ A 10.0.11.1
+ A 10.0.11.2
+ A 10.0.11.3
+ A 10.0.11.4
+ A 10.0.11.5
+ A 10.0.11.6
+ A 10.0.11.7
+ A 10.0.11.8
+ A 10.0.11.9
+ A 10.0.11.10
+ A 10.0.11.11
+ A 10.0.11.12
+ A 10.0.11.13
+ A 10.0.11.14
+ A 10.0.11.15
+ A 10.0.11.16
+ A 10.0.11.17
+ A 10.0.11.18
+ A 10.0.11.19
+ A 10.0.11.20
+ A 10.0.11.21
+ A 10.0.11.22
+ A 10.0.11.23
+ A 10.0.11.24
+ A 10.0.11.25
+ A 10.0.11.26
+ A 10.0.11.27
+ A 10.0.11.28
+ A 10.0.11.29
+ A 10.0.11.30
+ A 10.0.11.31
+ A 10.0.11.32
+ A 10.0.11.33
+ A 10.0.11.34
+ A 10.0.11.35
+ A 10.0.11.36
+ A 10.0.11.37
+ A 10.0.11.38
+ A 10.0.11.39
+ A 10.0.11.40
+ A 10.0.11.41
+ A 10.0.11.42
+ A 10.0.11.43
+ A 10.0.11.44
+ A 10.0.11.45
+ A 10.0.11.46
+ A 10.0.11.47
+ A 10.0.11.48
+ A 10.0.11.49
+ A 10.0.11.50
+ A 10.0.11.51
+ A 10.0.11.52
+ A 10.0.11.53
+ A 10.0.11.54
+ A 10.0.11.55
+ A 10.0.11.56
+ A 10.0.11.57
+ A 10.0.11.58
+ A 10.0.11.59
+ A 10.0.11.60
+ A 10.0.11.61
+ A 10.0.11.62
+ A 10.0.11.63
+ A 10.0.11.64
+ A 10.0.11.65
+ A 10.0.11.66
+ A 10.0.11.67
+ A 10.0.11.68
+ A 10.0.11.69
+ A 10.0.11.70
+ A 10.0.11.71
+ A 10.0.11.72
+ A 10.0.11.73
+ A 10.0.11.74
+ A 10.0.11.75
+ A 10.0.11.76
+ A 10.0.11.77
+ A 10.0.11.78
+ A 10.0.11.79
+ A 10.0.11.80
+ A 10.0.11.81
+ A 10.0.11.82
+ A 10.0.11.83
+ A 10.0.11.84
+ A 10.0.11.85
+ A 10.0.11.86
+ A 10.0.11.87
+ A 10.0.11.88
+ A 10.0.11.89
+ A 10.0.11.90
+ A 10.0.11.91
+ A 10.0.11.92
+ A 10.0.11.93
+ A 10.0.11.94
+ A 10.0.11.95
+ A 10.0.11.96
+ A 10.0.11.97
+ A 10.0.11.98
+ A 10.0.11.99
+ A 10.0.11.100
+ A 10.0.11.101
+ A 10.0.11.102
+ A 10.0.11.103
+ A 10.0.11.104
+ A 10.0.11.105
+ A 10.0.11.106
+ A 10.0.11.107
+ A 10.0.11.108
+ A 10.0.11.109
+ A 10.0.11.110
+ A 10.0.11.111
+ A 10.0.11.112
+ A 10.0.11.113
+ A 10.0.11.114
+ A 10.0.11.115
+ A 10.0.11.116
+ A 10.0.11.117
+ A 10.0.11.118
+ A 10.0.11.119
+ A 10.0.11.120
+ A 10.0.11.121
+ A 10.0.11.122
+ A 10.0.11.123
+ A 10.0.11.124
+ A 10.0.11.125
+ A 10.0.11.126
+ A 10.0.11.127
+ A 10.0.11.128
+ A 10.0.11.129
+ A 10.0.11.130
+ A 10.0.11.131
+ A 10.0.11.132
+ A 10.0.11.133
+ A 10.0.11.134
+ A 10.0.11.135
+ A 10.0.11.136
+ A 10.0.11.137
+ A 10.0.11.138
+ A 10.0.11.139
+ A 10.0.11.140
+ A 10.0.11.141
+ A 10.0.11.142
+ A 10.0.11.143
+ A 10.0.11.144
+ A 10.0.11.145
+ A 10.0.11.146
+ A 10.0.11.147
+ A 10.0.11.148
+ A 10.0.11.149
+ A 10.0.11.150
+ A 10.0.11.151
+ A 10.0.11.152
+ A 10.0.11.153
+ A 10.0.11.154
+ A 10.0.11.155
+ A 10.0.11.156
+ A 10.0.11.157
+ A 10.0.11.158
+ A 10.0.11.159
+ A 10.0.11.160
+ A 10.0.11.161
+ A 10.0.11.162
+ A 10.0.11.163
+ A 10.0.11.164
+ A 10.0.11.165
+ A 10.0.11.166
+ A 10.0.11.167
+ A 10.0.11.168
+ A 10.0.11.169
+ A 10.0.11.170
+ A 10.0.11.171
+ A 10.0.11.172
+ A 10.0.11.173
+ A 10.0.11.174
+ A 10.0.11.175
+ A 10.0.11.176
+ A 10.0.11.177
+ A 10.0.11.178
+ A 10.0.11.179
+ A 10.0.11.180
+ A 10.0.11.181
+ A 10.0.11.182
+ A 10.0.11.183
+ A 10.0.11.184
+ A 10.0.11.185
+ A 10.0.11.186
+ A 10.0.11.187
+ A 10.0.11.188
+ A 10.0.11.189
+ A 10.0.11.190
+ A 10.0.11.191
+ A 10.0.11.192
+ A 10.0.11.193
+ A 10.0.11.194
+ A 10.0.11.195
+ A 10.0.11.196
+ A 10.0.11.197
+ A 10.0.11.198
+ A 10.0.11.199
+ A 10.0.11.200
+ A 10.0.11.201
+ A 10.0.11.202
+ A 10.0.11.203
+ A 10.0.11.204
+ A 10.0.11.205
+ A 10.0.11.206
+ A 10.0.11.207
+ A 10.0.11.208
+ A 10.0.11.209
+ A 10.0.11.210
+ A 10.0.11.211
+ A 10.0.11.212
+ A 10.0.11.213
+ A 10.0.11.214
+ A 10.0.11.215
+ A 10.0.11.216
+ A 10.0.11.217
+ A 10.0.11.218
+ A 10.0.11.219
+ A 10.0.11.220
+ A 10.0.11.221
+ A 10.0.11.222
+ A 10.0.11.223
+ A 10.0.11.224
+ A 10.0.11.225
+ A 10.0.11.226
+ A 10.0.11.227
+ A 10.0.11.228
+ A 10.0.11.229
+ A 10.0.11.230
+ A 10.0.11.231
+ A 10.0.11.232
+ A 10.0.11.233
+ A 10.0.11.234
+ A 10.0.11.235
+ A 10.0.11.236
+ A 10.0.11.237
+ A 10.0.11.238
+ A 10.0.11.239
+ A 10.0.11.240
+ A 10.0.11.241
+ A 10.0.11.242
+ A 10.0.11.243
+ A 10.0.11.244
+ A 10.0.11.245
+ A 10.0.11.246
+ A 10.0.11.247
+ A 10.0.11.248
+ A 10.0.11.249
+ A 10.0.11.250
+ A 10.0.11.251
+ A 10.0.11.252
+ A 10.0.11.253
+ A 10.0.11.254
+ A 10.0.11.255
+ A 10.0.12.0
+ A 10.0.12.1
+ A 10.0.12.2
+ A 10.0.12.3
+ A 10.0.12.4
+ A 10.0.12.5
+ A 10.0.12.6
+ A 10.0.12.7
+ A 10.0.12.8
+ A 10.0.12.9
+ A 10.0.12.10
+ A 10.0.12.11
+ A 10.0.12.12
+ A 10.0.12.13
+ A 10.0.12.14
+ A 10.0.12.15
+ A 10.0.12.16
+ A 10.0.12.17
+ A 10.0.12.18
+ A 10.0.12.19
+ A 10.0.12.20
+ A 10.0.12.21
+ A 10.0.12.22
+ A 10.0.12.23
+ A 10.0.12.24
+ A 10.0.12.25
+ A 10.0.12.26
+ A 10.0.12.27
+ A 10.0.12.28
+ A 10.0.12.29
+ A 10.0.12.30
+ A 10.0.12.31
+ A 10.0.12.32
+ A 10.0.12.33
+ A 10.0.12.34
+ A 10.0.12.35
+ A 10.0.12.36
+ A 10.0.12.37
+ A 10.0.12.38
+ A 10.0.12.39
+ A 10.0.12.40
+ A 10.0.12.41
+ A 10.0.12.42
+ A 10.0.12.43
+ A 10.0.12.44
+ A 10.0.12.45
+ A 10.0.12.46
+ A 10.0.12.47
+ A 10.0.12.48
+ A 10.0.12.49
+ A 10.0.12.50
+ A 10.0.12.51
+ A 10.0.12.52
+ A 10.0.12.53
+ A 10.0.12.54
+ A 10.0.12.55
+ A 10.0.12.56
+ A 10.0.12.57
+ A 10.0.12.58
+ A 10.0.12.59
+ A 10.0.12.60
+ A 10.0.12.61
+ A 10.0.12.62
+ A 10.0.12.63
+ A 10.0.12.64
+ A 10.0.12.65
+ A 10.0.12.66
+ A 10.0.12.67
+ A 10.0.12.68
+ A 10.0.12.69
+ A 10.0.12.70
+ A 10.0.12.71
+ A 10.0.12.72
+ A 10.0.12.73
+ A 10.0.12.74
+ A 10.0.12.75
+ A 10.0.12.76
+ A 10.0.12.77
+ A 10.0.12.78
+ A 10.0.12.79
+ A 10.0.12.80
+ A 10.0.12.81
+ A 10.0.12.82
+ A 10.0.12.83
+ A 10.0.12.84
+ A 10.0.12.85
+ A 10.0.12.86
+ A 10.0.12.87
+ A 10.0.12.88
+ A 10.0.12.89
+ A 10.0.12.90
+ A 10.0.12.91
+ A 10.0.12.92
+ A 10.0.12.93
+ A 10.0.12.94
+ A 10.0.12.95
+ A 10.0.12.96
+ A 10.0.12.97
+ A 10.0.12.98
+ A 10.0.12.99
+ A 10.0.12.100
+ A 10.0.12.101
+ A 10.0.12.102
+ A 10.0.12.103
+ A 10.0.12.104
+ A 10.0.12.105
+ A 10.0.12.106
+ A 10.0.12.107
+ A 10.0.12.108
+ A 10.0.12.109
+ A 10.0.12.110
+ A 10.0.12.111
+ A 10.0.12.112
+ A 10.0.12.113
+ A 10.0.12.114
+ A 10.0.12.115
+ A 10.0.12.116
+ A 10.0.12.117
+ A 10.0.12.118
+ A 10.0.12.119
+ A 10.0.12.120
+ A 10.0.12.121
+ A 10.0.12.122
+ A 10.0.12.123
+ A 10.0.12.124
+ A 10.0.12.125
+ A 10.0.12.126
+ A 10.0.12.127
+ A 10.0.12.128
+ A 10.0.12.129
+ A 10.0.12.130
+ A 10.0.12.131
+ A 10.0.12.132
+ A 10.0.12.133
+ A 10.0.12.134
+ A 10.0.12.135
+ A 10.0.12.136
+ A 10.0.12.137
+ A 10.0.12.138
+ A 10.0.12.139
+ A 10.0.12.140
+ A 10.0.12.141
+ A 10.0.12.142
+ A 10.0.12.143
+ A 10.0.12.144
+ A 10.0.12.145
+ A 10.0.12.146
+ A 10.0.12.147
+ A 10.0.12.148
+ A 10.0.12.149
+ A 10.0.12.150
+ A 10.0.12.151
+ A 10.0.12.152
+ A 10.0.12.153
+ A 10.0.12.154
+ A 10.0.12.155
+ A 10.0.12.156
+ A 10.0.12.157
+ A 10.0.12.158
+ A 10.0.12.159
+ A 10.0.12.160
+ A 10.0.12.161
+ A 10.0.12.162
+ A 10.0.12.163
+ A 10.0.12.164
+ A 10.0.12.165
+ A 10.0.12.166
+ A 10.0.12.167
+ A 10.0.12.168
+ A 10.0.12.169
+ A 10.0.12.170
+ A 10.0.12.171
+ A 10.0.12.172
+ A 10.0.12.173
+ A 10.0.12.174
+ A 10.0.12.175
+ A 10.0.12.176
+ A 10.0.12.177
+ A 10.0.12.178
+ A 10.0.12.179
+ A 10.0.12.180
+ A 10.0.12.181
+ A 10.0.12.182
+ A 10.0.12.183
+ A 10.0.12.184
+ A 10.0.12.185
+ A 10.0.12.186
+ A 10.0.12.187
+ A 10.0.12.188
+ A 10.0.12.189
+ A 10.0.12.190
+ A 10.0.12.191
+ A 10.0.12.192
+ A 10.0.12.193
+ A 10.0.12.194
+ A 10.0.12.195
+ A 10.0.12.196
+ A 10.0.12.197
+ A 10.0.12.198
+ A 10.0.12.199
+ A 10.0.12.200
+ A 10.0.12.201
+ A 10.0.12.202
+ A 10.0.12.203
+ A 10.0.12.204
+ A 10.0.12.205
+ A 10.0.12.206
+ A 10.0.12.207
+ A 10.0.12.208
+ A 10.0.12.209
+ A 10.0.12.210
+ A 10.0.12.211
+ A 10.0.12.212
+ A 10.0.12.213
+ A 10.0.12.214
+ A 10.0.12.215
+ A 10.0.12.216
+ A 10.0.12.217
+ A 10.0.12.218
+ A 10.0.12.219
+ A 10.0.12.220
+ A 10.0.12.221
+ A 10.0.12.222
+ A 10.0.12.223
+ A 10.0.12.224
+ A 10.0.12.225
+ A 10.0.12.226
+ A 10.0.12.227
+ A 10.0.12.228
+ A 10.0.12.229
+ A 10.0.12.230
+ A 10.0.12.231
+ A 10.0.12.232
+ A 10.0.12.233
+ A 10.0.12.234
+ A 10.0.12.235
+ A 10.0.12.236
+ A 10.0.12.237
+ A 10.0.12.238
+ A 10.0.12.239
+ A 10.0.12.240
+ A 10.0.12.241
+ A 10.0.12.242
+ A 10.0.12.243
+ A 10.0.12.244
+ A 10.0.12.245
+ A 10.0.12.246
+ A 10.0.12.247
+ A 10.0.12.248
+ A 10.0.12.249
+ A 10.0.12.250
+ A 10.0.12.251
+ A 10.0.12.252
+ A 10.0.12.253
+ A 10.0.12.254
+ A 10.0.12.255
+ A 10.0.13.0
+ A 10.0.13.1
+ A 10.0.13.2
+ A 10.0.13.3
+ A 10.0.13.4
+ A 10.0.13.5
+ A 10.0.13.6
+ A 10.0.13.7
+ A 10.0.13.8
+ A 10.0.13.9
+ A 10.0.13.10
+ A 10.0.13.11
+ A 10.0.13.12
+ A 10.0.13.13
+ A 10.0.13.14
+ A 10.0.13.15
+ A 10.0.13.16
+ A 10.0.13.17
+ A 10.0.13.18
+ A 10.0.13.19
+ A 10.0.13.20
+ A 10.0.13.21
+ A 10.0.13.22
+ A 10.0.13.23
+ A 10.0.13.24
+ A 10.0.13.25
+ A 10.0.13.26
+ A 10.0.13.27
+ A 10.0.13.28
+ A 10.0.13.29
+ A 10.0.13.30
+ A 10.0.13.31
+ A 10.0.13.32
+ A 10.0.13.33
+ A 10.0.13.34
+ A 10.0.13.35
+ A 10.0.13.36
+ A 10.0.13.37
+ A 10.0.13.38
+ A 10.0.13.39
+ A 10.0.13.40
+ A 10.0.13.41
+ A 10.0.13.42
+ A 10.0.13.43
+ A 10.0.13.44
+ A 10.0.13.45
+ A 10.0.13.46
+ A 10.0.13.47
+ A 10.0.13.48
+ A 10.0.13.49
+ A 10.0.13.50
+ A 10.0.13.51
+ A 10.0.13.52
+ A 10.0.13.53
+ A 10.0.13.54
+ A 10.0.13.55
+ A 10.0.13.56
+ A 10.0.13.57
+ A 10.0.13.58
+ A 10.0.13.59
+ A 10.0.13.60
+ A 10.0.13.61
+ A 10.0.13.62
+ A 10.0.13.63
+ A 10.0.13.64
+ A 10.0.13.65
+ A 10.0.13.66
+ A 10.0.13.67
+ A 10.0.13.68
+ A 10.0.13.69
+ A 10.0.13.70
+ A 10.0.13.71
+ A 10.0.13.72
+ A 10.0.13.73
+ A 10.0.13.74
+ A 10.0.13.75
+ A 10.0.13.76
+ A 10.0.13.77
+ A 10.0.13.78
+ A 10.0.13.79
+ A 10.0.13.80
+ A 10.0.13.81
+ A 10.0.13.82
+ A 10.0.13.83
+ A 10.0.13.84
+ A 10.0.13.85
+ A 10.0.13.86
+ A 10.0.13.87
+ A 10.0.13.88
+ A 10.0.13.89
+ A 10.0.13.90
+ A 10.0.13.91
+ A 10.0.13.92
+ A 10.0.13.93
+ A 10.0.13.94
+ A 10.0.13.95
+ A 10.0.13.96
+ A 10.0.13.97
+ A 10.0.13.98
+ A 10.0.13.99
+ A 10.0.13.100
+ A 10.0.13.101
+ A 10.0.13.102
+ A 10.0.13.103
+ A 10.0.13.104
+ A 10.0.13.105
+ A 10.0.13.106
+ A 10.0.13.107
+ A 10.0.13.108
+ A 10.0.13.109
+ A 10.0.13.110
+ A 10.0.13.111
+ A 10.0.13.112
+ A 10.0.13.113
+ A 10.0.13.114
+ A 10.0.13.115
+ A 10.0.13.116
+ A 10.0.13.117
+ A 10.0.13.118
+ A 10.0.13.119
+ A 10.0.13.120
+ A 10.0.13.121
+ A 10.0.13.122
+ A 10.0.13.123
+ A 10.0.13.124
+ A 10.0.13.125
+ A 10.0.13.126
+ A 10.0.13.127
+ A 10.0.13.128
+ A 10.0.13.129
+ A 10.0.13.130
+ A 10.0.13.131
+ A 10.0.13.132
+ A 10.0.13.133
+ A 10.0.13.134
+ A 10.0.13.135
+ A 10.0.13.136
+ A 10.0.13.137
+ A 10.0.13.138
+ A 10.0.13.139
+ A 10.0.13.140
+ A 10.0.13.141
+ A 10.0.13.142
+ A 10.0.13.143
+ A 10.0.13.144
+ A 10.0.13.145
+ A 10.0.13.146
+ A 10.0.13.147
+ A 10.0.13.148
+ A 10.0.13.149
+ A 10.0.13.150
+ A 10.0.13.151
+ A 10.0.13.152
+ A 10.0.13.153
+ A 10.0.13.154
+ A 10.0.13.155
+ A 10.0.13.156
+ A 10.0.13.157
+ A 10.0.13.158
+ A 10.0.13.159
+ A 10.0.13.160
+ A 10.0.13.161
+ A 10.0.13.162
+ A 10.0.13.163
+ A 10.0.13.164
+ A 10.0.13.165
+ A 10.0.13.166
+ A 10.0.13.167
+ A 10.0.13.168
+ A 10.0.13.169
+ A 10.0.13.170
+ A 10.0.13.171
+ A 10.0.13.172
+ A 10.0.13.173
+ A 10.0.13.174
+ A 10.0.13.175
+ A 10.0.13.176
+ A 10.0.13.177
+ A 10.0.13.178
+ A 10.0.13.179
+ A 10.0.13.180
+ A 10.0.13.181
+ A 10.0.13.182
+ A 10.0.13.183
+ A 10.0.13.184
+ A 10.0.13.185
+ A 10.0.13.186
+ A 10.0.13.187
+ A 10.0.13.188
+ A 10.0.13.189
+ A 10.0.13.190
+ A 10.0.13.191
+ A 10.0.13.192
+ A 10.0.13.193
+ A 10.0.13.194
+ A 10.0.13.195
+ A 10.0.13.196
+ A 10.0.13.197
+ A 10.0.13.198
+ A 10.0.13.199
+ A 10.0.13.200
+ A 10.0.13.201
+ A 10.0.13.202
+ A 10.0.13.203
+ A 10.0.13.204
+ A 10.0.13.205
+ A 10.0.13.206
+ A 10.0.13.207
+ A 10.0.13.208
+ A 10.0.13.209
+ A 10.0.13.210
+ A 10.0.13.211
+ A 10.0.13.212
+ A 10.0.13.213
+ A 10.0.13.214
+ A 10.0.13.215
+ A 10.0.13.216
+ A 10.0.13.217
+ A 10.0.13.218
+ A 10.0.13.219
+ A 10.0.13.220
+ A 10.0.13.221
+ A 10.0.13.222
+ A 10.0.13.223
+ A 10.0.13.224
+ A 10.0.13.225
+ A 10.0.13.226
+ A 10.0.13.227
+ A 10.0.13.228
+ A 10.0.13.229
+ A 10.0.13.230
+ A 10.0.13.231
+ A 10.0.13.232
+ A 10.0.13.233
+ A 10.0.13.234
+ A 10.0.13.235
+ A 10.0.13.236
+ A 10.0.13.237
+ A 10.0.13.238
+ A 10.0.13.239
+ A 10.0.13.240
+ A 10.0.13.241
+ A 10.0.13.242
+ A 10.0.13.243
+ A 10.0.13.244
+ A 10.0.13.245
+ A 10.0.13.246
+ A 10.0.13.247
+ A 10.0.13.248
+ A 10.0.13.249
+ A 10.0.13.250
+ A 10.0.13.251
+ A 10.0.13.252
+ A 10.0.13.253
+ A 10.0.13.254
+ A 10.0.13.255
+ A 10.0.14.0
+ A 10.0.14.1
+ A 10.0.14.2
+ A 10.0.14.3
+ A 10.0.14.4
+ A 10.0.14.5
+ A 10.0.14.6
+ A 10.0.14.7
+ A 10.0.14.8
+ A 10.0.14.9
+ A 10.0.14.10
+ A 10.0.14.11
+ A 10.0.14.12
+ A 10.0.14.13
+ A 10.0.14.14
+ A 10.0.14.15
+ A 10.0.14.16
+ A 10.0.14.17
+ A 10.0.14.18
+ A 10.0.14.19
+ A 10.0.14.20
+ A 10.0.14.21
+ A 10.0.14.22
+ A 10.0.14.23
+ A 10.0.14.24
+ A 10.0.14.25
+ A 10.0.14.26
+ A 10.0.14.27
+ A 10.0.14.28
+ A 10.0.14.29
+ A 10.0.14.30
+ A 10.0.14.31
+ A 10.0.14.32
+ A 10.0.14.33
+ A 10.0.14.34
+ A 10.0.14.35
+ A 10.0.14.36
+ A 10.0.14.37
+ A 10.0.14.38
+ A 10.0.14.39
+ A 10.0.14.40
+ A 10.0.14.41
+ A 10.0.14.42
+ A 10.0.14.43
+ A 10.0.14.44
+ A 10.0.14.45
+ A 10.0.14.46
+ A 10.0.14.47
+ A 10.0.14.48
+ A 10.0.14.49
+ A 10.0.14.50
+ A 10.0.14.51
+ A 10.0.14.52
+ A 10.0.14.53
+ A 10.0.14.54
+ A 10.0.14.55
+ A 10.0.14.56
+ A 10.0.14.57
+ A 10.0.14.58
+ A 10.0.14.59
+ A 10.0.14.60
+ A 10.0.14.61
+ A 10.0.14.62
+ A 10.0.14.63
+ A 10.0.14.64
+ A 10.0.14.65
+ A 10.0.14.66
+ A 10.0.14.67
+ A 10.0.14.68
+ A 10.0.14.69
+ A 10.0.14.70
+ A 10.0.14.71
+ A 10.0.14.72
+ A 10.0.14.73
+ A 10.0.14.74
+ A 10.0.14.75
+ A 10.0.14.76
+ A 10.0.14.77
+ A 10.0.14.78
+ A 10.0.14.79
+ A 10.0.14.80
+ A 10.0.14.81
+ A 10.0.14.82
+ A 10.0.14.83
+ A 10.0.14.84
+ A 10.0.14.85
+ A 10.0.14.86
+ A 10.0.14.87
+ A 10.0.14.88
+ A 10.0.14.89
+ A 10.0.14.90
+ A 10.0.14.91
+ A 10.0.14.92
+ A 10.0.14.93
+ A 10.0.14.94
+ A 10.0.14.95
+ A 10.0.14.96
+ A 10.0.14.97
+ A 10.0.14.98
+ A 10.0.14.99
+ A 10.0.14.100
+ A 10.0.14.101
+ A 10.0.14.102
+ A 10.0.14.103
+ A 10.0.14.104
+ A 10.0.14.105
+ A 10.0.14.106
+ A 10.0.14.107
+ A 10.0.14.108
+ A 10.0.14.109
+ A 10.0.14.110
+ A 10.0.14.111
+ A 10.0.14.112
+ A 10.0.14.113
+ A 10.0.14.114
+ A 10.0.14.115
+ A 10.0.14.116
+ A 10.0.14.117
+ A 10.0.14.118
+ A 10.0.14.119
+ A 10.0.14.120
+ A 10.0.14.121
+ A 10.0.14.122
+ A 10.0.14.123
+ A 10.0.14.124
+ A 10.0.14.125
+ A 10.0.14.126
+ A 10.0.14.127
+ A 10.0.14.128
+ A 10.0.14.129
+ A 10.0.14.130
+ A 10.0.14.131
+ A 10.0.14.132
+ A 10.0.14.133
+ A 10.0.14.134
+ A 10.0.14.135
+ A 10.0.14.136
+ A 10.0.14.137
+ A 10.0.14.138
+ A 10.0.14.139
+ A 10.0.14.140
+ A 10.0.14.141
+ A 10.0.14.142
+ A 10.0.14.143
+ A 10.0.14.144
+ A 10.0.14.145
+ A 10.0.14.146
+ A 10.0.14.147
+ A 10.0.14.148
+ A 10.0.14.149
+ A 10.0.14.150
+ A 10.0.14.151
+ A 10.0.14.152
+ A 10.0.14.153
+ A 10.0.14.154
+ A 10.0.14.155
+ A 10.0.14.156
+ A 10.0.14.157
+ A 10.0.14.158
+ A 10.0.14.159
+ A 10.0.14.160
+ A 10.0.14.161
+ A 10.0.14.162
+ A 10.0.14.163
+ A 10.0.14.164
+ A 10.0.14.165
+ A 10.0.14.166
+ A 10.0.14.167
+ A 10.0.14.168
+ A 10.0.14.169
+ A 10.0.14.170
+ A 10.0.14.171
+ A 10.0.14.172
+ A 10.0.14.173
+ A 10.0.14.174
+ A 10.0.14.175
+ A 10.0.14.176
+ A 10.0.14.177
+ A 10.0.14.178
+ A 10.0.14.179
+ A 10.0.14.180
+ A 10.0.14.181
+ A 10.0.14.182
+ A 10.0.14.183
+ A 10.0.14.184
+ A 10.0.14.185
+ A 10.0.14.186
+ A 10.0.14.187
+ A 10.0.14.188
+ A 10.0.14.189
+ A 10.0.14.190
+ A 10.0.14.191
+ A 10.0.14.192
+ A 10.0.14.193
+ A 10.0.14.194
+ A 10.0.14.195
+ A 10.0.14.196
+ A 10.0.14.197
+ A 10.0.14.198
+ A 10.0.14.199
+ A 10.0.14.200
+ A 10.0.14.201
+ A 10.0.14.202
+ A 10.0.14.203
+ A 10.0.14.204
+ A 10.0.14.205
+ A 10.0.14.206
+ A 10.0.14.207
+ A 10.0.14.208
+ A 10.0.14.209
+ A 10.0.14.210
+ A 10.0.14.211
+ A 10.0.14.212
+ A 10.0.14.213
+ A 10.0.14.214
+ A 10.0.14.215
+ A 10.0.14.216
+ A 10.0.14.217
+ A 10.0.14.218
+ A 10.0.14.219
+ A 10.0.14.220
+ A 10.0.14.221
+ A 10.0.14.222
+ A 10.0.14.223
+ A 10.0.14.224
+ A 10.0.14.225
+ A 10.0.14.226
+ A 10.0.14.227
+ A 10.0.14.228
+ A 10.0.14.229
+ A 10.0.14.230
+ A 10.0.14.231
+ A 10.0.14.232
+ A 10.0.14.233
+ A 10.0.14.234
+ A 10.0.14.235
+ A 10.0.14.236
+ A 10.0.14.237
+ A 10.0.14.238
+ A 10.0.14.239
+ A 10.0.14.240
+ A 10.0.14.241
+ A 10.0.14.242
+ A 10.0.14.243
+ A 10.0.14.244
+ A 10.0.14.245
+ A 10.0.14.246
+ A 10.0.14.247
+ A 10.0.14.248
+ A 10.0.14.249
+ A 10.0.14.250
+ A 10.0.14.251
+ A 10.0.14.252
+ A 10.0.14.253
+ A 10.0.14.254
+ A 10.0.14.255
+ A 10.0.15.0
+ A 10.0.15.1
+ A 10.0.15.2
+ A 10.0.15.3
+ A 10.0.15.4
+ A 10.0.15.5
+ A 10.0.15.6
+ A 10.0.15.7
+ A 10.0.15.8
+ A 10.0.15.9
+ A 10.0.15.10
+ A 10.0.15.11
+ A 10.0.15.12
+ A 10.0.15.13
+ A 10.0.15.14
+ A 10.0.15.15
+ A 10.0.15.16
+ A 10.0.15.17
+ A 10.0.15.18
+ A 10.0.15.19
+ A 10.0.15.20
+ A 10.0.15.21
+ A 10.0.15.22
+ A 10.0.15.23
+ A 10.0.15.24
+ A 10.0.15.25
+ A 10.0.15.26
+ A 10.0.15.27
+ A 10.0.15.28
+ A 10.0.15.29
+ A 10.0.15.30
+ A 10.0.15.31
+ A 10.0.15.32
+ A 10.0.15.33
+ A 10.0.15.34
+ A 10.0.15.35
+ A 10.0.15.36
+ A 10.0.15.37
+ A 10.0.15.38
+ A 10.0.15.39
+ A 10.0.15.40
+ A 10.0.15.41
+ A 10.0.15.42
+ A 10.0.15.43
+ A 10.0.15.44
+ A 10.0.15.45
+ A 10.0.15.46
+ A 10.0.15.47
+ A 10.0.15.48
+ A 10.0.15.49
+ A 10.0.15.50
+ A 10.0.15.51
+ A 10.0.15.52
+ A 10.0.15.53
+ A 10.0.15.54
+ A 10.0.15.55
+ A 10.0.15.56
+ A 10.0.15.57
+ A 10.0.15.58
+ A 10.0.15.59
+ A 10.0.15.60
+ A 10.0.15.61
+ A 10.0.15.62
+ A 10.0.15.63
+ A 10.0.15.64
+ A 10.0.15.65
+ A 10.0.15.66
+ A 10.0.15.67
+ A 10.0.15.68
+ A 10.0.15.69
+ A 10.0.15.70
+ A 10.0.15.71
+ A 10.0.15.72
+ A 10.0.15.73
+ A 10.0.15.74
+ A 10.0.15.75
+ A 10.0.15.76
+ A 10.0.15.77
+ A 10.0.15.78
+ A 10.0.15.79
+ A 10.0.15.80
+ A 10.0.15.81
+ A 10.0.15.82
+ A 10.0.15.83
+ A 10.0.15.84
+ A 10.0.15.85
+ A 10.0.15.86
+ A 10.0.15.87
+ A 10.0.15.88
+ A 10.0.15.89
+ A 10.0.15.90
+ A 10.0.15.91
+ A 10.0.15.92
+ A 10.0.15.93
+ A 10.0.15.94
+ A 10.0.15.95
+ A 10.0.15.96
+ A 10.0.15.97
+ A 10.0.15.98
+ A 10.0.15.99
+ A 10.0.15.100
+ A 10.0.15.101
+ A 10.0.15.102
+ A 10.0.15.103
+ A 10.0.15.104
+ A 10.0.15.105
+ A 10.0.15.106
+ A 10.0.15.107
+ A 10.0.15.108
+ A 10.0.15.109
+ A 10.0.15.110
+ A 10.0.15.111
+ A 10.0.15.112
+ A 10.0.15.113
+ A 10.0.15.114
+ A 10.0.15.115
+ A 10.0.15.116
+ A 10.0.15.117
+ A 10.0.15.118
+ A 10.0.15.119
+ A 10.0.15.120
+ A 10.0.15.121
+ A 10.0.15.122
+ A 10.0.15.123
+ A 10.0.15.124
+ A 10.0.15.125
+ A 10.0.15.126
+ A 10.0.15.127
+ A 10.0.15.128
+ A 10.0.15.129
+ A 10.0.15.130
+ A 10.0.15.131
+ A 10.0.15.132
+ A 10.0.15.133
+ A 10.0.15.134
+ A 10.0.15.135
+ A 10.0.15.136
+ A 10.0.15.137
+ A 10.0.15.138
+ A 10.0.15.139
+ A 10.0.15.140
+ A 10.0.15.141
+ A 10.0.15.142
+ A 10.0.15.143
+ A 10.0.15.144
+ A 10.0.15.145
+ A 10.0.15.146
+ A 10.0.15.147
+ A 10.0.15.148
+ A 10.0.15.149
+ A 10.0.15.150
+ A 10.0.15.151
+ A 10.0.15.152
+ A 10.0.15.153
+ A 10.0.15.154
+ A 10.0.15.155
+ A 10.0.15.156
+ A 10.0.15.157
+ A 10.0.15.158
+ A 10.0.15.159
+5000 A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+ A 10.0.3.232
+ A 10.0.3.233
+ A 10.0.3.234
+ A 10.0.3.235
+ A 10.0.3.236
+ A 10.0.3.237
+ A 10.0.3.238
+ A 10.0.3.239
+ A 10.0.3.240
+ A 10.0.3.241
+ A 10.0.3.242
+ A 10.0.3.243
+ A 10.0.3.244
+ A 10.0.3.245
+ A 10.0.3.246
+ A 10.0.3.247
+ A 10.0.3.248
+ A 10.0.3.249
+ A 10.0.3.250
+ A 10.0.3.251
+ A 10.0.3.252
+ A 10.0.3.253
+ A 10.0.3.254
+ A 10.0.3.255
+ A 10.0.4.0
+ A 10.0.4.1
+ A 10.0.4.2
+ A 10.0.4.3
+ A 10.0.4.4
+ A 10.0.4.5
+ A 10.0.4.6
+ A 10.0.4.7
+ A 10.0.4.8
+ A 10.0.4.9
+ A 10.0.4.10
+ A 10.0.4.11
+ A 10.0.4.12
+ A 10.0.4.13
+ A 10.0.4.14
+ A 10.0.4.15
+ A 10.0.4.16
+ A 10.0.4.17
+ A 10.0.4.18
+ A 10.0.4.19
+ A 10.0.4.20
+ A 10.0.4.21
+ A 10.0.4.22
+ A 10.0.4.23
+ A 10.0.4.24
+ A 10.0.4.25
+ A 10.0.4.26
+ A 10.0.4.27
+ A 10.0.4.28
+ A 10.0.4.29
+ A 10.0.4.30
+ A 10.0.4.31
+ A 10.0.4.32
+ A 10.0.4.33
+ A 10.0.4.34
+ A 10.0.4.35
+ A 10.0.4.36
+ A 10.0.4.37
+ A 10.0.4.38
+ A 10.0.4.39
+ A 10.0.4.40
+ A 10.0.4.41
+ A 10.0.4.42
+ A 10.0.4.43
+ A 10.0.4.44
+ A 10.0.4.45
+ A 10.0.4.46
+ A 10.0.4.47
+ A 10.0.4.48
+ A 10.0.4.49
+ A 10.0.4.50
+ A 10.0.4.51
+ A 10.0.4.52
+ A 10.0.4.53
+ A 10.0.4.54
+ A 10.0.4.55
+ A 10.0.4.56
+ A 10.0.4.57
+ A 10.0.4.58
+ A 10.0.4.59
+ A 10.0.4.60
+ A 10.0.4.61
+ A 10.0.4.62
+ A 10.0.4.63
+ A 10.0.4.64
+ A 10.0.4.65
+ A 10.0.4.66
+ A 10.0.4.67
+ A 10.0.4.68
+ A 10.0.4.69
+ A 10.0.4.70
+ A 10.0.4.71
+ A 10.0.4.72
+ A 10.0.4.73
+ A 10.0.4.74
+ A 10.0.4.75
+ A 10.0.4.76
+ A 10.0.4.77
+ A 10.0.4.78
+ A 10.0.4.79
+ A 10.0.4.80
+ A 10.0.4.81
+ A 10.0.4.82
+ A 10.0.4.83
+ A 10.0.4.84
+ A 10.0.4.85
+ A 10.0.4.86
+ A 10.0.4.87
+ A 10.0.4.88
+ A 10.0.4.89
+ A 10.0.4.90
+ A 10.0.4.91
+ A 10.0.4.92
+ A 10.0.4.93
+ A 10.0.4.94
+ A 10.0.4.95
+ A 10.0.4.96
+ A 10.0.4.97
+ A 10.0.4.98
+ A 10.0.4.99
+ A 10.0.4.100
+ A 10.0.4.101
+ A 10.0.4.102
+ A 10.0.4.103
+ A 10.0.4.104
+ A 10.0.4.105
+ A 10.0.4.106
+ A 10.0.4.107
+ A 10.0.4.108
+ A 10.0.4.109
+ A 10.0.4.110
+ A 10.0.4.111
+ A 10.0.4.112
+ A 10.0.4.113
+ A 10.0.4.114
+ A 10.0.4.115
+ A 10.0.4.116
+ A 10.0.4.117
+ A 10.0.4.118
+ A 10.0.4.119
+ A 10.0.4.120
+ A 10.0.4.121
+ A 10.0.4.122
+ A 10.0.4.123
+ A 10.0.4.124
+ A 10.0.4.125
+ A 10.0.4.126
+ A 10.0.4.127
+ A 10.0.4.128
+ A 10.0.4.129
+ A 10.0.4.130
+ A 10.0.4.131
+ A 10.0.4.132
+ A 10.0.4.133
+ A 10.0.4.134
+ A 10.0.4.135
+ A 10.0.4.136
+ A 10.0.4.137
+ A 10.0.4.138
+ A 10.0.4.139
+ A 10.0.4.140
+ A 10.0.4.141
+ A 10.0.4.142
+ A 10.0.4.143
+ A 10.0.4.144
+ A 10.0.4.145
+ A 10.0.4.146
+ A 10.0.4.147
+ A 10.0.4.148
+ A 10.0.4.149
+ A 10.0.4.150
+ A 10.0.4.151
+ A 10.0.4.152
+ A 10.0.4.153
+ A 10.0.4.154
+ A 10.0.4.155
+ A 10.0.4.156
+ A 10.0.4.157
+ A 10.0.4.158
+ A 10.0.4.159
+ A 10.0.4.160
+ A 10.0.4.161
+ A 10.0.4.162
+ A 10.0.4.163
+ A 10.0.4.164
+ A 10.0.4.165
+ A 10.0.4.166
+ A 10.0.4.167
+ A 10.0.4.168
+ A 10.0.4.169
+ A 10.0.4.170
+ A 10.0.4.171
+ A 10.0.4.172
+ A 10.0.4.173
+ A 10.0.4.174
+ A 10.0.4.175
+ A 10.0.4.176
+ A 10.0.4.177
+ A 10.0.4.178
+ A 10.0.4.179
+ A 10.0.4.180
+ A 10.0.4.181
+ A 10.0.4.182
+ A 10.0.4.183
+ A 10.0.4.184
+ A 10.0.4.185
+ A 10.0.4.186
+ A 10.0.4.187
+ A 10.0.4.188
+ A 10.0.4.189
+ A 10.0.4.190
+ A 10.0.4.191
+ A 10.0.4.192
+ A 10.0.4.193
+ A 10.0.4.194
+ A 10.0.4.195
+ A 10.0.4.196
+ A 10.0.4.197
+ A 10.0.4.198
+ A 10.0.4.199
+ A 10.0.4.200
+ A 10.0.4.201
+ A 10.0.4.202
+ A 10.0.4.203
+ A 10.0.4.204
+ A 10.0.4.205
+ A 10.0.4.206
+ A 10.0.4.207
+ A 10.0.4.208
+ A 10.0.4.209
+ A 10.0.4.210
+ A 10.0.4.211
+ A 10.0.4.212
+ A 10.0.4.213
+ A 10.0.4.214
+ A 10.0.4.215
+ A 10.0.4.216
+ A 10.0.4.217
+ A 10.0.4.218
+ A 10.0.4.219
+ A 10.0.4.220
+ A 10.0.4.221
+ A 10.0.4.222
+ A 10.0.4.223
+ A 10.0.4.224
+ A 10.0.4.225
+ A 10.0.4.226
+ A 10.0.4.227
+ A 10.0.4.228
+ A 10.0.4.229
+ A 10.0.4.230
+ A 10.0.4.231
+ A 10.0.4.232
+ A 10.0.4.233
+ A 10.0.4.234
+ A 10.0.4.235
+ A 10.0.4.236
+ A 10.0.4.237
+ A 10.0.4.238
+ A 10.0.4.239
+ A 10.0.4.240
+ A 10.0.4.241
+ A 10.0.4.242
+ A 10.0.4.243
+ A 10.0.4.244
+ A 10.0.4.245
+ A 10.0.4.246
+ A 10.0.4.247
+ A 10.0.4.248
+ A 10.0.4.249
+ A 10.0.4.250
+ A 10.0.4.251
+ A 10.0.4.252
+ A 10.0.4.253
+ A 10.0.4.254
+ A 10.0.4.255
+ A 10.0.5.0
+ A 10.0.5.1
+ A 10.0.5.2
+ A 10.0.5.3
+ A 10.0.5.4
+ A 10.0.5.5
+ A 10.0.5.6
+ A 10.0.5.7
+ A 10.0.5.8
+ A 10.0.5.9
+ A 10.0.5.10
+ A 10.0.5.11
+ A 10.0.5.12
+ A 10.0.5.13
+ A 10.0.5.14
+ A 10.0.5.15
+ A 10.0.5.16
+ A 10.0.5.17
+ A 10.0.5.18
+ A 10.0.5.19
+ A 10.0.5.20
+ A 10.0.5.21
+ A 10.0.5.22
+ A 10.0.5.23
+ A 10.0.5.24
+ A 10.0.5.25
+ A 10.0.5.26
+ A 10.0.5.27
+ A 10.0.5.28
+ A 10.0.5.29
+ A 10.0.5.30
+ A 10.0.5.31
+ A 10.0.5.32
+ A 10.0.5.33
+ A 10.0.5.34
+ A 10.0.5.35
+ A 10.0.5.36
+ A 10.0.5.37
+ A 10.0.5.38
+ A 10.0.5.39
+ A 10.0.5.40
+ A 10.0.5.41
+ A 10.0.5.42
+ A 10.0.5.43
+ A 10.0.5.44
+ A 10.0.5.45
+ A 10.0.5.46
+ A 10.0.5.47
+ A 10.0.5.48
+ A 10.0.5.49
+ A 10.0.5.50
+ A 10.0.5.51
+ A 10.0.5.52
+ A 10.0.5.53
+ A 10.0.5.54
+ A 10.0.5.55
+ A 10.0.5.56
+ A 10.0.5.57
+ A 10.0.5.58
+ A 10.0.5.59
+ A 10.0.5.60
+ A 10.0.5.61
+ A 10.0.5.62
+ A 10.0.5.63
+ A 10.0.5.64
+ A 10.0.5.65
+ A 10.0.5.66
+ A 10.0.5.67
+ A 10.0.5.68
+ A 10.0.5.69
+ A 10.0.5.70
+ A 10.0.5.71
+ A 10.0.5.72
+ A 10.0.5.73
+ A 10.0.5.74
+ A 10.0.5.75
+ A 10.0.5.76
+ A 10.0.5.77
+ A 10.0.5.78
+ A 10.0.5.79
+ A 10.0.5.80
+ A 10.0.5.81
+ A 10.0.5.82
+ A 10.0.5.83
+ A 10.0.5.84
+ A 10.0.5.85
+ A 10.0.5.86
+ A 10.0.5.87
+ A 10.0.5.88
+ A 10.0.5.89
+ A 10.0.5.90
+ A 10.0.5.91
+ A 10.0.5.92
+ A 10.0.5.93
+ A 10.0.5.94
+ A 10.0.5.95
+ A 10.0.5.96
+ A 10.0.5.97
+ A 10.0.5.98
+ A 10.0.5.99
+ A 10.0.5.100
+ A 10.0.5.101
+ A 10.0.5.102
+ A 10.0.5.103
+ A 10.0.5.104
+ A 10.0.5.105
+ A 10.0.5.106
+ A 10.0.5.107
+ A 10.0.5.108
+ A 10.0.5.109
+ A 10.0.5.110
+ A 10.0.5.111
+ A 10.0.5.112
+ A 10.0.5.113
+ A 10.0.5.114
+ A 10.0.5.115
+ A 10.0.5.116
+ A 10.0.5.117
+ A 10.0.5.118
+ A 10.0.5.119
+ A 10.0.5.120
+ A 10.0.5.121
+ A 10.0.5.122
+ A 10.0.5.123
+ A 10.0.5.124
+ A 10.0.5.125
+ A 10.0.5.126
+ A 10.0.5.127
+ A 10.0.5.128
+ A 10.0.5.129
+ A 10.0.5.130
+ A 10.0.5.131
+ A 10.0.5.132
+ A 10.0.5.133
+ A 10.0.5.134
+ A 10.0.5.135
+ A 10.0.5.136
+ A 10.0.5.137
+ A 10.0.5.138
+ A 10.0.5.139
+ A 10.0.5.140
+ A 10.0.5.141
+ A 10.0.5.142
+ A 10.0.5.143
+ A 10.0.5.144
+ A 10.0.5.145
+ A 10.0.5.146
+ A 10.0.5.147
+ A 10.0.5.148
+ A 10.0.5.149
+ A 10.0.5.150
+ A 10.0.5.151
+ A 10.0.5.152
+ A 10.0.5.153
+ A 10.0.5.154
+ A 10.0.5.155
+ A 10.0.5.156
+ A 10.0.5.157
+ A 10.0.5.158
+ A 10.0.5.159
+ A 10.0.5.160
+ A 10.0.5.161
+ A 10.0.5.162
+ A 10.0.5.163
+ A 10.0.5.164
+ A 10.0.5.165
+ A 10.0.5.166
+ A 10.0.5.167
+ A 10.0.5.168
+ A 10.0.5.169
+ A 10.0.5.170
+ A 10.0.5.171
+ A 10.0.5.172
+ A 10.0.5.173
+ A 10.0.5.174
+ A 10.0.5.175
+ A 10.0.5.176
+ A 10.0.5.177
+ A 10.0.5.178
+ A 10.0.5.179
+ A 10.0.5.180
+ A 10.0.5.181
+ A 10.0.5.182
+ A 10.0.5.183
+ A 10.0.5.184
+ A 10.0.5.185
+ A 10.0.5.186
+ A 10.0.5.187
+ A 10.0.5.188
+ A 10.0.5.189
+ A 10.0.5.190
+ A 10.0.5.191
+ A 10.0.5.192
+ A 10.0.5.193
+ A 10.0.5.194
+ A 10.0.5.195
+ A 10.0.5.196
+ A 10.0.5.197
+ A 10.0.5.198
+ A 10.0.5.199
+ A 10.0.5.200
+ A 10.0.5.201
+ A 10.0.5.202
+ A 10.0.5.203
+ A 10.0.5.204
+ A 10.0.5.205
+ A 10.0.5.206
+ A 10.0.5.207
+ A 10.0.5.208
+ A 10.0.5.209
+ A 10.0.5.210
+ A 10.0.5.211
+ A 10.0.5.212
+ A 10.0.5.213
+ A 10.0.5.214
+ A 10.0.5.215
+ A 10.0.5.216
+ A 10.0.5.217
+ A 10.0.5.218
+ A 10.0.5.219
+ A 10.0.5.220
+ A 10.0.5.221
+ A 10.0.5.222
+ A 10.0.5.223
+ A 10.0.5.224
+ A 10.0.5.225
+ A 10.0.5.226
+ A 10.0.5.227
+ A 10.0.5.228
+ A 10.0.5.229
+ A 10.0.5.230
+ A 10.0.5.231
+ A 10.0.5.232
+ A 10.0.5.233
+ A 10.0.5.234
+ A 10.0.5.235
+ A 10.0.5.236
+ A 10.0.5.237
+ A 10.0.5.238
+ A 10.0.5.239
+ A 10.0.5.240
+ A 10.0.5.241
+ A 10.0.5.242
+ A 10.0.5.243
+ A 10.0.5.244
+ A 10.0.5.245
+ A 10.0.5.246
+ A 10.0.5.247
+ A 10.0.5.248
+ A 10.0.5.249
+ A 10.0.5.250
+ A 10.0.5.251
+ A 10.0.5.252
+ A 10.0.5.253
+ A 10.0.5.254
+ A 10.0.5.255
+ A 10.0.6.0
+ A 10.0.6.1
+ A 10.0.6.2
+ A 10.0.6.3
+ A 10.0.6.4
+ A 10.0.6.5
+ A 10.0.6.6
+ A 10.0.6.7
+ A 10.0.6.8
+ A 10.0.6.9
+ A 10.0.6.10
+ A 10.0.6.11
+ A 10.0.6.12
+ A 10.0.6.13
+ A 10.0.6.14
+ A 10.0.6.15
+ A 10.0.6.16
+ A 10.0.6.17
+ A 10.0.6.18
+ A 10.0.6.19
+ A 10.0.6.20
+ A 10.0.6.21
+ A 10.0.6.22
+ A 10.0.6.23
+ A 10.0.6.24
+ A 10.0.6.25
+ A 10.0.6.26
+ A 10.0.6.27
+ A 10.0.6.28
+ A 10.0.6.29
+ A 10.0.6.30
+ A 10.0.6.31
+ A 10.0.6.32
+ A 10.0.6.33
+ A 10.0.6.34
+ A 10.0.6.35
+ A 10.0.6.36
+ A 10.0.6.37
+ A 10.0.6.38
+ A 10.0.6.39
+ A 10.0.6.40
+ A 10.0.6.41
+ A 10.0.6.42
+ A 10.0.6.43
+ A 10.0.6.44
+ A 10.0.6.45
+ A 10.0.6.46
+ A 10.0.6.47
+ A 10.0.6.48
+ A 10.0.6.49
+ A 10.0.6.50
+ A 10.0.6.51
+ A 10.0.6.52
+ A 10.0.6.53
+ A 10.0.6.54
+ A 10.0.6.55
+ A 10.0.6.56
+ A 10.0.6.57
+ A 10.0.6.58
+ A 10.0.6.59
+ A 10.0.6.60
+ A 10.0.6.61
+ A 10.0.6.62
+ A 10.0.6.63
+ A 10.0.6.64
+ A 10.0.6.65
+ A 10.0.6.66
+ A 10.0.6.67
+ A 10.0.6.68
+ A 10.0.6.69
+ A 10.0.6.70
+ A 10.0.6.71
+ A 10.0.6.72
+ A 10.0.6.73
+ A 10.0.6.74
+ A 10.0.6.75
+ A 10.0.6.76
+ A 10.0.6.77
+ A 10.0.6.78
+ A 10.0.6.79
+ A 10.0.6.80
+ A 10.0.6.81
+ A 10.0.6.82
+ A 10.0.6.83
+ A 10.0.6.84
+ A 10.0.6.85
+ A 10.0.6.86
+ A 10.0.6.87
+ A 10.0.6.88
+ A 10.0.6.89
+ A 10.0.6.90
+ A 10.0.6.91
+ A 10.0.6.92
+ A 10.0.6.93
+ A 10.0.6.94
+ A 10.0.6.95
+ A 10.0.6.96
+ A 10.0.6.97
+ A 10.0.6.98
+ A 10.0.6.99
+ A 10.0.6.100
+ A 10.0.6.101
+ A 10.0.6.102
+ A 10.0.6.103
+ A 10.0.6.104
+ A 10.0.6.105
+ A 10.0.6.106
+ A 10.0.6.107
+ A 10.0.6.108
+ A 10.0.6.109
+ A 10.0.6.110
+ A 10.0.6.111
+ A 10.0.6.112
+ A 10.0.6.113
+ A 10.0.6.114
+ A 10.0.6.115
+ A 10.0.6.116
+ A 10.0.6.117
+ A 10.0.6.118
+ A 10.0.6.119
+ A 10.0.6.120
+ A 10.0.6.121
+ A 10.0.6.122
+ A 10.0.6.123
+ A 10.0.6.124
+ A 10.0.6.125
+ A 10.0.6.126
+ A 10.0.6.127
+ A 10.0.6.128
+ A 10.0.6.129
+ A 10.0.6.130
+ A 10.0.6.131
+ A 10.0.6.132
+ A 10.0.6.133
+ A 10.0.6.134
+ A 10.0.6.135
+ A 10.0.6.136
+ A 10.0.6.137
+ A 10.0.6.138
+ A 10.0.6.139
+ A 10.0.6.140
+ A 10.0.6.141
+ A 10.0.6.142
+ A 10.0.6.143
+ A 10.0.6.144
+ A 10.0.6.145
+ A 10.0.6.146
+ A 10.0.6.147
+ A 10.0.6.148
+ A 10.0.6.149
+ A 10.0.6.150
+ A 10.0.6.151
+ A 10.0.6.152
+ A 10.0.6.153
+ A 10.0.6.154
+ A 10.0.6.155
+ A 10.0.6.156
+ A 10.0.6.157
+ A 10.0.6.158
+ A 10.0.6.159
+ A 10.0.6.160
+ A 10.0.6.161
+ A 10.0.6.162
+ A 10.0.6.163
+ A 10.0.6.164
+ A 10.0.6.165
+ A 10.0.6.166
+ A 10.0.6.167
+ A 10.0.6.168
+ A 10.0.6.169
+ A 10.0.6.170
+ A 10.0.6.171
+ A 10.0.6.172
+ A 10.0.6.173
+ A 10.0.6.174
+ A 10.0.6.175
+ A 10.0.6.176
+ A 10.0.6.177
+ A 10.0.6.178
+ A 10.0.6.179
+ A 10.0.6.180
+ A 10.0.6.181
+ A 10.0.6.182
+ A 10.0.6.183
+ A 10.0.6.184
+ A 10.0.6.185
+ A 10.0.6.186
+ A 10.0.6.187
+ A 10.0.6.188
+ A 10.0.6.189
+ A 10.0.6.190
+ A 10.0.6.191
+ A 10.0.6.192
+ A 10.0.6.193
+ A 10.0.6.194
+ A 10.0.6.195
+ A 10.0.6.196
+ A 10.0.6.197
+ A 10.0.6.198
+ A 10.0.6.199
+ A 10.0.6.200
+ A 10.0.6.201
+ A 10.0.6.202
+ A 10.0.6.203
+ A 10.0.6.204
+ A 10.0.6.205
+ A 10.0.6.206
+ A 10.0.6.207
+ A 10.0.6.208
+ A 10.0.6.209
+ A 10.0.6.210
+ A 10.0.6.211
+ A 10.0.6.212
+ A 10.0.6.213
+ A 10.0.6.214
+ A 10.0.6.215
+ A 10.0.6.216
+ A 10.0.6.217
+ A 10.0.6.218
+ A 10.0.6.219
+ A 10.0.6.220
+ A 10.0.6.221
+ A 10.0.6.222
+ A 10.0.6.223
+ A 10.0.6.224
+ A 10.0.6.225
+ A 10.0.6.226
+ A 10.0.6.227
+ A 10.0.6.228
+ A 10.0.6.229
+ A 10.0.6.230
+ A 10.0.6.231
+ A 10.0.6.232
+ A 10.0.6.233
+ A 10.0.6.234
+ A 10.0.6.235
+ A 10.0.6.236
+ A 10.0.6.237
+ A 10.0.6.238
+ A 10.0.6.239
+ A 10.0.6.240
+ A 10.0.6.241
+ A 10.0.6.242
+ A 10.0.6.243
+ A 10.0.6.244
+ A 10.0.6.245
+ A 10.0.6.246
+ A 10.0.6.247
+ A 10.0.6.248
+ A 10.0.6.249
+ A 10.0.6.250
+ A 10.0.6.251
+ A 10.0.6.252
+ A 10.0.6.253
+ A 10.0.6.254
+ A 10.0.6.255
+ A 10.0.7.0
+ A 10.0.7.1
+ A 10.0.7.2
+ A 10.0.7.3
+ A 10.0.7.4
+ A 10.0.7.5
+ A 10.0.7.6
+ A 10.0.7.7
+ A 10.0.7.8
+ A 10.0.7.9
+ A 10.0.7.10
+ A 10.0.7.11
+ A 10.0.7.12
+ A 10.0.7.13
+ A 10.0.7.14
+ A 10.0.7.15
+ A 10.0.7.16
+ A 10.0.7.17
+ A 10.0.7.18
+ A 10.0.7.19
+ A 10.0.7.20
+ A 10.0.7.21
+ A 10.0.7.22
+ A 10.0.7.23
+ A 10.0.7.24
+ A 10.0.7.25
+ A 10.0.7.26
+ A 10.0.7.27
+ A 10.0.7.28
+ A 10.0.7.29
+ A 10.0.7.30
+ A 10.0.7.31
+ A 10.0.7.32
+ A 10.0.7.33
+ A 10.0.7.34
+ A 10.0.7.35
+ A 10.0.7.36
+ A 10.0.7.37
+ A 10.0.7.38
+ A 10.0.7.39
+ A 10.0.7.40
+ A 10.0.7.41
+ A 10.0.7.42
+ A 10.0.7.43
+ A 10.0.7.44
+ A 10.0.7.45
+ A 10.0.7.46
+ A 10.0.7.47
+ A 10.0.7.48
+ A 10.0.7.49
+ A 10.0.7.50
+ A 10.0.7.51
+ A 10.0.7.52
+ A 10.0.7.53
+ A 10.0.7.54
+ A 10.0.7.55
+ A 10.0.7.56
+ A 10.0.7.57
+ A 10.0.7.58
+ A 10.0.7.59
+ A 10.0.7.60
+ A 10.0.7.61
+ A 10.0.7.62
+ A 10.0.7.63
+ A 10.0.7.64
+ A 10.0.7.65
+ A 10.0.7.66
+ A 10.0.7.67
+ A 10.0.7.68
+ A 10.0.7.69
+ A 10.0.7.70
+ A 10.0.7.71
+ A 10.0.7.72
+ A 10.0.7.73
+ A 10.0.7.74
+ A 10.0.7.75
+ A 10.0.7.76
+ A 10.0.7.77
+ A 10.0.7.78
+ A 10.0.7.79
+ A 10.0.7.80
+ A 10.0.7.81
+ A 10.0.7.82
+ A 10.0.7.83
+ A 10.0.7.84
+ A 10.0.7.85
+ A 10.0.7.86
+ A 10.0.7.87
+ A 10.0.7.88
+ A 10.0.7.89
+ A 10.0.7.90
+ A 10.0.7.91
+ A 10.0.7.92
+ A 10.0.7.93
+ A 10.0.7.94
+ A 10.0.7.95
+ A 10.0.7.96
+ A 10.0.7.97
+ A 10.0.7.98
+ A 10.0.7.99
+ A 10.0.7.100
+ A 10.0.7.101
+ A 10.0.7.102
+ A 10.0.7.103
+ A 10.0.7.104
+ A 10.0.7.105
+ A 10.0.7.106
+ A 10.0.7.107
+ A 10.0.7.108
+ A 10.0.7.109
+ A 10.0.7.110
+ A 10.0.7.111
+ A 10.0.7.112
+ A 10.0.7.113
+ A 10.0.7.114
+ A 10.0.7.115
+ A 10.0.7.116
+ A 10.0.7.117
+ A 10.0.7.118
+ A 10.0.7.119
+ A 10.0.7.120
+ A 10.0.7.121
+ A 10.0.7.122
+ A 10.0.7.123
+ A 10.0.7.124
+ A 10.0.7.125
+ A 10.0.7.126
+ A 10.0.7.127
+ A 10.0.7.128
+ A 10.0.7.129
+ A 10.0.7.130
+ A 10.0.7.131
+ A 10.0.7.132
+ A 10.0.7.133
+ A 10.0.7.134
+ A 10.0.7.135
+ A 10.0.7.136
+ A 10.0.7.137
+ A 10.0.7.138
+ A 10.0.7.139
+ A 10.0.7.140
+ A 10.0.7.141
+ A 10.0.7.142
+ A 10.0.7.143
+ A 10.0.7.144
+ A 10.0.7.145
+ A 10.0.7.146
+ A 10.0.7.147
+ A 10.0.7.148
+ A 10.0.7.149
+ A 10.0.7.150
+ A 10.0.7.151
+ A 10.0.7.152
+ A 10.0.7.153
+ A 10.0.7.154
+ A 10.0.7.155
+ A 10.0.7.156
+ A 10.0.7.157
+ A 10.0.7.158
+ A 10.0.7.159
+ A 10.0.7.160
+ A 10.0.7.161
+ A 10.0.7.162
+ A 10.0.7.163
+ A 10.0.7.164
+ A 10.0.7.165
+ A 10.0.7.166
+ A 10.0.7.167
+ A 10.0.7.168
+ A 10.0.7.169
+ A 10.0.7.170
+ A 10.0.7.171
+ A 10.0.7.172
+ A 10.0.7.173
+ A 10.0.7.174
+ A 10.0.7.175
+ A 10.0.7.176
+ A 10.0.7.177
+ A 10.0.7.178
+ A 10.0.7.179
+ A 10.0.7.180
+ A 10.0.7.181
+ A 10.0.7.182
+ A 10.0.7.183
+ A 10.0.7.184
+ A 10.0.7.185
+ A 10.0.7.186
+ A 10.0.7.187
+ A 10.0.7.188
+ A 10.0.7.189
+ A 10.0.7.190
+ A 10.0.7.191
+ A 10.0.7.192
+ A 10.0.7.193
+ A 10.0.7.194
+ A 10.0.7.195
+ A 10.0.7.196
+ A 10.0.7.197
+ A 10.0.7.198
+ A 10.0.7.199
+ A 10.0.7.200
+ A 10.0.7.201
+ A 10.0.7.202
+ A 10.0.7.203
+ A 10.0.7.204
+ A 10.0.7.205
+ A 10.0.7.206
+ A 10.0.7.207
+ A 10.0.7.208
+ A 10.0.7.209
+ A 10.0.7.210
+ A 10.0.7.211
+ A 10.0.7.212
+ A 10.0.7.213
+ A 10.0.7.214
+ A 10.0.7.215
+ A 10.0.7.216
+ A 10.0.7.217
+ A 10.0.7.218
+ A 10.0.7.219
+ A 10.0.7.220
+ A 10.0.7.221
+ A 10.0.7.222
+ A 10.0.7.223
+ A 10.0.7.224
+ A 10.0.7.225
+ A 10.0.7.226
+ A 10.0.7.227
+ A 10.0.7.228
+ A 10.0.7.229
+ A 10.0.7.230
+ A 10.0.7.231
+ A 10.0.7.232
+ A 10.0.7.233
+ A 10.0.7.234
+ A 10.0.7.235
+ A 10.0.7.236
+ A 10.0.7.237
+ A 10.0.7.238
+ A 10.0.7.239
+ A 10.0.7.240
+ A 10.0.7.241
+ A 10.0.7.242
+ A 10.0.7.243
+ A 10.0.7.244
+ A 10.0.7.245
+ A 10.0.7.246
+ A 10.0.7.247
+ A 10.0.7.248
+ A 10.0.7.249
+ A 10.0.7.250
+ A 10.0.7.251
+ A 10.0.7.252
+ A 10.0.7.253
+ A 10.0.7.254
+ A 10.0.7.255
+ A 10.0.8.0
+ A 10.0.8.1
+ A 10.0.8.2
+ A 10.0.8.3
+ A 10.0.8.4
+ A 10.0.8.5
+ A 10.0.8.6
+ A 10.0.8.7
+ A 10.0.8.8
+ A 10.0.8.9
+ A 10.0.8.10
+ A 10.0.8.11
+ A 10.0.8.12
+ A 10.0.8.13
+ A 10.0.8.14
+ A 10.0.8.15
+ A 10.0.8.16
+ A 10.0.8.17
+ A 10.0.8.18
+ A 10.0.8.19
+ A 10.0.8.20
+ A 10.0.8.21
+ A 10.0.8.22
+ A 10.0.8.23
+ A 10.0.8.24
+ A 10.0.8.25
+ A 10.0.8.26
+ A 10.0.8.27
+ A 10.0.8.28
+ A 10.0.8.29
+ A 10.0.8.30
+ A 10.0.8.31
+ A 10.0.8.32
+ A 10.0.8.33
+ A 10.0.8.34
+ A 10.0.8.35
+ A 10.0.8.36
+ A 10.0.8.37
+ A 10.0.8.38
+ A 10.0.8.39
+ A 10.0.8.40
+ A 10.0.8.41
+ A 10.0.8.42
+ A 10.0.8.43
+ A 10.0.8.44
+ A 10.0.8.45
+ A 10.0.8.46
+ A 10.0.8.47
+ A 10.0.8.48
+ A 10.0.8.49
+ A 10.0.8.50
+ A 10.0.8.51
+ A 10.0.8.52
+ A 10.0.8.53
+ A 10.0.8.54
+ A 10.0.8.55
+ A 10.0.8.56
+ A 10.0.8.57
+ A 10.0.8.58
+ A 10.0.8.59
+ A 10.0.8.60
+ A 10.0.8.61
+ A 10.0.8.62
+ A 10.0.8.63
+ A 10.0.8.64
+ A 10.0.8.65
+ A 10.0.8.66
+ A 10.0.8.67
+ A 10.0.8.68
+ A 10.0.8.69
+ A 10.0.8.70
+ A 10.0.8.71
+ A 10.0.8.72
+ A 10.0.8.73
+ A 10.0.8.74
+ A 10.0.8.75
+ A 10.0.8.76
+ A 10.0.8.77
+ A 10.0.8.78
+ A 10.0.8.79
+ A 10.0.8.80
+ A 10.0.8.81
+ A 10.0.8.82
+ A 10.0.8.83
+ A 10.0.8.84
+ A 10.0.8.85
+ A 10.0.8.86
+ A 10.0.8.87
+ A 10.0.8.88
+ A 10.0.8.89
+ A 10.0.8.90
+ A 10.0.8.91
+ A 10.0.8.92
+ A 10.0.8.93
+ A 10.0.8.94
+ A 10.0.8.95
+ A 10.0.8.96
+ A 10.0.8.97
+ A 10.0.8.98
+ A 10.0.8.99
+ A 10.0.8.100
+ A 10.0.8.101
+ A 10.0.8.102
+ A 10.0.8.103
+ A 10.0.8.104
+ A 10.0.8.105
+ A 10.0.8.106
+ A 10.0.8.107
+ A 10.0.8.108
+ A 10.0.8.109
+ A 10.0.8.110
+ A 10.0.8.111
+ A 10.0.8.112
+ A 10.0.8.113
+ A 10.0.8.114
+ A 10.0.8.115
+ A 10.0.8.116
+ A 10.0.8.117
+ A 10.0.8.118
+ A 10.0.8.119
+ A 10.0.8.120
+ A 10.0.8.121
+ A 10.0.8.122
+ A 10.0.8.123
+ A 10.0.8.124
+ A 10.0.8.125
+ A 10.0.8.126
+ A 10.0.8.127
+ A 10.0.8.128
+ A 10.0.8.129
+ A 10.0.8.130
+ A 10.0.8.131
+ A 10.0.8.132
+ A 10.0.8.133
+ A 10.0.8.134
+ A 10.0.8.135
+ A 10.0.8.136
+ A 10.0.8.137
+ A 10.0.8.138
+ A 10.0.8.139
+ A 10.0.8.140
+ A 10.0.8.141
+ A 10.0.8.142
+ A 10.0.8.143
+ A 10.0.8.144
+ A 10.0.8.145
+ A 10.0.8.146
+ A 10.0.8.147
+ A 10.0.8.148
+ A 10.0.8.149
+ A 10.0.8.150
+ A 10.0.8.151
+ A 10.0.8.152
+ A 10.0.8.153
+ A 10.0.8.154
+ A 10.0.8.155
+ A 10.0.8.156
+ A 10.0.8.157
+ A 10.0.8.158
+ A 10.0.8.159
+ A 10.0.8.160
+ A 10.0.8.161
+ A 10.0.8.162
+ A 10.0.8.163
+ A 10.0.8.164
+ A 10.0.8.165
+ A 10.0.8.166
+ A 10.0.8.167
+ A 10.0.8.168
+ A 10.0.8.169
+ A 10.0.8.170
+ A 10.0.8.171
+ A 10.0.8.172
+ A 10.0.8.173
+ A 10.0.8.174
+ A 10.0.8.175
+ A 10.0.8.176
+ A 10.0.8.177
+ A 10.0.8.178
+ A 10.0.8.179
+ A 10.0.8.180
+ A 10.0.8.181
+ A 10.0.8.182
+ A 10.0.8.183
+ A 10.0.8.184
+ A 10.0.8.185
+ A 10.0.8.186
+ A 10.0.8.187
+ A 10.0.8.188
+ A 10.0.8.189
+ A 10.0.8.190
+ A 10.0.8.191
+ A 10.0.8.192
+ A 10.0.8.193
+ A 10.0.8.194
+ A 10.0.8.195
+ A 10.0.8.196
+ A 10.0.8.197
+ A 10.0.8.198
+ A 10.0.8.199
+ A 10.0.8.200
+ A 10.0.8.201
+ A 10.0.8.202
+ A 10.0.8.203
+ A 10.0.8.204
+ A 10.0.8.205
+ A 10.0.8.206
+ A 10.0.8.207
+ A 10.0.8.208
+ A 10.0.8.209
+ A 10.0.8.210
+ A 10.0.8.211
+ A 10.0.8.212
+ A 10.0.8.213
+ A 10.0.8.214
+ A 10.0.8.215
+ A 10.0.8.216
+ A 10.0.8.217
+ A 10.0.8.218
+ A 10.0.8.219
+ A 10.0.8.220
+ A 10.0.8.221
+ A 10.0.8.222
+ A 10.0.8.223
+ A 10.0.8.224
+ A 10.0.8.225
+ A 10.0.8.226
+ A 10.0.8.227
+ A 10.0.8.228
+ A 10.0.8.229
+ A 10.0.8.230
+ A 10.0.8.231
+ A 10.0.8.232
+ A 10.0.8.233
+ A 10.0.8.234
+ A 10.0.8.235
+ A 10.0.8.236
+ A 10.0.8.237
+ A 10.0.8.238
+ A 10.0.8.239
+ A 10.0.8.240
+ A 10.0.8.241
+ A 10.0.8.242
+ A 10.0.8.243
+ A 10.0.8.244
+ A 10.0.8.245
+ A 10.0.8.246
+ A 10.0.8.247
+ A 10.0.8.248
+ A 10.0.8.249
+ A 10.0.8.250
+ A 10.0.8.251
+ A 10.0.8.252
+ A 10.0.8.253
+ A 10.0.8.254
+ A 10.0.8.255
+ A 10.0.9.0
+ A 10.0.9.1
+ A 10.0.9.2
+ A 10.0.9.3
+ A 10.0.9.4
+ A 10.0.9.5
+ A 10.0.9.6
+ A 10.0.9.7
+ A 10.0.9.8
+ A 10.0.9.9
+ A 10.0.9.10
+ A 10.0.9.11
+ A 10.0.9.12
+ A 10.0.9.13
+ A 10.0.9.14
+ A 10.0.9.15
+ A 10.0.9.16
+ A 10.0.9.17
+ A 10.0.9.18
+ A 10.0.9.19
+ A 10.0.9.20
+ A 10.0.9.21
+ A 10.0.9.22
+ A 10.0.9.23
+ A 10.0.9.24
+ A 10.0.9.25
+ A 10.0.9.26
+ A 10.0.9.27
+ A 10.0.9.28
+ A 10.0.9.29
+ A 10.0.9.30
+ A 10.0.9.31
+ A 10.0.9.32
+ A 10.0.9.33
+ A 10.0.9.34
+ A 10.0.9.35
+ A 10.0.9.36
+ A 10.0.9.37
+ A 10.0.9.38
+ A 10.0.9.39
+ A 10.0.9.40
+ A 10.0.9.41
+ A 10.0.9.42
+ A 10.0.9.43
+ A 10.0.9.44
+ A 10.0.9.45
+ A 10.0.9.46
+ A 10.0.9.47
+ A 10.0.9.48
+ A 10.0.9.49
+ A 10.0.9.50
+ A 10.0.9.51
+ A 10.0.9.52
+ A 10.0.9.53
+ A 10.0.9.54
+ A 10.0.9.55
+ A 10.0.9.56
+ A 10.0.9.57
+ A 10.0.9.58
+ A 10.0.9.59
+ A 10.0.9.60
+ A 10.0.9.61
+ A 10.0.9.62
+ A 10.0.9.63
+ A 10.0.9.64
+ A 10.0.9.65
+ A 10.0.9.66
+ A 10.0.9.67
+ A 10.0.9.68
+ A 10.0.9.69
+ A 10.0.9.70
+ A 10.0.9.71
+ A 10.0.9.72
+ A 10.0.9.73
+ A 10.0.9.74
+ A 10.0.9.75
+ A 10.0.9.76
+ A 10.0.9.77
+ A 10.0.9.78
+ A 10.0.9.79
+ A 10.0.9.80
+ A 10.0.9.81
+ A 10.0.9.82
+ A 10.0.9.83
+ A 10.0.9.84
+ A 10.0.9.85
+ A 10.0.9.86
+ A 10.0.9.87
+ A 10.0.9.88
+ A 10.0.9.89
+ A 10.0.9.90
+ A 10.0.9.91
+ A 10.0.9.92
+ A 10.0.9.93
+ A 10.0.9.94
+ A 10.0.9.95
+ A 10.0.9.96
+ A 10.0.9.97
+ A 10.0.9.98
+ A 10.0.9.99
+ A 10.0.9.100
+ A 10.0.9.101
+ A 10.0.9.102
+ A 10.0.9.103
+ A 10.0.9.104
+ A 10.0.9.105
+ A 10.0.9.106
+ A 10.0.9.107
+ A 10.0.9.108
+ A 10.0.9.109
+ A 10.0.9.110
+ A 10.0.9.111
+ A 10.0.9.112
+ A 10.0.9.113
+ A 10.0.9.114
+ A 10.0.9.115
+ A 10.0.9.116
+ A 10.0.9.117
+ A 10.0.9.118
+ A 10.0.9.119
+ A 10.0.9.120
+ A 10.0.9.121
+ A 10.0.9.122
+ A 10.0.9.123
+ A 10.0.9.124
+ A 10.0.9.125
+ A 10.0.9.126
+ A 10.0.9.127
+ A 10.0.9.128
+ A 10.0.9.129
+ A 10.0.9.130
+ A 10.0.9.131
+ A 10.0.9.132
+ A 10.0.9.133
+ A 10.0.9.134
+ A 10.0.9.135
+ A 10.0.9.136
+ A 10.0.9.137
+ A 10.0.9.138
+ A 10.0.9.139
+ A 10.0.9.140
+ A 10.0.9.141
+ A 10.0.9.142
+ A 10.0.9.143
+ A 10.0.9.144
+ A 10.0.9.145
+ A 10.0.9.146
+ A 10.0.9.147
+ A 10.0.9.148
+ A 10.0.9.149
+ A 10.0.9.150
+ A 10.0.9.151
+ A 10.0.9.152
+ A 10.0.9.153
+ A 10.0.9.154
+ A 10.0.9.155
+ A 10.0.9.156
+ A 10.0.9.157
+ A 10.0.9.158
+ A 10.0.9.159
+ A 10.0.9.160
+ A 10.0.9.161
+ A 10.0.9.162
+ A 10.0.9.163
+ A 10.0.9.164
+ A 10.0.9.165
+ A 10.0.9.166
+ A 10.0.9.167
+ A 10.0.9.168
+ A 10.0.9.169
+ A 10.0.9.170
+ A 10.0.9.171
+ A 10.0.9.172
+ A 10.0.9.173
+ A 10.0.9.174
+ A 10.0.9.175
+ A 10.0.9.176
+ A 10.0.9.177
+ A 10.0.9.178
+ A 10.0.9.179
+ A 10.0.9.180
+ A 10.0.9.181
+ A 10.0.9.182
+ A 10.0.9.183
+ A 10.0.9.184
+ A 10.0.9.185
+ A 10.0.9.186
+ A 10.0.9.187
+ A 10.0.9.188
+ A 10.0.9.189
+ A 10.0.9.190
+ A 10.0.9.191
+ A 10.0.9.192
+ A 10.0.9.193
+ A 10.0.9.194
+ A 10.0.9.195
+ A 10.0.9.196
+ A 10.0.9.197
+ A 10.0.9.198
+ A 10.0.9.199
+ A 10.0.9.200
+ A 10.0.9.201
+ A 10.0.9.202
+ A 10.0.9.203
+ A 10.0.9.204
+ A 10.0.9.205
+ A 10.0.9.206
+ A 10.0.9.207
+ A 10.0.9.208
+ A 10.0.9.209
+ A 10.0.9.210
+ A 10.0.9.211
+ A 10.0.9.212
+ A 10.0.9.213
+ A 10.0.9.214
+ A 10.0.9.215
+ A 10.0.9.216
+ A 10.0.9.217
+ A 10.0.9.218
+ A 10.0.9.219
+ A 10.0.9.220
+ A 10.0.9.221
+ A 10.0.9.222
+ A 10.0.9.223
+ A 10.0.9.224
+ A 10.0.9.225
+ A 10.0.9.226
+ A 10.0.9.227
+ A 10.0.9.228
+ A 10.0.9.229
+ A 10.0.9.230
+ A 10.0.9.231
+ A 10.0.9.232
+ A 10.0.9.233
+ A 10.0.9.234
+ A 10.0.9.235
+ A 10.0.9.236
+ A 10.0.9.237
+ A 10.0.9.238
+ A 10.0.9.239
+ A 10.0.9.240
+ A 10.0.9.241
+ A 10.0.9.242
+ A 10.0.9.243
+ A 10.0.9.244
+ A 10.0.9.245
+ A 10.0.9.246
+ A 10.0.9.247
+ A 10.0.9.248
+ A 10.0.9.249
+ A 10.0.9.250
+ A 10.0.9.251
+ A 10.0.9.252
+ A 10.0.9.253
+ A 10.0.9.254
+ A 10.0.9.255
+ A 10.0.10.0
+ A 10.0.10.1
+ A 10.0.10.2
+ A 10.0.10.3
+ A 10.0.10.4
+ A 10.0.10.5
+ A 10.0.10.6
+ A 10.0.10.7
+ A 10.0.10.8
+ A 10.0.10.9
+ A 10.0.10.10
+ A 10.0.10.11
+ A 10.0.10.12
+ A 10.0.10.13
+ A 10.0.10.14
+ A 10.0.10.15
+ A 10.0.10.16
+ A 10.0.10.17
+ A 10.0.10.18
+ A 10.0.10.19
+ A 10.0.10.20
+ A 10.0.10.21
+ A 10.0.10.22
+ A 10.0.10.23
+ A 10.0.10.24
+ A 10.0.10.25
+ A 10.0.10.26
+ A 10.0.10.27
+ A 10.0.10.28
+ A 10.0.10.29
+ A 10.0.10.30
+ A 10.0.10.31
+ A 10.0.10.32
+ A 10.0.10.33
+ A 10.0.10.34
+ A 10.0.10.35
+ A 10.0.10.36
+ A 10.0.10.37
+ A 10.0.10.38
+ A 10.0.10.39
+ A 10.0.10.40
+ A 10.0.10.41
+ A 10.0.10.42
+ A 10.0.10.43
+ A 10.0.10.44
+ A 10.0.10.45
+ A 10.0.10.46
+ A 10.0.10.47
+ A 10.0.10.48
+ A 10.0.10.49
+ A 10.0.10.50
+ A 10.0.10.51
+ A 10.0.10.52
+ A 10.0.10.53
+ A 10.0.10.54
+ A 10.0.10.55
+ A 10.0.10.56
+ A 10.0.10.57
+ A 10.0.10.58
+ A 10.0.10.59
+ A 10.0.10.60
+ A 10.0.10.61
+ A 10.0.10.62
+ A 10.0.10.63
+ A 10.0.10.64
+ A 10.0.10.65
+ A 10.0.10.66
+ A 10.0.10.67
+ A 10.0.10.68
+ A 10.0.10.69
+ A 10.0.10.70
+ A 10.0.10.71
+ A 10.0.10.72
+ A 10.0.10.73
+ A 10.0.10.74
+ A 10.0.10.75
+ A 10.0.10.76
+ A 10.0.10.77
+ A 10.0.10.78
+ A 10.0.10.79
+ A 10.0.10.80
+ A 10.0.10.81
+ A 10.0.10.82
+ A 10.0.10.83
+ A 10.0.10.84
+ A 10.0.10.85
+ A 10.0.10.86
+ A 10.0.10.87
+ A 10.0.10.88
+ A 10.0.10.89
+ A 10.0.10.90
+ A 10.0.10.91
+ A 10.0.10.92
+ A 10.0.10.93
+ A 10.0.10.94
+ A 10.0.10.95
+ A 10.0.10.96
+ A 10.0.10.97
+ A 10.0.10.98
+ A 10.0.10.99
+ A 10.0.10.100
+ A 10.0.10.101
+ A 10.0.10.102
+ A 10.0.10.103
+ A 10.0.10.104
+ A 10.0.10.105
+ A 10.0.10.106
+ A 10.0.10.107
+ A 10.0.10.108
+ A 10.0.10.109
+ A 10.0.10.110
+ A 10.0.10.111
+ A 10.0.10.112
+ A 10.0.10.113
+ A 10.0.10.114
+ A 10.0.10.115
+ A 10.0.10.116
+ A 10.0.10.117
+ A 10.0.10.118
+ A 10.0.10.119
+ A 10.0.10.120
+ A 10.0.10.121
+ A 10.0.10.122
+ A 10.0.10.123
+ A 10.0.10.124
+ A 10.0.10.125
+ A 10.0.10.126
+ A 10.0.10.127
+ A 10.0.10.128
+ A 10.0.10.129
+ A 10.0.10.130
+ A 10.0.10.131
+ A 10.0.10.132
+ A 10.0.10.133
+ A 10.0.10.134
+ A 10.0.10.135
+ A 10.0.10.136
+ A 10.0.10.137
+ A 10.0.10.138
+ A 10.0.10.139
+ A 10.0.10.140
+ A 10.0.10.141
+ A 10.0.10.142
+ A 10.0.10.143
+ A 10.0.10.144
+ A 10.0.10.145
+ A 10.0.10.146
+ A 10.0.10.147
+ A 10.0.10.148
+ A 10.0.10.149
+ A 10.0.10.150
+ A 10.0.10.151
+ A 10.0.10.152
+ A 10.0.10.153
+ A 10.0.10.154
+ A 10.0.10.155
+ A 10.0.10.156
+ A 10.0.10.157
+ A 10.0.10.158
+ A 10.0.10.159
+ A 10.0.10.160
+ A 10.0.10.161
+ A 10.0.10.162
+ A 10.0.10.163
+ A 10.0.10.164
+ A 10.0.10.165
+ A 10.0.10.166
+ A 10.0.10.167
+ A 10.0.10.168
+ A 10.0.10.169
+ A 10.0.10.170
+ A 10.0.10.171
+ A 10.0.10.172
+ A 10.0.10.173
+ A 10.0.10.174
+ A 10.0.10.175
+ A 10.0.10.176
+ A 10.0.10.177
+ A 10.0.10.178
+ A 10.0.10.179
+ A 10.0.10.180
+ A 10.0.10.181
+ A 10.0.10.182
+ A 10.0.10.183
+ A 10.0.10.184
+ A 10.0.10.185
+ A 10.0.10.186
+ A 10.0.10.187
+ A 10.0.10.188
+ A 10.0.10.189
+ A 10.0.10.190
+ A 10.0.10.191
+ A 10.0.10.192
+ A 10.0.10.193
+ A 10.0.10.194
+ A 10.0.10.195
+ A 10.0.10.196
+ A 10.0.10.197
+ A 10.0.10.198
+ A 10.0.10.199
+ A 10.0.10.200
+ A 10.0.10.201
+ A 10.0.10.202
+ A 10.0.10.203
+ A 10.0.10.204
+ A 10.0.10.205
+ A 10.0.10.206
+ A 10.0.10.207
+ A 10.0.10.208
+ A 10.0.10.209
+ A 10.0.10.210
+ A 10.0.10.211
+ A 10.0.10.212
+ A 10.0.10.213
+ A 10.0.10.214
+ A 10.0.10.215
+ A 10.0.10.216
+ A 10.0.10.217
+ A 10.0.10.218
+ A 10.0.10.219
+ A 10.0.10.220
+ A 10.0.10.221
+ A 10.0.10.222
+ A 10.0.10.223
+ A 10.0.10.224
+ A 10.0.10.225
+ A 10.0.10.226
+ A 10.0.10.227
+ A 10.0.10.228
+ A 10.0.10.229
+ A 10.0.10.230
+ A 10.0.10.231
+ A 10.0.10.232
+ A 10.0.10.233
+ A 10.0.10.234
+ A 10.0.10.235
+ A 10.0.10.236
+ A 10.0.10.237
+ A 10.0.10.238
+ A 10.0.10.239
+ A 10.0.10.240
+ A 10.0.10.241
+ A 10.0.10.242
+ A 10.0.10.243
+ A 10.0.10.244
+ A 10.0.10.245
+ A 10.0.10.246
+ A 10.0.10.247
+ A 10.0.10.248
+ A 10.0.10.249
+ A 10.0.10.250
+ A 10.0.10.251
+ A 10.0.10.252
+ A 10.0.10.253
+ A 10.0.10.254
+ A 10.0.10.255
+ A 10.0.11.0
+ A 10.0.11.1
+ A 10.0.11.2
+ A 10.0.11.3
+ A 10.0.11.4
+ A 10.0.11.5
+ A 10.0.11.6
+ A 10.0.11.7
+ A 10.0.11.8
+ A 10.0.11.9
+ A 10.0.11.10
+ A 10.0.11.11
+ A 10.0.11.12
+ A 10.0.11.13
+ A 10.0.11.14
+ A 10.0.11.15
+ A 10.0.11.16
+ A 10.0.11.17
+ A 10.0.11.18
+ A 10.0.11.19
+ A 10.0.11.20
+ A 10.0.11.21
+ A 10.0.11.22
+ A 10.0.11.23
+ A 10.0.11.24
+ A 10.0.11.25
+ A 10.0.11.26
+ A 10.0.11.27
+ A 10.0.11.28
+ A 10.0.11.29
+ A 10.0.11.30
+ A 10.0.11.31
+ A 10.0.11.32
+ A 10.0.11.33
+ A 10.0.11.34
+ A 10.0.11.35
+ A 10.0.11.36
+ A 10.0.11.37
+ A 10.0.11.38
+ A 10.0.11.39
+ A 10.0.11.40
+ A 10.0.11.41
+ A 10.0.11.42
+ A 10.0.11.43
+ A 10.0.11.44
+ A 10.0.11.45
+ A 10.0.11.46
+ A 10.0.11.47
+ A 10.0.11.48
+ A 10.0.11.49
+ A 10.0.11.50
+ A 10.0.11.51
+ A 10.0.11.52
+ A 10.0.11.53
+ A 10.0.11.54
+ A 10.0.11.55
+ A 10.0.11.56
+ A 10.0.11.57
+ A 10.0.11.58
+ A 10.0.11.59
+ A 10.0.11.60
+ A 10.0.11.61
+ A 10.0.11.62
+ A 10.0.11.63
+ A 10.0.11.64
+ A 10.0.11.65
+ A 10.0.11.66
+ A 10.0.11.67
+ A 10.0.11.68
+ A 10.0.11.69
+ A 10.0.11.70
+ A 10.0.11.71
+ A 10.0.11.72
+ A 10.0.11.73
+ A 10.0.11.74
+ A 10.0.11.75
+ A 10.0.11.76
+ A 10.0.11.77
+ A 10.0.11.78
+ A 10.0.11.79
+ A 10.0.11.80
+ A 10.0.11.81
+ A 10.0.11.82
+ A 10.0.11.83
+ A 10.0.11.84
+ A 10.0.11.85
+ A 10.0.11.86
+ A 10.0.11.87
+ A 10.0.11.88
+ A 10.0.11.89
+ A 10.0.11.90
+ A 10.0.11.91
+ A 10.0.11.92
+ A 10.0.11.93
+ A 10.0.11.94
+ A 10.0.11.95
+ A 10.0.11.96
+ A 10.0.11.97
+ A 10.0.11.98
+ A 10.0.11.99
+ A 10.0.11.100
+ A 10.0.11.101
+ A 10.0.11.102
+ A 10.0.11.103
+ A 10.0.11.104
+ A 10.0.11.105
+ A 10.0.11.106
+ A 10.0.11.107
+ A 10.0.11.108
+ A 10.0.11.109
+ A 10.0.11.110
+ A 10.0.11.111
+ A 10.0.11.112
+ A 10.0.11.113
+ A 10.0.11.114
+ A 10.0.11.115
+ A 10.0.11.116
+ A 10.0.11.117
+ A 10.0.11.118
+ A 10.0.11.119
+ A 10.0.11.120
+ A 10.0.11.121
+ A 10.0.11.122
+ A 10.0.11.123
+ A 10.0.11.124
+ A 10.0.11.125
+ A 10.0.11.126
+ A 10.0.11.127
+ A 10.0.11.128
+ A 10.0.11.129
+ A 10.0.11.130
+ A 10.0.11.131
+ A 10.0.11.132
+ A 10.0.11.133
+ A 10.0.11.134
+ A 10.0.11.135
+ A 10.0.11.136
+ A 10.0.11.137
+ A 10.0.11.138
+ A 10.0.11.139
+ A 10.0.11.140
+ A 10.0.11.141
+ A 10.0.11.142
+ A 10.0.11.143
+ A 10.0.11.144
+ A 10.0.11.145
+ A 10.0.11.146
+ A 10.0.11.147
+ A 10.0.11.148
+ A 10.0.11.149
+ A 10.0.11.150
+ A 10.0.11.151
+ A 10.0.11.152
+ A 10.0.11.153
+ A 10.0.11.154
+ A 10.0.11.155
+ A 10.0.11.156
+ A 10.0.11.157
+ A 10.0.11.158
+ A 10.0.11.159
+ A 10.0.11.160
+ A 10.0.11.161
+ A 10.0.11.162
+ A 10.0.11.163
+ A 10.0.11.164
+ A 10.0.11.165
+ A 10.0.11.166
+ A 10.0.11.167
+ A 10.0.11.168
+ A 10.0.11.169
+ A 10.0.11.170
+ A 10.0.11.171
+ A 10.0.11.172
+ A 10.0.11.173
+ A 10.0.11.174
+ A 10.0.11.175
+ A 10.0.11.176
+ A 10.0.11.177
+ A 10.0.11.178
+ A 10.0.11.179
+ A 10.0.11.180
+ A 10.0.11.181
+ A 10.0.11.182
+ A 10.0.11.183
+ A 10.0.11.184
+ A 10.0.11.185
+ A 10.0.11.186
+ A 10.0.11.187
+ A 10.0.11.188
+ A 10.0.11.189
+ A 10.0.11.190
+ A 10.0.11.191
+ A 10.0.11.192
+ A 10.0.11.193
+ A 10.0.11.194
+ A 10.0.11.195
+ A 10.0.11.196
+ A 10.0.11.197
+ A 10.0.11.198
+ A 10.0.11.199
+ A 10.0.11.200
+ A 10.0.11.201
+ A 10.0.11.202
+ A 10.0.11.203
+ A 10.0.11.204
+ A 10.0.11.205
+ A 10.0.11.206
+ A 10.0.11.207
+ A 10.0.11.208
+ A 10.0.11.209
+ A 10.0.11.210
+ A 10.0.11.211
+ A 10.0.11.212
+ A 10.0.11.213
+ A 10.0.11.214
+ A 10.0.11.215
+ A 10.0.11.216
+ A 10.0.11.217
+ A 10.0.11.218
+ A 10.0.11.219
+ A 10.0.11.220
+ A 10.0.11.221
+ A 10.0.11.222
+ A 10.0.11.223
+ A 10.0.11.224
+ A 10.0.11.225
+ A 10.0.11.226
+ A 10.0.11.227
+ A 10.0.11.228
+ A 10.0.11.229
+ A 10.0.11.230
+ A 10.0.11.231
+ A 10.0.11.232
+ A 10.0.11.233
+ A 10.0.11.234
+ A 10.0.11.235
+ A 10.0.11.236
+ A 10.0.11.237
+ A 10.0.11.238
+ A 10.0.11.239
+ A 10.0.11.240
+ A 10.0.11.241
+ A 10.0.11.242
+ A 10.0.11.243
+ A 10.0.11.244
+ A 10.0.11.245
+ A 10.0.11.246
+ A 10.0.11.247
+ A 10.0.11.248
+ A 10.0.11.249
+ A 10.0.11.250
+ A 10.0.11.251
+ A 10.0.11.252
+ A 10.0.11.253
+ A 10.0.11.254
+ A 10.0.11.255
+ A 10.0.12.0
+ A 10.0.12.1
+ A 10.0.12.2
+ A 10.0.12.3
+ A 10.0.12.4
+ A 10.0.12.5
+ A 10.0.12.6
+ A 10.0.12.7
+ A 10.0.12.8
+ A 10.0.12.9
+ A 10.0.12.10
+ A 10.0.12.11
+ A 10.0.12.12
+ A 10.0.12.13
+ A 10.0.12.14
+ A 10.0.12.15
+ A 10.0.12.16
+ A 10.0.12.17
+ A 10.0.12.18
+ A 10.0.12.19
+ A 10.0.12.20
+ A 10.0.12.21
+ A 10.0.12.22
+ A 10.0.12.23
+ A 10.0.12.24
+ A 10.0.12.25
+ A 10.0.12.26
+ A 10.0.12.27
+ A 10.0.12.28
+ A 10.0.12.29
+ A 10.0.12.30
+ A 10.0.12.31
+ A 10.0.12.32
+ A 10.0.12.33
+ A 10.0.12.34
+ A 10.0.12.35
+ A 10.0.12.36
+ A 10.0.12.37
+ A 10.0.12.38
+ A 10.0.12.39
+ A 10.0.12.40
+ A 10.0.12.41
+ A 10.0.12.42
+ A 10.0.12.43
+ A 10.0.12.44
+ A 10.0.12.45
+ A 10.0.12.46
+ A 10.0.12.47
+ A 10.0.12.48
+ A 10.0.12.49
+ A 10.0.12.50
+ A 10.0.12.51
+ A 10.0.12.52
+ A 10.0.12.53
+ A 10.0.12.54
+ A 10.0.12.55
+ A 10.0.12.56
+ A 10.0.12.57
+ A 10.0.12.58
+ A 10.0.12.59
+ A 10.0.12.60
+ A 10.0.12.61
+ A 10.0.12.62
+ A 10.0.12.63
+ A 10.0.12.64
+ A 10.0.12.65
+ A 10.0.12.66
+ A 10.0.12.67
+ A 10.0.12.68
+ A 10.0.12.69
+ A 10.0.12.70
+ A 10.0.12.71
+ A 10.0.12.72
+ A 10.0.12.73
+ A 10.0.12.74
+ A 10.0.12.75
+ A 10.0.12.76
+ A 10.0.12.77
+ A 10.0.12.78
+ A 10.0.12.79
+ A 10.0.12.80
+ A 10.0.12.81
+ A 10.0.12.82
+ A 10.0.12.83
+ A 10.0.12.84
+ A 10.0.12.85
+ A 10.0.12.86
+ A 10.0.12.87
+ A 10.0.12.88
+ A 10.0.12.89
+ A 10.0.12.90
+ A 10.0.12.91
+ A 10.0.12.92
+ A 10.0.12.93
+ A 10.0.12.94
+ A 10.0.12.95
+ A 10.0.12.96
+ A 10.0.12.97
+ A 10.0.12.98
+ A 10.0.12.99
+ A 10.0.12.100
+ A 10.0.12.101
+ A 10.0.12.102
+ A 10.0.12.103
+ A 10.0.12.104
+ A 10.0.12.105
+ A 10.0.12.106
+ A 10.0.12.107
+ A 10.0.12.108
+ A 10.0.12.109
+ A 10.0.12.110
+ A 10.0.12.111
+ A 10.0.12.112
+ A 10.0.12.113
+ A 10.0.12.114
+ A 10.0.12.115
+ A 10.0.12.116
+ A 10.0.12.117
+ A 10.0.12.118
+ A 10.0.12.119
+ A 10.0.12.120
+ A 10.0.12.121
+ A 10.0.12.122
+ A 10.0.12.123
+ A 10.0.12.124
+ A 10.0.12.125
+ A 10.0.12.126
+ A 10.0.12.127
+ A 10.0.12.128
+ A 10.0.12.129
+ A 10.0.12.130
+ A 10.0.12.131
+ A 10.0.12.132
+ A 10.0.12.133
+ A 10.0.12.134
+ A 10.0.12.135
+ A 10.0.12.136
+ A 10.0.12.137
+ A 10.0.12.138
+ A 10.0.12.139
+ A 10.0.12.140
+ A 10.0.12.141
+ A 10.0.12.142
+ A 10.0.12.143
+ A 10.0.12.144
+ A 10.0.12.145
+ A 10.0.12.146
+ A 10.0.12.147
+ A 10.0.12.148
+ A 10.0.12.149
+ A 10.0.12.150
+ A 10.0.12.151
+ A 10.0.12.152
+ A 10.0.12.153
+ A 10.0.12.154
+ A 10.0.12.155
+ A 10.0.12.156
+ A 10.0.12.157
+ A 10.0.12.158
+ A 10.0.12.159
+ A 10.0.12.160
+ A 10.0.12.161
+ A 10.0.12.162
+ A 10.0.12.163
+ A 10.0.12.164
+ A 10.0.12.165
+ A 10.0.12.166
+ A 10.0.12.167
+ A 10.0.12.168
+ A 10.0.12.169
+ A 10.0.12.170
+ A 10.0.12.171
+ A 10.0.12.172
+ A 10.0.12.173
+ A 10.0.12.174
+ A 10.0.12.175
+ A 10.0.12.176
+ A 10.0.12.177
+ A 10.0.12.178
+ A 10.0.12.179
+ A 10.0.12.180
+ A 10.0.12.181
+ A 10.0.12.182
+ A 10.0.12.183
+ A 10.0.12.184
+ A 10.0.12.185
+ A 10.0.12.186
+ A 10.0.12.187
+ A 10.0.12.188
+ A 10.0.12.189
+ A 10.0.12.190
+ A 10.0.12.191
+ A 10.0.12.192
+ A 10.0.12.193
+ A 10.0.12.194
+ A 10.0.12.195
+ A 10.0.12.196
+ A 10.0.12.197
+ A 10.0.12.198
+ A 10.0.12.199
+ A 10.0.12.200
+ A 10.0.12.201
+ A 10.0.12.202
+ A 10.0.12.203
+ A 10.0.12.204
+ A 10.0.12.205
+ A 10.0.12.206
+ A 10.0.12.207
+ A 10.0.12.208
+ A 10.0.12.209
+ A 10.0.12.210
+ A 10.0.12.211
+ A 10.0.12.212
+ A 10.0.12.213
+ A 10.0.12.214
+ A 10.0.12.215
+ A 10.0.12.216
+ A 10.0.12.217
+ A 10.0.12.218
+ A 10.0.12.219
+ A 10.0.12.220
+ A 10.0.12.221
+ A 10.0.12.222
+ A 10.0.12.223
+ A 10.0.12.224
+ A 10.0.12.225
+ A 10.0.12.226
+ A 10.0.12.227
+ A 10.0.12.228
+ A 10.0.12.229
+ A 10.0.12.230
+ A 10.0.12.231
+ A 10.0.12.232
+ A 10.0.12.233
+ A 10.0.12.234
+ A 10.0.12.235
+ A 10.0.12.236
+ A 10.0.12.237
+ A 10.0.12.238
+ A 10.0.12.239
+ A 10.0.12.240
+ A 10.0.12.241
+ A 10.0.12.242
+ A 10.0.12.243
+ A 10.0.12.244
+ A 10.0.12.245
+ A 10.0.12.246
+ A 10.0.12.247
+ A 10.0.12.248
+ A 10.0.12.249
+ A 10.0.12.250
+ A 10.0.12.251
+ A 10.0.12.252
+ A 10.0.12.253
+ A 10.0.12.254
+ A 10.0.12.255
+ A 10.0.13.0
+ A 10.0.13.1
+ A 10.0.13.2
+ A 10.0.13.3
+ A 10.0.13.4
+ A 10.0.13.5
+ A 10.0.13.6
+ A 10.0.13.7
+ A 10.0.13.8
+ A 10.0.13.9
+ A 10.0.13.10
+ A 10.0.13.11
+ A 10.0.13.12
+ A 10.0.13.13
+ A 10.0.13.14
+ A 10.0.13.15
+ A 10.0.13.16
+ A 10.0.13.17
+ A 10.0.13.18
+ A 10.0.13.19
+ A 10.0.13.20
+ A 10.0.13.21
+ A 10.0.13.22
+ A 10.0.13.23
+ A 10.0.13.24
+ A 10.0.13.25
+ A 10.0.13.26
+ A 10.0.13.27
+ A 10.0.13.28
+ A 10.0.13.29
+ A 10.0.13.30
+ A 10.0.13.31
+ A 10.0.13.32
+ A 10.0.13.33
+ A 10.0.13.34
+ A 10.0.13.35
+ A 10.0.13.36
+ A 10.0.13.37
+ A 10.0.13.38
+ A 10.0.13.39
+ A 10.0.13.40
+ A 10.0.13.41
+ A 10.0.13.42
+ A 10.0.13.43
+ A 10.0.13.44
+ A 10.0.13.45
+ A 10.0.13.46
+ A 10.0.13.47
+ A 10.0.13.48
+ A 10.0.13.49
+ A 10.0.13.50
+ A 10.0.13.51
+ A 10.0.13.52
+ A 10.0.13.53
+ A 10.0.13.54
+ A 10.0.13.55
+ A 10.0.13.56
+ A 10.0.13.57
+ A 10.0.13.58
+ A 10.0.13.59
+ A 10.0.13.60
+ A 10.0.13.61
+ A 10.0.13.62
+ A 10.0.13.63
+ A 10.0.13.64
+ A 10.0.13.65
+ A 10.0.13.66
+ A 10.0.13.67
+ A 10.0.13.68
+ A 10.0.13.69
+ A 10.0.13.70
+ A 10.0.13.71
+ A 10.0.13.72
+ A 10.0.13.73
+ A 10.0.13.74
+ A 10.0.13.75
+ A 10.0.13.76
+ A 10.0.13.77
+ A 10.0.13.78
+ A 10.0.13.79
+ A 10.0.13.80
+ A 10.0.13.81
+ A 10.0.13.82
+ A 10.0.13.83
+ A 10.0.13.84
+ A 10.0.13.85
+ A 10.0.13.86
+ A 10.0.13.87
+ A 10.0.13.88
+ A 10.0.13.89
+ A 10.0.13.90
+ A 10.0.13.91
+ A 10.0.13.92
+ A 10.0.13.93
+ A 10.0.13.94
+ A 10.0.13.95
+ A 10.0.13.96
+ A 10.0.13.97
+ A 10.0.13.98
+ A 10.0.13.99
+ A 10.0.13.100
+ A 10.0.13.101
+ A 10.0.13.102
+ A 10.0.13.103
+ A 10.0.13.104
+ A 10.0.13.105
+ A 10.0.13.106
+ A 10.0.13.107
+ A 10.0.13.108
+ A 10.0.13.109
+ A 10.0.13.110
+ A 10.0.13.111
+ A 10.0.13.112
+ A 10.0.13.113
+ A 10.0.13.114
+ A 10.0.13.115
+ A 10.0.13.116
+ A 10.0.13.117
+ A 10.0.13.118
+ A 10.0.13.119
+ A 10.0.13.120
+ A 10.0.13.121
+ A 10.0.13.122
+ A 10.0.13.123
+ A 10.0.13.124
+ A 10.0.13.125
+ A 10.0.13.126
+ A 10.0.13.127
+ A 10.0.13.128
+ A 10.0.13.129
+ A 10.0.13.130
+ A 10.0.13.131
+ A 10.0.13.132
+ A 10.0.13.133
+ A 10.0.13.134
+ A 10.0.13.135
+ A 10.0.13.136
+ A 10.0.13.137
+ A 10.0.13.138
+ A 10.0.13.139
+ A 10.0.13.140
+ A 10.0.13.141
+ A 10.0.13.142
+ A 10.0.13.143
+ A 10.0.13.144
+ A 10.0.13.145
+ A 10.0.13.146
+ A 10.0.13.147
+ A 10.0.13.148
+ A 10.0.13.149
+ A 10.0.13.150
+ A 10.0.13.151
+ A 10.0.13.152
+ A 10.0.13.153
+ A 10.0.13.154
+ A 10.0.13.155
+ A 10.0.13.156
+ A 10.0.13.157
+ A 10.0.13.158
+ A 10.0.13.159
+ A 10.0.13.160
+ A 10.0.13.161
+ A 10.0.13.162
+ A 10.0.13.163
+ A 10.0.13.164
+ A 10.0.13.165
+ A 10.0.13.166
+ A 10.0.13.167
+ A 10.0.13.168
+ A 10.0.13.169
+ A 10.0.13.170
+ A 10.0.13.171
+ A 10.0.13.172
+ A 10.0.13.173
+ A 10.0.13.174
+ A 10.0.13.175
+ A 10.0.13.176
+ A 10.0.13.177
+ A 10.0.13.178
+ A 10.0.13.179
+ A 10.0.13.180
+ A 10.0.13.181
+ A 10.0.13.182
+ A 10.0.13.183
+ A 10.0.13.184
+ A 10.0.13.185
+ A 10.0.13.186
+ A 10.0.13.187
+ A 10.0.13.188
+ A 10.0.13.189
+ A 10.0.13.190
+ A 10.0.13.191
+ A 10.0.13.192
+ A 10.0.13.193
+ A 10.0.13.194
+ A 10.0.13.195
+ A 10.0.13.196
+ A 10.0.13.197
+ A 10.0.13.198
+ A 10.0.13.199
+ A 10.0.13.200
+ A 10.0.13.201
+ A 10.0.13.202
+ A 10.0.13.203
+ A 10.0.13.204
+ A 10.0.13.205
+ A 10.0.13.206
+ A 10.0.13.207
+ A 10.0.13.208
+ A 10.0.13.209
+ A 10.0.13.210
+ A 10.0.13.211
+ A 10.0.13.212
+ A 10.0.13.213
+ A 10.0.13.214
+ A 10.0.13.215
+ A 10.0.13.216
+ A 10.0.13.217
+ A 10.0.13.218
+ A 10.0.13.219
+ A 10.0.13.220
+ A 10.0.13.221
+ A 10.0.13.222
+ A 10.0.13.223
+ A 10.0.13.224
+ A 10.0.13.225
+ A 10.0.13.226
+ A 10.0.13.227
+ A 10.0.13.228
+ A 10.0.13.229
+ A 10.0.13.230
+ A 10.0.13.231
+ A 10.0.13.232
+ A 10.0.13.233
+ A 10.0.13.234
+ A 10.0.13.235
+ A 10.0.13.236
+ A 10.0.13.237
+ A 10.0.13.238
+ A 10.0.13.239
+ A 10.0.13.240
+ A 10.0.13.241
+ A 10.0.13.242
+ A 10.0.13.243
+ A 10.0.13.244
+ A 10.0.13.245
+ A 10.0.13.246
+ A 10.0.13.247
+ A 10.0.13.248
+ A 10.0.13.249
+ A 10.0.13.250
+ A 10.0.13.251
+ A 10.0.13.252
+ A 10.0.13.253
+ A 10.0.13.254
+ A 10.0.13.255
+ A 10.0.14.0
+ A 10.0.14.1
+ A 10.0.14.2
+ A 10.0.14.3
+ A 10.0.14.4
+ A 10.0.14.5
+ A 10.0.14.6
+ A 10.0.14.7
+ A 10.0.14.8
+ A 10.0.14.9
+ A 10.0.14.10
+ A 10.0.14.11
+ A 10.0.14.12
+ A 10.0.14.13
+ A 10.0.14.14
+ A 10.0.14.15
+ A 10.0.14.16
+ A 10.0.14.17
+ A 10.0.14.18
+ A 10.0.14.19
+ A 10.0.14.20
+ A 10.0.14.21
+ A 10.0.14.22
+ A 10.0.14.23
+ A 10.0.14.24
+ A 10.0.14.25
+ A 10.0.14.26
+ A 10.0.14.27
+ A 10.0.14.28
+ A 10.0.14.29
+ A 10.0.14.30
+ A 10.0.14.31
+ A 10.0.14.32
+ A 10.0.14.33
+ A 10.0.14.34
+ A 10.0.14.35
+ A 10.0.14.36
+ A 10.0.14.37
+ A 10.0.14.38
+ A 10.0.14.39
+ A 10.0.14.40
+ A 10.0.14.41
+ A 10.0.14.42
+ A 10.0.14.43
+ A 10.0.14.44
+ A 10.0.14.45
+ A 10.0.14.46
+ A 10.0.14.47
+ A 10.0.14.48
+ A 10.0.14.49
+ A 10.0.14.50
+ A 10.0.14.51
+ A 10.0.14.52
+ A 10.0.14.53
+ A 10.0.14.54
+ A 10.0.14.55
+ A 10.0.14.56
+ A 10.0.14.57
+ A 10.0.14.58
+ A 10.0.14.59
+ A 10.0.14.60
+ A 10.0.14.61
+ A 10.0.14.62
+ A 10.0.14.63
+ A 10.0.14.64
+ A 10.0.14.65
+ A 10.0.14.66
+ A 10.0.14.67
+ A 10.0.14.68
+ A 10.0.14.69
+ A 10.0.14.70
+ A 10.0.14.71
+ A 10.0.14.72
+ A 10.0.14.73
+ A 10.0.14.74
+ A 10.0.14.75
+ A 10.0.14.76
+ A 10.0.14.77
+ A 10.0.14.78
+ A 10.0.14.79
+ A 10.0.14.80
+ A 10.0.14.81
+ A 10.0.14.82
+ A 10.0.14.83
+ A 10.0.14.84
+ A 10.0.14.85
+ A 10.0.14.86
+ A 10.0.14.87
+ A 10.0.14.88
+ A 10.0.14.89
+ A 10.0.14.90
+ A 10.0.14.91
+ A 10.0.14.92
+ A 10.0.14.93
+ A 10.0.14.94
+ A 10.0.14.95
+ A 10.0.14.96
+ A 10.0.14.97
+ A 10.0.14.98
+ A 10.0.14.99
+ A 10.0.14.100
+ A 10.0.14.101
+ A 10.0.14.102
+ A 10.0.14.103
+ A 10.0.14.104
+ A 10.0.14.105
+ A 10.0.14.106
+ A 10.0.14.107
+ A 10.0.14.108
+ A 10.0.14.109
+ A 10.0.14.110
+ A 10.0.14.111
+ A 10.0.14.112
+ A 10.0.14.113
+ A 10.0.14.114
+ A 10.0.14.115
+ A 10.0.14.116
+ A 10.0.14.117
+ A 10.0.14.118
+ A 10.0.14.119
+ A 10.0.14.120
+ A 10.0.14.121
+ A 10.0.14.122
+ A 10.0.14.123
+ A 10.0.14.124
+ A 10.0.14.125
+ A 10.0.14.126
+ A 10.0.14.127
+ A 10.0.14.128
+ A 10.0.14.129
+ A 10.0.14.130
+ A 10.0.14.131
+ A 10.0.14.132
+ A 10.0.14.133
+ A 10.0.14.134
+ A 10.0.14.135
+ A 10.0.14.136
+ A 10.0.14.137
+ A 10.0.14.138
+ A 10.0.14.139
+ A 10.0.14.140
+ A 10.0.14.141
+ A 10.0.14.142
+ A 10.0.14.143
+ A 10.0.14.144
+ A 10.0.14.145
+ A 10.0.14.146
+ A 10.0.14.147
+ A 10.0.14.148
+ A 10.0.14.149
+ A 10.0.14.150
+ A 10.0.14.151
+ A 10.0.14.152
+ A 10.0.14.153
+ A 10.0.14.154
+ A 10.0.14.155
+ A 10.0.14.156
+ A 10.0.14.157
+ A 10.0.14.158
+ A 10.0.14.159
+ A 10.0.14.160
+ A 10.0.14.161
+ A 10.0.14.162
+ A 10.0.14.163
+ A 10.0.14.164
+ A 10.0.14.165
+ A 10.0.14.166
+ A 10.0.14.167
+ A 10.0.14.168
+ A 10.0.14.169
+ A 10.0.14.170
+ A 10.0.14.171
+ A 10.0.14.172
+ A 10.0.14.173
+ A 10.0.14.174
+ A 10.0.14.175
+ A 10.0.14.176
+ A 10.0.14.177
+ A 10.0.14.178
+ A 10.0.14.179
+ A 10.0.14.180
+ A 10.0.14.181
+ A 10.0.14.182
+ A 10.0.14.183
+ A 10.0.14.184
+ A 10.0.14.185
+ A 10.0.14.186
+ A 10.0.14.187
+ A 10.0.14.188
+ A 10.0.14.189
+ A 10.0.14.190
+ A 10.0.14.191
+ A 10.0.14.192
+ A 10.0.14.193
+ A 10.0.14.194
+ A 10.0.14.195
+ A 10.0.14.196
+ A 10.0.14.197
+ A 10.0.14.198
+ A 10.0.14.199
+ A 10.0.14.200
+ A 10.0.14.201
+ A 10.0.14.202
+ A 10.0.14.203
+ A 10.0.14.204
+ A 10.0.14.205
+ A 10.0.14.206
+ A 10.0.14.207
+ A 10.0.14.208
+ A 10.0.14.209
+ A 10.0.14.210
+ A 10.0.14.211
+ A 10.0.14.212
+ A 10.0.14.213
+ A 10.0.14.214
+ A 10.0.14.215
+ A 10.0.14.216
+ A 10.0.14.217
+ A 10.0.14.218
+ A 10.0.14.219
+ A 10.0.14.220
+ A 10.0.14.221
+ A 10.0.14.222
+ A 10.0.14.223
+ A 10.0.14.224
+ A 10.0.14.225
+ A 10.0.14.226
+ A 10.0.14.227
+ A 10.0.14.228
+ A 10.0.14.229
+ A 10.0.14.230
+ A 10.0.14.231
+ A 10.0.14.232
+ A 10.0.14.233
+ A 10.0.14.234
+ A 10.0.14.235
+ A 10.0.14.236
+ A 10.0.14.237
+ A 10.0.14.238
+ A 10.0.14.239
+ A 10.0.14.240
+ A 10.0.14.241
+ A 10.0.14.242
+ A 10.0.14.243
+ A 10.0.14.244
+ A 10.0.14.245
+ A 10.0.14.246
+ A 10.0.14.247
+ A 10.0.14.248
+ A 10.0.14.249
+ A 10.0.14.250
+ A 10.0.14.251
+ A 10.0.14.252
+ A 10.0.14.253
+ A 10.0.14.254
+ A 10.0.14.255
+ A 10.0.15.0
+ A 10.0.15.1
+ A 10.0.15.2
+ A 10.0.15.3
+ A 10.0.15.4
+ A 10.0.15.5
+ A 10.0.15.6
+ A 10.0.15.7
+ A 10.0.15.8
+ A 10.0.15.9
+ A 10.0.15.10
+ A 10.0.15.11
+ A 10.0.15.12
+ A 10.0.15.13
+ A 10.0.15.14
+ A 10.0.15.15
+ A 10.0.15.16
+ A 10.0.15.17
+ A 10.0.15.18
+ A 10.0.15.19
+ A 10.0.15.20
+ A 10.0.15.21
+ A 10.0.15.22
+ A 10.0.15.23
+ A 10.0.15.24
+ A 10.0.15.25
+ A 10.0.15.26
+ A 10.0.15.27
+ A 10.0.15.28
+ A 10.0.15.29
+ A 10.0.15.30
+ A 10.0.15.31
+ A 10.0.15.32
+ A 10.0.15.33
+ A 10.0.15.34
+ A 10.0.15.35
+ A 10.0.15.36
+ A 10.0.15.37
+ A 10.0.15.38
+ A 10.0.15.39
+ A 10.0.15.40
+ A 10.0.15.41
+ A 10.0.15.42
+ A 10.0.15.43
+ A 10.0.15.44
+ A 10.0.15.45
+ A 10.0.15.46
+ A 10.0.15.47
+ A 10.0.15.48
+ A 10.0.15.49
+ A 10.0.15.50
+ A 10.0.15.51
+ A 10.0.15.52
+ A 10.0.15.53
+ A 10.0.15.54
+ A 10.0.15.55
+ A 10.0.15.56
+ A 10.0.15.57
+ A 10.0.15.58
+ A 10.0.15.59
+ A 10.0.15.60
+ A 10.0.15.61
+ A 10.0.15.62
+ A 10.0.15.63
+ A 10.0.15.64
+ A 10.0.15.65
+ A 10.0.15.66
+ A 10.0.15.67
+ A 10.0.15.68
+ A 10.0.15.69
+ A 10.0.15.70
+ A 10.0.15.71
+ A 10.0.15.72
+ A 10.0.15.73
+ A 10.0.15.74
+ A 10.0.15.75
+ A 10.0.15.76
+ A 10.0.15.77
+ A 10.0.15.78
+ A 10.0.15.79
+ A 10.0.15.80
+ A 10.0.15.81
+ A 10.0.15.82
+ A 10.0.15.83
+ A 10.0.15.84
+ A 10.0.15.85
+ A 10.0.15.86
+ A 10.0.15.87
+ A 10.0.15.88
+ A 10.0.15.89
+ A 10.0.15.90
+ A 10.0.15.91
+ A 10.0.15.92
+ A 10.0.15.93
+ A 10.0.15.94
+ A 10.0.15.95
+ A 10.0.15.96
+ A 10.0.15.97
+ A 10.0.15.98
+ A 10.0.15.99
+ A 10.0.15.100
+ A 10.0.15.101
+ A 10.0.15.102
+ A 10.0.15.103
+ A 10.0.15.104
+ A 10.0.15.105
+ A 10.0.15.106
+ A 10.0.15.107
+ A 10.0.15.108
+ A 10.0.15.109
+ A 10.0.15.110
+ A 10.0.15.111
+ A 10.0.15.112
+ A 10.0.15.113
+ A 10.0.15.114
+ A 10.0.15.115
+ A 10.0.15.116
+ A 10.0.15.117
+ A 10.0.15.118
+ A 10.0.15.119
+ A 10.0.15.120
+ A 10.0.15.121
+ A 10.0.15.122
+ A 10.0.15.123
+ A 10.0.15.124
+ A 10.0.15.125
+ A 10.0.15.126
+ A 10.0.15.127
+ A 10.0.15.128
+ A 10.0.15.129
+ A 10.0.15.130
+ A 10.0.15.131
+ A 10.0.15.132
+ A 10.0.15.133
+ A 10.0.15.134
+ A 10.0.15.135
+ A 10.0.15.136
+ A 10.0.15.137
+ A 10.0.15.138
+ A 10.0.15.139
+ A 10.0.15.140
+ A 10.0.15.141
+ A 10.0.15.142
+ A 10.0.15.143
+ A 10.0.15.144
+ A 10.0.15.145
+ A 10.0.15.146
+ A 10.0.15.147
+ A 10.0.15.148
+ A 10.0.15.149
+ A 10.0.15.150
+ A 10.0.15.151
+ A 10.0.15.152
+ A 10.0.15.153
+ A 10.0.15.154
+ A 10.0.15.155
+ A 10.0.15.156
+ A 10.0.15.157
+ A 10.0.15.158
+ A 10.0.15.159
+ A 10.0.15.160
+ A 10.0.15.161
+ A 10.0.15.162
+ A 10.0.15.163
+ A 10.0.15.164
+ A 10.0.15.165
+ A 10.0.15.166
+ A 10.0.15.167
+ A 10.0.15.168
+ A 10.0.15.169
+ A 10.0.15.170
+ A 10.0.15.171
+ A 10.0.15.172
+ A 10.0.15.173
+ A 10.0.15.174
+ A 10.0.15.175
+ A 10.0.15.176
+ A 10.0.15.177
+ A 10.0.15.178
+ A 10.0.15.179
+ A 10.0.15.180
+ A 10.0.15.181
+ A 10.0.15.182
+ A 10.0.15.183
+ A 10.0.15.184
+ A 10.0.15.185
+ A 10.0.15.186
+ A 10.0.15.187
+ A 10.0.15.188
+ A 10.0.15.189
+ A 10.0.15.190
+ A 10.0.15.191
+ A 10.0.15.192
+ A 10.0.15.193
+ A 10.0.15.194
+ A 10.0.15.195
+ A 10.0.15.196
+ A 10.0.15.197
+ A 10.0.15.198
+ A 10.0.15.199
+ A 10.0.15.200
+ A 10.0.15.201
+ A 10.0.15.202
+ A 10.0.15.203
+ A 10.0.15.204
+ A 10.0.15.205
+ A 10.0.15.206
+ A 10.0.15.207
+ A 10.0.15.208
+ A 10.0.15.209
+ A 10.0.15.210
+ A 10.0.15.211
+ A 10.0.15.212
+ A 10.0.15.213
+ A 10.0.15.214
+ A 10.0.15.215
+ A 10.0.15.216
+ A 10.0.15.217
+ A 10.0.15.218
+ A 10.0.15.219
+ A 10.0.15.220
+ A 10.0.15.221
+ A 10.0.15.222
+ A 10.0.15.223
+ A 10.0.15.224
+ A 10.0.15.225
+ A 10.0.15.226
+ A 10.0.15.227
+ A 10.0.15.228
+ A 10.0.15.229
+ A 10.0.15.230
+ A 10.0.15.231
+ A 10.0.15.232
+ A 10.0.15.233
+ A 10.0.15.234
+ A 10.0.15.235
+ A 10.0.15.236
+ A 10.0.15.237
+ A 10.0.15.238
+ A 10.0.15.239
+ A 10.0.15.240
+ A 10.0.15.241
+ A 10.0.15.242
+ A 10.0.15.243
+ A 10.0.15.244
+ A 10.0.15.245
+ A 10.0.15.246
+ A 10.0.15.247
+ A 10.0.15.248
+ A 10.0.15.249
+ A 10.0.15.250
+ A 10.0.15.251
+ A 10.0.15.252
+ A 10.0.15.253
+ A 10.0.15.254
+ A 10.0.15.255
+ A 10.0.16.0
+ A 10.0.16.1
+ A 10.0.16.2
+ A 10.0.16.3
+ A 10.0.16.4
+ A 10.0.16.5
+ A 10.0.16.6
+ A 10.0.16.7
+ A 10.0.16.8
+ A 10.0.16.9
+ A 10.0.16.10
+ A 10.0.16.11
+ A 10.0.16.12
+ A 10.0.16.13
+ A 10.0.16.14
+ A 10.0.16.15
+ A 10.0.16.16
+ A 10.0.16.17
+ A 10.0.16.18
+ A 10.0.16.19
+ A 10.0.16.20
+ A 10.0.16.21
+ A 10.0.16.22
+ A 10.0.16.23
+ A 10.0.16.24
+ A 10.0.16.25
+ A 10.0.16.26
+ A 10.0.16.27
+ A 10.0.16.28
+ A 10.0.16.29
+ A 10.0.16.30
+ A 10.0.16.31
+ A 10.0.16.32
+ A 10.0.16.33
+ A 10.0.16.34
+ A 10.0.16.35
+ A 10.0.16.36
+ A 10.0.16.37
+ A 10.0.16.38
+ A 10.0.16.39
+ A 10.0.16.40
+ A 10.0.16.41
+ A 10.0.16.42
+ A 10.0.16.43
+ A 10.0.16.44
+ A 10.0.16.45
+ A 10.0.16.46
+ A 10.0.16.47
+ A 10.0.16.48
+ A 10.0.16.49
+ A 10.0.16.50
+ A 10.0.16.51
+ A 10.0.16.52
+ A 10.0.16.53
+ A 10.0.16.54
+ A 10.0.16.55
+ A 10.0.16.56
+ A 10.0.16.57
+ A 10.0.16.58
+ A 10.0.16.59
+ A 10.0.16.60
+ A 10.0.16.61
+ A 10.0.16.62
+ A 10.0.16.63
+ A 10.0.16.64
+ A 10.0.16.65
+ A 10.0.16.66
+ A 10.0.16.67
+ A 10.0.16.68
+ A 10.0.16.69
+ A 10.0.16.70
+ A 10.0.16.71
+ A 10.0.16.72
+ A 10.0.16.73
+ A 10.0.16.74
+ A 10.0.16.75
+ A 10.0.16.76
+ A 10.0.16.77
+ A 10.0.16.78
+ A 10.0.16.79
+ A 10.0.16.80
+ A 10.0.16.81
+ A 10.0.16.82
+ A 10.0.16.83
+ A 10.0.16.84
+ A 10.0.16.85
+ A 10.0.16.86
+ A 10.0.16.87
+ A 10.0.16.88
+ A 10.0.16.89
+ A 10.0.16.90
+ A 10.0.16.91
+ A 10.0.16.92
+ A 10.0.16.93
+ A 10.0.16.94
+ A 10.0.16.95
+ A 10.0.16.96
+ A 10.0.16.97
+ A 10.0.16.98
+ A 10.0.16.99
+ A 10.0.16.100
+ A 10.0.16.101
+ A 10.0.16.102
+ A 10.0.16.103
+ A 10.0.16.104
+ A 10.0.16.105
+ A 10.0.16.106
+ A 10.0.16.107
+ A 10.0.16.108
+ A 10.0.16.109
+ A 10.0.16.110
+ A 10.0.16.111
+ A 10.0.16.112
+ A 10.0.16.113
+ A 10.0.16.114
+ A 10.0.16.115
+ A 10.0.16.116
+ A 10.0.16.117
+ A 10.0.16.118
+ A 10.0.16.119
+ A 10.0.16.120
+ A 10.0.16.121
+ A 10.0.16.122
+ A 10.0.16.123
+ A 10.0.16.124
+ A 10.0.16.125
+ A 10.0.16.126
+ A 10.0.16.127
+ A 10.0.16.128
+ A 10.0.16.129
+ A 10.0.16.130
+ A 10.0.16.131
+ A 10.0.16.132
+ A 10.0.16.133
+ A 10.0.16.134
+ A 10.0.16.135
+ A 10.0.16.136
+ A 10.0.16.137
+ A 10.0.16.138
+ A 10.0.16.139
+ A 10.0.16.140
+ A 10.0.16.141
+ A 10.0.16.142
+ A 10.0.16.143
+ A 10.0.16.144
+ A 10.0.16.145
+ A 10.0.16.146
+ A 10.0.16.147
+ A 10.0.16.148
+ A 10.0.16.149
+ A 10.0.16.150
+ A 10.0.16.151
+ A 10.0.16.152
+ A 10.0.16.153
+ A 10.0.16.154
+ A 10.0.16.155
+ A 10.0.16.156
+ A 10.0.16.157
+ A 10.0.16.158
+ A 10.0.16.159
+ A 10.0.16.160
+ A 10.0.16.161
+ A 10.0.16.162
+ A 10.0.16.163
+ A 10.0.16.164
+ A 10.0.16.165
+ A 10.0.16.166
+ A 10.0.16.167
+ A 10.0.16.168
+ A 10.0.16.169
+ A 10.0.16.170
+ A 10.0.16.171
+ A 10.0.16.172
+ A 10.0.16.173
+ A 10.0.16.174
+ A 10.0.16.175
+ A 10.0.16.176
+ A 10.0.16.177
+ A 10.0.16.178
+ A 10.0.16.179
+ A 10.0.16.180
+ A 10.0.16.181
+ A 10.0.16.182
+ A 10.0.16.183
+ A 10.0.16.184
+ A 10.0.16.185
+ A 10.0.16.186
+ A 10.0.16.187
+ A 10.0.16.188
+ A 10.0.16.189
+ A 10.0.16.190
+ A 10.0.16.191
+ A 10.0.16.192
+ A 10.0.16.193
+ A 10.0.16.194
+ A 10.0.16.195
+ A 10.0.16.196
+ A 10.0.16.197
+ A 10.0.16.198
+ A 10.0.16.199
+ A 10.0.16.200
+ A 10.0.16.201
+ A 10.0.16.202
+ A 10.0.16.203
+ A 10.0.16.204
+ A 10.0.16.205
+ A 10.0.16.206
+ A 10.0.16.207
+ A 10.0.16.208
+ A 10.0.16.209
+ A 10.0.16.210
+ A 10.0.16.211
+ A 10.0.16.212
+ A 10.0.16.213
+ A 10.0.16.214
+ A 10.0.16.215
+ A 10.0.16.216
+ A 10.0.16.217
+ A 10.0.16.218
+ A 10.0.16.219
+ A 10.0.16.220
+ A 10.0.16.221
+ A 10.0.16.222
+ A 10.0.16.223
+ A 10.0.16.224
+ A 10.0.16.225
+ A 10.0.16.226
+ A 10.0.16.227
+ A 10.0.16.228
+ A 10.0.16.229
+ A 10.0.16.230
+ A 10.0.16.231
+ A 10.0.16.232
+ A 10.0.16.233
+ A 10.0.16.234
+ A 10.0.16.235
+ A 10.0.16.236
+ A 10.0.16.237
+ A 10.0.16.238
+ A 10.0.16.239
+ A 10.0.16.240
+ A 10.0.16.241
+ A 10.0.16.242
+ A 10.0.16.243
+ A 10.0.16.244
+ A 10.0.16.245
+ A 10.0.16.246
+ A 10.0.16.247
+ A 10.0.16.248
+ A 10.0.16.249
+ A 10.0.16.250
+ A 10.0.16.251
+ A 10.0.16.252
+ A 10.0.16.253
+ A 10.0.16.254
+ A 10.0.16.255
+ A 10.0.17.0
+ A 10.0.17.1
+ A 10.0.17.2
+ A 10.0.17.3
+ A 10.0.17.4
+ A 10.0.17.5
+ A 10.0.17.6
+ A 10.0.17.7
+ A 10.0.17.8
+ A 10.0.17.9
+ A 10.0.17.10
+ A 10.0.17.11
+ A 10.0.17.12
+ A 10.0.17.13
+ A 10.0.17.14
+ A 10.0.17.15
+ A 10.0.17.16
+ A 10.0.17.17
+ A 10.0.17.18
+ A 10.0.17.19
+ A 10.0.17.20
+ A 10.0.17.21
+ A 10.0.17.22
+ A 10.0.17.23
+ A 10.0.17.24
+ A 10.0.17.25
+ A 10.0.17.26
+ A 10.0.17.27
+ A 10.0.17.28
+ A 10.0.17.29
+ A 10.0.17.30
+ A 10.0.17.31
+ A 10.0.17.32
+ A 10.0.17.33
+ A 10.0.17.34
+ A 10.0.17.35
+ A 10.0.17.36
+ A 10.0.17.37
+ A 10.0.17.38
+ A 10.0.17.39
+ A 10.0.17.40
+ A 10.0.17.41
+ A 10.0.17.42
+ A 10.0.17.43
+ A 10.0.17.44
+ A 10.0.17.45
+ A 10.0.17.46
+ A 10.0.17.47
+ A 10.0.17.48
+ A 10.0.17.49
+ A 10.0.17.50
+ A 10.0.17.51
+ A 10.0.17.52
+ A 10.0.17.53
+ A 10.0.17.54
+ A 10.0.17.55
+ A 10.0.17.56
+ A 10.0.17.57
+ A 10.0.17.58
+ A 10.0.17.59
+ A 10.0.17.60
+ A 10.0.17.61
+ A 10.0.17.62
+ A 10.0.17.63
+ A 10.0.17.64
+ A 10.0.17.65
+ A 10.0.17.66
+ A 10.0.17.67
+ A 10.0.17.68
+ A 10.0.17.69
+ A 10.0.17.70
+ A 10.0.17.71
+ A 10.0.17.72
+ A 10.0.17.73
+ A 10.0.17.74
+ A 10.0.17.75
+ A 10.0.17.76
+ A 10.0.17.77
+ A 10.0.17.78
+ A 10.0.17.79
+ A 10.0.17.80
+ A 10.0.17.81
+ A 10.0.17.82
+ A 10.0.17.83
+ A 10.0.17.84
+ A 10.0.17.85
+ A 10.0.17.86
+ A 10.0.17.87
+ A 10.0.17.88
+ A 10.0.17.89
+ A 10.0.17.90
+ A 10.0.17.91
+ A 10.0.17.92
+ A 10.0.17.93
+ A 10.0.17.94
+ A 10.0.17.95
+ A 10.0.17.96
+ A 10.0.17.97
+ A 10.0.17.98
+ A 10.0.17.99
+ A 10.0.17.100
+ A 10.0.17.101
+ A 10.0.17.102
+ A 10.0.17.103
+ A 10.0.17.104
+ A 10.0.17.105
+ A 10.0.17.106
+ A 10.0.17.107
+ A 10.0.17.108
+ A 10.0.17.109
+ A 10.0.17.110
+ A 10.0.17.111
+ A 10.0.17.112
+ A 10.0.17.113
+ A 10.0.17.114
+ A 10.0.17.115
+ A 10.0.17.116
+ A 10.0.17.117
+ A 10.0.17.118
+ A 10.0.17.119
+ A 10.0.17.120
+ A 10.0.17.121
+ A 10.0.17.122
+ A 10.0.17.123
+ A 10.0.17.124
+ A 10.0.17.125
+ A 10.0.17.126
+ A 10.0.17.127
+ A 10.0.17.128
+ A 10.0.17.129
+ A 10.0.17.130
+ A 10.0.17.131
+ A 10.0.17.132
+ A 10.0.17.133
+ A 10.0.17.134
+ A 10.0.17.135
+ A 10.0.17.136
+ A 10.0.17.137
+ A 10.0.17.138
+ A 10.0.17.139
+ A 10.0.17.140
+ A 10.0.17.141
+ A 10.0.17.142
+ A 10.0.17.143
+ A 10.0.17.144
+ A 10.0.17.145
+ A 10.0.17.146
+ A 10.0.17.147
+ A 10.0.17.148
+ A 10.0.17.149
+ A 10.0.17.150
+ A 10.0.17.151
+ A 10.0.17.152
+ A 10.0.17.153
+ A 10.0.17.154
+ A 10.0.17.155
+ A 10.0.17.156
+ A 10.0.17.157
+ A 10.0.17.158
+ A 10.0.17.159
+ A 10.0.17.160
+ A 10.0.17.161
+ A 10.0.17.162
+ A 10.0.17.163
+ A 10.0.17.164
+ A 10.0.17.165
+ A 10.0.17.166
+ A 10.0.17.167
+ A 10.0.17.168
+ A 10.0.17.169
+ A 10.0.17.170
+ A 10.0.17.171
+ A 10.0.17.172
+ A 10.0.17.173
+ A 10.0.17.174
+ A 10.0.17.175
+ A 10.0.17.176
+ A 10.0.17.177
+ A 10.0.17.178
+ A 10.0.17.179
+ A 10.0.17.180
+ A 10.0.17.181
+ A 10.0.17.182
+ A 10.0.17.183
+ A 10.0.17.184
+ A 10.0.17.185
+ A 10.0.17.186
+ A 10.0.17.187
+ A 10.0.17.188
+ A 10.0.17.189
+ A 10.0.17.190
+ A 10.0.17.191
+ A 10.0.17.192
+ A 10.0.17.193
+ A 10.0.17.194
+ A 10.0.17.195
+ A 10.0.17.196
+ A 10.0.17.197
+ A 10.0.17.198
+ A 10.0.17.199
+ A 10.0.17.200
+ A 10.0.17.201
+ A 10.0.17.202
+ A 10.0.17.203
+ A 10.0.17.204
+ A 10.0.17.205
+ A 10.0.17.206
+ A 10.0.17.207
+ A 10.0.17.208
+ A 10.0.17.209
+ A 10.0.17.210
+ A 10.0.17.211
+ A 10.0.17.212
+ A 10.0.17.213
+ A 10.0.17.214
+ A 10.0.17.215
+ A 10.0.17.216
+ A 10.0.17.217
+ A 10.0.17.218
+ A 10.0.17.219
+ A 10.0.17.220
+ A 10.0.17.221
+ A 10.0.17.222
+ A 10.0.17.223
+ A 10.0.17.224
+ A 10.0.17.225
+ A 10.0.17.226
+ A 10.0.17.227
+ A 10.0.17.228
+ A 10.0.17.229
+ A 10.0.17.230
+ A 10.0.17.231
+ A 10.0.17.232
+ A 10.0.17.233
+ A 10.0.17.234
+ A 10.0.17.235
+ A 10.0.17.236
+ A 10.0.17.237
+ A 10.0.17.238
+ A 10.0.17.239
+ A 10.0.17.240
+ A 10.0.17.241
+ A 10.0.17.242
+ A 10.0.17.243
+ A 10.0.17.244
+ A 10.0.17.245
+ A 10.0.17.246
+ A 10.0.17.247
+ A 10.0.17.248
+ A 10.0.17.249
+ A 10.0.17.250
+ A 10.0.17.251
+ A 10.0.17.252
+ A 10.0.17.253
+ A 10.0.17.254
+ A 10.0.17.255
+ A 10.0.18.0
+ A 10.0.18.1
+ A 10.0.18.2
+ A 10.0.18.3
+ A 10.0.18.4
+ A 10.0.18.5
+ A 10.0.18.6
+ A 10.0.18.7
+ A 10.0.18.8
+ A 10.0.18.9
+ A 10.0.18.10
+ A 10.0.18.11
+ A 10.0.18.12
+ A 10.0.18.13
+ A 10.0.18.14
+ A 10.0.18.15
+ A 10.0.18.16
+ A 10.0.18.17
+ A 10.0.18.18
+ A 10.0.18.19
+ A 10.0.18.20
+ A 10.0.18.21
+ A 10.0.18.22
+ A 10.0.18.23
+ A 10.0.18.24
+ A 10.0.18.25
+ A 10.0.18.26
+ A 10.0.18.27
+ A 10.0.18.28
+ A 10.0.18.29
+ A 10.0.18.30
+ A 10.0.18.31
+ A 10.0.18.32
+ A 10.0.18.33
+ A 10.0.18.34
+ A 10.0.18.35
+ A 10.0.18.36
+ A 10.0.18.37
+ A 10.0.18.38
+ A 10.0.18.39
+ A 10.0.18.40
+ A 10.0.18.41
+ A 10.0.18.42
+ A 10.0.18.43
+ A 10.0.18.44
+ A 10.0.18.45
+ A 10.0.18.46
+ A 10.0.18.47
+ A 10.0.18.48
+ A 10.0.18.49
+ A 10.0.18.50
+ A 10.0.18.51
+ A 10.0.18.52
+ A 10.0.18.53
+ A 10.0.18.54
+ A 10.0.18.55
+ A 10.0.18.56
+ A 10.0.18.57
+ A 10.0.18.58
+ A 10.0.18.59
+ A 10.0.18.60
+ A 10.0.18.61
+ A 10.0.18.62
+ A 10.0.18.63
+ A 10.0.18.64
+ A 10.0.18.65
+ A 10.0.18.66
+ A 10.0.18.67
+ A 10.0.18.68
+ A 10.0.18.69
+ A 10.0.18.70
+ A 10.0.18.71
+ A 10.0.18.72
+ A 10.0.18.73
+ A 10.0.18.74
+ A 10.0.18.75
+ A 10.0.18.76
+ A 10.0.18.77
+ A 10.0.18.78
+ A 10.0.18.79
+ A 10.0.18.80
+ A 10.0.18.81
+ A 10.0.18.82
+ A 10.0.18.83
+ A 10.0.18.84
+ A 10.0.18.85
+ A 10.0.18.86
+ A 10.0.18.87
+ A 10.0.18.88
+ A 10.0.18.89
+ A 10.0.18.90
+ A 10.0.18.91
+ A 10.0.18.92
+ A 10.0.18.93
+ A 10.0.18.94
+ A 10.0.18.95
+ A 10.0.18.96
+ A 10.0.18.97
+ A 10.0.18.98
+ A 10.0.18.99
+ A 10.0.18.100
+ A 10.0.18.101
+ A 10.0.18.102
+ A 10.0.18.103
+ A 10.0.18.104
+ A 10.0.18.105
+ A 10.0.18.106
+ A 10.0.18.107
+ A 10.0.18.108
+ A 10.0.18.109
+ A 10.0.18.110
+ A 10.0.18.111
+ A 10.0.18.112
+ A 10.0.18.113
+ A 10.0.18.114
+ A 10.0.18.115
+ A 10.0.18.116
+ A 10.0.18.117
+ A 10.0.18.118
+ A 10.0.18.119
+ A 10.0.18.120
+ A 10.0.18.121
+ A 10.0.18.122
+ A 10.0.18.123
+ A 10.0.18.124
+ A 10.0.18.125
+ A 10.0.18.126
+ A 10.0.18.127
+ A 10.0.18.128
+ A 10.0.18.129
+ A 10.0.18.130
+ A 10.0.18.131
+ A 10.0.18.132
+ A 10.0.18.133
+ A 10.0.18.134
+ A 10.0.18.135
+ A 10.0.18.136
+ A 10.0.18.137
+ A 10.0.18.138
+ A 10.0.18.139
+ A 10.0.18.140
+ A 10.0.18.141
+ A 10.0.18.142
+ A 10.0.18.143
+ A 10.0.18.144
+ A 10.0.18.145
+ A 10.0.18.146
+ A 10.0.18.147
+ A 10.0.18.148
+ A 10.0.18.149
+ A 10.0.18.150
+ A 10.0.18.151
+ A 10.0.18.152
+ A 10.0.18.153
+ A 10.0.18.154
+ A 10.0.18.155
+ A 10.0.18.156
+ A 10.0.18.157
+ A 10.0.18.158
+ A 10.0.18.159
+ A 10.0.18.160
+ A 10.0.18.161
+ A 10.0.18.162
+ A 10.0.18.163
+ A 10.0.18.164
+ A 10.0.18.165
+ A 10.0.18.166
+ A 10.0.18.167
+ A 10.0.18.168
+ A 10.0.18.169
+ A 10.0.18.170
+ A 10.0.18.171
+ A 10.0.18.172
+ A 10.0.18.173
+ A 10.0.18.174
+ A 10.0.18.175
+ A 10.0.18.176
+ A 10.0.18.177
+ A 10.0.18.178
+ A 10.0.18.179
+ A 10.0.18.180
+ A 10.0.18.181
+ A 10.0.18.182
+ A 10.0.18.183
+ A 10.0.18.184
+ A 10.0.18.185
+ A 10.0.18.186
+ A 10.0.18.187
+ A 10.0.18.188
+ A 10.0.18.189
+ A 10.0.18.190
+ A 10.0.18.191
+ A 10.0.18.192
+ A 10.0.18.193
+ A 10.0.18.194
+ A 10.0.18.195
+ A 10.0.18.196
+ A 10.0.18.197
+ A 10.0.18.198
+ A 10.0.18.199
+ A 10.0.18.200
+ A 10.0.18.201
+ A 10.0.18.202
+ A 10.0.18.203
+ A 10.0.18.204
+ A 10.0.18.205
+ A 10.0.18.206
+ A 10.0.18.207
+ A 10.0.18.208
+ A 10.0.18.209
+ A 10.0.18.210
+ A 10.0.18.211
+ A 10.0.18.212
+ A 10.0.18.213
+ A 10.0.18.214
+ A 10.0.18.215
+ A 10.0.18.216
+ A 10.0.18.217
+ A 10.0.18.218
+ A 10.0.18.219
+ A 10.0.18.220
+ A 10.0.18.221
+ A 10.0.18.222
+ A 10.0.18.223
+ A 10.0.18.224
+ A 10.0.18.225
+ A 10.0.18.226
+ A 10.0.18.227
+ A 10.0.18.228
+ A 10.0.18.229
+ A 10.0.18.230
+ A 10.0.18.231
+ A 10.0.18.232
+ A 10.0.18.233
+ A 10.0.18.234
+ A 10.0.18.235
+ A 10.0.18.236
+ A 10.0.18.237
+ A 10.0.18.238
+ A 10.0.18.239
+ A 10.0.18.240
+ A 10.0.18.241
+ A 10.0.18.242
+ A 10.0.18.243
+ A 10.0.18.244
+ A 10.0.18.245
+ A 10.0.18.246
+ A 10.0.18.247
+ A 10.0.18.248
+ A 10.0.18.249
+ A 10.0.18.250
+ A 10.0.18.251
+ A 10.0.18.252
+ A 10.0.18.253
+ A 10.0.18.254
+ A 10.0.18.255
+ A 10.0.19.0
+ A 10.0.19.1
+ A 10.0.19.2
+ A 10.0.19.3
+ A 10.0.19.4
+ A 10.0.19.5
+ A 10.0.19.6
+ A 10.0.19.7
+ A 10.0.19.8
+ A 10.0.19.9
+ A 10.0.19.10
+ A 10.0.19.11
+ A 10.0.19.12
+ A 10.0.19.13
+ A 10.0.19.14
+ A 10.0.19.15
+ A 10.0.19.16
+ A 10.0.19.17
+ A 10.0.19.18
+ A 10.0.19.19
+ A 10.0.19.20
+ A 10.0.19.21
+ A 10.0.19.22
+ A 10.0.19.23
+ A 10.0.19.24
+ A 10.0.19.25
+ A 10.0.19.26
+ A 10.0.19.27
+ A 10.0.19.28
+ A 10.0.19.29
+ A 10.0.19.30
+ A 10.0.19.31
+ A 10.0.19.32
+ A 10.0.19.33
+ A 10.0.19.34
+ A 10.0.19.35
+ A 10.0.19.36
+ A 10.0.19.37
+ A 10.0.19.38
+ A 10.0.19.39
+ A 10.0.19.40
+ A 10.0.19.41
+ A 10.0.19.42
+ A 10.0.19.43
+ A 10.0.19.44
+ A 10.0.19.45
+ A 10.0.19.46
+ A 10.0.19.47
+ A 10.0.19.48
+ A 10.0.19.49
+ A 10.0.19.50
+ A 10.0.19.51
+ A 10.0.19.52
+ A 10.0.19.53
+ A 10.0.19.54
+ A 10.0.19.55
+ A 10.0.19.56
+ A 10.0.19.57
+ A 10.0.19.58
+ A 10.0.19.59
+ A 10.0.19.60
+ A 10.0.19.61
+ A 10.0.19.62
+ A 10.0.19.63
+ A 10.0.19.64
+ A 10.0.19.65
+ A 10.0.19.66
+ A 10.0.19.67
+ A 10.0.19.68
+ A 10.0.19.69
+ A 10.0.19.70
+ A 10.0.19.71
+ A 10.0.19.72
+ A 10.0.19.73
+ A 10.0.19.74
+ A 10.0.19.75
+ A 10.0.19.76
+ A 10.0.19.77
+ A 10.0.19.78
+ A 10.0.19.79
+ A 10.0.19.80
+ A 10.0.19.81
+ A 10.0.19.82
+ A 10.0.19.83
+ A 10.0.19.84
+ A 10.0.19.85
+ A 10.0.19.86
+ A 10.0.19.87
+ A 10.0.19.88
+ A 10.0.19.89
+ A 10.0.19.90
+ A 10.0.19.91
+ A 10.0.19.92
+ A 10.0.19.93
+ A 10.0.19.94
+ A 10.0.19.95
+ A 10.0.19.96
+ A 10.0.19.97
+ A 10.0.19.98
+ A 10.0.19.99
+ A 10.0.19.100
+ A 10.0.19.101
+ A 10.0.19.102
+ A 10.0.19.103
+ A 10.0.19.104
+ A 10.0.19.105
+ A 10.0.19.106
+ A 10.0.19.107
+ A 10.0.19.108
+ A 10.0.19.109
+ A 10.0.19.110
+ A 10.0.19.111
+ A 10.0.19.112
+ A 10.0.19.113
+ A 10.0.19.114
+ A 10.0.19.115
+ A 10.0.19.116
+ A 10.0.19.117
+ A 10.0.19.118
+ A 10.0.19.119
+ A 10.0.19.120
+ A 10.0.19.121
+ A 10.0.19.122
+ A 10.0.19.123
+ A 10.0.19.124
+ A 10.0.19.125
+ A 10.0.19.126
+ A 10.0.19.127
+ A 10.0.19.128
+ A 10.0.19.129
+ A 10.0.19.130
+ A 10.0.19.131
+ A 10.0.19.132
+ A 10.0.19.133
+ A 10.0.19.134
+ A 10.0.19.135
+a-maximum-rrset A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+ A 10.0.3.232
+ A 10.0.3.233
+ A 10.0.3.234
+ A 10.0.3.235
+ A 10.0.3.236
+ A 10.0.3.237
+ A 10.0.3.238
+ A 10.0.3.239
+ A 10.0.3.240
+ A 10.0.3.241
+ A 10.0.3.242
+ A 10.0.3.243
+ A 10.0.3.244
+ A 10.0.3.245
+ A 10.0.3.246
+ A 10.0.3.247
+ A 10.0.3.248
+ A 10.0.3.249
+ A 10.0.3.250
+ A 10.0.3.251
+ A 10.0.3.252
+ A 10.0.3.253
+ A 10.0.3.254
+ A 10.0.3.255
+ A 10.0.4.0
+ A 10.0.4.1
+ A 10.0.4.2
+ A 10.0.4.3
+ A 10.0.4.4
+ A 10.0.4.5
+ A 10.0.4.6
+ A 10.0.4.7
+ A 10.0.4.8
+ A 10.0.4.9
+ A 10.0.4.10
+ A 10.0.4.11
+ A 10.0.4.12
+ A 10.0.4.13
+ A 10.0.4.14
+ A 10.0.4.15
+ A 10.0.4.16
+ A 10.0.4.17
+ A 10.0.4.18
+ A 10.0.4.19
+ A 10.0.4.20
+ A 10.0.4.21
+ A 10.0.4.22
+ A 10.0.4.23
+ A 10.0.4.24
+ A 10.0.4.25
+ A 10.0.4.26
+ A 10.0.4.27
+ A 10.0.4.28
+ A 10.0.4.29
+ A 10.0.4.30
+ A 10.0.4.31
+ A 10.0.4.32
+ A 10.0.4.33
+ A 10.0.4.34
+ A 10.0.4.35
+ A 10.0.4.36
+ A 10.0.4.37
+ A 10.0.4.38
+ A 10.0.4.39
+ A 10.0.4.40
+ A 10.0.4.41
+ A 10.0.4.42
+ A 10.0.4.43
+ A 10.0.4.44
+ A 10.0.4.45
+ A 10.0.4.46
+ A 10.0.4.47
+ A 10.0.4.48
+ A 10.0.4.49
+ A 10.0.4.50
+ A 10.0.4.51
+ A 10.0.4.52
+ A 10.0.4.53
+ A 10.0.4.54
+ A 10.0.4.55
+ A 10.0.4.56
+ A 10.0.4.57
+ A 10.0.4.58
+ A 10.0.4.59
+ A 10.0.4.60
+ A 10.0.4.61
+ A 10.0.4.62
+ A 10.0.4.63
+ A 10.0.4.64
+ A 10.0.4.65
+ A 10.0.4.66
+ A 10.0.4.67
+ A 10.0.4.68
+ A 10.0.4.69
+ A 10.0.4.70
+ A 10.0.4.71
+ A 10.0.4.72
+ A 10.0.4.73
+ A 10.0.4.74
+ A 10.0.4.75
+ A 10.0.4.76
+ A 10.0.4.77
+ A 10.0.4.78
+ A 10.0.4.79
+ A 10.0.4.80
+ A 10.0.4.81
+ A 10.0.4.82
+ A 10.0.4.83
+ A 10.0.4.84
+ A 10.0.4.85
+ A 10.0.4.86
+ A 10.0.4.87
+ A 10.0.4.88
+ A 10.0.4.89
+ A 10.0.4.90
+ A 10.0.4.91
+ A 10.0.4.92
+ A 10.0.4.93
+ A 10.0.4.94
+ A 10.0.4.95
+ A 10.0.4.96
+ A 10.0.4.97
+ A 10.0.4.98
+ A 10.0.4.99
+ A 10.0.4.100
+ A 10.0.4.101
+ A 10.0.4.102
+ A 10.0.4.103
+ A 10.0.4.104
+ A 10.0.4.105
+ A 10.0.4.106
+ A 10.0.4.107
+ A 10.0.4.108
+ A 10.0.4.109
+ A 10.0.4.110
+ A 10.0.4.111
+ A 10.0.4.112
+ A 10.0.4.113
+ A 10.0.4.114
+ A 10.0.4.115
+ A 10.0.4.116
+ A 10.0.4.117
+ A 10.0.4.118
+ A 10.0.4.119
+ A 10.0.4.120
+ A 10.0.4.121
+ A 10.0.4.122
+ A 10.0.4.123
+ A 10.0.4.124
+ A 10.0.4.125
+ A 10.0.4.126
+ A 10.0.4.127
+ A 10.0.4.128
+ A 10.0.4.129
+ A 10.0.4.130
+ A 10.0.4.131
+ A 10.0.4.132
+ A 10.0.4.133
+ A 10.0.4.134
+ A 10.0.4.135
+ A 10.0.4.136
+ A 10.0.4.137
+ A 10.0.4.138
+ A 10.0.4.139
+ A 10.0.4.140
+ A 10.0.4.141
+ A 10.0.4.142
+ A 10.0.4.143
+ A 10.0.4.144
+ A 10.0.4.145
+ A 10.0.4.146
+ A 10.0.4.147
+ A 10.0.4.148
+ A 10.0.4.149
+ A 10.0.4.150
+ A 10.0.4.151
+ A 10.0.4.152
+ A 10.0.4.153
+ A 10.0.4.154
+ A 10.0.4.155
+ A 10.0.4.156
+ A 10.0.4.157
+ A 10.0.4.158
+ A 10.0.4.159
+ A 10.0.4.160
+ A 10.0.4.161
+ A 10.0.4.162
+ A 10.0.4.163
+ A 10.0.4.164
+ A 10.0.4.165
+ A 10.0.4.166
+ A 10.0.4.167
+ A 10.0.4.168
+ A 10.0.4.169
+ A 10.0.4.170
+ A 10.0.4.171
+ A 10.0.4.172
+ A 10.0.4.173
+ A 10.0.4.174
+ A 10.0.4.175
+ A 10.0.4.176
+ A 10.0.4.177
+ A 10.0.4.178
+ A 10.0.4.179
+ A 10.0.4.180
+ A 10.0.4.181
+ A 10.0.4.182
+ A 10.0.4.183
+ A 10.0.4.184
+ A 10.0.4.185
+ A 10.0.4.186
+ A 10.0.4.187
+ A 10.0.4.188
+ A 10.0.4.189
+ A 10.0.4.190
+ A 10.0.4.191
+ A 10.0.4.192
+ A 10.0.4.193
+ A 10.0.4.194
+ A 10.0.4.195
+ A 10.0.4.196
+ A 10.0.4.197
+ A 10.0.4.198
+ A 10.0.4.199
+ A 10.0.4.200
+ A 10.0.4.201
+ A 10.0.4.202
+ A 10.0.4.203
+ A 10.0.4.204
+ A 10.0.4.205
+ A 10.0.4.206
+ A 10.0.4.207
+ A 10.0.4.208
+ A 10.0.4.209
+ A 10.0.4.210
+ A 10.0.4.211
+ A 10.0.4.212
+ A 10.0.4.213
+ A 10.0.4.214
+ A 10.0.4.215
+ A 10.0.4.216
+ A 10.0.4.217
+ A 10.0.4.218
+ A 10.0.4.219
+ A 10.0.4.220
+ A 10.0.4.221
+ A 10.0.4.222
+ A 10.0.4.223
+ A 10.0.4.224
+ A 10.0.4.225
+ A 10.0.4.226
+ A 10.0.4.227
+ A 10.0.4.228
+ A 10.0.4.229
+ A 10.0.4.230
+ A 10.0.4.231
+ A 10.0.4.232
+ A 10.0.4.233
+ A 10.0.4.234
+ A 10.0.4.235
+ A 10.0.4.236
+ A 10.0.4.237
+ A 10.0.4.238
+ A 10.0.4.239
+ A 10.0.4.240
+ A 10.0.4.241
+ A 10.0.4.242
+ A 10.0.4.243
+ A 10.0.4.244
+ A 10.0.4.245
+ A 10.0.4.246
+ A 10.0.4.247
+ A 10.0.4.248
+ A 10.0.4.249
+ A 10.0.4.250
+ A 10.0.4.251
+ A 10.0.4.252
+ A 10.0.4.253
+ A 10.0.4.254
+ A 10.0.4.255
+ A 10.0.5.0
+ A 10.0.5.1
+ A 10.0.5.2
+ A 10.0.5.3
+ A 10.0.5.4
+ A 10.0.5.5
+ A 10.0.5.6
+ A 10.0.5.7
+ A 10.0.5.8
+ A 10.0.5.9
+ A 10.0.5.10
+ A 10.0.5.11
+ A 10.0.5.12
+ A 10.0.5.13
+ A 10.0.5.14
+ A 10.0.5.15
+ A 10.0.5.16
+ A 10.0.5.17
+ A 10.0.5.18
+ A 10.0.5.19
+ A 10.0.5.20
+ A 10.0.5.21
+ A 10.0.5.22
+ A 10.0.5.23
+ A 10.0.5.24
+ A 10.0.5.25
+ A 10.0.5.26
+ A 10.0.5.27
+ A 10.0.5.28
+ A 10.0.5.29
+ A 10.0.5.30
+ A 10.0.5.31
+ A 10.0.5.32
+ A 10.0.5.33
+ A 10.0.5.34
+ A 10.0.5.35
+ A 10.0.5.36
+ A 10.0.5.37
+ A 10.0.5.38
+ A 10.0.5.39
+ A 10.0.5.40
+ A 10.0.5.41
+ A 10.0.5.42
+ A 10.0.5.43
+ A 10.0.5.44
+ A 10.0.5.45
+ A 10.0.5.46
+ A 10.0.5.47
+ A 10.0.5.48
+ A 10.0.5.49
+ A 10.0.5.50
+ A 10.0.5.51
+ A 10.0.5.52
+ A 10.0.5.53
+ A 10.0.5.54
+ A 10.0.5.55
+ A 10.0.5.56
+ A 10.0.5.57
+ A 10.0.5.58
+ A 10.0.5.59
+ A 10.0.5.60
+ A 10.0.5.61
+ A 10.0.5.62
+ A 10.0.5.63
+ A 10.0.5.64
+ A 10.0.5.65
+ A 10.0.5.66
+ A 10.0.5.67
+ A 10.0.5.68
+ A 10.0.5.69
+ A 10.0.5.70
+ A 10.0.5.71
+ A 10.0.5.72
+ A 10.0.5.73
+ A 10.0.5.74
+ A 10.0.5.75
+ A 10.0.5.76
+ A 10.0.5.77
+ A 10.0.5.78
+ A 10.0.5.79
+ A 10.0.5.80
+ A 10.0.5.81
+ A 10.0.5.82
+ A 10.0.5.83
+ A 10.0.5.84
+ A 10.0.5.85
+ A 10.0.5.86
+ A 10.0.5.87
+ A 10.0.5.88
+ A 10.0.5.89
+ A 10.0.5.90
+ A 10.0.5.91
+ A 10.0.5.92
+ A 10.0.5.93
+ A 10.0.5.94
+ A 10.0.5.95
+ A 10.0.5.96
+ A 10.0.5.97
+ A 10.0.5.98
+ A 10.0.5.99
+ A 10.0.5.100
+ A 10.0.5.101
+ A 10.0.5.102
+ A 10.0.5.103
+ A 10.0.5.104
+ A 10.0.5.105
+ A 10.0.5.106
+ A 10.0.5.107
+ A 10.0.5.108
+ A 10.0.5.109
+ A 10.0.5.110
+ A 10.0.5.111
+ A 10.0.5.112
+ A 10.0.5.113
+ A 10.0.5.114
+ A 10.0.5.115
+ A 10.0.5.116
+ A 10.0.5.117
+ A 10.0.5.118
+ A 10.0.5.119
+ A 10.0.5.120
+ A 10.0.5.121
+ A 10.0.5.122
+ A 10.0.5.123
+ A 10.0.5.124
+ A 10.0.5.125
+ A 10.0.5.126
+ A 10.0.5.127
+ A 10.0.5.128
+ A 10.0.5.129
+ A 10.0.5.130
+ A 10.0.5.131
+ A 10.0.5.132
+ A 10.0.5.133
+ A 10.0.5.134
+ A 10.0.5.135
+ A 10.0.5.136
+ A 10.0.5.137
+ A 10.0.5.138
+ A 10.0.5.139
+ A 10.0.5.140
+ A 10.0.5.141
+ A 10.0.5.142
+ A 10.0.5.143
+ A 10.0.5.144
+ A 10.0.5.145
+ A 10.0.5.146
+ A 10.0.5.147
+ A 10.0.5.148
+ A 10.0.5.149
+ A 10.0.5.150
+ A 10.0.5.151
+ A 10.0.5.152
+ A 10.0.5.153
+ A 10.0.5.154
+ A 10.0.5.155
+ A 10.0.5.156
+ A 10.0.5.157
+ A 10.0.5.158
+ A 10.0.5.159
+ A 10.0.5.160
+ A 10.0.5.161
+ A 10.0.5.162
+ A 10.0.5.163
+ A 10.0.5.164
+ A 10.0.5.165
+ A 10.0.5.166
+ A 10.0.5.167
+ A 10.0.5.168
+ A 10.0.5.169
+ A 10.0.5.170
+ A 10.0.5.171
+ A 10.0.5.172
+ A 10.0.5.173
+ A 10.0.5.174
+ A 10.0.5.175
+ A 10.0.5.176
+ A 10.0.5.177
+ A 10.0.5.178
+ A 10.0.5.179
+ A 10.0.5.180
+ A 10.0.5.181
+ A 10.0.5.182
+ A 10.0.5.183
+ A 10.0.5.184
+ A 10.0.5.185
+ A 10.0.5.186
+ A 10.0.5.187
+ A 10.0.5.188
+ A 10.0.5.189
+ A 10.0.5.190
+ A 10.0.5.191
+ A 10.0.5.192
+ A 10.0.5.193
+ A 10.0.5.194
+ A 10.0.5.195
+ A 10.0.5.196
+ A 10.0.5.197
+ A 10.0.5.198
+ A 10.0.5.199
+ A 10.0.5.200
+ A 10.0.5.201
+ A 10.0.5.202
+ A 10.0.5.203
+ A 10.0.5.204
+ A 10.0.5.205
+ A 10.0.5.206
+ A 10.0.5.207
+ A 10.0.5.208
+ A 10.0.5.209
+ A 10.0.5.210
+ A 10.0.5.211
+ A 10.0.5.212
+ A 10.0.5.213
+ A 10.0.5.214
+ A 10.0.5.215
+ A 10.0.5.216
+ A 10.0.5.217
+ A 10.0.5.218
+ A 10.0.5.219
+ A 10.0.5.220
+ A 10.0.5.221
+ A 10.0.5.222
+ A 10.0.5.223
+ A 10.0.5.224
+ A 10.0.5.225
+ A 10.0.5.226
+ A 10.0.5.227
+ A 10.0.5.228
+ A 10.0.5.229
+ A 10.0.5.230
+ A 10.0.5.231
+ A 10.0.5.232
+ A 10.0.5.233
+ A 10.0.5.234
+ A 10.0.5.235
+ A 10.0.5.236
+ A 10.0.5.237
+ A 10.0.5.238
+ A 10.0.5.239
+ A 10.0.5.240
+ A 10.0.5.241
+ A 10.0.5.242
+ A 10.0.5.243
+ A 10.0.5.244
+ A 10.0.5.245
+ A 10.0.5.246
+ A 10.0.5.247
+ A 10.0.5.248
+ A 10.0.5.249
+ A 10.0.5.250
+ A 10.0.5.251
+ A 10.0.5.252
+ A 10.0.5.253
+ A 10.0.5.254
+ A 10.0.5.255
+ A 10.0.6.0
+ A 10.0.6.1
+ A 10.0.6.2
+ A 10.0.6.3
+ A 10.0.6.4
+ A 10.0.6.5
+ A 10.0.6.6
+ A 10.0.6.7
+ A 10.0.6.8
+ A 10.0.6.9
+ A 10.0.6.10
+ A 10.0.6.11
+ A 10.0.6.12
+ A 10.0.6.13
+ A 10.0.6.14
+ A 10.0.6.15
+ A 10.0.6.16
+ A 10.0.6.17
+ A 10.0.6.18
+ A 10.0.6.19
+ A 10.0.6.20
+ A 10.0.6.21
+ A 10.0.6.22
+ A 10.0.6.23
+ A 10.0.6.24
+ A 10.0.6.25
+ A 10.0.6.26
+ A 10.0.6.27
+ A 10.0.6.28
+ A 10.0.6.29
+ A 10.0.6.30
+ A 10.0.6.31
+ A 10.0.6.32
+ A 10.0.6.33
+ A 10.0.6.34
+ A 10.0.6.35
+ A 10.0.6.36
+ A 10.0.6.37
+ A 10.0.6.38
+ A 10.0.6.39
+ A 10.0.6.40
+ A 10.0.6.41
+ A 10.0.6.42
+ A 10.0.6.43
+ A 10.0.6.44
+ A 10.0.6.45
+ A 10.0.6.46
+ A 10.0.6.47
+ A 10.0.6.48
+ A 10.0.6.49
+ A 10.0.6.50
+ A 10.0.6.51
+ A 10.0.6.52
+ A 10.0.6.53
+ A 10.0.6.54
+ A 10.0.6.55
+ A 10.0.6.56
+ A 10.0.6.57
+ A 10.0.6.58
+ A 10.0.6.59
+ A 10.0.6.60
+ A 10.0.6.61
+ A 10.0.6.62
+ A 10.0.6.63
+ A 10.0.6.64
+ A 10.0.6.65
+ A 10.0.6.66
+ A 10.0.6.67
+ A 10.0.6.68
+ A 10.0.6.69
+ A 10.0.6.70
+ A 10.0.6.71
+ A 10.0.6.72
+ A 10.0.6.73
+ A 10.0.6.74
+ A 10.0.6.75
+ A 10.0.6.76
+ A 10.0.6.77
+ A 10.0.6.78
+ A 10.0.6.79
+ A 10.0.6.80
+ A 10.0.6.81
+ A 10.0.6.82
+ A 10.0.6.83
+ A 10.0.6.84
+ A 10.0.6.85
+ A 10.0.6.86
+ A 10.0.6.87
+ A 10.0.6.88
+ A 10.0.6.89
+ A 10.0.6.90
+ A 10.0.6.91
+ A 10.0.6.92
+ A 10.0.6.93
+ A 10.0.6.94
+ A 10.0.6.95
+ A 10.0.6.96
+ A 10.0.6.97
+ A 10.0.6.98
+ A 10.0.6.99
+ A 10.0.6.100
+ A 10.0.6.101
+ A 10.0.6.102
+ A 10.0.6.103
+ A 10.0.6.104
+ A 10.0.6.105
+ A 10.0.6.106
+ A 10.0.6.107
+ A 10.0.6.108
+ A 10.0.6.109
+ A 10.0.6.110
+ A 10.0.6.111
+ A 10.0.6.112
+ A 10.0.6.113
+ A 10.0.6.114
+ A 10.0.6.115
+ A 10.0.6.116
+ A 10.0.6.117
+ A 10.0.6.118
+ A 10.0.6.119
+ A 10.0.6.120
+ A 10.0.6.121
+ A 10.0.6.122
+ A 10.0.6.123
+ A 10.0.6.124
+ A 10.0.6.125
+ A 10.0.6.126
+ A 10.0.6.127
+ A 10.0.6.128
+ A 10.0.6.129
+ A 10.0.6.130
+ A 10.0.6.131
+ A 10.0.6.132
+ A 10.0.6.133
+ A 10.0.6.134
+ A 10.0.6.135
+ A 10.0.6.136
+ A 10.0.6.137
+ A 10.0.6.138
+ A 10.0.6.139
+ A 10.0.6.140
+ A 10.0.6.141
+ A 10.0.6.142
+ A 10.0.6.143
+ A 10.0.6.144
+ A 10.0.6.145
+ A 10.0.6.146
+ A 10.0.6.147
+ A 10.0.6.148
+ A 10.0.6.149
+ A 10.0.6.150
+ A 10.0.6.151
+ A 10.0.6.152
+ A 10.0.6.153
+ A 10.0.6.154
+ A 10.0.6.155
+ A 10.0.6.156
+ A 10.0.6.157
+ A 10.0.6.158
+ A 10.0.6.159
+ A 10.0.6.160
+ A 10.0.6.161
+ A 10.0.6.162
+ A 10.0.6.163
+ A 10.0.6.164
+ A 10.0.6.165
+ A 10.0.6.166
+ A 10.0.6.167
+ A 10.0.6.168
+ A 10.0.6.169
+ A 10.0.6.170
+ A 10.0.6.171
+ A 10.0.6.172
+ A 10.0.6.173
+ A 10.0.6.174
+ A 10.0.6.175
+ A 10.0.6.176
+ A 10.0.6.177
+ A 10.0.6.178
+ A 10.0.6.179
+ A 10.0.6.180
+ A 10.0.6.181
+ A 10.0.6.182
+ A 10.0.6.183
+ A 10.0.6.184
+ A 10.0.6.185
+ A 10.0.6.186
+ A 10.0.6.187
+ A 10.0.6.188
+ A 10.0.6.189
+ A 10.0.6.190
+ A 10.0.6.191
+ A 10.0.6.192
+ A 10.0.6.193
+ A 10.0.6.194
+ A 10.0.6.195
+ A 10.0.6.196
+ A 10.0.6.197
+ A 10.0.6.198
+ A 10.0.6.199
+ A 10.0.6.200
+ A 10.0.6.201
+ A 10.0.6.202
+ A 10.0.6.203
+ A 10.0.6.204
+ A 10.0.6.205
+ A 10.0.6.206
+ A 10.0.6.207
+ A 10.0.6.208
+ A 10.0.6.209
+ A 10.0.6.210
+ A 10.0.6.211
+ A 10.0.6.212
+ A 10.0.6.213
+ A 10.0.6.214
+ A 10.0.6.215
+ A 10.0.6.216
+ A 10.0.6.217
+ A 10.0.6.218
+ A 10.0.6.219
+ A 10.0.6.220
+ A 10.0.6.221
+ A 10.0.6.222
+ A 10.0.6.223
+ A 10.0.6.224
+ A 10.0.6.225
+ A 10.0.6.226
+ A 10.0.6.227
+ A 10.0.6.228
+ A 10.0.6.229
+ A 10.0.6.230
+ A 10.0.6.231
+ A 10.0.6.232
+ A 10.0.6.233
+ A 10.0.6.234
+ A 10.0.6.235
+ A 10.0.6.236
+ A 10.0.6.237
+ A 10.0.6.238
+ A 10.0.6.239
+ A 10.0.6.240
+ A 10.0.6.241
+ A 10.0.6.242
+ A 10.0.6.243
+ A 10.0.6.244
+ A 10.0.6.245
+ A 10.0.6.246
+ A 10.0.6.247
+ A 10.0.6.248
+ A 10.0.6.249
+ A 10.0.6.250
+ A 10.0.6.251
+ A 10.0.6.252
+ A 10.0.6.253
+ A 10.0.6.254
+ A 10.0.6.255
+ A 10.0.7.0
+ A 10.0.7.1
+ A 10.0.7.2
+ A 10.0.7.3
+ A 10.0.7.4
+ A 10.0.7.5
+ A 10.0.7.6
+ A 10.0.7.7
+ A 10.0.7.8
+ A 10.0.7.9
+ A 10.0.7.10
+ A 10.0.7.11
+ A 10.0.7.12
+ A 10.0.7.13
+ A 10.0.7.14
+ A 10.0.7.15
+ A 10.0.7.16
+ A 10.0.7.17
+ A 10.0.7.18
+ A 10.0.7.19
+ A 10.0.7.20
+ A 10.0.7.21
+ A 10.0.7.22
+ A 10.0.7.23
+ A 10.0.7.24
+ A 10.0.7.25
+ A 10.0.7.26
+ A 10.0.7.27
+ A 10.0.7.28
+ A 10.0.7.29
+ A 10.0.7.30
+ A 10.0.7.31
+ A 10.0.7.32
+ A 10.0.7.33
+ A 10.0.7.34
+ A 10.0.7.35
+ A 10.0.7.36
+ A 10.0.7.37
+ A 10.0.7.38
+ A 10.0.7.39
+ A 10.0.7.40
+ A 10.0.7.41
+ A 10.0.7.42
+ A 10.0.7.43
+ A 10.0.7.44
+ A 10.0.7.45
+ A 10.0.7.46
+ A 10.0.7.47
+ A 10.0.7.48
+ A 10.0.7.49
+ A 10.0.7.50
+ A 10.0.7.51
+ A 10.0.7.52
+ A 10.0.7.53
+ A 10.0.7.54
+ A 10.0.7.55
+ A 10.0.7.56
+ A 10.0.7.57
+ A 10.0.7.58
+ A 10.0.7.59
+ A 10.0.7.60
+ A 10.0.7.61
+ A 10.0.7.62
+ A 10.0.7.63
+ A 10.0.7.64
+ A 10.0.7.65
+ A 10.0.7.66
+ A 10.0.7.67
+ A 10.0.7.68
+ A 10.0.7.69
+ A 10.0.7.70
+ A 10.0.7.71
+ A 10.0.7.72
+ A 10.0.7.73
+ A 10.0.7.74
+ A 10.0.7.75
+ A 10.0.7.76
+ A 10.0.7.77
+ A 10.0.7.78
+ A 10.0.7.79
+ A 10.0.7.80
+ A 10.0.7.81
+ A 10.0.7.82
+ A 10.0.7.83
+ A 10.0.7.84
+ A 10.0.7.85
+ A 10.0.7.86
+ A 10.0.7.87
+ A 10.0.7.88
+ A 10.0.7.89
+ A 10.0.7.90
+ A 10.0.7.91
+ A 10.0.7.92
+ A 10.0.7.93
+ A 10.0.7.94
+ A 10.0.7.95
+ A 10.0.7.96
+ A 10.0.7.97
+ A 10.0.7.98
+ A 10.0.7.99
+ A 10.0.7.100
+ A 10.0.7.101
+ A 10.0.7.102
+ A 10.0.7.103
+ A 10.0.7.104
+ A 10.0.7.105
+ A 10.0.7.106
+ A 10.0.7.107
+ A 10.0.7.108
+ A 10.0.7.109
+ A 10.0.7.110
+ A 10.0.7.111
+ A 10.0.7.112
+ A 10.0.7.113
+ A 10.0.7.114
+ A 10.0.7.115
+ A 10.0.7.116
+ A 10.0.7.117
+ A 10.0.7.118
+ A 10.0.7.119
+ A 10.0.7.120
+ A 10.0.7.121
+ A 10.0.7.122
+ A 10.0.7.123
+ A 10.0.7.124
+ A 10.0.7.125
+ A 10.0.7.126
+ A 10.0.7.127
+ A 10.0.7.128
+ A 10.0.7.129
+ A 10.0.7.130
+ A 10.0.7.131
+ A 10.0.7.132
+ A 10.0.7.133
+ A 10.0.7.134
+ A 10.0.7.135
+ A 10.0.7.136
+ A 10.0.7.137
+ A 10.0.7.138
+ A 10.0.7.139
+ A 10.0.7.140
+ A 10.0.7.141
+ A 10.0.7.142
+ A 10.0.7.143
+ A 10.0.7.144
+ A 10.0.7.145
+ A 10.0.7.146
+ A 10.0.7.147
+ A 10.0.7.148
+ A 10.0.7.149
+ A 10.0.7.150
+ A 10.0.7.151
+ A 10.0.7.152
+ A 10.0.7.153
+ A 10.0.7.154
+ A 10.0.7.155
+ A 10.0.7.156
+ A 10.0.7.157
+ A 10.0.7.158
+ A 10.0.7.159
+ A 10.0.7.160
+ A 10.0.7.161
+ A 10.0.7.162
+ A 10.0.7.163
+ A 10.0.7.164
+ A 10.0.7.165
+ A 10.0.7.166
+ A 10.0.7.167
+ A 10.0.7.168
+ A 10.0.7.169
+ A 10.0.7.170
+ A 10.0.7.171
+ A 10.0.7.172
+ A 10.0.7.173
+ A 10.0.7.174
+ A 10.0.7.175
+ A 10.0.7.176
+ A 10.0.7.177
+ A 10.0.7.178
+ A 10.0.7.179
+ A 10.0.7.180
+ A 10.0.7.181
+ A 10.0.7.182
+ A 10.0.7.183
+ A 10.0.7.184
+ A 10.0.7.185
+ A 10.0.7.186
+ A 10.0.7.187
+ A 10.0.7.188
+ A 10.0.7.189
+ A 10.0.7.190
+ A 10.0.7.191
+ A 10.0.7.192
+ A 10.0.7.193
+ A 10.0.7.194
+ A 10.0.7.195
+ A 10.0.7.196
+ A 10.0.7.197
+ A 10.0.7.198
+ A 10.0.7.199
+ A 10.0.7.200
+ A 10.0.7.201
+ A 10.0.7.202
+ A 10.0.7.203
+ A 10.0.7.204
+ A 10.0.7.205
+ A 10.0.7.206
+ A 10.0.7.207
+ A 10.0.7.208
+ A 10.0.7.209
+ A 10.0.7.210
+ A 10.0.7.211
+ A 10.0.7.212
+ A 10.0.7.213
+ A 10.0.7.214
+ A 10.0.7.215
+ A 10.0.7.216
+ A 10.0.7.217
+ A 10.0.7.218
+ A 10.0.7.219
+ A 10.0.7.220
+ A 10.0.7.221
+ A 10.0.7.222
+ A 10.0.7.223
+ A 10.0.7.224
+ A 10.0.7.225
+ A 10.0.7.226
+ A 10.0.7.227
+ A 10.0.7.228
+ A 10.0.7.229
+ A 10.0.7.230
+ A 10.0.7.231
+ A 10.0.7.232
+ A 10.0.7.233
+ A 10.0.7.234
+ A 10.0.7.235
+ A 10.0.7.236
+ A 10.0.7.237
+ A 10.0.7.238
+ A 10.0.7.239
+ A 10.0.7.240
+ A 10.0.7.241
+ A 10.0.7.242
+ A 10.0.7.243
+ A 10.0.7.244
+ A 10.0.7.245
+ A 10.0.7.246
+ A 10.0.7.247
+ A 10.0.7.248
+ A 10.0.7.249
+ A 10.0.7.250
+ A 10.0.7.251
+ A 10.0.7.252
+ A 10.0.7.253
+ A 10.0.7.254
+ A 10.0.7.255
+ A 10.0.8.0
+ A 10.0.8.1
+ A 10.0.8.2
+ A 10.0.8.3
+ A 10.0.8.4
+ A 10.0.8.5
+ A 10.0.8.6
+ A 10.0.8.7
+ A 10.0.8.8
+ A 10.0.8.9
+ A 10.0.8.10
+ A 10.0.8.11
+ A 10.0.8.12
+ A 10.0.8.13
+ A 10.0.8.14
+ A 10.0.8.15
+ A 10.0.8.16
+ A 10.0.8.17
+ A 10.0.8.18
+ A 10.0.8.19
+ A 10.0.8.20
+ A 10.0.8.21
+ A 10.0.8.22
+ A 10.0.8.23
+ A 10.0.8.24
+ A 10.0.8.25
+ A 10.0.8.26
+ A 10.0.8.27
+ A 10.0.8.28
+ A 10.0.8.29
+ A 10.0.8.30
+ A 10.0.8.31
+ A 10.0.8.32
+ A 10.0.8.33
+ A 10.0.8.34
+ A 10.0.8.35
+ A 10.0.8.36
+ A 10.0.8.37
+ A 10.0.8.38
+ A 10.0.8.39
+ A 10.0.8.40
+ A 10.0.8.41
+ A 10.0.8.42
+ A 10.0.8.43
+ A 10.0.8.44
+ A 10.0.8.45
+ A 10.0.8.46
+ A 10.0.8.47
+ A 10.0.8.48
+ A 10.0.8.49
+ A 10.0.8.50
+ A 10.0.8.51
+ A 10.0.8.52
+ A 10.0.8.53
+ A 10.0.8.54
+ A 10.0.8.55
+ A 10.0.8.56
+ A 10.0.8.57
+ A 10.0.8.58
+ A 10.0.8.59
+ A 10.0.8.60
+ A 10.0.8.61
+ A 10.0.8.62
+ A 10.0.8.63
+ A 10.0.8.64
+ A 10.0.8.65
+ A 10.0.8.66
+ A 10.0.8.67
+ A 10.0.8.68
+ A 10.0.8.69
+ A 10.0.8.70
+ A 10.0.8.71
+ A 10.0.8.72
+ A 10.0.8.73
+ A 10.0.8.74
+ A 10.0.8.75
+ A 10.0.8.76
+ A 10.0.8.77
+ A 10.0.8.78
+ A 10.0.8.79
+ A 10.0.8.80
+ A 10.0.8.81
+ A 10.0.8.82
+ A 10.0.8.83
+ A 10.0.8.84
+ A 10.0.8.85
+ A 10.0.8.86
+ A 10.0.8.87
+ A 10.0.8.88
+ A 10.0.8.89
+ A 10.0.8.90
+ A 10.0.8.91
+ A 10.0.8.92
+ A 10.0.8.93
+ A 10.0.8.94
+ A 10.0.8.95
+ A 10.0.8.96
+ A 10.0.8.97
+ A 10.0.8.98
+ A 10.0.8.99
+ A 10.0.8.100
+ A 10.0.8.101
+ A 10.0.8.102
+ A 10.0.8.103
+ A 10.0.8.104
+ A 10.0.8.105
+ A 10.0.8.106
+ A 10.0.8.107
+ A 10.0.8.108
+ A 10.0.8.109
+ A 10.0.8.110
+ A 10.0.8.111
+ A 10.0.8.112
+ A 10.0.8.113
+ A 10.0.8.114
+ A 10.0.8.115
+ A 10.0.8.116
+ A 10.0.8.117
+ A 10.0.8.118
+ A 10.0.8.119
+ A 10.0.8.120
+ A 10.0.8.121
+ A 10.0.8.122
+ A 10.0.8.123
+ A 10.0.8.124
+ A 10.0.8.125
+ A 10.0.8.126
+ A 10.0.8.127
+ A 10.0.8.128
+ A 10.0.8.129
+ A 10.0.8.130
+ A 10.0.8.131
+ A 10.0.8.132
+ A 10.0.8.133
+ A 10.0.8.134
+ A 10.0.8.135
+ A 10.0.8.136
+ A 10.0.8.137
+ A 10.0.8.138
+ A 10.0.8.139
+ A 10.0.8.140
+ A 10.0.8.141
+ A 10.0.8.142
+ A 10.0.8.143
+ A 10.0.8.144
+ A 10.0.8.145
+ A 10.0.8.146
+ A 10.0.8.147
+ A 10.0.8.148
+ A 10.0.8.149
+ A 10.0.8.150
+ A 10.0.8.151
+ A 10.0.8.152
+ A 10.0.8.153
+ A 10.0.8.154
+ A 10.0.8.155
+ A 10.0.8.156
+ A 10.0.8.157
+ A 10.0.8.158
+ A 10.0.8.159
+ A 10.0.8.160
+ A 10.0.8.161
+ A 10.0.8.162
+ A 10.0.8.163
+ A 10.0.8.164
+ A 10.0.8.165
+ A 10.0.8.166
+ A 10.0.8.167
+ A 10.0.8.168
+ A 10.0.8.169
+ A 10.0.8.170
+ A 10.0.8.171
+ A 10.0.8.172
+ A 10.0.8.173
+ A 10.0.8.174
+ A 10.0.8.175
+ A 10.0.8.176
+ A 10.0.8.177
+ A 10.0.8.178
+ A 10.0.8.179
+ A 10.0.8.180
+ A 10.0.8.181
+ A 10.0.8.182
+ A 10.0.8.183
+ A 10.0.8.184
+ A 10.0.8.185
+ A 10.0.8.186
+ A 10.0.8.187
+ A 10.0.8.188
+ A 10.0.8.189
+ A 10.0.8.190
+ A 10.0.8.191
+ A 10.0.8.192
+ A 10.0.8.193
+ A 10.0.8.194
+ A 10.0.8.195
+ A 10.0.8.196
+ A 10.0.8.197
+ A 10.0.8.198
+ A 10.0.8.199
+ A 10.0.8.200
+ A 10.0.8.201
+ A 10.0.8.202
+ A 10.0.8.203
+ A 10.0.8.204
+ A 10.0.8.205
+ A 10.0.8.206
+ A 10.0.8.207
+ A 10.0.8.208
+ A 10.0.8.209
+ A 10.0.8.210
+ A 10.0.8.211
+ A 10.0.8.212
+ A 10.0.8.213
+ A 10.0.8.214
+ A 10.0.8.215
+ A 10.0.8.216
+ A 10.0.8.217
+ A 10.0.8.218
+ A 10.0.8.219
+ A 10.0.8.220
+ A 10.0.8.221
+ A 10.0.8.222
+ A 10.0.8.223
+ A 10.0.8.224
+ A 10.0.8.225
+ A 10.0.8.226
+ A 10.0.8.227
+ A 10.0.8.228
+ A 10.0.8.229
+ A 10.0.8.230
+ A 10.0.8.231
+ A 10.0.8.232
+ A 10.0.8.233
+ A 10.0.8.234
+ A 10.0.8.235
+ A 10.0.8.236
+ A 10.0.8.237
+ A 10.0.8.238
+ A 10.0.8.239
+ A 10.0.8.240
+ A 10.0.8.241
+ A 10.0.8.242
+ A 10.0.8.243
+ A 10.0.8.244
+ A 10.0.8.245
+ A 10.0.8.246
+ A 10.0.8.247
+ A 10.0.8.248
+ A 10.0.8.249
+ A 10.0.8.250
+ A 10.0.8.251
+ A 10.0.8.252
+ A 10.0.8.253
+ A 10.0.8.254
+ A 10.0.8.255
+ A 10.0.9.0
+ A 10.0.9.1
+ A 10.0.9.2
+ A 10.0.9.3
+ A 10.0.9.4
+ A 10.0.9.5
+ A 10.0.9.6
+ A 10.0.9.7
+ A 10.0.9.8
+ A 10.0.9.9
+ A 10.0.9.10
+ A 10.0.9.11
+ A 10.0.9.12
+ A 10.0.9.13
+ A 10.0.9.14
+ A 10.0.9.15
+ A 10.0.9.16
+ A 10.0.9.17
+ A 10.0.9.18
+ A 10.0.9.19
+ A 10.0.9.20
+ A 10.0.9.21
+ A 10.0.9.22
+ A 10.0.9.23
+ A 10.0.9.24
+ A 10.0.9.25
+ A 10.0.9.26
+ A 10.0.9.27
+ A 10.0.9.28
+ A 10.0.9.29
+ A 10.0.9.30
+ A 10.0.9.31
+ A 10.0.9.32
+ A 10.0.9.33
+ A 10.0.9.34
+ A 10.0.9.35
+ A 10.0.9.36
+ A 10.0.9.37
+ A 10.0.9.38
+ A 10.0.9.39
+ A 10.0.9.40
+ A 10.0.9.41
+ A 10.0.9.42
+ A 10.0.9.43
+ A 10.0.9.44
+ A 10.0.9.45
+ A 10.0.9.46
+ A 10.0.9.47
+ A 10.0.9.48
+ A 10.0.9.49
+ A 10.0.9.50
+ A 10.0.9.51
+ A 10.0.9.52
+ A 10.0.9.53
+ A 10.0.9.54
+ A 10.0.9.55
+ A 10.0.9.56
+ A 10.0.9.57
+ A 10.0.9.58
+ A 10.0.9.59
+ A 10.0.9.60
+ A 10.0.9.61
+ A 10.0.9.62
+ A 10.0.9.63
+ A 10.0.9.64
+ A 10.0.9.65
+ A 10.0.9.66
+ A 10.0.9.67
+ A 10.0.9.68
+ A 10.0.9.69
+ A 10.0.9.70
+ A 10.0.9.71
+ A 10.0.9.72
+ A 10.0.9.73
+ A 10.0.9.74
+ A 10.0.9.75
+ A 10.0.9.76
+ A 10.0.9.77
+ A 10.0.9.78
+ A 10.0.9.79
+ A 10.0.9.80
+ A 10.0.9.81
+ A 10.0.9.82
+ A 10.0.9.83
+ A 10.0.9.84
+ A 10.0.9.85
+ A 10.0.9.86
+ A 10.0.9.87
+ A 10.0.9.88
+ A 10.0.9.89
+ A 10.0.9.90
+ A 10.0.9.91
+ A 10.0.9.92
+ A 10.0.9.93
+ A 10.0.9.94
+ A 10.0.9.95
+ A 10.0.9.96
+ A 10.0.9.97
+ A 10.0.9.98
+ A 10.0.9.99
+ A 10.0.9.100
+ A 10.0.9.101
+ A 10.0.9.102
+ A 10.0.9.103
+ A 10.0.9.104
+ A 10.0.9.105
+ A 10.0.9.106
+ A 10.0.9.107
+ A 10.0.9.108
+ A 10.0.9.109
+ A 10.0.9.110
+ A 10.0.9.111
+ A 10.0.9.112
+ A 10.0.9.113
+ A 10.0.9.114
+ A 10.0.9.115
+ A 10.0.9.116
+ A 10.0.9.117
+ A 10.0.9.118
+ A 10.0.9.119
+ A 10.0.9.120
+ A 10.0.9.121
+ A 10.0.9.122
+ A 10.0.9.123
+ A 10.0.9.124
+ A 10.0.9.125
+ A 10.0.9.126
+ A 10.0.9.127
+ A 10.0.9.128
+ A 10.0.9.129
+ A 10.0.9.130
+ A 10.0.9.131
+ A 10.0.9.132
+ A 10.0.9.133
+ A 10.0.9.134
+ A 10.0.9.135
+ A 10.0.9.136
+ A 10.0.9.137
+ A 10.0.9.138
+ A 10.0.9.139
+ A 10.0.9.140
+ A 10.0.9.141
+ A 10.0.9.142
+ A 10.0.9.143
+ A 10.0.9.144
+ A 10.0.9.145
+ A 10.0.9.146
+ A 10.0.9.147
+ A 10.0.9.148
+ A 10.0.9.149
+ A 10.0.9.150
+ A 10.0.9.151
+ A 10.0.9.152
+ A 10.0.9.153
+ A 10.0.9.154
+ A 10.0.9.155
+ A 10.0.9.156
+ A 10.0.9.157
+ A 10.0.9.158
+ A 10.0.9.159
+ A 10.0.9.160
+ A 10.0.9.161
+ A 10.0.9.162
+ A 10.0.9.163
+ A 10.0.9.164
+ A 10.0.9.165
+ A 10.0.9.166
+ A 10.0.9.167
+ A 10.0.9.168
+ A 10.0.9.169
+ A 10.0.9.170
+ A 10.0.9.171
+ A 10.0.9.172
+ A 10.0.9.173
+ A 10.0.9.174
+ A 10.0.9.175
+ A 10.0.9.176
+ A 10.0.9.177
+ A 10.0.9.178
+ A 10.0.9.179
+ A 10.0.9.180
+ A 10.0.9.181
+ A 10.0.9.182
+ A 10.0.9.183
+ A 10.0.9.184
+ A 10.0.9.185
+ A 10.0.9.186
+ A 10.0.9.187
+ A 10.0.9.188
+ A 10.0.9.189
+ A 10.0.9.190
+ A 10.0.9.191
+ A 10.0.9.192
+ A 10.0.9.193
+ A 10.0.9.194
+ A 10.0.9.195
+ A 10.0.9.196
+ A 10.0.9.197
+ A 10.0.9.198
+ A 10.0.9.199
+ A 10.0.9.200
+ A 10.0.9.201
+ A 10.0.9.202
+ A 10.0.9.203
+ A 10.0.9.204
+ A 10.0.9.205
+ A 10.0.9.206
+ A 10.0.9.207
+ A 10.0.9.208
+ A 10.0.9.209
+ A 10.0.9.210
+ A 10.0.9.211
+ A 10.0.9.212
+ A 10.0.9.213
+ A 10.0.9.214
+ A 10.0.9.215
+ A 10.0.9.216
+ A 10.0.9.217
+ A 10.0.9.218
+ A 10.0.9.219
+ A 10.0.9.220
+ A 10.0.9.221
+ A 10.0.9.222
+ A 10.0.9.223
+ A 10.0.9.224
+ A 10.0.9.225
+ A 10.0.9.226
+ A 10.0.9.227
+ A 10.0.9.228
+ A 10.0.9.229
+ A 10.0.9.230
+ A 10.0.9.231
+ A 10.0.9.232
+ A 10.0.9.233
+ A 10.0.9.234
+ A 10.0.9.235
+ A 10.0.9.236
+ A 10.0.9.237
+ A 10.0.9.238
+ A 10.0.9.239
+ A 10.0.9.240
+ A 10.0.9.241
+ A 10.0.9.242
+ A 10.0.9.243
+ A 10.0.9.244
+ A 10.0.9.245
+ A 10.0.9.246
+ A 10.0.9.247
+ A 10.0.9.248
+ A 10.0.9.249
+ A 10.0.9.250
+ A 10.0.9.251
+ A 10.0.9.252
+ A 10.0.9.253
+ A 10.0.9.254
+ A 10.0.9.255
+ A 10.0.10.0
+ A 10.0.10.1
+ A 10.0.10.2
+ A 10.0.10.3
+ A 10.0.10.4
+ A 10.0.10.5
+ A 10.0.10.6
+ A 10.0.10.7
+ A 10.0.10.8
+ A 10.0.10.9
+ A 10.0.10.10
+ A 10.0.10.11
+ A 10.0.10.12
+ A 10.0.10.13
+ A 10.0.10.14
+ A 10.0.10.15
+ A 10.0.10.16
+ A 10.0.10.17
+ A 10.0.10.18
+ A 10.0.10.19
+ A 10.0.10.20
+ A 10.0.10.21
+ A 10.0.10.22
+ A 10.0.10.23
+ A 10.0.10.24
+ A 10.0.10.25
+ A 10.0.10.26
+ A 10.0.10.27
+ A 10.0.10.28
+ A 10.0.10.29
+ A 10.0.10.30
+ A 10.0.10.31
+ A 10.0.10.32
+ A 10.0.10.33
+ A 10.0.10.34
+ A 10.0.10.35
+ A 10.0.10.36
+ A 10.0.10.37
+ A 10.0.10.38
+ A 10.0.10.39
+ A 10.0.10.40
+ A 10.0.10.41
+ A 10.0.10.42
+ A 10.0.10.43
+ A 10.0.10.44
+ A 10.0.10.45
+ A 10.0.10.46
+ A 10.0.10.47
+ A 10.0.10.48
+ A 10.0.10.49
+ A 10.0.10.50
+ A 10.0.10.51
+ A 10.0.10.52
+ A 10.0.10.53
+ A 10.0.10.54
+ A 10.0.10.55
+ A 10.0.10.56
+ A 10.0.10.57
+ A 10.0.10.58
+ A 10.0.10.59
+ A 10.0.10.60
+ A 10.0.10.61
+ A 10.0.10.62
+ A 10.0.10.63
+ A 10.0.10.64
+ A 10.0.10.65
+ A 10.0.10.66
+ A 10.0.10.67
+ A 10.0.10.68
+ A 10.0.10.69
+ A 10.0.10.70
+ A 10.0.10.71
+ A 10.0.10.72
+ A 10.0.10.73
+ A 10.0.10.74
+ A 10.0.10.75
+ A 10.0.10.76
+ A 10.0.10.77
+ A 10.0.10.78
+ A 10.0.10.79
+ A 10.0.10.80
+ A 10.0.10.81
+ A 10.0.10.82
+ A 10.0.10.83
+ A 10.0.10.84
+ A 10.0.10.85
+ A 10.0.10.86
+ A 10.0.10.87
+ A 10.0.10.88
+ A 10.0.10.89
+ A 10.0.10.90
+ A 10.0.10.91
+ A 10.0.10.92
+ A 10.0.10.93
+ A 10.0.10.94
+ A 10.0.10.95
+ A 10.0.10.96
+ A 10.0.10.97
+ A 10.0.10.98
+ A 10.0.10.99
+ A 10.0.10.100
+ A 10.0.10.101
+ A 10.0.10.102
+ A 10.0.10.103
+ A 10.0.10.104
+ A 10.0.10.105
+ A 10.0.10.106
+ A 10.0.10.107
+ A 10.0.10.108
+ A 10.0.10.109
+ A 10.0.10.110
+ A 10.0.10.111
+ A 10.0.10.112
+ A 10.0.10.113
+ A 10.0.10.114
+ A 10.0.10.115
+ A 10.0.10.116
+ A 10.0.10.117
+ A 10.0.10.118
+ A 10.0.10.119
+ A 10.0.10.120
+ A 10.0.10.121
+ A 10.0.10.122
+ A 10.0.10.123
+ A 10.0.10.124
+ A 10.0.10.125
+ A 10.0.10.126
+ A 10.0.10.127
+ A 10.0.10.128
+ A 10.0.10.129
+ A 10.0.10.130
+ A 10.0.10.131
+ A 10.0.10.132
+ A 10.0.10.133
+ A 10.0.10.134
+ A 10.0.10.135
+ A 10.0.10.136
+ A 10.0.10.137
+ A 10.0.10.138
+ A 10.0.10.139
+ A 10.0.10.140
+ A 10.0.10.141
+ A 10.0.10.142
+ A 10.0.10.143
+ A 10.0.10.144
+ A 10.0.10.145
+ A 10.0.10.146
+ A 10.0.10.147
+ A 10.0.10.148
+ A 10.0.10.149
+ A 10.0.10.150
+ A 10.0.10.151
+ A 10.0.10.152
+ A 10.0.10.153
+ A 10.0.10.154
+ A 10.0.10.155
+ A 10.0.10.156
+ A 10.0.10.157
+ A 10.0.10.158
+ A 10.0.10.159
+ A 10.0.10.160
+ A 10.0.10.161
+ A 10.0.10.162
+ A 10.0.10.163
+ A 10.0.10.164
+ A 10.0.10.165
+ A 10.0.10.166
+ A 10.0.10.167
+ A 10.0.10.168
+ A 10.0.10.169
+ A 10.0.10.170
+ A 10.0.10.171
+ A 10.0.10.172
+ A 10.0.10.173
+ A 10.0.10.174
+ A 10.0.10.175
+ A 10.0.10.176
+ A 10.0.10.177
+ A 10.0.10.178
+ A 10.0.10.179
+ A 10.0.10.180
+ A 10.0.10.181
+ A 10.0.10.182
+ A 10.0.10.183
+ A 10.0.10.184
+ A 10.0.10.185
+ A 10.0.10.186
+ A 10.0.10.187
+ A 10.0.10.188
+ A 10.0.10.189
+ A 10.0.10.190
+ A 10.0.10.191
+ A 10.0.10.192
+ A 10.0.10.193
+ A 10.0.10.194
+ A 10.0.10.195
+ A 10.0.10.196
+ A 10.0.10.197
+ A 10.0.10.198
+ A 10.0.10.199
+ A 10.0.10.200
+ A 10.0.10.201
+ A 10.0.10.202
+ A 10.0.10.203
+ A 10.0.10.204
+ A 10.0.10.205
+ A 10.0.10.206
+ A 10.0.10.207
+ A 10.0.10.208
+ A 10.0.10.209
+ A 10.0.10.210
+ A 10.0.10.211
+ A 10.0.10.212
+ A 10.0.10.213
+ A 10.0.10.214
+ A 10.0.10.215
+ A 10.0.10.216
+ A 10.0.10.217
+ A 10.0.10.218
+ A 10.0.10.219
+ A 10.0.10.220
+ A 10.0.10.221
+ A 10.0.10.222
+ A 10.0.10.223
+ A 10.0.10.224
+ A 10.0.10.225
+ A 10.0.10.226
+ A 10.0.10.227
+ A 10.0.10.228
+ A 10.0.10.229
+ A 10.0.10.230
+ A 10.0.10.231
+ A 10.0.10.232
+ A 10.0.10.233
+ A 10.0.10.234
+ A 10.0.10.235
+ A 10.0.10.236
+ A 10.0.10.237
+ A 10.0.10.238
+ A 10.0.10.239
+ A 10.0.10.240
+ A 10.0.10.241
+ A 10.0.10.242
+ A 10.0.10.243
+ A 10.0.10.244
+ A 10.0.10.245
+ A 10.0.10.246
+ A 10.0.10.247
+ A 10.0.10.248
+ A 10.0.10.249
+ A 10.0.10.250
+ A 10.0.10.251
+ A 10.0.10.252
+ A 10.0.10.253
+ A 10.0.10.254
+ A 10.0.10.255
+ A 10.0.11.0
+ A 10.0.11.1
+ A 10.0.11.2
+ A 10.0.11.3
+ A 10.0.11.4
+ A 10.0.11.5
+ A 10.0.11.6
+ A 10.0.11.7
+ A 10.0.11.8
+ A 10.0.11.9
+ A 10.0.11.10
+ A 10.0.11.11
+ A 10.0.11.12
+ A 10.0.11.13
+ A 10.0.11.14
+ A 10.0.11.15
+ A 10.0.11.16
+ A 10.0.11.17
+ A 10.0.11.18
+ A 10.0.11.19
+ A 10.0.11.20
+ A 10.0.11.21
+ A 10.0.11.22
+ A 10.0.11.23
+ A 10.0.11.24
+ A 10.0.11.25
+ A 10.0.11.26
+ A 10.0.11.27
+ A 10.0.11.28
+ A 10.0.11.29
+ A 10.0.11.30
+ A 10.0.11.31
+ A 10.0.11.32
+ A 10.0.11.33
+ A 10.0.11.34
+ A 10.0.11.35
+ A 10.0.11.36
+ A 10.0.11.37
+ A 10.0.11.38
+ A 10.0.11.39
+ A 10.0.11.40
+ A 10.0.11.41
+ A 10.0.11.42
+ A 10.0.11.43
+ A 10.0.11.44
+ A 10.0.11.45
+ A 10.0.11.46
+ A 10.0.11.47
+ A 10.0.11.48
+ A 10.0.11.49
+ A 10.0.11.50
+ A 10.0.11.51
+ A 10.0.11.52
+ A 10.0.11.53
+ A 10.0.11.54
+ A 10.0.11.55
+ A 10.0.11.56
+ A 10.0.11.57
+ A 10.0.11.58
+ A 10.0.11.59
+ A 10.0.11.60
+ A 10.0.11.61
+ A 10.0.11.62
+ A 10.0.11.63
+ A 10.0.11.64
+ A 10.0.11.65
+ A 10.0.11.66
+ A 10.0.11.67
+ A 10.0.11.68
+ A 10.0.11.69
+ A 10.0.11.70
+ A 10.0.11.71
+ A 10.0.11.72
+ A 10.0.11.73
+ A 10.0.11.74
+ A 10.0.11.75
+ A 10.0.11.76
+ A 10.0.11.77
+ A 10.0.11.78
+ A 10.0.11.79
+ A 10.0.11.80
+ A 10.0.11.81
+ A 10.0.11.82
+ A 10.0.11.83
+ A 10.0.11.84
+ A 10.0.11.85
+ A 10.0.11.86
+ A 10.0.11.87
+ A 10.0.11.88
+ A 10.0.11.89
+ A 10.0.11.90
+ A 10.0.11.91
+ A 10.0.11.92
+ A 10.0.11.93
+ A 10.0.11.94
+ A 10.0.11.95
+ A 10.0.11.96
+ A 10.0.11.97
+ A 10.0.11.98
+ A 10.0.11.99
+ A 10.0.11.100
+ A 10.0.11.101
+ A 10.0.11.102
+ A 10.0.11.103
+ A 10.0.11.104
+ A 10.0.11.105
+ A 10.0.11.106
+ A 10.0.11.107
+ A 10.0.11.108
+ A 10.0.11.109
+ A 10.0.11.110
+ A 10.0.11.111
+ A 10.0.11.112
+ A 10.0.11.113
+ A 10.0.11.114
+ A 10.0.11.115
+ A 10.0.11.116
+ A 10.0.11.117
+ A 10.0.11.118
+ A 10.0.11.119
+ A 10.0.11.120
+ A 10.0.11.121
+ A 10.0.11.122
+ A 10.0.11.123
+ A 10.0.11.124
+ A 10.0.11.125
+ A 10.0.11.126
+ A 10.0.11.127
+ A 10.0.11.128
+ A 10.0.11.129
+ A 10.0.11.130
+ A 10.0.11.131
+ A 10.0.11.132
+ A 10.0.11.133
+ A 10.0.11.134
+ A 10.0.11.135
+ A 10.0.11.136
+ A 10.0.11.137
+ A 10.0.11.138
+ A 10.0.11.139
+ A 10.0.11.140
+ A 10.0.11.141
+ A 10.0.11.142
+ A 10.0.11.143
+ A 10.0.11.144
+ A 10.0.11.145
+ A 10.0.11.146
+ A 10.0.11.147
+ A 10.0.11.148
+ A 10.0.11.149
+ A 10.0.11.150
+ A 10.0.11.151
+ A 10.0.11.152
+ A 10.0.11.153
+ A 10.0.11.154
+ A 10.0.11.155
+ A 10.0.11.156
+ A 10.0.11.157
+ A 10.0.11.158
+ A 10.0.11.159
+ A 10.0.11.160
+ A 10.0.11.161
+ A 10.0.11.162
+ A 10.0.11.163
+ A 10.0.11.164
+ A 10.0.11.165
+ A 10.0.11.166
+ A 10.0.11.167
+ A 10.0.11.168
+ A 10.0.11.169
+ A 10.0.11.170
+ A 10.0.11.171
+ A 10.0.11.172
+ A 10.0.11.173
+ A 10.0.11.174
+ A 10.0.11.175
+ A 10.0.11.176
+ A 10.0.11.177
+ A 10.0.11.178
+ A 10.0.11.179
+ A 10.0.11.180
+ A 10.0.11.181
+ A 10.0.11.182
+ A 10.0.11.183
+ A 10.0.11.184
+ A 10.0.11.185
+ A 10.0.11.186
+ A 10.0.11.187
+ A 10.0.11.188
+ A 10.0.11.189
+ A 10.0.11.190
+ A 10.0.11.191
+ A 10.0.11.192
+ A 10.0.11.193
+ A 10.0.11.194
+ A 10.0.11.195
+ A 10.0.11.196
+ A 10.0.11.197
+ A 10.0.11.198
+ A 10.0.11.199
+ A 10.0.11.200
+ A 10.0.11.201
+ A 10.0.11.202
+ A 10.0.11.203
+ A 10.0.11.204
+ A 10.0.11.205
+ A 10.0.11.206
+ A 10.0.11.207
+ A 10.0.11.208
+ A 10.0.11.209
+ A 10.0.11.210
+ A 10.0.11.211
+ A 10.0.11.212
+ A 10.0.11.213
+ A 10.0.11.214
+ A 10.0.11.215
+ A 10.0.11.216
+ A 10.0.11.217
+ A 10.0.11.218
+ A 10.0.11.219
+ A 10.0.11.220
+ A 10.0.11.221
+ A 10.0.11.222
+ A 10.0.11.223
+ A 10.0.11.224
+ A 10.0.11.225
+ A 10.0.11.226
+ A 10.0.11.227
+ A 10.0.11.228
+ A 10.0.11.229
+ A 10.0.11.230
+ A 10.0.11.231
+ A 10.0.11.232
+ A 10.0.11.233
+ A 10.0.11.234
+ A 10.0.11.235
+ A 10.0.11.236
+ A 10.0.11.237
+ A 10.0.11.238
+ A 10.0.11.239
+ A 10.0.11.240
+ A 10.0.11.241
+ A 10.0.11.242
+ A 10.0.11.243
+ A 10.0.11.244
+ A 10.0.11.245
+ A 10.0.11.246
+ A 10.0.11.247
+ A 10.0.11.248
+ A 10.0.11.249
+ A 10.0.11.250
+ A 10.0.11.251
+ A 10.0.11.252
+ A 10.0.11.253
+ A 10.0.11.254
+ A 10.0.11.255
+ A 10.0.12.0
+ A 10.0.12.1
+ A 10.0.12.2
+ A 10.0.12.3
+ A 10.0.12.4
+ A 10.0.12.5
+ A 10.0.12.6
+ A 10.0.12.7
+ A 10.0.12.8
+ A 10.0.12.9
+ A 10.0.12.10
+ A 10.0.12.11
+ A 10.0.12.12
+ A 10.0.12.13
+ A 10.0.12.14
+ A 10.0.12.15
+ A 10.0.12.16
+ A 10.0.12.17
+ A 10.0.12.18
+ A 10.0.12.19
+ A 10.0.12.20
+ A 10.0.12.21
+ A 10.0.12.22
+ A 10.0.12.23
+ A 10.0.12.24
+ A 10.0.12.25
+ A 10.0.12.26
+ A 10.0.12.27
+ A 10.0.12.28
+ A 10.0.12.29
+ A 10.0.12.30
+ A 10.0.12.31
+ A 10.0.12.32
+ A 10.0.12.33
+ A 10.0.12.34
+ A 10.0.12.35
+ A 10.0.12.36
+ A 10.0.12.37
+ A 10.0.12.38
+ A 10.0.12.39
+ A 10.0.12.40
+ A 10.0.12.41
+ A 10.0.12.42
+ A 10.0.12.43
+ A 10.0.12.44
+ A 10.0.12.45
+ A 10.0.12.46
+ A 10.0.12.47
+ A 10.0.12.48
+ A 10.0.12.49
+ A 10.0.12.50
+ A 10.0.12.51
+ A 10.0.12.52
+ A 10.0.12.53
+ A 10.0.12.54
+ A 10.0.12.55
+ A 10.0.12.56
+ A 10.0.12.57
+ A 10.0.12.58
+ A 10.0.12.59
+ A 10.0.12.60
+ A 10.0.12.61
+ A 10.0.12.62
+ A 10.0.12.63
+ A 10.0.12.64
+ A 10.0.12.65
+ A 10.0.12.66
+ A 10.0.12.67
+ A 10.0.12.68
+ A 10.0.12.69
+ A 10.0.12.70
+ A 10.0.12.71
+ A 10.0.12.72
+ A 10.0.12.73
+ A 10.0.12.74
+ A 10.0.12.75
+ A 10.0.12.76
+ A 10.0.12.77
+ A 10.0.12.78
+ A 10.0.12.79
+ A 10.0.12.80
+ A 10.0.12.81
+ A 10.0.12.82
+ A 10.0.12.83
+ A 10.0.12.84
+ A 10.0.12.85
+ A 10.0.12.86
+ A 10.0.12.87
+ A 10.0.12.88
+ A 10.0.12.89
+ A 10.0.12.90
+ A 10.0.12.91
+ A 10.0.12.92
+ A 10.0.12.93
+ A 10.0.12.94
+ A 10.0.12.95
+ A 10.0.12.96
+ A 10.0.12.97
+ A 10.0.12.98
+ A 10.0.12.99
+ A 10.0.12.100
+ A 10.0.12.101
+ A 10.0.12.102
+ A 10.0.12.103
+ A 10.0.12.104
+ A 10.0.12.105
+ A 10.0.12.106
+ A 10.0.12.107
+ A 10.0.12.108
+ A 10.0.12.109
+ A 10.0.12.110
+ A 10.0.12.111
+ A 10.0.12.112
+ A 10.0.12.113
+ A 10.0.12.114
+ A 10.0.12.115
+ A 10.0.12.116
+ A 10.0.12.117
+ A 10.0.12.118
+ A 10.0.12.119
+ A 10.0.12.120
+ A 10.0.12.121
+ A 10.0.12.122
+ A 10.0.12.123
+ A 10.0.12.124
+ A 10.0.12.125
+ A 10.0.12.126
+ A 10.0.12.127
+ A 10.0.12.128
+ A 10.0.12.129
+ A 10.0.12.130
+ A 10.0.12.131
+ A 10.0.12.132
+ A 10.0.12.133
+ A 10.0.12.134
+ A 10.0.12.135
+ A 10.0.12.136
+ A 10.0.12.137
+ A 10.0.12.138
+ A 10.0.12.139
+ A 10.0.12.140
+ A 10.0.12.141
+ A 10.0.12.142
+ A 10.0.12.143
+ A 10.0.12.144
+ A 10.0.12.145
+ A 10.0.12.146
+ A 10.0.12.147
+ A 10.0.12.148
+ A 10.0.12.149
+ A 10.0.12.150
+ A 10.0.12.151
+ A 10.0.12.152
+ A 10.0.12.153
+ A 10.0.12.154
+ A 10.0.12.155
+ A 10.0.12.156
+ A 10.0.12.157
+ A 10.0.12.158
+ A 10.0.12.159
+ A 10.0.12.160
+ A 10.0.12.161
+ A 10.0.12.162
+ A 10.0.12.163
+ A 10.0.12.164
+ A 10.0.12.165
+ A 10.0.12.166
+ A 10.0.12.167
+ A 10.0.12.168
+ A 10.0.12.169
+ A 10.0.12.170
+ A 10.0.12.171
+ A 10.0.12.172
+ A 10.0.12.173
+ A 10.0.12.174
+ A 10.0.12.175
+ A 10.0.12.176
+ A 10.0.12.177
+ A 10.0.12.178
+ A 10.0.12.179
+ A 10.0.12.180
+ A 10.0.12.181
+ A 10.0.12.182
+ A 10.0.12.183
+ A 10.0.12.184
+ A 10.0.12.185
+ A 10.0.12.186
+ A 10.0.12.187
+ A 10.0.12.188
+ A 10.0.12.189
+ A 10.0.12.190
+ A 10.0.12.191
+ A 10.0.12.192
+ A 10.0.12.193
+ A 10.0.12.194
+ A 10.0.12.195
+ A 10.0.12.196
+ A 10.0.12.197
+ A 10.0.12.198
+ A 10.0.12.199
+ A 10.0.12.200
+ A 10.0.12.201
+ A 10.0.12.202
+ A 10.0.12.203
+ A 10.0.12.204
+ A 10.0.12.205
+ A 10.0.12.206
+ A 10.0.12.207
+ A 10.0.12.208
+ A 10.0.12.209
+ A 10.0.12.210
+ A 10.0.12.211
+ A 10.0.12.212
+ A 10.0.12.213
+ A 10.0.12.214
+ A 10.0.12.215
+ A 10.0.12.216
+ A 10.0.12.217
+ A 10.0.12.218
+ A 10.0.12.219
+ A 10.0.12.220
+ A 10.0.12.221
+ A 10.0.12.222
+ A 10.0.12.223
+ A 10.0.12.224
+ A 10.0.12.225
+ A 10.0.12.226
+ A 10.0.12.227
+ A 10.0.12.228
+ A 10.0.12.229
+ A 10.0.12.230
+ A 10.0.12.231
+ A 10.0.12.232
+ A 10.0.12.233
+ A 10.0.12.234
+ A 10.0.12.235
+ A 10.0.12.236
+ A 10.0.12.237
+ A 10.0.12.238
+ A 10.0.12.239
+ A 10.0.12.240
+ A 10.0.12.241
+ A 10.0.12.242
+ A 10.0.12.243
+ A 10.0.12.244
+ A 10.0.12.245
+ A 10.0.12.246
+ A 10.0.12.247
+ A 10.0.12.248
+ A 10.0.12.249
+ A 10.0.12.250
+ A 10.0.12.251
+ A 10.0.12.252
+ A 10.0.12.253
+ A 10.0.12.254
+ A 10.0.12.255
+ A 10.0.13.0
+ A 10.0.13.1
+ A 10.0.13.2
+ A 10.0.13.3
+ A 10.0.13.4
+ A 10.0.13.5
+ A 10.0.13.6
+ A 10.0.13.7
+ A 10.0.13.8
+ A 10.0.13.9
+ A 10.0.13.10
+ A 10.0.13.11
+ A 10.0.13.12
+ A 10.0.13.13
+ A 10.0.13.14
+ A 10.0.13.15
+ A 10.0.13.16
+ A 10.0.13.17
+ A 10.0.13.18
+ A 10.0.13.19
+ A 10.0.13.20
+ A 10.0.13.21
+ A 10.0.13.22
+ A 10.0.13.23
+ A 10.0.13.24
+ A 10.0.13.25
+ A 10.0.13.26
+ A 10.0.13.27
+ A 10.0.13.28
+ A 10.0.13.29
+ A 10.0.13.30
+ A 10.0.13.31
+ A 10.0.13.32
+ A 10.0.13.33
+ A 10.0.13.34
+ A 10.0.13.35
+ A 10.0.13.36
+ A 10.0.13.37
+ A 10.0.13.38
+ A 10.0.13.39
+ A 10.0.13.40
+ A 10.0.13.41
+ A 10.0.13.42
+ A 10.0.13.43
+ A 10.0.13.44
+ A 10.0.13.45
+ A 10.0.13.46
+ A 10.0.13.47
+ A 10.0.13.48
+ A 10.0.13.49
+ A 10.0.13.50
+ A 10.0.13.51
+ A 10.0.13.52
+ A 10.0.13.53
+ A 10.0.13.54
+ A 10.0.13.55
+ A 10.0.13.56
+ A 10.0.13.57
+ A 10.0.13.58
+ A 10.0.13.59
+ A 10.0.13.60
+ A 10.0.13.61
+ A 10.0.13.62
+ A 10.0.13.63
+ A 10.0.13.64
+ A 10.0.13.65
+ A 10.0.13.66
+ A 10.0.13.67
+ A 10.0.13.68
+ A 10.0.13.69
+ A 10.0.13.70
+ A 10.0.13.71
+ A 10.0.13.72
+ A 10.0.13.73
+ A 10.0.13.74
+ A 10.0.13.75
+ A 10.0.13.76
+ A 10.0.13.77
+ A 10.0.13.78
+ A 10.0.13.79
+ A 10.0.13.80
+ A 10.0.13.81
+ A 10.0.13.82
+ A 10.0.13.83
+ A 10.0.13.84
+ A 10.0.13.85
+ A 10.0.13.86
+ A 10.0.13.87
+ A 10.0.13.88
+ A 10.0.13.89
+ A 10.0.13.90
+ A 10.0.13.91
+ A 10.0.13.92
+ A 10.0.13.93
+ A 10.0.13.94
+ A 10.0.13.95
+ A 10.0.13.96
+ A 10.0.13.97
+ A 10.0.13.98
+ A 10.0.13.99
+ A 10.0.13.100
+ A 10.0.13.101
+ A 10.0.13.102
+ A 10.0.13.103
+ A 10.0.13.104
+ A 10.0.13.105
+ A 10.0.13.106
+ A 10.0.13.107
+ A 10.0.13.108
+ A 10.0.13.109
+ A 10.0.13.110
+ A 10.0.13.111
+ A 10.0.13.112
+ A 10.0.13.113
+ A 10.0.13.114
+ A 10.0.13.115
+ A 10.0.13.116
+ A 10.0.13.117
+ A 10.0.13.118
+ A 10.0.13.119
+ A 10.0.13.120
+ A 10.0.13.121
+ A 10.0.13.122
+ A 10.0.13.123
+ A 10.0.13.124
+ A 10.0.13.125
+ A 10.0.13.126
+ A 10.0.13.127
+ A 10.0.13.128
+ A 10.0.13.129
+ A 10.0.13.130
+ A 10.0.13.131
+ A 10.0.13.132
+ A 10.0.13.133
+ A 10.0.13.134
+ A 10.0.13.135
+ A 10.0.13.136
+ A 10.0.13.137
+ A 10.0.13.138
+ A 10.0.13.139
+ A 10.0.13.140
+ A 10.0.13.141
+ A 10.0.13.142
+ A 10.0.13.143
+ A 10.0.13.144
+ A 10.0.13.145
+ A 10.0.13.146
+ A 10.0.13.147
+ A 10.0.13.148
+ A 10.0.13.149
+ A 10.0.13.150
+ A 10.0.13.151
+ A 10.0.13.152
+ A 10.0.13.153
+ A 10.0.13.154
+ A 10.0.13.155
+ A 10.0.13.156
+ A 10.0.13.157
+ A 10.0.13.158
+ A 10.0.13.159
+ A 10.0.13.160
+ A 10.0.13.161
+ A 10.0.13.162
+ A 10.0.13.163
+ A 10.0.13.164
+ A 10.0.13.165
+ A 10.0.13.166
+ A 10.0.13.167
+ A 10.0.13.168
+ A 10.0.13.169
+ A 10.0.13.170
+ A 10.0.13.171
+ A 10.0.13.172
+ A 10.0.13.173
+ A 10.0.13.174
+ A 10.0.13.175
+ A 10.0.13.176
+ A 10.0.13.177
+ A 10.0.13.178
+ A 10.0.13.179
+ A 10.0.13.180
+ A 10.0.13.181
+ A 10.0.13.182
+ A 10.0.13.183
+ A 10.0.13.184
+ A 10.0.13.185
+ A 10.0.13.186
+ A 10.0.13.187
+ A 10.0.13.188
+ A 10.0.13.189
+ A 10.0.13.190
+ A 10.0.13.191
+ A 10.0.13.192
+ A 10.0.13.193
+ A 10.0.13.194
+ A 10.0.13.195
+ A 10.0.13.196
+ A 10.0.13.197
+ A 10.0.13.198
+ A 10.0.13.199
+ A 10.0.13.200
+ A 10.0.13.201
+ A 10.0.13.202
+ A 10.0.13.203
+ A 10.0.13.204
+ A 10.0.13.205
+ A 10.0.13.206
+ A 10.0.13.207
+ A 10.0.13.208
+ A 10.0.13.209
+ A 10.0.13.210
+ A 10.0.13.211
+ A 10.0.13.212
+ A 10.0.13.213
+ A 10.0.13.214
+ A 10.0.13.215
+ A 10.0.13.216
+ A 10.0.13.217
+ A 10.0.13.218
+ A 10.0.13.219
+ A 10.0.13.220
+ A 10.0.13.221
+ A 10.0.13.222
+ A 10.0.13.223
+ A 10.0.13.224
+ A 10.0.13.225
+ A 10.0.13.226
+ A 10.0.13.227
+ A 10.0.13.228
+ A 10.0.13.229
+ A 10.0.13.230
+ A 10.0.13.231
+ A 10.0.13.232
+ A 10.0.13.233
+ A 10.0.13.234
+ A 10.0.13.235
+ A 10.0.13.236
+ A 10.0.13.237
+ A 10.0.13.238
+ A 10.0.13.239
+ A 10.0.13.240
+ A 10.0.13.241
+ A 10.0.13.242
+ A 10.0.13.243
+ A 10.0.13.244
+ A 10.0.13.245
+ A 10.0.13.246
+ A 10.0.13.247
+ A 10.0.13.248
+ A 10.0.13.249
+ A 10.0.13.250
+ A 10.0.13.251
+ A 10.0.13.252
+ A 10.0.13.253
+ A 10.0.13.254
+ A 10.0.13.255
+ A 10.0.14.0
+ A 10.0.14.1
+ A 10.0.14.2
+ A 10.0.14.3
+ A 10.0.14.4
+ A 10.0.14.5
+ A 10.0.14.6
+ A 10.0.14.7
+ A 10.0.14.8
+ A 10.0.14.9
+ A 10.0.14.10
+ A 10.0.14.11
+ A 10.0.14.12
+ A 10.0.14.13
+ A 10.0.14.14
+ A 10.0.14.15
+ A 10.0.14.16
+ A 10.0.14.17
+ A 10.0.14.18
+ A 10.0.14.19
+ A 10.0.14.20
+ A 10.0.14.21
+ A 10.0.14.22
+ A 10.0.14.23
+ A 10.0.14.24
+ A 10.0.14.25
+ A 10.0.14.26
+ A 10.0.14.27
+ A 10.0.14.28
+ A 10.0.14.29
+ A 10.0.14.30
+ A 10.0.14.31
+ A 10.0.14.32
+ A 10.0.14.33
+ A 10.0.14.34
+ A 10.0.14.35
+ A 10.0.14.36
+ A 10.0.14.37
+ A 10.0.14.38
+ A 10.0.14.39
+ A 10.0.14.40
+ A 10.0.14.41
+ A 10.0.14.42
+ A 10.0.14.43
+ A 10.0.14.44
+ A 10.0.14.45
+ A 10.0.14.46
+ A 10.0.14.47
+ A 10.0.14.48
+ A 10.0.14.49
+ A 10.0.14.50
+ A 10.0.14.51
+ A 10.0.14.52
+ A 10.0.14.53
+ A 10.0.14.54
+ A 10.0.14.55
+ A 10.0.14.56
+ A 10.0.14.57
+ A 10.0.14.58
+ A 10.0.14.59
+ A 10.0.14.60
+ A 10.0.14.61
+ A 10.0.14.62
+ A 10.0.14.63
+ A 10.0.14.64
+ A 10.0.14.65
+ A 10.0.14.66
+ A 10.0.14.67
+ A 10.0.14.68
+ A 10.0.14.69
+ A 10.0.14.70
+ A 10.0.14.71
+ A 10.0.14.72
+ A 10.0.14.73
+ A 10.0.14.74
+ A 10.0.14.75
+ A 10.0.14.76
+ A 10.0.14.77
+ A 10.0.14.78
+ A 10.0.14.79
+ A 10.0.14.80
+ A 10.0.14.81
+ A 10.0.14.82
+ A 10.0.14.83
+ A 10.0.14.84
+ A 10.0.14.85
+ A 10.0.14.86
+ A 10.0.14.87
+ A 10.0.14.88
+ A 10.0.14.89
+ A 10.0.14.90
+ A 10.0.14.91
+ A 10.0.14.92
+ A 10.0.14.93
+ A 10.0.14.94
+ A 10.0.14.95
+ A 10.0.14.96
+ A 10.0.14.97
+ A 10.0.14.98
+ A 10.0.14.99
+ A 10.0.14.100
+ A 10.0.14.101
+ A 10.0.14.102
+ A 10.0.14.103
+ A 10.0.14.104
+ A 10.0.14.105
+ A 10.0.14.106
+ A 10.0.14.107
+ A 10.0.14.108
+ A 10.0.14.109
+ A 10.0.14.110
+ A 10.0.14.111
+ A 10.0.14.112
+ A 10.0.14.113
+ A 10.0.14.114
+ A 10.0.14.115
+ A 10.0.14.116
+ A 10.0.14.117
+ A 10.0.14.118
+ A 10.0.14.119
+ A 10.0.14.120
+ A 10.0.14.121
+ A 10.0.14.122
+ A 10.0.14.123
+ A 10.0.14.124
+ A 10.0.14.125
+ A 10.0.14.126
+ A 10.0.14.127
+ A 10.0.14.128
+ A 10.0.14.129
+ A 10.0.14.130
+ A 10.0.14.131
+ A 10.0.14.132
+ A 10.0.14.133
+ A 10.0.14.134
+ A 10.0.14.135
+ A 10.0.14.136
+ A 10.0.14.137
+ A 10.0.14.138
+ A 10.0.14.139
+ A 10.0.14.140
+ A 10.0.14.141
+ A 10.0.14.142
+ A 10.0.14.143
+ A 10.0.14.144
+ A 10.0.14.145
+ A 10.0.14.146
+ A 10.0.14.147
+ A 10.0.14.148
+ A 10.0.14.149
+ A 10.0.14.150
+ A 10.0.14.151
+ A 10.0.14.152
+ A 10.0.14.153
+ A 10.0.14.154
+ A 10.0.14.155
+ A 10.0.14.156
+ A 10.0.14.157
+ A 10.0.14.158
+ A 10.0.14.159
+ A 10.0.14.160
+ A 10.0.14.161
+ A 10.0.14.162
+ A 10.0.14.163
+ A 10.0.14.164
+ A 10.0.14.165
+ A 10.0.14.166
+ A 10.0.14.167
+ A 10.0.14.168
+ A 10.0.14.169
+ A 10.0.14.170
+ A 10.0.14.171
+ A 10.0.14.172
+ A 10.0.14.173
+ A 10.0.14.174
+ A 10.0.14.175
+ A 10.0.14.176
+ A 10.0.14.177
+ A 10.0.14.178
+ A 10.0.14.179
+ A 10.0.14.180
+ A 10.0.14.181
+ A 10.0.14.182
+ A 10.0.14.183
+ A 10.0.14.184
+ A 10.0.14.185
+ A 10.0.14.186
+ A 10.0.14.187
+ A 10.0.14.188
+ A 10.0.14.189
+ A 10.0.14.190
+ A 10.0.14.191
+ A 10.0.14.192
+ A 10.0.14.193
+ A 10.0.14.194
+ A 10.0.14.195
+ A 10.0.14.196
+ A 10.0.14.197
+ A 10.0.14.198
+ A 10.0.14.199
+ A 10.0.14.200
+ A 10.0.14.201
+ A 10.0.14.202
+ A 10.0.14.203
+ A 10.0.14.204
+ A 10.0.14.205
+ A 10.0.14.206
+ A 10.0.14.207
+ A 10.0.14.208
+ A 10.0.14.209
+ A 10.0.14.210
+ A 10.0.14.211
+ A 10.0.14.212
+ A 10.0.14.213
+ A 10.0.14.214
+ A 10.0.14.215
+ A 10.0.14.216
+ A 10.0.14.217
+ A 10.0.14.218
+ A 10.0.14.219
+ A 10.0.14.220
+ A 10.0.14.221
+ A 10.0.14.222
+ A 10.0.14.223
+ A 10.0.14.224
+ A 10.0.14.225
+ A 10.0.14.226
+ A 10.0.14.227
+ A 10.0.14.228
+ A 10.0.14.229
+ A 10.0.14.230
+ A 10.0.14.231
+ A 10.0.14.232
+ A 10.0.14.233
+ A 10.0.14.234
+ A 10.0.14.235
+ A 10.0.14.236
+ A 10.0.14.237
+ A 10.0.14.238
+ A 10.0.14.239
+ A 10.0.14.240
+ A 10.0.14.241
+ A 10.0.14.242
+ A 10.0.14.243
+ A 10.0.14.244
+ A 10.0.14.245
+ A 10.0.14.246
+ A 10.0.14.247
+ A 10.0.14.248
+ A 10.0.14.249
+ A 10.0.14.250
+ A 10.0.14.251
+ A 10.0.14.252
+ A 10.0.14.253
+ A 10.0.14.254
+ A 10.0.14.255
+ A 10.0.15.0
+ A 10.0.15.1
+ A 10.0.15.2
+ A 10.0.15.3
+ A 10.0.15.4
+ A 10.0.15.5
+ A 10.0.15.6
+ A 10.0.15.7
+ A 10.0.15.8
+ A 10.0.15.9
+ A 10.0.15.10
+ A 10.0.15.11
+ A 10.0.15.12
+ A 10.0.15.13
+ A 10.0.15.14
+ A 10.0.15.15
+ A 10.0.15.16
+ A 10.0.15.17
+ A 10.0.15.18
+ A 10.0.15.19
+ A 10.0.15.20
+ A 10.0.15.21
+ A 10.0.15.22
+ A 10.0.15.23
+ A 10.0.15.24
+ A 10.0.15.25
+ A 10.0.15.26
+ A 10.0.15.27
+ A 10.0.15.28
+ A 10.0.15.29
+ A 10.0.15.30
+ A 10.0.15.31
+ A 10.0.15.32
+ A 10.0.15.33
+ A 10.0.15.34
+ A 10.0.15.35
+ A 10.0.15.36
+ A 10.0.15.37
+ A 10.0.15.38
+ A 10.0.15.39
+ A 10.0.15.40
+ A 10.0.15.41
+ A 10.0.15.42
+ A 10.0.15.43
+ A 10.0.15.44
+ A 10.0.15.45
+ A 10.0.15.46
+ A 10.0.15.47
+ A 10.0.15.48
+ A 10.0.15.49
+ A 10.0.15.50
+ A 10.0.15.51
+ A 10.0.15.52
+ A 10.0.15.53
+ A 10.0.15.54
+ A 10.0.15.55
+ A 10.0.15.56
+ A 10.0.15.57
+ A 10.0.15.58
+ A 10.0.15.59
+ A 10.0.15.60
+ A 10.0.15.61
+ A 10.0.15.62
+ A 10.0.15.63
+ A 10.0.15.64
+ A 10.0.15.65
+ A 10.0.15.66
+ A 10.0.15.67
+ A 10.0.15.68
+ A 10.0.15.69
+ A 10.0.15.70
+ A 10.0.15.71
+ A 10.0.15.72
+ A 10.0.15.73
+ A 10.0.15.74
+ A 10.0.15.75
+ A 10.0.15.76
+ A 10.0.15.77
+ A 10.0.15.78
+ A 10.0.15.79
+ A 10.0.15.80
+ A 10.0.15.81
+ A 10.0.15.82
+ A 10.0.15.83
+ A 10.0.15.84
+ A 10.0.15.85
+ A 10.0.15.86
+ A 10.0.15.87
+ A 10.0.15.88
+ A 10.0.15.89
+ A 10.0.15.90
+ A 10.0.15.91
+ A 10.0.15.92
+ A 10.0.15.93
+ A 10.0.15.94
+ A 10.0.15.95
+ A 10.0.15.96
+ A 10.0.15.97
+ A 10.0.15.98
+ A 10.0.15.99
+ A 10.0.15.100
+ A 10.0.15.101
+ A 10.0.15.102
+ A 10.0.15.103
+ A 10.0.15.104
+ A 10.0.15.105
+ A 10.0.15.106
+ A 10.0.15.107
+ A 10.0.15.108
+ A 10.0.15.109
+ A 10.0.15.110
+ A 10.0.15.111
+ A 10.0.15.112
+ A 10.0.15.113
+ A 10.0.15.114
+ A 10.0.15.115
+ A 10.0.15.116
+ A 10.0.15.117
+ A 10.0.15.118
+ A 10.0.15.119
+ A 10.0.15.120
+ A 10.0.15.121
+ A 10.0.15.122
+ A 10.0.15.123
+ A 10.0.15.124
+ A 10.0.15.125
+ A 10.0.15.126
+ A 10.0.15.127
+ A 10.0.15.128
+ A 10.0.15.129
+ A 10.0.15.130
+ A 10.0.15.131
+ A 10.0.15.132
+ A 10.0.15.133
+ A 10.0.15.134
+ A 10.0.15.135
+ A 10.0.15.136
+ A 10.0.15.137
+ A 10.0.15.138
+ A 10.0.15.139
+ A 10.0.15.140
+ A 10.0.15.141
+ A 10.0.15.142
+ A 10.0.15.143
+ A 10.0.15.144
+ A 10.0.15.145
+ A 10.0.15.146
+ A 10.0.15.147
+ A 10.0.15.148
+ A 10.0.15.149
+ A 10.0.15.150
+ A 10.0.15.151
+ A 10.0.15.152
+ A 10.0.15.153
+ A 10.0.15.154
+ A 10.0.15.155
+ A 10.0.15.156
+ A 10.0.15.157
+ A 10.0.15.158
+ A 10.0.15.159
+ A 10.1.0.0
+ A 10.1.0.1
+ A 10.1.0.2
+ A 10.1.0.3
+ A 10.1.0.4
+ A 10.1.0.5
+ A 10.1.0.6
+ A 10.1.0.7
+ A 10.1.0.8
+ A 10.1.0.9
+ A 10.1.0.10
+ A 10.1.0.11
+ A 10.1.0.12
+ A 10.1.0.13
+ A 10.1.0.14
+ A 10.1.0.15
+ A 10.1.0.16
+ A 10.1.0.17
+ A 10.1.0.18
+ A 10.1.0.19
+ A 10.1.0.20
+ A 10.1.0.21
+ A 10.1.0.22
+ A 10.1.0.23
+ A 10.1.0.24
+ A 10.1.0.25
+ A 10.1.0.26
+ A 10.1.0.27
+ A 10.1.0.28
+ A 10.1.0.29
+ A 10.1.0.30
+ A 10.1.0.31
+ A 10.1.0.32
+ A 10.1.0.33
+ A 10.1.0.34
+ A 10.1.0.35
+ A 10.1.0.36
+ A 10.1.0.37
+ A 10.1.0.38
+ A 10.1.0.39
+ A 10.1.0.40
+ A 10.1.0.41
+ A 10.1.0.42
+ A 10.1.0.43
+ A 10.1.0.44
+ A 10.1.0.45
+ A 10.1.0.46
+ A 10.1.0.47
+ A 10.1.0.48
+ A 10.1.0.49
+ A 10.1.0.50
+ A 10.1.0.51
+ A 10.1.0.52
+ A 10.1.0.53
+ A 10.1.0.54
+ A 10.1.0.55
+ A 10.1.0.56
+ A 10.1.0.57
+ A 10.1.0.58
+ A 10.1.0.59
+ A 10.1.0.60
+ A 10.1.0.61
+ A 10.1.0.62
+ A 10.1.0.63
+ A 10.1.0.64
+ A 10.1.0.65
+ A 10.1.0.66
+ A 10.1.0.67
+ A 10.1.0.68
+ A 10.1.0.69
+ A 10.1.0.70
+ A 10.1.0.71
+ A 10.1.0.72
+ A 10.1.0.73
+ A 10.1.0.74
+ A 10.1.0.75
+ A 10.1.0.76
+ A 10.1.0.77
+ A 10.1.0.78
+ A 10.1.0.79
+ A 10.1.0.80
+ A 10.1.0.81
+ A 10.1.0.82
+ A 10.1.0.83
+ A 10.1.0.84
+ A 10.1.0.85
+ A 10.1.0.86
+ A 10.1.0.87
+ A 10.1.0.88
+ A 10.1.0.89
+ A 10.1.0.90
diff --git a/bin/tests/system/limits/ns1/named.conf.in b/bin/tests/system/limits/ns1/named.conf.in
new file mode 100644
index 0000000..780f9e2
--- /dev/null
+++ b/bin/tests/system/limits/ns1/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ minimal-responses no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/limits/ns1/root.db b/bin/tests/system/limits/ns1/root.db
new file mode 100644
index 0000000..b93cf32
--- /dev/null
+++ b/bin/tests/system/limits/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns1.example.
+ns1.example. A 10.53.0.1
diff --git a/bin/tests/system/limits/setup.sh b/bin/tests/system/limits/setup.sh
new file mode 100644
index 0000000..82240a7
--- /dev/null
+++ b/bin/tests/system/limits/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/limits/tests.sh b/bin/tests/system/limits/tests.sh
new file mode 100644
index 0000000..f2cf0fb
--- /dev/null
+++ b/bin/tests/system/limits/tests.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+
+status=0
+
+echo_i "1000 A records"
+$DIG $DIGOPTS +tcp +norec 1000.example. @10.53.0.1 a > dig.out.1000 || status=1
+# $DIG $DIGOPTS 1000.example. @10.53.0.1 a > knowngood.dig.out.1000
+digcomp knowngood.dig.out.1000 dig.out.1000 || status=1
+
+echo_i "2000 A records"
+$DIG $DIGOPTS +tcp +norec 2000.example. @10.53.0.1 a > dig.out.2000 || status=1
+# $DIG $DIGOPTS 2000.example. @10.53.0.1 a > knowngood.dig.out.2000
+digcomp knowngood.dig.out.2000 dig.out.2000 || status=1
+
+echo_i "3000 A records"
+$DIG $DIGOPTS +tcp +norec 3000.example. @10.53.0.1 a > dig.out.3000 || status=1
+# $DIG $DIGOPTS 3000.example. @10.53.0.1 a > knowngood.dig.out.3000
+digcomp knowngood.dig.out.3000 dig.out.3000 || status=1
+
+echo_i "4000 A records"
+$DIG $DIGOPTS +tcp +norec 4000.example. @10.53.0.1 a > dig.out.4000 || status=1
+# $DIG $DIGOPTS 4000.example. @10.53.0.1 a > knowngood.dig.out.4000
+digcomp knowngood.dig.out.4000 dig.out.4000 || status=1
+
+echo_i "exactly maximum rrset"
+$DIG $DIGOPTS +tcp +norec +noedns a-maximum-rrset.example. @10.53.0.1 a > dig.out.a-maximum-rrset \
+ || status=1
+# $DIG $DIGOPTS a-maximum-rrset.example. @10.53.0.1 a > knowngood.dig.out.a-maximum-rrset
+digcomp knowngood.dig.out.a-maximum-rrset dig.out.a-maximum-rrset || status=1
+
+echo_i "exceed maximum rrset (5000 A records)"
+$DIG $DIGOPTS +tcp +norec +noadd 5000.example. @10.53.0.1 a > dig.out.exceed || status=1
+# Look for truncation bit (tc).
+grep 'flags: .*tc.*;' dig.out.exceed > /dev/null || {
+ echo_i "TC bit was not set"
+ status=1
+}
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/limits/tests_sh_limits.py b/bin/tests/system/limits/tests_sh_limits.py
new file mode 100644
index 0000000..c7fb5ba
--- /dev/null
+++ b/bin/tests/system/limits/tests_sh_limits.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_limits(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/logfileconfig/clean.sh b/bin/tests/system/logfileconfig/clean.sh
new file mode 100644
index 0000000..befbcfe
--- /dev/null
+++ b/bin/tests/system/logfileconfig/clean.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after log file tests
+#
+rm -f ns1/named.conf
+rm -f ns1/named.args
+rm -f ns1/named.pid ns1/named.run ns1/named.run.prev
+rm -f ns1/named.memstats ns1/dig.out
+rm -f ns1/named_log ns1/named_pipe ns1/named_sym
+rm -rf ns1/named_dir
+rm -f ns1/named_deflog
+rm -f ns*/named.lock
+rm -f ns1/query_log
+rm -f ns1/named_iso8601
+rm -f ns1/named_iso8601_utc
+rm -f ns1/rndc.out.test*
+rm -f ns1/dig.out.test*
+rm -f ns1/named_vers
+rm -f ns1/named_vers.*
+rm -f ns1/named_ts
+rm -f ns1/named_ts.*
+rm -f ns1/named_inc
+rm -f ns1/named_inc.*
+rm -f ns1/named_unlimited
+rm -f ns1/named_unlimited.*
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/logfileconfig/named1.args b/bin/tests/system/logfileconfig/named1.args
new file mode 100644
index 0000000..764d4c9
--- /dev/null
+++ b/bin/tests/system/logfileconfig/named1.args
@@ -0,0 +1 @@
+-c named.conf -m record -T nosyslog -d 99 -D logfileconfig-ns1 -X named.lock -U 4
diff --git a/bin/tests/system/logfileconfig/named2.args b/bin/tests/system/logfileconfig/named2.args
new file mode 100644
index 0000000..fb9fe57
--- /dev/null
+++ b/bin/tests/system/logfileconfig/named2.args
@@ -0,0 +1 @@
+-c named.conf -m record -T nosyslog -d 99 -D logfileconfig-ns1 -X named.lock -U 4 -L named_deflog
diff --git a/bin/tests/system/logfileconfig/ns1/named.abspathconf.in b/bin/tests/system/logfileconfig/ns1/named.abspathconf.in
new file mode 100644
index 0000000..fdf8a8a
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.abspathconf.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+logging {
+ channel default_log {
+ buffered no;
+ file "@TMPDIR@/example.log" versions 1 size 1k suffix increment; # small size
+ severity debug 100;
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+
+ channel query_log {
+ file "query_log";
+ print-time yes;
+ buffered yes;
+ };
+ category queries { query_log; };
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.dirconf.in b/bin/tests/system/logfileconfig/ns1/named.dirconf.in
new file mode 100644
index 0000000..d6ee134
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.dirconf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+logging {
+ channel default_log {
+ file "/tmp";
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.incconf.in b/bin/tests/system/logfileconfig/ns1/named.incconf.in
new file mode 100644
index 0000000..d398c33
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.incconf.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+logging {
+ channel default_log {
+ buffered no;
+ file "named_inc" versions 1 size 1k suffix increment; # small size
+ severity debug 100;
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+
+ channel query_log {
+ file "query_log";
+ print-time yes;
+ buffered yes;
+ };
+ category queries { query_log; };
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.iso8601-utc.in b/bin/tests/system/logfileconfig/ns1/named.iso8601-utc.in
new file mode 100644
index 0000000..6ac14df
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.iso8601-utc.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+logging {
+ channel default_log {
+ file "named_iso8601_utc";
+ print-time iso8601-utc;
+ severity debug 9;
+ };
+ category default { default_log; default_debug; };
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.iso8601.in b/bin/tests/system/logfileconfig/ns1/named.iso8601.in
new file mode 100644
index 0000000..5a1bd5e
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.iso8601.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+logging {
+ channel default_log {
+ file "named_iso8601";
+ print-time iso8601;
+ severity debug 9;
+ };
+ category default { default_log; default_debug; };
+};
+
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.pipeconf.in b/bin/tests/system/logfileconfig/ns1/named.pipeconf.in
new file mode 100644
index 0000000..8f2ec63
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.pipeconf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+logging {
+ channel default_log {
+ file "named_pipe";
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.plain.in b/bin/tests/system/logfileconfig/ns1/named.plain.in
new file mode 100644
index 0000000..f31906b
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.plain.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+logging {
+ channel default_log {
+ file "named_log";
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+
+ channel query_log {
+ file "query_log";
+ print-time yes;
+ buffered yes;
+ };
+ category queries { query_log; };
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.plainconf.in b/bin/tests/system/logfileconfig/ns1/named.plainconf.in
new file mode 100644
index 0000000..d8dd5f5
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.plainconf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.symconf.in b/bin/tests/system/logfileconfig/ns1/named.symconf.in
new file mode 100644
index 0000000..9603365
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.symconf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+logging {
+ channel default_log {
+ file "named_sym";
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.tsconf.in b/bin/tests/system/logfileconfig/ns1/named.tsconf.in
new file mode 100644
index 0000000..7f76195
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.tsconf.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+logging {
+ channel default_log {
+ buffered no;
+ file "named_ts" versions 3 size 1000 suffix timestamp; # small size
+ severity debug 100;
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+
+ channel query_log {
+ file "query_log";
+ print-time yes;
+ buffered yes;
+ };
+ category queries { query_log; };
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.unlimited.in b/bin/tests/system/logfileconfig/ns1/named.unlimited.in
new file mode 100644
index 0000000..f806edd
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.unlimited.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+logging {
+ channel default_log {
+ buffered no;
+ file "named_unlimited" versions unlimited size 1000;
+ severity debug 100;
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+
+ channel query_log {
+ file "query_log";
+ print-time yes;
+ buffered yes;
+ };
+ category queries { query_log; };
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/logfileconfig/ns1/named.versconf.in b/bin/tests/system/logfileconfig/ns1/named.versconf.in
new file mode 100644
index 0000000..c30d8a3
--- /dev/null
+++ b/bin/tests/system/logfileconfig/ns1/named.versconf.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ recursion no;
+ notify yes;
+};
+
+logging {
+ channel default_log {
+ buffered no;
+ file "named_vers" versions 5 size 1000; // really small size
+ severity debug 100;
+ print-time yes;
+ };
+ category default { default_log; default_debug; };
+ category lame-servers { null; };
+
+ channel query_log {
+ file "query_log";
+ print-time yes;
+ buffered yes;
+ };
+ category queries { query_log; };
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; };
+};
+
+key rndc-key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
diff --git a/bin/tests/system/logfileconfig/setup.sh b/bin/tests/system/logfileconfig/setup.sh
new file mode 100644
index 0000000..7ad9bb0
--- /dev/null
+++ b/bin/tests/system/logfileconfig/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.plain.in ns1/named.conf
diff --git a/bin/tests/system/logfileconfig/tests.sh b/bin/tests/system/logfileconfig/tests.sh
new file mode 100644
index 0000000..d12fd06
--- /dev/null
+++ b/bin/tests/system/logfileconfig/tests.sh
@@ -0,0 +1,297 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+# Test given condition. If true, test again after a second. Used for testing
+# filesystem-dependent conditions in order to prevent false negatives caused by
+# directory contents not being synchronized immediately after rename() returns.
+test_with_retry() {
+ if test "$@"; then
+ sleep 1
+ if test "$@"; then
+ return 0
+ fi
+ fi
+ return 1
+}
+
+status=0
+n=0
+
+# First run with a known good config.
+n=$((n+1))
+echo_i "testing log file validity (only plain files allowed) ($n)"
+ret=0
+cat /dev/null > ns1/named_log
+copy_setports ns1/named.plainconf.in ns1/named.conf
+nextpart ns1/named.run > /dev/null
+rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Now try directory, expect failure
+n=$((n+1))
+echo_i "testing directory as log file ($n)"
+ret=0
+nextpart ns1/named.run > /dev/null
+copy_setports ns1/named.dirconf.in ns1/named.conf
+rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Now try pipe file, expect failure
+n=$((n+1))
+echo_i "testing pipe file as log file ($n)"
+ret=0
+nextpart ns1/named.run > /dev/null
+rm -f ns1/named_pipe
+if mkfifo ns1/named_pipe >/dev/null 2>&1; then
+ copy_setports ns1/named.pipeconf.in ns1/named.conf
+ rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+ wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1
+ if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+else
+ echo_i "skipping pipe test (unable to create pipe)"
+fi
+
+# Now try symlink file to plain file, expect success
+n=$((n+1))
+echo_i "testing symlink to plain file as log file ($n)"
+ret=0
+rm -f ns1/named_log ns1/named_sym
+touch ns1/named_log
+if ln -s $(pwd)/ns1/named_log $(pwd)/ns1/named_sym >/dev/null 2>&1; then
+ nextpart ns1/named.run > /dev/null
+ copy_setports ns1/named.symconf.in ns1/named.conf
+ rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+ wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1
+ if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+else
+ echo_i "skipping symlink test (unable to create symlink)"
+fi
+
+echo_i "repeat previous tests without named -g"
+copy_setports ns1/named.plain.in ns1/named.conf
+stop_server --use-rndc --port ${CONTROLPORT} ns1
+cp named1.args ns1/named.args
+start_server --noclean --restart --port ${PORT} ns1
+
+n=$((n+1))
+echo_i "testing log file validity (only plain files allowed) ($n)"
+ret=0
+cat /dev/null > ns1/named_log
+copy_setports ns1/named.plainconf.in ns1/named.conf
+nextpart ns1/named.run > /dev/null
+rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Now try directory, expect failure
+n=$((n+1))
+echo_i "testing directory as log file ($n)"
+ret=0
+nextpart ns1/named.run > /dev/null
+copy_setports ns1/named.dirconf.in ns1/named.conf
+rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Now try pipe file, expect failure
+n=$((n+1))
+echo_i "testing pipe file as log file ($n)"
+ret=0
+nextpart ns1/named.run > /dev/null
+rm -f ns1/named_pipe
+if mkfifo ns1/named_pipe >/dev/null 2>&1; then
+ copy_setports ns1/named.pipeconf.in ns1/named.conf
+ rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+ wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1
+ if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+else
+ echo_i "skipping pipe test (unable to create pipe)"
+fi
+
+# Now try symlink file to plain file, expect success
+n=$((n+1))
+echo_i "testing symlink to plain file as log file ($n)"
+ret=0
+rm -f ns1/named_log ns1/named_sym
+touch ns1/named_log
+if ln -s $(pwd)/ns1/named_log $(pwd)/ns1/named_sym >/dev/null 2>&1; then
+ nextpart ns1/named.run > /dev/null
+ copy_setports ns1/named.symconf.in ns1/named.conf
+ rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+ wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1
+ if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+else
+ echo_i "skipping symlink test (unable to create symlink)"
+fi
+
+echo_i "testing logging functionality"
+n=$((n+1))
+ret=0
+echo_i "testing iso8601 timestamp ($n)"
+copy_setports ns1/named.iso8601.in ns1/named.conf
+rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+grep '^....-..-..T..:..:..\.... ' ns1/named_iso8601 > /dev/null || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing iso8601-utc timestamp ($n)"
+ret=0
+copy_setports ns1/named.iso8601-utc.in ns1/named.conf
+rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+grep '^....-..-..T..:..:..\....Z' ns1/named_iso8601_utc > /dev/null || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing explicit versions ($n)"
+ret=0
+copy_setports ns1/named.versconf.in ns1/named.conf
+# a seconds since epoch version number
+touch ns1/named_vers.1480039317
+rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+$DIG version.bind txt ch @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+# we are configured to retain five logfiles (a current file
+# and 4 backups). so files with version number 5 or higher
+# should be removed.
+test_with_retry -f ns1/named_vers.1480039317 && ret=1
+test_with_retry -f ns1/named_vers.5 && ret=1
+test_with_retry -f ns1/named_vers.4 || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing timestamped versions ($n)"
+ret=0
+copy_setports ns1/named.tsconf.in ns1/named.conf
+# a seconds since epoch version number
+touch ns1/named_ts.1480039317
+# a timestamp version number
+touch ns1/named_ts.20150101120000120
+rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+_found2() (
+ $DIG version.bind txt ch @10.53.0.1 -p ${PORT} > dig.out.test$n
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+
+ # we are configured to keep three versions, so the oldest
+ # timestamped versions should be gone, and there should
+ # be two or three backup ones.
+ [ -f ns1/named_ts.1480039317 ] && return 1
+ [ -f ns1/named_ts.20150101120000120 ] && return 1
+ set -- ns1/named_ts.*
+ [ "$#" -eq 2 -o "$#" -eq 3 ] || return 1
+)
+retry_quiet 5 _found2 || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing incremented versions ($n)"
+ret=0
+copy_setports ns1/named.incconf.in ns1/named.conf
+try=0
+while test $try -lt 12
+do
+ touch ns1/named_inc.$try
+ try=$((try + 1))
+done
+rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+_found2() (
+ $DIG version.bind txt ch @10.53.0.1 -p ${PORT} > dig.out.test$n
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+
+ try=1
+ while test $try -lt 12
+ do
+ [ -f ns1/named_inc.$try ] && return 1
+ try=$((try + 1))
+ done
+ set -- ns1/named_inc.*
+ [ "$#" -eq 1 ] || return 1
+)
+retry_quiet 5 _found2 || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing absolute file path versions ($n)"
+ret=0
+copy_setports ns1/named.abspathconf.in ns1/named.conf
+try=0
+while test $try -lt 12
+do
+ touch $TMPDIR/example.log.$try
+ try=$((try + 1))
+done
+rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+_found2() (
+ $DIG version.bind txt ch @10.53.0.1 -p ${PORT} > dig.out.test$n
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+
+ try=1
+ while test $try -lt 12
+ do
+ [ -f $TMPDIR/example.log.$try ] && return 1
+ try=$((try + 1))
+ done
+ set -- $TMPDIR/example.log.*
+ [ "$#" -eq 1 ] || return 1
+)
+retry_quiet 5 _found2 || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing unlimited versions ($n)"
+ret=0
+copy_setports ns1/named.unlimited.in ns1/named.conf
+# a seconds since epoch version number
+touch ns1/named_unlimited.1480039317
+rndc_reconfig ns1 10.53.0.1 > rndc.out.test$n
+$DIG version.bind txt ch @10.53.0.1 -p ${PORT} > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+test_with_retry -f ns1/named_unlimited.1480039317 || ret=1
+test_with_retry -f ns1/named_unlimited.4 || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing default logfile using named -L file ($n)"
+ret=0
+stop_server ns1
+cp named2.args ns1/named.args
+test -f ns1/named.pid && ret=1
+rm -f ns1/named_deflog
+copy_setports ns1/named.plainconf.in ns1/named.conf
+start_server --noclean --restart --port ${PORT} ns1
+[ -f "ns1/named_deflog" ] || ret=1
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/logfileconfig/tests_sh_logfileconfig.py b/bin/tests/system/logfileconfig/tests_sh_logfileconfig.py
new file mode 100644
index 0000000..655a8ee
--- /dev/null
+++ b/bin/tests/system/logfileconfig/tests_sh_logfileconfig.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_logfileconfig(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/makejournal.c b/bin/tests/system/makejournal.c
new file mode 100644
index 0000000..63caa9a
--- /dev/null
+++ b/bin/tests/system/makejournal.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/fixedname.h>
+#include <dns/journal.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/types.h>
+
+#define CHECK(r) \
+ do { \
+ result = (r); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+isc_mem_t *mctx = NULL;
+isc_log_t *lctx = NULL;
+
+static bool dst_active = false;
+
+/*
+ * Logging categories: this needs to match the list in bin/named/log.c.
+ */
+static isc_logcategory_t categories[] = { { "", 0 },
+ { "client", 0 },
+ { "network", 0 },
+ { "update", 0 },
+ { "queries", 0 },
+ { "unmatched", 0 },
+ { "update-security", 0 },
+ { "query-errors", 0 },
+ { NULL, 0 } };
+
+static isc_result_t
+loadzone(dns_db_t **db, const char *origin, const char *filename) {
+ isc_result_t result;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+
+ name = dns_fixedname_initname(&fixed);
+
+ result = dns_name_fromstring(name, origin, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
+ dns_rdataclass_in, 0, NULL, db);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ result = dns_db_load(*db, filename, dns_masterformat_text, 0);
+ return (result);
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+ char *origin, *file1, *file2, *journal;
+ dns_db_t *olddb = NULL, *newdb = NULL;
+ isc_logdestination_t destination;
+ isc_logconfig_t *logconfig = NULL;
+
+ if (argc != 5) {
+ printf("usage: %s origin file1 file2 journal\n", argv[0]);
+ return (1);
+ }
+
+ origin = argv[1];
+ file1 = argv[2];
+ file2 = argv[3];
+ journal = argv[4];
+
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ isc_mem_create(&mctx);
+
+ CHECK(dst_lib_init(mctx, NULL));
+ dst_active = true;
+
+ isc_log_create(mctx, &lctx, &logconfig);
+ isc_log_registercategories(lctx, categories);
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC, &destination, 0);
+
+ CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL));
+
+ result = loadzone(&olddb, origin, file1);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "Couldn't load %s: ", file1);
+ goto cleanup;
+ }
+
+ result = loadzone(&newdb, origin, file2);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "Couldn't load %s: ", file2);
+ goto cleanup;
+ }
+
+ result = dns_db_diff(mctx, newdb, NULL, olddb, NULL, journal);
+
+cleanup:
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "%s\n", isc_result_totext(result));
+ }
+
+ if (newdb != NULL) {
+ dns_db_detach(&newdb);
+ }
+ if (olddb != NULL) {
+ dns_db_detach(&olddb);
+ }
+
+ if (lctx != NULL) {
+ isc_log_destroy(&lctx);
+ }
+ if (dst_active) {
+ dst_lib_destroy();
+ dst_active = false;
+ }
+ if (mctx != NULL) {
+ isc_mem_destroy(&mctx);
+ }
+
+ return (result != ISC_R_SUCCESS ? 1 : 0);
+}
diff --git a/bin/tests/system/masterfile/clean.sh b/bin/tests/system/masterfile/clean.sh
new file mode 100644
index 0000000..97aa377
--- /dev/null
+++ b/bin/tests/system/masterfile/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.*
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f checkzone.out*
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/masterfile/knowngood.dig.out b/bin/tests/system/masterfile/knowngood.dig.out
new file mode 100644
index 0000000..d4cbac8
--- /dev/null
+++ b/bin/tests/system/masterfile/knowngood.dig.out
@@ -0,0 +1,32 @@
+include. 300 IN SOA ns.include. hostmaster.include. 1 3600 1800 1814400 3600
+include. 300 IN NS ns.include.
+a.include. 300 IN A 10.0.0.1
+a.include. 300 IN A 10.0.0.99
+a.a.include. 300 IN A 10.0.1.1
+b.foo.a.include. 300 IN A 10.0.2.2
+b.include. 300 IN A 10.0.0.2
+a.b.include. 300 IN A 10.0.1.1
+c.b.include. 300 IN A 10.0.0.3
+b.foo.b.include. 300 IN A 10.0.2.2
+ns.include. 300 IN A 127.0.0.1
+include. 300 IN SOA ns.include. hostmaster.include. 1 3600 1800 1814400 3600
+ttl2. 1 IN SOA ns.ttl2. hostmaster.ttl2. 1 3600 1800 1814400 3
+ttl2. 1 IN NS ns.ttl2.
+a.ttl2. 1 IN TXT "inherited ttl 1"
+b.ttl2. 2 IN TXT "explicit ttl 2"
+c.ttl2. 2 IN TXT "inherited ttl 2"
+d.ttl2. 3 IN TXT "default ttl 3"
+e.ttl2. 2 IN TXT "explicit ttl 2"
+f.ttl2. 3 IN TXT "default ttl 3"
+ns.ttl2. 1 IN A 10.53.0.1
+ttl2. 1 IN SOA ns.ttl2. hostmaster.ttl2. 1 3600 1800 1814400 3
+ttl2. 1 IN SOA ns.ttl2. hostmaster.ttl2. 1 3600 1800 1814400 3
+ttl2. 1 IN NS ns.ttl2.
+a.ttl2. 1 IN TXT "inherited ttl 1"
+b.ttl2. 2 IN TXT "explicit ttl 2"
+c.ttl2. 2 IN TXT "inherited ttl 2"
+d.ttl2. 3 IN TXT "default ttl 3"
+e.ttl2. 2 IN TXT "explicit ttl 2"
+f.ttl2. 3 IN TXT "default ttl 3"
+ns.ttl2. 1 IN A 10.53.0.1
+ttl2. 1 IN SOA ns.ttl2. hostmaster.ttl2. 1 3600 1800 1814400 3
diff --git a/bin/tests/system/masterfile/ns1/include.db b/bin/tests/system/masterfile/ns1/include.db
new file mode 100644
index 0000000..149c819
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/include.db
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; Test $INCLUDE current domain name and origin semantics
+
+$TTL 300
+@ IN SOA ns hostmaster (
+ 1 ; serial
+ 3600
+ 1800
+ 1814400
+ 3600
+ )
+ NS ns
+
+ns A 127.0.0.1
+
+a A 10.0.0.1
+$INCLUDE sub.db a
+; use the current domain name
+ A 10.0.0.99
+b A 10.0.0.2
+$ORIGIN b
+$INCLUDE sub.db
+; use the current domain name
+; A 10.0.0.99
+c A 10.0.0.3
diff --git a/bin/tests/system/masterfile/ns1/named.conf.in b/bin/tests/system/masterfile/ns1/named.conf.in
new file mode 100644
index 0000000..4203aae
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+zone "include" {
+ type primary;
+ file "include.db";
+};
+
+zone "ttl1" {
+ type primary;
+ file "ttl1.db";
+};
+
+zone "ttl2" {
+ type primary;
+ file "ttl2.db";
+};
diff --git a/bin/tests/system/masterfile/ns1/sub.db b/bin/tests/system/masterfile/ns1/sub.db
new file mode 100644
index 0000000..7e027b0
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/sub.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+a A 10.0.1.1
+$ORIGIN foo
+b A 10.0.2.2
+
diff --git a/bin/tests/system/masterfile/ns1/ttl1.db b/bin/tests/system/masterfile/ns1/ttl1.db
new file mode 100644
index 0000000..56afe9d
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/ttl1.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ IN SOA ns hostmaster (
+ 1 ; serial
+ 3600
+ 1800
+ 1814400
+ 3
+ )
+ NS ns
+ns A 10.53.0.1
+a TXT "soa minttl 3"
+b 2 TXT "explicit ttl 2"
+c TXT "soa minttl 3"
+$TTL 1
+d TXT "default ttl 1"
+e 4 TXT "explicit ttl 4"
+f TXT "default ttl 1"
diff --git a/bin/tests/system/masterfile/ns1/ttl2.db b/bin/tests/system/masterfile/ns1/ttl2.db
new file mode 100644
index 0000000..778e8d3
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/ttl2.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 1 IN SOA ns hostmaster (
+ 1 ; serial
+ 3600
+ 1800
+ 1814400
+ 3
+ )
+ NS ns
+ns A 10.53.0.1
+a TXT "inherited ttl 1"
+b 2 TXT "explicit ttl 2"
+c TXT "inherited ttl 2"
+$TTL 3
+d TXT "default ttl 3"
+e 2 TXT "explicit ttl 2"
+f TXT "default ttl 3"
+
+
+
diff --git a/bin/tests/system/masterfile/ns2/example.db b/bin/tests/system/masterfile/ns2/example.db
new file mode 100644
index 0000000..414403a
--- /dev/null
+++ b/bin/tests/system/masterfile/ns2/example.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2010042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
diff --git a/bin/tests/system/masterfile/ns2/named.conf.in b/bin/tests/system/masterfile/ns2/named.conf.in
new file mode 100644
index 0000000..1f4ef91
--- /dev/null
+++ b/bin/tests/system/masterfile/ns2/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "missing" {
+ type primary;
+ file "missing.db";
+};
diff --git a/bin/tests/system/masterfile/setup.sh b/bin/tests/system/masterfile/setup.sh
new file mode 100644
index 0000000..46c18c4
--- /dev/null
+++ b/bin/tests/system/masterfile/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
diff --git a/bin/tests/system/masterfile/tests.sh b/bin/tests/system/masterfile/tests.sh
new file mode 100644
index 0000000..5755088
--- /dev/null
+++ b/bin/tests/system/masterfile/tests.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+
+status=0
+n=0
+
+ret=0
+n=$((n + 1))
+echo_i "test master file \$INCLUDE semantics ($n)"
+$DIG $DIGOPTS +nostats +nocmd include. axfr @10.53.0.1 >dig.out.$n
+
+echo_i "test master file BIND 8 compatibility TTL and \$TTL semantics ($n)"
+$DIG $DIGOPTS +nostats +nocmd ttl2. axfr @10.53.0.1 >>dig.out.$n
+
+echo_i "test of master file RFC1035 TTL and \$TTL semantics ($n)"
+$DIG $DIGOPTS +nostats +nocmd ttl2. axfr @10.53.0.1 >>dig.out.$n
+
+diff dig.out.$n knowngood.dig.out || status=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+ret=0
+n=$((n + 1))
+echo_i "test that the nameserver is running with a missing master file ($n)"
+$DIG $DIGOPTS +tcp +noall +answer example soa @10.53.0.2 > dig.out.$n
+grep SOA dig.out.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+ret=0
+n=$((n + 1))
+echo_i "test that the nameserver returns SERVFAIL for a missing master file ($n)"
+$DIG $DIGOPTS +tcp +all missing soa @10.53.0.2 > dig.out.$n
+grep "status: SERVFAIL" dig.out.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+ret=0
+n=$((n + 1))
+echo_i "test owner inheritance after "'$INCLUDE'" ($n)"
+$CHECKZONE -Dq example zone/inheritownerafterinclude.db > checkzone.out$n
+diff checkzone.out$n zone/inheritownerafterinclude.good || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/masterfile/tests_sh_masterfile.py b/bin/tests/system/masterfile/tests_sh_masterfile.py
new file mode 100644
index 0000000..1556892
--- /dev/null
+++ b/bin/tests/system/masterfile/tests_sh_masterfile.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_masterfile(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/masterfile/zone/inheritownerafterinclude.db b/bin/tests/system/masterfile/zone/inheritownerafterinclude.db
new file mode 100644
index 0000000..11b97ea
--- /dev/null
+++ b/bin/tests/system/masterfile/zone/inheritownerafterinclude.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 IN SOA . . 0 0 0 0 0
+$INCLUDE zone/nameservers.db
+ IN TXT "this should be at the zone apex"
diff --git a/bin/tests/system/masterfile/zone/inheritownerafterinclude.good b/bin/tests/system/masterfile/zone/inheritownerafterinclude.good
new file mode 100644
index 0000000..3877ed5
--- /dev/null
+++ b/bin/tests/system/masterfile/zone/inheritownerafterinclude.good
@@ -0,0 +1,3 @@
+example. 0 IN SOA . . 0 0 0 0 0
+example. 0 IN NS .
+example. 0 IN TXT "this should be at the zone apex"
diff --git a/bin/tests/system/masterfile/zone/nameservers.db b/bin/tests/system/masterfile/zone/nameservers.db
new file mode 100644
index 0000000..f7b6525
--- /dev/null
+++ b/bin/tests/system/masterfile/zone/nameservers.db
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ IN NS .
diff --git a/bin/tests/system/masterformat/clean.sh b/bin/tests/system/masterformat/clean.sh
new file mode 100755
index 0000000..04ff2b8
--- /dev/null
+++ b/bin/tests/system/masterformat/clean.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ./ns1/example.db.raw*
+rm -f ./ns1/example.db.compat
+rm -f ./ns1/example.db.serial.raw
+rm -f ./ns1/large.db ./ns1/large.db.raw
+rm -f ./ns1/signed.db.raw
+rm -f ./ns1/session.key
+rm -f ./dig.out.*
+rm -f ./dig.out
+rm -f ./*/named.memstats
+rm -f ./*/named.conf
+rm -f ./*/named.run
+rm -f ./ns2/example.db
+rm -f ./ns2/transfer.db.*
+rm -f ./ns2/formerly-text.db
+rm -f ./ns2/db-*
+rm -f ./ns2/large.bk
+rm -f ./ns3/example.db.raw ./ns3/dynamic.db.raw
+rm -f ./baseline.txt ./text.* ./raw.*
+rm -f ./ns1/Ksigned.* ./ns1/dsset-signed. ./ns1/signed.db.signed
+rm -f ./rndc.out
+rm -f ./ns*/named.lock
+rm -f ./ns*/managed-keys.bind*
diff --git a/bin/tests/system/masterformat/ns1/compile.sh b/bin/tests/system/masterformat/ns1/compile.sh
new file mode 100755
index 0000000..0c2e7fb
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/compile.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+$CHECKZONE -D -F raw -o example.db.raw example \
+ example.db > /dev/null 2>&1
+$CHECKZONE -D -F raw -o ../ns3/example.db.raw example \
+ example.db > /dev/null 2>&1
+$CHECKZONE -D -F raw -o ../ns3/dynamic.db.raw dynamic \
+ example.db > /dev/null 2>&1
+$CHECKZONE -D -F raw=1 -o example.db.raw1 example-explicit \
+ example.db > /dev/null 2>&1
+$CHECKZONE -D -F raw=0 -o example.db.compat example-compat \
+ example.db > /dev/null 2>&1
+$CHECKZONE -D -F raw -L 3333 -o example.db.serial.raw example \
+ example.db > /dev/null 2>&1
+$CHECKZONE -D -F raw -o large.db.raw large large.db > /dev/null 2>&1
+
+$KEYGEN -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK signed > /dev/null 2>&1
+$KEYGEN -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" signed > /dev/null 2>&1
+$SIGNER -S -f signed.db.signed -o signed signed.db > /dev/null
+$CHECKZONE -D -F raw -o signed.db.raw signed signed.db.signed > /dev/null 2>&1
diff --git a/bin/tests/system/masterformat/ns1/example.db b/bin/tests/system/masterformat/ns1/example.db
new file mode 100644
index 0000000..5ca0ae2
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/example.db
@@ -0,0 +1,58 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 1D
+
+@ IN SOA ns hostmaster (
+ 1
+ 3600
+ 1800
+ 1814400
+ 3
+ )
+ NS ns
+ns A 10.53.0.1
+mx MX 10 mail
+a A 10.53.0.1
+ A 10.53.0.2
+aaaa AAAA 2001:db8::53
+cname CNAME cname-target
+dname DNAME dname-target
+txt TXT "this is text"
+
+;;
+;; we are not testing DNSSEC behavior, so we don't care about the semantics
+;; of the following records.
+dnskey 300 DNSKEY 256 3 13 (
+ TEcpWeW1mJp+OujqyInMbjGRODJIYen/4kMR
+ wO6zW3RzrvmNIMgFag6G uXofiSwJ6YDeQ0O
+ 3uhPJsJ7ivpbh+w==
+ )
+private-dnskey 300 DNSKEY 256 3 253 ( AAo= )
+ds 300 DS 30795 1 1 (
+ 310D27F4D82C1FC2400704EA9939FE6E1CEA
+ A3B9 )
+cdnskey 300 CDNSKEY 256 3 13 (
+ TEcpWeW1mJp+OujqyInMbjGRODJIYen/4kMR
+ wO6zW3RzrvmNIMgFag6G uXofiSwJ6YDeQ0O
+ 3uhPJsJ7ivpbh+w==
+ )
+private-cdnskey 300 CDNSKEY 256 3 253 ( AAo= )
+cds 300 CDS 30795 1 1 (
+ 310D27F4D82C1FC2400704EA9939FE6E1CEA
+ A3B9 )
+nsec 600 NSEC nsecnext NS DS RRSIG NSEC
+rrsig 300 RRSIG SOA 1 0 300 20050714214747 (
+ 20050614214747 30795 .
+ yi/RRPAQmn6rnjDQaCqVValBa+ICF00ZldKf
+ ZSDaoew5mMUh83DlrrPPNeAxrzMSNzDGlJ6P
+ fdyIFgzPn/CvthF4kjBUAiJTp4r2zhlaUJQ+
+ QFo+drYXYgVJo6aA36fj )
diff --git a/bin/tests/system/masterformat/ns1/large.db.in b/bin/tests/system/masterformat/ns1/large.db.in
new file mode 100644
index 0000000..5a81863
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/large.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 1D
+
+@ IN SOA ns hostmaster (
+ 1
+ 3600
+ 1800
+ 1814400
+ 3
+ )
+ NS ns
+ns A 10.53.0.1
diff --git a/bin/tests/system/masterformat/ns1/named.conf.in b/bin/tests/system/masterformat/ns1/named.conf.in
new file mode 100644
index 0000000..a0d054f
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/named.conf.in
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ pid-file "named.pid";
+ listen-on port @PORT@ { 10.53.0.1; };
+ port @PORT@;
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ session-keyfile "session.key";
+ servfail-ttl 0;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type primary;
+ masterfile-format raw;
+ file "example.db.raw";
+};
+
+zone "compat-example" {
+ type primary;
+ masterfile-format raw;
+ file "example.db.compat";
+};
+
+zone "transfer1" {
+ type primary;
+ file "example.db";
+ allow-transfer { any; };
+};
+
+zone "transfer2" {
+ type primary;
+ file "example.db";
+ allow-transfer { any; };
+};
+
+zone "transfer3" {
+ type primary;
+ file "example.db";
+ allow-transfer { any; };
+};
+
+zone "transfer4" {
+ type primary;
+ file "example.db";
+ allow-transfer { any; };
+};
+
+
+zone "large" {
+ type primary;
+ file "large.db.raw";
+ masterfile-format raw;
+ allow-transfer { any; };
+};
+
+zone "signed" {
+ type primary;
+ file "signed.db.raw";
+ masterfile-format raw;
+ allow-transfer { any; };
+ update-policy local;
+ auto-dnssec maintain;
+};
diff --git a/bin/tests/system/masterformat/ns1/signed.db b/bin/tests/system/masterformat/ns1/signed.db
new file mode 100644
index 0000000..55d6fae
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/signed.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 1D
+
+@ IN SOA ns hostmaster (
+ 1
+ 3600
+ 1800
+ 1814400
+ 3
+ )
+ NS ns
+ns A 10.53.0.1
+mx MX 10 mail
+a A 10.53.0.1
+ A 10.53.0.2
+aaaa AAAA 2001:db8::53
+cname CNAME cname-target
+dname DNAME dname-target
+txt TXT "this is text"
diff --git a/bin/tests/system/masterformat/ns2/formerly-text.db.in b/bin/tests/system/masterformat/ns2/formerly-text.db.in
new file mode 100644
index 0000000..02ce216
--- /dev/null
+++ b/bin/tests/system/masterformat/ns2/formerly-text.db.in
@@ -0,0 +1,48 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 86400 ; 1 day
+transfer3 IN SOA ns.transfer3. hostmaster.transfer3. (
+ 1 ; serial
+ 3600 ; refresh (1 hour)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3 ; minimum (3 seconds)
+ )
+ NS ns.transfer3.
+$ORIGIN transfer3.
+a A 10.53.0.1
+ A 10.53.0.2
+aaaa AAAA 2001:db8::53
+cname CNAME cname-target
+dname DNAME dname-target
+$TTL 300 ; 5 minutes
+dnskey DNSKEY 256 3 13 (
+ TEcpWeW1mJp+OujqyInMbjGRODJIYen/4kMR
+ wO6zW3RzrvmNIMgFag6G uXofiSwJ6YDeQ0O
+ 3uhPJsJ7ivpbh+w==
+ )
+ds DS 30795 1 1 (
+ 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9 )
+$TTL 86400 ; 1 day
+mx MX 10 mail
+ns A 10.53.0.1
+$TTL 600 ; 10 minutes
+nsec NSEC nsecnext.transfer3. NS DS RRSIG NSEC
+$TTL 300 ; 5 minutes
+rrsig RRSIG SOA 1 0 300 (
+ 20050714214747 20050614214747 30795 .
+ yi/RRPAQmn6rnjDQaCqVValBa+ICF00ZldKfZSDaoew5
+ mMUh83DlrrPPNeAxrzMSNzDGlJ6PfdyIFgzPn/CvthF4
+ kjBUAiJTp4r2zhlaUJQ+QFo+drYXYgVJo6aA36fj )
+$TTL 86400 ; 1 day
+txt TXT "this is text"
diff --git a/bin/tests/system/masterformat/ns2/named.conf.in b/bin/tests/system/masterformat/ns2/named.conf.in
new file mode 100644
index 0000000..db68aef
--- /dev/null
+++ b/bin/tests/system/masterformat/ns2/named.conf.in
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ pid-file "named.pid";
+ listen-on port @PORT@ { 10.53.0.2; };
+ listen-on-v6 { none; };
+ port @PORT@;
+ recursion no;
+ notify no;
+ servfail-ttl 0;
+ dnssec-validation no;
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "transfer1" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "transfer.db.raw";
+};
+
+zone "transfer2" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ masterfile-format text;
+ file "transfer.db.txt";
+};
+
+zone "transfer3" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "formerly-text.db";
+};
+
+zone "transfer4" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ masterfile-format text;
+ masterfile-style full;
+ file "transfer.db.full";
+};
+
+zone "large" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ masterfile-format raw;
+ file "large.bk";
+};
diff --git a/bin/tests/system/masterformat/ns3/named.conf.in b/bin/tests/system/masterformat/ns3/named.conf.in
new file mode 100644
index 0000000..deaed8b
--- /dev/null
+++ b/bin/tests/system/masterformat/ns3/named.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+options {
+ pid-file "named.pid";
+ listen-on port @PORT@ { 10.53.0.3; };
+ port @PORT@;
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type primary;
+ masterfile-format raw;
+ file "example.db.raw";
+};
+
+zone "dynamic" {
+ type primary;
+ masterfile-format raw;
+ file "dynamic.db.raw";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/masterformat/setup.sh b/bin/tests/system/masterformat/setup.sh
new file mode 100755
index 0000000..d5fe367
--- /dev/null
+++ b/bin/tests/system/masterformat/setup.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+
+cp ns1/example.db ns2/
+cp ns2/formerly-text.db.in ns2/formerly-text.db
+cp ns1/large.db.in ns1/large.db
+awk 'END {
+ for (i = 0; i < 512; i++ ) { print "a TXT", i; }
+ for (i = 0; i < 1024; i++ ) { print "b TXT", i; }
+ for (i = 0; i < 2000; i++ ) { print "c TXT", i; }
+}' < /dev/null >> ns1/large.db
+cd ns1 && $SHELL compile.sh
diff --git a/bin/tests/system/masterformat/tests.sh b/bin/tests/system/masterformat/tests.sh
new file mode 100755
index 0000000..da9ec87
--- /dev/null
+++ b/bin/tests/system/masterformat/tests.sh
@@ -0,0 +1,278 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+status=0
+n=1
+
+israw () {
+ # shellcheck disable=SC2016
+ $PERL -e 'binmode STDIN;
+ read(STDIN, $input, 8);
+ ($style, $version) = unpack("NN", $input);
+ exit 1 if ($style != 2 || $version > 1);' < "$1" || return $?
+}
+
+isfull () {
+ # there should be no whitespace at the beginning of a line
+ if grep '^[ ][ ]*' "$1" > /dev/null 2>&1; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+rawversion () {
+ # shellcheck disable=SC2016
+ $PERL -e 'binmode STDIN;
+ read(STDIN, $input, 8);
+ if (length($input) < 8) { print "not raw\n"; exit 0; };
+ ($style, $version) = unpack("NN", $input);
+ print ($style == 2 || $style == 3 ? "$version\n" :
+ "not raw\n");' < "$1"
+}
+
+sourceserial () {
+ # shellcheck disable=SC2016
+ $PERL -e 'binmode STDIN;
+ read(STDIN, $input, 20);
+ if (length($input) < 20) { print "UNSET\n"; exit; };
+ ($format, $version, $dumptime, $flags, $sourceserial) =
+ unpack("NNNNN", $input);
+ if ($format != 2 || $version < 1) { print "UNSET\n"; exit; };
+ if ($flags & 02) {
+ print $sourceserial . "\n";
+ } else {
+ print "UNSET\n";
+ }' < "$1"
+}
+
+stomp () {
+ # shellcheck disable=SC2016
+ $PERL -e 'open(my $file, "+<", $ARGV[0]);
+ binmode $file;
+ seek($file, $ARGV[1], 0);
+ for (my $i = 0; $i < $ARGV[2]; $i++) {
+ print $file pack("C", $ARGV[3]);
+ }
+ close($file);' "$@"
+}
+
+restart () {
+ sleep 1
+ start_server --noclean --restart --port "${PORT}" ns3
+}
+
+dig_with_opts() {
+ "$DIG" +tcp +noauth +noadd +nosea +nostat +noquest +nocomm +nocmd -p "${PORT}" "$@"
+}
+
+rndccmd() {
+ "$RNDC" -c ../common/rndc.conf -p "${CONTROLPORT}" -s "$@"
+}
+
+status=0
+
+echo_i "checking that files in raw format loaded ($n)"
+ret=0
+set -- 1 2 3
+for zone in example example-explicit example-compat; do
+ for server in "$@"; do
+ for qname in ns mx a aaaa cname dname txt rrsig nsec \
+ dnskey ds cdnskey cds; do
+ qtype="$qname"
+ dig_with_opts @10.53.0.${server} -q ${qname}.${zone}. -t ${qtype}
+ echo
+ done > dig.out.${zone}.${server}.test${n}
+ for qname in private-dnskey private-cdnskey; do
+ qtype=$(expr "$qname" : '.*-\(.*\)')
+ dig_with_opts @10.53.0.${server} -q ${qname}.${zone}. -t ${qtype}
+ done >> dig.out.${zone}.${server}.test${n}
+ done
+ digcomp dig.out.${zone}.1.test${n} dig.out.${zone}.2.test${n} || ret=1
+ if [ "$zone" = "example" ]; then
+ set -- 1 2
+ digcomp dig.out.${zone}.1.test${n} dig.out.${zone}.3.test${n} || ret=1
+ fi
+done
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking raw format versions ($n)"
+ret=0
+israw ns1/example.db.raw || ret=1
+israw ns1/example.db.raw1 || ret=1
+israw ns1/example.db.compat || ret=1
+[ "$(rawversion ns1/example.db.raw)" -eq 1 ] || ret=1
+[ "$(rawversion ns1/example.db.raw1)" -eq 1 ] || ret=1
+[ "$(rawversion ns1/example.db.compat)" -eq 0 ] || ret=1
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking source serial numbers ($n)"
+ret=0
+[ "$(sourceserial ns1/example.db.raw)" = "UNSET" ] || ret=1
+[ "$(sourceserial ns1/example.db.serial.raw)" = "3333" ] || ret=1
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "waiting for transfers to complete"
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ test -f ns2/transfer.db.raw -a -f ns2/transfer.db.txt && break
+ sleep 1
+done
+
+echo_i "checking that secondary was saved in raw format by default ($n)"
+ret=0
+israw ns2/transfer.db.raw || ret=1
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that secondary was saved in text format when configured ($n)"
+ret=0
+israw ns2/transfer.db.txt && ret=1
+isfull ns2/transfer.db.txt && ret=1
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that secondary was saved in 'full' style when configured ($n)"
+ret=0
+isfull ns2/transfer.db.full > /dev/null 2>&1 || ret=1
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that secondary formerly in text format is now raw ($n)"
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ ret=0
+ israw ns2/formerly-text.db > /dev/null 2>&1 || ret=1
+ [ "$(rawversion ns2/formerly-text.db)" -eq 1 ] || ret=1
+ [ $ret -eq 0 ] && break
+ sleep 1
+done
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking that large rdatasets loaded ($n)"
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ret=0
+for a in a b c
+do
+ $DIG +tcp txt "${a}.large" @10.53.0.2 -p "${PORT}" > "dig.out.ns2.test$n"
+ grep "status: NOERROR" "dig.out.ns2.test$n" > /dev/null || ret=1
+done
+[ $ret -eq 0 ] && break
+sleep 1
+done
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking format transitions: text->raw->text ($n)"
+ret=0
+$CHECKZONE -D -f text -F text -o baseline.txt example.nil ns1/example.db > /dev/null
+$CHECKZONE -D -f text -F raw -o raw.1 example.nil baseline.txt > /dev/null
+$CHECKZONE -D -f raw -F text -o text.1 example.nil raw.1 > /dev/null
+cmp -s baseline.txt text.1 || ret=0
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking raw format loading with journal file rollforward ($n)"
+ret=0
+$NSUPDATE <<END > /dev/null || status=1
+server 10.53.0.3 ${PORT}
+ttl 600
+update add newtext.dynamic IN TXT "added text"
+update delete aaaa.dynamic
+send
+END
+dig_with_opts @10.53.0.3 newtext.dynamic txt > "dig.out.dynamic1.ns3.test$n"
+grep "added text" "dig.out.dynamic1.ns3.test$n" > /dev/null 2>&1 || ret=1
+dig_with_opts +comm @10.53.0.3 added.dynamic txt > "dig.out.dynamic2.ns3.test$n"
+grep "NXDOMAIN" "dig.out.dynamic2.ns3.test$n" > /dev/null 2>&1 || ret=1
+# using "rndc halt" ensures that we don't dump the zone file
+stop_server --use-rndc --halt --port ${CONTROLPORT} ns3
+restart
+check_added_text() {
+ dig_with_opts @10.53.0.3 newtext.dynamic txt > "dig.out.dynamic3.ns3.test$n" || return 1
+ grep "added text" "dig.out.dynamic3.ns3.test$n" > /dev/null || return 1
+ return 0
+}
+retry_quiet 10 check_added_text || ret=1
+dig_with_opts +comm @10.53.0.3 added.dynamic txt > "dig.out.dynamic4.ns3.test$n"
+grep "NXDOMAIN" "dig.out.dynamic4.ns3.test$n" > /dev/null 2>&1 || ret=1
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking raw format file dumps correctly ($n)"
+ret=0
+$NSUPDATE <<END > /dev/null || status=1
+server 10.53.0.3 ${PORT}
+ttl 600
+update add moretext.dynamic IN TXT "more text"
+send
+END
+dig_with_opts @10.53.0.3 moretext.dynamic txt > "dig.out.dynamic1.ns3.test$n"
+grep "more text" "dig.out.dynamic1.ns3.test$n" > /dev/null 2>&1 || ret=1
+# using "rndc stop" will cause the zone file to flush before shutdown
+stop_server --use-rndc --port ${CONTROLPORT} ns3
+rm ns3/*.jnl
+restart
+#shellcheck disable=SC2034
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ lret=0
+ dig_with_opts +comm @10.53.0.3 moretext.dynamic txt > "dig.out.dynamic2.ns3.test$n"
+ grep "more text" "dig.out.dynamic2.ns3.test$n" > /dev/null 2>&1 || lret=1
+ [ $lret -eq 0 ] && break;
+done
+[ $lret -eq 1 ] && ret=1
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking raw format zone is scheduled for resigning (compilezone) ($n)"
+ret=0
+rndccmd 10.53.0.1 zonestatus signed > rndc.out 2>&1 || ret=1
+grep 'next resign' rndc.out > /dev/null 2>&1 || ret=1
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "checking raw format zone is scheduled for resigning (signzone) ($n)"
+ret=0
+rndccmd 10.53.0.1 freeze signed > rndc.out 2>&1 || ret=1
+(cd ns1 || exit 1; $SIGNER -S -O raw -f signed.db.raw -o signed signed.db > /dev/null)
+rndc_reload ns1 10.53.0.1 signed
+rndccmd 10.53.0.1 zonestatus signed > rndc.out 2>&1 || ret=1
+grep 'next resign' rndc.out > /dev/null 2>&1 || ret=1
+n=$((n+1))
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/masterformat/tests_sh_masterformat.py b/bin/tests/system/masterformat/tests_sh_masterformat.py
new file mode 100644
index 0000000..b70f036
--- /dev/null
+++ b/bin/tests/system/masterformat/tests_sh_masterformat.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_masterformat(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/metadata/child.db b/bin/tests/system/metadata/child.db
new file mode 100644
index 0000000..35fff9c
--- /dev/null
+++ b/bin/tests/system/metadata/child.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 20
+child.parent.nil IN SOA ns.child.parent.nil. hostmaster.parent.nil. (
+ 1 ; serial
+ 2000 ; refresh (33 minutes 20 seconds)
+ 2000 ; retry (33 minutes 20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns.child.parent.nil.
+$ORIGIN child.parent.nil.
+$TTL 300 ; 5 minutes
+ns A 10.53.0.3
diff --git a/bin/tests/system/metadata/clean.sh b/bin/tests/system/metadata/clean.sh
new file mode 100644
index 0000000..bac7f18
--- /dev/null
+++ b/bin/tests/system/metadata/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f K* dsset-* *.signed *.new
+rm -f zsk.key ksk.key parent.ksk.key parent.zsk.key
+rm -f pending.key rolling.key standby.key inact.key
+rm -f prerev.key postrev.key oldstyle.key
+rm -f keys sigs
+rm -f tmp.out
+rm -f settime1.test* settime2.test*
+rm -f ns*/named.lock
diff --git a/bin/tests/system/metadata/parent.db b/bin/tests/system/metadata/parent.db
new file mode 100644
index 0000000..a5484e3
--- /dev/null
+++ b/bin/tests/system/metadata/parent.db
@@ -0,0 +1,31 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+parent.nil IN SOA ns1.parent.nil. hostmaster.parent.nil. (
+ 1 ; serial
+ 2000 ; refresh (33 minutes 20 seconds)
+ 2000 ; retry (33 minutes 20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns1.parent.nil.
+ NS ns2.parent.nil.
+$ORIGIN parent.nil.
+$TTL 3600 ; 1 hour
+a A 1.1.1.1
+$TTL 300 ; 5 minutes
+ns1 A 10.53.0.1
+ns2 A 10.53.0.2
+
+child NS ns.child
+ns.child A 10.53.0.3
diff --git a/bin/tests/system/metadata/setup.sh b/bin/tests/system/metadata/setup.sh
new file mode 100644
index 0000000..2d4e7cb
--- /dev/null
+++ b/bin/tests/system/metadata/setup.sh
@@ -0,0 +1,60 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+pzone=parent.nil
+czone=child.parent.nil
+
+echo_i "generating keys"
+
+# active zsk
+zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $czone)
+echo $zsk > zsk.key
+
+# not yet published or active
+pending=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -P none -A none $czone)
+echo $pending > pending.key
+
+# published but not active
+standby=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -A none $czone)
+echo $standby > standby.key
+
+# inactive
+inact=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -P now-24h -A now-24h -I now $czone)
+echo $inact > inact.key
+
+# active ksk
+ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $czone)
+echo $ksk > ksk.key
+
+# published but not YET active; will be active in 15 seconds
+rolling=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $czone)
+$SETTIME -A now+15s $rolling > /dev/null
+echo $rolling > rolling.key
+
+# revoked
+revoke1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $czone)
+echo $revoke1 > prerev.key
+revoke2=$($REVOKE $revoke1)
+echo $revoke2 | sed -e 's#\./##' -e "s/\.key.*$//" > postrev.key
+
+pzsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $pzone)
+echo $pzsk > parent.zsk.key
+
+pksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $pzone)
+echo $pksk > parent.ksk.key
+
+oldstyle=$($KEYGEN -Cq -a ${DEFAULT_ALGORITHM} $pzone)
+echo $oldstyle > oldstyle.key
+
diff --git a/bin/tests/system/metadata/tests.sh b/bin/tests/system/metadata/tests.sh
new file mode 100644
index 0000000..3a91bb7
--- /dev/null
+++ b/bin/tests/system/metadata/tests.sh
@@ -0,0 +1,233 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+pzone=parent.nil pfile=parent.db
+czone=child.parent.nil cfile=child.db
+status=0
+n=1
+
+echo_i "setting key timers"
+$SETTIME -A now+15s $(cat rolling.key) > /dev/null
+
+inact=$(keyfile_to_key_id "$(cat inact.key)")
+ksk=$(keyfile_to_key_id "$(cat ksk.key)")
+pending=$(keyfile_to_key_id "$(cat pending.key)")
+postrev=$(keyfile_to_key_id "$(cat postrev.key)")
+prerev=$(keyfile_to_key_id "$(cat prerev.key)")
+rolling=$(keyfile_to_key_id "$(cat rolling.key)")
+standby=$(keyfile_to_key_id "$(cat standby.key)")
+zsk=$(keyfile_to_key_id "$(cat zsk.key)")
+
+echo_i "signing zones"
+$SIGNER -Sg -o $czone $cfile > /dev/null
+$SIGNER -Sg -o $pzone $pfile > /dev/null
+
+awk '$2 ~ /RRSIG/ {
+ type = $3;
+ getline;
+ id = $3;
+ if ($4 ~ /'${czone}'/) {
+ print type, id
+ }
+}' < ${cfile}.signed > sigs
+
+awk '$2 ~ /DNSKEY/ {
+ flags = $3;
+ while ($0 !~ /key id =/)
+ getline;
+ id = $NF;
+ print flags, id;
+}' < ${cfile}.signed > keys
+
+echo_i "checking that KSK signed DNSKEY only ($n)"
+ret=0
+grep "DNSKEY $ksk"'$' sigs > /dev/null || ret=1
+grep "SOA $ksk"'$' sigs > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that ZSK signed ($n)"
+ret=0
+grep "SOA $zsk"'$' sigs > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that standby ZSK did not sign ($n)"
+ret=0
+grep " $standby"'$' sigs > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that inactive key did not sign ($n)"
+ret=0
+grep " $inact"'$' sigs > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that pending key was not published ($n)"
+ret=0
+grep " $pending"'$' keys > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that standby KSK did not sign but is delegated ($n)"
+ret=0
+grep " $rolling"'$' sigs > /dev/null && ret=1
+grep " $rolling"'$' keys > /dev/null || ret=1
+grep -E "DS[ ]*$rolling[ ]" ${pfile}.signed > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that key was revoked ($n)"
+ret=0
+grep " $prerev"'$' keys > /dev/null && ret=1
+grep " $postrev"'$' keys > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that revoked key self-signed ($n)"
+ret=0
+grep "DNSKEY $postrev"'$' sigs > /dev/null || ret=1
+grep "SOA $postrev"'$' sigs > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "waiting 20 seconds for key changes to occur"
+sleep 20
+
+echo_i "re-signing zone"
+$SIGNER -Sg -o $czone -f ${cfile}.new ${cfile}.signed > /dev/null
+
+echo_i "checking that standby KSK is now active ($n)"
+ret=0
+grep "DNSKEY $rolling"'$' sigs > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking update of an old-style key ($n)"
+ret=0
+# printing metadata should not work with an old-style key
+$SETTIME -pall $(cat oldstyle.key) > /dev/null 2>&1 && ret=1
+$SETTIME -f $(cat oldstyle.key) > /dev/null 2>&1 || ret=1
+# but now it should
+$SETTIME -pall $(cat oldstyle.key) > /dev/null 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking warning about permissions change on key with dnssec-settime ($n)"
+ret=0
+# settime should print a warning about changing the permissions
+chmod 644 $(cat oldstyle.key).private
+$SETTIME -P none $(cat oldstyle.key) > settime1.test$n 2>&1 || ret=1
+grep "warning: Permissions on the file.*have changed" settime1.test$n > /dev/null 2>&1 || ret=1
+$SETTIME -P none $(cat oldstyle.key) > settime2.test$n 2>&1 || ret=1
+grep "warning: Permissions on the file.*have changed" settime2.test$n > /dev/null 2>&1 && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking warning about delete date < inactive date with dnssec-settime ($n)"
+ret=0
+# settime should print a warning about delete < inactive
+$SETTIME -I now+15s -D now $(cat oldstyle.key) > tmp.out 2>&1 || ret=1
+grep "warning" tmp.out > /dev/null 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking no warning about delete date < inactive date with dnssec-settime when delete date is unset ($n)"
+ret=0
+$SETTIME -D none $(cat oldstyle.key) > tmp.out 2>&1 || ret=1
+$SETTIME -p all $(cat oldstyle.key) > tmp.out 2>&1 || ret=1
+grep "warning" tmp.out > /dev/null 2>&1 && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking warning about delete date < inactive date with dnssec-keygen ($n)"
+ret=0
+# keygen should print a warning about delete < inactive
+$KEYGEN -q -a ${DEFAULT_ALGORITHM} -I now+15s -D now $czone > tmp.out 2>&1 || ret=1
+grep "warning" tmp.out > /dev/null 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking correct behavior setting activation without publication date ($n)"
+ret=0
+key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -A +1w $czone)
+pub=$($SETTIME -upP $key | awk '{print $2}')
+act=$($SETTIME -upA $key | awk '{print $2}')
+[ $pub -eq $act ] || ret=1
+key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -A +1w -i 1d $czone)
+pub=$($SETTIME -upP $key | awk '{print $2}')
+act=$($SETTIME -upA $key | awk '{print $2}')
+[ $pub -lt $act ] || ret=1
+key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -A +1w -P never $czone)
+pub=$($SETTIME -upP $key | awk '{print $2}')
+[ $pub = "UNSET" ] || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking calculation of dates for a successor key ($n)"
+ret=0
+oldkey=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $czone)
+newkey=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $czone)
+$SETTIME -A -2d -I +2d $oldkey > settime1.test$n 2>&1 || ret=1
+$SETTIME -i 1d -S $oldkey $newkey > settime2.test$n 2>&1 || ret=1
+$SETTIME -pA $newkey | grep "1970" > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $czone)
+
+echo_i "checking -p output time is accepted ($n)"
+t=$($SETTIME -pA $key | sed 's/.*: //')
+$SETTIME -Psync "$t" $key > settime2.test$n 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking -up output time is accepted ($n)"
+t=$($SETTIME -upA $key | sed 's/.*: //')
+$SETTIME -Dsync "$t" $key > settime2.test$n 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking -p unset time is accepted ($n)"
+# The Delete timing metadata is unset.
+t=$($SETTIME -pD $key | sed 's/.*: //')
+$SETTIME -Psync "$t" $key > settime2.test$n 2>&1 || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/metadata/tests_sh_metadata.py b/bin/tests/system/metadata/tests_sh_metadata.py
new file mode 100644
index 0000000..4843288
--- /dev/null
+++ b/bin/tests/system/metadata/tests_sh_metadata.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_metadata(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/mirror/README b/bin/tests/system/mirror/README
new file mode 100644
index 0000000..f76b41b
--- /dev/null
+++ b/bin/tests/system/mirror/README
@@ -0,0 +1,26 @@
+<!--
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+-->
+
+This test checks whether zones configured with "type mirror;" behave as
+expected.
+
+ns1 is an authoritative-only server. It only serves the root zone, which is
+mirrored by ns3.
+
+ns2 is an authoritative-only server. It serves a number of zones, some of which
+are delegated to it by ns1 and used in recursive resolution tests aimed at ns3
+while others are only served so that ns3 has a primary server to mirror zones
+from during various tests of the mirror zone implementation.
+
+ns3 is a recursive resolver. It has a number of mirror zones configured. This
+is the only server whose behavior is being examined by this system test.
diff --git a/bin/tests/system/mirror/clean.sh b/bin/tests/system/mirror/clean.sh
new file mode 100644
index 0000000..2e02183
--- /dev/null
+++ b/bin/tests/system/mirror/clean.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */*.conf
+rm -f */*.db
+rm -f */*.jnl
+rm -f */*.mirror
+rm -f */*.nzd*
+rm -f */*.prev
+rm -f */*.signed
+rm -f */K*
+rm -f */db-*
+rm -f */dsset-*
+rm -f */jn-*
+rm -f */_default.nzf
+rm -f */managed-keys.bind*
+rm -f */named.memstats
+rm -f */named.run
+rm -f dig.out.*
+rm -f rndc.out.*
diff --git a/bin/tests/system/mirror/ns1/named.conf.in b/bin/tests/system/mirror/ns1/named.conf.in
new file mode 100644
index 0000000..22173f7
--- /dev/null
+++ b/bin/tests/system/mirror/ns1/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
diff --git a/bin/tests/system/mirror/ns1/root.db.in b/bin/tests/system/mirror/ns1/root.db.in
new file mode 100644
index 0000000..98ecf1f
--- /dev/null
+++ b/bin/tests/system/mirror/ns1/root.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA a.root-servers.nil. hostmaster 1 3600 1200 604800 3600
+@ NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+example NS ns2.example.
+ns2.example. A 10.53.0.2
+initially-unavailable. NS ns2.initially-unavailable.
+ns2.initially-unavailable. A 10.53.0.2
diff --git a/bin/tests/system/mirror/ns1/sign.sh b/bin/tests/system/mirror/ns1/sign.sh
new file mode 100644
index 0000000..ab613d5
--- /dev/null
+++ b/bin/tests/system/mirror/ns1/sign.sh
@@ -0,0 +1,37 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+( cd ../ns2 && $SHELL -e sign.sh )
+
+cp ../ns2/dsset-* .
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+keyname1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -f KSK $zone 2> /dev/null)
+keyname2=$($KEYGEN -a ${DEFAULT_ALGORITHM} $zone 2> /dev/null)
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -P -g -o $zone $zonefile > /dev/null
+
+# Add a trust anchor for a name whose non-existence can be securely proved
+# without recursing when the root zone is mirrored. This will exercise code
+# attempting to send TAT queries for such names (in ns3). Key data is
+# irrelevant here, so just reuse the root zone key generated above.
+sed "s/^\./nonexistent./;" $keyname1.key > $keyname1.modified.key
+
+keyfile_to_static_ds $keyname1 $keyname1.modified > trusted.conf
diff --git a/bin/tests/system/mirror/ns2/example.db.in b/bin/tests/system/mirror/ns2/example.db.in
new file mode 100644
index 0000000..5472399
--- /dev/null
+++ b/bin/tests/system/mirror/ns2/example.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2 hostmaster 1 3600 1200 604800 3600
+@ NS ns2
+ns2 A 10.53.0.2
+foo A 127.0.0.1
+sub NS ns2
diff --git a/bin/tests/system/mirror/ns2/initially-unavailable.db.in b/bin/tests/system/mirror/ns2/initially-unavailable.db.in
new file mode 100644
index 0000000..cf809e3
--- /dev/null
+++ b/bin/tests/system/mirror/ns2/initially-unavailable.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA a.root-servers.nil. hostmaster 1 3600 1200 604800 3600
+@ NS ns2
+ns2 A 10.53.0.2
+foo CNAME foo.example.
diff --git a/bin/tests/system/mirror/ns2/named.conf.in b/bin/tests/system/mirror/ns2/named.conf.in
new file mode 100644
index 0000000..7eaed5b
--- /dev/null
+++ b/bin/tests/system/mirror/ns2/named.conf.in
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "example" {
+ type primary;
+ file "example.db.signed";
+};
+
+zone "sub.example" {
+ type primary;
+ file "sub.example.db.signed";
+};
+
+zone "initially-unavailable" {
+ type primary;
+ file "initially-unavailable.db.signed";
+ allow-transfer { 10.53.0.254; };
+};
+
+zone "verify-addzone" {
+ type primary;
+ file "verify-addzone.db.original.signed";
+};
+
+zone "verify-axfr" {
+ type primary;
+ file "verify-axfr.db.signed";
+};
+
+zone "verify-csk" {
+ type primary;
+ file "verify-csk.db.signed";
+};
+
+zone "verify-ixfr" {
+ type primary;
+ file "verify-ixfr.db.signed";
+ ixfr-from-differences yes;
+ allow-transfer { 10.53.0.3; };
+};
+
+zone "verify-reconfig" {
+ type primary;
+ file "verify-reconfig.db.signed";
+};
+
+zone "verify-unsigned" {
+ type primary;
+ file "verify.db.in";
+};
+
+zone "verify-untrusted" {
+ type primary;
+ file "verify-untrusted.db.signed";
+};
diff --git a/bin/tests/system/mirror/ns2/sign.sh b/bin/tests/system/mirror/ns2/sign.sh
new file mode 100644
index 0000000..519fd83
--- /dev/null
+++ b/bin/tests/system/mirror/ns2/sign.sh
@@ -0,0 +1,79 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+keys_to_trust=""
+
+for zonename in sub.example example initially-unavailable; do
+ zone=$zonename
+ infile=$zonename.db.in
+ zonefile=$zonename.db
+
+ keyname1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -f KSK $zone 2> /dev/null)
+ keyname2=$($KEYGEN -a ${DEFAULT_ALGORITHM} $zone 2> /dev/null)
+
+ cat $infile $keyname1.key $keyname2.key > $zonefile
+
+ $SIGNER -P -g -o $zone $zonefile > /dev/null
+done
+
+# Only add the key for "initially-unavailable" to the list of keys trusted by
+# ns3. "example" is expected to be validated using a chain of trust starting in
+# the "root" zone on ns1.
+keys_to_trust="$keys_to_trust $keyname1"
+
+# Prepare a zone signed using a Combined Signing Key (CSK) without the SEP bit
+# set and add that key to the list of keys to trust.
+zone=verify-csk
+infile=verify.db.in
+zonefile=verify-csk.db
+
+keyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} $zone 2> /dev/null)
+cat $infile $keyname.key > $zonefile
+$SIGNER -P -o $zone $zonefile > /dev/null
+keys_to_trust="$keys_to_trust $keyname"
+
+# Prepare remaining zones used in the test.
+ORIGINAL_SERIAL=$(awk '$2 == "SOA" {print $5}' verify.db.in)
+UPDATED_SERIAL_BAD=$((ORIGINAL_SERIAL + 1))
+UPDATED_SERIAL_GOOD=$((ORIGINAL_SERIAL + 2))
+
+for variant in addzone axfr ixfr load reconfig untrusted; do
+ zone=verify-$variant
+ infile=verify.db.in
+ zonefile=verify-$variant.db
+
+ keyname1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -f KSK $zone 2> /dev/null)
+ keyname2=$($KEYGEN -a ${DEFAULT_ALGORITHM} $zone 2> /dev/null)
+
+ cat $infile $keyname1.key $keyname2.key > $zonefile
+
+ # Prepare a properly signed version of the zone ("*.original.signed").
+ $SIGNER -P -o $zone $zonefile > /dev/null
+ cp $zonefile.signed $zonefile.original.signed
+ # Prepare a version of the zone with a bogus SOA RRSIG ("*.bad.signed").
+ sed "s/${ORIGINAL_SERIAL}/${UPDATED_SERIAL_BAD}/;" $zonefile.signed > $zonefile.bad.signed
+ # Prepare another properly signed version of the zone ("*.good.signed").
+ sed "s/${ORIGINAL_SERIAL}/${UPDATED_SERIAL_GOOD}/;" $zonefile > $zonefile.good
+ $SIGNER -P -o $zone $zonefile.good > /dev/null
+ rm -f $zonefile.good
+
+ # Except for the "verify-untrusted" zone, declare the KSK used for
+ # signing the zone to be a trust anchor for ns3.
+ if [ "$variant" != "untrusted" ]; then
+ keys_to_trust="$keys_to_trust $keyname1"
+ fi
+done
+
+keyfile_to_static_ds $keys_to_trust > trusted-mirror.conf
diff --git a/bin/tests/system/mirror/ns2/sub.example.db.in b/bin/tests/system/mirror/ns2/sub.example.db.in
new file mode 100644
index 0000000..d2c15c7
--- /dev/null
+++ b/bin/tests/system/mirror/ns2/sub.example.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2.example. hostmaster 1 3600 1200 604800 3600
+@ NS ns2.example.
+foo A 127.0.0.1
diff --git a/bin/tests/system/mirror/ns2/verify.db.in b/bin/tests/system/mirror/ns2/verify.db.in
new file mode 100644
index 0000000..b3ed22a
--- /dev/null
+++ b/bin/tests/system/mirror/ns2/verify.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2 hostmaster 2000010100 3600 1200 604800 3600
+@ NS ns2
+ns2 A 10.53.0.2
diff --git a/bin/tests/system/mirror/ns3/named.args b/bin/tests/system/mirror/ns3/named.args
new file mode 100644
index 0000000..78f3feb
--- /dev/null
+++ b/bin/tests/system/mirror/ns3/named.args
@@ -0,0 +1 @@
+-D mirror-ns3 -X named.lock -m record -c named.conf -d 99 -g -U 4 -T maxcachesize=2097152 -T tat=3
diff --git a/bin/tests/system/mirror/ns3/named.conf.in b/bin/tests/system/mirror/ns3/named.conf.in
new file mode 100644
index 0000000..b644f45
--- /dev/null
+++ b/bin/tests/system/mirror/ns3/named.conf.in
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ allow-query-cache { 10.53.0.1; };
+ trust-anchor-telemetry yes;
+ allow-new-zones yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "." {
+ type mirror;
+ primaries { 10.53.0.1; };
+ file "root.db.mirror";
+};
+
+zone "initially-unavailable" {
+ type mirror;
+ primaries { 10.53.0.2; };
+ file "initially-unavailable.db.mirror";
+ use-alt-transfer-source no;
+};
+
+zone "verify-axfr" {
+ type mirror;
+ primaries { 10.53.0.2; };
+ file "verify-axfr.db.mirror";
+};
+
+zone "verify-csk" {
+ type mirror;
+ primaries { 10.53.0.2; };
+ file "verify-csk.db.mirror";
+};
+
+zone "verify-ixfr" {
+ type mirror;
+ primaries { 10.53.0.2; };
+ file "verify-ixfr.db.mirror";
+ masterfile-format text;
+};
+
+zone "verify-load" {
+ type mirror;
+ primaries { 10.53.0.2; };
+ file "verify-load.db.mirror";
+ masterfile-format text;
+};
+
+zone "verify-reconfig" {
+ type mirror;
+ primaries { 10.53.0.2; };
+ file "verify-reconfig.db.mirror";
+ masterfile-format text;
+};
+
+zone "verify-unsigned" {
+ type mirror;
+ primaries { 10.53.0.2; };
+ file "verify-unsigned.db.mirror";
+};
+
+zone "verify-untrusted" {
+ type mirror;
+ primaries { 10.53.0.2; };
+ file "verify-untrusted.db.mirror";
+};
+
+include "../ns1/trusted.conf";
+include "../ns2/trusted-mirror.conf";
diff --git a/bin/tests/system/mirror/setup.sh b/bin/tests/system/mirror/setup.sh
new file mode 100644
index 0000000..b80e797
--- /dev/null
+++ b/bin/tests/system/mirror/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+
+( cd ns1 && $SHELL -e sign.sh )
+
+cat ns2/verify-axfr.db.bad.signed > ns2/verify-axfr.db.signed
+cat ns2/verify-load.db.bad.signed > ns3/verify-load.db.mirror
diff --git a/bin/tests/system/mirror/tests.sh b/bin/tests/system/mirror/tests.sh
new file mode 100644
index 0000000..dc6cffa
--- /dev/null
+++ b/bin/tests/system/mirror/tests.sh
@@ -0,0 +1,558 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT} -b 10.53.0.1 +dnssec +time=2 +tries=1 +multi"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+# Wait until the transfer of the given zone to ns3 either completes
+# successfully or is aborted by a verification failure or a REFUSED response
+# from the primary. Note that matching on any transfer status is deliberately
+# avoided because some checks performed by this test cause transfer attempts to
+# end with the "IXFR failed" status, which is followed by an AXFR retry and
+# this test needs to check what the result of the latter transfer attempt is.
+wait_for_transfer() {
+ zone=$1
+ for i in 1 2 3 4 5 6 7 8 9 10; do
+ # Wait until a "freeing transfer context" message is logged
+ # after one of the transfer results we are looking for is
+ # logged. This is needed to prevent races when checking for
+ # "mirror zone is now in use" messages.
+ nextpartpeek ns3/named.run | \
+ awk "matched; /'$zone\/IN'.*Transfer status: (success|verify failure|REFUSED)/ {matched=1}" | \
+ grep "'$zone/IN'.*freeing transfer context" > /dev/null && return
+ sleep 1
+ done
+ echo_i "exceeded time limit waiting for proof of '$zone' being transferred to appear in ns3/named.run"
+ ret=1
+}
+
+# Wait until loading the given zone on the given server either completes
+# successfully for the specified serial number or fails.
+wait_for_load() {
+ zone=$1
+ serial=$2
+ log=$3
+ for i in 1 2 3 4 5 6 7 8 9 10; do
+ # Wait until a "zone_postload: (...): done" message is logged
+ # after one of the loading-related messages we are looking for
+ # is logged. This is needed to prevent races when checking for
+ # "mirror zone is now in use" messages.
+ nextpartpeek $log | \
+ awk "matched; /$zone.*(loaded serial $serial|unable to load)/ {matched=1}" | \
+ grep "zone_postload: zone $zone/IN: done" > /dev/null && return
+ sleep 1
+ done
+ echo_i "exceeded time limit waiting for proof of '$zone' being loaded to appear in $log"
+ ret=1
+}
+
+# Trigger a reload of ns2 and wait until loading the given zone completes.
+reload_zone() {
+ zone=$1
+ serial=$2
+ rndc_reload ns2 10.53.0.2
+ wait_for_load $zone $serial ns2/named.run
+}
+
+status=0
+n=0
+
+ORIGINAL_SERIAL=$(awk '$2 == "SOA" {print $5}' ns2/verify.db.in)
+UPDATED_SERIAL_BAD=$((ORIGINAL_SERIAL + 1))
+UPDATED_SERIAL_GOOD=$((ORIGINAL_SERIAL + 2))
+
+n=$((n + 1))
+echo_i "checking that an unsigned mirror zone is rejected ($n)"
+ret=0
+wait_for_transfer verify-unsigned
+$DIG $DIGOPTS @10.53.0.3 +norec verify-unsigned SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "${ORIGINAL_SERIAL}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1
+nextpartpeek ns3/named.run | grep "verify-unsigned.*Zone contains no DNSSEC keys" > /dev/null || ret=1
+nextpartpeek ns3/named.run | grep "verify-unsigned.*mirror zone is now in use" > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that a mirror zone signed using an untrusted key is rejected ($n)"
+ret=0
+nextpartreset ns3/named.run
+wait_for_transfer verify-untrusted
+$DIG $DIGOPTS @10.53.0.3 +norec verify-untrusted SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "${ORIGINAL_SERIAL}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1
+nextpartpeek ns3/named.run | grep "verify-untrusted.*No trusted DNSKEY found" > /dev/null || ret=1
+nextpartpeek ns3/named.run | grep "verify-untrusted.*mirror zone is now in use" > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that a mirror zone signed using a CSK without the SEP bit set is accepted ($n)"
+ret=0
+nextpartreset ns3/named.run
+wait_for_transfer verify-csk
+$DIG $DIGOPTS @10.53.0.3 +norec verify-csk SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1
+grep "${ORIGINAL_SERIAL}.*; serial" dig.out.ns3.test$n > /dev/null || ret=1
+nextpartpeek ns3/named.run | grep "verify-csk.*mirror zone is now in use" > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that an AXFR of an incorrectly signed mirror zone is rejected ($n)"
+ret=0
+nextpartreset ns3/named.run
+wait_for_transfer verify-axfr
+$DIG $DIGOPTS @10.53.0.3 +norec verify-axfr SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1
+nextpartpeek ns3/named.run | grep "No correct ${DEFAULT_ALGORITHM} signature for verify-axfr SOA" > /dev/null || ret=1
+nextpartpeek ns3/named.run | grep "verify-axfr.*mirror zone is now in use" > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that an AXFR of an updated, correctly signed mirror zone is accepted ($n)"
+ret=0
+nextpart ns3/named.run > /dev/null
+cat ns2/verify-axfr.db.good.signed > ns2/verify-axfr.db.signed
+reload_zone verify-axfr ${UPDATED_SERIAL_GOOD}
+$RNDCCMD 10.53.0.3 retransfer verify-axfr > /dev/null 2>&1
+wait_for_transfer verify-axfr
+$DIG $DIGOPTS @10.53.0.3 +norec verify-axfr SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1
+grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n > /dev/null || ret=1
+nextpartpeek ns3/named.run | grep "verify-axfr.*mirror zone is now in use" > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that an IXFR of an incorrectly signed mirror zone is rejected ($n)"
+nextpartreset ns3/named.run
+ret=0
+wait_for_transfer verify-ixfr
+# Sanity check: the initial, properly signed version of the zone should have
+# been announced as coming into effect.
+nextpart ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" > /dev/null || ret=1
+# Make a copy of the original zone file for reuse in journal tests below.
+cp ns2/verify-ixfr.db.signed ns3/verify-journal.db.mirror
+# Wait 1 second so that the zone file timestamp changes and the subsequent
+# invocation of "rndc reload" triggers a zone reload.
+sleep 1
+cat ns2/verify-ixfr.db.bad.signed > ns2/verify-ixfr.db.signed
+reload_zone verify-ixfr ${UPDATED_SERIAL_BAD}
+# Make a copy of the bad zone journal for reuse in journal tests below.
+cp ns2/verify-ixfr.db.signed.jnl ns3/verify-journal.db.bad.mirror.jnl
+# Trigger IXFR.
+$RNDCCMD 10.53.0.3 refresh verify-ixfr > /dev/null 2>&1
+wait_for_transfer verify-ixfr
+# Ensure the transfer was incremental as expected.
+if [ $(nextpartpeek ns3/named.run | grep "verify-ixfr.*got incremental response" | wc -l) -eq 0 ]; then
+ echo_i "failed: did not get an incremental response"
+ ret=1
+fi
+# Ensure the new, bad version of the zone was not accepted.
+$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA > dig.out.ns3.test$n 2>&1 || ret=1
+# A positive answer is expected as the original version of the "verify-ixfr"
+# zone should have been successfully verified.
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1
+grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1
+nextpartpeek ns3/named.run | grep "No correct ${DEFAULT_ALGORITHM} signature for verify-ixfr SOA" > /dev/null || ret=1
+# Despite the verification failure for this IXFR, this mirror zone should still
+# be in use as its previous version should have been verified successfully.
+nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is no longer in use" > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that an IXFR of an updated, correctly signed mirror zone is accepted after AXFR failover ($n)"
+ret=0
+nextpart ns3/named.run > /dev/null
+# Wait 1 second so that the zone file timestamp changes and the subsequent
+# invocation of "rndc reload" triggers a zone reload.
+sleep 1
+cat ns2/verify-ixfr.db.good.signed > ns2/verify-ixfr.db.signed
+reload_zone verify-ixfr ${UPDATED_SERIAL_GOOD}
+# Make a copy of the good zone journal for reuse in journal tests below.
+cp ns2/verify-ixfr.db.signed.jnl ns3/verify-journal.db.good.mirror.jnl
+# Trigger IXFR.
+$RNDCCMD 10.53.0.3 refresh verify-ixfr > /dev/null 2>&1
+wait_for_transfer verify-ixfr
+# Ensure the new, good version of the zone was accepted.
+$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1
+grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n > /dev/null || ret=1
+# The log message announcing the mirror zone coming into effect should not have
+# been logged this time since the mirror zone in question is expected to
+# already be in use before this test case is checked.
+nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that loading an incorrectly signed mirror zone from disk fails ($n)"
+ret=0
+nextpartreset ns3/named.run
+wait_for_load verify-load ${UPDATED_SERIAL_BAD} ns3/named.run
+$DIG $DIGOPTS @10.53.0.3 +norec verify-load SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1
+nextpartpeek ns3/named.run | grep "No correct ${DEFAULT_ALGORITHM} signature for verify-load SOA" > /dev/null || ret=1
+nextpartpeek ns3/named.run | grep "verify-load.*mirror zone is now in use" > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "ensuring trust anchor telemetry queries are sent upstream for a mirror zone ($n)"
+ret=0
+# ns3 is started with "-T tat=3", so TAT queries should have already been sent.
+grep "_ta-[-0-9a-f]*/NULL" ns1/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that loading a correctly signed mirror zone from disk succeeds ($n)"
+ret=0
+stop_server --use-rndc --port ${CONTROLPORT} ns3
+cat ns2/verify-load.db.good.signed > ns3/verify-load.db.mirror
+nextpart ns3/named.run > /dev/null
+start_server --noclean --restart --port ${PORT} ns3
+wait_for_load verify-load ${UPDATED_SERIAL_GOOD} ns3/named.run
+$DIG $DIGOPTS @10.53.0.3 +norec verify-load SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1
+grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n > /dev/null || ret=1
+nextpartpeek ns3/named.run | grep "verify-load.*mirror zone is now in use" > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that loading a journal for an incorrectly signed mirror zone fails ($n)"
+ret=0
+stop_server --use-rndc --port ${CONTROLPORT} ns3
+cp ns3/verify-journal.db.mirror ns3/verify-ixfr.db.mirror
+cp ns3/verify-journal.db.bad.mirror.jnl ns3/verify-ixfr.db.mirror.jnl
+# Temporarily disable transfers of the "verify-ixfr" zone on ns2. This is
+# required to reliably test whether the message announcing the mirror zone
+# coming into effect is not logged after a failed journal verification since
+# otherwise a corrected version of the zone may be transferred after
+# verification fails but before we look for the aforementioned log message.
+# (NOTE: Keep the embedded newline in the sed function list below.)
+sed '/^zone "verify-ixfr" {$/,/^};$/ {
+ s/10.53.0.3/10.53.0.254/
+}' ns2/named.conf > ns2/named.conf.modified
+mv ns2/named.conf.modified ns2/named.conf
+rndc_reconfig ns2 10.53.0.2
+nextpart ns3/named.run > /dev/null
+start_server --noclean --restart --port ${PORT} ns3
+wait_for_load verify-ixfr ${UPDATED_SERIAL_BAD} ns3/named.run
+$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1
+nextpartpeek ns3/named.run | grep "No correct ${DEFAULT_ALGORITHM} signature for verify-ixfr SOA" > /dev/null || ret=1
+nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" > /dev/null && ret=1
+# Restore transfers for the "verify-ixfr" zone on ns2.
+# (NOTE: Keep the embedded newline in the sed function list below.)
+sed '/^zone "verify-ixfr" {$/,/^};$/ {
+ s/10.53.0.254/10.53.0.3/
+}' ns2/named.conf > ns2/named.conf.modified
+mv ns2/named.conf.modified ns2/named.conf
+rndc_reconfig ns2 10.53.0.2
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that loading a journal for a correctly signed mirror zone succeeds ($n)"
+ret=0
+stop_server --use-rndc --port ${CONTROLPORT} ns3
+cp ns3/verify-journal.db.mirror ns3/verify-ixfr.db.mirror
+cp ns3/verify-journal.db.good.mirror.jnl ns3/verify-ixfr.db.mirror.jnl
+nextpart ns3/named.run > /dev/null
+start_server --noclean --restart --port ${PORT} ns3
+wait_for_load verify-ixfr ${UPDATED_SERIAL_GOOD} ns3/named.run
+$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1
+grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n > /dev/null || ret=1
+nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking delegations sourced from a mirror zone ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 foo.example A +norec > dig.out.ns3.test$n 2>&1 || ret=1
+# Check response code and flags in the answer.
+grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.* ad" dig.out.ns3.test$n > /dev/null && ret=1
+# Check that a delegation containing a DS RRset and glue is present.
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1
+grep "example.*IN.*NS" dig.out.ns3.test$n > /dev/null || ret=1
+grep "example.*IN.*DS" dig.out.ns3.test$n > /dev/null || ret=1
+grep "ns2.example.*A.*10.53.0.2" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that resolution involving a mirror zone works as expected ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 foo.example A > dig.out.ns3.test$n 2>&1 || ret=1
+# Check response code and flags in the answer.
+grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1
+# Ensure ns1 was not queried.
+grep "query 'foo.example/A/IN'" ns1/named.run > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that non-recursive queries for names below mirror zone get responded from cache ($n)"
+ret=0
+# Issue a non-recursive query for an RRset which is expected to be in cache.
+$DIG $DIGOPTS @10.53.0.3 +norec foo.example. A > dig.out.ns3.test$n 2>&1 || ret=1
+# Check response code and flags in the answer.
+grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1
+# Ensure the response is not a delegation.
+grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1
+grep "foo.example.*IN.*A.*127.0.0.1" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that delegations from cache which improve mirror zone delegations are properly handled ($n)"
+ret=0
+# First, issue a recursive query in order to cache an RRset which is not within
+# the mirror zone's bailiwick.
+$DIG $DIGOPTS @10.53.0.3 sub.example. NS > dig.out.ns3.test$n.1 2>&1 || ret=1
+# Ensure the child-side NS RRset is returned.
+grep "NOERROR" dig.out.ns3.test$n.1 > /dev/null || ret=1
+grep "ANSWER: 2" dig.out.ns3.test$n.1 > /dev/null || ret=1
+grep "sub.example.*IN.*NS" dig.out.ns3.test$n.1 > /dev/null || ret=1
+# Issue a non-recursive query for something below the cached zone cut.
+$DIG $DIGOPTS @10.53.0.3 +norec foo.sub.example. A > dig.out.ns3.test$n.2 2>&1 || ret=1
+# Ensure the cached NS RRset is returned in a delegation, along with the
+# parent-side DS RRset.
+grep "NOERROR" dig.out.ns3.test$n.2 > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns3.test$n.2 > /dev/null || ret=1
+grep "sub.example.*IN.*NS" dig.out.ns3.test$n.2 > /dev/null || ret=1
+grep "sub.example.*IN.*DS" dig.out.ns3.test$n.2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking flags set in a DNSKEY response sourced from a mirror zone ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 . DNSKEY > dig.out.ns3.test$n 2>&1 || ret=1
+# Check response code and flags in the answer.
+grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.* aa" dig.out.ns3.test$n > /dev/null && ret=1
+grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking flags set in a SOA response sourced from a mirror zone ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 . SOA > dig.out.ns3.test$n 2>&1 || ret=1
+# Check response code and flags in the answer.
+grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.* aa" dig.out.ns3.test$n > /dev/null && ret=1
+grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that resolution succeeds with unavailable mirror zone data ($n)"
+ret=0
+wait_for_transfer initially-unavailable
+# Query for a record in a zone that is set up to be mirrored, but
+# untransferrable from the configured primary. Resolution should still succeed.
+$DIG $DIGOPTS @10.53.0.3 foo.initially-unavailable. A > dig.out.ns3.test$n.1 2>&1 || ret=1
+# Check response code and flags in the answer.
+grep "NOERROR" dig.out.ns3.test$n.1 > /dev/null || ret=1
+grep "flags:.* ad" dig.out.ns3.test$n.1 > /dev/null || ret=1
+# Sanity check: the authoritative server should have been queried.
+nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" > /dev/null || ret=1
+# Reconfigure ns2 so that the zone can be mirrored on ns3.
+sed '/^zone "initially-unavailable" {$/,/^};$/ {
+ s/10.53.0.254/10.53.0.3/
+}' ns2/named.conf > ns2/named.conf.modified
+mv ns2/named.conf.modified ns2/named.conf
+rndc_reconfig ns2 10.53.0.2
+# Flush the cache on ns3 and retransfer the mirror zone.
+$RNDCCMD 10.53.0.3 flush > /dev/null 2>&1
+nextpart ns3/named.run > /dev/null
+$RNDCCMD 10.53.0.3 retransfer initially-unavailable > /dev/null 2>&1
+wait_for_transfer initially-unavailable
+# Query for the same record again. Resolution should still succeed.
+$DIG $DIGOPTS @10.53.0.3 foo.initially-unavailable. A > dig.out.ns3.test$n.2 2>&1 || ret=1
+# Check response code and flags in the answer.
+grep "NOERROR" dig.out.ns3.test$n.2 > /dev/null || ret=1
+grep "flags:.* ad" dig.out.ns3.test$n.2 > /dev/null || ret=1
+# Ensure the authoritative server was not queried.
+nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that resolution succeeds with expired mirror zone data ($n)"
+ret=0
+# Reconfigure ns2 so that the zone from the previous test can no longer be
+# mirrored on ns3.
+sed '/^zone "initially-unavailable" {$/,/^};$/ {
+ s/10.53.0.3/10.53.0.254/
+}' ns2/named.conf > ns2/named.conf.modified
+mv ns2/named.conf.modified ns2/named.conf
+rndc_reconfig ns2 10.53.0.2
+# Stop ns3, update the timestamp of the zone file to one far in the past, then
+# restart ns3.
+stop_server --use-rndc --port ${CONTROLPORT} ns3
+touch -t 200001010000 ns3/initially-unavailable.db.mirror
+nextpart ns3/named.run > /dev/null
+start_server --noclean --restart --port ${PORT} ns3
+# Ensure named attempts to retransfer the zone due to its expiry.
+wait_for_transfer initially-unavailable
+# Ensure the expected messages were logged.
+nextpartpeek ns3/named.run | grep "initially-unavailable.*expired" > /dev/null || ret=1
+nextpartpeek ns3/named.run | grep "initially-unavailable.*mirror zone is no longer in use" > /dev/null || ret=1
+# Query for a record in the expired zone. Resolution should still succeed.
+$DIG $DIGOPTS @10.53.0.3 foo.initially-unavailable. A > dig.out.ns3.test$n 2>&1 || ret=1
+# Check response code and flags in the answer.
+grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1
+# Sanity check: the authoritative server should have been queried.
+nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that clients without cache access cannot retrieve mirror zone data ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 -b 10.53.0.3 +norec . SOA > dig.out.ns3.test$n 2>&1 || ret=1
+# Check response code and flags in the answer.
+grep "REFUSED" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.* ad" dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that outgoing transfers of mirror zones are disabled by default ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 . AXFR > dig.out.ns3.test$n 2>&1 || ret=1
+grep "; Transfer failed" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that notifies are disabled by default for mirror zones ($n)"
+ret=0
+grep "initially-unavailable.*sending notifies" ns3/named.run > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking output of \"rndc zonestatus\" for a mirror zone ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 zonestatus . > rndc.out.ns3.test$n 2>&1
+grep "type: mirror" rndc.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that \"rndc reconfig\" properly handles a mirror -> secondary zone type change ($n)"
+ret=0
+# Sanity check before we start.
+$DIG $DIGOPTS @10.53.0.3 +norec verify-reconfig SOA > dig.out.ns3.test$n.1 2>&1 || ret=1
+grep "NOERROR" dig.out.ns3.test$n.1 > /dev/null || ret=1
+grep "flags:.* aa" dig.out.ns3.test$n.1 > /dev/null && ret=1
+grep "flags:.* ad" dig.out.ns3.test$n.1 > /dev/null || ret=1
+# Reconfigure the zone so that it is no longer a mirror zone.
+# (NOTE: Keep the embedded newline in the sed function list below.)
+sed '/^zone "verify-reconfig" {$/,/^};$/ {
+ s/type mirror;/type secondary;/
+}' ns3/named.conf > ns3/named.conf.modified
+mv ns3/named.conf.modified ns3/named.conf
+nextpart ns3/named.run > /dev/null
+rndc_reconfig ns3 10.53.0.3
+# Zones whose type was changed should not be reusable, which means the tested
+# zone should have been reloaded from disk.
+wait_for_load verify-reconfig ${ORIGINAL_SERIAL} ns3/named.run
+# Ensure responses sourced from the reconfigured zone have AA=1 and AD=0.
+$DIG $DIGOPTS @10.53.0.3 +norec verify-reconfig SOA > dig.out.ns3.test$n.2 2>&1 || ret=1
+grep "NOERROR" dig.out.ns3.test$n.2 > /dev/null || ret=1
+grep "flags:.* aa" dig.out.ns3.test$n.2 > /dev/null || ret=1
+grep "flags:.* ad" dig.out.ns3.test$n.2 > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that \"rndc reconfig\" properly handles a secondary -> mirror zone type change ($n)"
+ret=0
+# Put an incorrectly signed version of the zone in the zone file used by ns3.
+nextpart ns3/named.run > /dev/null
+cat ns2/verify-reconfig.db.bad.signed > ns3/verify-reconfig.db.mirror
+# Reconfigure the zone so that it is a mirror zone again.
+# (NOTE: Keep the embedded newline in the sed function list below.)
+sed '/^zone "verify-reconfig" {$/,/^};$/ {
+ s/type secondary;/type mirror;/
+}' ns3/named.conf > ns3/named.conf.modified
+mv ns3/named.conf.modified ns3/named.conf
+rndc_reconfig ns3 10.53.0.3
+# The reconfigured zone should fail verification.
+wait_for_load verify-reconfig ${UPDATED_SERIAL_BAD} ns3/named.run
+$DIG $DIGOPTS @10.53.0.3 +norec verify-reconfig SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1
+nextpart ns3/named.run | grep "No correct ${DEFAULT_ALGORITHM} signature for verify-reconfig SOA" > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that a mirror zone can be added using rndc ($n)"
+ret=0
+# Sanity check: the zone should not exist in the root zone.
+$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA > dig.out.ns3.test$n.1 2>&1 || ret=1
+grep "NXDOMAIN" dig.out.ns3.test$n.1 > /dev/null || ret=1
+grep "flags:.* aa" dig.out.ns3.test$n.1 > /dev/null && ret=1
+grep "flags:.* ad" dig.out.ns3.test$n.1 > /dev/null || ret=1
+# Mirror a zone which does not exist in the root zone.
+nextpart ns3/named.run > /dev/null
+$RNDCCMD 10.53.0.3 addzone verify-addzone '{ type mirror; primaries { 10.53.0.2; }; };' > rndc.out.ns3.test$n 2>&1 || ret=1
+wait_for_transfer verify-addzone
+# Check whether the mirror zone was added and whether it behaves as expected.
+$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA > dig.out.ns3.test$n.2 2>&1 || ret=1
+grep "NOERROR" dig.out.ns3.test$n.2 > /dev/null || ret=1
+grep "flags:.* aa" dig.out.ns3.test$n.2 > /dev/null && ret=1
+grep "flags:.* ad" dig.out.ns3.test$n.2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that a mirror zone can be deleted using rndc ($n)"
+ret=0
+# Remove the mirror zone added in the previous test.
+nextpart ns3/named.run > /dev/null
+$RNDCCMD 10.53.0.3 delzone verify-addzone > rndc.out.ns3.test$n 2>&1 || ret=1
+wait_for_log 20 "zone verify-addzone/IN: mirror zone is no longer in use; reverting to normal recursion" ns3/named.run || ret=1
+# Check whether the mirror zone was removed.
+$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA > dig.out.ns3.test$n 2>&1 || ret=1
+grep "NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+grep "flags:.* aa" dig.out.ns3.test$n > /dev/null && ret=1
+grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/mirror/tests_sh_mirror.py b/bin/tests/system/mirror/tests_sh_mirror.py
new file mode 100644
index 0000000..f8d6b9d
--- /dev/null
+++ b/bin/tests/system/mirror/tests_sh_mirror.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_mirror(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/mkeys/README b/bin/tests/system/mkeys/README
new file mode 100644
index 0000000..25637bf
--- /dev/null
+++ b/bin/tests/system/mkeys/README
@@ -0,0 +1,34 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+This is for testing RFC 5011 Automated Updates of DNSSEC Trust Anchors.
+
+ns1 is the root server that offers new KSKs and hosts one record for
+testing. The TTL for the zone's records is 2 seconds.
+
+ns2 is a validator that uses managed keys. "-T mkeytimers=2/20/40"
+is used so it will attempt do automated updates frequently. "-T tat=1"
+is used so it will send TAT queries once per second.
+
+ns3 is a validator with a broken initializing key in trust-anchors.
+
+ns4 is a validator with a deliberately broken managed-keys.bind and
+managed-keys.jnl, causing RFC 5011 initialization to fail.
+
+ns5 is a validator which is prevented from getting a response from the
+root server, causing key refresh queries to fail.
+
+ns6 is a validator which has unsupported algorithms, one at start up,
+one because of an algorithm rollover.
+
+ns7 is a validator with multiple views configured. It is used for
+testing per-view rndc commands and checking interactions between options
+related to and potentially affecting RFC 5011 processing.
diff --git a/bin/tests/system/mkeys/clean.sh b/bin/tests/system/mkeys/clean.sh
new file mode 100644
index 0000000..3f297a2
--- /dev/null
+++ b/bin/tests/system/mkeys/clean.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */K* */*.signed */trusted.conf */*.jnl */*.bk
+rm -f */island.conf
+rm -f */private.conf
+rm -f */managed*.conf ns1/managed.key ns1/managed.key.id
+rm -f */managed-keys.bind* */named.secroots
+rm -f */named.conf
+rm -f */named.memstats */named.run */named.run.prev
+rm -f dig.out* delv.out* rndc.out* signer.out*
+rm -f dsset-. ns1/dsset-.
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.lock
+rm -f ns1/dsset-sub.tld.
+rm -f ns1/dsset-tld.
+rm -f ns1/named.secroots ns1/root.db.signed* ns1/root.db.tmp
+rm -f ns1/zone.key
+rm -f ns3/broken.conf
+rm -f ns4/dsset-sub.foo.
+rm -f ns5/named.args
+rm -f ns7/view1.mkeys ns7/view2.mkeys
+rm -rf ns4/nope
diff --git a/bin/tests/system/mkeys/ns1/named1.conf.in b/bin/tests/system/mkeys/ns1/named1.conf.in
new file mode 100644
index 0000000..0b3f068
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/named1.conf.in
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+acl allowed {
+ ! 10.53.0.5;
+ any;
+};
+
+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 no;
+ dnssec-validation yes;
+ allow-query { allowed; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+ allow-update { any; };
+ auto-dnssec maintain;
+};
+
+zone "tld" {
+ type primary;
+ file "tld.db.signed";
+};
+
+zone "sub.tld" {
+ type primary;
+ file "sub.tld.db.signed";
+};
diff --git a/bin/tests/system/mkeys/ns1/named2.conf.in b/bin/tests/system/mkeys/ns1/named2.conf.in
new file mode 100644
index 0000000..4271668
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/named2.conf.in
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+acl allowed {
+ ! 10.53.0.5;
+ any;
+};
+
+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 no;
+ dnssec-validation yes;
+ allow-query { allowed; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+zone "tld" {
+ type primary;
+ file "tld.db.signed";
+};
+
+zone "sub.tld" {
+ type primary;
+ file "sub.tld.db.signed";
+};
diff --git a/bin/tests/system/mkeys/ns1/named3.conf.in b/bin/tests/system/mkeys/ns1/named3.conf.in
new file mode 100644
index 0000000..686177e
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/named3.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 no;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+zone "tld" {
+ type primary;
+ file "tld.db.signed";
+};
+
+zone "sub.tld" {
+ type primary;
+ file "sub.tld.db.signed";
+};
diff --git a/bin/tests/system/mkeys/ns1/root.db b/bin/tests/system/mkeys/ns1/root.db
new file mode 100644
index 0000000..bc83788
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/root.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 20
+. IN SOA gson.nominum.com. 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
+
+; no delegation
+
+example. TXT "This is a test."
+
+tld. NS ns.tld.
+ns.tld. A 10.53.0.1
diff --git a/bin/tests/system/mkeys/ns1/sign.sh b/bin/tests/system/mkeys/ns1/sign.sh
new file mode 100644
index 0000000..626e18f
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/sign.sh
@@ -0,0 +1,93 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=sub.tld
+zonefile=sub.tld.db
+
+keyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk $zone)
+zskkeyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $zone)
+
+$SIGNER -Sg -o $zone $zonefile > /dev/null 2>/dev/null
+keyfile_to_initial_ds $keyname > island.conf
+cp island.conf ../ns5/island.conf
+
+zone=tld
+zonefile=tld.db
+
+keyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk $zone)
+zskkeyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $zone)
+
+$SIGNER -Sg -o $zone $zonefile > /dev/null 2>/dev/null
+
+zone=.
+zonefile=root.db
+
+keyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk $zone)
+zskkeyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $zone)
+
+$SIGNER -Sg -o $zone $zonefile > /dev/null 2>/dev/null
+
+# Configure the resolving server with an initializing key.
+keyfile_to_initial_ds $keyname > managed.conf
+cp managed.conf ../ns2/managed.conf
+cp managed.conf ../ns4/managed.conf
+cp managed.conf ../ns5/managed.conf
+
+# Configure broken trust anchor for ns3
+# Rotate each nibble in the digest by -1
+$DSFROMKEY $keyname.key |
+awk '!/^; /{
+ printf "trust-anchors {\n"
+ printf "\t\""$1"\" initial-ds "
+ printf $4 " " $5 " " $6 " \""
+ for (i=7; i<=NF; i++) {
+ # rotate digest
+ digest=$i
+ gsub("0", ":", digest)
+ gsub("1", "0", digest)
+ gsub("2", "1", digest)
+ gsub("3", "2", digest)
+ gsub("4", "3", digest)
+ gsub("5", "4", digest)
+ gsub("6", "5", digest)
+ gsub("7", "6", digest)
+ gsub("8", "7", digest)
+ gsub("9", "8", digest)
+ gsub("A", "9", digest)
+ gsub("B", "A", digest)
+ gsub("C", "B", digest)
+ gsub("D", "C", digest)
+ gsub("E", "D", digest)
+ gsub("F", "E", digest)
+ gsub(":", "F", digest)
+ printf digest
+ }
+ printf "\";\n"
+ printf "};\n"
+ }' > ../ns3/broken.conf
+
+# Configure a static key to be used by delv.
+keyfile_to_static_ds $keyname > trusted.conf
+
+# Prepare an unsupported algorithm key.
+unsupportedkey=Kunknown.+255+00000
+cp unsupported.key "${unsupportedkey}.key"
+
+#
+# Save keyname and keyid for managed key id test.
+#
+echo "$keyname" > managed.key
+echo "$zskkeyname" > zone.key
+keyfile_to_key_id $keyname > managed.key.id
diff --git a/bin/tests/system/mkeys/ns1/sub.tld.db b/bin/tests/system/mkeys/ns1/sub.tld.db
new file mode 100644
index 0000000..35d4361
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/sub.tld.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 20
+sub.tld. IN SOA marka.isc.org. ns.sub.tld. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 2 ; minimum
+ )
+sub.tld. NS ns.sub.tld.
+ns.sub.tld. A 10.53.0.1
diff --git a/bin/tests/system/mkeys/ns1/tld.db b/bin/tests/system/mkeys/ns1/tld.db
new file mode 100644
index 0000000..5c54e0e
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/tld.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 20
+tld. IN SOA marka.isc.org. ns.tld. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 2 ; minimum
+ )
+tld. NS ns.tld.
+ns.tld. A 10.53.0.1
+sub.tld. NS ns.sub.tld.
+ns.sub.tld. A 10.53.0.1
diff --git a/bin/tests/system/mkeys/ns1/unsupported.key b/bin/tests/system/mkeys/ns1/unsupported.key
new file mode 100644
index 0000000..7435d03
--- /dev/null
+++ b/bin/tests/system/mkeys/ns1/unsupported.key
@@ -0,0 +1 @@
+. IN DNSKEY 257 3 255 BJiXuidPHuGIne8GlCBLG+Oq/FZruQd2s3uBo+SxY16NUP/Vwl8MctMK62KsblDU1gIJAdEMVep2tsOkuSm0bIbJ8NBex+N9rSvzH2YJlDCT9QnNfv4q5RRTcVA3lk9nkmWHo6zcAT33yuS+THOCSznOMCJRq8JGZ6xqMJLv9FucuK6CCe6QBAZ5e98dpyGTWQLu7AERKKFqda9YCk3KQfdzx/HZ4SpQpRLncIXvGm1PIMT8Ar95NB/BsFJGwr5ZTaQtRYOXf2DD7wD3pfMsTJCdZyC0J0EtGBG109I+Oou1cswUfqZLXip/aV3eaBAUqLcZpg8P8vAbrvEq4uMS4OMZeXL6nu0irrdS1Pqmax8RsC+x3fg9EBH3QmHroJZtiU5h+0x4qApp7HE4Z5zFRuxIp9iB
diff --git a/bin/tests/system/mkeys/ns2/named.args b/bin/tests/system/mkeys/ns2/named.args
new file mode 100644
index 0000000..e588c91
--- /dev/null
+++ b/bin/tests/system/mkeys/ns2/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 99 -D mkeys-ns2 -X named.lock -g -T maxcachesize=2097152 -T mkeytimers=5/10/20 -T tat=1
diff --git a/bin/tests/system/mkeys/ns2/named.conf.in b/bin/tests/system/mkeys/ns2/named.conf.in
new file mode 100644
index 0000000..1c77556
--- /dev/null
+++ b/bin/tests/system/mkeys/ns2/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+ servfail-ttl 0;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/mkeys/ns3/named.args b/bin/tests/system/mkeys/ns3/named.args
new file mode 100644
index 0000000..28396c3
--- /dev/null
+++ b/bin/tests/system/mkeys/ns3/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 99 -D mkeys-ns3 -X named.lock -g -T maxcachesize=2097152 -T mkeytimers=5/10/20
diff --git a/bin/tests/system/mkeys/ns3/named.conf.in b/bin/tests/system/mkeys/ns3/named.conf.in
new file mode 100644
index 0000000..374b184
--- /dev/null
+++ b/bin/tests/system/mkeys/ns3/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ notify no;
+ dnssec-validation yes;
+ bindkeys-file "managed.conf";
+ trust-anchor-telemetry no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "broken.conf";
diff --git a/bin/tests/system/mkeys/ns4/named.conf.in b/bin/tests/system/mkeys/ns4/named.conf.in
new file mode 100644
index 0000000..5c23708
--- /dev/null
+++ b/bin/tests/system/mkeys/ns4/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ notify no;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+ managed-keys-directory "nope";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "sub.foo" {
+ type primary;
+ file "sub.foo.db.signed";
+};
diff --git a/bin/tests/system/mkeys/ns4/sign.sh b/bin/tests/system/mkeys/ns4/sign.sh
new file mode 100644
index 0000000..d364e8e
--- /dev/null
+++ b/bin/tests/system/mkeys/ns4/sign.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=sub.foo
+zonefile=sub.foo.db
+
+keyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk $zone)
+zskkeyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $zone)
+
+$SIGNER -Sg -o $zone $zonefile > /dev/null 2>/dev/null
+keyfile_to_initial_ds $keyname > private.conf
+cp private.conf ../ns5/private.conf
diff --git a/bin/tests/system/mkeys/ns4/sub.foo.db b/bin/tests/system/mkeys/ns4/sub.foo.db
new file mode 100644
index 0000000..7bc3104
--- /dev/null
+++ b/bin/tests/system/mkeys/ns4/sub.foo.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 20
+sub.foo. IN SOA marka.isc.org. ns.foo. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 2 ; minimum
+ )
+sub.foo. NS ns.sub.foo.
+ns.sub.foo. A 10.53.0.4
diff --git a/bin/tests/system/mkeys/ns5/foo.db b/bin/tests/system/mkeys/ns5/foo.db
new file mode 100644
index 0000000..092a1c3
--- /dev/null
+++ b/bin/tests/system/mkeys/ns5/foo.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 20
+foo. IN SOA marka.isc.org. ns.foo. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 2 ; minimum
+ )
+foo. NS ns.foo.
+ns.foo. A 10.53.0.5
+sub.foo. NS ns.sub.foo.
+ns.sub.foo. A 10.53.0.4
diff --git a/bin/tests/system/mkeys/ns5/named.conf.in b/bin/tests/system/mkeys/ns5/named.conf.in
new file mode 100644
index 0000000..757d614
--- /dev/null
+++ b/bin/tests/system/mkeys/ns5/named.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ notify no;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+ servfail-ttl 0;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "foo" {
+ type primary;
+ file "foo.db";
+};
+
+include "island.conf";
+include "private.conf";
diff --git a/bin/tests/system/mkeys/ns5/named1.args b/bin/tests/system/mkeys/ns5/named1.args
new file mode 100644
index 0000000..6eeaa29
--- /dev/null
+++ b/bin/tests/system/mkeys/ns5/named1.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 99 -X named.lock -g -T maxcachesize=2097152
diff --git a/bin/tests/system/mkeys/ns5/named2.args b/bin/tests/system/mkeys/ns5/named2.args
new file mode 100644
index 0000000..34ac30d
--- /dev/null
+++ b/bin/tests/system/mkeys/ns5/named2.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 99 -X named.lock -g -T maxcachesize=2097152 -T mkeytimers=2/20/40
diff --git a/bin/tests/system/mkeys/ns6/named.args b/bin/tests/system/mkeys/ns6/named.args
new file mode 100644
index 0000000..7ef5cf0
--- /dev/null
+++ b/bin/tests/system/mkeys/ns6/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 99 -X named.lock -g -T maxcachesize=2097152 -T mkeytimers=5/10/20
diff --git a/bin/tests/system/mkeys/ns6/named.conf.in b/bin/tests/system/mkeys/ns6/named.conf.in
new file mode 100644
index 0000000..3279859
--- /dev/null
+++ b/bin/tests/system/mkeys/ns6/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS6
+
+options {
+ 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.6; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+ dnssec-validation yes;
+ trust-anchor-telemetry no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "managed.conf";
diff --git a/bin/tests/system/mkeys/ns6/setup.sh b/bin/tests/system/mkeys/ns6/setup.sh
new file mode 100644
index 0000000..fcbd287
--- /dev/null
+++ b/bin/tests/system/mkeys/ns6/setup.sh
@@ -0,0 +1,33 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=.
+zonefile=root.db
+
+# a key for a trust island
+islandkey=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk island.)
+
+# a key with unsupported algorithm
+unsupportedkey=Kunknown.+255+00000
+cp unsupported-managed.key "${unsupportedkey}.key"
+
+# root key
+rootkey=$(cat ../ns1/managed.key)
+cp "../ns1/${rootkey}.key" .
+
+# Configure the resolving server with an initializing key.
+# (We use key-format trust anchors here because otherwise the
+# unsupported algorithm test won't work.)
+keyfile_to_initial_keys $unsupportedkey $islandkey $rootkey > managed.conf
diff --git a/bin/tests/system/mkeys/ns6/unsupported-managed.key b/bin/tests/system/mkeys/ns6/unsupported-managed.key
new file mode 100644
index 0000000..be872a0
--- /dev/null
+++ b/bin/tests/system/mkeys/ns6/unsupported-managed.key
@@ -0,0 +1 @@
+unsupported. IN DNSKEY 257 3 255 BOOVAhiJDPqhfU7+yGXjhetrtC/rtjmwO1yo52BUHUd8R4hQ/ZPdYCVvQlvNkRxDblPkFM5YRXkesS30pJSoNYrg+djbMNumJrLG+lbhFIc/ahTjlYOxb1zm2z00ubHju/1uGBifiRvKWSK0Vr0u6NtS4PKZfsnXt+piSHiRAHSfkjGHwqPYYKh9EUW12kJmIzlMaM6WYl+gJOvL+f8VqNLtvsMPT6OPK/3h/Dnfnxyeudp/jzAnNDDiTgX2XfzIXB4UwxtzIOGaHLnprpNf3zoBm0kyaEdSQQ/qKkpCOqjBasYEHRjVz3RncPUkdLr7PQuPBfFDr3SUMMJqufJrO4IJjtD4cCBT7K1i39Jg471nEzU1vkPzxF+Rw1QHT4nZaXbltf3BEZGS4Knoe9XPwi5KjGW6
diff --git a/bin/tests/system/mkeys/ns7/named.conf.in b/bin/tests/system/mkeys/ns7/named.conf.in
new file mode 100644
index 0000000..b50246a
--- /dev/null
+++ b/bin/tests/system/mkeys/ns7/named.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS7
+
+options {
+ 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.7; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view view1 {
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+};
+
+view view2 {
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+};
diff --git a/bin/tests/system/mkeys/setup.sh b/bin/tests/system/mkeys/setup.sh
new file mode 100644
index 0000000..d1a30a2
--- /dev/null
+++ b/bin/tests/system/mkeys/setup.sh
@@ -0,0 +1,43 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+export ALGORITHM_SET="ecc_default"
+. ../conf.sh
+
+# Ensure the selected algorithm set is okay.
+if [ "$ALGORITHM_SET" = "error" ]; then
+ echofail "Algorithm selection failed." >&2
+ exit 1
+fi
+
+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
+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
+
+cp ns5/named1.args ns5/named.args
+
+( cd ns1 && $SHELL sign.sh )
+( cd ns4 && $SHELL sign.sh )
+( cd ns6 && $SHELL setup.sh )
+
+cp ns2/managed.conf ns2/managed1.conf
+
+cd ns4
+mkdir nope
+touch nope/managed-keys.bind
+touch nope/managed.keys.bind.jnl
+chmod 444 nope/*
diff --git a/bin/tests/system/mkeys/tests.sh b/bin/tests/system/mkeys/tests.sh
new file mode 100644
index 0000000..ed9dcf6
--- /dev/null
+++ b/bin/tests/system/mkeys/tests.sh
@@ -0,0 +1,882 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+export ALGORITHM_SET="ecc_default"
+#shellcheck source=conf.sh
+. ../conf.sh
+
+dig_with_opts() (
+ "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "${PORT}" "$@"
+)
+
+delv_with_opts() (
+ "$DELV" -a ns1/trusted.conf -p "${PORT}" "$@"
+)
+
+rndccmd() (
+ "$RNDC" -c ../common/rndc.conf -p "${CONTROLPORT}" -s "$@"
+)
+
+mkeys_reconfig_on() (
+ nsidx=$1
+ rndccmd "10.53.0.${nsidx}" reconfig . | sed "s/^/ns${nsidx} /" | cat_i
+)
+
+mkeys_reload_on() (
+ nsidx=$1
+ nextpart "ns${nsidx}"/named.run > /dev/null
+ rndc_reload "ns${nsidx}" "10.53.0.${nsidx}"
+ wait_for_log 20 "loaded serial" "ns${nsidx}"/named.run || return 1
+)
+
+mkeys_loadkeys_on() (
+ nsidx=$1
+ nextpart "ns${nsidx}"/named.run > /dev/null
+ rndccmd "10.53.0.${nsidx}" loadkeys . | sed "s/^/ns${nsidx} /" | cat_i
+ wait_for_log 20 "next key event" "ns${nsidx}"/named.run || return 1
+)
+
+mkeys_refresh_on() (
+ nsidx=$1
+ nextpart "ns${nsidx}"/named.run > /dev/null
+ rndccmd "10.53.0.${nsidx}" managed-keys refresh | sed "s/^/ns${nsidx} /" | cat_i
+ wait_for_log 20 "Returned from key fetch in keyfetch_done()" "ns${nsidx}"/named.run || return 1
+)
+
+mkeys_sync_on() (
+ # No race with mkeys_refresh_on() is possible as even if the latter
+ # returns immediately after the expected log message is written, the
+ # managed-keys zone is already locked and the command below calls
+ # dns_zone_flush(), which also attempts to take that zone's lock
+ nsidx=$1
+ nextpart "ns${nsidx}"/named.run > /dev/null
+ rndccmd "10.53.0.${nsidx}" managed-keys sync | sed "s/^/ns${nsidx} /" | cat_i
+ wait_for_log 20 "dump_done" "ns${nsidx}"/named.run || return 1
+)
+
+mkeys_status_on() (
+ # No race with mkeys_refresh_on() is possible as even if the latter
+ # returns immediately after the expected log message is written, the
+ # managed-keys zone is already locked and the command below calls
+ # mkey_status(), which in turn calls dns_zone_getrefreshkeytime(),
+ # which also attempts to take that zone's lock
+ nsidx=$1
+ rndccmd "10.53.0.${nsidx}" managed-keys status
+)
+
+mkeys_flush_on() (
+ nsidx=$1
+ rndccmd "10.53.0.${nsidx}" flush | sed "s/^/ns${nsidx} /" | cat_i
+)
+
+mkeys_secroots_on() (
+ nsidx=$1
+ rndccmd "10.53.0.${nsidx}" secroots | sed "s/^/ns${nsidx} /" | cat_i
+)
+
+original=$(cat ns1/managed.key)
+originalid=$(cat ns1/managed.key.id)
+
+status=0
+n=1
+
+rm -f dig.out.*
+
+echo_i "check for signed record ($n)"
+ret=0
+dig_with_opts +norec example. @10.53.0.1 TXT > dig.out.ns1.test$n || ret=1
+grep "^example\.[[:space:]]*[0-9]*[[:space:]]*IN[[:space:]]*TXT[[:space:]]*\"This is a test\.\"" dig.out.ns1.test$n > /dev/null || ret=1
+grep "^example\.[[:space:]]*[0-9]*[[:space:]]*IN[[:space:]]*RRSIG[[:space:]]*TXT[[:space:]]" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check positive validation with valid trust anchor ($n)"
+ret=0
+dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+if [ -x "$DELV" ]; then
+ n=$((n+1))
+ ret=0
+ echo_i "check positive validation using delv ($n)"
+ delv_with_opts @10.53.0.1 txt example > delv.out$n || ret=1
+ grep "; fully validated" delv.out$n > /dev/null || ret=1 # redundant
+ grep "example..*TXT.*This is a test" delv.out$n > /dev/null || ret=1
+ grep "example..*.RRSIG..*TXT" delv.out$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+fi
+
+n=$((n+1))
+echo_i "check for failed validation due to wrong key in managed-keys ($n)"
+ret=0
+dig_with_opts +noauth example. @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns3.test$n > /dev/null && ret=1
+grep "opcode: QUERY, status: SERVFAIL, id" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check new trust anchor can be added ($n)"
+ret=0
+standby1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk -K ns1 .)
+mkeys_loadkeys_on 1 || ret=1
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
+# there should be two keys listed now
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# one indicates current trust
+count=$(grep -c "trusted since" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# one indicates pending trust
+count=$(grep -c "trust pending" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check new trust anchor can't be added with bad initial key ($n)"
+ret=0
+mkeys_refresh_on 3 || ret=1
+mkeys_status_on 3 > rndc.out.$n 2>&1 || ret=1
+# there should be one key listed now
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# one line indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# ... and the key is not trusted
+count=$(grep -c "no trust" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "remove untrusted standby key, check timer restarts ($n)"
+ret=0
+mkeys_sync_on 2 || ret=1
+t1=$(grep "trust pending" ns2/managed-keys.bind) || true
+$SETTIME -D now -K ns1 "$standby1" > /dev/null
+mkeys_loadkeys_on 1 || ret=1
+# Less than a second may have passed since the last time ns2 received a
+# ./DNSKEY response from ns1. Ensure keys are refreshed at a different
+# timestamp to prevent false negatives caused by the acceptance timer getting
+# reset to the same timestamp.
+sleep 1
+mkeys_refresh_on 2 || ret=1
+mkeys_sync_on 2 || ret=1
+t2=$(grep "trust pending" ns2/managed-keys.bind) || true
+# trust pending date must be different
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "restore untrusted standby key, revoke original key ($n)"
+t1=$t2
+$SETTIME -D none -K ns1 "$standby1" > /dev/null
+$SETTIME -R now -K ns1 "$original" > /dev/null
+mkeys_loadkeys_on 1 || ret=1
+# Less than a second may have passed since the last time ns2 received a
+# ./DNSKEY response from ns1. Ensure keys are refreshed at a different
+# timestamp to prevent false negatives caused by the acceptance timer getting
+# reset to the same timestamp.
+sleep 1
+mkeys_refresh_on 2 || ret=1
+mkeys_sync_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
+# two keys listed
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# trust is revoked
+count=$(grep -c "trust revoked" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=$(grep -c "remove at" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# trust is still pending on the standby key
+count=$(grep -c "trust pending" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# pending date moved forward for the standby key
+t2=$(grep "trust pending" ns2/managed-keys.bind) || true
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "refresh managed-keys, ensure same result ($n)"
+t1=$t2
+# Less than a second may have passed since the last time ns2 received a
+# ./DNSKEY response from ns1. Ensure keys are refreshed at a different
+# timestamp to prevent false negatives caused by the acceptance timer getting
+# reset to the same timestamp.
+sleep 1
+mkeys_refresh_on 2 || ret=1
+mkeys_sync_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
+# two keys listed
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# trust is revoked
+count=$(grep -c "trust revoked" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=$(grep -c "remove at" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# trust is still pending on the standby key
+count=$(grep -c "trust pending" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# pending date moved forward for the standby key
+t2=$(grep "trust pending" ns2/managed-keys.bind) || true
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "restore revoked key, ensure same result ($n)"
+t1=$t2
+$SETTIME -R none -D now -K ns1 "$original" > /dev/null
+mkeys_loadkeys_on 1 || ret=1
+$SETTIME -D none -K ns1 "$original" > /dev/null
+mkeys_loadkeys_on 1 || ret=1
+# Less than a second may have passed since the last time ns2 received a
+# ./DNSKEY response from ns1. Ensure keys are refreshed at a different
+# timestamp to prevent false negatives caused by the acceptance timer getting
+# reset to the same timestamp.
+sleep 1
+mkeys_refresh_on 2 || ret=1
+mkeys_sync_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
+# two keys listed
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# trust is revoked
+count=$(grep -c "trust revoked" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=$(grep -c "remove at" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# trust is still pending on the standby key
+count=$(grep -c "trust pending" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# pending date moved forward for the standby key
+t2=$(grep "trust pending" ns2/managed-keys.bind) || true
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "reinitialize trust anchors, add second key to bind.keys"
+stop_server --use-rndc --port "${CONTROLPORT}" ns2
+rm -f ns2/managed-keys.bind*
+keyfile_to_initial_ds ns1/"$original" ns1/"$standby1" > ns2/managed.conf
+nextpart ns2/named.run > /dev/null
+start_server --noclean --restart --port "${PORT}" ns2
+
+n=$((n+1))
+echo_i "check that no key from bind.keys is marked as an initializing key ($n)"
+ret=0
+wait_for_log 20 "Returned from key fetch in keyfetch_done()" ns2/named.run || ret=1
+mkeys_secroots_on 2 || ret=1
+grep '; initializing' ns2/named.secroots > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "reinitialize trust anchors, revert to one key in bind.keys"
+stop_server --use-rndc --port "${CONTROLPORT}" ns2
+rm -f ns2/managed-keys.bind*
+mv ns2/managed1.conf ns2/managed.conf
+nextpart ns2/named.run > /dev/null
+start_server --noclean --restart --port "${PORT}" ns2
+
+n=$((n+1))
+echo_i "check that standby key is now trusted ($n)"
+ret=0
+wait_for_log 20 "Returned from key fetch in keyfetch_done()" ns2/named.run || ret=1
+mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
+# two keys listed
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# both indicate current trust
+count=$(grep -c "trusted since" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "revoke original key, add new standby ($n)"
+ret=0
+standby2=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk -K ns1 .)
+$SETTIME -R now -K ns1 "$original" > /dev/null
+mkeys_loadkeys_on 1 || ret=1
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
+# three keys listed
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 3 ] || ret=1
+# one is revoked
+count=$(grep -c "REVOKE" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# three lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 3 ] || ret=1
+# one indicates current trust
+count=$(grep -c "trusted since" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# one indicates revoked trust
+count=$(grep -c "trust revoked" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# one indicates trust pending
+count=$(grep -c "trust pending" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=$(grep -c "remove at" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "revoke standby before it is trusted ($n)"
+ret=0
+standby3=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk -K ns1 .)
+mkeys_loadkeys_on 1 || ret=1
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.1.$n 2>&1 || ret=1
+# four keys listed
+count=$(grep -c "keyid: " rndc.out.1.$n) || true
+[ "$count" -eq 4 ] || { echo_i "keyid: count ($count) != 4"; ret=1; }
+# one revoked
+count=$(grep -c "trust revoked" rndc.out.1.$n) || true
+[ "$count" -eq 1 ] || { echo_i "trust revoked count ($count) != 1"; ret=1; }
+# two pending
+count=$(grep -c "trust pending" rndc.out.1.$n) || true
+[ "$count" -eq 2 ] || { echo_i "trust pending count ($count) != 2"; ret=1; }
+$SETTIME -R now -K ns1 "$standby3" > /dev/null
+mkeys_loadkeys_on 1 || ret=1
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.2.$n 2>&1 || ret=1
+# now three keys listed
+count=$(grep -c "keyid: " rndc.out.2.$n) || true
+[ "$count" -eq 3 ] || { echo_i "keyid: count ($count) != 3"; ret=1; }
+# one revoked
+count=$(grep -c "trust revoked" rndc.out.2.$n) || true
+[ "$count" -eq 1 ] || { echo_i "trust revoked count ($count) != 1"; ret=1; }
+# one pending
+count=$(grep -c "trust pending" rndc.out.2.$n) || true
+[ "$count" -eq 1 ] || { echo_i "trust pending count ($count) != 1"; ret=1; }
+$SETTIME -D now -K ns1 "$standby3" > /dev/null
+mkeys_loadkeys_on 1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "wait 20 seconds for key add/remove holddowns to expire ($n)"
+ret=0
+sleep 20
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
+# two keys listed
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# none revoked
+count=$(grep -c "REVOKE" rndc.out.$n) || true
+[ "$count" -eq 0 ] || ret=1
+# two lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# both indicate current trust
+count=$(grep -c "trusted since" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "revoke all keys, confirm roll to insecure ($n)"
+ret=0
+$SETTIME -D now -K ns1 "$original" > /dev/null
+$SETTIME -R now -K ns1 "$standby1" > /dev/null
+$SETTIME -R now -K ns1 "$standby2" > /dev/null
+mkeys_loadkeys_on 1 || ret=1
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
+# two keys listed
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# both revoked
+count=$(grep -c "REVOKE" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# both indicate trust revoked
+count=$(grep -c "trust revoked" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# both have removal scheduled
+count=$(grep -c "remove at" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check for insecure response ($n)"
+ret=0
+mkeys_refresh_on 2 || ret=1
+dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "reset the root server ($n)"
+ret=0
+$SETTIME -D none -R none -K ns1 "$original" > /dev/null
+$SETTIME -D now -K ns1 "$standby1" > /dev/null
+$SETTIME -D now -K ns1 "$standby2" > /dev/null
+sleep 1 # ensure modification time changes
+$SIGNER -Sg -K ns1 -N unixtime -o . ns1/root.db > /dev/null 2>/dev/null
+copy_setports ns1/named2.conf.in ns1/named.conf
+rm -f ns1/root.db.signed.jnl
+mkeys_reconfig_on 1 || ret=1
+mkeys_reload_on 1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "reinitialize trust anchors"
+stop_server --use-rndc --port "${CONTROLPORT}" ns2
+rm -f ns2/managed-keys.bind*
+nextpart ns2/named.run > /dev/null
+start_server --noclean --restart --port "${PORT}" ns2
+
+n=$((n+1))
+echo_i "check positive validation ($n)"
+ret=0
+wait_for_log 20 "Returned from key fetch in keyfetch_done()" ns2/named.run || ret=1
+dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "revoke key with bad signature, check revocation is ignored ($n)"
+ret=0
+revoked=$($REVOKE -K ns1 "$original")
+rkeyid=$(keyfile_to_key_id "$revoked")
+rm -f ns1/root.db.signed.jnl
+# We need to activate at least one valid DNSKEY to prevent dnssec-signzone from
+# failing. Alternatively, we could use -P to disable post-sign verification,
+# but we actually do want post-sign verification to happen to ensure the zone
+# is correct before we break it on purpose.
+$SETTIME -R none -D none -K ns1 "$standby1" > /dev/null
+$SIGNER -Sg -K ns1 -N unixtime -O full -o . -f signer.out.$n ns1/root.db > /dev/null 2>/dev/null
+cp -f ns1/root.db.signed ns1/root.db.tmp
+BADSIG="SVn2tLDzpNX2rxR4xRceiCsiTqcWNKh7NQ0EQfCrVzp9WEmLw60sQ5kP xGk4FS/xSKfh89hO2O/H20Bzp0lMdtr2tKy8IMdU/mBZxQf2PXhUWRkg V2buVBKugTiOPTJSnaqYCN3rSfV1o7NtC1VNHKKK/D5g6bpDehdn5Gaq kpBhN+MSCCh9OZP2IT20luS1ARXxLlvuSVXJ3JYuuhTsQXUbX/SQpNoB Lo6ahCE55szJnmAxZEbb2KOVnSlZRA6ZBHDhdtO0S4OkvcmTutvcVV+7 w53CbKdaXhirvHIh0mZXmYk2PbPLDY7PU9wSH40UiWPOB9f00wwn6hUe uEQ1Qg=="
+# Less than a second may have passed since ns1 was started. If we call
+# dnssec-signzone immediately, ns1/root.db.signed will not be reloaded by the
+# subsequent "rndc reload ." call on platforms which do not set the
+# "nanoseconds" field of isc_time_t, due to zone load time being seemingly
+# equal to master file modification time.
+sleep 1
+sed -e "/ $rkeyid \./s, \. .*$, . $BADSIG," signer.out.$n > ns1/root.db.signed
+mkeys_reload_on 1 || ret=1
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
+# one key listed
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 1 ] || { echo_i "'keyid:' count ($count) != 1"; ret=1; }
+# it's the original key id
+count=$(grep -c "keyid: $originalid" rndc.out.$n) || true
+[ "$count" -eq 1 ] || { echo_i "'keyid: $originalid' count ($count) != 1"; ret=1; }
+# not revoked
+count=$(grep -c "REVOKE" rndc.out.$n) || true
+[ "$count" -eq 0 ] || { echo_i "'REVOKE' count ($count) != 0"; ret=1; }
+# trust is still current
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 1 ] || { echo_i "'trust' count != 1"; ret=1; }
+count=$(grep -c "trusted since" rndc.out.$n) || true
+[ "$count" -eq 1 ] || { echo_i "'trusted since' count != 1"; ret=1; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check validation fails with bad DNSKEY rrset ($n)"
+ret=0
+mkeys_flush_on 2 || ret=1
+dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "status: SERVFAIL" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "restore DNSKEY rrset, check validation succeeds again ($n)"
+ret=0
+rm -f "${revoked}".key "${revoked}".private
+rm -f ns1/root.db.signed.jnl
+$SETTIME -D none -R none -K ns1 "$original" > /dev/null
+$SETTIME -D now -K ns1 "$standby1" > /dev/null
+# Less than a second may have passed since ns1 was started. If we call
+# dnssec-signzone immediately, ns1/root.db.signed will not be reloaded by the
+# subsequent "rndc reload ." call on platforms which do not set the
+# "nanoseconds" field of isc_time_t, due to zone load time being seemingly
+# equal to master file modification time.
+sleep 1
+$SIGNER -Sg -K ns1 -N unixtime -o . ns1/root.db > /dev/null 2>/dev/null
+mkeys_reload_on 1 || ret=1
+mkeys_flush_on 2 || ret=1
+dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "reset the root server with no keys, check for minimal update ($n)"
+ret=0
+# Refresh keys first to prevent previous checks from influencing this one.
+# Note that we might still get occasional false negatives on some really slow
+# machines, when $t1 equals $t2 due to the time elapsed between "rndc
+# managed-keys status" calls being equal to the normal active refresh period
+# (as calculated per rules listed in RFC 5011 section 2.3) minus an "hour" (as
+# set using -T mkeytimers).
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.1.$n 2>&1 || ret=1
+t1=$(grep 'next refresh:' rndc.out.1.$n) || true
+stop_server --use-rndc --port "${CONTROLPORT}" ns1
+rm -f ns1/root.db.signed.jnl
+cp ns1/root.db ns1/root.db.signed
+nextpart ns1/named.run > /dev/null
+start_server --noclean --restart --port "${PORT}" ns1
+wait_for_log 20 "all zones loaded" ns1/named.run || ret=1
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.2.$n 2>&1 || ret=1
+# one key listed
+count=$(grep -c "keyid: " rndc.out.2.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# it's the original key id
+count=$(grep -c "keyid: $originalid" rndc.out.2.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# not revoked
+count=$(grep -c "REVOKE" rndc.out.2.$n) || true
+[ "$count" -eq 0 ] || ret=1
+# trust is still current
+count=$(grep -c "trust" rndc.out.2.$n) || true
+[ "$count" -eq 1 ] || ret=1
+count=$(grep -c "trusted since" rndc.out.2.$n) || true
+[ "$count" -eq 1 ] || ret=1
+t2=$(grep 'next refresh:' rndc.out.2.$n) || true
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "reset the root server with no signatures, check for minimal update ($n)"
+ret=0
+# Refresh keys first to prevent previous checks from influencing this one
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.1.$n 2>&1 || ret=1
+t1=$(grep 'next refresh:' rndc.out.1.$n) || true
+stop_server --use-rndc --port "${CONTROLPORT}" ns1
+rm -f ns1/root.db.signed.jnl
+cat ns1/K*.key >> ns1/root.db.signed
+nextpart ns1/named.run > /dev/null
+start_server --noclean --restart --port "${PORT}" ns1
+wait_for_log 20 "all zones loaded" ns1/named.run || ret=1
+# Less than a second may have passed since the last time ns2 received a
+# ./DNSKEY response from ns1. Ensure keys are refreshed at a different
+# timestamp to prevent minimal update from resetting it to the same timestamp.
+sleep 1
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.2.$n 2>&1 || ret=1
+# one key listed
+count=$(grep -c "keyid: " rndc.out.2.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# it's the original key id
+count=$(grep -c "keyid: $originalid" rndc.out.2.$n) || true
+[ "$count" -eq 1 ] || ret=1
+# not revoked
+count=$(grep -c "REVOKE" rndc.out.2.$n) || true
+[ "$count" -eq 0 ] || ret=1
+# trust is still current
+count=$(grep -c "trust" rndc.out.2.$n) || true
+[ "$count" -eq 1 ] || ret=1
+count=$(grep -c "trusted since" rndc.out.2.$n) || true
+[ "$count" -eq 1 ] || ret=1
+t2=$(grep 'next refresh:' rndc.out.2.$n) || true
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "restore root server, check validation succeeds again ($n)"
+ret=0
+rm -f ns1/root.db.signed.jnl
+$SIGNER -Sg -K ns1 -N unixtime -o . ns1/root.db > /dev/null 2>/dev/null
+mkeys_reload_on 1 || ret=1
+mkeys_refresh_on 2 || ret=1
+mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
+dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check that trust-anchor-telemetry queries are logged ($n)"
+ret=0
+grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/NULL" ns2/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check that trust-anchor-telemetry queries are received ($n)"
+ret=0
+grep "query '_ta-[0-9a-f][0-9a-f]*/NULL/IN' approved" ns1/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc-managed-keys destroy' ($n)"
+ret=0
+rndccmd 10.53.0.2 managed-keys destroy | sed 's/^/ns2 /' | cat_i
+mkeys_status_on 2 > rndc.out.1.$n 2>&1 || ret=1
+grep "no views with managed keys" rndc.out.1.$n > /dev/null || ret=1
+mkeys_reconfig_on 2 || ret=1
+check_root_trust_anchor_is_present_in_status() {
+ mkeys_status_on 2 > rndc.out.2.$n 2>&1 || return 1
+ grep "name: \." rndc.out.2.$n > /dev/null || return 1
+ return 0
+}
+retry_quiet 5 check_root_trust_anchor_is_present_in_status || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check that trust-anchor-telemetry queries contain the correct key ($n)"
+ret=0
+# convert the hexadecimal key from the TAT query into decimal and
+# compare against the known key.
+tathex=$(grep "query '_ta-[0-9a-f][0-9a-f]*/NULL/IN' approved" ns1/named.run | awk '{print $6; exit 0}' | sed -e 's/(_ta-\([0-9a-f][0-9a-f]*\)):/\1/') || true
+tatkey=$($PERL -e 'printf("%d\n", hex(@ARGV[0]));' "$tathex")
+realkey=$(rndccmd 10.53.0.2 secroots - | sed -n "s#.*${DEFAULT_ALGORITHM}/\([0-9][0-9]*\) ; .*managed.*#\1#p")
+[ "$tatkey" -eq "$realkey" ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check initialization fails if managed-keys can't be created ($n)"
+ret=0
+mkeys_secroots_on 4 || ret=1
+grep '; initializing managed' ns4/named.secroots > /dev/null 2>&1 || ret=1
+grep '; managed' ns4/named.secroots > /dev/null 2>&1 && ret=1
+grep '; trusted' ns4/named.secroots > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check failure to contact root servers does not prevent key refreshes after restart ($n)"
+ret=0
+# By the time we get here, ns5 should have attempted refreshing its managed
+# keys. These attempts should fail as ns1 is configured to REFUSE all queries
+# from ns5. Note that named1.args does not contain "-T mkeytimers"; this is to
+# ensure key refresh retry will be scheduled to one actual hour after the first
+# key refresh failure instead of just a few seconds, in order to prevent races
+# between the next scheduled key refresh time and startup time of restarted ns5.
+stop_server --use-rndc --port "${CONTROLPORT}" ns5
+nextpart ns5/named.run > /dev/null
+start_server --noclean --restart --port "${PORT}" ns5
+wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for '.':" ns5/named.run || ret=1
+wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.tld':" ns5/named.run || ret=1
+wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.foo':" ns5/named.run || ret=1
+# ns5/named.run will contain logs from both the old instance and the new
+# instance. In order for the test to pass, both must attempt a fetch.
+count=$(grep -c "Creating key fetch" ns5/named.run) || true
+[ "$count" -lt 2 ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc managed-keys' and islands of trust root unreachable ($n)"
+ret=0
+mkeys_sync_on 5
+mkeys_status_on 5 > rndc.out.$n 2>&1 || ret=1
+# there should be three keys listed now
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 3 ] || ret=1
+# three lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 3 ] || ret=1
+# one indicates current trust
+count=$(grep -c "trusted since" rndc.out.$n) || true
+[ "$count" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check key refreshes are resumed after root servers become available ($n)"
+ret=0
+stop_server --use-rndc --port "${CONTROLPORT}" ns5
+# Prevent previous check from affecting this one
+rm -f ns5/managed-keys.bind*
+# named2.args adds "-T mkeytimers=2/20/40" to named1.args as we need to wait for
+# an "hour" until keys are refreshed again after initial failure
+cp ns5/named2.args ns5/named.args
+nextpart ns5/named.run > /dev/null
+start_server --noclean --restart --port "${PORT}" ns5
+wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for '.': failure" ns5/named.run || ret=1
+wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.tld': failure" ns5/named.run || ret=1
+wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.foo': success" ns5/named.run || ret=1
+mkeys_secroots_on 5 || ret=1
+grep '; initializing managed' ns5/named.secroots > /dev/null 2>&1 || ret=1
+# ns1 should still REFUSE queries from ns5, so resolving should be impossible
+dig_with_opts +noauth example. @10.53.0.5 txt > dig.out.ns5.a.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns5.a.test$n > /dev/null && ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns5.a.test$n > /dev/null && ret=1
+grep "status: SERVFAIL" dig.out.ns5.a.test$n > /dev/null || ret=1
+# Allow queries from ns5 to ns1
+copy_setports ns1/named3.conf.in ns1/named.conf
+rm -f ns1/root.db.signed.jnl
+nextpart ns5/named.run > /dev/null
+mkeys_reconfig_on 1 || ret=1
+wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for '.': success" ns5/named.run || ret=1
+wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.tld': success" ns5/named.run || ret=1
+wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.foo': success" ns5/named.run || ret=1
+mkeys_secroots_on 5 || ret=1
+grep '; managed' ns5/named.secroots > /dev/null || ret=1
+# ns1 should not longer REFUSE queries from ns5, so managed keys should be
+# correctly refreshed and resolving should succeed
+dig_with_opts +noauth example. @10.53.0.5 txt > dig.out.ns5.b.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns5.b.test$n > /dev/null || ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns5.b.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns5.b.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "reinitialize trust anchors, add unsupported algorithm ($n)"
+ret=0
+stop_server --use-rndc --port "${CONTROLPORT}" ns6
+rm -f ns6/managed-keys.bind*
+nextpart ns6/named.run > /dev/null
+start_server --noclean --restart --port "${PORT}" ns6
+# log when an unsupported algorithm is encountered during startup
+wait_for_log 20 "ignoring initial-key for 'unsupported.': algorithm is unsupported" ns6/named.run || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "ignoring unsupported algorithm in managed-keys ($n)"
+ret=0
+mkeys_status_on 6 > rndc.out.$n 2>&1 || ret=1
+# there should still be only two keys listed (for . and island.)
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+
+n=$((n+1))
+echo_i "introduce unsupported algorithm rollover in authoritative zone ($n)"
+ret=0
+cp ns1/root.db ns1/root.db.orig
+ksk=$(cat ns1/managed.key)
+zsk=$(cat ns1/zone.key)
+cat "ns1/${ksk}.key" "ns1/${zsk}.key" ns1/unsupported.key >> ns1/root.db
+grep "\.[[:space:]]*IN[[:space:]]*DNSKEY[[:space:]]*257 3 255" ns1/root.db > /dev/null || ret=1
+$SIGNER -K ns1 -N unixtime -o . ns1/root.db "$ksk" "$zsk" > /dev/null 2>/dev/null || ret=1
+grep "DNSKEY.*257 3 255" ns1/root.db.signed > /dev/null || ret=1
+cp ns1/root.db.orig ns1/root.db
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "ignoring unsupported algorithm in rollover ($n)"
+ret=0
+mkeys_reload_on 1 || ret=1
+mkeys_refresh_on 6 || ret=1
+mkeys_status_on 6 > rndc.out.$n 2>&1 || ret=1
+# there should still be only two keys listed (for . and island.)
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 2 ] || ret=1
+# log when an unsupported algorithm is encountered during rollover
+wait_for_log 20 "Cannot compute tag for key in zone .: algorithm is unsupported" ns6/named.run || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc managed-keys' and views ($n)"
+ret=0
+rndccmd 10.53.0.7 managed-keys refresh in view1 > rndc.out.ns7.view1.test$n || ret=1
+grep "refreshing managed keys for 'view1'" rndc.out.ns7.view1.test$n > /dev/null || ret=1
+lines=$(wc -l < rndc.out.ns7.view1.test$n)
+[ "$lines" -eq 1 ] || ret=1
+rndccmd 10.53.0.7 managed-keys refresh > rndc.out.ns7.view2.test$n || ret=1
+lines=$(wc -l < rndc.out.ns7.view2.test$n)
+grep "refreshing managed keys for 'view1'" rndc.out.ns7.view2.test$n > /dev/null || ret=1
+grep "refreshing managed keys for 'view2'" rndc.out.ns7.view2.test$n > /dev/null || ret=1
+[ "$lines" -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc managed-keys' and islands of trust now that root is reachable ($n)"
+ret=0
+mkeys_sync_on 5
+mkeys_status_on 5 > rndc.out.$n 2>&1 || ret=1
+# there should be three keys listed now
+count=$(grep -c "keyid: " rndc.out.$n) || true
+[ "$count" -eq 3 ] || ret=1
+# theee lines indicating trust status
+count=$(grep -c "trust" rndc.out.$n) || true
+[ "$count" -eq 3 ] || ret=1
+# three indicates current trust
+count=$(grep -c "trusted since" rndc.out.$n) || true
+[ "$count" -eq 3 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/mkeys/tests_sh_mkeys.py b/bin/tests/system/mkeys/tests_sh_mkeys.py
new file mode 100644
index 0000000..141ee83
--- /dev/null
+++ b/bin/tests/system/mkeys/tests_sh_mkeys.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_mkeys(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/names/clean.sh b/bin/tests/system/names/clean.sh
new file mode 100644
index 0000000..1f8371b
--- /dev/null
+++ b/bin/tests/system/names/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.*.test*
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/named.pid
+rm -f ns*/named.conf
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
diff --git a/bin/tests/system/names/ns1/example.db b/bin/tests/system/names/ns1/example.db
new file mode 100644
index 0000000..a3e9f90
--- /dev/null
+++ b/bin/tests/system/names/ns1/example.db
@@ -0,0 +1,50 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns1
+ns1 A 10.53.0.1
+@ MX 0 m1.mail-servers.example.
+@ MX 0 m2.mail-servers.example.
+@ MX 0 m3.mail-servers.example.
+@ MX 0 m4.mail-servers.example.
+@ MX 0 m5.mail-servers.example.
+@ MX 0 m6.mail-servers.example.
+@ MX 0 m7.mail-servers.example.
+@ MX 0 m8.mail-servers.example.
+@ MX 0 m9.mail-servers.example.
+@ MX 0 m10.mail-servers.example.
+@ MX 0 m11.mail-servers.example.
+@ MX 0 m12.mail-servers.example.
+@ MX 0 m13.mail-servers.example.
+@ MX 0 m14.mail-servers.example.
+@ MX 0 m15.mail-servers.example.
+@ MX 0 m16.mail-servers.example.
+@ MX 0 m17.mail-servers.example.
+@ MX 0 m18.mail-servers.example.
+@ MX 0 m19.mail-servers.example.
+@ MX 0 m20.mail-servers.example.
+@ MX 0 m21.mail-servers.example.
+@ MX 0 m22.mail-servers.example.
+@ MX 0 m23.mail-servers.example.
+@ MX 0 m24.mail-servers.example.
+@ MX 0 m25.mail-servers.example.
+@ MX 0 m26.mail-servers.example.
+@ MX 0 m27.mail-servers.example.
+@ MX 0 m28.mail-servers.example.
+@ MX 0 m29.mail-servers.example.
diff --git a/bin/tests/system/names/ns1/named.conf.in b/bin/tests/system/names/ns1/named.conf.in
new file mode 100644
index 0000000..c065e38
--- /dev/null
+++ b/bin/tests/system/names/ns1/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+ dnssec-validation no;
+};
+
+
+view compress {
+ match-clients { 10.53.0.1/32; };
+ zone "example" {
+ type primary;
+ file "example.db";
+ };
+};
+
+view nocompress {
+ match-clients { 10.53.0.2/32; };
+ message-compression no;
+ zone "example" {
+ type primary;
+ file "example.db";
+ };
+};
diff --git a/bin/tests/system/names/setup.sh b/bin/tests/system/names/setup.sh
new file mode 100644
index 0000000..82240a7
--- /dev/null
+++ b/bin/tests/system/names/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/names/tests.sh b/bin/tests/system/names/tests.sh
new file mode 100644
index 0000000..9546298
--- /dev/null
+++ b/bin/tests/system/names/tests.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+nosea +stat +noquest +nocomm +nocmd -p ${PORT}"
+
+status=0
+
+echo_i "Getting message size with compression enabled"
+$DIG $DIGOPTS -b 10.53.0.1 @10.53.0.1 mx example > dig.compen.test
+COMPEN=$(grep ';; MSG SIZE' dig.compen.test |sed -e "s/.*: //g")
+cat dig.compen.test |grep -v ';;' |sort > dig.compen.sorted.test
+
+echo_i "Getting message size with compression disabled"
+$DIG $DIGOPTS -b 10.53.0.2 @10.53.0.1 mx example > dig.compdis.test
+COMPDIS=$(grep ';; MSG SIZE' dig.compdis.test |sed -e "s/.*: //g")
+cat dig.compdis.test |grep -v ';;' |sort > dig.compdis.sorted.test
+
+# the compression disabled message should be at least twice as large as with
+# compression disabled, but the content should be the same
+echo_i "Checking if responses are identical other than in message size"
+{ diff dig.compdis.sorted.test dig.compen.sorted.test >/dev/null; ret=$?; } || true
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "Checking if message with compression disabled is significantly larger"
+echo_i "Disabled $COMPDIS vs enabled $COMPEN"
+val=$(( (COMPDIS * 3 / 2) / COMPEN))
+if [ $val -le 1 ]; then
+ echo_i "failed"
+ status=$((status + 1))
+fi;
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/names/tests_sh_names.py b/bin/tests/system/names/tests_sh_names.py
new file mode 100644
index 0000000..ebeed2f
--- /dev/null
+++ b/bin/tests/system/names/tests_sh_names.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_names(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/notify/clean.sh b/bin/tests/system/notify/clean.sh
new file mode 100644
index 0000000..bf54325
--- /dev/null
+++ b/bin/tests/system/notify/clean.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f ./*/named.conf
+rm -f ./*/named.memstats
+rm -f ./*/named.port
+rm -f ./*/named.run ./*/named.run.prev
+rm -f awk.out.ns?.test*
+rm -f dig.out.?.ns5.test*
+rm -f dig.out.ns2.test*
+rm -f dig.out.ns3.test*
+rm -f dig.out.ns4.test*
+rm -f log.out
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
+rm -f ns*/named.lock
+rm -f ns2/example.db
+rm -f ns2/x21.db*
+rm -f ns3/example.bk
+rm -f ns4/x21.bk*
+rm -f ns5/x21.bk-b
+rm -f ns5/x21.bk-b.jnl
+rm -f ns5/x21.bk-c
+rm -f ns5/x21.bk-c.jnl
+rm -f ns5/x21.db.jnl
+rm -f tmp
diff --git a/bin/tests/system/notify/ns1/named.conf.in b/bin/tests/system/notify/ns1/named.conf.in
new file mode 100644
index 0000000..41a46be
--- /dev/null
+++ b/bin/tests/system/notify/ns1/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/notify/ns1/root.db b/bin/tests/system/notify/ns1/root.db
new file mode 100644
index 0000000..17780d1
--- /dev/null
+++ b/bin/tests/system/notify/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/notify/ns2/example1.db b/bin/tests/system/notify/ns2/example1.db
new file mode 100644
index 0000000..3b8d33b
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example1.db
@@ -0,0 +1,144 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 300 ; refresh (300 seconds)
+ 300 ; retry (300 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.0.0.1
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.
+ns A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/notify/ns2/example2.db b/bin/tests/system/notify/ns2/example2.db
new file mode 100644
index 0000000..c762dd6
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example2.db
@@ -0,0 +1,144 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 2 ; serial
+ 300 ; refresh (300 seconds)
+ 300 ; retry (300 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.0.0.2
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.
+ns A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/notify/ns2/example3.db b/bin/tests/system/notify/ns2/example3.db
new file mode 100644
index 0000000..dd3371b
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example3.db
@@ -0,0 +1,144 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 3 ; serial
+ 300 ; refresh (300 seconds)
+ 300 ; retry (300 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.0.0.3
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.
+ns A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/notify/ns2/example4.db b/bin/tests/system/notify/ns2/example4.db
new file mode 100644
index 0000000..86d9bf2
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example4.db
@@ -0,0 +1,144 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 4 ; serial
+ 300 ; refresh (300 seconds)
+ 300 ; retry (300 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.0.0.4
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.
+ns A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/notify/ns2/generic.db b/bin/tests/system/notify/ns2/generic.db
new file mode 100644
index 0000000..108b552
--- /dev/null
+++ b/bin/tests/system/notify/ns2/generic.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 300 ; refresh (300 seconds)
+ 300 ; retry (300 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
diff --git a/bin/tests/system/notify/ns2/named.conf.in b/bin/tests/system/notify/ns2/named.conf.in
new file mode 100644
index 0000000..bc5af9d
--- /dev/null
+++ b/bin/tests/system/notify/ns2/named.conf.in
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ startup-notify-rate 5;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ // Check that named can handle a empty also-notify.
+ also-notify { /* empty */ };
+};
+
+# use both 'primaries' and 'masters' to test that they
+# can work correctly together.
+primaries noport { 10.53.0.4; };
+masters x21 port @EXTRAPORT1@ { noport; };
+
+zone x1 {
+ type primary;
+ file "generic.db";
+ also-notify { 10.53.0.3; };
+ notify-source 10.53.0.2 port @EXTRAPORT2@;
+ notify primary-only;
+};
+zone x2 {
+ type primary;
+ file "generic.db";
+ also-notify { 10.53.0.3; };
+ notify master-only; # test old syntax
+};
+
+zone x3 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x4 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x5 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x6 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x7 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x8 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x9 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x10 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x11 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x12 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x13 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x14 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x15 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x16 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x17 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x18 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x19 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x20 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; };
+zone x21 { type primary; file "x21.db"; allow-update { any; }; also-notify { x21; }; };
diff --git a/bin/tests/system/notify/ns3/named.conf.in b/bin/tests/system/notify/ns3/named.conf.in
new file mode 100644
index 0000000..ee21f92
--- /dev/null
+++ b/bin/tests/system/notify/ns3/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "example.bk";
+ # non-responsive notify recipient (no reply, no ICMP errors)
+ also-notify { 10.53.10.53; };
+};
+
+zone "notify-source-port-test" {
+ type primary;
+ file "notify-source-port-test.db";
+ notify-source 10.53.0.3 port @EXTRAPORT2@;
+};
diff --git a/bin/tests/system/notify/ns3/notify-source-port-test.db b/bin/tests/system/notify/ns3/notify-source-port-test.db
new file mode 100644
index 0000000..221fca1
--- /dev/null
+++ b/bin/tests/system/notify/ns3/notify-source-port-test.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+notify-source-port-test. SOA mname1. . (
+ 1 ; serial
+ 300 ; refresh (300 seconds)
+ 300 ; retry (300 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+notify-source-port-test. NS ns2.notify-source-port-test.
+ns2.notify-source-port-test. A 10.53.0.2
+notify-source-port-test. NS ns3.notify-source-port-test.
+ns3.notify-source-port-test. A 10.53.0.3
diff --git a/bin/tests/system/notify/ns4/named.conf.in b/bin/tests/system/notify/ns4/named.conf.in
new file mode 100644
index 0000000..95a0ff9
--- /dev/null
+++ b/bin/tests/system/notify/ns4/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @EXTRAPORT1@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "x21" {
+ type secondary;
+ primaries { 10.53.0.2 port @PORT@; };
+ file "x21.bk";
+};
diff --git a/bin/tests/system/notify/ns4/named.port.in b/bin/tests/system/notify/ns4/named.port.in
new file mode 100644
index 0000000..8e94a3c
--- /dev/null
+++ b/bin/tests/system/notify/ns4/named.port.in
@@ -0,0 +1 @@
+@EXTRAPORT1@
diff --git a/bin/tests/system/notify/ns5/named.conf.in b/bin/tests/system/notify/ns5/named.conf.in
new file mode 100644
index 0000000..8d635e3
--- /dev/null
+++ b/bin/tests/system/notify/ns5/named.conf.in
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key "a" {
+ algorithm "hmac-md5";
+ secret "aaaaaaaaaaaaaaaaaaaa";
+};
+
+key "b" {
+ algorithm "hmac-md5";
+ secret "bbbbbbbbbbbbbbbbbbbb";
+};
+
+key "c" {
+ algorithm "hmac-md5";
+ secret "cccccccccccccccccccc";
+};
+
+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;
+ notify yes;
+ dnssec-validation no;
+};
+
+view "a" {
+ match-clients { key "a"; };
+ zone "x21" {
+ type primary;
+ also-notify { 10.53.0.5 key "b"; 10.53.0.5 key "c"; };
+ file "x21.db";
+ allow-update { any; };
+ };
+};
+
+view "b" {
+ match-clients { key "b"; };
+ zone "x21" {
+ type secondary;
+ primaries { 10.53.0.5 key "a"; };
+ file "x21.bk-b";
+ notify no;
+ };
+};
+
+view "c" {
+ match-clients { key "c"; };
+ zone "x21" {
+ type secondary;
+ primaries { 10.53.0.5 key "a"; };
+ file "x21.bk-c";
+ notify no;
+ };
+};
diff --git a/bin/tests/system/notify/ns5/x21.db b/bin/tests/system/notify/ns5/x21.db
new file mode 100644
index 0000000..8f2ac7d
--- /dev/null
+++ b/bin/tests/system/notify/ns5/x21.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 300 ; refresh (300 seconds)
+ 300 ; retry (300 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns5
+ns5 A 10.53.0.5
+a A 10.0.0.1
diff --git a/bin/tests/system/notify/setup.sh b/bin/tests/system/notify/setup.sh
new file mode 100644
index 0000000..19c41fc
--- /dev/null
+++ b/bin/tests/system/notify/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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 ns4/named.port.in ns4/named.port
+
+cp -f ns2/example1.db ns2/example.db
+cp -f ns2/generic.db ns2/x21.db
diff --git a/bin/tests/system/notify/tests.sh b/bin/tests/system/notify/tests.sh
new file mode 100644
index 0000000..ba9dfe3
--- /dev/null
+++ b/bin/tests/system/notify/tests.sh
@@ -0,0 +1,220 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck disable=SC2034
+. ../conf.sh
+
+dig_plus_opts() {
+ $DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p "${PORT}" "$@"
+}
+
+status=0
+n=0
+
+test_start() {
+ n=$((n+1))
+ echo_i "$* ($n)"
+ ret=0
+}
+
+test_end() {
+ [ $ret = 0 ] || echo_i "failed"
+ status=$((status + ret))
+}
+
+#
+# Wait up to 10 seconds for the servers to finish starting before testing.
+#
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $DIG +tcp -p "${PORT}" example @10.53.0.2 soa > dig.out.ns2.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+ grep "flags:.* aa[ ;]" dig.out.ns2.test$n > /dev/null || ret=1
+ $DIG +tcp -p "${PORT}" example @10.53.0.3 soa > dig.out.ns3.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+ grep "flags:.* aa[ ;]" dig.out.ns3.test$n > /dev/null || ret=1
+ nr=$(grep -c 'x[0-9].*sending notify to' ns2/named.run)
+ [ "$nr" -eq 20 ] || ret=1
+ [ $ret = 0 ] && break
+ sleep 1
+done
+
+test_start "checking initial status"
+
+dig_plus_opts a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "10.0.0.1" dig.out.ns2.test$n > /dev/null || ret=1
+
+dig_plus_opts a.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+grep "10.0.0.1" dig.out.ns3.test$n > /dev/null || ret=1
+
+digcomp dig.out.ns2.test$n dig.out.ns3.test$n || ret=1
+
+test_end
+
+test_start "checking startup notify rate limit"
+awk '/x[0-9].*sending notify to/ {
+ split($2, a, ":");
+ this = a[1] * 3600 + a[2] * 60 + a[3];
+ if (lasta1 && lasta1 > a[1]) {
+ fix = 3600 * 24;
+ }
+ this += fix;
+ if (last) {
+ delta = this - last;
+ print delta;
+
+ total += delta;
+ if (!maxdelta || delta > maxdelta) {
+ maxdelta = delta;
+ }
+ if (!mindelta || delta < mindelta) {
+ mindelta = delta;
+ }
+ }
+ lasta1 = a[1];
+ last = this;
+ count++;
+}
+END {
+ average = total / count;
+ print "mindelta:", mindelta;
+ print "maxdelta:" maxdelta;
+ print "count:", count;
+ print "average:", average;
+ if (average < 0.180) exit(1);
+ if (count < 20) exit(1);
+}' ns2/named.run > awk.out.ns2.test$n || ret=1
+test_end
+
+nextpart ns3/named.run > /dev/null
+
+sleep 1 # make sure filesystem time stamp is newer for reload.
+rm -f ns2/example.db
+cp -f ns2/example2.db ns2/example.db
+echo_i "reloading with example2 using HUP and waiting up to 45 seconds"
+kill -HUP "$(cat ns2/named.pid)"
+wait_for_log_re 45 "transfer of 'example/IN' from 10.53.0.2#.*success" ns3/named.run
+
+test_start "checking notify message was logged"
+grep 'notify from 10.53.0.2#[0-9][0-9]*: serial 2$' ns3/named.run > /dev/null || ret=1
+test_end
+
+test_start "checking example2 loaded"
+dig_plus_opts a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "10.0.0.2" dig.out.ns2.test$n > /dev/null || ret=1
+test_end
+
+test_start "checking example2 contents have been transferred after HUP reload"
+
+dig_plus_opts a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "10.0.0.2" dig.out.ns2.test$n > /dev/null || ret=1
+
+dig_plus_opts a.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+grep "10.0.0.2" dig.out.ns3.test$n > /dev/null || ret=1
+
+digcomp dig.out.ns2.test$n dig.out.ns3.test$n || ret=1
+
+test_end
+
+echo_i "stopping primary and restarting with example4 then waiting up to 45 seconds"
+stop_server ns2
+
+rm -f ns2/example.db
+cp -f ns2/example4.db ns2/example.db
+
+start_server --noclean --restart --port "${PORT}" ns2
+wait_for_log_re 45 "transfer of 'example/IN' from 10.53.0.2#.*success" ns3/named.run
+
+test_start "checking notify message was logged"
+grep 'notify from 10.53.0.2#[0-9][0-9]*: serial 4$' ns3/named.run > /dev/null || ret=1
+test_end
+
+test_start "checking example4 loaded"
+dig_plus_opts a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "10.0.0.4" dig.out.ns2.test$n > /dev/null || ret=1
+test_end
+
+test_start "checking example4 contents have been transferred after restart"
+
+dig_plus_opts a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "10.0.0.4" dig.out.ns2.test$n > /dev/null || ret=1
+
+dig_plus_opts a.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+grep "10.0.0.4" dig.out.ns3.test$n > /dev/null || ret=1
+
+digcomp dig.out.ns2.test$n dig.out.ns3.test$n || ret=1
+
+test_end
+
+test_start "checking notify to alternate port with primary server inheritance"
+$NSUPDATE << EOF
+server 10.53.0.2 ${PORT}
+zone x21
+update add added.x21 0 in txt "test string"
+send
+EOF
+fn="dig.out.ns4.test$n"
+for i in 1 2 3 4 5 6 7 8 9
+do
+ dig_plus_opts added.x21. @10.53.0.4 txt -p "$EXTRAPORT1" > "$fn" || ret=1
+ grep "test string" "$fn" > /dev/null && break
+ sleep 1
+done
+grep "test string" "$fn" > /dev/null || ret=1
+test_end
+
+test_start "checking notify to multiple views using tsig"
+$NSUPDATE << EOF
+server 10.53.0.5 ${PORT}
+zone x21
+key a aaaaaaaaaaaaaaaaaaaa
+update add added.x21 0 in txt "test string"
+send
+EOF
+fnb="dig.out.b.ns5.test$n"
+fnc="dig.out.c.ns5.test$n"
+for i in 1 2 3 4 5 6 7 8 9
+do
+ dig_plus_opts added.x21. -y b:bbbbbbbbbbbbbbbbbbbb @10.53.0.5 \
+ txt > "$fnb" || ret=1
+ dig_plus_opts added.x21. -y c:cccccccccccccccccccc @10.53.0.5 \
+ txt > "$fnc" || ret=1
+ grep "test string" "$fnb" > /dev/null &&
+ grep "test string" "$fnc" > /dev/null &&
+ break
+ sleep 1
+done
+grep "test string" "$fnb" > /dev/null || ret=1
+grep "test string" "$fnc" > /dev/null || ret=1
+grep "sending notify to 10.53.0.5#[0-9]* : TSIG (b)" ns5/named.run > /dev/null || ret=1
+grep "sending notify to 10.53.0.5#[0-9]* : TSIG (c)" ns5/named.run > /dev/null || ret=1
+test_end
+
+test_start "checking notify-source uses port option correctly"
+grep "10.53.0.3#${EXTRAPORT2}: received notify for zone 'notify-source-port-test'" ns2/named.run > /dev/null || ret=1
+test_end
+
+# notify messages were sent to unresponsive 10.53.10.53 during the tests
+# above, which should time out at some point; we need to wait for them to
+# appear in the logs in case the tests run faster than the notify timeouts
+
+test_start "checking notify retries expire within 45 seconds"
+nextpartreset ns3/named.run
+wait_for_log 45 'retries exceeded' ns3/named.run || ret=1
+test_end
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/notify/tests_sh_notify.py b/bin/tests/system/notify/tests_sh_notify.py
new file mode 100644
index 0000000..105b2d8
--- /dev/null
+++ b/bin/tests/system/notify/tests_sh_notify.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_notify(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/nsec3/clean.sh b/bin/tests/system/nsec3/clean.sh
new file mode 100644
index 0000000..7ca6829
--- /dev/null
+++ b/bin/tests/system/nsec3/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f dig.out.* rndc.signing.* update.out.* verify.out.*
+rm -f ns*/named.conf ns*/named.memstats ns*/named.run*
+rm -f ns*/*.jnl ns*/*.jbk ns*/managed-keys.bind
+rm -f ns*/K*.private ns*/K*.key ns*/K*.state
+rm -f ns*/dsset-* ns*/*.db ns*/*.db.signed
+rm -f ns*/keygen.out.* ns*/settime.out.*
+rm -f created.key-* *.created unused.key-*
diff --git a/bin/tests/system/nsec3/ns2/named.conf.in b/bin/tests/system/nsec3/ns2/named.conf.in
new file mode 100644
index 0000000..f4cc1b0
--- /dev/null
+++ b/bin/tests/system/nsec3/ns2/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+dnssec-policy "nsec3" {
+ nsec3param;
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ allow-transfer { any; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "nsec3-xfr-inline.kasp" {
+ type primary;
+ file "nsec3-xfr-inline.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3";
+};
diff --git a/bin/tests/system/nsec3/ns2/setup.sh b/bin/tests/system/nsec3/ns2/setup.sh
new file mode 100644
index 0000000..1cbe02f
--- /dev/null
+++ b/bin/tests/system/nsec3/ns2/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns2/setup.sh"
+
+zone="nsec3-xfr-inline.kasp"
+echo_i "setting up zone: $zone"
+zonefile="${zone}.db"
+cp template.db.in "$zonefile"
diff --git a/bin/tests/system/nsec3/ns2/template.db.in b/bin/tests/system/nsec3/ns2/template.db.in
new file mode 100644
index 0000000..8379c37
--- /dev/null
+++ b/bin/tests/system/nsec3/ns2/template.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns2
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+
diff --git a/bin/tests/system/nsec3/ns3/named.conf.in b/bin/tests/system/nsec3/ns3/named.conf.in
new file mode 100644
index 0000000..de09774
--- /dev/null
+++ b/bin/tests/system/nsec3/ns3/named.conf.in
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+dnssec-policy "nsec" {
+ // no need to change configuration: if no 'nsec3param' is set,
+ // NSEC will be used;
+};
+
+dnssec-policy "rsasha1" {
+ keys {
+ csk lifetime unlimited algorithm rsasha1;
+ };
+};
+
+dnssec-policy "nsec3" {
+ nsec3param;
+};
+
+dnssec-policy "optout" {
+ nsec3param optout yes;
+};
+
+dnssec-policy "nsec3-other" {
+ nsec3param iterations 11 optout yes salt-length 8;
+};
+
+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; };
+ allow-transfer { any; };
+ recursion no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+/* This zone starts with NSEC, but will be reconfigured to use NSEC3. */
+zone "nsec-to-nsec3.kasp" {
+ type primary;
+ file "nsec-to-nsec3.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec";
+};
+
+/*
+ * This zone starts with NSEC, but will be reconfigured to use NSEC3.
+ * This should work despite the incompatible RSAHSHA1 algorithm,
+ * because the DS is still in hidden state.
+ */
+zone "rsasha1-to-nsec3.kasp" {
+ type primary;
+ file "rsasha1-to-nsec3.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha1";
+};
+
+/*
+ * This zone starts with NSEC, but will be reconfigured to use NSEC3.
+ * This should block because RSASHA1 is not compatible with NSEC3,
+ * and the DS is published.
+ */
+zone "rsasha1-to-nsec3-wait.kasp" {
+ type primary;
+ file "rsasha1-to-nsec3-wait.kasp.db";
+ inline-signing yes;
+ dnssec-policy "rsasha1";
+};
+
+/*
+ * This zone starts with NSEC3, but will be reconfigured to use NSEC with an
+ * NSEC only algorithm. This should work despite the incompatible RSAHSHA1
+ * algorithm, because the DS is still in hidden state.
+ */
+zone "nsec3-to-rsasha1.kasp" {
+ type primary;
+ file "nsec3-to-rsasha1.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3";
+};
+
+/*
+ * This zone starts with NSEC3, but will be reconfigured to use NSEC with an
+ * NSEC only algorithm. This should also be fine because we are allowed
+ * to change to NSEC with any algorithm, then we can also publish the new
+ * DNSKEY and signatures of the RSASHA1 algorithm.
+ */
+zone "nsec3-to-rsasha1-ds.kasp" {
+ type primary;
+ file "nsec3-to-rsasha1-ds.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3";
+};
+
+
+/* These zones use the default NSEC3 settings. */
+zone "nsec3.kasp" {
+ type primary;
+ file "nsec3.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3";
+};
+
+zone "nsec3-dynamic.kasp" {
+ type primary;
+ file "nsec3-dynamic.kasp.db";
+ dnssec-policy "nsec3";
+ allow-update { any; };
+};
+
+/* This zone uses non-default NSEC3 settings. */
+zone "nsec3-other.kasp" {
+ type primary;
+ file "nsec3-other.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3-other";
+};
+
+/* These zones will be reconfigured to use other NSEC3 settings. */
+zone "nsec3-change.kasp" {
+ type primary;
+ file "nsec3-change.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3";
+};
+
+zone "nsec3-dynamic-change.kasp" {
+ type primary;
+ file "nsec3-dynamic-change.kasp.db";
+ dnssec-policy "nsec3";
+ allow-update { any; };
+};
+
+/* The zone will be reconfigured to use opt-out. */
+zone "nsec3-to-optout.kasp" {
+ type primary;
+ file "nsec3-to-optout.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3";
+};
+
+/* The zone will be reconfigured to disable opt-out. */
+zone "nsec3-from-optout.kasp" {
+ type primary;
+ file "nsec3-from-optout.kasp.db";
+ inline-signing yes;
+ dnssec-policy "optout";
+};
+
+/* The zone starts with NSEC3, but will be reconfigured to use NSEC. */
+zone "nsec3-to-nsec.kasp" {
+ type primary;
+ file "nsec3-to-nsec.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3";
+};
+
+/* The zone fails to load, this should not prevent shutdown. */
+zone "nsec3-fails-to-load.kasp" {
+ type primary;
+ file "nsec3-fails-to-load.kasp.db";
+ dnssec-policy "nsec3";
+ allow-update { any; };
+};
+
+/* These zones switch from dynamic to inline-signing or vice versa. */
+zone "nsec3-dynamic-to-inline.kasp" {
+ type primary;
+ file "nsec3-dynamic-to-inline.kasp.db";
+ dnssec-policy "nsec3";
+ allow-update { any; };
+};
+
+zone "nsec3-inline-to-dynamic.kasp" {
+ type primary;
+ file "nsec3-inline-to-dynamic.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3";
+};
+
+/* Test adding a NSEC3 record to an inline-signing dnssec-policy zone. */
+zone "nsec3-dynamic-update-inline.kasp" {
+ type primary;
+ file "nsec3-dynamic-update-inline.kasp.db";
+ inline-signing yes;
+ allow-update { any; };
+ dnssec-policy "nsec";
+};
+
+zone "nsec3-xfr-inline.kasp" {
+ type secondary;
+ file "nsec3-xfr-inline.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec";
+ primaries { 10.53.0.2; };
+};
diff --git a/bin/tests/system/nsec3/ns3/named2.conf.in b/bin/tests/system/nsec3/ns3/named2.conf.in
new file mode 100644
index 0000000..084bba3
--- /dev/null
+++ b/bin/tests/system/nsec3/ns3/named2.conf.in
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+dnssec-policy "nsec" {
+ // no need to change configuration: if no 'nsec3param' is set,
+ // NSEC will be used;
+};
+
+dnssec-policy "rsasha1" {
+ keys {
+ csk lifetime unlimited algorithm rsasha1;
+ };
+};
+
+dnssec-policy "nsec3" {
+ nsec3param;
+};
+
+dnssec-policy "optout" {
+ nsec3param optout yes;
+};
+
+dnssec-policy "nsec3-other" {
+ nsec3param iterations 11 optout yes salt-length 0;
+};
+
+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; };
+ allow-transfer { any; };
+ recursion no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+/* This zone starts with NSEC, but will be reconfigured to use NSEC3. */
+zone "nsec-to-nsec3.kasp" {
+ type primary;
+ file "nsec-to-nsec3.kasp.db";
+ inline-signing yes;
+ //dnssec-policy "nsec";
+ dnssec-policy "nsec3";
+};
+
+/*
+ * This zone starts with NSEC, but will be reconfigured to use NSEC3.
+ * This should work despite the incompatible RSAHSHA1 algorithm,
+ * because the DS is still in hidden state.
+ */
+zone "rsasha1-to-nsec3.kasp" {
+ type primary;
+ file "rsasha1-to-nsec3.kasp.db";
+ inline-signing yes;
+ //dnssec-policy "rsasha1";
+ dnssec-policy "nsec3";
+};
+
+/*
+ * This zone starts with NSEC, but will be reconfigured to use NSEC3.
+ * This should block because RSASHA1 is not compatible with NSEC3,
+ * and the DS is published.
+ */
+zone "rsasha1-to-nsec3-wait.kasp" {
+ type primary;
+ file "rsasha1-to-nsec3-wait.kasp.db";
+ inline-signing yes;
+ //dnssec-policy "rsasha1";
+ dnssec-policy "nsec3";
+};
+
+/*
+ * This zone starts with NSEC3, but will be reconfigured to use NSEC with an
+ * NSEC only algorithm. This should work despite the incompatible RSAHSHA1
+ * algorithm, because the DS is still in hidden state.
+ */
+zone "nsec3-to-rsasha1.kasp" {
+ type primary;
+ file "nsec3-to-rsasha1.kasp.db";
+ inline-signing yes;
+ //dnssec-policy "nsec3";
+ dnssec-policy "rsasha1";
+};
+
+/*
+ * This zone starts with NSEC3, but will be reconfigured to use NSEC with an
+ * NSEC only algorithm. This should also be fine because we are allowed
+ * to change to NSEC with any algorithm, then we can also publish the new
+ * DNSKEY and signatures of the RSASHA1 algorithm.
+ */
+zone "nsec3-to-rsasha1-ds.kasp" {
+ type primary;
+ file "nsec3-to-rsasha1-ds.kasp.db";
+ inline-signing yes;
+ //dnssec-policy "nsec3";
+ dnssec-policy "rsasha1";
+};
+
+/* These zones use the default NSEC3 settings. */
+zone "nsec3.kasp" {
+ type primary;
+ file "nsec3.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3";
+};
+
+zone "nsec3-dynamic.kasp" {
+ type primary;
+ file "nsec3-dynamic.kasp.db";
+ dnssec-policy "nsec3";
+ allow-update { any; };
+};
+
+/* This zone uses non-default NSEC3 settings. */
+zone "nsec3-other.kasp" {
+ type primary;
+ file "nsec3-other.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3-other";
+};
+
+/* These zone will be reconfigured to use other NSEC3 settings. */
+zone "nsec3-change.kasp" {
+ type primary;
+ file "nsec3-change.kasp.db";
+ inline-signing yes;
+ //dnssec-policy "nsec3";
+ dnssec-policy "nsec3-other";
+};
+
+zone "nsec3-dynamic-change.kasp" {
+ type primary;
+ file "nsec3-dynamic-change.kasp.db";
+ //dnssec-policy "nsec3";
+ dnssec-policy "nsec3-other";
+ allow-update { any; };
+};
+
+/* The zone will be reconfigured to use opt-out. */
+zone "nsec3-to-optout.kasp" {
+ type primary;
+ file "nsec3-to-optout.kasp.db";
+ inline-signing yes;
+ //dnssec-policy "nsec3";
+ dnssec-policy "optout";
+};
+
+/* The zone will be reconfigured to disable opt-out. */
+zone "nsec3-from-optout.kasp" {
+ type primary;
+ file "nsec3-from-optout.kasp.db";
+ inline-signing yes;
+ //dnssec-policy "optout";
+ dnssec-policy "nsec3";
+};
+
+/* The zone starts with NSEC3, but will be reconfigured to use NSEC. */
+zone "nsec3-to-nsec.kasp" {
+ type primary;
+ file "nsec3-to-nsec.kasp.db";
+ inline-signing yes;
+ //dnssec-policy "nsec3";
+ dnssec-policy "nsec";
+};
+
+/* The zone fails to load, but is fixed after a reload. */
+zone "nsec3-fails-to-load.kasp" {
+ type primary;
+ file "nsec3-fails-to-load.kasp.db";
+ dnssec-policy "nsec3";
+ allow-update { any; };
+};
+
+/* These zones switch from dynamic to inline-signing or vice versa. */
+zone "nsec3-dynamic-to-inline.kasp" {
+ type primary;
+ file "nsec3-dynamic-to-inline.kasp.db";
+ inline-signing yes;
+ dnssec-policy "nsec3";
+ allow-update { any; };
+};
+
+zone "nsec3-inline-to-dynamic.kasp" {
+ type primary;
+ file "nsec3-inline-to-dynamic.kasp.db";
+ inline-signing no;
+ dnssec-policy "nsec3";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/nsec3/ns3/nsec3-fails-to-load.kasp.db.in b/bin/tests/system/nsec3/ns3/nsec3-fails-to-load.kasp.db.in
new file mode 100644
index 0000000..77b0d10
--- /dev/null
+++ b/bin/tests/system/nsec3/ns3/nsec3-fails-to-load.kasp.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ IN SOA kasp. nsec3-fails-to-load.kasp. (
+ 1 ; serial
+ 30 ; refresh (30 seconds)
+ 10 ; retry (10 seconds)
+ 3600000 ; expire (5 weeks 6 days 16 hours)
+ 300 ; minimum (5 minutes)
+ )
+ NS nsec3-fails-to-load.kasp.
diff --git a/bin/tests/system/nsec3/ns3/setup.sh b/bin/tests/system/nsec3/ns3/setup.sh
new file mode 100644
index 0000000..68bc2e4
--- /dev/null
+++ b/bin/tests/system/nsec3/ns3/setup.sh
@@ -0,0 +1,60 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+echo_i "ns3/setup.sh"
+
+setup() {
+ zone="$1"
+ echo_i "setting up zone: $zone"
+ zonefile="${zone}.db"
+ infile="${zone}.db.infile"
+ cp template.db.in "$zonefile"
+}
+
+for zn in nsec-to-nsec3 nsec3 nsec3-other nsec3-change nsec3-to-nsec \
+ nsec3-to-optout nsec3-from-optout nsec3-dynamic \
+ nsec3-dynamic-change nsec3-dynamic-to-inline \
+ nsec3-inline-to-dynamic nsec3-dynamic-update-inline
+do
+ setup "${zn}.kasp"
+done
+
+if (cd ..; $SHELL ../testcrypto.sh -q RSASHA1)
+then
+ for zn in rsasha1-to-nsec3 rsasha1-to-nsec3-wait nsec3-to-rsasha1 \
+ nsec3-to-rsasha1-ds
+ do
+ setup "${zn}.kasp"
+ done
+
+ longago="now-1y"
+ keytimes="-P ${longago} -A ${longago}"
+ O="omnipresent"
+
+ zone="rsasha1-to-nsec3-wait.kasp"
+ CSK=$($KEYGEN -k "rsasha1" -l named.conf $keytimes $zone 2> keygen.out.$zone)
+ echo_i "Created key file $CSK"
+ $SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$CSK" > settime.out.$zone 2>&1
+
+ zone="nsec3-to-rsasha1-ds.kasp"
+ CSK=$($KEYGEN -k "default" -l named.conf $keytimes $zone 2> keygen.out.$zone)
+ echo_i "Created key file $CSK"
+ $SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$CSK" > settime.out.$zone 2>&1
+else
+ echo_i "skip: skip rsasha1 zones - signing with RSASHA1 not supported"
+fi
+
+cp nsec3-fails-to-load.kasp.db.in nsec3-fails-to-load.kasp.db
diff --git a/bin/tests/system/nsec3/ns3/template.db.in b/bin/tests/system/nsec3/ns3/template.db.in
new file mode 100644
index 0000000..010b05b
--- /dev/null
+++ b/bin/tests/system/nsec3/ns3/template.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+
+ NS ns3
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+
diff --git a/bin/tests/system/nsec3/setup.sh b/bin/tests/system/nsec3/setup.sh
new file mode 100644
index 0000000..bdd1ae9
--- /dev/null
+++ b/bin/tests/system/nsec3/setup.sh
@@ -0,0 +1,30 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+$SHELL clean.sh
+
+copy_setports ns2/named.conf.in ns2/named.conf
+(
+ cd ns2
+ $SHELL setup.sh
+)
+copy_setports ns3/named.conf.in ns3/named.conf
+(
+ cd ns3
+ $SHELL setup.sh
+)
diff --git a/bin/tests/system/nsec3/tests.sh b/bin/tests/system/nsec3/tests.sh
new file mode 100644
index 0000000..117bf63
--- /dev/null
+++ b/bin/tests/system/nsec3/tests.sh
@@ -0,0 +1,553 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+# shellcheck source=kasp.sh
+. ../kasp.sh
+
+# Log errors and increment $ret.
+log_error() {
+ echo_i "error: $1"
+ ret=$((ret+1))
+}
+
+# Call dig with default options.
+dig_with_opts() {
+ $DIG +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
+}
+
+# Call rndc.
+rndccmd() {
+ "$RNDC" -c ../common/rndc.conf -p "$CONTROLPORT" -s "$@"
+}
+
+# Set zone name ($1) and policy ($2) for testing nsec3.
+set_zone_policy() {
+ ZONE=$1
+ POLICY=$2
+ NUM_KEYS=$3
+ DNSKEY_TTL=$4
+}
+# Set expected NSEC3 parameters: flags ($1), iterations ($2), and
+# salt length ($3).
+set_nsec3param() {
+ FLAGS=$1
+ ITERATIONS=$2
+ SALTLEN=$3
+ # Reset salt.
+ SALT=""
+}
+
+# Set expected default dnssec-policy keys values.
+set_key_default_values() {
+ key_clear $1
+
+ set_keyrole $1 "csk"
+ set_keylifetime $1 "0"
+ set_keyalgorithm $1 "13" "ECDSAP256SHA256" "256"
+ set_keysigning $1 "yes"
+ set_zonesigning $1 "yes"
+
+ set_keystate $1 "GOAL" "omnipresent"
+ set_keystate $1 "STATE_DNSKEY" "rumoured"
+ set_keystate $1 "STATE_KRRSIG" "rumoured"
+ set_keystate $1 "STATE_ZRRSIG" "rumoured"
+ set_keystate $1 "STATE_DS" "hidden"
+}
+
+# Set expected rsasha1 dnssec-policy keys values.
+set_key_rsasha1_values() {
+ key_clear $1
+
+ set_keyrole $1 "csk"
+ set_keylifetime $1 "0"
+ set_keyalgorithm $1 "5" "RSASHA1" "2048"
+ set_keysigning $1 "yes"
+ set_zonesigning $1 "yes"
+
+ set_keystate $1 "GOAL" "omnipresent"
+ set_keystate $1 "STATE_DNSKEY" "rumoured"
+ set_keystate $1 "STATE_KRRSIG" "rumoured"
+ set_keystate $1 "STATE_ZRRSIG" "rumoured"
+ set_keystate $1 "STATE_DS" "hidden"
+}
+
+# Update the key states.
+set_key_states() {
+ set_keystate $1 "GOAL" "$2"
+ set_keystate $1 "STATE_DNSKEY" "$3"
+ set_keystate $1 "STATE_KRRSIG" "$4"
+ set_keystate $1 "STATE_ZRRSIG" "$5"
+ set_keystate $1 "STATE_DS" "$6"
+}
+
+# The apex NSEC3PARAM record indicates that it is signed.
+_wait_for_nsec3param() {
+ dig_with_opts +noquestion "@${SERVER}" "$ZONE" NSEC3PARAM > "dig.out.test$n.wait" || return 1
+ grep "${ZONE}\..*IN.*NSEC3PARAM.*1.*0.*${ITERATIONS}.*${SALT}" "dig.out.test$n.wait" > /dev/null || return 1
+ grep "${ZONE}\..*IN.*RRSIG" "dig.out.test$n.wait" > /dev/null || return 1
+ return 0
+}
+# The apex NSEC record indicates that it is signed.
+_wait_for_nsec() {
+ dig_with_opts +noquestion "@${SERVER}" "$ZONE" NSEC > "dig.out.test$n.wait" || return 1
+ grep "NS SOA" "dig.out.test$n.wait" > /dev/null || return 1
+ grep "${ZONE}\..*IN.*RRSIG" "dig.out.test$n.wait" > /dev/null || return 1
+ grep "${ZONE}\..*IN.*NSEC3PARAM" "dig.out.test$n.wait" > /dev/null && return 1
+ return 0
+}
+
+# Wait for the zone to be signed.
+wait_for_zone_is_signed() {
+ n=$((n+1))
+ ret=0
+ echo_i "wait for ${ZONE} to be signed with $1 ($n)"
+
+ if [ "$1" = "nsec3" ]; then
+ retry_quiet 10 _wait_for_nsec3param || log_error "wait for ${ZONE} to be signed failed"
+ else
+ retry_quiet 10 _wait_for_nsec || log_error "wait for ${ZONE} to be signed failed"
+ fi
+
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+# Test: check DNSSEC verify
+_check_dnssec_verify() {
+ dig_with_opts @$SERVER "${ZONE}" AXFR > "dig.out.test$n.axfr.$ZONE" || return 1
+ $VERIFY -z -o "$ZONE" "dig.out.test$n.axfr.$ZONE" > "verify.out.test$n.$ZONE" 2>&1 || return 1
+ return 0
+}
+
+# Test: check NSEC in answers
+_check_nsec_nsec3param() {
+ dig_with_opts +noquestion @$SERVER "${ZONE}" NSEC3PARAM > "dig.out.test$n.nsec3param.$ZONE" || return 1
+ grep "NSEC3PARAM" "dig.out.test$n.nsec3param.$ZONE" > /dev/null && return 1
+ return 0
+}
+
+_check_nsec_nxdomain() {
+ dig_with_opts @$SERVER "nosuchname.${ZONE}" > "dig.out.test$n.nxdomain.$ZONE" || return 1
+ grep "${ZONE}.*IN.*NSEC.*NS.*SOA.*RRSIG.*NSEC.*DNSKEY" "dig.out.test$n.nxdomain.$ZONE" > /dev/null || return 1
+ grep "NSEC3" "dig.out.test$n.nxdomain.$ZONE" > /dev/null && return 1
+ return 0
+}
+
+check_nsec() {
+ wait_for_zone_is_signed "nsec"
+
+ n=$((n+1))
+ echo_i "check DNSKEY rrset is signed correctly for zone ${ZONE} ($n)"
+ ret=0
+ check_keys
+ retry_quiet 10 _check_apex_dnskey || log_error "bad DNSKEY RRset for zone ${ZONE}"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "verify DNSSEC for zone ${ZONE} ($n)"
+ ret=0
+ retry_quiet 10 _check_dnssec_verify || log_error "DNSSEC verify failed for zone ${ZONE}"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check NSEC3PARAM response for zone ${ZONE} ($n)"
+ ret=0
+ retry_quiet 10 _check_nsec_nsec3param || log_error "unexpected NSEC3PARAM in response for zone ${ZONE}"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check NXDOMAIN response for zone ${ZONE} ($n)"
+ ret=0
+ retry_quiet 10 _check_nsec_nxdomain || log_error "bad NXDOMAIN response for zone ${ZONE}"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+# Test: check NSEC3 parameters in answers
+_check_nsec3_nsec3param() {
+ dig_with_opts +noquestion @$SERVER "${ZONE}" NSEC3PARAM > "dig.out.test$n.nsec3param.$ZONE" || return 1
+ grep "${ZONE}.*0.*IN.*NSEC3PARAM.*1.*0.*${ITERATIONS}.*${SALT}" "dig.out.test$n.nsec3param.$ZONE" > /dev/null || return 1
+
+ if [ -z "$SALT" ]; then
+ SALT=$(awk '$4 == "NSEC3PARAM" { print $8 }' dig.out.test$n.nsec3param.$ZONE)
+ fi
+ return 0
+}
+
+_check_nsec3_nxdomain() {
+ dig_with_opts @$SERVER "nosuchname.${ZONE}" > "dig.out.test$n.nxdomain.$ZONE" || return 1
+ grep ".*\.${ZONE}.*IN.*NSEC3.*1.${FLAGS}.*${ITERATIONS}.*${SALT}" "dig.out.test$n.nxdomain.$ZONE" > /dev/null || return 1
+ return 0
+}
+
+check_nsec3() {
+ wait_for_zone_is_signed "nsec3"
+
+ n=$((n+1))
+ echo_i "check that NSEC3PARAM 1 0 ${ITERATIONS} is published zone ${ZONE} ($n)"
+ ret=0
+ retry_quiet 10 _check_nsec3_nsec3param || log_error "bad NSEC3PARAM response for ${ZONE}"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check NXDOMAIN response has correct NSEC3 1 ${FLAGS} ${ITERATIONS} ${SALT} for zone ${ZONE} ($n)"
+ ret=0
+ retry_quiet 10 _check_nsec3_nxdomain || log_error "bad NXDOMAIN response for zone ${ZONE}"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "verify DNSSEC for zone ${ZONE} ($n)"
+ ret=0
+ retry_quiet 10 _check_dnssec_verify || log_error "DNSSEC verify failed for zone ${ZONE}"
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
+start_time="$(TZ=UTC date +%s)"
+status=0
+n=0
+
+key_clear "KEY1"
+key_clear "KEY2"
+key_clear "KEY3"
+key_clear "KEY4"
+
+# Zone: nsec-to-nsec3.kasp.
+set_zone_policy "nsec-to-nsec3.kasp" "nsec" 1 3600
+set_server "ns3" "10.53.0.3"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec
+
+if ($SHELL ../testcrypto.sh -q RSASHA1)
+then
+ # Zone: rsasha1-to-nsec3.kasp.
+ set_zone_policy "rsasha1-to-nsec3.kasp" "rsasha1" 1 3600
+ set_server "ns3" "10.53.0.3"
+ set_key_rsasha1_values "KEY1"
+ echo_i "initial check zone ${ZONE}"
+ check_nsec
+
+ # Zone: rsasha1-to-nsec3-wait.kasp.
+ set_zone_policy "rsasha1-to-nsec3-wait.kasp" "rsasha1" 1 3600
+ set_server "ns3" "10.53.0.3"
+ set_key_rsasha1_values "KEY1"
+ set_key_states "KEY1" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent"
+ echo_i "initial check zone ${ZONE}"
+ check_nsec
+
+ # Zone: nsec3-to-rsasha1.kasp.
+ set_zone_policy "nsec3-to-rsasha1.kasp" "nsec3" 1 3600
+ set_server "ns3" "10.53.0.3"
+ set_key_rsasha1_values "KEY1"
+ echo_i "initial check zone ${ZONE}"
+ check_nsec3
+
+ # Zone: nsec3-to-rsasha1-ds.kasp.
+ set_zone_policy "nsec3-to-rsasha1-ds.kasp" "nsec3" 1 3600
+ set_server "ns3" "10.53.0.3"
+ set_key_rsasha1_values "KEY1"
+ set_key_states "KEY1" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent"
+ echo_i "initial check zone ${ZONE}"
+ check_nsec3
+fi
+
+# Zone: nsec3.kasp.
+set_zone_policy "nsec3.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec3
+
+# Zone: nsec3-dynamic.kasp.
+set_zone_policy "nsec3-dynamic.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec3
+
+# Zone: nsec3-change.kasp.
+set_zone_policy "nsec3-change.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec3
+
+# Zone: nsec3-dynamic-change.kasp.
+set_zone_policy "nsec3-dynamic-change.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec3
+
+# Zone: nsec3-dynamic-to-inline.kasp.
+set_zone_policy "nsec3-dynamic-to-inline.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec3
+
+# Zone: nsec3-inline-to-dynamic.kasp.
+set_zone_policy "nsec3-inline-to-dynamic.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec3
+
+# Zone: nsec3-to-nsec.kasp.
+set_zone_policy "nsec3-to-nsec.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec3
+
+# Zone: nsec3-to-optout.kasp.
+set_zone_policy "nsec3-to-optout.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec3
+
+# Zone: nsec3-from-optout.kasp.
+set_zone_policy "nsec3-from-optout.kasp" "optout" 1 3600
+set_nsec3param "1" "0" "0"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec3
+
+# Zone: nsec3-other.kasp.
+set_zone_policy "nsec3-other.kasp" "nsec3-other" 1 3600
+set_nsec3param "1" "11" "8"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec3
+
+# Zone: nsec3-xfr-inline.kasp.
+# This is a secondary zone, where the primary is signed with NSEC3 but
+# the dnssec-policy dictates NSEC.
+set_zone_policy "nsec3-xfr-inline.kasp" "nsec" 1 3600
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec
+
+# Zone: nsec3-dynamic-update-inline.kasp.
+set_zone_policy "nsec3-dynamic-update-inline.kasp" "nsec" 1 3600
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec
+
+n=$((n+1))
+echo_i "dynamic update dnssec-policy zone ${ZONE} with NSEC3 ($n)"
+ret=0
+$NSUPDATE > update.out.$ZONE.test$n 2>&1 << END || ret=1
+server 10.53.0.3 ${PORT}
+zone ${ZONE}.
+update add 04O18462RI5903H8RDVL0QDT5B528DUJ.${ZONE}. 3600 NSEC3 0 0 0 408A4B2D412A4E95 1JMDDPMTFF8QQLIOINSIG4CR9OTICAOC A RRSIG
+send
+END
+wait_for_log 10 "updating zone '${ZONE}/IN': update failed: explicit NSEC3 updates are not allowed in secure zones (REFUSED)" ns3/named.run || ret=1
+check_nsec
+
+# Reconfig named.
+ret=0
+echo_i "reconfig dnssec-policy to trigger nsec3 rollovers"
+copy_setports ns3/named2.conf.in ns3/named.conf
+rndc_reconfig ns3 10.53.0.3
+
+# Zone: nsec-to-nsec3.kasp. (reconfigured)
+set_zone_policy "nsec-to-nsec3.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "check zone ${ZONE} after reconfig"
+check_nsec3
+
+if ($SHELL ../testcrypto.sh -q RSASHA1)
+then
+ # Zone: rsasha1-to-nsec3.kasp.
+ set_zone_policy "rsasha1-to-nsec3.kasp" "nsec3" 2 3600
+ set_server "ns3" "10.53.0.3"
+ set_key_rsasha1_values "KEY1"
+ set_key_states "KEY1" "hidden" "unretentive" "unretentive" "unretentive" "hidden"
+ set_keysigning "KEY1" "no"
+ set_zonesigning "KEY1" "no"
+ set_key_default_values "KEY2"
+ echo_i "check zone ${ZONE} after reconfig"
+ check_nsec3
+
+ # Zone: rsasha1-to-nsec3-wait.kasp.
+ set_zone_policy "rsasha1-to-nsec3-wait.kasp" "nsec3" 2 3600
+ set_server "ns3" "10.53.0.3"
+ set_key_rsasha1_values "KEY1"
+ set_key_states "KEY1" "hidden" "omnipresent" "omnipresent" "omnipresent" "omnipresent"
+ set_key_default_values "KEY2"
+ echo_i "check zone ${ZONE} after reconfig"
+ check_nsec
+
+ # Zone: nsec3-to-rsasha1.kasp.
+ set_zone_policy "nsec3-to-rsasha1.kasp" "rsasha1" 2 3600
+ set_nsec3param "1" "0" "0"
+ set_server "ns3" "10.53.0.3"
+ set_key_default_values "KEY1"
+ set_key_states "KEY1" "hidden" "unretentive" "unretentive" "unretentive" "hidden"
+ set_keysigning "KEY1" "no"
+ set_zonesigning "KEY1" "no"
+ set_key_rsasha1_values "KEY2"
+ echo_i "check zone ${ZONE} after reconfig"
+ check_nsec
+
+ # Zone: nsec3-to-rsasha1-ds.kasp.
+ set_zone_policy "nsec3-to-rsasha1-ds.kasp" "rsasha1" 2 3600
+ set_nsec3param "1" "0" "0"
+ set_server "ns3" "10.53.0.3"
+ set_key_default_values "KEY1"
+ set_key_states "KEY1" "hidden" "omnipresent" "omnipresent" "omnipresent" "omnipresent"
+ set_key_rsasha1_values "KEY2"
+ echo_i "check zone ${ZONE} after reconfig"
+ check_nsec
+
+ key_clear "KEY1"
+ key_clear "KEY2"
+fi
+
+# Zone: nsec3.kasp. (same)
+set_zone_policy "nsec3.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "check zone ${ZONE} after reconfig"
+check_nsec3
+
+# Zone: nsec3-dyamic.kasp. (same)
+set_zone_policy "nsec3-dynamic.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "check zone ${ZONE} after reconfig"
+check_nsec3
+
+# Zone: nsec3-change.kasp. (reconfigured)
+set_zone_policy "nsec3-change.kasp" "nsec3-other" 1 3600
+set_nsec3param "1" "11" "8"
+set_key_default_values "KEY1"
+echo_i "check zone ${ZONE} after reconfig"
+check_nsec3
+
+# Zone: nsec3-dynamic-change.kasp. (reconfigured)
+set_zone_policy "nsec3-dynamic-change.kasp" "nsec3-other" 1 3600
+set_nsec3param "1" "11" "8"
+set_key_default_values "KEY1"
+echo_i "check zone ${ZONE} after reconfig"
+check_nsec3
+
+# Zone: nsec3-dynamic-to-inline.kasp. (same)
+set_zone_policy "nsec3-dynamic-to-inline.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "check zone ${ZONE} after reconfig"
+check_nsec3
+
+# Zone: nsec3-inline-to-dynamic.kasp. (same)
+set_zone_policy "nsec3-inline-to-dynamic.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "initial check zone ${ZONE}"
+check_nsec3
+
+# Zone: nsec3-to-nsec.kasp. (reconfigured)
+set_zone_policy "nsec3-to-nsec.kasp" "nsec" 1 3600
+set_nsec3param "1" "11" "8"
+set_key_default_values "KEY1"
+echo_i "check zone ${ZONE} after reconfig"
+check_nsec
+
+# Zone: nsec3-to-optout.kasp. (reconfigured)
+# DISABLED:
+# There is a bug in the nsec3param building code that thinks when the
+# optout bit is changed, the chain already exists. [GL #2216]
+#set_zone_policy "nsec3-to-optout.kasp" "optout" 1 3600
+#set_nsec3param "1" "0" "0"
+#set_key_default_values "KEY1"
+#echo_i "check zone ${ZONE} after reconfig"
+#check_nsec3
+
+# Zone: nsec3-from-optout.kasp. (reconfigured)
+# DISABLED:
+# There is a bug in the nsec3param building code that thinks when the
+# optout bit is changed, the chain already exists. [GL #2216]
+#set_zone_policy "nsec3-from-optout.kasp" "nsec3" 1 3600
+#set_nsec3param "0" "0" "0"
+#set_key_default_values "KEY1"
+#echo_i "check zone ${ZONE} after reconfig"
+#check_nsec3
+
+# Zone: nsec3-other.kasp. (same)
+set_zone_policy "nsec3-other.kasp" "nsec3-other" 1 3600
+set_nsec3param "1" "11" "8"
+set_key_default_values "KEY1"
+echo_i "check zone ${ZONE} after reconfig"
+check_nsec3
+
+# Using rndc signing -nsec3param (should fail)
+set_zone_policy "nsec3-change.kasp" "nsec3-other" 1 3600
+echo_i "use rndc signing -nsec3param ${ZONE} to change NSEC3 settings"
+rndccmd $SERVER signing -nsec3param 1 1 12 ffff $ZONE > rndc.signing.test$n.$ZONE || log_error "failed to call rndc signing -nsec3param $ZONE"
+grep "zone uses dnssec-policy, use rndc dnssec command instead" rndc.signing.test$n.$ZONE > /dev/null || log_error "rndc signing -nsec3param should fail"
+check_nsec3
+
+# Test NSEC3 and NSEC3PARAM is the same after restart
+set_zone_policy "nsec3.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "check zone ${ZONE} before restart"
+check_nsec3
+
+# Restart named, NSEC3 should stay the same.
+ret=0
+echo "stop ns3"
+stop_server --use-rndc --port ${CONTROLPORT} ${DIR} || ret=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+ret=0
+echo "start ns3"
+start_server --noclean --restart --port ${PORT} ${DIR}
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+prevsalt="${SALT}"
+set_zone_policy "nsec3.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+SALT="${prevsalt}"
+echo_i "check zone ${ZONE} after restart has salt ${SALT}"
+check_nsec3
+
+# Zone: nsec3-fails-to-load.kasp. (should be fixed after reload)
+cp ns3/template.db.in ns3/nsec3-fails-to-load.kasp.db
+rndc_reload ns3 10.53.0.3
+
+set_zone_policy "nsec3-fails-to-load.kasp" "nsec3" 1 3600
+set_nsec3param "0" "0" "0"
+set_key_default_values "KEY1"
+echo_i "check zone ${ZONE} after reload"
+check_nsec3
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/nsec3/tests_sh_nsec3.py b/bin/tests/system/nsec3/tests_sh_nsec3.py
new file mode 100644
index 0000000..16df541
--- /dev/null
+++ b/bin/tests/system/nsec3/tests_sh_nsec3.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_nsec3(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/nslookup/clean.sh b/bin/tests/system/nslookup/clean.sh
new file mode 100644
index 0000000..dc0c70d
--- /dev/null
+++ b/bin/tests/system/nslookup/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns1/example.db
+rm -f nslookup.out*
+rm -f nslookup.err*
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/named.conf
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/nslookup/ns1/example.net.db b/bin/tests/system/nslookup/ns1/example.net.db
new file mode 100644
index 0000000..73aeeb1
--- /dev/null
+++ b/bin/tests/system/nslookup/ns1/example.net.db
@@ -0,0 +1,31 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+
+@ 86400 IN SOA ns1 hostmaster (
+ 1397051952 ; "SER0"
+ 5
+ 5
+ 1814400
+ 3600 )
+@ NS ns1
+ns1 A 10.53.0.1
+
+a-only A 1.2.3.4
+aaaa-only AAAA 2001::ffff
+
+dual A 1.2.3.4
+ AAAA 2001::ffff
+
+cname-a-only CNAME a-only
+cname-aaaa-only CNAME aaaa-only
+cname-dual CNAME dual
diff --git a/bin/tests/system/nslookup/ns1/named.conf.in b/bin/tests/system/nslookup/ns1/named.conf.in
new file mode 100644
index 0000000..8338a9c
--- /dev/null
+++ b/bin/tests/system/nslookup/ns1/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "example.net" {
+ type primary;
+ file "example.net.db";
+};
diff --git a/bin/tests/system/nslookup/setup.sh b/bin/tests/system/nslookup/setup.sh
new file mode 100644
index 0000000..67d3ccf
--- /dev/null
+++ b/bin/tests/system/nslookup/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 1 >ns1/example.db
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/nslookup/tests.sh b/bin/tests/system/nslookup/tests.sh
new file mode 100644
index 0000000..e985f19
--- /dev/null
+++ b/bin/tests/system/nslookup/tests.sh
@@ -0,0 +1,159 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck disable=SC2086
+. ../conf.sh
+
+status=0
+n=0
+
+n=$((n+1))
+echo_i "Check that domain names that are too big when applying a search list entry are handled cleanly ($n)"
+ret=0
+l=012345678901234567890123456789012345678901234567890123456789012
+t=0123456789012345678901234567890123456789012345678901234567890
+d=$l.$l.$l.$t
+$NSLOOKUP -port=${PORT} -domain=$d -type=soa example 10.53.0.1 2> nslookup.err${n} > nslookup.out${n} || ret=1
+lines=$(wc -l < nslookup.err${n})
+test $lines -eq 0 || ret=1
+grep "origin = ns1.example" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check A only lookup ($n)"
+ret=0
+$NSLOOKUP -port=${PORT} a-only.example.net 10.53.0.1 2> nslookup.err${n} > nslookup.out${n} || ret=1
+lines=$(wc -l < nslookup.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Server:" nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c a-only.example.net nslookup.out${n})
+test $lines -eq 1 || ret=1
+grep "1.2.3.4" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# See [GL #4044]
+n=$((n+1))
+echo_i "Check A only lookup with a delayed stdin input ($n)"
+ret=0
+(sleep 6 && echo "server 10.53.0.1" && echo "a-only.example.net.") | $NSLOOKUP -port=${PORT} 2> nslookup.err${n} > nslookup.out${n} || ret=1
+lines=$(wc -l < nslookup.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Server:" nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c a-only.example.net nslookup.out${n})
+test $lines -eq 1 || ret=1
+grep "1.2.3.4" nslookup.out${n} > /dev/null || ret=1
+grep "timed out" nslookup.out${n} > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check AAAA only lookup ($n)"
+ret=0
+$NSLOOKUP -port=${PORT} aaaa-only.example.net 10.53.0.1 2> nslookup.err${n} > nslookup.out${n} || ret=1
+lines=$(wc -l < nslookup.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Server:" nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c aaaa-only.example.net nslookup.out${n})
+test $lines -eq 1 || ret=1
+grep "2001::ffff" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check dual A + AAAA lookup ($n)"
+ret=0
+$NSLOOKUP -port=${PORT} dual.example.net 10.53.0.1 2> nslookup.err${n} > nslookup.out${n} || ret=1
+lines=$(wc -l < nslookup.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Server:" nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c dual.example.net nslookup.out${n})
+test $lines -eq 2 || ret=1
+grep "1.2.3.4" nslookup.out${n} > /dev/null || ret=1
+grep "2001::ffff" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check CNAME to A only lookup ($n)"
+ret=0
+$NSLOOKUP -port=${PORT} cname-a-only.example.net 10.53.0.1 2> nslookup.err${n} > nslookup.out${n} || ret=1
+lines=$(wc -l < nslookup.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Server:" nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c "canonical name" nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep a-only.example.net nslookup.out${n} | grep -cv "canonical name")
+test $lines -eq 1 || ret=1
+grep "1.2.3.4" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check CNAME to AAAA only lookup ($n)"
+ret=0
+$NSLOOKUP -port=${PORT} cname-aaaa-only.example.net 10.53.0.1 2> nslookup.err${n} > nslookup.out${n} || ret=1
+lines=$(wc -l < nslookup.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Server:" nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c "canonical name" nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep aaaa-only.example.net nslookup.out${n} | grep -cv "canonical name")
+test $lines -eq 1 || ret=1
+grep "2001::ffff" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check CNAME to dual A + AAAA lookup ($n)"
+ret=0
+$NSLOOKUP -port=${PORT} cname-dual.example.net 10.53.0.1 2> nslookup.err${n} > nslookup.out${n} || ret=1
+lines=$(wc -l < nslookup.err${n})
+test $lines -eq 0 || ret=1
+lines=$(grep -c "Server:" nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c "canonical name" nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep dual.example.net nslookup.out${n} | grep -cv "canonical name")
+test $lines -eq 2 || ret=1
+grep "1.2.3.4" nslookup.out${n} > /dev/null || ret=1
+grep "2001::ffff" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "Check ANY lookup ($n)"
+ret=0
+$NSLOOKUP -port=${PORT} -type=ANY example.net 10.53.0.1 2> nslookup.err${n} > nslookup.out${n} || ret=1
+lines=$(grep -c 'Address:.10\.53\.0\.1#'"${PORT}" nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c 'origin = ns1\.example\.net' nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c 'mail addr = hostmaster\.example\.net' nslookup.out${n})
+test $lines -eq 1 || ret=1
+lines=$(grep -c 'nameserver = ns1\.example\.net.' nslookup.out${n})
+test $lines -eq 1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/nslookup/tests_sh_nslookup.py b/bin/tests/system/nslookup/tests_sh_nslookup.py
new file mode 100644
index 0000000..9553a82
--- /dev/null
+++ b/bin/tests/system/nslookup/tests_sh_nslookup.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_nslookup(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/nsupdate/ans4/ans.pl b/bin/tests/system/nsupdate/ans4/ans.pl
new file mode 100644
index 0000000..30c792f
--- /dev/null
+++ b/bin/tests/system/nsupdate/ans4/ans.pl
@@ -0,0 +1,65 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use IO::Socket;
+use IO::File;
+use strict;
+
+# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early
+local $SIG{PIPE} = 'IGNORE';
+
+# Flush logged output after every line
+local $| = 1;
+
+my $server_addr = "10.53.0.4";
+if (@ARGV > 0) {
+ $server_addr = @ARGV[0];
+}
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!";
+my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $localport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+print "listening on $server_addr:$localport.\n";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";;
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+# Main
+for (;;) {
+ my $rin;
+ my $rout;
+
+ $rin = '';
+ vec($rin, fileno($udpsock), 1) = 1;
+ vec($rin, fileno($tcpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($udpsock), 1)) {
+ printf "UDP request\n";
+ my $buf;
+ $udpsock->recv($buf, 512);
+ } elsif (vec($rout, fileno($tcpsock), 1)) {
+ printf "TCP request\n";
+ }
+}
diff --git a/bin/tests/system/nsupdate/clean.sh b/bin/tests/system/nsupdate/clean.sh
new file mode 100644
index 0000000..689c2f5
--- /dev/null
+++ b/bin/tests/system/nsupdate/clean.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f */*.jnl
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run */ans.run
+rm -f */named.run.prev
+rm -f Kxxx.*
+rm -f check.out.*
+rm -f dig.out.*
+rm -f jp.out.ns3.*
+rm -f nextpart.out.*
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
+rm -f ns*/named.lock
+rm -f ns1/example.db ns1/unixtime.db ns1/yyyymmddvv.db ns1/update.db ns1/other.db ns1/keytests.db
+rm -f ns1/many.test.db
+rm -f ns1/maxjournal.db
+rm -f ns1/md5.key ns1/sha1.key ns1/sha224.key ns1/sha256.key ns1/sha384.key
+rm -f ns1/legacy157.key ns1/legacy161.key ns1/legacy162.key ns1/legacy163.key ns1/legacy164.key ns1/legacy165.key
+rm -f ns1/sample.db
+rm -f ns1/sha512.key ns1/ddns.key
+rm -f ns10/_default.tsigkeys
+rm -f ns10/example.com.db
+rm -f ns10/in-addr.db
+rm -f ns2/example.bk
+rm -f ns2/sample.db
+rm -f ns2/update.bk ns2/update.alt.bk
+rm -f ns3/*.signed
+rm -f ns3/K*
+rm -f ns3/delegation.test.db
+rm -f ns3/dnskey.test.db
+rm -f ns3/dsset-*
+rm -f ns3/example.db
+rm -f ns3/multisigner.test.db
+rm -f ns3/many.test.bk
+rm -f ns3/nsec3param.test.db
+rm -f ns3/too-big.test.db
+rm -f ns5/local.db
+rm -f ns6/in-addr.db
+rm -f ns7/_default.tsigkeys
+rm -f ns7/example.com.db
+rm -f ns7/in-addr.db
+rm -f ns8/_default.tsigkeys
+rm -f ns8/example.com.db
+rm -f ns8/in-addr.db
+rm -f ns9/_default.tsigkeys
+rm -f ns9/denyname.example.db
+rm -f ns9/example.com.db
+rm -f ns9/in-addr.db
+rm -f perl.update_test.out
+rm -f nsupdate.alg-*
+rm -f nsupdate.out*
+rm -f typelist.out.*
+rm -f update.out.*
+rm -f update.in.*
+rm -f verylarge
diff --git a/bin/tests/system/nsupdate/commandlist b/bin/tests/system/nsupdate/commandlist
new file mode 100644
index 0000000..41c8049
--- /dev/null
+++ b/bin/tests/system/nsupdate/commandlist
@@ -0,0 +1,15 @@
+server 127.0.0.1
+server 127.0.0.1 port
+update
+update delete
+update delete dummy
+update delete dummy in
+update delete dummy in a
+update delete dummy in a 127.0.0.1
+update add
+update add domain
+update add domain 0
+update add domain 0 in
+update add domain 0 in a
+update add domain 0 a
+update add domain 0 a in
diff --git a/bin/tests/system/nsupdate/knowngood.ns1.after b/bin/tests/system/nsupdate/knowngood.ns1.after
new file mode 100644
index 0000000..4114159
--- /dev/null
+++ b/bin/tests/system/nsupdate/knowngood.ns1.after
@@ -0,0 +1,99 @@
+example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 2 2000 2000 1814400 3600
+example.nil. 300 IN NS ns1.example.nil.
+example.nil. 300 IN NS ns2.example.nil.
+*.example.nil. 300 IN MX 10 mail.example.nil.
+a.example.nil. 300 IN TXT "foo foo foo"
+a.example.nil. 300 IN PTR foo.net.
+a01.example.nil. 3600 IN A 0.0.0.0
+a02.example.nil. 3600 IN A 255.255.255.255
+a601.example.nil. 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01.example.nil. 3600 IN AFSDB 0 hostname.example.nil.
+afsdb02.example.nil. 3600 IN AFSDB 65535 .
+b.example.nil. 300 IN CNAME foo.net.
+c.example.nil. 300 IN A 73.80.65.49
+cert01.example.nil. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+cname01.example.nil. 3600 IN CNAME cname-target.
+cname02.example.nil. 3600 IN CNAME cname-target.example.nil.
+cname03.example.nil. 3600 IN CNAME .
+d.example.nil. 300 IN A 73.80.65.49
+dname01.example.nil. 3600 IN DNAME dname-target.
+dname02.example.nil. 3600 IN DNAME dname-target.example.nil.
+dname03.example.nil. 3600 IN DNAME .
+e.example.nil. 300 IN MX 10 mail.example.nil.
+e.example.nil. 300 IN TXT "one"
+e.example.nil. 300 IN TXT "two"
+e.example.nil. 300 IN TXT "three"
+e.example.nil. 300 IN A 73.80.65.49
+e.example.nil. 300 IN A 73.80.65.50
+e.example.nil. 300 IN A 73.80.65.51
+e.example.nil. 300 IN A 73.80.65.52
+f.example.nil. 300 IN A 73.80.65.52
+gpos01.example.nil. 3600 IN GPOS "-22.6882" "116.8652" "250.0"
+gpos02.example.nil. 3600 IN GPOS "" "" ""
+hinfo01.example.nil. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02.example.nil. 3600 IN HINFO "PC" "NetBSD"
+isdn01.example.nil. 3600 IN ISDN "isdn-address"
+isdn02.example.nil. 3600 IN ISDN "isdn-address" "subaddress"
+isdn03.example.nil. 3600 IN ISDN "isdn-address"
+isdn04.example.nil. 3600 IN ISDN "isdn-address" "subaddress"
+key01.example.nil. 3600 IN KEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+kx01.example.nil. 3600 IN KX 10 kdc.example.nil.
+kx02.example.nil. 3600 IN KX 10 .
+loc01.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01.example.nil. 3600 IN MG madname.example.nil.
+mb02.example.nil. 3600 IN MG .
+mg01.example.nil. 3600 IN MG mgmname.example.nil.
+mg02.example.nil. 3600 IN MG .
+minfo01.example.nil. 3600 IN MINFO rmailbx.example.nil. emailbx.example.nil.
+minfo02.example.nil. 3600 IN MINFO . .
+mr01.example.nil. 3600 IN MR mrname.example.nil.
+mr02.example.nil. 3600 IN MR .
+mx01.example.nil. 3600 IN MX 10 mail.example.nil.
+mx02.example.nil. 3600 IN MX 10 .
+naptr01.example.nil. 3600 IN NAPTR 0 0 "" "" "" .
+naptr02.example.nil. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+ns1.example.nil. 300 IN A 10.53.0.1
+ns2.example.nil. 300 IN A 10.53.0.2
+nsap-ptr01.example.nil. 3600 IN NSAP-PTR .
+nsap-ptr01.example.nil. 3600 IN NSAP-PTR foo.
+nsap01.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01.example.nil. 3600 IN NXT a.secure.example.nil. NS SOA MX SIG KEY LOC NXT
+nxt02.example.nil. 3600 IN NXT . NSAP-PTR NXT
+nxt03.example.nil. 3600 IN NXT . A
+nxt04.example.nil. 3600 IN NXT . 127
+ptr01.example.nil. 3600 IN PTR example.nil.
+px01.example.nil. 3600 IN PX 65535 foo. bar.
+px02.example.nil. 3600 IN PX 65535 . .
+rp01.example.nil. 3600 IN RP mbox-dname.example.nil. txt-dname.example.nil.
+rp02.example.nil. 3600 IN RP . .
+rt01.example.nil. 3600 IN RT 0 intermediate-host.example.nil.
+rt02.example.nil. 3600 IN RT 65535 .
+s.example.nil. 300 IN NS ns.s.example.nil.
+ns.s.example.nil. 300 IN A 73.80.65.49
+sig01.example.nil. 3600 IN SIG NXT 1 3 3600 20000102030405 19961211100908 2143 foo.example.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+srv01.example.nil. 3600 IN SRV 0 0 0 .
+srv02.example.nil. 3600 IN SRV 65535 65535 65535 old-slow-box.example.com.
+txt01.example.nil. 3600 IN TXT "foo"
+txt02.example.nil. 3600 IN TXT "foo" "bar"
+txt03.example.nil. 3600 IN TXT "foo"
+txt04.example.nil. 3600 IN TXT "foo" "bar"
+txt05.example.nil. 3600 IN TXT "foo bar"
+txt06.example.nil. 3600 IN TXT "foo bar"
+txt07.example.nil. 3600 IN TXT "foo bar"
+txt08.example.nil. 3600 IN TXT "foo\010bar"
+txt09.example.nil. 3600 IN TXT "foo\010bar"
+txt10.example.nil. 3600 IN TXT "foo bar"
+txt11.example.nil. 3600 IN TXT "\"foo\""
+txt12.example.nil. 3600 IN TXT "\"foo\""
+u.example.nil. 300 IN TXT "txt-not-in-nxt"
+a.u.example.nil. 300 IN A 73.80.65.49
+b.u.example.nil. 300 IN A 73.80.65.49
+updated.example.nil. 600 IN TXT "Foo"
+updated.example.nil. 600 IN A 10.10.10.1
+wks01.example.nil. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23
+wks02.example.nil. 3600 IN WKS 10.0.0.1 17 0 1 2 53
+wks03.example.nil. 3600 IN WKS 10.0.0.2 6 65535
+x2501.example.nil. 3600 IN X25 "123456789"
+example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 2 2000 2000 1814400 3600
diff --git a/bin/tests/system/nsupdate/knowngood.ns1.afterstop b/bin/tests/system/nsupdate/knowngood.ns1.afterstop
new file mode 100644
index 0000000..e871d4c
--- /dev/null
+++ b/bin/tests/system/nsupdate/knowngood.ns1.afterstop
@@ -0,0 +1,3 @@
+updated4.example.nil. 600 IN A 10.10.10.3
+example.nil. 300 IN NS ns1.example.nil.
+example.nil. 300 IN NS ns2.example.nil.
diff --git a/bin/tests/system/nsupdate/knowngood.ns1.before b/bin/tests/system/nsupdate/knowngood.ns1.before
new file mode 100644
index 0000000..4a5e630
--- /dev/null
+++ b/bin/tests/system/nsupdate/knowngood.ns1.before
@@ -0,0 +1,98 @@
+example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 1 2000 2000 1814400 3600
+example.nil. 300 IN NS ns1.example.nil.
+example.nil. 300 IN NS ns2.example.nil.
+*.example.nil. 300 IN MX 10 mail.example.nil.
+a.example.nil. 300 IN TXT "foo foo foo"
+a.example.nil. 300 IN PTR foo.net.
+a01.example.nil. 3600 IN A 0.0.0.0
+a02.example.nil. 3600 IN A 255.255.255.255
+a601.example.nil. 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01.example.nil. 3600 IN AFSDB 0 hostname.example.nil.
+afsdb02.example.nil. 3600 IN AFSDB 65535 .
+b.example.nil. 300 IN CNAME foo.net.
+c.example.nil. 300 IN A 73.80.65.49
+cert01.example.nil. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+cname01.example.nil. 3600 IN CNAME cname-target.
+cname02.example.nil. 3600 IN CNAME cname-target.example.nil.
+cname03.example.nil. 3600 IN CNAME .
+d.example.nil. 300 IN A 73.80.65.49
+dname01.example.nil. 3600 IN DNAME dname-target.
+dname02.example.nil. 3600 IN DNAME dname-target.example.nil.
+dname03.example.nil. 3600 IN DNAME .
+e.example.nil. 300 IN MX 10 mail.example.nil.
+e.example.nil. 300 IN TXT "one"
+e.example.nil. 300 IN TXT "two"
+e.example.nil. 300 IN TXT "three"
+e.example.nil. 300 IN A 73.80.65.49
+e.example.nil. 300 IN A 73.80.65.50
+e.example.nil. 300 IN A 73.80.65.51
+e.example.nil. 300 IN A 73.80.65.52
+f.example.nil. 300 IN A 73.80.65.52
+gpos01.example.nil. 3600 IN GPOS "-22.6882" "116.8652" "250.0"
+gpos02.example.nil. 3600 IN GPOS "" "" ""
+hinfo01.example.nil. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02.example.nil. 3600 IN HINFO "PC" "NetBSD"
+isdn01.example.nil. 3600 IN ISDN "isdn-address"
+isdn02.example.nil. 3600 IN ISDN "isdn-address" "subaddress"
+isdn03.example.nil. 3600 IN ISDN "isdn-address"
+isdn04.example.nil. 3600 IN ISDN "isdn-address" "subaddress"
+key01.example.nil. 3600 IN KEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+kx01.example.nil. 3600 IN KX 10 kdc.example.nil.
+kx02.example.nil. 3600 IN KX 10 .
+loc01.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01.example.nil. 3600 IN MG madname.example.nil.
+mb02.example.nil. 3600 IN MG .
+mg01.example.nil. 3600 IN MG mgmname.example.nil.
+mg02.example.nil. 3600 IN MG .
+minfo01.example.nil. 3600 IN MINFO rmailbx.example.nil. emailbx.example.nil.
+minfo02.example.nil. 3600 IN MINFO . .
+mr01.example.nil. 3600 IN MR mrname.example.nil.
+mr02.example.nil. 3600 IN MR .
+mx01.example.nil. 3600 IN MX 10 mail.example.nil.
+mx02.example.nil. 3600 IN MX 10 .
+naptr01.example.nil. 3600 IN NAPTR 0 0 "" "" "" .
+naptr02.example.nil. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+ns1.example.nil. 300 IN A 10.53.0.1
+ns2.example.nil. 300 IN A 10.53.0.2
+nsap-ptr01.example.nil. 3600 IN NSAP-PTR .
+nsap-ptr01.example.nil. 3600 IN NSAP-PTR foo.
+nsap01.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01.example.nil. 3600 IN NXT a.secure.example.nil. NS SOA MX SIG KEY LOC NXT
+nxt02.example.nil. 3600 IN NXT . NSAP-PTR NXT
+nxt03.example.nil. 3600 IN NXT . A
+nxt04.example.nil. 3600 IN NXT . 127
+ptr01.example.nil. 3600 IN PTR example.nil.
+px01.example.nil. 3600 IN PX 65535 foo. bar.
+px02.example.nil. 3600 IN PX 65535 . .
+rp01.example.nil. 3600 IN RP mbox-dname.example.nil. txt-dname.example.nil.
+rp02.example.nil. 3600 IN RP . .
+rt01.example.nil. 3600 IN RT 0 intermediate-host.example.nil.
+rt02.example.nil. 3600 IN RT 65535 .
+s.example.nil. 300 IN NS ns.s.example.nil.
+ns.s.example.nil. 300 IN A 73.80.65.49
+sig01.example.nil. 3600 IN SIG NXT 1 3 3600 20000102030405 19961211100908 2143 foo.example.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+srv01.example.nil. 3600 IN SRV 0 0 0 .
+srv02.example.nil. 3600 IN SRV 65535 65535 65535 old-slow-box.example.com.
+t.example.nil. 301 IN A 73.80.65.49
+txt01.example.nil. 3600 IN TXT "foo"
+txt02.example.nil. 3600 IN TXT "foo" "bar"
+txt03.example.nil. 3600 IN TXT "foo"
+txt04.example.nil. 3600 IN TXT "foo" "bar"
+txt05.example.nil. 3600 IN TXT "foo bar"
+txt06.example.nil. 3600 IN TXT "foo bar"
+txt07.example.nil. 3600 IN TXT "foo bar"
+txt08.example.nil. 3600 IN TXT "foo\010bar"
+txt09.example.nil. 3600 IN TXT "foo\010bar"
+txt10.example.nil. 3600 IN TXT "foo bar"
+txt11.example.nil. 3600 IN TXT "\"foo\""
+txt12.example.nil. 3600 IN TXT "\"foo\""
+u.example.nil. 300 IN TXT "txt-not-in-nxt"
+a.u.example.nil. 300 IN A 73.80.65.49
+b.u.example.nil. 300 IN A 73.80.65.49
+wks01.example.nil. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23
+wks02.example.nil. 3600 IN WKS 10.0.0.1 17 0 1 2 53
+wks03.example.nil. 3600 IN WKS 10.0.0.2 6 65535
+x2501.example.nil. 3600 IN X25 "123456789"
+example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 1 2000 2000 1814400 3600
diff --git a/bin/tests/system/nsupdate/krb/setup.sh b/bin/tests/system/nsupdate/krb/setup.sh
new file mode 100644
index 0000000..3d254a8
--- /dev/null
+++ b/bin/tests/system/nsupdate/krb/setup.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -x
+
+PWD=$(pwd)
+
+KRB5_CONFIG="${PWD}/krb5.conf"
+export KRB5_CONFIG
+
+KRB5_KDC_PROFILE=${PWD}/krb5kdc
+export KRB5_KDC_PROFILE
+
+now=$(date +%s)
+lifetime=$((2147483647 - now))
+lifetime=$((lifetime / 3600 / 24 - 30))
+
+cat << EOF > "${KRB5_CONFIG}"
+[libdefaults]
+ default_realm = EXAMPLE.COM
+ dns_lookup_kdc = false
+ # Depending on what you are testing, you may want something like:
+ # default_keytab_name = FILE:/usr/local/var/keytab
+[realms]
+ EXAMPLE.COM = {
+ admin_server = 127.0.0.1:50001
+ kdc = 127.0.0.1:50000
+ database_module = DB2
+ kdc_ports = 50000
+ kadmind_port = 50001
+ }
+[dbmodules]
+ DB2 = {
+ db_library = db2
+ }
+[logging]
+ # Use any pathnames you want here.
+ kdc = FILE:${PWD}/kdc.log
+ admin_server = FILE:${PWD}/kadmin.log
+# Depending on what you are testing, you may want:
+# [domain_realm]
+# your.domain = EXAMPLE.COM
+EOF
+
+rm -rf ${KRB5_KDC_PROFILE}
+mkdir -p ${KRB5_KDC_PROFILE}
+chmod 700 ${KRB5_KDC_PROFILE}
+
+cat << EOF > "${KRB5_KDC_PROFILE}"/kdc.conf
+[kdcdefaults]
+ kdc_ports = 50000
+ kdc_tcp_ports = 50000
+
+[realms]
+ EXAMPLE.COM = {
+ key_stash_file = ${KRB5_KDC_PROFILE}/.k5.EXAMPLE.COM
+ database_module = EXAMPLE.COM
+ max_life = ${lifetime}d
+}
+
+[dbmodules]
+ EXAMPLE.COM = {
+ db_library = db2
+ database_name = ${KRB5_KDC_PROFILE}/principal
+ }
+EOF
+
+kdb5_util create -s <<EOF
+master
+master
+EOF
+
+krb5kdc -n &
+krb5kdcpid=$!
+#trap "kill $krb5kdcpid; wait; trap 0; exit" 0 15
+
+
+kadmin.local addprinc -maxlife ${lifetime}d -randkey DNS/ns7.example.com@EXAMPLE.COM
+kadmin.local addprinc -maxlife ${lifetime}d -randkey DNS/ns8.example.com@EXAMPLE.COM
+kadmin.local addprinc -maxlife ${lifetime}d -randkey host/machine.example.com@EXAMPLE.COM
+
+kadmin.local ktadd -k ns7-server.keytab DNS/ns7.example.com@EXAMPLE.COM
+kadmin.local ktadd -k ns8-server.keytab DNS/ns8.example.com@EXAMPLE.COM
+kadmin.local ktadd -k krb5-machine.keytab host/machine.example.com@EXAMPLE.COM
+
+kadmin.local addprinc -maxlife ${lifetime}d -randkey 'DNS/ns9.example.com@EXAMPLE.COM'
+kadmin.local addprinc -maxlife ${lifetime}d -randkey 'DNS/ns10.example.com@EXAMPLE.COM'
+kadmin.local addprinc -maxlife ${lifetime}d -randkey 'machine$@EXAMPLE.COM'
+
+kadmin.local ktadd -k ns9-server.keytab 'DNS/ns9.example.com@EXAMPLE.COM'
+kadmin.local ktadd -k ns10-server.keytab 'DNS/ns10.example.com@EXAMPLE.COM'
+kadmin.local ktadd -k ms-machine.keytab 'machine$@EXAMPLE.COM'
+
+kinit -V -k -t krb5-machine.keytab -l ${lifetime}d -c krb5-machine.ccache host/machine.example.com@EXAMPLE.COM
+kinit -V -k -t ms-machine.keytab -l ${lifetime}d -c ms-machine.ccache 'machine$@EXAMPLE.COM'
+
+cp ns7-server.keytab ../ns7/dns.keytab
+cp ns8-server.keytab ../ns8/dns-other-than-KRB5_KTNAME.keytab
+cp ns9-server.keytab ../ns9/dns.keytab
+cp ns10-server.keytab ../ns10/dns.keytab
+
+cp krb5-machine.ccache ../ns7/machine.ccache
+cp krb5-machine.ccache ../ns8/machine.ccache
+cp ms-machine.ccache ../ns9/machine.ccache
+cp ms-machine.ccache ../ns10/machine.ccache
+
+echo krb5kdc pid:$krb5kdcpid
diff --git a/bin/tests/system/nsupdate/ns1/example1.db b/bin/tests/system/nsupdate/ns1/example1.db
new file mode 100644
index 0000000..566b0a0
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/example1.db
@@ -0,0 +1,146 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example.nil IN SOA ns1.example.nil. hostmaster.example.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example.nil. NS ns1.example.nil.
+ns1.example.nil. A 10.53.0.1
+example.nil. NS ns2.example.nil.
+ns2.example.nil. A 10.53.0.2
+
+$ORIGIN example.nil.
+* MX 10 mail
+a TXT "foo foo foo"
+ PTR foo.net.
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.nil.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.nil.
+ns A 73.80.65.49
+$ORIGIN example.nil.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.nil.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.nil.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-157.+157+23571.key b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-157.+157+23571.key
new file mode 100644
index 0000000..bed002b
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-157.+157+23571.key
@@ -0,0 +1 @@
+legacy-157. IN KEY 0 3 157 mGcDSCx/fF121GOVJlITLg==
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-157.+157+23571.private b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-157.+157+23571.private
new file mode 100644
index 0000000..3ce72dd
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-157.+157+23571.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 157 (HMAC_MD5)
+Key: mGcDSCx/fF121GOVJlITLg==
+Bits: AAA=
+Created: 20230619042408
+Publish: 20230619042408
+Activate: 20230619042408
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-161.+161+23350.key b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-161.+161+23350.key
new file mode 100644
index 0000000..cb50883
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-161.+161+23350.key
@@ -0,0 +1 @@
+legacy-161. IN KEY 0 3 161 N80fGvcr8JifzRUJ62R4rQ==
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-161.+161+23350.private b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-161.+161+23350.private
new file mode 100644
index 0000000..dea2850
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-161.+161+23350.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 161 (HMAC_SHA1)
+Key: N80fGvcr8JifzRUJ62R4rQ==
+Bits: AAA=
+Created: 20230619042427
+Publish: 20230619042427
+Activate: 20230619042427
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-162.+162+00032.key b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-162.+162+00032.key
new file mode 100644
index 0000000..126c94f
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-162.+162+00032.key
@@ -0,0 +1 @@
+legacy-162. IN KEY 0 3 162 nSIKzFAGS7/tvBs8JteI+Q==
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-162.+162+00032.private b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-162.+162+00032.private
new file mode 100644
index 0000000..af78756
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-162.+162+00032.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 162 (HMAC_SHA224)
+Key: nSIKzFAGS7/tvBs8JteI+Q==
+Bits: AAA=
+Created: 20230619042555
+Publish: 20230619042555
+Activate: 20230619042555
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-163.+163+48857.key b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-163.+163+48857.key
new file mode 100644
index 0000000..6945b1b
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-163.+163+48857.key
@@ -0,0 +1 @@
+legacy-163. IN KEY 0 3 163 CvaupxnDeES3HnlYhTq53w==
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-163.+163+48857.private b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-163.+163+48857.private
new file mode 100644
index 0000000..590ba14
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-163.+163+48857.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 163 (HMAC_SHA256)
+Key: CvaupxnDeES3HnlYhTq53w==
+Bits: AAA=
+Created: 20230619042525
+Publish: 20230619042525
+Activate: 20230619042525
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-164.+164+09001.key b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-164.+164+09001.key
new file mode 100644
index 0000000..4869618
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-164.+164+09001.key
@@ -0,0 +1 @@
+legacy-164. IN KEY 0 3 164 wDldBJwJrYfPoL1Pj4ucOQ==
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-164.+164+09001.private b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-164.+164+09001.private
new file mode 100644
index 0000000..f06f67a
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-164.+164+09001.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 164 (HMAC_SHA384)
+Key: wDldBJwJrYfPoL1Pj4ucOQ==
+Bits: AAA=
+Created: 20230619042615
+Publish: 20230619042615
+Activate: 20230619042615
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-165.+165+61012.key b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-165.+165+61012.key
new file mode 100644
index 0000000..45a2811
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-165.+165+61012.key
@@ -0,0 +1 @@
+legacy-165. IN KEY 0 3 165 OgZrTcEa8P76hVY+xyN7Wg==
diff --git a/bin/tests/system/nsupdate/ns1/legacy/Klegacy-165.+165+61012.private b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-165.+165+61012.private
new file mode 100644
index 0000000..1635f2a
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/legacy/Klegacy-165.+165+61012.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 165 (HMAC_SHA512)
+Key: OgZrTcEa8P76hVY+xyN7Wg==
+Bits: AAA=
+Created: 20230619042627
+Publish: 20230619042627
+Activate: 20230619042627
diff --git a/bin/tests/system/nsupdate/ns1/many.test.db.in b/bin/tests/system/nsupdate/ns1/many.test.db.in
new file mode 100644
index 0000000..824971b
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/many.test.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns1.example.nil. hostmaster.example.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS ns1.example.nil.
+ NS ns2.example.nil.
diff --git a/bin/tests/system/nsupdate/ns1/max-ttl.db b/bin/tests/system/nsupdate/ns1/max-ttl.db
new file mode 100644
index 0000000..fea00b9
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/max-ttl.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+max-ttl.nil IN SOA ns1.max-ttl.nil. hostmaster.max-ttl.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+max-ttl.nil. NS ns1.max-ttl.nil.
+ns1.max-ttl.nil. A 10.53.0.1
+max-ttl.nil. NS ns2.max-ttl.nil.
+ns2.max-ttl.nil. A 10.53.0.2
+
+$ORIGIN max-ttl.nil.
+* MX 10 mail
+a TXT "foo foo foo"
+ PTR foo.net.
diff --git a/bin/tests/system/nsupdate/ns1/maxjournal.db.in b/bin/tests/system/nsupdate/ns1/maxjournal.db.in
new file mode 100644
index 0000000..d64842b
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/maxjournal.db.in
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns1.example.nil. hostmaster.example.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS ns1.example.nil.
diff --git a/bin/tests/system/nsupdate/ns1/named.conf.in b/bin/tests/system/nsupdate/ns1/named.conf.in
new file mode 100644
index 0000000..2c1899f
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/named.conf.in
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.1; 127.0.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ minimal-responses no;
+ update-quota 1;
+ dnssec-validation no;
+};
+
+acl named-acl {
+ any;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key altkey {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key restricted.example.nil {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key zonesub-key.example.nil {
+ algorithm hmac-md5;
+ secret "1234subk8765";
+};
+
+include "ddns.key";
+
+zone "example.nil" {
+ type primary;
+ file "example.db";
+ check-integrity no;
+ check-mx ignore;
+ update-policy {
+ grant zonesub-key.example.nil zonesub TXT;
+ grant ddns-key.example.nil subdomain example.nil ANY;
+ grant restricted.example.nil subdomain restricted.example.nil ANY;
+ };
+ allow-transfer { any; };
+};
+
+zone "max-ttl.nil" {
+ type primary;
+ file "max-ttl.db";
+ max-zone-ttl 300;
+ check-integrity no;
+ allow-update { named-acl; };
+ allow-transfer { any; };
+};
+
+zone "other.nil" {
+ type primary;
+ file "other.db";
+ check-integrity no;
+ check-mx warn;
+ update-policy local;
+ allow-query { !10.53.0.2; any; };
+ allow-query-on { 10.53.0.1; 127.0.0.1; };
+ allow-transfer { any; };
+};
+
+primaries others {
+ 10.53.0.2 port @PORT@;
+ 10.53.0.2 port @PORT@ key altkey;
+};
+
+zone "update.nil" {
+ type primary;
+ file "update.db";
+ check-integrity no;
+ check-mx fail;
+ allow-update { any; };
+ allow-transfer { any; };
+ also-notify { others; };
+};
+
+zone "unixtime.nil" {
+ type primary;
+ file "unixtime.db";
+ check-integrity no;
+ allow-update { any; };
+ allow-transfer { any; };
+ serial-update-method unixtime;
+};
+
+zone "yyyymmddvv.nil" {
+ type primary;
+ file "yyyymmddvv.db";
+ check-integrity no;
+ allow-update { any; };
+ allow-transfer { any; };
+ serial-update-method date;
+};
+
+include "md5.key";
+include "sha1.key";
+include "sha224.key";
+include "sha256.key";
+include "sha384.key";
+include "sha512.key";
+include "legacy157.key";
+include "legacy161.key";
+include "legacy162.key";
+include "legacy163.key";
+include "legacy164.key";
+include "legacy165.key";
+
+zone "keytests.nil" {
+ type primary;
+ file "keytests.db";
+ update-policy {
+ grant md5-key name md5.keytests.nil. ANY;
+ grant sha1-key name sha1.keytests.nil. ANY;
+ grant sha224-key name sha224.keytests.nil. ANY;
+ grant sha256-key name sha256.keytests.nil. ANY;
+ grant sha384-key name sha384.keytests.nil. ANY;
+ grant sha512-key name sha512.keytests.nil. ANY;
+ grant legacy-157 name 157.keytests.nil. ANY;
+ grant legacy-161 name 161.keytests.nil. ANY;
+ grant legacy-162 name 162.keytests.nil. ANY;
+ grant legacy-163 name 163.keytests.nil. ANY;
+ grant legacy-164 name 164.keytests.nil. ANY;
+ grant legacy-165 name 165.keytests.nil. ANY;
+ };
+};
+
+zone "many.test" {
+ type primary;
+ allow-update { any; };
+ file "many.test.db";
+};
+
+zone "sample" {
+ type primary;
+ allow-update { any; };
+ file "sample.db";
+};
+
+zone "maxjournal.test" {
+ type primary;
+ allow-update { any; };
+ file "maxjournal.db";
+ max-journal-size default;
+};
diff --git a/bin/tests/system/nsupdate/ns1/sample.db.in b/bin/tests/system/nsupdate/ns1/sample.db.in
new file mode 100644
index 0000000..9118bef
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/sample.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA ns1 . 0 0 0 0 0
+@ 0 NS ns1
+ns1 0 A 10.53.0.1
+; a RRset that exists
+exists 0 TXT This RRset exists.
+; nxdomain
+; A named without a TXT RRset
+no-txt 0 A 1.2.3.4
diff --git a/bin/tests/system/nsupdate/ns10/dns.keytab b/bin/tests/system/nsupdate/ns10/dns.keytab
new file mode 100644
index 0000000..95eea90
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns10/dns.keytab
Binary files differ
diff --git a/bin/tests/system/nsupdate/ns10/example.com.db.in b/bin/tests/system/nsupdate/ns10/example.com.db.in
new file mode 100644
index 0000000..f324b19
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns10/example.com.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns10.example.com. hostmaster.example.com. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns10
+ns10 A 10.53.0.10
+single.any.self-srv SRV 0 0 0 machine.example.com.
+many.any.self-srv SRV 0 0 0 machine.example.com.
+many.any.self-srv SRV 0 0 0 notmachine.example.com.
+single.srv.self-srv SRV 0 0 0 machine.example.com.
+many.srv.self-srv SRV 0 0 0 machine.example.com.
+many.srv.self-srv SRV 0 0 0 notmachine.example.com.
diff --git a/bin/tests/system/nsupdate/ns10/in-addr.db.in b/bin/tests/system/nsupdate/ns10/in-addr.db.in
new file mode 100644
index 0000000..dd5d64e
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns10/in-addr.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns10.example.com. hostmaster.example.com. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns10
+ns10 A 10.53.0.10
+single.any.self-ptr PTR machine.example.com.
+many.any.self-ptr PTR machine.example.com.
+many.any.self-ptr PTR notmachine.example.com.
+single.ptr.self-ptr PTR machine.example.com.
+many.ptr.self-ptr PTR machine.example.com.
+many.ptr.self-ptr PTR notmachine.example.com.
diff --git a/bin/tests/system/nsupdate/ns10/machine.ccache b/bin/tests/system/nsupdate/ns10/machine.ccache
new file mode 100644
index 0000000..ced26bd
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns10/machine.ccache
Binary files differ
diff --git a/bin/tests/system/nsupdate/ns10/named.conf.in b/bin/tests/system/nsupdate/ns10/named.conf.in
new file mode 100644
index 0000000..6053924
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns10/named.conf.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.10;
+ notify-source 10.53.0.10;
+ transfer-source 10.53.0.10;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.10; };
+ recursion no;
+ notify yes;
+ minimal-responses no;
+ dnssec-validation no;
+ @TKEY_CONFIGURATION@
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.10 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "in-addr.arpa" {
+ type primary;
+ file "in-addr.db";
+ update-policy { grant EXAMPLE.COM ms-subdomain-self-rhs . PTR; };
+};
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant EXAMPLE.COM ms-selfsub . ANY;
+ grant EXAMPLE.COM ms-subdomain _tcp.example.com SRV;
+ grant EXAMPLE.COM ms-subdomain-self-rhs self-srv.example.com SRV;
+ };
+};
diff --git a/bin/tests/system/nsupdate/ns2/named.conf.in b/bin/tests/system/nsupdate/ns2/named.conf.in
new file mode 100644
index 0000000..848662d
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns2/named.conf.in
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ serial-query-rate 1; // workaround for KB AA-01213
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key altkey {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+view alternate {
+ match-clients { key altkey; };
+
+ zone "update.nil" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "update.alt.bk";
+ allow-transfer { any; };
+ };
+};
+
+view primary {
+ match-clients { any; };
+
+ zone "example.nil" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "example.bk";
+ allow-transfer { any; };
+ };
+
+ zone "update.nil" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "update.bk";
+ allow-transfer { any; };
+ };
+
+ zone "sample" {
+ type primary;
+ allow-update { any; };
+ file "sample.db";
+ };
+};
diff --git a/bin/tests/system/nsupdate/ns2/sample.db.in b/bin/tests/system/nsupdate/ns2/sample.db.in
new file mode 100644
index 0000000..848cc86
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns2/sample.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA ns2 . 0 0 0 0 0
+@ 0 NS ns2
+ns2 0 A 10.53.0.2
+;
+; These prerequistes are reversed, relative to ns1/sample.db.in:
+; 'exists' does not exist.
+nxdomain 0 TXT This RRset exists.
+
+; a name with a TXT RRset
+no-txt 0 TXT This RRset exists
diff --git a/bin/tests/system/nsupdate/ns3/delegation.test.db.in b/bin/tests/system/nsupdate/ns3/delegation.test.db.in
new file mode 100644
index 0000000..195c73b
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/delegation.test.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 10
+delegation.test. IN SOA delegation.test. hostmaster.delegation.test. 1 3600 900 2419200 3600
+delegation.test. IN NS delegation.test.
+delegation.test. IN A 10.53.0.3
diff --git a/bin/tests/system/nsupdate/ns3/dnskey.test.db.in b/bin/tests/system/nsupdate/ns3/dnskey.test.db.in
new file mode 100644
index 0000000..df503fe
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/dnskey.test.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 10
+dnskey.test. IN SOA dnskey.test. hostmaster.dnskey.test. 1 3600 900 2419200 3600
+dnskey.test. IN NS dnskey.test.
+dnskey.test. IN A 10.53.0.3
diff --git a/bin/tests/system/nsupdate/ns3/example.db.in b/bin/tests/system/nsupdate/ns3/example.db.in
new file mode 100644
index 0000000..92c0998
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/example.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+example. 10 IN SOA example. hostmaster.example. 1 3600 900 2419200 3600
+example. 10 IN NS example.
+example. 10 IN A 10.53.0.3
+example. 10 IN NSEC3PARAM 1 1 0 -
diff --git a/bin/tests/system/nsupdate/ns3/multisigner.test.db.in b/bin/tests/system/nsupdate/ns3/multisigner.test.db.in
new file mode 100644
index 0000000..7b4d91c
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/multisigner.test.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+multisigner.test. 10 IN SOA multisigner.test. hostmaster.multisigner.test. 1 3600 900 2419200 3600
+multisigner.test. 10 IN NS multisigner.test.
+multisigner.test. 10 IN A 10.53.0.3
diff --git a/bin/tests/system/nsupdate/ns3/named.conf.in b/bin/tests/system/nsupdate/ns3/named.conf.in
new file mode 100644
index 0000000..0cfa1db
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/named.conf.in
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 no;
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "example" {
+ type primary;
+ allow-update { any; };
+ file "example.db";
+};
+
+zone "nsec3param.test" {
+ type primary;
+ allow-update { any; };
+ file "nsec3param.test.db.signed";
+};
+
+zone "dnskey.test" {
+ type primary;
+ allow-update { any; };
+ file "dnskey.test.db.signed";
+};
+
+zone "many.test" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ allow-update-forwarding { any; };
+ file "many.test.bk";
+};
+
+zone "delegation.test" {
+ type primary;
+ allow-update { any; };
+ file "delegation.test.db.signed";
+};
+
+zone "too-big.test" {
+ type primary;
+ allow-update { any; };
+ max-records 3;
+ file "too-big.test.db";
+};
+
+/* Zone for testing CDS and CDNSKEY updates from other provider */
+zone "multisigner.test" {
+ type primary;
+ allow-update { any; };
+ dnssec-policy "default";
+ file "multisigner.test.db";
+};
diff --git a/bin/tests/system/nsupdate/ns3/nsec3param.test.db.in b/bin/tests/system/nsupdate/ns3/nsec3param.test.db.in
new file mode 100644
index 0000000..b26f5bd
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/nsec3param.test.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 10
+nsec3param.test. IN SOA nsec3param.test. hostmaster.nsec3param.test. 1 3600 900 2419200 3600
+nsec3param.test. IN NS nsec3param.test.
+nsec3param.test. IN A 10.53.0.3
diff --git a/bin/tests/system/nsupdate/ns3/sign.sh b/bin/tests/system/nsupdate/ns3/sign.sh
new file mode 100644
index 0000000..519497c
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/sign.sh
@@ -0,0 +1,50 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=nsec3param.test.
+infile=nsec3param.test.db.in
+zonefile=nsec3param.test.db
+
+keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -P -3 - -H 1 -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
+
+zone=dnskey.test.
+infile=dnskey.test.db.in
+zonefile=dnskey.test.db
+
+keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
+keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -P -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
+
+zone=delegation.test.
+infile=delegation.test.db.in
+zonefile=delegation.test.db
+
+keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 -f KSK $zone)
+keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 $zone)
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -A -3 - -P -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
+
+# Just copy multisigner.db.in because it is signed with dnssec-policy.
+cp multisigner.test.db.in multisigner.test.db
diff --git a/bin/tests/system/nsupdate/ns3/too-big.test.db.in b/bin/tests/system/nsupdate/ns3/too-big.test.db.in
new file mode 100644
index 0000000..45ee9ad
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns3/too-big.test.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 10
+too-big.test. IN SOA too-big.test. hostmaster.too-big.test. 1 3600 900 2419200 3600
+too-big.test. IN NS too-big.test.
+too-big.test. IN A 10.53.0.3
diff --git a/bin/tests/system/nsupdate/ns5/local.db.in b/bin/tests/system/nsupdate/ns5/local.db.in
new file mode 100644
index 0000000..12a5d8b
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns5/local.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+local.nil IN SOA ns5.local.nil. hostmaster.local.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+local.nil. NS ns5.local.nil.
+ns5.local.nil. A 10.53.0.5
+
+$ORIGIN local.nil.
+a A 10.10.10.10
diff --git a/bin/tests/system/nsupdate/ns5/named.args b/bin/tests/system/nsupdate/ns5/named.args
new file mode 100644
index 0000000..fc5a5cd
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns5/named.args
@@ -0,0 +1 @@
+-D nsupdate-ns5 -m record -c named.conf -d 99 -X named.lock -g -U 4 -T maxcachesize=2097152 -T fixedlocal
diff --git a/bin/tests/system/nsupdate/ns5/named.conf.in b/bin/tests/system/nsupdate/ns5/named.conf.in
new file mode 100644
index 0000000..e3c4d1b
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns5/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.5; };
+ recursion no;
+ notify yes;
+ minimal-responses no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "local.nil" {
+ type primary;
+ file "local.db";
+ update-policy local;
+};
diff --git a/bin/tests/system/nsupdate/ns6/in-addr.db.in b/bin/tests/system/nsupdate/ns6/in-addr.db.in
new file mode 100644
index 0000000..9ac2b61
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns6/in-addr.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns5.local.nil. hostmaster.local.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns5
+ns5 A 10.53.0.5
diff --git a/bin/tests/system/nsupdate/ns6/named.args b/bin/tests/system/nsupdate/ns6/named.args
new file mode 100644
index 0000000..48e2bd8
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns6/named.args
@@ -0,0 +1 @@
+-D nsupdate-ns6 -m record -c named.conf -d 99 -X named.lock -g -U 4 -T maxcachesize=2097152 -T fixedlocal
diff --git a/bin/tests/system/nsupdate/ns6/named.conf.in b/bin/tests/system/nsupdate/ns6/named.conf.in
new file mode 100644
index 0000000..c636cfc
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns6/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.6;
+ notify-source 10.53.0.6;
+ transfer-source 10.53.0.6;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.6; };
+ recursion no;
+ notify yes;
+ minimal-responses no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "in-addr.arpa" {
+ type primary;
+ file "in-addr.db";
+ update-policy { grant * tcp-self . PTR(1) ANY(2) A; };
+};
diff --git a/bin/tests/system/nsupdate/ns7/dns.keytab b/bin/tests/system/nsupdate/ns7/dns.keytab
new file mode 100644
index 0000000..08d5ef4
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns7/dns.keytab
Binary files differ
diff --git a/bin/tests/system/nsupdate/ns7/example.com.db.in b/bin/tests/system/nsupdate/ns7/example.com.db.in
new file mode 100644
index 0000000..6e4b17a
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns7/example.com.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns7.example.com. hostmaster.example.com. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns7
+ns7 A 10.53.0.7
+single.any.self-srv SRV 0 0 0 machine.example.com.
+many.any.self-srv SRV 0 0 0 machine.example.com.
+many.any.self-srv SRV 0 0 0 notmachine.example.com.
+single.srv.self-srv SRV 0 0 0 machine.example.com.
+many.srv.self-srv SRV 0 0 0 machine.example.com.
+many.srv.self-srv SRV 0 0 0 notmachine.example.com.
diff --git a/bin/tests/system/nsupdate/ns7/in-addr.db.in b/bin/tests/system/nsupdate/ns7/in-addr.db.in
new file mode 100644
index 0000000..973c77f
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns7/in-addr.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns7.example.com. hostmaster.example.com. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns7
+ns7 A 10.53.0.7
+single.any.self-ptr PTR machine.example.com.
+many.any.self-ptr PTR machine.example.com.
+many.any.self-ptr PTR notmachine.example.com.
+single.ptr.self-ptr PTR machine.example.com.
+many.ptr.self-ptr PTR machine.example.com.
+many.ptr.self-ptr PTR notmachine.example.com.
diff --git a/bin/tests/system/nsupdate/ns7/machine.ccache b/bin/tests/system/nsupdate/ns7/machine.ccache
new file mode 100644
index 0000000..7dcd959
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns7/machine.ccache
Binary files differ
diff --git a/bin/tests/system/nsupdate/ns7/named1.conf.in b/bin/tests/system/nsupdate/ns7/named1.conf.in
new file mode 100644
index 0000000..28d2aea
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns7/named1.conf.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.7;
+ notify-source 10.53.0.7;
+ transfer-source 10.53.0.7;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.7; };
+ recursion no;
+ notify yes;
+ minimal-responses no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "in-addr.arpa" {
+ type primary;
+ file "in-addr.db";
+ update-policy { grant EXAMPLE.COM krb5-subdomain-self-rhs . PTR; };
+};
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant EXAMPLE.COM krb5-self . ANY;
+ grant EXAMPLE.COM krb5-subdomain _tcp.example.com SRV;
+ grant EXAMPLE.COM krb5-subdomain-self-rhs self-srv.example.com SRV;
+ grant EXAMPLE.COM krb5-subdomain-self-rhs self-srv-no-type.example.com;
+ };
+};
diff --git a/bin/tests/system/nsupdate/ns7/named2.conf.in b/bin/tests/system/nsupdate/ns7/named2.conf.in
new file mode 100644
index 0000000..e5886e9
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns7/named2.conf.in
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.7;
+ notify-source 10.53.0.7;
+ transfer-source 10.53.0.7;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.7; };
+ recursion no;
+ notify yes;
+ minimal-responses no;
+ dnssec-validation no;
+ tkey-gssapi-keytab "dns.keytab";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "in-addr.arpa" {
+ type primary;
+ file "in-addr.db";
+ update-policy { grant EXAMPLE.COM krb5-subdomain-self-rhs . PTR; };
+};
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant EXAMPLE.COM krb5-self . ANY;
+ grant EXAMPLE.COM krb5-subdomain _tcp.example.com SRV;
+ grant EXAMPLE.COM krb5-subdomain-self-rhs self-srv.example.com SRV;
+ grant EXAMPLE.COM krb5-subdomain-self-rhs self-srv-no-type.example.com;
+ };
+};
diff --git a/bin/tests/system/nsupdate/ns8/dns-other-than-KRB5_KTNAME.keytab b/bin/tests/system/nsupdate/ns8/dns-other-than-KRB5_KTNAME.keytab
new file mode 100644
index 0000000..3340049
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns8/dns-other-than-KRB5_KTNAME.keytab
Binary files differ
diff --git a/bin/tests/system/nsupdate/ns8/example.com.db.in b/bin/tests/system/nsupdate/ns8/example.com.db.in
new file mode 100644
index 0000000..f83a3eb
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns8/example.com.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns8.example.com. hostmaster.example.com. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns8
+ns8 A 10.53.0.8
diff --git a/bin/tests/system/nsupdate/ns8/in-addr.db.in b/bin/tests/system/nsupdate/ns8/in-addr.db.in
new file mode 100644
index 0000000..f83a3eb
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns8/in-addr.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns8.example.com. hostmaster.example.com. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns8
+ns8 A 10.53.0.8
diff --git a/bin/tests/system/nsupdate/ns8/machine.ccache b/bin/tests/system/nsupdate/ns8/machine.ccache
new file mode 100644
index 0000000..6e75aff
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns8/machine.ccache
Binary files differ
diff --git a/bin/tests/system/nsupdate/ns8/named.conf.in b/bin/tests/system/nsupdate/ns8/named.conf.in
new file mode 100644
index 0000000..f69d3ad
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns8/named.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.8;
+ notify-source 10.53.0.8;
+ transfer-source 10.53.0.8;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.8; };
+ recursion no;
+ notify yes;
+ minimal-responses no;
+ dnssec-validation no;
+ tkey-gssapi-keytab "dns-other-than-KRB5_KTNAME.keytab";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "in-addr.arpa" {
+ type primary;
+ file "in-addr.db";
+ update-policy { grant EXAMPLE.COM krb5-subdomain . PTR; };
+};
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant EXAMPLE.COM krb5-selfsub . ANY;
+ grant EXAMPLE.COM krb5-subdomain _tcp.example.com SRV;
+ };
+};
diff --git a/bin/tests/system/nsupdate/ns9/dns.keytab b/bin/tests/system/nsupdate/ns9/dns.keytab
new file mode 100644
index 0000000..470317f
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns9/dns.keytab
Binary files differ
diff --git a/bin/tests/system/nsupdate/ns9/example.com.db.in b/bin/tests/system/nsupdate/ns9/example.com.db.in
new file mode 100644
index 0000000..cb3fae5
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns9/example.com.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns9.example.com. hostmaster.example.com. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns9
+ns9 A 10.53.0.9
diff --git a/bin/tests/system/nsupdate/ns9/in-addr.db.in b/bin/tests/system/nsupdate/ns9/in-addr.db.in
new file mode 100644
index 0000000..cb3fae5
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns9/in-addr.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns9.example.com. hostmaster.example.com. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns9
+ns9 A 10.53.0.9
diff --git a/bin/tests/system/nsupdate/ns9/machine.ccache b/bin/tests/system/nsupdate/ns9/machine.ccache
new file mode 100644
index 0000000..2b59cec
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns9/machine.ccache
Binary files differ
diff --git a/bin/tests/system/nsupdate/ns9/named.conf.in b/bin/tests/system/nsupdate/ns9/named.conf.in
new file mode 100644
index 0000000..79a1cb9
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns9/named.conf.in
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.9; };
+ recursion no;
+ notify yes;
+ minimal-responses no;
+ dnssec-validation no;
+ @TKEY_CONFIGURATION@
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+key subkey {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "in-addr.arpa" {
+ type primary;
+ file "in-addr.db";
+ update-policy { grant EXAMPLE.COM ms-subdomain . PTR; };
+};
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+ update-policy {
+ grant EXAMPLE.COM ms-self . ANY;
+ grant EXAMPLE.COM ms-subdomain _tcp.example.com SRV;
+ };
+};
+
+zone "denyname.example" {
+ type primary;
+ file "denyname.example.db";
+ update-policy {
+ deny subkey name denyname.example;
+ grant subkey subdomain denyname.example;
+ };
+};
diff --git a/bin/tests/system/nsupdate/resolv.conf b/bin/tests/system/nsupdate/resolv.conf
new file mode 100644
index 0000000..e713bae
--- /dev/null
+++ b/bin/tests/system/nsupdate/resolv.conf
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+nameserver 10.53.0.1
+nameserver 10.53.0.3
diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh
new file mode 100644
index 0000000..7f8c27f
--- /dev/null
+++ b/bin/tests/system/nsupdate/setup.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+#
+# jnl and database files MUST be removed before we start
+#
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns5/named.conf.in ns5/named.conf
+copy_setports ns6/named.conf.in ns6/named.conf
+copy_setports ns7/named1.conf.in ns7/named.conf
+copy_setports ns8/named.conf.in ns8/named.conf
+
+# If "tkey-gssapi-credential" is set in the configuration and GSSAPI support is
+# not available, named will refuse to start. As the test system framework does
+# not support starting named instances conditionally, ensure that
+# "tkey-gssapi-credential" is only present in named.conf if GSSAPI support is
+# available.
+copy_setports ns9/named.conf.in ns9/named.conf.in.tkey
+copy_setports ns10/named.conf.in ns10/named.conf.in.tkey
+if $FEATURETEST --gssapi; then
+ sed 's|@TKEY_CONFIGURATION@|tkey-gssapi-credential "DNS/ns9.example.com@EXAMPLE.COM";|' ns9/named.conf.in.tkey > ns9/named.conf
+ sed 's|@TKEY_CONFIGURATION@|tkey-gssapi-credential "DNS/ns10.example.com@EXAMPLE.COM";|' ns10/named.conf.in.tkey > ns10/named.conf
+else
+ sed 's|@TKEY_CONFIGURATION@||' ns9/named.conf.in.tkey > ns9/named.conf
+ sed 's|@TKEY_CONFIGURATION@||' ns10/named.conf.in.tkey > ns10/named.conf
+fi
+rm -f ns9/named.conf.in.tkey
+rm -f ns10/named.conf.in.tkey
+
+copy_setports verylarge.in verylarge
+
+cp -f ns1/example1.db ns1/example.db
+sed 's/example.nil/other.nil/g' ns1/example1.db > ns1/other.db
+sed 's/example.nil/unixtime.nil/g' ns1/example1.db > ns1/unixtime.db
+sed 's/example.nil/yyyymmddvv.nil/g' ns1/example1.db > ns1/yyyymmddvv.db
+sed 's/example.nil/keytests.nil/g' ns1/example1.db > ns1/keytests.db
+cp -f ns3/example.db.in ns3/example.db
+cp -f ns3/too-big.test.db.in ns3/too-big.test.db
+
+# update_test.pl has its own zone file because it
+# requires a specific NS record set.
+cat <<\EOF >ns1/update.db
+$ORIGIN .
+$TTL 300 ; 5 minutes
+update.nil IN SOA ns1.example.nil. hostmaster.example.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+update.nil. NS ns1.update.nil.
+ns1.update.nil. A 10.53.0.2
+ns2.update.nil. AAAA ::1
+EOF
+
+$TSIGKEYGEN ddns-key.example.nil > ns1/ddns.key
+
+if $FEATURETEST --md5; then
+ $TSIGKEYGEN -a hmac-md5 md5-key > ns1/md5.key
+else
+ echo -n > ns1/md5.key
+fi
+$TSIGKEYGEN -a hmac-sha1 sha1-key > ns1/sha1.key
+$TSIGKEYGEN -a hmac-sha224 sha224-key > ns1/sha224.key
+$TSIGKEYGEN -a hmac-sha256 sha256-key > ns1/sha256.key
+$TSIGKEYGEN -a hmac-sha384 sha384-key > ns1/sha384.key
+$TSIGKEYGEN -a hmac-sha512 sha512-key > ns1/sha512.key
+
+if $FEATURETEST --md5; then
+ echo 'key "legacy-157" { algorithm "hmac-md5"; secret "mGcDSCx/fF121GOVJlITLg=="; };' > ns1/legacy157.key
+else
+ echo "/* MD5 NOT SUPPORTED */" > ns1/legacy157.key
+fi
+echo 'key "legacy-161" { algorithm "hmac-sha1"; secret "N80fGvcr8JifzRUJ62R4rQ=="; };' > ns1/legacy161.key
+echo 'key "legacy-162" { algorithm "hmac-sha224"; secret "nSIKzFAGS7/tvBs8JteI+Q=="; };' > ns1/legacy162.key
+echo 'key "legacy-163" { algorithm "hmac-sha256"; secret "CvaupxnDeES3HnlYhTq53w=="; };' > ns1/legacy163.key
+echo 'key "legacy-164" { algorithm "hmac-sha384"; secret "wDldBJwJrYfPoL1Pj4ucOQ=="; };' > ns1/legacy164.key
+echo 'key "legacy-165" { algorithm "hmac-sha512"; secret "OgZrTcEa8P76hVY+xyN7Wg=="; };' > ns1/legacy165.key
+
+(cd ns3; $SHELL -e sign.sh)
+
+cp -f ns1/many.test.db.in ns1/many.test.db
+
+cp ns1/sample.db.in ns1/sample.db
+cp ns2/sample.db.in ns2/sample.db
+
+cp -f ns1/maxjournal.db.in ns1/maxjournal.db
+
+cp -f ns5/local.db.in ns5/local.db
+cp -f ns6/in-addr.db.in ns6/in-addr.db
+cp -f ns7/in-addr.db.in ns7/in-addr.db
+cp -f ns7/example.com.db.in ns7/example.com.db
+cp -f ns8/in-addr.db.in ns8/in-addr.db
+cp -f ns8/example.com.db.in ns8/example.com.db
+cp -f ns9/in-addr.db.in ns9/in-addr.db
+cp -f ns9/example.com.db.in ns9/example.com.db
+cp -f ns9/example.com.db.in ns9/denyname.example.db
+cp -f ns10/in-addr.db.in ns10/in-addr.db
+cp -f ns10/example.com.db.in ns10/example.com.db
diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh
new file mode 100755
index 0000000..44830d4
--- /dev/null
+++ b/bin/tests/system/nsupdate/tests.sh
@@ -0,0 +1,2262 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+#
+# Uncomment when creating credential cache files.
+#
+# KRB5_CONFIG="$(pwd)/krb/krb5.conf"
+#
+# Cd krb and run krb/setup.sh to create new keys.
+# Run nsupdate system test.
+# Kill the krb5kdc server started by krb/setup.sh.
+# Check the expiry date on the cached machine.ccache with klist is in 2038.
+# Comment out KRB5_CONFIG.
+# Re-run nsupdate system test to confirm everything still works.
+# git add and commit the resulting ns*/machine.ccache and ns*/dns.keytab files.
+# Clean up krb.
+#
+
+status=0
+n=0
+
+nextpartreset ns3/named.run
+
+# wait for zone transfer to complete
+tries=0
+while true; do
+ if [ $tries -eq 10 ]
+ then
+ exit 1
+ fi
+
+ if grep "example.nil/IN.*Transfer status" ns2/named.run > /dev/null
+ then
+ break
+ else
+ echo_i "zones are not fully loaded, waiting..."
+ tries=$((tries + 1))
+ sleep 1
+ fi
+done
+
+has_positive_response() {
+ zone=$1
+ type=$2
+ ns=$3
+ $DIG $DIGOPTS +tcp +norec $zone $type @$ns > dig.out.post.test$n || return 1
+ grep "status: NOERROR" dig.out.post.test$n > /dev/null || return 1
+ grep "ANSWER: 0," dig.out.post.test$n > /dev/null && return 1
+ return 0
+}
+
+ret=0
+echo_i "fetching first copy of zone before update"
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.1 axfr > dig.out.ns1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "fetching second copy of zone before update"
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.2 axfr > dig.out.ns2 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "comparing pre-update copies to known good data"
+digcomp knowngood.ns1.before dig.out.ns1 || ret=1
+digcomp knowngood.ns1.before dig.out.ns2 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "ensure an unrelated zone is mentioned in its NOTAUTH log"
+$NSUPDATE -k ns1/ddns.key > nsupdate.out 2>&1 << END && ret=1
+server 10.53.0.1 ${PORT}
+zone unconfigured.test
+update add unconfigured.test 600 IN A 10.53.0.1
+send
+END
+grep NOTAUTH nsupdate.out > /dev/null 2>&1 || ret=1
+grep ' unconfigured.test: not authoritative' ns1/named.run \
+ > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "ensure a subdomain is mentioned in its NOTAUTH log"
+$NSUPDATE -k ns1/ddns.key > nsupdate.out 2>&1 << END && ret=1
+server 10.53.0.1 ${PORT}
+zone sub.sub.example.nil
+update add sub.sub.sub.example.nil 600 IN A 10.53.0.1
+send
+END
+grep NOTAUTH nsupdate.out > /dev/null 2>&1 || ret=1
+grep ' sub.sub.example.nil: not authoritative' ns1/named.run \
+ > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "updating zone"
+# nsupdate will print a ">" prompt to stdout as it gets each input line.
+$NSUPDATE -k ns1/ddns.key <<END > /dev/null || ret=1
+server 10.53.0.1 ${PORT}
+update add updated.example.nil. 600 A 10.10.10.1
+add updated.example.nil. 600 TXT Foo
+delete t.example.nil.
+
+END
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+echo_i "sleeping 5 seconds for server to incorporate changes"
+sleep 5
+
+ret=0
+echo_i "fetching first copy of zone after update"
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.1 axfr > dig.out.ns1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "fetching second copy of zone after update"
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.2 axfr > dig.out.ns2 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "comparing post-update copies to known good data"
+digcomp knowngood.ns1.after dig.out.ns1 || ret=1
+digcomp knowngood.ns1.after dig.out.ns2 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "testing local update policy"
+pre=$($DIG $DIGOPTS +short new.other.nil. @10.53.0.1 a) || ret=1
+[ -z "$pre" ] || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "updating zone"
+# nsupdate will print a ">" prompt to stdout as it gets each input line.
+$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > /dev/null <<END || ret=1
+zone other.nil.
+update add new.other.nil. 600 IN A 10.10.10.1
+send
+END
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+echo_i "sleeping 5 seconds for server to incorporate changes"
+sleep 5
+
+ret=0
+echo_i "checking result of update"
+post=$($DIG $DIGOPTS +short new.other.nil. @10.53.0.1 a) || ret=1
+[ "$post" = "10.10.10.1" ] || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "comparing post-update copy to known good data"
+digcomp knowngood.ns1.after dig.out.ns1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "testing zone consistency checks"
+# inserting an NS record without a corresponding A or AAAA record should fail
+$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > nsupdate.out 2>&1 << END && ret=1
+update add other.nil. 600 in ns ns3.other.nil.
+send
+END
+grep REFUSED nsupdate.out > /dev/null 2>&1 || ret=1
+# ...but should work if an A record is inserted first:
+$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
+update add ns4.other.nil 600 in a 10.53.0.1
+send
+update add other.nil. 600 in ns ns4.other.nil.
+send
+END
+grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
+# ...or if an AAAA record does:
+$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
+update add ns5.other.nil 600 in aaaa 2001:db8::1
+send
+update add other.nil. 600 in ns ns5.other.nil.
+send
+END
+grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
+# ...or if the NS and A/AAAA are inserted together:
+$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
+update add other.nil. 600 in ns ns6.other.nil.
+update add ns6.other.nil 600 in a 10.53.0.1
+send
+END
+grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+echo_i "sleeping 5 seconds for server to incorporate changes"
+sleep 5
+
+ret=0
+echo_i "checking result of update"
+$DIG $DIGOPTS +short @10.53.0.1 ns other.nil > dig.out.ns1 || ret=1
+grep ns3.other.nil dig.out.ns1 > /dev/null 2>&1 && ret=1
+grep ns4.other.nil dig.out.ns1 > /dev/null 2>&1 || ret=1
+grep ns5.other.nil dig.out.ns1 > /dev/null 2>&1 || ret=1
+grep ns6.other.nil dig.out.ns1 > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "ensure 'check-mx ignore' allows adding MX records containing an address without a warning"
+$NSUPDATE -k ns1/ddns.key > nsupdate.out 2>&1 << END || ret=1
+server 10.53.0.1 ${PORT}
+update add mx03.example.nil 600 IN MX 10 10.53.0.1
+send
+END
+grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
+grep "mx03.example.nil/MX:.*MX is an address" ns1/named.run > /dev/null 2>&1 && ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "ensure 'check-mx warn' allows adding MX records containing an address with a warning"
+$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
+update add mx03.other.nil 600 IN MX 10 10.53.0.1
+send
+END
+grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
+grep "mx03.other.nil/MX:.*MX is an address" ns1/named.run > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "ensure 'check-mx fail' prevents adding MX records containing an address with a warning"
+$NSUPDATE > nsupdate.out 2>&1 << END && ret=1
+server 10.53.0.1 ${PORT}
+update add mx03.update.nil 600 IN MX 10 10.53.0.1
+send
+END
+grep REFUSED nsupdate.out > /dev/null 2>&1 || ret=1
+grep "mx03.update.nil/MX:.*MX is an address" ns1/named.run > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "check SIG(0) key is accepted"
+key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -T KEY -n ENTITY xxx)
+echo "" | $NSUPDATE -k ${key}.private > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check TYPE=0 update is rejected by nsupdate ($n)"
+$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
+ server 10.53.0.1 ${PORT}
+ ttl 300
+ update add example.nil. in type0 ""
+ send
+END
+grep "unknown class/type" nsupdate.out > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check TYPE=0 prerequisite is handled ($n)"
+$NSUPDATE -k ns1/ddns.key <<END > nsupdate.out 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ prereq nxrrset example.nil. type0
+ send
+END
+$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 > dig.out.ns1.$n
+grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that TYPE=0 update is handled ($n)"
+echo "a0e4280000010000000100000000060001c00c000000fe000000000000" |
+$PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp > /dev/null || ret=1
+$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 > dig.out.ns1.$n
+grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that TYPE=0 additional data is handled ($n)"
+echo "a0e4280000010000000000010000060001c00c000000fe000000000000" |
+$PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp > /dev/null || ret=1
+$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 > dig.out.ns1.$n
+grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that update to undefined class is handled ($n)"
+echo "a0e4280000010001000000000000060101c00c000000fe000000000000" |
+$PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp > /dev/null || ret=1
+$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 > dig.out.ns1.$n
+grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that address family mismatch is handled ($n)"
+$NSUPDATE <<END > /dev/null 2>&1 && ret=1
+server ::1
+local 127.0.0.1
+update add 600 txt.example.nil in txt "test"
+send
+END
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+
+n=$((n + 1))
+ret=0
+echo_i "check that unixtime serial number is correctly generated ($n)"
+$DIG $DIGOPTS +short unixtime.nil. soa @10.53.0.1 > dig.out.old.test$n || ret=1
+oldserial=$(awk '{print $3}' dig.out.old.test$n) || ret=1
+start=$($PERL -e 'print time()."\n";')
+$NSUPDATE <<END > /dev/null 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ ttl 600
+ update add new.unixtime.nil in a 1.2.3.4
+ send
+END
+now=$($PERL -e 'print time()."\n";')
+sleep 1
+$DIG $DIGOPTS +short unixtime.nil. soa @10.53.0.1 > dig.out.new.test$n || ret=1
+serial=$(awk '{print $3}' dig.out.new.test$n) || ret=1
+[ "$oldserial" = "$serial" ] && { echo_i "oldserial == serial"; ret=1; }
+if [ "$serial" -lt "$start" ]; then
+ echo_i "out-of-range serial=$serial < start=$start"; ret=1;
+elif [ "$serial" -gt "$now" ]; then
+ echo_i "out-of-range serial=$serial > now=$now"; ret=1;
+fi
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ n=$((n + 1))
+ ret=0
+ echo_i "running update.pl test ($n)"
+ $PERL update_test.pl -s 10.53.0.1 -p ${PORT} update.nil. > perl.update_test.out || ret=1
+ [ $ret -eq 1 ] && { echo_i "failed"; status=1; }
+
+ if $PERL -e 'use Net::DNS; die "Net::DNS too old ($Net::DNS::VERSION < 1.01)" if ($Net::DNS::VERSION < 1.01)' > /dev/null
+ then
+ n=$((n + 1))
+ ret=0
+ echo_i "check for too many NSEC3 iterations log ($n)"
+ grep "updating zone 'update.nil/IN': too many NSEC3 iterations (151)" ns1/named.run > /dev/null || ret=1
+ [ $ret -eq 1 ] && { echo_i "failed"; status=1; }
+ fi
+else
+ echo_i "The second part of this test requires the Net::DNS library." >&2
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "fetching first copy of test zone ($n)"
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.1 axfr > dig.out.ns1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "fetching second copy of test zone ($n)"
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.2 axfr > dig.out.ns2 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "comparing zones ($n)"
+digcomp dig.out.ns1 dig.out.ns2 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+echo_i "SIGKILL and restart server ns1"
+cd ns1
+kill -KILL $(cat named.pid)
+rm named.pid
+cd ..
+sleep 10
+if
+ start_server --noclean --restart --port ${PORT} ns1
+then
+ echo_i "restarted server ns1"
+else
+ echo_i "could not restart server ns1"
+ exit 1
+fi
+sleep 10
+
+n=$((n + 1))
+ret=0
+echo_i "fetching ns1 after hard restart ($n)"
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.1 axfr > dig.out.ns1.after || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "comparing zones ($n)"
+digcomp dig.out.ns1 dig.out.ns1.after || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+echo_i "begin RT #482 regression test"
+
+n=$((n + 1))
+ret=0
+echo_i "update primary ($n)"
+$NSUPDATE -k ns1/ddns.key <<END > /dev/null || ret=1
+server 10.53.0.1 ${PORT}
+update add updated2.example.nil. 600 A 10.10.10.2
+update add updated2.example.nil. 600 TXT Bar
+update delete c.example.nil.
+send
+END
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+sleep 5
+
+echo_i "SIGHUP secondary"
+kill -HUP $(cat ns2/named.pid)
+
+sleep 5
+
+n=$((n + 1))
+ret=0
+echo_i "update primary again ($n)"
+$NSUPDATE -k ns1/ddns.key <<END > /dev/null || ret=1
+server 10.53.0.1 ${PORT}
+update add updated3.example.nil. 600 A 10.10.10.3
+update add updated3.example.nil. 600 TXT Zap
+del d.example.nil.
+send
+END
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+sleep 5
+
+echo_i "SIGHUP secondary again"
+kill -HUP $(cat ns2/named.pid)
+
+sleep 5
+
+n=$((n + 1))
+echo_i "check to 'out of sync' message ($n)"
+if grep "out of sync" ns2/named.run
+then
+ echo_i "failed (found 'out of sync')"
+ status=1
+fi
+
+echo_i "end RT #482 regression test"
+
+n=$((n + 1))
+ret=0
+echo_i "remove nonexistent PTR record ($n)"
+$NSUPDATE -k ns1/ddns.key -d << EOF > nsupdate.out.test$n 2>&1 || ret=1
+server 10.53.0.1 ${PORT}
+zone example.nil.
+update delete nonexistent.example.nil. 0 IN PTR foo.
+send
+EOF
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "remove nonexistent SRV record ($n)"
+$NSUPDATE -k ns1/ddns.key -d << EOF > nsupdate.out.test$n 2>&1 || ret=1
+server 10.53.0.1 ${PORT}
+zone example.nil.
+update delete nonexistent.example.nil. 0 IN SRV 0 0 0 foo.
+send
+EOF
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "start NSEC3PARAM changes via UPDATE on a unsigned zone test ($n)"
+$NSUPDATE << EOF
+server 10.53.0.3 ${PORT}
+update add example 3600 nsec3param 1 0 0 -
+send
+EOF
+
+# the zone is not signed. The nsec3param records should be removed.
+# this also proves that the server is still running.
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocmd +norec example.\
+ @10.53.0.3 nsec3param > dig.out.ns3.$n || ret=1
+grep "ANSWER: 0," dig.out.ns3.$n > /dev/null || ret=1
+grep "flags:[^;]* aa[ ;]" dig.out.ns3.$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "change the NSEC3PARAM ttl via update ($n)"
+$NSUPDATE << EOF
+server 10.53.0.3 ${PORT}
+update add nsec3param.test 3600 NSEC3PARAM 1 0 1 -
+send
+EOF
+
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocmd +norec nsec3param.test.\
+ @10.53.0.3 nsec3param > dig.out.ns3.$n || ret=1
+grep "ANSWER: 1," dig.out.ns3.$n > /dev/null || ret=1
+grep "3600.*NSEC3PARAM" dig.out.ns3.$n > /dev/null || ret=1
+grep "flags:[^;]* aa[ ;]" dig.out.ns3.$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "add a new NSEC3PARAM via update ($n)"
+$NSUPDATE << EOF
+server 10.53.0.3 ${PORT}
+update add nsec3param.test 3600 NSEC3PARAM 1 0 4 -
+send
+EOF
+
+_ret=1
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ $DIG $DIGOPTS +tcp +norec +time=1 +tries=1 @10.53.0.3 nsec3param.test. NSEC3PARAM > dig.out.ns3.$n || _ret=1
+ if grep "ANSWER: 2," dig.out.ns3.$n > /dev/null; then
+ _ret=0
+ break
+ fi
+ sleep 1
+done
+
+if [ $_ret -ne 0 ]; then ret=1; fi
+grep "NSEC3PARAM 1 0 4 -" dig.out.ns3.$n > /dev/null || ret=1
+grep "flags:[^;]* aa[ ;]" dig.out.ns3.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((ret + status)); fi
+
+n=$((n + 1))
+ret=0
+echo_i "add, delete and change the ttl of the NSEC3PARAM rrset via update ($n)"
+$NSUPDATE << EOF
+server 10.53.0.3 ${PORT}
+update delete nsec3param.test NSEC3PARAM
+update add nsec3param.test 7200 NSEC3PARAM 1 0 5 -
+send
+EOF
+
+_ret=1
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ $DIG $DIGOPTS +tcp +norec +time=1 +tries=1 @10.53.0.3 nsec3param.test. NSEC3PARAM > dig.out.ns3.$n || _ret=1
+ if grep "ANSWER: 1," dig.out.ns3.$n > /dev/null; then
+ _ret=0
+ break
+ fi
+ sleep 1
+done
+
+if [ $_ret -ne 0 ]; then ret=1; fi
+grep "7200.*NSEC3PARAM 1 0 5 -" dig.out.ns3.$n > /dev/null || ret=1
+grep "flags:[^;]* aa[ ;]" dig.out.ns3.$n > /dev/null || ret=1
+$JOURNALPRINT ns3/nsec3param.test.db.signed.jnl > jp.out.ns3.$n
+# intermediate TTL changes.
+grep "add nsec3param.test. 7200 IN NSEC3PARAM 1 0 4 -" jp.out.ns3.$n > /dev/null || ret=1
+grep "add nsec3param.test. 7200 IN NSEC3PARAM 1 0 1 -" jp.out.ns3.$n > /dev/null || ret=1
+# delayed adds and deletes.
+grep "add nsec3param.test. 0 IN TYPE65534 .# 6 000180000500" jp.out.ns3.$n > /dev/null || ret=1
+grep "add nsec3param.test. 0 IN TYPE65534 .# 6 000140000100" jp.out.ns3.$n > /dev/null || ret=1
+grep "add nsec3param.test. 0 IN TYPE65534 .# 6 000140000400" jp.out.ns3.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((ret + status)); fi
+
+
+ret=0
+echo_i "testing that rndc stop updates the file"
+$NSUPDATE -k ns1/ddns.key <<END > /dev/null || ret=1
+server 10.53.0.1 ${PORT}
+update add updated4.example.nil. 600 A 10.10.10.3
+send
+END
+sleep 3
+stop_server --use-rndc --port ${CONTROLPORT} ns1
+sleep 3
+# Removing the journal file and restarting the server means
+# that the data served by the new server process are exactly
+# those dumped to the file by "rndc stop".
+rm -f ns1/*jnl
+start_server --noclean --restart --port ${PORT} ns1
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ iret=0
+ $DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ updated4.example.nil. @10.53.0.1 a > dig.out.ns1 || iret=1
+ digcomp knowngood.ns1.afterstop dig.out.ns1 || iret=1
+ [ "$iret" -eq 0 ] && break
+ sleep 1
+done
+[ "$iret" -ne 0 ] && ret=1
+[ "$ret" -eq 0 ] || { echo_i "failed"; status=1; }
+
+ret=0
+echo_i "check that 'nsupdate -l' with a missing keyfile reports the missing file"
+$NSUPDATE -4 -p ${PORT} -l -k ns1/nonexistent.key 2> nsupdate.out < /dev/null && ret=1
+grep ns1/nonexistent.key nsupdate.out > /dev/null || ret=1
+if test $ret -ne 0
+then
+echo_i "failed"; status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check that 'update-policy local' works from localhost address ($n)"
+$NSUPDATE -k ns5/session.key > nsupdate.out.$n 2>&1 << END || ret=1
+server 10.53.0.5 ${PORT}
+local 127.0.0.1
+update add fromlocal.local.nil. 600 A 1.2.3.4
+send
+END
+grep REFUSED nsupdate.out.$n > /dev/null 2>&1 && ret=1
+$DIG $DIGOPTS @10.53.0.5 \
+ +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ fromlocal.local.nil. > dig.out.ns5.$n || ret=1
+grep fromlocal dig.out.ns5.$n > /dev/null 2>&1 || ret=1
+if test $ret -ne 0
+then
+echo_i "failed"; status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check that 'update-policy local' fails from non-localhost address ($n)"
+grep 'match on session key not from localhost' ns5/named.run > /dev/null && ret=1
+$NSUPDATE -k ns5/session.key > nsupdate.out.$n 2>&1 << END && ret=1
+server 10.53.0.5 ${PORT}
+local 10.53.0.1
+update add nonlocal.local.nil. 600 A 4.3.2.1
+send
+END
+grep REFUSED nsupdate.out.$n > /dev/null 2>&1 || ret=1
+grep 'match on session key not from localhost' ns5/named.run > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.5 \
+ +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ nonlocal.local.nil. > dig.out.ns5.$n || ret=1
+grep nonlocal dig.out.ns5.$n > /dev/null 2>&1 && ret=1
+if test $ret -ne 0
+then
+echo_i "failed"; status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check that 'update-policy tcp-self' refuses update of records via UDP ($n)"
+$NSUPDATE > nsupdate.out.$n 2>&1 << END && ret=1
+server 10.53.0.6 ${PORT}
+local 127.0.0.1
+update add 1.0.0.127.in-addr.arpa. 600 PTR localhost.
+send
+END
+grep REFUSED nsupdate.out.$n > /dev/null 2>&1 || ret=1
+$DIG $DIGOPTS @10.53.0.6 \
+ +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ -x 127.0.0.1 > dig.out.ns6.$n
+grep localhost. dig.out.ns6.$n > /dev/null 2>&1 && ret=1
+if test $ret -ne 0
+then
+echo_i "failed"; status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check that 'update-policy tcp-self' permits update of records for the client's own address via TCP ($n)"
+$NSUPDATE -v > nsupdate.out.$n 2>&1 << END || ret=1
+server 10.53.0.6 ${PORT}
+local 127.0.0.1
+update add 1.0.0.127.in-addr.arpa. 600 PTR localhost.
+send
+END
+grep REFUSED nsupdate.out.$n > /dev/null 2>&1 && ret=1
+$DIG $DIGOPTS @10.53.0.6 \
+ +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ -x 127.0.0.1 > dig.out.ns6.$n || ret=1
+grep localhost. dig.out.ns6.$n > /dev/null 2>&1 || ret=1
+if test $ret -ne 0
+then
+echo_i "failed"; status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check that 'update-policy tcp-self' refuses update of records for a different address from the client's own address via TCP ($n)"
+$NSUPDATE -v > nsupdate.out.$n 2>&1 << END && ret=1
+server 10.53.0.6 ${PORT}
+local 127.0.0.1
+update add 1.0.168.192.in-addr.arpa. 600 PTR localhost.
+send
+END
+grep REFUSED nsupdate.out.$n > /dev/null 2>&1 || ret=1
+$DIG $DIGOPTS @10.53.0.6 \
+ +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ -x 192.168.0.1 > dig.out.ns6.$n
+grep localhost. dig.out.ns6.$n > /dev/null 2>&1 && ret=1
+if test $ret -ne 0
+then
+echo_i "failed"; status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check that 'update-policy subdomain' is properly enforced ($n)"
+# "restricted.example.nil" matches "grant ... subdomain restricted.example.nil"
+# and thus this UPDATE should succeed.
+$NSUPDATE -d <<END > nsupdate.out1-$n 2>&1 || ret=1
+server 10.53.0.1 ${PORT}
+key restricted.example.nil 1234abcd8765
+update add restricted.example.nil 0 IN TXT everywhere.
+send
+END
+$DIG $DIGOPTS +tcp @10.53.0.1 restricted.example.nil TXT > dig.out.1.test$n || ret=1
+grep "TXT.*everywhere" dig.out.1.test$n > /dev/null || ret=1
+# "example.nil" does not match "grant ... subdomain restricted.example.nil" and
+# thus this UPDATE should fail.
+$NSUPDATE -d <<END > nsupdate.out2-$n 2>&1 && ret=1
+server 10.53.0.1 ${PORT}
+key restricted.example.nil 1234abcd8765
+update add example.nil 0 IN TXT everywhere.
+send
+END
+$DIG $DIGOPTS +tcp @10.53.0.1 example.nil TXT > dig.out.2.test$n || ret=1
+grep "TXT.*everywhere" dig.out.2.test$n > /dev/null && ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that 'update-policy zonesub' is properly enforced ($n)"
+# grant zonesub-key.example.nil zonesub TXT;
+# the A record update should be rejected as it is not in the type list
+$NSUPDATE -d <<END > nsupdate.out1-$n 2>&1 && ret=1
+server 10.53.0.1 ${PORT}
+key zonesub-key.example.nil 1234subk8765
+update add zonesub.example.nil 0 IN A 1.2.3.4
+send
+END
+$DIG $DIGOPTS +tcp @10.53.0.1 zonesub.example.nil A > dig.out.1.test$n || ret=1
+grep "status: REFUSED" nsupdate.out1-$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.1.test$n > /dev/null || ret=1
+# the TXT record update should be accepted as it is in the type list
+$NSUPDATE -d <<END > nsupdate.out2-$n 2>&1 || ret=1
+server 10.53.0.1 ${PORT}
+key zonesub-key.example.nil 1234subk8765
+update add zonesub.example.nil 0 IN TXT everywhere.
+send
+END
+$DIG $DIGOPTS +tcp @10.53.0.1 zonesub.example.nil TXT > dig.out.2.test$n || ret=1
+grep "status: REFUSED" nsupdate.out2-$n > /dev/null && ret=1
+grep "ANSWER: 1," dig.out.2.test$n > /dev/null || ret=1
+grep "TXT.*everywhere" dig.out.2.test$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check 'grant' in deny name + grant subdomain ($n)"
+$NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || ret=1
+key hmac-sha256:subkey 1234abcd8765
+server 10.53.0.9 ${PORT}
+zone denyname.example
+update add foo.denyname.example 3600 IN TXT added
+send
+EOF
+$DIG $DIGOPTS +tcp @10.53.0.9 foo.denyname.example TXT > dig.out.ns9.test$n
+grep "added" dig.out.ns9.test$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check 'deny' in deny name + grant subdomain ($n)"
+$NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+key hmac-sha256:subkey 1234abcd8765
+server 10.53.0.9 ${PORT}
+zone denyname.example
+update add denyname.example 3600 IN TXT added
+send
+EOF
+$DIG $DIGOPTS +tcp @10.53.0.9 denyname.example TXT > dig.out.ns9.test$n
+grep "added" dig.out.ns9.test$n > /dev/null && ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that changes to the DNSKEY RRset TTL do not have side effects ($n)"
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd dnskey.test. \
+ @10.53.0.3 dnskey | \
+ awk -v port="${PORT}" 'BEGIN { print "server 10.53.0.3", port; }
+ $2 == 10 && $3 == "IN" && $4 == "DNSKEY" { $2 = 600; print "update add", $0 }
+ END { print "send" }' > update.in.$n
+$NSUPDATE update.in.$n
+
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd dnskey.test. \
+ @10.53.0.3 any > dig.out.ns3.$n
+
+grep "600.*DNSKEY" dig.out.ns3.$n > /dev/null || ret=1
+grep TYPE65534 dig.out.ns3.$n > /dev/null && ret=1
+if test $ret -ne 0
+then
+echo_i "failed"; status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check notify with TSIG worked ($n)"
+# if the alternate view received a notify--meaning, the notify was
+# validly signed by "altkey"--then the zonefile update.alt.bk will
+# will have been created.
+[ -f ns2/update.alt.bk ] || ret=1
+if [ $ret -ne 0 ]; then
+ echo_i "failed"
+ status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check type list options ($n)"
+$NSUPDATE -T > typelist.out.T.${n} || { ret=1; echo_i "nsupdate -T failed"; }
+$NSUPDATE -P > typelist.out.P.${n} || { ret=1; echo_i "nsupdate -P failed"; }
+$NSUPDATE -TP > typelist.out.TP.${n} || { ret=1; echo_i "nsupdate -TP failed"; }
+grep ANY typelist.out.T.${n} > /dev/null && { ret=1; echo_i "failed: ANY found (-T)"; }
+grep ANY typelist.out.P.${n} > /dev/null && { ret=1; echo_i "failed: ANY found (-P)"; }
+grep ANY typelist.out.TP.${n} > /dev/null && { ret=1; echo_i "failed: ANY found (-TP)"; }
+grep KEYDATA typelist.out.T.${n} > /dev/null && { ret=1; echo_i "failed: KEYDATA found (-T)"; }
+grep KEYDATA typelist.out.P.${n} > /dev/null && { ret=1; echo_i "failed: KEYDATA found (-P)"; }
+grep KEYDATA typelist.out.TP.${n} > /dev/null && { ret=1; echo_i "failed: KEYDATA found (-TP)"; }
+grep AAAA typelist.out.T.${n} > /dev/null || { ret=1; echo_i "failed: AAAA not found (-T)"; }
+grep AAAA typelist.out.P.${n} > /dev/null && { ret=1; echo_i "failed: AAAA found (-P)"; }
+grep AAAA typelist.out.TP.${n} > /dev/null || { ret=1; echo_i "failed: AAAA not found (-TP)"; }
+if [ $ret -ne 0 ]; then
+ echo_i "failed"
+ status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check command list ($n)"
+(
+while read cmd
+do
+ { echo "$cmd" | $NSUPDATE > /dev/null 2>&1; rc=$?; } || true
+ if test $rc -gt 1 ; then
+ echo_i "failed ($cmd)"
+ ret=1
+ fi
+ { echo "$cmd " | $NSUPDATE > /dev/null 2>&1; rc=$?; } || true
+ if test $rc -gt 1 ; then
+ echo_i "failed ($cmd)"
+ ret=1
+ fi
+done
+exit $ret
+) < commandlist || ret=1
+if [ $ret -ne 0 ]; then
+ status=1
+fi
+
+n=$((n + 1))
+ret=0
+
+n=$((n + 1))
+ret=0
+echo_i "check TSIG key algorithms using legacy K file pairs (nsupdate -k) ($n)"
+if $FEATURETEST --md5
+then
+ ALGS="157 161 162 163 164 165"
+else
+ ALGS="161 162 163 164 165"
+ echo_i "skipping disabled md5 (157) algorithm"
+fi
+for alg in $ALGS; do
+ $NSUPDATE -k ns1/legacy/Klegacy-${alg}.+${alg}+*.key <<END > nsupdate.alg-$alg.out 2>&1 || ret=1
+server 10.53.0.1 ${PORT}
+update add ${alg}.keytests.nil. 600 A 10.10.10.3
+send
+END
+done
+sleep 2
+for alg in $ALGS; do
+ $DIG $DIGOPTS +short @10.53.0.1 ${alg}.keytests.nil | grep 10.10.10.3 > /dev/null 2>&1 || ret=1
+ grep "Use of K\* file pairs for HMAC is deprecated" nsupdate.alg-$alg.out > /dev/null || ret=1
+done
+if [ $ret -ne 0 ]; then
+ echo_i "failed"
+ status=1
+fi
+
+n=$((n + 1))
+ret=0
+
+echo_i "check TSIG key algorithms (nsupdate -k) ($n)"
+if $FEATURETEST --md5
+then
+ ALGS="md5 sha1 sha224 sha256 sha384 sha512"
+else
+ ALGS="sha1 sha224 sha256 sha384 sha512"
+ echo_i "skipping disabled md5 algorithm"
+fi
+for alg in $ALGS; do
+ $NSUPDATE -k ns1/${alg}.key <<END > /dev/null || ret=1
+server 10.53.0.1 ${PORT}
+update add ${alg}.keytests.nil. 600 A 10.10.10.3
+send
+END
+done
+sleep 2
+for alg in $ALGS; do
+ $DIG $DIGOPTS +short @10.53.0.1 ${alg}.keytests.nil | grep 10.10.10.3 > /dev/null 2>&1 || ret=1
+done
+if [ $ret -ne 0 ]; then
+ echo_i "failed"
+ status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check TSIG key algorithms (nsupdate -y) ($n)"
+for alg in md5 sha1 sha224 sha256 sha384 sha512; do
+ secret=$(sed -n 's/.*secret "\(.*\)";.*/\1/p' ns1/${alg}.key)
+ $NSUPDATE -y "hmac-${alg}:${alg}-key:$secret" <<END > /dev/null || ret=1
+server 10.53.0.1 ${PORT}
+update add ${alg}.keytests.nil. 600 A 10.10.10.50
+send
+END
+done
+sleep 2
+for alg in md5 sha1 sha224 sha256 sha384 sha512; do
+ $DIG $DIGOPTS +short @10.53.0.1 ${alg}.keytests.nil | grep 10.10.10.50 > /dev/null 2>&1 || ret=1
+done
+if [ $ret -ne 0 ]; then
+ echo_i "failed"
+ status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check that ttl is capped by max-ttl ($n)"
+$NSUPDATE <<END > /dev/null || ret=1
+server 10.53.0.1 ${PORT}
+update add cap.max-ttl.nil. 600 A 10.10.10.3
+update add nocap.max-ttl.nil. 150 A 10.10.10.3
+send
+END
+sleep 2
+$DIG $DIGOPTS @10.53.0.1 cap.max-ttl.nil | grep "^cap.max-ttl.nil. 300" > /dev/null 2>&1 || ret=1
+$DIG $DIGOPTS @10.53.0.1 nocap.max-ttl.nil | grep "^nocap.max-ttl.nil. 150" > /dev/null 2>&1 || ret=1
+if [ $ret -ne 0 ]; then
+ echo_i "failed"
+ status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "add a record which is truncated when logged. ($n)"
+$NSUPDATE verylarge || ret=1
+$DIG $DIGOPTS +tcp @10.53.0.1 txt txt.update.nil > dig.out.ns1.test$n
+grep "ANSWER: 1," dig.out.ns1.test$n > /dev/null || ret=1
+grep "adding an RR at 'txt.update.nil' TXT .* \[TRUNCATED\]" ns1/named.run > /dev/null || ret=1
+if [ $ret -ne 0 ]; then
+ echo_i "failed"
+ status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check that yyyymmddvv serial number is correctly generated ($n)"
+oldserial=$($DIG $DIGOPTS +short yyyymmddvv.nil. soa @10.53.0.1 | awk '{print $3}') || ret=1
+$NSUPDATE <<END > /dev/null 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ ttl 600
+ update add new.yyyymmddvv.nil in a 1.2.3.4
+ send
+END
+now=$($PERL -e '@lt=localtime(); printf "%.4d%0.2d%0.2d00\n",$lt[5]+1900,$lt[4]+1,$lt[3];')
+sleep 1
+serial=$($DIG $DIGOPTS +short yyyymmddvv.nil. soa @10.53.0.1 | awk '{print $3}') || ret=1
+[ "$oldserial" -ne "$serial" ] || ret=1
+[ "$serial" -eq "$now" ] || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+#
+# Refactor to use perl to launch the parallel updates.
+#
+if false
+then
+n=$((n + 1))
+echo_i "send many simultaneous updates via a update forwarder ($n)"
+ret=0
+for i in 0 1 2 3 4 5 6 7
+do
+(
+ for j in 0 1 2 3 4 5 6 7
+ do
+ (
+ $NSUPDATE << EOF
+server 10.53.0.3 ${PORT}
+zone many.test
+update add $i-$j.many.test 0 IN A 1.2.3.4
+send
+EOF
+ ) &
+ done
+ wait
+) &
+done
+wait
+dig axfr many.test @10.53.0.1 > dig.out.test$n
+lines=$(awk '$4 == "A" { l++ } END { print l }' dig.out.test$n)
+test ${lines:-0} -eq 64 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+fi
+
+n=$((n + 1))
+echo_i "check max-journal-size limits ($n)"
+ret=0
+rm -f nsupdate.out1-$n
+# add one record
+$NSUPDATE << EOF >> nsupdate.out1-$n 2>&1
+server 10.53.0.1 ${PORT}
+zone maxjournal.test
+update add z.maxjournal.test 300 IN A 10.20.30.40
+send
+EOF
+for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
+ # repeatedly add and remove the same set of records to fill up
+ # the journal file without changing the zone content
+ $NSUPDATE << EOF >> nsupdate.out1-$n 2>&1
+server 10.53.0.1 ${PORT}
+zone maxjournal.test
+update add a.maxjournal.test 300 IN A 1.2.3.4
+update add b.maxjournal.test 300 IN A 1.2.3.4
+update add c.maxjournal.test 300 IN A 1.2.3.4
+update add d.maxjournal.test 300 IN A 1.2.3.4
+send
+update del a.maxjournal.test
+update del b.maxjournal.test
+update del c.maxjournal.test
+update del d.maxjournal.test
+send
+EOF
+done
+# check that the journal is big enough to require truncation.
+size=$($PERL -e 'use File::stat; my $sb = stat(@ARGV[0]); printf("%s\n", $sb->size);' ns1/maxjournal.db.jnl)
+[ "$size" -gt 6000 ] || ret=1
+sleep 1
+$RNDCCMD 10.53.0.1 sync maxjournal.test
+check_size_lt_5000() (
+ size=$($PERL -e 'use File::stat; my $sb = stat(@ARGV[0]); printf("%s\n", $sb->size);' ns1/maxjournal.db.jnl)
+ [ "$size" -lt 5000 ]
+)
+retry_quiet 20 check_size_lt_5000 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+echo_i "check check-names processing ($n)"
+ret=0
+$NSUPDATE << EOF > nsupdate.out1-$n 2>&1 && ret=1
+update add # 0 in a 1.2.3.4
+EOF
+grep "bad owner" nsupdate.out1-$n > /dev/null || ret=1
+
+$NSUPDATE << EOF > nsupdate.out2-$n 2>&1 || ret=1
+check-names off
+update add # 0 in a 1.2.3.4
+EOF
+grep "bad owner" nsupdate.out2-$n > /dev/null && ret=1
+
+$NSUPDATE << EOF > nsupdate.out3-$n 2>&1 && ret=1
+update add . 0 in mx 0 #
+EOF
+grep "bad name" nsupdate.out3-$n > /dev/null || ret=1
+
+$NSUPDATE << EOF > nsupdate.out4-$n 2>&1 || ret=1
+check-names off
+update add . 0 in mx 0 #
+EOF
+grep "bad name" nsupdate.out4-$n > /dev/null && ret=1
+
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+echo_i "check adding of delegating NS records processing ($n)"
+ret=0
+$NSUPDATE -v << EOF > nsupdate.out.test$n 2>&1 || ret=1
+server 10.53.0.3 ${PORT}
+zone delegation.test.
+update add child.delegation.test. 3600 NS foo.example.net.
+update add child.delegation.test. 3600 NS bar.example.net.
+send
+EOF
+$DIG $DIGOPTS +tcp @10.53.0.3 ns child.delegation.test > dig.out.ns1.test$n
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
+grep "AUTHORITY: 2" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+echo_i "check deleting of delegating NS records processing ($n)"
+ret=0
+$NSUPDATE -v << EOF > nsupdate.out.test$n 2>&1 || ret=1
+server 10.53.0.3 ${PORT}
+zone delegation.test.
+update del child.delegation.test. 3600 NS foo.example.net.
+update del child.delegation.test. 3600 NS bar.example.net.
+send
+EOF
+$DIG $DIGOPTS +tcp @10.53.0.3 ns child.delegation.test > dig.out.ns1.test$n
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+echo_i "check that adding too many records is blocked ($n)"
+ret=0
+$NSUPDATE -v << EOF > nsupdate.out.test$n 2>&1 && ret=1
+server 10.53.0.3 ${PORT}
+zone too-big.test.
+update add r1.too-big.test 3600 IN TXT r1.too-big.test
+send
+EOF
+grep "update failed: SERVFAIL" nsupdate.out.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +tcp @10.53.0.3 r1.too-big.test TXT > dig.out.ns3.test$n
+grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+grep "records in zone (4) exceeds max-records (3)" ns3/named.run > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check whether valid addresses are used for primary failover (UDP with defaults) ($n)"
+t1=$($PERL -e 'print time()')
+$NSUPDATE <<END > nsupdate.out.test$n 2>&1 && ret=1
+server 10.53.0.4 ${PORT}
+zone unreachable.
+update add unreachable. 600 A 192.0.2.1
+send
+END
+t2=$($PERL -e 'print time()')
+grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out.test$n > /dev/null 2>&1 || ret=1
+grep "not implemented" nsupdate.out.test$n > /dev/null 2>&1 && ret=1
+elapsed=$((t2 - t1))
+# Check that default timeout value is respected, there should be 4 tries with 3 seconds each.
+test $elapsed -lt 12 && ret=1
+test $elapsed -gt 15 && ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check whether valid addresses are used for primary failover (UDP with -u udptimeout) ($n)"
+t1=$($PERL -e 'print time()')
+$NSUPDATE -u 4 -r 1 <<END > nsupdate.out.test$n 2>&1 && ret=1
+server 10.53.0.4 ${PORT}
+zone unreachable.
+update add unreachable. 600 A 192.0.2.1
+send
+END
+t2=$($PERL -e 'print time()')
+grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out.test$n > /dev/null 2>&1 || ret=1
+grep "not implemented" nsupdate.out.test$n > /dev/null 2>&1 && ret=1
+elapsed=$((t2 - t1))
+# Check that given timeout value is respected, there should be 2 tries with 4 seconds each.
+test $elapsed -lt 8 && ret=1
+test $elapsed -gt 12 && ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check whether valid addresses are used for primary failover (UDP with -t timeout) ($n)"
+t1=$($PERL -e 'print time()')
+$NSUPDATE -u 0 -t 8 -r 1 <<END > nsupdate.out.test$n 2>&1 && ret=1
+server 10.53.0.4 ${PORT}
+zone unreachable.
+update add unreachable. 600 A 192.0.2.1
+send
+END
+t2=$($PERL -e 'print time()')
+grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out.test$n > /dev/null 2>&1 || ret=1
+grep "not implemented" nsupdate.out.test$n > /dev/null 2>&1 && ret=1
+elapsed=$((t2 - t1))
+# Check that given timeout value is respected, there should be 2 tries with 4 seconds each.
+test $elapsed -lt 8 && ret=1
+test $elapsed -gt 12 && ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check whether valid addresses are used for primary failover (UDP with -u udptimeout -t timeout) ($n)"
+t1=$($PERL -e 'print time()')
+$NSUPDATE -u 4 -t 30 -r 1 <<END > nsupdate.out.test$n 2>&1 && ret=1
+server 10.53.0.4 ${PORT}
+zone unreachable.
+update add unreachable. 600 A 192.0.2.1
+send
+END
+t2=$($PERL -e 'print time()')
+grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out.test$n > /dev/null 2>&1 || ret=1
+grep "not implemented" nsupdate.out.test$n > /dev/null 2>&1 && ret=1
+elapsed=$((t2 - t1))
+# Check that given timeout value is respected, there should be 2 tries with 4 seconds each, as -u takes precedence over -t.
+test $elapsed -lt 8 && ret=1
+test $elapsed -gt 12 && ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check whether valid addresses are used for primary failover (TCP with -t timeout) ($n)"
+t1=$($PERL -e 'print time()')
+$NSUPDATE -t 8 -v <<END > nsupdate.out.test$n 2>&1 && ret=1
+server 10.53.0.4 ${PORT}
+zone unreachable.
+update add unreachable. 600 A 192.0.2.1
+send
+END
+t2=$($PERL -e 'print time()')
+grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out.test$n > /dev/null 2>&1 || ret=1
+grep "not implemented" nsupdate.out.test$n > /dev/null 2>&1 && ret=1
+elapsed=$((t2 - t1))
+# Check that given timeout value is respected, there should be 1 try with 8 seconds.
+test $elapsed -lt 8 && ret=1
+test $elapsed -gt 12 && ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "ensure bad owner name is fatal in non-interactive mode ($n)"
+$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
+ update add emptylabel..nil. 600 A 10.10.10.1
+END
+grep "invalid owner name: empty label" nsupdate.out > /dev/null || ret=1
+grep "syntax error" nsupdate.out > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "ensure bad owner name is not fatal in interactive mode ($n)"
+$NSUPDATE -i <<END > nsupdate.out 2>&1 || ret=1
+ update add emptylabel..nil. 600 A 10.10.10.1
+END
+grep "invalid owner name: empty label" nsupdate.out > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "ensure invalid key type is fatal in non-interactive mode ($n)"
+$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
+ key badkeytype:example abcd12345678
+END
+grep "unknown key type 'badkeytype'" nsupdate.out > /dev/null || ret=1
+grep "syntax error" nsupdate.out > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "ensure invalid key type is not fatal in interactive mode ($n)"
+$NSUPDATE -i <<END > nsupdate.out 2>&1 || ret=1
+ key badkeytype:example abcd12345678
+END
+grep "unknown key type 'badkeytype'" nsupdate.out > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "ensure unresolvable server name is fatal in non-interactive mode ($n)"
+$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
+ server unresolvable..
+END
+grep "couldn't get address for 'unresolvable..':" nsupdate.out > /dev/null || ret=1
+grep "syntax error" nsupdate.out > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "ensure unresolvable server name is not fatal in interactive mode ($n)"
+$NSUPDATE -i <<END > nsupdate.out 2>&1 || ret=1
+ server unresolvable..
+END
+grep "couldn't get address for 'unresolvable..':" nsupdate.out > /dev/null || ret=1
+grep "syntax error" nsupdate.out > /dev/null && ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check nsupdate -4 -6 ($n)"
+$NSUPDATE -4 -6 <<END > nsupdate.out.test$n 2>&1 && ret=1
+server 10.53.0.3 ${PORT}
+zone delegation.test.
+update del child.delegation.test. 3600 NS foo.example.net.
+update del child.delegation.test. 3600 NS bar.example.net.
+send
+END
+grep "only one of -4 and -6 allowed" nsupdate.out.test$n > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check nsupdate -4 with an IPv6 server address ($n)"
+$NSUPDATE -4 <<END > nsupdate.out.test$n 2>&1 && ret=1
+server fd92:7065:b8e:ffff::2 ${PORT}
+zone delegation.test.
+update del child.delegation.test. 3600 NS foo.example.net.
+update del child.delegation.test. 3600 NS bar.example.net.
+send
+END
+grep "address family not supported" nsupdate.out.test$n > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that TKEY in a update is rejected ($n)"
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 && ret=1
+server 10.53.0.3 ${PORT}
+update add tkey.example 0 in tkey invalid.algorithm. 1516055980 1516140801 1 0 16 gRof8D2BFKvl/vrr9Lmnjw== 16 gRof8D2BFKvl/vrr9Lmnjw==
+send
+END
+grep "UPDATE, status: NOERROR" nsupdate.out.test$n > /dev/null 2>&1 || ret=1
+grep "UPDATE, status: FORMERR" nsupdate.out.test$n > /dev/null 2>&1 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that max records is enforced ($n)"
+nextpart ns6/named.run > /dev/null
+$NSUPDATE -v > nsupdate.out.$n 2>&1 << END
+server 10.53.0.6 ${PORT}
+local 10.53.0.5
+update del 5.0.53.10.in-addr.arpa.
+update add 5.0.53.10.in-addr.arpa. 600 PTR localhost.
+update add 5.0.53.10.in-addr.arpa. 600 PTR other.
+send
+END
+$DIG $DIGOPTS @10.53.0.6 \
+ +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ -x 10.53.0.5 > dig.out.ns6.$n
+# the policy is 'grant * tcp-self . PTR(1) ANY(2) A;' so only the
+# first PTR record should be added.
+grep localhost. dig.out.ns6.$n > /dev/null 2>&1 || ret=1
+grep other. dig.out.ns6.$n > /dev/null 2>&1 && ret=1
+nextpart ns6/named.run > nextpart.out.$n
+grep "attempt to add more records than permitted by policy" nextpart.out.$n > /dev/null || ret=1
+if test $ret -ne 0
+then
+echo_i "failed"; status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check that max records for ANY is enforced ($n)"
+nextpart ns6/named.run > /dev/null
+$NSUPDATE -v > nsupdate.out.$n 2>&1 << END
+server 10.53.0.6 ${PORT}
+local 10.53.0.5
+update del 5.0.53.10.in-addr.arpa.
+update add 5.0.53.10.in-addr.arpa. 600 A 1.2.3.4
+update add 5.0.53.10.in-addr.arpa. 600 A 1.2.3.3
+update add 5.0.53.10.in-addr.arpa. 600 A 1.2.3.2
+update add 5.0.53.10.in-addr.arpa. 600 AAAA ::ffff:1.2.3.4
+update add 5.0.53.10.in-addr.arpa. 600 AAAA ::ffff:1.2.3.3
+update add 5.0.53.10.in-addr.arpa. 600 AAAA ::ffff:1.2.3.2
+send
+END
+$DIG $DIGOPTS @10.53.0.6 \
+ +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ ANY -x 10.53.0.5 > dig.out.ns6.test$n
+nextpart ns6/named.run > nextpart.out.test$n
+grep "attempt to add more records than permitted by policy" nextpart.out.test$n > /dev/null || ret=1
+# the policy is 'grant * tcp-self . PTR(1) ANY(2) A;' so all the A
+# records should have been added as there is no limit and the first 2
+# of the AAAA records added as they match ANY(2).
+c1=$(awk '$4 == "A" { print }' dig.out.ns6.test$n | wc -l)
+c2=$(awk '$4 == "AAAA" { print }' dig.out.ns6.test$n | wc -l)
+test "$c1" -eq 3 -a "$c2" -eq 2 || ret=1
+grep "::ffff:1.2.3.2" dig.out.ns6.test$n && ret=1
+if test $ret -ne 0
+then
+echo_i "failed"; status=1
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "check that DS to the zone apex is ignored ($n)"
+$DIG $DIGOPTS +tcp +norec example DS @10.53.0.3 > dig.out.pre.test$n || ret=1
+grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.pre.test$n > /dev/null || ret=1
+nextpart ns3/named.run > /dev/null
+# specify zone to override the default of adding to parent zone
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 || ret=1
+server 10.53.0.3 ${PORT}
+zone example
+update add example 0 in DS 14364 10 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C
+send
+END
+msg=": attempt to add a DS record at zone apex ignored"
+nextpart ns3/named.run | grep "$msg" > /dev/null || ret=1
+$DIG $DIGOPTS +tcp +norec example DS @10.53.0.3 > dig.out.post.test$n || ret=1
+grep "status: NOERROR" dig.out.post.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.post.test$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that CDS with mismatched algorithm to DNSSEC multisigner zone is not allowed ($n)"
+$DIG $DIGOPTS +tcp +norec multisigner.test CDS @10.53.0.3 > dig.out.pre.test$n || ret=1
+grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.pre.test$n > /dev/null || ret=1
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 && ret=1
+server 10.53.0.3 ${PORT}
+zone multisigner.test
+update add multisigner.test 3600 IN CDS 14364 14 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C
+send
+END
+msg=": bad CDS RRset"
+nextpart ns3/named.run | grep "$msg" > /dev/null || ret=1
+$DIG $DIGOPTS +tcp +norec multisigner.test CDS @10.53.0.3 > dig.out.post.test$n || ret=1
+grep "status: NOERROR" dig.out.post.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.post.test$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that CDNSKEY with mismatched algorithm to DNSSEC multisigner zone is not allowed ($n)"
+$DIG $DIGOPTS +tcp +norec multisigner.test CDNSKEY @10.53.0.3 > dig.out.pre.test$n || ret=1
+grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.pre.test$n > /dev/null || ret=1
+nextpart ns3/named.run > /dev/null
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 && ret=1
+server 10.53.0.3 ${PORT}
+zone multisigner.test
+update add multisigner.test 3600 IN CDNSKEY 257 3 14 d0NQ5PKmDz6P0B1WPMH9/UKRux/toSFwV2nTJYPA1Cx8pB0sJGTXbVhG U+6gye7VCHDhGIn9CjVfb2RJPW7GnQ==
+send
+END
+msg=": bad CDNSKEY RRset"
+nextpart ns3/named.run | grep "$msg" > /dev/null || ret=1
+$DIG $DIGOPTS +tcp +norec multisigner.test CDNSKEY @10.53.0.3 > dig.out.post.test$n || ret=1
+grep "status: NOERROR" dig.out.post.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.post.test$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that CDS to DNSSEC multisigner zone is allowed ($n)"
+$DIG $DIGOPTS +tcp +norec multisigner.test CDS @10.53.0.3 > dig.out.pre.test$n || ret=1
+grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.pre.test$n > /dev/null || ret=1
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 || ret=1
+server 10.53.0.3 ${PORT}
+zone multisigner.test
+update add multisigner.test 3600 IN CDS 14364 13 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C
+send
+END
+retry_quiet 5 has_positive_response multisigner.test CDS 10.53.0.3 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that CDNSKEY to DNSSEC multisigner zone is allowed ($n)"
+$DIG $DIGOPTS +tcp +norec multisigner.test CDNSKEY @10.53.0.3 > dig.out.pre.test$n || ret=1
+grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.pre.test$n > /dev/null || ret=1
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 || ret=1
+server 10.53.0.3 ${PORT}
+zone multisigner.test
+update add multisigner.test 3600 IN CDNSKEY 257 3 13 d0NQ5PKmDz6P0B1WPMH9/UKRux/toSFwV2nTJYPA1Cx8pB0sJGTXbVhG U+6gye7VCHDhGIn9CjVfb2RJPW7GnQ==
+send
+END
+retry_quiet 5 has_positive_response multisigner.test CDNSKEY 10.53.0.3 || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that excessive NSEC3PARAM iterations are rejected by nsupdate ($n)"
+$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 && ret=1
+server 10.53.0.3 ${PORT}
+zone example
+update add example 0 in NSEC3PARAM 1 0 151 -
+END
+grep "NSEC3PARAM has excessive iterations (> 150)" nsupdate.out.test$n >/dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check nsupdate retries with another server on REFUSED response ($n)"
+# resolv.conf uses 10.53.0.1 followed by 10.53.0.3; example is only
+# served by 10.53.0.3, so we should fail over to the second server;
+# that's what we're testing for. (failure is still expected, however,
+# because the address lookup for the primary doesn't use the overridden
+# resolv.conf file).
+$NSUPDATE -D -C resolv.conf -p ${PORT} << EOF > nsupdate.out.test$n 2>&1 && ret=1
+zone example
+update add a 3600 IN A 1.2.3.4
+send
+EOF
+grep '10.53.0.1.*REFUSED' nsupdate.out.test$n > /dev/null || ret=1
+grep 'Reply from SOA query' nsupdate.out.test$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that update is rejected if query is not allowed ($n)"
+{
+ $NSUPDATE -d <<END && ret=1
+ local 10.53.0.2
+ server 10.53.0.1 ${PORT}
+ update add reject.other.nil 3600 IN TXT Whatever
+ send
+END
+} > nsupdate.out.test$n 2>&1
+grep 'failed: REFUSED' nsupdate.out.test$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that update is rejected if quota is exceeded ($n)"
+for loop in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
+{
+ $NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > /dev/null 2>&1 <<END
+ update add txt-$loop.other.nil 3600 IN TXT Whatever
+ send
+END
+} &
+done
+wait_for_log 10 "too many DNS UPDATEs queued" ns1/named.run || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+if ! $FEATURETEST --gssapi ; then
+ echo_i "SKIPPED: GSSAPI tests"
+else
+ n=$((n + 1))
+ ret=0
+ echo_i "check GSS-API TKEY request rcode against a non configured server ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ send
+EOF
+ grep "response to GSS-TSIG query was unsuccessful (REFUSED)" nsupdate.out.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ copy_setports ns7/named2.conf.in ns7/named.conf
+ rndc_reload ns7 10.53.0.7
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check krb5-self match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update add machine.example.com 3600 IN A 10.53.0.7
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.7 machine.example.com A > dig.out.ns7.test$n
+ grep "status: NOERROR" dig.out.ns7.test$n > /dev/null || ret=1
+ grep "machine.example.com..*A.*10.53.0.7" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check krb5-self no-match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update add foo.example.com 3600 IN A 10.53.0.7
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.7 foo.example.com A > dig.out.ns7.test$n
+ grep "status: NXDOMAIN" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check krb5-subdomain match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update add _xxx._tcp.example.com 3600 IN SRV 0 0 0 machine.example.com
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.7 _xxx._tcp.example.com SRV > dig.out.ns7.test$n
+ grep "status: NOERROR" dig.out.ns7.test$n > /dev/null || ret=1
+ grep "_xxx._tcp.example.com.*SRV.*0 0 0 machine.example.com" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check krb5-subdomain no-match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update add _xxx._udp.example.com 3600 IN SRV 0 0 0 machine.example.com
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.7 _xxx._udp.example.com SRV > dig.out.ns7.test$n
+ grep "status: NXDOMAIN" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs match PTR ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone in-addr.arpa
+ update add 4.3.2.1.in-addr.arpa 3600 IN PTR machine.example.com
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.7 4.3.2.1.in-addr.arpa PTR > dig.out.ns7.test$n
+ grep "status: NOERROR" dig.out.ns7.test$n > /dev/null || ret=1
+ grep "4.3.2.1.in-addr.arpa.*PTR.*machine.example.com" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs no-match PTR ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone in-addr.arpa
+ update add 5.3.2.1.in-addr.arpa 3600 IN PTR notme.example.com
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.7 5.3.2.1.in-addr.arpa PTR > dig.out.ns7.test$n
+ grep "status: NXDOMAIN" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs match SRV ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update add _xxx.self-srv.example.com 3600 IN SRV 0 0 0 machine.example.com
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.7 _xxx.self-srv.example.com ANY > dig.out.ns7.test$n
+ grep "status: NOERROR" dig.out.ns7.test$n > /dev/null || ret=1
+ grep "_xxx.self-srv.example.com.*SRV.*0 0 0 machine.example.com" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs no listed types match (SRV & TXT) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update add _xxx.self-srv-no-type.example.com 3600 IN SRV 0 0 0 machine.example.com
+ update add _xxx.self-srv-no-type.example.com 3600 IN TXT a txt record
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.7 _xxx.self-srv-no-type.example.com ANY > dig.out.ns7.test$n
+ grep "status: NOERROR" dig.out.ns7.test$n > /dev/null || ret=1
+ grep '_xxx.self-srv-no-type.example.com.*SRV.*0 0 0 machine.example.com' dig.out.ns7.test$n > /dev/null || ret=1
+ grep '_xxx.self-srv-no-type.example.com.*TXT.*"a" "txt" "record"' dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs no-match RDATA (SRV) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update add _yyy.self-srv.example.com 3600 IN SRV 0 0 0 notme.example.com
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.7 _yyy.self-srv.example.com SRV > dig.out.ns7.test$n
+ grep "status: NXDOMAIN" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs no-match TYPE (TXT) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update add _yyy.self-srv.example.com 3600 IN TXT a-txt-record
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.7 _yyy.self-srv.example.com TXT > dig.out.ns7.test$n
+ grep "status: NXDOMAIN" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs delete PTR (matching PTR) ($n)"
+ $DIG $DIGOPTS +tcp @10.53.0.7 single.ptr.self-ptr.in-addr.arpa PTR > dig.out.ns7.pre.test$n
+ grep "status: NOERROR" dig.out.ns7.pre.test$n > /dev/null || ret=1
+ grep "ANSWER: 1," dig.out.ns7.pre.test$n > /dev/null || ret=1
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone in-addr.arpa
+ update delete single.ptr.self-ptr.in-addr.arpa PTR
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.7 single.ptr.self-ptr.in-addr.arpa PTR > dig.out.ns7.test$n
+ grep "status: NXDOMAIN" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs delete PTR (matching PTR with non-matching PTR) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone in-addr.arpa
+ update delete many.ptr.self-ptr.in-addr.arpa PTR
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.7 many.ptr.self-ptr.in-addr.arpa PTR > dig.out.ns7.test$n
+ grep "status: NOERROR" dig.out.ns7.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs delete ANY (matching PTR) ($n)"
+ $DIG $DIGOPTS +tcp @10.53.0.7 single.any.self-ptr.in-addr.arpa PTR > dig.out.ns7.pre.test$n
+ grep "status: NOERROR" dig.out.ns7.pre.test$n > /dev/null || ret=1
+ grep "ANSWER: 1," dig.out.ns7.pre.test$n > /dev/null || ret=1
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone in-addr.arpa
+ update delete single.any.self-ptr.in-addr.arpa
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.7 single.any.self-ptr.in-addr.arpa PTR > dig.out.ns7.test$n
+ grep "status: NXDOMAIN" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs delete ANY (matching PTR with non-matching PTR) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone in-addr.arpa
+ update delete many.any.self-ptr.in-addr.arpa
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.7 many.any.self-ptr.in-addr.arpa PTR > dig.out.ns7.test$n
+ grep "status: NOERROR" dig.out.ns7.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs delete SRV (matching SRV) ($n)"
+ $DIG $DIGOPTS +tcp @10.53.0.7 single.srv.self-srv.example.com SRV > dig.out.ns7.pre.test$n
+ grep "status: NOERROR" dig.out.ns7.pre.test$n > /dev/null || ret=1
+ grep "ANSWER: 1," dig.out.ns7.pre.test$n > /dev/null || ret=1
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update delete single.srv.self-srv.example.com SRV
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.7 single.srv.self-srv.example.com SRV > dig.out.ns7.test$n
+ grep "status: NXDOMAIN" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs delete SRV (matching SRV with non-matching SRV) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update delete many.srv.self-srv.example.com SRV
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.7 many.srv.self-srv.example.com SRV > dig.out.ns7.test$n
+ grep "status: NOERROR" dig.out.ns7.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs delete ANY (matching SRV) ($n)"
+ $DIG $DIGOPTS +tcp @10.53.0.7 single.any.self-srv.example.com SRV > dig.out.ns7.pre.test$n
+ grep "status: NOERROR" dig.out.ns7.pre.test$n > /dev/null || ret=1
+ grep "ANSWER: 1," dig.out.ns7.pre.test$n > /dev/null || ret=1
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update delete single.any.self-srv.example.com
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.7 single.any.self-srv.example.com SRV > dig.out.ns7.test$n
+ grep "status: NXDOMAIN" dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check krb5-subdomain-self-rhs delete ANY (matching SRV with non-matching SRV) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.7 ${PORT}
+ zone example.com
+ update delete many.any.self-srv.example.com
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.7 many.any.self-srv.example.com SRV > dig.out.ns7.test$n
+ grep "status: NOERROR" dig.out.ns7.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns7.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check krb5-selfsub match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns8/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.8 ${PORT}
+ zone example.com
+ update add xxx.machine.example.com 3600 IN A 10.53.0.8
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.8 xxx.machine.example.com A > dig.out.ns8.test$n
+ grep "status: NOERROR" dig.out.ns8.test$n > /dev/null || ret=1
+ grep "xxx.machine.example.com..*A.*10.53.0.8" dig.out.ns8.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check krb5-selfsub no-match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns8/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.8 ${PORT}
+ zone example.com
+ update add foo.example.com 3600 IN A 10.53.0.8
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.8 foo.example.com A > dig.out.ns8.test$n
+ grep "status: NXDOMAIN" dig.out.ns8.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check ms-self match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns9/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.9 ${PORT}
+ zone example.com
+ update add machine.example.com 3600 IN A 10.53.0.9
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.9 machine.example.com A > dig.out.ns9.test$n
+ grep "status: NOERROR" dig.out.ns9.test$n > /dev/null || ret=1
+ grep "machine.example.com..*A.*10.53.0.9" dig.out.ns9.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check ms-self no-match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns9/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.9 ${PORT}
+ zone example.com
+ update add foo.example.com 3600 IN A 10.53.0.9
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.9 foo.example.com A > dig.out.ns9.test$n
+ grep "status: NXDOMAIN" dig.out.ns9.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check ms-subdomain match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns9/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.9 ${PORT}
+ zone example.com
+ update add _xxx._tcp.example.com 3600 IN SRV 0 0 0 machine.example.com
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.9 _xxx._tcp.example.com SRV > dig.out.ns9.test$n
+ grep "status: NOERROR" dig.out.ns9.test$n > /dev/null || ret=1
+ grep "_xxx._tcp.example.com.*SRV.*0 0 0 machine.example.com" dig.out.ns9.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check ms-subdomain no-match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns9/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.9 ${PORT}
+ zone example.com
+ update add _xxx._udp.example.com 3600 IN SRV 0 0 0 machine.example.com
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.9 _xxx._udp.example.com SRV > dig.out.ns9.test$n
+ grep "status: NXDOMAIN" dig.out.ns9.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs match (PTR) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone in-addr.arpa
+ update add 4.3.2.1.in-addr.arpa 3600 IN PTR machine.example.com
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.10 4.3.2.1.in-addr.arpa PTR > dig.out.ns10.test$n
+ grep "status: NOERROR" dig.out.ns10.test$n > /dev/null || ret=1
+ grep "4.3.2.1.in-addr.arpa.*PTR.*machine.example.com" dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs no-match (PTR) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone in-addr.arpa
+ update add 5.3.2.1.in-addr.arpa 3600 IN PTR notme.example.com
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.10 5.3.2.1.in-addr.arpa PTR > dig.out.ns10.test$n
+ grep "status: NXDOMAIN" dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs match (SRV) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone example.com
+ update add _xxx.self-srv.example.com 3600 IN SRV 0 0 0 machine.example.com
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.10 _xxx.self-srv.example.com SRV > dig.out.ns10.test$n
+ grep "status: NOERROR" dig.out.ns10.test$n > /dev/null || ret=1
+ grep "_xxx.self-srv.example.com.*SRV.*0 0 0 machine.example.com" dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs no-match (SRV) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone example.com
+ update add _yyy.self-srv.example.com 3600 IN SRV 0 0 0 notme.example.com
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.10 _yyy.self-srv.example.com SRV > dig.out.ns10.test$n
+ grep "status: NXDOMAIN" dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs delete SRV (matching SRV) ($n)"
+ $DIG $DIGOPTS +tcp @10.53.0.10 single.srv.self-srv.example.com SRV > dig.out.ns10.pre.test$n
+ grep "status: NOERROR" dig.out.ns10.pre.test$n > /dev/null || ret=1
+ grep "ANSWER: 1," dig.out.ns10.pre.test$n > /dev/null || ret=1
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone example.com
+ update delete single.srv.self-srv.example.com SRV
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.10 single.srv.self-srv.example.com SRV > dig.out.ns10.test$n
+ grep "status: NXDOMAIN" dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs delete SRV (matching SRV with non-matching SRV) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone example.com
+ update delete many.srv.self-srv.example.com SRV
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.10 many.srv.self-srv.example.com SRV > dig.out.ns10.test$n
+ grep "status: NOERROR" dig.out.ns10.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs delete PTR (matching PTR) ($n)"
+ $DIG $DIGOPTS +tcp @10.53.0.10 single.ptr.self-ptr.in-addr.arpa PTR > dig.out.ns10.pre.test$n
+ grep "status: NOERROR" dig.out.ns10.pre.test$n > /dev/null || ret=1
+ grep "ANSWER: 1," dig.out.ns10.pre.test$n > /dev/null || ret=1
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone in-addr.arpa
+ update delete single.ptr.self-ptr.in-addr.arpa PTR
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.10 single.ptr.self-ptr.in-addr.arpa PTR > dig.out.ns10.test$n
+ grep "status: NXDOMAIN" dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs delete PTR (matching PTR with non-matching PTR) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone in-addr.arpa
+ update delete many.ptr.self-ptr.in-addr.arpa PTR
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.10 many.ptr.self-ptr.in-addr.arpa PTR > dig.out.ns10.test$n
+ grep "status: NOERROR" dig.out.ns10.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs delete ANY (matching PTR) ($n)"
+ $DIG $DIGOPTS +tcp @10.53.0.10 single.any.self-ptr.in-addr.arpa PTR > dig.out.ns10.pre.test$n
+ grep "status: NOERROR" dig.out.ns10.pre.test$n > /dev/null || ret=1
+ grep "ANSWER: 1," dig.out.ns10.pre.test$n > /dev/null || ret=1
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone in-addr.arpa
+ update delete single.any.self-ptr.in-addr.arpa
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.10 single.any.self-ptr.in-addr.arpa PTR > dig.out.ns10.test$n
+ grep "status: NXDOMAIN" dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs delete ANY (matching PTR with non-matching PTR) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone in-addr.arpa
+ update delete many.any.self-ptr.in-addr.arpa
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.10 many.any.self-ptr.in-addr.arpa PTR > dig.out.ns10.test$n
+ grep "status: NOERROR" dig.out.ns10.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs delete ANY (matching SRV) ($n)"
+ $DIG $DIGOPTS +tcp @10.53.0.10 single.any.self-srv.example.com SRV > dig.out.ns10.pre.test$n
+ grep "status: NOERROR" dig.out.ns10.pre.test$n > /dev/null || ret=1
+ grep "ANSWER: 1," dig.out.ns10.pre.test$n > /dev/null || ret=1
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone example.com
+ update delete single.any.self-srv.example.com
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.10 single.any.self-srv.example.com SRV > dig.out.ns10.test$n
+ grep "status: NXDOMAIN" dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n+1))
+ ret=0
+ echo_i "check ms-subdomain-self-rhs delete ANY (matching SRV with non-matching SRV) ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone example.com
+ update delete many.any.self-srv.example.com
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.10 many.any.self-srv.example.com SRV > dig.out.ns10.test$n
+ grep "status: NOERROR" dig.out.ns10.test$n > /dev/null || ret=1
+ grep "ANSWER: 2," dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check ms-selfsub match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE -d << EOF > nsupdate.out.test$n 2>&1 || ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone example.com
+ update add xxx.machine.example.com 3600 IN A 10.53.0.10
+ send
+EOF
+ $DIG $DIGOPTS +tcp @10.53.0.10 xxx.machine.example.com A > dig.out.ns10.test$n
+ grep "status: NOERROR" dig.out.ns10.test$n > /dev/null || ret=1
+ grep "xxx.machine.example.com..*A.*10.53.0.10" dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+ n=$((n + 1))
+ ret=0
+ echo_i "check ms-selfsub no-match ($n)"
+ KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache"
+ export KRB5CCNAME
+ $NSUPDATE << EOF > nsupdate.out.test$n 2>&1 && ret=1
+ gsstsig
+ realm EXAMPLE.COM
+ server 10.53.0.10 ${PORT}
+ zone example.com
+ update add foo.example.com 3600 IN A 10.53.0.10
+ send
+EOF
+ grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.10 foo.example.com A > dig.out.ns10.test$n
+ grep "status: NXDOMAIN" dig.out.ns10.test$n > /dev/null || ret=1
+ [ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/nsupdate/tests_sh_nsupdate.py b/bin/tests/system/nsupdate/tests_sh_nsupdate.py
new file mode 100644
index 0000000..897eb08
--- /dev/null
+++ b/bin/tests/system/nsupdate/tests_sh_nsupdate.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_nsupdate(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/nsupdate/update_test.pl b/bin/tests/system/nsupdate/update_test.pl
new file mode 100644
index 0000000..835f1f8
--- /dev/null
+++ b/bin/tests/system/nsupdate/update_test.pl
@@ -0,0 +1,429 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Dynamic update test suite.
+#
+# Usage:
+#
+# perl update_test.pl [-s server] [-p port] zone
+#
+# The server defaults to 127.0.0.1.
+# The port defaults to 53.
+#
+# The "Special NS rules" tests will only work correctly if the
+# zone has no NS records to begin with, or alternatively has a
+# single NS record pointing at the name "ns1" (relative to
+# the zone name).
+#
+# Installation notes:
+#
+# This program uses the Net::DNS::Resolver module.
+# You can install it by saying
+#
+# perl -MCPAN -e "install Net::DNS"
+#
+
+use Getopt::Std;
+use Net::DNS;
+use Net::DNS::Update;
+use Net::DNS::Resolver;
+
+$opt_s = "127.0.0.1";
+$opt_p = 53;
+
+getopt('s:p:');
+
+$res = new Net::DNS::Resolver;
+$res->nameservers($opt_s);
+$res->port($opt_p);
+$res->defnames(0); # Do not append default domain.
+
+@ARGV == 1 or die
+ "usage: perl update_test.pl [-s server] [-p port] zone\n";
+
+$zone = shift @ARGV;
+
+my $failures = 0;
+
+sub assert {
+ my ($cond, $explanation) = @_;
+ if (!$cond) {
+ print "Test Failed: $explanation ***\n";
+ $failures++;
+ }
+}
+
+sub test {
+ my ($expected, @records) = @_;
+
+ my $update = new Net::DNS::Update("$zone");
+
+ foreach $rec (@records) {
+ $update->push(@$rec);
+ }
+
+ $reply = $res->send($update);
+
+ # Did it work?
+ if (defined $reply) {
+ my $rcode = $reply->header->rcode;
+ assert($rcode eq $expected, "expected $expected, got $rcode");
+ } else {
+ print "Update failed: ", $res->errorstring, "\n";
+ $failures++;
+ }
+}
+
+sub section {
+ my ($msg) = @_;
+ print "$msg\n";
+}
+
+section("Delete any leftovers from previous tests");
+test("NOERROR", ["update", rr_del("a.$zone")]);
+test("NOERROR", ["update", rr_del("b.$zone")]);
+test("NOERROR", ["update", rr_del("c.$zone")]);
+test("NOERROR", ["update", rr_del("d.$zone")]);
+test("NOERROR", ["update", rr_del("e.$zone")]);
+test("NOERROR", ["update", rr_del("f.$zone")]);
+test("NOERROR", ["update", rr_del("ns.s.$zone")]);
+test("NOERROR", ["update", rr_del("s.$zone")]);
+test("NOERROR", ["update", rr_del("t.$zone")]);
+test("NOERROR", ["update", rr_del("*.$zone")]);
+test("NOERROR", ["update", rr_del("u.$zone")]);
+test("NOERROR", ["update", rr_del("a.u.$zone")]);
+test("NOERROR", ["update", rr_del("b.u.$zone")]);
+
+section("Simple prerequisites in the absence of data");
+# Name is in Use
+test("NXDOMAIN", ["pre", yxdomain("a.$zone")]);
+# RRset exists (value independent)
+test("NXRRSET", ["pre", yxrrset("a.$zone A")]);
+# Name is not in use
+test("NOERROR", ["pre", nxdomain("a.$zone")]);
+# RRset does not exist
+test("NOERROR", ["pre", nxrrset("a.$zone A")]);
+# RRset exists (value dependent)
+test("NXRRSET", ["pre", yxrrset("a.$zone A 73.80.65.49")]);
+
+
+section ("Simple creation of data");
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]);
+
+section ("Simple prerequisites in the presence of data");
+# Name is in use
+test("NOERROR", ["pre", yxdomain("a.$zone")]);
+# RRset exists (value independent)
+test("NOERROR", ["pre", yxrrset("a.$zone A")]);
+# Name is not in use
+test("YXDOMAIN", ["pre", nxdomain("a.$zone")]);
+# RRset does not exist
+test("YXRRSET", ["pre", nxrrset("a.$zone A")]);
+# RRset exists (value dependent)
+test("NOERROR", ["pre", yxrrset("a.$zone A 73.80.65.49")]);
+
+#
+# Merging of RRsets
+#
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]);
+
+section("Detailed tests of \"RRset exists (value dependent)\" prerequisites");
+test("NOERROR", ["pre",
+ yxrrset("a.$zone A 73.80.65.49"),
+ yxrrset("a.$zone A 73.80.65.50")]);
+test("NOERROR", ["pre",
+ yxrrset("a.$zone A 73.80.65.50"),
+ yxrrset("a.$zone A 73.80.65.49")]);
+test("NXRRSET", ["pre", yxrrset("a.$zone A 73.80.65.49")]);
+test("NXRRSET", ["pre", yxrrset("a.$zone A 73.80.65.50")]);
+test("NXRRSET", ["pre",
+ yxrrset("a.$zone A 73.80.65.49"),
+ yxrrset("a.$zone A 73.80.65.50"),
+ yxrrset("a.$zone A 73.80.65.51")]);
+
+
+section("Torture test of \"RRset exists (value dependent)\" prerequisites.");
+
+test("NOERROR", ["update",
+ rr_add("e.$zone 300 A 73.80.65.49"),
+ rr_add("e.$zone 300 TXT 'one'"),
+ rr_add("e.$zone 300 A 73.80.65.50")]);
+test("NOERROR", ["update",
+ rr_add("e.$zone 300 A 73.80.65.52"),
+ rr_add("f.$zone 300 A 73.80.65.52"),
+ rr_add("e.$zone 300 A 73.80.65.51")]);
+test("NOERROR", ["update",
+ rr_add("e.$zone 300 TXT 'three'"),
+ rr_add("e.$zone 300 TXT 'two'")]);
+test("NOERROR", ["update",
+ rr_add("e.$zone 300 MX 10 mail.$zone")]);
+
+test("NOERROR", ["pre",
+ yxrrset("e.$zone A 73.80.65.52"),
+ yxrrset("e.$zone TXT 'two'"),
+ yxrrset("e.$zone A 73.80.65.51"),
+ yxrrset("e.$zone TXT 'three'"),
+ yxrrset("e.$zone A 73.80.65.50"),
+ yxrrset("f.$zone A 73.80.65.52"),
+ yxrrset("e.$zone A 73.80.65.49"),
+ yxrrset("e.$zone TXT 'one'")]);
+
+
+section("Subtraction of RRsets");
+test("NOERROR", ["update", rr_del("a.$zone A 73.80.65.49")]);
+test("NOERROR", ["pre",
+ yxrrset("a.$zone A 73.80.65.50")]);
+
+test("NOERROR", ["update", rr_del("a.$zone A 73.80.65.50")]);
+test("NOERROR", ["pre", nxrrset("a.$zone A")]);
+test("NOERROR", ["pre", nxdomain("a.$zone")]);
+
+section("Other forms of deletion");
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]);
+test("NOERROR", ["update", rr_add("a.$zone 300 MX 10 mail.$zone")]);
+test("NOERROR", ["update", rr_del("a.$zone A")]);
+test("NOERROR", ["pre", nxrrset("a.$zone A")]);
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]);
+test("NOERROR", ["update", rr_del("a.$zone")]);
+test("NOERROR", ["pre", nxdomain("a.$zone")]);
+
+section("Case insensitivity");
+test("NOERROR", ["update", rr_add("a.$zone 300 PTR foo.net.")]);
+test("NOERROR", ["pre", yxrrset("A.$zone PTR fOo.NeT.")]);
+
+section("Special CNAME rules");
+test("NOERROR", ["update", rr_add("b.$zone 300 CNAME foo.net.")]);
+test("NOERROR", ["update", rr_add("b.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["pre", yxrrset("b.$zone CNAME foo.net.")]);
+test("NOERROR", ["pre", nxrrset("b.$zone A")]);
+
+test("NOERROR", ["update", rr_add("c.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["update", rr_add("c.$zone 300 CNAME foo.net.")]);
+test("NOERROR", ["pre", yxrrset("c.$zone A")]);
+test("NOERROR", ["pre", nxrrset("c.$zone CNAME")]);
+
+# XXX should test with SIG, KEY, NXT, too.
+
+#
+# Currently commented out because Net::DNS does not properly
+# support WKS records.
+#
+#section("Special WKS rules");
+#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 TCP telnet ftp")]);
+#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 UDP telnet ftp")]);
+#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.50 TCP telnet ftp")]);
+#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 TCP smtp")]);
+#test("NOERROR", ["pre",
+# yxrrset("c.$zone WKS 73.80.65.49 TCP smtp"),
+# yxrrset("c.$zone WKS 73.80.65.49 UDP telnet ftp"),
+# yxrrset("c.$zone WKS 73.80.65.50 TCP telnet ftp")]);
+
+
+section("Special NS rules");
+
+# Deleting the last NS record using "Delete an RR from an RRset"
+# should fail at the zone apex and work elsewhere. The pseudocode
+# in RFC2136 says it should fail everywhere, but this is in conflict
+# with the actual text.
+
+# Apex
+test("NOERROR", ["update",
+ rr_add("$zone 300 NS ns1.$zone"),
+ rr_add("$zone 300 NS ns2.$zone")]);
+test("NOERROR", ["update", rr_del("$zone NS ns1.$zone")]);
+test("NOERROR", ["update", rr_del("$zone NS ns2.$zone")]);
+test("NOERROR", ["pre",
+ yxrrset("$zone NS ns2.$zone")]);
+
+# Non-apex
+test("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]);
+test("NOERROR", ["update", rr_del("n.$zone NS ns1.$zone")]);
+test("NOERROR", ["pre", nxrrset("n.$zone NS")]);
+
+# Other ways of deleting NS records should also fail at the apex
+# and work elsewhere.
+
+# Non-apex
+test("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]);
+test("NOERROR", ["update", rr_del("n.$zone NS")]);
+test("NOERROR", ["pre", nxrrset("n.$zone NS")]);
+
+test("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]);
+test("NOERROR", ["pre", yxrrset("n.$zone NS")]);
+test("NOERROR", ["update", rr_del("n.$zone")]);
+test("NOERROR", ["pre", nxrrset("n.$zone NS")]);
+
+# Apex
+test("NOERROR", ["update", rr_del("$zone NS")]);
+test("NOERROR", ["pre",
+ yxrrset("$zone NS ns2.$zone")]);
+
+test("NOERROR", ["update", rr_del("$zone")]);
+test("NOERROR", ["pre",
+ yxrrset("$zone NS ns2.$zone")]);
+
+# They should not touch the SOA, either.
+
+test("NOERROR", ["update", rr_del("$zone SOA")]);
+test("NOERROR", ["pre", yxrrset("$zone SOA")]);
+
+
+section("Idempotency");
+
+test("NOERROR", ["update", rr_add("d.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["pre", yxrrset("d.$zone A 73.80.65.49")]);
+test("NOERROR", ["update",
+ rr_add("d.$zone 300 A 73.80.65.49"),
+ rr_del("d.$zone A")]);
+test("NOERROR", ["pre", nxrrset("d.$zone A")]);
+
+test("NOERROR", ["update", rr_del("d.$zone A 73.80.65.49")]);
+test("NOERROR", ["pre", nxrrset("d.$zone A")]);
+test("NOERROR", ["update",
+ rr_del("d.$zone A"),
+ rr_add("d.$zone 300 A 73.80.65.49")]);
+
+test("NOERROR", ["pre", yxrrset("d.$zone A")]);
+
+section("Out-of-zone prerequisites and updates");
+test("NOTZONE", ["pre", yxrrset("a.somewhere.else. A 73.80.65.49")]);
+test("NOTZONE", ["update", rr_add("a.somewhere.else. 300 A 73.80.65.49")]);
+
+
+section("Glue");
+test("NOERROR", ["update", rr_add("s.$zone 300 NS ns.s.$zone")]);
+test("NOERROR", ["update", rr_add("ns.s.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["pre", yxrrset("ns.s.$zone A 73.80.65.49")]);
+
+section("Wildcards");
+test("NOERROR", ["update", rr_add("*.$zone 300 MX 10 mail.$zone")]);
+test("NOERROR", ["pre", yxrrset("*.$zone MX 10 mail.$zone")]);
+test("NXRRSET", ["pre", yxrrset("w.$zone MX 10 mail.$zone")]);
+test("NOERROR", ["pre", nxrrset("w.$zone MX")]);
+test("NOERROR", ["pre", nxdomain("w.$zone")]);
+
+
+section("SOA serial handling");
+
+my $soatimers = "20 20 1814400 3600";
+
+# Get the current SOA serial number.
+my $query = $res->query($zone, "SOA");
+my ($old_soa) = $query->answer;
+
+my $old_serial = $old_soa->serial;
+
+# Increment it by 10.
+my $new_serial = $old_serial + 10;
+if ($new_serial > 0xFFFFFFFF) {
+ $new_serial -= 0x80000000;
+ $new_serial -= 0x80000000;
+}
+
+# Replace the SOA with a new one.
+test("NOERROR", ["update", rr_add("$zone 300 SOA mname1. . $new_serial $soatimers")]);
+
+# Check that the SOA really got replaced.
+($db_soa) = $res->query($zone, "SOA")->answer;
+assert($db_soa->mname eq "mname1");
+
+# Check that attempts to decrement the serial number are ignored.
+$new_serial = $old_serial - 10;
+if ($new_serial < 0) {
+ $new_serial += 0x80000000;
+ $new_serial += 0x80000000;
+}
+test("NOERROR", ["update", rr_add("$zone 300 SOA mname2. . $new_serial $soatimers")]);
+assert($db_soa->mname eq "mname1");
+
+# Check that attempts to leave the serial number unchanged are ignored.
+($old_soa) = $res->query($zone, "SOA")->answer;
+$old_serial = $old_soa->serial;
+test("NOERROR", ["update", rr_add("$zone 300 SOA mname3. . $old_serial " .
+ $soatimers)]);
+($db_soa) = $res->query($zone, "SOA")->answer;
+assert($db_soa->mname eq "mname1");
+
+#
+# Currently commented out because Net::DNS does not properly
+# support multiple strings in TXT records.
+#
+#section("Big data");
+#test("NOERROR", ["update", rr_add("a.$zone 300 TXT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")]);
+#test("NOERROR", ["update", rr_del("a.$zone TXT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")]);
+test("NOERROR", ["update", rr_add("a.$zone 300 TXT " . ("foo " x 3))]);
+
+section("Updating TTLs only");
+
+test("NOERROR", ["update", rr_add("t.$zone 300 A 73.80.65.49")]);
+($a) = $res->query("t.$zone", "A")->answer;
+$ttl = $a->ttl;
+assert($ttl == 300, "incorrect TTL value $ttl != 300");
+test("NOERROR", ["update",
+ rr_del("t.$zone A 73.80.65.49"),
+ rr_add("t.$zone 301 A 73.80.65.49")]);
+($a) = $res->query("t.$zone", "A")->answer;
+$ttl = $a->ttl;
+assert($ttl == 301, "incorrect TTL value $ttl != 301");
+
+# Add an RR that is identical to an existing one except for the TTL.
+# RFC2136 is not clear about what this should do; it says "duplicate RRs
+# will be silently ignored" but is an RR differing only in TTL
+# to be considered a duplicate or not? The test assumes that it
+# should not be considered a duplicate.
+test("NOERROR", ["update", rr_add("t.$zone 302 A 73.80.65.50")]);
+($a) = $res->query("t.$zone", "A")->answer;
+$ttl = $a->ttl;
+assert($ttl == 302, "incorrect TTL value $ttl != 302");
+
+section("TTL normalization");
+
+# The desired behaviour is that the old RRs get their TTL
+# changed to match the new one. RFC2136 does not explicitly
+# specify this, but I think it makes more sense than the
+# alternatives.
+
+test("NOERROR", ["update", rr_add("t.$zone 303 A 73.80.65.51")]);
+(@answers) = $res->query("t.$zone", "A")->answer;
+$nanswers = scalar @answers;
+assert($nanswers == 3, "wrong number of answers $nanswers != 3");
+foreach $a (@answers) {
+ $ttl = $a->ttl;
+ assert($ttl == 303, "incorrect TTL value $ttl != 303");
+}
+
+section("Obscuring existing data by zone cut");
+test("NOERROR", ["update", rr_add("a.u.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["update", rr_add("b.u.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["update", rr_add("u.$zone 300 TXT txt-not-in-nxt")]);
+test("NOERROR", ["update", rr_add("u.$zone 300 NS ns.u.$zone")]);
+
+test("NOERROR", ["update", rr_del("u.$zone NS ns.u.$zone")]);
+
+if ($Net::DNS::VERSION < 1.01) {
+ print "skipped Excessive NSEC3PARAM iterations; Net::DNS too old.\n";
+} else {
+ section("Excessive NSEC3PARAM iterations");
+ test("REFUSED", ["update", rr_add("$zone 300 NSEC3PARAM 1 0 151 -")]);
+ test("NOERROR", ["update", rr_add("$zone 300 NSEC3PARAM 1 0 150 -")]);
+}
+
+if ($failures) {
+ print "$failures tests failed.\n";
+} else {
+ print "All tests successful.\n";
+}
+exit $failures;
diff --git a/bin/tests/system/nsupdate/verylarge.in b/bin/tests/system/nsupdate/verylarge.in
new file mode 100644
index 0000000..2e66221
--- /dev/null
+++ b/bin/tests/system/nsupdate/verylarge.in
@@ -0,0 +1,3 @@
+server 10.53.0.1 @PORT@
+update add txt.update.nil. 600 TXT 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890
+send
diff --git a/bin/tests/system/nzd2nzf/clean.sh b/bin/tests/system/nzd2nzf/clean.sh
new file mode 100644
index 0000000..9b826ca
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ./*/named.conf
+rm -f ./*/named.run
+rm -f ./*/named.memstats
+rm -f dig.out.*
+rm -f rndc.out*
+rm -f ns*/*.nzf
+rm -f ns*/*.nzd ns*/*.nzd-lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/nzd2nzf/ns1/added.db b/bin/tests/system/nzd2nzf/ns1/added.db
new file mode 100644
index 0000000..286e717
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/ns1/added.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+;$ORIGIN added.example.
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ MX 10 mail
+
+a A 10.0.0.1
+mail A 10.0.0.2
diff --git a/bin/tests/system/nzd2nzf/ns1/named.conf.in b/bin/tests/system/nzd2nzf/ns1/named.conf.in
new file mode 100644
index 0000000..91ebc66
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/ns1/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ allow-query { any; };
+ recursion no;
+ allow-new-zones yes;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/nzd2nzf/prereq.sh b/bin/tests/system/nzd2nzf/prereq.sh
new file mode 100644
index 0000000..7c9e25d
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/prereq.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$FEATURETEST --with-lmdb || {
+ echo_i "This test requires LMDB support." >&2
+ exit 255
+}
+exit 0
diff --git a/bin/tests/system/nzd2nzf/setup.sh b/bin/tests/system/nzd2nzf/setup.sh
new file mode 100644
index 0000000..82240a7
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/nzd2nzf/tests.sh b/bin/tests/system/nzd2nzf/tests.sh
new file mode 100644
index 0000000..2cfc58f
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/tests.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+dig_with_opts() {
+ "$DIG" -p "${PORT}" "$@"
+}
+
+rndccmd() {
+ "$RNDC" -c ../common/rndc.conf -p "${CONTROLPORT}" -s "$@"
+}
+
+status=0
+n=0
+
+n=$((n+1))
+echo_i "querying for non-existing zone data ($n)"
+ret=0
+dig_with_opts @10.53.0.1 a.added.example a > dig.out.ns1.$n || ret=1
+grep 'status: REFUSED' dig.out.ns1.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "adding a new zone into default NZD using rndc addzone ($n)"
+rndccmd 10.53.0.1 addzone 'added.example { type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns1 /' | cat_i
+sleep 2
+
+n=$((n+1))
+echo_i "querying for existing zone data ($n)"
+ret=0
+dig_with_opts @10.53.0.1 a.added.example a > dig.out.ns1.$n || ret=1
+grep 'status: NOERROR' dig.out.ns1.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "stopping ns1"
+stop_server ns1
+
+n=$((n+1))
+echo_i "dumping _default.nzd to _default.nzf ($n)"
+$NZD2NZF ns1/_default.nzd > ns1/_default.nzf || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that _default.nzf contains the expected content ($n)"
+grep 'zone "added.example" { type primary; file "added.db"; };' ns1/_default.nzf > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "deleting _default.nzd database"
+rm -f ns1/_default.nzd
+
+echo_i "starting ns1 which should migrate the .nzf to .nzd"
+start_server --noclean --restart --port ${PORT} ns1
+
+n=$((n+1))
+echo_i "querying for zone data from migrated zone config ($n)"
+# retry loop in case the server restart above causes transient failures
+_do_query() (
+ dig_with_opts @10.53.0.1 a.added.example a > dig.out.ns1.$n &&
+ grep 'status: NOERROR' dig.out.ns1.$n > /dev/null
+)
+ret=0
+retry_quiet "10" _do_query || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+exit $status
diff --git a/bin/tests/system/nzd2nzf/tests_sh_nzd2nzf.py b/bin/tests/system/nzd2nzf/tests_sh_nzd2nzf.py
new file mode 100644
index 0000000..b030451
--- /dev/null
+++ b/bin/tests/system/nzd2nzf/tests_sh_nzd2nzf.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_nzd2nzf(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/org.isc.bind.system b/bin/tests/system/org.isc.bind.system
new file mode 100644
index 0000000..6c5a8cd
--- /dev/null
+++ b/bin/tests/system/org.isc.bind.system
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# see also ifconfig.sh.in and testsock.pl
+
+ifup() {
+ /sbin/ifconfig lo0 10.53.$1.$3 alias
+ /sbin/ifconfig lo0 inet6 fd92:7065:b8e:${2}ff::${3} alias
+}
+
+for ns in 1 2 3 4 5 6 7 8 9 10 11
+do
+ ifup 0 ff $ns
+done
+for ns in 1 2
+do
+ ifup 1 99 $ns
+ ifup 2 00 $ns
+done
diff --git a/bin/tests/system/org.isc.bind.system.plist b/bin/tests/system/org.isc.bind.system.plist
new file mode 100644
index 0000000..18d3c5d
--- /dev/null
+++ b/bin/tests/system/org.isc.bind.system.plist
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>org.isc.bind.system</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/bin/bash</string>
+ <string>/Library/LaunchDaemons/org.isc.bind.system</string>
+ </array>
+ <key>RunAtLoad</key>
+ <true/>
+</dict>
+</plist>
+
diff --git a/bin/tests/system/packet.pl b/bin/tests/system/packet.pl
new file mode 100644
index 0000000..900a0c0
--- /dev/null
+++ b/bin/tests/system/packet.pl
@@ -0,0 +1,164 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# This is a tool for sending an arbitrary packet via UDP or TCP to an
+# arbitrary address and port. The packet is specified in a file or on
+# the standard input, in the form of a series of bytes in hexadecimal.
+# Whitespace is ignored, as is anything following a '#' symbol.
+#
+# For example, the following input would generate normal query for
+# isc.org/NS/IN":
+#
+# # QID:
+# 0c d8
+# # header:
+# 01 00 00 01 00 00 00 00 00 00
+# # qname isc.org:
+# 03 69 73 63 03 6f 72 67 00
+# # qtype NS:
+# 00 02
+# # qclass IN:
+# 00 01
+#
+# Note that we do not wait for a response for the server. This is simply
+# a way of injecting arbitrary packets to test server resposnes.
+#
+# Usage: packet.pl [-a <address>] [-d] [-p <port>] [-t (udp|tcp)] [-r <repeats>] [filename]
+#
+# Options:
+# -a <address>: specify address (XXX: no IPv6 support yet)
+# -p <port>: specify port
+# -t <protocol>: specify UDP or TCP
+# -r <num>: send packet <num> times
+# -d: dump response packets
+#
+# If not specified, address defaults to 127.0.0.1, port to 53, protocol
+# to udp, and file to stdin.
+
+require 5.006.001;
+
+use strict;
+use Getopt::Std;
+use IO::File;
+use IO::Socket;
+
+sub usage {
+ print ("Usage: packet.pl [-a address] [-d] [-p port] [-t (tcp|udp)] [-r <repeats>] [file]\n");
+ exit 1;
+}
+
+my $sock;
+my $proto;
+
+sub dumppacket {
+ use Net::DNS;
+ use Net::DNS::Packet;
+
+ my $rin;
+ my $rout;
+ $rin = '';
+ vec($rin, fileno($sock), 1) = 1;
+ select($rout = $rin, undef, undef, 1);
+ if (vec($rout, fileno($sock), 1)) {
+ my $buf;
+
+ if ($proto eq "udp") {
+ $sock->recv($buf, 512);
+ } else {
+ my $n = $sock->sysread($buf, 2);
+ return unless $n == 2;
+ my $len = unpack("n", $buf);
+ $n = $sock->sysread($buf, $len);
+ return unless $n == $len;
+ }
+
+ my $response;
+ if ($Net::DNS::VERSION > 0.68) {
+ $response = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($response, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+ $response->print;
+ }
+}
+
+my %options={};
+getopts("a:dp:t:r:", \%options);
+
+my $addr = "127.0.0.1";
+$addr = $options{a} if defined $options{a};
+
+my $port = 53;
+$port = $options{p} if defined $options{p};
+
+$proto = "udp";
+$proto = lc $options{t} if defined $options{t};
+usage if ($proto !~ /^(udp|tcp)$/);
+
+my $repeats = 1;
+$repeats = $options{r} if defined $options{r};
+
+my $file = "STDIN";
+if (@ARGV >= 1) {
+ my $filename = shift @ARGV;
+ open FH, "<$filename" or die "$filename: $!";
+ $file = "FH";
+}
+
+my $input = "";
+while (defined(my $line = <$file>) ) {
+ chomp $line;
+ $line =~ s/#.*$//;
+ $input .= $line;
+}
+
+$input =~ s/\s+//g;
+my $data = pack("H*", $input);
+my $len = length $data;
+
+my $output = unpack("H*", $data);
+print ("sending $repeats time(s): $output\n");
+
+$sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port,
+ Blocking => 0,
+ Proto => $proto,) or die "$!";
+
+STDOUT->autoflush(1);
+
+my $bytes = 0;
+while ($repeats > 0) {
+ if ($proto eq "udp") {
+ $bytes += $sock->send($data);
+ } else {
+ $bytes += $sock->syswrite(pack("n", $len), 2);
+ $bytes += $sock->syswrite($data, $len);
+ }
+
+ $repeats = $repeats - 1;
+
+ if ($repeats % 1000 == 0) {
+ print ".";
+ }
+}
+
+$sock->shutdown(SHUT_WR);
+if (defined $options{d}) {
+ dumppacket;
+}
+
+$sock->close;
+close $file;
+print ("\nsent $bytes bytes to $addr:$port\n");
diff --git a/bin/tests/system/padding/clean.sh b/bin/tests/system/padding/clean.sh
new file mode 100644
index 0000000..eef2174
--- /dev/null
+++ b/bin/tests/system/padding/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.*
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/named.stats
+rm -f ns*/named.stats.prev
+rm -f ns*/named.lock
+rm -f ns*/named.conf
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/padding/ns1/named.conf.in b/bin/tests/system/padding/ns1/named.conf.in
new file mode 100644
index 0000000..32dbf90
--- /dev/null
+++ b/bin/tests/system/padding/ns1/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/padding/ns1/root.db b/bin/tests/system/padding/ns1/root.db
new file mode 100644
index 0000000..17780d1
--- /dev/null
+++ b/bin/tests/system/padding/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/padding/ns2/example.db b/bin/tests/system/padding/ns2/example.db
new file mode 100644
index 0000000..f6a4b03
--- /dev/null
+++ b/bin/tests/system/padding/ns2/example.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA ns2 hostmaster.isc.org. 1 600 600 1200 600
+@ NS ns2
+ns2 A 10.53.0.2
+foo A 10.53.1.1
diff --git a/bin/tests/system/padding/ns2/named.conf.in b/bin/tests/system/padding/ns2/named.conf.in
new file mode 100644
index 0000000..10ba86b
--- /dev/null
+++ b/bin/tests/system/padding/ns2/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ send-cookie yes;
+ response-padding { !10.53.0.8; any; } block-size 64;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/padding/ns3/named.conf.in b/bin/tests/system/padding/ns3/named.conf.in
new file mode 100644
index 0000000..a719249
--- /dev/null
+++ b/bin/tests/system/padding/ns3/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation no;
+};
+
+server 10.53.0.2 {
+ tcp-only yes;
+ padding 64;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/padding/ns4/named.conf.in b/bin/tests/system/padding/ns4/named.conf.in
new file mode 100644
index 0000000..6828f2a
--- /dev/null
+++ b/bin/tests/system/padding/ns4/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation no;
+};
+
+server 10.53.0.2 {
+ tcp-only no;
+ padding 64;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/padding/setup.sh b/bin/tests/system/padding/setup.sh
new file mode 100644
index 0000000..594ae98
--- /dev/null
+++ b/bin/tests/system/padding/setup.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL ./clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
+
+touch ns2/named.stats
diff --git a/bin/tests/system/padding/tests.sh b/bin/tests/system/padding/tests.sh
new file mode 100644
index 0000000..c952537
--- /dev/null
+++ b/bin/tests/system/padding/tests.sh
@@ -0,0 +1,135 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+n=0
+status=0
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+getcookie() {
+ awk '$2 == "COOKIE:" {
+ print $3;
+ }' < $1
+}
+
+echo_i "checking that dig handles padding ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +qr +padding=128 foo.example @10.53.0.2 > dig.out.test$n
+grep "; PAD" dig.out.test$n > /dev/null || ret=1
+grep "; QUERY SIZE: 128" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that dig added padding ($n)"
+ret=0
+n=$((n + 1))
+nextpart ns2/named.stats > /dev/null
+$RNDCCMD 10.53.0.2 stats
+wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1
+nextpart ns2/named.stats | grep "EDNS padding option received" > /dev/null || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that padding is added for TCP responses ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +vc +padding=128 foo.example @10.53.0.2 > dig.out.test$n
+grep "; PAD" dig.out.test$n > /dev/null || ret=1
+grep "rcvd: 128" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that padding is added to valid cookie responses ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +cookie foo.example @10.53.0.2 > dig.out.testc
+cookie=$(getcookie dig.out.testc)
+$DIG $DIGOPTS +cookie=$cookie +padding=128 foo.example @10.53.0.2 > dig.out.test$n
+grep "; PAD" dig.out.test$n > /dev/null || ret=1
+grep "rcvd: 128" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that padding must be requested (TCP) ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +vc foo.example @10.53.0.2 > dig.out.test$n
+grep "; PAD" dig.out.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that padding must be requested (valid cookie) ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +cookie=$cookie foo.example @10.53.0.2 > dig.out.test$n
+grep "; PAD" dig.out.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that padding can be filtered out ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +vc +padding=128 -b 10.53.0.8 foo.example @10.53.0.2 > dig.out.test$n
+grep "; PAD" dig.out.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that a TCP and padding server config enables padding ($n)"
+ret=0
+n=$((n + 1))
+nextpart ns2/named.stats > /dev/null
+$RNDCCMD 10.53.0.2 stats
+wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1
+opad=$(nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}')
+$DIG $DIGOPTS foo.example @10.53.0.3 > dig.out.test$n
+$RNDCCMD 10.53.0.2 stats
+wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1
+npad=$(nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}')
+if [ "$opad" -eq "$npad" ]; then echo_i "error: opad ($opad) == npad ($npad)"; ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that a padding server config should enforce TCP ($n)"
+ret=0
+n=$((n + 1))
+nextpart ns2/named.stats > /dev/null
+$RNDCCMD 10.53.0.2 stats
+wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1
+opad=$(nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}')
+$DIG $DIGOPTS foo.example @10.53.0.4 > dig.out.test$n
+$RNDCCMD 10.53.0.2 stats
+wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1
+npad=$(nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}')
+if [ "$opad" -ne "$npad" ]; then echo_i "error: opad ($opad) != npad ($npad)"; ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that zero-length padding option has no effect ($n)"
+ret=0
+n=$((n + 1))
+$DIG $DIGOPTS +qr +ednsopt=12 foo.example @10.53.0.2 > dig.out.test$n.1
+grep "; PAD" dig.out.test$n.1 > /dev/null || ret=1
+$DIG $DIGOPTS +qr +ednsopt=12:00 foo.example @10.53.0.2 > dig.out.test$n.2
+grep "; PAD" dig.out.test$n.2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/padding/tests_sh_padding.py b/bin/tests/system/padding/tests_sh_padding.py
new file mode 100644
index 0000000..a2eec7c
--- /dev/null
+++ b/bin/tests/system/padding/tests_sh_padding.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_padding(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/parallel.sh b/bin/tests/system/parallel.sh
new file mode 100644
index 0000000..11a424f
--- /dev/null
+++ b/bin/tests/system/parallel.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ./conf.sh
+
+PARALLELS=$(echo "$PARALLELDIRS" | sed "s|\([^ ][^ ]*\)|test-\1|g;" | tr _ - | tr "\n" " ")
+
+echo ".PHONY: $PARALLELS"
+echo
+echo "check_interfaces:"
+echo " @${PERL} testsock.pl > /dev/null 2>&1 || { \\"
+echo " echo \"I:NOTE: System tests were skipped because they require the\"; \\"
+echo " echo \"I: test IP addresses 10.53.0.* to be configured as alias\"; \\"
+echo " echo \"I: addresses on the loopback interface. Please run\"; \\"
+echo " echo \"I: \"bin/tests/system/ifconfig.sh up\" as root to configure them.\"; \\"
+echo " exit 1; \\"
+echo " }"
+echo
+echo "test check: $PARALLELS"
+for directory in $PARALLELDIRS ; do
+ echo
+ echo "test-$(echo "$directory" | tr _ -): check_interfaces"
+ echo " @${SHELL} ./legacy.run.sh -r $directory 2>&1 | tee test.output.$directory"
+done
diff --git a/bin/tests/system/pending/clean.sh b/bin/tests/system/pending/clean.sh
new file mode 100644
index 0000000..89a4b5b
--- /dev/null
+++ b/bin/tests/system/pending/clean.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -rf */*.signed
+rm -rf */*.jnl
+rm -rf */K*
+rm -rf */dsset-*
+rm -rf */named.memstats
+rm -rf */named.run
+rm -rf */trusted.conf
+rm -rf ns1/root.db
+rm -rf ns2/example.db
+rm -rf ns2/example.com.db
+rm -rf nsupdate.out.test
+rm -f ns*/named.lock
+rm -f ns*/named.conf
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/pending/ns1/named.conf.in b/bin/tests/system/pending/ns1/named.conf.in
new file mode 100644
index 0000000..af5d628
--- /dev/null
+++ b/bin/tests/system/pending/ns1/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "trusted.conf";
+
+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;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
diff --git a/bin/tests/system/pending/ns1/root.db.in b/bin/tests/system/pending/ns1/root.db.in
new file mode 100644
index 0000000..fe7fe92
--- /dev/null
+++ b/bin/tests/system/pending/ns1/root.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 30
+. IN SOA marka.isc.org. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example.com. NS ns2.example.com.
+ns2.example.com. A 10.53.0.2
+hostile. NS ns3.hostile.
+ns3.hostile. A 10.53.0.3
+nice.good. A 10.10.10.10
diff --git a/bin/tests/system/pending/ns1/sign.sh b/bin/tests/system/pending/ns1/sign.sh
new file mode 100644
index 0000000..cb3662f
--- /dev/null
+++ b/bin/tests/system/pending/ns1/sign.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+(cd ../ns2 && $SHELL -e sign.sh )
+
+cp ../ns2/dsset-example. .
+cp ../ns2/dsset-example.com. .
+
+keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -f KSK -n zone $zone)
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -g -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a static key.
+keyfile_to_static_ds $keyname2 > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+cp trusted.conf ../ns3/trusted.conf
+cp trusted.conf ../ns4/trusted.conf
diff --git a/bin/tests/system/pending/ns2/example.com.db.in b/bin/tests/system/pending/ns2/example.com.db.in
new file mode 100644
index 0000000..ee3a1b8
--- /dev/null
+++ b/bin/tests/system/pending/ns2/example.com.db.in
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 30
+@ IN SOA mname1. . (
+ 2009110300 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ MX 10 mail
+ns2 A 10.53.0.2
+mail A 192.0.2.2
+ AAAA 2001:db8::2
+pending-ok A 192.0.2.2
+pending-ng A 192.0.2.102
+removed A 10.9.8.7
diff --git a/bin/tests/system/pending/ns2/example.db.in b/bin/tests/system/pending/ns2/example.db.in
new file mode 100644
index 0000000..5b42e2a
--- /dev/null
+++ b/bin/tests/system/pending/ns2/example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 30
+$ORIGIN example.
+@ IN SOA mname1. . (
+ 2009110300 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ MX 10 mail
+ns2 A 10.53.0.2
+mail A 10.0.0.2
+bad CNAME nice.good.
+worse A 6.6.6.6
diff --git a/bin/tests/system/pending/ns2/forgery.db b/bin/tests/system/pending/ns2/forgery.db
new file mode 100644
index 0000000..fbf42bc
--- /dev/null
+++ b/bin/tests/system/pending/ns2/forgery.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 30
+$ORIGIN good.
+@ IN SOA mname1. . (
+ 2009110300 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+
+nice.good. CNAME worse.example.
diff --git a/bin/tests/system/pending/ns2/named.conf.in b/bin/tests/system/pending/ns2/named.conf.in
new file mode 100644
index 0000000..59824df
--- /dev/null
+++ b/bin/tests/system/pending/ns2/named.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+include "trusted.conf";
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db.signed";
+};
+
+zone "example.com" {
+ type primary;
+ file "example.com.db.signed";
+ allow-update { 10.53.0.0/16; };
+};
+
+zone "good" {
+ type primary;
+ file "forgery.db";
+ allow-query { any; };
+};
diff --git a/bin/tests/system/pending/ns2/sign.sh b/bin/tests/system/pending/ns2/sign.sh
new file mode 100644
index 0000000..4965f85
--- /dev/null
+++ b/bin/tests/system/pending/ns2/sign.sh
@@ -0,0 +1,33 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+for domain in example example.com; do
+ zone=${domain}.
+ infile=${domain}.db.in
+ zonefile=${domain}.db
+
+ keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+ keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -f KSK -n zone $zone)
+
+ cat $infile $keyname1.key $keyname2.key > $zonefile
+
+ $SIGNER -3 bebe -o $zone $zonefile > /dev/null
+done
+
+# remove "removed" record from example.com, causing the server to
+# send an apparently-invalid NXDOMAIN
+sed '/^removed/d' example.com.db.signed > example.com.db.new
+rm -f example.com.db.signed
+mv example.com.db.new example.com.db.signed
diff --git a/bin/tests/system/pending/ns3/hostile.db b/bin/tests/system/pending/ns3/hostile.db
new file mode 100644
index 0000000..a199922
--- /dev/null
+++ b/bin/tests/system/pending/ns3/hostile.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 30
+@ IN SOA mname1. . (
+ 2009110500 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ MX 10 mail.example.
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/pending/ns3/mail.example.db b/bin/tests/system/pending/ns3/mail.example.db
new file mode 100644
index 0000000..77eb731
--- /dev/null
+++ b/bin/tests/system/pending/ns3/mail.example.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 30
+@ IN SOA mname1. . (
+ 2009110300 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS ns3
+ns3 A 10.53.0.3
+;mail A 10.0.0.2 // the correct record
+@ A 10.0.0.3
diff --git a/bin/tests/system/pending/ns3/named.conf.in b/bin/tests/system/pending/ns3/named.conf.in
new file mode 100644
index 0000000..29afd19
--- /dev/null
+++ b/bin/tests/system/pending/ns3/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+include "trusted.conf";
+
+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 no;
+ notify no;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "mail.example" {
+ type primary;
+ file "mail.example.db";
+};
+
+zone "hostile" {
+ type primary;
+ file "hostile.db";
+};
diff --git a/bin/tests/system/pending/ns4/named.conf.in b/bin/tests/system/pending/ns4/named.conf.in
new file mode 100644
index 0000000..dfb5541
--- /dev/null
+++ b/bin/tests/system/pending/ns4/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "trusted.conf";
+
+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;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/pending/setup.sh b/bin/tests/system/pending/setup.sh
new file mode 100644
index 0000000..bf57f90
--- /dev/null
+++ b/bin/tests/system/pending/setup.sh
@@ -0,0 +1,23 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
+
+cd ns1 && $SHELL -e sign.sh
diff --git a/bin/tests/system/pending/tests.sh b/bin/tests/system/pending/tests.sh
new file mode 100644
index 0000000..362cef3
--- /dev/null
+++ b/bin/tests/system/pending/tests.sh
@@ -0,0 +1,200 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+# replace_data dname RR old_data new_data
+replace_data()
+{
+ if [ $# -ne 4 ]; then
+ echo_i "unexpected input for replace_data"
+ return 1
+ fi
+
+ _dname=$1
+ _rr=$2
+ _olddata=$3
+ _newdata=$4
+
+ _ret=0
+ $NSUPDATE -d <<END >> nsupdate.out.test 2>&1 || _ret=1
+server 10.53.0.2 ${PORT}
+update delete ${_dname} 30 ${_rr} ${_olddata}
+update add ${_dname} 30 ${_rr} ${_newdata}
+send
+END
+
+ if [ $_ret != 0 ]; then
+ echo_i "failed to update the test data"
+ return 1
+ fi
+
+ return 0
+}
+
+status=0
+n=0
+
+DIGOPTS="+short +tcp -p ${PORT}"
+DIGOPTS_CD="$DIGOPTS +cd"
+
+echo_i "Priming cache."
+ret=0
+expect="10 mail.example."
+ans=$($DIG $DIGOPTS_CD @10.53.0.4 hostile MX) || ret=1
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+echo_i "Checking that bogus additional is not returned with +CD."
+ret=0
+expect="10.0.0.2"
+ans=$($DIG $DIGOPTS_CD @10.53.0.4 mail.example A) || ret=1
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+#
+# Prime cache with pending additional records. These should not be promoted
+# to answer.
+#
+echo_i "Priming cache (pending additional A and AAAA)"
+ret=0
+expect="10 mail.example.com."
+ans=$($DIG $DIGOPTS @10.53.0.4 example.com MX) || ret=1
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+echo_i "Replacing pending A"
+ret=0
+replace_data mail.example.com. A 192.0.2.2 192.0.2.3 || ret=1
+status=$((status + ret))
+
+echo_i "Replacing pending AAAA"
+ret=0
+replace_data mail.example.com. AAAA 2001:db8::2 2001:db8::3 || ret=1
+status=$((status + ret))
+
+echo_i "Checking updated data to be returned (without CD)"
+ret=0
+expect="192.0.2.3"
+ans=$($DIG $DIGOPTS @10.53.0.4 mail.example.com A) || ret=1
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+echo_i "Checking updated data to be returned (with CD)"
+ret=0
+expect="2001:db8::3"
+ans=$($DIG $DIGOPTS_CD @10.53.0.4 mail.example.com AAAA) || ret=1
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+#
+# Prime cache with a pending answer record. It can be returned (without
+# validation) with +CD.
+#
+echo_i "Priming cache (pending answer)"
+ret=0
+expect="192.0.2.2"
+ans=$($DIG $DIGOPTS_CD @10.53.0.4 pending-ok.example.com A) || ret=1
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+echo_i "Replacing pending data"
+ret=0
+replace_data pending-ok.example.com. A 192.0.2.2 192.0.2.3 || ret=1
+status=$((status + ret))
+
+echo_i "Confirming cached pending data to be returned with CD"
+ret=0
+expect="192.0.2.2"
+ans=$($DIG $DIGOPTS_CD @10.53.0.4 pending-ok.example.com A) || ret=1
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+#
+# Prime cache with a pending answer record. It should not be returned
+# to no-DNSSEC clients.
+#
+echo_i "Priming cache (pending answer)"
+ret=0
+expect="192.0.2.102"
+ans=$($DIG $DIGOPTS_CD @10.53.0.4 pending-ng.example.com A) || ret=1
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+echo_i "Replacing pending data"
+ret=0
+replace_data pending-ng.example.com. A 192.0.2.102 192.0.2.103 || ret=1
+status=$((status + ret))
+
+echo_i "Confirming updated data returned, not the cached one, without CD"
+ret=0
+expect="192.0.2.103"
+ans=$($DIG $DIGOPTS @10.53.0.4 pending-ng.example.com A) || ret=1
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+#
+# Try to fool the resolver with an out-of-bailiwick CNAME
+#
+echo_i "Trying to Prime out-of-bailiwick pending answer with CD"
+ret=0
+expect="10.10.10.10"
+ans=$($DIG $DIGOPTS_CD @10.53.0.4 bad.example. A) || ret=1
+ans=$(echo $ans | awk '{print $NF}')
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+echo_i "Confirming the out-of-bailiwick answer is not cached or reused with CD"
+ret=0
+expect="10.10.10.10"
+ans=$($DIG $DIGOPTS_CD @10.53.0.4 nice.good. A) || ret=1
+ans=$(echo $ans | awk '{print $NF}')
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+#
+# Make sure the resolver doesn't cache bogus NXDOMAIN
+#
+echo_i "Trying to Prime bogus NXDOMAIN"
+ret=0
+expect="SERVFAIL"
+ans=$($DIG +tcp -p ${PORT} @10.53.0.4 removed.example.com. A) || ret=1
+ans=$(echo $ans | sed 's/^.*status: \([A-Z][A-Z]*\).*$/\1/')
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+echo_i "Confirming the bogus NXDOMAIN was not cached"
+ret=0
+expect="SERVFAIL"
+ans=$($DIG +tcp -p ${PORT} @10.53.0.4 removed.example.com. A) || ret=1
+ans=$(echo $ans | sed 's/^.*status: \([A-Z][A-Z]*\).*$/\1/')
+test "$ans" = "$expect" || ret=1
+test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'"
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/pending/tests_sh_pending.py b/bin/tests/system/pending/tests_sh_pending.py
new file mode 100644
index 0000000..54b5afb
--- /dev/null
+++ b/bin/tests/system/pending/tests_sh_pending.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_pending(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/pipelined/ans5/ans.py b/bin/tests/system/pipelined/ans5/ans.py
new file mode 100644
index 0000000..bac5ed3
--- /dev/null
+++ b/bin/tests/system/pipelined/ans5/ans.py
@@ -0,0 +1,212 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+############################################################################
+#
+# This tool acts as a TCP/UDP proxy and delays all incoming packets by 500
+# milliseconds.
+#
+# We use it to check pipelining - a client sents 8 questions over a
+# pipelined connection - that require asking a normal (examplea) and a
+# slow-responding (exampleb) servers:
+# a.examplea
+# a.exampleb
+# b.examplea
+# b.exampleb
+# c.examplea
+# c.exampleb
+# d.examplea
+# d.exampleb
+#
+# If pipelining works properly the answers will be returned out of order
+# with all answers from examplea returned first, and then all answers
+# from exampleb.
+#
+############################################################################
+
+from __future__ import print_function
+
+import datetime
+import os
+import select
+import signal
+import socket
+import sys
+import time
+import threading
+import struct
+
+DELAY = 0.5
+THREADS = []
+
+
+def log(msg):
+ print(datetime.datetime.now().strftime("%d-%b-%Y %H:%M:%S.%f ") + msg)
+
+
+def sigterm(*_):
+ log("SIGTERM received, shutting down")
+ for thread in THREADS:
+ thread.close()
+ thread.join()
+ os.remove("ans.pid")
+ sys.exit(0)
+
+
+class TCPDelayer(threading.Thread):
+ """For a given TCP connection conn we open a connection to (ip, port),
+ and then we delay each incoming packet by DELAY by putting it in a
+ queue.
+ In the pipelined test TCP should not be used, but it's here for
+ completnes.
+ """
+
+ def __init__(self, conn, ip, port):
+ threading.Thread.__init__(self)
+ self.conn = conn
+ self.cconn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.cconn.connect((ip, port))
+ self.queue = []
+ self.running = True
+
+ def close(self):
+ self.running = False
+
+ def run(self):
+ while self.running:
+ curr_timeout = 0.5
+ try:
+ curr_timeout = self.queue[0][0] - time.time()
+ except StopIteration:
+ pass
+ if curr_timeout > 0:
+ if curr_timeout == 0:
+ curr_timeout = 0.5
+ rfds, _, _ = select.select(
+ [self.conn, self.cconn], [], [], curr_timeout
+ )
+ if self.conn in rfds:
+ data = self.conn.recv(65535)
+ if not data:
+ return
+ self.queue.append((time.time() + DELAY, data))
+ if self.cconn in rfds:
+ data = self.cconn.recv(65535)
+ if not data == 0:
+ return
+ self.conn.send(data)
+ try:
+ while self.queue[0][0] - time.time() < 0:
+ _, data = self.queue.pop(0)
+ self.cconn.send(data)
+ except StopIteration:
+ pass
+
+
+class UDPDelayer(threading.Thread):
+ """Every incoming UDP packet is put in a queue for DELAY time, then
+ it's sent to (ip, port). We remember the query id to send the
+ response we get to a proper source, responses are not delayed.
+ """
+
+ def __init__(self, usock, ip, port):
+ threading.Thread.__init__(self)
+ self.sock = usock
+ self.csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ self.dst = (ip, port)
+ self.queue = []
+ self.qid_mapping = {}
+ self.running = True
+
+ def close(self):
+ self.running = False
+
+ def run(self):
+ while self.running:
+ curr_timeout = 0.5
+ if self.queue:
+ curr_timeout = self.queue[0][0] - time.time()
+ if curr_timeout >= 0:
+ if curr_timeout == 0:
+ curr_timeout = 0.5
+ rfds, _, _ = select.select(
+ [self.sock, self.csock], [], [], curr_timeout
+ )
+ if self.sock in rfds:
+ data, addr = self.sock.recvfrom(65535)
+ if not data:
+ return
+ self.queue.append((time.time() + DELAY, data))
+ qid = struct.unpack(">H", data[:2])[0]
+ log("Received a query from %s, queryid %d" % (str(addr), qid))
+ self.qid_mapping[qid] = addr
+ if self.csock in rfds:
+ data, addr = self.csock.recvfrom(65535)
+ if not data:
+ return
+ qid = struct.unpack(">H", data[:2])[0]
+ dst = self.qid_mapping.get(qid)
+ if dst is not None:
+ self.sock.sendto(data, dst)
+ log(
+ "Received a response from %s, queryid %d, sending to %s"
+ % (str(addr), qid, str(dst))
+ )
+ while self.queue and self.queue[0][0] - time.time() < 0:
+ _, data = self.queue.pop(0)
+ qid = struct.unpack(">H", data[:2])[0]
+ log("Sending a query to %s, queryid %d" % (str(self.dst), qid))
+ self.csock.sendto(data, self.dst)
+
+
+def main():
+ signal.signal(signal.SIGTERM, sigterm)
+ signal.signal(signal.SIGINT, sigterm)
+
+ with open("ans.pid", "w") as pidfile:
+ print(os.getpid(), file=pidfile)
+
+ listenip = "10.53.0.5"
+ serverip = "10.53.0.2"
+
+ try:
+ port = int(os.environ["PORT"])
+ except KeyError:
+ port = 5300
+
+ log("Listening on %s:%d" % (listenip, port))
+
+ usock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ usock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ usock.bind((listenip, port))
+ thread = UDPDelayer(usock, serverip, port)
+ thread.start()
+ THREADS.append(thread)
+
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ sock.bind((listenip, port))
+ sock.listen(1)
+ sock.settimeout(1)
+
+ while True:
+ try:
+ (clientsock, _) = sock.accept()
+ log("Accepted connection from %s" % clientsock)
+ thread = TCPDelayer(clientsock, serverip, port)
+ thread.start()
+ THREADS.append(thread)
+ except socket.timeout:
+ pass
+
+
+if __name__ == "__main__":
+ main()
diff --git a/bin/tests/system/pipelined/clean.sh b/bin/tests/system/pipelined/clean.sh
new file mode 100644
index 0000000..12c1733
--- /dev/null
+++ b/bin/tests/system/pipelined/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f raw* output*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/pipelined/input b/bin/tests/system/pipelined/input
new file mode 100644
index 0000000..485cf81
--- /dev/null
+++ b/bin/tests/system/pipelined/input
@@ -0,0 +1,8 @@
+a.examplea
+a.exampleb
+b.examplea
+b.exampleb
+c.examplea
+c.exampleb
+d.examplea
+d.exampleb
diff --git a/bin/tests/system/pipelined/inputb b/bin/tests/system/pipelined/inputb
new file mode 100644
index 0000000..6ea367e
--- /dev/null
+++ b/bin/tests/system/pipelined/inputb
@@ -0,0 +1,8 @@
+e.examplea
+e.exampleb
+f.examplea
+f.exampleb
+g.examplea
+g.exampleb
+h.examplea
+h.exampleb
diff --git a/bin/tests/system/pipelined/ns1/named.conf.in b/bin/tests/system/pipelined/ns1/named.conf.in
new file mode 100644
index 0000000..6cfac77
--- /dev/null
+++ b/bin/tests/system/pipelined/ns1/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/pipelined/ns1/root.db b/bin/tests/system/pipelined/ns1/root.db
new file mode 100644
index 0000000..f2819a1
--- /dev/null
+++ b/bin/tests/system/pipelined/ns1/root.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+examplea. NS ns2.examplea.
+ns2.examplea. A 10.53.0.5
+
+exampleb. NS ns3.exampleb.
+ns3.exampleb. A 10.53.0.3
diff --git a/bin/tests/system/pipelined/ns2/examplea.db b/bin/tests/system/pipelined/ns2/examplea.db
new file mode 100644
index 0000000..1be2d11
--- /dev/null
+++ b/bin/tests/system/pipelined/ns2/examplea.db
@@ -0,0 +1,32 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+examplea IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+examplea. NS ns2.examplea.
+ns2.examplea. A 10.53.0.5
+
+$ORIGIN examplea.
+a A 10.0.1.1
+b A 10.0.1.2
+c A 10.0.1.3
+d A 10.0.1.4
+e A 10.0.1.5
+f A 10.0.1.6
+g A 10.0.1.7
+h A 10.0.1.8
diff --git a/bin/tests/system/pipelined/ns2/named.conf.in b/bin/tests/system/pipelined/ns2/named.conf.in
new file mode 100644
index 0000000..3679e97
--- /dev/null
+++ b/bin/tests/system/pipelined/ns2/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "examplea" {
+ type primary;
+ file "examplea.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/pipelined/ns3/exampleb.db b/bin/tests/system/pipelined/ns3/exampleb.db
new file mode 100644
index 0000000..91b94c3
--- /dev/null
+++ b/bin/tests/system/pipelined/ns3/exampleb.db
@@ -0,0 +1,32 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+exampleb IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+exampleb. NS ns3.exampleb.
+ns3.exampleb. A 10.53.0.3
+
+$ORIGIN exampleb.
+a A 10.0.2.1
+b A 10.0.2.2
+c A 10.0.2.3
+d A 10.0.2.4
+e A 10.0.2.5
+f A 10.0.2.6
+g A 10.0.2.7
+h A 10.0.2.8
diff --git a/bin/tests/system/pipelined/ns3/named.conf.in b/bin/tests/system/pipelined/ns3/named.conf.in
new file mode 100644
index 0000000..d8943d5
--- /dev/null
+++ b/bin/tests/system/pipelined/ns3/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "exampleb" {
+ type primary;
+ file "exampleb.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/pipelined/ns4/named.conf.in b/bin/tests/system/pipelined/ns4/named.conf.in
new file mode 100644
index 0000000..5d4be1c
--- /dev/null
+++ b/bin/tests/system/pipelined/ns4/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ keep-response-order { 10.53.0.7/32; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/pipelined/pipequeries.c b/bin/tests/system/pipelined/pipequeries.c
new file mode 100644
index 0000000..7419d22
--- /dev/null
+++ b/bin/tests/system/pipelined/pipequeries.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/commandline.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/managers.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/netmgr.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/dispatch.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdataset.h>
+#include <dns/request.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/types.h>
+#include <dns/view.h>
+
+#define CHECK(str, x) \
+ { \
+ if ((x) != ISC_R_SUCCESS) { \
+ fprintf(stderr, "I:%s: %s\n", (str), \
+ isc_result_totext(x)); \
+ exit(-1); \
+ } \
+ }
+
+#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
+
+#define PORT 5300
+#define TIMEOUT 30
+
+static isc_mem_t *mctx = NULL;
+static dns_requestmgr_t *requestmgr = NULL;
+static bool have_src = false;
+static isc_sockaddr_t srcaddr;
+static isc_sockaddr_t dstaddr;
+static int onfly;
+
+static void
+recvresponse(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result;
+ dns_message_t *query = NULL;
+ dns_message_t *response = NULL;
+ isc_buffer_t outbuf;
+ char output[1024];
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "I:request event result: %s\n",
+ isc_result_totext(reqev->result));
+ exit(-1);
+ }
+
+ query = reqev->ev_arg;
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+
+ result = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ CHECK("dns_request_getresponse", result);
+
+ if (response->rcode != dns_rcode_noerror) {
+ result = dns_result_fromrcode(response->rcode);
+ fprintf(stderr, "I:response rcode: %s\n",
+ isc_result_totext(result));
+ exit(-1);
+ }
+ if (response->counts[DNS_SECTION_ANSWER] != 1U) {
+ fprintf(stderr, "I:response answer count (%u!=1)\n",
+ response->counts[DNS_SECTION_ANSWER]);
+ }
+
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_sectiontotext(
+ response, DNS_SECTION_ANSWER, &dns_master_style_simple,
+ DNS_MESSAGETEXTFLAG_NOCOMMENTS, &outbuf);
+ CHECK("dns_message_sectiontotext", result);
+ printf("%.*s", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+ fflush(stdout);
+
+ dns_message_detach(&query);
+ dns_message_detach(&response);
+ dns_request_destroy(&reqev->request);
+ isc_event_free(&event);
+
+ if (--onfly == 0) {
+ isc_app_shutdown();
+ }
+ return;
+}
+
+static isc_result_t
+sendquery(isc_task_t *task) {
+ dns_request_t *request = NULL;
+ dns_message_t *message = NULL;
+ dns_name_t *qname = NULL;
+ dns_rdataset_t *qrdataset = NULL;
+ isc_result_t result;
+ dns_fixedname_t queryname;
+ isc_buffer_t buf;
+ static char host[256];
+ int c;
+
+ c = scanf("%255s", host);
+ if (c == EOF) {
+ return (ISC_R_NOMORE);
+ }
+
+ onfly++;
+
+ dns_fixedname_init(&queryname);
+ isc_buffer_init(&buf, host, strlen(host));
+ isc_buffer_add(&buf, strlen(host));
+ result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf,
+ dns_rootname, 0, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
+
+ message->opcode = dns_opcode_query;
+ message->flags |= DNS_MESSAGEFLAG_RD;
+ message->rdclass = dns_rdataclass_in;
+ message->id = (unsigned short)(random() & 0xFFFF);
+
+ result = dns_message_gettempname(message, &qname);
+ CHECK("dns_message_gettempname", result);
+
+ result = dns_message_gettemprdataset(message, &qrdataset);
+ CHECK("dns_message_gettemprdataset", result);
+
+ dns_name_clone(dns_fixedname_name(&queryname), qname);
+ dns_rdataset_makequestion(qrdataset, dns_rdataclass_in,
+ dns_rdatatype_a);
+ ISC_LIST_APPEND(qname->list, qrdataset, link);
+ dns_message_addname(message, qname, DNS_SECTION_QUESTION);
+
+ result = dns_request_create(requestmgr, message,
+ have_src ? &srcaddr : NULL, &dstaddr,
+ DNS_REQUESTOPT_TCP, NULL, TIMEOUT, 0, 0,
+ task, recvresponse, message, &request);
+ CHECK("dns_request_create", result);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+sendqueries(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+
+ isc_event_free(&event);
+
+ do {
+ result = sendquery(task);
+ } while (result == ISC_R_SUCCESS);
+
+ if (onfly == 0) {
+ isc_app_shutdown();
+ }
+ return;
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_sockaddr_t bind_any;
+ struct in_addr inaddr;
+ isc_result_t result;
+ isc_log_t *lctx = NULL;
+ isc_logconfig_t *lcfg = NULL;
+ isc_nm_t *netmgr = NULL;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_task_t *task = NULL;
+ dns_dispatchmgr_t *dispatchmgr = NULL;
+ dns_dispatch_t *dispatchv4 = NULL;
+ dns_view_t *view = NULL;
+ uint16_t port = PORT;
+ int c;
+
+ RUNCHECK(isc_app_start());
+
+ isc_commandline_errprint = false;
+ while ((c = isc_commandline_parse(argc, argv, "p:r:")) != -1) {
+ switch (c) {
+ case 'p':
+ result = isc_parse_uint16(&port,
+ isc_commandline_argument, 10);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "bad port '%s'\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+ case 'r':
+ fprintf(stderr, "The -r option has been deprecated.\n");
+ break;
+ case '?':
+ fprintf(stderr, "%s: invalid argument '%c'", argv[0],
+ c);
+ break;
+ default:
+ break;
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+ POST(argv);
+
+ if (argc > 0) {
+ have_src = true;
+ }
+
+ isc_sockaddr_any(&bind_any);
+
+ result = ISC_R_FAILURE;
+ if (inet_pton(AF_INET, "10.53.0.7", &inaddr) != 1) {
+ CHECK("inet_pton", result);
+ }
+ isc_sockaddr_fromin(&srcaddr, &inaddr, 0);
+
+ result = ISC_R_FAILURE;
+ if (inet_pton(AF_INET, "10.53.0.4", &inaddr) != 1) {
+ CHECK("inet_pton", result);
+ }
+ isc_sockaddr_fromin(&dstaddr, &inaddr, port);
+
+ isc_mem_create(&mctx);
+
+ isc_log_create(mctx, &lctx, &lcfg);
+
+ RUNCHECK(dst_lib_init(mctx, NULL));
+
+ isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr, NULL);
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
+
+ RUNCHECK(dns_dispatch_createudp(
+ dispatchmgr, have_src ? &srcaddr : &bind_any, &dispatchv4));
+ RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4,
+ NULL, &requestmgr));
+
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+ RUNCHECK(isc_app_onrun(mctx, task, sendqueries, NULL));
+
+ (void)isc_app_run();
+
+ dns_view_detach(&view);
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+
+ dns_dispatch_detach(&dispatchv4);
+ dns_dispatchmgr_detach(&dispatchmgr);
+
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+
+ isc_managers_destroy(&netmgr, &taskmgr, NULL);
+
+ dst_lib_destroy();
+
+ isc_log_destroy(&lctx);
+
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/system/pipelined/ref b/bin/tests/system/pipelined/ref
new file mode 100644
index 0000000..fe123f6
--- /dev/null
+++ b/bin/tests/system/pipelined/ref
@@ -0,0 +1,8 @@
+a.examplea. 10.0.1.1
+a.exampleb. 10.0.2.1
+b.examplea. 10.0.1.2
+b.exampleb. 10.0.2.2
+c.examplea. 10.0.1.3
+c.exampleb. 10.0.2.3
+d.examplea. 10.0.1.4
+d.exampleb. 10.0.2.4
diff --git a/bin/tests/system/pipelined/refb b/bin/tests/system/pipelined/refb
new file mode 100644
index 0000000..a24c6bc
--- /dev/null
+++ b/bin/tests/system/pipelined/refb
@@ -0,0 +1,8 @@
+e.examplea. 10.0.1.5
+e.exampleb. 10.0.2.5
+f.examplea. 10.0.1.6
+f.exampleb. 10.0.2.6
+g.examplea. 10.0.1.7
+g.exampleb. 10.0.2.7
+h.examplea. 10.0.1.8
+h.exampleb. 10.0.2.8
diff --git a/bin/tests/system/pipelined/setup.sh b/bin/tests/system/pipelined/setup.sh
new file mode 100644
index 0000000..49a6426
--- /dev/null
+++ b/bin/tests/system/pipelined/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
diff --git a/bin/tests/system/pipelined/tests.sh b/bin/tests/system/pipelined/tests.sh
new file mode 100644
index 0000000..26c0d31
--- /dev/null
+++ b/bin/tests/system/pipelined/tests.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+MDIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+
+echo_i "check pipelined TCP queries"
+ret=0
+$PIPEQUERIES -p ${PORT} < input > raw || ret=1
+awk '{ print $1 " " $5 }' < raw > output
+sort < output > output-sorted
+diff ref output-sorted || { ret=1 ; echo_i "diff sorted failed"; }
+diff ref output > /dev/null && { ret=1 ; echo_i "diff out of order failed"; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check pipelined TCP queries using mdig"
+ret=0
+$RNDCCMD 10.53.0.4 flush
+sleep 1
+$MDIG $MDIGOPTS +noall +answer +vc -f input -b 10.53.0.4 @10.53.0.4 > raw.mdig
+awk '{ print $1 " " $5 }' < raw.mdig > output.mdig
+sort < output.mdig > output-sorted.mdig
+diff ref output-sorted.mdig || { ret=1 ; echo_i "diff sorted failed"; }
+diff ref output.mdig > /dev/null && { ret=1 ; echo_i "diff out of order failed"; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check keep-response-order"
+ret=0
+$RNDCCMD 10.53.0.4 flush
+sleep 1
+$PIPEQUERIES -p ${PORT} ++ < inputb > rawb || ret=1
+awk '{ print $1 " " $5 }' < rawb > outputb
+diff refb outputb || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check keep-response-order using mdig"
+ret=0
+$RNDCCMD 10.53.0.4 flush
+sleep 1
+$MDIG $MDIGOPTS +noall +answer +vc -f inputb -b 10.53.0.7 @10.53.0.4 > rawb.mdig
+awk '{ print $1 " " $5 }' < rawb.mdig > outputb.mdig
+diff refb outputb.mdig || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check mdig -4 -6"
+ret=0
+$RNDCCMD 10.53.0.4 flush
+sleep 1
+$MDIG $MDIGOPTS -4 -6 -f input @10.53.0.4 > output46.mdig 2>&1 && ret=1
+grep "only one of -4 and -6 allowed" output46.mdig > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "check mdig -4 with an IPv6 server address"
+ret=0
+$MDIG $MDIGOPTS -4 -f input @fd92:7065:b8e:ffff::2 > output4.mdig 2>&1 && ret=1
+grep "address family not supported" output4.mdig > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/pipelined/tests_sh_pipelined.py b/bin/tests/system/pipelined/tests_sh_pipelined.py
new file mode 100644
index 0000000..2d7fb92
--- /dev/null
+++ b/bin/tests/system/pipelined/tests_sh_pipelined.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_pipelined(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/pytest.ini b/bin/tests/system/pytest.ini
new file mode 100644
index 0000000..1559595
--- /dev/null
+++ b/bin/tests/system/pytest.ini
@@ -0,0 +1,20 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+[pytest]
+addopts = --tb=short -rA
+log_format = %(asctime)s %(levelname)s:%(name)s %(message)s
+log_date_format = %Y-%m-%d %H:%M:%S
+log_cli = 1
+log_level = INFO
+python_files = tests_*.py
+junit_logging = log
+junit_log_passing_tests = 0
diff --git a/bin/tests/system/pytest_custom_markers.py b/bin/tests/system/pytest_custom_markers.py
new file mode 100644
index 0000000..ba3a9d4
--- /dev/null
+++ b/bin/tests/system/pytest_custom_markers.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import os
+import subprocess
+
+import pytest
+
+
+long_test = pytest.mark.skipif(
+ not os.environ.get("CI_ENABLE_ALL_TESTS"), reason="CI_ENABLE_ALL_TESTS not set"
+)
+
+
+def feature_test(feature):
+ feature_test_bin = os.environ["FEATURETEST"]
+ try:
+ subprocess.run([feature_test_bin, feature], check=True)
+ except subprocess.CalledProcessError as exc:
+ if exc.returncode != 1:
+ raise
+ return False
+ return True
+
+
+have_libxml2 = pytest.mark.skipif(
+ not feature_test("--have-libxml2"), reason="libxml2 support disabled in the build"
+)
+
+have_json_c = pytest.mark.skipif(
+ not feature_test("--have-json-c"), reason="json-c support disabled in the build"
+)
+
+
+try:
+ import flaky as flaky_pkg
+except ModuleNotFoundError:
+ # In case the flaky package is not installed, run the tests as usual
+ # without any attempts to re-run them.
+ # pylint: disable=unused-argument
+ def flaky(*args, **kwargs):
+ """Mock decorator that doesn't do anything special, just returns the function."""
+
+ def wrapper(wrapped_obj):
+ return wrapped_obj
+
+ return wrapper
+
+else:
+ flaky = flaky_pkg.flaky
diff --git a/bin/tests/system/qmin/ans2/ans.py b/bin/tests/system/qmin/ans2/ans.py
new file mode 100755
index 0000000..1994ff3
--- /dev/null
+++ b/bin/tests/system/qmin/ans2/ans.py
@@ -0,0 +1,401 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from __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, dns.flags
+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)
+
+
+def endswith(domain, labels):
+ return domain.endswith("." + labels) or domain == labels
+
+
+############################################################################
+# Respond to a DNS query.
+# For good. it serves:
+# ns2.good. IN A 10.53.0.2
+# 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 milliseconds
+#
+# For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals
+#
+# For ugly. it works the same as for good., but returns garbage 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.
+# 8.2.6.0.1.0.0.2.ip6.arpa IN NS ns3.good
+# 1.0.0.2.ip6.arpa. IN NS ns2.good
+# ip6.arpa. IN NS ns2.good
+#
+# For stale. it serves:
+# a.b. NS ns.a.b.stale.
+# ns.a.b.stale. IN A 10.53.0.3
+# b. NS ns.b.stale.
+# ns.b.stale. IN A 10.53.0.4
+############################################################################
+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)
+ if typename == "A" or typename == "AAAA":
+ typename = "ADDR"
+ bad = False
+ ugly = 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 endswith(lqname, "1.0.0.2.ip6.arpa."):
+ # Direct query - give direct answer
+ if endswith(lqname, "8.2.6.0.1.0.0.2.ip6.arpa."):
+ # Delegate to ns3
+ r.authority.append(
+ dns.rrset.from_text(
+ "8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns3.good."
+ )
+ )
+ r.additional.append(
+ dns.rrset.from_text("ns3.good.", 60, IN, A, "10.53.0.3")
+ )
+ elif (
+ 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.",
+ )
+ )
+ r.flags |= dns.flags.AA
+ 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.", 30, IN, NS, "ns2.good.")
+ )
+ r.flags |= dns.flags.AA
+ elif endswith(
+ "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.",
+ lqname,
+ ):
+ # NODATA answer
+ r.authority.append(
+ dns.rrset.from_text(
+ "1.0.0.2.ip6.arpa.",
+ 30,
+ 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.",
+ 30,
+ IN,
+ SOA,
+ "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1",
+ )
+ )
+ r.set_rcode(NXDOMAIN)
+ return r
+ elif endswith(lqname, "ip6.arpa."):
+ if lqname == "ip6.arpa." and rrtype == NS:
+ # NS query at the apex
+ r.answer.append(dns.rrset.from_text("ip6.arpa.", 30, IN, NS, "ns2.good."))
+ r.flags |= dns.flags.AA
+ elif endswith("1.0.0.2.ip6.arpa.", lqname):
+ # NODATA answer
+ r.authority.append(
+ dns.rrset.from_text(
+ "ip6.arpa.",
+ 30,
+ IN,
+ SOA,
+ "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1",
+ )
+ )
+ else:
+ # NXDOMAIN
+ r.authority.append(
+ dns.rrset.from_text(
+ "ip6.arpa.",
+ 30,
+ IN,
+ SOA,
+ "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1",
+ )
+ )
+ r.set_rcode(NXDOMAIN)
+ return r
+ elif endswith(lqname, "stale."):
+ if endswith(lqname, "a.b.stale."):
+ # Delegate to ns.a.b.stale.
+ r.authority.append(
+ dns.rrset.from_text("a.b.stale.", 2, IN, NS, "ns.a.b.stale.")
+ )
+ r.additional.append(
+ dns.rrset.from_text("ns.a.b.stale.", 2, IN, A, "10.53.0.3")
+ )
+ elif endswith(lqname, "b.stale."):
+ # Delegate to ns.b.stale.
+ r.authority.append(
+ dns.rrset.from_text("b.stale.", 2, IN, NS, "ns.b.stale.")
+ )
+ r.additional.append(
+ dns.rrset.from_text("ns.b.stale.", 2, IN, A, "10.53.0.4")
+ )
+ elif lqname == "stale." and rrtype == NS:
+ # NS query at the apex.
+ r.answer.append(dns.rrset.from_text("stale.", 2, IN, NS, "ns2.stale."))
+ r.flags |= dns.flags.AA
+ elif lqname == "stale." and rrtype == SOA:
+ # SOA query at the apex.
+ r.answer.append(
+ dns.rrset.from_text(
+ "stale.", 2, IN, SOA, "ns2.stale. hostmaster.stale. 1 2 3 4 5"
+ )
+ )
+ r.flags |= dns.flags.AA
+ elif lqname == "stale.":
+ # NODATA answer
+ r.authority.append(
+ dns.rrset.from_text(
+ "stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5"
+ )
+ )
+ else:
+ # NXDOMAIN
+ r.authority.append(
+ dns.rrset.from_text(
+ "stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5"
+ )
+ )
+ r.set_rcode(NXDOMAIN)
+ return r
+ elif endswith(lqname, "bad."):
+ bad = True
+ suffix = "bad."
+ lqname = lqname[:-4]
+ elif endswith(lqname, "ugly."):
+ ugly = True
+ suffix = "ugly."
+ lqname = lqname[:-5]
+ elif endswith(lqname, "good."):
+ suffix = "good."
+ lqname = lqname[:-5]
+ elif endswith(lqname, "slow."):
+ slow = True
+ suffix = "slow."
+ lqname = lqname[:-5]
+ elif endswith(lqname, "fwd."):
+ suffix = "fwd."
+ lqname = lqname[:-4]
+ else:
+ r.set_rcode(REFUSED)
+ return r
+
+ # Good/bad/ugly differs only in how we treat non-empty terminals
+ if endswith(lqname, "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"))
+ r.flags |= dns.flags.AA
+ elif lqname == "" and rrtype == NS:
+ r.answer.append(dns.rrset.from_text(suffix, 30, IN, NS, "ns2." + suffix))
+ r.flags |= dns.flags.AA
+ elif lqname == "ns2." and rrtype == A:
+ r.answer.append(dns.rrset.from_text("ns2." + suffix, 30, IN, A, "10.53.0.2"))
+ r.flags |= dns.flags.AA
+ elif lqname == "ns2." and rrtype == AAAA:
+ r.answer.append(
+ dns.rrset.from_text("ns2." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::2")
+ )
+ r.flags |= dns.flags.AA
+ elif lqname == "ns3." and rrtype == A:
+ r.answer.append(dns.rrset.from_text("ns3." + suffix, 30, IN, A, "10.53.0.3"))
+ r.flags |= dns.flags.AA
+ elif lqname == "ns3." and rrtype == AAAA:
+ r.answer.append(
+ dns.rrset.from_text("ns3." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::3")
+ )
+ r.flags |= dns.flags.AA
+ elif lqname == "ns4." and rrtype == A:
+ r.answer.append(dns.rrset.from_text("ns4." + suffix, 30, IN, A, "10.53.0.4"))
+ r.flags |= dns.flags.AA
+ elif lqname == "ns4." and rrtype == AAAA:
+ r.answer.append(
+ dns.rrset.from_text("ns4." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::4")
+ )
+ r.flags |= dns.flags.AA
+ 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")
+ )
+ r.flags |= dns.flags.AA
+ 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"
+ )
+ )
+ r.flags |= dns.flags.AA
+ 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 (
+ endswith("icky.icky.icky.ptang.zoop.boing.", lqname)
+ or endswith(
+ "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.",
+ lqname,
+ )
+ or endswith("a.bit.longer.ns.name.", lqname)
+ ):
+ r.set_rcode(NXDOMAIN)
+ if ugly:
+ r.set_rcode(FORMERR)
+ if slow:
+ time.sleep(0.2)
+ 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/qmin/ans3/ans.py b/bin/tests/system/qmin/ans3/ans.py
new file mode 100755
index 0000000..079c3d2
--- /dev/null
+++ b/bin/tests/system/qmin/ans3/ans.py
@@ -0,0 +1,274 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from __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, dns.flags
+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)
+
+
+def endswith(domain, labels):
+ return domain.endswith("." + labels) or domain == labels
+
+
+############################################################################
+# 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 milliseconds
+#
+# For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals
+#
+# For ugly. it works the same as for good., but returns garbage to non-empty terminals
+#
+# For stale. it serves:
+# a.b.stale. IN TXT peekaboo (resolver did not do qname minimization)
+############################################################################
+def create_response(msg):
+ m = dns.message.from_wire(msg)
+ qname = m.question[0].name.to_text()
+ lqname = qname.lower()
+ labels = lqname.split(".")
+ suffix = ""
+
+ # get qtype
+ rrtype = m.question[0].rdtype
+ typename = dns.rdatatype.to_text(rrtype)
+ if typename == "A" or typename == "AAAA":
+ typename = "ADDR"
+ bad = False
+ ugly = 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)
+
+ ip6req = False
+
+ if endswith(lqname, "bad."):
+ bad = True
+ suffix = "bad."
+ lqname = lqname[:-4]
+ elif endswith(lqname, "ugly."):
+ ugly = True
+ suffix = "ugly."
+ lqname = lqname[:-5]
+ elif endswith(lqname, "good."):
+ suffix = "good."
+ lqname = lqname[:-5]
+ elif endswith(lqname, "slow."):
+ slow = True
+ suffix = "slow."
+ lqname = lqname[:-5]
+ elif endswith(lqname, "8.2.6.0.1.0.0.2.ip6.arpa."):
+ ip6req = True
+ elif endswith(lqname, "a.b.stale."):
+ if lqname == "a.b.stale.":
+ if rrtype == TXT:
+ # Direct query.
+ r.answer.append(dns.rrset.from_text(lqname, 1, IN, TXT, "peekaboo"))
+ r.flags |= dns.flags.AA
+ elif rrtype == NS:
+ # NS a.b.
+ r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.a.b.stale."))
+ r.additional.append(
+ dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3")
+ )
+ r.flags |= dns.flags.AA
+ elif rrtype == SOA:
+ # SOA a.b.
+ r.answer.append(
+ dns.rrset.from_text(
+ lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
+ )
+ )
+ r.flags |= dns.flags.AA
+ else:
+ # NODATA.
+ r.authority.append(
+ dns.rrset.from_text(
+ lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
+ )
+ )
+ else:
+ r.authority.append(
+ dns.rrset.from_text(
+ lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
+ )
+ )
+ r.set_rcode(NXDOMAIN)
+ # NXDOMAIN.
+ return r
+ 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)
+ )
+ r.flags |= dns.flags.AA
+ elif endswith(lqname, "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 endswith("icky.ptang.zoop.boing.", 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)
+ if ugly:
+ r.set_rcode(FORMERR)
+ elif endswith(lqname, "zoop.boing."):
+ 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)
+ elif ip6req:
+ r.authority.append(
+ dns.rrset.from_text(
+ "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns4.good."
+ )
+ )
+ r.additional.append(dns.rrset.from_text("ns4.good.", 60, IN, A, "10.53.0.4"))
+ 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/qmin/ans4/ans.py b/bin/tests/system/qmin/ans4/ans.py
new file mode 100755
index 0000000..f3d00c3
--- /dev/null
+++ b/bin/tests/system/qmin/ans4/ans.py
@@ -0,0 +1,320 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from __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, dns.flags
+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)
+
+
+def endswith(domain, labels):
+ return domain.endswith("." + labels) or domain == labels
+
+
+############################################################################
+# 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 milliseconds
+#
+# For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals
+#
+# For ugly. it works the same as for good., but returns garbage to non-empty terminals
+#
+# For stale. it serves:
+# a.b.stale. IN TXT hooray (resolver did do qname minimization)
+############################################################################
+def create_response(msg):
+ m = dns.message.from_wire(msg)
+ qname = m.question[0].name.to_text()
+ lqname = qname.lower()
+ labels = lqname.split(".")
+ suffix = ""
+
+ # get qtype
+ rrtype = m.question[0].rdtype
+ typename = dns.rdatatype.to_text(rrtype)
+ if typename == "A" or typename == "AAAA":
+ typename = "ADDR"
+ bad = False
+ slow = False
+ ugly = 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)
+
+ ip6req = False
+
+ if endswith(lqname, "bad."):
+ bad = True
+ suffix = "bad."
+ lqname = lqname[:-4]
+ elif endswith(lqname, "ugly."):
+ ugly = True
+ suffix = "ugly."
+ lqname = lqname[:-5]
+ elif endswith(lqname, "good."):
+ suffix = "good."
+ lqname = lqname[:-5]
+ elif endswith(lqname, "slow."):
+ slow = True
+ suffix = "slow."
+ lqname = lqname[:-5]
+ elif endswith(lqname, "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa."):
+ ip6req = True
+ elif endswith(lqname, "b.stale."):
+ if lqname == "a.b.stale.":
+ if rrtype == TXT:
+ # Direct query.
+ r.answer.append(dns.rrset.from_text(lqname, 1, IN, TXT, "hooray"))
+ r.flags |= dns.flags.AA
+ elif rrtype == NS:
+ # NS a.b.
+ r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.a.b.stale."))
+ r.additional.append(
+ dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3")
+ )
+ r.flags |= dns.flags.AA
+ elif rrtype == SOA:
+ # SOA a.b.
+ r.answer.append(
+ dns.rrset.from_text(
+ lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
+ )
+ )
+ r.flags |= dns.flags.AA
+ else:
+ # NODATA.
+ r.authority.append(
+ dns.rrset.from_text(
+ lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
+ )
+ )
+ elif lqname == "b.stale.":
+ if rrtype == NS:
+ # NS b.
+ r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.b.stale."))
+ r.additional.append(
+ dns.rrset.from_text("ns.b.stale.", 1, IN, A, "10.53.0.4")
+ )
+ r.flags |= dns.flags.AA
+ elif rrtype == SOA:
+ # SOA b.
+ r.answer.append(
+ dns.rrset.from_text(
+ lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5"
+ )
+ )
+ r.flags |= dns.flags.AA
+ else:
+ # NODATA.
+ r.authority.append(
+ dns.rrset.from_text(
+ lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5"
+ )
+ )
+ else:
+ r.authority.append(
+ dns.rrset.from_text(
+ lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5"
+ )
+ )
+ r.set_rcode(NXDOMAIN)
+ # NXDOMAIN.
+ return r
+ 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"))
+ r.flags |= dns.flags.AA
+ 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"))
+ r.flags |= dns.flags.AA
+ 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
+ )
+ )
+ r.flags |= dns.flags.AA
+ elif endswith(lqname, "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 endswith("more.icky.icky.icky.ptang.zoop.boing.", lqname):
+ r.set_rcode(NXDOMAIN)
+ if ugly:
+ r.set_rcode(FORMERR)
+ elif ip6req:
+ r.flags |= dns.flags.AA
+ if (
+ lqname
+ == "test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa."
+ and rrtype == TXT
+ ):
+ r.answer.append(
+ dns.rrset.from_text(
+ "test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.",
+ 1,
+ IN,
+ TXT,
+ "long_ip6_name",
+ )
+ )
+ elif endswith(
+ "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.",
+ lqname,
+ ):
+ # NODATA answer
+ r.authority.append(
+ dns.rrset.from_text(
+ "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.",
+ 60,
+ IN,
+ SOA,
+ "ns4.good. hostmaster.arpa. 2018050100 120 30 320 16",
+ )
+ )
+ else:
+ # NXDOMAIN
+ r.authority.append(
+ dns.rrset.from_text(
+ "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.",
+ 60,
+ IN,
+ SOA,
+ "ns4.good. hostmaster.arpa. 2018050100 120 30 320 16",
+ )
+ )
+ 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/qmin/clean.sh b/bin/tests/system/qmin/clean.sh
new file mode 100644
index 0000000..52c38e6
--- /dev/null
+++ b/bin/tests/system/qmin/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.conf
+rm -f */named.memstats
+rm -f */named.run */named.run.prev
+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/ns1/named.conf.in b/bin/tests/system/qmin/ns1/named.conf.in
new file mode 100644
index 0000000..e366cca
--- /dev/null
+++ b/bin/tests/system/qmin/ns1/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/qmin/ns1/root.db b/bin/tests/system/qmin/ns1/root.db
new file mode 100644
index 0000000..325f607
--- /dev/null
+++ b/bin/tests/system/qmin/ns1/root.db
@@ -0,0 +1,41 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 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
+
+ugly. NS ns2.ugly.
+ns2.ugly. A 10.53.0.2
+
+fwd. NS ns2.fwd.
+ns2.fwd. A 10.53.0.2
+
+$TTL 2
+stale. NS ns2.stale.
+ns2.stale. A 10.53.0.2
diff --git a/bin/tests/system/qmin/ns5/named.conf.in b/bin/tests/system/qmin/ns5/named.conf.in
new file mode 100644
index 0000000..d84d818
--- /dev/null
+++ b/bin/tests/system/qmin/ns5/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 disabled;
+ querylog yes;
+ resolver-query-timeout 30000; # 30 seconds
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/qmin/ns6/named.conf.in b/bin/tests/system/qmin/ns6/named.conf.in
new file mode 100644
index 0000000..828973c
--- /dev/null
+++ b/bin/tests/system/qmin/ns6/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS6
+
+options {
+ 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.6; };
+ listen-on-v6 { none; };
+ recursion yes;
+ qname-minimization strict;
+ querylog yes;
+ resolver-query-timeout 30000; # 30 seconds
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/qmin/ns7/named.conf.in b/bin/tests/system/qmin/ns7/named.conf.in
new file mode 100644
index 0000000..8ca3275
--- /dev/null
+++ b/bin/tests/system/qmin/ns7/named.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS7
+
+options {
+ 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.7; };
+ listen-on-v6 { none; };
+ recursion yes;
+ qname-minimization relaxed;
+ querylog yes;
+ resolver-query-timeout 30000; # 30 seconds
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "fwd." IN {
+ type forward;
+ forwarders {
+ 10.53.0.2;
+ };
+ forward only;
+};
diff --git a/bin/tests/system/qmin/setup.sh b/bin/tests/system/qmin/setup.sh
new file mode 100644
index 0000000..5825b3d
--- /dev/null
+++ b/bin/tests/system/qmin/setup.sh
@@ -0,0 +1,19 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+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/qmin/tests.sh b/bin/tests/system/qmin/tests.sh
new file mode 100755
index 0000000..b8d3128
--- /dev/null
+++ b/bin/tests/system/qmin/tests.sh
@@ -0,0 +1,537 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+CLEANQL="rm -f ans*/query.log"
+status=0
+n=0
+
+n=$((n+1))
+echo_i "query for .good is not minimized when qname-minimization is off ($n)"
+ret=0
+$CLEANQL
+$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
+ADDR icky.icky.icky.ptang.zoop.boing.good.
+ADDR ns3.good.
+ADDR ns3.good.
+ADDR a.bit.longer.ns.name.good.
+ADDR a.bit.longer.ns.name.good.
+__EOF
+echo "ADDR icky.icky.icky.ptang.zoop.boing.good." | diff ans3/query.log - > /dev/null || ret=1
+echo "ADDR 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=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .bad is not minimized when qname-minimization is off ($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
+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
+ADDR icky.icky.icky.ptang.zoop.boing.bad.
+ADDR ns3.bad.
+ADDR ns3.bad.
+ADDR a.bit.longer.ns.name.bad.
+ADDR a.bit.longer.ns.name.bad.
+__EOF
+echo "ADDR icky.icky.icky.ptang.zoop.boing.bad." | diff ans3/query.log - > /dev/null || ret=1
+echo "ADDR 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=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .slow is not minimized when qname-minimization is off ($n)"
+ret=0
+$CLEANQL
+$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
+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
+ADDR icky.icky.icky.ptang.zoop.boing.slow.
+ADDR ns3.slow.
+ADDR ns3.slow.
+ADDR a.bit.longer.ns.name.slow.
+ADDR a.bit.longer.ns.name.slow.
+__EOF
+echo "ADDR icky.icky.icky.ptang.zoop.boing.slow." | diff ans3/query.log - > /dev/null || ret=1
+echo "ADDR 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=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .ugly is not minimized when qname-minimization is off ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.5 flush
+$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.ugly. @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.ugly. 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
+ADDR icky.icky.icky.ptang.zoop.boing.ugly.
+ADDR ns3.ugly.
+ADDR ns3.ugly.
+ADDR a.bit.longer.ns.name.ugly.
+ADDR a.bit.longer.ns.name.ugly.
+__EOF
+echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans3/query.log - > /dev/null || ret=1
+echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans4/query.log - > /dev/null || ret=1
+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=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .good is properly minimized when qname-minimization is in strict mode ($n)"
+ret=0
+$CLEANQL
+$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
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+ADDR a.bit.longer.ns.name.good.
+ADDR a.bit.longer.ns.name.good.
+ADDR ns2.good.
+ADDR ns3.good.
+ADDR ns3.good.
+NS boing.good.
+NS good.
+NS zoop.boing.good.
+__EOF
+cat << __EOF | diff ans3/query.log - > /dev/null || ret=1
+NS zoop.boing.good.
+NS ptang.zoop.boing.good.
+NS icky.ptang.zoop.boing.good.
+__EOF
+cat << __EOF | diff ans4/query.log - > /dev/null || ret=1
+NS icky.ptang.zoop.boing.good.
+NS icky.icky.ptang.zoop.boing.good.
+ADDR icky.icky.icky.ptang.zoop.boing.good.
+__EOF
+for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .good is properly minimized when qname-minimization is in relaxed mode ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.7 flush
+$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @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.good. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1
+sleep 1
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+ADDR a.bit.longer.ns.name.good.
+ADDR a.bit.longer.ns.name.good.
+ADDR ns2.good.
+ADDR ns3.good.
+ADDR ns3.good.
+NS boing.good.
+NS zoop.boing.good.
+__EOF
+cat << __EOF | diff ans3/query.log - > /dev/null || ret=1
+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.
+ADDR icky.icky.icky.ptang.zoop.boing.good.
+__EOF
+for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .bad fails when qname-minimization is in strict mode ($n)"
+ret=0
+$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
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+ADDR ns2.bad.
+NS bad.
+NS boing.bad.
+__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=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .bad succeeds when qname-minimization is in relaxed mode ($n)"
+ret=0
+$CLEANQL
+$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
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+ADDR a.bit.longer.ns.name.bad.
+ADDR a.bit.longer.ns.name.bad.
+ADDR icky.icky.icky.ptang.zoop.boing.bad.
+ADDR ns2.bad.
+ADDR ns3.bad.
+ADDR ns3.bad.
+NS boing.bad.
+__EOF
+cat << __EOF | diff ans3/query.log - > /dev/null || ret=1
+ADDR icky.icky.icky.ptang.zoop.boing.bad.
+__EOF
+cat << __EOF | diff ans4/query.log - > /dev/null || ret=1
+ADDR icky.icky.icky.ptang.zoop.boing.bad.
+__EOF
+for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .ugly fails when qname-minimization is in strict mode ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.6 flush
+$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.ugly. @10.53.0.6 > dig.out.test$n
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+sleep 1
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+ADDR ns2.ugly.
+NS boing.ugly.
+NS ugly.
+__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=$((status+ret))
+$RNDCCMD 10.53.0.6 flush
+
+n=$((n+1))
+echo_i "query for .ugly succeeds when qname-minimization is in relaxed mode ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.7 flush
+$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.ugly. @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.ugly. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1
+sleep 1
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+ADDR a.bit.longer.ns.name.ugly.
+ADDR a.bit.longer.ns.name.ugly.
+ADDR icky.icky.icky.ptang.zoop.boing.ugly.
+ADDR ns2.ugly.
+ADDR ns3.ugly.
+ADDR ns3.ugly.
+NS boing.ugly.
+__EOF
+echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans3/query.log - > /dev/null || ret=1
+echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans4/query.log - > /dev/null || ret=1
+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=$((status+ret))
+$RNDCCMD 10.53.0.7 flush
+
+n=$((n+1))
+echo_i "information that minimization was unsuccessful for .ugly is logged in relaxed mode ($n)"
+ret=0
+wait_for_log 5 "success resolving 'icky.icky.icky.ptang.zoop.boing.ugly/A' after disabling qname minimization" ns7/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .slow is properly minimized when qname-minimization is on ($n)"
+ret=0
+$CLEANQL
+$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
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+ADDR a.bit.longer.ns.name.slow.
+ADDR a.bit.longer.ns.name.slow.
+ADDR ns2.slow.
+ADDR ns3.slow.
+ADDR ns3.slow.
+NS boing.slow.
+NS slow.
+NS zoop.boing.slow.
+__EOF
+cat << __EOF | diff ans3/query.log - > /dev/null || ret=1
+NS zoop.boing.slow.
+NS ptang.zoop.boing.slow.
+NS icky.ptang.zoop.boing.slow.
+__EOF
+cat << __EOF | diff ans4/query.log - > /dev/null || ret=1
+NS icky.ptang.zoop.boing.slow.
+NS icky.icky.ptang.zoop.boing.slow.
+ADDR 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=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .ip6.arpa succeeds and skips on proper boundaries when qname-minimization is on ($n)"
+ret=0
+$CLEANQL
+$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
+grep -v ADDR ans2/query.log > ans2/query.log.trimmed
+cat << __EOF | diff ans2/query.log.trimmed - > /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
+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=$((status+ret))
+
+n=$((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
+sleep 1
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+ADDR a.bit.longer.ns.name.good.
+ADDR a.bit.longer.ns.name.good.
+ADDR ns2.good.
+ADDR ns3.good.
+ADDR ns3.good.
+NS boing.good.
+NS good.
+NS zoop.boing.good.
+__EOF
+cat << __EOF | diff ans3/query.log - > /dev/null || ret=1
+NS zoop.boing.good.
+NS ptang.zoop.boing.good.
+NS icky.ptang.zoop.boing.good.
+__EOF
+# There's no NS icky.icky.icky.ptang.zoop.boing.good. query - we skipped it.
+cat << __EOF | diff ans4/query.log - > /dev/null || ret=1
+NS icky.ptang.zoop.boing.good.
+NS icky.icky.ptang.zoop.boing.good.
+ADDR 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=$((status+ret))
+
+n=$((n+1))
+echo_i "qname minimization is disabled when forwarding ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.7 flush
+$DIG $DIGOPTS a.bit.longer.ns.name.fwd. @10.53.0.7 > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "a.bit.longer.ns.name.fwd. 1 IN A 10.53.0.4" dig.out.test$n >/dev/null || ret=1
+sleep 1
+cat << __EOF | diff ans2/query.log - > /dev/null || ret=1
+ADDR a.bit.longer.ns.name.fwd.
+__EOF
+for ans in ans2; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "qname minimization resolves unusual ip6.arpa. names ($n)"
+ret=0
+$CLEANQL
+$DIG $DIGOPTS test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa. txt @10.53.0.7 > dig.out.test$n 2>&1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+# Expected output in dig.out.test$n:
+# ;; ANSWER SECTION:
+# test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa. 1 IN TXT "long_ip6_name"
+grep 'ip6\.arpa.*TXT.*long_ip6_name' dig.out.test$n > /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=$((status+ret))
+
+# Below are test cases for GL #2665: The QNAME minimization (if enabled) should
+# also occur on the second query, after the RRsets have expired from cache.
+# BIND will still have the entries in cache, but marked stale. These stale
+# entries should not prevent the resolver from minimizing the QNAME.
+# We query for the test domain a.b.stale. in all cases (QNAME minimization off,
+# strict mode, and relaxed mode) and expect it to behave the same the second
+# time when we have a stale delegation structure in cache.
+n=$((n+1))
+echo_i "query for .stale is not minimized when qname-minimization is off ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.5 flush
+$DIG $DIGOPTS @10.53.0.5 txt a.b.stale. > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "a\.b\.stale\..*1.*IN.*TXT.*peekaboo" dig.out.test$n > /dev/null || ret=1
+sleep 1
+echo "TXT a.b.stale." | diff ans2/query.log - > /dev/null || ret=1
+echo "TXT a.b.stale." | diff ans3/query.log - > /dev/null || ret=1
+test -f ans4/query.log && 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=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .stale is properly minimized when qname-minimization is in strict mode ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.6 flush
+$DIG $DIGOPTS @10.53.0.6 txt a.b.stale. > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n > /dev/null || ret=1
+sleep 1
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+ADDR ns.b.stale.
+ADDR ns2.stale.
+NS b.stale.
+NS stale.
+__EOF
+test -f ans3/query.log && ret=1
+sort ans4/query.log > ans4/query.log.sorted
+cat << __EOF | diff ans4/query.log.sorted - > /dev/null || ret=1
+ADDR ns.b.stale.
+NS b.stale.
+TXT a.b.stale.
+__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=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .stale is properly minimized when qname-minimization is in relaxed mode ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.7 flush
+$DIG $DIGOPTS @10.53.0.7 txt a.b.stale. > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n > /dev/null || ret=1
+sleep 1
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+ADDR ns.b.stale.
+ADDR ns2.stale.
+NS b.stale.
+__EOF
+test -f ans3/query.log && ret=1
+sort ans4/query.log > ans4/query.log.sorted
+cat << __EOF | diff ans4/query.log.sorted - > /dev/null || ret=1
+ADDR ns.b.stale.
+TXT a.b.stale.
+__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=$((status+ret))
+
+echo_i "sleep 2, allow entries in cache to go stale"
+sleep 2
+
+n=$((n+1))
+echo_i "query for .stale is not minimized when qname-minimization is off (stale cache) ($n)"
+ret=0
+$CLEANQL
+$DIG $DIGOPTS @10.53.0.5 txt a.b.stale. > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "a\.b\.stale\..*1.*IN.*TXT.*peekaboo" dig.out.test$n > /dev/null || ret=1
+sleep 1
+echo "TXT a.b.stale." | diff ans2/query.log - > /dev/null || ret=1
+echo "TXT a.b.stale." | diff ans3/query.log - > /dev/null || ret=1
+test -f ans4/query.log && 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=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .stale is properly minimized when qname-minimization is in strict mode (stale cache) ($n)"
+ret=0
+$CLEANQL
+$DIG $DIGOPTS @10.53.0.6 txt a.b.stale. > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n > /dev/null || ret=1
+sleep 1
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+NS b.stale.
+NS stale.
+__EOF
+test -f ans3/query.log && ret=1
+sort ans4/query.log > ans4/query.log.sorted
+cat << __EOF | diff ans4/query.log.sorted - > /dev/null || ret=1
+NS b.stale.
+TXT a.b.stale.
+__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=$((status+ret))
+
+n=$((n+1))
+echo_i "query for .stale is properly minimized when qname-minimization is in relaxed mode (stale cache) ($n)"
+ret=0
+$CLEANQL
+$DIG $DIGOPTS @10.53.0.7 txt a.b.stale. > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n > /dev/null || ret=1
+sleep 1
+sort ans2/query.log > ans2/query.log.sorted
+cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
+NS b.stale.
+__EOF
+test -f ans3/query.log && ret=1
+sort ans4/query.log > ans4/query.log.sorted
+cat << __EOF | diff ans4/query.log.sorted - > /dev/null || ret=1
+TXT a.b.stale.
+__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=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/qmin/tests_sh_qmin.py b/bin/tests/system/qmin/tests_sh_qmin.py
new file mode 100644
index 0000000..6077322
--- /dev/null
+++ b/bin/tests/system/qmin/tests_sh_qmin.py
@@ -0,0 +1,18 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import pytest_custom_markers
+
+
+# The qmin test is inherently unstable, see GL #904 for details.
+@pytest_custom_markers.flaky(max_runs=3)
+def test_qmin(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/reclimit/README b/bin/tests/system/reclimit/README
new file mode 100644
index 0000000..e474907
--- /dev/null
+++ b/bin/tests/system/reclimit/README
@@ -0,0 +1,19 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+system test for recursion limits
+
+ns1 -- root server
+ans2 -- for example.org: delegate to ns1.(n+1).example.org for all n, up to the
+ value specified in ans.limit (or forever if limit is 0)
+ns3 -- resolver under test
+ans4 -- for ns*.example.com: return address records.
+ans7 -- "victim" server
diff --git a/bin/tests/system/reclimit/ans2/ans.pl b/bin/tests/system/reclimit/ans2/ans.pl
new file mode 100644
index 0000000..4576951
--- /dev/null
+++ b/bin/tests/system/reclimit/ans2/ans.pl
@@ -0,0 +1,235 @@
+#!/usr/bin/env perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+use warnings;
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+
+my $localaddr = "10.53.0.2";
+my $limit = getlimit();
+my $no_more_waiting = 0;
+my @delayed_response;
+my $timeout;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "$localaddr",
+ LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+my $count = 0;
+my $send_response = 0;
+
+sub getlimit {
+ if ( -e "ans.limit") {
+ open(FH, "<", "ans.limit");
+ my $line = <FH>;
+ chomp $line;
+ close FH;
+ if ($line =~ /^\d+$/) {
+ return $line;
+ }
+ }
+
+ return 0;
+}
+
+# If $wait == 0 is returned, returned reply will be sent immediately.
+# If $wait == 1 is returned, sending the returned reply might be delayed; see
+# comments inside handle_UDP() for details.
+sub reply_handler {
+ my ($qname, $qclass, $qtype) = @_;
+ my ($rcode, @ans, @auth, @add, $wait);
+
+ print ("request: $qname/$qtype\n");
+ STDOUT->flush();
+
+ $wait = 0;
+ $count += 1;
+
+ if ($qname eq "count" ) {
+ if ($qtype eq "TXT") {
+ my ($ttl, $rdata) = (0, "$count");
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
+ push @ans, $rr;
+ print ("\tcount: $count\n");
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "reset" ) {
+ $count = 0;
+ $send_response = 0;
+ $limit = getlimit();
+ $rcode = "NOERROR";
+ print ("\tlimit: $limit\n");
+ } elsif ($qname eq "direct.example.org" ) {
+ if ($qtype eq "A") {
+ my ($ttl, $rdata) = (3600, $localaddr);
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
+ push @ans, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "indirect1.example.org" ||
+ $qname eq "indirect2.example.org" ||
+ $qname eq "indirect3.example.org" ||
+ $qname eq "indirect4.example.org" ||
+ $qname eq "indirect5.example.org" ||
+ $qname eq "indirect6.example.org" ||
+ $qname eq "indirect7.example.org" ||
+ $qname eq "indirect8.example.org") {
+ if (! $send_response) {
+ my $rr = new Net::DNS::RR("$qname 86400 $qclass NS ns1.1.example.org");
+ push @auth, $rr;
+ } elsif ($qtype eq "A") {
+ my ($ttl, $rdata) = (3600, $localaddr);
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
+ push @ans, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname =~ /^ns1\.(\d+)\.example\.org$/) {
+ my $next = $1 + 1;
+ $wait = 1;
+ if ($limit == 0 || (! $send_response && $next <= $limit)) {
+ my $rr = new Net::DNS::RR("$1.example.org 86400 $qclass NS ns1.$next.example.org");
+ push @auth, $rr;
+ } else {
+ $send_response = 1;
+ if ($qtype eq "A") {
+ my ($ttl, $rdata) = (3600, "10.53.0.4");
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
+ print("\tresponse: $qname $ttl $qclass $qtype $rdata\n");
+ push @ans, $rr;
+ }
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "direct.example.net" ) {
+ if ($qtype eq "A") {
+ my ($ttl, $rdata) = (3600, $localaddr);
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
+ push @ans, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif( $qname =~ /^ns1\.(\d+)\.example\.net$/ ) {
+ my $next = ($1 + 1) * 16;
+ for (my $i = 1; $i < 16; $i++) {
+ my $s = $next + $i;
+ my $rr = new Net::DNS::RR("$1.example.net 86400 $qclass NS ns1.$s.example.net");
+ push @auth, $rr;
+ $rr = new Net::DNS::RR("ns1.$s.example.net 86400 $qclass A 10.53.0.7");
+ push @add, $rr;
+ }
+ $rcode = "NOERROR";
+ } else {
+ $rcode = "NXDOMAIN";
+ }
+
+ return ($rcode, \@ans, \@auth, \@add, $wait);
+}
+
+sub handleUDP {
+ my ($buf, $peer) = @_;
+ my ($request, $rcode, $ans, $auth, $add, $wait);
+
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+
+ my ($question) = $request->question;
+ my $qname = $question->qname;
+ my $qclass = $question->qclass;
+ my $qtype = $question->qtype;
+
+ ($rcode, $ans, $auth, $add, $wait) = reply_handler($qname, $qclass, $qtype);
+
+ my $reply = $request->reply();
+
+ $reply->header->rcode($rcode);
+ $reply->header->aa(@$ans ? 1 : 0);
+ $reply->header->id($request->header->id);
+ $reply->{answer} = $ans if $ans;
+ $reply->{authority} = $auth if $auth;
+ $reply->{additional} = $add if $add;
+
+ if ($wait) {
+ # reply_handler() asked us to delay sending this reply until
+ # another reply with $wait == 1 is generated or a timeout
+ # occurs.
+ if (@delayed_response) {
+ # A delayed reply is already queued, so we can now send
+ # both the delayed reply and the current reply.
+ send_delayed_response();
+ return $reply;
+ } elsif ($no_more_waiting) {
+ # It was determined before that there is no point in
+ # waiting for "accompanying" queries. Thus, send the
+ # current reply immediately.
+ return $reply;
+ } else {
+ # No delayed reply is queued and the client is expected
+ # to send an "accompanying" query shortly. Do not send
+ # the current reply right now, just save it for later
+ # and wait for an "accompanying" query to be received.
+ @delayed_response = ($reply, $peer);
+ $timeout = 0.5;
+ return;
+ }
+ } else {
+ # Send reply immediately.
+ return $reply;
+ }
+}
+
+sub send_delayed_response {
+ my ($reply, $peer) = @delayed_response;
+ # Truncation to 512 bytes is required for triggering "NS explosion" on
+ # builds without IPv6 support
+ $udpsock->send($reply->data(512), 0, $peer);
+ undef @delayed_response;
+ undef $timeout;
+}
+
+# Main
+my $rin;
+my $rout;
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($udpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, $timeout);
+
+ if (vec($rout, fileno($udpsock), 1)) {
+ my ($buf, $peer, $reply);
+ $udpsock->recv($buf, 512);
+ $peer = $udpsock->peername();
+ $reply = handleUDP($buf, $peer);
+ # Truncation to 512 bytes is required for triggering "NS
+ # explosion" on builds without IPv6 support
+ $udpsock->send($reply->data(512), 0, $peer) if $reply;
+ } else {
+ # An "accompanying" query was expected to come in, but did not.
+ # Assume the client never sends "accompanying" queries to
+ # prevent pointlessly waiting for them ever again.
+ $no_more_waiting = 1;
+ # Send the delayed reply to the query which caused us to wait.
+ send_delayed_response();
+ }
+}
diff --git a/bin/tests/system/reclimit/ans4/ans.pl b/bin/tests/system/reclimit/ans4/ans.pl
new file mode 100644
index 0000000..d5002aa
--- /dev/null
+++ b/bin/tests/system/reclimit/ans4/ans.pl
@@ -0,0 +1,240 @@
+#!/usr/bin/env perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+use warnings;
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+
+my $localaddr = "10.53.0.4";
+my $limit = getlimit();
+my $no_more_waiting = 0;
+my @delayed_response;
+my $timeout;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "$localaddr",
+ LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+my $count = 0;
+my $send_response = 1;
+
+sub getlimit {
+ if ( -e "ans.limit") {
+ open(FH, "<", "ans.limit");
+ my $line = <FH>;
+ chomp $line;
+ close FH;
+ if ($line =~ /^\d+$/) {
+ return $line;
+ }
+ }
+
+ return 0;
+}
+
+# If $wait == 0 is returned, returned reply will be sent immediately.
+# If $wait == 1 is returned, sending the returned reply might be delayed; see
+# comments inside handle_UDP() for details.
+sub reply_handler {
+ my ($qname, $qclass, $qtype) = @_;
+ my ($rcode, @ans, @auth, @add, $wait);
+
+ print ("request: $qname/$qtype\n");
+ STDOUT->flush();
+
+ $wait = 0;
+ $count += 1;
+
+ if ($qname eq "count" ) {
+ if ($qtype eq "TXT") {
+ my ($ttl, $rdata) = (0, "$count");
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
+ push @ans, $rr;
+ print ("\tcount: $count\n");
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "reset" ) {
+ $count = 0;
+ $send_response = 1;
+ $limit = getlimit();
+ $rcode = "NOERROR";
+ print ("\tlimit: $limit\n");
+ } elsif ($qname eq "direct.example.org" ) {
+ if ($qtype eq "A") {
+ my ($ttl, $rdata) = (3600, $localaddr);
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
+ push @ans, $rr;
+ print ("\twait=$wait ans: $qname $ttl $qclass $qtype $rdata\n");
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "indirect1.example.org" ||
+ $qname eq "indirect2.example.org" ||
+ $qname eq "indirect3.example.org" ||
+ $qname eq "indirect4.example.org" ||
+ $qname eq "indirect5.example.org" ||
+ $qname eq "indirect6.example.org" ||
+ $qname eq "indirect7.example.org" ||
+ $qname eq "indirect8.example.org") {
+ if ($qtype eq "A") {
+ my ($ttl, $rdata) = (3600, $localaddr);
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
+ push @ans, $rr;
+ print ("\twait=$wait ans: $qname $ttl $qclass $qtype $rdata\n");
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname =~ /^ns1\.(\d+)\.example\.org$/) {
+ my $next = $1 + 1;
+ $wait = 1;
+ if ($limit == 0) {
+ my $rr = new Net::DNS::RR("$1.example.org 86400 $qclass NS ns1.$next.example.org");
+ push @auth, $rr;
+ print ("\twait=$wait auth: $1.example.org 86400 $qclass NS ns1.$next.example.org\n");
+ } else {
+ $send_response = 1;
+ if ($qtype eq "A") {
+ my ($ttl, $rdata) = (3600, $localaddr);
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
+ print("\tresponse: $qname $ttl $qclass $qtype $rdata\n");
+ push @ans, $rr;
+ }
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "direct.example.net" ) {
+ if ($qtype eq "A") {
+ my ($ttl, $rdata) = (3600, $localaddr);
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
+ push @ans, $rr;
+ print ("\twait=$wait ans: $qname $ttl $qclass $qtype $rdata\n");
+ }
+ $rcode = "NOERROR";
+ } elsif( $qname =~ /^ns1\.(\d+)\.example\.net$/ ) {
+ my $next = ($1 + 1) * 16;
+ for (my $i = 1; $i < 16; $i++) {
+ my $s = $next + $i;
+ my $rr = new Net::DNS::RR("$1.example.net 86400 $qclass NS ns1.$s.example.net");
+ push @auth, $rr;
+ print ("\twait=$wait auth: $1.example.net 86400 $qclass NS ns1.$s.example.net\n");
+ $rr = new Net::DNS::RR("ns1.$s.example.net 86400 $qclass A 10.53.0.7");
+ print ("\twait=$wait add: ns1.$s.example.net 86400 $qclass A 10.53.0.7\n");
+ push @add, $rr;
+ }
+ $rcode = "NOERROR";
+ } else {
+ $rcode = "NXDOMAIN";
+ print ("\twait=$wait NXDOMAIN\n");
+ }
+
+ return ($rcode, \@ans, \@auth, \@add, $wait);
+}
+
+sub handleUDP {
+ my ($buf, $peer) = @_;
+ my ($request, $rcode, $ans, $auth, $add, $wait);
+
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+
+ my ($question) = $request->question;
+ my $qname = $question->qname;
+ my $qclass = $question->qclass;
+ my $qtype = $question->qtype;
+
+ ($rcode, $ans, $auth, $add, $wait) = reply_handler($qname, $qclass, $qtype);
+
+ my $reply = $request->reply();
+
+ $reply->header->rcode($rcode);
+ $reply->header->aa(@$ans ? 1 : 0);
+ $reply->header->id($request->header->id);
+ $reply->{answer} = $ans if $ans;
+ $reply->{authority} = $auth if $auth;
+ $reply->{additional} = $add if $add;
+
+ if ($wait) {
+ # reply_handler() asked us to delay sending this reply until
+ # another reply with $wait == 1 is generated or a timeout
+ # occurs.
+ if (@delayed_response) {
+ # A delayed reply is already queued, so we can now send
+ # both the delayed reply and the current reply.
+ send_delayed_response();
+ return $reply;
+ } elsif ($no_more_waiting) {
+ # It was determined before that there is no point in
+ # waiting for "accompanying" queries. Thus, send the
+ # current reply immediately.
+ return $reply;
+ } else {
+ # No delayed reply is queued and the client is expected
+ # to send an "accompanying" query shortly. Do not send
+ # the current reply right now, just save it for later
+ # and wait for an "accompanying" query to be received.
+ @delayed_response = ($reply, $peer);
+ $timeout = 0.5;
+ return;
+ }
+ } else {
+ # Send reply immediately.
+ return $reply;
+ }
+}
+
+sub send_delayed_response {
+ my ($reply, $peer) = @delayed_response;
+ # Truncation to 512 bytes is required for triggering "NS explosion" on
+ # builds without IPv6 support
+ $udpsock->send($reply->data(512), 0, $peer);
+ undef @delayed_response;
+ undef $timeout;
+ print ("send_delayed_response\n");
+}
+
+# Main
+my $rin;
+my $rout;
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($udpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, $timeout);
+
+ if (vec($rout, fileno($udpsock), 1)) {
+ my ($buf, $peer, $reply);
+ $udpsock->recv($buf, 512);
+ $peer = $udpsock->peername();
+ $reply = handleUDP($buf, $peer);
+ # Truncation to 512 bytes is required for triggering "NS
+ # explosion" on builds without IPv6 support
+ $udpsock->send($reply->data(512), 0, $peer) if $reply;
+ } else {
+ # An "accompanying" query was expected to come in, but did not.
+ # Assume the client never sends "accompanying" queries to
+ # prevent pointlessly waiting for them ever again.
+ $no_more_waiting = 1;
+ # Send the delayed reply to the query which caused us to wait.
+ send_delayed_response();
+ }
+}
diff --git a/bin/tests/system/reclimit/ans7/ans.pl b/bin/tests/system/reclimit/ans7/ans.pl
new file mode 100644
index 0000000..41a44a6
--- /dev/null
+++ b/bin/tests/system/reclimit/ans7/ans.pl
@@ -0,0 +1,76 @@
+#!/usr/bin/env perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+use warnings;
+
+use IO::File;
+use Getopt::Long;
+use Net::DNS::Nameserver;
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+my $count = 0;
+
+my $localaddr = "10.53.0.7";
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+my $verbose = 0;
+
+sub reply_handler {
+ my ($qname, $qclass, $qtype, $peerhost, $query, $conn) = @_;
+ my ($rcode, @ans, @auth, @add);
+
+ print ("request: $qname/$qtype\n");
+ STDOUT->flush();
+
+ $count += 1;
+
+ if ($qname eq "count" ) {
+ if ($qtype eq "TXT") {
+ my ($ttl, $rdata) = (0, "$count");
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
+ push @ans, $rr;
+ print ("\tcount: $count\n");
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "reset") {
+ $count = 0;
+ $rcode = "NOERROR";
+ } else {
+ $rcode = "REFUSED";
+ }
+
+ # mark the answer as authoritative (by setting the 'aa' flag
+ return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
+}
+
+GetOptions(
+ 'port=i' => \$localport,
+ 'verbose!' => \$verbose,
+);
+
+my $ns = Net::DNS::Nameserver->new(
+ LocalAddr => $localaddr,
+ LocalPort => $localport,
+ ReplyHandler => \&reply_handler,
+ Verbose => $verbose,
+);
+
+$ns->main_loop;
diff --git a/bin/tests/system/reclimit/clean.sh b/bin/tests/system/reclimit/clean.sh
new file mode 100644
index 0000000..0a92f90
--- /dev/null
+++ b/bin/tests/system/reclimit/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out*
+rm -f ans?/ans.run
+rm -f ans2/ans.limit
+rm -f ans4/ans.limit
+rm -f ns?/named.memstats
+rm -f ns?/named.run
+rm -f ns*/named.conf
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/reclimit/ns1/named.conf.in b/bin/tests/system/reclimit/ns1/named.conf.in
new file mode 100644
index 0000000..63cb706
--- /dev/null
+++ b/bin/tests/system/reclimit/ns1/named.conf.in
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory ".";
+ 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;
+ dnssec-validation no;
+};
+
+zone "." { type primary; file "root.db"; };
diff --git a/bin/tests/system/reclimit/ns1/root.db b/bin/tests/system/reclimit/ns1/root.db
new file mode 100644
index 0000000..412715c
--- /dev/null
+++ b/bin/tests/system/reclimit/ns1/root.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 60 IN SOA ns.nil. hostmaster.ns.nil. 1 0 0 0 0
+. 60 IN NS ns.nil.
+ns.nil. 60 IN A 10.53.0.1
+ns.tld1. 60 IN A 10.53.0.1
+example.org. 60 IN NS direct.example.org.
+direct.example.org. 60 IN A 10.53.0.2
+example.net. 60 IN NS direct.example.net.
+direct.example.net. 60 IN A 10.53.0.2
+example.com. 60 IN NS direct.example.com.
+direct.example.com. 60 IN A 10.53.0.4
diff --git a/bin/tests/system/reclimit/ns3/hints.db b/bin/tests/system/reclimit/ns3/hints.db
new file mode 100644
index 0000000..c9264bf
--- /dev/null
+++ b/bin/tests/system/reclimit/ns3/hints.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 60 IN NS ns.nil.
+ns.nil. 60 IN A 10.53.0.1
diff --git a/bin/tests/system/reclimit/ns3/named1.conf.in b/bin/tests/system/reclimit/ns3/named1.conf.in
new file mode 100644
index 0000000..58b5d02
--- /dev/null
+++ b/bin/tests/system/reclimit/ns3/named1.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory ".";
+ 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; };
+ servfail-ttl 0;
+ qname-minimization disabled;
+ max-recursion-depth 12;
+ recursion yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints.db"; };
diff --git a/bin/tests/system/reclimit/ns3/named2.conf.in b/bin/tests/system/reclimit/ns3/named2.conf.in
new file mode 100644
index 0000000..b5389f4
--- /dev/null
+++ b/bin/tests/system/reclimit/ns3/named2.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory ".";
+ 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; };
+ servfail-ttl 0;
+ qname-minimization disabled;
+ max-recursion-depth 5;
+ recursion yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints.db"; };
diff --git a/bin/tests/system/reclimit/ns3/named3.conf.in b/bin/tests/system/reclimit/ns3/named3.conf.in
new file mode 100644
index 0000000..f356f24
--- /dev/null
+++ b/bin/tests/system/reclimit/ns3/named3.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory ".";
+ 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; };
+ servfail-ttl 0;
+ qname-minimization disabled;
+ max-recursion-depth 100;
+ max-recursion-queries 50;
+ recursion yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints.db"; };
diff --git a/bin/tests/system/reclimit/ns3/named4.conf.in b/bin/tests/system/reclimit/ns3/named4.conf.in
new file mode 100644
index 0000000..728f00b
--- /dev/null
+++ b/bin/tests/system/reclimit/ns3/named4.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory ".";
+ 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; };
+ servfail-ttl 0;
+ qname-minimization disabled;
+ max-recursion-depth 100;
+ max-recursion-queries 40;
+ recursion yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints.db"; };
diff --git a/bin/tests/system/reclimit/setup.sh b/bin/tests/system/reclimit/setup.sh
new file mode 100644
index 0000000..c877f3b
--- /dev/null
+++ b/bin/tests/system/reclimit/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns3/named1.conf.in ns3/named.conf
diff --git a/bin/tests/system/reclimit/tests.sh b/bin/tests/system/reclimit/tests.sh
new file mode 100644
index 0000000..7e80d22
--- /dev/null
+++ b/bin/tests/system/reclimit/tests.sh
@@ -0,0 +1,212 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+
+status=0
+n=0
+
+ns3_reset() {
+ copy_setports $1 ns3/named.conf
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reconfig 2>&1 | sed 's/^/I:ns3 /'
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush | sed 's/^/I:ns3 /'
+}
+
+ns3_sends_aaaa_queries() {
+ if grep "started AAAA fetch" ns3/named.run >/dev/null; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# Check whether the number of queries ans2 received from ns3 (this value is
+# read from dig output stored in file $1) is as expected. The expected query
+# count is variable:
+# - if ns3 sends AAAA queries, the query count should equal $2,
+# - if ns3 does not send AAAA queries, the query count should equal $3.
+check_query_count() {
+ count1=$(sed 's/[^0-9]//g;' $1)
+ count2=$(sed 's/[^0-9]//g;' $2)
+ count=$((count1 + count2))
+ #echo_i "count1=$count1 count2=$count2 count=$count"
+ expected_count_with_aaaa=$3
+ expected_count_without_aaaa=$4
+
+ if ns3_sends_aaaa_queries; then
+ expected_count=$expected_count_with_aaaa
+ else
+ expected_count=$expected_count_without_aaaa
+ fi
+
+ if [ $count -ne $expected_count ]; then
+ echo_i "count $count (actual) != $expected_count (expected)"
+ ret=1
+ fi
+}
+
+echo_i "set max-recursion-depth=12"
+
+n=$((n + 1))
+echo_i "attempt excessive-depth lookup ($n)"
+ret=0
+echo "1000" > ans2/ans.limit
+echo "1000" > ans4/ans.limit
+$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.4 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 indirect1.example.org > dig.out.1.test$n || ret=1
+grep "status: SERVFAIL" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
+$DIG $DIGOPTS +short @10.53.0.4 count txt > dig.out.4.test$n || ret=1
+check_query_count dig.out.2.test$n dig.out.4.test$n 27 14
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "attempt permissible lookup ($n)"
+ret=0
+echo "12" > ans2/ans.limit
+echo "12" > ans4/ans.limit
+ns3_reset ns3/named1.conf.in
+$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.4 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 indirect2.example.org > dig.out.1.test$n || ret=1
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
+$DIG $DIGOPTS +short @10.53.0.4 count txt > dig.out.4.test$n || ret=1
+check_query_count dig.out.2.test$n dig.out.4.test$n 50 26
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "set max-recursion-depth=5"
+
+n=$((n + 1))
+echo_i "attempt excessive-depth lookup ($n)"
+ret=0
+echo "12" > ans2/ans.limit
+ns3_reset ns3/named2.conf.in
+$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.4 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 indirect3.example.org > dig.out.1.test$n || ret=1
+grep "status: SERVFAIL" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
+$DIG $DIGOPTS +short @10.53.0.4 count txt > dig.out.4.test$n || ret=1
+check_query_count dig.out.2.test$n dig.out.4.test$n 13 7
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "attempt permissible lookup ($n)"
+ret=0
+echo "5" > ans2/ans.limit
+echo "5" > ans4/ans.limit
+ns3_reset ns3/named2.conf.in
+$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.4 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 indirect4.example.org > dig.out.1.test$n || ret=1
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
+$DIG $DIGOPTS +short @10.53.0.4 count txt > dig.out.4.test$n || ret=1
+check_query_count dig.out.2.test$n dig.out.4.test$n 22 12
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "set max-recursion-depth=100, max-recursion-queries=50"
+
+n=$((n + 1))
+echo_i "attempt excessive-queries lookup ($n)"
+ret=0
+echo "13" > ans2/ans.limit
+echo "13" > ans4/ans.limit
+ns3_reset ns3/named3.conf.in
+$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.4 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 indirect5.example.org > dig.out.1.test$n || ret=1
+if ns3_sends_aaaa_queries; then
+ grep "status: SERVFAIL" dig.out.1.test$n > /dev/null || ret=1
+fi
+$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
+$DIG $DIGOPTS +short @10.53.0.4 count txt > dig.out.4.test$n || ret=1
+eval count=$(cat dig.out.2.test$n)
+[ $count -le 50 ] || { ret=1; echo_i "count ($count) !<= 50"; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "attempt permissible lookup ($n)"
+ret=0
+echo "12" > ans2/ans.limit
+ns3_reset ns3/named3.conf.in
+$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 indirect6.example.org > dig.out.1.test$n || ret=1
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
+eval count=$(cat dig.out.2.test$n)
+[ $count -le 50 ] || { ret=1; echo_i "count ($count) !<= 50"; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "set max-recursion-depth=100, max-recursion-queries=40"
+
+n=$((n + 1))
+echo_i "attempt excessive-queries lookup ($n)"
+ret=0
+echo "11" > ans2/ans.limit
+ns3_reset ns3/named4.conf.in
+$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 indirect7.example.org > dig.out.1.test$n || ret=1
+if ns3_sends_aaaa_queries; then
+ grep "status: SERVFAIL" dig.out.1.test$n > /dev/null || ret=1
+fi
+$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
+eval count=$(cat dig.out.2.test$n)
+[ $count -le 40 ] || { ret=1; echo_i "count ($count) !<= 40"; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "attempt permissible lookup ($n)"
+ret=0
+echo "9" > ans2/ans.limit
+ns3_reset ns3/named4.conf.in
+$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
+$DIG $DIGOPTS @10.53.0.3 indirect8.example.org > dig.out.1.test$n || ret=1
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
+eval count=$(cat dig.out.2.test$n)
+[ $count -le 40 ] || { ret=1; echo_i "count ($count) !<= 40"; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "attempting NS explosion ($n)"
+ret=0
+ns3_reset ns3/named4.conf.in
+$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
+$DIG $DIGOPTS +short @10.53.0.3 ns1.1.example.net > dig.out.1.test$n || ret=1
+$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
+eval count=$(cat dig.out.2.test$n)
+[ $count -lt 50 ] || ret=1
+$DIG $DIGOPTS +short @10.53.0.7 count txt > dig.out.3.test$n || ret=1
+eval count=$(cat dig.out.3.test$n)
+[ $count -lt 50 ] || { ret=1; echo_i "count ($count) !<= 50"; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#grep "duplicate query" ns3/named.run
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/reclimit/tests_sh_reclimit.py b/bin/tests/system/reclimit/tests_sh_reclimit.py
new file mode 100644
index 0000000..4710027
--- /dev/null
+++ b/bin/tests/system/reclimit/tests_sh_reclimit.py
@@ -0,0 +1,18 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import pytest_custom_markers
+
+
+# The reclimit is known to be quite unstable. GL #1587
+@pytest_custom_markers.flaky(max_runs=2)
+def test_reclimit(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/redirect/clean.sh b/bin/tests/system/redirect/clean.sh
new file mode 100644
index 0000000..9489c94
--- /dev/null
+++ b/bin/tests/system/redirect/clean.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.stats
+rm -f dig.out.*
+rm -f ns*/named.lock
+rm -f ns1/K*
+rm -f ns1/dsset-nsec3.
+rm -f ns1/dsset-signed.
+rm -f ns1/nsec3.db*
+rm -f ns1/signed.db*
+rm -f ns2/*.db
+rm -f ns3/K*
+rm -f ns3/dsset-nsec3.
+rm -f ns3/dsset-signed.
+rm -f ns3/nsec3.db*
+rm -f ns3/signed.db*
+rm -f ns4/*.db
+rm -f ns5/dsset-*
+rm -f ns5/K* ns5/sign.ns5.*
+rm -f ns5/root.db ns5/root.db.signed
+rm -f ns5/signed.db ns5/signed.db.signed
+rm -f ns6/signed.db.signed
+rm -f rndc.out
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/redirect/conf/bad1.conf b/bin/tests/system/redirect/conf/bad1.conf
new file mode 100644
index 0000000..5ff4fee
--- /dev/null
+++ b/bin/tests/system/redirect/conf/bad1.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+zone "." {
+ type redirect;
+ file "redirect.db";
+ allow-query { 10.0.1.0; };
+/* option 'forwarders' is not allowed in 'redirect' zone '.' */
+ forwarders { 1.2.3.4; };
+};
diff --git a/bin/tests/system/redirect/conf/bad2.conf b/bin/tests/system/redirect/conf/bad2.conf
new file mode 100644
index 0000000..0cf0a68
--- /dev/null
+++ b/bin/tests/system/redirect/conf/bad2.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+zone "." {
+ type redirect;
+ file "redirect.db";
+ allow-query { 10.0.1.0; };
+/* option 'also-notify' is not allowed in 'redirect' zone '.' */
+ also-notify { 1.2.3.4; };
+};
diff --git a/bin/tests/system/redirect/conf/bad3.conf b/bin/tests/system/redirect/conf/bad3.conf
new file mode 100644
index 0000000..b034c5b
--- /dev/null
+++ b/bin/tests/system/redirect/conf/bad3.conf
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+/* redirect zones must be called "." */
+zone "x" {
+ type redirect;
+ file "redirect.db";
+ allow-query { 10.0.1.0; };
+};
diff --git a/bin/tests/system/redirect/conf/good1.conf b/bin/tests/system/redirect/conf/good1.conf
new file mode 100644
index 0000000..c5711e5
--- /dev/null
+++ b/bin/tests/system/redirect/conf/good1.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+zone "." {
+ type redirect;
+ file "redirect.db";
+};
diff --git a/bin/tests/system/redirect/conf/good2.conf b/bin/tests/system/redirect/conf/good2.conf
new file mode 100644
index 0000000..f6ebd63
--- /dev/null
+++ b/bin/tests/system/redirect/conf/good2.conf
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type primary;
+ file "primary.db";
+};
+
+zone "." {
+ type redirect;
+ file "redirect.db";
+};
diff --git a/bin/tests/system/redirect/conf/good3.conf b/bin/tests/system/redirect/conf/good3.conf
new file mode 100644
index 0000000..dcdd954
--- /dev/null
+++ b/bin/tests/system/redirect/conf/good3.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type secondary;
+ file "sec.db";
+ primaries { 1.2.3.4; };
+};
+
+zone "." {
+ type redirect;
+ file "redirect.db";
+};
diff --git a/bin/tests/system/redirect/conf/good4.conf b/bin/tests/system/redirect/conf/good4.conf
new file mode 100644
index 0000000..e046577
--- /dev/null
+++ b/bin/tests/system/redirect/conf/good4.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+zone "." {
+ type redirect;
+ file "redirect.db";
+ allow-query { 10.0.1.0; };
+};
diff --git a/bin/tests/system/redirect/ns1/example.db b/bin/tests/system/redirect/ns1/example.db
new file mode 100644
index 0000000..90c09d4
--- /dev/null
+++ b/bin/tests/system/redirect/ns1/example.db
@@ -0,0 +1,50 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns1 marka.isc.org. 0 0 0 0 1200
+@ NS ns1
+ns1 A 10.53.0.1
+excluded-good-a AAAA 2001:eeee::1
+ A 1.2.3.4
+excluded-bad-a AAAA 2001:eeee::2
+ A 10.0.0.1
+excluded-only AAAA 2001:eeee::3
+partially-excluded-good-a AAAA 2001:eeee::1
+ AAAA 2001::1
+ A 1.2.3.4
+partially-excluded-bad-a AAAA 2001:eeee::2
+ AAAA 2001::2
+ A 10.0.0.1
+partially-excluded-only AAAA 2001:eeee::3
+ AAAA 2001::3
+a-only A 1.2.3.5
+a-and-aaaa AAAA 2001::1
+ A 1.2.3.6
+aaaa-only AAAA 2001::2
+a-not-mapped A 10.0.0.2
+mx-only MX 10 ns.example.
+cname-excluded-good-a CNAME excluded-good-a
+cname-excluded-bad-a CNAME excluded-bad-a
+cname-excluded-only CNAME excluded-only
+cname-partial-excluded-good-a CNAME partial-excluded-good-a
+cname-partial-excluded-bad-a CNAME partial-excluded-bad-a
+cname-partial-excluded-only CNAME partial-excluded-only
+cname-a-only CNAME a-only
+cname-a-and-aaaa CNAME a-and-aaaa
+cname-aaaa-only CNAME aaaa-only
+cname-a-not-mapped CNAME a-not-mapped
+cname-mx-only CNAME mx-only
+cname-non-existent CNAME non-existent
+ttl-less-than-600 500 A 5.6.7.8
+ttl-more-than-600 700 A 5.6.7.8
+ttl-less-than-minimum 1100 A 5.6.7.8
+ttl-more-than-minimum 1300 A 5.6.7.8
diff --git a/bin/tests/system/redirect/ns1/named.conf.in b/bin/tests/system/redirect/ns1/named.conf.in
new file mode 100644
index 0000000..412b874
--- /dev/null
+++ b/bin/tests/system/redirect/ns1/named.conf.in
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+
+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; };
+ allow-recursion { 10.53.0.1; };
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "signed" {
+ type primary;
+ file "signed.db.signed";
+};
+
+zone "nsec3" {
+ type primary;
+ file "nsec3.db.signed";
+};
+
+zone "." {
+ type redirect;
+ file "redirect.db";
+ allow-query { !10.53.0.2; !10.53.0.4; any; };
+};
+
+// include "trusted.conf";
diff --git a/bin/tests/system/redirect/ns1/redirect.db b/bin/tests/system/redirect/ns1/redirect.db
new file mode 100644
index 0000000..b2a60bb
--- /dev/null
+++ b/bin/tests/system/redirect/ns1/redirect.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA ns.example.net hostmaster.example.net 0 0 0 0 0
+@ IN NS ns.example.net
+;
+; NS records do not need address records in this zone as it is not in the
+; normal namespace.
+;
+*. IN A 100.100.100.2
+*. IN AAAA 2001:ffff:ffff::100.100.100.2
diff --git a/bin/tests/system/redirect/ns1/root.db b/bin/tests/system/redirect/ns1/root.db
new file mode 100644
index 0000000..6df215f
--- /dev/null
+++ b/bin/tests/system/redirect/ns1/root.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA a.root-servers.nil. marka.isc.org. 0 0 0 0 0
+@ NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+example NS ns1.example.
+ns1.example. A 10.53.0.1
+signed NS ns1.example.
+ns1.signed. A 10.53.0.1
diff --git a/bin/tests/system/redirect/ns1/sign.sh b/bin/tests/system/redirect/ns1/sign.sh
new file mode 100644
index 0000000..974e6ca
--- /dev/null
+++ b/bin/tests/system/redirect/ns1/sign.sh
@@ -0,0 +1,36 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=signed
+infile=example.db
+zonefile=signed.db
+
+key1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $zone)
+key2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $zone)
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -o $zone $zonefile > /dev/null
+
+zone=nsec3
+infile=example.db
+zonefile=nsec3.db
+
+key1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 $zone)
+key2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 -fk $zone)
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -3 - -g -o $zone $zonefile > /dev/null
diff --git a/bin/tests/system/redirect/ns2/example.db.in b/bin/tests/system/redirect/ns2/example.db.in
new file mode 100644
index 0000000..a87ae7d
--- /dev/null
+++ b/bin/tests/system/redirect/ns2/example.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns.example.net hostmaster.example.net 0 0 0 0 0
+@ NS ns2
+ns2 A 10.53.0.2
+a A 10.53.0.2
diff --git a/bin/tests/system/redirect/ns2/named.conf.in b/bin/tests/system/redirect/ns2/named.conf.in
new file mode 100644
index 0000000..9b88736
--- /dev/null
+++ b/bin/tests/system/redirect/ns2/named.conf.in
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation yes;
+
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "." {
+ type redirect;
+ file "redirect.db";
+ allow-query { !10.53.0.4; any; };
+};
+
+zone "example.nil" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/redirect/ns2/redirect.db.in b/bin/tests/system/redirect/ns2/redirect.db.in
new file mode 100644
index 0000000..e05d64d
--- /dev/null
+++ b/bin/tests/system/redirect/ns2/redirect.db.in
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA ns.example.net hostmaster.example.net 0 0 0 0 0
+@ IN NS ns.example.net
+;
+; NS records do not need address records in this zone as it is not in the
+; normal namespace.
+;
+*. IN A 100.100.100.1
+*. IN AAAA 2001:ffff:ffff::100.100.100.1
diff --git a/bin/tests/system/redirect/ns3/example.db b/bin/tests/system/redirect/ns3/example.db
new file mode 100644
index 0000000..4cceedf
--- /dev/null
+++ b/bin/tests/system/redirect/ns3/example.db
@@ -0,0 +1,50 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns3 marka.isc.org. 0 0 0 0 1200
+@ NS ns3
+ns3 A 10.53.0.3
+excluded-good-a AAAA 2001:eeee::1
+ A 1.2.3.4
+excluded-bad-a AAAA 2001:eeee::2
+ A 10.0.0.1
+excluded-only AAAA 2001:eeee::3
+partially-excluded-good-a AAAA 2001:eeee::1
+ AAAA 2001::1
+ A 1.2.3.4
+partially-excluded-bad-a AAAA 2001:eeee::2
+ AAAA 2001::2
+ A 10.0.0.1
+partially-excluded-only AAAA 2001:eeee::3
+ AAAA 2001::3
+a-only A 1.2.3.5
+a-and-aaaa AAAA 2001::1
+ A 1.2.3.6
+aaaa-only AAAA 2001::2
+a-not-mapped A 10.0.0.2
+mx-only MX 10 ns.example.
+cname-excluded-good-a CNAME excluded-good-a
+cname-excluded-bad-a CNAME excluded-bad-a
+cname-excluded-only CNAME excluded-only
+cname-partial-excluded-good-a CNAME partial-excluded-good-a
+cname-partial-excluded-bad-a CNAME partial-excluded-bad-a
+cname-partial-excluded-only CNAME partial-excluded-only
+cname-a-only CNAME a-only
+cname-a-and-aaaa CNAME a-and-aaaa
+cname-aaaa-only CNAME aaaa-only
+cname-a-not-mapped CNAME a-not-mapped
+cname-mx-only CNAME mx-only
+cname-non-existent CNAME non-existent
+ttl-less-than-600 500 A 5.6.7.8
+ttl-more-than-600 700 A 5.6.7.8
+ttl-less-than-minimum 1100 A 5.6.7.8
+ttl-more-than-minimum 1300 A 5.6.7.8
diff --git a/bin/tests/system/redirect/ns3/named.conf.in b/bin/tests/system/redirect/ns3/named.conf.in
new file mode 100644
index 0000000..2113dd5
--- /dev/null
+++ b/bin/tests/system/redirect/ns3/named.conf.in
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+
+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; };
+ allow-recursion { 10.53.0.3; };
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "signed" {
+ type primary;
+ file "signed.db.signed";
+};
+
+zone "nsec3" {
+ type primary;
+ file "nsec3.db.signed";
+};
+
+zone "redirect" {
+ type primary;
+ file "redirect.db";
+};
+
+// include "trusted.conf";
diff --git a/bin/tests/system/redirect/ns3/redirect.db b/bin/tests/system/redirect/ns3/redirect.db
new file mode 100644
index 0000000..b5b63da
--- /dev/null
+++ b/bin/tests/system/redirect/ns3/redirect.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA a.root-servers.nil. hostmaster.example.net. 0 0 0 0 0
+@ IN NS a.root-servers.nil.
+* IN A 100.100.100.1
+* IN AAAA 2001:ffff:ffff::100.100.100.1
diff --git a/bin/tests/system/redirect/ns3/root.db b/bin/tests/system/redirect/ns3/root.db
new file mode 100644
index 0000000..13433ef
--- /dev/null
+++ b/bin/tests/system/redirect/ns3/root.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA a.root-servers.nil. marka.isc.org. 0 0 0 0 0
+@ NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.3
+example NS ns1.example.
+ns1.example. A 10.53.0.3
+signed NS ns1.example.
+ns1.signed. A 10.53.0.3
+redirect NS a.root-servers.nil
diff --git a/bin/tests/system/redirect/ns3/sign.sh b/bin/tests/system/redirect/ns3/sign.sh
new file mode 100644
index 0000000..974e6ca
--- /dev/null
+++ b/bin/tests/system/redirect/ns3/sign.sh
@@ -0,0 +1,36 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=signed
+infile=example.db
+zonefile=signed.db
+
+key1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $zone)
+key2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $zone)
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -o $zone $zonefile > /dev/null
+
+zone=nsec3
+infile=example.db
+zonefile=nsec3.db
+
+key1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 $zone)
+key2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 -fk $zone)
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -3 - -g -o $zone $zonefile > /dev/null
diff --git a/bin/tests/system/redirect/ns4/example.db.in b/bin/tests/system/redirect/ns4/example.db.in
new file mode 100644
index 0000000..8057d1b
--- /dev/null
+++ b/bin/tests/system/redirect/ns4/example.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns.example.net hostmaster.example.net 0 0 0 0 0
+@ NS ns4
+ns4 A 10.53.0.4
+a A 10.53.0.2
diff --git a/bin/tests/system/redirect/ns4/named.conf.in b/bin/tests/system/redirect/ns4/named.conf.in
new file mode 100644
index 0000000..1650e99
--- /dev/null
+++ b/bin/tests/system/redirect/ns4/named.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
+
+options {
+ query-source address 10.53.0.2; /* note this is not 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;
+ notify yes;
+ dnssec-validation yes;
+ nxdomain-redirect "redirect";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/redirect/ns4/root.hint b/bin/tests/system/redirect/ns4/root.hint
new file mode 100644
index 0000000..3889a8b
--- /dev/null
+++ b/bin/tests/system/redirect/ns4/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.3
diff --git a/bin/tests/system/redirect/ns5/named.conf.in b/bin/tests/system/redirect/ns5/named.conf.in
new file mode 100644
index 0000000..2513a45
--- /dev/null
+++ b/bin/tests/system/redirect/ns5/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+options {
+ port @PORT@;
+ listen-on port @PORT@ { 10.53.0.5; };
+ pid-file "named.pid";
+ nxdomain-redirect signed;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+// An unsigned zone that ns6 has a delegation for.
+zone "unsigned." {
+ type primary;
+ file "unsigned.db";
+};
diff --git a/bin/tests/system/redirect/ns5/root.db.in b/bin/tests/system/redirect/ns5/root.db.in
new file mode 100644
index 0000000..19aa61d
--- /dev/null
+++ b/bin/tests/system/redirect/ns5/root.db.in
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 86400 IN SOA a.root-servers.nil. hostmaster.example.net. 2019022100 1800 900 604800 86400
+. 518400 IN NS a.root-servers.nil.
+a.root-servers.nil. 518400 IN A 10.53.0.5
+signed. 172800 IN NS ns.signed.
+ns.signed. 172800 IN A 10.53.0.6
+unsigned. 172800 IN NS ns.unsigned.
+ns.unsigned. 172800 IN A 10.53.0.5
diff --git a/bin/tests/system/redirect/ns5/sign.sh b/bin/tests/system/redirect/ns5/sign.sh
new file mode 100644
index 0000000..ffe4e13
--- /dev/null
+++ b/bin/tests/system/redirect/ns5/sign.sh
@@ -0,0 +1,44 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+# We sign the zone here and move the signed zone to ns6.
+# The ns5 server actually does not serve this zone but
+# the DS and NS records are in the test root zone, and
+# delegate to ns6.
+zone=signed.
+infile=signed.db.in
+zonefile=signed.db
+
+key1=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS $zone 2> /dev/null)
+key2=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -fk $zone 2> /dev/null)
+
+cat $infile $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -O full -o $zone $zonefile > sign.ns5.signed.out
+
+cp signed.db.signed ../ns6
+
+# Root zone.
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+key1=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS $zone 2> /dev/null)
+key2=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -fk $zone 2> /dev/null)
+
+# cat $infile $key1.key $key2.key > $zonefile
+cat $infile dsset-signed. $key1.key $key2.key > $zonefile
+
+$SIGNER -P -g -O full -o $zone $zonefile > sign.ns5.root.out
diff --git a/bin/tests/system/redirect/ns5/signed.db.in b/bin/tests/system/redirect/ns5/signed.db.in
new file mode 100644
index 0000000..6579227
--- /dev/null
+++ b/bin/tests/system/redirect/ns5/signed.db.in
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA ns.signed. hostmaster.signed. 0 0 0 0 0
+@ IN NS ns.signed.
+
+ns.signed. IN A 10.0.53.6
+domain.signed. IN A 10.0.53.1
+
+* IN A 100.100.100.1
+* IN AAAA 2001:ffff:ffff::100.100.100.1
diff --git a/bin/tests/system/redirect/ns5/unsigned.db b/bin/tests/system/redirect/ns5/unsigned.db
new file mode 100644
index 0000000..10e06ff
--- /dev/null
+++ b/bin/tests/system/redirect/ns5/unsigned.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA ns.unsigned. hostmaster.unsigned. 0 0 0 0 0
+@ IN NS ns.unsigned.
+
+ns.unsigned. IN A 10.53.0.6
+domain.unsigned. IN A 10.0.53.1
+
+* IN A 100.100.100.1
+* IN AAAA 2001:ffff:ffff::100.100.100.1
diff --git a/bin/tests/system/redirect/ns6/named.conf.in b/bin/tests/system/redirect/ns6/named.conf.in
new file mode 100644
index 0000000..dee2bcf
--- /dev/null
+++ b/bin/tests/system/redirect/ns6/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS6
+
+options {
+ port @PORT@;
+ listen-on port @PORT@ { 10.53.0.6; };
+ pid-file "named.pid";
+ nxdomain-redirect unsigned;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+// A signed zone that ns5 has a delegation for.
+zone "signed." {
+ type primary;
+ file "signed.db.signed";
+};
diff --git a/bin/tests/system/redirect/ns6/root.db b/bin/tests/system/redirect/ns6/root.db
new file mode 100644
index 0000000..a8e6a45
--- /dev/null
+++ b/bin/tests/system/redirect/ns6/root.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 86400 IN SOA a.root-servers.nil. hostmaster.example.net. 2019022100 1800 900 604800 86400
+. 518400 IN NS a.root-servers.nil.
+a.root-servers.nil. 518400 IN A 10.53.0.6
+signed. 172800 IN NS ns.signed.
+ns.signed. 172800 IN A 10.53.0.6
+unsigned. 172800 IN NS ns.unsigned.
+ns.unsigned. 172800 IN A 10.53.0.5
diff --git a/bin/tests/system/redirect/setup.sh b/bin/tests/system/redirect/setup.sh
new file mode 100644
index 0000000..d182469
--- /dev/null
+++ b/bin/tests/system/redirect/setup.sh
@@ -0,0 +1,29 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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
+
+cp ns2/redirect.db.in ns2/redirect.db
+cp ns2/example.db.in ns2/example.db
+( cd ns1 && $SHELL sign.sh )
+
+cp ns4/example.db.in ns4/example.db
+( cd ns3 && $SHELL sign.sh )
+( cd ns5 && $SHELL sign.sh )
diff --git a/bin/tests/system/redirect/tests.sh b/bin/tests/system/redirect/tests.sh
new file mode 100644
index 0000000..83b90ad
--- /dev/null
+++ b/bin/tests/system/redirect/tests.sh
@@ -0,0 +1,549 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=1
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+for conf in conf/good*.conf
+do
+ echo_i "checking that $conf is accepted ($n)"
+ ret=0
+ $CHECKCONF "$conf" || ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+for conf in conf/bad*.conf
+do
+ echo_i "checking that $conf is rejected ($n)"
+ ret=0
+ $CHECKCONF "$conf" >/dev/null && ret=1
+ n=$((n + 1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+echo_i "checking A zone redirect works for nonexist ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A zone redirect updates statistics ($n)"
+ret=0
+rm -f ns2/named.stats 2>/dev/null
+$RNDCCMD 10.53.0.2 stats || ret=1
+PRE=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected$/\1/p" ns2/named.stats)
+$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 a > dig.out.ns2.test$n || ret=1
+rm -f ns2/named.stats 2>/dev/null
+$RNDCCMD 10.53.0.2 stats || ret=1
+POST=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected$/\1/p" ns2/named.stats)
+if [ $((POST - PRE)) != 1 ]; then ret=1; fi
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA zone redirect works for nonexist ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY zone redirect works for nonexist ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 any > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A zone redirect doesn't work for acl miss ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.4 a > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns2.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA zone redirect doesn't work for acl miss ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.4 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY zone redirect doesn't work for acl miss ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.4 any > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns2.test$n > /dev/null && ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A zone redirect works for signed nonexist, DO=0 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. @10.53.0.2 -b 10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA zone redirect works for signed nonexist, DO=0 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY zone redirect works for signed nonexist, DO=0 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. @10.53.0.2 -b 10.53.0.2 any > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A zone redirect fails for signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.2 -b 10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns2.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA zone redirect fails for signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY zone redirect fails for signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.2 -b 10.53.0.2 any > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns2.test$n > /dev/null && ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A zone redirect fails for nsec3 signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.2 -b 10.53.0.2 a > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns2.test$n > /dev/null && ret=1
+grep "IN.NSEC3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA zone redirect fails for nsec3 signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n > /dev/null && ret=1
+grep "IN.NSEC3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY zone redirect fails for nsec3 signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.2 -b 10.53.0.2 any > dig.out.ns2.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns2.test$n > /dev/null && ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n > /dev/null && ret=1
+grep "IN.NSEC3" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A zone redirect works for nonexist authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.1 a > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "100.100.100.2" dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA zone redirect works for nonexist authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY zone redirect works for nonexist authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.1 any > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "100.100.100.2" dig.out.ns1.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A zone redirect doesn't work for acl miss authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.4 a > dig.out.ns1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+grep "100.100.100.2" dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA zone redirect doesn't work for acl miss authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.4 aaaa > dig.out.ns1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY zone redirect doesn't work for acl miss authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.4 any > dig.out.ns1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+grep "100.100.100.2" dig.out.ns1.test$n > /dev/null && ret=1
+grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A zone redirect works for signed nonexist, DO=0 authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. @10.53.0.1 -b 10.53.0.1 a > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "100.100.100.2" dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA zone redirect works for signed nonexist, DO=0 authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY zone redirect works for signed nonexist, DO=0 authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. @10.53.0.1 -b 10.53.0.1 any > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "100.100.100.2" dig.out.ns1.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A zone redirect fails for signed nonexist, DO=1 authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.1 -b 10.53.0.1 a > dig.out.ns1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+grep "100.100.100.2" dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA zone redirect fails for signed nonexist, DO=1 authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY zone redirect fails for signed nonexist, DO=1 authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.1 -b 10.53.0.1 any > dig.out.ns1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+grep "100.100.100.2" dig.out.ns1.test$n > /dev/null && ret=1
+grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A zone redirect fails for nsec3 signed nonexist, DO=1 authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.1 -b 10.53.0.1 a > dig.out.ns1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+grep "100.100.100.2" dig.out.ns1.test$n > /dev/null && ret=1
+grep "IN.NSEC3" dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA zone redirect fails for nsec3 signed nonexist, DO=1 authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n > /dev/null && ret=1
+grep "IN.NSEC3" dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY zone redirect fails for nsec3 signed nonexist, DO=1 authoritative ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.1 -b 10.53.0.1 any > dig.out.ns1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+grep "100.100.100.2" dig.out.ns1.test$n > /dev/null && ret=1
+grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n > /dev/null && ret=1
+grep "IN.NSEC3" dig.out.ns1.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking zone redirect works (with noerror) when qtype is not found ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that redirect zones reload correctly"
+ret=0
+sleep 1 # ensure file mtime will have changed
+cat ns2/example.db.in | sed -e 's/0 0 0 0 0/1 0 0 0 0/' > ns2/example.db
+cat ns2/redirect.db.in | sed -e 's/0 0 0 0 0/1 0 0 0 0/' -e 's/\.1$/.2/' > ns2/redirect.db
+rndc_reload ns2 10.53.0.2
+for i in 1 2 3 4 5 6 7 8 9; do
+ tmp=0
+ $DIG $DIGOPTS +short @10.53.0.2 soa example.nil > dig.out.ns1.test$n || tmp=1
+ set -- $(cat dig.out.ns1.test$n)
+ [ $3 = 1 ] || tmp=1
+ $DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 a > dig.out.ns2.test$n || tmp=1
+ grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || tmp=1
+ grep "100.100.100.2" dig.out.ns2.test$n > /dev/null || tmp=1
+ [ $tmp -eq 0 ] && break
+ sleep 1
+done
+[ $tmp -eq 1 ] && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A nxdomain-redirect works for nonexist ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.4 -b 10.53.0.2 a > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "nonexist. .*100.100.100.1" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA nxdomain-redirect works for nonexist ($n)"
+ret=0
+rm -f ns4/named.stats 2>/dev/null
+$RNDCCMD 10.53.0.4 stats || ret=1
+PRE_RED=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected$/\1/p" ns4/named.stats)
+PRE_SUC=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected and resulted in a successful remote lookup$/\1/p" ns4/named.stats)
+$DIG $DIGOPTS nonexist. @10.53.0.4 -b 10.53.0.2 aaaa > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "nonexist. .*2001:ffff:ffff::6464:6401" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA nxdomain-redirect updates statistics ($n)"
+ret=0
+rm -f ns4/named.stats 2>/dev/null
+$RNDCCMD 10.53.0.4 stats || ret=1
+POST_RED=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected$/\1/p" ns4/named.stats)
+POST_SUC=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected and resulted in a successful remote lookup$/\1/p" ns4/named.stats)
+if [ $((POST_RED - PRE_RED)) != 1 ]; then ret=1; fi
+if [ $((POST_SUC - PRE_SUC)) != 1 ]; then ret=1; fi
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY nxdomain-redirect works for nonexist ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.4 -b 10.53.0.2 any > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns4.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A nxdomain-redirect works for signed nonexist, DO=0 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. @10.53.0.4 -b 10.53.0.2 a > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA nxdomain-redirect works for signed nonexist, DO=0 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. @10.53.0.4 -b 10.53.0.2 aaaa > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY nxdomain-redirect works for signed nonexist, DO=0 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. @10.53.0.4 -b 10.53.0.2 any > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns4.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A nxdomain-redirect fails for signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.4 -b 10.53.0.2 a > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA nxdomain-redirect fails for signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.4 -b 10.53.0.2 aaaa > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY nxdomain-redirect fails for signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.4 -b 10.53.0.2 any > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns4.test$n > /dev/null && ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking A nxdomain-redirect fails for nsec3 signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.4 -b 10.53.0.2 a > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns4.test$n > /dev/null && ret=1
+grep "IN.NSEC3" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking AAAA nxdomain-redirect fails for nsec3 signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.4 -b 10.53.0.2 aaaa > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n > /dev/null && ret=1
+grep "IN.NSEC3" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking ANY nxdomain-redirect fails for nsec3 signed nonexist, DO=1 ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.4 -b 10.53.0.2 any > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "100.100.100.1" dig.out.ns4.test$n > /dev/null && ret=1
+grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n > /dev/null && ret=1
+grep "IN.NSEC3" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking nxdomain-redirect works (with noerror) when qtype is not found ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.4 -b 10.53.0.2 txt > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking nxdomain-redirect against authoritative zone ($n)"
+ret=0
+$DIG $DIGOPTS nonexist.example @10.53.0.4 -b 10.53.0.2 a > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking tld nxdomain-redirect against signed root zone ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.5 asdfasdfasdf > dig.out.ns5.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns5.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking tld nxdomain-redirect against unsigned root zone ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.6 asdfasdfasdf > dig.out.ns6.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns6.test$n > /dev/null || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking extended error is not set on allow-recursion ($n)"
+ret=0
+$DIG $DIGOPTS example. @10.53.0.1 -b 10.53.0.2 soa > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "EDE" dig.out.ns1.test$n > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/redirect/tests_sh_redirect.py b/bin/tests/system/redirect/tests_sh_redirect.py
new file mode 100644
index 0000000..9009391
--- /dev/null
+++ b/bin/tests/system/redirect/tests_sh_redirect.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_redirect(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/resolve.c b/bin/tests/system/resolve.c
new file mode 100644
index 0000000..3142757
--- /dev/null
+++ b/bin/tests/system/resolve.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/attributes.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/managers.h>
+#include <isc/mem.h>
+#include <isc/netmgr.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/client.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+#include <irs/resconf.h>
+
+/*
+ * Global contexts
+ */
+
+isc_mem_t *ctxs_mctx = NULL;
+isc_appctx_t *ctxs_actx = NULL;
+isc_nm_t *ctxs_netmgr = NULL;
+isc_taskmgr_t *ctxs_taskmgr = NULL;
+isc_timermgr_t *ctxs_timermgr = NULL;
+
+static void
+ctxs_destroy(void) {
+ isc_managers_destroy(&ctxs_netmgr, &ctxs_taskmgr, &ctxs_timermgr);
+
+ if (ctxs_actx != NULL) {
+ isc_appctx_destroy(&ctxs_actx);
+ }
+
+ if (ctxs_mctx != NULL) {
+ isc_mem_destroy(&ctxs_mctx);
+ }
+}
+
+static isc_result_t
+ctxs_init(void) {
+ isc_result_t result;
+
+ isc_mem_create(&ctxs_mctx);
+
+ result = isc_appctx_create(ctxs_mctx, &ctxs_actx);
+ if (result != ISC_R_SUCCESS) {
+ goto fail;
+ }
+
+ isc_managers_create(ctxs_mctx, 1, 0, &ctxs_netmgr, &ctxs_taskmgr,
+ &ctxs_timermgr);
+
+ result = isc_app_ctxstart(ctxs_actx);
+ if (result != ISC_R_SUCCESS) {
+ goto fail;
+ }
+
+ return (ISC_R_SUCCESS);
+
+fail:
+ ctxs_destroy();
+
+ return (result);
+}
+
+static char *algname = NULL;
+
+static isc_result_t
+printdata(dns_rdataset_t *rdataset, dns_name_t *owner) {
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_region_t r;
+ char t[4096];
+
+ if (!dns_rdataset_isassociated(rdataset)) {
+ printf("[WARN: empty]\n");
+ return (ISC_R_SUCCESS);
+ }
+
+ isc_buffer_init(&target, t, sizeof(t));
+
+ result = dns_rdataset_totext(rdataset, owner, false, false, &target);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ isc_buffer_usedregion(&target, &r);
+ printf("%.*s", (int)r.length, (char *)r.base);
+
+ return (ISC_R_SUCCESS);
+}
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "resolve [-t RRtype] "
+ "[[-a algorithm] [-e] -k keyname -K keystring] "
+ "[-S domain:serveraddr_for_domain ] [-s server_address]"
+ "[-b address[#port]] hostname\n");
+
+ exit(1);
+}
+
+static void
+set_key(dns_client_t *client, char *keynamestr, char *keystr, bool is_sep) {
+ isc_result_t result;
+ dns_fixedname_t fkeyname;
+ unsigned int namelen;
+ dns_name_t *keyname;
+ dns_rdata_dnskey_t keystruct;
+ unsigned char keydata[4096];
+ isc_buffer_t keydatabuf;
+ unsigned char rrdata[4096];
+ isc_buffer_t rrdatabuf;
+ isc_buffer_t b;
+ isc_textregion_t tr;
+ isc_region_t r;
+ dns_secalg_t alg;
+
+ if (algname != NULL) {
+ tr.base = algname;
+ tr.length = strlen(algname);
+ result = dns_secalg_fromtext(&alg, &tr);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to identify the algorithm\n");
+ exit(1);
+ }
+ } else {
+ alg = DNS_KEYALG_RSASHA1;
+ }
+
+ keystruct.common.rdclass = dns_rdataclass_in;
+ keystruct.common.rdtype = dns_rdatatype_dnskey;
+ keystruct.flags = DNS_KEYOWNER_ZONE; /* fixed */
+ if (is_sep) {
+ keystruct.flags |= DNS_KEYFLAG_KSK;
+ }
+ keystruct.protocol = DNS_KEYPROTO_DNSSEC; /* fixed */
+ keystruct.algorithm = alg;
+
+ isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
+ isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
+ result = isc_base64_decodestring(keystr, &keydatabuf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "base64 decode failed\n");
+ exit(1);
+ }
+ isc_buffer_usedregion(&keydatabuf, &r);
+ keystruct.datalen = r.length;
+ keystruct.data = r.base;
+
+ result = dns_rdata_fromstruct(NULL, keystruct.common.rdclass,
+ keystruct.common.rdtype, &keystruct,
+ &rrdatabuf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to construct key rdata\n");
+ exit(1);
+ }
+ namelen = strlen(keynamestr);
+ isc_buffer_init(&b, keynamestr, namelen);
+ isc_buffer_add(&b, namelen);
+ keyname = dns_fixedname_initname(&fkeyname);
+ result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to construct key name\n");
+ exit(1);
+ }
+ result = dns_client_addtrustedkey(client, dns_rdataclass_in,
+ dns_rdatatype_dnskey, keyname,
+ &rrdatabuf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to add key for %s\n", keynamestr);
+ exit(1);
+ }
+}
+
+static void
+addserver(dns_client_t *client, const char *addrstr, const char *port,
+ const char *name_space) {
+ struct addrinfo hints, *res;
+ int gaierror;
+ isc_sockaddr_t sa;
+ isc_sockaddrlist_t servers;
+ isc_result_t result;
+ isc_buffer_t b;
+ dns_fixedname_t fname;
+ dns_name_t *name = NULL;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_flags = AI_NUMERICHOST;
+ gaierror = getaddrinfo(addrstr, port, &hints, &res);
+ if (gaierror != 0) {
+ fprintf(stderr, "getaddrinfo failed: %s\n",
+ gai_strerror(gaierror));
+ exit(1);
+ }
+ INSIST(res->ai_addrlen <= sizeof(sa.type));
+ memmove(&sa.type, res->ai_addr, res->ai_addrlen);
+ sa.length = (unsigned int)res->ai_addrlen;
+ freeaddrinfo(res);
+ ISC_LINK_INIT(&sa, link);
+ ISC_LIST_INIT(servers);
+ ISC_LIST_APPEND(servers, &sa, link);
+
+ if (name_space != NULL) {
+ unsigned int namelen = strlen(name_space);
+ isc_buffer_constinit(&b, name_space, namelen);
+ isc_buffer_add(&b, namelen);
+ name = dns_fixedname_initname(&fname);
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to convert qname: %u\n",
+ result);
+ exit(1);
+ }
+ }
+
+ result = dns_client_setservers(client, dns_rdataclass_in, name,
+ &servers);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "set server failed: %u\n", result);
+ exit(1);
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ int ch;
+ isc_textregion_t tr;
+ char *server = NULL;
+ char *altserver = NULL;
+ char *altserveraddr = NULL;
+ char *altservername = NULL;
+ dns_client_t *client = NULL;
+ char *keynamestr = NULL;
+ char *keystr = NULL;
+ isc_result_t result;
+ isc_buffer_t b;
+ dns_fixedname_t qname0;
+ unsigned int namelen;
+ dns_name_t *qname = NULL, *name = NULL;
+ dns_rdatatype_t type = dns_rdatatype_a;
+ dns_rdataset_t *rdataset = NULL;
+ dns_namelist_t namelist;
+ unsigned int clientopt, resopt = 0;
+ bool is_sep = false;
+ const char *port = "53";
+ struct in_addr in4;
+ struct in6_addr in6;
+ isc_sockaddr_t a4, a6;
+ isc_sockaddr_t *addr4 = NULL, *addr6 = NULL;
+
+ while ((ch = isc_commandline_parse(argc, argv, "a:b:es:t:k:K:p:S:")) !=
+ -1)
+ {
+ switch (ch) {
+ case 't':
+ tr.base = isc_commandline_argument;
+ tr.length = strlen(isc_commandline_argument);
+ result = dns_rdatatype_fromtext(&type, &tr);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "invalid RRtype: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+ case 'a':
+ algname = isc_commandline_argument;
+ break;
+ case 'b':
+ if (inet_pton(AF_INET, isc_commandline_argument,
+ &in4) == 1)
+ {
+ if (addr4 != NULL) {
+ fprintf(stderr, "only one local "
+ "address per family "
+ "can be specified\n");
+ exit(1);
+ }
+ isc_sockaddr_fromin(&a4, &in4, 0);
+ addr4 = &a4;
+ } else if (inet_pton(AF_INET6, isc_commandline_argument,
+ &in6) == 1)
+ {
+ if (addr6 != NULL) {
+ fprintf(stderr, "only one local "
+ "address per family "
+ "can be specified\n");
+ exit(1);
+ }
+ isc_sockaddr_fromin6(&a6, &in6, 0);
+ addr6 = &a6;
+ } else {
+ fprintf(stderr, "invalid address %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+ case 'e':
+ is_sep = true;
+ break;
+ case 'S':
+ if (altserver != NULL) {
+ fprintf(stderr,
+ "alternate server "
+ "already defined: %s\n",
+ altserver);
+ exit(1);
+ }
+ altserver = isc_commandline_argument;
+ break;
+ case 's':
+ if (server != NULL) {
+ fprintf(stderr,
+ "server "
+ "already defined: %s\n",
+ server);
+ exit(1);
+ }
+ server = isc_commandline_argument;
+ break;
+ case 'k':
+ keynamestr = isc_commandline_argument;
+ break;
+ case 'K':
+ keystr = isc_commandline_argument;
+ break;
+ case 'p':
+ port = isc_commandline_argument;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+ if (argc < 1) {
+ usage();
+ }
+
+ if (altserver != NULL) {
+ char *cp;
+
+ cp = strchr(altserver, ':');
+ if (cp == NULL) {
+ fprintf(stderr, "invalid alternate server: %s\n",
+ altserver);
+ exit(1);
+ }
+ *cp = '\0';
+ altservername = altserver;
+ altserveraddr = cp + 1;
+ }
+
+ result = ctxs_init();
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ result = dst_lib_init(ctxs_mctx, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dst_lib_init failed: %u\n", result);
+ exit(1);
+ }
+
+ clientopt = 0;
+ result = dns_client_create(ctxs_mctx, ctxs_actx, ctxs_taskmgr,
+ ctxs_netmgr, ctxs_timermgr, clientopt,
+ &client, addr4, addr6);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dns_client_create failed: %u, %s\n", result,
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ /* Set the nameserver */
+ if (server == NULL) {
+ irs_resconf_t *resconf = NULL;
+ isc_sockaddrlist_t *nameservers;
+
+ result = irs_resconf_load(ctxs_mctx, "/etc/resolv.conf",
+ &resconf);
+ if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
+ fprintf(stderr, "irs_resconf_load failed: %u\n",
+ result);
+ exit(1);
+ }
+ nameservers = irs_resconf_getnameservers(resconf);
+ result = dns_client_setservers(client, dns_rdataclass_in, NULL,
+ nameservers);
+ if (result != ISC_R_SUCCESS) {
+ irs_resconf_destroy(&resconf);
+ fprintf(stderr, "dns_client_setservers failed: %u\n",
+ result);
+ exit(1);
+ }
+ irs_resconf_destroy(&resconf);
+ } else {
+ addserver(client, server, port, NULL);
+ }
+
+ /* Set the alternate nameserver (when specified) */
+ if (altserver != NULL) {
+ addserver(client, altserveraddr, port, altservername);
+ }
+
+ /* Install DNSSEC key (if given) */
+ if (keynamestr != NULL) {
+ if (keystr == NULL) {
+ fprintf(stderr, "key string is missing "
+ "while key name is provided\n");
+ exit(1);
+ }
+ set_key(client, keynamestr, keystr, is_sep);
+ }
+
+ /* Construct qname */
+ namelen = strlen(argv[0]);
+ isc_buffer_init(&b, argv[0], namelen);
+ isc_buffer_add(&b, namelen);
+ qname = dns_fixedname_initname(&qname0);
+ result = dns_name_fromtext(qname, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to convert qname: %u\n", result);
+ }
+
+ /* Perform resolution */
+ if (keynamestr == NULL) {
+ resopt |= DNS_CLIENTRESOPT_NODNSSEC;
+ }
+ ISC_LIST_INIT(namelist);
+ result = dns_client_resolve(client, qname, dns_rdataclass_in, type,
+ resopt, &namelist);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "resolution failed: %s\n",
+ isc_result_totext(result));
+ }
+ for (name = ISC_LIST_HEAD(namelist); name != NULL;
+ name = ISC_LIST_NEXT(name, link))
+ {
+ for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (printdata(rdataset, name) != ISC_R_SUCCESS) {
+ fprintf(stderr, "print data failed\n");
+ }
+ }
+ }
+
+ dns_client_freeresanswer(client, &namelist);
+
+ /* Cleanup */
+cleanup:
+ if (client != NULL) {
+ dns_client_detach(&client);
+ }
+
+ ctxs_destroy();
+ dst_lib_destroy();
+
+ return (0);
+}
diff --git a/bin/tests/system/resolver/ans10/ans.py b/bin/tests/system/resolver/ans10/ans.py
new file mode 100644
index 0000000..6e95dbb
--- /dev/null
+++ b/bin/tests/system/resolver/ans10/ans.py
@@ -0,0 +1,152 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from __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, dns.flags
+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.
+# If there are EDNS options present return FORMERR copying the OPT record.
+# Otherwise:
+# SOA gets a unsigned response.
+# NS gets a unsigned response.
+# A gets a unsigned response.
+# All other types get a unsigned NODATA response.
+############################################################################
+def create_response(msg):
+ m = dns.message.from_wire(msg)
+ qname = m.question[0].name.to_text()
+ rrtype = m.question[0].rdtype
+ typename = dns.rdatatype.to_text(rrtype)
+
+ with open("query.log", "a") as f:
+ f.write("%s %s\n" % (typename, qname))
+ print("%s %s" % (typename, qname), end=" ")
+
+ if m.edns != -1 and len(m.options) != 0:
+ r = dns.message.make_response(m)
+ r.use_edns(
+ edns=m.edns, ednsflags=m.ednsflags, payload=m.payload, options=m.options
+ )
+ r.set_rcode(FORMERR)
+ else:
+ r = dns.message.make_response(m)
+ r.set_rcode(NOERROR)
+ if rrtype == A:
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10"))
+ elif rrtype == NS:
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, NS, "."))
+ elif rrtype == SOA:
+ r.answer.append(dns.rrset.from_text(qname, 1, IN, SOA, ". . 0 0 0 0 0"))
+ else:
+ r.authority.append(dns.rrset.from_text(qname, 1, IN, SOA, ". . 0 0 0 0 0"))
+ r.flags |= dns.flags.AA
+ 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.10"
+ip6 = "fd92:7065:b8e:ffff::10"
+
+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/resolver/ans2/ans.pl b/bin/tests/system/resolver/ans2/ans.pl
new file mode 100644
index 0000000..aa1d51b
--- /dev/null
+++ b/bin/tests/system/resolver/ans2/ans.pl
@@ -0,0 +1,147 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Ad hoc name server
+#
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.2",
+ LocalPort => $localport, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+for (;;) {
+ $sock->recv($buf, 512);
+
+ print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
+
+ my $packet;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ print "REQUEST:\n";
+ $packet->print;
+
+ $packet->header->qr(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+
+ 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"));
+ } elsif ($qname eq "cname2.example.com") {
+ # 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 =~ /redirect\.com/) {
+ $packet->push("authority", new Net::DNS::RR("redirect.com 300 NS ns.redirect.com"));
+ $packet->push("additional", new Net::DNS::RR("ns.redirect.com 300 A 10.53.0.6"));
+ } elsif ($qname =~ /\.tld1/) {
+ $packet->push("authority", new Net::DNS::RR("tld1 300 NS ns.tld1"));
+ $packet->push("additional", new Net::DNS::RR("ns.tld1 300 A 10.53.0.6"));
+ } elsif ($qname =~ /\.tld2/) {
+ $packet->push("authority", new Net::DNS::RR("tld2 300 NS ns.tld2"));
+ $packet->push("additional", new Net::DNS::RR("ns.tld2 300 A 10.53.0.7"));
+ } 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 "badcname.example.org" ||
+ $qname eq "goodcname.example.org" ||
+ $qname eq "foo.baddname.example.org" ||
+ $qname eq "foo.gooddname.example.org") {
+ # Data for address/alias filtering.
+ $packet->header->aa(1);
+ if ($qtype eq "A") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 300 A 192.0.2.1"));
+ } elsif ($qtype eq "AAAA") {
+ $packet->push("answer",
+ 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 =~ /example\.net/) {
+ $packet->push("authority", new Net::DNS::RR("example.net 300 NS ns.example.net"));
+ $packet->push("additional", new Net::DNS::RR("ns.example.net 300 A 10.53.0.3"));
+ } elsif ($qname =~ /lame\.example\.org/) {
+ $packet->header->ad(0);
+ $packet->header->aa(0);
+ $packet->push("authority", new Net::DNS::RR("lame.example.org 300 NS ns.lame.example.org"));
+ $packet->push("additional", new Net::DNS::RR("ns.lame.example.org 300 A 10.53.0.3"));
+ } elsif ($qname =~ /sub\.example\.org/) {
+ # Data for CNAME/DNAME filtering. The final answers are
+ # 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 =~ /glue-in-answer\.example\.org/) {
+ $packet->push("answer", new Net::DNS::RR("ns.glue-in-answer.example.org 300 A 10.53.0.3"));
+ $packet->push("authority", new Net::DNS::RR("glue-in-answer.example.org 300 NS ns.glue-in-answer.example.org"));
+ $packet->push("additional", new Net::DNS::RR("ns.glue-in-answer.example.org 300 A 10.53.0.3"));
+ } 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"));
+ } elsif ($qname =~ /\.partial-formerr/) {
+ $packet->header->rcode("FORMERR");
+ } else {
+ # Data for the "bogus referrals" test
+ $packet->push("authority", new Net::DNS::RR("below.www.example.com 300 NS ns.below.www.example.com"));
+ $packet->push("additional", new Net::DNS::RR("ns.below.www.example.com 300 A 10.53.0.3"));
+ }
+
+ $sock->send($packet->data);
+
+ print "RESPONSE:\n";
+ $packet->print;
+ print "\n";
+}
diff --git a/bin/tests/system/resolver/ans3/ans.pl b/bin/tests/system/resolver/ans3/ans.pl
new file mode 100644
index 0000000..893c9ed
--- /dev/null
+++ b/bin/tests/system/resolver/ans3/ans.pl
@@ -0,0 +1,191 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Ad hoc name server
+#
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early
+local $SIG{PIPE} = 'IGNORE';
+
+# Flush logged output after every line
+local $| = 1;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $server_addr = "10.53.0.3";
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!";
+my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $localport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+sub handleQuery {
+ my $buf = shift;
+ my $packet;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ print "REQUEST:\n";
+ $packet->print;
+
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+
+ if ($qname eq "example.net" && $qtype eq "NS") {
+ $packet->push("answer", new Net::DNS::RR($qname . " 300 NS ns.example.net"));
+ $packet->push("additional", new Net::DNS::RR("ns.example.net 300 A 10.53.0.3"));
+ } elsif ($qname eq "ns.example.net") {
+ $packet->push("answer", new Net::DNS::RR($qname . " 300 A 10.53.0.3"));
+ } elsif ($qname eq "nodata.example.net") {
+ # Do not add a SOA RRset.
+ } elsif ($qname eq "nxdomain.example.net") {
+ # Do not add a SOA RRset.
+ $packet->header->rcode(NXDOMAIN);
+ } elsif ($qname eq "www.example.net") {
+ # Data for address/alias filtering.
+ if ($qtype eq "A") {
+ $packet->push("answer", new Net::DNS::RR($qname . " 300 A 192.0.2.1"));
+ } elsif ($qtype eq "AAAA") {
+ $packet->push("answer", new Net::DNS::RR($qname . " 300 AAAA 2001:db8:beef::1"));
+ }
+ } elsif ($qname eq "badcname.example.net") {
+ $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" .
+ " 300 DNAME baddname.example.org"));
+ } elsif ($qname eq "foo.gooddname.example.net") {
+ $packet->push("answer",
+ new Net::DNS::RR("gooddname.example.net" .
+ " 300 DNAME gooddname.example.org"));
+ } elsif ($qname eq "goodcname.example.net") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 300 CNAME goodcname.example.org"));
+ } elsif ($qname =~ /^nodata\.example\.net$/i) {
+ $packet->header->aa(1);
+ } elsif ($qname =~ /^nxdomain\.example\.net$/i) {
+ $packet->header->aa(1);
+ $packet->header->rcode(NXDOMAIN);
+ } elsif ($qname =~ /lame\.example\.org/) {
+ $packet->header->ad(0);
+ $packet->header->aa(0);
+ $packet->push("authority", new Net::DNS::RR("lame.example.org 300 NS ns.lame.example.org"));
+ $packet->push("additional", new Net::DNS::RR("ns.lame.example.org 300 A 10.53.0.3"));
+ } elsif ($qname eq "large-referral.example.net") {
+ for (my $i = 1; $i < 1000; $i++) {
+ $packet->push("authority", new Net::DNS::RR("large-referral.example.net 300 NS ns" . $i . ".fake.redirect.com"));
+ }
+ # No glue records
+ } elsif ($qname eq "foo.bar.sub.tld1") {
+ $packet->push("answer", new Net::DNS::RR("$qname 300 TXT baz"));
+ } elsif ($qname eq "cname.sub.example.org") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 300 CNAME ok.sub.example.org"));
+ } elsif ($qname eq "ok.sub.example.org") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname . " 300 A 192.0.2.1"));
+ } elsif ($qname eq "www.dname.sub.example.org") {
+ $packet->push("answer",
+ new Net::DNS::RR("dname.sub.example.org" .
+ " 300 DNAME ok.sub.example.org"));
+ } elsif ($qname eq "www.ok.sub.example.org") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname . " 300 A 192.0.2.1"));
+ } elsif ($qname eq "foo.glue-in-answer.example.org") {
+ $packet->push("answer", new Net::DNS::RR($qname . " 300 A 192.0.2.1"));
+ } elsif ($qname eq "ns.example.net") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 300 A 10.53.0.3"));
+ } elsif ($qname =~ /\.partial-formerr/) {
+ $packet->push("answer",
+ new Net::DNS::RR($qname . " 1 A 10.53.0.3"));
+ } else {
+ $packet->push("answer", new Net::DNS::RR("www.example.com 300 A 1.2.3.4"));
+ }
+
+ print "RESPONSE:\n";
+ $packet->print;
+
+ return $packet->data;
+}
+
+# Main
+my $rin;
+my $rout;
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($tcpsock), 1) = 1;
+ vec($rin, fileno($udpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($udpsock), 1)) {
+ printf "UDP request\n";
+ my $buf;
+ $udpsock->recv($buf, 512);
+ my $result = handleQuery($buf);
+ my $num_chars = $udpsock->send($result);
+ print " Sent $num_chars bytes via UDP\n";
+ } elsif (vec($rout, fileno($tcpsock), 1)) {
+ my $conn = $tcpsock->accept;
+ my $buf;
+ for (;;) {
+ my $lenbuf;
+ my $n = $conn->sysread($lenbuf, 2);
+ last unless $n == 2;
+ my $len = unpack("n", $lenbuf);
+ $n = $conn->sysread($buf, $len);
+ last unless $n == $len;
+ print "TCP request\n";
+ my $result = handleQuery($buf);
+ $len = length($result);
+ $conn->syswrite(pack("n", $len), 2);
+ $n = $conn->syswrite($result, $len);
+ print " Sent: $n chars via TCP\n";
+ }
+ $conn->close;
+ }
+}
diff --git a/bin/tests/system/resolver/ans8/ans.pl b/bin/tests/system/resolver/ans8/ans.pl
new file mode 100644
index 0000000..a3d06b6
--- /dev/null
+++ b/bin/tests/system/resolver/ans8/ans.pl
@@ -0,0 +1,177 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use IO::File;
+use IO::Socket;
+use Data::Dumper;
+use Net::DNS;
+use Net::DNS::Packet;
+use strict;
+
+# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early
+local $SIG{PIPE} = 'IGNORE';
+
+# Flush logged output after every line
+local $| = 1;
+
+my $server_addr = "10.53.0.8";
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!";
+my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $localport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+print "listening on $server_addr:$localport.\n";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";;
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+sub handleUDP {
+ my ($buf) = @_;
+ my $request;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($request, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ my @questions = $request->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+ my $qclass = $questions[0]->qclass;
+ my $id = $request->header->id;
+
+ my $response = new Net::DNS::Packet($qname, $qtype, $qclass);
+ $response->header->qr(1);
+ $response->header->aa(1);
+ $response->header->tc(0);
+ $response->header->id($id);
+
+ # Responses to queries for no-questions/NS and ns.no-questions/A are
+ # _not_ malformed or truncated.
+ if ($qname eq "no-questions" && $qtype eq "NS") {
+ $response->push("answer", new Net::DNS::RR($qname . " 300 NS ns.no-questions"));
+ $response->push("additional", new Net::DNS::RR("ns.no-questions. 300 A 10.53.0.8"));
+ return $response->data;
+ } elsif ($qname eq "ns.no-questions") {
+ $response->push("answer", new Net::DNS::RR($qname . " 300 A 10.53.0.8"))
+ if ($qtype eq "A");
+ return $response->data;
+ } elsif ($qname =~ /\.formerr-to-all$/) {
+ $response->header->rcode("FORMERR");
+ return $response->data;
+ }
+
+ # don't use Net::DNS to construct the header only reply as early
+ # versions just get it completely wrong.
+
+ if ($qname eq "truncated.no-questions") {
+ # QR, AA, TC: forces TCP retry
+ return (pack("nnnnnn", $id, 0x8600, 0, 0, 0, 0));
+ } elsif ($qname eq "tcpalso.no-questions") {
+ # QR, REFUSED: forces TCP retry
+ return (pack("nnnnnn", $id, 0x8205, 0, 0, 0, 0));
+ }
+ # QR, AA
+ return (pack("nnnnnn", $id, 0x8400, 0, 0, 0, 0));
+}
+
+sub handleTCP {
+ my ($buf) = @_;
+ my $request;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($request, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ my @questions = $request->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+ my $qclass = $questions[0]->qclass;
+ my $id = $request->header->id;
+
+ my @results = ();
+ my $response = new Net::DNS::Packet($qname, $qtype, $qclass);
+
+ $response->header->qr(1);
+ $response->header->aa(1);
+ $response->header->id($id);
+ $response->push("answer", new Net::DNS::RR("$qname 300 A 1.2.3.4"));
+
+ if ($qname eq "tcpalso.no-questions") {
+ # for this qname we also return a bad reply over TCP
+ # QR, REFUSED, no question section
+ push (@results, pack("nnnnnn", $id, 0x8005, 0, 0, 0, 0));
+ } else {
+ push(@results, $response->data);
+ }
+
+ return \@results;
+}
+
+# Main
+my $rin;
+my $rout;
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($tcpsock), 1) = 1;
+ vec($rin, fileno($udpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($udpsock), 1)) {
+ printf "UDP request\n";
+ my $buf;
+ $udpsock->recv($buf, 512);
+ my $result = handleUDP($buf);
+ my $num_chars = $udpsock->send($result);
+ print " Sent $num_chars bytes via UDP\n";
+ } elsif (vec($rout, fileno($tcpsock), 1)) {
+ my $conn = $tcpsock->accept;
+ my $buf;
+ for (;;) {
+ my $lenbuf;
+ my $n = $conn->sysread($lenbuf, 2);
+ last unless $n == 2;
+ my $len = unpack("n", $lenbuf);
+ $n = $conn->sysread($buf, $len);
+ last unless $n == $len;
+ print "TCP request\n";
+ my $result = handleTCP($buf);
+ foreach my $response (@$result) {
+ $len = length($response);
+ $n = $conn->syswrite(pack("n", $len), 2);
+ $n = $conn->syswrite($response, $len);
+ print " Sent: $n chars via TCP\n";
+ }
+ }
+ $conn->close;
+ }
+}
diff --git a/bin/tests/system/resolver/clean.sh b/bin/tests/system/resolver/clean.sh
new file mode 100644
index 0000000..d4ff983
--- /dev/null
+++ b/bin/tests/system/resolver/clean.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after resolver tests.
+#
+rm -f ./*/named.conf
+rm -f ./*/named.memstats
+rm -f ./*/named.run ./*/named.run.prev
+rm -f ./*/ans.run
+rm -f ./*/*.jdb
+rm -f dig.out dig.out.* dig.*.out.*
+rm -f dig.*.foo.*
+rm -f dig.*.bar.*
+rm -f dig.*.prime.*
+rm -f nextpart.out.*
+rm -f ns4/tld.db
+rm -f ns6/K*
+rm -f ns6/example.net.db.signed ns6/example.net.db
+rm -f ns6/ds.example.net.db.signed ns6/ds.example.net.db
+rm -f ns6/dsset-ds.example.net*
+rm -f ns6/dsset-example.net* ns6/example.net.db.signed.jnl
+rm -f ns6/named.stats*
+rm -f ns6/to-be-removed.tld.db ns6/to-be-removed.tld.db.jnl
+rm -f ns7/server.db ns7/server.db.jnl
+rm -f resolve.out.*.test*
+rm -f .digrc
+rm -f ns*/named.lock
+rm -f ns5/trusted.conf
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
diff --git a/bin/tests/system/resolver/ns1/chaostest.db b/bin/tests/system/resolver/ns1/chaostest.db
new file mode 100644
index 0000000..153f31d
--- /dev/null
+++ b/bin/tests/system/resolver/ns1/chaostest.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ CHAOS SOA @ @ 1970010100 86400 600 86400 300
+@ CHAOS NS @
+version CHAOS TXT "CH 1.0"
+hostname CHAOS TXT "unknown"
diff --git a/bin/tests/system/resolver/ns1/named.conf.in b/bin/tests/system/resolver/ns1/named.conf.in
new file mode 100644
index 0000000..f0f9571
--- /dev/null
+++ b/bin/tests/system/resolver/ns1/named.conf.in
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; }
+ except-from { "example.org"; };
+ deny-answer-aliases { "example.org"; }
+ except-from { "goodcname.example.net";
+ "gooddname.example.net"; };
+ allow-query {!10.53.0.8; any; };
+ max-zone-ttl unlimited;
+ attach-cache "globalcache";
+};
+
+server 10.53.0.3 {
+ tcp-only yes;
+};
+
+server 10.42.23.3/32 {
+ notify-source 10.42.22.1;
+ query-source address 10.42.22.1 port 0;
+ transfer-source 10.42.22.1;
+};
+
+server fd92:7065:b8e:ffff::1000 {
+ notify-source-v6 fd92:7065:b8e:ffff::1001;
+ query-source-v6 address fd92:7065:b8e:ffff::1001 port 0;
+ transfer-source-v6 fd92:7065:b8e:ffff::1001;
+};
+
+/*
+ * Must be first view so that there is a CH cache with name
+ * "globalcache" before the recursive "default"/IN view is configured.
+ */
+view "class" chaos {
+ zone "chaostest" CHAOS {
+ type primary;
+ file "chaostest.db";
+ };
+};
+
+/*
+ * Must be second view so that so that we can check we don't attach to the
+ * "globalcache"/CH cache.
+ */
+view "default" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/resolver/ns1/root.hint b/bin/tests/system/resolver/ns1/root.hint
new file mode 100644
index 0000000..993227d
--- /dev/null
+++ b/bin/tests/system/resolver/ns1/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.2
diff --git a/bin/tests/system/resolver/ns4/broken.db b/bin/tests/system/resolver/ns4/broken.db
new file mode 100644
index 0000000..eb64f85
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/broken.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns.tld.
+ns A 10.53.0.4
+$TTL 5
+sub.broken. NS ns.sub.broken.
+ns.sub.broken. A 10.53.0.6
diff --git a/bin/tests/system/resolver/ns4/child.server.db b/bin/tests/system/resolver/ns4/child.server.db
new file mode 100644
index 0000000..188eb4a
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/child.server.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns
+ns A 10.53.0.4
+foo TXT "From NS 4"
+bar TXT "From NS 4"
diff --git a/bin/tests/system/resolver/ns4/moves.db b/bin/tests/system/resolver/ns4/moves.db
new file mode 100644
index 0000000..dc1c396
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/moves.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns.server.
+foo TXT "From NS 4"
+bar TXT "From NS 4"
diff --git a/bin/tests/system/resolver/ns4/named.conf.in b/bin/tests/system/resolver/ns4/named.conf.in
new file mode 100644
index 0000000..281c2ca
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/named.conf.in
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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 no;
+ dnssec-validation no;
+ /* test that named loads with root-delegation-only */
+ root-delegation-only;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "moves" {
+ type primary;
+ file "moves.db";
+};
+
+zone "child.server" {
+ type primary;
+ file "child.server.db";
+};
+
+zone "tld" {
+ type primary;
+ file "tld.db";
+};
+
+zone "broken" {
+ type primary;
+ file "broken.db";
+};
+
+zone "sourcens" {
+ type primary;
+ file "sourcens.db";
+};
+
+zone "v4only.net" {
+ type primary;
+ file "v4only.net.db";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/resolver/ns4/named.noaa b/bin/tests/system/resolver/ns4/named.noaa
new file mode 100644
index 0000000..be78cc2
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/named.noaa
@@ -0,0 +1,12 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+Add -T noaa.
diff --git a/bin/tests/system/resolver/ns4/root.db b/bin/tests/system/resolver/ns4/root.db
new file mode 100644
index 0000000..4e4418b
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/root.db
@@ -0,0 +1,39 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA marka.isc.org. a.root.servers.nil. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.4
+all-cnames NS cname.tld
+delegation-only. NS ns.delegation-only.
+ns.delegation-only. A 10.53.0.6
+example.net. NS ns.example.net.
+ns.example.net. A 10.53.0.6
+no-questions. NS ns.no-questions.
+ns.no-questions. A 10.53.0.8
+formerr-to-all. NS ns.formerr-to-all.
+ns.formerr-to-all. A 10.53.0.8
+sourcens. NS ns.sourcens.
+ns.sourcens. A 10.53.0.4
+targetns. NS ns.targetns.
+ns.targetns. A 10.53.0.6
+partial-formerr. NS ns.partial-formerr.
+ns.partial-formerr. A 10.53.0.2
+ns.partial-formerr. A 10.53.0.3
+options-formerr. NS ns.options-formerr.
+ns.options-formerr. A 10.53.0.10
diff --git a/bin/tests/system/resolver/ns4/sourcens.db b/bin/tests/system/resolver/ns4/sourcens.db
new file mode 100644
index 0000000..3567cfb
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/sourcens.db
@@ -0,0 +1,91 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; This zone contains a set of delegations with varying numbers of NS
+; records. This is used to check that BIND is limiting the number of
+; NS records it follows when resolving a delegation. It tests all
+; numbers of NS records up to twice the number followed.
+
+$TTL 60
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns
+ns A 10.53.0.4
+
+target1 NS ns.fake11.targetns.
+
+target2 NS ns.fake21.targetns.
+ NS ns.fake22.targetns.
+
+target3 NS ns.fake31.targetns.
+ NS ns.fake32.targetns.
+ NS ns.fake33.targetns.
+
+target4 NS ns.fake41.targetns.
+ NS ns.fake42.targetns.
+ NS ns.fake43.targetns.
+ NS ns.fake44.targetns.
+
+target5 NS ns.fake51.targetns.
+ NS ns.fake52.targetns.
+ NS ns.fake53.targetns.
+ NS ns.fake54.targetns.
+ NS ns.fake55.targetns.
+
+target6 NS ns.fake61.targetns.
+ NS ns.fake62.targetns.
+ NS ns.fake63.targetns.
+ NS ns.fake64.targetns.
+ NS ns.fake65.targetns.
+ NS ns.fake66.targetns.
+
+target7 NS ns.fake71.targetns.
+ NS ns.fake72.targetns.
+ NS ns.fake73.targetns.
+ NS ns.fake74.targetns.
+ NS ns.fake75.targetns.
+ NS ns.fake76.targetns.
+ NS ns.fake77.targetns.
+
+target8 NS ns.fake81.targetns.
+ NS ns.fake82.targetns.
+ NS ns.fake83.targetns.
+ NS ns.fake84.targetns.
+ NS ns.fake85.targetns.
+ NS ns.fake86.targetns.
+ NS ns.fake87.targetns.
+ NS ns.fake88.targetns.
+
+target9 NS ns.fake91.targetns.
+ NS ns.fake92.targetns.
+ NS ns.fake93.targetns.
+ NS ns.fake94.targetns.
+ NS ns.fake95.targetns.
+ NS ns.fake96.targetns.
+ NS ns.fake97.targetns.
+ NS ns.fake98.targetns.
+ NS ns.fake99.targetns.
+
+target10 NS ns.fake101.targetns.
+ NS ns.fake102.targetns.
+ NS ns.fake103.targetns.
+ NS ns.fake104.targetns.
+ NS ns.fake105.targetns.
+ NS ns.fake106.targetns.
+ NS ns.fake107.targetns.
+ NS ns.fake108.targetns.
+ NS ns.fake109.targetns.
+ NS ns.fake1010.targetns.
diff --git a/bin/tests/system/resolver/ns4/tld1.db b/bin/tests/system/resolver/ns4/tld1.db
new file mode 100644
index 0000000..03d7908
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/tld1.db
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns.tld.
+ns A 10.53.0.4
+$TTL 5
+to-be-removed NS ns.to-be-removed
+ns.to-be-removed A 10.53.0.6
+fetch.tld. NS ns.fetch.tld.
+ns.fetch.tld. A 10.53.0.6
+no-edns-version.tld. NS ns.no-edns-version.tld.
+ns.no-edns-version.tld. A 10.53.0.6
+edns-version.tld. NS ns.edns-version.tld.
+ns.edns-version.tld. A 10.53.0.7
+cname CNAME ns7
+ns7 A 10.53.0.7
+mixedttl 10 A 10.0.0.1
+mixedttl 15 TXT a TXT record
+mixedttl 20 AAAA 2001:db8::1
diff --git a/bin/tests/system/resolver/ns4/tld2.db b/bin/tests/system/resolver/ns4/tld2.db
new file mode 100644
index 0000000..c3a96d9
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/tld2.db
@@ -0,0 +1,35 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns.tld.
+ns A 10.53.0.4
+fetch.tld. NS ns.fetch.tld.
+ns.fetch.tld. A 10.53.0.6
+fetchall 10 A 1.2.3.4
+fetchall 10 AAAA ::1
+fetchall 10 TXT A short ttl
+no-edns-version.tld. NS ns.no-edns-version.tld.
+ns.no-edns-version.tld. A 10.53.0.6
+edns-version.tld. NS ns.edns-version.tld.
+ns.edns-version.tld. A 10.53.0.7
+cname CNAME ns7
+ns7 A 10.53.0.7
+mixedttl 10 A 10.0.0.1
+mixedttl 15 TXT a TXT record
+mixedttl 20 AAAA 2001:db8::1
diff --git a/bin/tests/system/resolver/ns4/v4only.net.db b/bin/tests/system/resolver/ns4/v4only.net.db
new file mode 100644
index 0000000..b097f3a
--- /dev/null
+++ b/bin/tests/system/resolver/ns4/v4only.net.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS v4.nameserver.
+ A 10.0.0.1
+* CNAME @
diff --git a/bin/tests/system/resolver/ns5/child.server.db b/bin/tests/system/resolver/ns5/child.server.db
new file mode 100644
index 0000000..2517b6c
--- /dev/null
+++ b/bin/tests/system/resolver/ns5/child.server.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns
+ns A 10.53.0.5
+foo TXT "From NS 5"
+bar TXT "From NS 5"
diff --git a/bin/tests/system/resolver/ns5/moves.db b/bin/tests/system/resolver/ns5/moves.db
new file mode 100644
index 0000000..57f4e91
--- /dev/null
+++ b/bin/tests/system/resolver/ns5/moves.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns.server.
+foo TXT "From NS 5"
+bar TXT "From NS 5"
diff --git a/bin/tests/system/resolver/ns5/named.conf.in b/bin/tests/system/resolver/ns5/named.conf.in
new file mode 100644
index 0000000..6ad4e6a
--- /dev/null
+++ b/bin/tests/system/resolver/ns5/named.conf.in
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+ querylog yes;
+ prefetch 4 10;
+};
+
+server 10.53.0.7 {
+ edns-version 0;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "moves" {
+ type primary;
+ file "moves.db";
+};
+
+zone "child.server" {
+ type primary;
+ file "child.server.db";
+};
+
+zone "delegation-only" {
+ type delegation-only;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/resolver/ns5/root.hint b/bin/tests/system/resolver/ns5/root.hint
new file mode 100644
index 0000000..3685f54
--- /dev/null
+++ b/bin/tests/system/resolver/ns5/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.4
diff --git a/bin/tests/system/resolver/ns6/broken.db b/bin/tests/system/resolver/ns6/broken.db
new file mode 100644
index 0000000..85b36bf
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/broken.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+@ IN NS ns
+ns IN A 10.53.0.6
+ns0 IN A 10.53.0.6
+ns1 IN A 10.53.0.6
+ns2 IN A 10.53.0.6
+ns3 IN A 10.53.0.6
+ns4 IN A 10.53.0.6
+ns5 IN A 10.53.0.6
+ns6 IN A 10.53.0.6
+ns7 IN A 10.53.0.6
+ns8 IN A 10.53.0.6
+ns9 IN A 10.53.0.6
+$TTL 1
+@ IN A 10.53.0.6
+www.sub IN A 10.53.0.6
diff --git a/bin/tests/system/resolver/ns6/delegation-only.db b/bin/tests/system/resolver/ns6/delegation-only.db
new file mode 100644
index 0000000..b144338
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/delegation-only.db
@@ -0,0 +1,33 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ IN SOA ns marka.isc.org. 1 0 0 0 120
+@ IN NS ns
+@ IN DNSKEY 256 3 7 AwEAAY9437GPWJHzBeR4FP6eJAie7gh2QSM6LUnbDAHvHOx8MNqgSVRM PZka2rAgivb65/MkT1lXRUegj91iRFP3iggTpCgvdUbcBjsYrdODsrwF YUMIUl1pU0lH9x7KvfFUOfSmG+Rk5UHUWuRZbNyc65Sq69iFXg5c11+8 MAkRoeDF
+;
+; Delegation only test CDS and CDNSKEY records. These should be
+; returned even if delegation-only is set for this zone.
+;
+@ IN A 1.2.3.4
+@ IN AAAA c::1.2.3.4
+@ IN CDS 12023 7 2 36FB69A752615831B47EA6EF9EA4619D0FB08ABDA69EA3ED200F4C02FF4921D4
+@ IN CDNSKEY 256 3 7 AwEAAY9437GPWJHzBeR4FP6eJAie7gh2QSM6LUnbDAHvHOx8MNqgSVRM PZka2rAgivb65/MkT1lXRUegj91iRFP3iggTpCgvdUbcBjsYrdODsrwF YUMIUl1pU0lH9x7KvfFUOfSmG+Rk5UHUWuRZbNyc65Sq69iFXg5c11+8 MAkRoeDF
+;
+; Delegation only test CDS and CDNSKEY records. These should be rejected
+; as they are not at the zone apex.
+;
+a IN A 1.2.3.4
+aaaa IN AAAA c::1.2.3.4
+cds IN CDS 21366 7 1 E6C1716CFB6BDC84E84CE1AB5510DAC69173B5B2
+cdnskey IN CDNSKEY 256 3 7 AwEAAY9437GPWJHzBeR4FP6eJAie7gh2QSM6LUnbDAHvHOx8MNqgSVRM PZka2rAgivb65/MkT1lXRUegj91iRFP3iggTpCgvdUbcBjsYrdODsrwF YUMIUl1pU0lH9x7KvfFUOfSmG+Rk5UHUWuRZbNyc65Sq69iFXg5c11+8 MAkRoeDF
+;
+ns IN A 10.53.0.6
diff --git a/bin/tests/system/resolver/ns6/ds.example.net.db.in b/bin/tests/system/resolver/ns6/ds.example.net.db.in
new file mode 100644
index 0000000..fad382b
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/ds.example.net.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+@ IN NS ns
+ns IN A 10.53.0.6
diff --git a/bin/tests/system/resolver/ns6/example.net.db.in b/bin/tests/system/resolver/ns6/example.net.db.in
new file mode 100644
index 0000000..4bef728
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/example.net.db.in
@@ -0,0 +1,34 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+@ IN NS ns
+@ IN MX 0 mail
+ns IN A 10.53.0.6
+mail IN A 10.53.0.6
+www IN HTTPS 0 http-server
+http-server IN A 10.53.0.6
+https-loop IN HTTPS 0 https-next
+https-loop IN A 10.53.0.6
+https-next IN HTTPS 0 https-loop
+https-next IN A 10.53.0.7
+https-cname IN HTTPS 0 cname-server
+cname-server IN CNAME cname-next
+cname-next IN CNAME http-server
+https-cname-loop IN HTTPS 0 https-cname-loop0
+https-cname-loop0 IN CNAME https-cname-loop0
+fetch 10 IN TXT A short ttl
+non-zero 10 IN TXT A short ttl
+zero 0 IN TXT A zero ttl
+$TTL 13
+ds IN NS ns.ds
+ns.ds IN A 10.53.0.6
diff --git a/bin/tests/system/resolver/ns6/fetch.tld.db b/bin/tests/system/resolver/ns6/fetch.tld.db
new file mode 100644
index 0000000..1d59e5a
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/fetch.tld.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.fetch.tld. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns.fetch.tld.
+ns.fetch.tld. A 10.53.0.6
+
+@ 13 TXT A short ttl
diff --git a/bin/tests/system/resolver/ns6/keygen.sh b/bin/tests/system/resolver/ns6/keygen.sh
new file mode 100644
index 0000000..2141a30
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/keygen.sh
@@ -0,0 +1,38 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+#
+# We use rsasha256 here to get a ZSK + KSK that don't fit in 512 bytes.
+#
+zone=ds.example.net
+zonefile="${zone}.db"
+infile="${zonefile}.in"
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a rsasha256 -fk $zone)
+zsk=$($KEYGEN -q -a rsasha256 -b 2048 $zone)
+cat $ksk.key $zsk.key >> $zonefile
+$SIGNER -P -o $zone $zonefile > /dev/null
+
+zone=example.net
+zonefile="${zone}.db"
+infile="${zonefile}.in"
+cp $infile $zonefile
+ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $zone)
+zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $zone)
+cat $ksk.key $zsk.key dsset-ds.example.net. >> $zonefile
+$SIGNER -P -o $zone $zonefile > /dev/null
+
+# Configure a static key to be used by delv
+keyfile_to_static_ds $ksk > ../ns5/trusted.conf
diff --git a/bin/tests/system/resolver/ns6/moves.db b/bin/tests/system/resolver/ns6/moves.db
new file mode 100644
index 0000000..06634ee
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/moves.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns.server.
+foo TXT "From NS 6"
+bar TXT "From NS 6"
diff --git a/bin/tests/system/resolver/ns6/named.conf.in b/bin/tests/system/resolver/ns6/named.conf.in
new file mode 100644
index 0000000..769b577
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/named.conf.in
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS6
+
+options {
+ 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.6; };
+ listen-on-v6 { fd92:7065:b8e:ffff::6; };
+ recursion no;
+ dnssec-validation no;
+ querylog yes;
+ statistics-file "named.stats";
+ /*
+ * test that named loads with root-delegation-only that
+ * has a exclude list.
+ */
+ root-delegation-only exclude { "a"; };
+ max-udp-size 4096;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example.net" {
+ type primary;
+ file "example.net.db.signed";
+ allow-update { any; };
+};
+
+zone "ds.example.net" {
+ type primary;
+ file "ds.example.net.db.signed";
+ allow-update { any; };
+};
+
+zone "to-be-removed.tld" {
+ type primary;
+ file "to-be-removed.tld.db";
+ allow-update { any; };
+};
+
+zone "broken" {
+ type primary;
+ file "broken.db";
+ allow-update { any; };
+};
+
+zone "redirect.com" {
+ type primary;
+ file "redirect.com.db";
+};
+
+zone "tld1" {
+ type primary;
+ file "tld1.db";
+};
+
+zone "no-edns-version.tld" {
+ type primary;
+ file "no-edns-version.tld.db";
+};
+
+zone "delegation-only" {
+ type primary;
+ file "delegation-only.db";
+};
+
+zone "fetch.tld" {
+ type primary;
+ file "fetch.tld.db";
+};
+
+zone "targetns" {
+ type primary;
+ file "targetns.db";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/resolver/ns6/no-edns-version.tld.db b/bin/tests/system/resolver/ns6/no-edns-version.tld.db
new file mode 100644
index 0000000..9ab654d
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/no-edns-version.tld.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA . . 0 0 0 0 0
+@ NS ns
+ns A 10.53.0.6
diff --git a/bin/tests/system/resolver/ns6/redirect.com.db b/bin/tests/system/resolver/ns6/redirect.com.db
new file mode 100644
index 0000000..f79f6dd
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/redirect.com.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+@ IN NS ns
+ns IN A 10.53.0.6
+
+; 10.53.1.* are non-responsive IP addresses
+$GENERATE 1-100 ns$.fake IN A 10.53.1.$
+$GENERATE 101-200 ns$.fake IN A 10.53.1.${-100}
+$GENERATE 201-300 ns$.fake IN A 10.53.1.${-200}
+$GENERATE 301-400 ns$.fake IN A 10.53.1.${-300}
+$GENERATE 401-500 ns$.fake IN A 10.53.1.${-400}
+$GENERATE 501-600 ns$.fake IN A 10.53.1.${-500}
+$GENERATE 601-700 ns$.fake IN A 10.53.1.${-600}
+$GENERATE 701-800 ns$.fake IN A 10.53.1.${-700}
+$GENERATE 801-900 ns$.fake IN A 10.53.1.${-800}
+$GENERATE 901-1000 ns$.fake IN A 10.53.1.${-900}
diff --git a/bin/tests/system/resolver/ns6/root.db b/bin/tests/system/resolver/ns6/root.db
new file mode 100644
index 0000000..096381c
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/root.db
@@ -0,0 +1,36 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA marka.isc.org. a.root.servers.nil. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.6
+a.root-servers.nil. AAAA fd92:7065:b8e:ffff::6
+moves. NS ns.server.
+server. NS ns7.server.
+ns7.server. A 10.53.0.7
+;
+; These two delegations are strictly not necessary as the test resolver (ns5)
+; doesn't have this zone as its root. They are just done for consistency with
+; the delegations in ns4/tld.
+;
+no-edns-version.tld. NS ns.no-edns-version.tld.
+ns.no-edns-version.tld. A 10.53.0.6
+edns-version.tld. NS ns.edns-version.tld.
+ns.edns-version.tld. A 10.53.0.7
+v4only.net. NS v4.nameserver.
+v4.nameserver. A 10.53.0.4
diff --git a/bin/tests/system/resolver/ns6/targetns.db b/bin/tests/system/resolver/ns6/targetns.db
new file mode 100644
index 0000000..4d9496b
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/targetns.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; In the test for checking how many NS records BIND will follow, this
+; zone marks the server as the one to which the NS lookups will be
+; directed.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+ NS ns
+ns A 10.53.0.6
diff --git a/bin/tests/system/resolver/ns6/tld1.db b/bin/tests/system/resolver/ns6/tld1.db
new file mode 100644
index 0000000..412509b
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/tld1.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+@ IN NS ns
+ns IN A 10.53.0.6
+
+$GENERATE 1-21 sub IN NS sub-ns$.tld2.
diff --git a/bin/tests/system/resolver/ns6/to-be-removed.tld.db.in b/bin/tests/system/resolver/ns6/to-be-removed.tld.db.in
new file mode 100644
index 0000000..5638090
--- /dev/null
+++ b/bin/tests/system/resolver/ns6/to-be-removed.tld.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+@ IN NS ns
+ns IN A 10.53.0.6
+ns0 IN A 10.53.0.6
+ns1 IN A 10.53.0.6
+ns2 IN A 10.53.0.6
+ns3 IN A 10.53.0.6
+ns4 IN A 10.53.0.6
+ns5 IN A 10.53.0.6
+ns6 IN A 10.53.0.6
+ns7 IN A 10.53.0.6
+ns8 IN A 10.53.0.6
+ns9 IN A 10.53.0.6
+$TTL 1
+@ IN A 10.53.0.6
+www IN A 10.53.0.6
diff --git a/bin/tests/system/resolver/ns7/all-cnames.db b/bin/tests/system/resolver/ns7/all-cnames.db
new file mode 100644
index 0000000..85003ee
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/all-cnames.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. ns.server. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS cname.tld.
diff --git a/bin/tests/system/resolver/ns7/edns-version.tld.db b/bin/tests/system/resolver/ns7/edns-version.tld.db
new file mode 100644
index 0000000..bcfae40
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/edns-version.tld.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ SOA . . 0 0 0 0 0
+@ NS ns
+ns A 10.53.0.7
diff --git a/bin/tests/system/resolver/ns7/named1.conf.in b/bin/tests/system/resolver/ns7/named1.conf.in
new file mode 100644
index 0000000..1d32ae9
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/named1.conf.in
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS7
+
+options {
+ 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.7; };
+ listen-on-v6 { fd92:7065:b8e:ffff::7; };
+ recursion yes;
+ dnssec-validation yes;
+ empty-zones-enable yes;
+ disable-empty-zone 20.172.in-addr.arpa;
+ /*
+ * check prefetch disabled
+ * check zero ttl not returned
+ */
+ prefetch 0;
+ querylog yes;
+ edns-udp-size 4096;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "server" {
+ type primary;
+ file "server.db";
+ allow-update { any; };
+};
+
+zone "edns-version.tld" {
+ type primary;
+ file "edns-version.tld.db";
+};
+
+zone "all-cnames" {
+ type primary;
+ file "all-cnames.db";
+};
+
+zone "tld2" {
+ type primary;
+ file "tld2.db";
+};
+
+zone "sub.tld1" {
+ type primary;
+ file "sub.tld1.db";
+};
diff --git a/bin/tests/system/resolver/ns7/named2.conf.in b/bin/tests/system/resolver/ns7/named2.conf.in
new file mode 100644
index 0000000..1d32ae9
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/named2.conf.in
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS7
+
+options {
+ 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.7; };
+ listen-on-v6 { fd92:7065:b8e:ffff::7; };
+ recursion yes;
+ dnssec-validation yes;
+ empty-zones-enable yes;
+ disable-empty-zone 20.172.in-addr.arpa;
+ /*
+ * check prefetch disabled
+ * check zero ttl not returned
+ */
+ prefetch 0;
+ querylog yes;
+ edns-udp-size 4096;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "server" {
+ type primary;
+ file "server.db";
+ allow-update { any; };
+};
+
+zone "edns-version.tld" {
+ type primary;
+ file "edns-version.tld.db";
+};
+
+zone "all-cnames" {
+ type primary;
+ file "all-cnames.db";
+};
+
+zone "tld2" {
+ type primary;
+ file "tld2.db";
+};
+
+zone "sub.tld1" {
+ type primary;
+ file "sub.tld1.db";
+};
diff --git a/bin/tests/system/resolver/ns7/root.hint b/bin/tests/system/resolver/ns7/root.hint
new file mode 100644
index 0000000..3337bd5
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.6
diff --git a/bin/tests/system/resolver/ns7/server.db.in b/bin/tests/system/resolver/ns7/server.db.in
new file mode 100644
index 0000000..7d5169a
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/server.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA marka.isc.org. a.root.servers.nil. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns7
+ns7 A 10.53.0.7
+ns A 10.53.0.5
+child NS ns.child
+ns.child A 10.53.0.5
diff --git a/bin/tests/system/resolver/ns7/sub.tld1.db b/bin/tests/system/resolver/ns7/sub.tld1.db
new file mode 100644
index 0000000..b2d46c6
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/sub.tld1.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+
+$GENERATE 1-21 @ IN NS sub-ns$.tld2.
+
+$GENERATE 1-21 bar IN NS bar-sub-ns$.tld2.
diff --git a/bin/tests/system/resolver/ns7/tld2.db b/bin/tests/system/resolver/ns7/tld2.db
new file mode 100644
index 0000000..1f31b51
--- /dev/null
+++ b/bin/tests/system/resolver/ns7/tld2.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+@ IN NS ns
+ns IN A 10.53.0.7
+
+$GENERATE 1-21 sub-ns$ IN A 10.53.0.7
+$GENERATE 1-21 bar-sub-ns$ IN A 10.53.0.3
diff --git a/bin/tests/system/resolver/ns9/named.args b/bin/tests/system/resolver/ns9/named.args
new file mode 100644
index 0000000..0c66bc0
--- /dev/null
+++ b/bin/tests/system/resolver/ns9/named.args
@@ -0,0 +1,2 @@
+# this server is IPv6 only
+-6 -m record -c named.conf -d 99 -D resolver-ns9 -X named.lock -g -T maxcachesize=2097152
diff --git a/bin/tests/system/resolver/ns9/named.conf.in b/bin/tests/system/resolver/ns9/named.conf.in
new file mode 100644
index 0000000..3be31db
--- /dev/null
+++ b/bin/tests/system/resolver/ns9/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS9
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { none; };
+ listen-on-v6 { fd92:7065:b8e:ffff::9; };
+ recursion yes;
+ dnssec-validation yes;
+ dual-stack-servers { fd92:7065:b8e:ffff::7; };
+ qname-minimization off;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet fd92:7065:b8e:ffff::9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/resolver/ns9/named.ipv6-only b/bin/tests/system/resolver/ns9/named.ipv6-only
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin/tests/system/resolver/ns9/named.ipv6-only
diff --git a/bin/tests/system/resolver/ns9/root.hint b/bin/tests/system/resolver/ns9/root.hint
new file mode 100644
index 0000000..f74fbf1
--- /dev/null
+++ b/bin/tests/system/resolver/ns9/root.hint
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.6
+a.root-servers.nil. IN AAAA fd92:7065:b8e:ffff::6;
diff --git a/bin/tests/system/resolver/setup.sh b/bin/tests/system/resolver/setup.sh
new file mode 100644
index 0000000..eeda13b
--- /dev/null
+++ b/bin/tests/system/resolver/setup.sh
@@ -0,0 +1,28 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=../conf.sh
+. ../conf.sh
+
+cp ns4/tld1.db ns4/tld.db
+cp ns6/to-be-removed.tld.db.in ns6/to-be-removed.tld.db
+cp ns7/server.db.in ns7/server.db
+
+copy_setports ns1/named.conf.in ns1/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/named1.conf.in ns7/named.conf
+copy_setports ns9/named.conf.in ns9/named.conf
+
+(cd ns6 && $SHELL keygen.sh)
diff --git a/bin/tests/system/resolver/tests.sh b/bin/tests/system/resolver/tests.sh
new file mode 100755
index 0000000..2232e5b
--- /dev/null
+++ b/bin/tests/system/resolver/tests.sh
@@ -0,0 +1,1022 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=../conf.sh
+. ../conf.sh
+
+dig_with_opts() {
+ "${DIG}" -p "${PORT}" "${@}"
+}
+
+resolve_with_opts() {
+ "${RESOLVE}" -p "${PORT}" "${@}"
+}
+
+rndccmd() {
+ "${RNDC}" -c ../common/rndc.conf -p "${CONTROLPORT}" -s "${@}"
+}
+
+status=0
+n=0
+
+n=$((n+1))
+echo_i "checking non-cachable NXDOMAIN response handling ($n)"
+ret=0
+dig_with_opts +tcp nxdomain.example.net @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if [ -x "${RESOLVE}" ] ; then
+ n=$((n+1))
+ echo_i "checking non-cachable NXDOMAIN response handling using dns_client ($n)"
+ ret=0
+ resolve_with_opts -t a -s 10.53.0.1 nxdomain.example.net 2> resolve.out.ns1.test${n} || ret=1
+ grep "resolution failed: ncache nxdomain" resolve.out.ns1.test${n} > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+if [ -x "${RESOLVE}" ] ; then
+ n=$((n+1))
+ echo_i "checking that local bound address can be set (Can't query from a denied address) ($n)"
+ ret=0
+ resolve_with_opts -b 10.53.0.8 -t a -s 10.53.0.1 www.example.org 2> resolve.out.ns1.test${n} || ret=1
+ grep "resolution failed: SERVFAIL" resolve.out.ns1.test${n} > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ n=$((n+1))
+ echo_i "checking that local bound address can be set (Can query from an allowed address) ($n)"
+ ret=0
+ resolve_with_opts -b 10.53.0.1 -t a -s 10.53.0.1 www.example.org > resolve.out.ns1.test${n} || ret=1
+ grep "www.example.org..*.192.0.2.1" resolve.out.ns1.test${n} > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n+1))
+echo_i "checking non-cachable NODATA response handling ($n)"
+ret=0
+dig_with_opts +tcp nodata.example.net @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if [ -x "${RESOLVE}" ] ; then
+ n=$((n+1))
+ echo_i "checking non-cachable NODATA response handling using dns_client ($n)"
+ ret=0
+ resolve_with_opts -t a -s 10.53.0.1 nodata.example.net 2> resolve.out.ns1.test${n} || ret=1
+ grep "resolution failed: ncache nxrrset" resolve.out.ns1.test${n} > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n+1))
+echo_i "checking handling of bogus referrals ($n)"
+# If the server has the "INSIST(!external)" bug, this query will kill it.
+dig_with_opts +tcp www.example.com. a @10.53.0.1 >/dev/null || { echo_i "failed"; status=$((status + 1)); }
+
+if [ -x "${RESOLVE}" ] ; then
+ n=$((n+1))
+ echo_i "checking handling of bogus referrals using dns_client ($n)"
+ ret=0
+ resolve_with_opts -t a -s 10.53.0.1 www.example.com 2> resolve.out.ns1.test${n} || ret=1
+ grep "resolution failed: SERVFAIL" resolve.out.ns1.test${n} > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n+1))
+echo_i "check handling of cname + other data / 1 ($n)"
+dig_with_opts +tcp cname1.example.com. a @10.53.0.1 >/dev/null || { echo_i "failed"; status=$((status + 1)); }
+
+n=$((n+1))
+echo_i "check handling of cname + other data / 2 ($n)"
+dig_with_opts +tcp cname2.example.com. a @10.53.0.1 >/dev/null || { echo_i "failed"; status=$((status + 1)); }
+
+n=$((n+1))
+echo_i "check that server is still running ($n)"
+dig_with_opts +tcp www.example.com. a @10.53.0.1 >/dev/null || { echo_i "failed"; status=$((status + 1)); }
+
+n=$((n+1))
+echo_i "checking answer IPv4 address filtering (deny) ($n)"
+ret=0
+dig_with_opts +tcp www.example.net @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "status: SERVFAIL" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "checking answer IPv6 address filtering (deny) ($n)"
+ret=0
+dig_with_opts +tcp www.example.net @10.53.0.1 aaaa > dig.out.ns1.test${n} || ret=1
+grep "status: SERVFAIL" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "checking answer IPv4 address filtering (accept) ($n)"
+ret=0
+dig_with_opts +tcp www.example.org @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+
+if [ -x "${RESOLVE}" ] ; then
+ n=$((n+1))
+ echo_i "checking answer IPv4 address filtering using dns_client (accept) ($n)"
+ ret=0
+ resolve_with_opts -t a -s 10.53.0.1 www.example.org > resolve.out.ns1.test${n} || ret=1
+ grep "www.example.org..*.192.0.2.1" resolve.out.ns1.test${n} > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n+1))
+echo_i "checking answer IPv6 address filtering (accept) ($n)"
+ret=0
+dig_with_opts +tcp www.example.org @10.53.0.1 aaaa > dig.out.ns1.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if [ -x "${RESOLVE}" ] ; then
+ n=$((n+1))
+ echo_i "checking answer IPv6 address filtering using dns_client (accept) ($n)"
+ ret=0
+ resolve_with_opts -t aaaa -s 10.53.0.1 www.example.org > resolve.out.ns1.test${n} || ret=1
+ grep "www.example.org..*.2001:db8:beef::1" resolve.out.ns1.test${n} > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n+1))
+echo_i "checking CNAME target filtering (deny) ($n)"
+ret=0
+dig_with_opts +tcp badcname.example.net @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "status: SERVFAIL" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "checking CNAME target filtering (accept) ($n)"
+ret=0
+dig_with_opts +tcp goodcname.example.net @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if [ -x "${RESOLVE}" ] ; then
+ n=$((n+1))
+ echo_i "checking CNAME target filtering using dns_client (accept) ($n)"
+ ret=0
+ resolve_with_opts -t a -s 10.53.0.1 goodcname.example.net > resolve.out.ns1.test${n} || ret=1
+ grep "goodcname.example.net..*.goodcname.example.org." resolve.out.ns1.test${n} > /dev/null || ret=1
+ grep "goodcname.example.org..*.192.0.2.1" resolve.out.ns1.test${n} > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n+1))
+echo_i "checking CNAME target filtering (accept due to subdomain) ($n)"
+ret=0
+dig_with_opts +tcp cname.sub.example.org @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if [ -x "${RESOLVE}" ] ; then
+ n=$((n+1))
+ echo_i "checking CNAME target filtering using dns_client (accept due to subdomain) ($n)"
+ ret=0
+ resolve_with_opts -t a -s 10.53.0.1 cname.sub.example.org > resolve.out.ns1.test${n} || ret=1
+ grep "cname.sub.example.org..*.ok.sub.example.org." resolve.out.ns1.test${n} > /dev/null || ret=1
+ grep "ok.sub.example.org..*.192.0.2.1" resolve.out.ns1.test${n} > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n+1))
+echo_i "checking DNAME target filtering (deny) ($n)"
+ret=0
+dig_with_opts +tcp foo.baddname.example.net @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "DNAME target foo.baddname.example.org denied for foo.baddname.example.net/IN" ns1/named.run >/dev/null || ret=1
+grep "status: SERVFAIL" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "checking DNAME target filtering (accept) ($n)"
+ret=0
+dig_with_opts +tcp foo.gooddname.example.net @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if [ -x "${RESOLVE}" ] ; then
+ n=$((n+1))
+ echo_i "checking DNAME target filtering using dns_client (accept) ($n)"
+ ret=0
+ resolve_with_opts -t a -s 10.53.0.1 foo.gooddname.example.net > resolve.out.ns1.test${n} || ret=1
+ grep "foo.gooddname.example.net..*.gooddname.example.org" resolve.out.ns1.test${n} > /dev/null || ret=1
+ grep "foo.gooddname.example.org..*.192.0.2.1" resolve.out.ns1.test${n} > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n+1))
+echo_i "checking DNAME target filtering (accept due to subdomain) ($n)"
+ret=0
+dig_with_opts +tcp www.dname.sub.example.org @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if [ -x "${RESOLVE}" ] ; then
+ n=$((n+1))
+ echo_i "checking DNAME target filtering using dns_client (accept due to subdomain) ($n)"
+ ret=0
+ resolve_with_opts -t a -s 10.53.0.1 www.dname.sub.example.org > resolve.out.ns1.test${n} || ret=1
+ grep "www.dname.sub.example.org..*.ok.sub.example.org." resolve.out.ns1.test${n} > /dev/null || ret=1
+ grep "www.ok.sub.example.org..*.192.0.2.1" resolve.out.ns1.test${n} > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n+1))
+echo_i "check that the resolver accepts a referral response with a non-empty ANSWER section ($n)"
+ret=0
+dig_with_opts @10.53.0.1 foo.glue-in-answer.example.org. A > dig.ns1.out.${n} || ret=1
+grep "status: NOERROR" dig.ns1.out.${n} > /dev/null || ret=1
+grep "foo.glue-in-answer.example.org.*192.0.2.1" dig.ns1.out.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that the resolver limits the number of NS records it follows in a referral response ($n)"
+# ns5 is the recusor being tested. ns4 holds the sourcens zone containing
+# names with varying numbers of NS records pointing to non-existent
+# nameservers in the targetns zone on ns6.
+ret=0
+rndccmd 10.53.0.5 flush || ret=1 # Ensure cache is empty before doing this test
+count_fetches () {
+ actual=$(nextpartpeek ns5/named.run | grep -c " fetch: ns.fake${nscount}")
+ [ "${actual:-0}" -eq "${expected}" ] || return 1
+ return 0
+}
+for nscount in 1 2 3 4 5 6 7 8 9 10
+do
+ # Verify number of NS records at source server
+ dig_with_opts +norecurse @10.53.0.4 target${nscount}.sourcens ns > dig.ns4.out.${nscount}.${n}
+ sourcerecs=$(grep NS dig.ns4.out.${nscount}.${n} | grep -cv ';')
+ test "${sourcerecs}" -eq "${nscount}" || ret=1
+ test "${sourcerecs}" -eq "${nscount}" || echo_i "NS count incorrect for target${nscount}.sourcens"
+
+ # Expected queries = 2 * number of NS records, up to a maximum of 10.
+ expected=$((nscount*2))
+ if [ "$expected" -gt 10 ]; then expected=10; fi
+ # Count the number of logged fetches
+ nextpart ns5/named.run > /dev/null
+ dig_with_opts @10.53.0.5 target${nscount}.sourcens A > dig.ns5.out.${nscount}.${n} || ret=1
+ retry_quiet 5 count_fetches ns5/named.run $nscount $expected || {
+ echo_i "query count error: $nscount NS records: expected queries $expected, actual $actual"; ret=1;
+ }
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "RT21594 regression test check setup ($n)"
+ret=0
+# Check that "aa" is not being set by the authoritative server.
+dig_with_opts +tcp . @10.53.0.4 soa > dig.ns4.out.${n} || ret=1
+grep 'flags: qr rd;' dig.ns4.out.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "RT21594 regression test positive answers ($n)"
+ret=0
+# Check that resolver accepts the non-authoritative positive answers.
+dig_with_opts +tcp . @10.53.0.5 soa > dig.ns5.out.${n} || ret=1
+grep "status: NOERROR" dig.ns5.out.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "RT21594 regression test NODATA answers ($n)"
+ret=0
+# Check that resolver accepts the non-authoritative nodata answers.
+dig_with_opts +tcp . @10.53.0.5 txt > dig.ns5.out.${n} || ret=1
+grep "status: NOERROR" dig.ns5.out.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "RT21594 regression test NXDOMAIN answers ($n)"
+ret=0
+# Check that resolver accepts the non-authoritative positive answers.
+dig_with_opts +tcp noexistent @10.53.0.5 txt > dig.ns5.out.${n} || ret=1
+grep "status: NXDOMAIN" dig.ns5.out.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that replacement of additional data by a negative cache no data entry clears the additional RRSIGs ($n)"
+ret=0
+dig_with_opts +tcp mx example.net @10.53.0.7 > dig.ns7.out.${n} || ret=1
+grep "status: NOERROR" dig.ns7.out.${n} > /dev/null || ret=1
+if [ $ret = 1 ]; then echo_i "mx priming failed"; fi
+$NSUPDATE << EOF
+server 10.53.0.6 ${PORT}
+zone example.net
+update delete mail.example.net A
+update add mail.example.net 0 AAAA ::1
+send
+EOF
+dig_with_opts +tcp a mail.example.net @10.53.0.7 > dig.ns7.out.${n} || ret=2
+grep "status: NOERROR" dig.ns7.out.${n} > /dev/null || ret=2
+grep "ANSWER: 0" dig.ns7.out.${n} > /dev/null || ret=2
+if [ $ret = 2 ]; then echo_i "ncache priming failed"; fi
+dig_with_opts +tcp mx example.net @10.53.0.7 > dig.ns7.out.${n} || ret=3
+grep "status: NOERROR" dig.ns7.out.${n} > /dev/null || ret=3
+dig_with_opts +tcp rrsig mail.example.net +norec @10.53.0.7 > dig.ns7.out.${n} || ret=4
+grep "status: NOERROR" dig.ns7.out.${n} > /dev/null || ret=4
+grep "ANSWER: 0" dig.ns7.out.${n} > /dev/null || ret=4
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "checking that update a nameservers address has immediate effects ($n)"
+ret=0
+dig_with_opts +tcp TXT foo.moves @10.53.0.7 > dig.ns7.foo.${n} || ret=1
+grep "From NS 5" dig.ns7.foo.${n} > /dev/null || ret=1
+$NSUPDATE << EOF
+server 10.53.0.7 ${PORT}
+zone server
+update delete ns.server A
+update add ns.server 300 A 10.53.0.4
+send
+EOF
+sleep 1
+dig_with_opts +tcp TXT bar.moves @10.53.0.7 > dig.ns7.bar.${n} || ret=1
+grep "From NS 4" dig.ns7.bar.${n} > /dev/null || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; status=1; fi
+
+n=$((n+1))
+echo_i "checking that update a nameservers glue has immediate effects ($n)"
+ret=0
+dig_with_opts +tcp TXT foo.child.server @10.53.0.7 > dig.ns7.foo.${n} || ret=1
+grep "From NS 5" dig.ns7.foo.${n} > /dev/null || ret=1
+$NSUPDATE << EOF
+server 10.53.0.7 ${PORT}
+zone server
+update delete ns.child.server A
+update add ns.child.server 300 A 10.53.0.4
+send
+EOF
+sleep 1
+dig_with_opts +tcp TXT bar.child.server @10.53.0.7 > dig.ns7.bar.${n} || ret=1
+grep "From NS 4" dig.ns7.bar.${n} > /dev/null || ret=1
+
+if [ $ret != 0 ]; then echo_i "failed"; status=1; fi
+
+n=$((n+1))
+echo_i "checking empty RFC 1918 reverse zones ($n)"
+ret=0
+# Check that "aa" is being set by the resolver for RFC 1918 zones
+# except the one that has been deliberately disabled
+dig_with_opts @10.53.0.7 -x 10.1.1.1 > dig.ns4.out.1.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.1.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 192.168.1.1 > dig.ns4.out.2.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.2.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.16.1.1 > dig.ns4.out.3.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.3.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.17.1.1 > dig.ns4.out.4.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.4.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.18.1.1 > dig.ns4.out.5.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.5.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.19.1.1 > dig.ns4.out.6.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.6.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.21.1.1 > dig.ns4.out.7.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.7.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.22.1.1 > dig.ns4.out.8.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.8.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.23.1.1 > dig.ns4.out.9.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.9.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.24.1.1 > dig.ns4.out.11.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.11.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.25.1.1 > dig.ns4.out.12.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.12.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.26.1.1 > dig.ns4.out.13.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.13.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.27.1.1 > dig.ns4.out.14.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.14.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.28.1.1 > dig.ns4.out.15.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.15.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.29.1.1 > dig.ns4.out.16.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.16.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.30.1.1 > dig.ns4.out.17.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.17.${n} > /dev/null || ret=1
+dig_with_opts @10.53.0.7 -x 172.31.1.1 > dig.ns4.out.18.${n} || ret=1
+grep 'flags: qr aa rd ra;' dig.ns4.out.18.${n} > /dev/null || ret=1
+# but this one should NOT be authoritative
+dig_with_opts @10.53.0.7 -x 172.20.1.1 > dig.ns4.out.19.${n} || ret=1
+grep 'flags: qr rd ra;' dig.ns4.out.19.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; status=1; fi
+
+n=$((n+1))
+echo_i "checking that removal of a delegation is honoured ($n)"
+ret=0
+dig_with_opts @10.53.0.5 www.to-be-removed.tld A > dig.ns5.prime.${n}
+grep "status: NOERROR" dig.ns5.prime.${n} > /dev/null || { ret=1; echo_i "priming failed"; }
+cp ns4/tld2.db ns4/tld.db
+rndc_reload ns4 10.53.0.4 tld
+old=
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ foo=0
+ dig_with_opts @10.53.0.5 ns$i.to-be-removed.tld A > /dev/null
+ dig_with_opts @10.53.0.5 www.to-be-removed.tld A > dig.ns5.out.${n}
+ grep "status: NXDOMAIN" dig.ns5.out.${n} > /dev/null || foo=1
+ [ $foo = 0 ] && break
+ $NSUPDATE << EOF
+server 10.53.0.6 ${PORT}
+zone to-be-removed.tld
+update add to-be-removed.tld 100 NS ns${i}.to-be-removed.tld
+update delete to-be-removed.tld NS ns${old}.to-be-removed.tld
+send
+EOF
+ old=$i
+ sleep 1
+done
+[ $ret = 0 ] && ret=$foo;
+if [ $ret != 0 ]; then echo_i "failed"; status=1; fi
+
+n=$((n+1))
+echo_i "check for improved error message with SOA mismatch ($n)"
+ret=0
+dig_with_opts @10.53.0.1 www.sub.broken aaaa > dig.out.ns1.test${n} || ret=1
+grep "not subdomain of zone" ns1/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+copy_setports ns7/named2.conf.in ns7/named.conf
+rndccmd 10.53.0.7 reconfig 2>&1 | sed 's/^/ns7 /' | cat_i
+
+n=$((n+1))
+echo_i "check resolution on the listening port ($n)"
+ret=0
+dig_with_opts +tcp +tries=2 +time=5 mx example.net @10.53.0.7 > dig.ns7.out.${n} || ret=2
+grep "status: NOERROR" dig.ns7.out.${n} > /dev/null || ret=1
+grep "ANSWER: 1" dig.ns7.out.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check prefetch (${n})"
+ret=0
+# read prefetch value from config.
+PREFETCH=$(sed -n "s/[[:space:]]*prefetch \([0-9]\).*/\1/p" ns5/named.conf)
+dig_with_opts @10.53.0.5 fetch.tld txt > dig.out.1.${n} || ret=1
+ttl1=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.1.${n})
+interval=$((ttl1 - PREFETCH + 1))
+# sleep so we are in prefetch range
+sleep ${interval:-0}
+# trigger prefetch
+dig_with_opts @10.53.0.5 fetch.tld txt > dig.out.2.${n} || ret=1
+ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n})
+sleep 1
+# check that prefetch occurred
+dig_with_opts @10.53.0.5 fetch.tld txt > dig.out.3.${n} || ret=1
+ttl=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.3.${n})
+test "${ttl:-0}" -gt "${ttl2:-1}" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check prefetch of validated DS's RRSIG TTL is updated (${n})"
+ret=0
+dig_with_opts +dnssec @10.53.0.5 ds.example.net ds > dig.out.1.${n} || ret=1
+dsttl1=$(awk '$4 == "DS" && $7 == "2" { print $2 }' dig.out.1.${n})
+interval=$((dsttl1 - PREFETCH + 1))
+# sleep so we are in prefetch range
+sleep ${interval:-0}
+# trigger prefetch
+dig_with_opts @10.53.0.5 ds.example.net ds > dig.out.2.${n} || ret=1
+dsttl2=$(awk '$4 == "DS" && $7 == "2" { print $2 }' dig.out.2.${n})
+sleep 1
+# check that prefetch occurred
+dig_with_opts @10.53.0.5 ds.example.net ds +dnssec > dig.out.3.${n} || ret=1
+dsttl=$(awk '$4 == "DS" && $7 == "2" { print $2 }' dig.out.3.${n})
+sigttl=$(awk '$4 == "RRSIG" && $5 == "DS" { print $2 }' dig.out.3.${n})
+test "${dsttl:-0}" -gt "${dsttl2:-1}" || ret=1
+test "${sigttl:-0}" -gt "${dsttl2:-1}" || ret=1
+test "${dsttl:-0}" -eq "${sigttl:-1}" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check prefetch disabled (${n})"
+ret=0
+dig_with_opts @10.53.0.7 fetch.example.net txt > dig.out.1.${n} || ret=1
+ttl1=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.1.${n})
+interval=$((ttl1 - PREFETCH + 1))
+# sleep so we are in expire range
+sleep ${interval:-0}
+tmp_ttl=$ttl1
+no_prefetch() {
+ # fetch record and ensure its ttl is in range 0 < ttl < tmp_ttl.
+ # since prefetch is disabled, updated ttl must be a lower value than
+ # the previous one.
+ dig_with_opts @10.53.0.7 fetch.example.net txt > dig.out.2.${n} || return 1
+ ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n})
+ # check that prefetch has not occurred
+ if [ "$ttl2" -ge "${tmp_ttl}" ]; then
+ return 1
+ fi
+ tmp_ttl=$ttl2
+}
+retry_quiet 3 no_prefetch || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check prefetch qtype * (${n})"
+ret=0
+dig_with_opts @10.53.0.5 fetchall.tld any > dig.out.1.${n} || ret=1
+ttl1=$(awk '/"A" "short" "ttl"/ { print $2 - 3 }' dig.out.1.${n})
+# sleep so we are in prefetch range
+sleep "${ttl1:-0}"
+# trigger prefetch
+dig_with_opts @10.53.0.5 fetchall.tld any > dig.out.2.${n} || ret=1
+ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n})
+sleep 1
+# check that prefetch occurred;
+# note that only one record is prefetched, which is the TXT record in this case,
+# because of the order of the records in the cache
+dig_with_opts @10.53.0.5 fetchall.tld any > dig.out.3.${n} || ret=1
+ttl3=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.3.${n})
+test "${ttl3:-0}" -gt "${ttl2:-1}" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that E was logged on EDNS queries in the query log (${n})"
+ret=0
+dig_with_opts @10.53.0.5 +edns edns.fetchall.tld any > dig.out.2.${n} || ret=1
+grep "query: edns.fetchall.tld IN ANY +E" ns5/named.run > /dev/null || ret=1
+dig_with_opts @10.53.0.5 +noedns noedns.fetchall.tld any > dig.out.2.${n} || ret=1
+grep "query: noedns.fetchall.tld IN ANY" ns5/named.run > /dev/null || ret=1
+grep "query: noedns.fetchall.tld IN ANY +E" ns5/named.run > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that '-t aaaa' in .digrc does not have unexpected side effects ($n)"
+ret=0
+echo "-t aaaa" > .digrc
+(HOME="$(pwd)" dig_with_opts @10.53.0.4 . > dig.out.1.${n}) || ret=1
+(HOME="$(pwd)" dig_with_opts @10.53.0.4 . A > dig.out.2.${n}) || ret=1
+(HOME="$(pwd)" dig_with_opts @10.53.0.4 -x 127.0.0.1 > dig.out.3.${n}) || ret=1
+grep ';\..*IN.*AAAA$' dig.out.1.${n} > /dev/null || ret=1
+grep ';\..*IN.*A$' dig.out.2.${n} > /dev/null || ret=1
+grep 'extra type option' dig.out.2.${n} > /dev/null && ret=1
+grep ';1\.0\.0\.127\.in-addr\.arpa\..*IN.*PTR$' dig.out.3.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+edns=$($FEATURETEST --edns-version)
+
+n=$((n+1))
+echo_i "check that EDNS version is logged (${n})"
+ret=0
+dig_with_opts @10.53.0.5 +edns edns0.fetchall.tld any > dig.out.2.${n} || ret=1
+grep "query: edns0.fetchall.tld IN ANY +E(0)" ns5/named.run > /dev/null || ret=1
+if test "${edns:-0}" != 0; then
+ dig_with_opts @10.53.0.5 +edns=1 edns1.fetchall.tld any > dig.out.2.${n} || ret=1
+ grep "query: edns1.fetchall.tld IN ANY +E(1)" ns5/named.run > /dev/null || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if test "${edns:-0}" != 0; then
+ n=$((n+1))
+ echo_i "check that edns-version is honoured (${n})"
+ ret=0
+ dig_with_opts @10.53.0.5 +edns no-edns-version.tld > dig.out.1.${n} || ret=1
+ grep "query: no-edns-version.tld IN A -E(1)" ns6/named.run > /dev/null || ret=1
+ dig_with_opts @10.53.0.5 +edns edns-version.tld > dig.out.2.${n} || ret=1
+ grep "query: edns-version.tld IN A -E(0)" ns7/named.run > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n+1))
+echo_i "check that CNAME nameserver is logged correctly (${n})"
+ret=0
+dig_with_opts soa all-cnames @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: SERVFAIL" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "skipping nameserver 'cname.tld' because it is a CNAME, while resolving 'all-cnames/SOA'" ns5/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that unexpected opcodes are handled correctly (${n})"
+ret=0
+dig_with_opts soa all-cnames @10.53.0.5 +opcode=15 +cd +rec +ad +zflag > dig.out.ns5.test${n} || ret=1
+grep "status: NOTIMP" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "flags:[^;]* qr[; ]" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "flags:[^;]* ra[; ]" dig.out.ns5.test${n} > /dev/null && ret=1
+grep "flags:[^;]* rd[; ]" dig.out.ns5.test${n} > /dev/null && ret=1
+grep "flags:[^;]* cd[; ]" dig.out.ns5.test${n} > /dev/null && ret=1
+grep "flags:[^;]* ad[; ]" dig.out.ns5.test${n} > /dev/null && ret=1
+grep "flags:[^;]*; MBZ: " dig.out.ns5.test${n} > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that EDNS client subnet with non-zeroed bits is handled correctly (${n})"
+ret=0
+# 0001 (IPv4) 1f (31 significant bits) 00 (0) ffffffff (255.255.255.255)
+dig_with_opts soa . @10.53.0.5 +ednsopt=8:00011f00ffffffff > dig.out.ns5.test${n} || ret=1
+grep "status: FORMERR" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "; EDNS: version:" dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that dig +subnet zeros address bits correctly (${n})"
+ret=0
+dig_with_opts soa . @10.53.0.5 +subnet=255.255.255.255/23 > dig.out.ns5.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "CLIENT-SUBNET: 255.255.254.0/23/0" dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that SOA query returns data for delegation-only apex (${n})"
+ret=0
+dig_with_opts soa delegation-only @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n+1))
+
+n=$((n+1))
+echo_i "check that NS query returns data for delegation-only apex (${n})"
+ret=0
+dig_with_opts ns delegation-only @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that A query returns data for delegation-only A apex (${n})"
+ret=0
+dig_with_opts a delegation-only @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that CDS query returns data for delegation-only apex (${n})"
+ret=0
+dig_with_opts cds delegation-only @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that AAAA query returns data for delegation-only AAAA apex (${n})"
+ret=0
+dig_with_opts a delegation-only @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n+1))
+
+echo_i "check that DNSKEY query returns data for delegation-only apex (${n})"
+ret=0
+dig_with_opts dnskey delegation-only @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that CDNSKEY query returns data for delegation-only apex (${n})"
+ret=0
+dig_with_opts cdnskey delegation-only @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns5.test${n} > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that NXDOMAIN is returned for delegation-only non-apex A data (${n})"
+ret=0
+dig_with_opts a a.delegation-only @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: NXDOMAIN" dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that NXDOMAIN is returned for delegation-only non-apex CDS data (${n})"
+ret=0
+dig_with_opts cds cds.delegation-only @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: NXDOMAIN" dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that NXDOMAIN is returned for delegation-only non-apex AAAA data (${n})"
+ret=0
+dig_with_opts aaaa aaaa.delegation-only @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: NXDOMAIN" dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n+1))
+
+echo_i "check that NXDOMAIN is returned for delegation-only non-apex CDNSKEY data (${n})"
+ret=0
+dig_with_opts cdnskey cdnskey.delegation-only @10.53.0.5 > dig.out.ns5.test${n} || ret=1
+grep "status: NXDOMAIN" dig.out.ns5.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check zero ttl not returned for learnt non zero ttl records (${n})"
+ret=0
+# use prefetch disabled server
+dig_with_opts @10.53.0.7 non-zero.example.net txt > dig.out.1.${n} || ret=1
+ttl1=$(awk '/"A" "short" "ttl"/ { print $2 - 2 }' dig.out.1.${n})
+# sleep so we are in expire range
+sleep "${ttl1:-0}"
+# look for ttl = 1, allow for one miss at getting zero ttl
+zerotonine="0 1 2 3 4 5 6 7 8 9"
+zerotonine="$zerotonine $zerotonine $zerotonine"
+for i in $zerotonine $zerotonine $zerotonine $zerotonine
+do
+ dig_with_opts @10.53.0.7 non-zero.example.net txt > dig.out.2.${n} || ret=1
+ ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n})
+ test "${ttl2:-1}" -eq 0 && break
+ test "${ttl2:-1}" -ge "${ttl1:-0}" && break
+ "${PERL}" -e 'select(undef, undef, undef, 0.05);'
+done
+test "${ttl2:-1}" -eq 0 && ret=1
+test "${ttl2:-1}" -ge "${ttl1:-0}" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check zero ttl is returned for learnt zero ttl records (${n})"
+ret=0
+dig_with_opts @10.53.0.7 zero.example.net txt > dig.out.1.${n} || ret=1
+ttl=$(awk '/"A" "zero" "ttl"/ { print $2 }' dig.out.1.${n})
+test "${ttl:-1}" -eq 0 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that 'ad' in not returned in truncated answer with empty answer and authority sections to request with +ad (${n})"
+ret=0
+dig_with_opts @10.53.0.6 dnskey ds.example.net +bufsize=512 +ad +nodnssec +ignore +norec > dig.out.$n
+grep "flags: qr aa tc; QUERY: 1, ANSWER: 0, AUTHORITY: 0" dig.out.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that 'ad' in not returned in truncated answer with empty answer and authority sections to request with +dnssec (${n})"
+ret=0
+dig_with_opts @10.53.0.6 dnskey ds.example.net +bufsize=512 +noad +dnssec +ignore +norec > dig.out.$n
+grep "flags: qr aa tc; QUERY: 1, ANSWER: 0, AUTHORITY: 0" dig.out.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that the resolver accepts a reply with empty question section with TC=1 and retries over TCP ($n)"
+ret=0
+dig_with_opts @10.53.0.5 truncated.no-questions. a +tries=3 +time=4 > dig.ns5.out.${n} || ret=1
+grep "status: NOERROR" dig.ns5.out.${n} > /dev/null || ret=1
+grep "ANSWER: 1," dig.ns5.out.${n} > /dev/null || ret=1
+grep "1\.2\.3\.4" dig.ns5.out.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that the resolver rejects a reply with empty question section with TC=0 ($n)"
+ret=0
+dig_with_opts @10.53.0.5 not-truncated.no-questions. a +tries=3 +time=4 > dig.ns5.out.${n} || ret=1
+grep "status: NOERROR" dig.ns5.out.${n} > /dev/null && ret=1
+grep "ANSWER: 1," dig.ns5.out.${n} > /dev/null && ret=1
+grep "1\.2\.3\.4" dig.ns5.out.${n} > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+if ${FEATURETEST} --enable-querytrace; then
+ n=$((n+1))
+ echo_i "check that SERVFAIL is returned for an empty question section via TCP ($n)"
+ ret=0
+ nextpart ns5/named.run > /dev/null
+ # bind to local address so that addresses in log messages are consistent
+ # between platforms
+ dig_with_opts @10.53.0.5 -b 10.53.0.5 tcpalso.no-questions. a +tries=2 +timeout=15 > dig.ns5.out.${n} || ret=1
+ grep "status: SERVFAIL" dig.ns5.out.${n} > /dev/null || ret=1
+ check_namedrun() {
+ nextpartpeek ns5/named.run > nextpart.out.${n}
+ grep 'resolving tcpalso.no-questions/A for [^:]*: empty question section, accepting it anyway as TC=1' nextpart.out.${n} > /dev/null || return 1
+ grep '(tcpalso.no-questions/A): connecting via TCP' nextpart.out.${n} > /dev/null || return 1
+ grep 'resolving tcpalso.no-questions/A for [^:]*: empty question section$' nextpart.out.${n} > /dev/null || return 1
+ grep '(tcpalso.no-questions/A): nextitem' nextpart.out.${n} > /dev/null || return 1
+ return 0
+ }
+ retry_quiet 12 check_namedrun || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+n=$((n+1))
+echo_i "checking SERVFAIL is returned when all authoritative servers return FORMERR ($n)"
+ret=0
+dig_with_opts @10.53.0.5 ns.formerr-to-all. a > dig.ns5.out.${n} || ret=1
+grep "status: SERVFAIL" dig.ns5.out.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "checking SERVFAIL is not returned if only some authoritative servers return FORMERR ($n)"
+ret=0
+dig_with_opts @10.53.0.5 ns.partial-formerr. a > dig.ns5.out.${n} || ret=1
+grep "status: SERVFAIL" dig.ns5.out.${n} > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check logged command line ($n)"
+ret=0
+grep "running as: .* -m record " ns1/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "checking NXDOMAIN is returned when querying non existing domain in CH class ($n)"
+ret=0
+dig_with_opts @10.53.0.1 id.hostname txt ch > dig.ns1.out.${n} || ret=1
+grep "status: NXDOMAIN" dig.ns1.out.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that the addition section for HTTPS is populated on initial query to a recursive server ($n)"
+ret=0
+dig_with_opts @10.53.0.7 www.example.net https > dig.out.ns7.${n} || ret=1
+grep "status: NOERROR" dig.out.ns7.${n} > /dev/null || ret=1
+grep "flags:[^;]* ra[ ;]" dig.out.ns7.${n} > /dev/null || ret=1
+grep "ADDITIONAL: 2" dig.out.ns7.${n} > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns7.${n} > /dev/null || ret=1
+grep "http-server\.example\.net\..*A.*10\.53\.0\.6" dig.out.ns7.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check HTTPS loop is handled properly ($n)"
+ret=0
+dig_with_opts @10.53.0.7 https-loop.example.net https > dig.out.ns7.${n} || ret=1
+grep "status: NOERROR" dig.out.ns7.${n} > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns7.${n} > /dev/null || ret=1
+grep "ADDITIONAL: 2" dig.out.ns7.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check HTTPS -> CNAME loop is handled properly ($n)"
+ret=0
+dig_with_opts @10.53.0.7 https-cname-loop.example.net https > dig.out.ns7.${n} || ret=1
+grep "status: NOERROR" dig.out.ns7.${n} > /dev/null || ret=1
+grep "ADDITIONAL: 2" dig.out.ns7.${n} > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns7.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check HTTPS cname chains are followed ($n)"
+ret=0
+dig_with_opts @10.53.0.7 https-cname.example.net https > dig.out.ns7.${n} || ret=1
+grep "status: NOERROR" dig.out.ns7.${n} > /dev/null || ret=1
+grep "ADDITIONAL: 4" dig.out.ns7.${n} > /dev/null || ret=1
+grep 'http-server\.example\.net\..*A.10\.53\.0\.6' dig.out.ns7.${n} > /dev/null || ret=1
+grep 'cname-server\.example\.net\..*CNAME.cname-next\.example\.net\.' dig.out.ns7.${n} > /dev/null || ret=1
+grep 'cname-next\.example\.net\..*CNAME.http-server\.example\.net\.' dig.out.ns7.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check ADB find loops are detected ($n)"
+ret=0
+dig_with_opts +tcp +tries=1 +timeout=5 @10.53.0.1 fake.lame.example.org > dig.out.ns1.${n} || ret=1
+grep "status: SERVFAIL" dig.out.ns1.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check handling of large referrals to unresponsive name servers ($n)"
+ret=0
+dig_with_opts +timeout=15 large-referral.example.net @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "status: SERVFAIL" dig.out.ns1.test${n} > /dev/null || ret=1
+# Check the total number of findname() calls triggered by a single query
+# for large-referral.example.net/A.
+findname_call_count="$(grep -c "large-referral\.example\.net.*FINDNAME" ns1/named.run || true)"
+if [ "${findname_call_count}" -gt 1000 ]; then
+ echo_i "failed: ${findname_call_count} (> 1000) findname() calls detected for large-referral.example.net"
+ ret=1
+fi
+# Check whether the limit of NS RRs processed for any delegation
+# encountered was not exceeded.
+if grep -Eq "dns_adb_createfind: started (A|AAAA) fetch for name ns21.fake.redirect.com" ns1/named.run; then
+ echo_i "failed: unexpected address fetch(es) were triggered for ns21.fake.redirect.com"
+ ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "checking query resolution for a domain with a valid glueless delegation chain ($n)"
+ret=0
+rndccmd 10.53.0.1 flush || ret=1
+dig_with_opts foo.bar.sub.tld1 @10.53.0.1 TXT > dig.out.ns1.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns1.test${n} > /dev/null || ret=1
+grep "IN.*TXT.*baz" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that correct namespace is chosen for dual-stack-servers ($n)"
+ret=0
+#
+# The two priming queries are needed until we fix dual-stack-servers fully
+#
+dig_with_opts @fd92:7065:b8e:ffff::9 v4.nameserver A > dig.out.prime1.${n} || ret=1
+dig_with_opts @fd92:7065:b8e:ffff::9 v4.nameserver AAAA > dig.out.prime2.${n} || ret=1
+dig_with_opts @fd92:7065:b8e:ffff::9 foo.v4only.net A > dig.out.ns9.${n} || ret=1
+grep "status: NOERROR" dig.out.ns9.${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check expired TTLs with qtype * (${n})"
+ret=0
+dig_with_opts +tcp @10.53.0.5 mixedttl.tld any > dig.out.1.${n} || ret=1
+ttl1=$(awk '$1 == "mixedttl.tld." && $4 == "A" { print $2 + 1 }' dig.out.1.${n})
+# sleep TTL + 1 so that record has expired
+sleep "${ttl1:-0}"
+dig_with_opts +tcp @10.53.0.5 mixedttl.tld any > dig.out.2.${n} || ret=1
+# check preconditions
+grep "ANSWER: 3," dig.out.1.${n} > /dev/null || ret=1
+lines=$(awk '$1 == "mixedttl.tld." && $2 > 30 { print }' dig.out.1.${n} | wc -l)
+test ${lines:-1} -ne 0 && ret=1
+# check behaviour (there may be 1 answer on very slow machines)
+grep "ANSWER: [12]," dig.out.2.${n} > /dev/null || ret=1
+lines=$(awk '$1 == "mixedttl.tld." && $2 > 30 { print }' dig.out.2.${n} | wc -l)
+test ${lines:-1} -ne 0 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+n=$((n+1))
+echo_i "check resolver behavior when FORMERR for EDNS options happens (${n})"
+ret=0
+msg="resolving options-formerr/A .* server sent FORMERR with echoed DNS COOKIE"
+if [ $ret != 0 ]; then echo_i "failed"; fi
+nextpart ns5/named.run >/dev/null
+dig_with_opts +tcp @10.53.0.5 options-formerr A > dig.out.${n} || ret=1
+grep "status: NOERROR" dig.out.${n} > /dev/null || ret=1
+nextpart ns5/named.run | grep "$msg" > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/resolver/tests_sh_resolver.py b/bin/tests/system/resolver/tests_sh_resolver.py
new file mode 100644
index 0000000..d8de300
--- /dev/null
+++ b/bin/tests/system/resolver/tests_sh_resolver.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_resolver(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/rndc/clean.sh b/bin/tests/system/rndc/clean.sh
new file mode 100644
index 0000000..d18b5a5
--- /dev/null
+++ b/bin/tests/system/rndc/clean.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.*.test*
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run ns*/named.run.prev
+rm -f ns2/named.stats
+rm -f ns2/nil.db ns2/other.db ns2/static.db ns2/*.jnl
+rm -f ns2/session.key
+rm -f ns3/named_dump.db*
+rm -f ns4/*.nta
+rm -f ns4/example.db ns4/example.db.jnl
+rm -f ns4/key?.conf
+rm -f ns6/huge.zone.db
+rm -f ns7/include.db ns7/test.db ns7/*.jnl
+rm -f ns7/named_dump.db*
+rm -f ns*/named.conf
+rm -f nsupdate.out.*.test*
+rm -f python.out.*.test*
+rm -f rndc.out.*.test*
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
+rm -f ns*/*.nta
diff --git a/bin/tests/system/rndc/gencheck.c b/bin/tests/system/rndc/gencheck.c
new file mode 100644
index 0000000..7949b66
--- /dev/null
+++ b/bin/tests/system/rndc/gencheck.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <isc/print.h>
+
+#define USAGE "usage: gencheck <filename>\n"
+
+static int
+check(const char *buf, ssize_t count, size_t *start) {
+ const char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789";
+ ssize_t i;
+
+ for (i = 0; i < count; i++, *start = (*start + 1) % (sizeof(chars) - 1))
+ {
+ /* Just ignore the trailing newline */
+ if (buf[i] == '\n') {
+ continue;
+ }
+ if (buf[i] != chars[*start]) {
+ return (0);
+ }
+ }
+
+ return (1);
+}
+
+int
+main(int argc, char **argv) {
+ int ret;
+ int fd;
+ ssize_t count;
+ char buf[1024];
+ size_t start;
+ size_t length;
+
+ ret = EXIT_FAILURE;
+ fd = -1;
+ length = 0;
+
+ if (argc != 2) {
+ fprintf(stderr, USAGE);
+ goto out;
+ }
+
+ fd = open(argv[1], O_RDONLY);
+ if (fd == -1) {
+ goto out;
+ }
+
+ start = 0;
+ while ((count = read(fd, buf, sizeof(buf))) != 0) {
+ if (count < 0) {
+ goto out;
+ }
+
+ if (!check(buf, count, &start)) {
+ goto out;
+ }
+
+ length += count;
+ }
+
+ ret = EXIT_SUCCESS;
+
+out:
+ printf("%lu\n", (unsigned long)length);
+
+ if (fd != -1) {
+ close(fd);
+ }
+
+ return (ret);
+}
diff --git a/bin/tests/system/rndc/ns2/incl.db b/bin/tests/system/rndc/ns2/incl.db
new file mode 100644
index 0000000..bb8b343
--- /dev/null
+++ b/bin/tests/system/rndc/ns2/incl.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; Used for testing $INCLUDE
+$INCLUDE "static.db"
diff --git a/bin/tests/system/rndc/ns2/named.conf.in b/bin/tests/system/rndc/ns2/named.conf.in
new file mode 100644
index 0000000..c3ce3eb
--- /dev/null
+++ b/bin/tests/system/rndc/ns2/named.conf.in
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+key secondkey {
+ secret "abcd1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; secondkey; };
+};
+
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "nil" {
+ type primary;
+ update-policy local;
+ file "nil.db";
+ ixfr-from-differences yes;
+};
+
+zone "other" {
+ type primary;
+ update-policy local;
+ file "other.db";
+};
+
+zone "static" {
+ type primary;
+ file "static.db";
+};
+
+zone "incl" {
+ type primary;
+ file "incl.db";
+};
diff --git a/bin/tests/system/rndc/ns2/secondkey.conf b/bin/tests/system/rndc/ns2/secondkey.conf
new file mode 100644
index 0000000..1b6af7b
--- /dev/null
+++ b/bin/tests/system/rndc/ns2/secondkey.conf
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ default-key "secondkey";
+};
+
+key secondkey {
+ secret "abcd1234abcd8765";
+ algorithm hmac-sha256;
+};
diff --git a/bin/tests/system/rndc/ns3/named.conf.in b/bin/tests/system/rndc/ns3/named.conf.in
new file mode 100644
index 0000000..ed159b4
--- /dev/null
+++ b/bin/tests/system/rndc/ns3/named.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+key secondkey {
+ secret "abcd1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view all {
+ match-clients { any; };
+
+ recursion no;
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+};
+
+view none {
+ match-clients { none; };
+};
diff --git a/bin/tests/system/rndc/ns4/named.conf.in b/bin/tests/system/rndc/ns4/named.conf.in
new file mode 100644
index 0000000..6dc37ec
--- /dev/null
+++ b/bin/tests/system/rndc/ns4/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+};
+
+view normal {
+ match-clients { any; };
+
+ zone example {
+ type primary;
+ file "example.db";
+ allow-update { any; };
+ };
+};
+
+view "view with a space" {
+ match-clients { none; };
+ zone example {
+ in-view normal;
+ };
+};
diff --git a/bin/tests/system/rndc/ns5/named.conf.in b/bin/tests/system/rndc/ns5/named.conf.in
new file mode 100644
index 0000000..e32fa49
--- /dev/null
+++ b/bin/tests/system/rndc/ns5/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; } read-only yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/rndc/ns6/named.args b/bin/tests/system/rndc/ns6/named.args
new file mode 100644
index 0000000..331f7f4
--- /dev/null
+++ b/bin/tests/system/rndc/ns6/named.args
@@ -0,0 +1,3 @@
+# teardown of a huge zone with tracing enabled takes way too long
+# -m none is set so that stop.pl does not timeout
+-D rndc-ns6 -X named.lock -m none -c named.conf -d 99 -g -U 4 -T maxcachesize=2097152
diff --git a/bin/tests/system/rndc/ns6/named.conf.in b/bin/tests/system/rndc/ns6/named.conf.in
new file mode 100644
index 0000000..a465a20
--- /dev/null
+++ b/bin/tests/system/rndc/ns6/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.6; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/rndc/ns7/include.db.in b/bin/tests/system/rndc/ns7/include.db.in
new file mode 100644
index 0000000..011997b
--- /dev/null
+++ b/bin/tests/system/rndc/ns7/include.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 86400 IN SOA ns7 hostmaster 1 5 5 1814400 3600
+@ NS ns7
+ns7 A 10.53.0.7
+
+text1 TXT "include 1"
diff --git a/bin/tests/system/rndc/ns7/include2.db.in b/bin/tests/system/rndc/ns7/include2.db.in
new file mode 100644
index 0000000..e5d1981
--- /dev/null
+++ b/bin/tests/system/rndc/ns7/include2.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 86400 IN SOA ns7 hostmaster 4 5 5 1814400 3600
+@ NS ns7
+ns7 A 10.53.0.7
+
+text1 TXT "include 2"
diff --git a/bin/tests/system/rndc/ns7/named.conf.in b/bin/tests/system/rndc/ns7/named.conf.in
new file mode 100644
index 0000000..2d4bf7f
--- /dev/null
+++ b/bin/tests/system/rndc/ns7/named.conf.in
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.7; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+key int {
+ algorithm @DEFAULT_HMAC@;
+ secret "FrSt77yPTFx6hTs4i2tKLB9LmE0=";
+};
+
+key ext {
+ algorithm @DEFAULT_HMAC@;
+ secret "FrSt77yPTFx6hTs4i2tKLB9LmE0=";
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view internal {
+ match-clients { key "int"; };
+
+ zone "test" {
+ type primary;
+ update-policy { grant int zonesub any; };
+ file "test.db";
+ ixfr-from-differences yes;
+ };
+};
+
+view external {
+ match-clients { key "ext"; };
+
+ zone "test" {
+ in-view internal;
+ };
+};
diff --git a/bin/tests/system/rndc/ns7/test.db.in b/bin/tests/system/rndc/ns7/test.db.in
new file mode 100644
index 0000000..0bff14e
--- /dev/null
+++ b/bin/tests/system/rndc/ns7/test.db.in
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+$INCLUDE "include.db"
diff --git a/bin/tests/system/rndc/setup.sh b/bin/tests/system/rndc/setup.sh
new file mode 100644
index 0000000..85d6b73
--- /dev/null
+++ b/bin/tests/system/rndc/setup.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns2/nil.db
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns2/other.db
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns2/static.db
+
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns4/example.db
+
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns6/huge.zone.db
+
+cp ns7/test.db.in ns7/test.db
+cp ns7/include.db.in ns7/include.db
+
+# we make the huge zone less huge if we're running under
+# TSAN, to give the test a fighting chance not to time out.
+size=1000000
+if $FEATURETEST --tsan; then
+ size=250000
+fi
+awk 'END { for (i = 1; i <= '${size}'; i++)
+ printf "host%d IN A 10.53.0.6\n", i; }' < /dev/null >> ns6/huge.zone.db
+
+copy_setports ns2/named.conf.in ns2/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
+
+make_key () {
+ $RNDCCONFGEN -k key$1 -A $3 -s 10.53.0.4 -p $2 \
+ > ns4/key${1}.conf 2> /dev/null
+ grep -E -v '(^# Start|^# End|^# Use|^[^#])' ns4/key$1.conf | cut -c3- | \
+ sed 's/allow { 10.53.0.4/allow { any/' >> ns4/named.conf
+}
+
+$FEATURETEST --md5 && make_key 1 ${EXTRAPORT1} hmac-md5
+make_key 2 ${EXTRAPORT2} hmac-sha1
+make_key 3 ${EXTRAPORT3} hmac-sha224
+make_key 4 ${EXTRAPORT4} hmac-sha256
+make_key 5 ${EXTRAPORT5} hmac-sha384
+make_key 6 ${EXTRAPORT6} hmac-sha512
+
+cat >> ns4/named.conf <<- EOF
+
+controls {
+ inet 10.53.0.4 port ${EXTRAPORT7}
+ allow { any; } keys { "key1"; "key2"; "key3";
+ "key4"; "key5"; "key6"; };
+};
+EOF
diff --git a/bin/tests/system/rndc/tests.sh b/bin/tests/system/rndc/tests.sh
new file mode 100644
index 0000000..2afaf8c
--- /dev/null
+++ b/bin/tests/system/rndc/tests.sh
@@ -0,0 +1,814 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd"
+DIGOPTS=""
+DIGCMD="$DIG $DIGOPTS -p ${PORT}"
+RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../common/rndc.conf -s"
+
+status=0
+n=0
+
+n=$((n+1))
+echo_i "preparing ($n)"
+ret=0
+$NSUPDATE -p ${PORT} -k ns2/session.key > /dev/null 2>&1 <<END || ret=1
+server 10.53.0.2
+zone nil.
+update add text1.nil. 600 IN TXT "addition 1"
+send
+zone other.
+update add text1.other. 600 IN TXT "addition 1"
+send
+END
+[ -s ns2/nil.db.jnl ] || {
+ echo_i "'test -s ns2/nil.db.jnl' failed when it shouldn't have"; ret=1;
+}
+[ -s ns2/other.db.jnl ] || {
+ echo_i "'test -s ns2/other.db.jnl' failed when it shouldn't have"; ret=1;
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "rndc freeze"
+$RNDCCMD 10.53.0.2 freeze | sed 's/^/ns2 /' | cat_i
+
+n=$((n+1))
+echo_i "checking zone was dumped ($n)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ grep "addition 1" ns2/nil.db > /dev/null && break
+ sleep 1
+done
+grep "addition 1" ns2/nil.db > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking journal file is still present ($n)"
+ret=0
+[ -s ns2/nil.db.jnl ] || {
+ echo_i "'test -s ns2/nil.db.jnl' failed when it shouldn't have"; ret=1;
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking zone not writable ($n)"
+ret=0
+$NSUPDATE -p ${PORT} -k ns2/session.key > /dev/null 2>&1 <<END && ret=1
+server 10.53.0.2
+zone nil.
+update add text2.nil. 600 IN TXT "addition 2"
+send
+END
+
+$DIGCMD @10.53.0.2 text2.nil. TXT > dig.out.1.test$n || ret=1
+grep 'addition 2' dig.out.1.test$n >/dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "rndc thaw"
+$RNDCCMD 10.53.0.2 thaw | sed 's/^/ns2 /' | cat_i
+
+n=$((n+1))
+echo_i "checking zone now writable ($n)"
+ret=0
+$NSUPDATE -p ${PORT} -k ns2/session.key > nsupdate.out.1.test$n 2>&1 <<END || ret=1
+server 10.53.0.2
+zone nil.
+update add text3.nil. 600 IN TXT "addition 3"
+send
+END
+$DIGCMD @10.53.0.2 text3.nil. TXT > dig.out.1.test$n || ret=1
+grep 'addition 3' dig.out.1.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "rndc sync"
+ret=0
+$RNDCCMD 10.53.0.2 sync nil | sed 's/^/ns2 /' | cat_i
+
+n=$((n+1))
+echo_i "checking zone was dumped ($n)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ grep "addition 3" ns2/nil.db > /dev/null && break
+ sleep 1
+done
+grep "addition 3" ns2/nil.db > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking journal file is still present ($n)"
+ret=0
+[ -s ns2/nil.db.jnl ] || {
+ echo_i "'test -s ns2/nil.db.jnl' failed when it shouldn't have"; ret=1;
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking zone is still writable ($n)"
+ret=0
+$NSUPDATE -p ${PORT} -k ns2/session.key > nsupdate.out.1.test$n 2>&1 <<END || ret=1
+server 10.53.0.2
+zone nil.
+update add text4.nil. 600 IN TXT "addition 4"
+send
+END
+
+$DIGCMD @10.53.0.2 text4.nil. TXT > dig.out.1.test$n || ret=1
+grep 'addition 4' dig.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "rndc sync -clean"
+ret=0
+$RNDCCMD 10.53.0.2 sync -clean nil | sed 's/^/ns2 /' | cat_i
+
+n=$((n+1))
+echo_i "checking zone was dumped ($n)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ grep "addition 4" ns2/nil.db > /dev/null && break
+ sleep 1
+done
+grep "addition 4" ns2/nil.db > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking journal file is deleted ($n)"
+ret=0
+[ -s ns2/nil.db.jnl ] && {
+ echo_i "'test -s ns2/nil.db.jnl' failed when it shouldn't have"; ret=1;
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking zone is still writable ($n)"
+ret=0
+$NSUPDATE -p ${PORT} -k ns2/session.key > /dev/null 2>&1 <<END || ret=1
+server 10.53.0.2
+zone nil.
+update add text5.nil. 600 IN TXT "addition 5"
+send
+END
+
+$DIGCMD @10.53.0.2 text4.nil. TXT > dig.out.1.test$n || ret=1
+grep 'addition 4' dig.out.1.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking other journal files not removed ($n)"
+ret=0
+[ -s ns2/other.db.jnl ] || {
+ echo_i "'test -s ns2/other.db.jnl' failed when it shouldn't have"; ret=1;
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "cleaning all zones ($n)"
+$RNDCCMD 10.53.0.2 sync -clean | sed 's/^/ns2 /' | cat_i
+
+n=$((n+1))
+echo_i "checking all journals removed ($n)"
+ret=0
+[ -s ns2/nil.db.jnl ] && {
+ echo_i "'test -s ns2/nil.db.jnl' succeeded when it shouldn't have"; ret=1;
+}
+[ -s ns2/other.db.jnl ] && {
+ echo_i "'test -s ns2/other.db.jnl' succeeded when it shouldn't have"; ret=1;
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that freezing static zones is not allowed ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 freeze static > rndc.out.1.test$n 2>&1 && ret=1
+grep 'not dynamic' rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that journal is removed when serial is changed before thaw ($n)"
+ret=0
+sleep 1
+$NSUPDATE -p ${PORT} -k ns2/session.key > nsupdate.out.1.test$n 2>&1 <<END || ret=1
+server 10.53.0.2
+zone other.
+update add text6.other. 600 IN TXT "addition 6"
+send
+END
+[ -s ns2/other.db.jnl ] || {
+ echo_i "'test -s ns2/other.db.jnl' failed when it shouldn't have"; ret=1;
+}
+$RNDCCMD 10.53.0.2 freeze other 2>&1 | sed 's/^/ns2 /' | cat_i
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ grep "addition 6" ns2/other.db > /dev/null && break
+ sleep 1
+done
+serial=$(awk '$3 ~ /serial/ {print $1}' ns2/other.db)
+newserial=$((serial + 1))
+sed s/$serial/$newserial/ ns2/other.db > ns2/other.db.new
+echo 'frozen TXT "frozen addition"' >> ns2/other.db.new
+mv -f ns2/other.db.new ns2/other.db
+$RNDCCMD 10.53.0.2 thaw 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 1
+[ -f ns2/other.db.jnl ] && {
+ echo_i "'test -f ns2/other.db.jnl' succeeded when it shouldn't have"; ret=1;
+}
+$NSUPDATE -p ${PORT} -k ns2/session.key > nsupdate.out.2.test$n 2>&1 <<END || ret=1
+server 10.53.0.2
+zone other.
+update add text7.other. 600 IN TXT "addition 7"
+send
+END
+$DIGCMD @10.53.0.2 text6.other. TXT > dig.out.1.test$n || ret=1
+grep 'addition 6' dig.out.1.test$n >/dev/null || ret=1
+$DIGCMD @10.53.0.2 text7.other. TXT > dig.out.2.test$n || ret=1
+grep 'addition 7' dig.out.2.test$n >/dev/null || ret=1
+$DIGCMD @10.53.0.2 frozen.other. TXT > dig.out.3.test$n || ret=1
+grep 'frozen addition' dig.out.3.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that journal is kept when ixfr-from-differences is in use ($n)"
+ret=0
+$NSUPDATE -p ${PORT} -k ns2/session.key > nsupdate.out.1.test$n 2>&1 <<END || ret=1
+server 10.53.0.2
+zone nil.
+update add text6.nil. 600 IN TXT "addition 6"
+send
+END
+[ -s ns2/nil.db.jnl ] || {
+ echo_i "'test -s ns2/nil.db.jnl' failed when it shouldn't have"; ret=1;
+}
+$RNDCCMD 10.53.0.2 freeze nil 2>&1 | sed 's/^/ns2 /' | cat_i
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ grep "addition 6" ns2/nil.db > /dev/null && break
+ sleep 1
+done
+serial=$(awk '$3 ~ /serial/ {print $1}' ns2/nil.db)
+newserial=$((serial + 1))
+sed s/$serial/$newserial/ ns2/nil.db > ns2/nil.db.new
+echo 'frozen TXT "frozen addition"' >> ns2/nil.db.new
+mv -f ns2/nil.db.new ns2/nil.db
+$RNDCCMD 10.53.0.2 thaw 2>&1 | sed 's/^/ns2 /' | cat_i
+sleep 1
+[ -s ns2/nil.db.jnl ] || {
+ echo_i "'test -s ns2/nil.db.jnl' failed when it shouldn't have"; ret=1;
+}
+$NSUPDATE -p ${PORT} -k ns2/session.key > nsupdate.out.2.test$n 2>&1 <<END || ret=1
+server 10.53.0.2
+zone nil.
+update add text7.nil. 600 IN TXT "addition 7"
+send
+END
+$DIGCMD @10.53.0.2 text6.nil. TXT > dig.out.1.test$n || ret=1
+grep 'addition 6' dig.out.1.test$n > /dev/null || ret=1
+$DIGCMD @10.53.0.2 text7.nil. TXT > dig.out.2.test$n || ret=1
+grep 'addition 7' dig.out.2.test$n > /dev/null || ret=1
+$DIGCMD @10.53.0.2 frozen.nil. TXT > dig.out.3.test$n || ret=1
+grep 'frozen addition' dig.out.3.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# temp test
+echo_i "dumping stats ($n)"
+$RNDCCMD 10.53.0.2 stats
+n=$((n+1))
+echo_i "verifying adb records in named.stats ($n)"
+grep "ADB stats" ns2/named.stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "test using second key ($n)"
+ret=0
+$RNDC -s 10.53.0.2 -p ${CONTROLPORT} -c ns2/secondkey.conf status > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "test 'rndc dumpdb' on a empty cache ($n)"
+ret=0
+rndc_dumpdb ns3 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "test 'rndc reload' on a zone with include files ($n)"
+ret=0
+grep "incl/IN: skipping load" ns2/named.run > /dev/null && ret=1
+loads=$(grep "incl/IN: starting load" ns2/named.run | wc -l)
+[ "$loads" -eq 1 ] || ret=1
+$RNDCCMD 10.53.0.2 reload > /dev/null || ret=1
+for i in 1 2 3 4 5 6 7 8 9
+do
+ tmp=0
+ grep "incl/IN: skipping load" ns2/named.run > /dev/null || tmp=1
+ [ $tmp -eq 0 ] && break
+ sleep 1
+done
+[ $tmp -eq 1 ] && ret=1
+touch ns2/static.db
+$RNDCCMD 10.53.0.2 reload > /dev/null || ret=1
+for i in 1 2 3 4 5 6 7 8 9
+do
+ tmp=0
+ loads=$(grep "incl/IN: starting load" ns2/named.run | wc -l)
+ [ "$loads" -eq 2 ] || tmp=1
+ [ $tmp -eq 0 ] && break
+ sleep 1
+done
+[ $tmp -eq 1 ] && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+if $FEATURETEST --md5; then
+ echo_i "testing rndc with hmac-md5 ($n)"
+ ret=0
+ $RNDC -s 10.53.0.4 -p ${EXTRAPORT1} -c ns4/key1.conf status > /dev/null 2>&1 || ret=1
+ for i in 2 3 4 5 6
+ do
+ $RNDC -s 10.53.0.4 -p ${EXTRAPORT1} -c ns4/key${i}.conf status > /dev/null 2>&1 && ret=1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+else
+ echo_i "skipping rndc with hmac-md5 ($n)"
+fi
+
+n=$((n+1))
+echo_i "testing rndc with hmac-sha1 ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT2} -c ns4/key2.conf status > /dev/null 2>&1 || ret=1
+for i in 1 3 4 5 6
+do
+ $RNDC -s 10.53.0.4 -p ${EXTRAPORT2} -c ns4/key${i}.conf status > /dev/null 2>&1 && ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing rndc with hmac-sha224 ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT3} -c ns4/key3.conf status > /dev/null 2>&1 || ret=1
+for i in 1 2 4 5 6
+do
+ $RNDC -s 10.53.0.4 -p ${EXTRAPORT3} -c ns4/key${i}.conf status > /dev/null 2>&1 && ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing rndc with hmac-sha256 ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT4} -c ns4/key4.conf status > /dev/null 2>&1 || ret=1
+for i in 1 2 3 5 6
+do
+ $RNDC -s 10.53.0.4 -p ${EXTRAPORT4} -c ns4/key${i}.conf status > /dev/null 2>&1 && ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing rndc with hmac-sha384 ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT5} -c ns4/key5.conf status > /dev/null 2>&1 || ret=1
+for i in 1 2 3 4 6
+do
+ $RNDC -s 10.53.0.4 -p ${EXTRAPORT5} -c ns4/key${i}.conf status > /dev/null 2>&1 && ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing rndc with hmac-sha512 ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf status > /dev/null 2>&1 || ret=1
+for i in 1 2 3 4 5
+do
+ $RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key${i}.conf status > /dev/null 2>&1 2>&1 && ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing single control channel with multiple algorithms ($n)"
+ret=0
+for i in 1 2 3 4 5 6
+do
+ $RNDC -s 10.53.0.4 -p ${EXTRAPORT7} -c ns4/key${i}.conf status > /dev/null 2>&1 || ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing automatic zones are reported ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf status > rndc.out.1.test$n || ret=1
+grep "number of zones: 201 (198 automatic)" rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing rndc with null command ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing rndc with unknown control channel command ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf obviouslynotacommand >/dev/null 2>&1 && ret=1
+# rndc: 'obviouslynotacommand' failed: unknown command
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing rndc with querylog command ($n)"
+ret=0
+# first enable it with querylog on option
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf querylog on >/dev/null 2>&1 || ret=1
+grep "query logging is now on" ns4/named.run > /dev/null || ret=1
+# query for builtin and check if query was logged (without +subnet)
+$DIG @10.53.0.4 -p ${PORT} -c ch -t txt foo12345.bind +qr > dig.out.1.test$n 2>&1 || ret=1
+grep "query: foo12345.bind CH TXT.*(.*)$" ns4/named.run > /dev/null || ret=1
+# query for another builtin zone and check if query was logged (with +subnet=127.0.0.1)
+$DIG +subnet=127.0.0.1 @10.53.0.4 -p ${PORT} -c ch -t txt foo12346.bind +qr > dig.out.2.test$n 2>&1 || ret=1
+grep "query: foo12346.bind CH TXT.*\[ECS 127\.0\.0\.1/32/0]" ns4/named.run > /dev/null || ret=1
+# query for another builtin zone and check if query was logged (with +subnet=127.0.0.1/24)
+$DIG +subnet=127.0.0.1/24 @10.53.0.4 -p ${PORT} -c ch -t txt foo12347.bind +qr > dig.out.3.test$n 2>&1 || ret=1
+grep "query: foo12347.bind CH TXT.*\[ECS 127\.0\.0\.0/24/0]" ns4/named.run > /dev/null || ret=1
+# query for another builtin zone and check if query was logged (with +subnet=::1)
+$DIG +subnet=::1 @10.53.0.4 -p ${PORT} -c ch -t txt foo12348.bind +qr > dig.out.4.test$n 2>&1 || ret=1
+grep "query: foo12348.bind CH TXT.*\[ECS ::1/128/0]" ns4/named.run > /dev/null || ret=1
+# toggle query logging and check again
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf querylog > /dev/null 2>&1 || ret=1
+grep "query logging is now off" ns4/named.run > /dev/null || ret=1
+# query for another builtin zone and check if query was logged (without +subnet)
+$DIG @10.53.0.4 -p ${PORT} -c ch -t txt foo9876.bind +qr > dig.out.5.test$n 2>&1 || ret=1
+grep "query: foo9876.bind CH TXT.*(.*)$" ns4/named.run > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+RNDCCMD4="$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf"
+n=$((n+1))
+echo_i "testing rndc nta time limits ($n)"
+ret=0
+$RNDCCMD4 nta -l 2h nta1.example > rndc.out.1.test$n 2>&1
+grep "Negative trust anchor added" rndc.out.1.test$n > /dev/null || ret=1
+$RNDCCMD4 nta -l 1d nta2.example > rndc.out.2.test$n 2>&1
+grep "Negative trust anchor added" rndc.out.2.test$n > /dev/null || ret=1
+$RNDCCMD4 nta -l 1w nta3.example > rndc.out.3.test$n 2>&1
+grep "Negative trust anchor added" rndc.out.3.test$n > /dev/null || ret=1
+$RNDCCMD4 nta -l 8d nta4.example > rndc.out.4.test$n 2>&1 && ret=1
+grep "NTA lifetime cannot exceed one week" rndc.out.4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing rndc nta -class option ($n)"
+ret=0
+nextpart ns4/named.run > /dev/null
+$RNDCCMD4 nta -c in nta1.example > rndc.out.1.test$n 2>&1
+nextpart ns4/named.run | grep "added NTA 'nta1.example'" > /dev/null || ret=1
+$RNDCCMD4 nta -c any nta1.example > rndc.out.2.test$n 2>&1
+nextpart ns4/named.run | grep "added NTA 'nta1.example'" > /dev/null || ret=1
+$RNDCCMD4 nta -c ch nta1.example > rndc.out.3.test$n 2>&1
+nextpart ns4/named.run | grep "added NTA 'nta1.example'" > /dev/null && ret=1
+$RNDCCMD4 nta -c fake nta1.example > rndc.out.4.test$n 2>&1 && ret=1
+nextpart ns4/named.run | grep "added NTA 'nta1.example'" > /dev/null && ret=1
+grep 'unknown class' rndc.out.4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+for i in 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288
+do
+ n=$((n+1))
+ echo_i "testing rndc buffer size limits (size=${i}) ($n)"
+ ret=0
+ $RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf testgen ${i} 2>&1 > rndc.out.$i.test$n || ret=1
+ { actual_size=$($GENCHECK rndc.out.$i.test$n); rc=$?; } || true
+ if [ "$rc" = "0" ]; then
+ expected_size=$((i+1))
+ if [ $actual_size != $expected_size ]; then ret=1; fi
+ else
+ ret=1
+ fi
+
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+done
+
+n=$((n+1))
+echo_i "testing rndc -r (show result) ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf -r testgen 0 2>&1 > rndc.out.1.test$n || ret=1
+grep "ISC_R_SUCCESS 0" rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "testing rndc with a token containing a space ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf -r flush '"view with a space"' 2>&1 > rndc.out.1.test$n || ret=1
+grep "not found" rndc.out.1.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "test 'rndc reconfig' with a broken config ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf reconfig > /dev/null || ret=1
+sleep 1
+mv ns4/named.conf ns4/named.conf.save
+echo "error error error" >> ns4/named.conf
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf reconfig > rndc.out.1.test$n 2>&1 && ret=1
+grep "rndc: 'reconfig' failed: unexpected token" rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check rndc status reports failure ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf status > rndc.out.1.test$n 2>&1 || ret=1
+grep "reload/reconfig failed" rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "restore working config ($n)"
+ret=0
+mv ns4/named.conf.save ns4/named.conf
+sleep 1
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf reconfig > /dev/null || ret=1
+sleep 1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc status' 'reload/reconfig failure' is cleared after successful reload/reconfig ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf status > rndc.out.1.test$n 2>&1 || ret=1
+grep "reload/reconfig failed" rndc.out.1.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "test read-only control channel access ($n)"
+ret=0
+$RNDCCMD 10.53.0.5 status > rndc.out.1.test$n 2>&1 || ret=1
+$RNDCCMD 10.53.0.5 nta -dump > rndc.out.2.test$n 2>&1 || ret=1
+$RNDCCMD 10.53.0.5 reconfig > rndc.out.3.test$n 2>&1 && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "test rndc status shows running on ($n)"
+ret=0
+$RNDCCMD 10.53.0.5 status > rndc.out.1.test$n 2>&1 || ret=1
+grep "^running on " rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "test 'rndc reconfig' with loading of a large zone ($n)"
+ret=0
+nextpart ns6/named.run > /dev/null
+cp ns6/named.conf ns6/named.conf.save
+echo "zone \"huge.zone\" { type primary; file \"huge.zone.db\"; };" >> ns6/named.conf
+echo_i "reloading config"
+$RNDCCMD 10.53.0.6 reconfig > rndc.out.1.test$n 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+sleep 1
+
+n=$((n+1))
+echo_i "check if zone load was scheduled ($n)"
+wait_for_log_peek 20 "scheduled loading new zones" ns6/named.run || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check if query for the zone returns SERVFAIL ($n)"
+$DIG @10.53.0.6 -p ${PORT} -t soa huge.zone > dig.out.1.test$n
+grep "SERVFAIL" dig.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed (ignored)"; ret=0; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "wait for the zones to be loaded ($n)"
+wait_for_log_peek 60 "huge.zone/IN: loaded serial" ns6/named.run || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check if query for the zone returns NOERROR ($n)"
+$DIG @10.53.0.6 -p ${PORT} -t soa huge.zone > dig.out.1.test$n
+grep "NOERROR" dig.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verify that the full command is logged ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 null with extra arguments > /dev/null 2>&1
+grep "received control channel command 'null with extra arguments'" ns2/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+mv ns6/named.conf.save ns6/named.conf
+sleep 1
+$RNDCCMD 10.53.0.6 reconfig > /dev/null || ret=1
+sleep 1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc \"\"' is handled ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 "" > rndc.out.1.test$n 2>&1 && ret=1
+grep "rndc: '' failed: failure" rndc.out.1.test$n > /dev/null
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check rndc -4 -6 ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 -4 -6 status > rndc.out.1.test$n 2>&1 && ret=1
+grep "only one of -4 and -6 allowed" rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check rndc -4 with an IPv6 server address ($n)"
+ret=0
+$RNDCCMD fd92:7065:b8e:ffff::2 -4 status > rndc.out.1.test$n 2>&1 && ret=1
+grep "address family not supported" rndc.out.1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check rndc nta reports adding to multiple views ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 nta test.com > rndc.out.test$n 2>&1 || ret=1
+lines=$(cat rndc.out.test$n | wc -l)
+[ ${lines:-0} -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc retransfer' of primary error message ($n)"
+ret=0
+$RNDCCMD 10.53.0.2 retransfer nil > rndc.out.test$n 2>&1 && ret=1
+grep "rndc: 'retransfer' failed: failure" rndc.out.test$n > /dev/null || ret=1
+grep "retransfer: inappropriate zone type: primary" rndc.out.test$n > /dev/null || ret=1
+lines=$(cat rndc.out.test$n | wc -l)
+[ ${lines:-0} -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc freeze' with in-view zones works ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf freeze > rndc.out.test$n 2>&1 || ret=1
+test -s rndc.out.test$n && sed 's/^/ns2 /' rndc.out.test$n | cat_i
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking non in-view zone instance is not writable ($n)"
+ret=0
+$NSUPDATE -p ${PORT} > /dev/null 2>&1 <<END && ret=1
+server 10.53.0.4
+zone example.
+update add text2.example. 600 IN TXT "addition 3"
+send
+END
+$DIGCMD @10.53.0.4 -p ${PORT} text2.example. TXT > dig.out.1.test$n || ret=1
+grep 'addition 3' dig.out.1.test$n >/dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc thaw' with in-view zones works ($n)"
+ret=0
+$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf thaw > rndc.out.test$n 2>&1 || ret=1
+test -s rndc.out.test$n && sed 's/^/ns2 /' rndc.out.test$n | cat_i
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking non in-view zone instance is now writable ($n)"
+ret=0
+$NSUPDATE -p ${PORT} > nsupdate.out.test$n 2>&1 <<END || ret=1
+server 10.53.0.4
+zone example.
+update add text2.example. 600 IN TXT "addition 3"
+send
+END
+$DIGCMD @10.53.0.4 -p ${PORT} text2.example. TXT > dig.out.1.test$n || ret=1
+grep 'addition 3' dig.out.1.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking initial in-view zone file is loaded ($n)"
+ret=0
+TSIG="$DEFAULT_HMAC:int:FrSt77yPTFx6hTs4i2tKLB9LmE0="
+$DIGCMD @10.53.0.7 -y "$TSIG" text1.test. TXT > dig.out.1.test$n || ret=1
+grep 'include 1' dig.out.1.test$n >/dev/null || ret=1
+TSIG="$DEFAULT_HMAC:ext:FrSt77yPTFx6hTs4i2tKLB9LmE0="
+$DIGCMD @10.53.0.7 -y "$TSIG" text1.test. TXT > dig.out.2.test$n || ret=1
+grep 'include 1' dig.out.2.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "update in-view zone ($n)"
+ret=0
+TSIG="$DEFAULT_HMAC:int:FrSt77yPTFx6hTs4i2tKLB9LmE0="
+$NSUPDATE -p ${PORT} -y "$TSIG" > /dev/null 2>&1 <<END || ret=1
+server 10.53.0.7
+zone test.
+update add text2.test. 600 IN TXT "addition 1"
+send
+END
+[ -s ns7/test.db.jnl ] || {
+ echo_i "'test -s ns7/test.db.jnl' failed when it shouldn't have"; ret=1;
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking update ($n)"
+ret=0
+TSIG="$DEFAULT_HMAC:int:FrSt77yPTFx6hTs4i2tKLB9LmE0="
+$DIGCMD @10.53.0.7 -y "$TSIG" text2.test. TXT > dig.out.1.test$n || ret=1
+grep 'addition 1' dig.out.1.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns7/named.run > /dev/null
+
+echo_i "rndc freeze"
+$RNDCCMD 10.53.0.7 freeze | sed 's/^/ns7 /' | cat_i | cat_i
+
+wait_for_log 3 "dump_done: zone test/IN/internal: enter" ns7/named.run
+
+echo_i "edit zone files"
+cp ns7/test.db.in ns7/test.db
+cp ns7/include2.db.in ns7/include.db
+
+echo_i "rndc thaw"
+$RNDCCMD 10.53.0.7 thaw | sed 's/^/ns7 /' | cat_i
+
+wait_for_log 3 "zone_postload: zone test/IN/internal: done" ns7/named.run
+
+echo_i "rndc reload"
+$RNDCCMD 10.53.0.7 reload | sed 's/^/ns7 /' | cat_i
+
+wait_for_log 3 "all zones loaded" ns7/named.run
+
+n=$((n+1))
+echo_i "checking zone file edits are loaded ($n)"
+ret=0
+TSIG="$DEFAULT_HMAC:int:FrSt77yPTFx6hTs4i2tKLB9LmE0="
+$DIGCMD @10.53.0.7 -y "$TSIG" text1.test. TXT > dig.out.1.test$n || ret=1
+grep 'include 2' dig.out.1.test$n >/dev/null || ret=1
+TSIG="$DEFAULT_HMAC:ext:FrSt77yPTFx6hTs4i2tKLB9LmE0="
+$DIGCMD @10.53.0.7 -y "$TSIG" text1.test. TXT > dig.out.2.test$n || ret=1
+grep 'include 2' dig.out.2.test$n >/dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rndc/tests_sh_rndc.py b/bin/tests/system/rndc/tests_sh_rndc.py
new file mode 100644
index 0000000..ac6a4dc
--- /dev/null
+++ b/bin/tests/system/rndc/tests_sh_rndc.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_rndc(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/rootkeysentinel/clean.sh b/bin/tests/system/rootkeysentinel/clean.sh
new file mode 100644
index 0000000..e9cd3cc
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.ns?.test*
+rm -f */dsset-*
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f */trusted.conf
+rm -f ns1/K.*
+rm -f ns1/root.db
+rm -f ns1/root.db.signed
+rm -f ns2/Kexample.*
+rm -f ns2/example.db
+rm -f ns2/example.db.signed
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/rootkeysentinel/ns1/named.conf.in b/bin/tests/system/rootkeysentinel/ns1/named.conf.in
new file mode 100644
index 0000000..930f3bc
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns1/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/rootkeysentinel/ns1/root.db.in b/bin/tests/system/rootkeysentinel/ns1/root.db.in
new file mode 100644
index 0000000..cc97041
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns1/root.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA marka.isc.org. a.root.servers.nil. (
+ 2018031400 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/rootkeysentinel/ns1/sign.sh b/bin/tests/system/rootkeysentinel/ns1/sign.sh
new file mode 100644
index 0000000..0f20053
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns1/sign.sh
@@ -0,0 +1,35 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyid=$(expr ${keyname} : 'K.+[0-9][0-9][0-9]+\(.*\)')
+
+(cd ../ns2 && $SHELL sign.sh ${keyid:-00000} )
+
+cp ../ns2/dsset-example. .
+
+cat $infile $keyname.key > $zonefile
+
+$SIGNER -P -g -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a static key.
+keyfile_to_static_ds $keyname > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+cp trusted.conf ../ns3/trusted.conf
+cp trusted.conf ../ns4/trusted.conf
diff --git a/bin/tests/system/rootkeysentinel/ns2/example.db.in b/bin/tests/system/rootkeysentinel/ns2/example.db.in
new file mode 100644
index 0000000..92ca3bf
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns2/example.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2018031400 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
diff --git a/bin/tests/system/rootkeysentinel/ns2/named.conf.in b/bin/tests/system/rootkeysentinel/ns2/named.conf.in
new file mode 100644
index 0000000..25e4e50
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns2/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+};
+
+zone "example" {
+ type primary;
+ file "example.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/rootkeysentinel/ns2/sign.sh b/bin/tests/system/rootkeysentinel/ns2/sign.sh
new file mode 100644
index 0000000..3e48f8a
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns2/sign.sh
@@ -0,0 +1,40 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+oldid=$(echo ${1:-0} | sed 's/^0*//')
+newid=$(printf '%05u' $(((oldid + 1000) % 65536)))
+badid=$(printf '%05u' $(((oldid + 7777) % 65536)))
+oldid=$(printf '%05u' $((oldid + 0)))
+
+. ../../conf.sh
+
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+keyname1=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone)
+keyname2=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone)
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+echo root-key-sentinel-is-ta-$oldid A 10.53.0.1 >> $zonefile
+echo root-key-sentinel-not-ta-$oldid A 10.53.0.2 >> $zonefile
+echo root-key-sentinel-is-ta-$newid A 10.53.0.3 >> $zonefile
+echo root-key-sentinel-not-ta-$newid A 10.53.0.4 >> $zonefile
+echo old-is-ta CNAME root-key-sentinel-is-ta-$oldid >> $zonefile
+echo old-not-ta CNAME root-key-sentinel-not-ta-$oldid >> $zonefile
+echo new-is-ta CNAME root-key-sentinel-is-ta-$newid >> $zonefile
+echo new-not-ta CNAME root-key-sentinel-not-ta-$newid >> $zonefile
+echo bad-is-ta CNAME root-key-sentinel-is-ta-$badid >> $zonefile
+echo bad-not-ta CNAME root-key-sentinel-not-ta-$badid >> $zonefile
+
+$SIGNER -P -g -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
diff --git a/bin/tests/system/rootkeysentinel/ns3/hint.db b/bin/tests/system/rootkeysentinel/ns3/hint.db
new file mode 100644
index 0000000..0018b52
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns3/hint.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
diff --git a/bin/tests/system/rootkeysentinel/ns3/named.conf.in b/bin/tests/system/rootkeysentinel/ns3/named.conf.in
new file mode 100644
index 0000000..c9682c9
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns3/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation yes;
+ root-key-sentinel yes;
+};
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/rootkeysentinel/ns4/hint.db b/bin/tests/system/rootkeysentinel/ns4/hint.db
new file mode 100644
index 0000000..0018b52
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns4/hint.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
diff --git a/bin/tests/system/rootkeysentinel/ns4/named.conf.in b/bin/tests/system/rootkeysentinel/ns4/named.conf.in
new file mode 100644
index 0000000..6f60ffd
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/ns4/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation yes;
+ root-key-sentinel no;
+};
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/rootkeysentinel/setup.sh b/bin/tests/system/rootkeysentinel/setup.sh
new file mode 100644
index 0000000..39e1edf
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
+
+cd ns1
+$SHELL sign.sh
diff --git a/bin/tests/system/rootkeysentinel/tests.sh b/bin/tests/system/rootkeysentinel/tests.sh
new file mode 100644
index 0000000..bfe653c
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/tests.sh
@@ -0,0 +1,295 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+
+newtest() {
+ n=$((n + 1))
+ case $# in
+ 1)
+ echo_i "$1 ($n)"
+ ;;
+ 2)
+ echo_i "$1"
+ echo_ic "$2 ($n)"
+ ;;
+ esac
+ ret=0
+}
+
+newtest "get test ids"
+$DIG $DIGOPTS . dnskey +short +rrcomm @10.53.0.1 > dig.out.ns1.test$n || ret=1
+oldid=$(sed -n 's/.*key id = //p' < dig.out.ns1.test$n)
+newid=$(printf "%05u" $(((oldid + 1000) % 65536)))
+badid=$(printf "%05u" $(((oldid + 7777) % 65536)))
+oldid=$(printf "%05u" $((oldid + 0)))
+echo_i "test id: oldid=${oldid} (configured)"
+echo_i "test id: newid=${newid} (not configured)"
+echo_i "test id: badid=${badid}"
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check authoritative server (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.2 example SOA > dig.out.ns2.test$n
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check test zone resolves with 'root-key-sentinel yes;'" " (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.3 example SOA > dig.out.ns3.test$n
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-${oldid}.example A > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel yes;' (expect SERVFAIL)"
+$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-${oldid}.example A > dig.out.ns3.test$n || ret=1
+grep "status: SERVFAIL" dig.out.ns3.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-not-ta with old ta, CD=1 and" " 'root-key-sentinel yes;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.3 +cd root-key-sentinel-not-ta-${oldid}.example A > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel yes;' (expect SERVFAIL)"
+$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-${newid}.example A > dig.out.ns3.test$n || ret=1
+grep "status: SERVFAIL" dig.out.ns3.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with new ta, CD=1 and" " 'root-key-sentinel yes;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.3 +cd root-key-sentinel-is-ta-${newid}.example A > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-${newid}.example A > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel yes;' (expect SERVFAIL)"
+$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-${badid}.example A > dig.out.ns3.test$n || ret=1
+grep "status: SERVFAIL" dig.out.ns3.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with bad ta, CD=1 and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.3 +cd root-key-sentinel-is-ta-${badid}.example A > dig.out.ns3.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-${badid}.example A > dig.out.ns3.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with out-of-range ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-72345.example A > dig.out.ns3.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-not-ta with out-of-range ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-72345.example A > dig.out.ns3.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with no-zero-pad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-1234.example A > dig.out.ns3.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-not-ta with no-zero-pad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-1234.example A > dig.out.ns3.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.3 old-is-ta.example A > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "old-is-ta.*CNAME.root-key-sentinel-is-ta-${oldid}.example." dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.3 old-not-ta.example A > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "old-not-ta.*CNAME.root-key-sentinel-not-ta-${oldid}.example." dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.3 new-is-ta.example A > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "new-is-ta.*CNAME.root-key-sentinel-is-ta-${newid}.example." dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.3 new-not-ta.example A > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+grep "new-not-ta.*CNAME.root-key-sentinel-not-ta-${newid}.example." dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.3 bad-is-ta.example A > dig.out.ns3.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+grep "bad-is-ta.*CNAME.root-key-sentinel-is-ta-${badid}.example" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.3 bad-not-ta.example A > dig.out.ns3.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+grep "bad-not-ta.*CNAME.root-key-sentinel-not-ta-${badid}.example." dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check test zone resolves with 'root-key-sentinel no;'" " (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.4 example SOA > dig.out.ns4.test$n
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-${oldid}.example A > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-${oldid}.example A > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-${newid}.example A > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-${newid}.example A > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-${badid}.example A > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-${badid}.example A > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with out-of-range ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-72345.example A > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-not-ta with out-of-range ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-72345.example A > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-is-ta with no-zero-pad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-1234.example A > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check root-key-sentinel-not-ta with no-zero-pad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-1234.example A > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.4 old-is-ta.example A > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "old-is-ta.*CNAME.root-key-sentinel-is-ta-${oldid}.example." dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.4 old-not-ta.example A > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "old-not-ta.*CNAME.root-key-sentinel-not-ta-${oldid}.example." dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.4 new-is-ta.example A > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "new-is-ta.*CNAME.root-key-sentinel-is-ta-${newid}.example." dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)"
+$DIG $DIGOPTS @10.53.0.4 new-not-ta.example A > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "new-not-ta.*CNAME.root-key-sentinel-not-ta-${newid}.example." dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.4 bad-is-ta.example A > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "bad-is-ta.*CNAME.root-key-sentinel-is-ta-${badid}.example" dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+newtest "check CNAME to root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
+$DIG $DIGOPTS @10.53.0.4 bad-not-ta.example A > dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "bad-not-ta.*CNAME.root-key-sentinel-not-ta-${badid}.example." dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rootkeysentinel/tests_sh_rootkeysentinel.py b/bin/tests/system/rootkeysentinel/tests_sh_rootkeysentinel.py
new file mode 100644
index 0000000..d1090d0
--- /dev/null
+++ b/bin/tests/system/rootkeysentinel/tests_sh_rootkeysentinel.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_rootkeysentinel(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/rpz/README b/bin/tests/system/rpz/README
new file mode 100644
index 0000000..238e360
--- /dev/null
+++ b/bin/tests/system/rpz/README
@@ -0,0 +1,36 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+The test setup for the RPZ tests prepares a query perf tool and sets up
+policy zones.
+
+Name servers
+------------
+
+ns1 is the root server.
+
+ns2 and ns4 are authoritative servers for the various test domains.
+
+ns3 is the main rewriting resolver.
+
+ns5 and ns7 are additional rewriting resolvers.
+
+ns6 is a forwarding server.
+
+
+Updating the response policy zones
+----------------------------------
+
+test1, test2, test3, test4, test5, and test6 are dynamic update files. These
+updates are made against ns3. The script function "start_group" is called to
+start an new batch of tests that may depend on certain server updates. The
+function takes an optional file name and if provided the server updates are
+performed before executing the test batch.
diff --git a/bin/tests/system/rpz/clean.sh b/bin/tests/system/rpz/clean.sh
new file mode 100644
index 0000000..35d6211
--- /dev/null
+++ b/bin/tests/system/rpz/clean.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Clean up after rpz tests.
+
+USAGE="$0: [-Px]"
+DEBUG=
+while getopts "Px" c; do
+ case $c in
+ x) set -x ;;
+ P) PARTIAL=set ;;
+ *) echo "$USAGE" 1>&2; exit 1;;
+ esac
+done
+shift $((OPTIND - 1))
+if test "$#" -ne 0; then
+ echo "$USAGE" 1>&2
+ exit 1
+fi
+
+# this might be called from setup.sh to partially clean up the files
+# from the first test pass so the second pass can be set up correctly.
+# remove those files first, then decide whether to remove the others.
+rm -f ns*/*.key ns*/*.private
+rm -f ns2/tld2s.db */bl.tld2.db */bl.tld2s.db
+rm -f ns3/bl*.db ns3/fast-expire.db ns*/empty.db
+rm -f ns3/manual-update-rpz.db
+rm -f ns3/mixed-case-rpz.db
+rm -f ns5/example.db ns5/bl.db ns5/fast-expire.db ns5/expire.conf
+rm -f ns8/manual-update-rpz.db
+rm -f */policy2.db
+rm -f */*.jnl
+
+if [ ${PARTIAL:-unset} = unset ]; then
+ rm -f proto.* dsset-* trusted.conf dig.out* nsupdate.tmp ns*/*tmp
+ rm -f ns5/requests ns5/*.perf
+ rm -f */named.memstats */*.run */*.run.prev */named.stats */session.key
+ rm -f */*.log */*core */*.pid
+ rm -f ns*/named.lock
+ rm -f ns*/named.conf
+ rm -f ns*/*switch
+ rm -f dnsrps*.conf
+ rm -f dnsrpzd.conf
+ rm -f dnsrpzd-license-cur.conf dnsrpzd.rpzf dnsrpzd.sock dnsrpzd.pid
+ rm -f ns*/managed-keys.bind*
+ rm -f tmp
+fi
diff --git a/bin/tests/system/rpz/dnsrps.c b/bin/tests/system/rpz/dnsrps.c
new file mode 100644
index 0000000..55d8a91
--- /dev/null
+++ b/bin/tests/system/rpz/dnsrps.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * -a exit(0) if dnsrps is available or dlopen() msg if not
+ * -p print the path to dnsrpzd configured in dnsrps so that
+ * dnsrpzd can be run by a setup.sh script.
+ * Exit(1) if dnsrps is not available
+ * -n domain print the serial number of a domain to check if a new
+ * version of a policy zone has been transferred to dnsrpzd.
+ * Exit(1) if dnsrps is not available
+ * -w sec.ond wait for seconds, because `sleep 0.1` is not portable
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <isc/print.h>
+#include <isc/util.h>
+
+#ifdef USE_DNSRPS
+#define LIBRPZ_LIB_OPEN DNSRPS_LIB_OPEN
+#include <dns/librpz.h>
+
+librpz_t *librpz;
+#else /* ifdef USE_DNSRPS */
+typedef struct {
+ char c[120];
+} librpz_emsg_t;
+#endif /* ifdef USE_DNSRPS */
+
+static bool
+link_dnsrps(librpz_emsg_t *emsg);
+
+#define USAGE "usage: [-ap] [-n domain] [-w sec.onds]\n"
+
+int
+main(int argc, char **argv) {
+#ifdef USE_DNSRPS
+ char cstr[sizeof("zone ") + 1024 + 10];
+ librpz_clist_t *clist;
+ librpz_client_t *client;
+ librpz_rsp_t *rsp;
+ uint32_t serial;
+#endif /* ifdef USE_DNSRPS */
+ double seconds;
+ librpz_emsg_t emsg;
+ char *p;
+ int i;
+
+ while ((i = getopt(argc, argv, "apn:w:")) != -1) {
+ switch (i) {
+ case 'a':
+ if (!link_dnsrps(&emsg)) {
+ printf("I:%s\n", emsg.c);
+ return (1);
+ }
+ return (0);
+
+ case 'p':
+ if (!link_dnsrps(&emsg)) {
+ fprintf(stderr, "## %s\n", emsg.c);
+ return (1);
+ }
+#ifdef USE_DNSRPS
+ printf("%s\n", librpz->dnsrpzd_path);
+#else /* ifdef USE_DNSRPS */
+ UNREACHABLE();
+#endif /* ifdef USE_DNSRPS */
+ return (0);
+
+ case 'n':
+ if (!link_dnsrps(&emsg)) {
+ fprintf(stderr, "## %s\n", emsg.c);
+ return (1);
+ }
+#ifdef USE_DNSRPS
+ /*
+ * Get the serial number of a policy zone from
+ * a running dnsrpzd daemon.
+ */
+ clist = librpz->clist_create(&emsg, NULL, NULL, NULL,
+ NULL, NULL);
+ if (clist == NULL) {
+ fprintf(stderr, "## %s: %s\n", optarg, emsg.c);
+ return (1);
+ }
+ snprintf(cstr, sizeof(cstr),
+ "zone %s; dnsrpzd \"\";"
+ " dnsrpzd-sock dnsrpzd.sock;"
+ " dnsrpzd-rpzf dnsrpzd.rpzf",
+ optarg);
+ client = librpz->client_create(&emsg, clist, cstr,
+ true);
+ if (client == NULL) {
+ fprintf(stderr, "## %s\n", emsg.c);
+ return (1);
+ }
+
+ rsp = NULL;
+ if (!librpz->rsp_create(&emsg, &rsp, NULL, client, true,
+ false) ||
+ rsp == NULL)
+ {
+ fprintf(stderr, "## %s\n", emsg.c);
+ librpz->client_detach(&client);
+ return (1);
+ }
+
+ if (!librpz->soa_serial(&emsg, &serial, optarg, rsp)) {
+ fprintf(stderr, "## %s\n", emsg.c);
+ librpz->client_detach(&client);
+ return (1);
+ }
+ librpz->rsp_detach(&rsp);
+ librpz->client_detach(&client);
+ printf("%u\n", serial);
+#else /* ifdef USE_DNSRPS */
+ UNREACHABLE();
+#endif /* ifdef USE_DNSRPS */
+ return (0);
+
+ case 'w':
+ seconds = strtod(optarg, &p);
+ if (seconds <= 0 || *p != '\0') {
+ fprintf(stderr, USAGE);
+ return (1);
+ }
+ usleep((int)(seconds * 1000.0 * 1000.0));
+ return (0);
+
+ default:
+ fprintf(stderr, USAGE);
+ return (1);
+ }
+ }
+ fprintf(stderr, USAGE);
+ return (1);
+}
+
+static bool
+link_dnsrps(librpz_emsg_t *emsg) {
+#ifdef USE_DNSRPS
+ librpz = librpz_lib_open(emsg, NULL, DNSRPS_LIBRPZ_PATH);
+ if (librpz == NULL) {
+ return (false);
+ }
+
+ return (true);
+#else /* ifdef USE_DNSRPS */
+ snprintf(emsg->c, sizeof(emsg->c), "DNSRPS not configured");
+ return (false);
+#endif /* ifdef USE_DNSRPS */
+}
diff --git a/bin/tests/system/rpz/dnsrpzd-license.conf b/bin/tests/system/rpz/dnsrpzd-license.conf
new file mode 100644
index 0000000..739b39d
--- /dev/null
+++ b/bin/tests/system/rpz/dnsrpzd-license.conf
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone isc.license.fastrpz.com {
+ primaries port 53 {
+ KEY farsight_fastrpz_license 104.244.14.176;
+ KEY farsight_fastrpz_license 2620:11c:f008::176;
+ };
+};
+
+key farsight_fastrpz_license {
+ algorithm hmac-sha256; secret "f405d02b4c8af54855fcebc1";
+};
diff --git a/bin/tests/system/rpz/dnsrpzd.conf.in b/bin/tests/system/rpz/dnsrpzd.conf.in
new file mode 100644
index 0000000..7365562
--- /dev/null
+++ b/bin/tests/system/rpz/dnsrpzd.conf.in
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# dnsrpzd configuration.
+
+pid-file ../dnsrpzd.pid
+
+include ../dnsrpzd-license-cur.conf
+
+# configure NOTIFY and zone transfers
+port @EXTRAPORT1@;
+listen-on port @EXTRAPORT1@ { 10.53.0.3; };
+allow-notify { 10.53.0.0/24; };
+
+zone "bl0" {type primary; file "../ns5/bl.db"; };
+zone "bl1" {type primary; file "../ns5/bl.db"; };
+zone "bl2" {type primary; file "../ns5/bl.db"; };
+zone "bl3" {type primary; file "../ns5/bl.db"; };
+zone "bl4" {type primary; file "../ns5/bl.db"; };
+zone "bl5" {type primary; file "../ns5/bl.db"; };
+zone "bl6" {type primary; file "../ns5/bl.db"; };
+zone "bl7" {type primary; file "../ns5/bl.db"; };
+zone "bl8" {type primary; file "../ns5/bl.db"; };
+zone "bl9" {type primary; file "../ns5/bl.db"; };
+zone "bl10" {type primary; file "../ns5/bl.db"; };
+zone "bl11" {type primary; file "../ns5/bl.db"; };
+zone "bl12" {type primary; file "../ns5/bl.db"; };
+zone "bl13" {type primary; file "../ns5/bl.db"; };
+zone "bl14" {type primary; file "../ns5/bl.db"; };
+zone "bl15" {type primary; file "../ns5/bl.db"; };
+zone "bl16" {type primary; file "../ns5/bl.db"; };
+zone "bl17" {type primary; file "../ns5/bl.db"; };
+zone "bl18" {type primary; file "../ns5/bl.db"; };
+zone "bl19" {type primary; file "../ns5/bl.db"; };
+
+zone "bl" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-2" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-given" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-passthru" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-no-op" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-disabled" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-nodata" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-nxdomain" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-cname" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-wildcname" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-garden" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-drop" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl-tcp-only" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+zone "bl.tld2" {type secondary; primaries port @PORT@ { 10.53.0.3; }; };
+
+zone "policy1" {type secondary; primaries port @PORT@ { 10.53.0.6; }; };
+zone "policy2" {type secondary; primaries port @PORT@ { 10.53.0.7; }; };
diff --git a/bin/tests/system/rpz/ns1/named.conf.in b/bin/tests/system/rpz/ns1/named.conf.in
new file mode 100644
index 0000000..8b466f0
--- /dev/null
+++ b/bin/tests/system/rpz/ns1/named.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ notify no;
+ minimal-responses no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {type primary; file "root.db";};
diff --git a/bin/tests/system/rpz/ns1/root.db b/bin/tests/system/rpz/ns1/root.db
new file mode 100644
index 0000000..6bf3d5a
--- /dev/null
+++ b/bin/tests/system/rpz/ns1/root.db
@@ -0,0 +1,42 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+. SOA ns. hostmaster.ns. ( 1 3600 1200 604800 60 )
+ NS ns.
+ns. A 10.53.0.1
+
+; rewrite responses from this zone
+tld2. NS ns.tld2.
+ns.tld2. A 10.53.0.2
+
+; rewrite responses from this secure zone unless dnssec requested (DO=1)
+tld2s. NS ns.tld2.
+
+; requests come from here
+tld3. NS ns.tld3.
+ns.tld3. A 10.53.0.3
+
+; rewrite responses from this zone
+tld4. NS ns.tld4.
+ns.tld4. A 10.53.0.4
+
+; performance test
+tld5. NS ns.tld5.
+ns.tld5. A 10.53.0.5
+
+; generate SERVFAIL
+servfail NS ns.tld2.
+
+a-only.example A 1.2.3.4
+no-a-no-aaaa.example TXT placeholder
+a-plus-aaaa.example A 1.2.3.4
+a-plus-aaaa.example AAAA ::1
diff --git a/bin/tests/system/rpz/ns10/hints b/bin/tests/system/rpz/ns10/hints
new file mode 100644
index 0000000..b657c39
--- /dev/null
+++ b/bin/tests/system/rpz/ns10/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 120 NS ns.
+ns. 120 A 10.53.0.1
diff --git a/bin/tests/system/rpz/ns10/named.conf.in b/bin/tests/system/rpz/ns10/named.conf.in
new file mode 100644
index 0000000..d645e38
--- /dev/null
+++ b/bin/tests/system/rpz/ns10/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.10;
+ notify-source 10.53.0.10;
+ transfer-source 10.53.0.10;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.10; };
+ listen-on-v6 { none; };
+ notify no;
+ minimal-responses no;
+ recursion yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+controls {
+ inet 10.53.0.10 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "../trusted.conf";
+zone "." { type hint; file "hints"; };
+
+# grafted on zones using stub and static-stub
+zone "stub-nomatch." {type primary; file "stub.db"; };
+zone "static-stub-nomatch." {type primary; file "stub.db"; };
diff --git a/bin/tests/system/rpz/ns10/stub.db b/bin/tests/system/rpz/ns10/stub.db
new file mode 100644
index 0000000..8ecac8c
--- /dev/null
+++ b/bin/tests/system/rpz/ns10/stub.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; RPZ rewrite responses from this zone
+
+$TTL 120
+@ SOA ns hostmaster.ns ( 1 3600 1200 604800 60 )
+ NS ns
+ns A 10.53.0.10
+
+a3-1 A 10.53.99.99
+
+a4-1 A 10.53.99.99
diff --git a/bin/tests/system/rpz/ns2/base-tld2s.db b/bin/tests/system/rpz/ns2/base-tld2s.db
new file mode 100644
index 0000000..77114ec
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/base-tld2s.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; RPZ rewrite responses from this signed zone
+
+$TTL 120
+@ SOA tld2s. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 )
+ NS ns
+ NS . ; check for RT 24985
+ns A 10.53.0.2
+
+
+a0-1 A 192.168.0.1
+a0-1-scname CNAME a0-1.tld2.
+
+a3-5 A 192.168.3.5
+
+a7-2 A 192.168.7.2
diff --git a/bin/tests/system/rpz/ns2/bl.tld2.db.in b/bin/tests/system/rpz/ns2/bl.tld2.db.in
new file mode 100644
index 0000000..25780b7
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/bl.tld2.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; primary for secondary RPZ zone
+
+$TTL 3600
+@ SOA rpz.tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+32.1.7.168.192.rpz-ip CNAME .
diff --git a/bin/tests/system/rpz/ns2/blv2.tld2.db.in b/bin/tests/system/rpz/ns2/blv2.tld2.db.in
new file mode 100644
index 0000000..123e1b4
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/blv2.tld2.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; primary for secondary RPZ zone
+
+$TTL 3600
+@ SOA rpz.tld2. hostmaster.ns.tld2. ( 2 3600 1200 604800 60 )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/rpz/ns2/blv3.tld2.db.in b/bin/tests/system/rpz/ns2/blv3.tld2.db.in
new file mode 100644
index 0000000..b8ba587
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/blv3.tld2.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; primary for secondary RPZ zone
+
+$TTL 3600
+@ SOA rpz.tld2. hostmaster.ns.tld2. ( 3 3600 1200 604800 60 )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+32.1.7.168.192.rpz-ip CNAME .
diff --git a/bin/tests/system/rpz/ns2/hints b/bin/tests/system/rpz/ns2/hints
new file mode 100644
index 0000000..b657c39
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 120 NS ns.
+ns. 120 A 10.53.0.1
diff --git a/bin/tests/system/rpz/ns2/named.conf.in b/bin/tests/system/rpz/ns2/named.conf.in
new file mode 100644
index 0000000..9b2ab3a
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/named.conf.in
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ notify no;
+ minimal-responses no;
+ recursion yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "../trusted.conf";
+zone "." { type hint; file "hints"; };
+
+zone "tld2." {type primary; file "tld2.db";};
+zone "sub1.tld2." {type primary; file "tld2.db";};
+zone "subsub.sub1.tld2." {type primary; file "tld2.db";};
+zone "sub2.tld2." {type primary; file "tld2.db";};
+zone "subsub.sub2.tld2." {type primary; file "tld2.db";};
+zone "sub3.tld2." {type primary; file "tld2.db";};
+zone "subsub.sub3.tld2." {type primary; file "tld2.db";};
+
+zone "tld2s." {type primary; file "tld2s.db";};
+
+zone "bl.tld2." {type primary; file "bl.tld2.db";
+ notify yes; notify-delay 0;};
+
+# grafted on zones using stub and static-stub
+zone "stub." {type primary; file "stub.db"; };
+zone "static-stub." {type primary; file "stub.db"; };
diff --git a/bin/tests/system/rpz/ns2/stub.db b/bin/tests/system/rpz/ns2/stub.db
new file mode 100644
index 0000000..e4b8781
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/stub.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; RPZ rewrite responses from this zone
+
+$TTL 120
+@ SOA tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 )
+ NS ns.sub1.tld2.
+
+a3-1 A 10.53.99.99
+
+a4-1 A 10.53.99.99
diff --git a/bin/tests/system/rpz/ns2/tld2.db b/bin/tests/system/rpz/ns2/tld2.db
new file mode 100644
index 0000000..c6f2556
--- /dev/null
+++ b/bin/tests/system/rpz/ns2/tld2.db
@@ -0,0 +1,125 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; RPZ rewrite responses from this zone
+
+$TTL 120
+@ SOA tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 )
+ NS ns
+ NS . ; check for RT 24985
+ns A 10.53.0.2
+
+
+txt-only TXT "txt-only-tld2"
+
+a12 A 12.12.12.12
+ AAAA 2001::12
+ TXT "a12 tld2 text"
+a12-cname CNAME a12
+
+a0-1 A 192.168.0.1
+ AAAA 2001:2::1
+ TXT "a0-1 tld2 text"
+a0-1-scname CNAME a0-1.tld2s.
+
+
+a3-1 A 192.168.3.1
+ AAAA 2001:2:3::1
+ TXT "a3-1 tld2 text"
+
+a3-2 A 192.168.3.2
+ AAAA 2001:2:3::2
+ TXT "a3-2 tld2 text"
+
+a3-3 A 192.168.3.3
+ AAAA 2001:2:3::3
+ TXT "a3-3 tld2 text"
+
+a3-4 A 192.168.3.4
+ AAAA 2001:2:3::4
+ TXT "a3-4 tld2 text"
+
+a3-5 A 192.168.3.5
+ AAAA 2001:2:3::5
+ TXT "a3-5 tld2 text"
+
+a3-6 A 192.168.3.6
+ AAAA 2001:2:3::6
+ TXT "a3-6 tld2 text"
+
+a3-7 A 192.168.3.7
+ AAAA 2001:2:3::7
+ TXT "a3-7 tld2 text"
+
+a3-8 A 192.168.3.8
+ AAAA 2001:2:3::8
+ TXT "a3-8 tld2 text"
+
+a3-9 A 192.168.3.9
+ AAAA 2001:2:3::9
+ TXT "a3-9 tld2 text"
+
+a4-1 A 192.168.4.1
+ AAAA 2001:2:4::1
+ TXT "a4-1 tld2 text"
+a4-1-aaaa AAAA 2001:2:4::1
+
+a4-2 A 192.168.4.2
+ AAAA 2001:2:4::2
+ TXT "a4-2 tld2 text"
+a4-2-cname CNAME a4-2
+
+a4-3 A 192.168.4.3
+ AAAA 2001:2:4::3
+ TXT "a4-3 tld2 text"
+a4-3-cname CNAME a4-3
+
+a4-4 A 192.168.4.4
+ AAAA 2001:2:4::4
+ TXT "a4-4 tld2 text"
+
+a4-5 A 192.168.4.5
+ AAAA 2001:2:4::5
+ TXT "a4-5 tld2 text"
+a4-5-cname CNAME a4-5
+a4-5-cname2 CNAME a4-5-cname
+a4-5-cname3 CNAME a4-5-cname2
+
+a4-6 A 192.168.4.6
+ AAAA 2001:2:4::6
+ TXT "a4-6 tld2 text"
+a4-6-cname CNAME a4-6
+a4-6-cname2 CNAME a4-6-cname
+a4-6-cname3 CNAME a4-6-cname2
+
+a5-1-2 A 192.168.5.1
+ A 192.168.5.2
+ TXT "a5-1-2 tld2 text"
+
+a5-2 A 192.168.5.2
+ TXT "a5-2 tld2 text"
+
+a5-3 A 192.168.5.3
+ TXT "a5-3 tld2 text"
+
+a5-4 A 192.168.5.4
+ TXT "a5-4 tld2 text"
+
+a6-1 A 192.168.6.1
+ TXT "a6-1 tld2 text"
+a6-2 A 192.168.6.2
+ TXT "a6-2 tld2 text"
+
+a7-1 A 192.168.7.1
+ TXT "a7-1 tld2 text"
+
+a7-2 A 192.168.7.2
+ TXT "a7-2 tld2 text"
diff --git a/bin/tests/system/rpz/ns3/base.db b/bin/tests/system/rpz/ns3/base.db
new file mode 100644
index 0000000..f2f15a0
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/base.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; RPZ test
+; This basic file is copied to several zone files before being used.
+; Its contents are also changed with nsupdate
+
+
+$TTL 300
+@ SOA blx. hostmaster.ns.blx. ( 1 3600 1200 604800 60 )
+ NS ns.tld3.
+
+; regression testing for some old crashes
+example.com NS example.org.
+
+domain.com cname foobar.com
diff --git a/bin/tests/system/rpz/ns3/broken.db.in b/bin/tests/system/rpz/ns3/broken.db.in
new file mode 100644
index 0000000..80aa313
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/broken.db.in
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; RPZ test
+; This basic file is copied to several zone files before being used.
+; Its contents are also changed with nsupdate
+
+
+; broken zone
+foobar
diff --git a/bin/tests/system/rpz/ns3/crash1 b/bin/tests/system/rpz/ns3/crash1
new file mode 100644
index 0000000..0c85191
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/crash1
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+; a bad zone that caused a crash related to dns_rdataset_disassociate()
+
+$TTL 120
+@ SOA crash1.tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 )
+
+ NS tld2.
diff --git a/bin/tests/system/rpz/ns3/crash2 b/bin/tests/system/rpz/ns3/crash2
new file mode 100644
index 0000000..ab70283
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/crash2
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+; a valid zone containing records that caused crashes
+
+$TTL 120
+@ SOA crash2.tld3. hostmaster.ns.tld3. ( 1 3600 1200 604800 60 )
+ NS ns
+ns A 10.53.0.3
+
+; #24 in test1, crashed new ASSERT() in rbtdb.c
+c1 A 172.16.1.24
+
+; #16 in test2, crashed new ASSERT() in rbtdb.c
+c2 A 172.16.1.16
diff --git a/bin/tests/system/rpz/ns3/hints b/bin/tests/system/rpz/ns3/hints
new file mode 100644
index 0000000..b657c39
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 120 NS ns.
+ns. 120 A 10.53.0.1
diff --git a/bin/tests/system/rpz/ns3/manual-update-rpz-2.db.in b/bin/tests/system/rpz/ns3/manual-update-rpz-2.db.in
new file mode 100644
index 0000000..f670b0c
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/manual-update-rpz-2.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; RPZ test
+; This basic file is copied to several zone files before being used.
+; Its contents are also changed with nsupdate
+
+
+$TTL 300
+@ SOA bl-reload. hostmaster.ns.bl-reload. ( 2 3600 1200 604800 60 )
+ NS ns.tld3.
+
+walled.tld2.bl-reload. 300 A 10.0.0.2
+
diff --git a/bin/tests/system/rpz/ns3/manual-update-rpz.db.in b/bin/tests/system/rpz/ns3/manual-update-rpz.db.in
new file mode 100644
index 0000000..a823448
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/manual-update-rpz.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; RPZ test
+; This basic file is copied to several zone files before being used.
+; Its contents are also changed with nsupdate
+
+
+$TTL 300
+@ SOA manual-update-rpz. hostmaster.ns.manual-rpz-update. ( 1 3600 1200 604800 60 )
+ NS ns.tld3.
+
+walled.tld2.manual-update-rpz. 300 A 10.0.0.1
diff --git a/bin/tests/system/rpz/ns3/mixed-case-rpz-1.db.in b/bin/tests/system/rpz/ns3/mixed-case-rpz-1.db.in
new file mode 100644
index 0000000..c8548fc
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/mixed-case-rpz-1.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA mixed-case-rpz. hostmaster.ns.mixed-case-rpz. ( 1 3600 1200 604800 60 )
+ NS ns.tld3.
+
+A6-2.TLD2 CNAME .
diff --git a/bin/tests/system/rpz/ns3/mixed-case-rpz-2.db.in b/bin/tests/system/rpz/ns3/mixed-case-rpz-2.db.in
new file mode 100644
index 0000000..7d99c5a
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/mixed-case-rpz-2.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA mixed-case-rpz. hostmaster.ns.mixed-case-rpz. ( 2 3600 1200 604800 60 )
+ NS ns.tld3.
+
+a6-1.tld2 CNAME .
+A6-2.TLD2 CNAME .
diff --git a/bin/tests/system/rpz/ns3/named.conf.in b/bin/tests/system/rpz/ns3/named.conf.in
new file mode 100644
index 0000000..6d2303c
--- /dev/null
+++ b/bin/tests/system/rpz/ns3/named.conf.in
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Main rpz test DNS server.
+ */
+
+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";
+ statistics-file "named.stats";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ notify yes;
+ minimal-responses no;
+ recursion yes;
+ dnssec-validation yes;
+ min-refresh-time 1;
+ min-retry-time 1;
+
+ response-policy {
+ zone "fast-expire";
+ zone "bl" max-policy-ttl 100;
+ zone "bl-2";
+ zone "bl-given" policy given recursive-only yes;
+ zone "bl-passthru" policy passthru;
+ zone "bl-no-op" policy no-op; # obsolete for passthru
+ zone "bl-disabled" policy disabled;
+ zone "bl-nodata" policy nodata recursive-only no;
+ zone "bl-nxdomain" policy nxdomain;
+ zone "bl-cname" policy cname txt-only.tld2.;
+ zone "bl-wildcname" policy cname *.tld4.;
+ zone "bl-garden" policy cname a12.tld2.;
+ zone "bl-drop" policy drop;
+ zone "bl-tcp-only" policy tcp-only;
+ zone "bl.tld2";
+ zone "manual-update-rpz";
+ zone "mixed-case-rpz";
+ }
+ add-soa yes
+ min-ns-dots 0
+ qname-wait-recurse yes
+ min-update-interval 0
+ nsdname-enable yes
+ nsip-enable yes
+ ;
+
+ include "../dnsrps.conf";
+ also-notify { 10.53.0.3 port @EXTRAPORT1@; };
+ notify-delay 0;
+};
+
+logging { category rpz { default_debug; }; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." { type hint; file "hints"; };
+
+zone "bl." {type primary; file "bl.db";
+ allow-update {any;};};
+zone "bl-2." {type primary; file "bl-2.db";
+ allow-update {any;};};
+zone "bl-given." {type primary; file "bl-given.db";
+ allow-update {any;};};
+zone "bl-passthru." {type primary; file "bl-passthru.db";
+ allow-update {any;};};
+zone "bl-no-op." {type primary; file "bl-no-op.db";
+ allow-update {any;};};
+zone "bl-disabled." {type primary; file "bl-disabled.db";
+ allow-update {any;};};
+zone "bl-nodata." {type primary; file "bl-nodata.db";
+ allow-update {any;};};
+zone "bl-nxdomain." {type primary; file "bl-nxdomain.db";
+ allow-update {any;};};
+zone "bl-cname." {type primary; file "bl-cname.db";
+ allow-update {any;};};
+zone "bl-wildcname." {type primary; file "bl-wildcname.db";
+ allow-update {any;};};
+zone "bl-garden." {type primary; file "bl-garden.db";
+ allow-update {any;};};
+zone "bl-drop." {type primary; file "bl-drop.db";
+ allow-update {any;};};
+zone "bl-tcp-only." {type primary; file "bl-tcp-only.db";
+ allow-update {any;};};
+
+zone "bl.tld2." {type secondary; file "bl.tld2.db"; primaries {10.53.0.2;};
+ request-ixfr no; masterfile-format text;};
+
+zone "crash1.tld2" {type primary; file "crash1"; notify no;};
+zone "crash2.tld3." {type primary; file "crash2"; notify no;};
+
+zone "manual-update-rpz." {
+ type primary;
+ file "manual-update-rpz.db";
+ notify no;
+};
+
+zone "mixed-case-rpz." {
+ type primary;
+ file "mixed-case-rpz.db";
+ notify no;
+};
+
+zone "fast-expire." {
+ type secondary;
+ file "fast-expire.db";
+ primaries { 10.53.0.5; };
+ notify no;
+};
+
+zone "stub." {
+ type stub;
+ primaries { 10.53.0.2; };
+};
+
+zone "static-stub." {
+ type static-stub;
+ server-addresses { 10.53.0.2; };
+};
+
+zone "stub-nomatch." {
+ type stub;
+ primaries { 10.53.0.10; };
+};
+
+zone "static-stub-nomatch." {
+ type static-stub;
+ server-addresses { 10.53.0.10; };
+};
+
+# A faulty dlz configuration to check if named with response policy zones
+# survives a certain class of failed configuration attempts (see GL #3880).
+# "dlz" is used because the dlz processing code is located in an ideal place in
+# the view configuration function for the test to cover the view reverting code.
+# The "BAD" comments below are necessary, because they will be removed using
+# 'sed' by tests.sh in order to activate the faulty configuration.
+#BAD dlz "bad-dlz" {
+#BAD database "dlopen bad-dlz.so example.org";
+#BAD };
diff --git a/bin/tests/system/rpz/ns4/hints b/bin/tests/system/rpz/ns4/hints
new file mode 100644
index 0000000..b657c39
--- /dev/null
+++ b/bin/tests/system/rpz/ns4/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 120 NS ns.
+ns. 120 A 10.53.0.1
diff --git a/bin/tests/system/rpz/ns4/named.conf.in b/bin/tests/system/rpz/ns4/named.conf.in
new file mode 100644
index 0000000..909f1c6
--- /dev/null
+++ b/bin/tests/system/rpz/ns4/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ notify no;
+ minimal-responses no;
+ recursion yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "../trusted.conf";
+zone "." { type hint; file "hints"; };
+
+zone "tld4." {type primary; file "tld4.db";};
+zone "sub1.tld4." {type primary; file "tld4.db";};
+zone "subsub.sub1.tld4." {type primary; file "tld4.db";};
+zone "sub2.tld4." {type primary; file "tld4.db";};
+zone "subsub.sub2.tld4." {type primary; file "tld4.db";};
diff --git a/bin/tests/system/rpz/ns4/tld4.db b/bin/tests/system/rpz/ns4/tld4.db
new file mode 100644
index 0000000..fca419c
--- /dev/null
+++ b/bin/tests/system/rpz/ns4/tld4.db
@@ -0,0 +1,66 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; RPZ rewrite responses from this zone
+
+$TTL 120
+@ SOA tld4. hostmaster.ns.tld4. ( 1 3600 1200 604800 60 )
+ NS ns
+ns A 10.53.0.4
+
+
+txt-only TXT "txt-only-tld4"
+
+a14 A 14.14.14.14
+ AAAA 2001::14
+ TXT "a14 text"
+a14-cname CNAME a14
+
+a0-1 A 192.168.0.1
+ AAAA 2001:2::1
+ TXT "a0-1 text"
+
+a3-1 A 192.168.3.1
+ AAAA 2001:2:3::1
+ TXT "a3-1 text"
+
+a3-2 A 192.168.3.2
+ AAAA 2001:2:3::2
+ TXT "a3-2 text"
+
+a4-1 A 192.168.4.1
+ AAAA 2001:2:4::1
+ TXT "a4-1 text"
+a4-1-aaaa AAAA 2001:2:4::1
+
+a4-2 A 192.168.4.2
+ AAAA 2001:2:4::2
+ TXT "a4-2 text"
+a4-2-cname CNAME a4-2
+
+a4-3 A 192.168.4.3
+ AAAA 2001:2:4::3
+ TXT "a4-3 text"
+a4-3-cname CNAME a4-3
+
+a4-4 A 192.168.4.4
+ AAAA 2001:2:4::4
+ TXT "a4-4 text"
+
+a3-6.tld2 A 56.56.56.56
+
+a3-7.sub1.tld2 A 57.57.57.57
+
+a3-8.tld2 A 58.58.58.58
+
+a3-9.sub9.tld2 A 59.59.59.59
+
+a3-10.tld2 A 60.60.60.60
diff --git a/bin/tests/system/rpz/ns5/empty.db.in b/bin/tests/system/rpz/ns5/empty.db.in
new file mode 100644
index 0000000..a7e9144
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/empty.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA . hostmaster.ns.example.tld5. ( 1 3600 1200 604800 60 )
+ NS .
diff --git a/bin/tests/system/rpz/ns5/expire.conf.in b/bin/tests/system/rpz/ns5/expire.conf.in
new file mode 100644
index 0000000..4c1c228
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/expire.conf.in
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+zone "fast-expire." {
+ type primary;
+ file "fast-expire.db";
+ allow-transfer { any; };
+ notify no;
+};
diff --git a/bin/tests/system/rpz/ns5/fast-expire.db.in b/bin/tests/system/rpz/ns5/fast-expire.db.in
new file mode 100644
index 0000000..cb2672e
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/fast-expire.db.in
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA fast-expire. hostmaster (
+ 1 3 1 5 60
+ )
+ NS ns.tld3.
+
+expired.fast-expire. A 10.0.0.10
diff --git a/bin/tests/system/rpz/ns5/hints b/bin/tests/system/rpz/ns5/hints
new file mode 100644
index 0000000..b657c39
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 120 NS ns.
+ns. 120 A 10.53.0.1
diff --git a/bin/tests/system/rpz/ns5/named.args b/bin/tests/system/rpz/ns5/named.args
new file mode 100644
index 0000000..56edbe3
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/named.args
@@ -0,0 +1,2 @@
+# run the performance test close to real life
+-c named.conf -D rpz-ns5 -X named.lock -gd3 -T maxcachesize=2097152
diff --git a/bin/tests/system/rpz/ns5/named.conf.in b/bin/tests/system/rpz/ns5/named.conf.in
new file mode 100644
index 0000000..e1f8fb6
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/named.conf.in
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Test rpz performance.
+ */
+
+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";
+ statistics-file "named.stats";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ ixfr-from-differences yes;
+ notify-delay 0;
+ notify yes;
+ minimal-responses no;
+ recursion yes;
+ dnssec-validation yes;
+
+ # turn rpz on or off
+ include "rpz-switch";
+
+ include "../dnsrps-secondary.conf";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "../trusted.conf";
+zone "." {type hint; file "hints"; };
+
+zone "tld5." {type primary; file "tld5.db"; };
+zone "example.tld5." {type primary; file "example.db"; };
+
+zone "bl0." {type primary; file "bl.db"; };
+zone "bl1." {type primary; file "bl.db"; };
+zone "bl2." {type primary; file "bl.db"; };
+zone "bl3." {type primary; file "bl.db"; };
+zone "bl4." {type primary; file "bl.db"; };
+zone "bl5." {type primary; file "bl.db"; };
+zone "bl6." {type primary; file "bl.db"; };
+zone "bl7." {type primary; file "bl.db"; };
+zone "bl8." {type primary; file "bl.db"; };
+zone "bl9." {type primary; file "bl.db"; };
+zone "bl10." {type primary; file "bl.db"; };
+zone "bl11." {type primary; file "bl.db"; };
+zone "bl12." {type primary; file "bl.db"; };
+zone "bl13." {type primary; file "bl.db"; };
+zone "bl14." {type primary; file "bl.db"; };
+zone "bl15." {type primary; file "bl.db"; };
+zone "bl16." {type primary; file "bl.db"; };
+zone "bl17." {type primary; file "bl.db"; };
+zone "bl18." {type primary; file "bl.db"; };
+zone "bl19." {type primary; file "bl.db"; };
+
+zone "policy1" {
+ type primary;
+ file "empty.db";
+ also-notify { 10.53.0.6; };
+ allow-update { any; };
+ allow-transfer { any; };
+};
+
+zone "policy2" {
+ type primary;
+ file "policy2.db";
+ allow-update { any; };
+ allow-transfer { any; };
+};
+
+include "expire.conf";
diff --git a/bin/tests/system/rpz/ns5/tld5.db b/bin/tests/system/rpz/ns5/tld5.db
new file mode 100644
index 0000000..b75e72f
--- /dev/null
+++ b/bin/tests/system/rpz/ns5/tld5.db
@@ -0,0 +1,32 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; RPZ performance test
+
+$TTL 120
+@ SOA . hostmaster.ns.example.tld5. ( 1 3600 1200 604800 60 )
+ NS ns
+ NS ns1
+ NS ns2
+ NS ns3
+ns A 10.53.0.5
+ns1 A 10.53.0.5
+ns2 A 10.53.0.5
+ns3 A 10.53.0.5
+
+
+$ORIGIN example.tld5.
+example.tld5. NS ns
+ NS ns1
+ns A 10.53.0.5
+ns1 A 10.53.0.5
+
+as-ns TXT "rewritten with ip-as-ns and qname-as-ns"
diff --git a/bin/tests/system/rpz/ns6/bl.tld2s.db.in b/bin/tests/system/rpz/ns6/bl.tld2s.db.in
new file mode 100644
index 0000000..4538050
--- /dev/null
+++ b/bin/tests/system/rpz/ns6/bl.tld2s.db.in
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA rpz.tld2. hostmaster.ns.tld2. ( 3 3600 1200 604800 60 )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+32.2.7.168.192.rpz-ip A 1.1.1.1
+ AAAA ::1
diff --git a/bin/tests/system/rpz/ns6/hints b/bin/tests/system/rpz/ns6/hints
new file mode 100644
index 0000000..b657c39
--- /dev/null
+++ b/bin/tests/system/rpz/ns6/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 120 NS ns.
+ns. 120 A 10.53.0.1
diff --git a/bin/tests/system/rpz/ns6/named.conf.in b/bin/tests/system/rpz/ns6/named.conf.in
new file mode 100644
index 0000000..c0ad5c4
--- /dev/null
+++ b/bin/tests/system/rpz/ns6/named.conf.in
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.6;
+ notify-source 10.53.0.6;
+ transfer-source 10.53.0.6;
+ port @PORT@;
+ pid-file "named.pid";
+ statistics-file "named.stats";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.6; };
+ listen-on-v6 { none; };
+ forward only;
+ forwarders { 10.53.0.3; };
+ minimal-responses no;
+ recursion yes;
+ dnssec-validation yes;
+ qname-minimization disabled;
+
+ response-policy {
+ zone "policy1" min-update-interval 0;
+ zone "bl.tld2s" policy given;
+ } qname-wait-recurse yes
+ // add-soa yes # leave add-soa as default for unset test
+ nsip-enable yes
+ nsdname-enable yes;
+
+ include "../dnsrps-secondary.conf";
+};
+
+logging { category rpz { default_debug; }; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "../trusted.conf";
+
+zone "policy1" {
+ type secondary;
+ primaries { 10.53.0.5; };
+ file "empty.db";
+ also-notify { 10.53.0.3 port @EXTRAPORT1@; };
+ notify-delay 0;
+ allow-transfer { any; };
+};
+
+zone "bl.tld2s." {
+ type primary;
+ file "bl.tld2s.db";
+};
diff --git a/bin/tests/system/rpz/ns7/hints b/bin/tests/system/rpz/ns7/hints
new file mode 100644
index 0000000..b657c39
--- /dev/null
+++ b/bin/tests/system/rpz/ns7/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 120 NS ns.
+ns. 120 A 10.53.0.1
diff --git a/bin/tests/system/rpz/ns7/named.conf.in b/bin/tests/system/rpz/ns7/named.conf.in
new file mode 100644
index 0000000..7effd3d
--- /dev/null
+++ b/bin/tests/system/rpz/ns7/named.conf.in
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.7;
+ notify-source 10.53.0.7;
+ transfer-source 10.53.0.7;
+ port @PORT@;
+ pid-file "named.pid";
+ statistics-file "named.stats";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.7; };
+ listen-on-v6 { none; };
+ minimal-responses no;
+ recursion yes;
+ dnssec-validation yes;
+
+ response-policy {
+ zone "policy2" add-soa no;
+ } qname-wait-recurse no
+ nsip-enable yes
+ nsdname-enable yes
+ min-update-interval 0;
+
+ include "../dnsrps-secondary.conf";
+};
+
+logging { category rpz { default_debug; }; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "../trusted.conf";
+
+zone "policy2" {
+ type secondary;
+ primaries { 10.53.0.5; };
+ file "policy2.db";
+ also-notify { 10.53.0.3 port @EXTRAPORT1@; };
+ notify-delay 0;
+ allow-transfer { any; };
+ request-ixfr no; // force axfr on rndc reload
+};
diff --git a/bin/tests/system/rpz/ns8/hints b/bin/tests/system/rpz/ns8/hints
new file mode 100644
index 0000000..b657c39
--- /dev/null
+++ b/bin/tests/system/rpz/ns8/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 120 NS ns.
+ns. 120 A 10.53.0.1
diff --git a/bin/tests/system/rpz/ns8/manual-update-rpz.db.in b/bin/tests/system/rpz/ns8/manual-update-rpz.db.in
new file mode 100644
index 0000000..a823448
--- /dev/null
+++ b/bin/tests/system/rpz/ns8/manual-update-rpz.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; RPZ test
+; This basic file is copied to several zone files before being used.
+; Its contents are also changed with nsupdate
+
+
+$TTL 300
+@ SOA manual-update-rpz. hostmaster.ns.manual-rpz-update. ( 1 3600 1200 604800 60 )
+ NS ns.tld3.
+
+walled.tld2.manual-update-rpz. 300 A 10.0.0.1
diff --git a/bin/tests/system/rpz/ns8/named.conf.in b/bin/tests/system/rpz/ns8/named.conf.in
new file mode 100644
index 0000000..aa8b342
--- /dev/null
+++ b/bin/tests/system/rpz/ns8/named.conf.in
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Main rpz test DNS server.
+ */
+
+options {
+ query-source address 10.53.0.8;
+ notify-source 10.53.0.8;
+ transfer-source 10.53.0.8;
+ port @PORT@;
+ pid-file "named.pid";
+ statistics-file "named.stats";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.8; };
+ listen-on-v6 { none; };
+ notify yes;
+ minimal-responses no;
+ recursion yes;
+ dnssec-validation yes;
+
+ response-policy {
+ zone "manual-update-rpz";
+ }
+ // add-soa yes // do not set testing default mode
+ min-ns-dots 0
+ qname-wait-recurse yes
+ min-update-interval 0
+ nsdname-enable yes
+ nsip-enable yes
+ ;
+
+ include "../dnsrps.conf";
+ also-notify { 10.53.0.8 port @EXTRAPORT1@; };
+ notify-delay 0;
+};
+
+logging { category rpz { default_debug; }; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+controls {
+ inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." { type hint; file "hints"; };
+
+zone "manual-update-rpz." {
+ type primary;
+ file "manual-update-rpz.db";
+ notify no;
+};
diff --git a/bin/tests/system/rpz/ns9/hints b/bin/tests/system/rpz/ns9/hints
new file mode 100644
index 0000000..b657c39
--- /dev/null
+++ b/bin/tests/system/rpz/ns9/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 120 NS ns.
+ns. 120 A 10.53.0.1
diff --git a/bin/tests/system/rpz/ns9/named.conf.in b/bin/tests/system/rpz/ns9/named.conf.in
new file mode 100644
index 0000000..70297bd
--- /dev/null
+++ b/bin/tests/system/rpz/ns9/named.conf.in
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * DNS64 / RPZ server.
+ */
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ statistics-file "named.stats";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ notify yes;
+ minimal-responses no;
+ recursion yes;
+ dnssec-validation yes;
+ dns64-server "example.localdomain.";
+ dns64 64:ff9b::/96 { };
+ response-policy {
+ zone "rpz";
+ }
+ qname-wait-recurse no ;
+
+ include "../dnsrps.conf";
+ notify-delay 0;
+};
+
+logging { category rpz { default_debug; }; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." { type hint; file "hints"; };
+
+zone "rpz." {
+ type primary;
+ file "rpz.db";
+ notify no;
+};
diff --git a/bin/tests/system/rpz/ns9/rpz.db b/bin/tests/system/rpz/ns9/rpz.db
new file mode 100644
index 0000000..dcbe5d6
--- /dev/null
+++ b/bin/tests/system/rpz/ns9/rpz.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+rpz. 28800 IN SOA rpz. hostmaster.rpz. 6 10800 3600 2419200 900
+rpz. 28800 IN NS .
+a-only.example.rpz. 28800 IN CNAME *.
+no-a-no-aaaa.example.rpz. 28800 IN CNAME *.
+a-plus-aaaa.example.rpz. 28800 IN CNAME *.
diff --git a/bin/tests/system/rpz/qperf.sh b/bin/tests/system/rpz/qperf.sh
new file mode 100644
index 0000000..146d1e2
--- /dev/null
+++ b/bin/tests/system/rpz/qperf.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+for QDIR in $(echo "$PATH" | tr : ' ') ../../../../contrib/queryperf; do
+ QPERF=$QDIR/queryperf
+ if test -f "$QPERF" -a -x "$QPERF"; then
+ echo $QPERF
+ exit 0
+ fi
+done
+
+exit 0
diff --git a/bin/tests/system/rpz/setup.sh b/bin/tests/system/rpz/setup.sh
new file mode 100644
index 0000000..75e4957
--- /dev/null
+++ b/bin/tests/system/rpz/setup.sh
@@ -0,0 +1,179 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# touch dnsrps-off to not test with DNSRPS
+
+set -e
+
+. ../conf.sh
+
+QPERF=$($SHELL qperf.sh)
+
+USAGE="$0: [-DNx]"
+DEBUG=
+while getopts "DNx" c; do
+ case $c in
+ x) set -x; DEBUG=-x ;;
+ D) TEST_DNSRPS="-D" ;;
+ N) PARTIAL=-P ;;
+ *) echo "$USAGE" 1>&2; exit 1 ;;
+ esac
+done
+shift $((OPTIND - 1))
+if test "$#" -ne 0; then
+ echo "$USAGE" 1>&2
+ exit 1
+fi
+
+if [ ${NOCLEAN:-unset} = unset ]; then
+ $SHELL clean.sh $PARTIAL $DEBUG
+fi
+
+for dir in ns*; do
+ touch $dir/named.run
+ nextpart $dir/named.run > /dev/null
+done
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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
+copy_setports ns8/named.conf.in ns8/named.conf
+copy_setports ns9/named.conf.in ns9/named.conf
+copy_setports ns10/named.conf.in ns10/named.conf
+
+copy_setports dnsrpzd.conf.in dnsrpzd.conf
+
+# decide whether to test DNSRPS
+# Note that dnsrps.conf and dnsrps-secondary.conf are included in named.conf
+# and differ from dnsrpz.conf which is used by dnsrpzd.
+$SHELL ../ckdnsrps.sh -A $TEST_DNSRPS $DEBUG
+test -z "$(grep 'dnsrps-enable yes' dnsrps.conf)" && TEST_DNSRPS=
+
+# set up test policy zones.
+# bl is the main test zone
+# bl-2 is used to check competing zones.
+# bl-{given,disabled,passthru,no-data,nxdomain,cname,wildcard,garden,
+# drop,tcp-only} are used to check policy overrides in named.conf.
+# NO-OP is an obsolete synonym for PASSHTRU
+for NM in '' -2 -given -disabled -passthru -no-op -nodata -nxdomain -cname -wildcname -garden -drop -tcp-only; do
+ sed -e "/SOA/s/blx/bl$NM/g" ns3/base.db >ns3/bl$NM.db
+done
+# bl zones are dynamically updated. Add one zone that is updated manually.
+cp ns3/manual-update-rpz.db.in ns3/manual-update-rpz.db
+cp ns8/manual-update-rpz.db.in ns8/manual-update-rpz.db
+
+cp ns3/mixed-case-rpz-1.db.in ns3/mixed-case-rpz.db
+
+# a zone that expires quickly and then can't be refreshed
+cp ns5/fast-expire.db.in ns5/fast-expire.db
+cp ns5/expire.conf.in ns5/expire.conf
+
+# $1=directory
+# $2=domain name
+# $3=input zone file
+# $4=output file
+signzone () {
+ KEYNAME=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -K $1 $2)
+ cat $1/$3 $1/$KEYNAME.key > $1/tmp
+ $SIGNER -P -K $1 -o $2 -f $1/$4 $1/tmp >/dev/null
+ sed -n -e 's/\(.*\) IN DNSKEY \([0-9]\{1,\} [0-9]\{1,\} [0-9]\{1,\}\) \(.*\)/trust-anchors {"\1" static-key \2 "\3";};/p' $1/$KEYNAME.key >>trusted.conf
+ DSFILENAME=dsset-${2}.
+ rm $DSFILENAME $1/tmp
+}
+signzone ns2 tld2s base-tld2s.db tld2s.db
+
+# Performance and a few other checks.
+cat <<EOF >ns5/rpz-switch
+response-policy {
+ zone "bl0"; zone "bl1"; zone "bl2"; zone "bl3"; zone "bl4";
+ zone "bl5"; zone "bl6"; zone "bl7"; zone "bl8"; zone "bl9";
+ zone "bl10"; zone "bl11"; zone "bl12"; zone "bl13"; zone "bl14";
+ zone "bl15"; zone "bl16"; zone "bl17"; zone "bl18"; zone "bl19";
+ } recursive-only no
+ qname-wait-recurse no
+ nsip-enable yes
+ nsdname-enable yes
+ max-policy-ttl 90
+ break-dnssec yes
+ ;
+EOF
+
+cat <<EOF >ns5/example.db
+\$TTL 300
+@ SOA . hostmaster.ns.example.tld5. ( 1 3600 1200 604800 60 )
+ NS ns
+ NS ns1
+ns A 10.53.0.5
+ns1 A 10.53.0.5
+EOF
+
+cat <<EOF >ns5/bl.db
+\$TTL 300
+@ SOA . hostmaster.ns.blperf. ( 1 3600 1200 604800 60 )
+ NS ns.tld5.
+
+; for "qname-wait-recurse no" in #35 test1
+x.servfail A 35.35.35.35
+; for "recursive-only no" in #8 test5
+a3-5.tld2 CNAME .
+; for "break-dnssec" in #9 & #10 test5
+a3-5.tld2s CNAME .
+; for "max-policy-ttl 90" in #17 test5
+a3-17.tld2 500 A 17.17.17.17
+
+; dummy NSDNAME policy to trigger lookups
+ns1.x.rpz-nsdname CNAME .
+EOF
+
+if test -n "$QPERF"; then
+ # Do not build the full zones if we will not use them.
+ $PERL -e 'for ($val = 1; $val <= 65535; ++$val) {
+ printf("host-%05d\tA 192.168.%d.%d\n", $val, $val/256, $val%256);
+ }' >>ns5/example.db
+
+ echo >>ns5/bl.db
+ echo "; rewrite some names" >>ns5/bl.db
+ $PERL -e 'for ($val = 2; $val <= 65535; $val += 69) {
+ printf("host-%05d.example.tld5\tCNAME\t.\n", $val);
+ }' >>ns5/bl.db
+
+ echo >>ns5/bl.db
+ echo "; rewrite with some not entirely trivial patricia trees" >>ns5/bl.db
+ $PERL -e 'for ($val = 3; $val <= 65535; $val += 69) {
+ printf("32.%d.%d.168.192.rpz-ip \tCNAME\t.\n",
+ $val%256, $val/256);
+ }' >>ns5/bl.db
+fi
+
+# some psuedo-random queryperf requests
+$PERL -e 'for ($cnt = $val = 1; $cnt <= 3000; ++$cnt) {
+ printf("host-%05d.example.tld5 A\n", $val);
+ $val = ($val * 9 + 32771) % 65536;
+ }' >ns5/requests
+
+cp ns2/bl.tld2.db.in ns2/bl.tld2.db
+cp ns5/empty.db.in ns5/empty.db
+cp ns5/empty.db.in ns5/policy2.db
+cp ns6/bl.tld2s.db.in ns6/bl.tld2s.db
+
+# Run dnsrpzd to get the license and prime the static policy zones
+if test -n "$TEST_DNSRPS"; then
+ DNSRPZD="$(../rpz/dnsrps -p)"
+ cd ns3
+ "$DNSRPZ" -D../dnsrpzd.rpzf -S../dnsrpzd.sock -C../dnsrpzd.conf \
+ -w 0 -dddd -L stdout >./dnsrpzd.run 2>&1
+fi
diff --git a/bin/tests/system/rpz/test1 b/bin/tests/system/rpz/test1
new file mode 100644
index 0000000..3dc0375
--- /dev/null
+++ b/bin/tests/system/rpz/test1
@@ -0,0 +1,99 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+
+; Use comment lines instead of blank lines to combine update requests into
+; single requests
+; Separate update requests for distinct TLDs with blank lines or 'send'
+; End the file with a blank line or 'send'
+
+server 10.53.0.3 @PORT@
+
+; QNAME tests
+
+; NXDOMAIN
+; 2, 25
+update add a0-1.tld2.bl. 300 CNAME .
+; NODATA
+; 3
+update add a3-1.tld2.bl. 300 CNAME *.
+; and no assert-botch
+; 4, 5
+update add a3-2.tld2.bl. 300 DNAME example.com.
+;
+; NXDOMAIN for a4-2-cname.tld2 via its target a4-2.tld2.
+; 6 and 7
+update add a4-2.tld2.bl 300 CNAME .
+; 8
+; NODATA for a4-3-cname.tld2 via its target a4-3.tld2.
+update add a4-3.tld2.bl 300 CNAME *.
+;
+; replace the A for a4-1.sub1.tld2 with 12.12.12.12
+; 9
+update add a4-1.sub1.tld2.bl. 300 A 12.12.12.12
+;
+; replace the A for *.sub2.tld2 with 12.12.12.12
+; 10
+update add a4-1.sub2.tld2.bl. 300 A 12.12.12.12
+;
+; replace NXDOMAIN for {nxc1,nxc2}.sub1.tld2 with 12.12.12.12 using CNAMEs
+; 11
+update add nxc1.sub1.tld2.bl. 300 CNAME a12.tld2.
+; 12
+update add nxc2.sub1.tld2.bl. 300 CNAME a12-cname.tld2.
+;
+; prefer the first conflicting zone
+; 13
+update add a4-4.tld2.bl. 300 A 127.4.4.1
+update add a6-1.tld2.bl. 300 CNAME a6-1.tld2.
+update add a6-2.tld2.bl. 300 A 127.6.2.1
+update add a6-1.tld2.bl. 300 A 127.6.1.1
+update add a6-2.tld2.bl. 300 CNAME a6-2.tld2.
+send
+update add a4-4.tld2.bl-2. 300 A 127.4.4.2
+send
+
+; wildcard CNAME
+; 16
+update add a3-6.tld2.bl. 300 CNAME *.tld4.
+; 17
+update add *.sub1.tld2.bl. 300 CNAME *.tld4.
+; CNAME chain
+; 18
+update add a4-5.tld2.bl. 300 A 127.0.0.16
+; stop at first hit in CNAME chain
+; 19
+update add a4-6.tld2.bl. 300 CNAME .
+update add a4-6-cname.tld2.bl. 300 A 127.0.0.17
+; no change instead of NXDOMAIN because +norecurse
+; 20
+update add a5-2.tld2.bl. 300 CNAME .
+; no change instead of NODATA because +norecurse
+; 21
+update add a5-3.tld2.bl. 300 CNAME *.
+; 22, 23
+update add a5-4.tld2.bl. 300 DNAME example.com.
+;
+; assert in rbtdb.c
+; 24
+update add c1.crash2.tld3.bl. 300 CNAME .
+; DO=1 without signatures, DO=0 with signatures are rewritten
+; 26 - 27
+update add a0-1.tld2s.bl. 300 CNAME .
+; 32
+update add a3-8.tld2.bl. 300 CNAME rpz-drop.
+; 33
+update add a3-9.tld2.bl. 300 CNAME rpz-tcp-only.
+; 34 qname-wait-recurse yes
+update add x.servfail.bl. 300 A 127.0.0.34
+send
diff --git a/bin/tests/system/rpz/test2 b/bin/tests/system/rpz/test2
new file mode 100644
index 0000000..ad71e3a
--- /dev/null
+++ b/bin/tests/system/rpz/test2
@@ -0,0 +1,77 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+
+; Use comment lines instead of blank lines to combine update requests into
+; single requests
+; Separate update requests for distinct TLDs with blank lines or 'send'
+; End the file with a blank line or 'send'
+; CNAME targets are absolute even without trailing "."
+
+; IP tests
+
+server 10.53.0.3 @PORT@
+
+; NODATA a3-1.tld2
+; 1
+update add 32.1.3.168.192.rpz-ip.bl 300 CNAME *.
+;
+; NXDOMAIN for 192.168.4.0/24, the network of a4-1.tld2 and a4-2.tld2
+; 4
+update add 24.0.4.168.192.rpz-ip.bl 300 CNAME .
+;
+; old passthru in NXDOMAIN CIDR block to leave a4-1.tld2 unchanged
+; 3
+update add 32.1.4.168.192.rpz-ip.bl 300 CNAME 32.1.4.168.192
+;
+; NODATA for a4-3.tld2
+; 8
+update add 32.3.4.168.192.rpz-ip.bl 300 CNAME *.
+;
+; NXDOMAIN for IPv6 a3-1.tld2
+; 9
+update add 128.1.zz.3.2.2001.rpz-ip.bl 300 CNAME .
+;
+; apply the policy with the lexically smaller trigger address of 192.168.5.1
+; to an RRset of more than one A RR
+; 11
+update add 32.1.5.168.192.rpz-ip.bl 300 A 127.0.0.1
+update add 32.2.5.168.192.rpz-ip.bl 300 A 127.0.0.2
+;
+; prefer first conflicting IP zone for a5-3.tld2
+; 12
+update add 32.3.5.168.192.rpz-ip.bl 300 A 127.0.0.1
+send
+update add 32.3.5.168.192.rpz-ip.bl-2 300 A 127.0.0.2
+send
+
+; prefer QNAME to IP for a5-4.tld2
+; 13, 14
+update add 32.4.5.168.192.rpz-ip.bl 300 CNAME a12.tld2.
+update add a5-4.tld2.bl 300 CNAME a14.tld4.
+;
+; poke hole in NXDOMAIN CIDR block to leave a4-4.tld2 unchanged
+; 15
+update add 32.4.4.168.192.rpz-ip.bl 300 CNAME rpz-passthru.
+;
+; assert in rbtdb.c
+; 16
+update add 32.16.1.16.172.rpz-ip.bl 300 CNAME .
+send
+update add c2.crash2.tld3.bl-2 300 A 127.0.0.16
+send
+
+; client-IP address trigger
+; 17
+update add 32.1.0.53.10.rpz-client-ip.bl 300 A 127.0.0.17
+send
diff --git a/bin/tests/system/rpz/test3 b/bin/tests/system/rpz/test3
new file mode 100644
index 0000000..222b757
--- /dev/null
+++ b/bin/tests/system/rpz/test3
@@ -0,0 +1,47 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; Use comment lines instead of blank lines to combine update requests into
+; single requests
+; Separate update requests for distinct TLDs with blank lines or 'send'
+; End the file with a blank line or 'send'
+
+; NSDNAME tests
+
+server 10.53.0.3 @PORT@
+
+; 3, 4, 5
+; NXDOMAIN for *.sub1.tld2 by NSDNAME
+update add *.sub1.tld2.rpz-nsdname.bl. 300 CNAME .
+;
+; 6
+; walled garden for *.sub2.tld2
+update add *.sub2.tld2.rpz-nsdname.bl. 300 CNAME a12-cname.tld2.
+;
+; 7, 8
+; exempt a3-2.tld2 and anything in 192.168.0.0/24
+; also checks that IP policies are preferred over NSDNAME policies
+update add a3-2.tld2.bl 300 CNAME a3-2.tld2.
+update add 24.0.0.168.192.rpz-ip.bl 300 CNAME 24.0.0.168.192.
+;
+; 9
+; prefer QNAME policy to NSDNAME policy
+update add a4-1.tld2.bl. 300 A 12.12.12.12
+; 10
+; prefer policy for largest NS name
+update add ns.sub3.tld2.rpz-nsdname.bl. 300 A 127.0.0.1
+update add ns.subsub.sub3.tld2.rpz-nsdname.bl. 300 A 127.0.0.2
+
+; ip-as-qname rewrites all of tld5
+update add ns.tld5.bl. 300 A 12.12.12.12
+send
diff --git a/bin/tests/system/rpz/test4 b/bin/tests/system/rpz/test4
new file mode 100644
index 0000000..7b95dd3
--- /dev/null
+++ b/bin/tests/system/rpz/test4
@@ -0,0 +1,36 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; Use comment lines instead of blank lines to combine update requests into
+; single requests
+; Separate update requests for distinct TLDs with blank lines or 'send'
+; End the file with a blank line or 'send'
+
+; NSIP tests
+
+server 10.53.0.3 @PORT@
+
+; NXDOMAIN for all of tld2 based on its server IP address
+update add 32.2.0.53.10.rpz-nsip.bl. 300 CNAME .
+;
+; exempt a3-2.tld2 and anything in 192.168.0.0/24
+; also checks that IP policies are preferred over NSIP policies
+update add a3-2.tld2.bl 300 CNAME a3-2.tld2.
+update add 24.0.0.168.192.rpz-ip.bl 300 CNAME 24.0.0.168.192.
+;
+; prefer NSIP policy to NSDNAME policy
+update add ns.tld2.rpz-nsdname.bl. 300 CNAME 10.0.0.1
+
+; ip-as-ns rewrites all of tld5
+update add 32.5.0.53.10.rpz-ip.bl. 300 A 12.12.12.12
+send
diff --git a/bin/tests/system/rpz/test4a b/bin/tests/system/rpz/test4a
new file mode 100644
index 0000000..83a175d
--- /dev/null
+++ b/bin/tests/system/rpz/test4a
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; Use comment lines instead of blank lines to combine update requests into
+; single requests
+; Separate update requests for distinct TLDs with blank lines or 'send'
+; End the file with a blank line or 'send'
+
+; walled-garden NSIP tests
+
+server 10.53.0.3 @PORT@
+
+; rewrite all of tld2 based on its server IP address
+update add 32.2.0.53.10.rpz-nsip.bl. 300 A 41.41.41.41
+update add 32.2.0.53.10.rpz-nsip.bl. 300 AAAA 2041::41
+update add 32.2.0.53.10.rpz-nsip.bl. 300 TXT "NSIP walled garden"
+send
diff --git a/bin/tests/system/rpz/test5 b/bin/tests/system/rpz/test5
new file mode 100644
index 0000000..f30a6be
--- /dev/null
+++ b/bin/tests/system/rpz/test5
@@ -0,0 +1,60 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; Use comment lines instead of blank lines to combine update requests into
+; single requests
+; Separate update requests for distinct TLDs with blank lines or 'send'
+; End the file with a blank line or 'send'
+
+; the policies or replacements specified in ns3/named.conf override these
+
+server 10.53.0.3 @PORT@
+
+; 1
+update add a3-1.tld2.bl-given. 300 A 127.0.0.1
+send
+; 2
+update add a3-2.tld2.bl-passthru. 300 A 127.0.0.2
+send
+; 3
+update add a3-3.tld2.bl-no-op. 300 A 127.0.0.3
+send
+; 4
+update add a3-4.tld2.bl-disabled. 300 A 127.0.0.4
+send
+; 5 - 7
+update add a3-5.tld2.bl-nodata. 300 A 127.0.0.5
+send
+; 11
+update add a3-6.tld2.bl-nxdomain. 300 A 127.0.0.11
+send
+; 12
+update add a3-7.tld2.bl-cname. 300 A 127.0.0.12
+send
+; 13
+update add a3-8.tld2.bl-wildcname. 300 A 127.0.0.13
+; 14
+update add *.sub9.tld2.bl-wildcname. 300 A 127.0.1.14
+send
+; 15
+update add a3-15.tld2.bl-garden. 300 A 127.0.0.15
+send
+; 16
+update add a3-16.tld2.bl. 300 A 127.0.0.16
+send
+; 18
+update add a3-18.tld2.bl-drop. 300 A 127.0.0.18
+send
+; 19
+update add a3-19.tld2.bl-tcp-only. 300 A 127.0.0.19
+send
diff --git a/bin/tests/system/rpz/test6 b/bin/tests/system/rpz/test6
new file mode 100644
index 0000000..e5c2381
--- /dev/null
+++ b/bin/tests/system/rpz/test6
@@ -0,0 +1,37 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+
+
+; Use comment lines instead of blank lines to combine update requests into
+; single requests
+; Separate update requests for distinct TLDs with blank lines or 'send'
+; End the file with a blank line or 'send'
+
+server 10.53.0.3 @PORT@
+
+; Poke the radix tree a little.
+update add 128.1111.2222.3333.4444.5555.6666.7777.8888.rpz-ip.bl. 300 CNAME .
+update add 128.1111.2222.3333.4444.5555.6666.zz.rpz-ip.bl. 300 CNAME .
+update add 128.1111.2222.3333.4444.5555.zz.8888.rpz-ip.bl. 300 CNAME .
+update add 128.1111.2222.3333.4444.zz.8888.rpz-ip.bl. 300 CNAME .
+update add 128.zz.3333.4444.0.0.8888.rpz-ip.bl. 300 CNAME .
+update add 128.zz.3333.4444.0.7777.8888.rpz-ip.bl. 300 CNAME .
+update add 128.zz.3333.4444.0.8777.8888.rpz-ip.bl. 300 CNAME .
+update add 127.zz.3333.4444.0.8777.8888.rpz-ip.bl. 300 CNAME .
+;
+;
+; regression testing for some old crashes
+update add redirect.bl. 300 A 127.0.0.1
+update add *.redirect.bl. 300 A 127.0.0.1
+update add *.credirect.bl. 300 CNAME google.com.
+;
+send
diff --git a/bin/tests/system/rpz/tests.sh b/bin/tests/system/rpz/tests.sh
new file mode 100644
index 0000000..658250e
--- /dev/null
+++ b/bin/tests/system/rpz/tests.sh
@@ -0,0 +1,1020 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# test response policy zones (RPZ)
+
+# touch dnsrps-off to not test with DNSRPS
+# touch dnsrps-only to not test with classic RPZ
+
+. ../conf.sh
+
+ns=10.53.0
+ns1=$ns.1 # root, defining the others
+ns2=$ns.2 # authoritative server whose records are rewritten
+ns3=$ns.3 # main rewriting resolver
+ns4=$ns.4 # another authoritative server that is rewritten
+ns5=$ns.5 # another rewriting resolver
+ns6=$ns.6 # a forwarding server
+ns7=$ns.7 # another rewriting resolver
+ns8=$ns.8 # another rewriting resolver
+ns9=$ns.9 # another rewriting resolver
+ns10=$ns.10 # authoritative server
+
+HAVE_CORE=
+
+status=0
+t=0
+
+DEBUG=
+SAVE_RESULTS=
+ARGS=
+
+USAGE="$0: [-xS]"
+while getopts "xS:" c; do
+ case $c in
+ x) set -x; DEBUG=-x; ARGS="$ARGS -x";;
+ S) SAVE_RESULTS=-S; ARGS="$ARGS -S";;
+ *) echo "$USAGE" 1>&2; exit 1;;
+ esac
+done
+shift $((OPTIND - 1))
+if test "$#" -ne 0; then
+ echo "$USAGE" 1>&2
+ exit 1
+fi
+# really quit on control-C
+trap 'exit 1' 1 2 15
+
+TS='%H:%M:%S '
+TS=
+comment () {
+ if test -n "$TS"; then
+ date "+${TS}$*" | cat_i
+ fi
+}
+
+DNSRPSCMD=./dnsrps
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+if test -x "$DNSRPSCMD"; then
+ # speed up the many delays for dnsrpzd by waiting only 0.1 seconds
+ WAIT_CMD="$DNSRPSCMD -w 0.1"
+ TEN_SECS=100
+else
+ WAIT_CMD="sleep 1"
+ TEN_SECS=10
+fi
+
+digcmd () {
+ if test "$1" = TCP; then
+ shift
+ fi
+ # Default to +noauth and @$ns3
+ # Also default to -bX where X is the @value so that OS X will choose
+ # the right IP source address.
+ digcmd_args=$(echo "+nocookie +noadd +time=2 +tries=1 -p ${PORT} $*" | \
+ sed -e "/@/!s/.*/& @$ns3/" \
+ -e '/-b/!s/@\([^ ]*\)/@\1 -b\1/' \
+ -e '/+n?o?auth/!s/.*/+noauth &/')
+ #echo_i "dig $digcmd_args 1>&2
+ $DIG $digcmd_args || return
+}
+
+# set DIGNM=file name for dig output
+GROUP_NM=
+TEST_NUM=0
+make_dignm () {
+ TEST_NUM=$((TEST_NUM + 1))
+ DIGNM=dig.out$GROUP_NM-$TEST_NUM
+ while test -f $DIGNM; do
+ DIGNM="$DIGNM+"
+ done
+}
+
+setret () {
+ ret=1
+ status=$((status + 1))
+ echo_i "$*"
+}
+
+# set $SN to the SOA serial number of a zone
+# $1=domain
+# $2=DNS server and client IP address
+get_sn() {
+ SOA=$($DIG -p ${PORT} +short +norecurse soa "$1" "@$2" "-b$2")
+ SN=$(expr "$SOA" : '[^ ]* [^ ]* \([^ ]*\) .*' || true)
+ test "$SN" != "" && return
+ echo_i "no serial number from \`dig -p ${PORT} soa $1 @$2\` in \"$SOA\""
+ exit 1
+}
+
+get_sn_fast () {
+ RSN=$($DNSRPSCMD -n "$1")
+ #echo "dnsrps serial for $1 is $RSN"
+ if test -z "$RSN"; then
+ echo_i "dnsrps failed to get SOA serial number for $1"
+ exit 1
+ fi
+}
+
+# check that dnsrpzd has loaded its zones
+# $1=domain
+# $2=DNS server IP address
+FZONES=$(sed -n -e 's/^zone "\(.*\)".*\(10.53.0..\).*/Z=\1;M=\2/p' dnsrpzd.conf)
+dnsrps_loaded() {
+ test "$mode" = dnsrps || return 0
+ n=0
+ for V in $FZONES; do
+ eval "$V"
+ get_sn $Z $M
+ while true; do
+ get_sn_fast "$Z"
+ if test "$SN" -eq "0$RSN"; then
+ #echo "$Z @$M serial=$SN"
+ break
+ fi
+ n=$((n + 1))
+ if test "$n" -gt $TEN_SECS; then
+ echo_i "dnsrps serial for $Z is $RSN instead of $SN"
+ exit 1
+ fi
+ $WAIT_CMD
+ done
+ done
+}
+
+# check the serial number in an SOA to ensure that a policy zone has
+# been (re)loaded
+# $1=serial number
+# $2=domain
+# $3=DNS server
+ck_soa() {
+ n=0
+ while true; do
+ if test "$mode" = dnsrps; then
+ get_sn_fast "$2"
+ test "$RSN" -eq "$1" && return
+ else
+ get_sn "$2" "$3"
+ test "$SN" -eq "$1" && return
+ fi
+ n=$((n + 1))
+ if test "$n" -gt $TEN_SECS; then
+ echo_i "got serial number \"$SN\" instead of \"$1\" from $2 @$3"
+ return
+ fi
+ $WAIT_CMD
+ done
+}
+
+# (re)load the response policy zones with the rules in the file $TEST_FILE
+load_db () {
+ if test -n "$TEST_FILE"; then
+ copy_setports $TEST_FILE tmp
+ if $NSUPDATE -v tmp; then :
+ $RNDCCMD $ns3 sync
+ else
+ echo_i "failed to update policy zone with $TEST_FILE"
+ $RNDCCMD $ns3 sync
+ exit 1
+ fi
+ rm -f tmp
+ fi
+}
+
+# restart name server
+# $1 ns number
+# $2 rebuild bl rpz zones if "rebuild-bl-rpz"
+restart () {
+ # try to ensure that the server really has stopped
+ # and won't mess with ns$1/name.pid
+ if test -z "$HAVE_CORE" -a -f ns$1/named.pid; then
+ $RNDCCMD $ns$1 halt >/dev/null 2>&1
+ if test -f ns$1/named.pid; then
+ sleep 1
+ PID=$(cat ns$1/named.pid 2>/dev/null)
+ if test -n "$PID"; then
+ echo_i "killing ns$1 server $PID"
+ kill -9 $PID
+ fi
+ fi
+ fi
+ rm -f ns$1/*.jnl
+ if [ "$2" = "rebuild-bl-rpz" ]; then
+ if test -f ns$1/base.db; then
+ for NM in ns$1/bl*.db; do
+ cp -f ns$1/base.db $NM
+ done
+ fi
+ fi
+ start_server --noclean --restart --port ${PORT} ns$1
+ load_db
+ dnsrps_loaded
+ sleep 1
+}
+
+# $1=server and irrelevant args
+# $2=error message
+ckalive () {
+ CKALIVE_NS=$(expr "$1" : '.*@ns\([1-9]\).*' || true)
+ if test -z "$CKALIVE_NS"; then
+ CKALIVE_NS=3
+ fi
+ eval CKALIVE_IP=\$ns$CKALIVE_NS
+ $RNDCCMD $CKALIVE_IP status >/dev/null 2>&1 && return 0
+ HAVE_CORE=yes
+ setret "$2"
+ # restart the server to avoid stalling waiting for it to stop
+ restart $CKALIVE_NS "rebuild-bl-rpz"
+ return 0
+}
+
+resetstats () {
+ NSDIR=$1
+ eval "${NSDIR}_CNT=''"
+}
+
+ckstats () {
+ HOST=$1
+ LABEL="$2"
+ NSDIR="$3"
+ EXPECTED="$4"
+ $RNDCCMD $HOST stats
+ NEW_CNT=$(sed -n -e 's/[ ]*\([0-9]*\).response policy.*/\1/p' \
+ $NSDIR/named.stats | tail -1)
+ eval "OLD_CNT=\$${NSDIR}_CNT"
+ NEW_CNT=$((NEW_CNT))
+ OLD_CNT=$((OLD_CNT))
+ GOT=$((NEW_CNT - OLD_CNT))
+ if test "$GOT" -ne "$EXPECTED"; then
+ setret "wrong $LABEL $NSDIR statistics of $GOT instead of $EXPECTED"
+ fi
+ eval "${NSDIR}_CNT=$NEW_CNT"
+}
+
+ckstatsrange () {
+ HOST=$1
+ LABEL="$2"
+ NSDIR="$3"
+ MIN="$4"
+ MAX="$5"
+ $RNDCCMD $HOST stats
+ NEW_CNT=$(sed -n -e 's/[ ]*\([0-9]*\).response policy.*/\1/p' \
+ $NSDIR/named.stats | tail -1)
+ eval "OLD_CNT=\$${NSDIR}_CNT"
+ NEW_CNT=$((NEW_CNT))
+ OLD_CNT=$((OLD_CNT))
+ GOT=$((NEW_CNT - OLD_CNT))
+ if test "$GOT" -lt "$MIN" -o "$GOT" -gt "$MAX"; then
+ setret "wrong $LABEL $NSDIR statistics of $GOT instead of ${MIN}..${MAX}"
+ fi
+ eval "${NSDIR}_CNT=$NEW_CNT"
+}
+
+# $1=message
+# $2=optional test file name
+start_group () {
+ ret=0
+ t=$((t + 1))
+ test -n "$1" && date "+${TS}checking $1 (${t})" | cat_i
+ TEST_FILE=$2
+ if test -n "$TEST_FILE"; then
+ GROUP_NM="-$TEST_FILE"
+ load_db
+ else
+ GROUP_NM=
+ fi
+ dnsrps_loaded
+ TEST_NUM=0
+}
+
+end_group () {
+ if test -n "$TEST_FILE"; then
+ # remove the previous set of test rules
+ copy_setports $TEST_FILE tmp
+ sed -e 's/[ ]add[ ]/ delete /' tmp | $NSUPDATE
+ rm -f tmp
+ TEST_FILE=
+ fi
+ ckalive $ns3 "failed; ns3 server crashed and restarted"
+ dnsrps_loaded
+ GROUP_NM=
+}
+
+clean_result () {
+ if test -z "$SAVE_RESULTS"; then
+ rm -f $*
+ fi
+}
+
+# $1=dig args
+# $2=other dig output file
+ckresult () {
+ #ckalive "$1" "server crashed by 'dig $1'" || return 1
+ expr "$1" : 'TCP ' > /dev/null && tcp=1 || tcp=0
+ digarg=${1#TCP }
+
+ if grep "flags:.* aa .*ad;" $DIGNM; then
+ setret "'dig $digarg' AA and AD set;"
+ elif grep "flags:.* aa .*ad;" $DIGNM; then
+ setret "'dig $digarg' AD set;"
+ fi
+
+ if $PERL ../digcomp.pl $DIGNM $2 >/dev/null; then
+ grep -q 'Truncated, retrying in TCP' $DIGNM && trunc=1 || trunc=0
+ if [ "$tcp" -ne "$trunc" ]; then
+ setret "'dig $digarg' wrong; no or unexpected truncation in $DIGNM"
+ else
+ clean_result ${DIGNM}*
+ fi
+ return 0
+ fi
+ setret "'dig $digarg' wrong; diff $DIGNM $2"
+ return 0
+}
+
+# check only that the server does not crash
+# $1=target domain
+# $2=optional query type
+nocrash () {
+ digcmd $* >/dev/null
+ ckalive "$*" "server crashed by 'dig $*'"
+}
+
+
+# check rewrite to NXDOMAIN
+# $1=target domain
+# $2=optional query type
+nxdomain () {
+ make_dignm
+ digcmd $* \
+ | sed -e 's/^[a-z].* IN CNAME /;xxx &/' \
+ -e 's/^[a-z].* IN RRSIG /;xxx &/' \
+ >$DIGNM
+ ckresult "$*" proto.nxdomain
+}
+
+# check rewrite to NODATA
+# $1=target domain
+# $2=optional query type
+nodata () {
+ make_dignm
+ digcmd $* \
+ | sed -e 's/^[a-z].* IN CNAME /;xxx &/' >$DIGNM
+ ckresult "$*" proto.nodata
+}
+
+# check rewrite to an address
+# modify the output so that it is easily compared, but save the original line
+# $1=IPv4 address
+# $2=digcmd args
+# $3=optional TTL
+addr () {
+ ADDR=$1
+ make_dignm
+ digcmd $2 >$DIGNM
+ #ckalive "$2" "server crashed by 'dig $2'" || return 1
+ ADDR_ESC=$(echo "$ADDR" | sed -e 's/\./\\./g')
+ ADDR_TTL=$(sed -n -e "s/^[-.a-z0-9]\{1,\}[ ]*\([0-9]*\) IN AA* ${ADDR_ESC}\$/\1/p" $DIGNM)
+ if test -z "$ADDR_TTL"; then
+ setret "'dig $2' wrong; no address $ADDR record in $DIGNM"
+ return 0
+ fi
+ if test -n "$3" && test "$ADDR_TTL" -ne "$3"; then
+ setret "'dig $2' wrong; TTL=$ADDR_TTL instead of $3 in $DIGNM"
+ return 0
+ fi
+ clean_result ${DIGNM}*
+}
+
+# Check that a response is not rewritten
+# Use $ns1 instead of the authority for most test domains, $ns2 to prevent
+# spurious differences for `dig +norecurse`
+# $1=optional "TCP"
+# remaining args for dig
+nochange () {
+ make_dignm
+ digcmd $* >$DIGNM
+ digcmd $* @$ns1 >${DIGNM}_OK
+ ckresult "$*" ${DIGNM}_OK && clean_result ${DIGNM}_OK
+}
+
+nochange_ns10 () {
+ make_dignm
+ digcmd $* >$DIGNM
+ digcmd $* @$ns10 >${DIGNM}_OK
+ ckresult "$*" ${DIGNM}_OK && clean_result ${DIGNM}_OK
+}
+
+# check against a 'here document'
+here () {
+ make_dignm
+ sed -e 's/^[ ]*//' >${DIGNM}_OK
+ digcmd $* >$DIGNM
+ ckresult "$*" ${DIGNM}_OK
+}
+
+# check dropped response
+DROPPED='^;; no servers could be reached'
+drop () {
+ make_dignm
+ digcmd $* >$DIGNM || true
+ if grep "$DROPPED" $DIGNM >/dev/null; then
+ clean_result ${DIGNM}*
+ return 0
+ fi
+ setret "'dig $1' wrong; response in $DIGNM"
+ return 0
+}
+
+nsd() {
+ $NSUPDATE -p ${PORT} << EOF
+ server $1
+ ttl 300
+ update $2 $3 IN CNAME .
+ update $2 $4 IN CNAME .
+ send
+EOF
+ sleep 2
+}
+
+#
+# generate prototype NXDOMAIN response to compare against.
+#
+make_proto_nxdomain() {
+ digcmd nonexistent @$ns2 >proto.nxdomain || return 1
+ grep "status: NXDOMAIN" proto.nxdomain >/dev/null || return 1
+ return 0
+}
+
+#
+# generate prototype NODATA response to compare against.
+#
+make_proto_nodata() {
+ digcmd txt-only.tld2 @$ns2 >proto.nodata || return 1
+ grep "status: NOERROR" proto.nodata >/dev/null || return 1
+ return 0
+}
+
+# ensure that the fast-expire zone is populated before we begin testing
+$RNDCCMD $ns3 retransfer fast-expire
+
+native=0
+dnsrps=0
+for mode in native dnsrps; do
+ status=0
+ case ${mode} in
+ native)
+ if [ -e dnsrps-only ] ; then
+ echo_i "'dnsrps-only' found: skipping native RPZ sub-test"
+ continue
+ else
+ echo_i "running native RPZ sub-test"
+ fi
+ ;;
+ dnsrps)
+ if [ -e dnsrps-off ] ; then
+ echo_i "'dnsrps-off' found: skipping DNSRPS sub-test"
+ continue
+ fi
+ echo_i "attempting to configure servers with DNSRPS..."
+ stop_server --use-rndc --port ${CONTROLPORT}
+ $SHELL ./setup.sh -N -D $DEBUG
+ for server in ns*; do
+ resetstats $server
+ done
+ sed -n 's/^## //p' dnsrps.conf | cat_i
+ if grep '^#fail' dnsrps.conf >/dev/null; then
+ echo_i "exit status: 1"
+ exit 1
+ fi
+ if grep '^#skip' dnsrps.conf > /dev/null; then
+ echo_i "DNSRPS sub-test skipped"
+ continue
+ else
+ echo_i "running DNSRPS sub-test"
+ start_server --noclean --restart --port ${PORT}
+ sleep 3
+ fi
+ ;;
+ esac
+
+ # make prototype files to check against rewritten results
+ retry_quiet 10 make_proto_nxdomain
+ retry_quiet 10 make_proto_nodata
+
+ start_group "QNAME rewrites" test1
+ nochange . # 1 do not crash or rewrite root
+ nxdomain a0-1.tld2 # 2
+ nodata a3-1.tld2 # 3
+ nodata a3-2.tld2 # 4 nodata at DNAME itself
+ nochange sub.a3-2.tld2 # 5 miss where DNAME might work
+ nxdomain a4-2.tld2 # 6 rewrite based on CNAME target
+ nxdomain a4-2-cname.tld2 # 7
+ nodata a4-3-cname.tld2 # 8
+ addr 12.12.12.12 a4-1.sub1.tld2 # 9 A replacement
+ addr 12.12.12.12 a4-1.sub2.tld2 # 10 A replacement with wildcard
+ addr 12.12.12.12 nxc1.sub1.tld2 # 11 replace NXDOMAIN with CNAME
+ addr 12.12.12.12 nxc2.sub1.tld2 # 12 replace NXDOMAIN with CNAME chain
+ addr 127.4.4.1 a4-4.tld2 # 13 prefer 1st conflicting QNAME zone
+ nochange a6-1.tld2 # 14
+ addr 127.6.2.1 a6-2.tld2 # 15
+ addr 56.56.56.56 a3-6.tld2 # 16 wildcard CNAME
+ addr 57.57.57.57 a3-7.sub1.tld2 # 17 wildcard CNAME
+ addr 127.0.0.16 a4-5-cname3.tld2 # 18 CNAME chain
+ addr 127.0.0.17 a4-6-cname3.tld2 # 19 stop short in CNAME chain
+ nochange a5-2.tld2 +norecurse # 20 check that RD=1 is required
+ nochange a5-3.tld2 +norecurse # 21
+ nochange a5-4.tld2 +norecurse # 22
+ nochange sub.a5-4.tld2 +norecurse # 23
+ nxdomain c1.crash2.tld3 # 24 assert in rbtdb.c
+ nxdomain a0-1.tld2 +dnssec # 25 simple DO=1 without signatures
+ nxdomain a0-1.tld2s +nodnssec # 26 simple DO=0 with signatures
+ nochange a0-1.tld2s +dnssec # 27 simple DO=1 with signatures
+ nxdomain a0-1s-cname.tld2s +dnssec # 28 DNSSEC too early in CNAME chain
+ nochange a0-1-scname.tld2 +dnssec # 29 DNSSEC on target in CNAME chain
+ nochange a0-1.tld2s srv +auth +dnssec # 30 no write for DNSSEC and no record
+ nxdomain a0-1.tld2s srv +nodnssec # 31
+ drop a3-8.tld2 any # 32 drop
+ nochange TCP a3-9.tld2 # 33 tcp-only
+ here x.servfail <<'EOF' # 34 qname-wait-recurse yes
+ ;; status: SERVFAIL, x
+EOF
+ addr 35.35.35.35 "x.servfail @$ns5" # 35 qname-wait-recurse no
+ end_group
+ ckstats $ns3 test1 ns3 22
+ ckstats $ns5 test1 ns5 1
+ ckstats $ns6 test1 ns6 0
+
+ start_group "NXDOMAIN/NODATA action on QNAME trigger" test1
+ nxdomain a0-1.tld2 @$ns6 # 1
+ nodata a3-1.tld2 @$ns6 # 2
+ nodata a3-2.tld2 @$ns6 # 3 nodata at DNAME itself
+ nxdomain a4-2.tld2 @$ns6 # 4 rewrite based on CNAME target
+ nxdomain a4-2-cname.tld2 @$ns6 # 5
+ nodata a4-3-cname.tld2 @$ns6 # 6
+ addr 12.12.12.12 "a4-1.sub1.tld2 @$ns6" # 7 A replacement
+ addr 12.12.12.12 "a4-1.sub2.tld2 @$ns6" # 8 A replacement with wildcard
+ addr 127.4.4.1 "a4-4.tld2 @$ns6" # 9 prefer 1st conflicting QNAME zone
+ addr 12.12.12.12 "nxc1.sub1.tld2 @$ns6" # 10 replace NXDOMAIN w/ CNAME
+ addr 12.12.12.12 "nxc2.sub1.tld2 @$ns6" # 11 replace NXDOMAIN w/ CNAME chain
+ addr 127.6.2.1 "a6-2.tld2 @$ns6" # 12
+ addr 56.56.56.56 "a3-6.tld2 @$ns6" # 13 wildcard CNAME
+ addr 57.57.57.57 "a3-7.sub1.tld2 @$ns6" # 14 wildcard CNAME
+ addr 127.0.0.16 "a4-5-cname3.tld2 @$ns6" # 15 CNAME chain
+ addr 127.0.0.17 "a4-6-cname3.tld2 @$ns6" # 16 stop short in CNAME chain
+ nxdomain c1.crash2.tld3 @$ns6 # 17 assert in rbtdb.c
+ nxdomain a0-1.tld2 +dnssec @$ns6 # 18 simple DO=1 without sigs
+ nxdomain a0-1s-cname.tld2s +dnssec @$ns6 # 19
+ drop a3-8.tld2 any @$ns6 # 20 drop
+ end_group
+ ckstatsrange $ns3 test1 ns3 22 30
+ ckstats $ns5 test1 ns5 0
+ ckstats $ns6 test1 ns6 0
+
+ start_group "IP rewrites" test2
+ nodata a3-1.tld2 # 1 NODATA
+ nochange a3-2.tld2 # 2 no policy record so no change
+ nochange a4-1.tld2 # 3 obsolete PASSTHRU record style
+ nxdomain a4-2.tld2 # 4
+ nochange a4-2.tld2 -taaaa # 5 no A => no policy rewrite
+ nochange a4-2.tld2 -ttxt # 6 no A => no policy rewrite
+ nxdomain a4-2.tld2 -tany # 7 no A => no policy rewrite
+ nodata a4-3.tld2 # 8
+ nxdomain a3-1.tld2 -taaaa # 9 IPv6 policy
+ nochange a4-1-aaaa.tld2 -taaaa # 10
+ addr 127.0.0.1 a5-1-2.tld2 # 11 prefer smallest policy address
+ addr 127.0.0.1 a5-3.tld2 # 12 prefer first conflicting IP zone
+ nochange a5-4.tld2 +norecurse # 13 check that RD=1 is required for #14
+ addr 14.14.14.14 a5-4.tld2 # 14 prefer QNAME to IP
+ nochange a4-4.tld2 # 15 PASSTHRU
+ nxdomain c2.crash2.tld3 # 16 assert in rbtdb.c
+ addr 127.0.0.17 "a4-4.tld2 -b $ns1" # 17 client-IP address trigger
+ nxdomain a7-1.tld2 # 18 secondary policy zone (RT34450)
+ # updating an response zone policy
+ cp ns2/blv2.tld2.db.in ns2/bl.tld2.db
+ rndc_reload ns2 $ns2 bl.tld2
+ ck_soa 2 bl.tld2 $ns3
+ nochange a7-1.tld2 # 19 PASSTHRU
+ # ensure that a clock tick has occurred so that named will do the reload
+ sleep 1
+ cp ns2/blv3.tld2.db.in ns2/bl.tld2.db
+ rndc_reload ns2 $ns2 bl.tld2
+ ck_soa 3 bl.tld2 $ns3
+ nxdomain a7-1.tld2 # 20 secondary policy zone (RT34450)
+ end_group
+ ckstats $ns3 test2 ns3 12
+
+ # check that IP addresses for previous group were deleted from the radix tree
+ start_group "radix tree deletions"
+ nochange a3-1.tld2
+ nochange a3-2.tld2
+ nochange a4-1.tld2
+ nochange a4-2.tld2
+ nochange a4-2.tld2 -taaaa
+ nochange a4-2.tld2 -ttxt
+ nochange a4-2.tld2 -tany
+ nochange a4-3.tld2
+ nochange a3-1.tld2 -tAAAA
+ nochange a4-1-aaaa.tld2 -tAAAA
+ nochange a5-1-2.tld2
+ end_group
+ ckstats $ns3 'radix tree deletions' ns3 0
+
+ # these tests assume "min-ns-dots 0"
+ start_group "NSDNAME rewrites" test3
+ nextpart ns3/named.run > /dev/null
+ nochange a3-1.tld2 # 1
+ nochange a3-1.tld2 +dnssec # 2 this once caused problems
+ nxdomain a3-1.sub1.tld2 # 3 NXDOMAIN *.sub1.tld2 by NSDNAME
+ nxdomain a3-1.subsub.sub1.tld2 # 4
+ nxdomain a3-1.subsub.sub1.tld2 -tany # 5
+ addr 12.12.12.12 a4-2.subsub.sub2.tld2 # 6 walled garden for *.sub2.tld2
+ nochange a3-2.tld2. # 7 exempt rewrite by name
+ nochange a0-1.tld2. # 8 exempt rewrite by address block
+ addr 12.12.12.12 a4-1.tld2 # 9 prefer QNAME policy to NSDNAME
+ addr 127.0.0.1 a3-1.sub3.tld2 # 10 prefer policy for largest NSDNAME
+ addr 127.0.0.2 a3-1.subsub.sub3.tld2 # 11
+ nxdomain xxx.crash1.tld2 # 12 dns_db_detachnode() crash
+
+ nxdomain a3-1.stub # 13
+ nxdomain a3-1.static-stub # 14
+ nochange_ns10 a3-1.stub-nomatch # 15
+ nochange_ns10 a3-1.static-stub-nomatch # 16
+ if [ "$mode" = dnsrps ]; then
+ addr 12.12.12.12 as-ns.tld5. # 17 qname-as-ns
+ fi
+ nextpart ns3/named.run | grep -q "unrecognized NS rpz_rrset_find() failed: glue" &&
+ setret "seen: unrecognized NS rpz_rrset_find() failed: glue"
+ end_group
+ if [ "$mode" = dnsrps ]; then
+ ckstats $ns3 test3 ns3 10
+ else
+ ckstats $ns3 test3 ns3 9
+ fi
+
+ # these tests assume "min-ns-dots 0"
+ start_group "NSIP rewrites" test4
+ nextpart ns3/named.run > /dev/null
+ nxdomain a3-1.tld2 # 1 NXDOMAIN for all of tld2
+ nochange a3-2.tld2. # 2 exempt rewrite by name
+ nochange a0-1.tld2. # 3 exempt rewrite by address block
+ nochange a3-1.tld4 # 4 different NS IP address
+ nxdomain a4-1.stub # 5
+ nxdomain a4-1.static-stub # 6
+ nochange_ns10 a4-1.stub-nomatch # 7
+ nochange_ns10 a4-1.static-stub-nomatch # 8
+ if [ "$mode" = dnsrps ]; then
+ addr 12.12.12.12 as-ns.tld5. # 9 ip-as-ns
+ fi
+ nextpart ns3/named.run | grep -q "unrecognized NS rpz_rrset_find() failed: glue" &&
+ setret "seen: unrecognized NS rpz_rrset_find() failed: glue"
+ end_group
+
+ start_group "walled garden NSIP rewrites" test4a
+ addr 41.41.41.41 a3-1.tld2 # 1 walled garden for all of tld2
+ addr 2041::41 'a3-1.tld2 AAAA' # 2 walled garden for all of tld2
+ here a3-1.tld2 TXT <<'EOF' # 3 text message for all of tld2
+ ;; status: NOERROR, x
+ a3-1.tld2. x IN TXT "NSIP walled garden"
+EOF
+ end_group
+ if [ "$mode" = dnsrps ]; then
+ ckstats $ns3 test4 ns3 7
+ else
+ ckstats $ns3 test4 ns3 6
+ fi
+
+ # policies in ./test5 overridden by response-policy{} in ns3/named.conf
+ # and in ns5/named.conf
+ start_group "policy overrides" test5
+ addr 127.0.0.1 a3-1.tld2 # 1 bl-given
+ nochange a3-2.tld2 # 2 bl-passthru
+ nochange a3-3.tld2 # 3 bl-no-op (obsolete for passthru)
+ nochange a3-4.tld2 # 4 bl-disabled
+ nodata a3-5.tld2 # 5 bl-nodata zone recursive-only no
+ nodata a3-5.tld2 +norecurse # 6 bl-nodata zone recursive-only no
+ nodata a3-5.tld2 # 7 bl-nodata not needed
+ nxdomain a3-5.tld2 +norecurse @$ns5 # 8 bl-nodata global recursive-only no
+ nxdomain a3-5.tld2s @$ns5 # 9 bl-nodata global break-dnssec
+ nxdomain a3-5.tld2s +dnssec @$ns5 # 10 bl-nodata global break-dnssec
+ nxdomain a3-6.tld2 # 11 bl-nxdomain
+ here a3-7.tld2 -tany <<'EOF' # 12
+ ;; status: NOERROR, x
+ a3-7.tld2. x IN CNAME txt-only.tld2.
+ txt-only.tld2. x IN TXT "txt-only-tld2"
+EOF
+ addr 58.58.58.58 a3-8.tld2 # 13 bl_wildcname
+ addr 59.59.59.59 a3-9.sub9.tld2 # 14 bl_wildcname
+ addr 12.12.12.12 a3-15.tld2 # 15 bl-garden via CNAME to a12.tld2
+ addr 127.0.0.16 a3-16.tld2 100 # 16 bl max-policy-ttl 100
+ addr 17.17.17.17 "a3-17.tld2 @$ns5" 90 # 17 ns5 bl max-policy-ttl 90
+ drop a3-18.tld2 any # 18 bl-drop
+ nxdomain TCP a3-19.tld2 # 19 bl-tcp-only
+ end_group
+ ckstats $ns3 test5 ns3 12
+ ckstats $ns5 test5 ns5 4
+
+ # check that miscellaneous bugs are still absent
+ start_group "crashes" test6
+ for Q in RRSIG SIG ANY 'ANY +dnssec'; do
+ nocrash a3-1.tld2 -t$Q
+ nocrash a3-2.tld2 -t$Q
+ nocrash a3-5.tld2 -t$Q
+ nocrash www.redirect -t$Q
+ nocrash www.credirect -t$Q
+ done
+
+ # This is not a bug, because any data leaked by writing 24.4.3.2.10.rpz-ip
+ # (or whatever) is available by publishing "foo A 10.2.3.4" and then
+ # resolving foo.
+ # nxdomain 32.3.2.1.127.rpz-ip
+ end_group
+ ckstats $ns3 bugs ns3 8
+
+ # superficial test for major performance bugs
+ QPERF=$(sh qperf.sh)
+ if test -n "$QPERF"; then
+ perf () {
+ date "+${TS}checking performance $1" | cat_i
+ # Dry run to prime everything
+ comment "before dry run $1"
+ $RNDCCMD $ns5 notrace
+ $QPERF -c -1 -l30 -d ns5/requests -s $ns5 -p ${PORT} >/dev/null
+ comment "before real test $1"
+ PFILE="ns5/$2.perf"
+ $QPERF -c -1 -l30 -d ns5/requests -s $ns5 -p ${PORT} >$PFILE
+ comment "after test $1"
+ X=$(sed -n -e 's/.*Returned *\([^ ]*:\) *\([0-9]*\) .*/\1\2/p' $PFILE \
+ | tr '\n' ' ')
+ if test "$X" != "$3"; then
+ setret "wrong results '$X' in $PFILE"
+ fi
+ ckalive $ns5 "failed; server #5 crashed"
+ }
+ trim () {
+ sed -n -e 's/.*Queries per second: *\([0-9]*\).*/\1/p' ns5/$1.perf
+ }
+
+ # get qps with rpz
+ perf 'with RPZ' rpz 'NOERROR:2900 NXDOMAIN:100 '
+ RPZ=$(trim rpz)
+ # turn off rpz and measure qps again
+ echo "# RPZ off" >ns5/rpz-switch
+ RNDCCMD_OUT=$($RNDCCMD $ns5 reload)
+ perf 'without RPZ' norpz 'NOERROR:3000 '
+ NORPZ=$(trim norpz)
+
+ PERCENT=$(( (RPZ * 100 + (NORPZ / 2)) / NORPZ))
+ echo_i "$RPZ qps with RPZ is $PERCENT% of $NORPZ qps without RPZ"
+
+ MIN_PERCENT=30
+ if test "$PERCENT" -lt $MIN_PERCENT; then
+ echo_i "$RPZ qps with rpz or $PERCENT% is below $MIN_PERCENT% of $NORPZ qps"
+ fi
+
+ if test "$PERCENT" -ge 100; then
+ echo_i "$RPZ qps with RPZ or $PERCENT% of $NORPZ qps without RPZ is too high"
+ fi
+
+ ckstats $ns5 performance ns5 200
+
+ else
+ echo_i "performance not checked; queryperf not available"
+ fi
+
+ if [ "$mode" = dnsrps ]; then
+ echo_i "checking that dnsrpzd is automatically restarted"
+ OLD_PID=$(cat dnsrpzd.pid)
+ kill "$OLD_PID"
+ n=0
+ while true; do
+ NEW_PID=$(cat dnsrpzd.pid 2>/dev/null)
+ if test -n "$NEW_PID" -a "0$OLD_PID" -ne "0$NEW_PID"; then
+ #echo "OLD_PID=$OLD_PID NEW_PID=$NEW_PID"
+ break;
+ fi
+ $DIG -p ${PORT} +short +norecurse a0-1.tld2 @$ns3 >/dev/null
+ n=$((n + 1))
+ if test "$n" -gt $TEN_SECS; then
+ setret "dnsrpzd did not restart"
+ break
+ fi
+ $WAIT_CMD
+ done
+ fi
+
+ # Ensure ns3 manages to transfer the fast-expire zone before shutdown.
+ nextpartreset ns3/named.run
+ wait_for_log 20 "zone fast-expire/IN: transferred serial 1" ns3/named.run
+
+ # reconfigure the ns5 primary server without the fast-expire zone, so
+ # it can't be refreshed on ns3, and will expire in 5 seconds.
+ cat /dev/null > ns5/expire.conf
+ rndc_reconfig ns5 10.53.0.5
+
+ # restart the main test RPZ server to see if that creates a core file
+ if test -z "$HAVE_CORE"; then
+ stop_server --use-rndc --port ${CONTROLPORT} ns3
+ restart 3 "rebuild-bl-rpz"
+ HAVE_CORE=$(find ns* -name '*core*' -print)
+ test -z "$HAVE_CORE" || setret "found $HAVE_CORE; memory leak?"
+ fi
+
+ # look for complaints from lib/dns/rpz.c and bin/name/query.c
+ for runfile in ns*/named.run; do
+ EMSGS=$(nextpart $runfile | grep -E -l 'invalid rpz|rpz.*failed' || true)
+ if test -n "$EMSGS"; then
+ setret "error messages in $runfile starting with:"
+ grep -E 'invalid rpz|rpz.*failed' ns*/named.run | \
+ sed -e '10,$d' -e 's/^//' | cat_i
+ fi
+ done
+
+ if [ native = "$mode" ]; then
+ # restart the main test RPZ server with a bad zone.
+ t=$((t + 1))
+ echo_i "checking that ns3 with broken rpz does not crash (${t})"
+ stop_server --use-rndc --port ${CONTROLPORT} ns3
+ cp ns3/broken.db.in ns3/bl.db
+ restart 3 # do not rebuild rpz zones
+ nocrash a3-1.tld2 -tA
+ stop_server --use-rndc --port ${CONTROLPORT} ns3
+ restart 3 "rebuild-bl-rpz"
+
+ t=$((t + 1))
+ echo_i "checking if rpz survives a certain class of failed reconfiguration attempts (${t})"
+ sed -e "s/^#BAD//" < ns3/named.conf.in > ns3/named.conf.tmp
+ copy_setports ns3/named.conf.tmp ns3/named.conf
+ rm ns3/named.conf.tmp
+ $RNDCCMD $ns3 reconfig > /dev/null 2>&1 && setret "failed"
+ sleep 1
+ copy_setports ns3/named.conf.in ns3/named.conf
+ $RNDCCMD $ns3 reconfig || setret "failed"
+
+ # reload a RPZ zone that is now deliberately broken.
+ t=$((t + 1))
+ echo_i "checking rpz failed update will keep previous rpz rules (${t})"
+ $DIG -p ${PORT} @$ns3 walled.tld2 > dig.out.$t.before
+ grep "walled\.tld2\..*IN.*A.*10\.0\.0\.1" dig.out.$t.before > /dev/null || setret "failed"
+ cp ns3/broken.db.in ns3/manual-update-rpz.db
+ rndc_reload ns3 $ns3 manual-update-rpz
+ sleep 1
+ # ensure previous RPZ rules still apply.
+ $DIG -p ${PORT} @$ns3 walled.tld2 > dig.out.$t.after
+ grep "walled\.tld2\..*IN.*A.*10\.0\.0\.1" dig.out.$t.after > /dev/null || setret "failed"
+
+ t=$((t + 1))
+ echo_i "checking reload of a mixed-case RPZ zone (${t})"
+ # First, a sanity check: the A6-2.TLD2.mixed-case-rpz RPZ record should
+ # cause a6-2.tld2 NOERROR answers to be rewritten to NXDOMAIN answers.
+ $DIG -p ${PORT} @$ns3 a6-2.tld2. A > dig.out.$t.before
+ grep "status: NXDOMAIN" dig.out.$t.before >/dev/null || setret "failed"
+ # Add a sibling name (a6-1.tld2.mixed-case-rpz, with "tld2" in lowercase
+ # rather than uppercase) before A6-2.TLD.mixed-case-rpz.
+ nextpart ns3/named.run > /dev/null
+ cp ns3/mixed-case-rpz-2.db.in ns3/mixed-case-rpz.db
+ rndc_reload ns3 $ns3 mixed-case-rpz
+ wait_for_log 20 "rpz: mixed-case-rpz: reload done" ns3/named.run
+ # a6-2.tld2 NOERROR answers should still be rewritten to NXDOMAIN answers.
+ # (The bug we try to trigger here caused a6-2.tld2.mixed-case-rpz to be
+ # erroneously removed from the summary RPZ database after reload.)
+ $DIG -p ${PORT} @$ns3 a6-2.tld2. A > dig.out.$t.after
+ grep "status: NXDOMAIN" dig.out.$t.after >/dev/null || setret "failed"
+ fi
+
+ t=$((t + 1))
+ echo_i "checking that ttl values are not zeroed when qtype is '*' (${t})"
+ $DIG +noall +answer -p ${PORT} @$ns3 any a3-2.tld2 > dig.out.$t
+ ttl=$(awk '/a3-2 tld2 text/ {print $2}' dig.out.$t)
+ if test ${ttl:=0} -eq 0; then setret "failed"; fi
+
+ t=$((t + 1))
+ echo_i "checking rpz updates/transfers with parent nodes added after children (${t})"
+ # regression test for RT #36272: the success condition
+ # is the secondary server not crashing.
+ for i in 1 2 3 4 5; do
+ nsd $ns5 add example.com.policy1. '*.example.com.policy1.'
+ nsd $ns5 delete example.com.policy1. '*.example.com.policy1.'
+ done
+ for i in 1 2 3 4 5; do
+ nsd $ns5 add '*.example.com.policy1.' example.com.policy1.
+ nsd $ns5 delete '*.example.com.policy1.' example.com.policy1.
+ done
+
+ t=$((t + 1))
+ echo_i "checking that going from an empty policy zone works (${t})"
+ nsd $ns5 add '*.x.servfail.policy2.' x.servfail.policy2.
+ sleep 1
+ rndc_reload ns7 $ns7 policy2
+ $DIG z.x.servfail -p ${PORT} @$ns7 > dig.out.${t}
+ grep NXDOMAIN dig.out.${t} > /dev/null || setret "failed"
+
+ t=$((t + 1))
+ echo_i "checking that "add-soa no" at rpz zone level works (${t})"
+ $DIG z.x.servfail -p ${PORT} @$ns7 > dig.out.${t}
+ grep SOA dig.out.${t} > /dev/null && setret "failed"
+
+ if [ native = "$mode" ]; then
+ t=$((t + 1))
+ echo_i "checking that "add-soa yes" at response-policy level works (${t})"
+ $DIG walled.tld2 -p ${PORT} +noall +add @$ns3 > dig.out.${t}
+ grep "^manual-update-rpz\..*SOA" dig.out.${t} > /dev/null || setret "failed"
+ fi
+
+ if [ native = "$mode" ]; then
+ t=$((t + 1))
+ echo_i "reconfiguring server with 'add-soa no' (${t})"
+ cp ns3/named.conf ns3/named.conf.tmp
+ sed -e "s/add-soa yes/add-soa no/g" < ns3/named.conf.tmp > ns3/named.conf
+ rndc_reconfig ns3 $ns3
+ echo_i "checking that 'add-soa no' at response-policy level works (${t})"
+ $DIG walled.tld2 -p ${PORT} +noall +add @$ns3 > dig.out.${t}
+ grep "^manual-update-rpz\..*SOA" dig.out.${t} > /dev/null && setret "failed"
+ fi
+
+ if [ native = "$mode" ]; then
+ t=$((t + 1))
+ echo_i "checking that 'add-soa unset' works (${t})"
+ $DIG walled.tld2 -p ${PORT} +noall +add @$ns8 > dig.out.${t}
+ grep "^manual-update-rpz\..*SOA" dig.out.${t} > /dev/null || setret "failed"
+ fi
+
+ # dnsrps does not allow NS RRs in policy zones, so this check
+ # with dnsrps results in no rewriting.
+ if [ native = "$mode" ]; then
+ t=$((t + 1))
+ echo_i "checking rpz with delegation fails correctly (${t})"
+ $DIG -p ${PORT} @$ns3 ns example.com > dig.out.$t
+ grep "status: SERVFAIL" dig.out.$t > /dev/null || setret "failed"
+
+ t=$((t + 1))
+ echo_i "checking policies from expired zone are no longer in effect ($t)"
+ $DIG -p ${PORT} @$ns3 a expired > dig.out.$t
+ grep "expired.*10.0.0.10" dig.out.$t > /dev/null && setret "failed"
+ grep "fast-expire/IN: response-policy zone expired" ns3/named.run > /dev/null || setret "failed"
+ fi
+
+ # RPZ 'CNAME *.' (NODATA) trumps DNS64. Test against various DNS64 scenarios.
+ for label in a-only no-a-no-aaaa a-plus-aaaa
+ do
+ for type in AAAA A
+ do
+ t=$((t + 1))
+ case $label in
+ a-only)
+ echo_i "checking rpz 'CNAME *.' (NODATA) with dns64, $type lookup with A-only (${t})"
+ ;;
+ no-a-no-aaaa)
+ echo_i "checking rpz 'CNAME *.' (NODATA) with dns64, $type lookup with no A or AAAA (${t})"
+ ;;
+ a-plus-aaaa)
+ echo_i "checking rpz 'CNAME *.' (NODATA) with dns64, $type lookup with A and AAAA (${t})"
+ ;;
+ esac
+ ret=0
+ $DIG ${label}.example -p ${PORT} $type @10.53.0.9 > dig.out.${t}
+ grep "status: NOERROR" dig.out.$t > /dev/null || ret=1
+ grep "ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 2$" dig.out.$t > /dev/null || ret=1
+ grep "^rpz" dig.out.$t > /dev/null || ret=1
+ [ $ret -eq 0 ] || echo_i "failed"
+ status=$((status + ret))
+ done
+ done
+
+ if [ native = "$mode" ]; then
+ t=$((t + 1))
+ echo_i "checking that rewriting CD=1 queries handles pending data correctly (${t})"
+ $RNDCCMD $ns3 flush
+ $RNDCCMD $ns6 flush
+ $DIG a7-2.tld2s -p ${PORT} @$ns6 +cd > dig.out.${t}
+ grep -w "1.1.1.1" dig.out.${t} > /dev/null || setret "failed"
+ fi
+
+ [ $status -ne 0 ] && pf=fail || pf=pass
+ case $mode in
+ native)
+ native=$status
+ echo_i "status (native RPZ sub-test): $status ($pf)";;
+
+ dnsrps)
+ dnsrps=$status
+ echo_i "status (DNSRPS sub-test): $status ($pf)";;
+ *) echo_i "invalid test mode";;
+ esac
+done
+status=$((native + dnsrps))
+
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rpz/tests_sh_rpz.py b/bin/tests/system/rpz/tests_sh_rpz.py
new file mode 100644
index 0000000..1d551b5
--- /dev/null
+++ b/bin/tests/system/rpz/tests_sh_rpz.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_rpz(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/rpzextra/clean.sh b/bin/tests/system/rpzextra/clean.sh
new file mode 100644
index 0000000..928ee8b
--- /dev/null
+++ b/bin/tests/system/rpzextra/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/*.jnl
+rm -f ns*/named.conf
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run
+rm -f ns*/rpz*.txt
+rm -rf __pycache__
+rm -f ns3/*-rpz-external.local.db
diff --git a/bin/tests/system/rpzextra/ns2/allowed.db b/bin/tests/system/rpzextra/ns2/allowed.db
new file mode 100644
index 0000000..57a733c
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns2/allowed.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+
+@ IN SOA ns1 root.allowed. 2020040101 4h 1h 1w 60
+@ IN NS ns1
+ns1 IN A 10.53.0.2
+@ IN A 10.53.0.2
+www IN A 10.53.0.2
diff --git a/bin/tests/system/rpzextra/ns2/baddomain.db b/bin/tests/system/rpzextra/ns2/baddomain.db
new file mode 100644
index 0000000..3946da3
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns2/baddomain.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+
+@ IN SOA ns1 root.baddomain. (
+ 2020040101
+ 4h
+ 1h
+ 1w
+ 60
+)
+
+ IN NS ns1
+
+ns1 IN A 10.53.0.2
+
+baddomain. IN A 10.53.0.2
+www IN A 10.53.0.3
diff --git a/bin/tests/system/rpzextra/ns2/gooddomain.db b/bin/tests/system/rpzextra/ns2/gooddomain.db
new file mode 100644
index 0000000..1fb720c
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns2/gooddomain.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+
+@ IN SOA ns1 root.gooddomain. (
+ 2020040101
+ 4h
+ 1h
+ 1w
+ 60
+)
+
+ IN NS ns1
+
+ns1 IN A 10.53.0.2
+
+gooddomain. IN A 10.53.0.2
+www IN A 10.53.0.3
diff --git a/bin/tests/system/rpzextra/ns2/named.conf.in b/bin/tests/system/rpzextra/ns2/named.conf.in
new file mode 100644
index 0000000..6317563
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns2/named.conf.in
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ listen-on { 10.53.0.2; };
+ pid-file "named.pid";
+ notify no;
+ dnssec-validation no;
+ allow-query { any; };
+};
+
+zone "allowed" {
+ type primary;
+ file "allowed.db";
+ allow-transfer { none; };
+};
+
+zone "baddomain" {
+ type primary;
+ file "baddomain.db";
+ allow-transfer { none; };
+};
+
+zone "gooddomain" {
+ type primary;
+ file "gooddomain.db";
+ allow-transfer { none; };
+};
+
+zone "rpz-external.local" {
+ type primary;
+ file "rpz-external.local.db";
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/rpzextra/ns2/rpz-external.local.db b/bin/tests/system/rpzextra/ns2/rpz-external.local.db
new file mode 100644
index 0000000..b3ab69e
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns2/rpz-external.local.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+
+@ IN SOA localhost.rpz-external.local root.rpz-external.local. (
+ 2020022500 ; serial number
+ 60 ; refresh every minute
+ 60 ; retry every minute
+ 432000 ; expire in 5 days
+ 60 ; negative caching ttl, 1 minute
+)
+
+
+ IN NS LOCALHOST.
+
+allowed IN CNAME .
+*.allowed IN CNAME .
diff --git a/bin/tests/system/rpzextra/ns3/external-rpz.local.db b/bin/tests/system/rpzextra/ns3/external-rpz.local.db
new file mode 100644
index 0000000..aad6b89
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns3/external-rpz.local.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+
+@ IN SOA localhost.rpz.local root.rpz.local. (
+ 2020022500 ; serial number
+ 60 ; refresh every minute
+ 60 ; retry every minute
+ 432000 ; expire in 5 days
+ 60 ; negative caching ttl, 1 minute
+)
+
+
+ IN NS LOCALHOST.
+
+allowed IN CNAME rpz-passthru.
+*.allowed IN CNAME rpz-passthru.
+
+gooddomain IN CNAME .
+*.gooddomain IN CNAME .
diff --git a/bin/tests/system/rpzextra/ns3/first-rpz.local.db b/bin/tests/system/rpzextra/ns3/first-rpz.local.db
new file mode 100644
index 0000000..4203ca1
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns3/first-rpz.local.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+
+@ IN SOA localhost.rpz.local root.rpz.local. (
+ 2020022500 ; serial number
+ 60 ; refresh every minute
+ 60 ; retry every minute
+ 432000 ; expire in 5 days
+ 60 ; negative caching ttl, 1 minute
+)
+
+
+ IN NS LOCALHOST.
+
+allowed IN CNAME rpz-passthru.
+*.allowed IN CNAME rpz-passthru.
+
+baddomain IN CNAME .
+*.baddomain IN CNAME .
diff --git a/bin/tests/system/rpzextra/ns3/fourth-rpz-extra.local.db b/bin/tests/system/rpzextra/ns3/fourth-rpz-extra.local.db
new file mode 100644
index 0000000..471030c
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns3/fourth-rpz-extra.local.db
@@ -0,0 +1,32 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+
+@ IN SOA localhost.rpz-extra.local root.rpz-extra.local. (
+ 2020022500 ; serial number
+ 60 ; refresh every minute
+ 60 ; retry every minute
+ 432000 ; expire in 5 days
+ 60 ; negative caching ttl, 1 minute
+)
+
+
+ IN NS LOCALHOST.
+
+allowed IN CNAME rpz-passthru.
+*.allowed IN CNAME rpz-passthru.
+
+gooddomain IN CNAME .
+*.gooddomain IN CNAME .
+
+baddomain IN CNAME .
+*.baddomain IN CNAME .
diff --git a/bin/tests/system/rpzextra/ns3/named.args b/bin/tests/system/rpzextra/ns3/named.args
new file mode 100644
index 0000000..970fc22
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns3/named.args
@@ -0,0 +1 @@
+ -m record -c named.conf -d 99 -D rpzextra-ns1 -X named.lock -U 4 -T maxcachesize=2097152
diff --git a/bin/tests/system/rpzextra/ns3/named.conf.in b/bin/tests/system/rpzextra/ns3/named.conf.in
new file mode 100644
index 0000000..cd459bc
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns3/named.conf.in
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ listen-on { 10.53.0.3; };
+ pid-file "named.pid";
+ notify no;
+ dnssec-validation no;
+ allow-query { any; };
+ recursion yes;
+ allow-recursion { any; };
+ empty-zones-enable false;
+ response-policy {
+ zone "rpz-extra.local";
+ };
+};
+
+logging {
+ channel rpz_passthru {
+ file "rpz_passthru.txt" versions 3 size 5m;
+ print-time yes;
+ print-category yes;
+ print-severity yes;
+ severity info;
+ };
+
+ channel rpz_log {
+ file "rpz.txt" versions 3 size 20m;
+ print-time yes;
+ print-category yes;
+ print-severity yes;
+ severity info;
+ };
+
+ category rpz { rpz_log; default_debug; };
+ category rpz-passthru { rpz_passthru; default_debug; };
+};
+
+view "first" {
+ match-clients { 10.53.0.1; };
+ zone "." {
+ type hint;
+ file "root.db";
+ };
+ zone "rpz.local" {
+ type primary;
+ file "first-rpz.local.db";
+ allow-transfer { none; };
+ allow-query { localhost; };
+ };
+ response-policy {
+ zone "rpz.local";
+ };
+};
+
+view "second" {
+ match-clients { 10.53.0.2; };
+ zone "." {
+ type hint;
+ file "root.db";
+ };
+ zone "rpz-external.local" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "second-rpz-external.local.db";
+ allow-query { 10.53.0.2; };
+ };
+ response-policy {
+ zone "rpz-external.local";
+ };
+};
+
+view "third" {
+ match-clients { 10.53.0.3; };
+ zone "." {
+ type hint;
+ file "root.db";
+ };
+ zone "rpz-extra.local" {
+ type primary;
+ file "third-rpz-extra.local.db";
+ allow-transfer { none; };
+ allow-query { localhost; };
+ };
+};
+
+view "fourth" {
+ match-clients { 10.53.0.4; };
+ zone "." {
+ type hint;
+ file "root.db";
+ };
+ zone "rpz-extra.local" {
+ type primary;
+ file "fourth-rpz-extra.local.db";
+ allow-transfer { none; };
+ allow-query { localhost; };
+ };
+};
+
+view "external" {
+ match-clients { any; };
+ zone "." {
+ type hint;
+ file "root.db";
+ };
+ zone "rpz.local" {
+ type primary;
+ file "external-rpz.local.db";
+ allow-transfer { none; };
+ allow-query { localhost; };
+ };
+ zone "rpz-external.local" {
+ type secondary;
+ masterfile-format text;
+ primaries { 10.53.0.2; };
+ file "external-rpz-external.local.db";
+ allow-query { 10.53.0.5; };
+ };
+ response-policy {
+ zone "rpz-external.local";
+ zone "rpz.local";
+ };
+};
diff --git a/bin/tests/system/rpzextra/ns3/root.db b/bin/tests/system/rpzextra/ns3/root.db
new file mode 100644
index 0000000..ca49988
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns3/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS ns1.allowed
+
+
+allowed. NS ns1.allowed.
+ns1.allowed. A 10.53.0.2
+
+baddomain. NS ns1.baddomain.
+ns1.baddomain. A 10.53.0.2
+
+gooddomain. NS ns1.gooddomain.
+ns1.gooddomain. A 10.53.0.2
diff --git a/bin/tests/system/rpzextra/ns3/third-rpz-extra.local.db b/bin/tests/system/rpzextra/ns3/third-rpz-extra.local.db
new file mode 100644
index 0000000..a8b46fa
--- /dev/null
+++ b/bin/tests/system/rpzextra/ns3/third-rpz-extra.local.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+
+@ IN SOA localhost.rpz-extra.local root.rpz-extra.local. (
+ 2020022500 ; serial number
+ 60 ; refresh every minute
+ 60 ; retry every minute
+ 432000 ; expire in 5 days
+ 60 ; negative caching ttl, 1 minute
+)
+
+
+ IN NS LOCALHOST.
+
+allowed IN CNAME rpz-passthru.
+*.allowed IN CNAME rpz-passthru.
diff --git a/bin/tests/system/rpzextra/setup.sh b/bin/tests/system/rpzextra/setup.sh
new file mode 100644
index 0000000..2dbb388
--- /dev/null
+++ b/bin/tests/system/rpzextra/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# touch dnsrps-off to not test with DNSRPS
+
+set -e
+
+. ../conf.sh
+
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
diff --git a/bin/tests/system/rpzextra/tests_rpzextra.py b/bin/tests/system/rpzextra/tests_rpzextra.py
new file mode 100644
index 0000000..ab5da45
--- /dev/null
+++ b/bin/tests/system/rpzextra/tests_rpzextra.py
@@ -0,0 +1,143 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import time
+import os
+
+import pytest
+
+pytest.importorskip("dns", minversion="2.0.0")
+import dns.resolver
+
+
+def wait_for_transfer(ip, port, client_ip, name, rrtype):
+ resolver = dns.resolver.Resolver()
+ resolver.nameservers = [ip]
+ resolver.port = port
+
+ for _ in range(10):
+ try:
+ resolver.resolve(name, rrtype, source=client_ip)
+ except dns.resolver.NoNameservers:
+ time.sleep(1)
+ else:
+ break
+ else:
+ raise RuntimeError(
+ "zone transfer failed: "
+ f"client {client_ip} got NXDOMAIN for {name} {rrtype} from @{ip}:{port}"
+ )
+
+
+def test_rpz_multiple_views(named_port):
+ resolver = dns.resolver.Resolver()
+ resolver.nameservers = ["10.53.0.3"]
+ resolver.port = named_port
+
+ wait_for_transfer("10.53.0.3", named_port, "10.53.0.2", "rpz-external.local", "SOA")
+ wait_for_transfer("10.53.0.3", named_port, "10.53.0.5", "rpz-external.local", "SOA")
+
+ # For 10.53.0.1 source IP:
+ # - baddomain.com isn't allowed (CNAME .), should return NXDOMAIN
+ # - gooddomain.com is allowed
+ # - allowed. is allowed
+ with pytest.raises(dns.resolver.NXDOMAIN):
+ resolver.resolve("baddomain.", "A", source="10.53.0.1")
+
+ ans = resolver.resolve("gooddomain.", "A", source="10.53.0.1")
+ assert ans[0].address == "10.53.0.2"
+
+ ans = resolver.resolve("allowed.", "A", source="10.53.0.1")
+ assert ans[0].address == "10.53.0.2"
+
+ # For 10.53.0.2 source IP:
+ # - allowed.com isn't allowed (CNAME .), should return NXDOMAIN
+ # - baddomain.com is allowed
+ # - gooddomain.com is allowed
+ ans = resolver.resolve("baddomain.", "A", source="10.53.0.2")
+ assert ans[0].address == "10.53.0.2"
+
+ ans = resolver.resolve("gooddomain.", "A", source="10.53.0.2")
+ assert ans[0].address == "10.53.0.2"
+
+ with pytest.raises(dns.resolver.NXDOMAIN):
+ resolver.resolve("allowed.", "A", source="10.53.0.2")
+
+ # For 10.53.0.3 source IP:
+ # - gooddomain.com is allowed
+ # - baddomain.com is allowed
+ # - allowed. is allowed
+ ans = resolver.resolve("baddomain.", "A", source="10.53.0.3")
+ assert ans[0].address == "10.53.0.2"
+
+ ans = resolver.resolve("gooddomain.", "A", source="10.53.0.3")
+ assert ans[0].address == "10.53.0.2"
+
+ ans = resolver.resolve("allowed.", "A", source="10.53.0.3")
+ assert ans[0].address == "10.53.0.2"
+
+ # For 10.53.0.4 source IP:
+ # - gooddomain.com isn't allowed (CNAME .), should return NXDOMAIN
+ # - baddomain.com isn't allowed (CNAME .), should return NXDOMAIN
+ # - allowed. is allowed
+ with pytest.raises(dns.resolver.NXDOMAIN):
+ resolver.resolve("baddomain.", "A", source="10.53.0.4")
+
+ with pytest.raises(dns.resolver.NXDOMAIN):
+ resolver.resolve("gooddomain.", "A", source="10.53.0.4")
+
+ ans = resolver.resolve("allowed.", "A", source="10.53.0.4")
+ assert ans[0].address == "10.53.0.2"
+
+ # For 10.53.0.5 (any) source IP:
+ # - baddomain.com is allowed
+ # - gooddomain.com isn't allowed (CNAME .), should return NXDOMAIN
+ # - allowed.com isn't allowed (CNAME .), should return NXDOMAIN
+ ans = resolver.resolve("baddomain.", "A", source="10.53.0.5")
+ assert ans[0].address == "10.53.0.2"
+
+ with pytest.raises(dns.resolver.NXDOMAIN):
+ resolver.resolve("gooddomain.", "A", source="10.53.0.5")
+
+ with pytest.raises(dns.resolver.NXDOMAIN):
+ resolver.resolve("allowed.", "A", source="10.53.0.5")
+
+
+def test_rpz_passthru_logging(named_port):
+ resolver = dns.resolver.Resolver()
+ resolver.nameservers = ["10.53.0.3"]
+ resolver.port = named_port
+
+ # Should generate a log entry into rpz_passthru.txt
+ ans = resolver.resolve("allowed.", "A", source="10.53.0.1")
+ assert ans[0].address == "10.53.0.2"
+
+ # baddomain.com isn't allowed (CNAME .), should return NXDOMAIN
+ # Should generate a log entry into rpz.txt
+ with pytest.raises(dns.resolver.NXDOMAIN):
+ resolver.resolve("baddomain.", "A", source="10.53.0.1")
+
+ rpz_passthru_logfile = os.path.join("ns3", "rpz_passthru.txt")
+ rpz_logfile = os.path.join("ns3", "rpz.txt")
+
+ assert os.path.isfile(rpz_passthru_logfile)
+ assert os.path.isfile(rpz_logfile)
+
+ with open(rpz_passthru_logfile, encoding="utf-8") as log_file:
+ line = log_file.read()
+ assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" in line
+
+ with open(rpz_logfile, encoding="utf-8") as log_file:
+ line = log_file.read()
+ assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" not in line
+ assert "rpz QNAME NXDOMAIN rewrite baddomain/A/IN" in line
diff --git a/bin/tests/system/rpzrecurse/README b/bin/tests/system/rpzrecurse/README
new file mode 100644
index 0000000..5936e05
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/README
@@ -0,0 +1,124 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+These tests check RPZ recursion behavior (including skipping
+recursion when appropriate).
+
+The general structure of the tests is:
+
+* The resolver (ns2) with an unqualified view containing the policy
+ zones, the response-policy statement, and a root hint zone
+
+* The auth server that contains two authoritative zones, l1.l0 and
+ l2.l1.l0, both delegated to itself. l2.l1.l0 specifies a non-existent
+ zone data file and so will generate SERVFAILs for any queries to it.
+
+The l2.l1.l0 zone was chosen to generate SERVFAIL responses because RPZ
+evaluation will use that error response whenever it encounters it during
+processing, thus making it a binary indicator for whether or not
+recursion was attempted. This also allows us to not worry about having
+to craft 'ip', 'nsdname', and 'nsip' rules that matched the queries.
+
+Each test is intended to be fed a number of queries constructed as
+qXX.l2.l1.l0, where XX is the 1-based query sequence number (e.g. the
+first query of each test is q01.l2.l1.l0).
+
+For all the tests the triggers are constructed as follows:
+client-ip - match 127.0.0.1/32
+ip - match 255.255.255.255/32 (does not matter due to SERVFAIL)
+nsdname - match ns.example.org (also does not matter)
+nsip - match 255.255.255.255/32 (also does not matter)
+qname - match qXX.l2.l1.l0, where XX is the query sequence number that
+is intended to be matched by this qname rule.
+
+Here's the detail on the test cases:
+
+Group 1 - testing skipping recursion for a single policy zone with only
+records that allow recursion to be skipped
+
+Test 1a:
+ 1 policy zone containing 1 'client-ip' trigger
+ 1 query, expected to skip recursion
+
+Test 1b:
+ 1 policy zone containing 1 'qname' trigger (q01)
+ 2 queries, q01 is expected to skip recursion, q02 is expected to
+ recurse
+
+Test 1c:
+ 1 policy zone containing both a 'client-ip' and 'qname' trigger (q02)
+ 1 query, expected to skip recursion
+
+Group 2 - testing skipping recursion with multiple policy zones when all
+zones have only trigger types eligible to skip recursion with
+
+Test 2a:
+ 32 policy zones, each containing 1 'qname' trigger (qNN, where NN is
+ the zone's sequence 1-based sequence number formatted to 2 digits,
+ so each of the first 32 queries should match a different zone)
+ 33 queries, the first 32 of which are expected to skip recursion
+ while the 33rd is expected to recurse
+
+Group 3 - Testing interaction of triggers that require recursion when in
+a single zone, both alone and with triggers that allow recursion to be
+skipped
+
+Test 3a:
+ 1 policy zone containing 1 'ip' trigger
+ 1 query, expected to recurse
+
+Test 3b:
+ 1 policy zone containing 1 'nsdname' trigger
+ 1 query, expected to recurse
+
+Test 3c:
+ 1 policy zone containing 1 'nsip' trigger
+ 1 query, expected to recurse
+
+Test 3d:
+ 1 policy zone containing 1 'ip' trigger and 1 'qname' trigger (q02)
+ 2 queries, the first should not recurse and the second should recurse
+
+Test 3e:
+ 1 policy zone containing 1 'nsdname' trigger and 1 'qname' trigger
+ (q02)
+ 2 queries, the first should not recurse and the second should recurse
+
+Test 3f:
+ 1 policy zone containing 1 'nsip' trigger and 1 'qname' trigger (q02)
+ 2 queries, the first should not recurse and the second should recurse
+
+Group 4 - contains 32 subtests designed to verify that recursion is
+skippable for only the appropriate zones based on the order specified in
+the 'response-policy' statement
+
+Tests 4aa to 4bf:
+ 32 policy zones per test, one of which is configured with 1 'ip'
+ trigger and one 'qname' trigger while the others are configured
+ only with 1 'qname' trigger. The zone with both triggers starts
+ listed first and is moved backwards by one position with each
+ test. The 'qname' triggers in the zones are structured so that
+ the zones are tested starting with the first zone and the 'ip'
+ trigger is tested before the 'qname' trigger for that zone.
+ 33 queries per test, where the number expected to skip recursion
+ matches the test sequence number: e.g. 1 skip for 4aa, 26 skips
+ for 4az, and 32 skips for 4bf
+
+Group 5 - This test verifies that the "pivot" policy zone for whether or
+not recursion can be skipped is the first listed zone with applicable
+trigger types rather than a later listed zone.
+
+Test 5a:
+ 5 policy zones, the 1st, 3rd, and 5th configured with 1 'qname'
+ trigger each (q01, q04, and q06, respectively), the 2nd and 4th
+ each configured with an 'ip' and 'qname' trigger (q02 and q05,
+ respectively for the 'qname' triggers
+ 6 queries, of which only q01 and q02 are expected to skip recursion
diff --git a/bin/tests/system/rpzrecurse/ans5/ans.pl b/bin/tests/system/rpzrecurse/ans5/ans.pl
new file mode 100644
index 0000000..9c5efb3
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ans5/ans.pl
@@ -0,0 +1,81 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.5",
+ LocalPort => $localport, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+for (;;) {
+ $sock->recv($buf, 512);
+
+ print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
+
+ my $packet;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ print "REQUEST:\n";
+ $packet->print;
+
+ $packet->header->qr(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+
+ my $donotrespond = 0;
+
+ $packet->header->aa(1);
+ if ($qtype eq "A") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 300 A 10.53.0.5"));
+ #} elsif ($qtype eq "AAAA") {
+ #$packet->push("answer",
+ #new Net::DNS::RR($qname .
+ #" 300 AAAA 2001:db8:beef::1"));
+ } elsif ($qtype eq "NS") {
+ $donotrespond = 1;
+ }
+
+ if ($donotrespond == 0) {
+ $sock->send($packet->data);
+ print "RESPONSE:\n";
+ $packet->print;
+ print "\n";
+ } else {
+ print "DROP:\n";
+ }
+}
diff --git a/bin/tests/system/rpzrecurse/clean.sh b/bin/tests/system/rpzrecurse/clean.sh
new file mode 100644
index 0000000..45b7940
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/clean.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Clean up after rpz tests.
+
+rm -f dig.out.*
+
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/*.run
+rm -f ns*/*core *core
+rm -f ns*/named.conf
+
+rm -f ns2/*.local
+rm -f ns2/*.queries
+rm -f ns2/named.[0-9]*.conf
+rm -f ns2/named.conf.header
+
+rm -f ns3/named.conf
+rm -f ns3/named.run.prev
+
+rm -f dnsrps*.conf dnsrpzd*
+rm -f ns*/session.key
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
diff --git a/bin/tests/system/rpzrecurse/ns1/db.l0 b/bin/tests/system/rpzrecurse/ns1/db.l0
new file mode 100644
index 0000000..e6077fc
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/db.l0
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 10.53.0.1
+l1 NS ns.l1
+ns.l1 A 10.53.0.1
diff --git a/bin/tests/system/rpzrecurse/ns1/db.l1.l0 b/bin/tests/system/rpzrecurse/ns1/db.l1.l0
new file mode 100644
index 0000000..f51d5f7
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/db.l1.l0
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 10.53.0.1
+l2 NS ns.l2
+ns.l2 A 10.53.0.1
diff --git a/bin/tests/system/rpzrecurse/ns1/example.com.db b/bin/tests/system/rpzrecurse/ns1/example.com.db
new file mode 100644
index 0000000..3bd11ec
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/example.com.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA ns.example.com. root.example.com. 1 3600 3600 3600 3600
+@ NS ns.example.com.
+
+ns.example.com. A 10.53.0.1
+@ A 1.2.3.4
+www A 1.2.3.5
diff --git a/bin/tests/system/rpzrecurse/ns1/example.db b/bin/tests/system/rpzrecurse/ns1/example.db
new file mode 100644
index 0000000..0e71776
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/example.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA root.example. example. 1 3600 3600 3600 3600
+@ IN NS ns.example.
+www IN CNAME cname
+cname IN A 10.53.0.1
diff --git a/bin/tests/system/rpzrecurse/ns1/named.conf.in b/bin/tests/system/rpzrecurse/ns1/named.conf.in
new file mode 100644
index 0000000..4fbb35a
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/named.conf.in
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ querylog yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "test.example.org" {
+ type primary;
+ file "example.db";
+};
+
+zone "l0" {
+ type primary;
+ file "db.l0";
+};
+
+zone "l1.l0" {
+ type primary;
+ file "db.l1.l0";
+};
+
+zone "l2.l1.l0" {
+ type primary;
+ file "does-not-exist";
+};
+
+zone "test1.example.net" {
+ type primary;
+ file "test1.example.net.db";
+};
+
+zone "test2.example.net" {
+ type primary;
+ file "test2.example.net.db";
+};
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+};
diff --git a/bin/tests/system/rpzrecurse/ns1/root.db b/bin/tests/system/rpzrecurse/ns1/root.db
new file mode 100644
index 0000000..51be203
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA muks.isc.org. a.root.servers.nil. (
+ 2010 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns.example.
+ns.example. A 10.53.0.1
+
+l0. NS ns.l0.
+ns.l0. A 10.53.0.1
diff --git a/bin/tests/system/rpzrecurse/ns1/test1.example.net.db b/bin/tests/system/rpzrecurse/ns1/test1.example.net.db
new file mode 100644
index 0000000..66ca007
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/test1.example.net.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA root.example. example. 1 3600 3600 3600 3600
+@ NS ns.example.
+ns.example. A 10.53.0.1
+test1.example.net. A 1.2.3.4
+www.test1.example.net. A 5.6.7.8
diff --git a/bin/tests/system/rpzrecurse/ns1/test2.example.net.db b/bin/tests/system/rpzrecurse/ns1/test2.example.net.db
new file mode 100644
index 0000000..57db115
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns1/test2.example.net.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA root.example. example. 1 3600 3600 3600 3600
+@ NS ns.example.
+ns.example. A 10.53.0.1
+test2.example.net. A 8.7.6.5
+www.test2.example.net. A 4.3.2.1
diff --git a/bin/tests/system/rpzrecurse/ns2/db.clientip1 b/bin/tests/system/rpzrecurse/ns2/db.clientip1
new file mode 100644
index 0000000..f0d53d2
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.clientip1
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+32.4.0.53.10.rpz-client-ip A 10.53.0.2
+24.0.0.53.10.rpz-client-ip A 10.53.0.1
diff --git a/bin/tests/system/rpzrecurse/ns2/db.clientip2 b/bin/tests/system/rpzrecurse/ns2/db.clientip2
new file mode 100644
index 0000000..dfcc341
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.clientip2
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+24.0.0.53.10.rpz-client-ip A 10.53.0.3
diff --git a/bin/tests/system/rpzrecurse/ns2/db.clientip21 b/bin/tests/system/rpzrecurse/ns2/db.clientip21
new file mode 100644
index 0000000..4ce2af1
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.clientip21
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+32.3.0.53.10.rpz-client-ip A 10.53.0.1
+31.2.0.53.10.rpz-client-ip CNAME .
diff --git a/bin/tests/system/rpzrecurse/ns2/db.given b/bin/tests/system/rpzrecurse/ns2/db.given
new file mode 100644
index 0000000..d464a53
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.given
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN given.zone.
+$TTL 3600
+@ IN SOA ns.given.zone. hostmaster.given.zone. 1 600 300 604800 3600
+ IN NS ns.given.zone.
+
+ns.given.zone. IN A 127.0.0.1
+; this should be ignored as it matches an earlier passthru entry.
+example.com CNAME .
+; this should be ignored as it matches an earlier wildcard passthru entry.
+www.example.com CNAME .
diff --git a/bin/tests/system/rpzrecurse/ns2/db.invalidprefixlength b/bin/tests/system/rpzrecurse/ns2/db.invalidprefixlength
new file mode 100644
index 0000000..f496670
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.invalidprefixlength
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+1000.4.0.53.10.rpz-client-ip A 10.53.0.1
diff --git a/bin/tests/system/rpzrecurse/ns2/db.log1 b/bin/tests/system/rpzrecurse/ns2/db.log1
new file mode 100644
index 0000000..495885b
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.log1
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+32.4.0.53.10.rpz-client-ip A 10.53.0.4
diff --git a/bin/tests/system/rpzrecurse/ns2/db.log2 b/bin/tests/system/rpzrecurse/ns2/db.log2
new file mode 100644
index 0000000..91ff8c5
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.log2
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+32.4.0.53.10.rpz-client-ip A 10.53.0.4
+32.3.0.53.10.rpz-client-ip A 10.53.0.3
diff --git a/bin/tests/system/rpzrecurse/ns2/db.log3 b/bin/tests/system/rpzrecurse/ns2/db.log3
new file mode 100644
index 0000000..65ed980
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.log3
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+32.4.0.53.10.rpz-client-ip A 10.53.0.4
+32.3.0.53.10.rpz-client-ip A 10.53.0.3
+32.2.0.53.10.rpz-client-ip A 10.53.0.2
diff --git a/bin/tests/system/rpzrecurse/ns2/db.passthru b/bin/tests/system/rpzrecurse/ns2/db.passthru
new file mode 100644
index 0000000..eac3533
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.passthru
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN passthru.zone.
+$TTL 3600
+@ IN SOA ns.passthru.zone. hostmaster.passthru.zone. 1 600 300 604800 3600
+ IN NS ns.passthru.zone.
+
+ns.passthru.zone. IN A 127.0.0.1
+
+example.com CNAME rpz-passthru.
+*.example.com CNAME rpz-passthru.
diff --git a/bin/tests/system/rpzrecurse/ns2/db.wildcard1 b/bin/tests/system/rpzrecurse/ns2/db.wildcard1
new file mode 100644
index 0000000..3e5c78f
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard1
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+*.test1.example.net CNAME .
+test1.example.net CNAME .
diff --git a/bin/tests/system/rpzrecurse/ns2/db.wildcard2a b/bin/tests/system/rpzrecurse/ns2/db.wildcard2a
new file mode 100644
index 0000000..3e5c78f
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard2a
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+*.test1.example.net CNAME .
+test1.example.net CNAME .
diff --git a/bin/tests/system/rpzrecurse/ns2/db.wildcard2b b/bin/tests/system/rpzrecurse/ns2/db.wildcard2b
new file mode 100644
index 0000000..f8e6123
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard2b
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+*.test2.example.net CNAME .
+test2.example.net CNAME .
diff --git a/bin/tests/system/rpzrecurse/ns2/db.wildcard3 b/bin/tests/system/rpzrecurse/ns2/db.wildcard3
new file mode 100644
index 0000000..5354c04
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard3
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 60
+@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+*.test1.example.net CNAME .
diff --git a/bin/tests/system/rpzrecurse/ns2/named.clientip.conf b/bin/tests/system/rpzrecurse/ns2/named.clientip.conf
new file mode 100644
index 0000000..a9ec4ca
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.clientip.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+
+ # policy configuration to be tested
+ response-policy {
+ zone "clientip1";
+ zone "clientip2";
+ } qname-wait-recurse no
+ nsdname-enable yes
+ nsip-enable yes;
+
+ # policy zones to be tested
+ zone "clientip1" { type primary; file "db.clientip1"; };
+ zone "clientip2" { type primary; file "db.clientip2"; };
+
+ recursion yes;
+ dnssec-validation yes;
+};
diff --git a/bin/tests/system/rpzrecurse/ns2/named.clientip2.conf b/bin/tests/system/rpzrecurse/ns2/named.clientip2.conf
new file mode 100644
index 0000000..39b67d8
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.clientip2.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+
+ servfail-ttl 0;
+
+ # policy configuration to be tested
+ response-policy {
+ zone "clientip21";
+ } qname-wait-recurse no
+ nsdname-enable yes
+ nsip-enable yes;
+
+ # policy zones to be tested
+ zone "clientip21" { type primary; file "db.clientip21"; };
+
+ recursion yes;
+ dnssec-validation yes;
+};
diff --git a/bin/tests/system/rpzrecurse/ns2/named.conf.header.in b/bin/tests/system/rpzrecurse/ns2/named.conf.header.in
new file mode 100644
index 0000000..2fb1678
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.conf.header.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ querylog yes;
+
+ # let ns3 start dnsrpzd
+ include "../dnsrps-secondary.conf";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
diff --git a/bin/tests/system/rpzrecurse/ns2/named.default.conf b/bin/tests/system/rpzrecurse/ns2/named.default.conf
new file mode 100644
index 0000000..929b88f
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.default.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+
+ recursion yes;
+ dnssec-validation yes;
+};
diff --git a/bin/tests/system/rpzrecurse/ns2/named.invalidprefixlength.conf b/bin/tests/system/rpzrecurse/ns2/named.invalidprefixlength.conf
new file mode 100644
index 0000000..2f2b735
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.invalidprefixlength.conf
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+
+ # policy configuration to be tested
+ response-policy {
+ zone "invalidprefixlength";
+ };
+
+ # policy zones to be tested
+ zone "invalidprefixlength" { type primary; file "db.invalidprefixlength"; };
+};
diff --git a/bin/tests/system/rpzrecurse/ns2/named.log.conf b/bin/tests/system/rpzrecurse/ns2/named.log.conf
new file mode 100644
index 0000000..a19367e
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.log.conf
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+
+ # policy configuration to be tested
+ response-policy {
+ zone "log1" log no;
+ zone "log2" log yes;
+ zone "log3"; # missing log clause
+ } qname-wait-recurse no
+ nsdname-enable yes
+ nsip-enable yes;
+
+ # policy zones to be tested
+ zone "log1" { type primary; file "db.log1"; };
+ zone "log2" { type primary; file "db.log2"; };
+ zone "log3" { type primary; file "db.log3"; };
+
+ recursion yes;
+ dnssec-validation yes;
+};
diff --git a/bin/tests/system/rpzrecurse/ns2/named.max.conf b/bin/tests/system/rpzrecurse/ns2/named.max.conf
new file mode 100644
index 0000000..b07783b
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.max.conf
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+
+ # policy configuration to be tested
+ response-policy {
+ zone "max1";
+ zone "max2";
+ zone "max3";
+ zone "max4";
+ zone "max5";
+ zone "max6";
+ zone "max7";
+ zone "max8";
+ zone "max9";
+ zone "max10";
+ zone "max11";
+ zone "max12";
+ zone "max13";
+ zone "max14";
+ zone "max15";
+ zone "max16";
+ zone "max17";
+ zone "max18";
+ zone "max19";
+ zone "max20";
+ zone "max21";
+ zone "max22";
+ zone "max23";
+ zone "max24";
+ zone "max25";
+ zone "max26";
+ zone "max27";
+ zone "max28";
+ zone "max29";
+ zone "max30";
+ zone "max31";
+ zone "max32";
+ zone "max33";
+ zone "max34";
+ zone "max35";
+ zone "max36";
+ zone "max37";
+ zone "max38";
+ zone "max39";
+ zone "max40";
+ zone "max41";
+ zone "max42";
+ zone "max43";
+ zone "max44";
+ zone "max45";
+ zone "max46";
+ zone "max47";
+ zone "max48";
+ zone "max49";
+ zone "max50";
+ zone "max51";
+ zone "max52";
+ zone "max53";
+ zone "max54";
+ zone "max55";
+ zone "max56";
+ zone "max57";
+ zone "max58";
+ zone "max59";
+ zone "max60";
+ zone "max61";
+ zone "max62";
+ zone "max63";
+ zone "max64";
+ } qname-wait-recurse no
+ nsdname-enable yes
+ nsip-enable yes;
+
+ # policy zones to be tested
+ zone "max1" { type primary; file "db.max1.local"; };
+ zone "max2" { type primary; file "db.max2.local"; };
+ zone "max3" { type primary; file "db.max3.local"; };
+ zone "max4" { type primary; file "db.max4.local"; };
+ zone "max5" { type primary; file "db.max5.local"; };
+ zone "max6" { type primary; file "db.max6.local"; };
+ zone "max7" { type primary; file "db.max7.local"; };
+ zone "max8" { type primary; file "db.max8.local"; };
+ zone "max9" { type primary; file "db.max9.local"; };
+ zone "max10" { type primary; file "db.max10.local"; };
+ zone "max11" { type primary; file "db.max11.local"; };
+ zone "max12" { type primary; file "db.max12.local"; };
+ zone "max13" { type primary; file "db.max13.local"; };
+ zone "max14" { type primary; file "db.max14.local"; };
+ zone "max15" { type primary; file "db.max15.local"; };
+ zone "max16" { type primary; file "db.max16.local"; };
+ zone "max17" { type primary; file "db.max17.local"; };
+ zone "max18" { type primary; file "db.max18.local"; };
+ zone "max19" { type primary; file "db.max19.local"; };
+ zone "max20" { type primary; file "db.max20.local"; };
+ zone "max21" { type primary; file "db.max21.local"; };
+ zone "max22" { type primary; file "db.max22.local"; };
+ zone "max23" { type primary; file "db.max23.local"; };
+ zone "max24" { type primary; file "db.max24.local"; };
+ zone "max25" { type primary; file "db.max25.local"; };
+ zone "max26" { type primary; file "db.max26.local"; };
+ zone "max27" { type primary; file "db.max27.local"; };
+ zone "max28" { type primary; file "db.max28.local"; };
+ zone "max29" { type primary; file "db.max29.local"; };
+ zone "max30" { type primary; file "db.max30.local"; };
+ zone "max31" { type primary; file "db.max31.local"; };
+ zone "max32" { type primary; file "db.max32.local"; };
+ zone "max33" { type primary; file "db.max33.local"; };
+ zone "max34" { type primary; file "db.max34.local"; };
+ zone "max35" { type primary; file "db.max35.local"; };
+ zone "max36" { type primary; file "db.max36.local"; };
+ zone "max37" { type primary; file "db.max37.local"; };
+ zone "max38" { type primary; file "db.max38.local"; };
+ zone "max39" { type primary; file "db.max39.local"; };
+ zone "max40" { type primary; file "db.max40.local"; };
+ zone "max41" { type primary; file "db.max41.local"; };
+ zone "max42" { type primary; file "db.max42.local"; };
+ zone "max43" { type primary; file "db.max43.local"; };
+ zone "max44" { type primary; file "db.max44.local"; };
+ zone "max45" { type primary; file "db.max45.local"; };
+ zone "max46" { type primary; file "db.max46.local"; };
+ zone "max47" { type primary; file "db.max47.local"; };
+ zone "max48" { type primary; file "db.max48.local"; };
+ zone "max49" { type primary; file "db.max49.local"; };
+ zone "max50" { type primary; file "db.max50.local"; };
+ zone "max51" { type primary; file "db.max51.local"; };
+ zone "max52" { type primary; file "db.max52.local"; };
+ zone "max53" { type primary; file "db.max53.local"; };
+ zone "max54" { type primary; file "db.max54.local"; };
+ zone "max55" { type primary; file "db.max55.local"; };
+ zone "max56" { type primary; file "db.max56.local"; };
+ zone "max57" { type primary; file "db.max57.local"; };
+ zone "max58" { type primary; file "db.max58.local"; };
+ zone "max59" { type primary; file "db.max59.local"; };
+ zone "max60" { type primary; file "db.max60.local"; };
+ zone "max61" { type primary; file "db.max61.local"; };
+ zone "max62" { type primary; file "db.max62.local"; };
+ zone "max63" { type primary; file "db.max63.local"; };
+ zone "max64" { type primary; file "db.max64.local"; };
+
+ recursion yes;
+ dnssec-validation yes;
+};
diff --git a/bin/tests/system/rpzrecurse/ns2/named.wildcard1.conf b/bin/tests/system/rpzrecurse/ns2/named.wildcard1.conf
new file mode 100644
index 0000000..23ef4eb
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.wildcard1.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+
+ # policy configuration to be tested
+ response-policy {
+ zone "wildcard1" policy NXDOMAIN;
+ } qname-wait-recurse yes
+ nsdname-enable yes
+ nsip-enable yes;
+
+ # policy zones to be tested
+ zone "wildcard1" { type primary; file "db.wildcard1"; };
+
+ recursion yes;
+ dnssec-validation yes;
+};
diff --git a/bin/tests/system/rpzrecurse/ns2/named.wildcard2.conf b/bin/tests/system/rpzrecurse/ns2/named.wildcard2.conf
new file mode 100644
index 0000000..b570b47
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.wildcard2.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+
+ # policy configuration to be tested
+ response-policy {
+ zone "wildcard2a" policy NXDOMAIN;
+ zone "wildcard2b" policy NXDOMAIN;
+ } qname-wait-recurse yes
+ nsdname-enable yes
+ nsip-enable yes;
+
+ # policy zones to be tested
+ zone "wildcard2a" { type primary; file "db.wildcard2a"; };
+ zone "wildcard2b" { type primary; file "db.wildcard2b"; };
+
+ recursion yes;
+ dnssec-validation yes;
+};
diff --git a/bin/tests/system/rpzrecurse/ns2/named.wildcard3.conf b/bin/tests/system/rpzrecurse/ns2/named.wildcard3.conf
new file mode 100644
index 0000000..befb7d2
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.wildcard3.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+
+ # policy configuration to be tested
+ response-policy {
+ zone "wildcard3" policy NXDOMAIN;
+ } qname-wait-recurse yes
+ nsdname-enable yes
+ nsip-enable yes;
+
+ # policy zones to be tested
+ zone "wildcard3" { type primary; file "db.wildcard3"; };
+
+ recursion yes;
+ dnssec-validation yes;
+};
diff --git a/bin/tests/system/rpzrecurse/ns2/named.wildcard4.conf b/bin/tests/system/rpzrecurse/ns2/named.wildcard4.conf
new file mode 100644
index 0000000..e18f496
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/named.wildcard4.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ # policy configuration to be tested
+ response-policy {
+ zone "passthru.zone" policy passthru;
+ zone "given.zone" policy given;
+ } qname-wait-recurse yes
+ nsdname-enable yes
+ nsip-enable yes;
+
+ # policy zones to be tested
+ zone "passthru.zone" { type primary; file "db.passthru"; };
+ zone "given.zone" { type primary; file "db.given"; };
+
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+
+ recursion yes;
+ dnssec-validation yes;
+};
diff --git a/bin/tests/system/rpzrecurse/ns2/root.hint b/bin/tests/system/rpzrecurse/ns2/root.hint
new file mode 100644
index 0000000..ced47f3
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns2/root.hint
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 999999
+. IN NS ns.example.
+ns.example. IN A 10.53.0.1
diff --git a/bin/tests/system/rpzrecurse/ns3/example.db b/bin/tests/system/rpzrecurse/ns3/example.db
new file mode 100644
index 0000000..201a174
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns3/example.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 0
+@ SOA . . 0 0 0 0 0
+@ NS ns
+ns A 10.53.0.3
+child NS ns.child
+ns.child A 10.53.0.4
diff --git a/bin/tests/system/rpzrecurse/ns3/named1.conf.in b/bin/tests/system/rpzrecurse/ns3/named1.conf.in
new file mode 100644
index 0000000..f838535
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns3/named1.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ response-policy { zone "policy"; }
+ qname-wait-recurse yes
+ nsip-enable yes
+ nsdname-enable yes;
+
+ include "../dnsrps.conf";
+};
+
+zone "policy" { type primary; file "policy.db"; };
+
+zone "example.tld" { type primary; file "example.db"; };
+
+zone "." { type primary; file "root.db"; };
diff --git a/bin/tests/system/rpzrecurse/ns3/named2.conf.in b/bin/tests/system/rpzrecurse/ns3/named2.conf.in
new file mode 100644
index 0000000..40f6b49
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns3/named2.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation yes;
+ response-policy { zone "policy"; } nsip-wait-recurse no
+ qname-wait-recurse yes
+ nsip-enable yes
+ nsdname-enable yes;
+
+ include "../dnsrps.conf";
+};
+
+zone "policy" { type primary; file "policy.db"; };
+
+zone "example.tld" { type primary; file "example.db"; };
+
+zone "." { type primary; file "root.db"; };
diff --git a/bin/tests/system/rpzrecurse/ns3/named3.conf.in b/bin/tests/system/rpzrecurse/ns3/named3.conf.in
new file mode 100644
index 0000000..3926bf9
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns3/named3.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation yes;
+ response-policy { zone "policy"; } nsdname-wait-recurse no
+ nsdname-enable yes;
+
+ include "../dnsrps.conf";
+};
+
+zone "policy" { type primary; file "policy.db"; };
+
+zone "example.tld" { type primary; file "example.db"; };
+
+zone "." { type primary; file "root.db"; };
diff --git a/bin/tests/system/rpzrecurse/ns3/policy.db b/bin/tests/system/rpzrecurse/ns3/policy.db
new file mode 100644
index 0000000..526d75c
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns3/policy.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 0
+@ SOA . . 0 0 0 0 0
+@ NS .
+32.100.0.53.10.rpz-nsip CNAME .
diff --git a/bin/tests/system/rpzrecurse/ns3/root.db b/bin/tests/system/rpzrecurse/ns3/root.db
new file mode 100644
index 0000000..665953d
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns3/root.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 0
+@ SOA . . 0 0 0 0 0
+@ NS ns
+ns A 10.53.0.3
+foo NS foo.ns5
+ns5.foo A 10.53.0.5
diff --git a/bin/tests/system/rpzrecurse/ns4/child.example.db b/bin/tests/system/rpzrecurse/ns4/child.example.db
new file mode 100644
index 0000000..47a90fb
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns4/child.example.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 0
+@ SOA . . 0 0 0 0 0
+@ NS ns
+ns A 10.53.0.4
+foo NS ns.foo
+foo NS ns.foo.
+ns.foo A 10.53.0.5
diff --git a/bin/tests/system/rpzrecurse/ns4/named.conf.in b/bin/tests/system/rpzrecurse/ns4/named.conf.in
new file mode 100644
index 0000000..b8d87b9
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/ns4/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "child.example.tld" { type primary; file "child.example.db"; };
diff --git a/bin/tests/system/rpzrecurse/setup.sh b/bin/tests/system/rpzrecurse/setup.sh
new file mode 100644
index 0000000..4dcd5ed
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/setup.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# touch dnsrps-off to not test with DNSRPS
+
+set -e
+
+. ../conf.sh
+
+USAGE="$0: [-DNx]"
+DEBUG=
+while getopts "DNx" c; do
+ case $c in
+ x) set -x; DEBUG=-x;;
+ D) TEST_DNSRPS="-D";;
+ N) NOCLEAN=set;;
+ *) echo "$USAGE" 1>&2; exit 1;;
+ esac
+done
+shift $((OPTIND - 1))
+if test "$#" -ne 0; then
+ echo "$USAGE" 1>&2
+ exit 1
+fi
+
+[ ${NOCLEAN:-unset} = unset ] && $SHELL clean.sh $DEBUG
+
+$PERL testgen.pl
+
+copy_setports ns1/named.conf.in ns1/named.conf
+
+copy_setports ns2/named.conf.header.in ns2/named.conf.header
+copy_setports ns2/named.default.conf ns2/named.conf
+
+copy_setports ns3/named1.conf.in ns3/named.conf
+
+copy_setports ns4/named.conf.in ns4/named.conf
+
+# setup policy zones for a 64-zone test
+i=1
+while test $i -le 64
+do
+ echo "\$TTL 60" > ns2/db.max$i.local
+ echo "@ IN SOA root.ns ns 1996072700 3600 1800 86400 60" >> ns2/db.max$i.local
+ echo " NS ns" >> ns2/db.max$i.local
+ echo "ns A 127.0.0.1" >> ns2/db.max$i.local
+
+ j=1
+ while test $j -le $i
+ do
+ echo "name$j A 10.53.0.$i" >> ns2/db.max$i.local
+ j=$((j + 1))
+ done
+ i=$((i + 1))
+done
+
+# decide whether to test DNSRPS
+$SHELL ../ckdnsrps.sh $TEST_DNSRPS $DEBUG
+test -z "$(grep 'dnsrps-enable yes' dnsrps.conf)" && TEST_DNSRPS=
+
+CWD=$(pwd)
+cat <<EOF >dnsrpzd.conf
+PID-FILE $CWD/dnsrpzd.pid;
+
+include $CWD/dnsrpzd-license-cur.conf
+
+zone "policy" { type primary; file "`pwd`/ns3/policy.db"; };
+EOF
+sed -n -e 's/^ *//' -e "/zone.*.*primary/s@file \"@&$CWD/ns2/@p" ns2/*.conf \
+ >>dnsrpzd.conf
+
+# Run dnsrpzd to get the license and prime the static policy zones
+if test -n "$TEST_DNSRPS"; then
+ DNSRPZD="$(../rpz/dnsrps -p)"
+ "$DNSRPZD" -D./dnsrpzd.rpzf -S./dnsrpzd.sock -C./dnsrpzd.conf \
+ -w 0 -dddd -L stdout >./dnsrpzd.run 2>&1
+fi
diff --git a/bin/tests/system/rpzrecurse/testgen.pl b/bin/tests/system/rpzrecurse/testgen.pl
new file mode 100755
index 0000000..4131bd9
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/testgen.pl
@@ -0,0 +1,343 @@
+#!/usr/bin/env perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+use warnings;
+
+my $boilerplate_header = <<'EOB';
+# common configuration
+include "named.conf.header";
+
+view "recursive" {
+ zone "." {
+ type hint;
+ file "root.hint";
+ };
+
+ # policy configuration to be tested
+ response-policy {
+EOB
+
+my $no_option = <<'EOB';
+ } nsdname-enable yes nsip-enable yes;
+
+ # policy zones to be tested
+EOB
+
+my $qname_wait_recurse = <<'EOB';
+ } nsdname-enable yes nsip-enable yes qname-wait-recurse no;
+
+ # policy zones to be tested
+EOB
+
+my $boilerplate_end = <<'EOB';
+};
+EOB
+
+my $policy_option = $qname_wait_recurse;
+
+my $serialnum = "1";
+my $policy_zone_header = <<'EOH';
+$TTL 60
+@ IN SOA root.ns ns SERIAL 3600 1800 86400 60
+ NS ns
+ns A 127.0.0.1
+EOH
+
+sub policy_client_ip {
+ return "32.1.0.0.127.rpz-client-ip CNAME .\n";
+}
+
+sub policy_qname {
+ my $query_nbr = shift;
+ return sprintf "q%02d.l2.l1.l0 CNAME .\n", $query_nbr;
+}
+
+sub policy_ip {
+ return "32.255.255.255.255.rpz-ip CNAME .\n";
+}
+
+sub policy_nsdname {
+ return "ns.example.org.rpz-nsdname CNAME .\n";
+}
+
+sub policy_nsip {
+ return "32.255.255.255.255.rpz-ip CNAME .\n";
+}
+
+my %static_triggers = (
+ 'client-ip' => \&policy_client_ip,
+ 'ip' => \&policy_ip,
+ 'nsdname' => \&policy_nsdname,
+ 'nsip' => \&policy_nsip,
+);
+
+sub mkconf {
+ my $case_id = shift;
+ my $n_queries = shift;
+
+ { # generate the query list
+ my $query_list_filename = "ns2/$case_id.queries";
+ my $query_list_fh;
+
+ open $query_list_fh, ">$query_list_filename" or die;
+
+ for( my $i = 1; $i <= $n_queries; $i++ ) {
+ print $query_list_fh sprintf "q%02d.l2.l1.l0\n", $i;
+ }
+ }
+
+ my @zones;
+
+ { # generate the conf file
+ my $conf_filename = "ns2/named.$case_id.conf";
+
+ my $conf_fh;
+
+ open $conf_fh, ">$conf_filename" or die;
+
+ print $conf_fh $boilerplate_header;
+
+ my $zone_seq = 0;
+
+ @zones = map {
+ [
+ sprintf( "$case_id.%02d.policy.local", $zone_seq++ ),
+ $_,
+ ];
+ } @_;
+
+ print $conf_fh map { qq{ zone "$_->[0]";\n} } @zones;
+
+ print $conf_fh $policy_option;
+
+ print $conf_fh map { qq{ zone "$_->[0]" { type primary; file "db.$_->[0]"; };\n} } @zones;
+
+ print $conf_fh $boilerplate_end;
+ }
+
+ # generate the policy zone contents
+ foreach my $policy_zone_info( @zones ) {
+ my $policy_zone_name = $policy_zone_info->[0];
+ my $policy_zone_contents = $policy_zone_info->[1];
+
+ my $policy_zone_filename = "ns2/db.$policy_zone_name";
+ my $policy_zone_fh;
+
+ open $policy_zone_fh, ">$policy_zone_filename" or die;
+
+ my $header = $policy_zone_header;
+ $header =~ s/SERIAL/$serialnum/;
+ print $policy_zone_fh $header;
+
+ foreach my $trigger( @$policy_zone_contents ) {
+ if( exists $static_triggers{$trigger} ) {
+ # matches a trigger type with a static value
+ print $policy_zone_fh $static_triggers{$trigger}->();
+ }
+ else {
+ # a qname trigger, where what was specified is the query number it should match
+ print $policy_zone_fh policy_qname( $trigger );
+ }
+ }
+ }
+}
+
+mkconf(
+ '1a',
+ 1,
+ [ 'client-ip' ],
+);
+
+mkconf(
+ '1b',
+ 2,
+ [ 1 ],
+);
+
+mkconf(
+ '1c',
+ 1,
+ [ 'client-ip', 2 ],
+);
+
+mkconf(
+ '2a',
+ 33,
+ map { [ $_ ]; } 1 .. 32
+);
+
+mkconf(
+ '3a',
+ 1,
+ [ 'ip' ],
+);
+
+mkconf(
+ '3b',
+ 1,
+ [ 'nsdname' ],
+);
+
+mkconf(
+ '3c',
+ 1,
+ [ 'nsip' ],
+);
+
+mkconf(
+ '3d',
+ 2,
+ [ 'ip', 1 ]
+);
+
+mkconf(
+ '3e',
+ 2,
+ [ 'nsdname', 1 ]
+);
+
+mkconf(
+ '3f',
+ 2,
+ [ 'nsip', 1 ]
+);
+
+{
+ my $seq_code = 'aa';
+ my $seq_nbr = 0;
+
+ while( $seq_nbr < 32 ) {
+
+ mkconf(
+ "4$seq_code",
+ 33,
+ ( map { [ $_ ]; } 1 .. $seq_nbr ),
+ [ 'ip', $seq_nbr + 2 ],
+ ( map { [ $_ + 2 ]; } ($seq_nbr + 1) .. 31 ),
+ );
+
+ $seq_code++;
+ $seq_nbr++;
+ }
+}
+
+mkconf(
+ '5a',
+ 6,
+ [ 1 ],
+ [ 2, 'ip' ],
+ [ 4 ],
+ [ 5, 'ip' ],
+ [ 6 ],
+);
+
+$policy_option = $no_option;
+
+mkconf(
+ '6a',
+ 0,
+ [ ],
+);
+
+$serialnum = "2";
+mkconf(
+ '6b',
+ 0,
+ [ 'nsdname' ],
+);
+
+$serialnum = "3";
+mkconf(
+ '6c',
+ 0,
+ [ ],
+);
+
+__END__
+
+0x01 - has client-ip
+ 32.1.0.0.127.rpz-client-ip CNAME .
+0x02 - has qname
+ qX.l2.l1.l0 CNAME .
+0x10 - has ip
+ 32.255.255.255.255.rpz-ip CNAME .
+0x20 - has nsdname
+ ns.example.org.rpz-nsdname CNAME .
+0x40 - has nsip
+ 32.255.255.255.255.rpz-nsip CNAME .
+
+$case.$seq.policy.local
+
+case 1a = 0x01
+ .q01 = (00,0x01)=-r
+case 1b = 0x02
+ .q01 = (00,0x02)=-r
+ .q02 = (--,----)=+r
+case 1c = 0x03
+ .q01 = (00,0x01)=-r
+
+case 2a = 0x03{32}
+ .q01 = (00,0x02)=-r
+ .q02 = (01,0x02)=-r
+ ...
+ .q31 = (30,0x02)=-r
+ .q32 = (31,0x02)=-r
+ .q33 = (--,----)=+r
+
+case 3a = 0x10
+ .q01 = (00,0x10)=+r
+case 3b = 0x20
+ .q01 = (00,0x20)=+r
+case 3c = 0x40
+ .q01 = (00,0x40)=+r
+case 3d = 0x12
+ .q01 = (00,0x10)=+r
+ .q02 = (00,0x02)=-r
+case 3e = 0x22
+ .q01 = (00,0x20)=+r
+ .q02 = (00,0x02)=-r
+case 3f = 0x42
+ .q01 = (00,0x40)=+r
+ .q02 = (00,0x02)=-r
+
+case 4aa = 0x12,0x02{31}
+ .q01 = (00,0x10)=+r
+ .q02 = (00,0x02)=-r
+ .q03 = (01,0x02)=+r
+ ...
+ .q32 = (30,0x02)=+r
+ .q33 = (31,0x02)=+r
+case 4__ = 0x02{n(1->30)},0x12,0x02{31-n}
+ .q01 = (00,0x02)=-r
+ ...
+ .q(n+1) = (n,0x10)=+r
+ .q(n+2) = (n,0x02)=-r
+ ...
+ .q33 = (31,0x02)=+r
+case 4bf = 0x02{31},0x12
+ .q01 = (00,0x02)=-r
+ .q02 = (01,0x02)=-r
+ ...
+ .q31 = (30,0x02)=-r
+ .q32 = (31,0x10)=+r
+ .q33 = (31,0x02)=-r
+
+case 5a = 0x02,0x12,0x02,0x12,0x02
+ .q01 = (00,0x02)=-r
+ .q02 = (01,0x02)=-r
+ .q03 = (01,0x10)=+r
+ .q04 = (02,0x02)=+r
+ .q05 = (03,0x02)=+r
+ .q06 = (04,0x02)=+r
+
diff --git a/bin/tests/system/rpzrecurse/tests.sh b/bin/tests/system/rpzrecurse/tests.sh
new file mode 100644
index 0000000..eed53e8
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/tests.sh
@@ -0,0 +1,563 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# touch dnsrps-off to not test with DNSRPS
+# touch dnsrps-only to not test with classic RPZ
+
+. ../conf.sh
+
+status=0
+
+t=0
+
+DEBUG=
+ARGS=
+
+USAGE="$0: [-xS]"
+while getopts "xS:" c; do
+ case $c in
+ x) set -x; DEBUG=-x; ARGS="$ARGS -x";;
+ S) SAVE_RESULTS=-S; ARGS="$ARGS -S";;
+ *) echo "$USAGE" 1>&2; exit 1;;
+ esac
+done
+shift $((OPTIND - 1))
+if test "$#" -ne 0; then
+ echo "$USAGE" 1>&2
+ exit 1
+fi
+# really quit on control-C
+trap 'exit 1' 1 2 15
+
+DNSRPSCMD=../rpz/dnsrps
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+# $1 = test name (such as 1a, 1b, etc. for which named.$1.conf exists)
+run_server() {
+ TESTNAME=$1
+
+ echo_i "stopping resolver"
+ stop_server --use-rndc --port ${CONTROLPORT} ns2
+
+ sleep 1
+
+ echo_i "starting resolver using named.$TESTNAME.conf"
+ cp -f ns2/named.$TESTNAME.conf ns2/named.conf
+ start_server --noclean --restart --port ${PORT} ns2
+ sleep 3
+}
+
+run_query() {
+ TESTNAME=$1
+ LINE=$2
+
+ NAME=$(sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1)
+ $DIG $DIGOPTS $NAME a @10.53.0.2 -p ${PORT} -b 127.0.0.1 > dig.out.${t}
+ grep "status: SERVFAIL" dig.out.${t} > /dev/null 2>&1 && return 1
+ return 0
+}
+
+# $1 = test name (such as 1a, 1b, etc. for which $1.queries exists)
+# $2 = line number in query file to test (the name to query is taken from this line)
+expect_norecurse() {
+ TESTNAME=$1
+ LINE=$2
+
+ NAME=$(sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1)
+ t=$((t + 1))
+ echo_i "testing $NAME doesn't recurse (${t})"
+ add_test_marker 10.53.0.2
+ run_query $TESTNAME $LINE || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+}
+
+# $1 = test name (such as 1a, 1b, etc. for which $1.queries exists)
+# $2 = line number in query file to test (the name to query is taken from this line)
+expect_recurse() {
+ TESTNAME=$1
+ LINE=$2
+
+ NAME=$(sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1)
+ t=$((t + 1))
+ echo_i "testing $NAME recurses (${t})"
+ add_test_marker 10.53.0.2
+ run_query $TESTNAME $LINE && {
+ echo_i "test ${t} failed"
+ status=1
+ }
+ return 0
+}
+
+add_test_marker() {
+ for ns in $@
+ do
+ $RNDCCMD $ns null ---- test ${t} ----
+ done
+}
+
+native=0
+dnsrps=0
+for mode in native dnsrps; do
+ status=0
+ case $mode in
+ native)
+ if [ -e dnsrps-only ] ; then
+ echo_i "'dnsrps-only' found: skipping native RPZ sub-test"
+ continue
+ else
+ echo_i "running native RPZ sub-test"
+ fi
+ ;;
+ dnsrps)
+ if [ -e dnsrps-off ] ; then
+ echo_i "'dnsrps-off' found: skipping DNSRPS sub-test"
+ continue
+ fi
+ echo_i "attempting to configure servers with DNSRPS..."
+ stop_server --use-rndc --port ${CONTROLPORT}
+ $SHELL ./setup.sh -N -D $DEBUG
+ sed -n 's/^## //p' dnsrps.conf | cat_i
+ if grep '^#fail' dnsrps.conf >/dev/null; then
+ echo_i "exit status: 1"
+ exit 1
+ fi
+ if grep '^#skip' dnsrps.conf > /dev/null; then
+ echo_i "DNSRPS sub-test skipped"
+ continue
+ else
+ echo_i "running DNSRPS sub-test"
+ start_server --noclean --restart --port ${PORT}
+ sleep 3
+ fi
+ ;;
+ esac
+
+ # show whether and why DNSRPS is enabled or disabled
+ sed -n 's/^## //p' dnsrps.conf | cat_i
+
+ t=$((t + 1))
+ echo_i "testing that l1.l0 exists without RPZ (${t})"
+ add_test_marker 10.53.0.2
+ $DIG $DIGOPTS l1.l0 ns @10.53.0.2 -p ${PORT} > dig.out.${t}
+ grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+
+ t=$((t + 1))
+ echo_i "testing that l2.l1.l0 returns SERVFAIL without RPZ (${t})"
+ add_test_marker 10.53.0.2
+ $DIG $DIGOPTS l2.l1.l0 ns @10.53.0.2 -p ${PORT} > dig.out.${t}
+ grep "status: SERVFAIL" dig.out.${t} > /dev/null 2>&1 || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+
+ # Group 1
+ run_server 1a
+ expect_norecurse 1a 1
+ run_server 1b
+ expect_norecurse 1b 1
+ expect_recurse 1b 2
+ run_server 1c
+ expect_norecurse 1c 1
+
+ # Group 2
+ run_server 2a
+ for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
+ 21 22 23 24 25 26 27 28 29 30 31 32
+ do
+ expect_norecurse 2a $n
+ done
+ expect_recurse 2a 33
+
+ # Group 3
+ run_server 3a
+ expect_recurse 3a 1
+ run_server 3b
+ expect_recurse 3b 1
+ run_server 3c
+ expect_recurse 3c 1
+ run_server 3d
+ expect_norecurse 3d 1
+ expect_recurse 3d 2
+ run_server 3e
+ expect_norecurse 3e 1
+ expect_recurse 3e 2
+ run_server 3f
+ expect_norecurse 3f 1
+ expect_recurse 3f 2
+
+ # Group 4
+ testlist="aa ap bf"
+ values="1 16 32"
+ # Uncomment the following to test every skip value instead of
+ # only a sample of values
+ #
+ #testlist="aa ab ac ad ae af ag ah ai aj ak al am an ao ap \
+ # aq ar as at au av aw ax ay az ba bb bc bd be bf"
+ #values="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
+ # 21 22 23 24 25 26 27 28 29 30 31 32"
+ set -- $values
+ for n in $testlist; do
+ run_server 4$n
+ ni=$1
+ t=$((t + 1))
+ echo_i "testing that ${ni} of 33 queries skip recursion (${t})"
+ add_test_marker 10.53.0.2
+ c=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 \
+ 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
+ do
+ run_query 4$n $i || c=$((c + 1))
+ done
+ skipped=$((33 - c))
+ if [ $skipped != $ni ]; then
+ echo_i "test $t failed (actual=$skipped, expected=$ni)"
+ status=1
+ fi
+ shift
+ done
+
+ # Group 5
+ run_server 5a
+ expect_norecurse 5a 1
+ expect_norecurse 5a 2
+ expect_recurse 5a 3
+ expect_recurse 5a 4
+ expect_recurse 5a 5
+ expect_recurse 5a 6
+
+ # Group 6
+ echo_i "check recursive behavior consistency during policy update races"
+ run_server 6a
+ sleep 1
+ t=$((t + 1))
+ echo_i "running dig to cache CNAME record (${t})"
+ add_test_marker 10.53.0.1 10.53.0.2
+ $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org CNAME > dig.out.${t}
+ sleep 1
+ echo_i "suspending authority server"
+ PID=$(cat ns1/named.pid)
+ kill -STOP $PID
+ echo_i "adding an NSDNAME policy"
+ cp ns2/db.6a.00.policy.local ns2/saved.policy.local
+ cp ns2/db.6b.00.policy.local ns2/db.6a.00.policy.local
+ $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i
+ test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true
+ sleep 1
+ t=$((t + 1))
+ echo_i "running dig to follow CNAME (blocks, so runs in the background) (${t})"
+ add_test_marker 10.53.0.2
+ $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org A +time=5 > dig.out.${t} &
+ sleep 1
+ echo_i "removing the NSDNAME policy"
+ cp ns2/db.6c.00.policy.local ns2/db.6a.00.policy.local
+ $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i
+ test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true
+ sleep 1
+ echo_i "resuming authority server"
+ PID=$(cat ns1/named.pid)
+ kill -CONT $PID
+ add_test_marker 10.53.0.1
+ for n in 1 2 3 4 5 6 7 8 9
+ do
+ sleep 1
+ [ -s dig.out.${t} ] || continue
+ grep "status: .*," dig.out.${t} > /dev/null 2>&1 && break
+ done
+ grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+
+ echo_i "check recursive behavior consistency during policy removal races"
+ cp ns2/saved.policy.local ns2/db.6a.00.policy.local
+ run_server 6a
+ sleep 1
+ t=$((t + 1))
+ echo_i "running dig to cache CNAME record (${t})"
+ add_test_marker 10.53.0.1 10.53.0.2
+ $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org CNAME > dig.out.${t}
+ sleep 1
+ echo_i "suspending authority server"
+ PID=$(cat ns1/named.pid)
+ kill -STOP $PID
+ echo_i "adding an NSDNAME policy"
+ cp ns2/db.6b.00.policy.local ns2/db.6a.00.policy.local
+ $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i
+ test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true
+ sleep 1
+ t=$((t + 1))
+ echo_i "running dig to follow CNAME (blocks, so runs in the background) (${t})"
+ add_test_marker 10.53.0.2
+ $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org A +time=5 > dig.out.${t} &
+ sleep 1
+ echo_i "removing the policy zone"
+ cp ns2/named.default.conf ns2/named.conf
+ rndc_reconfig ns2 10.53.0.2
+ test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true
+ sleep 1
+ echo_i "resuming authority server"
+ PID=$(cat ns1/named.pid)
+ kill -CONT $PID
+ add_test_marker 10.53.0.1
+ for n in 1 2 3 4 5 6 7 8 9; do
+ sleep 1
+ [ -s dig.out.${t} ] || continue
+ grep "status: .*," dig.out.${t} > /dev/null 2>&1 && break
+ done
+ grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+
+ # Check maximum number of RPZ zones (64)
+ t=$((t + 1))
+ echo_i "testing maximum number of RPZ zones (${t})"
+ add_test_marker 10.53.0.2
+ run_server max
+ i=1
+ while test $i -le 64
+ do
+ $DIG $DIGOPTS name$i a @10.53.0.2 -p ${PORT} -b 10.53.0.1 > dig.out.${t}.${i}
+ grep "^name$i.[ ]*[0-9]*[ ]*IN[ ]*A[ ]*10.53.0.$i" dig.out.${t}.${i} > /dev/null 2>&1 || {
+ echo_i "test $t failed: didn't get expected answer from policy zone $i"
+ status=1
+ }
+ i=$((i + 1))
+ done
+
+ # Check CLIENT-IP behavior
+ t=$((t + 1))
+ echo_i "testing CLIENT-IP behavior (${t})"
+ add_test_marker 10.53.0.2
+ run_server clientip
+ $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 > dig.out.${t}
+ grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || {
+ echo_i "test $t failed: query failed"
+ status=1
+ }
+ grep "^l2.l1.l0.[ ]*[0-9]*[ ]*IN[ ]*A[ ]*10.53.0.2" dig.out.${t} > /dev/null 2>&1 || {
+ echo_i "test $t failed: didn't get expected answer"
+ status=1
+ }
+
+ # Check CLIENT-IP behavior #2
+ t=$((t + 1))
+ echo_i "testing CLIENT-IP behavior #2 (${t})"
+ add_test_marker 10.53.0.2
+ run_server clientip2
+ $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.1 > dig.out.${t}.1
+ grep "status: SERVFAIL" dig.out.${t}.1 > /dev/null 2>&1 || {
+ echo_i "test $t failed: query failed"
+ status=1
+ }
+ $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.2 > dig.out.${t}.2
+ grep "status: NXDOMAIN" dig.out.${t}.2 > /dev/null 2>&1 || {
+ echo_i "test $t failed: query failed"
+ status=1
+ }
+ $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.3 > dig.out.${t}.3
+ grep "status: NOERROR" dig.out.${t}.3 > /dev/null 2>&1 || {
+ echo_i "test $t failed: query failed"
+ status=1
+ }
+ grep "^l2.l1.l0.[ ]*[0-9]*[ ]*IN[ ]*A[ ]*10.53.0.1" dig.out.${t}.3 > /dev/null 2>&1 || {
+ echo_i "test $t failed: didn't get expected answer"
+ status=1
+ }
+ $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 > dig.out.${t}.4
+ grep "status: SERVFAIL" dig.out.${t}.4 > /dev/null 2>&1 || {
+ echo_i "test $t failed: query failed"
+ status=1
+ }
+
+ # Check RPZ log clause
+ t=$((t + 1))
+ echo_i "testing RPZ log clause (${t})"
+ add_test_marker 10.53.0.2
+ run_server log
+ cur=$(awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run)
+ $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 > dig.out.${t}
+ $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.3 >> dig.out.${t}
+ $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.2 >> dig.out.${t}
+ sed -n "$cur,"'$p' < ns2/named.run | grep "view recursive: rpz CLIENT-IP Local-Data rewrite l2.l1.l0/A/IN via 32.4.0.53.10.rpz-client-ip.log1" > /dev/null && {
+ echo_ic "failed: unexpected rewrite message for policy zone log1 was logged"
+ status=1
+ }
+ sed -n "$cur,"'$p' < ns2/named.run | grep "view recursive: rpz CLIENT-IP Local-Data rewrite l2.l1.l0/A/IN via 32.3.0.53.10.rpz-client-ip.log2" > /dev/null || {
+ echo_ic "failed: expected rewrite message for policy zone log2 was not logged"
+ status=1
+ }
+ sed -n "$cur,"'$p' < ns2/named.run | grep "view recursive: rpz CLIENT-IP Local-Data rewrite l2.l1.l0/A/IN via 32.2.0.53.10.rpz-client-ip.log3" > /dev/null || {
+ echo_ic "failed: expected rewrite message for policy zone log3 was not logged"
+ status=1
+ }
+
+ # Check wildcard behavior
+
+ t=$((t + 1))
+ echo_i "testing wildcard behavior with 1 RPZ zone (${t})"
+ add_test_marker 10.53.0.2
+ run_server wildcard1
+ $DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.1
+ grep "status: NXDOMAIN" dig.out.${t}.1 > /dev/null || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+ $DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.2
+ grep "status: NXDOMAIN" dig.out.${t}.2 > /dev/null || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+
+ t=$((t + 1))
+ echo_i "testing wildcard behavior with 2 RPZ zones (${t})"
+ add_test_marker 10.53.0.2
+ run_server wildcard2
+ $DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.1
+ grep "status: NXDOMAIN" dig.out.${t}.1 > /dev/null || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+ $DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.2
+ grep "status: NXDOMAIN" dig.out.${t}.2 > /dev/null || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+
+ t=$((t + 1))
+ echo_i "testing wildcard behavior with 1 RPZ zone and no non-wildcard triggers (${t})"
+ add_test_marker 10.53.0.2
+ run_server wildcard3
+ $DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.1
+ grep "status: NXDOMAIN" dig.out.${t}.1 > /dev/null || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+ $DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.2
+ grep "status: NOERROR" dig.out.${t}.2 > /dev/null || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+
+ t=$((t + 1))
+ echo_i "testing wildcard passthru before explicit drop (${t})"
+ add_test_marker 10.53.0.2
+ run_server wildcard4
+ $DIG $DIGOPTS example.com a @10.53.0.2 -p ${PORT} > dig.out.${t}.1
+ grep "status: NOERROR" dig.out.${t}.1 > /dev/null || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+ $DIG $DIGOPTS www.example.com a @10.53.0.2 -p ${PORT} > dig.out.${t}.2
+ grep "status: NOERROR" dig.out.${t}.2 > /dev/null || {
+ echo_i "test ${t} failed"
+ status=1
+ }
+
+ if [ "$mode" = "native" ]; then
+ # Check for invalid prefix length error
+ t=$((t + 1))
+ echo_i "testing for invalid prefix length error (${t})"
+ add_test_marker 10.53.0.2
+ run_server invalidprefixlength
+ grep "invalid rpz IP address \"1000.4.0.53.10.rpz-client-ip.invalidprefixlength\"; invalid prefix length of 1000$" ns2/named.run > /dev/null || {
+ echo_ic "failed: expected that invalid prefix length error would be logged"
+ status=1
+ }
+ fi
+
+ t=$((t + 1))
+ echo_i "checking 'nsip-wait-recurse no' is faster than 'nsip-wait-recurse yes' ($t)"
+ add_test_marker 10.53.0.2 10.53.0.3
+ echo_i "timing 'nsip-wait-recurse yes' (default)"
+ ret=0
+ t1=$($PERL -e 'print time()."\n";')
+ $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a > dig.out.yes.$t
+ t2=$($PERL -e 'print time()."\n";')
+ p1=$((t2 - t1))
+ echo_i "elapsed time $p1 seconds"
+
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush
+ copy_setports ns3/named2.conf.in ns3/named.conf
+ nextpart ns3/named.run > /dev/null
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload > /dev/null
+ wait_for_log 20 "rpz: policy: reload done" ns3/named.run || ret=1
+
+ echo_i "timing 'nsip-wait-recurse no'"
+ t3=$($PERL -e 'print time()."\n";')
+ $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a > dig.out.no.$t
+ t4=$($PERL -e 'print time()."\n";')
+ p2=$((t4 - t3))
+ echo_i "elapsed time $p2 seconds"
+
+ if test $p1 -le $p2; then ret=1; fi
+ if test $ret != 0; then echo_i "failed"; fi
+ status=$((status + ret))
+
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush
+ # restore original named.conf
+ copy_setports ns3/named1.conf.in ns3/named.conf
+ nextpart ns3/named.run > /dev/null
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload > /dev/null
+ wait_for_log 20 "rpz: policy: reload done" ns3/named.run || ret=1
+
+ t=$((t + 1))
+ echo_i "checking 'nsdname-wait-recurse no' is faster than 'nsdname-wait-recurse yes' ($t)"
+ add_test_marker 10.53.0.2 10.53.0.3
+ echo_i "timing 'nsdname-wait-recurse yes' (default)"
+ ret=0
+ t1=$($PERL -e 'print time()."\n";')
+ $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a > dig.out.yes.$t
+ t2=$($PERL -e 'print time()."\n";')
+ p1=$((t2 - t1))
+ echo_i "elapsed time $p1 seconds"
+
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush
+ copy_setports ns3/named3.conf.in ns3/named.conf
+ nextpart ns3/named.run > /dev/null
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload > /dev/null
+ wait_for_log 20 "rpz: policy: reload done" ns3/named.run || ret=1
+
+ echo_i "timing 'nsdname-wait-recurse no'"
+ t3=$($PERL -e 'print time()."\n";')
+ $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a > dig.out.no.$t
+ t4=$($PERL -e 'print time()."\n";')
+ p2=$((t4 - t3))
+ echo_i "elapsed time $p2 seconds"
+
+ if test $p1 -le $p2; then ret=1; fi
+ if test $ret != 0; then echo_i "failed"; fi
+ status=$((status + ret))
+
+
+ [ $status -ne 0 ] && pf=fail || pf=pass
+ case $mode in
+ native)
+ native=$status
+ echo_i "status (native RPZ sub-test): $status ($pf)";;
+ dnsrps)
+ dnsrps=$status
+ echo_i "status (DNSRPS sub-test): $status ($pf)";;
+ *) echo_i "invalid test mode";;
+ esac
+done
+status=$((native + dnsrps))
+
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rpzrecurse/tests_sh_rpzrecurse.py b/bin/tests/system/rpzrecurse/tests_sh_rpzrecurse.py
new file mode 100644
index 0000000..903ac49
--- /dev/null
+++ b/bin/tests/system/rpzrecurse/tests_sh_rpzrecurse.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_rpzrecurse(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/rrchecker/classlist.good b/bin/tests/system/rrchecker/classlist.good
new file mode 100644
index 0000000..f0fff1a
--- /dev/null
+++ b/bin/tests/system/rrchecker/classlist.good
@@ -0,0 +1,3 @@
+IN
+CH
+HS
diff --git a/bin/tests/system/rrchecker/clean.sh b/bin/tests/system/rrchecker/clean.sh
new file mode 100644
index 0000000..166247d
--- /dev/null
+++ b/bin/tests/system/rrchecker/clean.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f classlist.out privatelist.out typelist.out tempzone checkzone.out* checker.out
+rm -f ns*/named.lock
diff --git a/bin/tests/system/rrchecker/privatelist.good b/bin/tests/system/rrchecker/privatelist.good
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin/tests/system/rrchecker/privatelist.good
diff --git a/bin/tests/system/rrchecker/tests.sh b/bin/tests/system/rrchecker/tests.sh
new file mode 100644
index 0000000..65e9d43
--- /dev/null
+++ b/bin/tests/system/rrchecker/tests.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+n=$((n + 1))
+echo_i "class list ($n)"
+$RRCHECKER -C > classlist.out
+diff classlist.out classlist.good || { echo_i "failed"; status=$((status + 1)); }
+
+n=$((n + 1))
+echo_i "type list ($n)"
+$RRCHECKER -T > typelist.out
+diff typelist.out typelist.good || { echo_i "failed"; status=$((status + 1)); }
+
+n=$((n + 1))
+echo_i "private type list ($n)"
+$RRCHECKER -P > privatelist.out
+diff privatelist.out privatelist.good || { echo_i "failed"; status=$((status + 1)); }
+
+myecho() {
+cat << EOF
+$*
+EOF
+}
+
+n=$((n + 1))
+echo_i "check conversions to canonical format ($n)"
+ret=0
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 0 > tempzone
+$CHECKZONE -Dq . tempzone | sed '/^;/d' > checkzone.out$n
+while read -r name tt cl ty rest
+do
+ myecho "$cl $ty $rest" | $RRCHECKER -p > checker.out || {
+ ret=1
+ echo_i "'$cl $ty $rest' not handled."
+ }
+ read -r cl0 ty0 rest0 < checker.out
+ test "$cl $ty $rest" = "$cl0 $ty0 $rest0" || {
+ ret=1
+ echo_i "'$cl $ty $rest' != '$cl0 $ty0 $rest0'"
+ }
+done < checkzone.out$n
+test $ret -eq 0 || { echo_i "failed"; status=$((status + 1)); }
+
+n=$((n + 1))
+echo_i "check conversions to and from unknown record format ($n)"
+ret=0
+$CHECKZONE -Dq . tempzone | sed '/^;/d' > checkzone.out$n
+while read -r name tt cl ty rest
+do
+ myecho "$cl $ty $rest" | $RRCHECKER -u > checker.out || {
+ ret=1
+ echo_i "'$cl $ty $rest' not converted to unknown record format"
+ }
+ read -r clu tyu restu < checker.out
+ myecho "$clu $tyu $restu" | $RRCHECKER -p > checker.out || {
+ ret=1
+ echo_i "'$cl $ty $rest' not converted back to canonical format"
+ }
+ read -r cl0 ty0 rest0 < checker.out
+ test "$cl $ty $rest" = "$cl0 $ty0 $rest0" || {
+ ret=1
+ echo_i "'$cl $ty $rest' != '$cl0 $ty0 $rest0'"
+ }
+done < checkzone.out$n
+test $ret -eq 0 || { echo_i "failed"; status=$((status + 1)); }
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rrchecker/tests_sh_rrchecker.py b/bin/tests/system/rrchecker/tests_sh_rrchecker.py
new file mode 100644
index 0000000..16368e7
--- /dev/null
+++ b/bin/tests/system/rrchecker/tests_sh_rrchecker.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_rrchecker(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/rrchecker/typelist.good b/bin/tests/system/rrchecker/typelist.good
new file mode 100644
index 0000000..3c3e5cd
--- /dev/null
+++ b/bin/tests/system/rrchecker/typelist.good
@@ -0,0 +1,81 @@
+A
+NS
+MD
+MF
+CNAME
+SOA
+MB
+MG
+MR
+NULL
+WKS
+PTR
+HINFO
+MINFO
+MX
+TXT
+RP
+AFSDB
+X25
+ISDN
+RT
+NSAP
+NSAP-PTR
+SIG
+KEY
+PX
+GPOS
+AAAA
+LOC
+NXT
+EID
+NIMLOC
+SRV
+ATMA
+NAPTR
+KX
+CERT
+A6
+DNAME
+SINK
+APL
+DS
+SSHFP
+IPSECKEY
+RRSIG
+NSEC
+DNSKEY
+DHCID
+NSEC3
+NSEC3PARAM
+TLSA
+SMIMEA
+HIP
+NINFO
+RKEY
+TALINK
+CDS
+CDNSKEY
+OPENPGPKEY
+CSYNC
+ZONEMD
+SVCB
+HTTPS
+SPF
+UINFO
+UID
+GID
+UNSPEC
+NID
+L32
+L64
+LP
+EUI48
+EUI64
+URI
+CAA
+AVC
+DOA
+AMTRELAY
+TA
+DLV
diff --git a/bin/tests/system/rrl/broken.conf.in b/bin/tests/system/rrl/broken.conf.in
new file mode 100644
index 0000000..956593a
--- /dev/null
+++ b/bin/tests/system/rrl/broken.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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";
+ statistics-file "named.stats";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ notify no;
+ dnssec-validation no;
+
+ rate-limit {
+ responses-per-second 2;
+ all-per-second 50;
+ slip 3;
+ exempt-clients { 10.53.0.7; };
+ log-only yes;
+
+ min-table-size 0;
+ max-table-size 0;
+ };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
diff --git a/bin/tests/system/rrl/clean.sh b/bin/tests/system/rrl/clean.sh
new file mode 100644
index 0000000..739366a
--- /dev/null
+++ b/bin/tests/system/rrl/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Clean up after rrl tests.
+
+rm -f dig.out* *mdig.out*
+rm -f */named.memstats */named.run */named.stats */log-* */session.key
+rm -f ns3/bl*.db */*.jnl */*.core */*.pid
+rm -f ns*/named.lock
+rm -f ns*/named.conf
+rm -f broken.conf
+rm -f broken.out
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/rrl/ns1/named.conf.in b/bin/tests/system/rrl/ns1/named.conf.in
new file mode 100644
index 0000000..e4da6ef
--- /dev/null
+++ b/bin/tests/system/rrl/ns1/named.conf.in
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ notify no;
+ recursion yes;
+ dnssec-validation yes;
+};
+
+zone "." {type primary; file "root.db";};
diff --git a/bin/tests/system/rrl/ns1/root.db b/bin/tests/system/rrl/ns1/root.db
new file mode 100644
index 0000000..68265fe
--- /dev/null
+++ b/bin/tests/system/rrl/ns1/root.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA ns. hostmaster.ns. ( 1 3600 1200 604800 60 )
+@ NS ns.
+ns. A 10.53.0.1
+. A 10.53.0.1
+
+; limit responses from here
+tld2. NS ns.tld2.
+ns.tld2. A 10.53.0.2
+
+; limit recursion to here
+tld3. NS ns.tld3.
+ns.tld3. A 10.53.0.3
+
+; generate SERVFAIL
+tld4. NS ns.tld3.
diff --git a/bin/tests/system/rrl/ns2/hints b/bin/tests/system/rrl/ns2/hints
new file mode 100644
index 0000000..a1d435e
--- /dev/null
+++ b/bin/tests/system/rrl/ns2/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns1.
+ns1. 0 A 10.53.0.1
diff --git a/bin/tests/system/rrl/ns2/named.conf.in b/bin/tests/system/rrl/ns2/named.conf.in
new file mode 100644
index 0000000..abe4f9c
--- /dev/null
+++ b/bin/tests/system/rrl/ns2/named.conf.in
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ statistics-file "named.stats";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ notify no;
+ recursion yes;
+ dnssec-validation yes;
+
+ rate-limit {
+ responses-per-second 2;
+ all-per-second 50;
+ slip 3;
+ exempt-clients { 10.53.0.7; };
+
+ // small enough to force a table expansion
+ min-table-size 75;
+ };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+/*
+ * These log settings have no effect unless "-g" is removed from ../../start.pl
+ */
+logging {
+ channel debug {
+ file "log-debug";
+ print-category yes; print-severity yes; severity debug 10;
+ };
+ channel queries {
+ file "log-queries";
+ print-category yes; print-severity yes; severity info;
+ };
+ category rate-limit { debug; queries; };
+ category queries { debug; queries; };
+};
+
+zone "." { type hint; file "hints"; };
+
+zone "tld2."{ type primary; file "tld2.db"; };
diff --git a/bin/tests/system/rrl/ns2/tld2.db b/bin/tests/system/rrl/ns2/tld2.db
new file mode 100644
index 0000000..a1a832b
--- /dev/null
+++ b/bin/tests/system/rrl/ns2/tld2.db
@@ -0,0 +1,42 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; rate limit response from this zone
+
+$TTL 120
+@ SOA tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 )
+ NS ns
+ NS .
+ns A 10.53.0.2
+
+; basic rate limiting
+a1 A 192.0.2.1
+
+; wildcards
+*.a2 A 192.0.2.2
+
+; a3 is in tld3
+
+; a4 does not exist to give NXDOMAIN
+
+; a5 for TCP requests
+a5 A 192.0.2.5
+
+; a6 for whitelisted clients
+a6 A 192.0.2.6
+
+; a7 for SERVFAIL
+
+; a8 for NODATA
+a8 A 192.0.2.8
+
+; a9 for all-per-second limit
+$GENERATE 101-180 all$.a9 A 192.0.2.8
diff --git a/bin/tests/system/rrl/ns3/hints b/bin/tests/system/rrl/ns3/hints
new file mode 100644
index 0000000..a1d435e
--- /dev/null
+++ b/bin/tests/system/rrl/ns3/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns1.
+ns1. 0 A 10.53.0.1
diff --git a/bin/tests/system/rrl/ns3/named.conf.in b/bin/tests/system/rrl/ns3/named.conf.in
new file mode 100644
index 0000000..8807f44
--- /dev/null
+++ b/bin/tests/system/rrl/ns3/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ notify no;
+ recursion yes;
+ dnssec-validation yes;
+
+ // check that all of the options are parsed without limiting anything
+ rate-limit {
+ responses-per-second 200;
+ referrals-per-second 220;
+ nodata-per-second 230;
+ nxdomains-per-second 240;
+ errors-per-second 250;
+ all-per-second 700;
+ ipv4-prefix-length 24;
+ ipv6-prefix-length 64;
+ qps-scale 10;
+ window 1;
+ max-table-size 1000;
+ log-only no;
+ min-table-size 0;
+ };
+
+};
+
+zone "." { type hint; file "hints"; };
+
+zone "tld3."{ type primary; file "tld3.db"; };
diff --git a/bin/tests/system/rrl/ns3/tld3.db b/bin/tests/system/rrl/ns3/tld3.db
new file mode 100644
index 0000000..a534c6e
--- /dev/null
+++ b/bin/tests/system/rrl/ns3/tld3.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; rate limit response from this zone
+
+$TTL 120
+@ SOA tld3. hostmaster.ns.tld3. ( 1 3600 1200 604800 60 )
+ NS ns
+ NS .
+ns A 10.53.0.3
+
+*.a3 A 192.0.3.3
diff --git a/bin/tests/system/rrl/ns4/hints b/bin/tests/system/rrl/ns4/hints
new file mode 100644
index 0000000..a1d435e
--- /dev/null
+++ b/bin/tests/system/rrl/ns4/hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 0 NS ns1.
+ns1. 0 A 10.53.0.1
diff --git a/bin/tests/system/rrl/ns4/named.conf.in b/bin/tests/system/rrl/ns4/named.conf.in
new file mode 100644
index 0000000..3cd598e
--- /dev/null
+++ b/bin/tests/system/rrl/ns4/named.conf.in
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ session-keyfile "session.key";
+ pid-file "named.pid";
+ statistics-file "named.stats";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ notify no;
+ recursion yes;
+ dnssec-validation yes;
+ max-udp-size 4096;
+
+ rate-limit {
+ responses-per-second 2;
+ all-per-second 50;
+ slip 3;
+ exempt-clients { 10.53.0.7; };
+ log-only yes;
+
+ // small enough to force a table expansion
+ min-table-size 75;
+ };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+/*
+ * These log settings have no effect unless "-g" is removed from ../../start.pl
+ */
+logging {
+ channel debug {
+ file "log-debug";
+ print-category yes; print-severity yes; severity debug 10;
+ };
+ channel queries {
+ file "log-queries";
+ print-category yes; print-severity yes; severity info;
+ };
+ category rate-limit { debug; queries; };
+ category queries { debug; queries; };
+};
+
+zone "." { type hint; file "hints"; };
+
+zone "tld4."{ type primary; file "tld4.db"; };
diff --git a/bin/tests/system/rrl/ns4/tld4.db b/bin/tests/system/rrl/ns4/tld4.db
new file mode 100644
index 0000000..a7bc319
--- /dev/null
+++ b/bin/tests/system/rrl/ns4/tld4.db
@@ -0,0 +1,45 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; rate limit response from this zone
+
+$TTL 120
+@ SOA tld4. hostmaster.ns.tld4. ( 1 3600 1200 604800 60 )
+ NS ns
+ NS .
+ns A 10.53.0.2
+
+; basic rate limiting
+a1 A 192.0.2.1
+
+; wildcards
+*.a2 A 192.0.2.2
+
+; a3 is in tld3
+
+; a4 does not exist to give NXDOMAIN
+
+; a5 for TCP requests
+a5 A 192.0.2.5
+
+; a6 for whitelisted clients
+a6 A 192.0.2.6
+
+; a7 for SERVFAIL
+
+; a8 for NODATA
+a8 A 192.0.2.8
+
+; a9 for all-per-second limit
+$GENERATE 101-180 all$.a9 A 192.0.2.8
+
+; oversized TXT record
+$GENERATE 1-100 big 1 TXT "txt$"
diff --git a/bin/tests/system/rrl/setup.sh b/bin/tests/system/rrl/setup.sh
new file mode 100644
index 0000000..752b02c
--- /dev/null
+++ b/bin/tests/system/rrl/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports broken.conf.in broken.conf
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
diff --git a/bin/tests/system/rrl/tests.sh b/bin/tests/system/rrl/tests.sh
new file mode 100644
index 0000000..9465b93
--- /dev/null
+++ b/bin/tests/system/rrl/tests.sh
@@ -0,0 +1,290 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# test response rate limiting
+
+. ../conf.sh
+
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+#set -x
+
+ns1=10.53.0.1 # root, defining the others
+ns2=10.53.0.2 # test server
+ns3=10.53.0.3 # secondary test server
+ns4=10.53.0.4 # log-only test server
+ns7=10.53.0.7 # whitelisted client
+
+USAGE="$0: [-x]"
+while getopts "x" c; do
+ case $c in
+ x) set -x;;
+ *) echo "$USAGE" 1>&2; exit 1;;
+ esac
+done
+shift $((OPTIND - 1))
+if test "$#" -ne 0; then
+ echo "$USAGE" 1>&2
+ exit 1
+fi
+# really quit on control-C
+trap 'exit 1' 1 2 15
+
+
+ret=0
+setret () {
+ ret=1
+ echo_i "$*"
+}
+
+
+# Wait until soon after the start of a second to make results consistent.
+# The start of a second credits a rate limit.
+# This would be far easier in C or by assuming a modern version of perl.
+sec_start () {
+ START=$(date)
+ while true; do
+ NOW=$(date)
+ if test "$START" != "$NOW"; then
+ return
+ fi
+ $PERL -e 'select(undef, undef, undef, 0.05)' || true
+ done
+}
+
+
+# turn off ${HOME}/.digrc
+HOME=/dev/null; export HOME
+
+# $1=number of tests $2=target domain $3=dig options
+QNUM=1
+burst () {
+ BURST_LIMIT=$1; shift
+ BURST_DOM_BASE="$1"; shift
+
+ XCNT=$CNT
+ CNT='XXX'
+ eval FILENAME="mdig.out-$BURST_DOM_BASE"
+ CNT=$XCNT
+
+ DOMS=""
+ CNTS=$($PERL -e 'for ( $i = 0; $i < '$BURST_LIMIT'; $i++) { printf "%03d\n", '$QNUM' + $i; }')
+ for CNT in $CNTS
+ do
+ eval BURST_DOM="$BURST_DOM_BASE"
+ DOMS="$DOMS $BURST_DOM"
+ done
+ ARGS="+burst +nocookie +continue +time=1 +tries=1 -p ${PORT} $* @$ns2 $DOMS"
+ $MDIG $ARGS 2>&1 | \
+ tee -a full-$FILENAME | \
+ sed -n -e '/^;; AUTHORITY/,/^$/d' \
+ -e '/^;; ADDITIONAL/,/^$/d' \
+ -e 's/^[^;].* \([^ ]\{1,\}\)$/\1/p' \
+ -e 's/;; flags.* tc .*/TC/p' \
+ -e 's/;; .* status: NXDOMAIN.*/NXDOMAIN/p' \
+ -e 's/;; .* status: NOERROR.*/NOERROR/p' \
+ -e 's/;; .* status: SERVFAIL.*/SERVFAIL/p' \
+ -e 's/response failed with timed out.*/drop/p' \
+ -e 's/;; communications error to.*/drop/p' >> $FILENAME &
+ QNUM=$((QNUM + BURST_LIMIT))
+}
+
+# compare integers $1 and $2; ensure the difference is no more than $3
+range () {
+ $PERL -e 'if (abs(int($ARGV[0]) - int($ARGV[1])) > int($ARGV[2])) { exit(1) }' $1 $2 $3
+}
+
+# $1=domain $2=IP address $3=# of IP addresses $4=TC $5=drop
+# $6=NXDOMAIN $7=SERVFAIL or other errors
+ck_result() {
+ # wait to the background mdig calls to complete.
+ wait
+ BAD=no
+ ADDRS=$(grep -E "^$2$" mdig.out-$1 2>/dev/null | wc -l)
+ # count simple truncated and truncated NXDOMAIN as TC
+ TC=$(grep -E "^TC|NXDOMAINTC$" mdig.out-$1 2>/dev/null | wc -l)
+ DROP=$(grep -E "^drop$" mdig.out-$1 2>/dev/null | wc -l)
+ # count NXDOMAIN and truncated NXDOMAIN as NXDOMAIN
+ NXDOMAIN=$(grep -E "^NXDOMAIN|NXDOMAINTC$" mdig.out-$1 2>/dev/null | wc -l)
+ SERVFAIL=$(grep -E "^SERVFAIL$" mdig.out-$1 2>/dev/null | wc -l)
+ NOERROR=$(grep -E "^NOERROR$" mdig.out-$1 2>/dev/null | wc -l)
+
+ range $ADDRS "$3" 1 ||
+ setret "$ADDRS instead of $3 '$2' responses for $1" &&
+ BAD=yes
+
+ range $TC "$4" 1 ||
+ setret "$TC instead of $4 truncation responses for $1" &&
+ BAD=yes
+
+ range $DROP "$5" 1 ||
+ setret "$DROP instead of $5 dropped responses for $1" &&
+ BAD=yes
+
+ range $NXDOMAIN "$6" 1 ||
+ setret "$NXDOMAIN instead of $6 NXDOMAIN responses for $1" &&
+ BAD=yes
+
+ range $SERVFAIL "$7" 1 ||
+ setret "$SERVFAIL instead of $7 error responses for $1" &&
+ BAD=yes
+
+ range $NOERROR "$8" 1 ||
+ setret "$NOERROR instead of $8 NOERROR responses for $1" &&
+ BAD=yes
+
+ if test -z "$BAD"; then
+ rm -f mdig.out-$1
+ fi
+}
+
+
+ckstats () {
+ LABEL="$1"; shift
+ TYPE="$1"; shift
+ EXPECTED="$1"; shift
+ C=$(cat ns2/named.stats |
+ sed -n -e "s/[ ]*\([0-9]*\).responses $TYPE for rate limits.*/\1/p" |
+ tail -1)
+ C=$((C))
+
+ range "$C" $EXPECTED 1 ||
+ setret "wrong $LABEL $TYPE statistics of $C instead of $EXPECTED"
+}
+
+
+#########
+sec_start
+
+# Tests of referrals to "." must be done before the hints are loaded.
+burst 5 a1.tld3 +norec
+# basic rate limiting
+burst 3 a1.tld2
+# delay allows an additional response.
+sleep 1
+burst 10 a1.tld2
+# Request 30 different qnames to try a wildcard.
+burst 30 'y.x$CNT.a2.tld2'
+
+# IP TC drop NXDOMAIN SERVFAIL NOERROR
+# referrals to "."
+ck_result a1.tld3 x 0 1 2 0 0 2
+# check 13 results including 1 second delay that allows an additional response
+ck_result a1.tld2 192.0.2.1 3 4 6 0 0 8
+
+# Check the wildcard answers.
+# The zone origin name of the 30 requests is counted.
+ck_result 'y.x*.a2.tld2' 192.0.2.2 2 10 18 0 0 12
+
+#########
+sec_start
+
+burst 10 'x.a3.tld3'
+burst 10 'y$CNT.a3.tld3'
+burst 10 'z$CNT.a4.tld2'
+
+# 10 identical recursive responses are limited
+ck_result 'x.a3.tld3' 192.0.3.3 2 3 5 0 0 5
+
+# 10 different recursive responses are not limited
+ck_result 'y*.a3.tld3' 192.0.3.3 10 0 0 0 0 10
+
+# 10 different NXDOMAIN responses are limited based on the parent name.
+# We count 13 responses because we count truncated NXDOMAIN responses
+# as both truncated and NXDOMAIN.
+ck_result 'z*.a4.tld2' x 0 3 5 5 0 0
+
+$RNDCCMD $ns2 stats
+ckstats first dropped 36
+ckstats first truncated 21
+
+
+#########
+sec_start
+
+burst 10 a5.tld2 +tcp
+burst 10 a6.tld2 -b $ns7
+burst 10 a7.tld4
+burst 2 a8.tld2 -t AAAA
+burst 2 a8.tld2 -t TXT
+burst 2 a8.tld2 -t SPF
+
+# IP TC drop NXDOMAIN SERVFAIL NOERROR
+# TCP responses are not rate limited
+ck_result a5.tld2 192.0.2.5 10 0 0 0 0 10
+
+# whitelisted client is not rate limited
+ck_result a6.tld2 192.0.2.6 10 0 0 0 0 10
+
+# Errors such as SERVFAIL are rate limited.
+ck_result a7.tld4 x 0 0 8 0 2 0
+
+# NODATA responses are counted as the same regardless of qtype.
+ck_result a8.tld2 x 0 2 2 0 0 4
+
+$RNDCCMD $ns2 stats
+ckstats second dropped 46
+ckstats second truncated 23
+
+
+#########
+sec_start
+
+# IP TC drop NXDOMAIN SERVFAIL NOERROR
+# all-per-second
+# The qnames are all unique but the client IP address is constant.
+QNUM=101
+burst 60 'all$CNT.a9.tld2'
+
+ck_result 'a*.a9.tld2' 192.0.2.8 50 0 10 0 0 50
+
+$RNDCCMD $ns2 stats
+ckstats final dropped 56
+ckstats final truncated 23
+
+#########
+sec_start
+
+DIGOPTS="+nocookie +nosearch +time=1 +tries=1 +ignore -p ${PORT}"
+$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
+$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
+$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
+$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
+$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
+$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
+$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
+$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
+$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
+$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
+$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
+
+# regression test for GL #2839
+DIGOPTS="+bufsize=4096 +ignore -p ${PORT}"
+$DIG $DIGOPTS @$ns4 TXT big.tld4 > /dev/null 2>&1
+
+grep "would limit" ns4/named.run >/dev/null 2>&1 ||
+setret "\"would limit\" not found in log file."
+
+$NAMED -D rrl-ns5 -gc broken.conf > broken.out 2>&1 &
+sleep 2
+grep "min-table-size 1" broken.out > /dev/null || setret "min-table-size 0 was not changed to 1"
+
+if [ -f named.pid ]; then
+ kill $(cat named.pid)
+ setret "named should not have started, but did"
+fi
+
+echo_i "exit status: $ret"
+[ $ret -eq 0 ] || exit 1
diff --git a/bin/tests/system/rrl/tests_sh_rrl.py b/bin/tests/system/rrl/tests_sh_rrl.py
new file mode 100644
index 0000000..05b43a6
--- /dev/null
+++ b/bin/tests/system/rrl/tests_sh_rrl.py
@@ -0,0 +1,18 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import pytest_custom_markers
+
+
+# The rrl is known to be quite unstable. GL #172
+@pytest_custom_markers.flaky(max_runs=2)
+def test_rrl(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/rrsetorder/clean.sh b/bin/tests/system/rrsetorder/clean.sh
new file mode 100644
index 0000000..c64ae34
--- /dev/null
+++ b/bin/tests/system/rrsetorder/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out.test*
+rm -f dig.out.cyclic dig.out.fixed dig.out.random dig.out.nomatch dig.out.none
+rm -f dig.out.0 dig.out.1 dig.out.2 dig.out.3
+rm -f dig.out.cyclic2
+rm -f ns2/root.bk
+rm -f ns?/named.run ns?/named.core
+rm -f */named.memstats
+rm -f ns*/named.lock
+rm -f ns*/named.conf
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/rrsetorder/ns1/named.conf.in b/bin/tests/system/rrsetorder/ns1/named.conf.in
new file mode 100644
index 0000000..98301c2
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns1/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+ rrset-order {
+ name "fixed.example" order fixed;
+ name "random.example" order random;
+ name "cyclic.example" order cyclic;
+ name "none.example" order none;
+ type NS order random;
+ order cyclic;
+ };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+ notify explicit;
+ also-notify { 10.53.0.2; };
+};
diff --git a/bin/tests/system/rrsetorder/ns1/root.db b/bin/tests/system/rrsetorder/ns1/root.db
new file mode 100644
index 0000000..094eec7
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns1/root.db
@@ -0,0 +1,51 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+. SOA hostmaster.isc.org. a.root-servers.nil. (
+ 2000042100
+ 600
+ 600
+ 1200
+ 600 )
+. NS a.root-servers.nil.
+. NS cyclic.example.
+a.root-servers.nil. A 10.53.0.1
+;
+fixed.example. A 1.2.3.4
+fixed.example. A 1.2.3.3
+fixed.example. A 1.2.3.1
+fixed.example. A 1.2.3.2
+;
+random.example. A 1.2.3.1
+random.example. A 1.2.3.2
+random.example. A 1.2.3.3
+random.example. A 1.2.3.4
+;
+cyclic.example. A 1.2.3.4
+cyclic.example. A 1.2.3.3
+cyclic.example. A 1.2.3.2
+cyclic.example. A 1.2.3.1
+;
+cyclic2.example. A 1.2.3.4
+cyclic2.example. A 1.2.3.3
+cyclic2.example. A 1.2.3.2
+cyclic2.example. A 1.2.3.1
+;
+nomatch.example. A 1.2.3.1
+nomatch.example. A 1.2.3.2
+nomatch.example. A 1.2.3.3
+nomatch.example. A 1.2.3.4
+;
+none.example. A 1.2.3.1
+none.example. A 1.2.3.2
+none.example. A 1.2.3.3
+none.example. A 1.2.3.4
diff --git a/bin/tests/system/rrsetorder/ns2/named.conf.in b/bin/tests/system/rrsetorder/ns2/named.conf.in
new file mode 100644
index 0000000..164400a
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns2/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ rrset-order {
+ name "fixed.example" order fixed;
+ name "random.example" order random;
+ name "cyclic.example" order cyclic;
+ name "none.example" order none;
+ type NS order random;
+ order cyclic;
+ };
+};
+
+zone "." {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "root.bk";
+};
diff --git a/bin/tests/system/rrsetorder/ns3/named.conf.in b/bin/tests/system/rrsetorder/ns3/named.conf.in
new file mode 100644
index 0000000..a5850ca
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns3/named.conf.in
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ rrset-order {
+ name "fixed.example" order fixed;
+ name "random.example" order random;
+ name "cyclic.example" order cyclic;
+ name "none.example" order none;
+ type NS order random;
+ order cyclic;
+ };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/rrsetorder/ns4/named.conf.in b/bin/tests/system/rrsetorder/ns4/named.conf.in
new file mode 100644
index 0000000..d12f50f
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns4/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ rrset-order {
+ class IN type A name "host.example.com" order random;
+ };
+
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/rrsetorder/ns5/named.conf.in b/bin/tests/system/rrsetorder/ns5/named.conf.in
new file mode 100644
index 0000000..d1a4cfa
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns5/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ dnssec-validation yes;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.fixed.good b/bin/tests/system/rrsetorder/reference.dig.out.fixed.good
new file mode 100644
index 0000000..eaf9c63
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.fixed.good
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.3
+1.2.3.1
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good1 b/bin/tests/system/rrsetorder/reference.dig.out.random.good1
new file mode 100644
index 0000000..c272c75
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good1
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.2
+1.2.3.3
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good10 b/bin/tests/system/rrsetorder/reference.dig.out.random.good10
new file mode 100644
index 0000000..6a39e3f
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good10
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.3
+1.2.3.4
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good11 b/bin/tests/system/rrsetorder/reference.dig.out.random.good11
new file mode 100644
index 0000000..efbc792
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good11
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.4
+1.2.3.1
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good12 b/bin/tests/system/rrsetorder/reference.dig.out.random.good12
new file mode 100644
index 0000000..c859a2e
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good12
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.4
+1.2.3.3
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good13 b/bin/tests/system/rrsetorder/reference.dig.out.random.good13
new file mode 100644
index 0000000..49bf54b
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good13
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.1
+1.2.3.2
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good14 b/bin/tests/system/rrsetorder/reference.dig.out.random.good14
new file mode 100644
index 0000000..974aa89
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good14
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.1
+1.2.3.4
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good15 b/bin/tests/system/rrsetorder/reference.dig.out.random.good15
new file mode 100644
index 0000000..e8deb67
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good15
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.2
+1.2.3.1
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good16 b/bin/tests/system/rrsetorder/reference.dig.out.random.good16
new file mode 100644
index 0000000..f467087
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good16
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.2
+1.2.3.4
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good17 b/bin/tests/system/rrsetorder/reference.dig.out.random.good17
new file mode 100644
index 0000000..6082a25
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good17
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.4
+1.2.3.1
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good18 b/bin/tests/system/rrsetorder/reference.dig.out.random.good18
new file mode 100644
index 0000000..07eefa0
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good18
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.4
+1.2.3.2
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good19 b/bin/tests/system/rrsetorder/reference.dig.out.random.good19
new file mode 100644
index 0000000..a5530c6
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good19
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.1
+1.2.3.2
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good2 b/bin/tests/system/rrsetorder/reference.dig.out.random.good2
new file mode 100644
index 0000000..00da93a
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good2
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.2
+1.2.3.4
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good20 b/bin/tests/system/rrsetorder/reference.dig.out.random.good20
new file mode 100644
index 0000000..6dcf6da
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good20
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.1
+1.2.3.3
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good21 b/bin/tests/system/rrsetorder/reference.dig.out.random.good21
new file mode 100644
index 0000000..9dcc63f
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good21
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.2
+1.2.3.1
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good22 b/bin/tests/system/rrsetorder/reference.dig.out.random.good22
new file mode 100644
index 0000000..4c51aa6
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good22
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.2
+1.2.3.3
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good23 b/bin/tests/system/rrsetorder/reference.dig.out.random.good23
new file mode 100644
index 0000000..eaf9c63
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good23
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.3
+1.2.3.1
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good24 b/bin/tests/system/rrsetorder/reference.dig.out.random.good24
new file mode 100644
index 0000000..c25c756
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good24
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.3
+1.2.3.2
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good3 b/bin/tests/system/rrsetorder/reference.dig.out.random.good3
new file mode 100644
index 0000000..4d50059
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good3
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.3
+1.2.3.2
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good4 b/bin/tests/system/rrsetorder/reference.dig.out.random.good4
new file mode 100644
index 0000000..0b34afa
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good4
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.3
+1.2.3.4
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good5 b/bin/tests/system/rrsetorder/reference.dig.out.random.good5
new file mode 100644
index 0000000..efe0e25
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good5
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.4
+1.2.3.2
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good6 b/bin/tests/system/rrsetorder/reference.dig.out.random.good6
new file mode 100644
index 0000000..d2ca6fc
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good6
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.4
+1.2.3.3
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good7 b/bin/tests/system/rrsetorder/reference.dig.out.random.good7
new file mode 100644
index 0000000..0d8312a
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good7
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.1
+1.2.3.3
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good8 b/bin/tests/system/rrsetorder/reference.dig.out.random.good8
new file mode 100644
index 0000000..3b27693
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good8
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.1
+1.2.3.4
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good9 b/bin/tests/system/rrsetorder/reference.dig.out.random.good9
new file mode 100644
index 0000000..61192af
--- /dev/null
+++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good9
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.3
+1.2.3.1
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/setup.sh b/bin/tests/system/rrsetorder/setup.sh
new file mode 100644
index 0000000..fbb1a38
--- /dev/null
+++ b/bin/tests/system/rrsetorder/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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/rrsetorder/tests.sh b/bin/tests/system/rrsetorder/tests.sh
new file mode 100644
index 0000000..cf8bbd1
--- /dev/null
+++ b/bin/tests/system/rrsetorder/tests.sh
@@ -0,0 +1,558 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short +nocookie"
+
+dig_cmd() {
+ # shellcheck disable=SC2086
+ "$DIG" $DIGOPTS -p "${PORT}" "$@" | grep -v '^;'
+}
+
+status=0
+
+GOOD_RANDOM="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24"
+GOOD_RANDOM_NO=24
+
+if grep "^#define DNS_RDATASET_FIXED" "$TOP_BUILDDIR/config.h" > /dev/null 2>&1 ; then
+ test_fixed=true
+else
+ echo_i "Order 'fixed' disabled at compile time"
+ test_fixed=false
+fi
+
+#
+#
+#
+if $test_fixed; then
+ echo_i "Checking order fixed (primary)"
+ ret=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ dig_cmd @10.53.0.1 fixed.example > dig.out.fixed || ret=1
+ diff dig.out.fixed reference.dig.out.fixed.good >/dev/null || ret=1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+else
+ echo_i "Checking order fixed behaves as cyclic when disabled (primary)"
+ ret=0
+ matches=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+ do
+ j=$((i % 4))
+ dig_cmd @10.53.0.1 fixed.example > dig.out.fixed || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.fixed dig.out.$j
+ else
+ diff dig.out.fixed dig.out.$j >/dev/null && matches=$((matches + 1))
+ fi
+ done
+ diff dig.out.0 dig.out.1 >/dev/null && ret=1
+ diff dig.out.0 dig.out.2 >/dev/null && ret=1
+ diff dig.out.0 dig.out.3 >/dev/null && ret=1
+ diff dig.out.1 dig.out.2 >/dev/null && ret=1
+ diff dig.out.1 dig.out.3 >/dev/null && ret=1
+ diff dig.out.2 dig.out.3 >/dev/null && ret=1
+ if [ $matches -ne 16 ]; then ret=1; fi
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+#
+#
+#
+echo_i "Checking order cyclic (primary + additional)"
+ret=0
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=$((i % 4))
+ dig_cmd @10.53.0.1 cyclic.example > dig.out.cyclic || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic dig.out.$j
+ else
+ diff dig.out.cyclic dig.out.$j >/dev/null && matches=$((matches + 1))
+ fi
+done
+diff dig.out.0 dig.out.1 >/dev/null && ret=1
+diff dig.out.0 dig.out.2 >/dev/null && ret=1
+diff dig.out.0 dig.out.3 >/dev/null && ret=1
+diff dig.out.1 dig.out.2 >/dev/null && ret=1
+diff dig.out.1 dig.out.3 >/dev/null && ret=1
+diff dig.out.2 dig.out.3 >/dev/null && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#
+#
+#
+echo_i "Checking order cyclic (primary)"
+ret=0
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=$((i % 4))
+ dig_cmd @10.53.0.1 cyclic2.example > dig.out.cyclic2 || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic2 dig.out.$j
+ else
+ diff dig.out.cyclic2 dig.out.$j >/dev/null && matches=$((matches + 1))
+ fi
+done
+diff dig.out.0 dig.out.1 >/dev/null && ret=1
+diff dig.out.0 dig.out.2 >/dev/null && ret=1
+diff dig.out.0 dig.out.3 >/dev/null && ret=1
+diff dig.out.1 dig.out.2 >/dev/null && ret=1
+diff dig.out.1 dig.out.3 >/dev/null && ret=1
+diff dig.out.2 dig.out.3 >/dev/null && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+echo_i "Checking order random (primary)"
+ret=0
+for i in $GOOD_RANDOM
+do
+ eval match$i=0
+done
+for i in 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 0 1 2 3 4 5 6 7 9
+do
+ dig_cmd @10.53.0.1 random.example > dig.out.random || ret=1
+ match=0
+ for j in $GOOD_RANDOM
+ do
+ eval "diff dig.out.random reference.dig.out.random.good$j >/dev/null && match$j=1 match=1 || true"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=0
+for i in $GOOD_RANDOM
+do
+ eval "match=\$((match + match$i))"
+done
+echo_i "Random selection return $match of ${GOOD_RANDOM_NO} possible orders in 36 samples"
+if [ $match -lt $((GOOD_RANDOM_NO / 3)) ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "Checking order none (primary)"
+ret=0
+# Fetch the "reference" response and ensure it contains the expected records.
+dig_cmd @10.53.0.1 none.example > dig.out.none || ret=1
+for i in 1 2 3 4; do
+ grep -F -q 1.2.3.$i dig.out.none || ret=1
+done
+# Ensure 20 further queries result in the same response as the "reference" one.
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
+ dig_cmd @10.53.0.1 none.example > dig.out.test$i || ret=1
+ diff dig.out.none dig.out.test$i >/dev/null || ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#
+#
+#
+if $test_fixed; then
+ echo_i "Checking order fixed (secondary)"
+ ret=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ dig_cmd @10.53.0.2 fixed.example > dig.out.fixed || ret=1
+ diff dig.out.fixed reference.dig.out.fixed.good || ret=1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+#
+#
+#
+echo_i "Checking order cyclic (secondary + additional)"
+ret=0
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=$((i % 4))
+ dig_cmd @10.53.0.2 cyclic.example > dig.out.cyclic || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic dig.out.$j
+ else
+ diff dig.out.cyclic dig.out.$j >/dev/null && matches=$((matches + 1))
+ fi
+done
+diff dig.out.0 dig.out.1 >/dev/null && ret=1
+diff dig.out.0 dig.out.2 >/dev/null && ret=1
+diff dig.out.0 dig.out.3 >/dev/null && ret=1
+diff dig.out.1 dig.out.2 >/dev/null && ret=1
+diff dig.out.1 dig.out.3 >/dev/null && ret=1
+diff dig.out.2 dig.out.3 >/dev/null && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#
+#
+#
+echo_i "Checking order cyclic (secondary)"
+ret=0
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=$((i % 4))
+ dig_cmd @10.53.0.2 cyclic2.example > dig.out.cyclic2 || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic2 dig.out.$j
+ else
+ diff dig.out.cyclic2 dig.out.$j >/dev/null && matches=$((matches + 1))
+ fi
+done
+diff dig.out.0 dig.out.1 >/dev/null && ret=1
+diff dig.out.0 dig.out.2 >/dev/null && ret=1
+diff dig.out.0 dig.out.3 >/dev/null && ret=1
+diff dig.out.1 dig.out.2 >/dev/null && ret=1
+diff dig.out.1 dig.out.3 >/dev/null && ret=1
+diff dig.out.2 dig.out.3 >/dev/null && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "Checking order random (secondary)"
+ret=0
+for i in $GOOD_RANDOM
+do
+ eval match$i=0
+done
+for i in 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 0 1 2 3 4 5 6 7 9
+do
+ dig_cmd @10.53.0.2 random.example > dig.out.random || ret=1
+ match=0
+ for j in $GOOD_RANDOM
+ do
+ eval "diff dig.out.random reference.dig.out.random.good$j >/dev/null && match$j=1 match=1 || true"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=0
+for i in $GOOD_RANDOM
+do
+ eval "match=\$((match + match$i))"
+done
+echo_i "Random selection return $match of ${GOOD_RANDOM_NO} possible orders in 36 samples"
+if [ $match -lt $((GOOD_RANDOM_NO / 3)) ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "Checking order none (secondary)"
+ret=0
+# Fetch the "reference" response and ensure it contains the expected records.
+dig_cmd @10.53.0.2 none.example > dig.out.none || ret=1
+for i in 1 2 3 4; do
+ grep -F -q 1.2.3.$i dig.out.none || ret=1
+done
+# Ensure 20 further queries result in the same response as the "reference" one.
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
+ dig_cmd @10.53.0.2 none.example > dig.out.test$i || ret=1
+ diff dig.out.none dig.out.test$i >/dev/null || ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "Shutting down secondary"
+
+stop_server ns2
+
+echo_i "Checking for secondary's on disk copy of zone"
+
+if [ ! -f ns2/root.bk ]
+then
+ echo_i "failed";
+ status=$((status + 1))
+fi
+
+echo_i "Re-starting secondary"
+
+start_server --noclean --restart --port ${PORT} ns2
+
+#
+#
+#
+if $test_fixed; then
+ echo_i "Checking order fixed (secondary loaded from disk)"
+ ret=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ dig_cmd @10.53.0.2 fixed.example > dig.out.fixed || ret=1
+ diff dig.out.fixed reference.dig.out.fixed.good || ret=1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+#
+#
+#
+echo_i "Checking order cyclic (secondary + additional, loaded from disk)"
+ret=0
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=$((i % 4))
+ dig_cmd @10.53.0.2 cyclic.example > dig.out.cyclic || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic dig.out.$j
+ else
+ diff dig.out.cyclic dig.out.$j >/dev/null && matches=$((matches + 1))
+ fi
+done
+diff dig.out.0 dig.out.1 >/dev/null && ret=1
+diff dig.out.0 dig.out.2 >/dev/null && ret=1
+diff dig.out.0 dig.out.3 >/dev/null && ret=1
+diff dig.out.1 dig.out.2 >/dev/null && ret=1
+diff dig.out.1 dig.out.3 >/dev/null && ret=1
+diff dig.out.2 dig.out.3 >/dev/null && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#
+#
+#
+echo_i "Checking order cyclic (secondary loaded from disk)"
+ret=0
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=$((i % 4))
+ dig_cmd @10.53.0.2 cyclic2.example > dig.out.cyclic2 || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic2 dig.out.$j
+ else
+ diff dig.out.cyclic2 dig.out.$j >/dev/null && matches=$((matches + 1))
+ fi
+done
+diff dig.out.0 dig.out.1 >/dev/null && ret=1
+diff dig.out.0 dig.out.2 >/dev/null && ret=1
+diff dig.out.0 dig.out.3 >/dev/null && ret=1
+diff dig.out.1 dig.out.2 >/dev/null && ret=1
+diff dig.out.1 dig.out.3 >/dev/null && ret=1
+diff dig.out.2 dig.out.3 >/dev/null && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "Checking order random (secondary loaded from disk)"
+ret=0
+for i in $GOOD_RANDOM
+do
+ eval match$i=0
+done
+for i in 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 0 1 2 3 4 5 6 7 9
+do
+ dig_cmd @10.53.0.2 random.example > dig.out.random || ret=1
+ match=0
+ for j in $GOOD_RANDOM
+ do
+ eval "diff dig.out.random reference.dig.out.random.good$j >/dev/null && match$j=1 match=1 || true"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=0
+for i in $GOOD_RANDOM
+do
+ eval "match=\$((match + match$i))"
+done
+echo_i "Random selection return $match of ${GOOD_RANDOM_NO} possible orders in 36 samples"
+if [ $match -lt $((GOOD_RANDOM_NO / 3)) ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "Checking order none (secondary loaded from disk)"
+ret=0
+# Fetch the "reference" response and ensure it contains the expected records.
+dig_cmd @10.53.0.2 none.example > dig.out.none || ret=1
+for i in 1 2 3 4; do
+ grep -F -q 1.2.3.$i dig.out.none || ret=1
+done
+# Ensure 20 further queries result in the same response as the "reference" one.
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
+ dig_cmd @10.53.0.2 none.example > dig.out.test$i || ret=1
+ diff dig.out.none dig.out.test$i >/dev/null || ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#
+#
+#
+if $test_fixed; then
+ echo_i "Checking order fixed (cache)"
+ ret=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ dig_cmd @10.53.0.3 fixed.example > dig.out.fixed || ret=1
+ diff dig.out.fixed reference.dig.out.fixed.good || ret=1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+fi
+
+#
+#
+#
+echo_i "Checking order cyclic (cache + additional)"
+ret=0
+# prime acache
+dig_cmd @10.53.0.3 cyclic.example > dig.out.cyclic || ret=1
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=$((i % 4))
+ dig_cmd @10.53.0.3 cyclic.example > dig.out.cyclic || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic dig.out.$j
+ else
+ diff dig.out.cyclic dig.out.$j >/dev/null && matches=$((matches + 1))
+ fi
+done
+diff dig.out.0 dig.out.1 >/dev/null && ret=1
+diff dig.out.0 dig.out.2 >/dev/null && ret=1
+diff dig.out.0 dig.out.3 >/dev/null && ret=1
+diff dig.out.1 dig.out.2 >/dev/null && ret=1
+diff dig.out.1 dig.out.3 >/dev/null && ret=1
+diff dig.out.2 dig.out.3 >/dev/null && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+#
+#
+#
+echo_i "Checking order cyclic (cache)"
+ret=0
+# prime acache
+dig_cmd @10.53.0.3 cyclic2.example > dig.out.cyclic2 || ret=1
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=$((i % 4))
+ dig_cmd @10.53.0.3 cyclic2.example > dig.out.cyclic2 || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic2 dig.out.$j
+ else
+ diff dig.out.cyclic2 dig.out.$j >/dev/null && matches=$((matches + 1))
+ fi
+done
+diff dig.out.0 dig.out.1 >/dev/null && ret=1
+diff dig.out.0 dig.out.2 >/dev/null && ret=1
+diff dig.out.0 dig.out.3 >/dev/null && ret=1
+diff dig.out.1 dig.out.2 >/dev/null && ret=1
+diff dig.out.1 dig.out.3 >/dev/null && ret=1
+diff dig.out.2 dig.out.3 >/dev/null && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "Checking order random (cache)"
+ret=0
+for i in $GOOD_RANDOM
+do
+ eval match$i=0
+done
+for i in 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 0 1 2 3 4 5 6 7 9
+do
+ dig_cmd @10.53.0.3 random.example > dig.out.random || ret=1
+ match=0
+ for j in $GOOD_RANDOM
+ do
+ eval "diff dig.out.random reference.dig.out.random.good$j >/dev/null && match$j=1 match=1 || true"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=0
+for i in $GOOD_RANDOM
+do
+ eval "match=\$((match + match$i))"
+done
+echo_i "Random selection return $match of ${GOOD_RANDOM_NO} possible orders in 36 samples"
+if [ $match -lt $((GOOD_RANDOM_NO / 3)) ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "Checking order none (cache)"
+ret=0
+# Fetch the "reference" response and ensure it contains the expected records.
+dig_cmd @10.53.0.3 none.example > dig.out.none || ret=1
+for i in 1 2 3 4; do
+ grep -F -q 1.2.3.$i dig.out.none || ret=1
+done
+# Ensure 20 further queries result in the same response as the "reference" one.
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
+ dig_cmd @10.53.0.3 none.example > dig.out.test$i || ret=1
+ diff dig.out.none dig.out.test$i >/dev/null || ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "Checking default order (cache)"
+ret=0
+for i in $GOOD_RANDOM
+do
+ eval match$i=0
+done
+for i in 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 0 1 2 3 4 5 6 7 9
+do
+ dig_cmd @10.53.0.5 random.example > dig.out.random || ret=1
+ match=0
+ for j in $GOOD_RANDOM
+ do
+ eval "diff dig.out.random reference.dig.out.random.good$j >/dev/null && match$j=1 match=1 || true"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=0
+for i in $GOOD_RANDOM
+do
+ eval "match=\$((match + match$i))"
+done
+echo_i "Default selection return $match of ${GOOD_RANDOM_NO} possible orders in 36 samples"
+if [ $match -lt $((GOOD_RANDOM_NO / 3)) ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "Checking default order no match in rrset-order (cache)"
+ret=0
+# Fetch the "reference" response and ensure it contains the expected records.
+dig_cmd @10.53.0.4 nomatch.example > dig.out.nomatch || ret=1
+for i in 1 2 3 4; do
+ grep -F -q 1.2.3.$i dig.out.nomatch || ret=1
+done
+# Ensure 20 further queries result in the same response as the "reference" one.
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
+ dig_cmd @10.53.0.4 nomatch.example > dig.out.test$i || ret=1
+ diff dig.out.nomatch dig.out.test$i >/dev/null || ret=1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rrsetorder/tests_sh_rrsetorder.py b/bin/tests/system/rrsetorder/tests_sh_rrsetorder.py
new file mode 100644
index 0000000..e413f97
--- /dev/null
+++ b/bin/tests/system/rrsetorder/tests_sh_rrsetorder.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_rrsetorder(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/rsabigexponent/README.md b/bin/tests/system/rsabigexponent/README.md
new file mode 100644
index 0000000..44afdbd
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/README.md
@@ -0,0 +1,39 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+The `rsabigexponent` test is used to `check max-rsa-exponent-size`.
+
+We only run this test on builds without PKCS#11, as we have control over
+the RSA exponent size with plain OpenSSL. We have not explored how to do
+this with PKCS#11, which would require generating such a key and then
+signing a zone with it. Additionally, even with control of the exponent
+size with PKCS#11, generating a DNSKEY with this property and signing
+such a zone would be slow and undesirable for each test run; instead, we
+use a pregenerated DNSKEY and a saved signed zone. These are located in
+`rsabigexponent/ns2` and currently use RSASHA1 for the `DNSKEY`
+algorithm; however, that may need to be changed in the future.
+
+To generate the `DNSKEY` used in this test, we used `bigkey.c`, as
+dnssec-keygen is not capable of generating such keys.
+
+Do **not** remove `bigkey.c` as it may be needed to generate a new
+`DNSKEY` for testing purposes.
+
+`bigkey` is used to both test that we are not running under PKCS#11 and
+generate a `DNSKEY` key with a large RSA exponent.
+
+To regenerate `ns2/example.db.bad` comment out the range test in
+opensslrsa_parse before signing the zone with a ZSK key generated
+by `bigkey`.
+
+ if (BN_num_bits(e) > RSA_MAX_PUBEXP_BITS) {
+ DST_RET(ISC_R_RANGE);
+ }
diff --git a/bin/tests/system/rsabigexponent/bigkey.c b/bin/tests/system/rsabigexponent/bigkey.c
new file mode 100644
index 0000000..19fc9ba
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/bigkey.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#define DST_KEY_INTERNAL
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/rsa.h>
+
+#include <isc/result.h>
+
+#include <dns/dnssec.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+dst_key_t *key;
+dns_fixedname_t fname;
+dns_name_t *name;
+unsigned int bits = 2048U;
+isc_mem_t *mctx;
+isc_log_t *log_;
+isc_logconfig_t *logconfig;
+int level = ISC_LOG_WARNING;
+isc_logdestination_t destination;
+char filename[255];
+isc_result_t result;
+isc_buffer_t buf;
+RSA *rsa;
+BIGNUM *e;
+EVP_PKEY *pkey;
+
+#define CHECK(op, msg) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ fprintf(stderr, \
+ "fatal error: %s returns %s at file %s line " \
+ "%d\n", \
+ msg, isc_result_totext(result), __FILE__, \
+ __LINE__); \
+ ERR_clear_error(); \
+ exit(1); \
+ } \
+ } while (0)
+
+int
+main(int argc, char **argv) {
+ UNUSED(argc);
+ UNUSED(argv);
+
+ rsa = RSA_new();
+ e = BN_new();
+ pkey = EVP_PKEY_new();
+
+ if ((rsa == NULL) || (e == NULL) || (pkey == NULL) ||
+ !EVP_PKEY_set1_RSA(pkey, rsa))
+ {
+ fprintf(stderr, "fatal error: basic OpenSSL failure\n");
+ ERR_clear_error();
+ exit(1);
+ }
+
+ /* e = 0x1000000000001 */
+ BN_set_bit(e, 0);
+ BN_set_bit(e, 48);
+
+ if (RSA_generate_key_ex(rsa, bits, e, NULL)) {
+ BN_free(e);
+ RSA_free(rsa);
+ } else {
+ fprintf(stderr,
+ "fatal error: RSA_generate_key_ex() fails "
+ "at file %s line %d\n",
+ __FILE__, __LINE__);
+ ERR_clear_error();
+ exit(1);
+ }
+
+ isc_mem_create(&mctx);
+ CHECK(dst_lib_init(mctx, NULL), "dst_lib_init()");
+ isc_log_create(mctx, &log_, &logconfig);
+ isc_log_setcontext(log_);
+ dns_log_init(log_);
+ dns_log_setcontext(log_);
+ isc_log_settag(logconfig, "bigkey");
+
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, level,
+ &destination,
+ ISC_LOG_PRINTTAG | ISC_LOG_PRINTLEVEL);
+
+ CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL), "isc_log_"
+ "usechannel("
+ ")");
+ name = dns_fixedname_initname(&fname);
+ isc_buffer_constinit(&buf, "example.", strlen("example."));
+ isc_buffer_add(&buf, strlen("example."));
+ CHECK(dns_name_fromtext(name, &buf, dns_rootname, 0, NULL), "dns_name_"
+ "fromtext("
+ "\"example."
+ "\")");
+
+ CHECK(dst_key_buildinternal(name, DNS_KEYALG_RSASHA256, bits,
+ DNS_KEYOWNER_ZONE, DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in, pkey, mctx, &key),
+ "dst_key_buildinternal(...)");
+
+ CHECK(dst_key_tofile(key, DST_TYPE_PRIVATE | DST_TYPE_PUBLIC, NULL),
+ "dst_key_tofile()");
+ isc_buffer_init(&buf, filename, sizeof(filename) - 1);
+ isc_buffer_clear(&buf);
+ CHECK(dst_key_buildfilename(key, 0, NULL, &buf), "dst_key_"
+ "buildfilename()");
+ printf("%s\n", filename);
+ dst_key_free(&key);
+
+ isc_log_destroy(&log_);
+ isc_log_setcontext(NULL);
+ dns_log_setcontext(NULL);
+ dst_lib_destroy();
+ isc_mem_destroy(&mctx);
+ return (0);
+}
+
+/*! \file */
diff --git a/bin/tests/system/rsabigexponent/clean.sh b/bin/tests/system/rsabigexponent/clean.sh
new file mode 100644
index 0000000..22ea41a
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f K* */K* */dsset-*. */*.signed */trusted.conf */tmp*
+rm -f ns*/dsset-example
+rm -f ns*/named.run
+rm -f ns*/named.memstats
+rm -f ns1/root.db
+rm -f ns2/signer.err
+rm -f dig.out.*
+rm -f ns*/named.lock
+rm -f ns*/named.conf
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/rsabigexponent/conf/bad01.conf b/bin/tests/system/rsabigexponent/conf/bad01.conf
new file mode 100644
index 0000000..720d197
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/bad01.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ max-rsa-exponent-size 1;
+};
diff --git a/bin/tests/system/rsabigexponent/conf/bad02.conf b/bin/tests/system/rsabigexponent/conf/bad02.conf
new file mode 100644
index 0000000..bd1e827
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/bad02.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ max-rsa-exponent-size 34;
+};
diff --git a/bin/tests/system/rsabigexponent/conf/bad03.conf b/bin/tests/system/rsabigexponent/conf/bad03.conf
new file mode 100644
index 0000000..4331b52
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/bad03.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ max-rsa-exponent-size 4097;
+};
diff --git a/bin/tests/system/rsabigexponent/conf/good01.conf b/bin/tests/system/rsabigexponent/conf/good01.conf
new file mode 100644
index 0000000..1d2cd01
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/good01.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ max-rsa-exponent-size 0;
+};
diff --git a/bin/tests/system/rsabigexponent/conf/good02.conf b/bin/tests/system/rsabigexponent/conf/good02.conf
new file mode 100644
index 0000000..861e054
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/good02.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ max-rsa-exponent-size 35;
+};
diff --git a/bin/tests/system/rsabigexponent/conf/good03.conf b/bin/tests/system/rsabigexponent/conf/good03.conf
new file mode 100644
index 0000000..14a98f8
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/conf/good03.conf
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ max-rsa-exponent-size 4096;
+};
diff --git a/bin/tests/system/rsabigexponent/ns1/named.conf.in b/bin/tests/system/rsabigexponent/ns1/named.conf.in
new file mode 100644
index 0000000..4a9822d
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns1/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/rsabigexponent/ns1/root.db.in b/bin/tests/system/rsabigexponent/ns1/root.db.in
new file mode 100644
index 0000000..a85d814
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns1/root.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2012050600 ; serial
+ 3600 ; refresh
+ 1200 ; retry
+ 604800 ; expire
+ 60 ; minimum
+ )
+@ NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+;
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/rsabigexponent/ns1/sign.sh b/bin/tests/system/rsabigexponent/ns1/sign.sh
new file mode 100755
index 0000000..8a2f6b9
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns1/sign.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+cp ../ns2/dsset-example.in dsset-example.
+
+keyname=$($KEYGEN -q -a RSASHA256 -b 2048 -n zone $zone)
+
+cat $infile $keyname.key > $zonefile
+
+$SIGNER -P -g -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a static key.
+keyfile_to_static_ds $keyname > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+cp trusted.conf ../ns3/trusted.conf
+
+cd ../ns2 && $SHELL -e ./sign.sh
diff --git a/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.key b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.key
new file mode 100644
index 0000000..60ff187
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.key
@@ -0,0 +1,5 @@
+; This is a key-signing key, keyid 51650, for example.
+; Created: 20220721024334 (Thu Jul 21 12:43:34 2022)
+; Publish: 20220721024334 (Thu Jul 21 12:43:34 2022)
+; Activate: 20220721024334 (Thu Jul 21 12:43:34 2022)
+example. IN DNSKEY 257 3 8 AwEAAeeXAGBcXxSNj5X/PWT8XDBk4U9OUkZ7YKQBf2IN3V6OZomt/s3F UWIh70Wot+z1Ld3Rfswq1DjCaWNRFOMhs+9j3Fhc46wMZ4pnsDW1nLHk 2TnQRdrbiuhLkQy5oNMjSRxu924XLw5ylsuqjxE7vXcCeKSFe674roSq wo39atWsTJMDz0FQGxlPucnXai0nHoCeC7+u1s+wLaGcpNSZlsab7Zny FD4HZ3HKUCJw/Jjr5CZjqal9KdmWSC1SINRtlAN6PX5VSiNEncnYMCdj iv+ZhRGn+aHh1BmEWomGbAm2Jjw5mrYMgDs9lJRc5Vtg0YXb9OkYvxNF V4QGw1oeF+M=
diff --git a/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.private b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.private
new file mode 100644
index 0000000..d38a0b3
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.private
@@ -0,0 +1,13 @@
+Private-key-format: v1.3
+Algorithm: 8 (RSASHA256)
+Modulus: 55cAYFxfFI2Plf89ZPxcMGThT05SRntgpAF/Yg3dXo5mia3+zcVRYiHvRai37PUt3dF+zCrUOMJpY1EU4yGz72PcWFzjrAxnimewNbWcseTZOdBF2tuK6EuRDLmg0yNJHG73bhcvDnKWy6qPETu9dwJ4pIV7rviuhKrCjf1q1axMkwPPQVAbGU+5yddqLScegJ4Lv67Wz7AtoZyk1JmWxpvtmfIUPgdnccpQInD8mOvkJmOpqX0p2ZZILVIg1G2UA3o9flVKI0SdydgwJ2OK/5mFEaf5oeHUGYRaiYZsCbYmPDmatgyAOz2UlFzlW2DRhdv06Ri/E0VXhAbDWh4X4w==
+PublicExponent: AQAB
+PrivateExponent: QaMgBa+YeRxIElS1g14tCMBGxXHmyrgkI0eTYWiZkbedYy8v1QU0NDJ2/NC9VEkHF2PNYrNO08lyEiaEW32NYG92n4qwMm6PmAAcRpSzFQ5N7N9VNRrdK0pjkW45IS5Shd8DfK3QdfFPQOkVxGYgpE7Mf6Cfde9gkxRMsO6erXEud6KyBm8kwBR/ipDeUQvpyGkZEQPjLxJG6REjMVhPKTzCV+82DWEf+Ok/3Uxa94+ocAbySHAV3j4YcWpVGWT002gc6CGk8c6TsPYnDkfKQ3moPQZijH7F8zrARtoobCX9TsMFhBqReceZrbzN7en2cZGR5MSISzoTNSr4rGo6aQ==
+Prime1: 8AV9EllWtclD62XHo95Z3h7JJ9t2gY7fUFG0WMbkI0Wj6kcr7k3bFfLj7GEJ1qgVW4Qpu7XnBvPB9hnqoCkbHLzc8ws1D2tY+PsXzvw9IxoXNM/eCobeulu/rYhJl2PcpY9bPcaaR0hldGoCHdFYSo8oi+C5hfRtIMVjnDtHSmk=
+Prime2: 9wHRxgyHjtl8ro9HAkvujxFkhChm4xLxIRM8pfZ+D1VHpzFRD3/RK8CVYVRB8GsQoFRygHBMOW1oHqynN9jddvJrQbHOqFZAbQQlesp0jRPd9Mm6q0cDwYcD4apscB2CUrUswMzoD3H4saIjGnitCsG/t+sLTvuK/giuMdS2Tms=
+Exponent1: pnSH+pOuiL+dtMCPJVvsoxhilJukodD9mewv0GmOic+gD7dwBgJEcAJUgvgBJLbIqQENGDrcj3u5Bf2PM6eOP+3SpVMeZyUhPPqV1lwj4hYUBfIqoM5L5J4AXk5oCu+cc8zpj/wNvmW8xnFGKnumaX7Ctc8Rmo6ap+F8ZTrPBBE=
+Exponent2: txXZKIRnAkJAwZ6f0pr3w4Hv0GmmAZArvQlmPdncDH94sfvDCssB/v0rfE4Y5hxl4YFWsc8LINHwiDQPajzLwvvi9nnWJT5xWJznLwHbrCparbPNMmFb7lmmTeGlqOCmlamG942qQLCI1xnIDTn/gWalNaz539xhZPSIMZVqX+s=
+Coefficient: eK9cQKFRLaU4udqB8t8KSQxlNl0x9J+9bcaEzn0+579LrZUZvspfiR4DNGwr9qK+PWk+CU7/6xsWbq2zbKIEWucoR97t+E8Zhx00GCDbiu/QI2wviEcYbB2udznRv1WSIDoCWf2TXeh5G2E2ugt5F4+b56qMXmT7IudxYGPtQCY=
+Created: 20220721024334
+Publish: 20220721024334
+Activate: 20220721024334
diff --git a/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.key b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.key
new file mode 100644
index 0000000..a1f14c9
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.key
@@ -0,0 +1,2 @@
+; This is a zone-signing key, keyid 52810, for example.
+example. IN DNSKEY 256 3 8 BwEAAAAAAAHYYy161+wCg6yFHRlyex8oVkcK+K2SBUryI1+DEKzjusH6 yLfzzlJCPGrubmD+jseKYwXfzelJkRQbMDjWbMYLHKytuPtwnJMSeVh+ a/Ore6oVPXy716EYpsEBSmVjfQyS0mGHpwrYk4QaKjJDM7Q173EFl/sE eXjHqInlzOgJbXqsCrSfA94anSt42DGhJeeIfQ8b3vqD/nCnA6C7khIt AWlfJto7d42Ev8tckjr3CrTW9tn9pHb2DKeh85rKeJBBLMYQU3jfF5KH EEsjztLGMnPLlXTteh8wKrk/0IJrot17w0FR0H2v8oG3xDXxfhJ0OeTW 7dtBHD6ISgqeJ9zt
diff --git a/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.private b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.private
new file mode 100644
index 0000000..bbb5ad9
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.3
+Algorithm: 8 (RSASHA256)
+Modulus: 2GMtetfsAoOshR0ZcnsfKFZHCvitkgVK8iNfgxCs47rB+si3885SQjxq7m5g/o7HimMF383pSZEUGzA41mzGCxysrbj7cJyTEnlYfmvzq3uqFT18u9ehGKbBAUplY30MktJhh6cK2JOEGioyQzO0Ne9xBZf7BHl4x6iJ5czoCW16rAq0nwPeGp0reNgxoSXniH0PG976g/5wpwOgu5ISLQFpXybaO3eNhL/LXJI69wq01vbZ/aR29gynofOayniQQSzGEFN43xeShxBLI87SxjJzy5V07XofMCq5P9CCa6Lde8NBUdB9r/KBt8Q18X4SdDnk1u3bQRw+iEoKnifc7Q==
+PublicExponent: AQAAAAAAAQ==
+PrivateExponent: aD+JLNdCtAk1++UwcGdPslSoWq2szZHGrY+I+YfhfcBZrPP13exC40hgUgRNuYJOaJ3WMpgsKI4p8YDVNttF6LI7WNBURQhmBSwquB5BWWkoh7uR4PfKWGB0ZkDwUQcA2IdMVS4+QAKVQMmUXGnXhQI1p8duAORZp0gE71VsHTEzwf5AIEG2+f/oCjDsMJN0J7X3qktJr5ho64aMHyHf5+yKk6fFcy7wfC175SkIZ53uBfpCsFXkgq8YukXfcyoG5o4FUHheGnDwkVOzviEUHk8xweJnNNRbV6n/ck9AXzq3VSA9BbrXtRzZmre/L6tJvEnbH0EycwDkxCMlOSqGbQ==
+Prime1: /hnW5M2vzAoAjx2wum98YZZ6gv1IpV88c4HDLA3vY79Qxd8FYanldxPNjgQJEPjHD5hG6tGN+cjZdXv/X+sk5j3fmCB7RKwMKcoD8A/jyH2JaQLTbXm6EBd1BCMIN+w3W+A2E6evYYyINLwMUwqRlUcAaD8HoDLK8iz6iAUhFss=
+Prime2: 2gEuuug1PDnbWWFVzzMUrVXiRiFqJVTTvR3AjJVJNZPwAL4FMenh98rtI3s1zSB6P4RSyvRJ6YMOAT0ZrMxviJy76EExGgCB5F4w7g67I7VGPuA1tLn5kt5j9j5wQmdq1yMG5QpCJWr7bxjSDYvIzy2sZjZ/KTuHGtUzFUnHrCc=
+Exponent1: MaDlpmDYxZ2QvM+cp58Bj160u+21qIA/UZ2ysh6102uQmYHm92481z2+AvCJuq2PpkuROMd/4i2w7L0RbfZ2MYzUFndLZ8NgmNDjNDfUzeRQl2KQdAOLK4DNXmf3mKwLO0Sbj/pxgj0vYAe9gcU4Pe8ukVuSX0nkehbDi4cjfr0=
+Exponent2: cNHFlVCwvEPNVnpQCZS3iqF/D3HN8FtP2st0CrYbjQI8DYpcQUWVMqUqdqFOkYM0/qadpkX+JMlPJTjJZ8YDYYWIZGSC2ruMPIxB7DayVDBbgugmsC1isZjyApdQ44xtdNVyMYmcYeHUz5gR1x/eWdGNyjzMEvfbEjXIKbRykAM=
+Coefficient: ovH/7MP64Dai8draXD3t+jl6UTchig+LDwXA2GvlZY0HVP+9yvE49VSKhoYxolL/ZmabIgzzOAyJ66SyYq31ozxbpKrBGiFdzAbgkJgFIbdYMgfLHXNkH1vissGeY0KdS5ee6sKDfk1VmE94UOVHi11oslvnTiG2RF/I3koYV7Q=
diff --git a/bin/tests/system/rsabigexponent/ns2/dsset-example.in b/bin/tests/system/rsabigexponent/ns2/dsset-example.in
new file mode 100644
index 0000000..9ad254b
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/dsset-example.in
@@ -0,0 +1 @@
+example. IN DS 51650 8 2 F225122667540159A30620B2D0888036BDF76276D245DE3453C883F0C3276705
diff --git a/bin/tests/system/rsabigexponent/ns2/example.db.bad b/bin/tests/system/rsabigexponent/ns2/example.db.bad
new file mode 100644
index 0000000..b105978
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/example.db.bad
@@ -0,0 +1,156 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+example. 300 IN SOA mname1. . (
+ 2012050601 ; serial
+ 3600 ; refresh (1 hour)
+ 600 ; retry (10 minutes)
+ 604800 ; expire (1 week)
+ 3600 ; minimum (1 hour)
+ )
+ 300 RRSIG SOA 8 1 300 (
+ 20361231235959 20000101000000 52810 example.
+ IfZrUTjdr4Ull5MSQW4eHxrub6X5O8VWB3vG
+ kg6TBT8f2Aw4hLcwT0X47xRqL9nU1kKA3qpu
+ mi71wqiZPbYI+suHYGuqRO/V6YujdQRpLhGS
+ gTpLmETa46unkMDY6sze41AlCyzR79yaDxVS
+ +pS2V1AVYzQzzeswJXHwSLO5HKtClPL3izpV
+ AJD1+dL0UZRs9yOqbxU1RgvASPFEt+1Wd2p6
+ qwyeadJ7PB0PL7QQXSDsQ09Ms1BGoKq5p6Os
+ HtgXPo+aZQR2gczm3Yals9I1tZnk/ZM86aS0
+ 63NrEEUQycMNCr100WgWzYQzO90SmJMqpdeZ
+ fxzlRQbY7jN4qRbM7A== )
+ 300 NS ns2.example.
+ 300 RRSIG NS 8 1 300 (
+ 20361231235959 20000101000000 52810 example.
+ VUPhDucH6rlx93V13b7OSAQ6fE/9jlxhCTXv
+ peBD69WOa4jZHMZf60gqy10gLVMx35gZdEaU
+ cJqaBcAniSwPY3a7mxclMja7fmuCB9wcSbiP
+ pwk5KIYSgIvoWp3ro2I19C0IDQDVWtH1xqdQ
+ Dv+3MV39Zpf0AnXB05mBopI2DQI9mYHCnmis
+ F3pfcfs+h/ipyodE5kccBBRvtfKWHly342Xe
+ azHKM4eyuGj9NLwuwsoVgnyQ3I9hrKVAiUjS
+ fQ4cxyBVhh+Wb1/VrVSbX+X9VNzQ04mcREHS
+ yXIPoIQBNju3dyOSTQ+VIeasRvRU8nqMS/1f
+ oeqj5ehTjtfejF6Jfw== )
+ 300 NSEC a.example. NS SOA RRSIG NSEC DNSKEY
+ 300 RRSIG NSEC 8 1 300 (
+ 20361231235959 20000101000000 52810 example.
+ bG90DOCaN7BhihvtCUs2eJhSHkRaV582ROQi
+ AbamawevX8NQGJeVpHb3t5ekQuK5EWjLFr6i
+ bga5TpeP8HOv3lDb8w7kb7xOrHycw5Sizws5
+ PZTvtuty9nT6dZ9h4pfLNTbW+SBV904xv3JT
+ ZlXoxtm4JAdmKUcGiCFLjMvwbQ5SKEZq27uN
+ 9xCeY0CPkQmiGbTrySYFyNZsBBsL2OI5ec2V
+ TbQVSDhnnEhbVdMb8Yh2sTt9H/CT1yG2s4U9
+ a9ccxguFzt6mk+f5ZL+WKgxkTOMOrZW3dyiI
+ x53dNQyZN/tczibox/LLG/SaET5wR/V5gDsh
+ 9DObfc9u1+of/H0lhg== )
+ 300 DNSKEY 257 3 8 (
+ AwEAAeeXAGBcXxSNj5X/PWT8XDBk4U9OUkZ7
+ YKQBf2IN3V6OZomt/s3FUWIh70Wot+z1Ld3R
+ fswq1DjCaWNRFOMhs+9j3Fhc46wMZ4pnsDW1
+ nLHk2TnQRdrbiuhLkQy5oNMjSRxu924XLw5y
+ lsuqjxE7vXcCeKSFe674roSqwo39atWsTJMD
+ z0FQGxlPucnXai0nHoCeC7+u1s+wLaGcpNSZ
+ lsab7ZnyFD4HZ3HKUCJw/Jjr5CZjqal9KdmW
+ SC1SINRtlAN6PX5VSiNEncnYMCdjiv+ZhRGn
+ +aHh1BmEWomGbAm2Jjw5mrYMgDs9lJRc5Vtg
+ 0YXb9OkYvxNFV4QGw1oeF+M=
+ ) ; KSK; alg = RSASHA256 ; key id = 51650
+ 300 DNSKEY 256 3 8 (
+ BwEAAAAAAAHYYy161+wCg6yFHRlyex8oVkcK
+ +K2SBUryI1+DEKzjusH6yLfzzlJCPGrubmD+
+ jseKYwXfzelJkRQbMDjWbMYLHKytuPtwnJMS
+ eVh+a/Ore6oVPXy716EYpsEBSmVjfQyS0mGH
+ pwrYk4QaKjJDM7Q173EFl/sEeXjHqInlzOgJ
+ bXqsCrSfA94anSt42DGhJeeIfQ8b3vqD/nCn
+ A6C7khItAWlfJto7d42Ev8tckjr3CrTW9tn9
+ pHb2DKeh85rKeJBBLMYQU3jfF5KHEEsjztLG
+ MnPLlXTteh8wKrk/0IJrot17w0FR0H2v8oG3
+ xDXxfhJ0OeTW7dtBHD6ISgqeJ9zt
+ ) ; ZSK; alg = RSASHA256 ; key id = 52810
+ 300 RRSIG DNSKEY 8 1 300 (
+ 20361231235959 20000101000000 52810 example.
+ O4q1oueEgPoWHhrLiobGvMQLS2KHN+xxSddf
+ y6fqksqivRLgj0633fnEZrFtc44YueV+L4gQ
+ kaoWCCpR0yQH4BOw4p3FVjEgl+jXLzIc7amw
+ ZfKAnSOtMoTaBCQ2hN8b2ducUHgKV7ta9bca
+ lO0wuqqp2OOO/n9S3YMBVfrCW4jL2w1QPC+b
+ lm/4ka8OwqKKGAcO0d/nGeOPJZnfbddSzqEQ
+ C3j1tGavwBC4RAGilxw3XoyoICDp0LQR7M9a
+ tWAxYmMfilEEfpip9R3HhCa+ynIVsHP8yTXE
+ dlWM3LUZePm44aV38YeObJpRMkb8sO5VrbZn
+ 8hJoIs3eyguC4HKKTg== )
+ 300 RRSIG DNSKEY 8 1 300 (
+ 20361231235959 20000101000000 51650 example.
+ Eaw79mOoImGg+ymMJ+9paoanUgR/Od0Pxv/X
+ mevid1TRbssSc2KynAToxSXRcOQwRQjto9sC
+ qj0pOekPPmW1I6DRlMOGDS6l0Uuk51GvUuRD
+ Xbr19BG73mcPuKfYHNbx6cUHvBlPilnjM803
+ m9E8DK6Ba9uo/MNhgtWoWj8wQxqP2YS+HW3v
+ bOv/p4en9Dc5ft6ATtSYj84ejuPAKnfVbleI
+ fJW+qIQ7q9A24xEZ4QlWuRovjsoASVsuLnX+
+ X4sQYlWBIPMQYQ8RIN1CgSRPGb603pAq9ru6
+ ySpjlxHQRtdOGBNJleg9Wz612rHRd3x7BM+8
+ /Lvz31Ot/JSh3u4DSQ== )
+a.example. 300 IN A 10.0.0.1
+ 300 RRSIG A 8 2 300 (
+ 20361231235959 20000101000000 52810 example.
+ zp4L0Um0guehtT+4GQaMeYx5PiwEbSRyi7sg
+ Xv2uFn/wFML/Df0PgCxCYkWKL2Db/j15IZON
+ uz2CNRG7lDMZsb+JgyLZ6R3OuSKjwzA++kUu
+ 8ExPpdrFHxZFMPefkU1vjf7E1yt4/aSaO23T
+ m0F6yFHcVfBE1DElG1vLWO6cWtSIMKjXOo15
+ Zy2hHhT/7jKhqcHnwwCBHLuV9/e9OmI34H7I
+ Sd3Ik8dnNEjRTVbLem3tQMfQ9ZfYDHPHli+z
+ Z5dGgPmpyNPq5bfs7O5uCO5cNCbouFdEnc6O
+ DA9QiyOGba8w7vI1gHMvA+rWPpA+fTGgrVRq
+ 7bTfa0jTOsybR8rZjg== )
+ 300 NSEC ns2.example. A RRSIG NSEC
+ 300 RRSIG NSEC 8 2 300 (
+ 20361231235959 20000101000000 52810 example.
+ oh6oqdC9OIoO0jIN0x9MIBlYlzAg2LFYffrP
+ QlgPAtPn8A9cPCxU2i6hJ1ubqc6o1LVD7LH6
+ GVj842Ytys1uO2Nwf9xXS4gbchJ6NE9IjQh6
+ IoBNmlgdfprzJEJlEFx73dytakfcjc+hIj8t
+ b14Lu2/5BBDSamw+uVyeV8Wg2jNdrN7UEqyA
+ ccnhLPWHAOtspzxrmCrBDPc6Geelu8KzARs5
+ qOZ/p9CKffmKL/65K/N8WWKQWVNI22tAbiWT
+ J1t3BNkOLUSKMvEVLFcgStV4QtFcQrSB96Hu
+ D2rSbAGsH5Ujmz4GTxhOSqd8OJ7XDEWlhZod
+ LhUBltfjmakorhGqqg== )
+ns2.example. 300 IN A 10.53.0.2
+ 300 RRSIG A 8 2 300 (
+ 20361231235959 20000101000000 52810 example.
+ sDlETJwDoWqYZdcwYBW/l+Ot4Tb3mSXJvW3R
+ 1fsoiq/obWZeC+bU2MszckcZKPET2CRqBD+c
+ uLCcOhZrcH0m25Y02SAzOOG2V12KNvWVznSz
+ bZw+/+ucYhxhiNKherdwpHOAdjlhG//zFHDy
+ sAxmrtjWO2DT9pv1Hd/Hm3aGgAYTs0ryyeyo
+ k05sTgdr43APFkX4SNoNXGUEt8E0uMghIvhi
+ mgKSQ45fZFsZeUiEfwvtQ8uAuDNOLWK49Bw5
+ 184QrQ/NZ3YVyJercg7wm/jFMVkgxggiOl2q
+ ZCLadaSQNnsvtbwgyTktRJb5YovzZEQrH7O0
+ vW/DAN1Cqa1nXw/kZA== )
+ 300 NSEC example. A RRSIG NSEC
+ 300 RRSIG NSEC 8 2 300 (
+ 20361231235959 20000101000000 52810 example.
+ DyLuymW3Bv6irCLzfUGnz2cy1XctqfW7ycLc
+ 7wgDzDLNvJ6tqr8tjHKMdCODJDiG+lR5oFo7
+ 8RA604OYcmJjLIAMj3fCxzBkIlH5SXRcJ86X
+ a8U6oXrgt6IvUMC2crdWMVgVnSWlqBS4TNNg
+ QhUa+vt+Em8ce3fveqh1tXm1hzysSroOQtMk
+ HOPAtwYR9XP4mTdbC43AU/67jsYPqXq59lm4
+ sE1tmnVdhXuOk7yNAt8O2CSZGGZl5bYMC4On
+ IgWZP7liebXAmhmXpHbBf5/BaE9dVfvWzYTT
+ 4wUch+f8TDwwyTqumrlrPsVnvkQ9V0LwODox
+ PxWWxFAznmUMEtlo3g== )
diff --git a/bin/tests/system/rsabigexponent/ns2/example.db.in b/bin/tests/system/rsabigexponent/ns2/example.db.in
new file mode 100644
index 0000000..a2a6964
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/example.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2012050601 ; serial
+ 3600 ; refresh
+ 600 ; retry
+ 604800 ; expire
+ 3600 ; minimum
+ )
+ NS ns2
+ns2 A 10.53.0.2
+
+a A 10.0.0.1
diff --git a/bin/tests/system/rsabigexponent/ns2/named.conf.in b/bin/tests/system/rsabigexponent/ns2/named.conf.in
new file mode 100644
index 0000000..c81b3f6
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db.bad";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/rsabigexponent/ns2/sign.sh b/bin/tests/system/rsabigexponent/ns2/sign.sh
new file mode 100755
index 0000000..53e2257
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns2/sign.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=example.
+infile=example.db.in
+outfile=example.db.bad
+
+for i in Xexample.+008+51650.key Xexample.+008+51650.private \
+ Xexample.+008+52810.key Xexample.+008+52810.private
+do
+ cp $i $(echo $i | sed s/X/K/)
+done
+
+$SIGNER -g -s 20000101000000 -e 20361231235959 -o $zone \
+ $infile Kexample.+008+52810.key \
+ > /dev/null 2> signer.err || true
diff --git a/bin/tests/system/rsabigexponent/ns3/named.conf.in b/bin/tests/system/rsabigexponent/ns3/named.conf.in
new file mode 100644
index 0000000..bc63656
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/ns3/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ notify yes;
+ dnssec-validation yes;
+ max-rsa-exponent-size 35;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/rsabigexponent/setup.sh b/bin/tests/system/rsabigexponent/setup.sh
new file mode 100644
index 0000000..b7c2801
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+
+cd ns1 && $SHELL -e sign.sh
diff --git a/bin/tests/system/rsabigexponent/tests.sh b/bin/tests/system/rsabigexponent/tests.sh
new file mode 100644
index 0000000..39ebd8a
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/tests.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+
+for f in conf/good*.conf
+do
+ echo_i "checking '$f'"
+ ret=0
+ $CHECKCONF $f > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+for f in conf/bad*.conf
+do
+ echo_i "checking '$f'"
+ ret=0
+ $CHECKCONF $f > /dev/null && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+echo_i "checking that RSA big exponent keys can't be loaded"
+ret=0
+grep "out of range" ns2/signer.err > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking that RSA big exponent signature can't validate"
+ret=0
+$DIG $DIGOPTS a.example @10.53.0.2 > dig.out.ns2 || ret=1
+$DIG $DIGOPTS a.example @10.53.0.3 > dig.out.ns3 || ret=1
+grep "status: NOERROR" dig.out.ns2 > /dev/null || ret=1
+grep "status: SERVFAIL" dig.out.ns3 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/rsabigexponent/tests_sh_rsabigexponent.py b/bin/tests/system/rsabigexponent/tests_sh_rsabigexponent.py
new file mode 100644
index 0000000..38ab381
--- /dev/null
+++ b/bin/tests/system/rsabigexponent/tests_sh_rsabigexponent.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_rsabigexponent(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/run.gdb b/bin/tests/system/run.gdb
new file mode 100644
index 0000000..60981e1
--- /dev/null
+++ b/bin/tests/system/run.gdb
@@ -0,0 +1 @@
+thread apply all bt full
diff --git a/bin/tests/system/run.sh b/bin/tests/system/run.sh
new file mode 100755
index 0000000..8e87c0f
--- /dev/null
+++ b/bin/tests/system/run.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Run a single system test using the pytest runner. This is a simple wrapper
+# around pytest for convenience.
+#
+
+if [ -z "$1" ] || [ ! -d "$1" ]; then
+ echo "Usage: $0 system_test_dir [pytest_args]"
+ exit 2
+fi
+
+system_test_dir="$1"
+shift
+
+(cd "$system_test_dir" || exit 2 ; /usr/bin/env python3 -m pytest "$@")
diff --git a/bin/tests/system/runall.sh b/bin/tests/system/runall.sh
new file mode 100755
index 0000000..bbd072e
--- /dev/null
+++ b/bin/tests/system/runall.sh
@@ -0,0 +1,99 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Run all the system tests.
+#
+# Usage:
+# runall.sh [-c] [-n] [numprocesses]
+#
+# -c Force colored output.
+#
+# -n Noclean. Keep all output files produced by all tests. These
+# can later be removed by running "cleanall.sh".
+#
+# numprocess Number of concurrent processes to use when running the tests.
+# The default is one, which causes the tests to run sequentially.
+
+. ./conf.sh
+
+usage="Usage: ./runall.sh [-c] [-n] [numprocesses]"
+
+# Preserve values of environment variables which are already set.
+
+SYSTEMTEST_FORCE_COLOR=${SYSTEMTEST_FORCE_COLOR:-0}
+SYSTEMTEST_NO_CLEAN=${SYSTEMTEST_NO_CLEAN:-0}
+
+# Handle command line switches if present.
+
+while getopts "cn-" flag; do
+ case "$flag" in
+ c) SYSTEMTEST_FORCE_COLOR=1 ;;
+ n) SYSTEMTEST_NO_CLEAN=1 ;;
+ -) break;;
+ *) exit 1;;
+ esac
+done
+export NOCLEAN
+shift $((OPTIND-1))
+
+# Obtain number of processes to use.
+
+if [ $# -eq 0 ]; then
+ numproc=1
+elif [ $# -eq 1 ]; then
+ if [ "$1" -ne "$1" ] 2>&1; then
+ # Value passed is not numeric
+ echo "$usage" >&2
+ exit 1
+ fi
+ numproc=$1
+else
+ echo "$usage" >&2
+ exit 1
+fi
+
+# Run the tests.
+
+export SYSTEMTEST_FORCE_COLOR
+export SYSTEMTEST_NO_CLEAN
+
+status=0
+
+if [ "$NOPARALLEL" = "" ]; then
+ # use "make" to run tests in parallel.
+ make -j "$numproc" check
+ status=$?
+else
+ # the NOPARALLEL environment variable indicates that tests must be
+ # run sequentially.
+ $PERL testsock.pl || {
+ cat <<-EOF
+ I:NOTE: System tests were skipped because they require the
+ I: test IP addresses 10.53.0.* to be configured as alias
+ I: addresses on the loopback interface. Please run
+ I: "bin/tests/system/ifconfig.sh up" as root to configure them.
+ EOF
+ exit 1
+ }
+ (
+ status=0
+ for testdir in $SUBDIRS; do
+ $SHELL legacy.run.sh -r "$testdir" || status=1
+ done
+ echo "$status" > systests.status
+ ) 2>&1 | tee "systests.output"
+ read -r status < systests.status
+ rm systests.status
+fi
+
+exit "$status"
diff --git a/bin/tests/system/runsequential.sh b/bin/tests/system/runsequential.sh
new file mode 100755
index 0000000..953bff0
--- /dev/null
+++ b/bin/tests/system/runsequential.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Run system tests that must be run sequentially
+#
+# Note: Use "make check" (or runall.sh) to run all the system tests. This
+# script will just run those tests that require that each of their nameservers
+# is the only one running on an IP address.
+#
+
+. ./conf.sh
+
+for d in $SEQUENTIALDIRS
+do
+ $SHELL legacy.run.sh "${@}" "$d" 2>&1 | tee "test.output.$d"
+done
diff --git a/bin/tests/system/runtime/README b/bin/tests/system/runtime/README
new file mode 100644
index 0000000..9272f12
--- /dev/null
+++ b/bin/tests/system/runtime/README
@@ -0,0 +1,13 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+Tests of runtime checks, e.g., that named prevents duplicate processes
+from running.
diff --git a/bin/tests/system/runtime/clean.sh b/bin/tests/system/runtime/clean.sh
new file mode 100644
index 0000000..39fdc0c
--- /dev/null
+++ b/bin/tests/system/runtime/clean.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+[ -d ns2/nope ] && chmod 755 ns2/nope
+
+rm -f *.pid
+rm -f */named*.run
+rm -f */named.memstats
+rm -f kill*.out
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.lock ns*/named*.pid ns*/other.lock
+rm -f ns2/named.conf ns2/named-alt*.conf
+rm -f rndc.out*
+rm -rf ns2/nope
+rm -rf ns2/tmp.*
diff --git a/bin/tests/system/runtime/ctrl-chars b/bin/tests/system/runtime/ctrl-chars
new file mode 100644
index 0000000..4ce1650
--- /dev/null
+++ b/bin/tests/system/runtime/ctrl-chars
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/bin/tests/system/runtime/long-cmd-line b/bin/tests/system/runtime/long-cmd-line
new file mode 100644
index 0000000..e691a71
--- /dev/null
+++ b/bin/tests/system/runtime/long-cmd-line
@@ -0,0 +1 @@
+-m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage
diff --git a/bin/tests/system/runtime/ns2/named-alt1.conf.in b/bin/tests/system/runtime/ns2/named-alt1.conf.in
new file mode 100644
index 0000000..4efb3d7
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt1.conf.in
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt2.conf.in b/bin/tests/system/runtime/ns2/named-alt2.conf.in
new file mode 100644
index 0000000..ab374f8
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt2.conf.in
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt3.conf.in b/bin/tests/system/runtime/ns2/named-alt3.conf.in
new file mode 100644
index 0000000..0f351aa
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt3.conf.in
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ port @PORT@;
+ pid-file "named-alt3.pid";
+ lock-file none;
+ listen-on { 10.53.0.2; 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt4.conf.in b/bin/tests/system/runtime/ns2/named-alt4.conf.in
new file mode 100644
index 0000000..4c0312a
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt4.conf.in
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory "./nope";
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt5.conf.in b/bin/tests/system/runtime/ns2/named-alt5.conf.in
new file mode 100644
index 0000000..71b7e09
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt5.conf.in
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ managed-keys-directory "./nope";
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt6.conf.in b/bin/tests/system/runtime/ns2/named-alt6.conf.in
new file mode 100644
index 0000000..fb79924
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt6.conf.in
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ new-zones-directory "./nope";
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt7.conf.in b/bin/tests/system/runtime/ns2/named-alt7.conf.in
new file mode 100644
index 0000000..722316f
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt7.conf.in
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt9.conf.in b/bin/tests/system/runtime/ns2/named-alt9.conf.in
new file mode 100644
index 0000000..f0ebcd3
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt9.conf.in
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named9.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
diff --git a/bin/tests/system/runtime/ns2/named1.conf.in b/bin/tests/system/runtime/ns2/named1.conf.in
new file mode 100644
index 0000000..d8b3148
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named1.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/runtime/setup.sh b/bin/tests/system/runtime/setup.sh
new file mode 100644
index 0000000..f6747ce
--- /dev/null
+++ b/bin/tests/system/runtime/setup.sh
@@ -0,0 +1,29 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns2/named1.conf.in ns2/named.conf
+
+copy_setports ns2/named-alt1.conf.in ns2/named-alt1.conf
+copy_setports ns2/named-alt2.conf.in ns2/named-alt2.conf
+copy_setports ns2/named-alt3.conf.in ns2/named-alt3.conf
+copy_setports ns2/named-alt4.conf.in ns2/named-alt4.conf
+copy_setports ns2/named-alt5.conf.in ns2/named-alt5.conf
+copy_setports ns2/named-alt6.conf.in ns2/named-alt6.conf
+copy_setports ns2/named-alt7.conf.in ns2/named-alt7.conf
+
+mkdir ns2/nope
+chmod 555 ns2/nope
diff --git a/bin/tests/system/runtime/tests.sh b/bin/tests/system/runtime/tests.sh
new file mode 100644
index 0000000..6fd428e
--- /dev/null
+++ b/bin/tests/system/runtime/tests.sh
@@ -0,0 +1,252 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+NAMED_DEFAULT_ARGS="-m record -d 99 -g -U 4"
+
+kill_named() {
+ pidfile="${1}"
+ if [ ! -r "${pidfile}" ]; then
+ return 1
+ fi
+
+ pid=$(cat "${pidfile}" 2>/dev/null)
+ if [ "${pid:+set}" = "set" ]; then
+ kill -15 "${pid}" >/dev/null 2>&1
+ retries=10
+ while [ "$retries" -gt 0 ]; do
+ if ! kill -0 "${pid}" >/dev/null 2>&1; then
+ break
+ fi
+ sleep 1
+ retries=$((retries-1))
+ done
+ # Timed-out
+ if [ "$retries" -eq 0 ]; then
+ echo_i "failed to kill named ($pidfile)"
+ return 1
+ fi
+ fi
+ rm -f "${pidfile}"
+ return 0
+}
+
+check_named_log() {
+ grep "$@" >/dev/null 2>&1
+}
+
+run_named() (
+ dir="$1"
+ shift
+ run="$1"
+ shift
+ if cd "$dir" > /dev/null 2>&1
+ then
+ "${NAMED}" "$@" ${NAMED_DEFAULT_ARGS} >> "$run" 2>&1 &
+ echo $!
+ fi
+)
+
+check_pid() (
+ return $(! kill -0 "${1}" >/dev/null 2>&1)
+)
+
+status=0
+n=0
+
+n=$((n+1))
+echo_i "verifying that named started normally ($n)"
+ret=0
+[ -s ns2/named.pid ] || ret=1
+grep "unable to listen on any configured interface" ns2/named.run > /dev/null && ret=1
+grep "another named process" ns2/named.run > /dev/null && ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verifying that named checks for conflicting named processes ($n)"
+ret=0
+testpid=$(run_named ns2 named$n.run -c named-alt2.conf -D runtime-ns2-extra-2 -X named.lock)
+test -n "$testpid" || ret=1
+retry_quiet 10 check_named_log "another named process" ns2/named$n.run || ret=1
+test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1
+test -n "$testpid" && kill -15 $testpid > kill$n.out 2>&1 && ret=1
+test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verifying that 'lock-file none' disables process check ($n)"
+ret=0
+testpid=$(run_named ns2 named$n.run -c named-alt3.conf -D runtime-ns2-extra-3)
+test -n "$testpid" || ret=1
+retry_quiet 60 check_named_log "running$" ns2/named$n.run || ret=1
+grep "another named process" ns2/named$n.run > /dev/null && ret=1
+kill_named ns2/named-alt3.pid || ret=1
+test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that named refuses to reconfigure if working directory is not writable ($n)"
+ret=0
+copy_setports ns2/named-alt4.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reconfig > rndc.out.$n 2>&1 && ret=1
+grep "failed: permission denied" rndc.out.$n > /dev/null 2>&1 || ret=1
+sleep 1
+grep "[^-]directory './nope' is not writable" ns2/named.run > /dev/null 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that named refuses to reconfigure if managed-keys-directory is not writable ($n)"
+ret=0
+copy_setports ns2/named-alt5.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reconfig > rndc.out.$n 2>&1 && ret=1
+grep "failed: permission denied" rndc.out.$n > /dev/null 2>&1 || ret=1
+sleep 1
+grep "managed-keys-directory './nope' is not writable" ns2/named.run > /dev/null 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that named refuses to reconfigure if new-zones-directory is not writable ($n)"
+ret=0
+copy_setports ns2/named-alt6.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reconfig > rndc.out.$n 2>&1 && ret=1
+grep "failed: permission denied" rndc.out.$n > /dev/null 2>&1 || ret=1
+sleep 1
+grep "new-zones-directory './nope' is not writable" ns2/named.run > /dev/null 2>&1 || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that named recovers when configuration file is valid again ($n)"
+ret=0
+copy_setports ns2/named1.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reconfig > rndc.out.$n 2>&1 || ret=1
+[ -s ns2/named.pid ] || ret=1
+kill_named ns2/named.pid || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that named refuses to start if working directory is not writable ($n)"
+ret=0
+testpid=$(run_named ns2 named$n.run -c named-alt4.conf -D runtime-ns2-extra-4)
+test -n "$testpid" || ret=1
+retry_quiet 10 check_named_log "exiting (due to fatal error)" ns2/named$n.run || ret=1
+grep "[^-]directory './nope' is not writable" ns2/named$n.run > /dev/null 2>&1 || ret=1
+kill_named ns2/named.pid && ret=1
+test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that named refuses to start if managed-keys-directory is not writable ($n)"
+ret=0
+testpid=$(run_named ns2 named$n.run -c named-alt5.conf -D runtime-ns2-extra-5)
+test -n "$testpid" || ret=1
+retry_quiet 10 check_named_log "exiting (due to fatal error)" ns2/named$n.run || ret=1
+grep "managed-keys-directory './nope' is not writable" ns2/named$n.run > /dev/null 2>&1 || ret=1
+kill_named named.pid && ret=1
+test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that named refuses to start if new-zones-directory is not writable ($n)"
+ret=0
+testpid=$(run_named ns2 named$n.run -c named-alt6.conf -D runtime-ns2-extra-6)
+test -n "$testpid" || ret=1
+retry_quiet 10 check_named_log "exiting (due to fatal error)" ns2/named$n.run || ret=1
+grep "new-zones-directory './nope' is not writable" ns2/named$n.run > /dev/null 2>&1 || ret=1
+kill_named ns2/named.pid && ret=1
+test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that named logs control characters in octal notation ($n)"
+ret=0
+INSTANCE_NAME="runtime-ns2-extra-7-$(cat ctrl-chars)"
+testpid=$(run_named ns2 named$n.run -c named-alt7.conf -D "${INSTANCE_NAME}")
+test -n "$testpid" || ret=1
+retry_quiet 60 check_named_log "running$" ns2/named$n.run || ret=1
+grep 'running as.*\\177\\033' ns2/named$n.run > /dev/null || ret=1
+kill_named ns2/named.pid || ret=1
+test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that named escapes special characters in the logs ($n)"
+ret=0
+INSTANCE_NAME="runtime-ns2-extra-8-$;"
+testpid=$(run_named ns2 named$n.run -c named-alt7.conf -D "${INSTANCE_NAME}")
+test -n "$testpid" || ret=1
+retry_quiet 60 check_named_log "running$" ns2/named$n.run || ret=1
+grep 'running as.*\\$\\;' ns2/named$n.run > /dev/null || ret=1
+kill_named ns2/named.pid || ret=1
+test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that named logs an ellipsis when the command line is larger than 8k bytes ($n)"
+ret=0
+LONG_CMD_LINE=$(cat long-cmd-line)
+# shellcheck disable=SC2086
+testpid=$(run_named ns2 named$n.run $LONG_CMD_LINE -c "named-alt7.conf")
+test -n "$testpid" || ret=1
+retry_quiet 60 check_named_log "running$" ns2/named$n.run || ret=1
+grep "running as.*\.\.\.$" ns2/named$n.run > /dev/null || ret=1
+kill_named ns2/named.pid || ret=1
+test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verifying that named switches UID ($n)"
+if [ "$(id -u)" -eq 0 ]; then
+ ret=0
+ { TEMP_NAMED_DIR=$(mktemp -d "$(pwd)/ns2/tmp.XXXXXXXX"); rc=$?; } || true
+ if [ "$rc" -eq 0 ]; then
+ copy_setports ns2/named-alt9.conf.in "${TEMP_NAMED_DIR}/named-alt9.conf"
+ chown -R nobody: "${TEMP_NAMED_DIR}"
+ chmod 0700 "${TEMP_NAMED_DIR}"
+ testpid=$(run_named "${TEMP_NAMED_DIR}" "${TEMP_NAMED_DIR}/named$n.run" -u nobody -c named-alt9.conf)
+ test -n "$testpid" || ret=1
+ retry_quiet 60 check_named_log "running$" "${TEMP_NAMED_DIR}/named$n.run" || ret=1
+ [ -s "${TEMP_NAMED_DIR}/named9.pid" ] || ret=1
+ grep "loading configuration: permission denied" "${TEMP_NAMED_DIR}/named$n.run" > /dev/null && ret=1
+ kill_named "${TEMP_NAMED_DIR}/named9.pid" || ret=1
+ test -n "$testpid" || ret=1
+ test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1
+ else
+ echo_i "mktemp failed"
+ ret=1
+ fi
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+else
+ echo_i "skipped, not running as root or running on Windows"
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/runtime/tests_sh_runtime.py b/bin/tests/system/runtime/tests_sh_runtime.py
new file mode 100644
index 0000000..089690e
--- /dev/null
+++ b/bin/tests/system/runtime/tests_sh_runtime.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_runtime(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/send.pl b/bin/tests/system/send.pl
new file mode 100644
index 0000000..62b4f7a
--- /dev/null
+++ b/bin/tests/system/send.pl
@@ -0,0 +1,33 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Send a file to a given address and port using TCP. Used for
+# configuring the test server in ans.pl.
+#
+
+use IO::File;
+use IO::Socket;
+
+@ARGV == 2 or die "usage: send.pl host port [file ...]\n";
+
+my $host = shift @ARGV;
+my $port = shift @ARGV;
+
+my $sock = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port,
+ Proto => "tcp",) or die "$!";
+while (<>) {
+ $sock->syswrite($_, length $_);
+}
+
+$sock->close;
diff --git a/bin/tests/system/serve-stale/ans2/ans.pl b/bin/tests/system/serve-stale/ans2/ans.pl
new file mode 100644
index 0000000..3fdc1fc
--- /dev/null
+++ b/bin/tests/system/serve-stale/ans2/ans.pl
@@ -0,0 +1,331 @@
+#!/usr/bin/env perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use strict;
+use warnings;
+
+use IO::File;
+use IO::Socket;
+use Getopt::Long;
+use Net::DNS;
+use Time::HiRes qw(usleep nanosleep);
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+# If send_response is set, the server will respond, otherwise the query will
+# be dropped.
+my $send_response = 1;
+# If slow_response is set, a lookup for the CNAME target (target.example) is
+# delayed. Other lookups will not be delayed.
+my $slow_response = 0;
+
+my $localaddr = "10.53.0.2";
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "$localaddr",
+ LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!";
+
+#
+# Delegation
+#
+my $SOA = "example 300 IN SOA . . 0 0 0 0 300";
+my $NS = "example 300 IN NS ns.example";
+my $A = "ns.example 300 IN A $localaddr";
+
+#
+# Slow delegation
+#
+my $slowSOA = "slow 300 IN SOA . . 0 0 0 0 300";
+my $slowNS = "slow 300 IN NS ns.slow";
+my $slowA = "ns.slow 300 IN A $localaddr";
+my $slowTXT = "data.slow 2 IN TXT \"A slow text record with a 2 second ttl\"";
+my $slownegSOA = "slow 2 IN SOA . . 0 0 0 0 300";
+
+#
+# Records to be TTL stretched
+#
+my $TXT = "data.example 2 IN TXT \"A text record with a 2 second ttl\"";
+my $LONGTXT = "longttl.example 600 IN TXT \"A text record with a 600 second ttl\"";
+my $CAA = "othertype.example 2 IN CAA 0 issue \"ca1.example.net\"";
+my $negSOA = "example 2 IN SOA . . 0 0 0 0 300";
+my $CNAME = "cname.example 7 IN CNAME target.example";
+my $TARGET = "target.example 9 IN A $localaddr";
+my $SHORTCNAME = "shortttl.cname.example 1 IN CNAME longttl.target.example";
+my $LONGTARGET = "longttl.target.example 600 IN A $localaddr";
+
+sub reply_handler {
+ my ($qname, $qclass, $qtype) = @_;
+ my ($rcode, @ans, @auth, @add);
+
+ print ("request: $qname/$qtype\n");
+ STDOUT->flush();
+
+ # Control whether we send a response or not.
+ # We always respond to control commands.
+ if ($qname eq "enable" ) {
+ if ($qtype eq "TXT") {
+ $send_response = 1;
+ my $rr = new Net::DNS::RR("$qname 0 $qclass TXT \"$send_response\"");
+ push @ans, $rr;
+ }
+ $rcode = "NOERROR";
+ return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
+ } elsif ($qname eq "disable" ) {
+ if ($qtype eq "TXT") {
+ $send_response = 0;
+ my $rr = new Net::DNS::RR("$qname 0 $qclass TXT \"$send_response\"");
+ push @ans, $rr;
+ }
+ $rcode = "NOERROR";
+ return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
+ } elsif ($qname eq "slowdown" ) {
+ if ($qtype eq "TXT") {
+ $send_response = 1;
+ $slow_response = 1;
+ my $rr = new Net::DNS::RR("$qname 0 $qclass TXT \"$send_response\"");
+ push @ans, $rr;
+ }
+ $rcode = "NOERROR";
+ return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
+ }
+
+ # If we are not responding to queries we are done.
+ return if (!$send_response);
+
+ if (index($qname, "latency") == 0) {
+ # simulate network latency before answering
+ print " Sleeping 50 milliseconds\n";
+ select(undef, undef, undef, 0.05);
+ }
+
+ # Construct the response and send it.
+ if ($qname eq "ns.example" ) {
+ if ($qtype eq "A") {
+ my $rr = new Net::DNS::RR($A);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($SOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "example") {
+ if ($qtype eq "NS") {
+ my $rr = new Net::DNS::RR($NS);
+ push @auth, $rr;
+ $rr = new Net::DNS::RR($A);
+ push @add, $rr;
+ } elsif ($qtype eq "SOA") {
+ my $rr = new Net::DNS::RR($SOA);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($SOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "nodata.example") {
+ my $rr = new Net::DNS::RR($negSOA);
+ push @auth, $rr;
+ $rcode = "NOERROR";
+ } elsif ($qname eq "data.example") {
+ if ($qtype eq "TXT") {
+ my $rr = new Net::DNS::RR($TXT);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($negSOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "a-only.example") {
+ if ($qtype eq "A") {
+ my $rr = new Net::DNS::RR("a-only.example 2 IN A $localaddr");
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($negSOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "cname.example") {
+ if ($qtype eq "A") {
+ my $rr = new Net::DNS::RR($CNAME);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($negSOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "target.example") {
+ if ($slow_response) {
+ print " Sleeping 3 seconds\n";
+ sleep(3);
+ }
+ if ($qtype eq "A") {
+ my $rr = new Net::DNS::RR($TARGET);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($negSOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "shortttl.cname.example") {
+ if ($qtype eq "A") {
+ my $rr = new Net::DNS::RR($SHORTCNAME);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($negSOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "longttl.target.example") {
+ if ($slow_response) {
+ print " Sleeping 3 seconds\n";
+ sleep(3);
+ }
+ if ($qtype eq "A") {
+ my $rr = new Net::DNS::RR($LONGTARGET);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($negSOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "longttl.example") {
+ if ($qtype eq "TXT") {
+ my $rr = new Net::DNS::RR($LONGTXT);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($negSOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "nxdomain.example") {
+ my $rr = new Net::DNS::RR($negSOA);
+ push @auth, $rr;
+ $rcode = "NXDOMAIN";
+ } elsif ($qname eq "othertype.example") {
+ if ($qtype eq "CAA") {
+ my $rr = new Net::DNS::RR($CAA);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($negSOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "ns.slow" ) {
+ if ($qtype eq "A") {
+ my $rr = new Net::DNS::RR($slowA);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($slowSOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "slow") {
+ if ($qtype eq "NS") {
+ my $rr = new Net::DNS::RR($slowNS);
+ push @auth, $rr;
+ $rr = new Net::DNS::RR($slowA);
+ push @add, $rr;
+ } elsif ($qtype eq "SOA") {
+ my $rr = new Net::DNS::RR($slowSOA);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($slowSOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } elsif ($qname eq "data.slow") {
+ if ($slow_response) {
+ print " Sleeping 3 seconds\n";
+ sleep(3);
+ # only one time
+ $slow_response = 0;
+ }
+ if ($qtype eq "TXT") {
+ my $rr = new Net::DNS::RR($slowTXT);
+ push @ans, $rr;
+ } else {
+ my $rr = new Net::DNS::RR($slownegSOA);
+ push @auth, $rr;
+ }
+ $rcode = "NOERROR";
+ } else {
+ my $rr = new Net::DNS::RR($SOA);
+ push @auth, $rr;
+ $rcode = "NXDOMAIN";
+ }
+
+ # mark the answer as authoritative (by setting the 'aa' flag)
+ return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
+}
+
+GetOptions(
+ 'port=i' => \$localport,
+);
+
+my $rin;
+my $rout;
+
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($udpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($udpsock), 1)) {
+ my ($buf, $request, $err);
+ $udpsock->recv($buf, 512);
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($request, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ my @questions = $request->question;
+ my $qname = $questions[0]->qname;
+ my $qclass = $questions[0]->qclass;
+ my $qtype = $questions[0]->qtype;
+ my $id = $request->header->id;
+
+ my ($rcode, $ans, $auth, $add, $headermask) = reply_handler($qname, $qclass, $qtype);
+
+ if (!defined($rcode)) {
+ print " Silently ignoring query\n";
+ next;
+ }
+
+ my $reply = Net::DNS::Packet->new();
+ $reply->header->qr(1);
+ $reply->header->aa(1) if $headermask->{'aa'};
+ $reply->header->id($id);
+ $reply->header->rcode($rcode);
+ $reply->push("question", @questions);
+ $reply->push("answer", @$ans) if $ans;
+ $reply->push("authority", @$auth) if $auth;
+ $reply->push("additional", @$add) if $add;
+
+ my $num_chars = $udpsock->send($reply->data);
+ print " Sent $num_chars bytes via UDP\n";
+ }
+}
diff --git a/bin/tests/system/serve-stale/clean.sh b/bin/tests/system/serve-stale/clean.sh
new file mode 100644
index 0000000..b4a0d50
--- /dev/null
+++ b/bin/tests/system/serve-stale/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out*
+rm -f ns*/named.conf
+rm -f ns*/root.bk
+rm -f rndc.out.test*
+rm -f */named.run */named.memstats
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named_dump*
+rm -f ns*/named.stats*
+rm -f ns*/named.run.prev
diff --git a/bin/tests/system/serve-stale/ns1/named1.conf.in b/bin/tests/system/serve-stale/ns1/named1.conf.in
new file mode 100644
index 0000000..d25611d
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns1/named1.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 yes;
+ dnssec-validation no;
+ max-stale-ttl 3600;
+ stale-answer-ttl 4;
+ stale-answer-enable yes;
+ stale-cache-enable yes;
+ stale-refresh-time 30;
+ servfail-ttl 0;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/serve-stale/ns1/named2.conf.in b/bin/tests/system/serve-stale/ns1/named2.conf.in
new file mode 100644
index 0000000..82e5e76
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns1/named2.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 yes;
+ dnssec-validation no;
+ max-stale-ttl 3600;
+ stale-answer-ttl 4;
+ stale-answer-enable yes;
+ stale-cache-enable yes;
+ stale-refresh-time 0;
+ servfail-ttl 0;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/serve-stale/ns1/named3.conf.in b/bin/tests/system/serve-stale/ns1/named3.conf.in
new file mode 100644
index 0000000..4f6f175
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns1/named3.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 yes;
+ dnssec-validation no;
+ max-stale-ttl 20;
+ stale-answer-ttl 3;
+ stale-answer-enable yes;
+ stale-cache-enable yes;
+ servfail-ttl 0;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/serve-stale/ns1/named4.conf.in b/bin/tests/system/serve-stale/ns1/named4.conf.in
new file mode 100644
index 0000000..f2cc2a8
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns1/named4.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 yes;
+ dnssec-validation no;
+ max-stale-ttl 20;
+ stale-answer-ttl 3;
+ stale-answer-enable yes;
+ stale-cache-enable yes;
+ stale-refresh-time 0;
+ servfail-ttl 0;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "stale.test" {
+ type primary;
+ file "stale.test.db";
+};
diff --git a/bin/tests/system/serve-stale/ns1/root.db b/bin/tests/system/serve-stale/ns1/root.db
new file mode 100644
index 0000000..aef8e31
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns1/root.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 300 SOA . . 0 0 0 0 0
+. 300 NS ns.nil.
+ns.nil. 300 A 10.53.0.1
+example. 300 NS ns.example.
+ns.example. 300 A 10.53.0.2
+slow. 300 NS ns.slow.
+ns.slow. 300 A 10.53.0.2
diff --git a/bin/tests/system/serve-stale/ns1/stale.test.db b/bin/tests/system/serve-stale/ns1/stale.test.db
new file mode 100644
index 0000000..d389e7c
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns1/stale.test.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN stale.test.
+stale.test. 300 SOA . . 0 0 0 0 0
+stale.test. 300 NS ns.stale.test.
+ns.stale.test. 300 A 10.53.0.1
+cname1.stale.test. 1 CNAME a1.stale.test.
+a1.stale.test. 1 A 192.0.2.1
+cname2.stale.test. 1 CNAME a2.stale.test.
+a2.stale.test. 300 A 192.0.2.2
diff --git a/bin/tests/system/serve-stale/ns3/named1.conf.in b/bin/tests/system/serve-stale/ns3/named1.conf.in
new file mode 100644
index 0000000..5c7dddd
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns3/named1.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dump-file "named_dump3.db";
+ stale-cache-enable yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "root.bk";
+};
diff --git a/bin/tests/system/serve-stale/ns3/named2.conf.in b/bin/tests/system/serve-stale/ns3/named2.conf.in
new file mode 100644
index 0000000..0a316d8
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns3/named2.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Test default stale-answer-client-timeout value
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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; };
+ dnssec-validation no;
+ recursion yes;
+ stale-answer-enable yes;
+ stale-cache-enable yes;
+ stale-answer-ttl 3;
+ stale-refresh-time 0;
+ stale-answer-client-timeout 1800; # 1.8 seconds
+ recursive-clients 10; # CVE-2022-3924
+ max-stale-ttl 3600;
+ resolver-query-timeout 30000; # 30 seconds
+ qname-minimization disabled;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
diff --git a/bin/tests/system/serve-stale/ns3/named3.conf.in b/bin/tests/system/serve-stale/ns3/named3.conf.in
new file mode 100644
index 0000000..cef5e52
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns3/named3.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Test disable of stale-answer-client-timeout.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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; };
+ dnssec-validation no;
+ recursion yes;
+ stale-answer-enable yes;
+ stale-cache-enable yes;
+ stale-answer-ttl 3;
+ stale-refresh-time 0;
+ max-stale-ttl 3600;
+ resolver-query-timeout 10000; # 10 seconds
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
diff --git a/bin/tests/system/serve-stale/ns3/named4.conf.in b/bin/tests/system/serve-stale/ns3/named4.conf.in
new file mode 100644
index 0000000..abc1eb7
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns3/named4.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Test stale-answer-client-timeout 0.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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; };
+ dnssec-validation no;
+ recursion yes;
+ stale-answer-enable yes;
+ stale-cache-enable yes;
+ stale-answer-ttl 3;
+ stale-answer-client-timeout 0;
+ stale-refresh-time 0;
+ resolver-query-timeout 10000; # 10 seconds
+ max-stale-ttl 3600;
+ recursive-clients 10;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
diff --git a/bin/tests/system/serve-stale/ns3/named5.conf.in b/bin/tests/system/serve-stale/ns3/named5.conf.in
new file mode 100644
index 0000000..b695901
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns3/named5.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Test stale-answer-client-timeout 0.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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; };
+ dnssec-validation no;
+ recursion yes;
+ stale-answer-enable yes;
+ stale-cache-enable yes;
+ stale-answer-ttl 3;
+ stale-answer-client-timeout 0;
+ stale-refresh-time 4;
+ resolver-query-timeout 10000; # 10 seconds
+ max-stale-ttl 3600;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
diff --git a/bin/tests/system/serve-stale/ns3/named6.conf.in b/bin/tests/system/serve-stale/ns3/named6.conf.in
new file mode 100644
index 0000000..307c3bc
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns3/named6.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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; };
+ dnssec-validation no;
+ recursion yes;
+ stale-answer-enable no;
+ stale-cache-enable yes;
+ stale-answer-ttl 3;
+ stale-refresh-time 4;
+ resolver-query-timeout 10000; # 10 seconds
+ fetches-per-zone 1 fail;
+ fetches-per-server 1 fail;
+ max-stale-ttl 3600;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
diff --git a/bin/tests/system/serve-stale/ns3/named7.conf.in b/bin/tests/system/serve-stale/ns3/named7.conf.in
new file mode 100644
index 0000000..12d9ee3
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns3/named7.conf.in
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Test serve-stale interaction with fetch-limits (dual-mode).
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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; };
+ dnssec-validation no;
+ recursion yes;
+ /*
+ * stale-answer-enable is not strictly required because serving
+ * stale answers is enabled in the test via rndc.
+ */
+ stale-answer-enable yes;
+ stale-cache-enable yes;
+ stale-answer-ttl 3;
+ stale-refresh-time 4;
+ resolver-query-timeout 10000; # 10 seconds
+ fetches-per-zone 1 fail;
+ fetches-per-server 1 fail;
+ max-stale-ttl 3600;
+};
+
+zone "." {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "root.bk";
+};
diff --git a/bin/tests/system/serve-stale/ns3/named8.conf.in b/bin/tests/system/serve-stale/ns3/named8.conf.in
new file mode 100644
index 0000000..7b5792d
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns3/named8.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation no;
+ stale-answer-enable yes;
+ stale-cache-enable yes;
+ stale-answer-client-timeout 1800;
+ prefetch 2 8;
+ dns64 2001:aaaa::/96 {
+ clients { any; };
+ mapped { any; };
+ };
+};
+
+zone "." {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "root.bk";
+};
diff --git a/bin/tests/system/serve-stale/ns3/root.db b/bin/tests/system/serve-stale/ns3/root.db
new file mode 100644
index 0000000..bbf039c
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns3/root.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 300 NS ns.nil.
+ns.nil. 300 A 10.53.0.1
diff --git a/bin/tests/system/serve-stale/ns4/named.conf.in b/bin/tests/system/serve-stale/ns4/named.conf.in
new file mode 100644
index 0000000..ac7dd99
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns4/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation no;
+ dump-file "named_dump.db";
+ stale-answer-enable no;
+ stale-cache-enable yes;
+};
+
+zone "." {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "root.bk";
+};
diff --git a/bin/tests/system/serve-stale/ns5/named.conf.in b/bin/tests/system/serve-stale/ns5/named.conf.in
new file mode 100644
index 0000000..9874728
--- /dev/null
+++ b/bin/tests/system/serve-stale/ns5/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation no;
+ dump-file "named_dump.db";
+ stale-answer-enable yes;
+ stale-cache-enable no;
+ max-cache-ttl 24h;
+};
+
+zone "." {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "root.bk";
+};
diff --git a/bin/tests/system/serve-stale/setup.sh b/bin/tests/system/serve-stale/setup.sh
new file mode 100644
index 0000000..0a0dc47
--- /dev/null
+++ b/bin/tests/system/serve-stale/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named1.conf.in ns1/named.conf
+copy_setports ns3/named1.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/serve-stale/tests.sh b/bin/tests/system/serve-stale/tests.sh
new file mode 100755
index 0000000..8c5ce84
--- /dev/null
+++ b/bin/tests/system/serve-stale/tests.sh
@@ -0,0 +1,2705 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+DIG="$DIG +time=12 +tries=1"
+
+max_stale_ttl=$(sed -ne 's,^[[:space:]]*max-stale-ttl \([[:digit:]]*\).*,\1,p' $TOP_SRCDIR/bin/named/config.c)
+stale_answer_ttl=$(sed -ne 's,^[[:space:]]*stale-answer-ttl \([[:digit:]]*\).*,\1,p' $TOP_SRCDIR/bin/named/config.c)
+
+status=0
+n=0
+
+#
+# First test server with serve-stale options set.
+#
+echo_i "test server with serve-stale options set"
+
+n=$((n+1))
+echo_i "prime cache longttl.example TXT ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 longttl.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache data.example TXT ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache othertype.example CAA ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nodata.example TXT ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nxdomain.example TXT ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$n
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verify prime cache statistics ($n)"
+ret=0
+rm -f ns1/named.stats
+$RNDCCMD 10.53.0.1 stats > /dev/null 2>&1
+[ -f ns1/named.stats ] || ret=1
+cp ns1/named.stats ns1/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After prime queries, we expect
+# two active TXT, one active Others, one nxrrset TXT, and one NXDOMAIN.
+grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n > ns1/named.stats.$n.cachedb || ret=1
+grep "1 Others" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "2 TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 !TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 NXDOMAIN" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+sleep 2
+
+# Run rndc dumpdb, test whether the stale data has correct comment printed.
+# The max-stale-ttl is 3600 seconds, so the comment should say the data is
+# stale for somewhere between 3500-3599 seconds.
+echo_i "check rndc dump stale data.example ($n)"
+rndc_dumpdb ns1 || ret=1
+awk '/; stale/ { x=$0; getline; print x, $0}' ns1/named_dump.db.test$n |
+ grep "; stale data\.example.*3[56]...*TXT.*A text record with a 2 second ttl" > /dev/null 2>&1 || ret=1
+# Also make sure the not expired data does not have a stale comment.
+awk '/; authanswer/ { x=$0; getline; print x, $0}' ns1/named_dump.db.test$n |
+ grep "; authanswer longttl\.example.*[56]...*TXT.*A text record with a 600 second ttl" > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "sending queries for tests $((n+1))-$((n+5))..."
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} @10.53.0.1 longttl.example TXT > dig.out.test$((n+2)) &
+$DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+3)) &
+$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+4)) &
+$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+5)) &
+
+wait
+
+n=$((n+1))
+echo_i "check stale data.example TXT ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check non-stale longttl.example TXT ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "longttl\.example\..*59[0-9].*IN.*TXT.*A text record with a 600 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale othertype.example CAA ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "othertype\.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nodata.example TXT ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nxdomain.example TXT ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verify stale cache statistics ($n)"
+ret=0
+rm -f ns1/named.stats
+$RNDCCMD 10.53.0.1 stats > /dev/null 2>&1
+[ -f ns1/named.stats ] || ret=1
+cp ns1/named.stats ns1/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After serve-stale queries, we
+# expect one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one
+# stale NXDOMAIN.
+grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n > ns1/named.stats.$n.cachedb || ret=1
+grep "1 TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #Others" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #!TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+status=$((status+ret))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+# Test stale-refresh-time when serve-stale is enabled via configuration.
+# Steps for testing stale-refresh-time option (default).
+# 1. Prime cache data.example txt
+# 2. Disable responses from authoritative server.
+# 3. Sleep for TTL duration so rrset TTL expires (2 sec)
+# 4. Query data.example
+# 5. Check if response come from stale rrset (4 sec TTL)
+# 6. Enable responses from authoritative server.
+# 7. Query data.example
+# 8. Check if response come from stale rrset, since the query
+# is still within stale-refresh-time window.
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 1-3 done above.
+
+# Step 4.
+n=$((n+1))
+echo_i "sending query for test ($n)"
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
+
+# Step 5.
+echo_i "check stale data.example TXT (stale-refresh-time) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 6.
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 7.
+echo_i "sending query for test $((n+1))"
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1))
+
+# Step 8.
+n=$((n+1))
+echo_i "check stale data.example TXT comes from cache (stale-refresh-time) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#
+# Test disabling serve-stale via rndc.
+#
+
+n=$((n+1))
+echo_i "updating ns1/named.conf ($n)"
+ret=0
+copy_setports ns1/named2.conf.in ns1/named.conf
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "running 'rndc reload' ($n)"
+ret=0
+rndc_reload ns1 10.53.0.1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "running 'rndc serve-stale off' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale off || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers disabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "sending queries for tests $((n+1))-$((n+4))..."
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+2)) &
+$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+3)) &
+$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+4)) &
+
+wait
+
+n=$((n+1))
+echo_i "check stale data.example TXT (serve-stale off) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale othertype.example CAA (serve-stale off) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nodata.example TXT (serve-stale off) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nxdomain.example TXT (serve-stale off) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#
+# Test enabling serve-stale via rndc.
+#
+n=$((n+1))
+echo_i "running 'rndc serve-stale on' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale on || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "sending queries for tests $((n+1))-$((n+4))..."
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+2)) &
+$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+3)) &
+$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+4)) &
+
+wait
+
+n=$((n+1))
+echo_i "check stale data.example TXT (serve-stale on) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale othertype.example CAA (serve-stale on) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "othertype\.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nodata.example TXT (serve-stale on) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nxdomain.example TXT (serve-stale on) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "running 'rndc serve-stale off' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale off || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "running 'rndc serve-stale reset' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale reset || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "sending queries for tests $((n+1))-$((n+4))..."
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+2)) &
+$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+3)) &
+$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+4)) &
+
+wait
+
+n=$((n+1))
+echo_i "check stale data.example TXT (serve-stale reset) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale othertype.example CAA (serve-stale reset) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "othertype.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nodata.example TXT (serve-stale reset) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nxdomain.example TXT (serve-stale reset) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "running 'rndc serve-stale off' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale off || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers disabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#
+# Update named.conf.
+# Test server with low max-stale-ttl.
+#
+echo_i "test server with serve-stale options set, low max-stale-ttl"
+
+n=$((n+1))
+echo_i "updating ns1/named.conf ($n)"
+ret=0
+copy_setports ns1/named3.conf.in ns1/named.conf
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "running 'rndc reload' ($n)"
+ret=0
+rndc_reload ns1 10.53.0.1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers disabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "flush cache, re-enable serve-stale and query again ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 flushtree example > rndc.out.test$n.1 2>&1 || ret=1
+$RNDCCMD 10.53.0.1 serve-stale on > rndc.out.test$n.2 2>&1 || ret=1
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache longttl.example TXT (low max-stale-ttl) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 longttl.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache data.example TXT (low max-stale-ttl) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache othertype.example CAA (low max-stale-ttl) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nodata.example TXT (low max-stale-ttl) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nxdomain.example TXT (low max-stale-ttl) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$n
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Keep track of time so we can access these RRset later, when we expect them
+# to become ancient.
+t1=$($PERL -e 'print time()')
+
+n=$((n+1))
+echo_i "verify prime cache statistics (low max-stale-ttl) ($n)"
+ret=0
+rm -f ns1/named.stats
+$RNDCCMD 10.53.0.1 stats > /dev/null 2>&1
+[ -f ns1/named.stats ] || ret=1
+cp ns1/named.stats ns1/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After prime queries, we expect
+# two active TXT RRsets, one active Others, one nxrrset TXT, and one NXDOMAIN.
+grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n > ns1/named.stats.$n.cachedb || ret=1
+grep "2 TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 Others" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 !TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 NXDOMAIN" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+status=$((status+ret))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+sleep 2
+
+echo_i "sending queries for tests $((n+1))-$((n+4))..."
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+2)) &
+$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+3)) &
+$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+4)) &
+
+wait
+
+n=$((n+1))
+echo_i "check stale data.example TXT (low max-stale-ttl) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale othertype.example CAA (low max-stale-ttl) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "othertype\.example\..*3.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nodata.example TXT (low max-stale-ttl) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*3.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nxdomain.example TXT (low max-stale-ttl) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verify stale cache statistics (low max-stale-ttl) ($n)"
+ret=0
+rm -f ns1/named.stats
+$RNDCCMD 10.53.0.1 stats > /dev/null 2>&1
+[ -f ns1/named.stats ] || ret=1
+cp ns1/named.stats ns1/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After serve-stale queries, we
+# expect one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one
+# stale NXDOMAIN.
+grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n > ns1/named.stats.$n.cachedb || ret=1
+grep "1 TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #Others" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #!TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
+
+status=$((status+ret))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+# Retrieve max-stale-ttl value.
+interval_to_ancient=$(grep 'max-stale-ttl' ns1/named3.conf.in | awk '{ print $2 }' | tr -d ';')
+# We add 2 seconds to it since this is the ttl value of the records being
+# tested.
+interval_to_ancient=$((interval_to_ancient + 2))
+t2=$($PERL -e 'print time()')
+elapsed=$((t2 - t1))
+
+# If elapsed time so far is less than max-stale-ttl + 2 seconds, then we sleep
+# enough to ensure that we'll ask for ancient RRsets in the next queries.
+if [ $elapsed -lt $interval_to_ancient ]; then
+ sleep $((interval_to_ancient - elapsed))
+fi
+
+echo_i "sending queries for tests $((n+1))-$((n+4))..."
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+2)) &
+$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+3)) &
+$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+4)) &
+
+wait
+
+n=$((n+1))
+echo_i "check ancient data.example TXT (low max-stale-ttl) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check ancient othertype.example CAA (low max-stale-ttl) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check ancient nodata.example TXT (low max-stale-ttl) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check ancient nxdomain.example TXT (low max-stale-ttl) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Test stale-refresh-time when serve-stale is enabled via rndc.
+# Steps for testing stale-refresh-time option (default).
+# 1. Prime cache data.example txt
+# 2. Disable responses from authoritative server.
+# 3. Sleep for TTL duration so rrset TTL expires (2 sec)
+# 4. Query data.example
+# 5. Check if response come from stale rrset (3 sec TTL)
+# 6. Enable responses from authoritative server.
+# 7. Query data.example
+# 8. Check if response come from stale rrset, since the query
+# is within stale-refresh-time window.
+n=$((n+1))
+echo_i "flush cache, enable responses from authoritative server ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 flushtree example > rndc.out.test$n.1 2>&1 || ret=1
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 1.
+n=$((n+1))
+echo_i "prime cache data.example TXT (stale-refresh-time rndc) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 2.
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 3.
+sleep 2
+
+# Step 4.
+n=$((n+1))
+echo_i "sending query for test ($n)"
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
+
+# Step 5.
+echo_i "check stale data.example TXT (stale-refresh-time rndc) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 6.
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 7.
+echo_i "sending query for test $((n+1))"
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1))
+
+# Step 8.
+n=$((n+1))
+echo_i "check stale data.example TXT comes from cache (stale-refresh-time rndc) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Steps for testing stale-refresh-time option (disabled).
+# 1. Prime cache data.example txt
+# 2. Disable responses from authoritative server.
+# 3. Sleep for TTL duration so rrset TTL expires (2 sec)
+# 4. Query data.example
+# 5. Check if response come from stale rrset (3 sec TTL)
+# 6. Enable responses from authoritative server.
+# 7. Query data.example
+# 8. Check if response come from stale rrset, since the query
+# is within stale-refresh-time window.
+n=$((n+1))
+echo_i "updating ns1/named.conf ($n)"
+ret=0
+copy_setports ns1/named4.conf.in ns1/named.conf
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "running 'rndc reload' ($n)"
+ret=0
+rndc_reload ns1 10.53.0.1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=0)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "flush cache, enable responses from authoritative server ($n)"
+ret=0
+$RNDCCMD 10.53.0.1 flushtree example > rndc.out.test$n.1 2>&1 || ret=1
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 1.
+n=$((n+1))
+echo_i "prime cache data.example TXT (stale-refresh-time disabled) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 2.
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 3.
+sleep 2
+
+# Step 4.
+n=$((n+1))
+echo_i "sending query for test ($n)"
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
+
+# Step 5.
+echo_i "check stale data.example TXT (stale-refresh-time disabled) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 6.
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Step 7.
+echo_i "sending query for test $((n+1))"
+$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1))
+
+# Step 8.
+n=$((n+1))
+echo_i "check data.example TXT comes from authoritative (stale-refresh-time disabled) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#
+# Now test server with no serve-stale options set.
+#
+echo_i "test server with no serve-stale options set"
+
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache longttl.example TXT (max-stale-ttl default) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 longttl.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache data.example TXT (max-stale-ttl default) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache othertype.example CAA (max-stale-ttl default) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 othertype.example CAA > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "othertype\.example\..*2.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nodata.example TXT (max-stale-ttl default) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*2.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nxdomain.example TXT (max-stale-ttl default) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT > dig.out.test$n
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*2.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verify prime cache statistics (max-stale-ttl default) ($n)"
+ret=0
+rm -f ns3/named.stats
+$RNDCCMD 10.53.0.3 stats > /dev/null 2>&1
+[ -f ns3/named.stats ] || ret=1
+cp ns3/named.stats ns3/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After prime queries, we expect
+# two active TXT RRsets, one active Others, one nxrrset TXT, and one NXDOMAIN.
+grep -A 10 "++ Cache DB RRsets ++" ns3/named.stats.$n > ns3/named.stats.$n.cachedb || ret=1
+grep "2 TXT" ns3/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 Others" ns3/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 !TXT" ns3/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 NXDOMAIN" ns3/named.stats.$n.cachedb > /dev/null || ret=1
+status=$((status+ret))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep "_default: stale cache enabled; stale answers disabled (stale-answer-ttl=$stale_answer_ttl max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+sleep 2
+
+echo_i "sending queries for tests $((n+1))-$((n+4))..."
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} @10.53.0.3 othertype.example CAA > dig.out.test$((n+2)) &
+$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$((n+3)) &
+$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT > dig.out.test$((n+4)) &
+
+wait
+
+n=$((n+1))
+echo_i "check fail of data.example TXT (max-stale-ttl default) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check fail of othertype.example CAA (max-stale-ttl default) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check fail of nodata.example TXT (max-stale-ttl default) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check fail of nxdomain.example TXT (max-stale-ttl default) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verify stale cache statistics (max-stale-ttl default) ($n)"
+ret=0
+rm -f ns3/named.stats
+$RNDCCMD 10.53.0.3 stats > /dev/null 2>&1
+[ -f ns3/named.stats ] || ret=1
+cp ns3/named.stats ns3/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After last queries, we expect
+# one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one stale
+# NXDOMAIN.
+grep -A 10 "++ Cache DB RRsets ++" ns3/named.stats.$n > ns3/named.stats.$n.cachedb || ret=1
+grep "1 TXT" ns3/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #TXT" ns3/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #Others" ns3/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #!TXT" ns3/named.stats.$n.cachedb > /dev/null || ret=1
+
+status=$((status+ret))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale on' ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 serve-stale on > rndc.out.test$n 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep "_default: stale cache enabled; stale answers enabled (stale-answer-ttl=$stale_answer_ttl max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+sleep 2
+
+# Check that if we don't have stale data for a domain name, we will
+# not answer anything until the resolver query timeout.
+n=$((n+1))
+echo_i "check notincache.example TXT times out (max-stale-ttl default) ($n)"
+ret=0
+$DIG -p ${PORT} +tries=1 +timeout=3 @10.53.0.3 notfound.example TXT > dig.out.test$n 2>&1 && ret=1
+grep "timed out" dig.out.test$n > /dev/null || ret=1
+grep ";; no servers could be reached" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "sending queries for tests $((n+1))-$((n+4))..."
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} @10.53.0.3 othertype.example CAA > dig.out.test$((n+2)) &
+$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$((n+3)) &
+$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT > dig.out.test$((n+4)) &
+$DIG -p ${PORT} @10.53.0.3 notfound.example TXT > dig.out.test$((n+5)) &
+
+wait
+
+n=$((n+1))
+echo_i "check data.example TXT (max-stale-ttl default) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*30.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check othertype.example CAA (max-stale-ttl default) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "example\..*30.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check nodata.example TXT (max-stale-ttl default) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*30.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check nxdomain.example TXT (max-stale-ttl default) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# The notfound.example check is different than nxdomain.example because
+# we didn't send a prime query to add notfound.example to the cache.
+n=$((n+1))
+echo_i "check notfound.example TXT (max-stale-ttl default) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#
+# Now test server with serve-stale answers disabled.
+#
+echo_i "test server with serve-stale disabled"
+
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache longttl.example TTL (serve-stale answers disabled) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.4 longttl.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache data.example TTL (serve-stale answers disabled) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.4 data.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache othertype.example CAA (serve-stale answers disabled) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.4 othertype.example CAA > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "othertype\.example\..*2.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nodata.example TXT (serve-stale answers disabled) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.4 nodata.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*2.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nxdomain.example TXT (serve-stale answers disabled) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.4 nxdomain.example TXT > dig.out.test$n
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*2.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verify prime cache statistics (serve-stale answers disabled) ($n)"
+ret=0
+rm -f ns4/named.stats
+$RNDCCMD 10.53.0.4 stats > /dev/null 2>&1
+[ -f ns4/named.stats ] || ret=1
+cp ns4/named.stats ns4/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After prime queries, we expect
+# two active TXT RRsets, one active Others, one nxrrset TXT, and one NXDOMAIN.
+grep -A 10 "++ Cache DB RRsets ++" ns4/named.stats.$n > ns4/named.stats.$n.cachedb || ret=1
+grep "2 TXT" ns4/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 Others" ns4/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 !TXT" ns4/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 NXDOMAIN" ns4/named.stats.$n.cachedb > /dev/null || ret=1
+status=$((status+ret))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.4 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep "_default: stale cache enabled; stale answers disabled (stale-answer-ttl=$stale_answer_ttl max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+sleep 2
+
+echo_i "sending queries for tests $((n+1))-$((n+4))..."
+$DIG -p ${PORT} @10.53.0.4 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} @10.53.0.4 othertype.example CAA > dig.out.test$((n+2)) &
+$DIG -p ${PORT} @10.53.0.4 nodata.example TXT > dig.out.test$((n+3)) &
+$DIG -p ${PORT} @10.53.0.4 nxdomain.example TXT > dig.out.test$((n+4)) &
+
+wait
+
+n=$((n+1))
+echo_i "check fail of data.example TXT (serve-stale answers disabled) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check fail of othertype.example TXT (serve-stale answers disabled) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check fail of nodata.example TXT (serve-stale answers disabled) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check fail of nxdomain.example TXT (serve-stale answers disabled) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verify stale cache statistics (serve-stale answers disabled) ($n)"
+ret=0
+rm -f ns4/named.stats
+$RNDCCMD 10.53.0.4 stats > /dev/null 2>&1
+[ -f ns4/named.stats ] || ret=1
+cp ns4/named.stats ns4/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After last queries, we expect
+# one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one stale
+# NXDOMAIN.
+grep -A 10 "++ Cache DB RRsets ++" ns4/named.stats.$n > ns4/named.stats.$n.cachedb || ret=1
+grep "1 TXT" ns4/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #TXT" ns4/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #Others" ns4/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 #!TXT" ns4/named.stats.$n.cachedb > /dev/null || ret=1
+status=$((status+ret))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+# Dump the cache.
+n=$((n+1))
+echo_i "dump the cache (serve-stale answers disabled) ($n)"
+ret=0
+rndc_dumpdb ns4 -cache || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "stop ns4"
+stop_server --use-rndc --port ${CONTROLPORT} ns4
+
+# Load the cache as if it was five minutes (RBTDB_VIRTUAL) older. Since
+# max-stale-ttl defaults to a week, we need to adjust the date by one week and
+# five minutes.
+LASTWEEK=$(TZ=UTC perl -e 'my $now = time();
+ my $oneWeekAgo = $now - 604800;
+ my $fiveMinutesAgo = $oneWeekAgo - 300;
+ my ($s, $m, $h, $d, $mo, $y) = (localtime($fiveMinutesAgo))[0, 1, 2, 3, 4, 5];
+ printf("%04d%02d%02d%02d%02d%02d", $y+1900, $mo+1, $d, $h, $m, $s);')
+
+echo_i "mock the cache date to $LASTWEEK (serve-stale answers disabled) ($n)"
+ret=0
+sed -E "s/DATE [0-9]{14}/DATE $LASTWEEK/g" ns4/named_dump.db.test$n > ns4/named_dump.db.out || ret=1
+cp ns4/named_dump.db.out ns4/named_dump.db
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "start ns4"
+start_server --noclean --restart --port ${PORT} ns4
+
+n=$((n+1))
+echo_i "verify ancient cache statistics (serve-stale answers disabled) ($n)"
+ret=0
+rm -f ns4/named.stats
+$RNDCCMD 10.53.0.4 stats #> /dev/null 2>&1
+[ -f ns4/named.stats ] || ret=1
+cp ns4/named.stats ns4/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After last queries, we expect
+# everything to be removed or scheduled to be removed.
+grep -A 10 "++ Cache DB RRsets ++" ns4/named.stats.$n > ns4/named.stats.$n.cachedb || ret=1
+grep "#TXT" ns4/named.stats.$n.cachedb > /dev/null && ret=1
+grep "#Others" ns4/named.stats.$n.cachedb > /dev/null && ret=1
+grep "#!TXT" ns4/named.stats.$n.cachedb > /dev/null && ret=1
+grep "#NXDOMAIN" ns4/named.stats.$n.cachedb > /dev/null && ret=1
+status=$((status+ret))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+#
+# Test the server with stale-cache disabled.
+#
+echo_i "test server with serve-stale cache disabled"
+
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache longttl.example TXT (serve-stale cache disabled) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.5 longttl.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache data.example TXT (serve-stale cache disabled) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.5 data.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache othertype.example CAA (serve-stale cache disabled) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.5 othertype.example CAA > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "othertype\.example\..*2.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nodata.example TXT (serve-stale cache disabled) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.5 nodata.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*2.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nxdomain.example TXT (serve-stale cache disabled) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.5 nxdomain.example TXT > dig.out.test$n
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*2.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verify prime cache statistics (serve-stale cache disabled) ($n)"
+ret=0
+rm -f ns5/named.stats
+$RNDCCMD 10.53.0.5 stats > /dev/null 2>&1
+[ -f ns5/named.stats ] || ret=1
+cp ns5/named.stats ns5/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After serve-stale queries,
+# we expect two active TXT RRsets, one active Others, one nxrrset TXT, and
+# one NXDOMAIN.
+grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n > ns5/named.stats.$n.cachedb || ret=1
+grep "2 TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 Others" ns5/named.stats.$n.cachedb > /dev/null || ret=1
+grep "1 !TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1
+status=$((status+ret))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.5 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep "_default: stale cache disabled; stale answers unavailable" rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+sleep 2
+
+echo_i "sending queries for tests $((n+1))-$((n+4))..."
+$DIG -p ${PORT} @10.53.0.5 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} @10.53.0.5 othertype.example CAA > dig.out.test$((n+2)) &
+$DIG -p ${PORT} @10.53.0.5 nodata.example TXT > dig.out.test$((n+3)) &
+$DIG -p ${PORT} @10.53.0.5 nxdomain.example TXT > dig.out.test$((n+4)) &
+
+wait
+
+n=$((n+1))
+echo_i "check fail of data.example TXT (serve-stale cache disabled) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check fail of othertype.example CAA (serve-stale cache disabled) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check fail of nodata.example TXT (serve-stale cache disabled) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check fail of nxdomain.example TXT (serve-stale cache disabled) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "verify stale cache statistics (serve-stale cache disabled) ($n)"
+ret=0
+rm -f ns5/named.stats
+$RNDCCMD 10.53.0.5 stats > /dev/null 2>&1
+[ -f ns5/named.stats ] || ret=1
+cp ns5/named.stats ns5/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After serve-stale queries,
+# we expect one active TXT (longttl) and the rest to be expired from cache,
+# but since we keep everything for 5 minutes (RBTDB_VIRTUAL) in the cache
+# after expiry, they still show up in the stats.
+grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n > ns5/named.stats.$n.cachedb || ret=1
+grep -F "1 Others" ns5/named.stats.$n.cachedb > /dev/null || ret=1
+grep -F "2 TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1
+grep -F "1 !TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1
+status=$((status+ret))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+# Dump the cache.
+n=$((n+1))
+echo_i "dump the cache (serve-stale cache disabled) ($n)"
+ret=0
+rndc_dumpdb ns5 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+# Check that expired records are not dumped.
+ret=0
+grep "; expired since .* (awaiting cleanup)" ns5/named_dump.db.test$n && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Dump the cache including expired entries.
+n=$((n+1))
+echo_i "dump the cache including expired entries (serve-stale cache disabled) ($n)"
+ret=0
+rndc_dumpdb ns5 -expired || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Check that expired records are dumped.
+echo_i "check rndc dump expired data.example ($n)"
+ret=0
+awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n |
+ grep "; expired since .* (awaiting cleanup) data\.example\..*A text record with a 2 second ttl" > /dev/null 2>&1 || ret=1
+awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n |
+ grep "; expired since .* (awaiting cleanup) nodata\.example\." > /dev/null 2>&1 || ret=1
+awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n |
+ grep "; expired since .* (awaiting cleanup) nxdomain\.example\." > /dev/null 2>&1 || ret=1
+awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n |
+ grep "; expired since .* (awaiting cleanup) othertype\.example\." > /dev/null 2>&1 || ret=1
+# Also make sure the not expired data does not have an expired comment.
+awk '/; authanswer/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n |
+ grep "; authanswer longttl\.example.*A text record with a 600 second ttl" > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "stop ns5"
+stop_server --use-rndc --port ${CONTROLPORT} ns5
+
+# Load the cache as if it was five minutes (RBTDB_VIRTUAL) older.
+cp ns5/named_dump.db.test$n ns5/named_dump.db
+FIVEMINUTESAGO=$(TZ=UTC perl -e 'my $now = time();
+ my $fiveMinutesAgo = 300;
+ my ($s, $m, $h, $d, $mo, $y) = (localtime($fiveMinutesAgo))[0, 1, 2, 3, 4, 5];
+ printf("%04d%02d%02d%02d%02d%02d", $y+1900, $mo+1, $d, $h, $m, $s);')
+
+n=$((n+1))
+echo_i "mock the cache date to $FIVEMINUTESAGO (serve-stale cache disabled) ($n)"
+ret=0
+sed -E "s/DATE [0-9]{14}/DATE $FIVEMINUTESAGO/g" ns5/named_dump.db > ns5/named_dump.db.out || ret=1
+cp ns5/named_dump.db.out ns5/named_dump.db
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "start ns5"
+start_server --noclean --restart --port ${PORT} ns5
+
+n=$((n+1))
+echo_i "verify ancient cache statistics (serve-stale cache disabled) ($n)"
+ret=0
+rm -f ns5/named.stats
+$RNDCCMD 10.53.0.5 stats #> /dev/null 2>&1
+[ -f ns5/named.stats ] || ret=1
+cp ns5/named.stats ns5/named.stats.$n
+# Check first 10 lines of Cache DB statistics. After last queries, we expect
+# everything to be removed or scheduled to be removed.
+grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n > ns5/named.stats.$n.cachedb || ret=1
+grep -F "#TXT" ns5/named.stats.$n.cachedb > /dev/null && ret=1
+grep -F "#Others" ns5/named.stats.$n.cachedb > /dev/null && ret=1
+grep -F "#!TXT" ns5/named.stats.$n.cachedb > /dev/null && ret=1
+status=$((status+ret))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+
+################################################
+# Test for stale-answer-client-timeout (1.8s). #
+################################################
+echo_i "test stale-answer-client-timeout (1.8)"
+
+n=$((n+1))
+echo_i "updating ns3/named.conf ($n)"
+ret=0
+copy_setports ns3/named2.conf.in ns3/named.conf
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "restart ns3"
+stop_server --use-rndc --port ${CONTROLPORT} ns3
+start_server --noclean --restart --port ${PORT} ns3
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache data.example TXT (stale-answer-client-timeout) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nodata.example TXT (stale-answer-client-timeout) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "delay responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt slowdown > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache data.slow TXT (stale-answer-client-timeout) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 data.slow TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Allow RRset to become stale.
+sleep 2
+
+nextpart ns3/named.run > /dev/null
+
+echo_i "sending queries for tests $((n+1))-$((n+3))..."
+t1=$($PERL -e 'print time()')
+$DIG -p ${PORT} +tries=1 +timeout=11 @10.53.0.3 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} +tries=1 +timeout=11 @10.53.0.3 nodata.example TXT > dig.out.test$((n+2)) &
+$DIG -p ${PORT} +tries=1 +timeout=11 @10.53.0.3 data.slow TXT > dig.out.test$((n+3)) &
+wait
+t2=$($PERL -e 'print time()')
+
+# We configured a long value of 30 seconds for resolver-query-timeout.
+# That should give us enough time to receive an stale answer from cache
+# after stale-answer-client-timeout timer of 1.8 sec triggers.
+n=$((n+1))
+echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 1.8) ($n)"
+ret=0
+wait_for_log 5 "data.example client timeout, stale answer used" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (client timeout)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+# Configured stale-answer-client-timeout is 1.8s, we allow some extra time
+# just in case other tests are taking too much cpu.
+[ $((t2 - t1)) -le 10 ] || { echo_i "query took $((t2 - t1))s to resolve."; ret=1; }
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nodata.example TXT comes from cache (stale-answer-client-timeout 1.8) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (client timeout)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*3.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale data.slow TXT comes from cache (stale-answer-client-timeout 1.8) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (client timeout)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.slow\..*3.*IN.*TXT.*A slow text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Now query for RRset not in cache. The first query should time out, but once
+# we enable the authoritative server, the second query should be able to get a
+# response.
+
+nextpart ns3/named.run > /dev/null
+
+echo_i "sending queries for tests $((n+2))-$((n+4))..."
+# first dig runs in background for 10 seconds, second in background for 3
+# seconds and the last for 3 seconds in the foreground.
+# the second RRSIG lookup triggers the issue in [GL #3622]
+$DIG -p ${PORT} +tries=1 +timeout=10 @10.53.0.3 longttl.example TXT > dig.out.test$((n+3)) &
+$DIG -p ${PORT} +tries=1 +timeout=3 @10.53.0.3 longttl.example RRSIG > dig.out.test$((n+4)) &
+$DIG -p ${PORT} +tries=1 +timeout=3 @10.53.0.3 longttl.example TXT > dig.out.test$((n+2)) || true
+
+# Enable the authoritative name server after stale-answer-client-timeout.
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check not in cache longttl.example TXT times out (stale-answer-client-timeout 1.8) ($n)"
+ret=0
+wait_for_log 4 "longttl.example client timeout, stale answer unavailable" ns3/named.run || ret=1
+grep "timed out" dig.out.test$n > /dev/null || ret=1
+grep ";; no servers could be reached" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+wait
+
+n=$((n+1))
+echo_i "check not in cache longttl.example TXT comes from authoritative (stale-answer-client-timeout 1.8) ($n)"
+ret=0
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check not in cache longttl.example RRSIG times out (stale-answer-client-timeout 1.8) ($n)"
+ret=0
+grep "timed out" dig.out.test$n > /dev/null || ret=1
+grep ";; no servers could be reached" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# CVE-2022-3924, GL #3619
+n=$((n+1))
+echo_i "check that named survives reaching recursive-clients quota (stale-answer-client-timeout 1.8) ($n)"
+ret=0
+num=0
+# Make sure to exceed the configured value of 'recursive-clients 10;' by running
+# 20 parallel queries with simulated network latency.
+while [ $num -lt 20 ]; do
+ $DIG +tries=1 -p ${PORT} @10.53.0.3 "latency${num}.data.example" TXT >/dev/null 2>&1 &
+ num=$((num+1))
+done;
+check_server_responds() {
+ $DIG -p ${PORT} @10.53.0.3 version.bind txt ch >dig.out.test$n || return 1
+ grep "status: NOERROR" dig.out.test$n > /dev/null || return 1
+}
+retry_quiet 5 check_server_responds || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#############################################
+# Test for stale-answer-client-timeout off. #
+#############################################
+echo_i "test stale-answer-client-timeout (off)"
+
+n=$((n+1))
+echo_i "updating ns3/named.conf ($n)"
+ret=0
+copy_setports ns3/named3.conf.in ns3/named.conf
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "running 'rndc reload' ($n)"
+ret=0
+rndc_reload ns3 10.53.0.3
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Send a query, auth server is disabled, we will enable it after a while in
+# order to receive an answer before resolver-query-timeout expires. Since
+# stale-answer-client-timeout is disabled we must receive an answer from
+# authoritative server.
+echo_i "sending query for test $((n+2))"
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$((n+2)) &
+sleep 3
+
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Wait until dig is done.
+wait
+
+n=$((n+1))
+echo_i "check data.example TXT comes from authoritative server (stale-answer-client-timeout off) ($n)"
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+##############################################################
+# Test for stale-answer-client-timeout off and CNAME record. #
+##############################################################
+echo_i "test stale-answer-client-timeout (0) and CNAME record"
+
+n=$((n+1))
+echo_i "prime cache shortttl.cname.example (stale-answer-client-timeout off) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 shortttl.cname.example A > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "shortttl\.cname\.example\..*1.*IN.*CNAME.*longttl\.target\.example\." dig.out.test$n > /dev/null || ret=1
+grep "longttl\.target\.example\..*600.*IN.*A.*10\.53\.0\.2" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Allow RRset to become stale.
+sleep 1
+
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "check stale shortttl.cname.example comes from cache (stale-answer-client-timeout off) ($n)"
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 shortttl.cname.example A > dig.out.test$n
+wait_for_log 5 "shortttl.cname.example resolver failure, stale answer used" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "shortttl\.cname\.example\..*3.*IN.*CNAME.*longttl\.target\.example\." dig.out.test$n > /dev/null || ret=1
+# We can't reliably test the TTL of the longttl.target.example A record.
+grep "longttl\.target\.example\..*IN.*A.*10\.53\.0\.2" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check server is alive or restart ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 status > rndc.out.test$n 2>&1 || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+ echo_i "restart ns3"
+ start_server --noclean --restart --port ${PORT} serve-stale ns3
+fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check server is alive or restart ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 status > rndc.out.test$n 2>&1 || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+ echo_i "restart ns3"
+ start_server --noclean --restart --port ${PORT} serve-stale ns3
+fi
+status=$((status+ret))
+
+#############################################
+# Test for stale-answer-client-timeout 0. #
+#############################################
+echo_i "test stale-answer-client-timeout (0)"
+
+n=$((n+1))
+echo_i "updating ns3/named.conf ($n)"
+ret=0
+copy_setports ns3/named4.conf.in ns3/named.conf
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "restart ns3"
+stop_server --use-rndc --port ${CONTROLPORT} ns3
+start_server --noclean --restart --port ${PORT} ns3
+
+n=$((n+1))
+echo_i "prime cache data.example TXT (stale-answer-client-timeout 0)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache nodata.example TXT (stale-answer-client-timeout 0)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Allow RRset to become stale.
+sleep 2
+
+n=$((n+1))
+ret=0
+echo_i "check stale nodata.example TXT comes from cache (stale-answer-client-timeout 0) ($n)"
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$n
+wait_for_log 5 "nodata.example stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
+grep "example\..*3.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0) ($n)"
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+wait_for_log 5 "data.example stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+wait_for_rrset_refresh() {
+ $DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+ grep "status: NOERROR" dig.out.test$n > /dev/null || return 1
+ grep "EDE" dig.out.test$n > /dev/null && return 1
+ grep "ANSWER: 1," dig.out.test$n > /dev/null || return 1
+ grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || return 1
+}
+
+# This test ensures that after we get stale data due to
+# stale-answer-client-timeout 0, enabling the authoritative server will allow
+# the RRset to be updated.
+n=$((n+1))
+ret=0
+echo_i "check stale data.example TXT was refreshed (stale-answer-client-timeout 0) ($n)"
+retry_quiet 10 wait_for_rrset_refresh || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+wait_for_nodata_refresh() {
+ $DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$n
+ grep "status: NOERROR" dig.out.test$n > /dev/null || return 1
+ grep "ANSWER: 0," dig.out.test$n > /dev/null || return 1
+ grep "example\..*[12].*IN.*SOA" dig.out.test$n > /dev/null || return 1
+ return 0
+}
+
+n=$((n+1))
+ret=0
+echo_i "check stale nodata.example TXT was refreshed (stale-answer-client-timeout 0) ($n)"
+retry_quiet 10 wait_for_nodata_refresh || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+####################################################################
+# Test for stale-answer-client-timeout 0 and recursive-clients 10. #
+# CVE-2023-2911, GL #4089 #
+# ##################################################################
+echo_i "test stale-answer-client-timeout (0) and recursive-clients 10"
+
+n=$((n+1))
+echo_i "prime cache data.slow TXT (stale-answer-client-timeout 0) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 data.slow TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Run the following check twice. Sometimes a priming query interrupts the first
+# attempt to exceed the quota.
+attempt=0
+while [ $ret -eq 0 ] && [ $attempt -lt 2 ]; do
+ n=$((n+1))
+ echo_i "slow down response from authoritative server ($n)"
+ ret=0
+ $DIG -p ${PORT} @10.53.0.2 slowdown TXT > dig.out.test$n
+ grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+ grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ # Let the data.slow TTL expire
+ sleep 2
+
+ n=$((n+1))
+ echo_i "check that named survives reaching recursive-clients quota (stale-answer-client-timeout 0) ($n)"
+ ret=0
+ num=0
+ # Attempt to exceed the configured value of 'recursive-clients 10;' by running
+ # 20 parallel queries for the stale domain which has slow auth.
+ while [ $num -lt 20 ]; do
+ $DIG +tries=1 +timeout=10 -p ${PORT} @10.53.0.3 data.slow TXT >/dev/null 2>&1 &
+ num=$((num+1))
+ done;
+ # Let the dig processes finish.
+ wait
+ retry_quiet 5 check_server_responds || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ attempt=$((attempt+1))
+done
+
+# Restart ns3 to avoid the exceeded recursive-clients limit from previous check
+# to interfere with subsequent checks.
+echo_i "restart ns3"
+stop_server --use-rndc --port ${CONTROLPORT} ns3
+start_server --noclean --restart --port ${PORT} ns3
+
+############################################################
+# Test for stale-answer-client-timeout 0 and CNAME record. #
+############################################################
+echo_i "test stale-answer-client-timeout (0) and CNAME record"
+
+n=$((n+1))
+echo_i "prime cache cname1.stale.test A (stale-answer-client-timeout 0) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 cname1.stale.test A > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "cname1\.stale\.test\..*1.*IN.*CNAME.*a1\.stale\.test\." dig.out.test$n > /dev/null || ret=1
+grep "a1\.stale\.test\..*1.*IN.*A.*192\.0\.2\.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Allow RRset to become stale.
+sleep 1
+
+n=$((n+1))
+ret=0
+echo_i "check stale cname1.stale.test A comes from cache (stale-answer-client-timeout 0) ($n)"
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 cname1.stale.test A > dig.out.test$n
+wait_for_log 5 "cname1.stale.test stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "cname1\.stale\.test\..*3.*IN.*CNAME.*a1\.stale\.test\." dig.out.test$n > /dev/null || ret=1
+grep "a1\.stale\.test\..*3.*IN.*A.*192\.0\.2\.1" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check server is alive or restart ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 status > rndc.out.test$n 2>&1 || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+ echo_i "restart ns3"
+ start_server --noclean --restart --port ${PORT} ns3
+fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache cname2.stale.test A (stale-answer-client-timeout 0) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 cname2.stale.test A > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "cname2\.stale\.test\..*1.*IN.*CNAME.*a2\.stale\.test\." dig.out.test$n > /dev/null || ret=1
+grep "a2\.stale\.test\..*300.*IN.*A.*192\.0\.2\.2" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Allow CNAME record in the RRSET to become stale.
+sleep 1
+
+n=$((n+1))
+ret=0
+echo_i "check stale cname2.stale.test A comes from cache (stale-answer-client-timeout 0) ($n)"
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 cname2.stale.test A > dig.out.test$n
+wait_for_log 5 "cname2.stale.test stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "cname2\.stale\.test\..*3.*IN.*CNAME.*a2\.stale\.test\." dig.out.test$n > /dev/null || ret=1
+# We can't reliably test the TTL of the a2.stale.test A record.
+grep "a2\.stale\.test\..*IN.*A.*192\.0\.2\.2" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check server is alive or restart ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 status > rndc.out.test$n 2>&1 || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+ echo_i "restart ns3"
+ start_server --noclean --restart --port ${PORT} ns3
+fi
+status=$((status+ret))
+
+####################################################################
+# Test for stale-answer-client-timeout 0 and stale-refresh-time 4. #
+####################################################################
+echo_i "test stale-answer-client-timeout (0) and stale-refresh-time (4)"
+
+n=$((n+1))
+echo_i "updating ns3/named.conf ($n)"
+ret=0
+copy_setports ns3/named5.conf.in ns3/named.conf
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "running 'rndc reload' ($n)"
+ret=0
+rndc_reload ns3 10.53.0.3
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "flush cache, enable responses from authoritative server ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 flushtree example > rndc.out.test$n.1 2>&1 || ret=1
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "prime cache data.example TXT (stale-answer-client-timeout 0, stale-refresh-time 4) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Allow RRset to become stale.
+sleep 2
+
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+wait_for_log 5 "data.example stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# This test ensures that after we get stale data due to
+# stale-answer-client-timeout 0, enabling the authoritative server will allow
+# the RRset to be updated.
+n=$((n+1))
+ret=0
+echo_i "check stale data.example TXT was refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
+retry_quiet 10 wait_for_rrset_refresh || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Allow RRset to become stale.
+sleep 2
+
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+wait_for_log 5 "data.example stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Allow stale-refresh-time to be activated.
+n=$((n+1))
+ret=0
+echo_i "wait until resolver query times out, activating stale-refresh-time"
+wait_for_log 15 "data.example resolver failure, stale answer used" ns3/named.run || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "check stale data.example TXT comes from cache within stale-refresh-time (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+wait_for_log 5 "data.example query within stale refresh time" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "enable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# We give BIND some time to ensure that after we enable authoritative server,
+# this RRset is still not refreshed because it was hit during
+# stale-refresh-time window.
+sleep 1
+
+n=$((n+1))
+ret=0
+echo_i "check stale data.example TXT was not refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+wait_for_log 5 "data.example query within stale refresh time" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# After the refresh-time-window, the RRset will be refreshed.
+sleep 4
+
+n=$((n+1))
+ret=0
+echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+wait_for_log 5 "data.example stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+ret=0
+echo_i "check stale data.example TXT was refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE" dig.out.test$n > /dev/null && ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+####################################################################
+# Test serve-stale's interaction with fetch limits (cache only) #
+#################################################################
+echo_i "test serve-stale's interaction with fetch-limits (cache only)"
+
+# We update the named configuration to enable fetch-limits. The fetch-limits
+# are set to 1, which is ridiciously low, but that is because for this test we
+# want to reach the fetch-limits.
+n=$((n+1))
+echo_i "updating ns3/named.conf ($n)"
+ret=0
+copy_setports ns3/named6.conf.in ns3/named.conf
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "running 'rndc reload' ($n)"
+ret=0
+rndc_reload ns3 10.53.0.3
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Disable responses from authoritative server. If we can't resolve the example
+# zone, fetch limits will be reached.
+n=$((n+1))
+echo_i "disable responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Allow RRset to become stale.
+sleep 2
+
+# Turn on serve-stale.
+n=$((n+1))
+echo_i "running 'rndc serve-stale on' ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 serve-stale on || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=4)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Hit the fetch-limits. We burst the name server with a small batch of queries.
+# Only 2 queries are required to hit the fetch-limits. The first query will
+# start to resolve, the second one hit the fetch-limits.
+burst() {
+ num=${1}
+ rm -f burst.input.$$
+ while [ $num -gt 0 ]; do
+ num=$((num - 1))
+ echo "fetch${num}.example A" >> burst.input.$$
+ done
+ $PERL ../ditch.pl -p ${PORT} -s 10.53.0.3 burst.input.$$
+ rm -f burst.input.$$
+}
+
+wait_for_fetchlimits() {
+ burst 2
+ # We expect a query for nx.example to fail because fetch-limits for
+ # the domain 'example.' (and everything below) has been reached.
+ $DIG -p ${PORT} +tries=1 +timeout=1 @10.53.0.3 nx.example > dig.out.test$n
+ grep "status: SERVFAIL" dig.out.test$n > /dev/null || return 1
+}
+
+n=$((n+1))
+echo_i "hit fetch limits ($n)"
+ret=0
+retry_quiet 10 wait_for_fetchlimits || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Expect stale data now (because fetch-limits for the domain 'example.' (and
+# everything below) has been reached. But we have a stale RRset for
+# 'data.example/TXT' that can be used.
+n=$((n+1))
+ret=0
+echo_i "check stale data.example TXT comes from cache (fetch-limits) ($n)"
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+wait_for_log 5 "data.example resolver failure, stale answer used" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# The previous query should not have started the stale-refresh-time window.
+n=$((n+1))
+ret=0
+echo_i "check stale data.example TXT comes from cache again (fetch-limits) ($n)"
+nextpart ns3/named.run > /dev/null
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
+wait_for_log 5 "data.example resolver failure, stale answer used" ns3/named.run || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "EDE: 3 (Stale Answer): (resolver failure" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+########################################################################
+# Test serve-stale's interaction with fetch limits (dual-mode) #
+########################################################################
+echo_i "test serve-stale's interaction with fetch limits (dual-mode)"
+
+# Update named configuration so that ns3 becomes a recursive resolver which is
+# also a secondary server for the root zone.
+n=$((n+1))
+echo_i "updating ns3/named.conf ($n)"
+ret=0
+copy_setports ns3/named7.conf.in ns3/named.conf
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "running 'rndc reload' ($n)"
+ret=0
+rndc_reload ns3 10.53.0.3
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check 'rndc serve-stale status' ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=4)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Flush the cache to ensure the example/NS RRset cached during previous tests
+# does not override the authoritative delegation found in the root zone.
+n=$((n+1))
+echo_i "flush cache ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 flush > rndc.out.test$n 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Test that after flush, serve-stale configuration is not reset.
+n=$((n+1))
+echo_i "check serve-stale configuration is not reset after flush ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 serve-stale status > rndc.out.test$n 2>&1 || ret=1
+grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=4)' rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Query name server with low fetch limits. The authoritative server (ans2) is
+# not responding. Sending queries for multiple names in the 'example' zone
+# in parallel causes the fetch limit for that zone (set to 1) to be
+# reached. This should not trigger a crash.
+echo_i "sending queries for tests $((n+1))-$((n+4))..."
+$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$((n+1)) &
+$DIG -p ${PORT} @10.53.0.3 othertype.example CAA > dig.out.test$((n+2)) &
+$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$((n+3)) &
+$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT > dig.out.test$((n+4)) &
+
+wait
+
+# Expect SERVFAIL for the entries not in cache.
+n=$((n+1))
+echo_i "check stale data.example TXT (fetch-limits dual-mode) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale othertype.example CAA (fetch-limits dual-mode) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nodata.example TXT (fetch-limits dual-mode) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check stale nxdomain.example TXT (fetch-limits dual-mode) ($n)"
+ret=0
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check DNS64 processing of a stale negative answer ($n)"
+ret=0
+# configure ns3 with dns64
+copy_setports ns3/named8.conf.in ns3/named.conf
+rndc_reload ns3 10.53.0.3
+# flush cache, enable ans2 responses, make sure serve-stale is on
+$RNDCCMD 10.53.0.3 flush > rndc.out.test$n.1 2>&1 || ret=1
+$DIG -p ${PORT} @10.53.0.2 txt enable > /dev/null
+$RNDCCMD 10.53.0.3 serve-stale on > rndc.out.test$n.2 2>&1 || ret=1
+# prime the cache with an AAAA NXRRSET response
+$DIG -p ${PORT} @10.53.0.3 a-only.example AAAA > dig.out.1.test$n
+grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
+grep "2001:aaaa" dig.out.1.test$n > /dev/null || ret=1
+# disable responses from the auth server
+$DIG -p ${PORT} @10.53.0.2 txt disable > /dev/null
+# wait two seconds for the previous answer to become stale
+sleep 2
+# resend the query and wait in the background; we should get a stale answer
+$DIG -p ${PORT} @10.53.0.3 a-only.example AAAA > dig.out.2.test$n &
+# re-enable queries after a pause, so the server gets a real answer too
+sleep 2
+$DIG -p ${PORT} @10.53.0.2 txt enable > /dev/null
+wait
+grep "status: NOERROR" dig.out.2.test$n > /dev/null || ret=1
+grep "2001:aaaa" dig.out.2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+###########################################################
+# Test serve-stale's interaction with prefetch processing #
+###########################################################
+echo_i "test serve-stale's interaction with prefetch processing"
+
+# Test case for #2733, ensuring that prefetch queries do not trigger
+# a lookup due to stale-answer-client-timeout.
+#
+# 1. Cache the following records:
+# cname.example 7 IN CNAME target.example.
+# target.example 9 IN A <addr>.
+# 2. Let the CNAME RRset expire.
+# 3. Query for 'cname.example/A'.
+#
+# This starts recursion because cname.example/CNAME is expired.
+# The authoritative server is up so likely it will respond before
+# stale-answer-client-timeout is triggered.
+# The 'target.example/A' RRset is found in cache with a positive value
+# and is eligble for prefetching.
+# A prefetch is done for 'target.example/A', our ans2 server will
+# delay the request.
+# The 'prefetch_done()' callback should have the right event type
+# (DNS_EVENT_FETCHDONE).
+
+# flush cache
+n=$((n+1))
+echo_i "flush cache ($n)"
+ret=0
+$RNDCCMD 10.53.0.3 flushtree example > rndc.out.test$n.1 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# prime the cache with CNAME and A; CNAME expires sooner
+n=$((n+1))
+echo_i "prime cache cname.example A (stale-answer-client-timeout 1.8) ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 cname.example A > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "cname\.example\..*7.*IN.*CNAME.*target\.example\." dig.out.test$n > /dev/null || ret=1
+grep "target\.example\..*9.*IN.*A" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# wait for the CNAME to be stale; A will still be valid and in prefetch window.
+# (the longer TTL is needed, otherwise data won't be prefetch-eligible.)
+sleep 7
+
+# re-enable auth responses, but with a delay answering the A
+n=$((n+1))
+echo_i "delay responses from authoritative server ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.2 txt slowdown > dig.out.test$n
+grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
+grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# resend the query and wait in the background; we should get a stale answer
+n=$((n+1))
+echo_i "check prefetch processing of a stale CNAME target ($n)"
+ret=0
+$DIG -p ${PORT} @10.53.0.3 cname.example A > dig.out.test$n &
+sleep 2
+wait
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1
+grep "cname\.example\..*7.*IN.*CNAME.*target\.example\." dig.out.test$n > /dev/null || ret=1
+grep "target\.example\..*[1-2].*IN.*A" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/serve-stale/tests_sh_serve_stale.py b/bin/tests/system/serve-stale/tests_sh_serve_stale.py
new file mode 100644
index 0000000..3e6d3a1
--- /dev/null
+++ b/bin/tests/system/serve-stale/tests_sh_serve_stale.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_serve_stale(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/setup.sh b/bin/tests/system/setup.sh
new file mode 100644
index 0000000..23145fa
--- /dev/null
+++ b/bin/tests/system/setup.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Run a system test.
+#
+
+. ./conf.sh
+
+test $# -gt 0 || { echo "usage: $0 test-directory" >&2; exit 1; }
+
+test=$1
+shift
+
+test -d $test || { echo "$0: $test: no such test" >&2; exit 1; }
+
+# Set up any dynamically generated test data
+if test -f $test/setup.sh
+then
+ ( cd $test && $SHELL setup.sh "$@" )
+fi
+
+
diff --git a/bin/tests/system/sfcache/README b/bin/tests/system/sfcache/README
new file mode 100644
index 0000000..91b2126
--- /dev/null
+++ b/bin/tests/system/sfcache/README
@@ -0,0 +1,19 @@
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+
+The test setup for the SERVFAIL ncache tests has a secure root.
+
+ns1 is the root server.
+
+ns2 is an authoritative server for the various test domains.
+
+ns5 is a caching-only server, configured with the an incorrect trusted
+key for the root. It is used for testing failure cases.
diff --git a/bin/tests/system/sfcache/clean.sh b/bin/tests/system/sfcache/clean.sh
new file mode 100644
index 0000000..e8bd818
--- /dev/null
+++ b/bin/tests/system/sfcache/clean.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f ./*/K*.key ./*/K*.private ./*/*.signed ./*/*.db ./*/dsset-*
+rm -f ./*/managed.conf ./*/trusted.conf
+rm -f ./*/named.memstats
+rm -f ./*/named.conf
+rm -f ./*/named.run ./*/named.run.prev
+rm -f ./dig.*
+rm -f ./rndc.*
+rm -f ./sfcache.*
+rm -f ./ns*/managed-keys.bind*
+rm -f ./ns*/named.lock
+rm -f ./ns5/named.run.part*
+rm -f ./ns5/named_dump*
diff --git a/bin/tests/system/sfcache/ns1/named.conf.in b/bin/tests/system/sfcache/ns1/named.conf.in
new file mode 100644
index 0000000..4a9822d
--- /dev/null
+++ b/bin/tests/system/sfcache/ns1/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/sfcache/ns1/root.db.in b/bin/tests/system/sfcache/ns1/root.db.in
new file mode 100644
index 0000000..1deb998
--- /dev/null
+++ b/bin/tests/system/sfcache/ns1/root.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example2. NS ns2.example2.
+ns2.example2. A 10.53.0.2
diff --git a/bin/tests/system/sfcache/ns1/sign.sh b/bin/tests/system/sfcache/ns1/sign.sh
new file mode 100644
index 0000000..a94ad58
--- /dev/null
+++ b/bin/tests/system/sfcache/ns1/sign.sh
@@ -0,0 +1,38 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+(cd ../ns2 && $SHELL sign.sh )
+
+cp "../ns2/dsset-example." .
+
+keyname=$($KEYGEN -q -a "${DEFAULT_ALGORITHM}" -b "${DEFAULT_BITS}" -n zone $zone)
+
+cat "$infile" "$keyname.key" > "$zonefile"
+
+$SIGNER -P -g -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a static key.
+keyfile_to_static_ds "$keyname" > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+
+# ...or with an initializing key.
+keyfile_to_initial_ds "$keyname" > managed.conf
diff --git a/bin/tests/system/sfcache/ns2/example.db.in b/bin/tests/system/sfcache/ns2/example.db.in
new file mode 100644
index 0000000..c035ee8
--- /dev/null
+++ b/bin/tests/system/sfcache/ns2/example.db.in
@@ -0,0 +1,103 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+
+; Used for testing ANY queries
+foo TXT "testing"
+foo A 10.0.1.0
+
+bad-cname CNAME a
+bad-dname DNAME @
+
+; Used for testing CNAME queries
+cname1 CNAME cname1-target
+cname1-target TXT "testing cname"
+
+cname2 CNAME cname2-target
+cname2-target TXT "testing cname"
+
+; Used for testing DNAME queries
+dname1 DNAME dname1-target
+foo.dname1-target TXT "testing dname"
+
+dname2 DNAME dname2-target
+foo.dname2-target TXT "testing dname"
+
+; A secure subdomain
+secure NS ns.secure
+ns.secure A 10.53.0.3
+
+; An insecure subdomain
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+
+; A secure subdomain we're going to inject bogus data into
+bogus NS ns.bogus
+ns.bogus A 10.53.0.3
+
+; A dynamic secure subdomain
+dynamic NS dynamic
+dynamic A 10.53.0.3
+
+; A insecure subdomain
+mustbesecure NS ns.mustbesecure
+ns.mustbesecure A 10.53.0.3
+
+; A rfc2535 signed zone w/ CNAME
+rfc2535 NS ns.rfc2535
+ns.rfc2535 A 10.53.0.3
+
+z A 10.0.0.26
+
+keyless NS ns.keyless
+ns.keyless A 10.53.0.3
+
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+
+optout NS ns.optout
+ns.optout A 10.53.0.3
+
+nsec3-unknown NS ns.nsec3-unknown
+ns.nsec3-unknown A 10.53.0.3
+
+optout-unknown NS ns.optout-unknown
+ns.optout-unknown A 10.53.0.3
+
+multiple NS ns.multiple
+ns.multiple A 10.53.0.3
+
+*.wild A 10.0.0.27
+
+rsasha256 NS ns.rsasha256
+ns.rsasha256 A 10.53.0.3
+
+rsasha512 NS ns.rsasha512
+ns.rsasha512 A 10.53.0.3
+
+kskonly NS ns.kskonly
+ns.kskonly A 10.53.0.3
diff --git a/bin/tests/system/sfcache/ns2/named.conf.in b/bin/tests/system/sfcache/ns2/named.conf.in
new file mode 100644
index 0000000..afb5a86
--- /dev/null
+++ b/bin/tests/system/sfcache/ns2/named.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db.signed";
+ allow-update { any; };
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/sfcache/ns2/sign.sh b/bin/tests/system/sfcache/ns2/sign.sh
new file mode 100644
index 0000000..038d079
--- /dev/null
+++ b/bin/tests/system/sfcache/ns2/sign.sh
@@ -0,0 +1,28 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+keyname1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+keyname2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$keyname1.key" "$keyname2.key" > "$zonefile"
+
+"$SIGNER" -P -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" > /dev/null
diff --git a/bin/tests/system/sfcache/ns5/named.conf.in b/bin/tests/system/sfcache/ns5/named.conf.in
new file mode 100644
index 0000000..272d65b
--- /dev/null
+++ b/bin/tests/system/sfcache/ns5/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+ servfail-ttl 30;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/sfcache/ns5/sign.sh b/bin/tests/system/sfcache/ns5/sign.sh
new file mode 100644
index 0000000..6ca88de
--- /dev/null
+++ b/bin/tests/system/sfcache/ns5/sign.sh
@@ -0,0 +1,21 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone ".")
+
+keyfile_to_static_ds "$keyname" > trusted.conf
diff --git a/bin/tests/system/sfcache/setup.sh b/bin/tests/system/sfcache/setup.sh
new file mode 100644
index 0000000..a51b814
--- /dev/null
+++ b/bin/tests/system/sfcache/setup.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns5/named.conf.in ns5/named.conf
+
+cd ns1 && $SHELL sign.sh && cd ..
+cd ns5 && $SHELL sign.sh && cd ..
diff --git a/bin/tests/system/sfcache/tests.sh b/bin/tests/system/sfcache/tests.sh
new file mode 100644
index 0000000..d2aeee7
--- /dev/null
+++ b/bin/tests/system/sfcache/tests.sh
@@ -0,0 +1,107 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+dig_with_opts() {
+ "$DIG" +tcp +noadd +nosea +nostat +nocmd -p "$PORT" "$@"
+}
+
+rndc_with_opts() {
+ "$RNDC" -c ../common/rndc.conf -p "$CONTROLPORT" -s "$@"
+}
+
+echo_i "checking DNSSEC SERVFAIL is cached ($n)"
+ret=0
+dig_with_opts +dnssec foo.example. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
+rndc_dumpdb ns5 -all
+awk '/Zone/{out=0} { if (out) print } /SERVFAIL/{out=1}' ns5/named_dump.db.test$n > sfcache.$n
+grep "^; foo.example/A" sfcache.$n > /dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking SERVFAIL is returned from cache ($n)"
+ret=0
+dig_with_opts +dnssec foo.example. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking that +cd bypasses cache check ($n)"
+ret=0
+dig_with_opts +dnssec +cd foo.example. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "SERVFAIL" dig.out.ns5.test$n > /dev/null && ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "switching to non-dnssec SERVFAIL tests"
+ret=0
+rndc_with_opts 10.53.0.5 flush 2>&1 | sed 's/^/I:ns5 /'
+rndc_dumpdb ns5 -all
+mv ns5/named_dump.db.test$n ns5/named_dump.db.test$n.1
+awk '/SERVFAIL/ { next; out=1 } /Zone/ { out=0 } { if (out) print }' ns5/named_dump.db.test$n.1 > sfcache.$n.1
+[ -s "sfcache.$n.1" ] && ret=1
+echo_i "checking SERVFAIL is cached ($n)"
+dig_with_opts bar.example2. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
+rndc_dumpdb ns5 -all
+mv ns5/named_dump.db.test$n ns5/named_dump.db.test$n.2
+awk '/Zone/{out=0} { if (out) print } /SERVFAIL/{out=1}' ns5/named_dump.db.test$n.2 > sfcache.$n.2
+grep "^; bar.example2/A" sfcache.$n.2 > /dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking SERVFAIL is returned from cache ($n)"
+ret=0
+nextpart ns5/named.run > /dev/null
+dig_with_opts bar.example2. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+nextpart ns5/named.run > ns5/named.run.part$n
+grep 'servfail cache hit bar.example2/A (CD=0)' ns5/named.run.part$n > /dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking cache is bypassed with +cd query ($n)"
+ret=0
+dig_with_opts +cd bar.example2. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+nextpart ns5/named.run > ns5/named.run.part$n
+grep 'servfail cache hit' ns5/named.run.part$n > /dev/null && ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "checking cache is used for subsequent +cd query ($n)"
+ret=0
+dig_with_opts +dnssec bar.example2. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+nextpart ns5/named.run > ns5/named.run.part$n
+grep 'servfail cache hit bar.example2/A (CD=1)' ns5/named.run.part$n > /dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/sfcache/tests_sh_sfcache.py b/bin/tests/system/sfcache/tests_sh_sfcache.py
new file mode 100644
index 0000000..d323b39
--- /dev/null
+++ b/bin/tests/system/sfcache/tests_sh_sfcache.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_sfcache(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/shutdown/clean.sh b/bin/tests/system/shutdown/clean.sh
new file mode 100644
index 0000000..d958521
--- /dev/null
+++ b/bin/tests/system/shutdown/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/*.jnl
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/rpz*.txt
+rm -f */named.conf
+rm -f */named.run
+rm -rf __pycache__
diff --git a/bin/tests/system/shutdown/ns1/named.conf.in b/bin/tests/system/shutdown/ns1/named.conf.in
new file mode 100644
index 0000000..f0f5210
--- /dev/null
+++ b/bin/tests/system/shutdown/ns1/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ listen-on { 10.53.0.1; };
+ pid-file "named.pid";
+ notify no;
+ dnssec-validation no;
+ allow-query { any; };
+ recursion yes;
+ allow-recursion { any; };
+};
+
+# Delegate .test domain to 10.53.0.2
+zone "." {
+ type primary;
+ file "root.db";
+ allow-transfer { none; };
+};
diff --git a/bin/tests/system/shutdown/ns1/root.db b/bin/tests/system/shutdown/ns1/root.db
new file mode 100644
index 0000000..60f1b30
--- /dev/null
+++ b/bin/tests/system/shutdown/ns1/root.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA a.root. root.test. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+
+. IN NS a.root.
+a.root. IN A 10.53.0.1
+
+test IN NS ns1.test
+ns1.test IN A 10.53.0.2
diff --git a/bin/tests/system/shutdown/ns2/named.conf.in b/bin/tests/system/shutdown/ns2/named.conf.in
new file mode 100644
index 0000000..2ed91dc
--- /dev/null
+++ b/bin/tests/system/shutdown/ns2/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ listen-on { 10.53.0.2; };
+ pid-file "named.pid";
+ notify no;
+ dnssec-validation no;
+ allow-query { any; };
+};
+
+# 10.53.0.2 is authoritative for .test domain
+zone "test" {
+ type primary;
+ file "test.db";
+ allow-transfer { none; };
+};
diff --git a/bin/tests/system/shutdown/ns2/test.db b/bin/tests/system/shutdown/ns2/test.db
new file mode 100644
index 0000000..91c16ec
--- /dev/null
+++ b/bin/tests/system/shutdown/ns2/test.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+
+@ IN SOA ns1 root.test. 2020040101 4h 1h 1w 60
+@ IN NS ns1
+ns1 IN A 10.53.0.2
+@ IN A 10.53.0.2
+www IN A 10.53.0.2
diff --git a/bin/tests/system/shutdown/resolver/named.conf.in b/bin/tests/system/shutdown/resolver/named.conf.in
new file mode 100644
index 0000000..5007579
--- /dev/null
+++ b/bin/tests/system/shutdown/resolver/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+logging {
+ channel basic {
+ file "named.run";
+ severity debug 999;
+ print-time yes;
+ };
+ category default { basic; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ listen-on { 10.53.0.3; };
+ pid-file "named.pid";
+ notify no;
+ dnssec-validation no;
+ allow-query { any; };
+ allow-recursion { any; };
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
diff --git a/bin/tests/system/shutdown/resolver/root.db b/bin/tests/system/shutdown/resolver/root.db
new file mode 100644
index 0000000..88e0ba8
--- /dev/null
+++ b/bin/tests/system/shutdown/resolver/root.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA a.root. root.root. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. IN NS a.root.
+a.root. IN A 10.53.0.1
diff --git a/bin/tests/system/shutdown/setup.sh b/bin/tests/system/shutdown/setup.sh
new file mode 100644
index 0000000..cdeab82
--- /dev/null
+++ b/bin/tests/system/shutdown/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# touch dnsrps-off to not test with DNSRPS
+
+set -e
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports resolver/named.conf.in resolver/named.conf
diff --git a/bin/tests/system/shutdown/tests_shutdown.py b/bin/tests/system/shutdown/tests_shutdown.py
new file mode 100755
index 0000000..89cada2
--- /dev/null
+++ b/bin/tests/system/shutdown/tests_shutdown.py
@@ -0,0 +1,206 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from concurrent.futures import ThreadPoolExecutor, as_completed
+import os
+import random
+import signal
+import subprocess
+from string import ascii_lowercase as letters
+import time
+
+import pytest
+
+pytest.importorskip("dns", minversion="2.0.0")
+import dns.exception
+import dns.resolver
+
+
+def do_work(named_proc, resolver, rndc_cmd, kill_method, n_workers, n_queries):
+ """Creates a number of A queries to run in parallel
+ in order simulate a slightly more realistic test scenario.
+
+ The main idea of this function is to create and send a bunch
+ of A queries to a target named instance and during this process
+ a request for shutting down named will be issued.
+
+ In the process of shutting down named, a couple control connections
+ are created (by launching rndc) to ensure that the crash was fixed.
+
+ if kill_method=="rndc" named will be asked to shutdown by
+ means of rndc stop.
+ if kill_method=="sigterm" named will be killed by SIGTERM on
+ POSIX systems or by TerminateProcess() on Windows systems.
+
+ :param named_proc: named process instance
+ :type named_proc: subprocess.Popen
+
+ :param resolver: target resolver
+ :type resolver: dns.resolver.Resolver
+
+ :param rndc_cmd: rndc command with default arguments
+ :type rndc_cmd: list of strings, e.g. ["rndc", "-p", "23750"]
+
+ :kill_method: "rndc" or "sigterm"
+ :type kill_method: str
+
+ :param n_workers: Number of worker threads to create
+ :type n_workers: int
+
+ :param n_queries: Total number of queries to send
+ :type n_queries: int
+ """
+ # pylint: disable-msg=too-many-arguments
+ # pylint: disable-msg=too-many-locals
+
+ # helper function, args must be a list or tuple with arguments to rndc.
+ def launch_rndc(args):
+ return subprocess.call(rndc_cmd + args, timeout=10)
+
+ # We're going to execute queries in parallel by means of a thread pool.
+ # dnspython functions block, so we need to circunvent that.
+ with ThreadPoolExecutor(n_workers + 1) as executor:
+ # Helper dict, where keys=Future objects and values are tags used
+ # to process results later.
+ futures = {}
+
+ # 50% of work will be A queries.
+ # 1 work will be rndc stop.
+ # Remaining work will be rndc status (so we test parallel control
+ # connections that were crashing named).
+ shutdown = True
+ for i in range(n_queries):
+ if i < (n_queries // 2):
+ # Half work will be standard A queries.
+ # Among those we split 50% queries relname='www',
+ # 50% queries relname=random characters
+ if random.randrange(2) == 1:
+ tag = "good"
+ relname = "www"
+ else:
+ tag = "bad"
+ length = random.randint(4, 10)
+ relname = "".join(
+ letters[random.randrange(len(letters))] for i in range(length)
+ )
+
+ qname = relname + ".test"
+ futures[executor.submit(resolver.resolve, qname, "A")] = tag
+ elif shutdown: # We attempt to stop named in the middle
+ shutdown = False
+ if kill_method == "rndc":
+ futures[executor.submit(launch_rndc, ["stop"])] = "stop"
+ else:
+ futures[executor.submit(named_proc.terminate)] = "kill"
+ else:
+ # We attempt to send couple rndc commands while named is
+ # being shutdown
+ futures[executor.submit(launch_rndc, ["status"])] = "status"
+
+ ret_code = -1
+ for future in as_completed(futures):
+ try:
+ result = future.result()
+ # If tag is "stop", result is an instance of
+ # subprocess.CompletedProcess, then we check returncode
+ # attribute to know if rncd stop command finished successfully.
+ #
+ # if tag is "kill" then the main function will check if
+ # named process exited gracefully after SIGTERM signal.
+ if futures[future] == "stop":
+ ret_code = result
+
+ except (
+ dns.resolver.NXDOMAIN,
+ dns.resolver.NoNameservers,
+ dns.exception.Timeout,
+ ):
+ pass
+
+ if kill_method == "rndc":
+ assert ret_code == 0
+
+
+def wait_for_named_loaded(resolver, retries=10):
+ for _ in range(retries):
+ try:
+ resolver.resolve("version.bind", "TXT", "CH")
+ return True
+ except (dns.resolver.NoNameservers, dns.exception.Timeout):
+ time.sleep(1)
+ return False
+
+
+def wait_for_proc_termination(proc, max_timeout=10):
+ for _ in range(max_timeout):
+ if proc.poll() is not None:
+ return True
+ time.sleep(1)
+
+ proc.send_signal(signal.SIGABRT)
+ for _ in range(max_timeout):
+ if proc.poll() is not None:
+ return True
+ time.sleep(1)
+
+ return False
+
+
+# We test named shutting down using two methods:
+# Method 1: using rndc ctop
+# Method 2: killing with SIGTERM
+# In both methods named should exit gracefully.
+@pytest.mark.parametrize("kill_method", ["rndc", "sigterm"])
+def test_named_shutdown(named_port, control_port, kill_method):
+ # pylint: disable-msg=too-many-locals
+ cfg_dir = os.path.join(os.getcwd(), "resolver")
+ assert os.path.isdir(cfg_dir)
+
+ cfg_file = os.path.join(cfg_dir, "named.conf")
+ assert os.path.isfile(cfg_file)
+
+ named = os.getenv("NAMED")
+ assert named is not None
+
+ rndc = os.getenv("RNDC")
+ assert rndc is not None
+
+ # rndc configuration resides in ../common/rndc.conf
+ rndc_cfg = os.path.join("..", "common", "rndc.conf")
+ assert os.path.isfile(rndc_cfg)
+
+ # rndc command with default arguments.
+ rndc_cmd = [rndc, "-c", rndc_cfg, "-p", str(control_port), "-s", "10.53.0.3"]
+
+ # We create a resolver instance that will be used to send queries.
+ resolver = dns.resolver.Resolver()
+ resolver.nameservers = ["10.53.0.3"]
+ resolver.port = named_port
+
+ named_cmdline = [named, "-c", cfg_file, "-f"]
+ with subprocess.Popen(named_cmdline, cwd=cfg_dir) as named_proc:
+ try:
+ assert named_proc.poll() is None, "named isn't running"
+ assert wait_for_named_loaded(resolver)
+ do_work(
+ named_proc,
+ resolver,
+ rndc_cmd,
+ kill_method,
+ n_workers=12,
+ n_queries=16,
+ )
+ assert wait_for_proc_termination(named_proc)
+ assert named_proc.returncode == 0, "named crashed"
+ finally: # Ensure named is terminated in case of an exception
+ named_proc.kill()
diff --git a/bin/tests/system/smartsign/child.db b/bin/tests/system/smartsign/child.db
new file mode 100644
index 0000000..878df45
--- /dev/null
+++ b/bin/tests/system/smartsign/child.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 60 ; 1 minute
+child.parent.nil IN SOA ns.child.parent.nil. hostmaster.parent.nil. (
+ 1 ; serial
+ 2000 ; refresh (33 minutes 20 seconds)
+ 2000 ; retry (33 minutes 20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns.child.parent.nil.
+$ORIGIN child.parent.nil.
+$TTL 300 ; 5 minutes
+ns A 10.53.0.3
diff --git a/bin/tests/system/smartsign/clean.sh b/bin/tests/system/smartsign/clean.sh
new file mode 100644
index 0000000..ad975af
--- /dev/null
+++ b/bin/tests/system/smartsign/clean.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f K* dsset-* *.signed dnskey.sigs other.sigs dsset.out
+rm -f ns*/named.lock
diff --git a/bin/tests/system/smartsign/parent.db b/bin/tests/system/smartsign/parent.db
new file mode 100644
index 0000000..a5484e3
--- /dev/null
+++ b/bin/tests/system/smartsign/parent.db
@@ -0,0 +1,31 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+parent.nil IN SOA ns1.parent.nil. hostmaster.parent.nil. (
+ 1 ; serial
+ 2000 ; refresh (33 minutes 20 seconds)
+ 2000 ; retry (33 minutes 20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns1.parent.nil.
+ NS ns2.parent.nil.
+$ORIGIN parent.nil.
+$TTL 3600 ; 1 hour
+a A 1.1.1.1
+$TTL 300 ; 5 minutes
+ns1 A 10.53.0.1
+ns2 A 10.53.0.2
+
+child NS ns.child
+ns.child A 10.53.0.3
diff --git a/bin/tests/system/smartsign/tests.sh b/bin/tests/system/smartsign/tests.sh
new file mode 100644
index 0000000..1da21bf
--- /dev/null
+++ b/bin/tests/system/smartsign/tests.sh
@@ -0,0 +1,369 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+
+pzone=parent.nil
+pfile=parent.db
+
+czone=child.parent.nil
+cfile=child.db
+
+echo_i "generating child's keys"
+# active zsk
+czsk1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -L 30 $czone)
+
+# not yet published or active
+czsk2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -P none -A none $czone)
+
+# published but not active
+czsk3=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -A none $czone)
+
+# inactive
+czsk4=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -P now-24h -A now-24h -I now $czone)
+
+# active in 12 hours, inactive 12 hours after that...
+czsk5=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -P now+12h -A now+12h -I now+24h $czone)
+
+# explicit successor to czk5
+# (suppressing warning about lack of removal date)
+czsk6=$($KEYGEN -q -S $czsk5 -i 6h 2>/dev/null)
+
+# active ksk
+cksk1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk -L 30 $czone)
+
+# published but not YET active; will be active in 20 seconds
+cksk2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $czone)
+# $SETTIME moved after other $KEYGENs
+
+echo_i "revoking key"
+# revoking key changes its ID
+cksk3=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $czone)
+cksk4=$($REVOKE $cksk3)
+
+echo_i "setting up sync key"
+cksk5=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk -P now+1mo -A now+1mo -Psync now $czone)
+
+echo_i "and future sync key"
+cksk6=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk -P now+1mo -A now+1mo -Psync now+1mo $czone)
+
+echo_i "generating parent keys"
+pzsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $pzone)
+pksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $pzone)
+
+echo_i "setting child's activation time"
+# using now+30s to fix RT 24561
+$SETTIME -A now+30s $cksk2 > /dev/null
+
+echo_i "signing child zone"
+czoneout=$($SIGNER -Sg -e now+1d -X now+2d -o $czone $cfile)
+
+echo_i "signing parent zone"
+pzoneout=$($SIGNER -Sg -o $pzone $pfile)
+
+czactive=$(keyfile_to_key_id $czsk1)
+czgenerated=$(keyfile_to_key_id $czsk2)
+czpublished=$(keyfile_to_key_id $czsk3)
+czinactive=$(keyfile_to_key_id $czsk4)
+czpredecessor=$(keyfile_to_key_id $czsk5)
+czsuccessor=$(keyfile_to_key_id $czsk6)
+ckactive=$(keyfile_to_key_id $cksk1)
+ckpublished=$(keyfile_to_key_id $cksk2)
+ckprerevoke=$(keyfile_to_key_id $cksk3)
+ckrevoked=$(keyfile_to_key_id $cksk4)
+
+pzid=$(keyfile_to_key_id $pzsk)
+pkid=$(keyfile_to_key_id $pksk)
+
+echo_i "checking dnssec-signzone output matches expectations"
+ret=0
+echo "$pzoneout" | grep 'KSKs: 1 active, 0 stand-by, 0 revoked' > /dev/null || ret=1
+echo "$pzoneout" | grep 'ZSKs: 1 active, 0 stand-by, 0 revoked' > /dev/null || ret=1
+echo "$czoneout" | grep 'KSKs: 1 active, 1 stand-by, 1 revoked' > /dev/null || ret=1
+echo "$czoneout" | grep 'ZSKs: 1 active, 2 stand-by, 0 revoked' > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo_i "parent $pzoneout"
+ echo_i "child $czoneout"
+ echo_i "failed";
+fi
+status=$((status + ret))
+
+echo_i "rechecking dnssec-signzone output with -x"
+ret=0
+# use an alternate output file so -x doesn't interfere with later checks
+pzoneout=$($SIGNER -Sxg -o $pzone -f ${pfile}2.signed $pfile)
+czoneout=$($SIGNER -Sxg -e now+1d -X now+2d -o $czone -f ${cfile}2.signed $cfile)
+echo "$pzoneout" | grep 'KSKs: 1 active, 0 stand-by, 0 revoked' > /dev/null || ret=1
+echo "$pzoneout" | grep 'ZSKs: 1 active, 0 present, 0 revoked' > /dev/null || ret=1
+echo "$czoneout" | grep 'KSKs: 1 active, 1 stand-by, 1 revoked' > /dev/null || ret=1
+echo "$czoneout" | grep 'ZSKs: 1 active, 2 present, 0 revoked' > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo_i "parent $pzoneout"
+ echo_i "child $czoneout"
+ echo_i "failed";
+fi
+status=$((status + ret))
+
+echo_i "checking parent zone DNSKEY set"
+ret=0
+grep "key id = $pzid" $pfile.signed > /dev/null || {
+ ret=1
+ echo_i "missing expected parent ZSK id = $pzid"
+}
+grep "key id = $pkid" $pfile.signed > /dev/null || {
+ ret=1
+ echo_i "missing expected parent KSK id = $pkid"
+}
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking parent zone DS records"
+ret=0
+awk '$2 == "DS" {print $3}' $pfile.signed > dsset.out
+grep -w "$ckactive" dsset.out > /dev/null || ret=1
+grep -w "$ckpublished" dsset.out > /dev/null || ret=1
+# revoked key should not be there, hence the &&
+grep -w "$ckprerevoke" dsset.out > /dev/null && ret=1
+grep -w "$ckrevoked" dsset.out > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking child zone DNSKEY set"
+ret=0
+grep "key id = $ckactive\$" $cfile.signed > /dev/null || {
+ ret=1
+ echo_i "missing expected child KSK id = $ckactive"
+}
+grep "key id = $ckpublished\$" $cfile.signed > /dev/null || {
+ ret=1
+ echo_i "missing expected child prepublished KSK id = $ckpublished"
+}
+grep "key id = $ckrevoked\$" $cfile.signed > /dev/null || {
+ ret=1
+ echo_i "missing expected child revoked KSK id = $ckrevoked"
+}
+grep "key id = $czactive\$" $cfile.signed > /dev/null || {
+ ret=1
+ echo_i "missing expected child ZSK id = $czactive"
+}
+grep "key id = $czpublished\$" $cfile.signed > /dev/null || {
+ ret=1
+ echo_i "missing expected child prepublished ZSK id = $czpublished"
+}
+grep "key id = $czinactive\$" $cfile.signed > /dev/null || {
+ ret=1
+ echo_i "missing expected child inactive ZSK id = $czinactive"
+}
+# should not be there, hence the &&
+grep "key id = $ckprerevoke\$" $cfile.signed > /dev/null && {
+ ret=1
+ echo_i "found unexpected child pre-revoke ZSK id = $ckprerevoke"
+}
+grep "key id = $czgenerated\$" $cfile.signed > /dev/null && {
+ ret=1
+ echo_i "found unexpected child generated ZSK id = $czgenerated"
+}
+grep "key id = $czpredecessor\$" $cfile.signed > /dev/null && {
+ echo_i "found unexpected ZSK predecessor id = $czpredecessor (ignored)"
+}
+grep "key id = $czsuccessor\$" $cfile.signed > /dev/null && {
+ echo_i "found unexpected ZSK successor id = $czsuccessor (ignored)"
+}
+#grep "key id = $czpredecessor\$" $cfile.signed > /dev/null && ret=1
+#grep "key id = $czsuccessor\$" $cfile.signed > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking key TTLs are correct"
+ret=0
+grep "${czone}. 30 IN" ${czsk1}.key > /dev/null 2>&1 || ret=1
+grep "${czone}. 30 IN" ${cksk1}.key > /dev/null 2>&1 || ret=1
+grep "${czone}. IN" ${czsk2}.key > /dev/null 2>&1 || ret=1
+$SETTIME -L 45 ${czsk2} > /dev/null
+grep "${czone}. 45 IN" ${czsk2}.key > /dev/null 2>&1 || ret=1
+$SETTIME -L 0 ${czsk2} > /dev/null
+grep "${czone}. IN" ${czsk2}.key > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking key TTLs were imported correctly"
+ret=0
+awk 'BEGIN {r = 0} $2 == "DNSKEY" && $1 != 30 {r = 1} END {exit r}' \
+ ${cfile}.signed || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "re-signing and checking imported TTLs again"
+ret=0
+$SETTIME -L 15 ${czsk2} > /dev/null
+czoneout=$($SIGNER -Sg -e now+1d -X now+2d -o $czone $cfile)
+awk 'BEGIN {r = 0} $2 == "DNSKEY" && $1 != 15 {r = 1} END {exit r}' \
+ ${cfile}.signed || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# There is some weirdness in Solaris 10 (Generic_120011-14), which
+# is why the next section has all those echo $ret > /dev/null;sync
+# commands
+echo_i "checking child zone signatures"
+ret=0
+# check DNSKEY signatures first
+awk '$2 == "RRSIG" && $3 == "DNSKEY" { getline; print $3 }' $cfile.signed > dnskey.sigs
+sub=0
+grep -w "$ckactive" dnskey.sigs > /dev/null || sub=1
+if [ $sub != 0 ]; then echo_i "missing ckactive $ckactive (dnskey)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$ckrevoked" dnskey.sigs > /dev/null || sub=1
+if [ $sub != 0 ]; then echo_i "missing ckrevoke $ckrevoke (dnskey)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$czactive" dnskey.sigs > /dev/null || sub=1
+if [ $sub != 0 ]; then echo_i "missing czactive $czactive (dnskey)"; ret=1; fi
+# should not be there:
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$ckprerevoke" dnskey.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found ckprerevoke $ckprerevoke (dnskey)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$ckpublished" dnskey.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found ckpublished $ckpublished (dnskey)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$czpublished" dnskey.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found czpublished $czpublished (dnskey)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$czinactive" dnskey.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found czinactive $czinactive (dnskey)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$czgenerated" dnskey.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found czgenerated $czgenerated (dnskey)"; ret=1; fi
+# now check other signatures first
+awk '$2 == "RRSIG" && $3 != "DNSKEY" && $3 != "CDNSKEY" && $3 != "CDS" { getline; print $3 }' $cfile.signed | sort -un > other.sigs
+# should not be there:
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$ckactive" other.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found ckactive $ckactive (other)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$ckpublished" other.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found ckpublished $ckpublished (other)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$ckprerevoke" other.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found ckprerevoke $ckprerevoke (other)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$ckrevoked" other.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found ckrevoked $ckrevoked (other)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$czpublished" other.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found czpublished $czpublished (other)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$czinactive" other.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found czinactive $czinactive (other)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$czgenerated" other.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found czgenerated $czgenerated (other)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$czpredecessor" other.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found czpredecessor $czpredecessor (other)"; ret=1; fi
+echo $ret > /dev/null
+sync
+sub=0
+grep -w "$czsuccessor" other.sigs > /dev/null && sub=1
+if [ $sub != 0 ]; then echo_i "found czsuccessor $czsuccessor (other)"; ret=1; fi
+if [ $ret != 0 ]; then
+ sed 's/^/I:dnskey sigs: /' < dnskey.sigs
+ sed 's/^/I:other sigs: /' < other.sigs
+ echo_i "failed";
+fi
+status=$((status + ret))
+
+echo_i "checking RRSIG expiry date correctness"
+dnskey_expiry=$($CHECKZONE -o - $czone $cfile.signed 2> /dev/null |
+ awk '$4 == "RRSIG" && $5 == "DNSKEY" {print $9; exit}' |
+ cut -c1-10)
+soa_expiry=$($CHECKZONE -o - $czone $cfile.signed 2> /dev/null |
+ awk '$4 == "RRSIG" && $5 == "SOA" {print $9; exit}' |
+ cut -c1-10)
+[ $dnskey_expiry -gt $soa_expiry ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "waiting 30 seconds for key activation"
+sleep 30
+echo_i "re-signing child zone"
+czoneout2=$($SIGNER -Sg -o $czone -f $cfile.new $cfile.signed)
+mv $cfile.new $cfile.signed
+
+echo_i "checking dnssec-signzone output matches expectations"
+ret=0
+echo "$czoneout2" | grep 'KSKs: 2 active, 0 stand-by, 1 revoked' > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking child zone signatures again"
+ret=0
+awk '$2 == "RRSIG" && $3 == "DNSKEY" { getline; print $3 }' $cfile.signed > dnskey.sigs
+grep -w "$ckpublished" dnskey.sigs > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking sync record publication"
+ret=0
+awk 'BEGIN { r=1 } $2 == "CDNSKEY" { r=0 } END { exit r }' $cfile.signed || ret=1
+awk 'BEGIN { r=1 } $2 == "CDS" { r=0 } END { exit r }' $cfile.signed || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# this also checks that the future sync record is not yet published
+echo_i "checking sync record deletion"
+ret=0
+$SETTIME -P now -A now -Dsync now ${cksk5} > /dev/null
+$SIGNER -Sg -o $czone -f $cfile.new $cfile.signed > /dev/null
+mv $cfile.new $cfile.signed
+awk 'BEGIN { r=1 } $2 == "CDNSKEY" { r=0 } END { exit r }' $cfile.signed && ret=1
+awk 'BEGIN { r=1 } $2 == "CDS" { r=0 } END { exit r }' $cfile.signed && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/smartsign/tests_sh_smartsign.py b/bin/tests/system/smartsign/tests_sh_smartsign.py
new file mode 100644
index 0000000..e291b64
--- /dev/null
+++ b/bin/tests/system/smartsign/tests_sh_smartsign.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_smartsign(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/sortlist/clean.sh b/bin/tests/system/sortlist/clean.sh
new file mode 100644
index 0000000..b490f46
--- /dev/null
+++ b/bin/tests/system/sortlist/clean.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f *.dig *.good *.out
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/sortlist/ns1/example.db b/bin/tests/system/sortlist/ns1/example.db
new file mode 100644
index 0000000..b68e215
--- /dev/null
+++ b/bin/tests/system/sortlist/ns1/example.db
@@ -0,0 +1,37 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns1.example. hostmaster.example. (
+ 2000042795 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns1.example.
+ns1.example. A 10.53.0.1
+
+; Let's see what the sortlist picks out of this...
+a A 1.1.1.1
+a A 1.1.1.5
+a A 1.1.1.2
+a A 192.168.3.1
+a A 1.1.1.3
+a A 192.168.1.1
+a A 1.1.1.4
+
+b A 10.53.0.1
+b A 10.53.0.2
+b A 10.53.0.3
+b A 10.53.0.4
+b A 10.53.0.5
+
diff --git a/bin/tests/system/sortlist/ns1/named.conf.in b/bin/tests/system/sortlist/ns1/named.conf.in
new file mode 100644
index 0000000..1a0b3ad
--- /dev/null
+++ b/bin/tests/system/sortlist/ns1/named.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+
+ sortlist {
+ { 10.53.0.1; // IF 10.53.0.1
+ {
+ !1.1.1.4; !1.1.1.2; !1.1.1.3; !1.1.1.1; // sort these last,
+ 192.168.3/24; // this first
+ { 192.168.2/24; 192.168.1/24; }; }; }; // and these next
+ { { 10.53.0.2; 10.53.0.3; }; }; // Prefer self
+ 10.53.0.4; // BIND 8 compat
+ { 10.53.0.5; 10.53.0.5; }; // BIND 8 compat
+ };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/sortlist/ns1/root.db b/bin/tests/system/sortlist/ns1/root.db
new file mode 100644
index 0000000..17780d1
--- /dev/null
+++ b/bin/tests/system/sortlist/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/sortlist/setup.sh b/bin/tests/system/sortlist/setup.sh
new file mode 100644
index 0000000..82240a7
--- /dev/null
+++ b/bin/tests/system/sortlist/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/sortlist/tests.sh b/bin/tests/system/sortlist/tests.sh
new file mode 100644
index 0000000..894b022
--- /dev/null
+++ b/bin/tests/system/sortlist/tests.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd -p ${PORT}"
+
+status=0
+
+echo_i "test 2-element sortlist statement"
+cat <<EOF >test1.good
+a.example. 300 IN A 192.168.3.1
+a.example. 300 IN A 192.168.1.1
+a.example. 300 IN A 1.1.1.5
+a.example. 300 IN A 1.1.1.1
+a.example. 300 IN A 1.1.1.3
+a.example. 300 IN A 1.1.1.2
+a.example. 300 IN A 1.1.1.4
+EOF
+$DIG $DIGOPTS a.example. @10.53.0.1 -b 10.53.0.1 >test1.dig
+# Note that this can't use digcomp.pl because here, the ordering of the
+# result RRs is significant.
+diff test1.dig test1.good || status=1
+
+echo_i "test 1-element sortlist statement and undocumented BIND 8 features"
+ cat <<EOF >test2.good
+b.example. 300 IN A 10.53.0.$n
+EOF
+
+$DIG $DIGOPTS b.example. @10.53.0.1 -b 10.53.0.2 | sed 1q | \
+ grep -E '10.53.0.(2|3)$' > test2.out &&
+$DIG $DIGOPTS b.example. @10.53.0.1 -b 10.53.0.3 | sed 1q | \
+ grep -E '10.53.0.(2|3)$' >> test2.out &&
+$DIG $DIGOPTS b.example. @10.53.0.1 -b 10.53.0.4 | sed 1q | \
+ grep -E '10.53.0.4$' >> test2.out &&
+$DIG $DIGOPTS b.example. @10.53.0.1 -b 10.53.0.5 | sed 1q | \
+ grep -E '10.53.0.5$' >> test2.out || status=1
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/sortlist/tests_sh_sortlist.py b/bin/tests/system/sortlist/tests_sh_sortlist.py
new file mode 100644
index 0000000..5a66d7d
--- /dev/null
+++ b/bin/tests/system/sortlist/tests_sh_sortlist.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_sortlist(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/spf/clean.sh b/bin/tests/system/spf/clean.sh
new file mode 100644
index 0000000..90dc7b6
--- /dev/null
+++ b/bin/tests/system/spf/clean.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns1/named.run
+rm -f ns1/named.memstats
+rm -f ns*/named.lock
+rm -f ns*/named.conf
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/spf/ns1/named.conf.in b/bin/tests/system/spf/ns1/named.conf.in
new file mode 100644
index 0000000..d25251a
--- /dev/null
+++ b/bin/tests/system/spf/ns1/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ ixfr-from-differences yes;
+};
+
+zone "spf" {
+ type primary;
+ file "spf.db";
+};
+
+zone "warn" {
+ type primary;
+ file "spf.db";
+ check-spf warn;
+};
+
+zone "nowarn" {
+ type primary;
+ file "spf.db";
+ check-spf ignore;
+};
diff --git a/bin/tests/system/spf/ns1/spf.db b/bin/tests/system/spf/ns1/spf.db
new file mode 100644
index 0000000..9527b1b
--- /dev/null
+++ b/bin/tests/system/spf/ns1/spf.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 IN SOA . . 0 0 0 0 0
+@ 0 IN NS .
+@ 0 IN TXT "v=spf1 -all"
+@ 0 IN SPF "v=spf1 -all"
+x 0 IN TXT "v=spf1"
+y 0 IN SPF "v=spf1"
+y 0 IN TXT "a non spf record"
diff --git a/bin/tests/system/spf/setup.sh b/bin/tests/system/spf/setup.sh
new file mode 100644
index 0000000..82240a7
--- /dev/null
+++ b/bin/tests/system/spf/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/spf/tests.sh b/bin/tests/system/spf/tests.sh
new file mode 100644
index 0000000..07e6c19
--- /dev/null
+++ b/bin/tests/system/spf/tests.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+n=1
+status=0
+
+# Wait until all zones are loaded before checking SPF related logs
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ grep "all zones loaded" ns1/named.run > /dev/null && break
+ sleep 1
+done
+
+echo_i "checking that SPF warnings have been correctly generated ($n)"
+ret=0
+
+grep "zone spf/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1
+grep "'y.spf' found type SPF" ns1/named.run > /dev/null || ret=1
+grep "'spf' found type SPF" ns1/named.run > /dev/null && ret=1
+
+grep "zone warn/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1
+grep "'y.warn' found type SPF" ns1/named.run > /dev/null || ret=1
+grep "'warn' found type SPF" ns1/named.run > /dev/null && ret=1
+
+grep "zone nowarn/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1
+grep "'y.nowarn' found type SPF" ns1/named.run > /dev/null && ret=1
+grep "'nowarn' found type SPF" ns1/named.run > /dev/null && ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/spf/tests_sh_spf.py b/bin/tests/system/spf/tests_sh_spf.py
new file mode 100644
index 0000000..53c623d
--- /dev/null
+++ b/bin/tests/system/spf/tests_sh_spf.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_spf(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/start.pl b/bin/tests/system/start.pl
new file mode 100755
index 0000000..2a2d780
--- /dev/null
+++ b/bin/tests/system/start.pl
@@ -0,0 +1,452 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Framework for starting test servers.
+# Based on the type of server specified, check for port availability, remove
+# temporary files, start the server, and verify that the server is running.
+# If a server is specified, start it. Otherwise, start all servers for test.
+
+use strict;
+use warnings;
+
+use Cwd ':DEFAULT', 'abs_path';
+use English '-no_match_vars';
+use Getopt::Long;
+use Time::HiRes 'sleep'; # allows sleeping fractional seconds
+
+# Usage:
+# perl start.pl [--noclean] [--restart] [--port port] [--taskset cpus] test [server [options]]
+#
+# --noclean Do not cleanup files in server directory.
+#
+# --restart Indicate that the server is being restarted, so get the
+# server to append output to an existing log file instead of
+# starting a new one.
+#
+# --port port Specify the default port being used by the server to answer
+# queries (default 5300). This script will interrogate the
+# server on this port to see if it is running. (Note: for
+# "named" nameservers, this can be overridden by the presence
+# of the file "named.port" in the server directory containing
+# the number of the query port.)
+#
+# --taskset cpus Use taskset to signal which cpus can be used. For example
+# cpus=fff0 means all cpus aexcept for 0, 1, 2, and 3 are
+# eligible.
+#
+# test Name of the test directory.
+#
+# server Name of the server directory. This will be of the form
+# "nsN" or "ansN", where "N" is an integer between 1 and 8.
+# If not given, the script will start all the servers in the
+# test directory.
+#
+# options Alternate options for the server.
+#
+# NOTE: options must be specified with '-- "<option list>"',
+# for instance: start.pl . ns1 -- "-c n.conf -d 43"
+#
+# ALSO NOTE: this variable will be filled with the contents
+# of the first non-commented/non-blank line of args in a file
+# called "named.args" in an ns*/ subdirectory. Only the FIRST
+# non-commented/non-blank line is used (everything else in
+# the file is ignored). If "options" is already set, then
+# "named.args" is ignored.
+
+my $usage = "usage: $0 [--noclean] [--restart] [--port <port>] [--taskset <cpus>] test-directory [server-directory [server-options]]";
+my $clean = 1;
+my $restart = 0;
+my $queryport = 5300;
+my $taskset = "";
+
+GetOptions(
+ 'clean!' => \$clean,
+ 'restart!' => \$restart,
+ 'port=i' => \$queryport,
+ 'taskset=s' => \$taskset,
+) or die "$usage\n";
+
+my( $test, $server_arg, $options_arg ) = @ARGV;
+
+if (!$test) {
+ die "$usage\n";
+}
+
+# Global variables
+my $builddir = $ENV{'builddir'};
+my $srcdir = $ENV{'srcdir'};
+my $testdir = "$builddir/$test";
+
+if (! -d $testdir) {
+ die "No test directory: \"$testdir\"\n";
+}
+
+if ($server_arg && ! -d "$testdir/$server_arg") {
+ die "No server directory: \"$testdir/$server_arg\"\n";
+}
+
+my $NAMED = $ENV{'NAMED'};
+my $DIG = $ENV{'DIG'};
+my $PERL = $ENV{'PERL'};
+my $PYTHON = $ENV{'PYTHON'};
+
+# Start the server(s)
+
+my @ns;
+my @ans;
+
+if ($server_arg) {
+ if ($server_arg =~ /^ns/) {
+ push(@ns, $server_arg);
+ } elsif ($server_arg =~ /^ans/) {
+ push(@ans, $server_arg);
+ } else {
+ print "$0: ns or ans directory expected";
+ print "I:$test:failed";
+ }
+} else {
+ # Determine which servers need to be started for this test.
+ opendir DIR, $testdir or die "unable to read test directory: \"$test\" ($OS_ERROR)\n";
+ my @files = sort readdir DIR;
+ closedir DIR;
+
+ @ns = grep /^ns[0-9]*$/, @files;
+ @ans = grep /^ans[0-9]*$/, @files;
+}
+
+# Start the servers we found.
+
+foreach my $name(@ns) {
+ my $instances_so_far = count_running_lines($name);
+ &check_ns_port($name);
+ &start_ns_server($name, $options_arg);
+ &verify_ns_server($name, $instances_so_far);
+}
+
+foreach my $name(@ans) {
+ &start_ans_server($name);
+}
+
+# Subroutines
+
+sub read_ns_port {
+ my ( $server ) = @_;
+ my $port = $queryport;
+ my $options = "";
+
+ if ($server) {
+ my $file = $testdir . "/" . $server . "/named.port";
+
+ if (-e $file) {
+ open(my $fh, "<", $file) or die "unable to read ports file \"$file\" ($OS_ERROR)";
+
+ my $line = <$fh>;
+
+ if ($line) {
+ chomp $line;
+ $port = $line;
+ }
+ }
+ }
+ return ($port);
+}
+
+sub check_ns_port {
+ my ( $server ) = @_;
+ my $options = "";
+ my $port = read_ns_port($server);
+
+ if ($server =~ /(\d+)$/) {
+ $options = "-i $1";
+ }
+
+ my $tries = 0;
+
+ while (1) {
+ my $return = system("$PERL $srcdir/testsock.pl -p $port $options");
+
+ if ($return == 0) {
+ last;
+ }
+
+ $tries++;
+
+ if ($tries > 4) {
+ print "$0: could not bind to server addresses, still running?\n";
+ print "I:$test:server sockets not available\n";
+ print "I:$test:failed\n";
+
+ system("$PERL $srcdir/stop.pl $test"); # Is this the correct behavior?
+
+ exit 1;
+ }
+
+ print "I:$test:Couldn't bind to socket (yet)\n";
+ sleep 2;
+ }
+}
+
+sub start_server {
+ my ( $server, $command, $pid_file ) = @_;
+
+ chdir "$testdir/$server" or die "unable to chdir \"$testdir/$server\" ($OS_ERROR)\n";
+
+ # start the server
+ my $child = `$command`;
+ chomp($child);
+
+ # wait up to 90 seconds for the server to start and to write the
+ # pid file otherwise kill this server and any others that have
+ # already been started
+ my $tries = 0;
+ while (!-s $pid_file) {
+ if (++$tries > 900) {
+ print "I:$test:Couldn't start server $command (pid=$child)\n";
+ print "I:$test:failed\n";
+ kill "ABRT", $child if ("$child" ne "");
+ chdir "$testdir";
+ system "$PERL $srcdir/stop.pl $test";
+ exit 1;
+ }
+ sleep 0.1;
+ }
+
+ # go back to the top level directory
+ chdir $builddir;
+}
+
+sub construct_ns_command {
+ my ( $server, $options ) = @_;
+
+ my $command;
+
+ if ($ENV{'USE_VALGRIND'}) {
+ $command = "valgrind -q --gen-suppressions=all --num-callers=48 --fullpath-after= --log-file=named-$server-valgrind-%p.log ";
+
+ if ($ENV{'USE_VALGRIND'} eq 'helgrind') {
+ $command .= "--tool=helgrind ";
+ } else {
+ $command .= "--tool=memcheck --track-origins=yes --leak-check=full ";
+ }
+
+ $command .= "$NAMED -m none ";
+ } else {
+ if ($taskset) {
+ $command = "taskset $taskset $NAMED ";
+ } else {
+ $command = "$NAMED ";
+ }
+ }
+
+ my $args_file = $testdir . "/" . $server . "/" . "named.args";
+
+ if ($options) {
+ $command .= $options;
+ } elsif (-e $args_file) {
+ open(my $fh, "<", $args_file) or die "unable to read args_file \"$args_file\" ($OS_ERROR)\n";
+
+ while(my $line=<$fh>) {
+ next if ($line =~ /^\s*$/); #discard blank lines
+ next if ($line =~ /^\s*#/); #discard comment lines
+
+ chomp $line;
+
+ $line =~ s/#.*$//;
+
+ $command .= $line;
+
+ last;
+ }
+ } else {
+ $command .= "-D $test-$server ";
+ $command .= "-X named.lock ";
+ $command .= "-m record ";
+
+ foreach my $t_option(
+ "dropedns", "ednsformerr", "ednsnotimp", "ednsrefused",
+ "noaa", "noedns", "nosoa", "maxudp512", "maxudp1460",
+ ) {
+ if (-e "$testdir/$server/named.$t_option") {
+ $command .= "-T $t_option "
+ }
+ }
+
+ $command .= "-c named.conf -d 99 -g -U 4 -T maxcachesize=2097152";
+ }
+
+ if (-e "$testdir/$server/named.notcp") {
+ $command .= " -T notcp"
+ }
+
+ if ($restart) {
+ $command .= " >>named.run 2>&1 &";
+ } else {
+ $command .= " >named.run 2>&1 &";
+ }
+
+ # get the shell to report the pid of the server ($!)
+ $command .= " echo \$!";
+
+ return $command;
+}
+
+sub start_ns_server {
+ my ( $server, $options ) = @_;
+
+ my $cleanup_files;
+ my $command;
+ my $pid_file;
+
+ $cleanup_files = "{./*.jnl,./*.bk,./*.st,./named.run}";
+
+ $command = construct_ns_command($server, $options);
+
+ $pid_file = "named.pid";
+
+ if ($clean) {
+ unlink glob $cleanup_files;
+ }
+
+ start_server($server, $command, $pid_file);
+}
+
+sub construct_ans_command {
+ my ( $server, $options ) = @_;
+
+ my $command;
+ my $n;
+
+ if ($server =~ /^ans(\d+)/) {
+ $n = $1;
+ } else {
+ die "unable to parse server number from name \"$server\"\n";
+ }
+
+ if (-e "$testdir/$server/ans.py") {
+ $command = "$PYTHON -u ans.py 10.53.0.$n $queryport";
+ } elsif (-e "$testdir/$server/ans.pl") {
+ $command = "$PERL ans.pl";
+ } else {
+ $command = "$PERL $srcdir/ans.pl 10.53.0.$n";
+ }
+
+ if ($options) {
+ $command .= $options;
+ }
+
+ if ($restart) {
+ $command .= " >>ans.run 2>&1 &";
+ } else {
+ $command .= " >ans.run 2>&1 &";
+ }
+
+ # get the shell to report the pid of the server ($!)
+ $command .= " echo \$!";
+
+ return $command;
+}
+
+sub start_ans_server {
+ my ( $server, $options ) = @_;
+
+ my $cleanup_files;
+ my $command;
+ my $pid_file;
+
+ $cleanup_files = "{./ans.run}";
+ $command = construct_ans_command($server, $options);
+ $pid_file = "ans.pid";
+
+ if ($clean) {
+ unlink glob $cleanup_files;
+ }
+
+ start_server($server, $command, $pid_file);
+}
+
+sub count_running_lines {
+ my ( $server ) = @_;
+
+ my $runfile = "$testdir/$server/named.run";
+
+ # the shell *ought* to have created the file immediately, but this
+ # logic allows the creation to be delayed without issues
+ if (open(my $fh, "<", $runfile)) {
+ # the two non-whitespace blobs should be the date and time
+ # but we don't care about them really, only that they are there
+ return scalar(grep /^\S+ \S+ running\R/, <$fh>);
+ } else {
+ return 0;
+ }
+}
+
+sub verify_ns_server {
+ my ( $server, $instances_so_far ) = @_;
+
+ my $tries = 0;
+
+ while (count_running_lines($server) < $instances_so_far + 1) {
+ $tries++;
+
+ if ($tries >= 30) {
+ print "I:$test:server $server seems to have not started\n";
+ print "I:$test:failed\n";
+
+ system("$PERL $srcdir/stop.pl $test");
+
+ exit 1;
+ }
+
+ sleep 2;
+ }
+
+ $tries = 0;
+
+ my $port = read_ns_port($server);
+ my $tcp = "+tcp";
+ my $n;
+
+ if ($server =~ /^ns(\d+)/) {
+ $n = $1;
+ } else {
+ die "unable to parse server number from name \"$server\"\n";
+ }
+
+ if (-e "$testdir/$server/named.notcp") {
+ $tcp = "";
+ }
+
+ my $ip = "10.53.0.$n";
+ if (-e "$testdir/$server/named.ipv6-only") {
+ $ip = "fd92:7065:b8e:ffff::$n";
+ }
+
+ while (1) {
+ my $return = system("$DIG $tcp +noadd +nosea +nostat +noquest +nocomm +nocmd +noedns -p $port version.bind. chaos txt \@$ip > /dev/null");
+
+ last if ($return == 0);
+
+ $tries++;
+
+ if ($tries >= 30) {
+ print "I:$test:no response from $server\n";
+ print "I:$test:failed\n";
+
+ system("$PERL $srcdir/stop.pl $test");
+
+ exit 1;
+ }
+
+ sleep 2;
+ }
+}
diff --git a/bin/tests/system/start.sh.in b/bin/tests/system/start.sh.in
new file mode 100644
index 0000000..0e05845
--- /dev/null
+++ b/bin/tests/system/start.sh.in
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+builddir=@builddir@
+srcdir=@srcdir@
+
+# shellcheck source=conf.sh
+. "${builddir}/conf.sh"
+
+$PERL "${srcdir}/start.pl" "$@"
diff --git a/bin/tests/system/staticstub/clean.sh b/bin/tests/system/staticstub/clean.sh
new file mode 100755
index 0000000..f0dbe28
--- /dev/null
+++ b/bin/tests/system/staticstub/clean.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f tmp
+rm -f dig.out.*
+rm -f ns*/named.lock
+rm -f ns*/named.conf
+rm -f ns3/example.db
+rm -f ns3/undelegated.db
+rm -f ns4/sub.example.db
+rm -f ns?/named.memstats
+rm -f ns?/named.run
+rm -f ns?/named_dump.db
+rm -rf */*.signed
+rm -rf */K*
+rm -rf */dsset-*
+rm -rf */trusted.conf
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/staticstub/conf/bad01.conf b/bin/tests/system/staticstub/conf/bad01.conf
new file mode 100644
index 0000000..a849de4
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad01.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# prefix cannot be specified in the address list field.
+zone "example.com" {
+ type static-stub;
+ server-addresses { 192.0.2.0/24; };
+};
diff --git a/bin/tests/system/staticstub/conf/bad02.conf b/bin/tests/system/staticstub/conf/bad02.conf
new file mode 100644
index 0000000..9c85d00
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad02.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# server-names must be valid domain names.
+zone "example.com" {
+ type static-stub;
+ server-names { "\11.example.net"; };
+};
diff --git a/bin/tests/system/staticstub/conf/bad03.conf b/bin/tests/system/staticstub/conf/bad03.conf
new file mode 100644
index 0000000..b5aa0f4
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad03.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# Explicit port specification is not allowed (for now).
+zone "example.com" {
+ type static-stub;
+ server-addresses { 192.0.2.2 port 5301; };
+};
diff --git a/bin/tests/system/staticstub/conf/bad04.conf b/bin/tests/system/staticstub/conf/bad04.conf
new file mode 100644
index 0000000..ec25b7a
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad04.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# scoped address is not allowed.
+zone "example.com" {
+ type static-stub;
+ server-addresses { fe80::1%1; };
+};
diff --git a/bin/tests/system/staticstub/conf/bad05.conf b/bin/tests/system/staticstub/conf/bad05.conf
new file mode 100644
index 0000000..e47f412
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad05.conf
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# server-name must not be a subdomain of the zone name.
+zone "example.com" {
+ type static-stub;
+ # server-name equals to the zone name.
+ server-names { "example.com"; };
+};
diff --git a/bin/tests/system/staticstub/conf/bad06.conf b/bin/tests/system/staticstub/conf/bad06.conf
new file mode 100644
index 0000000..be75748
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad06.conf
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# server-name must not be a subdomain of the zone name.
+zone "example.com" {
+ type static-stub;
+ # server-name is a real subdomain of the zone name.
+ server-names { "ns.example.com"; };
+};
diff --git a/bin/tests/system/staticstub/conf/bad07.conf b/bin/tests/system/staticstub/conf/bad07.conf
new file mode 100644
index 0000000..dd1879f
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad07.conf
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# server-addresses must not be specified more than once.
+zone "example.com" {
+ type static-stub;
+ server-addresses { 192.0.2.1; };
+ server-addresses { 192.0.2.2; };
+};
diff --git a/bin/tests/system/staticstub/conf/bad08.conf b/bin/tests/system/staticstub/conf/bad08.conf
new file mode 100644
index 0000000..c389c9d
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad08.conf
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# server-names must not be specified more than once.
+zone "example.com" {
+ type static-stub;
+ server-names { ns1.example.net; };
+ server-names { ns2.example.net; };
+};
diff --git a/bin/tests/system/staticstub/conf/bad09.conf b/bin/tests/system/staticstub/conf/bad09.conf
new file mode 100644
index 0000000..09e92e6
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad09.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# "primaries" isn't allowed for a static-stub zone (unlike a stub zone).
+zone "example.com" {
+ type static-stub;
+ primaries { 192.0.2.1; };
+};
diff --git a/bin/tests/system/staticstub/conf/bad10.conf b/bin/tests/system/staticstub/conf/bad10.conf
new file mode 100644
index 0000000..b9d2862
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad10.conf
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# "server-addresses" isn't allowed for a pure stub zone.
+# (or most of other types of zones, but confirming one case should be good
+# enough)
+zone "example.com" {
+ type stub;
+ server-addresses { 192.0.2.1; };
+};
diff --git a/bin/tests/system/staticstub/conf/bad11.conf b/bin/tests/system/staticstub/conf/bad11.conf
new file mode 100644
index 0000000..0b97e70
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/bad11.conf
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# "server-names" isn't allowed for a pure stub zone.
+# (or most of other types of zones, but confirming one case should be good
+# enough)
+zone "example.com" {
+ type stub;
+ server-names { "ns.example.net"; };
+};
diff --git a/bin/tests/system/staticstub/conf/good01.conf b/bin/tests/system/staticstub/conf/good01.conf
new file mode 100644
index 0000000..93f19af
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/good01.conf
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# both server-addresses and server-names can be specified.
+zone "example.com" {
+ type static-stub;
+ server-addresses { 192.0.2.1; };
+ server-names { "ns.example.net"; };
+};
diff --git a/bin/tests/system/staticstub/conf/good02.conf b/bin/tests/system/staticstub/conf/good02.conf
new file mode 100644
index 0000000..6a8a413
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/good02.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# both IPv4 and IPv6 server-addresses should be allowable.
+zone "example.com" {
+ type static-stub;
+ server-addresses { 192.0.2.1; 2001:db8::53; };
+};
diff --git a/bin/tests/system/staticstub/conf/good03.conf b/bin/tests/system/staticstub/conf/good03.conf
new file mode 100644
index 0000000..faa9ab3
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/good03.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# server-addresses can be empty, though it's meaningless.
+zone "example.com" {
+ type static-stub;
+ server-addresses {};
+};
diff --git a/bin/tests/system/staticstub/conf/good04.conf b/bin/tests/system/staticstub/conf/good04.conf
new file mode 100644
index 0000000..161e4f0
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/good04.conf
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# server-names can be empty, though it's meaningless.
+zone "example.com" {
+ type static-stub;
+ server-names {};
+};
diff --git a/bin/tests/system/staticstub/conf/good05.conf b/bin/tests/system/staticstub/conf/good05.conf
new file mode 100644
index 0000000..e1db2fd
--- /dev/null
+++ b/bin/tests/system/staticstub/conf/good05.conf
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# less common options
+zone "example.com" {
+ type static-stub;
+ allow-query { 127.0.0.1; };
+ zone-statistics yes;
+};
diff --git a/bin/tests/system/staticstub/knowngood.dig.out.rec b/bin/tests/system/staticstub/knowngood.dig.out.rec
new file mode 100644
index 0000000..e854082
--- /dev/null
+++ b/bin/tests/system/staticstub/knowngood.dig.out.rec
@@ -0,0 +1,18 @@
+
+; <<>> DiG 8.2 <<>> -p @10.53.0.3 data.child.example txt
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; data.example, type = TXT, class = IN
+
+;; ANSWER SECTION:
+data.example. 5M IN TXT "some" "test" "data"
+
+;; Total query time: 8 msec
+;; FROM: draco to SERVER: 10.53.0.3
+;; WHEN: Wed Jun 21 10:58:54 2000
+;; MSG SIZE sent: 36 rcvd: 97
+
diff --git a/bin/tests/system/staticstub/ns1/named.conf.in b/bin/tests/system/staticstub/ns1/named.conf.in
new file mode 100644
index 0000000..985b932
--- /dev/null
+++ b/bin/tests/system/staticstub/ns1/named.conf.in
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+};
+
+zone "." { type primary; file "root.db"; };
diff --git a/bin/tests/system/staticstub/ns1/root.db b/bin/tests/system/staticstub/ns1/root.db
new file mode 100644
index 0000000..26bc039
--- /dev/null
+++ b/bin/tests/system/staticstub/ns1/root.db
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA a.root-servers.nil. hostmaster.isc.org. 1 600 600 1200 600
+@ NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example.com. NS example.
+
+ns.example.net. A 10.53.0.3
diff --git a/bin/tests/system/staticstub/ns2/named.conf.in b/bin/tests/system/staticstub/ns2/named.conf.in
new file mode 100644
index 0000000..55483ab
--- /dev/null
+++ b/bin/tests/system/staticstub/ns2/named.conf.in
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "trusted.conf";
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type static-stub;
+ server-addresses { 10.53.0.3; };
+ allow-query { !10.53.0.7; any; };
+};
+
+zone "example.org" {
+ type static-stub;
+ SERVER_CONFIG_PLACEHOLDER
+};
+
+zone "example.info" {
+ type static-stub;
+ server-addresses { ::1; }; #ns4
+};
+
+zone "undelegated" {
+ type static-stub;
+ server-addresses { 10.53.0.3; };
+};
diff --git a/bin/tests/system/staticstub/ns3/example.db.in b/bin/tests/system/staticstub/ns3/example.db.in
new file mode 100644
index 0000000..c3b7d81
--- /dev/null
+++ b/bin/tests/system/staticstub/ns3/example.db.in
@@ -0,0 +1,32 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA ns3.example. hostmaster.example. (
+ 2010080900 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns4.example. ; fake
+example. A 10.53.0.4 ; fake
+example. AAAA ::1 ; fake
+
+ns4.example. A 10.53.0.4
+data.example. TXT "some" "test" "data"
+data2.example. TXT "2nd test data"
+data3.example. TXT "3rd test data"
+data4.example. TXT "4th test data"
+
+sub.example. NS ns.sub.example.
+ns.sub.example. A 10.53.0.4
diff --git a/bin/tests/system/staticstub/ns3/example.org.db b/bin/tests/system/staticstub/ns3/example.org.db
new file mode 100644
index 0000000..aec2f99
--- /dev/null
+++ b/bin/tests/system/staticstub/ns3/example.org.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example.org IN SOA ns.example.org. hostmaster.example.org. (
+ 2010080906 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example.org. NS ns.example.org.
+ns.example.org. A 10.53.0.3
+
+data.example.org. TXT "example org data"
diff --git a/bin/tests/system/staticstub/ns3/named.conf.in b/bin/tests/system/staticstub/ns3/named.conf.in
new file mode 100644
index 0000000..e6e49c3
--- /dev/null
+++ b/bin/tests/system/staticstub/ns3/named.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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 no;
+ dnssec-validation no;
+ notify no;
+};
+
+EXAMPLE_ZONE_PLACEHOLDER
+
+zone "example.org" {
+ type primary;
+ file "example.org.db";
+};
+
+zone "undelegated" {
+ type primary;
+ file "undelegated.db.signed";
+};
diff --git a/bin/tests/system/staticstub/ns3/sign.sh b/bin/tests/system/staticstub/ns3/sign.sh
new file mode 100755
index 0000000..9d87137
--- /dev/null
+++ b/bin/tests/system/staticstub/ns3/sign.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+(cd ../ns4 && $SHELL -e sign.sh )
+
+cp ../ns4/dsset-sub.example. .
+
+keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -f KSK -n zone $zone)
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -g -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a trusted key.
+keyfile_to_static_ds $keyname2 > trusted.conf
+
+zone=undelegated
+infile=undelegated.db.in
+zonefile=undelegated.db
+keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -f KSK -n zone $zone)
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -g -o $zone $zonefile > /dev/null
+
+keyfile_to_static_ds $keyname2 >> trusted.conf
+cp trusted.conf ../ns2/trusted.conf
diff --git a/bin/tests/system/staticstub/ns3/undelegated.db.in b/bin/tests/system/staticstub/ns3/undelegated.db.in
new file mode 100644
index 0000000..a7010ef
--- /dev/null
+++ b/bin/tests/system/staticstub/ns3/undelegated.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+undelegated. IN SOA ns3.undelegated. hostmaster.undelegated. (
+ 2010080900 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+undelegated. NS ns3.undelegated.
+undelegated. A 10.53.0.4
+undelegated. AAAA ::1
+ns3.undelegated. A 10.53.0.3
diff --git a/bin/tests/system/staticstub/ns4/example.com.db b/bin/tests/system/staticstub/ns4/example.com.db
new file mode 100644
index 0000000..3db8fa4
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/example.com.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example.com IN SOA example. hostmaster.example. (
+ 2010080701 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example.com. NS example.
+
+data.example.com. TXT "example com data"
diff --git a/bin/tests/system/staticstub/ns4/example.info.db b/bin/tests/system/staticstub/ns4/example.info.db
new file mode 100644
index 0000000..169c70d
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/example.info.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example.info IN SOA ns.example.info. hostmaster.example.info. (
+ 2010080902 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example.info. NS ns.example.info.
+ns.example.info. A 10.53.0.4
+
+data.example.info. TXT "example info data"
diff --git a/bin/tests/system/staticstub/ns4/example.org.db b/bin/tests/system/staticstub/ns4/example.org.db
new file mode 100644
index 0000000..69dc7e3
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/example.org.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example.org IN SOA ns.example.org. hostmaster.example.org. (
+ 2010080908 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example.org. NS ns.example.org.
+ns.example.org. A 10.53.0.3
+
+data.example.org. TXT "example org data"
+data2.example.org. TXT "2nd example org data"
diff --git a/bin/tests/system/staticstub/ns4/named.conf.in b/bin/tests/system/staticstub/ns4/named.conf.in
new file mode 100644
index 0000000..40c2a17
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { ::1; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+};
+
+zone "example.com" {
+ type primary;
+ file "example.com.db";
+};
+
+zone "example.org" {
+ type primary;
+ file "example.org.db";
+};
+
+zone "sub.example" {
+ type primary;
+ file "sub.example.db.signed";
+};
+
+zone "example.info" {
+ type primary;
+ file "example.info.db";
+};
diff --git a/bin/tests/system/staticstub/ns4/sign.sh b/bin/tests/system/staticstub/ns4/sign.sh
new file mode 100755
index 0000000..0598016
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/sign.sh
@@ -0,0 +1,25 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=sub.example
+infile=${zone}.db.in
+zonefile=${zone}.db
+
+keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -f KSK -n zone $zone)
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -o $zone $zonefile > /dev/null
diff --git a/bin/tests/system/staticstub/ns4/sub.example.db.in b/bin/tests/system/staticstub/ns4/sub.example.db.in
new file mode 100644
index 0000000..255396b
--- /dev/null
+++ b/bin/tests/system/staticstub/ns4/sub.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+sub.example. IN SOA ns.sub.example. hostmaster.example. (
+ 2010080900 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+sub.example. NS ns.sub.example.
+ns.sub.example. A 10.53.0.4
+
+data1.sub.example. TXT "1st sub test data"
+data2.sub.example. TXT "2nd sub test data"
+data3.sub.example. TXT "3rd sub test data"
diff --git a/bin/tests/system/staticstub/setup.sh b/bin/tests/system/staticstub/setup.sh
new file mode 100755
index 0000000..61c5621
--- /dev/null
+++ b/bin/tests/system/staticstub/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in tmp
+sed 's/SERVER_CONFIG_PLACEHOLDER/server-names { "ns.example.net"; };/' tmp > ns2/named.conf
+
+copy_setports ns3/named.conf.in tmp
+sed 's/EXAMPLE_ZONE_PLACEHOLDER/zone "example" { type primary; file "example.db.signed"; };/' tmp > ns3/named.conf
+
+copy_setports ns4/named.conf.in ns4/named.conf
+
+cd ns3 && $SHELL -e sign.sh
diff --git a/bin/tests/system/staticstub/tests.sh b/bin/tests/system/staticstub/tests.sh
new file mode 100755
index 0000000..e0f5788
--- /dev/null
+++ b/bin/tests/system/staticstub/tests.sh
@@ -0,0 +1,219 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+n=0
+
+for conf in conf/good*.conf
+do
+ n=$((n + 1))
+ echo_i "checking that $conf is accepted ($n)"
+ ret=0
+ $CHECKCONF "$conf" || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+for conf in conf/bad*.conf
+do
+ n=$((n + 1))
+ echo_i "checking that $conf is rejected ($n)"
+ ret=0
+ $CHECKCONF "$conf" >/dev/null && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+done
+
+n=$((n + 1))
+echo_i "trying an axfr that should be denied (NOTAUTH) ($n)"
+ret=0
+$DIG $DIGOPTS +tcp data.example. @10.53.0.2 axfr > dig.out.ns2.test$n || ret=1
+grep "; Transfer failed." dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "non recursive query for a static-stub zone with server name should be rejected ($n)"
+ret=0
+ $DIG $DIGOPTS +tcp +norec data.example. @10.53.0.2 txt > dig.out.ns2.test$n \
+ || ret=1
+grep "REFUSED" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "non recursive query for a static-stub zone with server name should be rejected ($n)"
+ret=0
+$DIG $DIGOPTS +tcp +norec data.example.org. @10.53.0.2 txt > dig.out.ns2.test$n \
+ || ret=1
+grep "REFUSED" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "allow-query ACL ($n)"
+ret=0
+$DIG $DIGOPTS +tcp +norec data.example. @10.53.0.2 txt -b 10.53.0.7 \
+ > dig.out.ns2.test$n || ret=1
+grep "REFUSED" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "look for static-stub zone data with recursion (should be found) ($n)"
+ret=0
+$DIG $DIGOPTS +tcp +noauth data.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+digcomp knowngood.dig.out.rec dig.out.ns2.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking authoritative NS is ignored for delegation ($n)"
+ret=0
+# the auth server returns a different (and incorrect) NS for .example.
+$DIG $DIGOPTS +tcp example. @10.53.0.2 ns > dig.out.ns2.test1.$n || ret=1
+grep "ns4.example." dig.out.ns2.test1.$n > /dev/null || ret=1
+# but static-stub configuration should still be used
+$DIG $DIGOPTS +tcp data2.example. @10.53.0.2 txt > dig.out.ns2.test2.$n || ret=1
+grep "2nd test data" dig.out.ns2.test2.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking queries for a child zone of the static-stub zone ($n)"
+ret=0
+# prime the delegation to a child zone of the static-stub zone
+$DIG $DIGOPTS +tcp data1.sub.example. @10.53.0.2 txt > dig.out.ns2.test1.$n || ret=1
+grep "1st sub test data" dig.out.ns2.test1.$n > /dev/null || ret=1
+# temporarily disable the the parent zone
+copy_setports ns3/named.conf.in tmp
+sed 's/EXAMPLE_ZONE_PLACEHOLDER//' tmp > ns3/named.conf
+rndc_reload ns3 10.53.0.3
+# query the child zone again. this should directly go to the child and
+# succeed.
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS +tcp data2.sub.example. @10.53.0.2 txt > dig.out.ns2.test2.$n || ret=1
+ grep "2nd sub test data" dig.out.ns2.test2.$n > /dev/null && break
+ sleep 1
+done
+grep "2nd sub test data" dig.out.ns2.test2.$n > /dev/null || ret=1
+# re-enable the parent
+copy_setports ns3/named.conf.in tmp
+sed 's/EXAMPLE_ZONE_PLACEHOLDER/zone "example" { type primary; file "example.db.signed"; };/' tmp > ns3/named.conf
+rndc_reload ns3 10.53.0.3
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking authoritative NS addresses are ignored for delegation ($n)"
+ret=0
+# the auth server returns a different (and incorrect) A/AAA RR for .example.
+$DIG $DIGOPTS +tcp example. @10.53.0.2 a > dig.out.ns2.test1.$n || ret=1
+grep "10.53.0.4" dig.out.ns2.test1.$n > /dev/null || ret=1
+$DIG $DIGOPTS +tcp example. @10.53.0.2 aaaa > dig.out.ns2.test2.$n || ret=1
+grep "::1" dig.out.ns2.test2.$n > /dev/null || ret=1
+# reload the server. this will flush the ADB.
+rndc_reload ns2 10.53.0.2
+# ask another RR that would require delegation. static-stub configuration
+# should still be used instead of the authoritative A/AAAA cached above.
+$DIG $DIGOPTS +tcp data3.example. @10.53.0.2 txt > dig.out.ns2.test3.$n || ret=1
+grep "3rd test data" dig.out.ns2.test3.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# the authoritative server of the query domain (example.com) is the apex
+# name of the static-stub zone (example). in this case the static-stub
+# configuration must be ignored and cached information must be used.
+n=$((n + 1))
+echo_i "checking NS of static-stub is ignored when referenced from other domain ($n)"
+ret=0
+$DIG $DIGOPTS +tcp data.example.com. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "example com data" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# check server-names
+n=$((n + 1))
+echo_i "checking static-stub with a server-name ($n)"
+ret=0
+$DIG $DIGOPTS +tcp data.example.org. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "example org data" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+# Note: for a short term workaround we use ::1, assuming it's configured and
+# usable for our tests. We should eventually use the test ULA and available
+# checks introduced in change 2916.
+if testsock6 ::1
+then
+ echo_i "checking IPv6 static-stub address ($n)"
+ ret=0
+ $DIG $DIGOPTS +tcp data.example.info. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+ grep "example info data" dig.out.ns2.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+else
+ echo_i "SKIPPED: checking IPv6 static-stub address ($n)"
+fi
+
+n=$((n + 1))
+echo_i "look for static-stub zone data with DNSSEC validation ($n)"
+ret=0
+$DIG $DIGOPTS +tcp +dnssec data4.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "ad; QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep "4th test data" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "look for a child of static-stub zone data with DNSSEC validation ($n)"
+ret=0
+$DIG $DIGOPTS +tcp +dnssec data3.sub.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "ad; QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep "3rd sub test data" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# reload with a different name server: existing zone shouldn't be reused.
+n=$((n + 1))
+echo_i "checking server reload with a different static-stub config ($n)"
+ret=0
+copy_setports ns2/named.conf.in tmp
+sed 's/SERVER_CONFIG_PLACEHOLDER/server-addresses { 10.53.0.4; };/' tmp > ns2/named.conf
+rndc_reload ns2 10.53.0.2
+$DIG $DIGOPTS +tcp data2.example.org. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "2nd example org data" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking static-stub of a undelegated tld resolves after DS query ($n)"
+ret=0
+$DIG $DIGOPTS undelegated. @10.53.0.2 ds > dig.out.ns2.ds.test$n
+$DIG $DIGOPTS undelegated. @10.53.0.2 soa > dig.out.ns2.soa.test$n
+grep "status: NXDOMAIN" dig.out.ns2.ds.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns2.soa.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/staticstub/tests_sh_staticstub.py b/bin/tests/system/staticstub/tests_sh_staticstub.py
new file mode 100644
index 0000000..52c661c
--- /dev/null
+++ b/bin/tests/system/staticstub/tests_sh_staticstub.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_staticstub(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/statistics/ans4/ans.pl b/bin/tests/system/statistics/ans4/ans.pl
new file mode 100644
index 0000000..3a37a82
--- /dev/null
+++ b/bin/tests/system/statistics/ans4/ans.pl
@@ -0,0 +1,118 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Ad hoc name server
+#
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.4",
+ LocalPort => $localport, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+for (;;) {
+ $sock->recv($buf, 512);
+
+ print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
+
+ my $packet;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ print "REQUEST:\n";
+ $packet->print;
+
+ $packet->header->qr(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+
+ my $donotrespond = 0;
+
+ if ($qname eq "foo.info") {
+ $donotrespond = 1;
+ } 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"));
+ } elsif ($qname eq "cname2.example.com") {
+ # 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 "www.example.org" || $qname eq "www.example.net" ||
+ $qname eq "badcname.example.org" ||
+ $qname eq "goodcname.example.org" ||
+ $qname eq "foo.baddname.example.org" ||
+ $qname eq "foo.gooddname.example.org") {
+ # Data for address/alias filtering.
+ $packet->header->aa(1);
+ if ($qtype eq "A") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 300 A 192.0.2.1"));
+ } elsif ($qtype eq "AAAA") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 300 AAAA 2001:db8:beef::1"));
+ }
+ } elsif ($qname eq "badcname.example.net" ||
+ $qname eq "goodcname.example.net") {
+ # Data for CNAME/DNAME filtering. We need to make one-level
+ # delegation to avoid automatic acceptance for subdomain aliases
+ $packet->push("authority", new Net::DNS::RR("example.net 300 NS ns.example.net"));
+ $packet->push("additional", new Net::DNS::RR("ns.example.net 300 A 10.53.0.3"));
+ } elsif ($qname =~ /^nodata\.example\.net$/i) {
+ $packet->header->aa(1);
+ } elsif ($qname =~ /^nxdomain\.example\.net$/i) {
+ $packet->header->aa(1);
+ $packet->header->rcode(NXDOMAIN);
+ } elsif ($qname =~ /sub\.example\.org/) {
+ # Data for CNAME/DNAME filtering. The final answers are
+ # 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"));
+ } else {
+ # Data for the "bogus referrals" test
+ $packet->push("authority", new Net::DNS::RR("below.www.example.com 300 NS ns.below.www.example.com"));
+ $packet->push("additional", new Net::DNS::RR("ns.below.www.example.com 300 A 10.53.0.3"));
+ }
+
+ if ($donotrespond == 0) {
+ $sock->send($packet->data);
+ print "RESPONSE:\n";
+ $packet->print;
+ print "\n";
+ }
+}
diff --git a/bin/tests/system/statistics/clean.sh b/bin/tests/system/statistics/clean.sh
new file mode 100644
index 0000000..37fa7dc
--- /dev/null
+++ b/bin/tests/system/statistics/clean.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f ns3/example.bk
+rm -f ns3/internal.bk
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f */ans.run
+rm -f */named.stats
+rm -f */named.stats-stage*
+rm -f dig.out*
+rm -f curl.out.*
+rm -f ns*/named.lock
+rm -f stats*out
+rm -f ns*/managed-keys.bind*
+rm -f xsltproc.out.*
+rm -f named.stats.* ns*/named.stats.*
diff --git a/bin/tests/system/statistics/ns1/named.conf.in b/bin/tests/system/statistics/ns1/named.conf.in
new file mode 100644
index 0000000..8fd14f9
--- /dev/null
+++ b/bin/tests/system/statistics/ns1/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+};
+
+statistics-channels {
+ inet 10.53.0.1 port @EXTRAPORT1@ allow { any; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example.info." {
+ type primary;
+ file "example-info.db";
+};
+
+zone "32/1.0.0.127-in-addr.example." {
+ type primary;
+ file "zone.db";
+};
diff --git a/bin/tests/system/statistics/ns1/root.db b/bin/tests/system/statistics/ns1/root.db
new file mode 100644
index 0000000..17780d1
--- /dev/null
+++ b/bin/tests/system/statistics/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/statistics/ns1/zone.db b/bin/tests/system/statistics/ns1/zone.db
new file mode 100644
index 0000000..7feee2c
--- /dev/null
+++ b/bin/tests/system/statistics/ns1/zone.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 IN SOA ns.example. hostmaster.example. 1 3600 1200 604800 3600
+@ 3600 IN NS ns.example.
+ns.example. 3600 IN A 10.53.0.1
diff --git a/bin/tests/system/statistics/ns2/example.db b/bin/tests/system/statistics/ns2/example.db
new file mode 100644
index 0000000..4d60ce3
--- /dev/null
+++ b/bin/tests/system/statistics/ns2/example.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+$ORIGIN example.
+a A 10.0.0.1
+ MX 10 mail.example.
+
+mail A 10.0.0.2
diff --git a/bin/tests/system/statistics/ns2/internal.db b/bin/tests/system/statistics/ns2/internal.db
new file mode 100644
index 0000000..4f1014f
--- /dev/null
+++ b/bin/tests/system/statistics/ns2/internal.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.1.0.1
+ MX 10 intmail.example.
+
+intmail A 10.1.0.2
diff --git a/bin/tests/system/statistics/ns2/named.conf.in b/bin/tests/system/statistics/ns2/named.conf.in
new file mode 100644
index 0000000..48fb8b4
--- /dev/null
+++ b/bin/tests/system/statistics/ns2/named.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+};
+
+statistics-channels {
+ inet 10.53.0.2 port @EXTRAPORT1@ allow { any; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/statistics/ns2/named2.conf.in b/bin/tests/system/statistics/ns2/named2.conf.in
new file mode 100644
index 0000000..d370931
--- /dev/null
+++ b/bin/tests/system/statistics/ns2/named2.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+};
+
+statistics-channels {
+ inet 10.53.0.2 port @EXTRAPORT1@ allow { any; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-update { any; };
+ zone-statistics full;
+};
diff --git a/bin/tests/system/statistics/ns3/internal.db b/bin/tests/system/statistics/ns3/internal.db
new file mode 100644
index 0000000..c93c2b0
--- /dev/null
+++ b/bin/tests/system/statistics/ns3/internal.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.1.0.1
+ MX 10 intmail.example.
+
+intmail A 10.1.0.2
diff --git a/bin/tests/system/statistics/ns3/named.conf.in b/bin/tests/system/statistics/ns3/named.conf.in
new file mode 100644
index 0000000..4cc712d
--- /dev/null
+++ b/bin/tests/system/statistics/ns3/named.conf.in
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ qname-minimization disabled;
+ zone-statistics yes;
+};
+
+statistics-channels {
+ inet 10.53.0.3 port @EXTRAPORT1@ allow { any; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
+zone "example" {
+ type primary;
+ allow-update { any; };
+ file "internal.db";
+};
+
+zone "a-secondary" {
+ type secondary;
+ file "sec.bk";
+ primaries { 10.53.0.1; };
+};
diff --git a/bin/tests/system/statistics/ns3/root.hint b/bin/tests/system/statistics/ns3/root.hint
new file mode 100644
index 0000000..0f5c701
--- /dev/null
+++ b/bin/tests/system/statistics/ns3/root.hint
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+;
+; The configured root server is intentionally bad here,
+; so we can count queries "on fly", priming and the other
+; counters that would be immediately resolved if the root
+; nameservers would work.
+;
+
+$TTL 999999
+. IN NS d.root-servers.nil.
+d.root-servers.nil. IN A 10.53.0.4
diff --git a/bin/tests/system/statistics/setup.sh b/bin/tests/system/statistics/setup.sh
new file mode 100644
index 0000000..7ffda55
--- /dev/null
+++ b/bin/tests/system/statistics/setup.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
diff --git a/bin/tests/system/statistics/tests.sh b/bin/tests/system/statistics/tests.sh
new file mode 100644
index 0000000..af57b60
--- /dev/null
+++ b/bin/tests/system/statistics/tests.sh
@@ -0,0 +1,282 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGCMD="$DIG +tcp -p ${PORT}"
+RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../common/rndc.conf"
+
+status=0
+
+ret=0
+n=1
+stats=0
+nsock0nstat=0
+nsock1nstat=0
+rndc_stats() {
+ _ns=$1
+ _ip=$2
+
+ $RNDCCMD -s $_ip stats > /dev/null 2>&1 || return 1
+ [ -f "${_ns}/named.stats" ] || return 1
+
+ last_stats=named.stats.$_ns-$stats-$n
+ mv ${_ns}/named.stats $last_stats
+ stats=$((stats+1))
+}
+
+echo_i "fetching a.example from ns2's initial configuration ($n)"
+$DIGCMD +noauth a.example. @10.53.0.2 any > dig.out.ns2.1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "dumping initial stats for ns2 ($n)"
+rndc_stats ns2 10.53.0.2 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "verifying adb records in named.stats ($n)"
+grep "ADB stats" $last_stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "checking for 1 entry in adb hash table in named.stats ($n)"
+grep "1 Addresses in hash table" $last_stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "verifying cache statistics in named.stats ($n)"
+grep "Cache Statistics" $last_stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "checking for 2 entries in adb hash table in named.stats ($n)"
+$DIGCMD a.example.info. @10.53.0.2 any > /dev/null 2>&1
+rndc_stats ns2 10.53.0.2 || ret=1
+grep "2 Addresses in hash table" $last_stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "dumping initial stats for ns3 ($n)"
+rndc_stats ns3 10.53.0.3 || ret=1
+nsock0nstat=$(grep "UDP/IPv4 sockets active" $last_stats | awk '{print $1}')
+[ 0 -ne ${nsock0nstat} ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "sending queries to ns3"
+$DIGCMD +tries=2 +time=1 +recurse @10.53.0.3 foo.info. any > /dev/null 2>&1 || true
+
+ret=0
+echo_i "dumping updated stats for ns3 ($n)"
+getstats() {
+ rndc_stats ns3 10.53.0.3 || return 1
+ grep "2 recursing clients" $last_stats > /dev/null || return 1
+}
+retry_quiet 5 getstats || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "verifying recursing clients output in named.stats ($n)"
+grep "2 recursing clients" $last_stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "verifying active fetches output in named.stats ($n)"
+grep "1 active fetches" $last_stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "verifying active sockets output in named.stats ($n)"
+nsock1nstat=$(grep "UDP/IPv4 sockets active" $last_stats | awk '{print $1}')
+[ $((nsock1nstat - nsock0nstat)) -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# there should be 1 UDP and no TCP queries. As the TCP counter is zero
+# no status line is emitted.
+ret=0
+echo_i "verifying queries in progress in named.stats ($n)"
+grep "1 UDP queries in progress" $last_stats > /dev/null || ret=1
+grep "TCP queries in progress" $last_stats > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "verifying bucket size output ($n)"
+grep "bucket size" $last_stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "checking priming queries are counted ($n)"
+grep "priming queries" $last_stats > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "checking that zones with slash are properly shown in XML output ($n)"
+if $FEATURETEST --have-libxml2 && [ -x ${CURL} ] ; then
+ ${CURL} http://10.53.0.1:${EXTRAPORT1}/xml/v3/zones > curl.out.${n} 2>/dev/null || ret=1
+ grep '<zone name="32/1.0.0.127-in-addr.example" rdataclass="IN">' curl.out.${n} > /dev/null || ret=1
+else
+ echo_i "skipping test as libxml2 and/or curl was not found"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "checking that zones return their type ($n)"
+if $FEATURETEST --have-libxml2 && [ -x ${CURL} ] ; then
+ ${CURL} http://10.53.0.1:${EXTRAPORT1}/xml/v3/zones > curl.out.${n} 2>/dev/null || ret=1
+ grep '<zone name="32/1.0.0.127-in-addr.example" rdataclass="IN"><type>primary</type>' curl.out.${n} > /dev/null || ret=1
+else
+ echo_i "skipping test as libxml2 and/or curl was not found"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "checking bind9.xsl vs xml ($n)"
+if $FEATURETEST --have-libxml2 && "${CURL}" --http1.1 http://10.53.0.3:${EXTRAPORT1} > /dev/null 2>&1 && [ -x "${XSLTPROC}" ] ; then
+ $DIGCMD +notcp +recurse @10.53.0.3 soa . > dig.out.test$n.1 2>&1
+ $DIGCMD +notcp +recurse @10.53.0.3 soa example > dig.out.test$n.2 2>&1
+ # check multiple requests over the same socket
+ time1=$($PERL -e 'print time(), "\n";')
+ ${CURL} --http1.1 -o curl.out.${n}.xml http://10.53.0.3:${EXTRAPORT1}/xml/v3 \
+ -o curl.out.${n}.xsl http://10.53.0.3:${EXTRAPORT1}/bind9.xsl 2>/dev/null || ret=1
+ time2=$($PERL -e 'print time(), "\n";')
+ test $((time2 - time1)) -lt 5 || ret=1
+ diff ${TOP_SRCDIR}/bin/named/bind9.xsl curl.out.${n}.xsl || ret=1
+ ${XSLTPROC} curl.out.${n}.xsl - < curl.out.${n}.xml > xsltproc.out.${n} 2>/dev/null || ret=1
+ cp curl.out.${n}.xml stats.xml.out || ret=1
+
+ #
+ # grep for expected sections.
+ #
+ grep "<h1>ISC Bind 9 Configuration and Statistics</h1>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Server Status</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Incoming Requests by DNS Opcode</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h3>Incoming Queries by Query Type</h3>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Outgoing Queries per view</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h3>View " xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Server Statistics</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Zone Maintenance Statistics</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ # grep "<h2>Resolver Statistics (Common)</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h3>Resolver Statistics for View " xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h3>ADB Statistics for View " xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h3>Cache Statistics for View " xsltproc.out.${n} >/dev/null || ret=1
+ # grep "<h3>Cache DB RRsets for View " xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Traffic Size Statistics</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h4>UDP Requests Received</h4>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h4>UDP Responses Sent</h4>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h4>TCP Requests Received</h4>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h4>TCP Responses Sent</h4>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Socket I/O Statistics</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h3>Zones for View " xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Received QTYPES per view/zone</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h3>View _default" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h4>Zone example" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Response Codes per view/zone</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h3>View _default" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h4>Zone example" xsltproc.out.${n} >/dev/null || ret=1
+ # grep "<h2>Glue cache statistics</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h3>View _default" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h4>Zone example" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Task Manager Configuration</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Tasks</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Memory Usage Summary</h2>" xsltproc.out.${n} >/dev/null || ret=1
+ grep "<h2>Memory Contexts</h2>" xsltproc.out.${n} >/dev/null || ret=1
+else
+ echo_i "skipping test as libxml2 and/or curl with HTTP/1.1 support and/or xsltproc was not found"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "checking bind9.xml socket statistics ($n)"
+if $FEATURETEST --have-libxml2 && [ -e stats.xml.out ] && [ -x "${XSLTPROC}" ] ; then
+ # Socket statistics (expect no errors)
+ grep "<counter name=\"TCP4AcceptFail\">0</counter>" stats.xml.out >/dev/null || ret=1
+ grep "<counter name=\"TCP4BindFail\">0</counter>" stats.xml.out >/dev/null || ret=1
+ grep "<counter name=\"TCP4ConnFail\">0</counter>" stats.xml.out >/dev/null || ret=1
+ grep "<counter name=\"TCP4OpenFail\">0</counter>" stats.xml.out >/dev/null || ret=1
+ grep "<counter name=\"TCP4RecvErr\">0</counter>" stats.xml.out >/dev/null || ret=1
+ # grep "<counter name=\"TCP4SendErr\">0</counter>" stats.xml.out >/dev/null || ret=1
+
+ grep "<counter name=\"TCP6AcceptFail\">0</counter>" stats.xml.out >/dev/null || ret=1
+ grep "<counter name=\"TCP6BindFail\">0</counter>" stats.xml.out >/dev/null || ret=1
+ grep "<counter name=\"TCP6ConnFail\">0</counter>" stats.xml.out >/dev/null || ret=1
+ grep "<counter name=\"TCP6OpenFail\">0</counter>" stats.xml.out >/dev/null || ret=1
+ grep "<counter name=\"TCP6RecvErr\">0</counter>" stats.xml.out >/dev/null || ret=1
+ grep "<counter name=\"TCP6SendErr\">0</counter>" stats.xml.out >/dev/null || ret=1
+else
+ echo_i "skipping test as libxml2 and/or stats.xml.out file and/or xsltproc was not found"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "Check that 'zone-statistics full;' is processed by 'rndc reconfig' ($n)"
+ret=0
+# off by default
+rndc_stats ns2 10.53.0.2 || ret=1
+sed -n '/Per Zone Query Statistics/,/^++/p' $last_stats | grep -F '[example]' > /dev/null && ret=0
+# turn on
+copy_setports ns2/named2.conf.in ns2/named.conf
+rndc_reconfig ns2 10.53.0.2
+rndc_stats ns2 10.53.0.2 || ret=1
+sed -n '/Per Zone Query Statistics/,/^++/p' $last_stats | grep -F '[example]' > /dev/null || ret=1
+# turn off
+copy_setports ns2/named.conf.in ns2/named.conf
+rndc_reconfig ns2 10.53.0.2
+rndc_stats ns2 10.53.0.2 || ret=1
+sed -n '/Per Zone Query Statistics/,/^++/p' $last_stats | grep -F '[example]' > /dev/null && ret=0
+# turn on
+copy_setports ns2/named2.conf.in ns2/named.conf
+rndc_reconfig ns2 10.53.0.2
+rndc_stats ns2 10.53.0.2 || ret=1
+sed -n '/Per Zone Query Statistics/,/^++/p' $last_stats | grep -F '[example]' > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/statistics/tests_sh_statistics.py b/bin/tests/system/statistics/tests_sh_statistics.py
new file mode 100644
index 0000000..d87688f
--- /dev/null
+++ b/bin/tests/system/statistics/tests_sh_statistics.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_statistics(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/statschannel/clean.sh b/bin/tests/system/statschannel/clean.sh
new file mode 100644
index 0000000..b0ab571
--- /dev/null
+++ b/bin/tests/system/statschannel/clean.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ./Kdnssec*
+rm -f bind9.xsl.1 bind9.xsl.2 bind9.xsl.3
+rm -f compressed.headers regular.headers compressed.out regular.out
+rm -f dig.out*
+rm -f nc.out* curl.out* header.in*
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.conf
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run*
+rm -f ns*/named.stats
+rm -f ns*/signzone.out.*
+rm -f ns2/*.db.signed* ns2/dsset-*. ns2/*.jbk
+rm -f ns2/Kdnssec* ns2/dnssec.*.id
+rm -f ns2/Kmanykeys* ns2/manykeys.*.id
+rm -f ns2/dnssec.db.signed* ns2/dsset-dnssec.
+rm -f ns3/*.db
+rm -f traffic traffic.out.* traffic.json.* traffic.xml.*
+rm -f xml.*mem json.*mem
+rm -f xml.*stats json.*stats
+rm -f zones zones.out.* zones.json.* zones.xml.* zones.expect.*
+rm -rf ./__pycache__
diff --git a/bin/tests/system/statschannel/conftest.py b/bin/tests/system/statschannel/conftest.py
new file mode 100644
index 0000000..363dd7a
--- /dev/null
+++ b/bin/tests/system/statschannel/conftest.py
@@ -0,0 +1,25 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import os
+import pytest
+
+
+@pytest.fixture
+def statsport(request):
+ # pylint: disable=unused-argument
+ env_port = os.getenv("EXTRAPORT1")
+ if env_port is None:
+ env_port = 5301
+ else:
+ env_port = int(env_port)
+
+ return env_port
diff --git a/bin/tests/system/statschannel/fetch.pl b/bin/tests/system/statschannel/fetch.pl
new file mode 100644
index 0000000..b09ed54
--- /dev/null
+++ b/bin/tests/system/statschannel/fetch.pl
@@ -0,0 +1,43 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# fetch.pl:
+# Simple script to fetch HTTP content from the statistics channel
+# of a BIND server. Fetches the full XML stats from 10.53.0.2 port
+# 8853 by default; these can be overridden by command line arguments.
+
+use File::Fetch;
+use Getopt::Std;
+
+sub usage {
+ print ("Usage: fetch.pl [-s address] [-p port] [path]\n");
+ exit 1;
+}
+
+my %options={};
+getopts("s:p:", \%options);
+
+my $addr = "10.53.0.2";
+$addr = $options{s} if defined $options{s};
+
+my $path = 'xml/v3';
+if (@ARGV >= 1) {
+ $path = shift @ARGV;
+}
+
+my $port = 8853;
+$port = $options{p} if defined $options{p};
+
+my $ff = File::Fetch->new(uri => "http://$addr:$port/$path");
+my $file = $ff->fetch() or die $ff->error;
+print ("$file\n");
diff --git a/bin/tests/system/statschannel/generic.py b/bin/tests/system/statschannel/generic.py
new file mode 100644
index 0000000..bf4b038
--- /dev/null
+++ b/bin/tests/system/statschannel/generic.py
@@ -0,0 +1,108 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from datetime import datetime, timedelta
+import os
+
+
+# ISO datetime format without msec
+fmt = "%Y-%m-%dT%H:%M:%SZ"
+
+# The constants were taken from BIND 9 source code (lib/dns/zone.c)
+max_refresh = timedelta(seconds=2419200) # 4 weeks
+max_expires = timedelta(seconds=14515200) # 24 weeks
+now = datetime.utcnow().replace(microsecond=0)
+dayzero = datetime.utcfromtimestamp(0).replace(microsecond=0)
+
+
+# Generic helper functions
+def check_expires(expires, min_time, max_time):
+ assert expires >= min_time
+ assert expires <= max_time
+
+
+def check_refresh(refresh, min_time, max_time):
+ assert refresh >= min_time
+ assert refresh <= max_time
+
+
+def check_loaded(loaded, expected): # pylint: disable=unused-argument
+ # Sanity check the zone timers values
+ # NOTE This check has been disabled due to GL #3983
+ # assert loaded == expected
+ # assert loaded < now
+ pass
+
+
+def check_zone_timers(loaded, expires, refresh, loaded_exp):
+ # Sanity checks the zone timers values
+ if expires is not None:
+ check_expires(expires, now, now + max_expires)
+ if refresh is not None:
+ check_refresh(refresh, now, now + max_refresh)
+ check_loaded(loaded, loaded_exp)
+
+
+#
+# The output is gibberish, but at least make sure it does not crash.
+#
+def check_manykeys(name, zone=None):
+ # pylint: disable=unused-argument
+ assert name == "manykeys"
+
+
+def zone_mtime(zonedir, name):
+ try:
+ si = os.stat(os.path.join(zonedir, "{}.db".format(name)))
+ except FileNotFoundError:
+ return dayzero
+
+ mtime = datetime.utcfromtimestamp(si.st_mtime).replace(microsecond=0)
+
+ return mtime
+
+
+def test_zone_timers_primary(fetch_zones, load_timers, **kwargs):
+ statsip = kwargs["statsip"]
+ statsport = kwargs["statsport"]
+ zonedir = kwargs["zonedir"]
+
+ zones = fetch_zones(statsip, statsport)
+
+ for zone in zones:
+ (name, loaded, expires, refresh) = load_timers(zone, True)
+ mtime = zone_mtime(zonedir, name)
+ check_zone_timers(loaded, expires, refresh, mtime)
+
+
+def test_zone_timers_secondary(fetch_zones, load_timers, **kwargs):
+ statsip = kwargs["statsip"]
+ statsport = kwargs["statsport"]
+ zonedir = kwargs["zonedir"]
+
+ zones = fetch_zones(statsip, statsport)
+
+ for zone in zones:
+ (name, loaded, expires, refresh) = load_timers(zone, False)
+ mtime = zone_mtime(zonedir, name)
+ check_zone_timers(loaded, expires, refresh, mtime)
+
+
+def test_zone_with_many_keys(fetch_zones, load_zone, **kwargs):
+ statsip = kwargs["statsip"]
+ statsport = kwargs["statsport"]
+
+ zones = fetch_zones(statsip, statsport)
+
+ for zone in zones:
+ name = load_zone(zone)
+ if name == "manykeys":
+ check_manykeys(name)
diff --git a/bin/tests/system/statschannel/generic_dnspython.py b/bin/tests/system/statschannel/generic_dnspython.py
new file mode 100644
index 0000000..34a0398
--- /dev/null
+++ b/bin/tests/system/statschannel/generic_dnspython.py
@@ -0,0 +1,128 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from collections import defaultdict
+
+import dns.message
+import dns.query
+import dns.rcode
+
+
+TIMEOUT = 10
+
+
+def create_msg(qname, qtype):
+ msg = dns.message.make_query(
+ qname, qtype, want_dnssec=True, use_edns=0, payload=4096
+ )
+
+ return msg
+
+
+def udp_query(ip, port, msg):
+ ans = dns.query.udp(msg, ip, TIMEOUT, port=port)
+ assert ans.rcode() == dns.rcode.NOERROR
+
+ return ans
+
+
+def tcp_query(ip, port, msg):
+ ans = dns.query.tcp(msg, ip, TIMEOUT, port=port)
+ assert ans.rcode() == dns.rcode.NOERROR
+
+ return ans
+
+
+def create_expected(data):
+ expected = {
+ "dns-tcp-requests-sizes-received-ipv4": defaultdict(int),
+ "dns-tcp-responses-sizes-sent-ipv4": defaultdict(int),
+ "dns-tcp-requests-sizes-received-ipv6": defaultdict(int),
+ "dns-tcp-responses-sizes-sent-ipv6": defaultdict(int),
+ "dns-udp-requests-sizes-received-ipv4": defaultdict(int),
+ "dns-udp-requests-sizes-received-ipv6": defaultdict(int),
+ "dns-udp-responses-sizes-sent-ipv4": defaultdict(int),
+ "dns-udp-responses-sizes-sent-ipv6": defaultdict(int),
+ }
+
+ for k, v in data.items():
+ for kk, vv in v.items():
+ expected[k][kk] += vv
+
+ return expected
+
+
+def update_expected(expected, key, msg):
+ msg_len = len(msg.to_wire())
+ bucket_num = (msg_len // 16) * 16
+ bucket = "{}-{}".format(bucket_num, bucket_num + 15)
+
+ expected[key][bucket] += 1
+
+
+def check_traffic(data, expected):
+ def ordered(obj):
+ if isinstance(obj, dict):
+ return sorted((k, ordered(v)) for k, v in obj.items())
+ if isinstance(obj, list):
+ return sorted(ordered(x) for x in obj)
+ return obj
+
+ ordered_data = ordered(data)
+ ordered_expected = ordered(expected)
+
+ assert len(ordered_data) == 8
+ assert len(ordered_expected) == 8
+ assert len(data) == len(ordered_data)
+ assert len(expected) == len(ordered_expected)
+
+ assert ordered_data == ordered_expected
+
+
+def test_traffic(fetch_traffic, **kwargs):
+ statsip = kwargs["statsip"]
+ statsport = kwargs["statsport"]
+ port = kwargs["port"]
+
+ data = fetch_traffic(statsip, statsport)
+ exp = create_expected(data)
+
+ msg = create_msg("short.example.", "TXT")
+ update_expected(exp, "dns-udp-requests-sizes-received-ipv4", msg)
+ ans = udp_query(statsip, port, msg)
+ update_expected(exp, "dns-udp-responses-sizes-sent-ipv4", ans)
+ data = fetch_traffic(statsip, statsport)
+
+ check_traffic(data, exp)
+
+ msg = create_msg("long.example.", "TXT")
+ update_expected(exp, "dns-udp-requests-sizes-received-ipv4", msg)
+ ans = udp_query(statsip, port, msg)
+ update_expected(exp, "dns-udp-responses-sizes-sent-ipv4", ans)
+ data = fetch_traffic(statsip, statsport)
+
+ check_traffic(data, exp)
+
+ msg = create_msg("short.example.", "TXT")
+ update_expected(exp, "dns-tcp-requests-sizes-received-ipv4", msg)
+ ans = tcp_query(statsip, port, msg)
+ update_expected(exp, "dns-tcp-responses-sizes-sent-ipv4", ans)
+ data = fetch_traffic(statsip, statsport)
+
+ check_traffic(data, exp)
+
+ msg = create_msg("long.example.", "TXT")
+ update_expected(exp, "dns-tcp-requests-sizes-received-ipv4", msg)
+ ans = tcp_query(statsip, port, msg)
+ update_expected(exp, "dns-tcp-responses-sizes-sent-ipv4", ans)
+ data = fetch_traffic(statsip, statsport)
+
+ check_traffic(data, exp)
diff --git a/bin/tests/system/statschannel/mem-xml.pl b/bin/tests/system/statschannel/mem-xml.pl
new file mode 100644
index 0000000..4483aae
--- /dev/null
+++ b/bin/tests/system/statschannel/mem-xml.pl
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# server-xml.pl:
+# Parses the XML version of the server stats into a normalized format.
+
+use XML::Simple;
+use Data::Dumper;
+
+my $ref = XMLin("xml.mem");
+print Dumper($ref);
diff --git a/bin/tests/system/statschannel/ns1/example.db b/bin/tests/system/statschannel/ns1/example.db
new file mode 100644
index 0000000..5c2635e
--- /dev/null
+++ b/bin/tests/system/statschannel/ns1/example.db
@@ -0,0 +1,49 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+$ORIGIN example.
+a A 10.0.0.1
+ MX 10 mail.example.
+short TXT "short text"
+long TXT (
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ )
+
+mail A 10.0.0.2
diff --git a/bin/tests/system/statschannel/ns1/named.conf.in b/bin/tests/system/statschannel/ns1/named.conf.in
new file mode 100644
index 0000000..52fd9fd
--- /dev/null
+++ b/bin/tests/system/statschannel/ns1/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify explicit;
+ minimal-responses no;
+ version none; // make statistics independent of the version number
+};
+
+statistics-channels { inet 10.53.0.1 port @EXTRAPORT1@ allow { localhost; }; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-transfer { any; };
+};
diff --git a/bin/tests/system/statschannel/ns2/dnssec.db.in b/bin/tests/system/statschannel/ns2/dnssec.db.in
new file mode 100644
index 0000000..90ae166
--- /dev/null
+++ b/bin/tests/system/statschannel/ns2/dnssec.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300
+
+dnssec. IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+dnssec. NS ns2.dnssec.
+ns2.dnssec. A 10.53.0.2
+
+$ORIGIN dnssec.
+a A 10.0.0.1
+ MX 10 mail.dnssec.
+mail A 10.0.0.2
diff --git a/bin/tests/system/statschannel/ns2/example.db b/bin/tests/system/statschannel/ns2/example.db
new file mode 100644
index 0000000..5c2635e
--- /dev/null
+++ b/bin/tests/system/statschannel/ns2/example.db
@@ -0,0 +1,49 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+$ORIGIN example.
+a A 10.0.0.1
+ MX 10 mail.example.
+short TXT "short text"
+long TXT (
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ )
+
+mail A 10.0.0.2
diff --git a/bin/tests/system/statschannel/ns2/manykeys.db.in b/bin/tests/system/statschannel/ns2/manykeys.db.in
new file mode 100644
index 0000000..3281a39
--- /dev/null
+++ b/bin/tests/system/statschannel/ns2/manykeys.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300
+
+manykeys. IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+manykeys. NS ns2.manykeys.
+ns2.manykeys. A 10.53.0.2
+
+$ORIGIN manykeys.
+a A 10.0.0.1
+ MX 10 mail.manykeys.
+mail A 10.0.0.2
diff --git a/bin/tests/system/statschannel/ns2/named.conf.in b/bin/tests/system/statschannel/ns2/named.conf.in
new file mode 100644
index 0000000..0221f3d
--- /dev/null
+++ b/bin/tests/system/statschannel/ns2/named.conf.in
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+ minimal-responses no;
+ version none; // make statistics independent of the version number
+};
+
+statistics-channels { inet 10.53.0.2 port @EXTRAPORT1@ allow { localhost; }; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+dnssec-policy "manykeys" {
+ keys {
+ ksk lifetime unlimited algorithm 8;
+ zsk lifetime unlimited algorithm 8;
+ ksk lifetime unlimited algorithm 13;
+ zsk lifetime unlimited algorithm 13;
+ ksk lifetime unlimited algorithm 14;
+ zsk lifetime unlimited algorithm 14;
+ };
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-transfer { any; };
+};
+
+zone "dnssec" {
+ type primary;
+ file "dnssec.db.signed";
+ auto-dnssec maintain;
+ allow-update { any; };
+ zone-statistics full;
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+};
+
+zone "manykeys" {
+ type primary;
+ file "manykeys.db.signed";
+ allow-update { any; };
+ zone-statistics full;
+ dnssec-policy "manykeys";
+};
diff --git a/bin/tests/system/statschannel/ns2/named2.conf.in b/bin/tests/system/statschannel/ns2/named2.conf.in
new file mode 100644
index 0000000..0f5a2d3
--- /dev/null
+++ b/bin/tests/system/statschannel/ns2/named2.conf.in
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+ minimal-responses no;
+ version none; // make statistics independent of the version number
+};
+
+statistics-channels { inet 10.53.0.2 port @EXTRAPORT1@ allow { localhost; }; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+dnssec-policy "manykeys" {
+ keys {
+ ksk lifetime unlimited algorithm 8;
+ zsk lifetime unlimited algorithm 8;
+ };
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-transfer { any; };
+};
+
+zone "dnssec" {
+ type primary;
+ file "dnssec.db.signed";
+ auto-dnssec maintain;
+ allow-update { any; };
+ zone-statistics full;
+ dnssec-dnskey-kskonly yes;
+ update-check-ksk yes;
+};
+
+zone "manykeys" {
+ type primary;
+ file "manykeys.db.signed";
+ allow-update { any; };
+ zone-statistics full;
+ dnssec-policy "manykeys";
+};
diff --git a/bin/tests/system/statschannel/ns2/sign.sh b/bin/tests/system/statschannel/ns2/sign.sh
new file mode 100644
index 0000000..f9429ca
--- /dev/null
+++ b/bin/tests/system/statschannel/ns2/sign.sh
@@ -0,0 +1,45 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+zone=dnssec.
+infile=dnssec.db.in
+zonefile=dnssec.db.signed
+ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
+zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+# Sign deliberately with a very short expiration date.
+"$SIGNER" -P -S -x -O full -e "now"+1s -o "$zone" -f "$zonefile" "$infile" > "signzone.out.$zone" 2>&1
+keyfile_to_key_id "$ksk" > dnssec.ksk.id
+keyfile_to_key_id "$zsk" > dnssec.zsk.id
+
+zone=manykeys.
+infile=manykeys.db.in
+zonefile=manykeys.db.signed
+ksk8=$("$KEYGEN" -q -a RSASHA256 -b 2048 -f KSK "$zone")
+zsk8=$("$KEYGEN" -q -a RSASHA256 -b 2048 "$zone")
+ksk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -b 256 -f KSK "$zone")
+zsk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -b 256 "$zone")
+ksk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -b 384 -f KSK "$zone")
+zsk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -b 384 "$zone")
+# Sign deliberately with a very short expiration date.
+"$SIGNER" -S -x -O full -e "now"+1s -o "$zone" -f "$zonefile" "$infile" > "signzone.out.$zone" 2>&1
+keyfile_to_key_id "$ksk8" > manykeys.ksk8.id
+keyfile_to_key_id "$zsk8" > manykeys.zsk8.id
+keyfile_to_key_id "$ksk13" > manykeys.ksk13.id
+keyfile_to_key_id "$zsk13" > manykeys.zsk13.id
+keyfile_to_key_id "$ksk14" > manykeys.ksk14.id
+keyfile_to_key_id "$zsk14" > manykeys.zsk14.id
diff --git a/bin/tests/system/statschannel/ns3/named.conf.in b/bin/tests/system/statschannel/ns3/named.conf.in
new file mode 100644
index 0000000..cf3fc09
--- /dev/null
+++ b/bin/tests/system/statschannel/ns3/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+ minimal-responses no;
+ version none; // make statistics independent of the version number
+};
+
+statistics-channels { inet 10.53.0.3 port @EXTRAPORT1@ allow { localhost; }; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type secondary;
+ file "example.db";
+ primaries { 10.53.0.1; };
+};
diff --git a/bin/tests/system/statschannel/server-json.pl b/bin/tests/system/statschannel/server-json.pl
new file mode 100644
index 0000000..3715318
--- /dev/null
+++ b/bin/tests/system/statschannel/server-json.pl
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# server-json.pl:
+# Parses the JSON version of the server stats into a normalized format.
+
+use JSON;
+
+open(INPUT, "<json.stats");
+my $text = do{local$/;<INPUT>};
+close(INPUT);
+
+my $ref = decode_json($text);
+foreach $key (keys %{$ref->{opcodes}}) {
+ print "opcode " . $key . ": " . $ref->{opcodes}->{$key} . "\n";
+}
+foreach $key (keys %{$ref->{rcodes}}) {
+ print "rcode " . $key . ": " . $ref->{rcodes}->{$key} . "\n";
+}
+foreach $key (keys %{$ref->{qtypes}}) {
+ print "qtype " . $key . ": " . $ref->{qtypes}->{$key} . "\n";
+}
+foreach $key (keys %{$ref->{nsstats}}) {
+ print "nsstat " . $key . ": " . $ref->{nsstats}->{$key} . "\n";
+}
diff --git a/bin/tests/system/statschannel/server-xml.pl b/bin/tests/system/statschannel/server-xml.pl
new file mode 100644
index 0000000..5f76360
--- /dev/null
+++ b/bin/tests/system/statschannel/server-xml.pl
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# server-xml.pl:
+# Parses the XML version of the server stats into a normalized format.
+
+use XML::Simple;
+
+my $ref = XMLin("xml.stats");
+my $counters = $ref->{server}->{counters};
+foreach $group (@$counters) {
+ foreach $key (keys %{$group->{counter}}) {
+ print $group->{type} . " " . $key . ": ". $group->{counter}->{$key}->{content} . "\n";
+ }
+}
diff --git a/bin/tests/system/statschannel/setup.sh b/bin/tests/system/statschannel/setup.sh
new file mode 100644
index 0000000..f5ef3ee
--- /dev/null
+++ b/bin/tests/system/statschannel/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+for conf in ns*/named.conf.in; do
+ copy_setports "$conf" "$(dirname "$conf")/$(basename "$conf" .in)"
+done
+
+(cd ns2 && $SHELL sign.sh)
diff --git a/bin/tests/system/statschannel/tests.sh b/bin/tests/system/statschannel/tests.sh
new file mode 100644
index 0000000..f06cad4
--- /dev/null
+++ b/bin/tests/system/statschannel/tests.sh
@@ -0,0 +1,656 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+DIGCMD="$DIG @10.53.0.2 -p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+if ! $FEATURETEST --have-json-c
+then
+ unset PERL_JSON
+ echo_i "JSON was not configured; skipping" >&2
+elif $PERL -e 'use JSON;' 2>/dev/null
+then
+ PERL_JSON=1
+else
+ unset PERL_JSON
+ echo_i "JSON tests require JSON library; skipping" >&2
+fi
+
+if ! $FEATURETEST --have-libxml2
+then
+ unset PERL_XML
+ echo_i "XML was not configured; skipping" >&2
+elif $PERL -e 'use XML::Simple;' 2>/dev/null
+then
+ PERL_XML=1
+else
+ unset PERL_XML
+ echo_i "XML tests require XML::Simple; skipping" >&2
+fi
+
+if [ ! "$PERL_JSON" ] && [ ! "$PERL_XML" ]; then
+ echo_i "skipping all tests"
+ exit 0
+fi
+
+
+getzones() {
+ sleep 1
+ echo_i "... using $1"
+ case $1 in
+ xml) path='xml/v3/zones' ;;
+ json) path='json/v1/zones' ;;
+ *) return 1 ;;
+ esac
+ file=$($PERL fetch.pl -p ${EXTRAPORT1} $path)
+ cp $file $file.$1.$3
+ { $PERL zones-${1}.pl $file $2 2>/dev/null | sort > zones.out.$3; result=$?; } || true
+ return $result
+}
+
+# TODO: Move loadkeys_on to conf.sh.common
+loadkeys_on() {
+ nsidx=$1
+ zone=$2
+ nextpart ns${nsidx}/named.run > /dev/null
+ $RNDCCMD 10.53.0.${nsidx} loadkeys ${zone} | sed "s/^/ns${nsidx} /" | cat_i
+ wait_for_log 20 "next key event" ns${nsidx}/named.run
+}
+
+# verify that the http server dropped the connection without replying
+check_http_dropped() {
+ if [ -x "${NC}" ] ; then
+ "${NC}" 10.53.0.3 "${EXTRAPORT1}" > nc.out$n || ret=1
+ if test -s nc.out$n; then
+ ret=1
+ fi
+ else
+ echo_i "skipping test as nc not found"
+ fi
+}
+
+status=0
+n=1
+
+echo_i "check content-length parse error ($n)"
+ret=0
+check_http_dropped <<EOF
+POST /xml/v3/status HTTP/1.0
+Content-Length: nah
+
+EOF
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "check negative content-length ($n)"
+ret=0
+check_http_dropped <<EOF
+POST /xml/v3/status HTTP/1.0
+Content-Length: -50
+
+EOF
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "check content-length 32-bit overflow ($n)"
+check_http_dropped <<EOF
+POST /xml/v3/status HTTP/1.0
+Content-Length: 4294967239
+
+EOF
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "check content-length 64-bit overflow ($n)"
+check_http_dropped <<EOF
+POST /xml/v3/status HTTP/1.0
+Content-Length: 18446744073709551549
+
+EOF
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "Prepare for if-modified-since test ($n)"
+ret=0
+i=0
+if $FEATURETEST --have-libxml2 && [ -x "${CURL}" ] ; then
+ URL="http://10.53.0.3:${EXTRAPORT1}/bind9.xsl"
+ ${CURL} --silent --show-error --fail --output bind9.xsl.1 $URL
+ ret=$?
+else
+ echo_i "skipping test: requires libxml2 and curl"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "checking consistency between named.stats and xml/json ($n)"
+ret=0
+rm -f ns2/named.stats
+$DIGCMD +tcp example ns > dig.out.$n || ret=1
+$RNDCCMD 10.53.0.2 stats 2>&1 | sed 's/^/I:ns1 /'
+query_count=$(awk '/QUERY/ {print $1}' ns2/named.stats)
+txt_count=$(awk '/TXT/ {print $1}' ns2/named.stats)
+noerror_count=$(awk '/NOERROR/ {print $1}' ns2/named.stats)
+if [ $PERL_XML ]; then
+ file=$($PERL fetch.pl -p ${EXTRAPORT1} xml/v3/server)
+ mv $file xml.stats
+ $PERL server-xml.pl > xml.fmtstats 2> /dev/null
+ xml_query_count=$(awk '/opcode QUERY/ { print $NF }' xml.fmtstats)
+ xml_query_count=${xml_query_count:-0}
+ [ "$query_count" -eq "$xml_query_count" ] || ret=1
+ xml_txt_count=$(awk '/qtype TXT/ { print $NF }' xml.fmtstats)
+ xml_txt_count=${xml_txt_count:-0}
+ [ "$txt_count" -eq "$xml_txt_count" ] || ret=1
+ xml_noerror_count=$(awk '/rcode NOERROR/ { print $NF }' xml.fmtstats)
+ xml_noerror_count=${xml_noerror_count:-0}
+ [ "$noerror_count" -eq "$xml_noerror_count" ] || ret=1
+fi
+if [ $PERL_JSON ]; then
+ file=$($PERL fetch.pl -p ${EXTRAPORT1} json/v1/server)
+ mv $file json.stats
+ $PERL server-json.pl > json.fmtstats 2> /dev/null
+ json_query_count=$(awk '/opcode QUERY/ { print $NF }' json.fmtstats)
+ json_query_count=${json_query_count:-0}
+ [ "$query_count" -eq "$json_query_count" ] || ret=1
+ json_txt_count=$(awk '/qtype TXT/ { print $NF }' json.fmtstats)
+ json_txt_count=${json_txt_count:-0}
+ [ "$txt_count" -eq "$json_txt_count" ] || ret=1
+ json_noerror_count=$(awk '/rcode NOERROR/ { print $NF }' json.fmtstats)
+ json_noerror_count=${json_noerror_count:-0}
+ [ "$noerror_count" -eq "$json_noerror_count" ] || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "checking malloced memory statistics xml/json ($n)"
+if [ $PERL_XML ]; then
+ file=$($PERL fetch.pl -p ${EXTRAPORT1} xml/v3/mem)
+ mv $file xml.mem
+ $PERL mem-xml.pl $file > xml.fmtmem
+ grep "'Malloced' => '[0-9][0-9]*'" xml.fmtmem > /dev/null || ret=1
+ grep "'malloced' => '[0-9][0-9]*'" xml.fmtmem > /dev/null || ret=1
+ grep "'maxmalloced' => '[0-9][0-9]*'" xml.fmtmem > /dev/null || ret=1
+fi
+if [ $PERL_JSON ]; then
+ file=$($PERL fetch.pl -p ${EXTRAPORT1} json/v1/mem)
+ mv $file json.mem
+ grep '"malloced":[0-9][0-9]*,' json.mem > /dev/null || ret=1
+ grep '"maxmalloced":[0-9][0-9]*,' json.mem > /dev/null || ret=1
+ grep '"Malloced":[0-9][0-9]*,' json.mem > /dev/null || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "checking consistency between regular and compressed output ($n)"
+ret=0
+if [ -x "${CURL}" ] ; then
+ for i in 1 2 3 4 5; do
+ ret=0
+ if $FEATURETEST --have-libxml2;
+ then
+ URL="http://10.53.0.2:${EXTRAPORT1}/xml/v3/server"
+ filter_str='s#<current-time>.*</current-time>##g'
+ else
+ URL="http://10.53.0.2:${EXTRAPORT1}/json/v1/server"
+ filter_str='s#"current-time.*",##g'
+ fi
+ "${CURL}" -D regular.headers "$URL" 2>/dev/null | \
+ sed -e "$filter_str" > regular.out || ret=1
+ "${CURL}" -D compressed.headers --compressed "$URL" 2>/dev/null | \
+ sed -e "$filter_str" > compressed.out || ret=1
+ diff regular.out compressed.out >/dev/null || ret=1
+ if [ $ret != 0 ]; then
+ echo_i "failed on try $i, probably a timing issue, trying again"
+ sleep 1
+ else
+ break
+ fi
+ done
+else
+ echo_i "skipping test as curl not found"
+fi
+status=$((status + ret))
+n=$((n + 1))
+
+ret=0
+echo_i "checking if compressed output is really compressed ($n)"
+if $FEATURETEST --with-zlib;
+then
+ REGSIZE=$(cat regular.headers | \
+ grep -i Content-Length | sed -e "s/.*: \([0-9]*\).*/\1/")
+ COMPSIZE=$(cat compressed.headers | \
+ grep -i Content-Length | sed -e "s/.*: \([0-9]*\).*/\1/")
+ if [ ! $((REGSIZE / COMPSIZE)) -gt 2 ]; then
+ ret=1
+ fi
+else
+ echo_i "skipped"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# Test dnssec sign statistics.
+zone="dnssec"
+sign_prefix="dnssec-sign operations"
+refresh_prefix="dnssec-refresh operations"
+ksk_id=$(cat ns2/$zone.ksk.id)
+zsk_id=$(cat ns2/$zone.zsk.id)
+
+# Test sign operations for scheduled resigning.
+ret=0
+# The dnssec zone has 10 RRsets to sign (including NSEC) with the ZSK and one
+# RRset (DNSKEY) with the KSK. So starting named with signatures that expire
+# almost right away, this should trigger 10 zsk and 1 ksk sign operations.
+echo "${refresh_prefix} ${zsk_id}: 10" > zones.expect
+echo "${refresh_prefix} ${ksk_id}: 1" >> zones.expect
+echo "${sign_prefix} ${zsk_id}: 10" >> zones.expect
+echo "${sign_prefix} ${ksk_id}: 1" >> zones.expect
+cat zones.expect | sort > zones.expect.$n
+rm -f zones.expect
+# Fetch and check the dnssec sign statistics.
+echo_i "fetching zone '$zone' stats data after zone maintenance at startup ($n)"
+if [ $PERL_XML ]; then
+ getzones xml $zone x$n || ret=1
+ cmp zones.out.x$n zones.expect.$n || ret=1
+fi
+if [ $PERL_JSON ]; then
+ getzones json 0 j$n || ret=1
+ cmp zones.out.j$n zones.expect.$n || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# Test sign operations after dynamic update.
+ret=0
+(
+# Update dnssec zone to trigger signature creation.
+echo zone $zone
+echo server 10.53.0.2 "$PORT"
+echo update add $zone. 300 in txt "nsupdate added me"
+echo send
+) | $NSUPDATE
+# This should trigger the resign of SOA, TXT and NSEC (+3 zsk).
+echo "${refresh_prefix} ${zsk_id}: 10" > zones.expect
+echo "${refresh_prefix} ${ksk_id}: 1" >> zones.expect
+echo "${sign_prefix} ${zsk_id}: 13" >> zones.expect
+echo "${sign_prefix} ${ksk_id}: 1" >> zones.expect
+cat zones.expect | sort > zones.expect.$n
+rm -f zones.expect
+# Fetch and check the dnssec sign statistics.
+echo_i "fetching zone '$zone' stats data after dynamic update ($n)"
+if [ $PERL_XML ]; then
+ getzones xml $zone x$n || ret=1
+ cmp zones.out.x$n zones.expect.$n || ret=1
+fi
+if [ $PERL_JSON ]; then
+ getzones json 0 j$n || ret=1
+ cmp zones.out.j$n zones.expect.$n || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# Test sign operations of KSK.
+ret=0
+echo_i "fetch zone '$zone' stats data after updating DNSKEY RRset ($n)"
+# Add a standby DNSKEY, this triggers resigning the DNSKEY RRset.
+zsk=$("$KEYGEN" -K ns2 -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+$SETTIME -K ns2 -P now -A never $zsk.key > /dev/null
+loadkeys_on 2 $zone || ret=1
+# This should trigger the resign of SOA (+1 zsk) and DNSKEY (+1 ksk).
+echo "${refresh_prefix} ${zsk_id}: 11" > zones.expect
+echo "${refresh_prefix} ${ksk_id}: 2" >> zones.expect
+echo "${sign_prefix} ${zsk_id}: 14" >> zones.expect
+echo "${sign_prefix} ${ksk_id}: 2" >> zones.expect
+cat zones.expect | sort > zones.expect.$n
+rm -f zones.expect
+# Fetch and check the dnssec sign statistics.
+if [ $PERL_XML ]; then
+ getzones xml $zone x$n || ret=1
+ cmp zones.out.x$n zones.expect.$n || ret=1
+fi
+if [ $PERL_JSON ]; then
+ getzones json 0 j$n || ret=1
+ cmp zones.out.j$n zones.expect.$n || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# Test sign operations for scheduled resigning (many keys).
+ret=0
+zone="manykeys"
+ksk8_id=$(cat ns2/$zone.ksk8.id)
+zsk8_id=$(cat ns2/$zone.zsk8.id)
+ksk13_id=$(cat ns2/$zone.ksk13.id)
+zsk13_id=$(cat ns2/$zone.zsk13.id)
+ksk14_id=$(cat ns2/$zone.ksk14.id)
+zsk14_id=$(cat ns2/$zone.zsk14.id)
+# The dnssec zone has 10 RRsets to sign (including NSEC) with the ZSKs and one
+# RRset (DNSKEY) with the KSKs. So starting named with signatures that expire
+# almost right away, this should trigger 10 zsk and 1 ksk sign operations per
+# key.
+echo "${refresh_prefix} ${zsk8_id}: 10" > zones.expect
+echo "${refresh_prefix} ${zsk13_id}: 10" >> zones.expect
+echo "${refresh_prefix} ${zsk14_id}: 10" >> zones.expect
+echo "${refresh_prefix} ${ksk8_id}: 1" >> zones.expect
+echo "${refresh_prefix} ${ksk13_id}: 1" >> zones.expect
+echo "${refresh_prefix} ${ksk14_id}: 1" >> zones.expect
+echo "${sign_prefix} ${zsk8_id}: 10" >> zones.expect
+echo "${sign_prefix} ${zsk13_id}: 10" >> zones.expect
+echo "${sign_prefix} ${zsk14_id}: 10" >> zones.expect
+echo "${sign_prefix} ${ksk8_id}: 1" >> zones.expect
+echo "${sign_prefix} ${ksk13_id}: 1" >> zones.expect
+echo "${sign_prefix} ${ksk14_id}: 1" >> zones.expect
+cat zones.expect | sort > zones.expect.$n
+rm -f zones.expect
+# Fetch and check the dnssec sign statistics.
+echo_i "fetching zone '$zone' stats data after zone maintenance at startup ($n)"
+if [ $PERL_XML ]; then
+ getzones xml $zone x$n || ret=1
+ cmp zones.out.x$n zones.expect.$n || ret=1
+fi
+if [ $PERL_JSON ]; then
+ getzones json 2 j$n || ret=1
+ cmp zones.out.j$n zones.expect.$n || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# Test sign operations after dynamic update (many keys).
+ret=0
+(
+# Update dnssec zone to trigger signature creation.
+echo zone $zone
+echo server 10.53.0.2 "$PORT"
+echo update add $zone. 300 in txt "nsupdate added me"
+echo send
+) | $NSUPDATE
+# This should trigger the resign of SOA, TXT and NSEC (+3 zsk).
+echo "${refresh_prefix} ${zsk8_id}: 10" > zones.expect
+echo "${refresh_prefix} ${zsk13_id}: 10" >> zones.expect
+echo "${refresh_prefix} ${zsk14_id}: 10" >> zones.expect
+echo "${refresh_prefix} ${ksk8_id}: 1" >> zones.expect
+echo "${refresh_prefix} ${ksk13_id}: 1" >> zones.expect
+echo "${refresh_prefix} ${ksk14_id}: 1" >> zones.expect
+echo "${sign_prefix} ${zsk8_id}: 13" >> zones.expect
+echo "${sign_prefix} ${zsk13_id}: 13" >> zones.expect
+echo "${sign_prefix} ${zsk14_id}: 13" >> zones.expect
+echo "${sign_prefix} ${ksk8_id}: 1" >> zones.expect
+echo "${sign_prefix} ${ksk13_id}: 1" >> zones.expect
+echo "${sign_prefix} ${ksk14_id}: 1" >> zones.expect
+cat zones.expect | sort > zones.expect.$n
+rm -f zones.expect
+# Fetch and check the dnssec sign statistics.
+echo_i "fetching zone '$zone' stats data after dynamic update ($n)"
+if [ $PERL_XML ]; then
+ getzones xml $zone x$n || ret=1
+ cmp zones.out.x$n zones.expect.$n || ret=1
+fi
+if [ $PERL_JSON ]; then
+ getzones json 2 j$n || ret=1
+ cmp zones.out.j$n zones.expect.$n || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+# Test sign operations after dnssec-policy change (removing keys).
+ret=0
+copy_setports ns2/named2.conf.in ns2/named.conf
+$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/I:ns2 /'
+# This should trigger the resign of DNSKEY (+1 ksk), and SOA, NSEC,
+# TYPE65534 (+3 zsk). The dnssec-sign statistics for the removed keys should
+# be cleared and thus no longer visible. But NSEC and SOA are (mistakenly)
+# counted double, one time because of zone_resigninc and one time because of
+# zone_nsec3chain. So +5 zsk in total.
+echo "${refresh_prefix} ${zsk8_id}: 15" > zones.expect
+echo "${refresh_prefix} ${ksk8_id}: 2" >> zones.expect
+echo "${sign_prefix} ${zsk8_id}: 18" >> zones.expect
+echo "${sign_prefix} ${ksk8_id}: 2" >> zones.expect
+cat zones.expect | sort > zones.expect.$n
+rm -f zones.expect
+# Fetch and check the dnssec sign statistics.
+echo_i "fetching zone '$zone' stats data after dnssec-policy change ($n)"
+if [ $PERL_XML ]; then
+ getzones xml $zone x$n || ret=1
+ cmp zones.out.x$n zones.expect.$n || ret=1
+fi
+if [ $PERL_JSON ]; then
+ getzones json 2 j$n || ret=1
+ cmp zones.out.j$n zones.expect.$n || ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "Check HTTP/1.1 client-side pipelined requests are handled (GET) ($n)"
+ret=0
+if [ -x "${NC}" ] ; then
+ "${NC}" 10.53.0.3 "${EXTRAPORT1}" << EOF > nc.out$n || ret=1
+GET /xml/v3/status HTTP/1.1
+Host: 10.53.0.3:${EXTRAPORT1}
+
+GET /xml/v3/status HTTP/1.1
+Host: 10.53.0.3:${EXTRAPORT1}
+Connection: close
+
+EOF
+ lines=$(grep -c "^<statistics version" nc.out$n)
+ test "$lines" = 2 || ret=1
+ # keep-alive not needed in HTTP/1.1, second response has close
+ lines=$(grep -c "^Connection: Keep-Alive" nc.out$n || true)
+ test "$lines" = 0 || ret=1
+ lines=$(grep -c "^Connection: close" nc.out$n)
+ test "$lines" = 1 || ret=1
+else
+ echo_i "skipping test as nc not found"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "Check HTTP/1.1 client-side pipelined requests are handled (POST) ($n)"
+ret=0
+if [ -x "${NC}" ]; then
+ "${NC}" 10.53.0.3 "${EXTRAPORT1}" << EOF > nc.out$n || ret=1
+POST /xml/v3/status HTTP/1.1
+Host: 10.53.0.3:${EXTRAPORT1}
+Content-Type: application/json
+Content-Length: 3
+
+{}
+POST /xml/v3/status HTTP/1.1
+Host: 10.53.0.3:${EXTRAPORT1}
+Content-Type: application/json
+Content-Length: 3
+Connection: close
+
+{}
+EOF
+ lines=$(grep -c "^<statistics version" nc.out$n)
+ test "$lines" = 2 || ret=1
+ # keep-alive not needed in HTTP/1.1, second response has close
+ lines=$(grep -c "^Connection: Keep-Alive" nc.out$n || true)
+ test "$lines" = 0 || ret=1
+ lines=$(grep -c "^Connection: close" nc.out$n)
+ test "$lines" = 1 || ret=1
+else
+ echo_i "skipping test as nc not found"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "Check HTTP/1.0 keep-alive ($n)"
+ret=0
+if [ -x "${NC}" ]; then
+ "${NC}" 10.53.0.3 "${EXTRAPORT1}" << EOF > nc.out$n || ret=1
+GET /xml/v3/status HTTP/1.0
+Connection: keep-alive
+
+GET /xml/v3/status HTTP/1.0
+
+EOF
+ # should be two responses
+ lines=$(grep -c "^<statistics version" nc.out$n)
+ test "$lines" = 2 || ret=1
+ # first response has keep-alive, second has close
+ lines=$(grep -c "^Connection: Keep-Alive" nc.out$n || true)
+ test "$lines" = 1 || ret=1
+ lines=$(grep -c "^Connection: close" nc.out$n)
+ test "$lines" = 1 || ret=1
+else
+ echo_i "skipping test as nc not found"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "Check inconsistent Connection: headers ($n)"
+ret=0
+if [ -x "${NC}" ]; then
+ "${NC}" 10.53.0.3 "${EXTRAPORT1}" << EOF > nc.out$n || ret=1
+GET /xml/v3/status HTTP/1.0
+Connection: keep-alive
+Connection: close
+
+GET /xml/v3/status HTTP/1.0
+
+EOF
+ # should be one response (second is ignored)
+ lines=$(grep -c "^<statistics version" nc.out$n)
+ test "$lines" = 1 || ret=1
+ # no keep-alive, one close
+ lines=$(grep -c "^Connection: Keep-Alive" nc.out$n || true)
+ test "$lines" = 0 || ret=1
+ lines=$(grep -c "^Connection: close" nc.out$n)
+ test "$lines" = 1 || ret=1
+else
+ echo_i "skipping test as nc not found"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+if [ -x "${CURL}" ] && ! ("${CURL}" --next 2>&1 | grep 'option --next: is unknown'); then
+ CURL_NEXT="${CURL}"
+fi
+
+echo_i "Check HTTP with more than 100 headers ($n)"
+ret=0
+i=0
+if [ -x "${CURL_NEXT}" ] ; then
+ # build input stream.
+ : > header.in$n
+ while test $i -lt 101
+ do
+ printf 'X-Bloat%d: VGhlIG1vc3QgY29tbW9uIHJlYXNvbiBmb3IgYmxvYXRpbmcgaXMgaGF2aW5nIGEgbG90IG9mIGdhcyBpbiB5b3VyIGd1dC4gCg==\r\n' $i >> header.in$n
+ i=$((i+1))
+ done
+ printf '\r\n' >> header.in$n
+
+ # send the requests then wait for named to close the socket.
+ URL="http://10.53.0.3:${EXTRAPORT1}/xml/v3/status"
+ "${CURL}" --silent --include --get "$URL" --next --get --header @header.in$n "$URL" > curl.out$n && ret=1
+ # we expect 1 request to be processed.
+ lines=$(grep -c "^<statistics version" curl.out$n)
+ test "$lines" = 1 || ret=1
+else
+ echo_i "skipping test as curl with --next support not found"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "Check HTTP/1.1 keep-alive with truncated stream ($n)"
+ret=0
+i=0
+if [ -x "${CURL_NEXT}" ] ; then
+ # build input stream.
+ printf 'X-Bloat: ' > header.in$n
+ while test $i -lt 5000
+ do
+ printf '%s' "VGhlIG1vc3QgY29tbW9uIHJlYXNvbiBmb3IgYmxvYXRpbmcgaXMgaGF2aW5nIGEgbG90IG9mIGdhcyBpbiB5b3VyIGd1dC4gCg==" >> header.in$n
+ i=$((i+1))
+ done
+ printf '\r\n' >> header.in$n
+
+ # send the requests then wait for named to close the socket.
+ URL="http://10.53.0.3:${EXTRAPORT1}/xml/v3/status"
+ "${CURL}" --silent --include --get "$URL" --next --get --header @header.in$n "$URL" > curl.out$n && ret=1
+ # we expect 1 request to be processed.
+ lines=$(grep -c "^<statistics version" curl.out$n)
+ test "$lines" = 1 || ret=1
+else
+ echo_i "skipping test as curl with --next support not found"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "Check that consequtive responses do not grow excessively ($n)"
+ret=0
+i=0
+if [ -x "${CURL}" ] ; then
+ URL="http://10.53.0.3:${EXTRAPORT1}/json/v1"
+ "${CURL}" --silent --include --header "Accept-Encoding: deflate, gzip, br, zstd" "$URL" "$URL" "$URL" "$URL" "$URL" "$URL" "$URL" "$URL" "$URL" "$URL" > curl.out$n || ret=1
+ grep -a Content-Length curl.out$n | awk 'BEGIN { prev=0; } { if (prev != 0 && $2 - prev > 100) { exit(1); } prev = $2; }' || ret=1
+else
+ echo_i "skipping test as curl not found"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "Check if-modified-since works ($n)"
+ret=0
+if $FEATURETEST --have-libxml2 && [ -x "${CURL}" ] ; then
+ URL="http://10.53.0.3:${EXTRAPORT1}/bind9.xsl"
+ # ensure over-long time stamps are ignored
+ ${CURL} --silent --show-error --fail --output bind9.xsl.2 $URL \
+ --header 'If-Modified-Since: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789'
+ if ! [ bind9.xsl.2 -nt bind9.xsl.1 ] ||
+ ! ${CURL} --silent --show-error --fail \
+ --output bind9.xsl.3 $URL \
+ --time-cond bind9.xsl.1 ||
+ [ -f bind9.xsl.3 ]
+ then
+ ret=1
+ fi
+else
+ echo_i "skipping test: requires libxml2 and curl"
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/statschannel/tests_json.py b/bin/tests/system/statschannel/tests_json.py
new file mode 100755
index 0000000..c459925
--- /dev/null
+++ b/bin/tests/system/statschannel/tests_json.py
@@ -0,0 +1,105 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from datetime import datetime
+
+import pytest
+
+import generic
+import pytest_custom_markers
+
+pytestmark = pytest_custom_markers.have_json_c
+requests = pytest.importorskip("requests")
+
+
+# JSON helper functions
+def fetch_zones_json(statsip, statsport):
+ r = requests.get(
+ "http://{}:{}/json/v1/zones".format(statsip, statsport), timeout=600
+ )
+ assert r.status_code == 200
+
+ data = r.json()
+ return data["views"]["_default"]["zones"]
+
+
+def fetch_traffic_json(statsip, statsport):
+ r = requests.get(
+ "http://{}:{}/json/v1/traffic".format(statsip, statsport), timeout=600
+ )
+ assert r.status_code == 200
+
+ data = r.json()
+
+ return data["traffic"]
+
+
+def load_timers_json(zone, primary=True):
+ name = zone["name"]
+
+ # Check if the primary zone timer exists
+ assert "loaded" in zone
+ loaded = datetime.strptime(zone["loaded"], generic.fmt)
+
+ if primary:
+ # Check if the secondary zone timers does not exist
+ assert "expires" not in zone
+ assert "refresh" not in zone
+ expires = None
+ refresh = None
+ else:
+ assert "expires" in zone
+ assert "refresh" in zone
+ expires = datetime.strptime(zone["expires"], generic.fmt)
+ refresh = datetime.strptime(zone["refresh"], generic.fmt)
+
+ return (name, loaded, expires, refresh)
+
+
+def load_zone_json(zone):
+ name = zone["name"]
+
+ return name
+
+
+def test_zone_timers_primary_json(statsport):
+ generic.test_zone_timers_primary(
+ fetch_zones_json,
+ load_timers_json,
+ statsip="10.53.0.1",
+ statsport=statsport,
+ zonedir="ns1",
+ )
+
+
+def test_zone_timers_secondary_json(statsport):
+ generic.test_zone_timers_secondary(
+ fetch_zones_json,
+ load_timers_json,
+ statsip="10.53.0.3",
+ statsport=statsport,
+ zonedir="ns3",
+ )
+
+
+def test_zone_with_many_keys_json(statsport):
+ generic.test_zone_with_many_keys(
+ fetch_zones_json, load_zone_json, statsip="10.53.0.2", statsport=statsport
+ )
+
+
+def test_traffic_json(named_port, statsport):
+ generic_dnspython = pytest.importorskip("generic_dnspython")
+ generic_dnspython.test_traffic(
+ fetch_traffic_json, statsip="10.53.0.2", statsport=statsport, port=named_port
+ )
diff --git a/bin/tests/system/statschannel/tests_sh_statschannel.py b/bin/tests/system/statschannel/tests_sh_statschannel.py
new file mode 100644
index 0000000..85d5d14
--- /dev/null
+++ b/bin/tests/system/statschannel/tests_sh_statschannel.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_statschannel(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/statschannel/tests_xml.py b/bin/tests/system/statschannel/tests_xml.py
new file mode 100755
index 0000000..7f0b37e
--- /dev/null
+++ b/bin/tests/system/statschannel/tests_xml.py
@@ -0,0 +1,135 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from datetime import datetime
+import xml.etree.ElementTree as ET
+
+import pytest
+
+import generic
+import pytest_custom_markers
+
+pytestmark = pytest_custom_markers.have_libxml2
+requests = pytest.importorskip("requests")
+
+
+# XML helper functions
+def fetch_zones_xml(statsip, statsport):
+ r = requests.get(
+ "http://{}:{}/xml/v3/zones".format(statsip, statsport), timeout=600
+ )
+ assert r.status_code == 200
+
+ root = ET.fromstring(r.text)
+
+ default_view = None
+ for view in root.find("views").iter("view"):
+ if view.attrib["name"] == "_default":
+ default_view = view
+ break
+ assert default_view is not None
+
+ return default_view.find("zones").findall("zone")
+
+
+def fetch_traffic_xml(statsip, statsport):
+ def load_counters(data):
+ out = {}
+ for counter in data.findall("counter"):
+ out[counter.attrib["name"]] = int(counter.text)
+
+ return out
+
+ r = requests.get(
+ "http://{}:{}/xml/v3/traffic".format(statsip, statsport), timeout=600
+ )
+ assert r.status_code == 200
+
+ root = ET.fromstring(r.text)
+
+ traffic = {}
+ for ip in ["ipv4", "ipv6"]:
+ for proto in ["udp", "tcp"]:
+ proto_root = root.find("traffic").find(ip).find(proto)
+ for counters in proto_root.findall("counters"):
+ if counters.attrib["type"] == "request-size":
+ key = "dns-{}-requests-sizes-received-{}".format(proto, ip)
+ else:
+ key = "dns-{}-responses-sizes-sent-{}".format(proto, ip)
+
+ values = load_counters(counters)
+ traffic[key] = values
+
+ return traffic
+
+
+def load_timers_xml(zone, primary=True):
+ name = zone.attrib["name"]
+
+ loaded_el = zone.find("loaded")
+ assert loaded_el is not None
+ loaded = datetime.strptime(loaded_el.text, generic.fmt)
+
+ expires_el = zone.find("expires")
+ refresh_el = zone.find("refresh")
+ if primary:
+ assert expires_el is None
+ assert refresh_el is None
+ expires = None
+ refresh = None
+ else:
+ assert expires_el is not None
+ assert refresh_el is not None
+ expires = datetime.strptime(expires_el.text, generic.fmt)
+ refresh = datetime.strptime(refresh_el.text, generic.fmt)
+
+ return (name, loaded, expires, refresh)
+
+
+def load_zone_xml(zone):
+ name = zone.attrib["name"]
+
+ return name
+
+
+def test_zone_timers_primary_xml(statsport):
+ generic.test_zone_timers_primary(
+ fetch_zones_xml,
+ load_timers_xml,
+ statsip="10.53.0.1",
+ statsport=statsport,
+ zonedir="ns1",
+ )
+
+
+def test_zone_timers_secondary_xml(statsport):
+ generic.test_zone_timers_secondary(
+ fetch_zones_xml,
+ load_timers_xml,
+ statsip="10.53.0.3",
+ statsport=statsport,
+ zonedir="ns3",
+ )
+
+
+def test_zone_with_many_keys_xml(statsport):
+ generic.test_zone_with_many_keys(
+ fetch_zones_xml, load_zone_xml, statsip="10.53.0.2", statsport=statsport
+ )
+
+
+def test_traffic_xml(named_port, statsport):
+ generic_dnspython = pytest.importorskip("generic_dnspython")
+ generic_dnspython.test_traffic(
+ fetch_traffic_xml, statsip="10.53.0.2", statsport=statsport, port=named_port
+ )
diff --git a/bin/tests/system/statschannel/traffic-json.pl b/bin/tests/system/statschannel/traffic-json.pl
new file mode 100644
index 0000000..353d6c7
--- /dev/null
+++ b/bin/tests/system/statschannel/traffic-json.pl
@@ -0,0 +1,49 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# traffic-json.pl:
+# Parses the JSON version of the RSSAC002 traffic stats into a
+# normalized format.
+
+use JSON;
+
+my $file = $ARGV[0];
+open(INPUT, "<$file");
+my $text = do{local$/;<INPUT>};
+close(INPUT);
+
+my $ref = decode_json($text);
+
+my $tcprcvd = $ref->{traffic}->{"dns-tcp-requests-sizes-received-ipv4"};
+my $type = "tcp request-size ";
+foreach $key (keys %{$tcprcvd}) {
+ print $type . $key . ": ". $tcprcvd->{$key} ."\n";
+}
+
+my $tcpsent = $ref->{traffic}->{"dns-tcp-responses-sizes-sent-ipv4"};
+my $type = "tcp response-size ";
+foreach $key (keys %{$tcpsent}) {
+ print $type . $key . ": ". $tcpsent->{$key} ."\n";
+}
+
+my $udprcvd = $ref->{traffic}->{"dns-udp-requests-sizes-received-ipv4"};
+my $type = "udp request-size ";
+foreach $key (keys %{$udprcvd}) {
+ print $type . $key . ": ". $udprcvd->{$key} ."\n";
+}
+
+my $udpsent = $ref->{traffic}->{"dns-udp-responses-sizes-sent-ipv4"};
+my $type = "udp response-size ";
+foreach $key (keys %{$udpsent}) {
+ print $type . $key . ": ". $udpsent->{$key} ."\n";
+}
diff --git a/bin/tests/system/statschannel/traffic-xml.pl b/bin/tests/system/statschannel/traffic-xml.pl
new file mode 100644
index 0000000..5552cc5
--- /dev/null
+++ b/bin/tests/system/statschannel/traffic-xml.pl
@@ -0,0 +1,46 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# traffic-xml.pl:
+# Parses the XML version of the RSSAC002 traffic stats into a
+# normalized format.
+
+use XML::Simple;
+
+my $file = $ARGV[0];
+
+my $ref = XMLin($file);
+
+my $udp = $ref->{traffic}->{ipv4}->{udp}->{counters};
+foreach $group (@$udp) {
+ my $type = "udp " . $group->{type} . " ";
+ if (exists $group->{counter}->{name}) {
+ print $type . $group->{counter}->{name} . ": " . $group->{counter}->{content} . "\n";
+ } else {
+ foreach $key (keys %{$group->{counter}}) {
+ print $type . $key . ": ". $group->{counter}->{$key}->{content} ."\n";
+ }
+ }
+}
+
+my $tcp = $ref->{traffic}->{ipv4}->{tcp}->{counters};
+foreach $group (@$tcp) {
+ my $type = "tcp " . $group->{type} . " ";
+ if (exists $group->{counter}->{name}) {
+ print $type . $group->{counter}->{name} . ": " . $group->{counter}->{content} . "\n";
+ } else {
+ foreach $key (keys %{$group->{counter}}) {
+ print $type . $key . ": ". $group->{counter}->{$key}->{content} ."\n";
+ }
+ }
+}
diff --git a/bin/tests/system/statschannel/traffic.expect.1 b/bin/tests/system/statschannel/traffic.expect.1
new file mode 100644
index 0000000..5938d5d
--- /dev/null
+++ b/bin/tests/system/statschannel/traffic.expect.1
@@ -0,0 +1,2 @@
+tcp request-size 16-31: 1
+tcp response-size 64-79: 1
diff --git a/bin/tests/system/statschannel/traffic.expect.2 b/bin/tests/system/statschannel/traffic.expect.2
new file mode 100644
index 0000000..6c9e25a
--- /dev/null
+++ b/bin/tests/system/statschannel/traffic.expect.2
@@ -0,0 +1,4 @@
+tcp request-size 16-31: 1
+tcp response-size 64-79: 1
+udp request-size 48-63: 1
+udp response-size 112-127: 1
diff --git a/bin/tests/system/statschannel/traffic.expect.4 b/bin/tests/system/statschannel/traffic.expect.4
new file mode 100644
index 0000000..3f892f5
--- /dev/null
+++ b/bin/tests/system/statschannel/traffic.expect.4
@@ -0,0 +1,5 @@
+tcp request-size 16-31: 1
+tcp response-size 64-79: 1
+udp request-size 48-63: 2
+udp response-size 112-127: 1
+udp response-size 848-863: 1
diff --git a/bin/tests/system/statschannel/traffic.expect.5 b/bin/tests/system/statschannel/traffic.expect.5
new file mode 100644
index 0000000..15911b1
--- /dev/null
+++ b/bin/tests/system/statschannel/traffic.expect.5
@@ -0,0 +1,7 @@
+tcp request-size 16-31: 1
+tcp request-size 48-63: 1
+tcp response-size 112-127: 1
+tcp response-size 64-79: 1
+udp request-size 48-63: 2
+udp response-size 112-127: 1
+udp response-size 848-863: 1
diff --git a/bin/tests/system/statschannel/traffic.expect.6 b/bin/tests/system/statschannel/traffic.expect.6
new file mode 100644
index 0000000..73fc8f1
--- /dev/null
+++ b/bin/tests/system/statschannel/traffic.expect.6
@@ -0,0 +1,8 @@
+tcp request-size 16-31: 1
+tcp request-size 48-63: 2
+tcp response-size 112-127: 1
+tcp response-size 64-79: 1
+tcp response-size 848-863: 1
+udp request-size 48-63: 2
+udp response-size 112-127: 1
+udp response-size 848-863: 1
diff --git a/bin/tests/system/statschannel/zones-json.pl b/bin/tests/system/statschannel/zones-json.pl
new file mode 100644
index 0000000..9eec9db
--- /dev/null
+++ b/bin/tests/system/statschannel/zones-json.pl
@@ -0,0 +1,37 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# zones-json.pl:
+# Parses the JSON version of the dnssec sign stats for the
+# "dnssec" zone in the default view into a normalized format.
+
+use JSON;
+
+my $file = $ARGV[0];
+my $zone = $ARGV[1];
+open(INPUT, "<$file");
+my $text = do{local$/;<INPUT>};
+close(INPUT);
+
+my $ref = decode_json($text);
+
+my $dnssecsign = $ref->{views}->{_default}->{zones}[$zone]->{"dnssec-sign"};
+my $type = "dnssec-sign operations ";
+foreach $key (keys %{$dnssecsign}) {
+ print $type . $key . ": ". $dnssecsign->{$key} ."\n";
+}
+my $dnssecrefresh = $ref->{views}->{_default}->{zones}[$zone]->{"dnssec-refresh"};
+my $type = "dnssec-refresh operations ";
+foreach $key (keys %{$dnssecrefresh}) {
+ print $type . $key . ": ". $dnssecrefresh->{$key} ."\n";
+}
diff --git a/bin/tests/system/statschannel/zones-xml.pl b/bin/tests/system/statschannel/zones-xml.pl
new file mode 100644
index 0000000..be86852
--- /dev/null
+++ b/bin/tests/system/statschannel/zones-xml.pl
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# zones-xml.pl:
+# Parses the XML version of the dnssec sign stats for the
+# "dnssec" zone in the default view into a normalized format.
+
+use XML::Simple;
+
+my $file = $ARGV[0];
+my $zone = $ARGV[1];
+
+my $ref = XMLin($file);
+
+my $counters = $ref->{views}->{view}->{_default}->{zones}->{zone}->{$zone}->{counters};
+
+foreach $group (@$counters) {
+
+ my $type = $group->{type};
+
+ if ($type eq "dnssec-sign" || $type eq "dnssec-refresh") {
+ if (exists $group->{counter}->{name}) {
+ print $type . " operations " . $group->{counter}->{name} . ": " . $group->{counter}->{content} . "\n";
+ } else {
+ foreach $key (keys %{$group->{counter}}) {
+ print $type . " operations " . $key . ": ". $group->{counter}->{$key}->{content} ."\n";
+ }
+ }
+ }
+}
diff --git a/bin/tests/system/stop.pl b/bin/tests/system/stop.pl
new file mode 100644
index 0000000..572f709
--- /dev/null
+++ b/bin/tests/system/stop.pl
@@ -0,0 +1,281 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Framework for stopping test servers
+# Based on the type of server specified, signal the server to stop, wait
+# briefly for it to die, and then kill it if it is still alive.
+# If a server is specified, stop it. Otherwise, stop all servers for test.
+
+use strict;
+use warnings;
+
+use Cwd ':DEFAULT', 'abs_path';
+use English '-no_match_vars';
+use Getopt::Long;
+
+# Usage:
+# perl stop.pl [--use-rndc [--port port]] test [server]
+#
+# --use-rndc Attempt to stop the server via the "rndc stop" command.
+#
+# --port port Only relevant if --use-rndc is specified, this sets the
+# command port over which the attempt should be made. If
+# not specified, port 9953 is used.
+#
+# test Name of the test directory.
+#
+# server Name of the server directory.
+
+my $usage = "usage: $0 [--use-rndc [--halt] [--port port]] test-directory [server-directory]";
+
+my $use_rndc = 0;
+my $halt = 0;
+my $rndc_port = 9953;
+my $errors = 0;
+
+GetOptions(
+ 'use-rndc!' => \$use_rndc,
+ 'halt!' => \$halt,
+ 'port=i' => \$rndc_port
+ ) or die "$usage\n";
+
+my ( $test, $server_arg ) = @ARGV;
+
+if (!$test) {
+ die "$usage\n";
+}
+
+# Global variables
+my $builddir = $ENV{'builddir'};
+my $srcdir = $ENV{'srcdir'};
+my $testdir = "$builddir/$test";
+
+if (! -d $testdir) {
+ die "No test directory: \"$testdir\"\n";
+}
+
+if ($server_arg && ! -d "$testdir/$server_arg") {
+ die "No server directory: \"$testdir/$server_arg\"\n";
+}
+
+my $RNDC = $ENV{RNDC};
+
+my @ns;
+my @ans;
+
+if ($server_arg) {
+ if ($server_arg =~ /^ns/) {
+ push(@ns, $server_arg);
+ } elsif ($server_arg =~ /^ans/) {
+ push(@ans, $server_arg);
+ } else {
+ print "$0: ns or ans directory expected";
+ print "I:$test:failed";
+ }
+} else {
+ # Determine which servers need to be stopped for this test.
+ opendir DIR, $testdir or die "unable to read test directory: \"$test\" ($OS_ERROR)\n";
+ my @files = sort readdir DIR;
+ closedir DIR;
+
+ @ns = grep /^ns[0-9]*$/, @files;
+ @ans = grep /^ans[0-9]*$/, @files;
+}
+
+# Stop the server(s), pass 1: rndc.
+if ($use_rndc) {
+ foreach my $name(@ns) {
+ stop_rndc($name, $rndc_port);
+ }
+
+ @ns = wait_for_servers(30, @ns);
+}
+
+# Pass 2: SIGTERM
+foreach my $name (@ns) {
+ stop_signal($name, "TERM");
+}
+
+@ns = wait_for_servers(60, @ns);
+
+foreach my $name(@ans) {
+ stop_signal($name, "TERM", 1);
+}
+
+@ans = wait_for_servers(1200, @ans);
+
+# Pass 3: SIGABRT
+foreach my $name (@ns) {
+ print "I:$test:$name didn't die when sent a SIGTERM\n";
+ stop_signal($name, "ABRT");
+ $errors = 1;
+}
+foreach my $name (@ans) {
+ print "I:$test:$name didn't die when sent a SIGTERM\n";
+ stop_signal($name, "ABRT", 1);
+ $errors = 1;
+}
+
+exit($errors);
+
+# Subroutines
+
+# Return the full path to a given server's lock file.
+sub server_lock_file {
+ my ( $server ) = @_;
+
+ return $testdir . "/" . $server . "/named.lock" if ($server =~ /^ns/);
+ return if ($server =~ /^ans/);
+
+ die "Unknown server type $server\n";
+}
+
+# Return the full path to a given server's PID file.
+sub server_pid_file {
+ my ( $server ) = @_;
+
+ return $testdir . "/" . $server . "/named.pid" if ($server =~ /^ns/);
+ return $testdir . "/" . $server . "/ans.pid" if ($server =~ /^ans/);
+
+ die "Unknown server type $server\n";
+}
+
+# Read a PID.
+sub read_pid {
+ my ( $pid_file ) = @_;
+
+ return unless -f $pid_file;
+ # we don't really care about the race condition here
+ my $result = open(my $fh, "<", $pid_file);
+ if (!defined($result)) {
+ print "I:$test:$pid_file: $!\n";
+ unlink $pid_file;
+ return;
+ }
+
+ my $pid = <$fh>;
+ return unless defined($pid);
+
+ chomp($pid);
+ return $pid;
+}
+
+# Stop a named process with rndc.
+sub stop_rndc {
+ my ( $server, $port ) = @_;
+ my $n;
+
+ if ($server =~ /^ns(\d+)/) {
+ $n = $1;
+ } else {
+ die "unable to parse server number from name \"$server\"\n";
+ }
+
+ my $ip = "10.53.0.$n";
+ if (-e "$testdir/$server/named.ipv6-only") {
+ $ip = "fd92:7065:b8e:ffff::$n";
+ }
+
+ my $how = $halt ? "halt" : "stop";
+
+ # Ugly, but should work.
+ system("$RNDC -c ../common/rndc.conf -s $ip -p $port $how | sed 's/^/I:$test:$server /'");
+ return;
+}
+
+sub server_died {
+ my ( $server, $signal ) = @_;
+
+ print "I:$test:$server died before a SIG$signal was sent\n";
+ $errors = 1;
+
+ my $pid_file = server_pid_file($server);
+ unlink($pid_file);
+
+ return;
+}
+
+sub send_signal {
+ my ( $signal, $pid, $ans ) = @_;
+
+ if (! defined $ans) {
+ $ans = 0;
+ }
+
+ my $result = 0;
+
+ $result = kill $signal, $pid;
+ return $result;
+}
+
+# Stop a server by sending a signal to it.
+sub stop_signal {
+ my ( $server, $signal, $ans ) = @_;
+ if (! defined $ans) {
+ $ans = 0;
+ }
+
+ my $pid_file = server_pid_file($server);
+ my $pid = read_pid($pid_file);
+
+ return unless defined($pid);
+
+ # Send signal to the server, and bail out if signal can't be sent
+ if (send_signal($signal, $pid, $ans) != 1) {
+ server_died($server, $signal);
+ return;
+ }
+
+ return;
+}
+
+sub pid_file_exists {
+ my ( $server ) = @_;
+
+ my $pid_file = server_pid_file($server);
+ my $pid = read_pid($pid_file);
+
+ return unless defined($pid);
+
+ # If we're here, the PID file hasn't been cleaned up yet
+ if (send_signal(0, $pid) == 0) {
+ print "I:$test:$server crashed on shutdown\n";
+ $errors = 1;
+ return;
+ }
+
+ return $server;
+}
+
+sub lock_file_exists {
+ my ( $server ) = @_;
+ my $lock_file = server_lock_file($server);
+
+ return unless defined($lock_file) && -f $lock_file;
+
+ return $server;
+}
+
+sub wait_for_servers {
+ my ( $timeout, @servers ) = @_;
+
+ while ($timeout > 0 && @servers > 0) {
+ sleep 1 if (@servers > 0);
+ @servers =
+ grep { defined($_) }
+ map { pid_file_exists($_) || lock_file_exists($_) } @servers;
+ $timeout--;
+ }
+
+ return @servers;
+}
diff --git a/bin/tests/system/stop.sh.in b/bin/tests/system/stop.sh.in
new file mode 100644
index 0000000..9b21356
--- /dev/null
+++ b/bin/tests/system/stop.sh.in
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+builddir=@builddir@
+srcdir=@srcdir@
+
+# shellcheck source=conf.sh
+. "${builddir}/conf.sh"
+
+export builddir srcdir
+
+$PERL "${srcdir}/stop.pl" "$@"
diff --git a/bin/tests/system/stopall.sh b/bin/tests/system/stopall.sh
new file mode 100644
index 0000000..8eaa9d9
--- /dev/null
+++ b/bin/tests/system/stopall.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Stop all hanging processes from any system tests.
+#
+
+. ./conf.sh
+
+for d in $SUBDIRS
+do
+ $SHELL stop.sh $d
+done
diff --git a/bin/tests/system/stress/clean.sh b/bin/tests/system/stress/clean.sh
new file mode 100644
index 0000000..4833fa7
--- /dev/null
+++ b/bin/tests/system/stress/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns?/zone*.bk
+
+rm -f ns2/zone0*.db
+rm -f ns2/zone0*.jnl
+rm -f */named.memstats
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.run
+rm -f ns*/named.conf
diff --git a/bin/tests/system/stress/ns2/named.conf.in b/bin/tests/system/stress/ns2/named.conf.in
new file mode 100644
index 0000000..607e0b5
--- /dev/null
+++ b/bin/tests/system/stress/ns2/named.conf.in
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "zone000000.example" {
+ type primary;
+ allow-update { any; };
+ file "zone000000.example.db";
+};
+
+zone "zone000001.example" {
+ type primary;
+ allow-update { any; };
+ file "zone000001.example.db";
+};
+
+zone "zone000002.example" {
+ type primary;
+ allow-update { any; };
+ file "zone000002.example.db";
+};
+
+zone "zone000003.example" {
+ type primary;
+ allow-update { any; };
+ file "zone000003.example.db";
+};
+
+zone "zone000004.example" {
+ type primary;
+ allow-update { any; };
+ file "zone000004.example.db";
+};
diff --git a/bin/tests/system/stress/ns2/zone.template.db b/bin/tests/system/stress/ns2/zone.template.db
new file mode 100644
index 0000000..7ca1cc3
--- /dev/null
+++ b/bin/tests/system/stress/ns2/zone.template.db
@@ -0,0 +1,21 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA ns2 hostmaster 1 300 120 3600 86400
+@ NS ns2
+ NS ns3
+ NS ns4
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+ns4 A 10.53.0.4
+
+$GENERATE 0-999 name${0,6} A 10.0.0.1
diff --git a/bin/tests/system/stress/ns3/named.conf.in b/bin/tests/system/stress/ns3/named.conf.in
new file mode 100644
index 0000000..13e54a5
--- /dev/null
+++ b/bin/tests/system/stress/ns3/named.conf.in
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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;
+ dnssec-validation yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+server 10.53.0.4 {
+ provide-ixfr no;
+};
+
+server 10.53.0.2 {
+ request-ixfr no;
+};
+
+zone "zone000000.example" {
+ type secondary;
+ file "zone000000.example.bk";
+ primaries { 10.53.0.2; };
+};
+
+zone "zone000001.example" {
+ type secondary;
+ file "zone000001.example.bk";
+ primaries { 10.53.0.2; };
+};
+
+zone "zone000002.example" {
+ type secondary;
+ file "zone000002.example.bk";
+ primaries { 10.53.0.2; };
+};
+
+zone "zone000003.example" {
+ type secondary;
+ file "zone000003.example.bk";
+ primaries { 10.53.0.2; };
+};
+
+zone "zone000004.example" {
+ type secondary;
+ file "zone000004.example.bk";
+ primaries { 10.53.0.2; };
+};
diff --git a/bin/tests/system/stress/ns4/named.conf.in b/bin/tests/system/stress/ns4/named.conf.in
new file mode 100644
index 0000000..26296f5
--- /dev/null
+++ b/bin/tests/system/stress/ns4/named.conf.in
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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;
+ dnssec-validation yes;
+ notify yes;
+};
+
+zone "zone000000.example" {
+ type secondary;
+ file "zone000000.example.bk";
+ primaries { 10.53.0.3; };
+};
+
+zone "zone000001.example" {
+ type secondary;
+ file "zone000001.example.bk";
+ primaries { 10.53.0.3; };
+};
+
+zone "zone000002.example" {
+ type secondary;
+ file "zone000002.example.bk";
+ primaries { 10.53.0.3; };
+};
+
+zone "zone000003.example" {
+ type secondary;
+ file "zone000003.example.bk";
+ primaries { 10.53.0.3; };
+};
+
+zone "zone000004.example" {
+ type secondary;
+ file "zone000004.example.bk";
+ primaries { 10.53.0.3; };
+};
diff --git a/bin/tests/system/stress/setup.sh b/bin/tests/system/stress/setup.sh
new file mode 100644
index 0000000..aab7002
--- /dev/null
+++ b/bin/tests/system/stress/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+cp ns2/zone.template.db ns2/zone000000.example.db
+cp ns2/zone.template.db ns2/zone000001.example.db
+cp ns2/zone.template.db ns2/zone000002.example.db
+cp ns2/zone.template.db ns2/zone000003.example.db
+cp ns2/zone.template.db ns2/zone000004.example.db
+
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
diff --git a/bin/tests/system/stress/tests_stress_update.py b/bin/tests/system/stress/tests_stress_update.py
new file mode 100644
index 0000000..d326f14
--- /dev/null
+++ b/bin/tests/system/stress/tests_stress_update.py
@@ -0,0 +1,79 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import concurrent.futures
+import os
+import subprocess
+import time
+import dns.query
+import dns.update
+
+
+def rndc_loop(test_state, server):
+ rndc = os.getenv("RNDC")
+ port = os.getenv("CONTROLPORT")
+
+ cmdline = [
+ rndc,
+ "-c",
+ "../common/rndc.conf",
+ "-p",
+ port,
+ "-s",
+ server,
+ "reload",
+ ]
+
+ while not test_state["finished"]:
+ subprocess.run(cmdline, check=False)
+ time.sleep(1)
+
+
+def update_zone(test_state, zone, named_port, logger):
+ server = "10.53.0.2"
+ for i in range(1000):
+ if test_state["finished"]:
+ return
+ update = dns.update.UpdateMessage(zone)
+ update.add(f"dynamic-{i}.{zone}", 300, "TXT", f"txt-{i}")
+ try:
+ response = dns.query.udp(update, server, 10, named_port)
+ assert response.rcode() == dns.rcode.NOERROR
+ except dns.exception.Timeout:
+ logger.info(f"error: query timeout for {zone}")
+
+ logger.info(f"Update of {server} zone {zone} successful")
+
+
+# If the test has run to completion without named crashing, it has succeeded.
+def test_update_stress(named_port, logger):
+ test_state = {"finished": False}
+
+ with concurrent.futures.ThreadPoolExecutor() as executor:
+ executor.submit(rndc_loop, test_state, "10.53.0.3")
+
+ updaters = []
+ for i in range(5):
+ zone = f"zone00000{i}.example."
+ updaters.append(
+ executor.submit(update_zone, test_state, zone, named_port, logger)
+ )
+
+ # All the update_zone() tasks are expected to complete within 5
+ # minutes. If they do not, we cannot assert immediately as that will
+ # cause the ThreadPoolExecutor context manager to wait indefinitely;
+ # instead, we first signal all tasks that it is time to exit and only
+ # check whether any task failed to finish within 5 minutes outside of
+ # the ThreadPoolExecutor context manager.
+ unfinished_tasks = concurrent.futures.wait(updaters, timeout=300).not_done
+ test_state["finished"] = True
+
+ assert not unfinished_tasks
diff --git a/bin/tests/system/stub/clean.sh b/bin/tests/system/stub/clean.sh
new file mode 100644
index 0000000..504df03
--- /dev/null
+++ b/bin/tests/system/stub/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after stub tests.
+#
+rm -f dig.out.ns[35] ns3/child.example.st
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
+rm -f ns5/example.db
diff --git a/bin/tests/system/stub/knowngood.dig.out.norec b/bin/tests/system/stub/knowngood.dig.out.norec
new file mode 100644
index 0000000..ca0e458
--- /dev/null
+++ b/bin/tests/system/stub/knowngood.dig.out.norec
@@ -0,0 +1,21 @@
+
+; <<>> DiG 8.2 <<>> -p @10.53.0.3 +norec data.child.example txt
+; (1 server found)
+;; res options: init defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 216
+;; flags: qr ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; data.child.example, type = TXT, class = IN
+
+;; AUTHORITY SECTION:
+child.example. 5M IN NS ns2.child.example.
+
+;; ADDITIONAL SECTION:
+ns2.child.example. 5M IN A 10.53.0.2
+
+;; Total query time: 3 msec
+;; FROM: draco to SERVER: 10.53.0.3
+;; WHEN: Wed Jun 21 10:58:37 2000
+;; MSG SIZE sent: 36 rcvd: 70
+
diff --git a/bin/tests/system/stub/knowngood.dig.out.rec b/bin/tests/system/stub/knowngood.dig.out.rec
new file mode 100644
index 0000000..8ea1968
--- /dev/null
+++ b/bin/tests/system/stub/knowngood.dig.out.rec
@@ -0,0 +1,18 @@
+
+; <<>> DiG 8.2 <<>> -p @10.53.0.3 data.child.example txt
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; data.child.example, type = TXT, class = IN
+
+;; ANSWER SECTION:
+data.child.example. 5M IN TXT "some" "test" "data"
+
+;; Total query time: 8 msec
+;; FROM: draco to SERVER: 10.53.0.3
+;; WHEN: Wed Jun 21 10:58:54 2000
+;; MSG SIZE sent: 36 rcvd: 97
+
diff --git a/bin/tests/system/stub/ns1/named.conf.in b/bin/tests/system/stub/ns1/named.conf.in
new file mode 100644
index 0000000..2bf1b40
--- /dev/null
+++ b/bin/tests/system/stub/ns1/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ minimal-responses no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/stub/ns1/root.db b/bin/tests/system/stub/ns1/root.db
new file mode 100644
index 0000000..361f93e
--- /dev/null
+++ b/bin/tests/system/stub/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
diff --git a/bin/tests/system/stub/ns2/child.example.db b/bin/tests/system/stub/ns2/child.example.db
new file mode 100644
index 0000000..9b50a2a
--- /dev/null
+++ b/bin/tests/system/stub/ns2/child.example.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+child.example. IN SOA ns2.child.example. hostmaster.child.example. (
+ 2000042795 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+child.example. NS ns2.child.example.
+ns2.child.example. A 10.53.0.2
+data TXT some test data
diff --git a/bin/tests/system/stub/ns2/named.conf.in b/bin/tests/system/stub/ns2/named.conf.in
new file mode 100644
index 0000000..1f006e0
--- /dev/null
+++ b/bin/tests/system/stub/ns2/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ minimal-responses no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "child.example" {
+ type primary;
+ file "child.example.db";
+};
diff --git a/bin/tests/system/stub/ns3/example.db b/bin/tests/system/stub/ns3/example.db
new file mode 100644
index 0000000..4d0b3f0
--- /dev/null
+++ b/bin/tests/system/stub/ns3/example.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA ns3.example. hostmaster.example. (
+ 2000042795 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
diff --git a/bin/tests/system/stub/ns3/named.conf.in b/bin/tests/system/stub/ns3/named.conf.in
new file mode 100644
index 0000000..e8e432f
--- /dev/null
+++ b/bin/tests/system/stub/ns3/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+ minimal-responses no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "child.example" {
+ type stub;
+ file "child.example.st";
+ primaries { 10.53.0.2; };
+};
diff --git a/bin/tests/system/stub/ns4/example.db b/bin/tests/system/stub/ns4/example.db
new file mode 100644
index 0000000..1afe983
--- /dev/null
+++ b/bin/tests/system/stub/ns4/example.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns4.example. hostmaster.example. (
+ 2000042795 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ IN NS ns4
+ns4 IN A 10.53.0.4
+ IN AAAA fd92:7065:b8e:ffff::4
+target IN TXT "test"
diff --git a/bin/tests/system/stub/ns4/named.conf.in b/bin/tests/system/stub/ns4/named.conf.in
new file mode 100644
index 0000000..7e53972
--- /dev/null
+++ b/bin/tests/system/stub/ns4/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ minimal-responses yes;
+ dnssec-validation no;
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
diff --git a/bin/tests/system/stub/ns5/named.conf.in b/bin/tests/system/stub/ns5/named.conf.in
new file mode 100644
index 0000000..39e38cc
--- /dev/null
+++ b/bin/tests/system/stub/ns5/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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; };
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type stub;
+ file "example.db";
+ primaries { 10.53.0.4 port @PORT@; };
+};
diff --git a/bin/tests/system/stub/setup.sh b/bin/tests/system/stub/setup.sh
new file mode 100644
index 0000000..5d12d6a
--- /dev/null
+++ b/bin/tests/system/stub/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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/stub/tests.sh b/bin/tests/system/stub/tests.sh
new file mode 100644
index 0000000..9a9ca66
--- /dev/null
+++ b/bin/tests/system/stub/tests.sh
@@ -0,0 +1,88 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp -p ${PORT}"
+
+status=0
+echo_i "check that the stub zone has been saved to disk"
+for i in 1 2 3 4 5 6 7 8 9 20
+do
+ [ -f ns3/child.example.st ] && break
+ sleep 1
+done
+[ -f ns3/child.example.st ] || { status=1; echo_i "failed"; }
+
+for pass in 1 2
+do
+
+echo_i "trying an axfr that should be denied (NOTAUTH) (pass=$pass)"
+ret=0
+$DIG $DIGOPTS child.example. @10.53.0.3 axfr > dig.out.ns3 || ret=1
+grep "; Transfer failed." dig.out.ns3 > /dev/null || ret=1
+[ $ret = 0 ] || { status=1; echo_i "failed"; }
+
+echo_i "look for stub zone data without recursion (should not be found) (pass=$pass)"
+for i in 1 2 3 4 5 6 7 8 9
+do
+ ret=0
+ $DIG $DIGOPTS +norec data.child.example. \
+ @10.53.0.3 txt > dig.out.ns3 || ret=1
+ grep "status: NOERROR" dig.out.ns3 > /dev/null || ret=1
+ [ $ret = 0 ] && break
+ sleep 1
+done
+digcomp knowngood.dig.out.norec dig.out.ns3 || ret=1
+[ $ret = 0 ] || { status=1; echo_i "failed"; }
+
+echo_i "look for stub zone data with recursion (should be found) (pass=$pass)"
+ret=0
+$DIG $DIGOPTS +noauth +noadd data.child.example. @10.53.0.3 txt > dig.out.ns3 || ret=1
+digcomp knowngood.dig.out.rec dig.out.ns3 || ret=1
+[ $ret = 0 ] || { status=1; echo_i "failed"; }
+
+[ $pass = 1 ] && {
+ echo_i "stopping stub server"
+ stop_server ns3
+
+ echo_i "re-starting stub server"
+ start_server --noclean --restart --port ${PORT} ns3
+}
+done
+
+echo_i "check that glue record is correctly transferred from primary when minimal-responses is on"
+ret=0
+# First ensure that zone data was transfered.
+for i in 1 2 3 4 5 6 7; do
+ [ -f ns5/example.db ] && break
+ sleep 1
+done
+
+if [ -f ns5/example.db ]; then
+ # If NS glue wasn't transferred, this query would fail.
+ $DIG $DIGOPTS +nodnssec @10.53.0.5 target.example. txt > dig.out.ns5 || ret=1
+ grep 'target\.example.*TXT.*"test"' dig.out.ns5 > /dev/null || ret=1
+ # Ensure both ipv4 and ipv6 glue records were transferred.
+ grep -E 'ns4[[:space:]]+A[[:space:]]+10.53.0.4' ns5/example.db > /dev/null || ret=1
+ grep -E 'AAAA[[:space:]]+fd92:7065:b8e:ffff::4' ns5/example.db > /dev/null || ret=1
+ [ $ret = 0 ] || { status=1; echo_i "failed"; }
+else
+ status=1
+ echo_i "failed: stub zone transfer failed ns4(primary) <---> ns5/example.db"
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/stub/tests_sh_stub.py b/bin/tests/system/stub/tests_sh_stub.py
new file mode 100644
index 0000000..311e450
--- /dev/null
+++ b/bin/tests/system/stub/tests_sh_stub.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_stub(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/synthfromdnssec/clean.sh b/bin/tests/system/synthfromdnssec/clean.sh
new file mode 100644
index 0000000..bd86173
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/clean.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f ./*/named.memstats
+rm -f ./*/named.conf
+rm -f ./*/named.run
+rm -f ./*/named.run.prev
+rm -f ./*/named.stats
+rm -f ./dig.out.*
+rm -f ./ns1/K*+*+*.key
+rm -f ./ns1/K*+*+*.private
+rm -f ./ns1/dsset-*
+rm -f ./ns1/example.db
+rm -f ./ns1/example.db.signed
+rm -f ./ns1/insecure.example.db
+rm -f ./ns1/insecure.example.db.signed
+rm -f ./ns1/dnamed.db
+rm -f ./ns1/dnamed.db.signed
+rm -f ./ns1/minimal.db
+rm -f ./ns1/minimal.db.signed
+rm -f ./ns1/root.db
+rm -f ./ns1/root.db.signed
+rm -f ./ns1/soa-without-dnskey.db
+rm -f ./ns1/soa-without-dnskey.db.signed
+rm -f ./ns1/trusted.conf
+rm -f ./ns2/named_dump.db
+rm -f ./ns*/managed-keys.bind*
+rm -f ./nodata.out ./insecure.nodata.out
+rm -f ./nxdomain.out ./insecure.nxdomain.out
+rm -f ./wild.out ./insecure.wild.out
+rm -f ./wildcname.out ./insecure.wildcname.out
+rm -f ./wildnodata1nsec.out ./insecure.wildnodata1nsec.out
+rm -f ./wildnodata2nsec.out ./insecure.wildnodata2nsec.out
+rm -f ./wildnodata2nsecafterdata.out ./insecure.wildnodata2nsecafterdata.out
+rm -f ./minimal.nxdomain.out
+rm -f ./black.out
+rm -f ./xml.out*
+rm -f ./json.out*
diff --git a/bin/tests/system/synthfromdnssec/ns1/dnamed.db.in b/bin/tests/system/synthfromdnssec/ns1/dnamed.db.in
new file mode 100644
index 0000000..61dfcf8
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns1/dnamed.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns1 hostmaster 1 3600 1200 604800 5
+@ NS ns1
+ns1 A 10.53.0.1
+a A 10.53.0.1
+dname DNAME example.
diff --git a/bin/tests/system/synthfromdnssec/ns1/example.db.in b/bin/tests/system/synthfromdnssec/ns1/example.db.in
new file mode 100644
index 0000000..79d5c27
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns1/example.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns1 hostmaster 1 3600 1200 604800 3600
+@ NS ns1
+ns1 A 10.53.0.1
+nodata TXT nodata
+*.wild-a A 1.2.3.4
+*.wild-cname CNAME ns1
+*.wild-1-nsec A 1.2.3.4
+*.wild-2-nsec A 1.2.3.4
+_x.wild-2-nsec TXT a name beween wild-2-nsec and a.wild-2-nsec
+*.wild-2-nsec-afterdata A 1.2.3.4
+*.wild-2-nsec-afterdata AAAA 2002::1
+_x.wild-2-nsec-afterdata TXT a name beween wild-2-nsec-afterdata and a.wild-2-nsec-afterdata
+dnamed DNAME dnamed.
diff --git a/bin/tests/system/synthfromdnssec/ns1/minimal.db.in b/bin/tests/system/synthfromdnssec/ns1/minimal.db.in
new file mode 100644
index 0000000..2df3890
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns1/minimal.db.in
@@ -0,0 +1,46 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+minimal. 3600 SOA ns1.minimal. hostmaster.minimal. (
+ 1 ; serial
+ 3600 ; refresh (1 hour)
+ 1200 ; retry (20 minutes)
+ 604800 ; expire (1 week)
+ 3600 ; minimum (1 hour)
+ )
+ 3600 NS ns1.minimal.
+ 3600 NSEC badtypemap.minimal. NS SOA RRSIG NSEC DNSKEY
+; bad NSEC type map without RRSIG or NSEC
+badtypemap.minimal. 3600 NSEC black.minimal. A
+badtypemap.minimal. 3600 A 1.2.3.4
+badtypemap.minimal. 3600 AAAA 2002::1
+; cloudflare black lie
+black.minimal. 3600 NSEC \000.black.minimal. RRSIG NSEC
+;
+dnamed.minimal. 3600 DNAME dnamed.
+ 3600 NSEC insecure.minimal. DNAME RRSIG NSEC
+insecure.minimal. 3600 NS ns1.insecure.minimal.
+ 3600 NSEC nodata.minimal. NS RRSIG NSEC
+nodata.minimal. 3600 TXT "nodata"
+ 3600 NSEC ns1.minimal. TXT RRSIG NSEC
+; incomplete chain pointing at non-existent ns2.minimal
+ns1.minimal. 3600 A 10.53.0.1
+ 3600 NSEC ns2.minimal. A RRSIG NSEC
+; minimal response for nxdomain.minimal.
+nxdomaia.minimal. 3600 NSEC nxdomaiz.minimal. RRSIG NSEC
+;
+*.wild-a.minimal. 3600 A 1.2.3.4
+ 3600 NSEC *.wild-cname.minimal. A RRSIG NSEC
+*.wild-cname.minimal. 3600 CNAME ns1.minimal.
+ 3600 NSEC minimal. CNAME RRSIG NSEC
+; glue
+ns1.insecure.minimal. 3600 A 10.53.0.1
diff --git a/bin/tests/system/synthfromdnssec/ns1/named.conf.in b/bin/tests/system/synthfromdnssec/ns1/named.conf.in
new file mode 100644
index 0000000..9a86e24
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns1/named.conf.in
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+statistics-channels {
+ inet 10.53.0.1 port @EXTRAPORT1@ allow { any; };
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+zone "example" {
+ type primary;
+ file "example.db.signed";
+};
+
+zone "insecure.example" {
+ type primary;
+ file "insecure.example.db.signed";
+};
+
+zone "dnamed" {
+ type primary;
+ file "dnamed.db.signed";
+};
+
+zone "minimal" {
+ type primary;
+ file "minimal.db.signed";
+};
+
+zone "soa-without-dnskey" {
+ type primary;
+ file "soa-without-dnskey.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/synthfromdnssec/ns1/root.db.in b/bin/tests/system/synthfromdnssec/ns1/root.db.in
new file mode 100644
index 0000000..bade656
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns1/root.db.in
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns1 hostmaster 1 3600 1200 604800 3600
+@ NS ns1
+ns1 A 10.53.0.1
+example NS ns1.example
+fun NS ns1.example
+ns1.example A 10.53.0.1
+dnamed NS ns1.dnamed
+ns1.dnamed A 10.53.0.1
+minimal NS ns1.minimal
+ns1.minimal A 10.53.0.1
+soa-without-dnskey NS ns1.soa-without-dnskey
+ns1.soa-without-dnskey A 10.53.0.1
diff --git a/bin/tests/system/synthfromdnssec/ns1/sign.sh b/bin/tests/system/synthfromdnssec/ns1/sign.sh
new file mode 100644
index 0000000..9f699a0
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns1/sign.sh
@@ -0,0 +1,76 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+zone=example
+infile=example.db.in
+zonefile=example.db
+
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+cat "$infile" "$keyname.key" > "$zonefile"
+echo insecure NS ns1.insecure >> "$zonefile"
+echo ns1.insecure A 10.53.0.1 >> "$zonefile"
+
+$SIGNER -P -o $zone $zonefile > /dev/null
+
+zone=insecure.example
+infile=example.db.in
+zonefile=insecure.example.db
+
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+cat "$infile" "$keyname.key" > "$zonefile"
+
+$SIGNER -P -o $zone $zonefile > /dev/null
+
+zone=dnamed
+infile=dnamed.db.in
+zonefile=dnamed.db
+
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+cat "$infile" "$keyname.key" > "$zonefile"
+
+$SIGNER -P -o $zone $zonefile > /dev/null
+
+zone=minimal
+infile=minimal.db.in
+zonefile=minimal.db
+
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+cat "$infile" "$keyname.key" > "$zonefile"
+
+# do not regenerate NSEC chain as there in a minimal NSEC record present
+$SIGNER -P -Z nonsecify -o $zone $zonefile > /dev/null
+
+zone=soa-without-dnskey
+infile=soa-without-dnskey.db.in
+zonefile=soa-without-dnskey.db
+
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+cat "$infile" "$keyname.key" > "$zonefile"
+
+# do not regenerate NSEC chain as there in a minimal NSEC record present
+$SIGNER -P -Z nonsecify -o $zone $zonefile > /dev/null
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} -n zone $zone)
+cat "$infile" "$keyname.key" > "$zonefile"
+
+$SIGNER -P -g -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a static key.
+keyfile_to_static_ds "$keyname" > trusted.conf
diff --git a/bin/tests/system/synthfromdnssec/ns1/soa-without-dnskey.db.in b/bin/tests/system/synthfromdnssec/ns1/soa-without-dnskey.db.in
new file mode 100644
index 0000000..a8ad40c
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns1/soa-without-dnskey.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+soa-without-dnskey. 3600 SOA ns1.soa-without-dnskey. hostmaster.soa-without-dnskey. (
+ 1 ; serial
+ 3600 ; refresh (1 hour)
+ 1200 ; retry (20 minutes)
+ 604800 ; expire (1 week)
+ 3600 ; minimum (1 hour)
+ )
+ 3600 NS ns1.soa-without-dnskey.
+ 3600 NSEC ns1.soa-without-dnskey. NS SOA RRSIG NSEC
+ns1.soa-without-dnskey. 3600 A 10.53.0.1
+ 3600 NSEC soa-without-dnskey. A RRSIG NSEC
diff --git a/bin/tests/system/synthfromdnssec/ns2/example.internal.db b/bin/tests/system/synthfromdnssec/ns2/example.internal.db
new file mode 100644
index 0000000..938159b
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns2/example.internal.db
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns2 hostmaster 1 3600 1200 604800 3600
+@ NS ns2
+@ A 1.2.3.4
+ns2 A 10.53.0.2
diff --git a/bin/tests/system/synthfromdnssec/ns2/named.conf.in b/bin/tests/system/synthfromdnssec/ns2/named.conf.in
new file mode 100644
index 0000000..f4b5059
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns2/named.conf.in
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+statistics-channels {
+ inet 10.53.0.2 port @EXTRAPORT1@ allow { any; };
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
+
+zone "example.internal" {
+ type primary;
+ file "example.internal.db";
+};
+
+zone "example.internal2" {
+ type primary;
+ file "example.internal.db";
+};
+
+include "../ns1/trusted.conf";
diff --git a/bin/tests/system/synthfromdnssec/ns2/root.hints b/bin/tests/system/synthfromdnssec/ns2/root.hints
new file mode 100644
index 0000000..6b80b9e
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns2/root.hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS ns1
+ns1 A 10.53.0.1
diff --git a/bin/tests/system/synthfromdnssec/ns3/named.conf.in b/bin/tests/system/synthfromdnssec/ns3/named.conf.in
new file mode 100644
index 0000000..874143a
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns3/named.conf.in
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ notify no;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+statistics-channels {
+ inet 10.53.0.3 port @EXTRAPORT1@ allow { any; };
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
+
+zone "." {
+ type redirect;
+ file "redirect.db";
+};
+
+include "../ns1/trusted.conf";
diff --git a/bin/tests/system/synthfromdnssec/ns3/redirect.db b/bin/tests/system/synthfromdnssec/ns3/redirect.db
new file mode 100644
index 0000000..c529ad2
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns3/redirect.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA ns.example.net hostmaster.example.net 0 0 0 0 0
+@ IN NS ns.example.net
+;
+; NS records do not need address records in this zone as it is not in the
+; normal namespace.
+;
+*.redirect. IN A 100.100.100.2
+*.redirect. IN AAAA 2001:ffff:ffff::100.100.100.2
diff --git a/bin/tests/system/synthfromdnssec/ns3/root.hints b/bin/tests/system/synthfromdnssec/ns3/root.hints
new file mode 100644
index 0000000..6b80b9e
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns3/root.hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS ns1
+ns1 A 10.53.0.1
diff --git a/bin/tests/system/synthfromdnssec/ns4/named.conf.in b/bin/tests/system/synthfromdnssec/ns4/named.conf.in
new file mode 100644
index 0000000..c9d9210
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns4/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ notify no;
+ dnssec-validation yes;
+ synth-from-dnssec no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+statistics-channels {
+ inet 10.53.0.4 port @EXTRAPORT1@ allow { any; };
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
+
+include "../ns1/trusted.conf";
diff --git a/bin/tests/system/synthfromdnssec/ns4/root.hints b/bin/tests/system/synthfromdnssec/ns4/root.hints
new file mode 100644
index 0000000..6b80b9e
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns4/root.hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS ns1
+ns1 A 10.53.0.1
diff --git a/bin/tests/system/synthfromdnssec/ns5/internal2.db b/bin/tests/system/synthfromdnssec/ns5/internal2.db
new file mode 100644
index 0000000..4f07f70
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns5/internal2.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA ns5 hostmaster 1 3600 1200 604800 3600
+@ NS ns5
+ns5 A 10.53.0.5
+example NS ns2.example
+ns2.example A 10.53.0.2
diff --git a/bin/tests/system/synthfromdnssec/ns5/named.conf.in b/bin/tests/system/synthfromdnssec/ns5/named.conf.in
new file mode 100644
index 0000000..4249548
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns5/named.conf.in
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ notify no;
+ dnssec-validation yes;
+ synth-from-dnssec yes;
+ validate-except { example.internal; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+statistics-channels {
+ inet 10.53.0.5 port @EXTRAPORT1@ allow { any; };
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
+
+zone "example.internal" {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.2; };
+};
+
+zone "internal2" {
+ type primary;
+ file "internal2.db";
+};
+
+include "../ns1/trusted.conf";
diff --git a/bin/tests/system/synthfromdnssec/ns5/root.hints b/bin/tests/system/synthfromdnssec/ns5/root.hints
new file mode 100644
index 0000000..6b80b9e
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns5/root.hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS ns1
+ns1 A 10.53.0.1
diff --git a/bin/tests/system/synthfromdnssec/ns6/named.conf.in b/bin/tests/system/synthfromdnssec/ns6/named.conf.in
new file mode 100644
index 0000000..c10e0f7
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns6/named.conf.in
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS6
+
+options {
+ 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.6; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+ dnssec-validation no;
+ synth-from-dnssec yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+statistics-channels {
+ inet 10.53.0.6 port @EXTRAPORT1@ allow { any; };
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
+
+include "../ns1/trusted.conf";
diff --git a/bin/tests/system/synthfromdnssec/ns6/root.hints b/bin/tests/system/synthfromdnssec/ns6/root.hints
new file mode 100644
index 0000000..6b80b9e
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/ns6/root.hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS ns1
+ns1 A 10.53.0.1
diff --git a/bin/tests/system/synthfromdnssec/setup.sh b/bin/tests/system/synthfromdnssec/setup.sh
new file mode 100644
index 0000000..d109871
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/setup.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+set -e
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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
+
+(
+ cd ns1
+ $SHELL sign.sh
+)
diff --git a/bin/tests/system/synthfromdnssec/tests.sh b/bin/tests/system/synthfromdnssec/tests.sh
new file mode 100644
index 0000000..1bfd00b
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/tests.sh
@@ -0,0 +1,904 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# set -e
+#
+# shellcheck source=conf.sh
+. ../conf.sh
+
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+set -e
+
+status=0
+n=1
+synth_default=yes
+
+rm -f dig.out.*
+
+dig_with_opts() {
+ "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
+}
+
+check_ad_flag() {
+ if [ ${1} = yes ]
+ then
+ grep "flags:[^;]* ad[^;]*; QUERY" ${2} > /dev/null || return 1
+ else
+ grep "flags:[^;]* ad[^;]*; QUERY" ${2} > /dev/null && return 1
+ fi
+ return 0
+}
+
+check_status() {
+ grep "status: ${1}," ${2} > /dev/null || return 1
+ return 0
+}
+
+check_synth_soa() (
+ name=$(echo "$1" | sed 's/\./\\./g')
+ grep "^${name}.*[0-9]*.IN.SOA" ${2} > /dev/null || return 1
+ grep "^${name}.*3600.IN.SOA" ${2} > /dev/null && return 1
+ return 0
+)
+
+check_nosynth_soa() (
+ name=$(echo "$1" | sed 's/\./\\./g')
+ grep "^${name}.*3600.IN.SOA" ${2} > /dev/null || return 1
+ return 0
+)
+
+check_synth_a() (
+ name=$(echo "$1" | sed 's/\./\\./g')
+ grep "^${name}.*[0-9]*.IN.A.[0-2]" ${2} > /dev/null || return 1
+ grep "^${name}.*3600.IN.A.[0-2]" ${2} > /dev/null && return 1
+ return 0
+)
+
+check_nosynth_a() (
+ name=$(echo "$1" | sed 's/\./\\./g')
+ grep "^${name}.*3600.IN.A.[0-2]" ${2} > /dev/null || return 1
+ return 0
+)
+
+check_synth_aaaa() (
+ name=$(echo "$1" | sed 's/\./\\./g')
+ grep "^${name}.*[0-9]*.IN.AAAA" ${2} > /dev/null || return 1
+ grep "^${name}.*3600.IN.A" ${2} > /dev/null && return 1
+ return 0
+)
+
+check_nosynth_aaaa() (
+ name=$(echo "$1" | sed 's/\./\\./g')
+ grep "^${name}.*3600.IN.AAAA" ${2} > /dev/null || return 1
+ return 0
+)
+
+check_synth_cname() (
+ name=$(echo "$1" | sed 's/\./\\./g')
+ grep "^${name}.*[0-9]*.IN.CNAME" ${2} > /dev/null || return 1
+ grep "^${name}.*3600.IN.CNAME" ${2} > /dev/null && return 1
+ return 0
+)
+
+check_nosynth_cname() (
+ name=$(echo "$1" | sed 's/\./\\./g')
+ grep "^${name}.*3600.IN.CNAME" ${2} > /dev/null || return 1
+ return 0
+)
+
+check_auth_count() {
+ grep "AUTHORITY: ${1}," ${2} > /dev/null || return 1
+ return 0
+}
+
+for ns in 2 4 5 6
+do
+ case $ns in
+ 2) ad=yes; description="<default>";;
+ 4) ad=yes; description="no";;
+ 5) ad=yes; description="yes";;
+ 6) ad=no; description="yes; dnssec-validation no";;
+ *) exit 1;;
+ esac
+ echo_i "prime negative NXDOMAIN response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NXDOMAIN dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa example. dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && cp dig.out.ns${ns}.test$n nxdomain.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime negative NODATA response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts nodata.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa example. dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && cp dig.out.ns${ns}.test$n nodata.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime wildcard response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.wild-a.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_a a.wild-a.example. dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && sed 's/^a\./b./' dig.out.ns${ns}.test$n > wild.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime wildcard CNAME response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.wild-cname.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_cname a.wild-cname.example. dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && sed 's/^a\./b./' dig.out.ns${ns}.test$n > wildcname.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime wildcard NODATA 1 NSEC response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.wild-1-nsec.example. @10.53.0.${ns} TXT > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa example. dig.out.ns${ns}.test$n || ret=1
+ check_auth_count 4 dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && sed 's/^a\./b./' dig.out.ns${ns}.test$n > wildnodata1nsec.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime wildcard NODATA 2 NSEC response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.wild-2-nsec.example. @10.53.0.${ns} TXT > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa example. dig.out.ns${ns}.test$n || ret=1
+ check_auth_count 6 dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && sed 's/^a\./b./' dig.out.ns${ns}.test$n > wildnodata2nsec.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime wildcard NODATA 2 NSEC after data response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.wild-2-nsec-afterdata.example. @10.53.0.${ns} TXT > dig.out.txt.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.txt.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.txt.ns${ns}.test$n || ret=1
+ check_nosynth_soa example. dig.out.txt.ns${ns}.test$n || ret=1
+ check_auth_count 6 dig.out.txt.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && sed 's/^a\./b./' dig.out.txt.ns${ns}.test$n > wildnodata2nsecafterdata.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime insecure negative NXDOMAIN response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.insecure.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NXDOMAIN dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa insecure.example. dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && cp dig.out.ns${ns}.test$n insecure.nxdomain.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime insecure negative NODATA response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts nodata.insecure.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa insecure.example. dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && cp dig.out.ns${ns}.test$n insecure.nodata.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime insecure wildcard response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.wild-a.insecure.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_a a.wild-a.insecure.example. dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && sed 's/^a\./b./' dig.out.ns${ns}.test$n > insecure.wild.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime wildcard CNAME response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.wild-cname.insecure.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_cname a.wild-cname.insecure.example. dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && sed 's/^a\./b./' dig.out.ns${ns}.test$n > insecure.wildcname.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime insecure wildcard NODATA 1 NSEC response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.wild-1-nsec.insecure.example. @10.53.0.${ns} TXT > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa insecure.example. dig.out.ns${ns}.test$n || ret=1
+ check_auth_count 4 dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && cp dig.out.ns${ns}.test$n insecure.wildnodata1nsec.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime insecure wildcard NODATA 2 NSEC response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.wild-2-nsec.insecure.example. @10.53.0.${ns} TXT > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa insecure.example. dig.out.ns${ns}.test$n || ret=1
+ check_auth_count 6 dig.out.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && cp dig.out.ns${ns}.test$n insecure.wildnodata2nsec.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime insecure wildcard NODATA 2 NSEC after data response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts a.wild-2-nsec-afterdata.insecure.example. @10.53.0.${ns} TXT > dig.out.txt.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.txt.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.txt.ns${ns}.test$n || ret=1
+ check_nosynth_soa insecure.example. dig.out.txt.ns${ns}.test$n || ret=1
+ check_auth_count 6 dig.out.txt.ns${ns}.test$n || ret=1
+ [ $ns -eq 2 ] && sed 's/^a\./b./' dig.out.txt.ns${ns}.test$n > insecure.wildnodata2nsecafterdata.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime minimal NXDOMAIN response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts nxdomain.minimal. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NXDOMAIN dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa minimal. dig.out.ns${ns}.test$n || ret=1
+ grep "nxdomaia.minimal.*3600.IN.NSEC.nxdomaiz.minimal. RRSIG NSEC" dig.out.ns${ns}.test$n > /dev/null || ret=1
+ [ $ns -eq 2 ] && cp dig.out.ns${ns}.test$n minimal.nxdomain.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime black lie NODATA response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts black.minimal. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa minimal. dig.out.ns${ns}.test$n || ret=1
+ grep 'black.minimal.*3600.IN.NSEC.\\000.black.minimal. RRSIG NSEC' dig.out.ns${ns}.test$n > /dev/null || ret=1
+ [ $ns -eq 2 ] && cp dig.out.ns${ns}.test$n black.out
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime bad type map NODATA response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts badtypemap.minimal. @10.53.0.${ns} TXT > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa minimal. dig.out.ns${ns}.test$n || ret=1
+ grep 'badtypemap.minimal.*3600.IN.NSEC.black.minimal. A$' dig.out.ns${ns}.test$n > /dev/null || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "prime SOA without DNSKEY bad type map NODATA response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts soa-without-dnskey. @10.53.0.${ns} TXT > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa soa-without-dnskey. dig.out.ns${ns}.test$n || ret=1
+ grep 'soa-without-dnskey.*3600.IN.NSEC.ns1.soa-without-dnskey. NS SOA RRSIG NSEC$' dig.out.ns${ns}.test$n > /dev/null || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+done
+
+echo_i "prime redirect response (+nodnssec) (synth-from-dnssec <default>;) ($n)"
+ret=0
+dig_with_opts +nodnssec a.redirect. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+check_ad_flag no dig.out.ns3.test$n || ret=1
+check_status NOERROR dig.out.ns3.test$n || ret=1
+grep 'a\.redirect\..*300.IN.A.100\.100\.100\.2' dig.out.ns3.test$n > /dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#
+# ensure TTL of synthesised answers differs from direct answers.
+#
+sleep 1
+
+for ns in 2 4 5 6
+do
+ case $ns in
+ 2) ad=yes synth=${synth_default} description="<default>";;
+ 4) ad=yes synth=no description="no";;
+ 5) ad=yes synth=yes description="yes";;
+ 6) ad=no synth=no description="yes; dnssec-validation no";;
+ *) exit 1;;
+ esac
+ echo_i "check synthesized NXDOMAIN response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NXDOMAIN dig.out.ns${ns}.test$n || ret=1
+ if [ ${synth} = yes ]
+ then
+ check_synth_soa example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.example/A > /dev/null && ret=1
+ else
+ check_nosynth_soa example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.example/A > /dev/null || ret=1
+ fi
+ digcomp nxdomain.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check synthesized NODATA response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts nodata.example. @10.53.0.${ns} aaaa > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ if [ ${synth} = yes ]
+ then
+ check_synth_soa example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep nodata.example/AAAA > /dev/null && ret=1
+ else
+ check_nosynth_soa example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep nodata.example/AAAA > /dev/null || ret=1
+ fi
+ digcomp nodata.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check synthesized wildcard response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.wild-a.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ if [ ${synth} = yes ]
+ then
+ check_synth_a b.wild-a.example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.wild-a.example/A > /dev/null && ret=1
+ else
+ check_nosynth_a b.wild-a.example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.wild-a.example/A > /dev/null || ret=1
+ fi
+ digcomp wild.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check synthesized wildcard CNAME response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.wild-cname.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ if [ ${synth} = yes ]
+ then
+ check_synth_cname b.wild-cname.example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.wild-cname.example/A > /dev/null && ret=1
+ else
+ check_nosynth_cname b.wild-cname.example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.wild-cname.example/A > /dev/null || ret=1
+ fi
+ grep "ns1.example.*.IN.A" dig.out.ns${ns}.test$n > /dev/null || ret=1
+ digcomp wildcname.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check synthesized wildcard NODATA 1 NSEC response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.wild-1-nsec.example. @10.53.0.${ns} AAAA > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ if [ ${synth} = yes ]
+ then
+ check_synth_soa example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.wild-1-nsec.example/AAAA > /dev/null && ret=1
+ else
+ check_nosynth_soa example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.wild-1-nsec.example/AAAA > /dev/null || ret=1
+ fi
+ digcomp wildnodata1nsec.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check synthesized wildcard NODATA 2 NSEC response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.wild-2-nsec.example. @10.53.0.${ns} AAAA > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ if [ ${synth} = yes ]
+ then
+ check_synth_soa example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.wild-2-nsec.example/AAAA > /dev/null && ret=1
+ else
+ check_nosynth_soa example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.wild-2-nsec.example/AAAA > /dev/null || ret=1
+ fi
+ digcomp wildnodata2nsec.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check synthesized wildcard NODATA 2 NSEC after data response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ # Use AAAA to avoid cached qname minimisation _.wild-2-nsec-afterdata.example A record
+ dig_with_opts b.wild-2-nsec-afterdata.example. @10.53.0.${ns} AAAA > dig.out.a.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.a.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.a.ns${ns}.test$n || ret=1
+ check_nosynth_aaaa b.wild-2-nsec-afterdata.example. dig.out.a.ns${ns}.test$n || ret=1
+ #
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.wild-2-nsec-afterdata.example. @10.53.0.${ns} TLSA > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ if [ ${synth} = yes ]
+ then
+ check_synth_soa example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.wild-2-nsec-afterdata.example/TLSA > /dev/null && ret=1
+ else
+ check_nosynth_soa example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.wild-2-nsec-afterdata.example/TLSA > /dev/null || ret=1
+ fi
+ digcomp wildnodata2nsecafterdata.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check insecure NXDOMAIN response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.insecure.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NXDOMAIN dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa insecure.example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.insecure.example/A > /dev/null || ret=1
+ digcomp insecure.nxdomain.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check insecure NODATA response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts nodata.insecure.example. @10.53.0.${ns} aaaa > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa insecure.example. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep nodata.insecure.example/AAAA > /dev/null || ret=1
+ digcomp insecure.nodata.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check insecure wildcard response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.wild-a.insecure.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ grep "b\.wild-a\.insecure\.example\..*3600.IN.A" dig.out.ns${ns}.test$n > /dev/null || ret=1
+ nextpart ns1/named.run | grep b.wild-a.insecure.example/A > /dev/null || ret=1
+ digcomp insecure.wild.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check insecure wildcard CNAME response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.wild-cname.insecure.example. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_cname b.wild-cname.insecure.example dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep b.wild-cname.insecure.example/A > /dev/null || ret=1
+ grep "ns1.insecure.example.*.IN.A" dig.out.ns${ns}.test$n > /dev/null || ret=1
+ digcomp insecure.wildcname.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check insecure wildcard NODATA 1 NSEC response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.wild-1-nsec.insecure.example. @10.53.0.${ns} AAAA > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa insecure.example. dig.out.ns${ns}.test$n || ret=1
+ digcomp insecure.wildnodata1nsec.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check insecure wildcard NODATA 2 NSEC response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.wild-2-nsec.insecure.example. @10.53.0.${ns} AAAA > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa insecure.example. dig.out.ns${ns}.test$n || ret=1
+ digcomp insecure.wildnodata2nsec.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check insecure wildcard NODATA 2 NSEC after data response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts b.wild-2-nsec-afterdata.insecure.example. @10.53.0.${ns} AAAA > dig.out.a.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.a.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.a.ns${ns}.test$n || ret=1
+ check_nosynth_aaaa b.wild-2-nsec-afterdata.insecure.example. dig.out.a.ns${ns}.test$n || ret=1
+ #
+ dig_with_opts b.wild-2-nsec-afterdata.insecure.example. @10.53.0.${ns} TLSA > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag no dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa insecure.example. dig.out.ns${ns}.test$n || ret=1
+ digcomp insecure.wildnodata2nsecafterdata.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check minimal NXDOMAIN response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts nxdomaic.minimal. @10.53.0.${ns} a > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NXDOMAIN dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa minimal. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep nxdomaic.minimal/A > /dev/null || ret=1
+ digcomp minimal.nxdomain.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check black lie NODATA response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ nextpart ns1/named.run > /dev/null
+ dig_with_opts black.minimal. @10.53.0.${ns} aaaa > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa minimal. dig.out.ns${ns}.test$n || ret=1
+ nextpart ns1/named.run | grep black.minimal/AAAA > /dev/null || ret=1
+ digcomp black.out dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check bad type map NODATA response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts badtypemap.minimal. @10.53.0.${ns} HINFO > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa minimal. dig.out.ns${ns}.test$n || ret=1
+ grep 'badtypemap.minimal.*3600.IN.NSEC.black.minimal. A$' dig.out.ns${ns}.test$n > /dev/null || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check bad type map NODATA response with existent data (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts badtypemap.minimal. @10.53.0.${ns} AAAA > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_aaaa badtypemap.minimal. dig.out.ns${ns}.test$n || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check SOA without DNSKEY bad type map NODATA response (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ dig_with_opts soa-without-dnskey. @10.53.0.${ns} A > dig.out.ns${ns}.test$n || ret=1
+ check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
+ check_status NOERROR dig.out.ns${ns}.test$n || ret=1
+ check_nosynth_soa soa-without-dnskey. dig.out.ns${ns}.test$n || ret=1
+ grep 'soa-without-dnskey.*3600.IN.NSEC.ns1.soa-without-dnskey. NS SOA RRSIG NSEC$' dig.out.ns${ns}.test$n > /dev/null || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check 'rndc stats' output for 'covering nsec returned' (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ ${RNDCCMD} 10.53.0.${ns} stats 2>&1 | sed 's/^/ns6 /' | cat_i
+ # 2 views, _bind should always be '0 covering nsec returned'
+ count=$(grep "covering nsec returned" ns${ns}/named.stats | wc -l)
+ test $count = 2 || ret=1
+ zero=$(grep " 0 covering nsec returned" ns${ns}/named.stats | wc -l)
+ if [ ${synth} = yes ]
+ then
+ test $zero = 1 || ret=1
+ else
+ test $zero = 2 || ret=1
+ fi
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check 'rndc stats' output for 'cache NSEC auxiliary database nodes' (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ # 2 views, _bind should always be '0 cache NSEC auxiliary database nodes'
+ count=$(grep "cache NSEC auxiliary database nodes" ns${ns}/named.stats | wc -l)
+ test $count = 2 || ret=1
+ zero=$(grep "0 cache NSEC auxiliary database nodes" ns${ns}/named.stats | wc -l)
+ if [ ${ad} = yes ]
+ then
+ test $zero = 1 || ret=1
+ else
+ test $zero = 2 || ret=1
+ fi
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ for synthesized in NXDOMAIN no-data wildcard
+ do
+ case $synthesized in
+ NXDOMAIN) count=1;;
+ no-data) count=4;;
+ wildcard) count=2;;
+ esac
+ echo_i "check 'rndc stats' output for 'synthesized a ${synthesized} response' (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ if [ ${synth} = yes ]
+ then
+ grep "$count synthesized a ${synthesized} response" ns${ns}/named.stats > /dev/null || ret=1
+ else
+ grep "synthesized a ${synthesized} response" ns${ns}/named.stats > /dev/null && ret=1
+ fi
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ done
+
+ if ${FEATURETEST} --have-libxml2 && [ -x "${CURL}" ] ; then
+ echo_i "getting XML statisistcs for (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ xml=xml.out$n
+ ${CURL} http://10.53.0.${ns}:${EXTRAPORT1}/xml/v3/server > $xml 2>/dev/null || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check XML for 'CoveringNSEC' with (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ counter=$(sed -n 's;.*<view name="_default">.*\(<counter name="CoveringNSEC">[0-9]*</counter>\).*</view><view.*;\1;gp' $xml)
+ count=$(echo "$counter" | grep CoveringNSEC | wc -l)
+ test $count = 1 || ret=1
+ zero=$(echo "$counter" | grep ">0<" | wc -l)
+ if [ ${synth} = yes ]
+ then
+ test $zero = 0 || ret=1
+ else
+ test $zero = 1 || ret=1
+ fi
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check XML for 'CacheNSECNodes' with (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ counter=$(sed -n 's;.*<view name="_default">.*\(<counter name="CacheNSECNodes">[0-9]*</counter>\).*</view><view.*;\1;gp' $xml)
+ count=$(echo "$counter" | grep CacheNSECNodes | wc -l)
+ test $count = 1 || ret=1
+ zero=$(echo "$counter" | grep ">0<" | wc -l)
+ if [ ${ad} = yes ]
+ then
+ test $zero = 0 || ret=1
+ else
+ test $zero = 1 || ret=1
+ fi
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ for synthesized in SynthNXDOMAIN SynthNODATA SynthWILDCARD
+ do
+ case $synthesized in
+ SynthNXDOMAIN) count=1;;
+ SynthNODATA) count=4;;
+ SynthWILDCARD) count=2;;
+ esac
+
+ echo_i "check XML for '$synthesized}' with (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ if [ ${synth} = yes ]
+ then
+ grep '<counter name="'$synthesized'">'$count'</counter>' $xml > /dev/null || ret=1
+ else
+ grep '<counter name="'$synthesized'">'0'</counter>' $xml > /dev/null || ret=1
+ fi
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ done
+ else
+ echo_i "Skipping XML statistics checks"
+ fi
+
+ if $FEATURETEST --have-json-c && [ -x "${CURL}" ] ; then
+ echo_i "getting JSON statisistcs for (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ json=json.out$n
+ ${CURL} http://10.53.0.${ns}:${EXTRAPORT1}/json/v1/server > $json 2>/dev/null || ret=1
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check JSON for 'CoveringNSEC' with (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ count=$(grep '"CoveringNSEC":' $json | wc -l)
+ test $count = 2 || ret=1
+ zero=$(grep '"CoveringNSEC":0' $json | wc -l)
+ if [ ${synth} = yes ]
+ then
+ test $zero = 1 || ret=1
+ else
+ test $zero = 2 || ret=1
+ fi
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ echo_i "check JSON for 'CacheNSECNodes' with (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ count=$(grep '"CacheNSECNodes":' $json | wc -l)
+ test $count = 2 || ret=1
+ zero=$(grep '"CacheNSECNodes":0' $json | wc -l)
+ if [ ${ad} = yes ]
+ then
+ test $zero = 1 || ret=1
+ else
+ test $zero = 2 || ret=1
+ fi
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ for synthesized in SynthNXDOMAIN SynthNODATA SynthWILDCARD
+ do
+ case $synthesized in
+ SynthNXDOMAIN) count=1;;
+ SynthNODATA) count=4;;
+ SynthWILDCARD) count=2;;
+ esac
+
+ echo_i "check JSON for '$synthesized}' with (synth-from-dnssec ${description};) ($n)"
+ ret=0
+ if [ ${synth} = yes ]
+ then
+ grep '"'$synthesized'":'$count'' $json > /dev/null || ret=1
+ else
+ grep '"'$synthesized'":' $json > /dev/null && ret=1
+ fi
+ n=$((n+1))
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+ done
+ else
+ echo_i "Skipping JSON statistics checks"
+ fi
+done
+
+echo_i "check redirect response (+dnssec) (synth-from-dnssec <default>;) ($n)"
+ret=0
+synth=${synth_default}
+dig_with_opts b.redirect. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+check_ad_flag yes dig.out.ns3.test$n || ret=1
+check_status NXDOMAIN dig.out.ns3.test$n || ret=1
+if [ ${synth} = yes ]
+then
+ check_synth_soa . dig.out.ns3.test$n || ret=1
+else
+ check_nosynth_soa . dig.out.ns3.test$n || ret=1
+fi
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "check redirect response (+nodnssec) (synth-from-dnssec <default>;) ($n)"
+ret=0
+dig_with_opts +nodnssec b.redirect. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+check_ad_flag no dig.out.ns3.test$n || ret=1
+check_status NOERROR dig.out.ns3.test$n || ret=1
+grep 'b\.redirect\..*300.IN.A.100\.100\.100\.2' dig.out.ns3.test$n > /dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "check DNAME handling (synth-from-dnssec yes;) ($n)"
+ret=0
+dig_with_opts dnamed.example. ns @10.53.0.5 > dig.out.ns5.test$n || ret=1
+dig_with_opts a.dnamed.example. a @10.53.0.5 > dig.out.ns5-1.test$n || ret=1
+check_status NOERROR dig.out.ns5-1.test$n || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "regression test for CVE-2022-0635 ($n)"
+ret=0
+# add DNAME to cache
+dig_with_opts dname.dnamed. dname @10.53.0.5 > dig.out.ns5-1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns5-1.test$n >/dev/null || ret=1
+# add A record to cache at name before DNAME owner
+dig_with_opts a.dnamed. a @10.53.0.5 > dig.out.ns5-2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns5-2.test$n >/dev/null || ret=1
+# add NSEC record to cache at name before DNAME owner
+dig_with_opts a.dnamed. aaaa @10.53.0.5 > dig.out.ns5-3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns5-3.test$n >/dev/null || ret=1
+# wait for NSEC to timeout
+sleep 6
+# use DNAME for lookup
+dig_with_opts b.dname.dnamed a @10.53.0.5 > dig.out.ns5-4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns5-4.test$n >/dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "check synth-from-dnssec with grafted zone (forward only) ($n)"
+ret=0
+#prime cache with NXDOMAIN NSEC covering 'fun' to 'minimal'
+dig_with_opts internal @10.53.0.5 > dig.out.ns5-1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns5-1.test$n >/dev/null || ret=1
+grep '^fun\..*NSEC.minimal\. ' dig.out.ns5-1.test$n >/dev/null || ret=1
+#perform lookup in grafted zone
+dig_with_opts example.internal @10.53.0.5 > dig.out.ns5-2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns5-2.test$n >/dev/null || ret=1
+grep '^example\.internal\..*A.1.2.3.4$' dig.out.ns5-2.test$n >/dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "check synth-from-dnssec with grafted zone (primary zone) ($n)"
+ret=0
+#prime cache with NXDOMAIN NSEC covering 'fun' to 'minimal'
+dig_with_opts internal @10.53.0.5 > dig.out.ns5-1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns5-1.test$n >/dev/null || ret=1
+grep '^fun\..*NSEC.minimal\. ' dig.out.ns5-1.test$n >/dev/null || ret=1
+#perform lookup in grafted zone
+dig_with_opts example.internal2 @10.53.0.5 > dig.out.ns5-2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns5-2.test$n >/dev/null || ret=1
+grep '^example\.internal2\..*A.1.2.3.4$' dig.out.ns5-2.test$n >/dev/null || ret=1
+n=$((n+1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/synthfromdnssec/tests_sh_synthfromdnssec.py b/bin/tests/system/synthfromdnssec/tests_sh_synthfromdnssec.py
new file mode 100644
index 0000000..5cbf848
--- /dev/null
+++ b/bin/tests/system/synthfromdnssec/tests_sh_synthfromdnssec.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_synthfromdnssec(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/tcp/1996-alloc_dnsbuf-crash-test.pkt b/bin/tests/system/tcp/1996-alloc_dnsbuf-crash-test.pkt
new file mode 100644
index 0000000..7520c3a
--- /dev/null
+++ b/bin/tests/system/tcp/1996-alloc_dnsbuf-crash-test.pkt
@@ -0,0 +1,12 @@
+# Transaction ID
+0001
+# Standard query
+0000
+# Questions: 1, Additional: 1
+0001 0000 0000 0000
+# QNAME: www.isc.org
+03 697363 03 6F7267 00
+# Type: AXFR
+00fc
+# Class: IN
+0001
diff --git a/bin/tests/system/tcp/ans6/ans.py b/bin/tests/system/tcp/ans6/ans.py
new file mode 100644
index 0000000..4595ddc
--- /dev/null
+++ b/bin/tests/system/tcp/ans6/ans.py
@@ -0,0 +1,157 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+############################################################################
+#
+# This tool allows an arbitrary number of TCP connections to be made to the
+# specified service and to keep them open until told otherwise. It is
+# controlled by writing text commands to a TCP socket (default port: 5309).
+#
+# Currently supported commands:
+#
+# - open <COUNT> <HOST> <PORT>
+#
+# Opens <COUNT> TCP connections to <HOST>:<PORT> and keeps them open.
+# <HOST> must be an IP address (IPv4 or IPv6).
+#
+# - close <COUNT>
+#
+# Close the oldest <COUNT> previously established connections.
+#
+############################################################################
+
+from __future__ import print_function
+
+import datetime
+import errno
+import os
+import select
+import signal
+import socket
+import sys
+import time
+
+
+# Timeout for establishing all connections requested by a single 'open' command.
+OPEN_TIMEOUT = 2
+VERSION_QUERY = b"\x00\x1e\xaf\xb8\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07version\x04bind\x00\x00\x10\x00\x03"
+
+
+def log(msg):
+ print(datetime.datetime.now().strftime("%d-%b-%Y %H:%M:%S.%f ") + msg)
+
+
+def open_connections(active_conns, count, host, port):
+ queued = []
+ errors = []
+
+ try:
+ socket.inet_aton(host)
+ family = socket.AF_INET
+ except socket.error:
+ family = socket.AF_INET6
+
+ log("Opening %d connections..." % count)
+
+ for _ in range(count):
+ sock = socket.socket(family, socket.SOCK_STREAM)
+ sock.setblocking(0)
+ err = sock.connect_ex((host, port))
+ if err not in (0, errno.EINPROGRESS):
+ log("%s on connect for socket %s" % (errno.errorcode[err], sock))
+ errors.append(sock)
+ else:
+ queued.append(sock)
+
+ start = time.time()
+ while queued:
+ now = time.time()
+ time_left = OPEN_TIMEOUT - (now - start)
+ if time_left <= 0:
+ break
+ _, wsocks, _ = select.select([], queued, [], time_left)
+ for sock in wsocks:
+ queued.remove(sock)
+ err = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
+ if err:
+ log("%s for socket %s" % (errno.errorcode[err], sock))
+ errors.append(sock)
+ else:
+ sock.send(VERSION_QUERY)
+ active_conns.append(sock)
+
+ if errors:
+ log("result=FAIL: %d connection(s) failed" % len(errors))
+ elif queued:
+ log("result=FAIL: Timed out, aborting %d pending connections" % len(queued))
+ for sock in queued:
+ sock.close()
+ else:
+ log("result=OK: Successfully opened %d connections" % count)
+
+
+def close_connections(active_conns, count):
+ log("Closing %s connections..." % "all" if count == 0 else str(count))
+ if count == 0:
+ count = len(active_conns)
+ for _ in range(count):
+ sock = active_conns.pop(0)
+ sock.close()
+ log("result=OK: Successfully closed %d connections" % count)
+
+
+def sigterm(*_):
+ log("SIGTERM received, shutting down")
+ os.remove("ans.pid")
+ sys.exit(0)
+
+
+def main():
+ active_conns = []
+
+ signal.signal(signal.SIGTERM, sigterm)
+
+ with open("ans.pid", "w") as pidfile:
+ print(os.getpid(), file=pidfile)
+
+ listenip = "10.53.0.6"
+ try:
+ port = int(os.environ["CONTROLPORT"])
+ except KeyError:
+ port = 5309
+
+ log("Listening on %s:%d" % (listenip, port))
+
+ ctlsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ ctlsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ ctlsock.bind((listenip, port))
+ ctlsock.listen(1)
+
+ while True:
+ (clientsock, _) = ctlsock.accept()
+ log("Accepted control connection from %s" % clientsock)
+ cmdline = clientsock.recv(512).decode("ascii").strip()
+ if cmdline:
+ log("Received command: %s" % cmdline)
+ cmd = cmdline.split()
+ if cmd[0] == "open":
+ count, host, port = cmd[1:]
+ open_connections(active_conns, int(count), host, int(port))
+ elif cmd[0] == "close":
+ (count,) = cmd[1:]
+ close_connections(active_conns, int(count))
+ else:
+ log("result=FAIL: Unknown command")
+ clientsock.close()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/bin/tests/system/tcp/clean.sh b/bin/tests/system/tcp/clean.sh
new file mode 100644
index 0000000..1ea5b60
--- /dev/null
+++ b/bin/tests/system/tcp/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ./*/named.memstats
+rm -f ./*/named.run
+rm -f ./*/named.conf
+rm -f ./*/named.stats*
+rm -f ans6/ans.run*
+rm -f dig.out*
+rm -f rndc.out*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/tcp/ns1/named.conf.in b/bin/tests/system/tcp/ns1/named.conf.in
new file mode 100644
index 0000000..010e754
--- /dev/null
+++ b/bin/tests/system/tcp/ns1/named.conf.in
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ statistics-file "named.stats";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/tcp/ns1/root.db b/bin/tests/system/tcp/ns1/root.db
new file mode 100644
index 0000000..17780d1
--- /dev/null
+++ b/bin/tests/system/tcp/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/tcp/ns2/example.db b/bin/tests/system/tcp/ns2/example.db
new file mode 100644
index 0000000..4d60ce3
--- /dev/null
+++ b/bin/tests/system/tcp/ns2/example.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+$ORIGIN example.
+a A 10.0.0.1
+ MX 10 mail.example.
+
+mail A 10.0.0.2
diff --git a/bin/tests/system/tcp/ns2/named.conf.in b/bin/tests/system/tcp/ns2/named.conf.in
new file mode 100644
index 0000000..0a97093
--- /dev/null
+++ b/bin/tests/system/tcp/ns2/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+ statistics-file "named.stats";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/tcp/ns3/named.conf.in b/bin/tests/system/tcp/ns3/named.conf.in
new file mode 100644
index 0000000..8516d72
--- /dev/null
+++ b/bin/tests/system/tcp/ns3/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+};
+
+server 10.53.0.1 { tcp-only yes; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/tcp/ns4/named.conf.in b/bin/tests/system/tcp/ns4/named.conf.in
new file mode 100644
index 0000000..a7758cc
--- /dev/null
+++ b/bin/tests/system/tcp/ns4/named.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+ forwarders { 10.53.0.2; };
+ forward only;
+};
+
+server 10.53.0.2 { tcp-only yes; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+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/tcp/ns5/named.conf.in b/bin/tests/system/tcp/ns5/named.conf.in
new file mode 100644
index 0000000..bd754f7
--- /dev/null
+++ b/bin/tests/system/tcp/ns5/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS5
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ tcp-listen-queue 32;
+ recursion yes;
+ notify yes;
+ tcp-clients 17;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/tcp/ns7/named.conf.in b/bin/tests/system/tcp/ns7/named.conf.in
new file mode 100644
index 0000000..5441519
--- /dev/null
+++ b/bin/tests/system/tcp/ns7/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.7;
+ notify-source 10.53.0.7;
+ transfer-source 10.53.0.7;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.7; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ statistics-file "named.stats";
+ tcp-clients 1;
+ keep-response-order { any; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/tcp/ns7/named.dropedns b/bin/tests/system/tcp/ns7/named.dropedns
new file mode 100644
index 0000000..37dd9cf
--- /dev/null
+++ b/bin/tests/system/tcp/ns7/named.dropedns
@@ -0,0 +1 @@
+dropedns
diff --git a/bin/tests/system/tcp/ns7/root.db b/bin/tests/system/tcp/ns7/root.db
new file mode 100644
index 0000000..bb31741
--- /dev/null
+++ b/bin/tests/system/tcp/ns7/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.7
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/tcp/setup.sh b/bin/tests/system/tcp/setup.sh
new file mode 100644
index 0000000..475f399
--- /dev/null
+++ b/bin/tests/system/tcp/setup.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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 ns7/named.conf.in ns7/named.conf
diff --git a/bin/tests/system/tcp/tests.sh b/bin/tests/system/tcp/tests.sh
new file mode 100644
index 0000000..12ca679
--- /dev/null
+++ b/bin/tests/system/tcp/tests.sh
@@ -0,0 +1,203 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=../conf.sh
+. ../conf.sh
+
+dig_with_opts() {
+ "${DIG}" -p "${PORT}" "$@"
+}
+
+rndccmd() {
+ "${RNDC}" -p "${CONTROLPORT}" -c ../common/rndc.conf -s "$@"
+}
+
+status=0
+n=0
+
+n=$((n + 1))
+echo_i "initializing TCP statistics ($n)"
+ret=0
+rndccmd 10.53.0.1 stats || ret=1
+rndccmd 10.53.0.2 stats || ret=1
+mv ns1/named.stats ns1/named.stats.test$n
+mv ns2/named.stats ns2/named.stats.test$n
+ntcp10="$(grep "TCP requests received" ns1/named.stats.test$n | tail -1 | awk '{print $1}')"
+ntcp20="$(grep "TCP requests received" ns2/named.stats.test$n | tail -1 | awk '{print $1}')"
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking TCP request statistics (resolver) ($n)"
+ret=0
+dig_with_opts @10.53.0.3 txt.example. > dig.out.test$n
+sleep 1
+rndccmd 10.53.0.1 stats || ret=1
+rndccmd 10.53.0.2 stats || ret=1
+mv ns1/named.stats ns1/named.stats.test$n
+mv ns2/named.stats ns2/named.stats.test$n
+ntcp11="$(grep "TCP requests received" ns1/named.stats.test$n | tail -1 | awk '{print $1}')"
+ntcp21="$(grep "TCP requests received" ns2/named.stats.test$n | tail -1 | awk '{print $1}')"
+if [ "$ntcp10" -ge "$ntcp11" ]; then ret=1; fi
+if [ "$ntcp20" -ne "$ntcp21" ]; then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking TCP request statistics (forwarder) ($n)"
+ret=0
+dig_with_opts @10.53.0.4 txt.example. > dig.out.test$n
+sleep 1
+rndccmd 10.53.0.1 stats || ret=1
+rndccmd 10.53.0.2 stats || ret=1
+mv ns1/named.stats ns1/named.stats.test$n
+mv ns2/named.stats ns2/named.stats.test$n
+ntcp12="$(grep "TCP requests received" ns1/named.stats.test$n | tail -1 | awk '{print $1}')"
+ntcp22="$(grep "TCP requests received" ns2/named.stats.test$n | tail -1 | awk '{print $1}')"
+if [ "$ntcp11" -ne "$ntcp12" ]; then ret=1; fi
+if [ "$ntcp21" -ge "$ntcp22" ];then ret=1; fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# -------- TCP high-water tests ----------
+refresh_tcp_stats() {
+ rndccmd 10.53.0.5 status > rndc.out.$n || ret=1
+ TCP_CUR="$(sed -n "s/^tcp clients: \([0-9][0-9]*\).*/\1/p" rndc.out.$n)"
+ TCP_LIMIT="$(sed -n "s/^tcp clients: .*\/\([0-9][0-9]*\)/\1/p" rndc.out.$n)"
+ TCP_HIGH="$(sed -n "s/^TCP high-water: \([0-9][0-9]*\)/\1/p" rndc.out.$n)"
+}
+
+# Send a command to the tool script listening on 10.53.0.6.
+send_command() {
+ nextpart ans6/ans.run > /dev/null
+ echo "$*" | send 10.53.0.6 "${CONTROLPORT}"
+ wait_for_log_peek 10 "result=" ans6/ans.run || ret=1
+ if ! nextpartpeek ans6/ans.run | grep -qF "result=OK"; then
+ return 1
+ fi
+}
+
+# Instructs ans6 to open $1 TCP connections to 10.53.0.5.
+open_connections() {
+ send_command "open" "${1}" 10.53.0.5 "${PORT}" || return 1
+}
+
+# Instructs ans6 to close $1 TCP connections to 10.53.0.5.
+close_connections() {
+ send_command "close" "${1}" || return 1
+}
+
+# Check TCP connections are working normally before opening
+# multiple connections
+n=$((n + 1))
+echo_i "checking TCP query repsonse ($n)"
+ret=0
+dig_with_opts +tcp @10.53.0.5 txt.example > dig.out.test$n
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check TCP statistics after server startup before using them as a baseline for
+# subsequent checks.
+n=$((n + 1))
+echo_i "TCP high-water: check initial statistics ($n)"
+ret=0
+refresh_tcp_stats
+assert_int_equal "${TCP_CUR}" 0 "current TCP clients count" || ret=1
+# We compare initial tcp-highwater value with 1 because as part of the
+# system test startup, the script start.pl executes dig to check if target
+# named is running, and that increments tcp-quota by one.
+assert_int_equal "${TCP_HIGH}" 1 "tcp-highwater count" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Ensure the TCP high-water statistic gets updated after some TCP connections
+# are established.
+n=$((n + 1))
+echo_i "TCP high-water: check value after some TCP connections are established ($n)"
+ret=0
+OLD_TCP_CUR="${TCP_CUR}"
+TCP_ADDED=9
+open_connections "${TCP_ADDED}" || ret=1
+check_stats_added() {
+ refresh_tcp_stats
+ assert_int_equal "${TCP_CUR}" $((OLD_TCP_CUR + TCP_ADDED)) "current TCP clients count" || return 1
+ assert_int_equal "${TCP_HIGH}" $((OLD_TCP_CUR + TCP_ADDED)) "TCP high-water value" || return 1
+}
+retry 2 check_stats_added || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Ensure the TCP high-water statistic remains unchanged after some TCP
+# connections are closed.
+n=$((n + 1))
+echo_i "TCP high-water: check value after some TCP connections are closed ($n)"
+ret=0
+OLD_TCP_CUR="${TCP_CUR}"
+OLD_TCP_HIGH="${TCP_HIGH}"
+TCP_REMOVED=5
+close_connections "${TCP_REMOVED}" || ret=1
+check_stats_removed() {
+ refresh_tcp_stats
+ assert_int_equal "${TCP_CUR}" $((OLD_TCP_CUR - TCP_REMOVED)) "current TCP clients count" || return 1
+ assert_int_equal "${TCP_HIGH}" "${OLD_TCP_HIGH}" "TCP high-water value" || return 1
+}
+retry 2 check_stats_removed || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Ensure the TCP high-water statistic never exceeds the configured TCP clients
+# limit.
+n=$((n + 1))
+echo_i "TCP high-water: ensure tcp-clients is an upper bound ($n)"
+ret=0
+open_connections $((TCP_LIMIT + 1)) || ret=1
+check_stats_limit() {
+ refresh_tcp_stats
+ assert_int_equal "${TCP_CUR}" "${TCP_LIMIT}" "current TCP clients count" || return 1
+ assert_int_equal "${TCP_HIGH}" "${TCP_LIMIT}" "TCP high-water value" || return 1
+}
+retry 2 check_stats_limit || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+# Check TCP connections are working normally before opening
+# multiple connections
+n=$((n + 1))
+echo_i "checking TCP response recovery ($n)"
+ret=0
+# "0" closes all connections
+close_connections 0 || ret=1
+dig_with_opts +tcp @10.53.0.5 txt.example > dig.out.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+####################################################
+# NOTE: The next test resets the debug level to 1. #
+####################################################
+
+n=$((n + 1))
+echo_i "checking that BIND 9 doesn't crash on long TCP messages ($n)"
+ret=0
+# Avoid logging useless information.
+rndccmd 10.53.0.1 trace 1 || ret=1
+{ $PERL ../packet.pl -a "10.53.0.1" -p "${PORT}" -t tcp -r 300000 1996-alloc_dnsbuf-crash-test.pkt || ret=1 ; } | cat_i
+dig_with_opts +tcp @10.53.0.1 txt.example > dig.out.test$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/tcp/tests_sh_tcp.py b/bin/tests/system/tcp/tests_sh_tcp.py
new file mode 100644
index 0000000..b1d797c
--- /dev/null
+++ b/bin/tests/system/tcp/tests_sh_tcp.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_tcp(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/tcp/tests_tcp.py b/bin/tests/system/tcp/tests_tcp.py
new file mode 100644
index 0000000..532b47b
--- /dev/null
+++ b/bin/tests/system/tcp/tests_tcp.py
@@ -0,0 +1,116 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# pylint: disable=unused-variable
+
+import socket
+import struct
+import time
+
+import pytest
+
+pytest.importorskip("dns", minversion="2.0.0")
+import dns.message
+import dns.query
+
+
+TIMEOUT = 10
+
+
+def create_msg(qname, qtype, edns=-1):
+ msg = dns.message.make_query(qname, qtype, use_edns=edns)
+ return msg
+
+
+def timeout():
+ return time.time() + TIMEOUT
+
+
+def create_socket(host, port):
+ sock = socket.create_connection((host, port), timeout=10)
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)
+ return sock
+
+
+def test_tcp_garbage(named_port):
+ with create_socket("10.53.0.7", named_port) as sock:
+ msg = create_msg("a.example.", "A")
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+
+ wire = msg.to_wire()
+ assert len(wire) > 0
+
+ # Send DNS message shorter than DNS message header (12),
+ # this should cause the connection to be terminated
+ sock.send(struct.pack("!H", 11))
+ sock.send(struct.pack("!s", b"0123456789a"))
+
+ with pytest.raises(EOFError):
+ try:
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+ except ConnectionError as e:
+ raise EOFError from e
+
+
+def test_tcp_garbage_response(named_port):
+ with create_socket("10.53.0.7", named_port) as sock:
+ msg = create_msg("a.example.", "A")
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+
+ wire = msg.to_wire()
+ assert len(wire) > 0
+
+ # Send DNS response instead of DNS query, this should cause
+ # the connection to be terminated
+
+ rmsg = dns.message.make_response(msg)
+ (sbytes, stime) = dns.query.send_tcp(sock, rmsg, timeout())
+
+ with pytest.raises(EOFError):
+ try:
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+ except ConnectionError as e:
+ raise EOFError from e
+
+
+# Regression test for CVE-2022-0396
+def test_close_wait(named_port):
+ with create_socket("10.53.0.7", named_port) as sock:
+ msg = create_msg("a.example.", "A")
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+
+ msg = dns.message.make_query("a.example.", "A", use_edns=0, payload=1232)
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+
+ # Shutdown the socket, but ignore the other side closing the socket
+ # first because we sent DNS message with EDNS0
+ try:
+ sock.shutdown(socket.SHUT_RDWR)
+ except ConnectionError:
+ pass
+ except OSError:
+ pass
+
+ # BIND allows one TCP client, the part above sends DNS messaage with EDNS0
+ # after the first query. BIND should react adequately because of
+ # ns7/named.dropedns and close the socket, making room for the next
+ # request. If it gets stuck in CLOSE_WAIT state, there is no connection
+ # available for the query below and it will time out.
+ with create_socket("10.53.0.7", named_port) as sock:
+ msg = create_msg("a.example.", "A")
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
diff --git a/bin/tests/system/testcrypto.sh b/bin/tests/system/testcrypto.sh
new file mode 100755
index 0000000..ceaaf37
--- /dev/null
+++ b/bin/tests/system/testcrypto.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+prog=$0
+args=""
+quiet=0
+dir=""
+msg="cryptography"
+
+if test -z "$KEYGEN"; then
+ . ../conf.sh
+ alg="-a $DEFAULT_ALGORITHM -b $DEFAULT_BITS"
+else
+ alg=""
+ quiet=1
+ args="-q"
+fi
+
+while test "$#" -gt 0; do
+ case $1 in
+ -q)
+ if test $quiet -eq 0; then
+ args="$args -q"
+ quiet=1
+ fi
+ ;;
+ rsa|RSA|rsasha1|RSASHA1)
+ alg="-a RSASHA1"
+ msg="RSA cryptography"
+ ;;
+ rsasha256|RSASHA256)
+ alg="-a RSASHA256"
+ msg="RSA cryptography"
+ ;;
+ rsasha512|RSASHA512)
+ alg="-a RSASHA512"
+ msg="RSA cryptography"
+ ;;
+ ecdsa|ECDSA|ecdsap256sha256|ECDSAP256SHA256)
+ alg="-a ECDSAP256SHA256"
+ msg="ECDSA cryptography"
+ ;;
+ ecdsap384sha384|ECDSAP384SHA384)
+ alg="-a ECDSAP384SHA384"
+ msg="ECDSA cryptography"
+ ;;
+ eddsa|EDDSA|ed25519|ED25519)
+ alg="-a ED25519"
+ msg="EDDSA cryptography"
+ ;;
+ ed448|ED448)
+ alg="-a ED448"
+ msg="EDDSA cryptography"
+ ;;
+ *)
+ echo "${prog}: unknown argument"
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+if test -z "$alg"; then
+ echo "${prog}: no algorithm selected"
+ exit 1
+fi
+
+if test -n "$TMPDIR"; then
+ dir=$(mktemp -d "$TMPDIR/XXXXXX")
+ args="$args -K $dir"
+fi
+
+if $KEYGEN $args $alg foo > /dev/null 2>&1
+then
+ if test -z "$dir"; then
+ rm -f Kfoo*
+ else
+ rm -rf "$dir"
+ fi
+else
+ if test $quiet -eq 0; then
+ echo_i "This test requires support for $msg" >&2
+ fi
+ exit 255
+fi
diff --git a/bin/tests/system/testsock.pl b/bin/tests/system/testsock.pl
new file mode 100755
index 0000000..e793874
--- /dev/null
+++ b/bin/tests/system/testsock.pl
@@ -0,0 +1,55 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Test whether the interfaces on 10.53.0.* are up.
+
+require 5.001;
+
+use Cwd 'abs_path';
+use File::Basename;
+use Socket;
+use Getopt::Long;
+
+my $port = 0;
+my $id = 0;
+GetOptions("p=i" => \$port,
+ "i=i" => \$id);
+
+my @ids;
+if ($id != 0) {
+ @ids = ($id);
+} else {
+ my $dir = dirname(abs_path($0));
+ my $fn = "$dir/ifconfig.sh.in";
+ open FH, "< $fn" or die "open < $fn: $!\n";
+ while (<FH>) {
+ @ids = (1..$1)
+ if /^max=(\d+)\s*$/;
+ }
+ close FH;
+ die "could not find max IP address in $fn\n"
+ unless @ids > 1;
+}
+
+foreach $id (@ids) {
+ my $addr = pack("C4", 10, 53, 0, $id);
+ my $sa = pack_sockaddr_in($port, $addr);
+ socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp"))
+ or die "$0: socket: $!\n";
+ setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1));
+
+ bind(SOCK, $sa)
+ or die sprintf("$0: bind(%s, %d): $!\n",
+ inet_ntoa($addr), $port);
+ close(SOCK);
+}
diff --git a/bin/tests/system/testsock6.pl b/bin/tests/system/testsock6.pl
new file mode 100644
index 0000000..5903684
--- /dev/null
+++ b/bin/tests/system/testsock6.pl
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+require 5.001;
+
+use IO::Socket::INET6;
+
+foreach $addr (@ARGV) {
+ my $sock;
+ $sock = IO::Socket::INET6->new(LocalAddr => $addr,
+ LocalPort => 0,
+ Proto => tcp)
+ or die "Can't bind : $@\n";
+ close($sock);
+}
diff --git a/bin/tests/system/testsummary.sh b/bin/tests/system/testsummary.sh
new file mode 100644
index 0000000..52c79b9
--- /dev/null
+++ b/bin/tests/system/testsummary.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# Creates the system tests output file from the various test.output.* files. It
+# then searches that file and prints the number of tests passed, failed, not
+# run. It also checks whether the IP addresses 10.53.0.[1-8] were set up and,
+# if not, prints a warning.
+#
+# Usage:
+# testsummary.sh [-n]
+#
+# -n Do NOT delete the individual test.output.* files after concatenating
+# them into systests.output.
+#
+# Status return:
+# 0 - no tests failed
+# 1 - one or more tests failed
+
+. ./conf.sh
+
+keepfile=0
+
+while getopts "n" flag; do
+ case $flag in
+ n) keepfile=1 ;;
+ *) exit 1 ;;
+ esac
+done
+
+if [ "$(find . -name 'test.output.*' 2>/dev/null | wc -l)" -eq 0 ]; then
+ echowarn "I:No 'test.output.*' files were found."
+ echowarn "I:Printing summary from pre-existing 'systests.output'."
+else
+ cat test.output.* > systests.output
+ if [ $keepfile -eq 0 ]; then
+ rm -f test.output.*
+ fi
+fi
+
+if [ ! -f systests.output ]; then
+ echowarn "I:No 'systests.output' file found."
+ exit 1
+fi
+
+status=0
+echoinfo "I:System test result summary:"
+echoinfo "$(grep 'R:[a-z0-9_-][a-z0-9_-]*:[A-Z][A-Z]*' systests.output | cut -d':' -f3 | sort | uniq -c | sed -e 's/^/I:/')"
+
+FAILED_TESTS=$(grep 'R:[a-z0-9_-][a-z0-9_-]*:FAIL' systests.output | cut -d':' -f2 | sort | sed -e 's/^/I: /')
+if [ -n "${FAILED_TESTS}" ]; then
+ echoinfo "I:The following system tests failed:"
+ echoinfo "${FAILED_TESTS}"
+ status=1
+fi
+
+CRASHED_TESTS=$(find . \( -name 'core' -or -name 'core.*' -or -name '*.core' \) ! -name '*.txt' | cut -d'/' -f2 | sort -u | sed -e 's/^/I: /')
+if [ -n "${CRASHED_TESTS}" ]; then
+ echoinfo "I:Core dumps were found for the following system tests:"
+ echoinfo "${CRASHED_TESTS}"
+fi
+
+ASSERTION_FAILED_TESTS=$(find . -name named.run -print0 | xargs -0 grep "assertion failure" | cut -d'/' -f2 | sort -u | sed -e 's/^/I: /')
+if [ -n "${ASSERTION_FAILED_TESTS}" ]; then
+ echoinfo "I:Assertion failures were detected for the following system tests:"
+ echoinfo "${ASSERTION_FAILED_TESTS}"
+fi
+
+TSAN_REPORT_TESTS=$(find . -name 'tsan.*' | cut -d'/' -f2 | sort -u | sed -e 's/^/I: /')
+if [ -n "${TSAN_REPORT_TESTS}" ]; then
+ echoinfo "I:ThreadSanitizer reported issues for the following system tests:"
+ echoinfo "${TSAN_REPORT_TESTS}"
+fi
+
+RESULTS_FOUND=$(grep -c 'R:[a-z0-9_-][a-z0-9_-]*:[A-Z][A-Z]*' systests.output)
+TESTS_RUN=$(echo "${SUBDIRS}" | wc -w)
+if [ "${RESULTS_FOUND}" -ne "${TESTS_RUN}" ]; then
+ echofail "I:Found ${RESULTS_FOUND} test results, but ${TESTS_RUN} tests were run"
+ status=1
+fi
+
+exit $status
diff --git a/bin/tests/system/timeouts/clean.sh b/bin/tests/system/timeouts/clean.sh
new file mode 100644
index 0000000..0da8a9c
--- /dev/null
+++ b/bin/tests/system/timeouts/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ./ns*/managed-keys.bind*
+rm -f ./ns*/named.conf
+rm -f ./ns*/named.lock
+rm -f ./ns*/named.memstats
+rm -f ./ns*/named.run*
+rm -f ./ns*/named.stats
+rm -rf ./__pycache__
+rm -f ./ns*/large.db
diff --git a/bin/tests/system/timeouts/ns1/example.db b/bin/tests/system/timeouts/ns1/example.db
new file mode 100644
index 0000000..cb321ff
--- /dev/null
+++ b/bin/tests/system/timeouts/ns1/example.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns1
+ns1 A 10.53.0.1
+@ A 10.53.0.1
+a A 10.53.0.1
+b A 10.53.0.1
+$INCLUDE large.db
diff --git a/bin/tests/system/timeouts/ns1/named.args b/bin/tests/system/timeouts/ns1/named.args
new file mode 100644
index 0000000..437a77f
--- /dev/null
+++ b/bin/tests/system/timeouts/ns1/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 1 -D timeouts-ns1 -X named.lock -g -T maxcachesize=2097152
diff --git a/bin/tests/system/timeouts/ns1/named.conf.in b/bin/tests/system/timeouts/ns1/named.conf.in
new file mode 100644
index 0000000..1c46549
--- /dev/null
+++ b/bin/tests/system/timeouts/ns1/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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; };
+ dnssec-validation no;
+ recursion no;
+ notify no;
+ tcp-initial-timeout 20;
+ tcp-idle-timeout 50;
+ tcp-keepalive-timeout 70;
+ max-transfer-time-out 5; /* minutes */
+ max-transfer-idle-out 1; /* minutes */
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "example." {
+ type primary;
+ file "example.db";
+ check-integrity no;
+};
diff --git a/bin/tests/system/timeouts/ns1/root.db b/bin/tests/system/timeouts/ns1/root.db
new file mode 100644
index 0000000..cb48acd
--- /dev/null
+++ b/bin/tests/system/timeouts/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.isc.org. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns1.example.
+ns1.example. A 10.53.0.1
diff --git a/bin/tests/system/timeouts/prereq.sh b/bin/tests/system/timeouts/prereq.sh
new file mode 100644
index 0000000..0fac912
--- /dev/null
+++ b/bin/tests/system/timeouts/prereq.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+if test -n "$PYTHON"
+then
+ if $PYTHON -c "from dns.query import send_tcp" 2> /dev/null
+ then
+ :
+ else
+ echo_i "This test requires the dnspython >= 2.0.0 module." >&2
+ exit 1
+ fi
+else
+ echo_i "This test requires Python and the dnspython module." >&2
+ exit 1
+fi
+
+exit 0
diff --git a/bin/tests/system/timeouts/setup.sh b/bin/tests/system/timeouts/setup.sh
new file mode 100644
index 0000000..c4019d2
--- /dev/null
+++ b/bin/tests/system/timeouts/setup.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+
+#
+# Generate a large enough zone, so the transfer takes longer than
+# tcp-initial-timeout interval
+#
+$PYTHON -c "
+print('large IN TXT', end=' ')
+for a in range(128):
+ print('\"%s\"' % ('A' * 240), end=' ')
+print('')
+
+for a in range(150000):
+ print('%s IN NS a' % (a))
+ print('%s IN NS b' % (a))" > ns1/large.db
diff --git a/bin/tests/system/timeouts/tests_tcp_timeouts.py b/bin/tests/system/timeouts/tests_tcp_timeouts.py
new file mode 100644
index 0000000..2e2a4b4
--- /dev/null
+++ b/bin/tests/system/timeouts/tests_tcp_timeouts.py
@@ -0,0 +1,279 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# pylint: disable=unused-variable
+
+import socket
+import time
+
+import pytest
+
+pytest.importorskip("dns", minversion="2.0.0")
+import dns.edns
+import dns.message
+import dns.name
+import dns.query
+import dns.rdataclass
+import dns.rdatatype
+
+import pytest_custom_markers # pylint: disable=import-error
+
+
+TIMEOUT = 10
+
+
+def create_msg(qname, qtype):
+ msg = dns.message.make_query(
+ qname, qtype, want_dnssec=True, use_edns=0, payload=4096
+ )
+ return msg
+
+
+def timeout():
+ return time.time() + TIMEOUT
+
+
+def test_initial_timeout(named_port):
+ #
+ # The initial timeout is 2.5 seconds, so this should timeout
+ #
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ sock.connect(("10.53.0.1", named_port))
+
+ time.sleep(3)
+
+ msg = create_msg("example.", "A")
+
+ with pytest.raises(EOFError):
+ try:
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+ except ConnectionError as e:
+ raise EOFError from e
+
+
+def test_idle_timeout(named_port):
+ #
+ # The idle timeout is 5 seconds, so the third message should fail
+ #
+ msg = create_msg("example.", "A")
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ sock.connect(("10.53.0.1", named_port))
+
+ time.sleep(1)
+
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+
+ time.sleep(2)
+
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+
+ time.sleep(6)
+
+ with pytest.raises(EOFError):
+ try:
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+ except ConnectionError as e:
+ raise EOFError from e
+
+
+def test_keepalive_timeout(named_port):
+ #
+ # Keepalive is 7 seconds, so the third message should succeed.
+ #
+ msg = create_msg("example.", "A")
+ kopt = dns.edns.GenericOption(11, b"\x00")
+ msg.use_edns(edns=True, payload=4096, options=[kopt])
+
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ sock.connect(("10.53.0.1", named_port))
+
+ time.sleep(1)
+
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+
+ time.sleep(2)
+
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+
+ time.sleep(6)
+
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+
+
+def test_pipelining_timeout(named_port):
+ #
+ # The pipelining should only timeout after the last message is received
+ #
+ msg = create_msg("example.", "A")
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ sock.connect(("10.53.0.1", named_port))
+
+ time.sleep(1)
+
+ # Send and receive 25 DNS queries
+ for n in range(25):
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ for n in range(25):
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+
+ time.sleep(3)
+
+ # Send and receive 25 DNS queries
+ for n in range(25):
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ for n in range(25):
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+
+ time.sleep(6)
+
+ with pytest.raises(EOFError):
+ try:
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+ except ConnectionError as e:
+ raise EOFError from e
+
+
+def test_long_axfr(named_port):
+ #
+ # The timers should not fire during AXFR, thus the connection should not
+ # close abruptly
+ #
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ sock.connect(("10.53.0.1", named_port))
+
+ name = dns.name.from_text("example.")
+ msg = create_msg("example.", "AXFR")
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+
+ # Receive the initial DNS message with SOA
+ (response, rtime) = dns.query.receive_tcp(
+ sock, timeout(), one_rr_per_rrset=True
+ )
+ soa = response.get_rrset(
+ dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA
+ )
+ assert soa is not None
+
+ # Pull DNS message from wire until the second SOA is received
+ while True:
+ (response, rtime) = dns.query.receive_tcp(
+ sock, timeout(), one_rr_per_rrset=True
+ )
+ soa = response.get_rrset(
+ dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA
+ )
+ if soa is not None:
+ break
+ assert soa is not None
+
+
+@pytest_custom_markers.flaky(max_runs=3)
+def test_send_timeout(named_port):
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ sock.connect(("10.53.0.1", named_port))
+
+ # Send and receive single large RDATA over TCP
+ msg = create_msg("large.example.", "TXT")
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+
+ # Send and receive 28 large (~32k) DNS queries that should
+ # fill the default maximum 208k TCP send buffer
+ for n in range(28):
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+
+ # configure idle interval is 5 seconds, sleep 6 to make sure we are
+ # above the interval
+ time.sleep(6)
+
+ with pytest.raises(EOFError):
+ try:
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+ (response, rtime) = dns.query.receive_tcp(sock, timeout())
+ except ConnectionError as e:
+ raise EOFError from e
+
+
+@pytest_custom_markers.long_test
+def test_max_transfer_idle_out(named_port):
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ sock.connect(("10.53.0.1", named_port))
+
+ name = dns.name.from_text("example.")
+ msg = create_msg("example.", "AXFR")
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+
+ # Receive the initial DNS message with SOA
+ (response, rtime) = dns.query.receive_tcp(
+ sock, timeout(), one_rr_per_rrset=True
+ )
+ soa = response.get_rrset(
+ dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA
+ )
+ assert soa is not None
+
+ time.sleep(61) # max-transfer-idle-out is 1 minute
+
+ with pytest.raises(ConnectionResetError):
+ # Process queued TCP messages
+ while True:
+ (response, rtime) = dns.query.receive_tcp(
+ sock, timeout(), one_rr_per_rrset=True
+ )
+ soa = response.get_rrset(
+ dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA
+ )
+ if soa is not None:
+ break
+ assert soa is None
+
+
+@pytest_custom_markers.long_test
+def test_max_transfer_time_out(named_port):
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ sock.connect(("10.53.0.1", named_port))
+
+ name = dns.name.from_text("example.")
+ msg = create_msg("example.", "AXFR")
+ (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
+
+ # Receive the initial DNS message with SOA
+ (response, rtime) = dns.query.receive_tcp(
+ sock, timeout(), one_rr_per_rrset=True
+ )
+ soa = response.get_rrset(
+ dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA
+ )
+ assert soa is not None
+
+ # The loop should timeout at the 5 minutes (max-transfer-time-out)
+ with pytest.raises(EOFError):
+ while True:
+ time.sleep(1)
+ (response, rtime) = dns.query.receive_tcp(
+ sock, timeout(), one_rr_per_rrset=True
+ )
+ soa = response.get_rrset(
+ dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA
+ )
+ if soa is not None:
+ break
+ assert soa is None
diff --git a/bin/tests/system/tkey/clean.sh b/bin/tests/system/tkey/clean.sh
new file mode 100644
index 0000000..f5df065
--- /dev/null
+++ b/bin/tests/system/tkey/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f ./K*
+rm -f ./dig.out.*
+rm -f ./rndc.out.*
+rm -f ns*/K*
+rm -f ns*/_default.tsigkeys
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.conf
+rm -f ns*/named.conf-e
+rm -f ns*/named.lock
+rm -f ns*/named.memstats
+rm -f ns*/named.run
diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c
new file mode 100644
index 0000000..37f6e48
--- /dev/null
+++ b/bin/tests/system/tkey/keycreate.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/managers.h>
+#include <isc/mem.h>
+#include <isc/netmgr.h>
+#include <isc/nonce.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/dispatch.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/request.h>
+#include <dns/result.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+
+#define CHECK(str, x) \
+ { \
+ if ((x) != ISC_R_SUCCESS) { \
+ fprintf(stderr, "I:%s: %s\n", (str), \
+ isc_result_totext(x)); \
+ exit(-1); \
+ } \
+ }
+
+#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
+
+#define TIMEOUT 30
+
+static char *ip_address = NULL;
+static int port = 0;
+
+static dst_key_t *ourkey = NULL;
+static isc_mem_t *mctx = NULL;
+static dns_tsigkey_t *tsigkey = NULL, *initialkey = NULL;
+static dns_tsig_keyring_t *ring = NULL;
+static unsigned char noncedata[16];
+static isc_buffer_t nonce;
+static dns_requestmgr_t *requestmgr = NULL;
+static const char *ownername_str = ".";
+
+static void
+recvquery(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result;
+ dns_message_t *query = NULL, *response = NULL;
+ char keyname[256];
+ isc_buffer_t keynamebuf;
+ int type;
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "I:request event result: %s\n",
+ isc_result_totext(reqev->result));
+ exit(-1);
+ }
+
+ query = reqev->ev_arg;
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+
+ result = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ CHECK("dns_request_getresponse", result);
+
+ if (response->rcode != dns_rcode_noerror) {
+ result = dns_result_fromrcode(response->rcode);
+ fprintf(stderr, "I:response rcode: %s\n",
+ isc_result_totext(result));
+ exit(-1);
+ }
+
+ result = dns_tkey_processdhresponse(query, response, ourkey, &nonce,
+ &tsigkey, ring);
+ CHECK("dns_tkey_processdhresponse", result);
+
+ /*
+ * Yes, this is a hack.
+ */
+ isc_buffer_init(&keynamebuf, keyname, sizeof(keyname));
+ result = dst_key_buildfilename(tsigkey->key, 0, "", &keynamebuf);
+ CHECK("dst_key_buildfilename", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&keynamebuf),
+ (char *)isc_buffer_base(&keynamebuf));
+ type = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_KEY;
+ result = dst_key_tofile(tsigkey->key, type, "");
+ CHECK("dst_key_tofile", result);
+
+ dns_message_detach(&query);
+ dns_message_detach(&response);
+ dns_request_destroy(&reqev->request);
+ isc_event_free(&event);
+ isc_app_shutdown();
+ return;
+}
+
+static void
+sendquery(isc_task_t *task, isc_event_t *event) {
+ struct in_addr inaddr;
+ isc_sockaddr_t address;
+ isc_region_t r;
+ isc_result_t result;
+ dns_fixedname_t keyname;
+ dns_fixedname_t ownername;
+ isc_buffer_t namestr, keybuf;
+ unsigned char keydata[9];
+ dns_message_t *query = NULL;
+ dns_request_t *request = NULL;
+ static char keystr[] = "0123456789ab";
+
+ isc_event_free(&event);
+
+ result = ISC_R_FAILURE;
+ if (inet_pton(AF_INET, ip_address, &inaddr) != 1) {
+ CHECK("inet_pton", result);
+ }
+ isc_sockaddr_fromin(&address, &inaddr, port);
+
+ dns_fixedname_init(&keyname);
+ isc_buffer_constinit(&namestr, "tkeytest.", 9);
+ isc_buffer_add(&namestr, 9);
+ result = dns_name_fromtext(dns_fixedname_name(&keyname), &namestr, NULL,
+ 0, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ dns_fixedname_init(&ownername);
+ isc_buffer_constinit(&namestr, ownername_str, strlen(ownername_str));
+ isc_buffer_add(&namestr, strlen(ownername_str));
+ result = dns_name_fromtext(dns_fixedname_name(&ownername), &namestr,
+ NULL, 0, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ isc_buffer_init(&keybuf, keydata, 9);
+ result = isc_base64_decodestring(keystr, &keybuf);
+ CHECK("isc_base64_decodestring", result);
+
+ isc_buffer_usedregion(&keybuf, &r);
+
+ result = dns_tsigkey_create(
+ dns_fixedname_name(&keyname), DNS_TSIG_HMACMD5_NAME,
+ isc_buffer_base(&keybuf), isc_buffer_usedlength(&keybuf), false,
+ NULL, 0, 0, mctx, ring, &initialkey);
+ CHECK("dns_tsigkey_create", result);
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
+
+ result = dns_tkey_builddhquery(query, ourkey,
+ dns_fixedname_name(&ownername),
+ DNS_TSIG_HMACMD5_NAME, &nonce, 3600);
+ CHECK("dns_tkey_builddhquery", result);
+
+ result = dns_request_create(requestmgr, query, NULL, &address,
+ DNS_REQUESTOPT_TCP, initialkey, TIMEOUT, 0,
+ 0, task, recvquery, query, &request);
+ CHECK("dns_request_create", result);
+}
+
+int
+main(int argc, char *argv[]) {
+ char *ourkeyname = NULL;
+ isc_nm_t *netmgr = NULL;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_sockaddr_t bind_any;
+ dns_dispatchmgr_t *dispatchmgr = NULL;
+ dns_dispatch_t *dispatchv4 = NULL;
+ dns_view_t *view = NULL;
+ dns_tkeyctx_t *tctx = NULL;
+ isc_log_t *log = NULL;
+ isc_logconfig_t *logconfig = NULL;
+ isc_task_t *task = NULL;
+ isc_result_t result;
+ int type;
+
+ RUNCHECK(isc_app_start());
+
+ if (argc < 4) {
+ fprintf(stderr, "I:no DH key provided\n");
+ exit(-1);
+ }
+ ip_address = argv[1];
+ port = atoi(argv[2]);
+ ourkeyname = argv[3];
+
+ if (argc >= 5) {
+ ownername_str = argv[4];
+ }
+
+ isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+ isc_mem_create(&mctx);
+
+ isc_log_create(mctx, &log, &logconfig);
+
+ RUNCHECK(dst_lib_init(mctx, NULL));
+
+ isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr, NULL);
+
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
+
+ isc_sockaddr_any(&bind_any);
+ RUNCHECK(dns_dispatch_createudp(dispatchmgr, &bind_any, &dispatchv4));
+ RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4,
+ NULL, &requestmgr));
+
+ RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
+ RUNCHECK(dns_tkeyctx_create(mctx, &tctx));
+
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+ dns_view_setkeyring(view, ring);
+ dns_tsigkeyring_detach(&ring);
+
+ RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL));
+
+ type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
+ result = dst_key_fromnamedfile(ourkeyname, NULL, type, mctx, &ourkey);
+ CHECK("dst_key_fromnamedfile", result);
+
+ isc_buffer_init(&nonce, noncedata, sizeof(noncedata));
+ isc_nonce_buf(noncedata, sizeof(noncedata));
+ isc_buffer_add(&nonce, sizeof(noncedata));
+
+ (void)isc_app_run();
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+ dns_dispatch_detach(&dispatchv4);
+ dns_dispatchmgr_detach(&dispatchmgr);
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+ isc_managers_destroy(&netmgr, &taskmgr, NULL);
+
+ dst_key_free(&ourkey);
+ dns_tsigkey_detach(&initialkey);
+ dns_tsigkey_detach(&tsigkey);
+
+ dns_tkeyctx_destroy(&tctx);
+
+ dns_view_detach(&view);
+
+ isc_log_destroy(&log);
+
+ dst_lib_destroy();
+
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/system/tkey/keydelete.c b/bin/tests/system/tkey/keydelete.c
new file mode 100644
index 0000000..f653a18
--- /dev/null
+++ b/bin/tests/system/tkey/keydelete.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/managers.h>
+#include <isc/mem.h>
+#include <isc/netmgr.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/dispatch.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/request.h>
+#include <dns/result.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+
+#define CHECK(str, x) \
+ { \
+ if ((x) != ISC_R_SUCCESS) { \
+ fprintf(stderr, "I:%s: %s\n", (str), \
+ isc_result_totext(x)); \
+ exit(-1); \
+ } \
+ }
+
+#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
+
+#define TIMEOUT 30
+
+static char *ip_address = NULL;
+static int port;
+static isc_mem_t *mctx = NULL;
+static dns_tsigkey_t *tsigkey = NULL;
+static dns_tsig_keyring_t *ring = NULL;
+static dns_requestmgr_t *requestmgr = NULL;
+
+static void
+recvquery(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result;
+ dns_message_t *query = NULL, *response = NULL;
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "I:request event result: %s\n",
+ isc_result_totext(reqev->result));
+ exit(-1);
+ }
+
+ query = reqev->ev_arg;
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+
+ result = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ CHECK("dns_request_getresponse", result);
+
+ if (response->rcode != dns_rcode_noerror) {
+ result = dns_result_fromrcode(response->rcode);
+ fprintf(stderr, "I:response rcode: %s\n",
+ isc_result_totext(result));
+ exit(-1);
+ }
+
+ result = dns_tkey_processdeleteresponse(query, response, ring);
+ CHECK("dns_tkey_processdhresponse", result);
+
+ dns_message_detach(&query);
+ dns_message_detach(&response);
+ dns_request_destroy(&reqev->request);
+ isc_event_free(&event);
+ isc_app_shutdown();
+ return;
+}
+
+static void
+sendquery(isc_task_t *task, isc_event_t *event) {
+ struct in_addr inaddr;
+ isc_sockaddr_t address;
+ isc_result_t result;
+ dns_message_t *query = NULL;
+ dns_request_t *request = NULL;
+
+ isc_event_free(&event);
+
+ result = ISC_R_FAILURE;
+ if (inet_pton(AF_INET, ip_address, &inaddr) != 1) {
+ CHECK("inet_pton", result);
+ }
+ isc_sockaddr_fromin(&address, &inaddr, port);
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
+
+ result = dns_tkey_builddeletequery(query, tsigkey);
+ CHECK("dns_tkey_builddeletequery", result);
+
+ result = dns_request_create(requestmgr, query, NULL, &address,
+ DNS_REQUESTOPT_TCP, tsigkey, TIMEOUT, 0, 0,
+ task, recvquery, query, &request);
+ CHECK("dns_request_create", result);
+}
+
+int
+main(int argc, char **argv) {
+ char *keyname = NULL;
+ isc_nm_t *netmgr = NULL;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_sockaddr_t bind_any;
+ dns_dispatchmgr_t *dispatchmgr = NULL;
+ dns_dispatch_t *dispatchv4 = NULL;
+ dns_view_t *view = NULL;
+ dns_tkeyctx_t *tctx = NULL;
+ dst_key_t *dstkey = NULL;
+ isc_log_t *log = NULL;
+ isc_logconfig_t *logconfig = NULL;
+ isc_task_t *task = NULL;
+ isc_result_t result;
+ int type;
+
+ RUNCHECK(isc_app_start());
+
+ if (argc < 4) {
+ fprintf(stderr, "I:no key to delete\n");
+ exit(-1);
+ }
+ if (strcmp(argv[1], "-r") == 0) {
+ fprintf(stderr, "I:The -r options has been deprecated\n");
+ exit(-1);
+ }
+ ip_address = argv[1];
+ port = atoi(argv[2]);
+ keyname = argv[3];
+
+ isc_mem_create(&mctx);
+
+ isc_log_create(mctx, &log, &logconfig);
+
+ RUNCHECK(dst_lib_init(mctx, NULL));
+
+ isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr, NULL);
+
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
+ isc_sockaddr_any(&bind_any);
+ RUNCHECK(dns_dispatch_createudp(dispatchmgr, &bind_any, &dispatchv4));
+ RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4,
+ NULL, &requestmgr));
+
+ RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
+ RUNCHECK(dns_tkeyctx_create(mctx, &tctx));
+
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+ dns_view_setkeyring(view, ring);
+
+ RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL));
+
+ type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
+ result = dst_key_fromnamedfile(keyname, NULL, type, mctx, &dstkey);
+ CHECK("dst_key_fromnamedfile", result);
+ result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
+ DNS_TSIG_HMACMD5_NAME, dstkey, true,
+ NULL, 0, 0, mctx, ring, &tsigkey);
+ dst_key_free(&dstkey);
+ CHECK("dns_tsigkey_createfromkey", result);
+
+ (void)isc_app_run();
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+ dns_dispatch_detach(&dispatchv4);
+ dns_dispatchmgr_detach(&dispatchmgr);
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+ isc_managers_destroy(&netmgr, &taskmgr, NULL);
+
+ dns_tsigkeyring_detach(&ring);
+
+ dns_tsigkey_detach(&tsigkey);
+
+ dns_tkeyctx_destroy(&tctx);
+
+ dns_view_detach(&view);
+
+ isc_log_destroy(&log);
+
+ dst_lib_destroy();
+
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/system/tkey/ns1/example.db b/bin/tests/system/tkey/ns1/example.db
new file mode 100644
index 0000000..a847946
--- /dev/null
+++ b/bin/tests/system/tkey/ns1/example.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 1D
+
+@ IN SOA ns hostmaster (
+ 1
+ 3600
+ 1800
+ 1814400
+ 3
+ )
+ NS ns
+ns A 10.53.0.1
+mx MX 10 mail
+a A 10.53.0.1
+ A 10.53.0.2
+txt TXT "this is text"
+
diff --git a/bin/tests/system/tkey/ns1/named.conf.in b/bin/tests/system/tkey/ns1/named.conf.in
new file mode 100644
index 0000000..c5c372c
--- /dev/null
+++ b/bin/tests/system/tkey/ns1/named.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+controls { /* empty */ };
+
+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;
+ dnssec-validation no;
+ notify no;
+ tkey-domain "server";
+ tkey-dhkey "server" KEYID;
+ allow-query-cache { any; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key "tkeytest." {
+ algorithm hmac-md5;
+ secret "0123456789ab";
+};
+
+zone example {
+ type primary;
+ file "example.db";
+ allow-query { key tkeytest.; none; };
+};
diff --git a/bin/tests/system/tkey/ns1/setup.sh b/bin/tests/system/tkey/ns1/setup.sh
new file mode 100644
index 0000000..b283f73
--- /dev/null
+++ b/bin/tests/system/tkey/ns1/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../../conf.sh
+
+keyname=$($KEYGEN -T KEY -a DH -b 768 -n host server)
+keyid=$(keyfile_to_key_id "$keyname")
+sed -i -e "s;KEYID;$keyid;" named.conf
diff --git a/bin/tests/system/tkey/setup.sh b/bin/tests/system/tkey/setup.sh
new file mode 100644
index 0000000..bc6aa51
--- /dev/null
+++ b/bin/tests/system/tkey/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+
+cd ns1 && $SHELL setup.sh
diff --git a/bin/tests/system/tkey/tests.sh b/bin/tests/system/tkey/tests.sh
new file mode 100644
index 0000000..864542f
--- /dev/null
+++ b/bin/tests/system/tkey/tests.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+dig_with_opts() {
+ "$DIG" @10.53.0.1 -p "$PORT" "$@"
+}
+
+status=0
+n=1
+
+echo_i "generating new DH key ($n)"
+ret=0
+dhkeyname=$($KEYGEN -T KEY -a DH -b 768 -n host client) || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+ status=$((status+ret))
+ echo_i "exit status: $status"
+ exit $status
+fi
+status=$((status+ret))
+n=$((n+1))
+
+for owner in . foo.example.
+do
+ echo_i "creating new key using owner name \"$owner\" ($n)"
+ ret=0
+ keyname=$($KEYCREATE 10.53.0.1 "$PORT" "$dhkeyname" $owner) || ret=1
+ if [ $ret != 0 ]; then
+ echo_i "failed"
+ status=$((status+ret))
+ echo_i "exit status: $status"
+ exit $status
+ fi
+ status=$((status+ret))
+ n=$((n+1))
+
+ echo_i "checking the new key ($n)"
+ ret=0
+ dig_with_opts txt txt.example -k "$keyname" > dig.out.test$n || ret=1
+ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+ grep "TSIG.*hmac-md5.*NOERROR" dig.out.test$n > /dev/null || ret=1
+ grep "Some TSIG could not be validated" dig.out.test$n > /dev/null && ret=1
+ if [ $ret != 0 ]; then
+ echo_i "failed"
+ fi
+ status=$((status+ret))
+ n=$((n+1))
+
+ echo_i "deleting new key ($n)"
+ ret=0
+ $KEYDELETE 10.53.0.1 "$PORT" "$keyname" || ret=1
+ if [ $ret != 0 ]; then
+ echo_i "failed"
+ fi
+ status=$((status+ret))
+ n=$((n+1))
+
+ echo_i "checking that new key has been deleted ($n)"
+ ret=0
+ dig_with_opts txt txt.example -k "$keyname" > dig.out.test$n || ret=1
+ grep "status: NOERROR" dig.out.test$n > /dev/null && ret=1
+ grep "TSIG.*hmac-md5.*NOERROR" dig.out.test$n > /dev/null && ret=1
+ grep "Some TSIG could not be validated" dig.out.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]; then
+ echo_i "failed"
+ fi
+ status=$((status+ret))
+ n=$((n+1))
+done
+
+echo_i "creating new key using owner name bar.example. ($n)"
+ret=0
+keyname=$($KEYCREATE 10.53.0.1 "$PORT" "$dhkeyname" bar.example.) || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+ status=$((status+ret))
+ echo_i "exit status: $status"
+ exit $status
+fi
+status=$((status+ret))
+n=$((n+1))
+
+echo_i "checking the key with 'rndc tsig-list' ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p "$CONTROLPORT" tsig-list > rndc.out.test$n
+grep "key \"bar.example.server" rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+fi
+status=$((status+ret))
+n=$((n+1))
+
+echo_i "using key in a request ($n)"
+ret=0
+dig_with_opts -k "$keyname" txt.example txt > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+fi
+status=$((status+ret))
+n=$((n+1))
+
+echo_i "deleting the key with 'rndc tsig-delete' ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p "$CONTROLPORT" tsig-delete bar.example.server > /dev/null || ret=1
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p "$CONTROLPORT" tsig-list > rndc.out.test$n
+grep "key \"bar.example.server" rndc.out.test$n > /dev/null && ret=1
+dig_with_opts -k "$keyname" txt.example txt > dig.out.test$n || ret=1
+grep "TSIG could not be validated" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+fi
+status=$((status+ret))
+n=$((n+1))
+
+echo_i "recreating the bar.example. key ($n)"
+ret=0
+keyname=$($KEYCREATE 10.53.0.1 "$PORT" "$dhkeyname" bar.example.) || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+ status=$((status+ret))
+ echo_i "exit status: $status"
+ exit $status
+fi
+status=$((status+ret))
+n=$((n+1))
+
+echo_i "checking the new key with 'rndc tsig-list' ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p "$CONTROLPORT" tsig-list > rndc.out.test$n
+grep "key \"bar.example.server" rndc.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+fi
+status=$((status+ret))
+n=$((n+1))
+
+echo_i "using the new key in a request ($n)"
+ret=0
+dig_with_opts -k "$keyname" txt.example txt > dig.out.test$n || ret=1
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then
+ echo_i "failed"
+fi
+status=$((status+ret))
+n=$((n+1))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/tkey/tests_sh_tkey.py b/bin/tests/system/tkey/tests_sh_tkey.py
new file mode 100644
index 0000000..9a29490
--- /dev/null
+++ b/bin/tests/system/tkey/tests_sh_tkey.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_tkey(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/tools/clean.sh b/bin/tests/system/tools/clean.sh
new file mode 100644
index 0000000..32a8e97
--- /dev/null
+++ b/bin/tests/system/tools/clean.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f NSEC3
+rm -f nsec3hash
+rm -f nsec3param
+rm -f testcases
diff --git a/bin/tests/system/tools/setup.sh b/bin/tests/system/tools/setup.sh
new file mode 100644
index 0000000..b8ae3b4
--- /dev/null
+++ b/bin/tests/system/tools/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+$SHELL clean.sh
diff --git a/bin/tests/system/tools/tests.sh b/bin/tests/system/tools/tests.sh
new file mode 100644
index 0000000..a7113cb
--- /dev/null
+++ b/bin/tests/system/tools/tests.sh
@@ -0,0 +1,107 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+status=0
+
+checkout() {
+ rc=$1
+ case $rc in
+ 0) : ok ;;
+ *) echo_i "failed"
+ status=$((status + 1))
+ return 1 ;;
+ esac
+ case $out in
+ *$hash*) : ok ;;
+ *) echo_i "expect $hash"
+ echo_i "output $out"
+ echo_i "failed"
+ status=$((status + 1)) ;;
+ esac
+}
+
+# test cases taken from RFC 5155 appendix A
+algo=1 flags=0 iters=12 salt="aabbccdd"
+while read name hash
+do
+ echo_i "checking $NSEC3HASH $name"
+ { out=$($NSEC3HASH $salt $algo $iters $name); rc=$?; } || true
+ checkout $rc
+
+ echo_i "checking $NSEC3HASH -r $name"
+ { out=$($NSEC3HASH -r $algo $flags $iters $salt $name); rc=$?; } || true
+ checkout $rc
+
+done <<EOF
+*.w.example R53BQ7CC2UVMUBFU5OCMM6PERS9TK9EN
+2t7b4g4vsa5smi47k61mv5bv1a22bojr.example KOHAR7MBB8DC2CE8A9QVL8HON4K53UHI
+a.example 35MTHGPGCU1QG68FAB165KLNSNK3DPVL
+ai.example GJEQE526PLBF1G8MKLP59ENFD789NJGI
+example 0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM
+ns1.example 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR
+ns2.example Q04JKCEVQVMU85R014C7DKBA38O0JI5R
+w.example K8UDEMVP1J2F7EG6JEBPS17VP3N8I58H
+x.w.example B4UM86EGHHDS6NEA196SMVMLO4ORS995
+x.y.w.example 2VPTU5TIMAMQTTGL4LUU9KG21E0AOR3S
+xx.example T644EBQK9BIBCNA874GIVR6JOJ62MLHV
+y.w.example JI6NEOAEPV8B5O6K4EV33ABHA8HT9FGC
+EOF
+
+# test empty salt
+checkempty() {
+ rc=$1
+ hash=CK0POJMG874LJREF7EFN8430QVIT8BSM checkout $rc &&
+ hash=- checkout $rc
+}
+name=com algo=1 flags=1 iters=0
+echo_i "checking $NSEC3HASH '' $name"
+{ out=$($NSEC3HASH '' $algo $iters $name); rc=$?; } || true
+checkempty $rc
+echo_i "checking $NSEC3HASH - $name"
+{ out=$($NSEC3HASH - $algo $iters $name); rc=$?; } || true
+checkempty $rc
+echo_i "checking $NSEC3HASH -- '' $name"
+{ out=$($NSEC3HASH -- '' $algo $iters $name); rc=$?; } || true
+checkempty $rc
+echo_i "checking $NSEC3HASH -- - $name"
+{ out=$($NSEC3HASH -- - $algo $iters $name); rc=$?; } || true
+checkempty $rc
+echo_i "checking $NSEC3HASH -r '' $name"
+{ out=$($NSEC3HASH -r $algo $flags $iters '' $name); rc=$?; } || true
+checkempty $rc
+echo_i "checking $NSEC3HASH -r - $name"
+{ out=$($NSEC3HASH -r $algo $flags $iters - $name); rc=$?; } || true
+checkempty $rc
+
+checkfail() {
+ rc=$1
+ case $rc in
+ 0) echo_i "failed to fail"
+ status=$((status + 1))
+ return 1 ;;
+ esac
+}
+echo_i "checking $NSEC3HASH missing args"
+{ out=$($NSEC3HASH 00 1 0 2>&1); rc=$?; } || true
+checkfail $rc
+echo_i "checking $NSEC3HASH extra args"
+{ out=$($NSEC3HASH 00 1 0 two names 2>&1); rc=$?; } || true
+checkfail $rc
+echo_i "checking $NSEC3HASH bad option"
+{ out=$($NSEC3HASH -? 2>&1); rc=$?; } || true
+checkfail $rc
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/tools/tests_sh_tools.py b/bin/tests/system/tools/tests_sh_tools.py
new file mode 100644
index 0000000..319a0fe
--- /dev/null
+++ b/bin/tests/system/tools/tests_sh_tools.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_tools(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/transport-acl/clean.sh b/bin/tests/system/transport-acl/clean.sh
new file mode 100644
index 0000000..e8d1b95
--- /dev/null
+++ b/bin/tests/system/transport-acl/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f ./*/named.conf
+rm -f ./*/named.memstats
+rm -f ./*/named.run
+rm -f ./*/named.run.prev
+rm -f ./dig.out.*
+rm -f ./*/example.db
+rm -rf ./headers.*
diff --git a/bin/tests/system/transport-acl/ns1/named.conf.in b/bin/tests/system/transport-acl/ns1/named.conf.in
new file mode 100644
index 0000000..cf0ccd5
--- /dev/null
+++ b/bin/tests/system/transport-acl/ns1/named.conf.in
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+tls self-signed {
+ cert-file "../self-signed-cert.pem";
+ key-file "../self-signed-key.pem";
+};
+
+options {
+ pid-file "named.pid";
+ ##
+ # generic test
+ listen-on port @PORT@ { 10.53.0.1; };
+ listen-on port @TLSPORT@ tls self-signed { 10.53.0.1; };
+ # test #1
+ listen-on port @EXTRAPORT1@ { 10.53.0.1; };
+ listen-on port @EXTRAPORT1@ tls self-signed { 10.53.0.2; };
+ listen-on port @EXTRAPORT2@ { 10.53.0.1; };
+ listen-on port @EXTRAPORT2@ tls self-signed { 10.53.0.2; };
+ # test #2
+ listen-on port @EXTRAPORT1@ { 10.53.0.3; };
+ listen-on port @EXTRAPORT2@ { 10.53.0.3; };
+ listen-on port @EXTRAPORT1@ tls self-signed { 10.53.0.4; };
+ listen-on port @EXTRAPORT2@ tls self-signed { 10.53.0.4; };
+ # test #3
+ listen-on port @EXTRAPORT3@ tls self-signed { 10.53.0.3; };
+ listen-on port @EXTRAPORT4@ tls self-signed { 10.53.0.3; };
+ listen-on port @EXTRAPORT3@ { 10.53.0.4; };
+ listen-on port @EXTRAPORT4@ { 10.53.0.4; };
+ # test #4
+ listen-on port @EXTRAPORT1@ { 10.53.0.5; };
+ listen-on port @EXTRAPORT2@ { 10.53.0.5; };
+ listen-on port @EXTRAPORT1@ tls self-signed { 10.53.0.6; };
+ # test #5
+ listen-on port @EXTRAPORT3@ tls self-signed { 10.53.0.1; };
+ listen-on port @EXTRAPORT4@ tls self-signed { 10.53.0.1; };
+ listen-on port @EXTRAPORT3@ { 10.53.0.2; };
+ # test #6
+ listen-on port @EXTRAPORT5@ { 10.53.0.1; };
+ # test #7
+ listen-on port @EXTRAPORT6@ tls self-signed { 10.53.0.1; };
+ # test #7
+ listen-on port @EXTRAPORT7@ tls self-signed { 10.53.0.1; };
+ # test #8
+ listen-on port @EXTRAPORT8@ { 10.53.0.1; };
+ ##
+ listen-on-v6 { none; };
+ recursion no;
+ notify explicit;
+ statistics-file "named.stats";
+ dnssec-validation yes;
+ tcp-initial-timeout 1200;
+};
+
+zone "example0" {
+ type primary;
+ file "example.db";
+ allow-transfer port @TLSPORT@ transport tls { any; };
+};
+
+zone "example1" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT1@ { any; };
+};
+
+zone "example2" {
+ type primary;
+ file "example.db";
+ allow-transfer transport tcp { any; };
+};
+
+zone "example3" {
+ type primary;
+ file "example.db";
+ allow-transfer transport tls { any; };
+};
+
+zone "example4" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT1@ transport tcp { any; };
+};
+
+zone "example5" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT3@ transport tls { any; };
+};
+
+zone "example6" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT5@ transport tcp { 10.53.0.7; 10.53.0.8; 10.53.0.9; };
+};
+
+zone "example7" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT6@ transport tls { 10.53.0.7; 10.53.0.8; 10.53.0.9; };
+};
+
+zone "example8" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT7@ transport tls { 10.53.0.1; 10.53.0.2; 10.53.0.3; };
+};
+
+zone "example9" {
+ type primary;
+ file "example.db";
+ allow-transfer port @EXTRAPORT8@ transport tcp { 10.53.0.7; !10.53.0.8; 10.53.0.9; };
+};
diff --git a/bin/tests/system/transport-acl/self-signed-cert.pem b/bin/tests/system/transport-acl/self-signed-cert.pem
new file mode 100644
index 0000000..d569353
--- /dev/null
+++ b/bin/tests/system/transport-acl/self-signed-cert.pem
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIEwTCCAymgAwIBAgIUJm/nnhqH3omkx9PqEyewJhYg/sQwDQYJKoZIhvcNAQEL
+BQAwbzELMAkGA1UEBhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4G
+A1UEBwwHS2hhcmtpdjEMMAoGA1UECgwDSVNDMQ8wDQYDVQQLDAZTVy1FbmcxFTAT
+BgNVBAMMDHRlc3QuaXNjLm9yZzAgFw0yMTExMjkxMTQ0MDRaGA8yMTIxMTEzMDEx
+NDQwNFowbzELMAkGA1UEBhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQ
+MA4GA1UEBwwHS2hhcmtpdjEMMAoGA1UECgwDSVNDMQ8wDQYDVQQLDAZTVy1Fbmcx
+FTATBgNVBAMMDHRlc3QuaXNjLm9yZzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCC
+AYoCggGBAM8hzYSedQFajsjJKVnZ3BeWLOGULJO2ixQZ/vMnAk6q5a6JFST5DYVA
+G84S8GKzswZibNNuKJnuuQO3mBE2+Pioc+vxtewxlzbcQ2EaKgbx5IVezzHtQUYw
+WUUdSv7ViKOVeaI9jvXqpYUbbtLogSVkPB+/oWU1Wu4y/TkXc4wEqBxQx+P4kNnj
+stCP7r5HMkvBqQgmod5rjqLFohtIQbEhjSBaoK+td25vWUvfG/isduiKx52tC4k3
+CBnBOIfvgkNmJk5Rh3RufbiyBSCtgBcH3wp9VSByqC7roFQqzBkZm0aCmuggNmXb
+OXU7klEyVmAeiqLvfQSkjNsDmlaTsHCszgIB9RPA4f07KV62uFsdOu0K48yXBnEa
+nZeIFqwuTS+PU7T+SnWQGoJLDvCa6IPERqk+5j94BET84/z942WLVqSLlqAoa1rF
+5686m2Dgj10SRUpE99bmVg+HZRwO/ZbkLgu+tILqpYpnKP6n8FDpjW0Jnl77uw9S
+UeAvbGyw5QIDAQABo1MwUTAdBgNVHQ4EFgQUJV5YRDD9iF+uz9AFx5fA86CtlVQw
+HwYDVR0jBBgwFoAUJV5YRDD9iF+uz9AFx5fA86CtlVQwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAYEAi8sOMYGFs6n1C23vXorx5Zbbym5QkUVgYbxe
+9VaBy0Y/PgvXaxtz8zytbtFhyU5izXNZ7k8A4vnJ/TGxoIj503ArBMZj+CiwIBVI
+yMzheDp+MY4F19OIy/TsQglYeOEhK/PA9uj5GZYE1Ar6Qck4wl2vk3iaTMsaniyV
+zPqCiso2YDLISSvF3nvLcTQ8nX6JyYR/3J0t5biLcissPvubgzguoULRn2VwWw/7
+MaRXXPMTBTyCAylJrSgfBKvYmJcnHHocTAZkGElDaYHfALlR+5K9wi/QYwz3kFpN
+mS55yjSBlPPxH0rZw8fOdCLNbyzPjP+aXXoTUJa5/X7RNGKQTcuohektsuU1quxo
+lugrRYjhiytqBUek3qtBJfmX28LnfZHyKpDpHO6wykQS7FTWb69c6tvAzlwFbH7o
+onyhZz1Z2iXw4u7N4nTlj1VqHVMiEr2KUfxtOm5HQ7tZFSaWIA0HfIRB7WD3Escz
+DY3Bbu9bS711Yywp+NpvOqBSvMon
+-----END CERTIFICATE-----
diff --git a/bin/tests/system/transport-acl/self-signed-key.pem b/bin/tests/system/transport-acl/self-signed-key.pem
new file mode 100644
index 0000000..5d9748b
--- /dev/null
+++ b/bin/tests/system/transport-acl/self-signed-key.pem
@@ -0,0 +1,40 @@
+-----BEGIN PRIVATE KEY-----
+MIIG/AIBADANBgkqhkiG9w0BAQEFAASCBuYwggbiAgEAAoIBgQDPIc2EnnUBWo7I
+ySlZ2dwXlizhlCyTtosUGf7zJwJOquWuiRUk+Q2FQBvOEvBis7MGYmzTbiiZ7rkD
+t5gRNvj4qHPr8bXsMZc23ENhGioG8eSFXs8x7UFGMFlFHUr+1YijlXmiPY716qWF
+G27S6IElZDwfv6FlNVruMv05F3OMBKgcUMfj+JDZ47LQj+6+RzJLwakIJqHea46i
+xaIbSEGxIY0gWqCvrXdub1lL3xv4rHboisedrQuJNwgZwTiH74JDZiZOUYd0bn24
+sgUgrYAXB98KfVUgcqgu66BUKswZGZtGgproIDZl2zl1O5JRMlZgHoqi730EpIzb
+A5pWk7BwrM4CAfUTwOH9OyletrhbHTrtCuPMlwZxGp2XiBasLk0vj1O0/kp1kBqC
+Sw7wmuiDxEapPuY/eARE/OP8/eNli1aki5agKGtaxeevOptg4I9dEkVKRPfW5lYP
+h2UcDv2W5C4LvrSC6qWKZyj+p/BQ6Y1tCZ5e+7sPUlHgL2xssOUCAwEAAQKCAYAy
+VN9wy2RZKN0rUx5WNAc0QAy13+CZIDFZeBuokCESZpqbN7pImrA7YeGfyKBbC5mE
+AqS5F7qL9SNGEPXFsRr8qUpJ2hk/xKke7pT84nO17k9+TRSB6EoFOThn//86Pz8N
+qQO+dcDoZtVDq+/ZFiBTqrClclZQlo969C7uEZHFQ1hqUQLRlZP1LkxEO8VivUAu
+gmeFkIWi23X0fZuvj3ZPCX0WkI8dQUSVND95nURZv+bBCQAKg4MbG6E/SOFovrzz
+ohKK2zqSU+ncfWROYX/ulKMJKIhOKtxkprBnj2nSemTUEf5gDk9oDqsYClGmEcSL
+XvNxq3WpVt4u7Fsr1QZ6fh/IYIQnKvI/H0wwYojtzkh3FGdb/K0dnKeoebUqlc9Q
+4UwKGshhcbk2130t/zIdd5wnL5uj+xjh0cYSO5JqlcZwXC97SWDmEowCo8M/k8ie
+c9cQeIOXUKvT3DvnEh1LAtfI8gW3g9GVHad4k25dQ4ZSiyXsKL2+mOWn+4WmQx0C
+gcEA6UqykoDp2j6nfMA+5fEfNOplyXJMyTBxMoaFb+cO8P2qjjKOMyLJewXqW/3g
+wWaPcl3dGVCPaqmQxf+fDEarSkDxkroN02YaQy3xdAAZvoUDc00VKq9BFe3TZEuP
+7/sN3t3Ey7K5KVyKgh4cGPqSCCXrk3OPCyiRFxWa4wQAXuntT1iXkXGzXuoDPzCH
+xWRiM+z3se6PdoPXMbJhuL04b4CIUmHSrGbqtO5bi6IDOksIhaKMFs4c7escSF+7
+jj0zAoHBAONLPcUT9uhzMIXe9BBdRYms65G3VjsTbS8MC/QiR6nl5/evQb0hDp0G
+/tbLf9F9QVMA2onhK1mjafHFC4oVrwrLT+VZezKsQm3ICoqOFqxL+6dAu93A2dDA
+99YCc6pCrmagaDpA5tz1UwBwA77pl2aMV2g7iIe2p+hmL6dx6Tp8jN+Mu0KXViyT
+gPG9LITJQSu13EZgRukNnYu7+L2+NWfyGCbfCJ5/2qXmryjefoboR48sa8jZyUmQ
+rf/VAG3phwKBwDE/lqD82+E5tsvMHbsXAtp93Q0AtxsFwe/DnCm6YloXgsjP/Vro
+LhZtckMHPko1p3SiQgmVCyGeODTEOMQzqvda7GRoKIEHHeYurbkqSEUC+W5+yEgh
+hSDm+uhCV1l26z+wG1pRGWuU4JyFVLMlOmzD7I5NJ9ZYMwDni7H+50EiKvnEHwMS
+OKaByjutuAvAnEaP8N48GUcQn/4axSxlraNERAL4KaxBcazOYL8CbaIBswPbA63Q
+xySmrGrO4t4tJwKBwGITmnDKv5Tn930cimXxSUsyAWgcGypcpJVTdmj+zbuDCAg5
+aH1qoTqixR38K4hCqwhc6u/p6GHCgLmhU+xelOxsdGo7pUxlRjjGw72ruB7anpk5
+9pamW5aXXZnL7wr9wPFpr+/LB5M6jHk43HTpqLnIPwMsBSrCZ0uBpHh1T7U7/zGL
+MVZ3pOiRMWeeQHJ/wQ5SZ906N/7iMCQWlSuSwsq6jS9guABknP1PQC+7ag9edVpT
+SaMeTpvewSYOTCQhSwKBwEmZP/Jh76G3bETPSPcIyPB0vgYmYiAftmvtwHzUL14V
+dOfNbwXF6WiepSceLbw99LNpMwfRfKBGVDLRhKMqL7QR8ZKNew5AvfXVZ1yDNKu+
+/4hqFLUhsAARsfNofAzvKOtWmghVBzO9TauAyv3prFgjfvDkA+EZ2amDvXChkP/Q
+7ck2aIUu9Sr4kPTUigIRlu6c18QQiLobXC7yKx6GhEpJsh9xGHHDJqkG16l+u1ju
+bEd5UJArJoST5lff5y7MyQ==
+-----END PRIVATE KEY-----
diff --git a/bin/tests/system/transport-acl/setup.sh b/bin/tests/system/transport-acl/setup.sh
new file mode 100644
index 0000000..672a5b6
--- /dev/null
+++ b/bin/tests/system/transport-acl/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck disable=SC1091
+. ../conf.sh
+
+$SHELL clean.sh
+
+$SHELL "${TOP_SRCDIR}"/bin/tests/system/genzone.sh 2 > ns1/example.db
+
+copy_setports ns1/named.conf.in ns1/named.conf
diff --git a/bin/tests/system/transport-acl/tests.sh b/bin/tests/system/transport-acl/tests.sh
new file mode 100644
index 0000000..9bed02b
--- /dev/null
+++ b/bin/tests/system/transport-acl/tests.sh
@@ -0,0 +1,124 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck disable=SC1091
+. ../conf.sh
+
+dig_out_basename="dig.out.test"
+testing="testing allow-transfer transport ACL functionality"
+
+dig_with_opts() {
+ # shellcheck disable=SC2086
+ "$DIG" +noadd +nosea +nostat +noquest +nocmd "$@"
+}
+
+status=0
+n=0
+
+run_dig_test () {
+ test_message="$1"
+ shift
+ n=$((n+1))
+ echo_i "$test_message ($n)"
+ ret=0
+ dig_with_opts "$@" > "$dig_out_basename$n" || ret=1
+}
+
+run_dig_expect_axfr_success () {
+ run_dig_test "$@"
+ grep "; Transfer failed" "$dig_out_basename$n" > /dev/null && ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+}
+
+run_dig_expect_axfr_failure () {
+ run_dig_test "$@"
+ grep "; Transfer failed" "$dig_out_basename$n" > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status + ret))
+}
+
+# generic tests
+run_dig_expect_axfr_success "$testing for XoT" -p "${TLSPORT}" +tls -b 10.53.0.10 @10.53.0.1 axfr example0
+
+run_dig_expect_axfr_failure "$testing XFR via TCP (failure expected)" -p "${PORT}" +tcp -b 10.53.0.10 @10.53.0.1 axfr example0
+
+# 1. Test allow-transfer port X, transfer works with TCP and TLS on port X but not port Y.
+
+run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT1}" +tcp -b 10.53.0.10 @10.53.0.1 axfr example1
+
+run_dig_expect_axfr_success "$testing for XoT" -p "${EXTRAPORT1}" +tls -b 10.53.0.10 @10.53.0.2 axfr example1
+
+run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT2}" +tcp -b 10.53.0.10 @10.53.0.1 axfr example1
+
+run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT2}" +tls -b 10.53.0.10 @10.53.0.2 axfr example1
+
+# 2. Test allow-transfer transport tcp, transfer works with TCP on any port but not TLS.
+
+run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT1}" +tcp -b 10.53.0.10 @10.53.0.3 axfr example2
+
+run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT2}" +tcp -b 10.53.0.10 @10.53.0.3 axfr example2
+
+run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT1}" +tls -b 10.53.0.10 @10.53.0.4 axfr example2
+
+run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT2}" +tls -b 10.53.0.10 @10.53.0.4 axfr example2
+
+# 3. Test allow-transfer transport tls, transfer works with TLS on any port but not TCP.
+run_dig_expect_axfr_success "$testing for XoT" -p "${EXTRAPORT3}" +tls -b 10.53.0.10 @10.53.0.3 axfr example3
+
+run_dig_expect_axfr_success "$testing for XoT" -p "${EXTRAPORT4}" +tls -b 10.53.0.10 @10.53.0.3 axfr example3
+
+run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT3}" +tcp -b 10.53.0.10 @10.53.0.4 axfr example3
+
+run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT4}" +tcp -b 10.53.0.10 @10.53.0.4 axfr example3
+
+# 4. Test allow-transfer port X transport tcp, transfer works with TCP on port X but not port Y and not with TLS on port X.
+
+run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT1}" +tcp -b 10.53.0.10 @10.53.0.5 axfr example4
+
+run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT2}" +tcp -b 10.53.0.10 @10.53.0.5 axfr example4
+
+run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT1}" +tls -b 10.53.0.10 @10.53.0.6 axfr example4
+
+# 5. Test allow-transfer port X transport tls, transfer works with TLS on port X but not port Y and not with TCP on port X.
+
+run_dig_expect_axfr_success "$testing for XoT" -p "${EXTRAPORT3}" +tls -b 10.53.0.10 @10.53.0.1 axfr example5
+
+run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT4}" +tls -b 10.53.0.10 @10.53.0.1 axfr example5
+
+run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT3}" +tcp -b 10.53.0.10 @10.53.0.2 axfr example5
+
+# 6. Test with multiple allow-transfer available, first ACL is a match.
+run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT5}" +tcp -b 10.53.0.7 @10.53.0.1 axfr example6
+
+run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT5}" +tcp -b 10.53.0.6 @10.53.0.1 axfr example6
+
+# 7. Test with multiple allow-transfer available, last ACL is a match.
+run_dig_expect_axfr_success "$testing for XoT" -p "${EXTRAPORT6}" +tls -b 10.53.0.9 @10.53.0.1 axfr example7
+
+run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT6}" +tls -b 10.53.0.6 @10.53.0.1 axfr example7
+
+# 8. Test with multiple allow-transfer available, no ACL is a match.
+run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT7}" +tls -b 10.53.0.7 @10.53.0.1 axfr example8
+
+# 9. Test with multiple allow-transfer available, negated ACL is used.
+run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT8}" +tcp -b 10.53.0.7 @10.53.0.1 axfr example9
+
+run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT8}" +tcp -b 10.53.0.8 @10.53.0.1 axfr example9
+
+run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT8}" +tcp -b 10.53.0.9 @10.53.0.1 axfr example9
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/transport-acl/tests_sh_transport_acl.py b/bin/tests/system/transport-acl/tests_sh_transport_acl.py
new file mode 100644
index 0000000..400c859
--- /dev/null
+++ b/bin/tests/system/transport-acl/tests_sh_transport_acl.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_transport_acl(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/tsig/ans2/ans.pl b/bin/tests/system/tsig/ans2/ans.pl
new file mode 100644
index 0000000..09ab29b
--- /dev/null
+++ b/bin/tests/system/tsig/ans2/ans.pl
@@ -0,0 +1,52 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# An adhoc server that returns a TC=1 response with the final byte
+# removed to generate UNEXPECTEDEND form dns_message_parse.
+#
+
+use IO::File;
+use IO::Socket;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+printf "localport %u\n", $localport;
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.2",
+ LocalPort => $localport, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+sub arraystring {
+ my $string = join("", @_);
+ return $string;
+}
+
+for (;;) {
+ $from = $sock->recv($buf, 512);
+ ($port, $ip_address) = unpack_sockaddr_in($from);
+ $l = length($buf);
+ printf "received %u bytes from %s#%u\n", $l, inet_ntoa($ip_address), $port;
+ @up = unpack("C[$l]", $buf);
+ $up[2] |= 0x80; # QR
+ $up[2] |= 0x02; # TC
+ $up[3] |= 0x80; # RA
+ $l -= 1; # truncate the response 1 byte
+ $replydata = pack("C[$l]", @up);
+ printf "sent %u bytes\n", $sock->send($replydata);
+}
diff --git a/bin/tests/system/tsig/badlocation b/bin/tests/system/tsig/badlocation
new file mode 100644
index 0000000..4477423
--- /dev/null
+++ b/bin/tests/system/tsig/badlocation
@@ -0,0 +1,37 @@
+# Transaction ID
+1122
+# Standard query
+0000
+# Questions: 1, Additional: 1
+0001 0000 0001 0000
+# QNAME: isc.org
+03 69 73 63 03 6F 72 67 00
+# Type: A (Host Address)
+0001
+# Class: IN
+0001
+# Specially crafted TSIG Resource Record
+# Name: "sha256"
+06 73 68 61 32 35 36 00
+# Type: TSIG (Transaction Signature)
+00fa
+# Class: ANY
+00ff
+# TTL: 0
+00000000
+# RdLen: 29
+001d
+# Algorithm Name: hmac-sha256
+0b 68 6D 61 63 2D 73 68 61 32 35 36 00
+# Time Signed: Jan 1, 1970 01:00:00.000000000 CET
+00 00 00 00 00 00
+# Fudge: 300
+012c
+# MAC Size: 0; MAC: empty
+0000
+# Original ID: 0
+0000
+# Error: no error
+0000
+# Other Data Length: 0
+0000
diff --git a/bin/tests/system/tsig/badtime b/bin/tests/system/tsig/badtime
new file mode 100644
index 0000000..7926404
--- /dev/null
+++ b/bin/tests/system/tsig/badtime
@@ -0,0 +1,37 @@
+# Transaction ID
+1122
+# Standard query
+0000
+# Questions: 1, Additional: 1
+0001 0000 0000 0001
+# QNAME: isc.org
+03 69 73 63 03 6F 72 67 00
+# Type: A (Host Address)
+0001
+# Class: IN
+0001
+# Specially crafted TSIG Resource Record
+# Name: "sha256"
+06 73 68 61 32 35 36 00
+# Type: TSIG (Transaction Signature)
+00fa
+# Class: ANY
+00ff
+# TTL: 0
+00000000
+# RdLen: 29
+001d
+# Algorithm Name: hmac-sha256
+0b 68 6D 61 63 2D 73 68 61 32 35 36 00
+# Time Signed: Jan 1, 1970 01:00:00.000000000 CET
+00 00 00 00 00 00
+# Fudge: 300
+012c
+# MAC Size: 0; MAC: empty
+0000
+# Original ID: 0
+0000
+# Error: BADSIG
+0010
+# Other Data Length: 0
+0000
diff --git a/bin/tests/system/tsig/clean.sh b/bin/tests/system/tsig/clean.sh
new file mode 100644
index 0000000..b173ffe
--- /dev/null
+++ b/bin/tests/system/tsig/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after tsig tests.
+#
+
+rm -f dig.out.*
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f Kexample.net.*
+rm -f keygen.out?
+rm -f ns*/managed-keys.bind*
+rm -f packet.out
diff --git a/bin/tests/system/tsig/ns1/example.db b/bin/tests/system/tsig/ns1/example.db
new file mode 100644
index 0000000..7854613
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/example.db
@@ -0,0 +1,163 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example.nil IN SOA ns1.example.nil. hostmaster.example.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example.nil. NS ns1.example.nil.
+ns1.example.nil. A 10.53.0.1
+example.nil. NS ns2.example.nil.
+ns2.example.nil. A 10.53.0.2
+
+$ORIGIN example.nil.
+* MX 10 mail
+a TXT "foo foo foo"
+ PTR foo.net.
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" ":(.*):\\1:" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.nil.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.nil.
+ns A 73.80.65.49
+$ORIGIN example.nil.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.nil.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.nil.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
+large TXT ( 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890 )
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-md5-legacy.+157+22023.key b/bin/tests/system/tsig/ns1/legacy/Khmac-md5-legacy.+157+22023.key
new file mode 100644
index 0000000..37ee8ae
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-md5-legacy.+157+22023.key
@@ -0,0 +1 @@
+hmac-md5-legacy. IN KEY 0 3 157 B7HCXJs0XnSPzypG5oHuGw==
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-md5-legacy.+157+22023.private b/bin/tests/system/tsig/ns1/legacy/Khmac-md5-legacy.+157+22023.private
new file mode 100644
index 0000000..8b2f435
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-md5-legacy.+157+22023.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 157 (HMAC_MD5)
+Key: B7HCXJs0XnSPzypG5oHuGw==
+Bits: AAA=
+Created: 20230619071002
+Publish: 20230619071002
+Activate: 20230619071002
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-sha1-legacy.+161+50591.key b/bin/tests/system/tsig/ns1/legacy/Khmac-sha1-legacy.+161+50591.key
new file mode 100644
index 0000000..bd1445d
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-sha1-legacy.+161+50591.key
@@ -0,0 +1 @@
+hmac-sha1-legacy. IN KEY 0 3 161 TxGx9XBp6Pp5yYAOKXdERA==
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-sha1-legacy.+161+50591.private b/bin/tests/system/tsig/ns1/legacy/Khmac-sha1-legacy.+161+50591.private
new file mode 100644
index 0000000..fe3d7ec
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-sha1-legacy.+161+50591.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 161 (HMAC_SHA1)
+Key: TxGx9XBp6Pp5yYAOKXdERA==
+Bits: AAA=
+Created: 20230619071031
+Publish: 20230619071031
+Activate: 20230619071031
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-sha224-legacy.+162+50865.key b/bin/tests/system/tsig/ns1/legacy/Khmac-sha224-legacy.+162+50865.key
new file mode 100644
index 0000000..c849be9
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-sha224-legacy.+162+50865.key
@@ -0,0 +1 @@
+hmac-sha224-legacy. IN KEY 0 3 162 H8Hyw718rLqToQFRLAeFWQ==
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-sha224-legacy.+162+50865.private b/bin/tests/system/tsig/ns1/legacy/Khmac-sha224-legacy.+162+50865.private
new file mode 100644
index 0000000..a2f31ec
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-sha224-legacy.+162+50865.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 162 (HMAC_SHA224)
+Key: H8Hyw718rLqToQFRLAeFWQ==
+Bits: AAA=
+Created: 20230619071136
+Publish: 20230619071136
+Activate: 20230619071136
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-sha256-legacy.+163+38999.key b/bin/tests/system/tsig/ns1/legacy/Khmac-sha256-legacy.+163+38999.key
new file mode 100644
index 0000000..1bbb6f0
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-sha256-legacy.+163+38999.key
@@ -0,0 +1 @@
+hmac-sha256-legacy. IN KEY 0 3 163 fdT9hiPov4ThMEfRv1FNmA==
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-sha256-legacy.+163+38999.private b/bin/tests/system/tsig/ns1/legacy/Khmac-sha256-legacy.+163+38999.private
new file mode 100644
index 0000000..0b209c6
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-sha256-legacy.+163+38999.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 163 (HMAC_SHA256)
+Key: fdT9hiPov4ThMEfRv1FNmA==
+Bits: AAA=
+Created: 20230619071043
+Publish: 20230619071043
+Activate: 20230619071043
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-sha384-legacy.+164+56610.key b/bin/tests/system/tsig/ns1/legacy/Khmac-sha384-legacy.+164+56610.key
new file mode 100644
index 0000000..46fae39
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-sha384-legacy.+164+56610.key
@@ -0,0 +1 @@
+hmac-sha384-legacy. IN KEY 0 3 164 fnshFIjQTLFap6+j2JGBkA==
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-sha384-legacy.+164+56610.private b/bin/tests/system/tsig/ns1/legacy/Khmac-sha384-legacy.+164+56610.private
new file mode 100644
index 0000000..be5aa12
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-sha384-legacy.+164+56610.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 164 (HMAC_SHA384)
+Key: fnshFIjQTLFap6+j2JGBkA==
+Bits: AAA=
+Created: 20230619071109
+Publish: 20230619071109
+Activate: 20230619071109
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-sha512-legacy.+165+22767.key b/bin/tests/system/tsig/ns1/legacy/Khmac-sha512-legacy.+165+22767.key
new file mode 100644
index 0000000..0defc84
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-sha512-legacy.+165+22767.key
@@ -0,0 +1 @@
+hmac-sha512-legacy. IN KEY 0 3 165 BZwNLICp2tj4hi6gil41eg==
diff --git a/bin/tests/system/tsig/ns1/legacy/Khmac-sha512-legacy.+165+22767.private b/bin/tests/system/tsig/ns1/legacy/Khmac-sha512-legacy.+165+22767.private
new file mode 100644
index 0000000..21268e5
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/legacy/Khmac-sha512-legacy.+165+22767.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.3
+Algorithm: 165 (HMAC_SHA512)
+Key: BZwNLICp2tj4hi6gil41eg==
+Bits: AAA=
+Created: 20230619071124
+Publish: 20230619071124
+Activate: 20230619071124
diff --git a/bin/tests/system/tsig/ns1/named.conf.in b/bin/tests/system/tsig/ns1/named.conf.in
new file mode 100644
index 0000000..de16ccf
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/named.conf.in
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+};
+
+# md5 key appended by setup.sh at the end
+
+key "sha1" {
+ secret "FrSt77yPTFx6hTs4i2tKLB9LmE0=";
+ algorithm hmac-sha1;
+};
+
+key "sha224" {
+ secret "hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA==";
+ algorithm hmac-sha224;
+};
+
+key "sha256" {
+ secret "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY=";
+ algorithm hmac-sha256;
+};
+
+key "sha384" {
+ secret "OaDdoAk2LAcLtYeUnsT7A9XHjsb6ZEma7OCvUpMraQIJX6HetGrlKmF7yglO1G2h";
+ algorithm hmac-sha384;
+};
+
+key "sha512" {
+ secret "jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4fe6Uasc0ckctEmg==";
+ algorithm hmac-sha512;
+};
+
+# hmac-md5-legacy key appended by setup.sh at the end
+
+key "hmac-sha1-legacy" {
+ algorithm "hmac-sha1";
+ secret "TxGx9XBp6Pp5yYAOKXdERA==";
+};
+
+key "hmac-sha224-legacy" {
+ algorithm "hmac-sha224";
+ secret "H8Hyw718rLqToQFRLAeFWQ==";
+};
+
+key "hmac-sha256-legacy" {
+ algorithm "hmac-sha256";
+ secret "fdT9hiPov4ThMEfRv1FNmA==";
+};
+
+key "hmac-sha384-legacy" {
+ algorithm "hmac-sha384";
+ secret "fnshFIjQTLFap6+j2JGBkA==";
+};
+
+key "hmac-sha512-legacy" {
+ algorithm "hmac-sha512";
+ secret "BZwNLICp2tj4hi6gil41eg==";
+};
+
+# md5-trunc key appended by setup.sh at the end
+
+key "sha1-trunc" {
+ secret "FrSt77yPTFx6hTs4i2tKLB9LmE0=";
+ algorithm hmac-sha1-80;
+};
+
+key "sha224-trunc" {
+ secret "hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA==";
+ algorithm hmac-sha224-112;
+};
+
+key "sha256-trunc" {
+ secret "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY=";
+ algorithm hmac-sha256-128;
+};
+
+key "sha384-trunc" {
+ secret "OaDdoAk2LAcLtYeUnsT7A9XHjsb6ZEma7OCvUpMraQIJX6HetGrlKmF7yglO1G2h";
+ algorithm hmac-sha384-192;
+};
+
+key "sha512-trunc" {
+ secret "jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4fe6Uasc0ckctEmg==";
+ algorithm hmac-sha512-256;
+};
+
+zone "example.nil" {
+ type primary;
+ file "example.db";
+};
+
+server 10.53.0.2 {
+ keys sha256;
+};
+
+zone "bad-tsig" {
+ type forward;
+ forwarders { 10.53.0.2; };
+ forward only;
+};
diff --git a/bin/tests/system/tsig/setup.sh b/bin/tests/system/tsig/setup.sh
new file mode 100644
index 0000000..d8dbbe3
--- /dev/null
+++ b/bin/tests/system/tsig/setup.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+
+if $FEATURETEST --md5
+then
+ cat >> ns1/named.conf << EOF
+# Conditionally included when support for MD5 is available
+key "md5" {
+ secret "97rnFx24Tfna4mHPfgnerA==";
+ algorithm hmac-md5;
+};
+
+key "hmac-md5-legacy" {
+ algorithm "hmac-md5";
+ secret "B7HCXJs0XnSPzypG5oHuGw==";
+};
+
+key "md5-trunc" {
+ secret "97rnFx24Tfna4mHPfgnerA==";
+ algorithm hmac-md5-80;
+};
+EOF
+fi
diff --git a/bin/tests/system/tsig/tests.sh b/bin/tests/system/tsig/tests.sh
new file mode 100644
index 0000000..68c5b6d
--- /dev/null
+++ b/bin/tests/system/tsig/tests.sh
@@ -0,0 +1,322 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+
+#
+# Shared secrets.
+#
+md5="97rnFx24Tfna4mHPfgnerA=="
+sha1="FrSt77yPTFx6hTs4i2tKLB9LmE0="
+sha224="hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA=="
+sha256="R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY="
+sha384="OaDdoAk2LAcLtYeUnsT7A9XHjsb6ZEma7OCvUpMraQIJX6HetGrlKmF7yglO1G2h"
+sha512="jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4fe6Uasc0ckctEmg=="
+
+status=0
+
+if $FEATURETEST --md5
+then
+ echo_i "fetching using hmac-md5 (old form)"
+ ret=0
+ $DIG $DIGOPTS example.nil. -y "md5:$md5" @10.53.0.1 soa > dig.out.md5.old || ret=1
+ grep -i "md5.*TSIG.*NOERROR" dig.out.md5.old > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+ fi
+
+ echo_i "fetching using hmac-md5 (new form)"
+ ret=0
+ $DIG $DIGOPTS example.nil. -y "hmac-md5:md5:$md5" @10.53.0.1 soa > dig.out.md5.new || ret=1
+ grep -i "md5.*TSIG.*NOERROR" dig.out.md5.new > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+ fi
+else
+ echo_i "skipping using hmac-md5"
+fi
+
+echo_i "fetching using hmac-sha1"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha1:sha1:$sha1" @10.53.0.1 soa > dig.out.sha1 || ret=1
+grep -i "sha1.*TSIG.*NOERROR" dig.out.sha1 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha224"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha224:sha224:$sha224" @10.53.0.1 soa > dig.out.sha224 || ret=1
+grep -i "sha224.*TSIG.*NOERROR" dig.out.sha224 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha256"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha256:sha256:$sha256" @10.53.0.1 soa > dig.out.sha256 || ret=1
+grep -i "sha256.*TSIG.*NOERROR" dig.out.sha256 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha384"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha384:sha384:$sha384" @10.53.0.1 soa > dig.out.sha384 || ret=1
+grep -i "sha384.*TSIG.*NOERROR" dig.out.sha384 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha512"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha512:sha512:$sha512" @10.53.0.1 soa > dig.out.sha512 || ret=1
+grep -i "sha512.*TSIG.*NOERROR" dig.out.sha512 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+#
+#
+# Truncated TSIG
+#
+#
+if $FEATURETEST --md5
+then
+ echo_i "fetching using hmac-md5 (trunc)"
+ ret=0
+ $DIG $DIGOPTS example.nil. -y "hmac-md5-80:md5-trunc:$md5" @10.53.0.1 soa > dig.out.md5.trunc || ret=1
+ grep -i "md5-trunc.*TSIG.*NOERROR" dig.out.md5.trunc > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+ fi
+else
+ echo_i "skipping using hmac-md5 (trunc)"
+fi
+
+echo_i "fetching using hmac-sha1 (trunc)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha1-80:sha1-trunc:$sha1" @10.53.0.1 soa > dig.out.sha1.trunc || ret=1
+grep -i "sha1.*TSIG.*NOERROR" dig.out.sha1.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha224 (trunc)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha224-112:sha224-trunc:$sha224" @10.53.0.1 soa > dig.out.sha224.trunc || ret=1
+grep -i "sha224-trunc.*TSIG.*NOERROR" dig.out.sha224.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha256 (trunc)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha256-128:sha256-trunc:$sha256" @10.53.0.1 soa > dig.out.sha256.trunc || ret=1
+grep -i "sha256-trunc.*TSIG.*NOERROR" dig.out.sha256.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha384 (trunc)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha384-192:sha384-trunc:$sha384" @10.53.0.1 soa > dig.out.sha384.trunc || ret=1
+grep -i "sha384-trunc.*TSIG.*NOERROR" dig.out.sha384.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha512-256 (trunc)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha512-256:sha512-trunc:$sha512" @10.53.0.1 soa > dig.out.sha512.trunc || ret=1
+grep -i "sha512-trunc.*TSIG.*NOERROR" dig.out.sha512.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+
+#
+#
+# Check for bad truncation.
+#
+#
+if $FEATURETEST --md5
+then
+ echo_i "fetching using hmac-md5-80 (BADTRUNC)"
+ ret=0
+ $DIG $DIGOPTS example.nil. -y "hmac-md5-80:md5:$md5" @10.53.0.1 soa > dig.out.md5-80 || ret=1
+ grep -i "md5.*TSIG.*BADTRUNC" dig.out.md5-80 > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+ fi
+else
+ echo_i "skipping using hmac-md5-80 (BADTRUNC)"
+fi
+
+echo_i "fetching using hmac-sha1-80 (BADTRUNC)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha1-80:sha1:$sha1" @10.53.0.1 soa > dig.out.sha1-80 || ret=1
+grep -i "sha1.*TSIG.*BADTRUNC" dig.out.sha1-80 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha224-112 (BADTRUNC)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha224-112:sha224:$sha224" @10.53.0.1 soa > dig.out.sha224-112 || ret=1
+grep -i "sha224.*TSIG.*BADTRUNC" dig.out.sha224-112 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha256-128 (BADTRUNC)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha256-128:sha256:$sha256" @10.53.0.1 soa > dig.out.sha256-128 || ret=1
+grep -i "sha256.*TSIG.*BADTRUNC" dig.out.sha256-128 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha384-192 (BADTRUNC)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha384-192:sha384:$sha384" @10.53.0.1 soa > dig.out.sha384-192 || ret=1
+grep -i "sha384.*TSIG.*BADTRUNC" dig.out.sha384-192 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha512-256 (BADTRUNC)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha512-256:sha512:$sha512" @10.53.0.1 soa > dig.out.sha512-256 || ret=1
+grep -i "sha512.*TSIG.*BADTRUNC" dig.out.sha512-256 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "attempting fetch with bad tsig algorithm"
+ret=0
+$DIG $DIGOPTS example.nil. -y "badalgo:invalid:$sha512" @10.53.0.1 soa > dig.out.badalgo 2>&1 || ret=1
+grep -i "Couldn't create key invalid: algorithm is unsupported" dig.out.badalgo > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "checking both OPT and TSIG records are returned when TC=1"
+ret=0
+$DIG -p ${PORT} +ignore +bufsize=512 large.example.nil -y "hmac-sha1:sha1:$sha1" @10.53.0.1 txt > dig.out.large 2>&1 || ret=1
+grep "flags:.* tc[ ;]" dig.out.large > /dev/null || ret=1
+grep "status: NOERROR" dig.out.large > /dev/null || ret=1
+grep "EDNS:" dig.out.large > /dev/null || ret=1
+grep -i "sha1.*TSIG.*NOERROR" dig.out.sha1 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "check that dnssec-keygen won't generate TSIG keys"
+ret=0
+$KEYGEN -a hmac-sha256 -b 128 -n host example.net > keygen.out3 2>&1 && ret=1
+grep "unknown algorithm" keygen.out3 > /dev/null || ret=1
+
+echo_i "check that a 'BADTIME' response with 'QR=0' is handled as a request"
+ret=0
+$PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp < badtime > /dev/null || ret=1
+$DIG -p ${PORT} @10.53.0.1 version.bind txt ch > dig.out.verify || ret=1
+grep "status: NOERROR" dig.out.verify > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+if "$PERL" -e 'use Net::DNS; use Net::DNS::Packet;' > /dev/null 2>&1
+then
+ echo_i "check that TSIG in the wrong place returns FORMERR"
+ ret=0
+ $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t udp -d < badlocation > packet.out
+ grep "rcode = FORMERR" packet.out > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+ fi
+fi
+
+echo_i "check that a malformed truncated response to a TSIG query is handled"
+ret=0
+$DIG -p $PORT @10.53.0.1 bad-tsig > dig.out.bad-tsig || ret=1
+grep "status: SERVFAIL" dig.out.bad-tsig > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+if $FEATURETEST --md5
+then
+ echo_i "fetching using hmac-md5 (legacy)"
+ ret=0
+ $DIG $DIGOPTS example.nil. -k ns1/legacy/Khmac-md5-legacy.+*.key @10.53.0.1 soa > dig.out.md5.legacy 2>&1 || ret=1
+ grep -i "md5.*TSIG.*NOERROR" dig.out.md5.legacy > /dev/null || ret=1
+ grep "Use of K\* file pairs for HMAC is deprecated" dig.out.md5.legacy > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+ fi
+else
+ echo_i "skipping using hmac-md5"
+fi
+
+echo_i "fetching using hmac-sha1 (legacy)"
+ret=0
+$DIG $DIGOPTS example.nil. -k ns1/legacy/Khmac-sha1-legacy.+*.key @10.53.0.1 soa > dig.out.sha1.legacy 2>&1 || ret=1
+grep -i "sha1.*TSIG.*NOERROR" dig.out.sha1.legacy > /dev/null || ret=1
+grep "Use of K\* file pairs for HMAC is deprecated" dig.out.sha1.legacy > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha224 (legacy)"
+ret=0
+$DIG $DIGOPTS example.nil. -k ns1/legacy/Khmac-sha224-legacy.+*.key @10.53.0.1 soa > dig.out.sha224 2>&1 || ret=1
+grep -i "sha224.*TSIG.*NOERROR" dig.out.sha224 > /dev/null || ret=1
+grep "Use of K\* file pairs for HMAC is deprecated" dig.out.sha224 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha256 (legacy)"
+ret=0
+$DIG $DIGOPTS example.nil. -k ns1/legacy/Khmac-sha256-legacy.*.key @10.53.0.1 soa > dig.out.sha256 2>&1 || ret=1
+grep -i "sha256.*TSIG.*NOERROR" dig.out.sha256 > /dev/null || ret=1
+grep "Use of K\* file pairs for HMAC is deprecated" dig.out.sha256 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha384 (legacy)"
+ret=0
+$DIG $DIGOPTS example.nil. -k ns1/legacy/Khmac-sha384-legacy.*.key @10.53.0.1 soa > dig.out.sha384 2>&1 || ret=1
+grep -i "sha384.*TSIG.*NOERROR" dig.out.sha384 > /dev/null || ret=1
+grep "Use of K\* file pairs for HMAC is deprecated" dig.out.sha384 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha512 (legacy)"
+ret=0
+$DIG $DIGOPTS example.nil. -k ns1/legacy/Khmac-sha512-legacy.*.key @10.53.0.1 soa > dig.out.sha512 2>&1 || ret=1
+grep "Use of K\* file pairs for HMAC is deprecated" dig.out.sha512 > /dev/null || ret=1
+grep -i "sha512.*TSIG.*NOERROR" dig.out.sha512 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/tsig/tests_sh_tsig.py b/bin/tests/system/tsig/tests_sh_tsig.py
new file mode 100644
index 0000000..b421852
--- /dev/null
+++ b/bin/tests/system/tsig/tests_sh_tsig.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_tsig(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/tsiggss/authsock.pl b/bin/tests/system/tsiggss/authsock.pl
new file mode 100644
index 0000000..4c76bf8
--- /dev/null
+++ b/bin/tests/system/tsiggss/authsock.pl
@@ -0,0 +1,91 @@
+#!/usr/bin/env perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# test the update-policy external protocol
+
+require 5.6.0;
+
+use IO::Socket::UNIX;
+use Getopt::Long;
+
+my $path;
+my $typeallowed = "A";
+my $pidfile = "authsock.pid";
+my $timeout = 0;
+
+GetOptions("path=s" => \$path,
+ "type=s" => \$typeallowed,
+ "pidfile=s" => \$pidfile,
+ "timeout=i" => \$timeout);
+
+if (!defined($path)) {
+ print("Usage: authsock.pl --path=<sockpath> --type=type --pidfile=pidfile\n");
+ exit(1);
+}
+
+unlink($path);
+my $server = IO::Socket::UNIX->new(Local => $path, Type => SOCK_STREAM, Listen => 8) or
+ die "unable to create socket $path";
+chmod 0777, $path;
+
+# setup our pidfile
+open(my $pid,">",$pidfile)
+ or die "unable to open pidfile $pidfile";
+print $pid "$$\n";
+close($pid);
+
+if ($timeout != 0) {
+ # die after the given timeout
+ alarm($timeout);
+}
+
+while (my $client = $server->accept()) {
+ $client->recv(my $buf, 8, 0);
+ my ($version, $req_len) = unpack('N N', $buf);
+
+ if ($version != 1 || $req_len < 17) {
+ printf("Badly formatted request\n");
+ $client->send(pack('N', 2));
+ next;
+ }
+
+ $client->recv(my $buf, $req_len - 8, 0);
+
+ my ($signer,
+ $name,
+ $addr,
+ $type,
+ $key,
+ $key_data) = unpack('Z* Z* Z* Z* Z* N/a', $buf);
+
+ if ($req_len != length($buf)+8) {
+ printf("Length mismatch %u %u\n", $req_len, length($buf)+8);
+ $client->send(pack('N', 2));
+ next;
+ }
+
+ printf("version=%u signer=%s name=%s addr=%s type=%s key=%s key_data_len=%u\n",
+ $version, $signer, $name, $addr, $type, $key, length($key_data));
+
+ my $result;
+ if ($typeallowed eq $type) {
+ $result = 1;
+ printf("allowed type %s == %s\n", $type, $typeallowed);
+ } else {
+ printf("disallowed type %s != %s\n", $type, $typeallowed);
+ $result = 0;
+ }
+
+ $reply = pack('N', $result);
+ $client->send($reply);
+}
diff --git a/bin/tests/system/tsiggss/clean.sh b/bin/tests/system/tsiggss/clean.sh
new file mode 100644
index 0000000..0ace209
--- /dev/null
+++ b/bin/tests/system/tsiggss/clean.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after tsiggss tests.
+#
+
+rm -f ns1/*.jnl ns1/update.txt ns1/auth.sock
+rm -f ns1/*.db ns1/K*.key ns1/K*.private
+rm -f ns1/_default.tsigkeys
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f authsock.pid
+rm -f ns1/core
+rm -f nsupdate.out*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/tsiggss/ns1/administrator.ccache b/bin/tests/system/tsiggss/ns1/administrator.ccache
new file mode 100644
index 0000000..e6c2e74
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/administrator.ccache
Binary files differ
diff --git a/bin/tests/system/tsiggss/ns1/dns.keytab b/bin/tests/system/tsiggss/ns1/dns.keytab
new file mode 100644
index 0000000..dcb863b
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/dns.keytab
Binary files differ
diff --git a/bin/tests/system/tsiggss/ns1/example.nil.db.in b/bin/tests/system/tsiggss/ns1/example.nil.db.in
new file mode 100644
index 0000000..ffa7e58
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/example.nil.db.in
@@ -0,0 +1,62 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+; -*- zone -*-
+; this was generated by a Samba4 provision, and is typical
+; of a AD DNS zone
+$ORIGIN example.nil.
+$TTL 1W
+@ IN SOA blu hostmaster (
+ 2010113027 ; serial
+ 2D ; refresh
+ 4H ; retry
+ 6W ; expiry
+ 1W ) ; minimum
+ IN NS blu
+
+ IN A 10.53.0.1
+;
+
+blu IN A 10.53.0.1
+gc._msdcs IN A 10.53.0.1
+
+fb33eb58-5d58-4100-a114-256e0a97ffc1._msdcs IN CNAME blu
+;
+; global catalog servers
+_gc._tcp IN SRV 0 100 3268 blu
+_gc._tcp.Default-First-Site-Name._sites IN SRV 0 100 3268 blu
+_ldap._tcp.gc._msdcs IN SRV 0 100 3268 blu
+_ldap._tcp.Default-First-Site-Name._sites.gc._msdcs IN SRV 0 100 3268 blu
+;
+; ldap servers
+_ldap._tcp IN SRV 0 100 389 blu
+_ldap._tcp.dc._msdcs IN SRV 0 100 389 blu
+_ldap._tcp.pdc._msdcs IN SRV 0 100 389 blu
+_ldap._tcp.d86745b4-f3e0-4af3-be03-2130d1534be8.domains._msdcs IN SRV 0 100 389 blu
+_ldap._tcp.Default-First-Site-Name._sites IN SRV 0 100 389 blu
+_ldap._tcp.Default-First-Site-Name._sites.dc._msdcs IN SRV 0 100 389 blu
+;
+; krb5 servers
+_kerberos._tcp IN SRV 0 100 88 blu
+_kerberos._tcp.dc._msdcs IN SRV 0 100 88 blu
+_kerberos._tcp.Default-First-Site-Name._sites IN SRV 0 100 88 blu
+_kerberos._tcp.Default-First-Site-Name._sites.dc._msdcs IN SRV 0 100 88 blu
+_kerberos._udp IN SRV 0 100 88 blu
+; MIT kpasswd likes to lookup this name on password change
+_kerberos-master._tcp IN SRV 0 100 88 blu
+_kerberos-master._udp IN SRV 0 100 88 blu
+;
+; kpasswd
+_kpasswd._tcp IN SRV 0 100 464 blu
+_kpasswd._udp IN SRV 0 100 464 blu
+;
+; heimdal 'find realm for host' hack
+_kerberos IN TXT EXAMPLE.NIL
diff --git a/bin/tests/system/tsiggss/ns1/named.conf.in b/bin/tests/system/tsiggss/ns1/named.conf.in
new file mode 100644
index 0000000..7b34c32
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/named.conf.in
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.1; 127.0.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ tkey-gssapi-keytab "dns.keytab";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example.nil." IN {
+ type primary;
+ file "example.nil.db";
+
+ update-policy {
+ grant Administrator@EXAMPLE.NIL wildcard * A AAAA SRV CNAME;
+ grant testdenied@EXAMPLE.NIL wildcard * TXT;
+ grant "local:auth.sock" external * CNAME;
+ };
+
+ /* we need to use check-names ignore so _msdcs A records can be created */
+ check-names ignore;
+};
diff --git a/bin/tests/system/tsiggss/ns1/testdenied.ccache b/bin/tests/system/tsiggss/ns1/testdenied.ccache
new file mode 100644
index 0000000..070e85b
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/testdenied.ccache
Binary files differ
diff --git a/bin/tests/system/tsiggss/prereq.sh b/bin/tests/system/tsiggss/prereq.sh
new file mode 100644
index 0000000..0f8e2d6
--- /dev/null
+++ b/bin/tests/system/tsiggss/prereq.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+# enable the tsiggss test only if gssapi was enabled
+$FEATURETEST --gssapi || {
+ echo_i "gssapi and krb5 not supported - skipping tsiggss test"
+ exit 255
+}
+
+exit 0
diff --git a/bin/tests/system/tsiggss/setup.sh b/bin/tests/system/tsiggss/setup.sh
new file mode 100644
index 0000000..37b80fd
--- /dev/null
+++ b/bin/tests/system/tsiggss/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+
+key=$($KEYGEN -Cq -K ns1 -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n HOST -T KEY key.example.nil.)
+cat ns1/example.nil.db.in ns1/${key}.key > ns1/example.nil.db
diff --git a/bin/tests/system/tsiggss/tests.sh b/bin/tests/system/tsiggss/tests.sh
new file mode 100644
index 0000000..97cc7bb
--- /dev/null
+++ b/bin/tests/system/tsiggss/tests.sh
@@ -0,0 +1,178 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# tests for TSIG-GSS updates
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=1
+
+DIGOPTS="@10.53.0.1 -p ${PORT}"
+
+test_update () {
+ num="$1"
+ host="$2"
+ type="$3"
+ cmd="$4"
+ digout="$5"
+
+ cat <<EOF > ns1/update.txt
+server 10.53.0.1 ${PORT}
+update add $host $cmd
+send
+answer
+EOF
+ echo_i "testing update for $host $type $cmd"
+ $NSUPDATE -g -d ns1/update.txt > nsupdate.out${num} 2>&1 || {
+ echo_i "update failed for $host $type $cmd"
+ sed "s/^/I:/" nsupdate.out${num}
+ return 1
+ }
+
+ # Verify that TKEY response is signed.
+ tkeyout=$(awk '/recvmsg reply from GSS-TSIG query/,/Sending update to/' nsupdate.out${num})
+ pattern="recvmsg reply from GSS-TSIG query .* opcode: QUERY, status: NOERROR, id: .* flags: qr; QUESTION: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; QUESTION SECTION: ;.* ANY TKEY ;; ANSWER SECTION: .* 0 ANY TKEY gss-tsig\. .* ;; TSIG PSEUDOSECTION: .* 0 ANY TSIG gss-tsig\. .* NOERROR 0"
+ echo $tkeyout | grep "$pattern" > /dev/null || {
+ echo_i "bad tkey response (not tsig signed)"
+ return 1
+ }
+
+ # Weak verification that TKEY response is signed.
+ grep -q "flags: qr; QUESTION: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" nsupdate.out${num} || {
+ echo_i "bad tkey response (not tsig signed)"
+ return 1
+ }
+
+ out=$($DIG $DIGOPTS -t $type -q $host | grep -E "^${host}")
+ lines=$(echo "$out" | grep "$digout" | wc -l)
+ [ $lines -eq 1 ] || {
+ echo_i "dig output incorrect for $host $type $cmd: $out"
+ return 1
+ }
+ return 0
+}
+
+
+# Testing updates with good credentials.
+KRB5CCNAME="FILE:"$(pwd)/ns1/administrator.ccache
+export KRB5CCNAME
+
+echo_i "testing updates to testdc1 as administrator ($n)"
+ret=0
+test_update $n testdc1.example.nil. A "86400 A 10.53.0.10" "10.53.0.10" || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing updates to testdc2 as administrator ($n)"
+ret=0
+test_update $n testdc2.example.nil. A "86400 A 10.53.0.11" "10.53.0.11" || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing updates to denied as administrator ($n)"
+ret=0
+test_update $n denied.example.nil. TXT "86400 TXT helloworld" "helloworld" > /dev/null && ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+
+# Testing denied updates.
+KRB5CCNAME="FILE:"$(pwd)/ns1/testdenied.ccache
+export KRB5CCNAME
+
+echo_i "testing updates to denied (A) as a user ($n)"
+ret=0
+test_update $n testdenied.example.nil. A "86400 A 10.53.0.12" "10.53.0.12" > /dev/null && ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing updates to denied (TXT) as a user ($n)"
+ret=0
+test_update $n testdenied.example.nil. TXT "86400 TXT helloworld" "helloworld" || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing external update policy (CNAME) ($n)"
+ret=0
+test_update $n testcname.example.nil. CNAME "86400 CNAME testdenied.example.nil" "testdenied" > /dev/null && ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing external update policy (CNAME) with auth sock ($n)"
+ret=0
+$PERL ./authsock.pl --type=CNAME --path=ns1/auth.sock --pidfile=authsock.pid --timeout=120 > /dev/null 2>&1 &
+sleep 1
+test_update $n testcname.example.nil. CNAME "86400 CNAME testdenied.example.nil" "testdenied" || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing external update policy (A) ($n)"
+ret=0
+test_update $n testcname.example.nil. A "86400 A 10.53.0.13" "10.53.0.13" > /dev/null && ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing external policy with SIG(0) key ($n)"
+ret=0
+$NSUPDATE -k ns1/Kkey.example.nil.*.private <<END > /dev/null 2>&1 || ret=1
+server 10.53.0.1 ${PORT}
+zone example.nil
+update add fred.example.nil 120 cname foo.bar.
+send
+END
+output=$($DIG $DIGOPTS +short cname fred.example.nil.)
+[ -n "$output" ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "ensure too long realm name is fatal in non-interactive mode ($n)"
+ret=0
+$NSUPDATE <<END > nsupdate.out${n} 2>&1 && ret=1
+ realm namenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename
+END
+grep "realm is too long" nsupdate.out${n} > /dev/null || ret=1
+grep "syntax error" nsupdate.out${n} > /dev/null || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "ensure too long realm name is not fatal in interactive mode ($n)"
+ret=0
+$NSUPDATE -i <<END > nsupdate.out${n} 2>&1 || ret=1
+ realm namenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename
+END
+grep "realm is too long" nsupdate.out${n} > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+[ $status -eq 0 ] && echo_i "tsiggss tests all OK"
+
+kill $(cat authsock.pid)
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/tsiggss/tests_isc_spnego_flaws.py b/bin/tests/system/tsiggss/tests_isc_spnego_flaws.py
new file mode 100755
index 0000000..6340b5a
--- /dev/null
+++ b/bin/tests/system/tsiggss/tests_isc_spnego_flaws.py
@@ -0,0 +1,219 @@
+#!/usr/bin/python
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+"""
+A tool for reproducing ISC SPNEGO vulnerabilities
+"""
+
+import argparse
+import datetime
+import struct
+import time
+
+import pytest
+
+pytest.importorskip("dns")
+import dns.message
+import dns.name
+import dns.query
+import dns.rdata
+import dns.rdataclass
+import dns.rdatatype
+import dns.rrset
+
+
+class CraftedTKEYQuery:
+ # pylint: disable=too-few-public-methods
+
+ """
+ A class for preparing crafted TKEY queries
+ """
+
+ def __init__(self, opts: argparse.Namespace) -> None:
+ # Prepare crafted key data
+ tkey_data = ASN1Encoder(opts).get_tkey_data()
+ # Prepare TKEY RDATA containing crafted key data
+ rdata = dns.rdata.GenericRdata(
+ dns.rdataclass.ANY, dns.rdatatype.TKEY, self._get_tkey_rdata(tkey_data)
+ )
+ # Prepare TKEY RRset with crafted RDATA (for the ADDITIONAL section)
+ rrset = dns.rrset.from_rdata(dns.name.root, dns.rdatatype.TKEY, rdata)
+
+ # Prepare complete TKEY query to send
+ self.msg = dns.message.make_query(
+ dns.name.root, dns.rdatatype.TKEY, dns.rdataclass.ANY
+ )
+ self.msg.additional.append(rrset)
+
+ def _get_tkey_rdata(self, tkey_data: bytes) -> bytes:
+ """
+ Return the RDATA to be used for the TKEY RRset sent in the ADDITIONAL
+ section
+ """
+ tkey_rdata = dns.name.from_text("gss-tsig.").to_wire() # domain
+ if not tkey_rdata:
+ return b""
+ tkey_rdata += struct.pack(">I", int(time.time()) - 3600) # inception
+ tkey_rdata += struct.pack(">I", int(time.time()) + 86400) # expiration
+ tkey_rdata += struct.pack(">H", 3) # mode
+ tkey_rdata += struct.pack(">H", 0) # error
+ tkey_rdata += self._with_len(tkey_data) # key
+ tkey_rdata += struct.pack(">H", 0) # other size
+ return tkey_rdata
+
+ def _with_len(self, data: bytes) -> bytes:
+ """
+ Return 'data' with its length prepended as a 16-bit big-endian integer
+ """
+ return struct.pack(">H", len(data)) + data
+
+
+class ASN1Encoder:
+ # pylint: disable=too-few-public-methods
+
+ """
+ A custom ASN1 encoder which allows preparing malformed GSSAPI tokens
+ """
+
+ SPNEGO_OID = b"\x06\x06\x2b\x06\x01\x05\x05\x02"
+
+ def __init__(self, opts: argparse.Namespace) -> None:
+ self._real_oid_length = opts.real_oid_length
+ self._extra_oid_length = opts.extra_oid_length
+
+ # The TKEY RR being sent contains an encoded negTokenInit SPNEGO message.
+ # RFC 4178 section 4.2 specifies how such a message is constructed.
+
+ def get_tkey_data(self) -> bytes:
+ """
+ Return the key data field of the TKEY RR to be sent
+ """
+ return self._asn1(
+ data_id=b"\x60", data=self.SPNEGO_OID + self._get_negtokeninit()
+ )
+
+ def _get_negtokeninit(self) -> bytes:
+ """
+ Return the ASN.1 DER-encoded form of the negTokenInit message to send
+ """
+ return self._asn1(
+ data_id=b"\xa0",
+ data=self._asn1(
+ data_id=b"\x30",
+ data=self._get_mechtypelist(),
+ extra_length=self._extra_oid_length,
+ ),
+ extra_length=self._extra_oid_length,
+ )
+
+ def _get_mechtypelist(self) -> bytes:
+ """
+ Return the ASN.1 DER-encoded form of the MechTypeList to send
+ """
+ return self._asn1(
+ data_id=b"\xa0",
+ data=self._asn1(
+ data_id=b"\x30",
+ data=self._get_mechtype(),
+ extra_length=self._extra_oid_length,
+ ),
+ extra_length=self._extra_oid_length,
+ )
+
+ def _get_mechtype(self) -> bytes:
+ """
+ Return the ASN.1 DER-encoded form of a bogus security mechanism OID
+ which consists of 'self._real_oid_length' 0x01 bytes
+ """
+ return self._asn1(
+ data_id=b"\x06",
+ data=b"\x01" * self._real_oid_length,
+ extra_length=self._extra_oid_length,
+ )
+
+ def _asn1(self, data_id: bytes, data: bytes, extra_length: int = 0) -> bytes:
+ """
+ Return the ASN.1 DER-encoded form of 'data' to be included in GSSAPI
+ key data, designated with 'data_id' as the content identifier. Setting
+ 'extra_length' to a positive integer allows data length indicated in
+ the ASN.1 DER representation of 'data' to be increased beyond its
+ actual size.
+ """
+ data_len = struct.pack(">I", len(data) + extra_length)
+ return data_id + b"\x84" + data_len + data
+
+
+def parse_options() -> argparse.Namespace:
+ """
+ Parse command line options
+ """
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--server-ip", required=True)
+ parser.add_argument("--server-port", type=int, default=53)
+ parser.add_argument("--real-oid-length", type=int, default=1)
+ parser.add_argument("--extra-oid-length", type=int, default=0)
+
+ return parser.parse_args()
+
+
+def send_crafted_tkey_query(opts: argparse.Namespace) -> None:
+ """
+ Script entry point
+ """
+
+ query = CraftedTKEYQuery(opts).msg
+ print("# > " + str(datetime.datetime.now()))
+ print(query.to_text())
+ print()
+
+ response = dns.query.tcp(query, opts.server_ip, timeout=2, port=opts.server_port)
+ print("# < " + str(datetime.datetime.now()))
+ print(response.to_text())
+ print()
+
+
+def test_cve_2020_8625(named_port):
+ """
+ Reproducer for CVE-2020-8625. When run for an affected BIND 9 version,
+ send_crafted_tkey_query() will raise a network-related exception due to
+ named (ns1) becoming unavailable after crashing.
+ """
+ for i in range(0, 50):
+ opts = argparse.Namespace(
+ server_ip="10.53.0.1",
+ server_port=named_port,
+ real_oid_length=i,
+ extra_oid_length=0,
+ )
+ send_crafted_tkey_query(opts)
+
+
+def test_cve_2021_25216(named_port):
+ """
+ Reproducer for CVE-2021-25216. When run for an affected BIND 9 version,
+ send_crafted_tkey_query() will raise a network-related exception due to
+ named (ns1) becoming unavailable after crashing.
+ """
+ opts = argparse.Namespace(
+ server_ip="10.53.0.1",
+ server_port=named_port,
+ real_oid_length=1,
+ extra_oid_length=1073741824,
+ )
+ send_crafted_tkey_query(opts)
+
+
+if __name__ == "__main__":
+ cli_opts = parse_options()
+ send_crafted_tkey_query(cli_opts)
diff --git a/bin/tests/system/tsiggss/tests_sh_tsiggss.py b/bin/tests/system/tsiggss/tests_sh_tsiggss.py
new file mode 100644
index 0000000..926a9a9
--- /dev/null
+++ b/bin/tests/system/tsiggss/tests_sh_tsiggss.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_tsiggss(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/ttl/clean.sh b/bin/tests/system/ttl/clean.sh
new file mode 100644
index 0000000..3bb41d9
--- /dev/null
+++ b/bin/tests/system/ttl/clean.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ./*/named.conf
+rm -f ./*/named.memstats
+rm -f ./*/named.run
+rm -f ./ns*/managed-keys.bind*
diff --git a/bin/tests/system/ttl/ns1/max-example.db b/bin/tests/system/ttl/ns1/max-example.db
new file mode 100644
index 0000000..aeaafc7
--- /dev/null
+++ b/bin/tests/system/ttl/ns1/max-example.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+max-example. 1209600 IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 1209600 ; minimum (2 weeks)
+ )
+max-example. 1209600 IN NS ns.max-example.
+ns.max-example. 1209600 IN A 10.53.0.1
diff --git a/bin/tests/system/ttl/ns1/min-example.db b/bin/tests/system/ttl/ns1/min-example.db
new file mode 100644
index 0000000..87d6e7e
--- /dev/null
+++ b/bin/tests/system/ttl/ns1/min-example.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+min-example. 0 IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 0 ; minimum (0 seconds)
+ )
+min-example. 0 IN NS ns.min-example.
+ns.min-example. 0 IN A 10.53.0.1
diff --git a/bin/tests/system/ttl/ns1/named.conf.in b/bin/tests/system/ttl/ns1/named.conf.in
new file mode 100644
index 0000000..51eee0c
--- /dev/null
+++ b/bin/tests/system/ttl/ns1/named.conf.in
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation no;
+ check-integrity no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "min-example" {
+ type primary;
+ file "min-example.db";
+};
+
+zone "max-example" {
+ type primary;
+ file "max-example.db";
+};
diff --git a/bin/tests/system/ttl/ns2/hints.db b/bin/tests/system/ttl/ns2/hints.db
new file mode 100644
index 0000000..c9264bf
--- /dev/null
+++ b/bin/tests/system/ttl/ns2/hints.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. 60 IN NS ns.nil.
+ns.nil. 60 IN A 10.53.0.1
diff --git a/bin/tests/system/ttl/ns2/named.conf.in b/bin/tests/system/ttl/ns2/named.conf.in
new file mode 100644
index 0000000..1716807
--- /dev/null
+++ b/bin/tests/system/ttl/ns2/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ directory ".";
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ servfail-ttl 0;
+ max-recursion-depth 12;
+ recursion yes;
+ dnssec-validation no;
+ min-cache-ttl 60;
+ min-ncache-ttl 30;
+ max-cache-ttl 120;
+ max-ncache-ttl 60;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." { type hint; file "hints.db"; };
diff --git a/bin/tests/system/ttl/setup.sh b/bin/tests/system/ttl/setup.sh
new file mode 100644
index 0000000..6929ec5
--- /dev/null
+++ b/bin/tests/system/ttl/setup.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
diff --git a/bin/tests/system/ttl/tests_cache_ttl.py b/bin/tests/system/ttl/tests_cache_ttl.py
new file mode 100644
index 0000000..9025283
--- /dev/null
+++ b/bin/tests/system/ttl/tests_cache_ttl.py
@@ -0,0 +1,32 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import pytest
+
+pytest.importorskip("dns")
+import dns.message
+import dns.query
+
+
+@pytest.mark.parametrize(
+ "qname,rdtype,expected_ttl",
+ [
+ ("min-example.", "SOA", 60),
+ ("min-example.", "MX", 30),
+ ("max-example.", "SOA", 120),
+ ("max-example.", "MX", 60),
+ ],
+)
+def test_cache_ttl(qname, rdtype, expected_ttl, named_port):
+ msg = dns.message.make_query(qname, rdtype)
+ response = dns.query.udp(msg, "10.53.0.2", timeout=10, port=named_port)
+ for rr in response.answer + response.authority:
+ assert rr.ttl == expected_ttl
diff --git a/bin/tests/system/unknown/clean.sh b/bin/tests/system/unknown/clean.sh
new file mode 100644
index 0000000..1d73edd
--- /dev/null
+++ b/bin/tests/system/unknown/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f dig.out* check.out
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f */*.bk
+rm -f */*.bk.*
+rm -f ns3/Kexample.*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
diff --git a/bin/tests/system/unknown/large.out b/bin/tests/system/unknown/large.out
new file mode 100644
index 0000000..812bde5
--- /dev/null
+++ b/bin/tests/system/unknown/large.out
@@ -0,0 +1 @@
+\# 48000 45841674994E4F5E4BA43AADA754D631DFB7E12155E7F10C551032B3 E56ED5BA5136C15CDA201E7E5E54FB60A99388B61A565C1CF74CD8AA E1AEE7FBEB54CEBEE065CF2B1B317F67277AE733183C668BA81A7EFE C322D36FB5CC6293AD7F7AE3544A7C64D404C4EEB1B889E9780A213B D548A018BE2E1B6A3B8840D714DDB8C0A66BEAA4C2A1471D216AD0EB 8D2C884960D30FD3FAD058C47EACE42AAB0F0D40A690CA3BAF9616B7 373B889788E891757AE0EEACCD291D87D05DAED8631D1EBF9202F816 59754CA11221E902A69C7BF0039310EDF5305ACE5404DDD02163BE0A 22334879A27BFA7702E13D06F15887261A12ABFD0C01966FA67F97ED 38C521DBCFF8A2AA8DAF53F1EAA7991B6767DA0E68B2EBB38BEB8F1A ADAA30C1185870DAD0091E7AF0BBED453CE081BA5DC87CA5A764592E D7312C6A26F7E358EF35182A49763A61C9A0C5DBDDCF199251381215 51EB3C3CED9F529F03A85429F42F75503EFA6E1301AA7AD9B29C5AAA A1EF6EE5BBE9E2639D65BAF98A6B06243483A2453969F65F9A0DAD3D 8630522079B8C1079E28057D63696739B71F57EE85AB20A596865D77 EF70412C7A4BE7D9D5A4EB13709F0EC1AF6A4CF962364761EBD62EFB 4F16EE843C1B214944EFF2C81563C4AC4C854C32972DF761F17FDCAC 3E40E02757FDF1FA57F77E1C86C3D488B02D4634501801BE4F929FFD E0ED07112093D9018D59CEE1733BFDC8A968A831D42B95C087A578E3 C6EEFACFA1C9089072AB490D631B2D00CB75CB33586917F103842856 CA2F5CCD449465B4A86A37F8147D626969F02DAFACD4BA81B680E5DC 288037ADA3BE902E2EF9C129710200AC93F5D3BF1C1418B65D98BDF1 01D38D9B2C5F25A3D09A4638DCC2C0D0CF411F3ED747E6745AC7A8BE 03EA2EE990979CF3B8398C4BFB058012DE25FBF0E1081C4205AFC54D 3BDA63565BC0BC3F6AF91F083ABC26AC7047E2759F28525498AE6461 A1F66B900FDE5D8CD6C842C587F28620444AD5BD3B522F0294C14E22 79B5C577F3F41C15A723A20259805AA18360F6B954B75D98BEECD0C0 A0AD151B0027CCA891932ADFCA9B7ECA33FD585031C188F8D851E3BB C8552F340E1319553BFE776975BAEE6ACF025B8C4849C0A430049734 114B75345228D19846B39580F1C328068A4B36C43EF13380BE7E5406 0ACD9494EE99908F57E779A4C20728135D509B52D5066CC7BAC77F1C 4FCF81E9F0C7CF621593E90F398C56B14FDDC74F62A4854655CB27B1 DC94A83F9A4A52055EA74EA3129F88CB8D01870BFD5157CB966CFA41 21E018C2DD72F363DFA5011D1072FD9350DDE79BEC213520CD68CCEA 356EE24B2C3E84871540C410353E9514188A46771B07B2B0E261287D 353A8D55A71077B4B509FB99C80D7D07F6739CBC9ED82A5A40E624C0 860A42049585C0ABC164B6E5E726DA58B6FAF8384E0C8E9A03BAE074 415335BAC4E72AAD561CB77A8D7AAD25C67F3D74F38B62F43A2012FB E62C0DEF6BE948098DBCBB0F06769663B8E6A7C0D88AC914DBB8BAA7 85F4509B2DECAD57F85516D2AEF23A24202B4123F4CE41E97653B5F3 8E7E092C8EBFDC36A46D204237AE71484F4249740C2ECA7BEACE1699 CCAAC0DAA6AD8C1A0C5AEB59086C2179A235085D0C68942C8FBD67EC 7FCF627049DF4790757F40D7D027FBEAE4A358EDD5867C7F56710460 38E3086D76D3E22F868DBE60C64EB123BBF15358FD7D5B6511CEDECF A701494B143F77F7463D8E3099B811E8AB53092B3EF6E995A655086B CF61EB773900D425132A04530BEFC404F5BC27D98DD2367BB815580F 8BB7CBEF4793680648959A44A6CD216196A4BD61D1CC44326869877E 2BE943C6C7BB95B854117B1A0B00D33083AFE54461024BD791B2724B ED82EDD289F9376C7E0502627E1E3672345DC53F1F25AFB60568CA28 C84B9214D32FB5D805CDD31324640519C3DD0B6519FA93AB15D734FC 0C5ABBFA90C910C90C3F38B0688B584B6285427F760414C9445B415F E433908035081F5CA081AB53CC7C2701F65A18A5E64EBA887BAD3343 2735C1E62AD2B35F0A258892D919835DFA523E2BAC6DDEBDC0C57640 1F21D937711D774153A7EC42125D24D115240FADB90FE0061D9EC041 EF2905E4AA3E81C453572DF0F72A43D070492261DCAD28174F8B1697 9DB03C2F96D9E53CBFEF510A1BB5D6CFBC4F92A9E94C0C018738E2A9 30922603083124284B076FC1F93AFB20878CCF756C8DE07DC6D01C27 3FF2608136A8DCE64BA4287CC19E35B72B40A32B435F3BFBE94A97F0 972AEBB4C54D95F4993EB831307D22647A1EB7C525FD470FB9CA13D3 404CA5ECFF99E87B73C5B88FD4A905220DB8D183C325E7D27A4D70F7 1469ED347AB68A9F7F1A5EA235BCD9F9BBBEF91A9DF227109D715941 F54EA464C9F8A9D0724BD4C9772023B086BD521C516449C780500CB3 3630AE28CF02C19C0958FAEE545B953CA46217B7AD600679ACD85DCF ECCF4012AA9D5A7E1A1B1A43C7D9A91F8766ED3A5EF61A7A0840BEE2 B8EECCD5932CB1438A7AA271CE6906BDC3D9230AB8D0B095BE53869B 37455D0BAC413F518E39767F23FC669AA0742B8B5196FEDD1284C27D 05372F4653618962468AE24A6C575DAEA152D036619ADB965487D063 1B6182A0EBDD5AAC519ABBC1CBE766283788E8FCE8CE91760EDB4CDA C1636DE694364FED377B9DD5512BB258FF28533CA454EE161E69A58F 7964A88AFAFE768340ED78896D02FCC6D00090728C86C3C21CF4B89E EB975E2A674B64DA5BC5D05F6D647252E7B3394031BC9B4565C466E5 D9B8D9C2DD96A9950AE0D879BFD8C343709968F0D4A885D9C0A4AD22 B08FA3CB093DCD583AFD49966CB842F3E739FC665AE78550914896A2 D8F660726E02B7847AFAF327990A3478362C091F2B0BF7DD8AFD4F93 5141E63C7C4A680BB02BF84BA0E2FBCE5FCACF1CD51C7732E97A358D BFF58DC07AE2CFC5F66EF5A8532F31BFCFA86886751ECFE4D3234C3E C84EABCB9DE56BD72847E894AC95103FEB7DE2C89780E7377ED61A1B D813F64957419BD798632AA7B5A43D5E90463FE5DB8373A91487E71A B990C0B68C4F86305A3CB78216C98188D9C4FF715D7CC72BD4B64253 B4A894B2B9A3F7AA6C41A1ED2A7CC3553C3716C6D3CA42E4746A1801 93FF49E0B8063412EF9DF6217C97D30FB7ECC5ABACF22E08105B0B09 807B3F3CDF66A695F46F5ACE7FFF41208859CA38610F6A91368685C9 EF8E68958ACAB3C7F198A484ACD6592CDD0F1507AF662A61E9FE8EB4 0EFEEBED64888802978952DD21C9D903B2BE0845C3611A138C2750B1 35D0D55FAE5AE23A8274DA034E28D2B7760F82AB2F83AB1CD34D9C45 F7FB63527845704A4E68CF578C8604F269F70DB8F4462980EEAAA40A C20076FDDDFA2F2F31AE7E031388ED6BCBF0DA39FD210351C956151C 5A69B8DB3ECBA80B6DA822A858E8D5ABC24D3AFBADE4B8FAC50CD36F 3926AF3CC6917D2A54A83540BBC96ECADBCDBA189849B07B865538B3 B4FE142D2DFC0DEC688DA44B3C0B8C4605A00CC826BD5826A8E43F22 5E75D246DE2C896394AC9169746689010F2E958029F874A084813663 BF14A38111685457842BE8566C634FE7BD34A0846B82929DC357F06B A186A3A6917521881A1B84473B9D6BE8C10DDA27655BCEF81AC6E717 CCA29E9E0F6A02578B7A6F97CEC7B600785C4ACE6EAFE9F7F604F754 0538F96501467456BF132D1F52555DE292C21E3AA5FC24CD57E2A65E 742E2FEC311F3CBD19B9B4F8E9C5A66191F4C19B8F641D9C7FA58338 F179B533DCBF6A88849E4BD01B094B5B8B09BBF3095F683029DFA61A 4C91A582DF0380AA4A0ABC97A7BA9735BC7C2894AE6883B42CDCA772 626C31088C1684F64DEA810199C2D48A5467DB001BA4E274C0F7A5E7 62CC615A91FE537B356C7D76D24D310EF4D6D1E19F1788FED740686E 9BCE08E6B06B99A3BB7100477563992420FC70BB75B783820DF34C3F 7595E7EFC3E225EA5F2B33C05F515E1D3B4DA67B0DD461E1A82260B6 D2B7A0A43265A8003A5FD13F57CF05878211C6E1EB8C635A2C8D1533 F0260FAD1DF4FA41CE398E0974A5EA54AEBECF6E9AE57562BAA826C9 831C56CAB61565E2697E96F563D55B75B48A4FB6F32C02EBC2BFEC9F D519C396FFF42F1C4953DCD2EDE87F62EA90CDB1ACBAC2B187EF7104 7DE4477514612593FD7F849E4190A59BC147EA07B794E0880EA37F5F 27AA5FA78905F6495668253890699E319F14D54996E36E1F6DDED0C9 552605AD9D20F8F4E6DD26FDB7FC681415F15D47E4997995A671F85F 56E54A146D1E16C7909B0EFD42CAFB92F12B9F4F88157A68CCF8DCF3 295AE65D26DD53233CD414F73881A5FED934C577B7C66F484965E1EA 507F2FDB20141A9C6458F22265E26CE6AC906B4BD43F178331328BEA 55C61E737F2F130E51F0ED343A9E9709036ABE6338446B8CA7B9CD83 1F4C63908FCB6EB134626F89DF0A134F9F7CD196BC96A5DDD2B2CC55 30220D4708D5D2FC55EB64ECC1B668970E7DF11FAEB3782630A37920 89E2A0443631AEC02CF8078C8CACB3BBFFF7304670B391690AE1A29B 445A46CF78B84D26E830B8D072C2F0A2292CF29AE11F509855C1972D 5F86A13773FE91954B2EB5C8E75B9554C082FE65EA01D0D6794D621B 231DB56DD59EEEBE4D71144B966C19B402DBAA25D051F9DCAB7F0631 42D35123D9CA28A89A4CF3E771095F794F6A7D495870AC9F47D1E024 B5341C931590225B76931999C9D341D8CDEA4D0443D719E09ED22758 4243480B618246A318ADDF475A70F3BE57C3278E23D48874E2682486 4ABE829CA2318DDEC436D182040F014D4FBCB1FBDBF2AB82B613B7DD B45DC7635796A6AB203F8D9A6A04C08B40BE8452B4058EB6199FF68C A8A570F1A179ED662E4FBC1DDB8364CCABDB7D25EB9BFA6844D4D379 FFF7161F13D287AF0B6B9EF3D2C164BC63D412F04CC3DDBEDA6D9738 38B329108388EF700E42E232009782D380127200412E27671DF2B17D 5D7FA517CE12C66D6B84B11365611CB11E0BF27B06F3B86C4B4572E6 3702DAD0A3F9784656D16F7B731951FAEFD190B4F7E0322871A2733C 30670C311DB6F8C24E51C747525D04E551DFE1EC6A20E796D0B7F4BE 73896895FD6BF922B02BDC0C1412317AC0975D0CBC8C5A01F17F842C 9CDEF7CDB02055425BB1EE0FBE46BAB2FB6C3D3E3D86EB066EDD23B5 7F18C3B9FEC9C6C3D8D41B77DADA06F08890490354F95E97FECEE7F6 BDE50325F659971D8940C6B299531EC9E07413CDB92EA26DB7AE21A1 51CD59BFE72B8A19998384EE8985CC47544EDC79F5F266F0887664DB 09136792E75DFBC306DB725E5D1089DE94E3305A3DB61B799A22EBEA 3A72C52A9EAA89A2983F47FD0C685445D30C6023C855613F33E023E1 A73120762816B70CA46FE2BF0C14B9706DA2F993FE00053AC6828033 7B92FE344695DA64CAE061541164BCADAEFAECEE529AEF20F0530104 26633AAD07A98D8D6453AD0164951D85C5DB7965F6B845C01EE4B13D A933CB152151E8052BD6052B22CED3F3CE96040A23B6661AE0789309 70CD342D2464C0638C7988D06A5DDF9130FD4148A8221FEBF8200323 C42890E57AD3C60AE443C72F60388F755BD0F8D8082BC7CC7C26B280 B6C186FEE3E7161793BE25C8373D7714E1DB51F9AF53809CDE5C1141 A183A84643B4D8CD3D1777E9F5C70F0822C115F2C663D2C02315EB18 3CAA4122703E24792756FFA86077FEB7E4FDE2304CCB5A8AE1B2BB50 6699EBFF1067C50E835F8CACB46E0FC93216764F999687F6BC9F9351 6B777391D03CB2C74DCAB8F5A3CD2F0C2715548F8EB36B1B138D0D95 9513884CE3B6A4F7A835943687C92D9E95C9BD30AEECE528C9965C4C 927F21F584F37B42075188D24E2EDE898E55A6E33B7357792BA7FABE F7CB09E1814D6F2DD1D5C8D029D2421EE6FD905B393D9D47AD6B9F28 05EC387154E88251C2E066A9EB378E00C7EE4E52872DCD718C67308C 6388BF175EC90FF818F49C4F80633DBA8351D0F162A5FFCD9642E553 E6763DFB97B52899FFBD4614568EB13A730B1ADBA54A41445E70BC6F 1BC5723FD236B133B966EE67D9604EFCBC828EAEE587598DAFC81F0C 71EFE2D5D07C41959DF2636B3B3054903534D678E436382EA38D8D24 041B7A254DDDB783FFA19AA7C128D5A932BC8AC3E04DF72305CEE704 33D4920C35D22B21D2DCFA2A4640B7AFA4134C1530CA677D175DE1BE 666B24408CA698AAC57A5D9DD41B9737CE9CF73C3027AD2C50D80AE4 B3966B00459EF11505297E096B86933EFA71830B010FBC41D7832DE0 DA01E9EDDDB1AEA400F535CC4B601E80F95E17E0FA104BCF16A3C451 4A8F2F6AFC59669B1F2DE45895A6CE3800823F3AFAB29E44077F5B46 89240D10E62C1282B6F8E15F922E02CC2D9CBB40F2722FB6EFD6C8E9 21575DF9A46D3FA7E014B0E91E1204F4081052D93A0871C35CE92B92 FF3C49F90FC42727D5C9405540DC8406499FE053FD146423A888E1A3 E0728C69381E0A2221ADC4D0BF9B51F7DDD4A8EA74BFDF20054B9359 98DE4CC852FAF08907F5C2A33686EFF3572D55E6227A3CB9C463D0CF 6A2A617516ED7F5993F4530B46D2791902E12DAF36A73C6CA7B6D486 592C2E85B2FE942492240E3B6012A8D1F28D37F1F2B43CD94D7B93AA 56DE82D4135A84190272CCB9A6AB606D5A929F0BC2B0D0485429F2B8 066307E0404FF7EBFD02EFF231838D43BFE1D8ECB77372ABCE6DAA1A 48B37C9D30D94C12E81388B10845B62BB311325929A21712930C5D61 D058F5F8ABCE4C198DDC482034407B7F360BA1A65B2E3B3037C06C3C AD7C706CDB45AB39C9317BE281BDF524C2FFDB29C6B3BE40B91B62CB 7735A463829C4CB8BAD28CEDA3D8B955791E75B8405A6C039615DBD9 DEE3BA95F922BCA586A39119FEC0F510FCC5C5CE70C9D6B09CB0A47F 314C09C3735C7E7C74784EF20953111F3EB067547167A78827072356 DF64C101F536A075A2ACA016E13A9F8695E2E7C09E56BE291A75958C 3DE58351E50124DCB4846C97B58427C344B773B27F5D49F4B781A13C 87ADACA9FAE45BF53A8E9F6A8485D476297DD31AD7C635DC4BF775D2 F869E79E3E92F0AF0AB2F0C9C610E76B8A83998EEE7EAB21D3B6F428 0754F1653D076DF87FD2C41FB744F41D20F540631DFA55ADAD22879A BE3498A425C035E624BD8032FC55F131319152DA21A415ECFDFBDE3A 847F86EE4221D7C84D76F56ADA0D8895F2545BB4B3F4176934A4C07E 22921B23934B7E08993102D33094042AFA053C95AB0254A0F8DCD930 5569C270CEC22E49DB90462320CFD05642EE9FBCA1A9F28D0AD119CD FE19B7A7902F039FFC484795A0379FE0C83743B9158638811BE89CFA A14A10F3ED22249D5A57C4AFE42314F71445B7146CB4698BBD4D65C7 F399481E131990245EB34495E490D74750CF9CA38AD44C767AD2B653 EA5017277D688CF40E036717E46B379D004B4F705DFB93CB10A821D8 B3D02DF61F3B3E7125C3464BB30CBE4D41E8203A6FF270059E2C32DF B7B9084D23182C98334ED88F7494D5F4415E9FFCB5C282F6EE8C43D2 5EB4BF38B855DA2E956F215616E66A215BD62E834B150BDD0A9C16DA 61FE88FD5EA186F9543BF71D3A7BED4BA24B4B91DCD1736D71B926F6 42A8BDA5C891873795E19865D13D41640293C6F04D6300EC7594630E 8F4B962EE4FD9A19A19F5EA9D0BDF87306A580A6CCDC995EBAC0D9A6 FEFC145F3C1254679D61B2550DB75B3E05EC44BB7B7E1DB2EDDCE797 88EE430C9F394401127A6925CD8686A6EB48DF587B3D97C5A1A093D0 A510FFCDFD99C243A84DA3B2EBDF1F9AC84B19D2385777AA74F4D990 69628E9B0300035816906B45FF35C4E255C6CAE2131CBAADDFF7EE88 D8DF8A70B4DFA16B4EE08B95725B34301C5760422B395CFC6FF2E8BC ACA5D3368B184C25BD1D1F9E3EEF8ACF67ECEE3B3A2848AD8F930A54 474016512B5EED312A0A6E1E4130B430BFC602CA6CADCA9538A60EC4 E797B0F7D72FCA7F4E63D32C7226B0E5DEC95595B648DF8682769DEB CEEBC0451F562CBC4954753DA83DECD988C045B44558AA69B0DAACD2 0507DE0E1D17FD0E81AA483364956C285D6D75DE2E85C7291D70F17E F44D85444B44F7348D9F2BF3B8778D0E75FF2A45E815BE9B82C8FB97 E26575FEA32D8D458F7776E18406F60A2F0BE74921272C095BE2E3A1 108B2E1B598A1B1B9440197363EF48E123279157F233141C90E127AA D98CE05042318765C6FD3625F8D20D6BC269B78F1489EC5DD8747ABD 96631F85FAC2537AF9E4DED1CF292262A59A9ABEAA4644AAE2EF5F1E 78C332A2A7ECA12FFAB4DB02EFE11C5E008D1831BC9F31EF392D9FAB A7C2311E362649FDE64EA9DDE3DBE9556B8C534835681665E7440B62 4D7F43BFAA01F4A911654AAA28728AEBB7EB433C753E2CF25B7B4229 1454E3E0010FF9D62BDD0E2B211CB53963A4C477AF23C452862200BF F51F233E036526F51F6AEF66E923F58AE7611BADBF47C4E13EB509A7 BED7371BA0E1C86ADB8C120006DBCB345F8F2B47CB48D0B905CDF3E3 23E5B63F48E3D8D9D4143744EF2598EBC3343A3CB86AFE9DE6D14611 797E1CDEE2E753259002796BB75378705105E4CEA49F77F3FC4BEB16 AA8524FBB12B9E5D65E4057807E689AE0CF73AFB5C391ADAF34C37BF CD230195CB4FD80FE5A959464339926636670EE65B1FA05EC1B11CD5 9439E0B1C0F903519CB63012B04F2EEB8FD0628B30CD19AAA5AFB965 565CDDEA0DF6828E4729FB154F20D15A071922AE6036A423150302AE 477C6234B53A5189BC0B031409CEBE716E6B63F5AC51618C00422FDB 410C322AFF0D16AD43E1744CB84E2E8C73B997B0C6EEC3276B83A9A7 CD61A2C25F07684AA602251B5CE4A5B1D04580E38EE3F84B57918508 2A24DE6E0F341891A1DD9DEC8D13FBC99BD27393762504AC7FF22F4C ACDFC24F60E86AFA9F5EEEA3260FA150A6E9E5582F9A38E8C5FD1BBA E91149E86EE9C923CA3BBD9C9197AA777EDC9881E48BDC7797D78EA7 AB0F2653D01A5B6575EA262D6B9F8446F12C8829AFF4D0AB393386C3 4A4B7C76B561279B1853541F108C5BCFCBFA409B11BA8F073E5609A1 75BB5D721239DE7C62C0F7D2623F3AA685DBE9A68D46FC1C44C97E91 77034DE301246E605000F780C37A8C3C5D2DEE05AB24A14AE99EF970 3E46C1846BF4E0943D69CC6E26DBF2E6D8520199BC8722BBA0A04D7E 0BE38E5426E6321E87196B60827C152DF6C3FEE15390807E29DFDF95 C167EBE1C798AD241E0CF628C124390EC99A12D2787534E8A7F465D6 0ED174DDE1A549A6048F967E02BBD38507433F1767C62AEA91BADE80 5FBF81DC1016429B1781F5709830765152140780EA7AFCAEBC050105 577002752EBC5FADF6A480C39A400F2A4B4E4D3177AC56F977A834B6 1EC159E3E418B13C593BDA9D1D8ADF700A6E56666DCEE95F0D78EEF5 E7B376F3CC271FD509D6CAF1AAD7F8F39692FC9F089A0B602DA1F673 8F3DFE724AB46043196FF29A05438CFD3E8CCC758B3CBCA2359691E9 6B8BDA93456D8478FBAF17FBEE09F8B92F73DEB36686CD00F1C56D2C 0E8A622761467008E5561CED20783C8CFE58C0BD2F0D2D37D95758B8 F384D1CB53C0C78743F6F592CC12222E40CC3439FF88BC4FCE1F3F86 4490347717DB9CD92188282D71EFD9AF49A24AF48613CCD21E37FE70 3DC9EDDF154FB4F6E5A9AA1A7CF9EFAD397DB7D37FE5B5EEE0ED05D5 2A2B8A9BE809B08BF9E37BA24C112CA7FFB04EB8A5EBF84C8FCBB11B 3CCF5A74B315678843FEDAFF528B2819ED53DF3956BDCFDD430F4F17 FAE4F5DA66381F01BDB4173835C20FB5A53A56CFA9C2E7F9DFF8AFB1 51B99C87E4E664794463076F0ED01E753DC83F59E20D43F687794B73 C87943A83044D7A6DDA34F5E59FDFD08F8DA7F50F849EE986473B3E4 BBA7FB04E059FF72C0182D2D79B5130822E270317F17FBE2275F50A2 F267C0AF86262C93C08C70F40789FBA2F163680AAE1C441A5B473DA6 10D97CB77978FD260C02533D59A25B941D0EB332BB831128EE68C4C8 D132E35B19EA4CB70028611F9C94252323537E24DA9548E2CA8C753D 5325E9412EE2145DACC6E39D75D481FC06E21257FAD4EED7B6945D89 C4512BDA4CA60CC509551DCD36D9E8B43D3100AEE532848A82CA9A30 D280CB08445AC3703AECF12F2F5D386A3B530F7BEC78BDA5B8660C12 31E798170E7FC85E3731D95202588D386F7A95AC980318DD66204B10 CCAC46E3018485F06B99D315D9D00767CCF6BE2DCF76BA07A36AD7FE 8D4BEBCFFBF0E3F0F1E4019911D55E256D97899D2E2AE17047D0AE8B 33B87466DDAE25D509C118D843AC99DE2DCBB4BF65B5CB473DC64E77 03618D19518420A5508F2905D9C3E460F7A564DEB07735CB97B8CA7D 25EE81DA547B24B328AD02477C436050CEE4AA368EBBB8F6AF1E18DF 725BA14F75F0ED274BBDFD33CB70284902352BCC20FD778F261AB0B8 E95773CBD0C885DAB1B5B04C5B030B52740FB178984257519ECE427D 3E3B5CE6EC9D2BF2E3BA311BCF81F2F68FF2C60F18A7D2328C9BDAD1 6BA1804267DEC7594A0A202CDBE6B75A3D01B851322AB4B271DF7633 6DA7558E1B86E50B488D72C65BDEC1C8C91BEFEBB18A7E792645298E 0492842BDE70F404D70321191A05E7E18E88DE01A4FAF66533DC61F1 7B3E5C09BED484CCB11E4E9986247D417B7957ACCA5D52D8A54667B5 2D5FB7F86A498533B5DABA6DE302E3EFFA384BB1A7DC3D655DB991AD 96675C0E211A43AB076494AC22328B7AC6AF9F68B5D1B61E411E832E 20963A59AC3381F0F7B0220E9D0B7644C13B4F342F3D913C0CD40C16 6C8F205552BA0D40AA3CE7536A73F0E37C56F6CF6EC05AD23F4514A0 42456DA61A93C4FEEE283DEE4D06459219FD5B9CC646564599A8374D 118CF50126EE5750334EB053ED02F165D2088E931C448D01B019E99B C6278D28AD51707AF1FDCED96868DB164023B620360980F41B799DFE 5128743D9E846A93CC7E90AAB95FE6CC11C19A7DD63479A64DE91792 93BF80146B3843E4BF4CDD5862DFDDC1C08A7606D2F9581697154CB6 2776FAB5635162EF47E8243D82C42167E3A2D36CE13DC37DCE1D6013 B8A909DF50110A503BC53784EC0790A24CEE85349D94C8DCA95B5471 271A1BDDF96C9CEA5DDFF0E497F3D0E13B4EABEA8663ED398CE1B093 F734E6739B9B2A580BB207B29B8CEF0DFEEC03338F6DED40FC15302D 52CB3F9F0F0655461FF2CA6B478F11FBF5B818B5D7793E6D4395855F 14F8A9F1614EBE7C01653F784A5AFC96DE462284F3D6953785BDD41D 3DBDC1EA583B12A61AB17AC8827313B01248778F76F2B8B8FC6CF3B8 8BEB8D177531348A0AC0543BEEDD87DB164B6E8D791AA04B2133306A 93535726967986EE6701EF923C6C31B38076AC568EB86ACA9C9612DE E1B106E882BB11A46E7021EF694A16DA53CFFBD5D4D2FA9F010C6535 1BACF8B0DEF5A64EE32004FAE90F4E9F37809344E1BC7E695403B844 7C15B5366D1D267B7A21651E0DCCCA745CF75570AB1D8A57B2BB6851 FDD41904BE0200CBA44536E370E923F76BFDA60601E2E841FF09A689 BB648C39A2CEC056B221F33EF0C21178FEBF4E59AE1A1019918AB6B0 A2B491B94794F8FF121D6FCFEE902526F5386360CA48EF37FAC49161 8E7416AD1CEA19358BF23A0808D17F4C8526E524B02F76EC858D7F58 C081D84915CF7F289E3A5AEA019A4536122A50B21AF468FA23E709BB A3752D3592819F174A77BD95330F1734A60303F8C04B17C97E5451E3 B500F9706D53643A6877FA704172A2B04C0EF3CD5E8276184AFB11EF 47892C1FFDFD796D183DA535A983A76334E611D01EF57633C7C8AB9A 7E6194C5E5190D47053CE62DE7872FE24A536E10C7D9F4700F1793ED C71EAC3A4E885D7D34943B3E158B69378C2AE1DB1022D1F76167CDD6 6CEAA97E1000975DDAA3D8293AA9CC2122C9CE145974EB4C39B68273 06AB4631D12534497B8C10DBC0C3B75800A4F7E31F096FF1E3C3E6EC 6007B8BD82271E412E4894320025A7F2C37C555EEED34B433132B93D 780FB5CC7AAD11728E53017565BACD1FD26D078A1454A50BFF4D55D2 BCBFB9FC3AAA810BD848FC0C29CDA6A112162686CE96517AA43C0B99 4A2E95FB603EFEEDB25EBAFFA57764374E51D1CAA9B792AB922A55A0 889B48751F5E2BAF8644CFBD3C78AAE5C705CB8B8ECD507D79B14955 807565988F8DB697DBDD28AEBC2BAAF4B1FF54154F44AAF2F478548A E693230B82712790F3BCB0DC0913D4EFA562582C55D97B4000819777 23487B46B56860FC090AE27A01B5506AD351C283AE7908714528FDB7 D23653B710DC093567892214F2C9FCB716A3DE1DB734B49578407904 3F86984C7BF28DF2A21DD7CF926E8812611888674DE191CD2ECEE86F 2CDA1A5EA144F0BB7B76202D21566507EB386B0DE37CED06898E93B3 A69D7F5E8ACBD89F9E106B5519BE4DB863E4E332CAD22B5B9465F9A8 3AD5CDAF9ED1921338601DC36EFD67A481C145A64E417D122B2577D5 A4821B0E95C5E22704FB390B2DE004B880E885898321BD5696353A9E 221C9AB694797054ACC98787678188007ED2F52C649809234F5C8968 08703C5320DADB6D09B7ED83D955A3139BDB3DE6CF343D77BCB0C993 97EC26660AADC1B01BC00D005A5AB832259D00F6A28B5E62DA422D37 868237C75604E483BD5D977A87ED6095FC4604E498938B123C9EFE9E 93F8A2B19F0780DB7F75454BCDD36285CC994B516191645B81F99041 2A950FC7E6FAE28EFED0DAD9FB749EC7B82BF450283A76D627F911DB 39EA0B5AAB29256E23556A41629D5C39F721B13232A60B52581AB4E6 584141792C7CAF432E1DA87DA74FE9F4BBBAAC01B83D2EE2BD29D6FE DE81A2C2E894B993402C8DBFAA35228FA5F37C8B462DDA4001009E00 D06B10B2694D9099496C9D2F51146EEB2158A14068AFB818C1E28629 337D3DC50DAFBDAD00FF4C8AE6D3391911C255628B7B94E2BE41EC71 54E25208687E305E94A102BC83CF8156C3E460F21CC6877DEC8B7A86 8C374AE5DB60A902086055948B52AA6167CE257F5590BB7F1B38BD43 4F3B28278A4DA0DBC249E22987B7C86E491B222CC60431571B9D6129 322ABE7F0BBDC63E48FAA0C6F595CE02D93799861FFA16EE7C4E7E6D 70DB222CC7122ED2A567E596E20731D5DF7342CC8A69184C0B7DB62A 9D95D2EB893A3B262D03694492452340D18B8FA36D2EB728A13B13A7 CF48D3C7E13040BD20D006EC57E779DFF9AC004DB4A4408EE8640549 6CE288177422B222C186A3845C0C1E218D2CCB570FE29478DA4CD071 E7ADF135EB1762F5C66AE15DCA6EFBF93385236B82C84454ECF904A1 21119ADD36C5FB70549F2BCE09633094C61368F5DE53B22FB772C38E EF77A74FBBE1246CAD6E4EF3245172991C45D7DEAAB0C0E1C0A33CA2 297EB507A3C6833AFBC7B0A6AF1E101F19FABE274C2271C5FA9A4674 094418D5897D570F95B2483979E904ACA9EB76D80263CD639C93E6AB D84D0340CC3553735F0C068D653A274686A33264E85CE37336A8DD88 DA61BE72AFF9775E44D043B75D11BC8C7D7BA9C4934548446156BF92 7E8E070AF4085FE8A832E6BDB8C1A0361ECD792D8059B4F2FD3EB9C9 C1342B444F219F44068E3D2649536EFDD72EAB8B2BA7A3EE20D0E951 67DD263F2E4D3134A0A9D7ED987DCF6AA3C3AE8F295ACC75C2F3200F 5ED5ECB87E34D3BE0A052BED44089128AD60D4F00B637D5C1CA9DB23 67067F3FFE616CE6E9209BDAAEB3EB8F57C63EFC63186BE7E4E097C4 354E3C8E94B91B61166B3BC3D3978E720818BE12B4944B00F4A37986 73E644953256DC41FA44BC0824859493D54B3DF7DD9218BF5A0D5BE9 50093ED39F63832A82484B4ECCB02E1BEADFF1390A8D78037B565CB7 5F1373C9B03AAD7805A9E3D79CF2877127BA9E1FF84D66F76D4926CF FB1791910F52393DD1CA3B2DE172014C08DBAF02F16BFEE6F2A1F67C D69BFE6EF9AEC8DF4D725EFB693CAA2A7B744D749F545F8BFBCF3757 BC39047499829B319748D2949A72938FF0071AE3336334A981BE8DAC ACEDF5B3C4AC2563CC8991F7E5DB47E433646369F9D6E7318226E2EE F40C0D392F202AC52EE1B23C058206FF826CDD85BFF1D8CA63205121 47C3E41BDE7AB06D38A55648590F5AE5389ECC643172130E458826BE D9E11FCF376C019B7B9B662DD7A84F2CC8B06AD6AAC5353EBA572C4F 53D29381CFE8B8815D8889D9DA82118FEB52DD4A369848396418F955 C71ED2F568CB98D24C4C2EED1C47993CE6E03D2DDC4F6AB07F05E37A 01014CAD1AB3E225EAE6DA4A8CF665E60B0D45872DAF193A5FF85177 7426541AE4E0A6756DF40E89A34977DDB976C577366E38B922308E92 6DA7EFF93FB32CB6483F347F2CF97DA028A7973E29A324BE87A2D0A8 7F2133C9E49A7FA9543B2A8D0B1214E0560CC5D25DA0B843172D31D0 8D21D17AF073008B555E3DB7753B9ED413446733756CE47548109B5F 5AB39A586A9DDD008084CCECEE5E7A347489336AB3B5816E8993E228 8F8C2567F7D4288D7228CCE48C091965B45FEE766217CC45B7D61BEF F7941098196507F1EE8AA526A42873070111DE21053A22664B79066E 6318A8AD2B28A5790641130CF641BAC1E25496E33F3665CD317BDBFA 06794E97BCFA6C7F802DFE399A2C442D58EDCD7F9DB7E51E68E74291 0A0039B308B1DAA24B0091920C2F96AF5F1B893B145E833D05E51387 56D2B00262CB7DA3F29A345CC11ADB647D3A5BF300A14139D8D736EE DA87E390FB6107275F4F759DB864B61F2690A7C4CE05F8CCAC507F64 A494F1C2D13F5D22AF2A93B1ECE5BCA3DE764919F6D3D6DFCEFDA9F4 AB99821B5D1F2AA26EFE5F4EBD1E6448FD1E1809F68E48A44B12C5A9 1718A297DA0745A39F4C4B188C81A1112217C8F401D2C1A791942FF2 170B658A762A3E6AE768A209E38D2E150968460789CE3998708884E0 15A09D95B9CEA3D02E2D79D79AF00B90D5C261E4F558246F68CFF10A 8D84495040FF507CB9E5B9FA3E2E730371B667DE3311F441AB53A6AE 38A7FDC6D123F236320EADF7D9855204098A26602163A3747E8F23CD D3C140F4AE01DEB412E59F7F60157F5AB58BBD3147206B96D449F0DD D14C0D5F135E8DA55B451FB330B42B5CB2B4259E0EC123C3111843F5 ADE3873A89A2286D5B59B3897B49595962869F5DE3A5057CF15775F0 558DE9C1E039810239B9E2CA65FA6B435C1C6A972C12C74C5E467B2E 1FA78C5A7A45EA1687E7F4C5B8B6B2337B11E1B7DA0E3B03DE83FA0C 110F25624D75FB6154A1325228C82D54F001792B0EFF004D698F37FB 14B824063DF051969E409447D4990AFEC6DE3AD77E582C84DDD8F44F 6DBA17C79B4CEAB11B7189DB90B2DD571BE84557E52053BB7BF5482F E3DC1348D7F9581687195D8D0F9C834DB3C1F9BBBD53132E7BB48ACC 27B2982E1DDE1C5B82D5705D0CCCD02F8E17C2CB0B27FDD6346FBE90 B3D1DB5D8DBFC48CC3BD59CC8593B30A1FD2A23E0D27AB3F654471FA 980D2E923749EA3A10447D920B8A9CA77C4376DD00CE035E486590FF F276E3073CCFD0D45C548C746BB986CD091E82F4E649AC614C52E87F D8A8B8F86948E5DAA2DD56E3E45C7ABFC4B69A38ECD60596C21E8EA1 861FAF0DA12E7D99DA1F84F379CC686F0E3B32B9801F4562CFB0CBCC A656FCD6954AA720CF1995B58314F974BA9984CA982666629431028C E709EDCDA13DE3E7929E4587D0ACB7A4B55D99DEE00CB98DECF73F6A 1F1FC1992BBB0C3115B02B0033926B89A83FE3189F51390D0D5434EF E43096F6C287A0A06051F918BB48B5161F8C76286896F4577D76B385 61FC750972978CF1D5EE1D6433A97D9E709BE8FA658DF0E58E7BAEC3 4FBFCBF93DC6B7A1D1CBA86F77F169F9A9B60ECEB2EE503694B57D8A 35D491424190A6CF7660F6A4D9607EA70B4F0EE1583B5EF898DCDC82 6F0E9BAFB5BA8F5968DE14D0C961FE4A47C327BB14C573DD9051CC01 688D541EE78CAE8C3396CF35D8E7536A3027F4DBFF12E078B98FA11F D2545005D0288B5C57A854A3F8FE4D08DFAC51EF84D165B9EECF7108 C69DA8B9B0DDC294F651BCC08F28FCE68982394E92FD6E3ECFD242E8 D26CD69F898A21A6F476EEC6196074A4A401E57C1E123373D2C60387 78101FCBF6DD6024314EAC1A3AC562F5B756BB124925426E1152BFDC 6BDB18359FE3620BA2438034E4246572127B287F16059FA0C0F7D378 BF07AC9956138BEDB33D261F393368232EA60CAF6261FD3B4F4BF8B6 42540320AC98D3114AA11D1094B70778F0F889E09421009B0EEA4D36 B7FE90A23CF6C5ABC4078311F3C9BF3A3A38BF093A4B5E913B96922B 54AB0CB8658F73AFBCD2CD4368CE25742460E70F59D1AD49100561F5 32DD0B2DD8F88B4FBBAE7F3AF495A0AFC0B1FF9119F8BA3F982756C2 B13E970BA7A22DA1A80E05B5D5F836DE4319D5541C9DD84A50FC0049 207F35D3D470DC0D5FD84F2FE286DE12839399CEEF4FD9922734D5CA C4A5464A61FC21E9B1C5D48F7247E209DBEFA6EF4ED9743CFC8FE4D0 46F949B82B2AE4CDA5640D8D7C4D10735CA83AF3B6E592E4189CA6A1 39CF59D84E29044993D030824D59396514FCCE071980086FDD311A07 0154C042D55F63AA2B53B045458E619FDC692FF7DF5B150240BEB5D9 A94859D0429DDC7E63E7E77334783DE6F7CD2AE69DFFEF85AB5FF5C5 DEBD0073734A6045BC13A339596C19FAEEFE2F2DF20A44A7AEAA7E99 5A2E5666D23D06D06DC7C4D2315C889F6E5B0A3B8F9EDD732063FA68 5FBA9566BD7893BC75FF75DB360DA205AA1A474A5419F63E2983AE20 1AFFA9362910BA1792B573887A83497BB06C166D6A70775E07B21494 9003F9A017414BB67119294B3960AE2E1B8218112669F43907FCB364 A0FF799BC6C3F51431CC52BD96EBBD2E2762617AEC18A39CB47CDD49 2625ED46CE56F7EEA2238AFE29C27B269C77975733C1D037BA89B601 C02C6F47A62921F0921FB98C0B0D785297E67431132C3DA0B6DFF585 2F00E7E5563B90CF7F1EC86E193CE64F1634E9DCFF5DA7E677D9F518 3554B210BA9FFE473AE1157F05F0D830695FF56D646EEEEBCEC0A946 488797E934DDA791D6ECA75770633CD6F70CFDE8A65DCC0678124477 94E2F641989EDEBADA8811582E935C61B7C1F2C6E6D37CA561D64423 F6582B0DC20CD0A77401566AFAC743B6AC237DA980ED723B96ECD778 57523A5FAB5B078E9B9C5AB801E924F2A7F55E3A0EB3FCF54348E33E BFDC9D1B5AB96630C5F64AEC15A0F8033CD87E398A5B4088E10BD024 EA739495330980853245CF5F6CCDFC90F154972857B03A7BAA03EB4C 513F267A00565E3A7E61734511B3F38CD4858349B61C6F24B34F7332 3F02C57AB456DF142728D6A0FB7378E6B1BEE9E0F79E9AE3A4B9BAEB C7FF3BCC5BDD6C0B59A6971A3EEBB3271DD2053B2CEED6A4C6AC3FFB D20390064D48126BD7459AA31F5C576B82B93EF6C7A7484F556D2415 8B6F061EE683C71CE1F7F0D39F3EAD7BD230BE59A8F5AA38C1B6BDB2 A6341D02444DA8E010B2CD52F857FC7F1824F70A10CE6687410F6B33 E5A30BB2344D32A5644B694054E27ACF2FA6416E80694E355B829B0C 2EE2B2CA9EC24908D2D3F1C1C199844178767DE8CEF61482FF6D6077 5D9DF3648D3BD784D4378AF83E0D10746B64D2B5445EB38F80FA2103 A246F5F953A90C9779EEDC77E036420DAA0BC94A8542EAD9B3996945 0299C95A873732AA0A52FFAA8E726E11E7120E2805B40698A6B06A0A 05312FCCCA61CA85DD506C109E19BE7B57AE8CB67033FE2C2D13AFA1 1759C8BAF5FFF5F8FBA7D58089E9BC5C3C2BC37E4D9C4A47D41CC11F DF2ECB99652C81DCC099A1E977E7C71F3B0099A44D4BD5E6A479C3F7 D7DB6DABCAB0886980A74675592A1EB8BFB6DBC33CE0B7EC358CFDC7 7C00DFC14744E069B29AC7B91EAB4B1A07A281A9CB1AB90D98322797 FB64B1516A257627AB1C87D09E7F56ED5E216A879999EF857AA1C1B4 577D981147832186A7CCECC9E0C1686741304B7864F6F69135B0212C C44CF061EA743AD7F1DDB6124C095A7984D0CE10F64366008D27A2EB 9A480DF823094BE00D83F2E38B043D003B79F576FE8B84A0EA144BAE 9BACF73A9CF5E591B53517CF9AFFFDB100CCDEB7A0823FBAB165FBEB D986A9605BD82699E2E7022F96980944CCFC4AF88D55D75794F96B2B 8D6D036CC0690BF51D8D8D78F6C1BC2A520515A6F4BAFBFD9ACD3CBA 166804A7B80253F24503D9BAE6A774C5BE16E7DB0F84DED4A2347FD4 3A94F747A85C1FC487B9C8FEA43C39B58049FD2E54F1E046321E6947 55CBEC4B1F987C5470E47068C8EC5A81E08D495F8FFC8A8954CC1F23 6BFFC730E92D359E987B68FBDFF3EECB88473BEFA193F8FA3F975ED6 23BE3600C39713F6CF3CC7D55CF38A6DD333CE76D15E4898A874FBB0 50DD0358FCC315D3847BC136280A91720C259DEAF74293BA82690111 33302EF6A5AE3D640B00CEAD988E71805D5714E6903681AFE422572A 93490B20B9ABBF2A581F82A9E8F13D5D89BF2B3A4EB4E05F72A66AD8 79B590A38C2121602270555EE32E0845F1DD6DB4AF24DE314971A6BB 12B50F371D833DFF51193F5536206903F77CD091A76B551A2F0CFA8A DB9922FD782FDAFA235DA37DF81EEE601CF96A98FD60AED68F57421C B5B4C5AC0E628D00AB047874AB021E8B3577DC05D5F10F000019018F 3D1673751A1AA220756E5FF5202E192EB560E331E41471A47A42C5B7 4BE579B849C59CA91BF3E0A2F1EFA9362AA08E8D3008895892896643 434329DFCFDE3EC2D1430EFDBA50316B59E38779C7BBFBBE07CB5A04 A540C646F5101CEC51219B1E07A09872B2463A29F524072207CACD40 7E14901BEB9FBAECDDEA72CF683D04CA4E7EEE27F1F3258C108E6270 D3DF012065259540BCB9B4A030A0BC5874037AFEF6CA161EB235749D 7759521B4CE2E8B1F154BDFD74688B61762EE06C7456D132AF20B3F3 CEC654D43FA9E95346D977C733FAE94EDBC22C9B62D642723DCDDF02 2AD58A8BEB77126C1AF8DF6C7DEAD320A8EBE2FFD3AE76F6AD07B046 44447855E301A094750DC73788B6C51E2D46801ED40558E66AED0BFA 732A381BF019F1255EF7C5E2C247C68596D06E760145433A64D9A3EE E2F541CDCB0647061B17F061401D49D54438D6C53381A50435DD0038 5DEAE225E6D2365EFEE8164B729BD567B3435605C2752469C1824B2C 4995C7078086746A1B5CCAD4CF9862EA315049FB561C236F360070C6 C89FB15DE38BC5B012C8CCB250BC28F28FF9E2B7E2BB02761F8C8FB7 F3E170AE06593493AABD931E6E673128685EC38ACE2C7A61968581F6 B09EEF0AB22F054CBC41186B8EE853465EE31EB7BAF8D725CE1AD62E BF64C3FB4FA361DD4DD0A1DB75DE295C195968B1D4DD700BE5724721 B60013B5CB4664094C6137D7DEAD7AED2F6B3949864A80F4E443F8E8 F6DF2DD3DCD98D87474EFC2AEC2E9ADEB2D7E1CEE0870A04D4494F08 4B844432533475B3522B3709B51A9494BE94285C2A60A7AFBD570FAD 313BEB1971FB009C2E32F5D89AD2019F369AEE7C63CC50DDF1604C3F 604490D792AB81776570D1915801A1C4557B3D5604FE60FEC7B2D74B 907FC55385B0D92F736F02857F0CD36262B4CFC1EC3CF1CC696C3BD1 8D7D6FB54EC07F9AD64EF8F4205EE64633764C86200C97DD48AD5F8C 4346A9D434B5DC494362A16A034E4F4400F20E6AD6D3F79B532A8C2B 696852105C30FEB90BB018170F2F778B0610EB5B0D59E6E6C4F2B50F D96587E9F73B46A4ECF57607BF52CD7C05F790A76FE5713734BDB54A 37645FD5A22114010FDAADC9013932E4AADF0BDADD09193D2014E96E 1BC0137B382819D2941A8FCD34EA252CF4D863B33A8EE186F43A2259 5FD84E47E8F3D23BA60B719F92A4D122C445673AE08703A968F0145D E30F626F6CCBC81A361178E464ED170654A179A2FF84560D97FFD373 0E49837EA71C0290DFBD2D3BB959DFC0A8B2BA1AC7A9404E3D25BCF4 EDE38919323561122C295754666471B32F0A110C01802776C354DCF3 CE8D25A520375A58DE14A8B119B1DFC3E5AD19B33997FCFAB2C8D12D 64CBF62337B37C8CCCFCF529ADF7935977DE3AEF6F2341CCC5F95545 630FFA14603D16F9782ACEAB73E582D85F9ED590CF7DA278857BC1C0 F90BCF5A9D136E2363DA9C6DE091EA25EA4759A80C9D704AF410896C 909FC2625AB5EC578527320FC5AC3408D2881000B84A9F15C3166B34 C0C5193962F70C260B4B90B71860057B2BE4B00C26C21442DD155F6A 1B74F6BBC123FED8D806E0D3488844F1E3F937296C4D110F75C653B2 DB2978DD56C6A849443D623454465BF1CD37B7ABC683AB97689EEF35 B147C1C5BF01714579F1374646455C90CD04CCB40FB6EEA80586B58F 49D5A8A072D9F803AEC8A744EC570D64EB3A8F65D7A9484ABE50A240 6E0A87345FB415CA1C63FE082B3412EF0345BA0B1DB9230FA701AAF4 5C9B2B05933ACD316084BDD3F59BEFDA9B7A3E8B8C40ED537A041E78 C31DE1B104B3FEE5800BC8E8C5EFA07813DCB06E920ED7FD99008337 E1B8E3C9F789F81A430BCBC1AAF6C341FF56BF588992873068441BE9 662C5CF0B3BBAAA0F391921E792D44D0092D6217CF5141EBA59AA0BB E42A15A84D73465C0AA2B4B22A4ABEC7C8C4EEB4176BFB7A2E240DCB A57C2F8D4416FCCC11363767EEB8333340126ED94A3367E0D9926CDF 95340A7BAB9EB145920656FE1C89D70FBF3B918A8905C8AAC45141FB CB88296A286DF74F9C6163616FA2C502222F0F6B46FAAFA66366BF35 27451270FB0F93E70218844644FE8703CF367FD492B5B9470D4A3B52 97538F4E6928513656F960D41B59578E5B5071109D7C7CE6D9FAD1F2 F83B4E6DD187F362CB66212A0C4EEE8C4AC72BC9C65E4C5D812D320B FB6F717C791FE71B0C79BF3801EA097AAC1F4FF7CF8A2B30A7662C7D 65934201C6B103304795E918618ECC2D22C3F53DC1EE88738B175615 38B0B1BD3D0A3F7CD8CB7A0AE79E25E225EE38F00AC7A058653C2099 574B1724C6A3270BE506ED154AFB4F6F040FAA3C48701CD4E12FA1EE FAACBCA94AB0626C210D5D7EDD088FC4D4FDA8F655F9C1B8363E437C A688953AF2926644F1E8CDB71F7D69D34598B6BEEA3F671A1C970D5F 85F56C06CC72C9CD218D6EBFE5478F2F45A187353404C8484BC6A8A2 FC5476272657369AB0361000BB1A92DA51EDEC76653004393C2A2775 73F05ED450E6708E3A5758202D6DC8EB004D733BB1B4353C7B179FBD 3098FE467539C7414D6A7ED11EC35FB46B57A73F45B90A5042B44A51 83ACF28FAA4DAC84611EB07FB59700B14CE74205C63EDF329DEAC51A 22348AFF3FB7509619E87828B3CB4F036A6BD2213E32C0C9DE472593 2763B76F8CD20884E28B0C63446625C29F0ADA0821EBB988B45E6BE8 92228A97A5725D1DF726442FBAE48EA949FFFEF89B71279D1EAB17D6 0AFCC221D4E1F576ADEB025D0A41033CC97ECF711AC17FF3057D8838 2420EC045F81013AB9BD441606B282C6F3B94FC1427C18D947DCD875 364193C551E667CDC9E17F8487DED8A99A419DBD1798C5DE16035835 A78BA5A03810686A9D3197205AE34E1A01A6038E0C834D1104A151D4 9FB25851B74750785862A17188631E1F3D26EAF3B596414299A0B2B1 5E313D2F109684554A07406601BF3E578DFC26F10551AA6F6BE4409C C137640A37F5C5D664FA54C43CE9A2D89E00500A8CAC417F0DF0AE17 6E602ECB3033774F73A12FF5CD6DDF272C121C4D5DB01E14AAF14C53 60F6A9660189B7C3371A59B9F4CE1AAB0E926A05C60FAD09755DE43B 56FF268B93C030D4904B2F0F5351B9DB07A72511D004623488BA7A9D D9AF3BE9F1718F473E6BDA562F5A593CCA040D61B05D23EC05593AE8 F97A285766F99A6FB7636C8DB9C6BDFAEAEE5305E1541F4733CA6B58 5031AF83E139C38F0289A03AD13B15DB21EA0EB94A89C0684AA656EB C9C8DF0FCCE8E2B60F7A7CDB6D03BB0525FFD979DEAC326F26A22AD3 4FD324155E57920A6F8EFF15C4C9E88022E0C00F0919A10827E52AB8 FE8791793BC010B6C97A2083E59AD33AE602ACADDC49CE67FAE1E96F B5D472D87CEA78857C185FF052DBD4D6EDEC0AF6CE8AE267E99002AF 16E8AF1F85A7D9A040A0112EEF52D76A1620B4487349786676F94439 7020C071EDD06B1BE2B149C1D600DC4EC2491988F2961B5B3C54D29F 534F31B227BDBD4622C2ADE53F75D03AE038B39EABA343D169CE8CD0 47302305198C288A1A70317D107D10226B0EAAD2732E109BCF9347A7 B3B7C26B3E0A00D872745DB72F48A708B4D7350F8244AB91D5D68E30 96C629278F1B70B6CB09B55144039BB90F099C32924E19A062D66BC7 DDD1F1411274E59E7C0A965BCC87CD107A96525FE31A1F4D2FFE636C E5621A55E3496411A08DC86D9E05D197733B463AE2E0F096CBD0A26E C13AE6EFB5BA693848CBF327E40C3EE9658A79E46035397FB34AC4C2 1209EBAAC96EA35EDB264173AE3A99A9F1F6FA1A4395BD181F8186B4 70A1115CB3EF224D6C31653247B49EBBD009B596B92C09CB6EA002D2 5C9AED4FEE593BBB0F16C04E80A5816EDEE194985B3E92D9A0CA307E 86413501278DBE46B959317B27FB041CCD960138333181F404C346BF 706C4C6BBFFD712E62E60FCB5AA4671632909AA91BA4CF34CF335D01 311B050FE6F1A97D986FDD787591D97944E33A7ED5C70E0C224621DE 30DE8AFDFDD4AB2D715931BEE9A14AFFE00911D7C2A18C8A7C144109 4C316CC43CC3E46DCFD2D9A75760A347CB4BAEDE5E5FAD6B86A5B484 53ECA73F5AB138CB16925FC3E5F4A9D641E7B15D0040B68D5558969A 441CD7AD54586D42D5E083B3457C96B78F75276619876D45E9505274 F6C0014FA872DB6DD7CDB2D3A4F3FA2CC9F0AF9AD9059019CFF3ABE2 FD87E003861C53BE5F2C60F4A2B070F77C2E577995A521447F326FC5 2D80137BD1C37E9C8EBEBC5C535D313F8AD4E15346D858629B759BB0 E3D32E6EB0830971324B66767C3D0A536813F6899B0C4AC4CB05B17A 93C239D46379E3AE660BD771543CBE9CE43096B3E46D30816E620A54 29DA6B0C3F07A6DBC409B32C976AEC55199C856F2DF6B076457F10E7 CC358D07241AEE41DBD5EA496FDBE74478FD85FF4648631BBDDEBEEE 5B5A5BFA7FC67F7CC60EA08424C43F6BEBD8D3A9F84CD654F71B159F 0029367F4F13DFEE75A0DE78DC9C09A81CD5F1545C526D99D245AB00 380C961DEB2A31EAD63333FCD5799FC409EF7F879F361036ABD2F905 05AA485D39AFDA3D70850CA05B829080B9F509BBE4C9DB2F1648D0AB 7D313CA424248E869C22B43735642616B45292A01CE7DB1F9E9604F7 1A627559DE4E91600B3772E83EC4783DCF5EFAFF69754F0B8C048729 E63CB5723FBFD75CE026F2308C71F813CDB1A846ACA4E2E412B00366 049351512D6C4D69E266F2044E1638C8C2287B46A1F02A82FC6821D5 8031D8D93FA1E879787428B8655446F54E42F8438D3163E7784E5AB7 356EEE6E330B43CBE86892C5683B6383BC5F316DBCC1BA062A3E805B 2DA091AAA4B75A59116151038E46DF5467EF80B7C047F9C8A565DA2E 831279136A5B86B71AEA6DB19437D4B3D366653671605D6244B2BE7D 0CABB0D2B7516FCBED8E11D50E5BF0227BD5C90F53D4E6B154460323 A1CA5739D18DD50EED67FCE861399586FE0EC142E6BB5D426517A869 740AE6208A75B196EB61C75EFEB2BED0736BE74A4BEF3E9DF6C6AD97 904C42AE1A2A344B3C6D9301620DD86D00552FD2026D70AFE443C43C 7AB5AC247972AEECCA551186CF11D7AACEDAAB0809D5C7A3FC90CD6F EFCA458FDEBF338F239B2DF628FBAF0C39C742E7941E960FAAAAD857 50955F0E3D5A29D9415CB1D5F018A665B691AE95E9CF90A6BEB6000B 88CC5FF886D56F81F0F38535502E5D7AF269FB988D05AE1CC92BA397 D485404DE4BFEE81361A1355EB5393580CA7BB5E7D8B7FC97B93DAAF D65B6AC699FD61B071C0152777B89B8FFE8B0413D2846004794BA822 6673F67AF131708F6D3818C32D2410E2C7C5A2E53C3FBDEA32D5ACB5 5BA78C464147120E3B4BD25AEC1AC207D1D50BC18251DB79C44492C0 022E6A709B6A1E500F3CF207B1BB185A17FE29E49457467F9966B959 0C9D8F06D1A91489000887CE35EFECE384F60D42E5DF79BA4BCB3C52 6C9D9F00D18EF37A3C86377F3DC23F8E4183023E1F3A499508FAA998 B316DFDF25052C434096DB419DA17E1C9AAFB767A25F4C4098D369FA 1205B459C63D568985C959E2774C413E3F07A0DD295674C3561B7D63 6AB8C5252D57813FA17475FFA44C29799C146E6DD7472278728A7108 C6949A583412B6AB04C61A71C4D20D549312D280C90015CC4F0DA2A8 1CCFFB2C996EB3B2D3E61BA3FB2543A7D290F637F8714149C2C2BEF2 473B00AE18B2105937112B35DF78372DFD81555034C642DB14EBD87F C191E5C4CE134C94BE62BCEFC2E7F489525FE2ED229A1D67FD4A97EE DCAFD219DAC1266FD546DAAE56E0D46FC0712E48C1000423FA65D835 A95BFEB5963C6F9D4FF3245271C08443A1796767746B31CCCD75FF27 FF99B440F7D995CA43DFC9397E889A025A1DA79040903FB840C08A42 70EAC3AA3800B4A76C2F5DACB46A723667C289478A14BF83B9922691 FD34463DCBCB3D181609927BF831B415A9C7DAC9D9FDDD3029D51B46 81F1933138ED10ACE174AB3AE848BCFB545DB6EB201543C8E02E39C6 250E2088DF30E1F1CE534A43B71F88869CD657A2AD469D501E2AAB32 35509E2B14DAC47A34A518A7464E8F3C48362A17CD29C84638B6699C E87FD070D6DD5871654834F1D3C5F3FAA6ADF480858816AD5E076109 C5A38C78762E9043D981E794F429EF4F1A1FD9DE0EE383AC0BCE9F1D E7A2526BB140DE68643FC2A167FE19D637C5C5133C08141691AB24A2 D62324EFA1901F933DAE04BC0CD9FD35ED515C206D84D465FD6F8EEE D765E5DF1B1AB951B079E470F06AD449996BF3A2E1DB3710C852588B 8517717C7C1B471A7246E2597A3B9AE45B0D91140429C0CD3BE63E3A 02846C57443D64CD97EF7BAC41DEBC1F01D20529E50BBAED79D03ECF E2ABC34820DCA71C0318952B02DAFD08CFCF9895E3B0D27BE12F7C58 BBF4744808DF115D182592A855EA10E2EE226BD16896CD06E3B8DD5F 8225CCB90796BFA15E1EFA92697E19A8A887D208C725086C2C99F576 E60CC9DC9627736894C24D61DE8FFE7559801CFE1FA0A9333C796ED2 51B323BE792348DBF7B76AF08DD1B9EFD65BCE33DC03003449390158 3B0C03F2345E089F413C9AF5B7F6177D7816451D67AB7C06E97EDDFA 1BDC8498CAC4C914D56949EDDBC80FEDD3CA6A0E040CB0028FB98D8D EE20D6DE9574D28C60F262C920C07351C7CA300492B198FA880AF738 F5709C02C28694D97DD36AEC78EAA0008118C333BD2D87BF5C2E990A 37E74A18FBC9854A4E84F7E7EA11D724F44B67CCC618FB8EB65DDF3B 6464C38536A181D502EF617AE7CD74286848353031AEC28487FE8868 74A952623E8828FD6E457F54D82D6E42B8185B9BF0B194080AE5AEB7 E5CB4528818D6E7E8120F6192124CD3EB37F16D5C703F4404F23E475 17AA63BE0F3F690EF9CF742030C78C49574D749BCE2A11B683C70FE2 303B1DE06187B68AA5051B0594A35FBFA937532830755326F66AF7A0 A85DA7A6ED52DA2D9DFE3BDAA640F9CCDAD017A692C54C94B36354CC D3B982D3172E0049D2A08EAED97B665DA9AB2B1C7AC4F35D56842C23 82DD8E7FA6034528D22DC6CB353163C4ACFE65FB9D6D1AE9EC0D195C B3DC6E69541EB2A2FD2AAFF2C898480F56F3FDB6DA1536316E3558BE 99DABBDFF3AC094851B231AC5C38DA0BE56759445C9457DEF0919162 358D40D2459A1C171C97CA15EA33995EA13D59ACA27CE038596A7CF8 B6894B68D41741A16A6283CAA365383D005829D4C7EEB9993C45AD42 39A47C77D2D13A6968B0E7D7A98050703DEE5CA2130CAA5657945504 7FAA2B40CA0BD6F3A52BC609192E4718DE98AAC908EAD2186923A4A0 0A30430C811CDA380612AE0F7BFFC188EEC94B0D8042C5B404C636F3 65CB67927AA3E34A88731ABCCB5CBDAB1F0ED06A58AE06B696471B49 73A69F7D617325D2AF132C531D09F391047FE45A847165755D777AD4 C52659BEBEBA01C68B18246BEBBFED5F2AB0A9F6AAC6EAE83A6FB3EF E20FA2C5372932AE7986205ECE9CC68187ADABAE272C5435EBB0C938 3DA2C42128D5440DDE2EE847DDDD247FB2EEBA35479D96FE24D9AC3B 8D761B76DD77FE7F7A6A57170B17F79D6EB338CB45C3959DD1F98CB3 511E22CF57F13A3A08EAF7C5A08BC4CE364CB9BF9CDBF10C43BBD00A 8C992DEC55813D23B43937CE195CD48D33490A9C513263C3273D0F34 3BAE0494E23FA0D164D17E8FB65FE37423D5D5A63F7946169B7BCDA5 5D8CD4E25BCB09EC34A23D67419FE5D36E27992887A9B53CC0BF8439 6122934FE1597E0EF2CEA9CE8538D8FB0D7C47AAB6299222778C971A 6C9DE945F0F9EAEB3DE40FCFA5578D0EA917F5D38DA1AC99D411323F EF23D9088126DD6E9DE32AEAEBEE1D24581EC433C3E22EE1202A789B C0A447B71A92442FDF8FE581952FEA7383046526719A0B52F2210B37 20AE25C08AA8CDADF1A8CAF9D480851D615310E4AFF0CCF25D2F4400 BC0B32E9DF26B0528F995F44EF7959B61EEAFE90271F7BADC53C8B0A CF7484336F88FDD708F5D51FEBB18EE1EC608CEE42F556B7EEADE7B4 C3519F2B2C74259E41A9D2725E9528890AC11ACB73925180B5B72921 4BFEBBB73BA3E4B6CEB1E9F9BF092D20BC4642DCA9876400F433CF48 B0A22CE413F773791ABFE6DD3563F4FA2C90BC20275F1B3C6E460F20 3CFB17FF6C729036A96EE4037AFA701DC0CCDC05120167FB3926EE61 8D13F07BDDFC44D0E1ED392D082CEE181683C66AE1838339722B9C2F 6B3A8C4B66E49C27133B3C1A24B26064974ED97513281ADB98DE2091 58F9ECFAEF6BEE9BC2FA310A8C4FE947E4D3E5A1E69FB3117FC7CEA9 B34EF02D337DD72337D6831BC73DB7E97E0EEC37C2DE6DE41E9CB8C1 B470CF38D074DB911DFDD5988F9816266526B9C0C857B0C70BDD2FEB FA46C3740696976BB93E3323BB288334988777BF1472667AEB25951D 4BAEE4055C996EA9BB50B1987E52EE4A8FAB2280DD1679E037D77CB3 A6C82B0D195F0E9DC13257966D29336E5D11DD9B584BE0AECCC0F9E0 1C680126D630618DCC4FC42BE574470ECFC9A68E9D18A2B0148C40FD EC0C11D0E4141E1590C23BBF315FB411BB445920EF5DB6CB38ED2CC5 392F75040291A06A1AFB131C580E481ABD844482E3A53EB416215E54 548635766723A1BAC7246C02C342FD25CF680D5CFE2472816DAB546D C9CFA192C3B1C2E602FE87B7E6B64F288E62FBAC4A5EFB9496300C39 95ED7B80105B76BF7522CE26605B87F0DF6B098435A71EAAF1CC52AE AFB0B74BF6787500976BE3265BF4D44403C55ED28979A7A9770AA921 451528769E2BB344698B410A6D66FD9B6932E3E2D74D073D0D5DE770 4C38D5480C24FDAB10C9388CFD262DFC02D6D945D4C1CB13ABE06FC2 DD3273910B1ADDE85C982D0D3ED9E93D7694479B818591C267B9CCB0 CC4F7D973476AE8D622FAF2A837759D1C0BA9771707CC22ED5E7A609 6EEFEE61ED7C8545405DA40CACC403983C17EA620C6AA2E7E9E4395C 84CBD83A506126BE9CCE711B2BD83F806277DE4F6CE7C73BB4CF34E2 6ABCFE9B07EBD7E0EFBEBE91365A5C66446CC4CED906706D43F1556C A9A92804E7AC0C777AC349B0E093778CF278E191CC60475BFEB83781 9E33644635F5D422D0A6CA871E1C784E1902195EA4C16D21F268186D 35CC02B60D8C4FB8BB764B7A220101401A6FB1C46AEFF1C9777A6BEF B252A19D41543E4DF2F6E5021DB40CD6EB98FB2F788061F7CFA33DF6 7F3871D1CD3DEA5DFA9998946EC250F89EF090932B850450874D8A52 7E4D7131F4403783A1D814461AAB61AEC75904793FBA241CA0B04723 67CAF44FF2AAE947C33FCE5B9B0ED7D5304FFA5B35CE371FA5CD4847 B03629F31014BD48CBC32FA8847EC32690B5123F5C94EC0AA601E63B 4981BC4D2C6C0BACCF670C10B420A61DF84A8307DDED712D1D58E3A7 201E849A1EFDE6D9E0608A0D545F0AD897B5DDF1D6051E4552116604 602C51D7F3109A0128C3A6439A8365CC44BD1EE3AD461B36B2FC6392 2CC623D13D4F9397906E3D63D467FAA593765CDB77190ABC1A10C393 F9DCDF28E930538B7758AD608305C1215980143128138857DB62CCC0 BCB132DF5E1CD9DF969704AB715F23407E3FC13698A3CE520D3E861B 37B4E5B75657E49AE98E11561D94A5841D91AB0589063A09F7E5667C FDE1B7102592722CBD48B7053C6F379300D166FC2C415FD87BB0BF00 0B382E0DAEEA49E208CAA99BBFE93413113103F2D699389DF89AC43A E184DE78FC873BF78E8B5D7784304860E3D4BBB34AF21A5C075963ED 405E1B3C641A908A65394A11741B35DBC419C1A74E95662E769D8967 896A88F8637B15A946DB082543F06458D56F69361E913C907B9FCF4C E8B71A825AF82A05D654A642EFA96264C7CDD3116271D4EFF4771104 FB52D28E0A189B129C8112E2DDAEC629D46C392BE39345408163FC98 EA57539BFE5F634C06CB123F60F59216E0FC9884BAE5B81C2BCA5809 65571374417DE68D49774CBD0EB24AA7EC136B4E638BFD2F4B383083 0BE6182732B98C345FD7FCE1C023CDF804456E6F833DDCAAC126DFB8 E1F3A3BF294DDFBF9119AF1F9FAA2FBDD3751A17F1F6D5FDF003F8F8 D9A4EDB06ADCE6EC5C905EA4E0843814B2095E35D8531D33664BC720 0E01C0D193BC46EEA908D0BE537882BD1D448B49A04325CCCFD49E66 AB3283134861280C0F5AFFAB381B216A3E009CAA1BBED05E8AC76384 39FC904C24E1B518D66C1180F428032C65646D94150AACA07C3A33E7 A5D5201C01AAD171BCDCE2CA91C630E4080257FFEBA9089A0CC1E43B EF8C479E2B593789A56F5B95DF4F9E947C31BF01D85FC148A38F469A 022C1021105340199D37DE15026B849A263F0D88E895594901A00AE8 0EFC3C421D60B5872B6A9704D5503BBB8CE868A4381009BE99E6095A 13290159E2AF932FB465931984E3D4E24F210919A5497EEFBF5DA850 3BB8C4B2A0D99E424FDB4A0C716B694171D3C3D91F519F89B0761D42 D5F2FEC884C13350740F35DD8B3CE72BF006BDB1846753965D479863 899381E8ED53A63DF2382503E52BE6F676766F610FEB898574D70196 B4C8CDD8BC0E07146DA50F8BF3A2526D73DC3A5B21AA6E9F9536B4EB AFE0D4576F21B6EBF7ECE5E7A4088E5FB1D954C769F2C6109E8026E8 2161C144F217F028A0ED2678DFEB772FD0A04B0082FA8DEB751981AE 7A093988C4249B41420340375CA7C7C7F6D448F7DF237AF13C201E0C EBEE4914EC6A70D519BCDDDEBD35C38E37FBDD2C0E27E188DF01C34E EE39AD4E5462B3A99BE16037B050B18DA11DDC8B13A1EA1E2DC4CAC5 139F166CC9834B60BAE7C86FDD22C8FE7642C99A70971EC1D69BDAF2 31A1298CE119E220592824E13B798AFB582A742D0A7EFBDE3C24F93A 5182CEA371B3C87FAFCF6E1B1AFEB8945F4B410CBFDF96596890CFD7 1B1455E99821BE651A23E7FD0C20A98EDEA39ADDFF2576B01CC0965C 5A9CE4E69A62BB9BAF812B33D0CA0BCAFC46D95F6D8C574F492F7A7A 064FB98245D13D875F120FD9087623E837434032D086C32F64DB0CFF 06F50C0AD9C42B5A1125152E79E349CB69DD3D34359063EDDB7836AF 513FFF225C2153E088215CF07DDA9B72DC40D08C46AFCF99EE7CF76E 2EEA6DE403FF5067A18B49404E2879AE524E9DC5860524328B3CDA5A 847181C48C6E99849C1C237E53CFFC7762CD9C42D56E8F7D5F6660FD 33E3F610E1B06590EFD9A7049A8ED27EE52E5E03BAEF4AC0433CA441 7BA36DEB9EFF5F697F7E9123F02139BC2BBA0420162AA91D73C943F5 557F8F7FC499FBFB31906A59F147BA8D43C969CE9AA3733C5FCB3913 347292A6960B48524445D579B57F428AED99D4A04756FF7710EE6266 975DC4A160ABA4D9F1B605639415CDB1A877331F58A4093044A32D48 219BBF62F9F0FA1C4D7852C56344898D62EF07BC23939EEA10BA4419 B3253003079ACBD1A647276ABC929F3655B8B5CCD2824D3F3187C22E E0E052DA18BF12552EE6E0F2D3BDF834C3961FB679DB9EAE21CB2A9A 0446543FB2055B455117D6926948F64318E65406E9F3B641DCA9757A 6B1D9264C8B05947786A45FD3071B8149C984235E32315717997DEC5 FBD23D96A889035D419E534DD5950AE8D127C3A5EDB8AEE4F55B4B19 93C42BB071B51622F91570CC5E85E21FFB09EEDCC141A10C7D422B12 52D0E4D2670435F40BBD6E170DED4E9CC9DFA23456303838AE2180E8 F77D3C1B0A4C24D30B8BC0F1C325D9C7AD8D422904C2ADE453B3857E A1392A489AD0AB255259FD102D31AA48379A7F39CBFD3CC9C37F914A 998CF99562CF6B332C10462BCB36734FFFF19BEBAF0F3C5B153CA2CD C9FBB3615D8BEB36794F6EB17631BE53558120C121431D47CCDF594C 40941600200106D02DF2EB4962D1E1EFC34040AD301E7942A7AE6475 742037049E63580033FEA82A0AC72757542DB2B057F5358B35626918 56369AE66DFB1711FF957342ACEA44C76EC40EE5F1339BDD85794D37 4E7B31489A0338DE87FF1E40B2CA5906EA91EF1ADB7C1C5AE7B08CF4 1911FA9B70C6321C931484FFA9B5058905437F4E0234991A404A10D1 13361E9DCB5367B9B916A034A43DF172C82665541F04D4C5F00BFDA4 5AC07F39054682E295A1D9D3A0D31295CB86EEA198F1E41B4B0314F8 B87D2A80450AB5079AD1B05C35FF1473D5A91BA7293597661FA20AEA DAFFCAE57AB2EF23865884ADC629918E070E197EFC89CE5E5B7DCCE6 D49B8EBD227078C28C70238A5FFC011BD5452DF7581E88099DD72037 D52C2B76614CD160789B735A366E14893D0CE00C396471A902836AA4 7418F47B067B0B20B059B36F79A2A58D24FFC02E59E699B9B9A6ABA5 6980048CD7FCCCF1ACA6D54C11D8791293ADC2B8D434088FBD57B288 59BADF097A51296E695FFB2CBB5B7A63C84581A0D7259E8AB5582517 BD0441D1AC9821485444EE4B96F59EBD2229191B70F3FD0E93A9865E D6010F423C4A7CDEF90F82147062202A639C9DEB1BB88DBD32445584 1FFE4BB22E8F4641C2CB76F511257834B6780AE2661C39AA77322D4B D5C42F4257005517170AC9184BD49A6E9005D090260B0DA6020B45B0 905F12670666C59E0A9C90F6AD5AD5D9D8E11C419B07AC90D0A4229A 01932262E6DCD386EFC5E0F722E1D943727D1055B7EB8458F0D807B1 90471AFFC226C88676E8DD42D1C04B007BC8F686DA9C2C8F7CC5243D EE76136ECA5F488FF7F41F0470B17181ABD0E844E5758478D00A43F0 3B5E44F864C730A95C59A485AF034FD76A416CFC23FCD2D0FE90465B C5CDAC67673FC638C4C805297D84D2499CD43F668DB50A3FB1F138F3 8B77B60DD0F2E9E273FA2C3B5EDA2F5465C6ECEE1183C446343A6E1F 7FE96CFCF32E1D5A7DBC57BB78A3957C3B5CE9937F22D30357D12692 085ED0F67B8CBD2348371A5ED34CEF4E0AAF3E8CC67FDE4D9D791590 9232843D989CA2C276125D72C1EAED4A82EB9BF96D74690609C5FBAA DDDB9E7F3069AA0A3C2B9C61008B916BF1C864323BD174B0B71EB35E C9390ED1FDF3065DA917981435D1DB5135D7E3EB2458AB541CB0853E 208140238D6C41D0B56935BBDE440E30DDDA7EB955E7EB07F45AEB80 E28AC4C6B2E9E3E369003730CEB00102D3C8579ED03CE514B3B14CDE FA5128992DAF363DDE067A1DEAAEBFBD2C813F4C3B5537A59583D196 7742E7F0AD62735422C5E81AFF0E07912A210ED85F79E061273AA7AE 5E32689EC9C87A3BCC0E8F5D825F25C4919420C47A4535630F8871D0 A76B526BFF22A3978FF61FC75F9C0FF9CD7CF840D4C1F0F37E643D16 E62E7500A29344D69817AF3C839E722F32252AE14F93353734BA946F B7985FA96F459EA65C9EC94442EB6F405F1097919FB892E0BD7DF0DC A04C41C59759F62380E5BF439CC05C3EEB11628431C44027F494D541 39BFD38934C8A08B724EDF3606D6B6359098325A2799F554FE8599A6 B74D81EB2CC70ED7035B878246FA7128652175AB8775F07294A83676 587037ACACF5F5C83028AF110188D19824C0EC1948D7A6CE803FDDE3 0C11A760ACE49DF1E8C138160004095A6E8A8F20B3139CAE9E1968A2 6D70C34AB01C05B26F1757B22BB1B13AB16A73EF7CD495571D436F71 5E20B66124CB5DAAC27CA33898F7E24B5B349A40C1886584E31699BD C3C67FD07D3100DF15EB9E35D168B72681B74A8A40BDB8EB8E62D1E3 0A7179B7B755245F4F9C72E3676E0C5122C0AC9EA955702E90451070 281257B040943ADA79F84023414AC82A074809B43D0EFD0B7A30E25B 1300D898548735EF3C1D2EB412F7520C1B06291AC7333DE55080BF6A 541AF3D4EE50C1FC507DA9052ACDB7DE663094BD53FEA7743CF10A80 BD8BF14269D2D2994F13DE0C810AE6C47B5D6A4CC05DE86695A9984A CC560225BD62DF0DFCA5C6C29DD1A67352F6AE590896B8FDB6C1A710 7F19A0C2821D3D99C2D1F0F47F36A313F2317E38A8FCCFFCBF53DEE0 2867D05CF0E061DF2E15BFA0F048230208434035CBCA81FE29AD9E4E F0503A7BD987467017E1860EC56FE01BE07F3B617288CD6FC7D83874 7EEF297C2A1B451D9A6412182FDAE162DD959541DA3F3025CD05897D FC00D0FF54040F107CA5FBBBA7F6D891AEE880347D7CD5DC8C4A4DB5 0B838B4A60ACF965B2A9E669A024B2886FAA5CD3161B24E228E6181F 553B12814C45815B42763664538D9E5B24092F36F972F7AF849A2B92 C75A31A9B9A8EE9D520F22AFF3986CFFC7DF7B1959B313EB8346E336 B612264D9884632336ACD303BC2A3772BA3FED7C3388984FE4B10CE3 A6E8CF0000E4C7657B989735C62A0389B395DD39075781DF21505A2E ECAD6782940C2B2534D602BBF09BED5033DF4F797E9A41821CBB9FB0 785E41F6D59652C96C39FEF091DDE2DB2F4F656C4F125FAEFE2811CE 658BCD1FD6F3A4FE90898BC7456B05A94B74FD97BFD00414425B9387 5BF4ACD3FBA06008E77DE01142D737B9AB1142A8CCBEDA8686F18E2E 3F11741A7A1B66BA934D5C737D13BB2804AC7D6EFE8EBD2C24EEEE2A 309DCA022FC8CB847B21F6D8FE0647B3022EE76264788BFBD609D396 61F59C0219764372E19B3DC316A99A988786553D48C2AC8E56F4EDE5 A7044E9A286A417150DBE9CE80A34C703E3568FDDD2D00DD499C3219 15C77BB1D21A8119403F65A53486D7FD6630CF54DBC5B37FC9F9F610 C707A573B7282C829A63E8458883A959E00B054DB2D16FC8FEC6E87B 0DCC37666E796704B1FC7CCB348364F103EA04ECEF12179C8EF9F0FD F0AAADB8D19B425587C3A49250456610CD123EE01C2270A45E1DD7C4 B11738C02C394E5A879A5B919803856B95D7A2543D200F3949CCCF2E 078A11F186934F059E664C4031B27DD42280D90116FD64A3EA6A0A8C FC8623CFEBABE8F9B827E72042F1F4B1C21345F4B63294D764E14F12 003A8A8A48A80DC1D4700696899D042475F4C1947EEEF5B7539B9DCC 334B3D63EA1C6019BD27586F8E9A216D960599738E35E0273E051939 ED91253B108ABC058F8C7C8EA9104214E5EFFEA4B0C82E116AB82CB3 9C0B5FE8D3C291B5ACD370849FB787DCBA0E274E5473ECC9FABD1BA4 52DF90FFF45344844ED5FECFDB1FC48470BC88F3FC7A41AFB030F4C0 9159C5BE9452FACFA507B619013D52241AEC38AE14AD4B7BBCE34696 892850A5F3C84EE901912F6154FB4EE62EFF8C336FEF6D51CFAAB514 9DAEE26A235B8039C3EB5C295735270E98AAEE1FB981772586968E5F B50F535EB75B37C044DF1117F40CEBECE416FC5E6FBE8CC7C0BDE053 73D63D65B7C7D54F10B0421D3195CE2886945003086697F837475078 8BB2A4B741ED5B159166B27A98F80ECEE8A3FDEB5F8C3F18294877D7 5295268E8233F7B406BA230AD904F06C0A586AD8725E9C5B70EA59DC 91F0A74D9D54509B9A419BBA2A27BE35A6736B9B677AEF1C030A0D4C 50C93C0D6E7C823975C087DA2B45172B6D1268C9ABBFC2590E1DB3B7 563617856526015EB926CD99F1A7CAA16833AD364996156C5514B79A F5E49825203826E7CECA020E628F6434689BD64D99007F5A80B79D33 5FA48FCE4D30341E06D27AF4A23C62C611AFDB0136B687828E03A4E0 0303F1CBE91E83094E837B58A8A77888B522964AD29748DD451A464F 6998D08674B447A9F5F371D12D197F6B3B650AB17DF4D2A66B6838EB 918FF353DA90C8E8E40A717825BEBFB5182ABB212C0C6C637D06E5CE 588ECED411FF0BE5427995C2AC8B3AFA8C09B453A576998A97BB1142 B0553E617E6F8064F5A7A6993C8021DF7ADF633D138D865A5B31D610 F333DCD85ED7EC98F3EC0AC23A4929DE69822C6A618994946E90A8F2 E40D51937B8A224BC52261ACC2F52332121991141279F7F3B3F8F6EF 74B780A259E7D67E6768A163683892D5A1D580C92E152A0E74268896 256EF5B8780DF3C6407DA5D962431D2531C24F17C079D27663380A81 9E7F34DC7805367E9BD7DE7DD10B03B6AEC312A16155E3C30307CB2B 4CAA567CFAE5B5233A7F2068A160A3CD618758AC107C839EB0090ED6 C95C037F20A8FA474A3370F83F6D6FFC90345D6E667B4AB3BDD77DDF AA8919C41AC03323D6FD8A20FCF8767BAE66F32F34820BD3E221B09E F542881EFB953076D2731EDA05ED1D98BEFF5D5E65BF60DA4633058F 029AAAA24838F500DB30401E8364DBDE335B50FC2858116FBF432CD2 94FA90B2606D4341CB27A1ADA1A9155A3DE83CA42C296C7A63C71D9F 19E0FBACDB814CFFDD13F39817B26776A2CE6F16D9F42D4D9548E8AF C89C69A89E993A0EE84DB1770601370532BAD928414BBBA386A9841C F5E4014212FDA34B2A8655BEF5695FE90846089E03201B75AAD11D06 5157D5DE991587A2608F780F7572B890C7A625727F1ACA828015E8FA 993A69DA47C04DC5D4D0996C33D3D7CC71640F8D68DCE4F18BE91D1E A2B6216C9A6409A633CD1EC7EBC6A9ABA9EDA8461DD9BF84DD6A1501 65FEE2A177948D523815F6E59D14789ADB89D3F66D383E8A76CB5EBC 5ADAAEDC5CFA373D8343434F05774DEFCE89935F52E00E7728022F4C C0993B56C3F1E295DED438B94937DC889B6EF5BF766853C3B1DF3377 A767E8FC823A7FBBA0B10388CADA8B2EB8B95E3F0DE6C82954801F5C B186086F2B8509A0855981D729E6D30DB04CD14816D49719E2632A17 FC4347B9223F2F8CC53B30D5100D44B73A3334A6D09B26768A8BBBE8 944E3102AD02E03BFE383811EA33DF134D49BD468D0CAB8C5CBFC6E9 FAE490CBDE48DACFA1EB50ABC990FF18A27A547D1A0CA01047092B5A E65B261D302D08DCDC68B950E862EC5387F14F93787F92C6BD83A0FD 71E68F5B52A1FAB2B3AA24D140417820C6AEAB4E47E377C6F1C1BFD8 B026CAD25C9A85257C1CD506DC1B64B6EEBF9FB43BF5F2BFAF064AB6 B2F7B88BF47F33DC910B58F70DF314886FBAC6DF0001D07290EF00CF AEBBB85F6EADFFC37195A56E591021238830D13C8D3D15D6F0D907FF A75AC3550E9579FCF1468267B39CF88071444AA4760AE81272622229 B101E641DAF041B03AD672773C2AA190150D82A36751AD479BD0664B A3A24BB7F512B4C381C1139227086EFFD89E2BEDE2D6A4B773D4CF80 FD47C8653E82C4E815B263D9CBCA16A73BB26CC0110EB27FFF14D484 3F4F220CD4275CA4DB009D0E84B88F099FF620E4366F236FA4B901E8 0FD0F0BA1644441492781FB7D0CED88824E89BAF97371D2E2628C023 209AA34FF0BF775A631C0A4EFA797EEE95C056BC5D8A777F23D1CED3 0DAEA27D7FC1AEA65AEF9D9FE614608F2C10136A5898B6062D8E67EA 4A990C6051D35FD493B61DB67B8CBFF577D02385DE5474DAFC7A77F9 94A4A202BB8231147BC48428422B0C83DD812DDA0A734860DA56FB2B 33118FE4761DD77991FFB5EEC959359A1173863475523751C814765F CC34999D896B661AC2C4255A739DA44ED2930DB07C3205E5F9DEADA0 D03A844300B029E83FC09B54001D2DF2C7B429D75BDEF94E8B742932 CE08BDD43F995481EC91ACD2E6329CB4D52AF3C0104A2D75AD8A48CF 078AC58C34C68545B3705EEDBBF07106692087ECF206DA308F0D380A 083FE85C00668D2D24CFD46B1E649AAE5CD8BACC15561D73E2A70DFF 2A8991D501A632EC0BECA18D4AAED1CAE8698C448E265E30D4A2D5FE D417FAE8BE697F806A1B6C7343B1F27842F0C6AAFF1E57FE911E22E9 C140E95BAD02AE3932CB67755CBAAE80B04F51F16CDE511D4746D003 B8E32F08ED60BBF2B23D470CA8887100484C7035B166046BDF37EFB9 EE219CC279AFD2D67FAB6B513E939F8AF616DA4352C0D41FA58542F3 E2DEE21045503EB27CF2ABFEDC38A0E1E0D16A736262B49C62BC00C6 99D9828DA30A39226509B0A8EE7B49D8041776A4DEA7E2176080C2F8 45FA73505693B4043545A949276A9C10ABF5326C1C3A715B407054A2 FC1E4CDB0BEAF16B0321B3ACF88F403C36FFCC00FF6B3B7250A6AD16 51720E923E25A7F74AE64D3D1BE80BDF917BF26103D72514362C2F33 CB3E053A704BC84AB472B72875DA0F9ED556CCCC4A631D6FD3F69535 8F6882AC54EBB7E5A3E6254DE5764AC671CDE8AA32393C7E8537D446 905347E723E322230781AB9CA9E4BBE0CA57F769CF9D081592F5F1BA F4636D8AC9D4C6D799189B42A1FFA321FFDF40F3EF366F858565E9DF C6E7B4F24CAEBB851E9B9262A0C15E9D762A5FB810E7EDB02A84607B 3C4163CC6C6073EC86F6059FB8D99438AEDEBE72C2E9C610C61FB4D3 F3A7D8267B3896BC71C66EAAA62E5BF4B8E08BF9AEA839362030BBF9 8381EE0EF98C659EA4702CDA5CFD09E4119FBE6411D7277ED2A19D52 8B5599D63E655508D2F30B9F4B1AEA1EBCD02FB6674A46F1041F69B9 9A914C828692FD69556DB3430CFDC927AD6B54D36AC7846CA6300C9F 9C67E94360C122CDDC65D58DD6E5918FB01739EA99414A71A27E1635 05B38141BFFEEED087C7F4F7736305CB1CF2FD867C0C5BD6CAE0B0B8 5096768FDB5F5A589ACAD5A6F32AF707C1B3F13D199FA3CAFB6166CE 6BDCDF9B8E32E1B654F28721CBFBA93EBC1FF077899D43F1B94FA04B B19858321825B1749CBB3A14FC0EEC06CF47EB8482065C393F940964 35174E8FDE959ADE68F4706793D264E0F395500E5D5498D49970EE0B 7CC9FA65E0EEDF8D149EAB53EB39DA143896F63E74ADE5D25E680AC0 40931BE13CFCEFAD7B2EC72B6A600CEADCB964BE5B8F4855578CE89E 549B0BE175655EFD6BDD65B609F4BE6D0F50FC1E8C9570BFD40634FF 3C048F9AE41F035A9C6104962B612BA966A42036468165D6F36FEEB1 CCAAEC8B6F875AF7A25A756DFCCA73A7D3005CB5CDAEA38932C6D2D0 8E2F9F994F242AF5C008E2602FA3A899EE9017E03FC785B14B3EEF94 7D052A420C08F3CB4C38982581F9C648A9A10782E08DA4D2273E7E58 FC62F58EDB673599DA1B2623076EB1717DD43C37C6B7BD264C8D8BF7 6622EA962DC883845265731D8F52E350107EB2A99DC5902878A4C927 D62D735DB14F7A64BFDE3CD3EBE1069F119BF042263CCF3FEA4E8532 2AB0B2BBE85F422947542FA19C5F6DADF21224E8CB1857616133518A 7A9EA51F2CE7CEB5FE34D21C906E8CAEDA6683F24648714C16B10743 65811D3BA273FE9C6DC1F5EEB4A4D054F8AE4F3DC5BA11DB27CDE3E4 3AA711FB5826773A798CAA3F4C89C68BAEA03086B33BE4B309155147 D0A041BA2D167E5214F98B1DFD615869906EB7121FD87A006E915C08 44E6429C0D33CF38AB6DD15D65DE8791DE57CFCF44CB72168458B579 4D269722F3B5E62EF70CA375A47A02608767EC866C76DF92BAE24693 69A708D8751AC546AEB83B96A25A05910786314C1F4B70D386563D35 76DD76F36AE6DB2EB1C6C689470D22BE69A2D8E5A555302DE90C95D0 1B60E4280842D5244442428FEA4E66C379B66833B1C33A78E82A1D3E 7C58F85507E74D9BEB799A6C82DA54C42B61B457737D515A6451B061 3E5E9F211A8BAAD0521E744D1BF162823ADA566CF838DA5B9E24BF53 7427036ED1DA1E22A592884BE2212B599F374FE89DB77561A9D1E962 180D1A399B30E2A0CB587BE0A89913EF46F8497AC202BCA8279DF44B 00C790F9D8F960F6DC8FFB68C55DA5BF5EA94CE5978AB72F42C7A598 34CE133B3954448E4CF35580272405377B8C7D8E4DDF8C2940FF9969 75BE0086D659DF8F80C06A4872BF7243ADE2AA7CB4B8C7682861ACDF 7DB34133E75F54312905FAA6DEE3090B18AC993525C8D73B3E03F4DD 6C56DA112DE976E7BC66D0674E907EAE9A87B48B3ECFF34A28F72224 E5C40723CD68B8D29EE9E8FAC513987394A7D352C3593063DD2C9738 F581F9B2D9DA62BCAAC80AEF3887B50C1FF452757AE4C3359CE43BF0 6E9A2E8472C11049D28B8F192413E1D71EDCA372076E17E25BBD0CF7 785198DFB693DA5C0934B38FA8914FE39459ADAE99063D7A032FE057 259C59B4529CB9123EC4F722BAE2EECE3CDB935B1988C5AF5ABD60D6 C81BBCBA2C6A95508C1A326B373E1076722A169FA0CD7E61FCE7251E 3C3F23B0E3A8319D094EA5F3826983D37278A8D4C8B55E53D72C13D9 9EAB19B4E4A73A134854FDA9A7846A341379C7F45087F19372EDCB5C 56A22145AC925B530B94A98E3FE8E0264543FDFBFD5882DD3D0EC7E1 68261F6752D303203BD02F618C7E0ECDD0B547E6A7A14B0712721FD3 23DB9B4446B29843F2B48555DD79ACFE9FA9B99F5FD2CA5D0A7DFB6A 67942E8AB05A399E1B453B0F044D2823C29AEEF6D1D41E573814535B 02BD11A664F1A99B8B6A8F2A27C46997B087E006ECBDEA939EBD7569 A7607227832F9D2C71C750061EF132BCC8957FF61C2ED16130475272 D92A27F9A8B2D2973532AD7AD2735DF45B8D00F138B7066ED8B35702 52732317BB95960CE831B7A241B6F24B417D6CBC4A646AE3C9BC9761 DB05C88727979F305F506E42D02D2E260FF074E0F6470FB2B59F5195 F631AD49EA2D99CB4F9F1B61741DD1CA696A11FB1233FF672B99114B 9ECBF0463B0AD9E23AD6F5CC478725F377C540B5E22A28FA9E97904D C470AA808E7561A051E14954C9332E955D5BD699C2AD7A81014D67F1 8C040FDCBFEEA1BB54965680FDDE66D87ECDBE20978171B8FBAD8825 010B9EF8C35DB3D238370F8E71ACE3AB9084FED24B3D5A640962944B 086709E28B08569036EDCFFC0146551E3563035A3451DB13729EB19B 7FC4CF759356C985B4E0B201FDF9D38BB515F7C097991A402ED75B30 82F3D008C28C9787F7AAC141A86C2F5496B7BEF71C97BB2F7B83EF46 61E938151F671DEAF116C8EA2ED81E7EAC34F08ECADACA87303207AC 889699328D38BB3216670F7131B2FD271D45DA62A29E8ABC019453B9 CB78C7F8F9551C842E562BCD120BDEB148B662E64AC469786721608E CC6E4A060D762FD45866E4680C1F79F9F0E9865ED6874D1099DB9DD4 B4287AE38DD74AAA414D1A9B096C771A34D85AD47A6F81A2DF990BEB 9B60D9D0F756BCD4677C65B0E44AF76EBAAFC8432D163344D3E90786 DEF2D86203FCB4AF72C383257B0353E75FDEDF6090A9714FEB34EB93 AF5CA7B6F535AACE6ABF802154747F4A6E60C062386CCD3C265CAD4B 573D7167F30C8F981D605A55EA2C961F2499AF83E66796058A184D6A 4626DEBBCE8F9BB7905C2E4836AB874F3E13FBF9E42EE9A7BE38A4F5 AF9047602A753F85D767C266E5050E26C59D8ED651029E80C1954C05 50C2DF9C1A8FE1BEA4AC26FDFB53A9EB04111D1CAE0AAB623EC16FF6 B858E6AAFF69129931E4827D4A347E49A6DA79E8B9BF6EFBF534954B 17D2373027EBD43FEC24B15D62432CBC1E02A666E371BA6C45B6EDDC 31B1F9D49C0591371BD1083242487379CE8C5825C246A5BB703BC694 F452640C015C313A35FAE0EF721746827B59A825A179145FD7B0A3FE 2764A21FC2962F705CAFA1A4BA334BF23E158A06DF43290EF7250B50 DD0DEECCEAC2E87E0FC964AA4F917CD16A1D9B752D7635B4D6E10A59 34C080F2937FE884068D99BB0E19CF20F23EF214217DD94A7837A108 5F528BF97E41629651BAB980A7CA3619B0105FD4CC944D37CBD261B9 BAC5B8C8FC21423F259EC3E32392C315ED607182A4A33C6C5278938E 534F570084EE95497BBBF15AAB9759C1BB2E4D67E9F5F8112EC75627 C47A78D27E84AACDB4072FE1F419EB4795BD0D400CE2BFC84A5F9621 A3C5765FB5C078BF8F663559F60812D99FB66A9C0F3A7D0A7FCC1FD6 FC3D4FD233E447F883F9A94645368271605BD679A47DDE00560C7C9A 1FB228047C4E153BE666D5E851C1D24F039E2D59A90E6AE9F9B355AC 8789679061B875FEF53A11456B664F0D311D7334454D5C1F8EC7695F 6F1563671AA29EFB2655C85E263AB1BD71B631834BD87553501E14C5 9B8144CF20EE7804031AEB1AEA1255BA64E9510A2ECFAC608882751E D574E6C21228B9B54CAA4442A3C58D723F97445A296F98D788171FC4 E516CBBD6F8F5055ED36E59558ABDE1FF07D8A9134409A38E35AC02F 80F71FD7B7B0FF3CD89EB4E595D2A6509C2EA0F9A4F1037AA19CA7E8 E6A73A1B2058B9E265951B7E911762933727F083463E4E5668AF8DFD 49FA6D52BB556788D28B004346597E76F5CBCDFB26CEC90D1A60D84B A0E8898F8E41D20FDED761EF62F42247A8B055DF9819719E8CD6335B 8E4F37923A250347057E1DD7A680E205B5BF3D3069E8C9766A18EB7C 78F7FCFB8FA80949A4BB08AE1B9C5D510E14A2B5289CD975981BA5F5 DB009C1638646F75BA53F969394ED5CFB9DA72AC0B01FDB9CE377AEB AEC33B88ED052D67BD5D2BC60D3F6B19C408B661150FBC7335D17A7C DC955079C13B88C59F68C594BAA601E4D8996ED317FD900F28280261 CF74ED5DF089961F8A2EDA457DE8A99BDF34E4D587FD1571306CC78D 44C8D6493B7717B1384997DEDB7FD787BEFC843054EEE75E21590A30 63797DEF0CB04D63DFF36E7CA8B9E983DA41006F0BCD2C6FBC79B638 DA293DFBF73EB5B1C85EE8981A84FD25BC65649FBE8F8BDE55661CE4 66B8CD2A4DD1F4C4C9753E6C8513ACBC6A1B42C3D98A01667D4EAD79 AF8C6F8E3CF159FA77E8399D7AC470E0F83F9600321D1CBC9B03C4D3 CCADD54183A24ABAB381A5A651BAC93624F9AABBF2C9B823D6828D7F ACB4155423B9FBC17145352CCBA30B8B409D25FC6617072F369D58D4 BF543806E81204D8162A4B612F4428667BBA350924457BE6CB0BBC6C 3A47C60255158CF58A17CA4B9878BF9D63D474611DA7F9677C2F2857 07B90EB1576D799BE450DAF73ACF59BAE5B08D0FD3AE1594A4F41621 55D5064BF76C11F0823A37986039C3C71D822142AADD2ABA828AB63A 839ABF5465761006A8099D9A9303E129C9474C273DC721BBF5DAF9FF ABBF2AE22344D46DAA398AAF736E78F82CD072BE69D1129C8CD75ECB 3D9AAAA28202B6EE2F2FDE58359BA2F67DA7E35E8BBB3EEE3FD84A96 FF9A746AE8D28163F86C5E1D875F4D14F6965AC7E193D4B620731772 A29AB5C4A43F78184CF21C59ADDB1A3EF559579D94C5890C5FF2812C 4CE552A6B657EBAD60DF9D721804A0AB68633DD0D5036670128D6853 CC5FC13E64D37BD6DB01177F916D108BC7996DB91E9D2592A8AB1CEB D7E20C904E4EEA1B6A94A1E33CEE5FC3F36B89E3541C66A8CFE79948 0E134F86010170CF81F4659A3DB698B1405135A2EA171FC04104D27A D12D2917C2E82C81D0A3A2682F2D4B812203DC4230A8EA950502B2DC 983DCC1AF813854306B1F148DFF156FEA2FA8F3DCE4DBED065049D4E B7A08F550832D5C08294645B093499D384F0D3F1ED15811D958C47FD 4377EDC7E6B742969802E17A92EF8D02E0F421F5E03181DEAB5F4B78 FC5A6F42478FC2C1A197017078493F57EAFAD29F2B3B1B7F5CC7E77C F28974AC9CA06FF329B73F5F856DD6C0D9F10643AC7865FD045FA861 B09B6E0FE10F280B5A270D8099904301C5964E0A6D8197700438F2CC 67AE69D2D2A168C3CA11564C7D0A9A2975B068683275C05AD633381F 7905940B2A9862065498C4D900FF82A1B453AC584196DEC3ADC1C79F 3ADAFE12C0AC943AE215A5D43A6723B26D50E9FC116761CA497E23C1 11A58543D971CFF43EC16C72ED9B075F2B9076D7644E8BA30A0AC3AF 89557DEC6B22AB5BC084620223376F5904E138B9C5C3E5F40021E2E0 2DF7755E7EFA268F8C7AD5F21381ED940C0879F16B22DC27461D742A F570348222E912D56342DB6F9FB0270492B67486DE15142839817F2C A7551E518576A3725863B2A64244664BA8A3D5EBFDD5A116EFB6E155 7C5DE44D5D24EB9FB7DA6C9470EA52D22343D5D483D1A43BBCA1D87D E2D4F9FE1921BEAEC00349E6165D009D6D7B94290C4B496586E251F0 EBE3A9279F2142F064F1194C744A491E60D5FDC748E7FDAC3E26FC9B 467536AD4B52F079E0A5EEA8E8118B6F7A4E468A8BAB55ADE9F58675 341C24A311A4900033D67CEE0313B42C50745F8F904480CB1C902B2B 323629A35E848A794863ED560DBC9640C4883F823EB60671D3BDEE51 B7B055800442B4D671A77D9EDA588534C13D4D008CDE28F41E73EBF7 A7BADE42A535DC5FAD570D376F3BA7972E3AEA75F0240120F96E3494 25FB2E91F83EBB789E394EFDB5EE5F4FDBC16222891A10C1360450B1 0DE27ABCF890DBAC751C6E7FE5B15655CB9FA1F56CECF70B5367FD8D DF3DA647CA99F1F5B6B31E75EFC048BBD2217A0540F3A2D8DA122870 49E9813646D1CA97F0632F237F667A19C566D33FDBC0C9DF6B3EF98A 95A9763C045772F5D6F027E251BCDACC89647236F00FDC39976CB33D 184D8AA6517E3A1C32E3E0AE4D5BDDBCA3C1558266F4F6DF3E3D0F31 40AB4E853D8EE049DA7E0FAA01436AF7303412A050C52DF06A44ACD9 67FCCA0FF2C17BA1A19954852A87044B3580E873B2052731538DB055 DCE460BC360E9F0CE9E2586C08E656E35889DAAD8D3908E1A9E453E3 DD9091ED58A34A68B03E7FD0A4187F62E2019D03570101DDA3254957 8649D4F03E6EDE20E5AC2128F3C22C1EEFF0949A02A22ED2F1AF71BC 665ACB7DA162193A80C2A54376B8031A39FAF4A775FD67106BB0C6C3 BCF53429EE5C7A4CB4A26BA915CD8B4E5F2294480E5AE7869D15698F 5F7D17E8B202BB5233409A94B4BACB49180DCB9BAC6E481D8373C949 C301C777926043F7E7EA1B1EBE7108DCEBDE026AF9640AE1C327C8DC 078C77B212974359142850D46CD909A1FB3F75A2554FB850AF532930 1E9614D9ACC9FFD1878E3042B433A312FA905D315E1238425E6518A1 C58E589A8BD98765BD66B8B6E7CFCBAF15A2C55551F5C8D7D8FB28D8 AEDD5BE8E7F11E3AE40AD4A4096E932189076C76A03A70CDDE79F077 15747563F02097638C51C46EBED7B009DB9501440B3180FB663C600B 3882334AE8F072667DEA45245C9F7379A06B6B50CA49488E18CE4FB6 5E1C9A212FB325F5B9276FABB2213AB09B19868544B4C67088290060 17553BEE76C43E9CC6BB0863256FFF9549648C1E8A955D819AA1BFFE 33429DA7B38F484B3054D980730D79BD09DB98B5984FC1F42C30F8D4 5AD5E590BFF6919847C829F0C475C06FE529536F2EB414D3B59217F5 3407068F5BD06A3D53063D49F5B7D573DEDD6754BADB32ED2717560E 485F22CE57DDA485267738550753AF539487355F2B34F498831D9DBA 3B8DA5A856B80905E2BFD9CE7C56A588356E61DFCAD0506C21F1149D 23B660C999BCD3BB351FEFAED9A018900290796B1513F92666B78214 AA5201EEBD2DE23AEC103D41E059D8145CC0434138B1D9A53CBD6385 9139B67B0BC7759C7C0CB068FE09A5C30894158705DC14295F8B38DE AA4403115B7BAD9D334252F4EB5B1DBBC05092939D7519DD0D4782BE 10DB23A0F545854FEE6C98B87448010F0339EDA13C2A3983AD9B299E 33CD2DEC279889A8718D881B43D3F02F1707CF0841D302D9B83EC2B6 1B667C8B9937925DFE24E102E33E4C8FAC736BD708774FB52C57DD0C 5E1DB648CCE6D62D02F2EB184C624EA821B2C07D02E4C9DE1FBB9AE8 2D93EC4BCA6F025AAEEC532618592ED2C0383BCAC2EBF9029B14BA09 9AFBDF4DCAD63B1FEFFFE0850E54D4B55173D3289B1BAEAA45904773 65B42BF7688FE4269653702C6D212F9DBE304A421A28B3804B86244F E0FF9B33CDC4A51C2E8C79179A807ACC2BB31B048323722ACAB36DCC B835B57F653C3E0CAE7C0DBE61E799923B1447ACE41B35FFC3958E42 4E28C7A2FB01F3311065D0AE69E4846132E4AE170BA493E478444465 2EFE40ADB2B6D007D2291CBE3456D373112A7ACAC4B666FC4A63EA4D 956A36EFA4A1CCBBA22FD9F239D26AC63DDE4C7730CF3EA43FDD8B78 3C92DC3BA69F8BD07C1B712C7A156DEEDE7EAF1433FFF654A9B05BEF 9A8563DE6F1AA4CEC9FA05A953B70A404F42EC7620FC75AC88A5B775 35C4C4198AD2B6B9283C6EE76DD3E891CD0B036E7BEC726BB7CAB22C C5F4B236A43A9E32042D88F35EACAEFE750B1E8AEF0A84683804F54F F9D047DDD81B84902D79D1FC9228F43229289B9EF2E4EC606A4C4010 B7558545873BFDDAADA8B68F82C8FC5BA39416ABB87FDF4C46828037 D7E72E93475866FDCC0799D3A655504055CD6C1598CBA627BF38651A 1476A794E10B99428C9C142767DB30606CE64E94450A5B9628F86E7E 8539B8506716B13410AD9A55A31AFA4AC8B6F75229764151AD85EAE0 1BE4F26B1200E3B5E33B5BDF05DC1B5EF8C52ABE7A48D9708F910F52 E4B80696713ED53ACC929334933B98E37351AAEA6C55F8B95900A713 9CE569946D5FAD0FEDF1B41F79ADC82B9C59A163DED1DBBEFD939357 E65A1EF5951F44754937A75A1690B8FD775E9C71FB1A2A7F436D6874 7A86CA7845EC52B666CD4FB95D429D049628BECC224A9F6C32247CE0 591B2A47ED979A0CE60E9344B74EB25252E8B0C23AD7B23398CCC46F F807522B1FA091B990B585BC53FFA68E7431E486BA118204246F2CF9 F274AB6DF21274FED4F717DCFE9FCFE4917351458529444392B87E29 E93FF4C09C02549242726DDFC6FD78071F10566FD5E2C95970E9C918 FF77521A4F7A7611CCD02E3BBDF47E61F4D560BC81A58CA5A1AF4F44 FE03E2F4A2C69321FC36C74D1430F475336EBC2FD630410073F8FBC0 059CB233D9FBEC770E8D13FAA60E3D595F95B57E1902A2A30EDFA5BF 6BB260F51C129558D90AD6977065B4AF30351A3AEAC19B211F7A293B 1D65502D9276117474C45649A5465C7FCBB6A42F5D32F0AB4AFB1760 B3A0A8AB37585E39C82BAE87D244D12CB4C4B1BF6C5A80A221A01E6E 0DD7546B2CAB0AFE248D4D25D3A4745A41E711BD4DBC2B8A9D35BF6A B1BE4A18C8867ED036291F70137D392F4F899EE8779117205FD7A38F A6DE5343FBD9A7D4827684F3E1A098E89E05FC75AF6AAF0A09D6808C 5D03B07213EDCEE5C4F6FB88E01BF2E7D3E05E01EF3EA6544349F95C F44250DCEC069931CBBA04EC85F7E1C076AB5633C5ECB80F27DFFCE2 87D1DAF86A20DC42FFB6B5AF9E68D7BE433AD875C27465EED2EC83B1 D04A338BE17E545A95E29F1A449A46A7EFAF78683897600CA9716BBA C5C4891C84EF7509CB125DEA633533F85680D3F0A166DA6F7C3C1212 D1AAC387EDA156A94329704804B271A10D1F10FB04CE39A393755838 9463DFEF3ED005CC13A4EBD17B0BA4196D5B6ABCB0DB7A3C14E2D2AF E3F32E192B464973D9A18F8663E757FF0E9452D5562650122E874B92 EF2A18A2A4713EE13976CF6FB3A058310C506C2AE9F332C19672F9D4 E3A3F5024E3A1FF20F5D41AADDBD8CA359F873F51443DB1866B41A99 661F621FCC3D3C8EE093B8B0A7CAE480E622B4F4F6EAB7C0C6EEFEB0 BF9D50FBFC92CCF194C94320130DC684CEEFF99C84D72CD78574467C 992C4B3427ED49CFAD72D89D9C774820A73A631D7AFE42DE41F14270 EA4D8B8E5EAFA6CBC142103386B1F7DA86D931AFCB2D0ACCCBEF2192 FFB1305E953C169B9F905EC48F2B3DE5C34A3E1E5CA738B159789F41 E6E7737557952DE547EA39F9840AE12A8576167E83856040C28A2712 10890723C44D87E0CB26E3E839BB2E6E02B9E8ED31C4B6A31006916C 79CF8EDCDB711D7A47662405A80F891B2A668D0060308B91F8E80132 70437C6D4F6F0812EB3B32B458C929C39FF0FBBB805CD5D0D7959EDA B74AD3A7454E7E61BD78894C895A42ED3791B13E0B191770A46E72A4 F51F44698269753086E67F45A248232066A9A4BA472F4041198A1D8C C10E79E63713E614C7297938504CAFC69CAA6EAB6A5E2935AF8C9DF0 DA863897AD5E1D3BB76ACCBAC7B1CCC06A049106BAFA10352C61193A BC577BBFE44B9022FEFD6606247F4F4F9048AA990D72E1A50AF93153 459E0B94422B8F68E12FBCC6AF7434A71C6A335C814B6E9FE15D82E9 46F600E269BB0A4030D06C96F3ECEB502A26B8ABF68911E279C19CD6 7CF450C80DF60B854C32BDCF7A50E8EE76B7352D3428AC4BC99A656B 3026258EA0ED27FF22E0734EC1C2BB9ACA0041819D055928F5F7DA7F 924120F763D7511E8DEF8A793C01E804335A26B972F39DFAC9D14F2C 48861D13E699FAC9B8FB6168415F22DEED1060CEFF7D57FA8DEE3BD1 B0B3A76273B5167AAF10582FA0E060DD351B51349045981E9FE9B1AB 707DA5B2E9F428FAE3DFC6059BEC1AA3D62A51D0357A34D098528FEE B7DE58F2B5EDDF4AD6D1EACD5402017485724E9D0E3C97D04B1B6C89 82AA6C772E5397AF42A9695579BC9D3A046A90022BEE564CC514A90F 86C576EB55553C2B8479B61F5A419C182F21A923D23C2D134EFC59FE ACF5BA4DD70140973C3A9676A3C609541C6658AEB7708A589C38155D 5B1663D2DE1EC37CC21A9F457FB1BA129D457E60E4B53D0B616E2044 2DE58539E152051FC692DC03503C8B7D9B692D677F4307FA4320C70F 30B58462521DD14377A93CBD4DF48DB3D4B760749AE4CD1483EC01E2 99CE9BAA8F2EED6FCE78A4F7AAEC915DF289A330F6CA522FB43DDB69 7223F2196ADE088C674B7C9F3B35732FAE629DF23B30B406BE180E27 6F281C017410D45EB7113B9916747FD7F219F9BE0E56F96C42BD81FC F4227B874A9880760F078175267E1B277BD8207C28A442AA3F8469B3 72337A770EDB7191391FE68EB7BA7BF1D226071DE3472F27D99A10E0 CA2C286607B9C40AE6409F8B0730A778835C2A8753F98C34C9E2E17D 48973826A2E834502544A2BC5AA5B291BD62CB7A7801FBC3DDCF209E EDB7CFE29582CC34C19B270DD99ED9522C9CC24DA86BD0D78656DE42 15F96C29C3A54913B1174F0941E92493166E0A403ABF332C932BA48F 86E45011409C4896E0C232ACE0CEB73DC4A0EE5D1C04C08A8B0270DD BEB4B6A289D25691575E56B3CF540D19E264226C56A371C6EF9F3AA7 28B7645249C056AAEE478209F14D149DC7BEC272F2C54BD4CCE1C740 2D4C7398443DF26ADB28E6604E471509C3153C8FCA1FCE5009EF6816 E4B910790741B0FCCE6A9ED97351A80D9B25F368B295800DCE909253 E4EF9D1CB5A95E62995AC52B01336E4386E97E83EA8B3B739A2789A1 E868A2143E4700B852F5DA11B315DC87E97A930806E5800D14FA6766 31861F1A599BB4A3DBBEF0E1C13B9950021D5CA4C627376C461EFF35 93A6879D2195861A18FF58B7DDC9CF4571048B0D186378D8E5C8CFDE FFDC61E58BF65018BCDBAC16A8094B1027FC4C06DBA77D1E0546FBEB 6E774F165FEA1DE55E431E7484B3BA7E5CB87335064523AF3F963E35 4579DE41AC03EF1E0E17BE23A828616AFA2A5592646C77D3AE58D206 B43441515E68FE8565269EBCA7A49F917B9B4A2DD763B42B40CC6FE8 EB50AA1D1549E59505FE642E6E1CE4B01F6C4030890B0BC5A9DEFD7F AE92701B75F27A40CC2604837F484FD10B43258390197CAB581EC283 FFB5EC62D9C5C76E8E2EF345D6DDA73C22C204FEF8B409EF760106C7 33EFE17DE5A3BD05BE0CA58DCC3936D73D08DAEBCEC605EA46EBA48D 12B975C0B0A0F0BE7CA5FA80FBD5A4BFDD0BB29CF66E67046F27C54D 317F39DA01D1EFB0C8CE55C2940652084105E1CA58792B59ECD8F40B 20032B296CC6A2F7E0C43FB22FEBD76B86114035D2448CB8A75A6F7D 86A6046C75A1D78436A02365400599D186C5430D9BE1136122E99598 223B35331759FAD347878D0AA1CF09E3286BCEF66456FE5E7AC1497C FCE78D9ED8CE0834D4B1CA51C9283E949703AB45BD68ECB4A8AC8D4D 41C4003624EF72CFFB191EE229DD36108D6FC7F9AD9165FDA7515C71 76EE90384F2E7A64590167227A7DD7E8B4B14533B439AF85B5C37561 923F68793C50E9CADCC18502AD7C97A1F5F657DCD89A2D6804B29DC0 0F7DA2FFA71754067057AE28977890F97A8318BD1A17D9973F7A7A67 56120B75E5394ECA829E0CB07EEBD914F168B9A529DD6E9974A37455 8A11FA847271673BFC5CB1BA235F76B232F9B5318FB12D9A2923D426 A38CFDDBA2102622793DB7324342018372CDE495AE7398F78CDC02CB 493415B45AB6AD7286B946CEC69C12160E9B818AE32712A89183B159 F5684F666B96699F30A12B1C08D47078E22B2EA0D353384E7F436188 C170CC558675339796871C1ABCC826B8B4CE4E8F4F30623BDB564F5D D5FF813A072F7605D93E9E5751B10ADA68DFECDC18DE63DBCBE91A22 0913995BE1DEA18B9F29FCC648F34AF6A842B4DE6543F1269796AD55 E950F40626876356C6764CEEA1CA4EDEAC30DEE6F7B9ADEAC0A2D31D 81F9E508163B88F1525022F1EDD91184132E37D33232BFDFB52E5C21 4B3A64EF91727910A09E9B67D8B6A2B365FD1DB5A8479243FE9BAC4E 8EEE2C374907DCA0614CB91D0E57D0CCAD93E1A8FA87E7A33AFDD5A7 6973BB79F175CCC021D9F8CF54064E8C3ECBDF9A05078AF1B377F47D 4EF8B4974B70E60B2138CB4A5DFDC283437C3BBF867B8F685B270E45 D848E765D77A2F75B4DBA216B9B069F546A1BC4A9532A1FC3BCFEF83 C27017D15CDB60CF679F6655E12E4056CF73BD529675D0DA67EB6EB4 F176584970E38093B69761206BAA0AADA82F54B40B247F726CB45AF8 F9F78A5E024D8B4EAABE5A94E7E916803AF9A3A394C005CA752B8F15 AF811CBA87FC7C9573083F01F3158A36BAA0F74021AF11582955006E 1AE2AF18152C1B56A936BC28CA6FB688F8452E92E21458A07FA19617 34EB3BDEE276533C3A0C6F63F107198758C85E201B9234EA8BBA5B19 086709EF903AD6AFA1095B184A0F9222C31670CB7AA942D8A6EEFD29 DAE378C6726A2BC655172BB2B54DC9F657AB074C41C7E55F133DFD8F 34F41D33BA199879CCB9D30D85CD9896F1E38E850864E596F1F544BF 541EE35BE669D934847F639C2A4F63F233B3AA954DCFE747F4EF9144 1E131BFB422EFC900557A06E505E97C814F4E6B479114702DE14AA83 F2C47136BBAB260177EB5236F2229A9715B0F776A851BBAA815E41E3 6BB1495127B117A4D1FD5535FADD38397A7530D6986DC93AB3D600CA C4A8FF163A38C4A9A0C1CCDBAED7CE4EBA7E7383943A40DD79B125DB EB9F3D395406A4686CB6D65BE1B570FD036FD33350544582D0DBE1CC 1E34B9FA284887C2D1A30315B960C3A49924D6FD2EA7B8D945376D23 43FDA5E4CE43518A89DD7FB206172DE267B4C44E48060937E70AF5AB 2D5BDCCC0307C73DA42944986F63965777688C0F95A3292C3880C33E F116BF1A66A54DC7F2A16A1EF19B1054B816A5877CEFD469D62E8FEA AD2501E8085693FDB8E932316FDA51F22025C91539D062D7B4C68444 5D43293164710173392CB06069D154EEDA76750E40B9F6706F5EF42E 07A61BEA2326F0321DBD937037F7B64C9605E70A18BD208AF6C1A785 7BEADD2014B5250DA344673BB3B9B49F31BBD5D485FAE2F6440446FD AB895B14E9F0B50412C7EBEBF5FA0894B2AE507C5E20730E26C442A3 7DC9E19C6743ECED3C34F8DE97350358F7F7F913C18739D8BA42C968 214F593A75EA1207489A9EBE13968C9144E3ABB57BF5192FEDC358AF B15568FE93F44F8567D3791C9C8B0C87002BB87B57327258079465F7 5DCBB2E51183E501B22C1F3913D390681DA4C42802141F4074BC6C9B 1A67151B7D3417C02DF7981CC56F9EE9E41A88CC6EEDEC05BE86CF98 606238799D07F6B49C3A642D9596837588C04AED9C71E28C2AC29A30 A2F0CD9B7086AC9EE0A7E5D5B608B39D420943C608E2D98C56DAA31D 5A4CFA13271B0908FC940DB2384C96364DEE50BE3E2109667164A274 13D21076AC449688305F92E20B616753CBDF6C798B82728BF08806A7 97243E66AD698A794800BA9C2FCE1C7BE98536CE31B9D3A758335838 A0A866BE9E7704758891EC67C40202D32AAC05C8FF1CDBD7264B95CC 6BD1915DD4E8449904484ED252CB601329D543C003166222F215EC34 94DDAFDD8AB1A951BF490D708DF98A390ABF303B55D1EDD918F450DA 38BCF9464A719281768DC0970067C3FC7FCE33D821EBE8B10834E9B0 B03B1768DE41FC060DCADC47CE15CD39CEE8D5BD40E61E20F7145491 04994816E060F444C245486D2C40E9C8DC7C6945E1AD680B7691062B 8AA75B33B564EA721A61113E7D01643D444536A32CB2B4CEBE5A67A9 B72913904FDB87534DB3EF35A912FA0F7F6A82737C390F0EC79EC77A E386499A2F533A160D187E570A072B96E70226C7A48CB1386AD6A28C 9D8801227554B1F7F2DD800A992A772CE50E90A317F810D89BC73C7C 3E1BC8A0CC8E5648B29634A225F9FEE3C828CD03B76B72025D7C3D64 C48066501D19F340D5F3A03A52DFEB7BF65E3E1F14371F3F2E985D71 7D17F7F21BED39E6B54B0157A9134925C61FD0FFC82691F336AFA1A6 1196A6090B75AAC567A00146500587587CE2910F00E1103A701B2DB7 5436417C21B58AF4706F03827F6D7513BC1B2B689467372678BF5F2B 695762D632D7C4ED4754B96A0C36E0142E54FDF3502C0BBDA611309F D9A58FF6005DB674933B903188644724E76A277001ECAFCFE896CE41 74A22A5A2C74237421E1B699FBE8ED4CD7483C608E07737249D89402 082619DB1E25DD8E67940591D7891433278928E39DB1C2276FA27839 3AA4A6A70E703F7FE91775D1686A2D4ADC155325625DB56BC58621B5 4C00F2F02324160DBCF54909C06CCB68DF9DED544A887960617D6878 3A79747C405276FADE0416A978EBA6DE0CA107F4A6308AC04210092A F44E186687102F0E9D6E67B305F8E12814B6F5886208BBFC6F9B930E 631939310A00D5AF89117545AED7750C70029D04043F3A6FB4AF2AC0 FAEFA5E04AD5DF52EFC079366C0DDD722341E8CF9B818A6EC4D0DEAB 785B6BCDE5295289F593B589D42F42C519F4E76A41381AE96CE6DD55 6C8542C631DC2E7BFBCA030B0CE40A9A8287FA5D0A54199324F7B62F 54752351761EDAE30F5FB9F6E4FFC7967E5D97AE10B42A2B4134215D 0D5ECF2A322E54E0B5384DB19B7C02C73895DC4B9E501D67AE4A97A8 8F4EF6B80D40DAD748925D00C7B012E7E1243D1881B5C5C8C2D498B5 EDF194F79CB7EEC75888B732B1A90A10AB005F7A8ACB9BFD3277FC66 FD9EA207AC7333C8CECF32CAC49313CFF854E118EFA62123B130D9BD 5E25175BDAA70593E7967B3B8BA69E6E2931E865C8B02931B68B1275 07FF1C1CB5C9003735FF40EC8E14F5749B0BF8CC2C9BF44A3B3C20B9 D0443986E148C6E0DF05E01BA061B693607D46ED3611DA718BCC060F A93FD15E71671A473E68050D07C99A39A1D49716F0F9FCA49F100569 7F61B37531EBEACE897C7D091A2531A00970BBF02D0059A2847B6612 27387A036B7F0C0896370DEEB75F2A4A818ABC644BFB1F489D404842 30E4C7CACA7D42E8C460CD52062390087852FD9C86BD798562D85E59 FC56D6C3E2805060DDA7474677E651B9FD9985E787CF7CE47CB6479B 05FB243D3883E006240B96F477BA40074928A85395D99B3959306F3C 4A5CD2AB3C3C933A804F3D76B5C4B00CD06929EAFBAEBDD5DE8FDDAD 126B74557C341F9C4B6FCCA925CE81867193157D6F926FA9123D9395 EB2EE2F89FF78C5237B0666070576CA90D329802C4099175605FEEDD D5E292351174101A8FC32487B58243485598D38494544A77DE056DEB D1157C4F908D3AB4327F3E9E8817ECE2F03B5AB10F1DCBDA9CAFDA6D 048FA78404B65DABA32C276982B16D3DB545AD0D190926C097376758 3651B468F205988B86EC95D0AC4AAC7F7785A7D5AF1B81E1295C5EBC 8E45DE27205477D7640EEDB312B113EC52B4145A008F33FF771553FC E0816B989AD8A413BEF0EF37243BA0DD410113CCCA14C4D8F1EC2549 C2CDABD69D64D6D6832565AFA7EEA21A22817BD4511F32185000EB4F E42928ED2D5409C3C9B119CE31B9775AD9D827A7EA14B2D523D1F4CA 581CB0D01B1F9BC27D73526325945BE49EDE71FD6CBCB5EA2050607A F8B1A21323B930CE47A74B3E61C0485AD29C28F440639650465BB325 07C6DB63E7ED32102AEC8B1DA1625458BF605085E5960C0AF9E0C5FC A29BC4D13E8CFC888DD599B0C1A9879441757FF845FAE462ABA8A6DE 8D6608FD29EF9347A3E7130486D3ED5E2D0D175DDA1D150F36AA1028 193B8AC4EE5D4996D4DD2053B8F1DA595E597B4CCEC71CD9D62CCC2A 67B0F290BCA0D02294C3C41D16CA801746ACAB24891EC531211E6104 9C8CC041D85DB2D138654370480E6A1D85CF1DD5B30FFA43DD7E2B7E 4BF556C650B87D4C23AE83F6A74874D3FE7F57FC1E5D2B044A9E5865 F70522545E8E96E581EF01689CCC10DA5896F4EE05DB3A7DD50BCD37 3D322CEF906EFEDFEDB8D8D14F45FE3BEABCCB1FF2105594EAAB3169 6E1EC571855E57084B53C6618ADC0790BABE725A8D263927ABC32864 FCBA5BACC591EB4A165C95223F23C0F0ED46C9D841E7AB66AE4214B2 AFDF5CA80537D60DFF114DE78AE94D32557A1088F45D01060921D6FD 801330E1E3FF1AD0E974B91765B082358BE77CC4C5445DC47A56DAC0 9B4875F9043F5E6156E39DEAF3D44A752DDBD33397A7B42A52A70FAA DA56B32D90BDF808550E4FD51DFDD21B52477F1B776F4CF8C438C1AC 87ABAFF92AD95DFE91D71290F3FB55B9AE26F56CBC0E114CC4DBF728 0977DEB850826FE37CD28FD3BC7BC4096ABC02AC2288D45E746BDE2B BEB93A2AE256F350787A435327D48AE4AC669B4DE56D6CE7B7AFFA7B 65330BAEFA7B88B4754BE553B805674E6CBA41EA64866A26DD15EEF2 9B9D20AEDFE4A5351CEC523950CF031215F0221C5267EDD8482913C2 4122E59D5DA63D2900EBDDA36011998383BC7F098A5FC03E2B00CF4C A1096AE6D12A728154629B488481B5F14724301AF4DAE2B0B042C01C DCEBEB157C99F0104315F2DBDB7E778D8A5D13D3E8EA38115827D3EB B063384AA5D78AB644DCF525488ABA367A987F355FE5D097CC650BFE 8DACEF6D44837D21C691815AF3C7DD9B859483E0C1CA7D0F93F86038 E90C90B6EB28E2114073741B7D08E4A2461E41BCB5CAF526EEA7E225 233DFB74F4ED35B526B026814401D41CD9557BC49104A5DAED3E6020 2C0AA20ABE8C3FA72B32AFA3ED7903E0DAB7770235CC0CF5278785D0 807615F94622291280F231995BF31D923A99C8C88E5780F3D2B699AE DEB371B726C4307E9A2EBEFB08C69660A8522C4158F68A4E4CBECDC7 E7CFA75F2B43C59A79AB62DB3694A93CBC7DC316719D7F510C863421 7726E8CEBCA5E34EECD0732F6557BB602278BC2F38F7DCC35CB55B5E A732C93C996D6F3946C42B8D69937D8B0DE6D5265FDB301AD88507BE 97E2A1C3778526B063AEE095493C1597F4A70206121CFC5E3D8E3DC3 F0B8483A89267C22715EB78AEEEB3BA051CFB9229532ABE0ACBAFAB9 80EA8F9152564CBFC27A0EEF1235C7C3E7B31A0C4A58351898CF5EDF B0E83D3D2BA69A9B31F85C2340F7CFEC40561785A4EDC427AB784A9B 10628AA433E9DB78C8A927D76F3BF55ED5E77233DA80AA72BA63884B F588C25DE63D20DD208A1B2CF5B9B6A2262250DA09AFBEA29745575E FD08BE41566B9A410134D2FFE716AD1E15E6FE5782FDCD0DE6AB8CA6 99C80DA41D77273ED1D1E1119D271E14D607ABA17BD00904C81A850D 537BC63BE50705E1D445713CD869F781D2B9E49EB0F15E6C2D493B8C D62C34B92FC1170D7D9C988B2F637A3406025893BF4254C9A29C5ABA 31BE7E0A230CFAE88C26CDF166119FCF45A556D96FAAE67DDB5C8531 5374398A4B40708DD8B02580F7E0E1F7C25CA4BD0D8B2D09C9683F13 E2479708A65E6CF48DE2B613E7809A8B480EFD915F0900C9B56921DF C54CBA5CD8CD3FE2F7A6FD3BED5294180D6583D6450F6032A0689B90 35BC4FD1D267704E83915D7484EEE88EC1F05E3B0A10557FA4DCB2BA 23B768D4023032D686A4BC2BBFFD10C23A371FE7231B39F8C252FAD8 B1456CFBFA83EE4CDB9186057809ABF067AAB8DA36EBC07F8E14F75B 74D4F3D29207FF4351ADC4603CC0717EA6CA061FFD682293EAC803DE CFB64604EA830700C4C8AA7350E18DB6BCB61D92CC27DE15BC80CDED A44615A3CDA1466A10A641F6E75487BE6DCD3A1552DDB74FD12F926D 7CAD9F0D61C46290933AEC59022D924C42F0C809813C78189124276C D3A40B7A9D71AE793E635F809B198DC11D6B58B320F37058406FAA18 1A6C82CF99EF4820634A2A11731B7DF9AEAD2240CB70F66C978B6A46 0E7FA7A3225916C66935FD7B75505436DED0C4D7138B240578811EEA E0B58221F9526A9749F83C56855380972C0231979168CC0ECCBF6189 F6688A8A4FE3E64EC3B68AFB42261E9CCB3B28931CD56CD8216FC6A7 4D967220640455C31F9F1B85D11BEB593BD1CB1720CA0C99E4342F3F 7CF627ACCEAFC9DDDDF48AAA6BEB59BE6F351B2C59030EE461FE1BAA B532D326EDD5E8E3EF1AC266A8420252996A4348CD51DA8B0D478A51 E9D4C187D8F22DFDBF917119029B9876037A97AF6ADD6C5AD9031941 700E69ACEC93810DA968945606840FFF4C4150C18B95AFD0B3C349D3 03448F8B66723C06866E2512A5F1E9A1A47BFDBCEBED8FCE69C00A74 C3B5D5C4F348A102040763CCB0038FB8535670C24FCC1A6810806443 941E02D6F76DCC070FB1314D209E8B98F932E703AA5371F962D9B17D 622A72E3C4FDFEB247359DA41E6123799D58F2C1FE4E2E3E0037FD6E 85B652E1DA41719B9D14526D9EB990526757DE1EB64E22D4D20284CD E61CE186212D7E0D5B9CCA32651342C26500DC018B92B98934273308 1CCBA272671A251232C953FCA368DA319915D2694855EEF15B476DFB FD8295176C966550589A2974D9581BFF36A471588FD305D1D0FA7042 5323BE771B7AB965FFC4533CEDBBA10740D0E61DA4E121B10CCED3B3 061C17FDE0D225E9BA9D2E144DA8A1258C588E5A2906B84EA306CD35 26752CBD977970B021C96ADF28D76A40BDCA678BC76160FF20CE1FB3 C0DB80E6FDBF0CFCCD9445225E93059AC708514EDF91B75563A78C43 740D59D79702E3ADD3284A5A4853F3D4F8134AB7487C8AC8BBE1FAB1 AE90AFF36CD4CD80605D737D12321AA4971B3DC9047F582AAD5D31CE 27767D7207EBFEEC89794C54FCD3F3D686F9ACF563264151DEC93E08 3CF0AA32FDD65FFB2C77511E882A40FD8BF2BD330319F7F8F32A96D4 F00638527AB2DEBBBD4F605DE0E272A45EEB0B1B7ADD8E9B9888EFA1 CC4F6D9D70E120A3A49878232141EB0B4651DB7C22525D35B4A4E861 93612EECD4AED19CE22B4CE5261549CC0ACD2F3BB53BBAA1C86E8527 22148D4F70D67ED095FFDB4502348D9FE6B0C0947901806939747BF0 F6442EE8F6A15220C18386FEE0B96DCE544C999F297F6770D0E7CE70 1CB0671D52703B3515A0B06E0677FEF304DBB931A0193E9E3FDE242D 3323F70F455E63C3C62077EB1B98275B954D7E9B6BCF63FC8DD21C8C 5F1675FC2CDAD0622F0907828B0B4A9DA5AE29F9114B6AB2D174D228 D6DB1802D9940F9603C9A5D9BA6C039EC3C268911BB4CEDFD292F476 8902416E62FE498E94DA5453FA26A54DE35DB5A8A6BC78BDD2465521 352678553B5D34839F6F406F752BE2AD1900B40C32F8BC2F6916E41B DEE04C7468EBCCC9512224536AB00B56B9A3D05E26898B068CA08F81 E5F0FEA43EDFBBB5D5B8F2FA4DA62CB2B1679120EEF305ADDEC0E059 D5CF7914FE9016E8AB9456AE6AB9AAF8ED676950EAE9553F3149203A 5FA85A9D1123FB24A1082B88F78F32756396A4535F71848D114F71C7 6A6CA881032DFA961A3294D1E1E6450B786C061344411A7CCB4B729C 7428A1EE4FB0748317D5B286C6B5E2C810BDDC6B641472D95FD9E078 EEE54B18F171F0D39398F0146468D89190D3E68BEEA430EE60F3DB8B 9785E020E9446F5370F6B08E458E96458AB2B5B235E20159B4CA8AD8 8D95C46BA933B4CB26219F8D47EE769478A0A2534D3C2F23793A2D14 857394E32BBCDB24683B2FDA15A5AA61A35B60585F11F07609481E5C 5EE2EDC11E9904A9F71D351FE4A3D96870F591001F1B2FE0732CA1B4 8C5D27570D946B469817B63C2EDF55C468B9132CEC0CCA2492D77126 41178491FCA52EEDD6AB8B0B718DBF9B4BF42F7594026165A7B0B373 4697A3042BEA76EA2A7F1CE622FE9CC678F25F9A0781DBAE9CEA0E57 EB3B6709C49243731731FD72AD96B1FC0806402B84452A3F19740FE4 4C906A5DA93DB8C7F94AC62E0B28EE59F7C565FC8B2104A26513DBB2 BE75397D30ECE1E1A95A052ED6FE74FD3DF7151F81A1372A1D9E46C3 917C658FB090B16F417D23B89694A4AC3CA3F84F13DC2CB03A823612 8F1F078F4D7FA7338B59D89A139F858D0FFF7EA5C3258ED71D60BB39 0859137DDBE2980F5BEC8F9199462688F104B31B528F38873B133345 10F7093945904D9067424E276B2BF49D50A2F9423C1C439B6A2C8A1B 28FC1266A0662BDE76B45CF05DC5A4FF161362A2D2CA43096587E274 06905F9FB4EB121B6C664AA9A30A06A139359DBD0D1DEC4AD960C434 DB5D5C0EDEE56A187194B4A32ADD3C60203B99E60D2436FE785BAFF7 89250DDD5957598C6587C128A173CE8AD632F24083384C00D3FD47F1 C871C61E1499EB5496F24CF3136762B32B167FC59C1B0FA0F2EA4677 68FA763F3321A271D57802BB1D6B939C80E21E1610FF92045B7EAFDB 32D340BE7ED9B6AACD6FC0E08A361072C2A4B38B1B4ED8A89EFABE98 AFA5E7996B89977B347421D1690CB7BDF44A183AD003EAF2CE01786B 4378C97D98260E20B46C6C546EAB906677A6AB8651F167AC459093BC FB23F9526490D4112830D5A65224043A4E5B05F8268DB23752BF4F86 57A21FE92036D96DAD7399BE6984C4F79456A477FB0BDB71EE005658 14E721BD4E029D7F6D944C60ED9AF3851DB74AE5686438974C6DC8A7 802E9E77BC2411EF3B38FE979BB9E095DF9EA1C0D40D67DFD91D74A2 D710224A5B45C41CB31E4C9D5A060500F3D12F42D0196B5B80AB1125 3DC5A4A5D03AEB6465B10988E147628695FCCA43D7EC2E0A1E826234 BF4824C56BFFE3098EEA53DB2DF0C5A8DACA79026F2491B84257D7A5 2BF54192DB6556A8AEC8F6279CE2228361A331936BBEFE96D0C26904 47AFE5B9FE503C06AF0B4F39408EF34B077D5DFCF3CD939D01CDDA9B 1DAA9F3D03EC36502931458255DC7AA21316204170701AED92E3B34C 9EE5559578F5032500060D4B6498561BA57204CBFDD89C7A680EF087 A7A7F8A64B8A6BBF209B5412F57FF65B89EE8268F1799DD05CAF2E91 36CA70C3388A679B7B63B3CF4E57073FD09C73188944870A77788326 0A393D64FFB9408DF70E6E750C83DB8EA21B73CF988EE723D83762B6 BD05319725A0F66E321B5B2F8936392063E9654F9D2900C8D9002115 2F0BBBFFF50557AE78427FE065DCF4FE2EBD2052AD5F693131EE1A0D D630FE5739745813E96FDF07688BA86EA00660876F75ACB35544D336 E6909F1B892259246CBA5E1ECD9527CD73849DA318CE566220EF7510 20DC952E8B06EEB64A2F37C5F2D56158DFED4BD9ACD8B93DF7BD665C F2A46C49E0CC23961E2AF74553298D21F12516C2655777EAC267F02A EF794DD329B242A3445B107466CCA029F061A4C49DC9F6F9F0071C0C A17CD3F7BFA41CAB168723E10C2C5003D1B480FD765E3DA8E956C5DC 309C1C2FCA0024117A1C8F819D46B3E1F253C209ED735B9542895637 31B6846E6A7BE8AF802BDB6B27104EF6BE8B743E32FA95FDA605A094 1650CDF22C424D9E78B499C981058EA5E0AF0892B2BC3DBB85835A6D 71E382E1E48CED52F9D3F03A87129B0EE4D436DE062AB9AA6A1A4006 DAA7AE0777A62EA822E3AE64E759E51D15958807F64B3504B1B6BA34 A712E1CCB0AB8D0DAAAD5A2B8529C77B7A5BE1C65C34AFFF6AD15B5E 5B5AA92153EF83D9437FFED05DB0C2C94F95E3C2A7DC959E458999E6 0288D2CB0838DA67450B9D441BC74FC4DD9EC10CDA172D381721C03C 8458EF33D16A915D098EF47D8E6F7EB9FFD03E93310836AA04B2ABE8 1A24A35142B056FF2AA4022948B1A8E9F75974107091F7222CB87D31 C8F0C30528A6E05B83F7A5CD84DE98CA779E97FE1030E1C4F7AC3150 A8E1D51B94BFE9DA9B79885B7A91E7B5810BAC58F2EE96181193AB07 98B20013C82CC538FBC9AB780807EBD9ECCD3390D356514618E89F54 BCFD858CF524C3D8D23A71B08388BA389D02508CE402B6B2EB752B22 E5BB4121FB278299C4FE418D6F46AE17FBD53032F40F9961FB30FA6A 22833B1BD555CA39BDF5B8620B337D2A33A27D2E7674E781CF430028 42FEB5B0C52FBB1C3329023A79C826D7598118CE2AF4AC2EFB1DC998 00CD58523C027C76C8C54D938D7817219B93B8B6E529756903C7BD93 C5DAC1A0557677B11714DAE7CCDFA35630F0969F90F8F1DEDBA31091 8C969775A2C41B7FF75EA219C3380E5F987BC88DAEFCB43C1A6E3ECB 9CC5C2F23FF11633B2413A462785A59098681677156798D5D3C418F5 46BBCA6CD301DF97A1214C57BFCFF791E1317651AE8DB9A53BF80863 10A8D596A73C406E0393E3F50213213E794700635ED2FB683B44A15F 234A626AD7CDF828F76B5892FE107FF2FE81C672AA74FB906B713104 70E42D61A1B10F73FE95BF92F5D8C14F7B106952A8482707A14E74D2 36DA9FC6DB8EC56C267816C04205D265863BBAFD5FE274DEC567505E 418AC3A835D3005B170C8EB83C7D52D4717175D464E11ADCE0B713E4 7058A43E3F7ED261F4EAB44BBD46F66CB23B485A885222884F4A9F01 81B362D7ADAF1F8B3E5EA25B35BD2C35DEA1261BD90BFAD6AC6DFD00 05E7770A6A7104923A17C62331EA9203EB445F04750D8570573A0D1E 33776887E8954456B69701C08CB0D5718E7D4A952AE0366FF86D342D D377A242EB2D63C700C70846BB57A2C84FB302C812286A1A1173FE16 7BA14490883C0F24BF9A355C6FB85EBB7D041E7EDB809EE920F6C815 60A42D6326F380DDBDAEB8E5639E30E6CECDC88009F10AD9ADC010BA DABB231137DAE2D9FF2C6C06D7EFA835C83DF828C26E73737D1C3E9B 36EF80D13B159674884A6E7D805A4D3ABE061084CFCAE2BF413E3C6C F471E45FCF8B4C6D4DE5A374239B0146CDFC535FFA5959F83403D2B6 B145904DD649D2F4CBE5A42947897443C6390392822E452C198130C2 EE38B1F8FBDAAB0789EF7F578E669ED58152266B18F4C1287AB7D6CF 7D3E5C4D65B96DCA9092F3B1158684AD5872E4DA8935B16A5E35D2EE F99FE06B11B222CBAD282820B51F62D562A57E63D37BCE7A33DF0706 ABAA826370A3B71ACEF42B59C54A1610D8232DBC9A6A9F002614185E 9AF14433454867F743175565E0D267CF17B7A4F10C097849776E17D1 A655876A7FFE75F0E8D120D1097811D5A63E3B717D7149342CEE643E 6C8E3C2F2E3E4340D1788CFB463109C7DE0AB94A0D7A2F3B30383ACE B9F18DABB95B4AD59ED2EE79AB232F259122B91C8FB49094EFF359ED F1ABF842FF8E8E135C427B4CE0AB68715758C45DEC71DDD0A5ED3023 A0592B38B6CDFDA92340B3446F08DD4497E142AB4E5EABD02226806A 8BBC375ABD13EF6FB1A0A56461F1BAB4DD13985B40F89BD14A165E5B DD4CCC7B1AD70E743FFC13ED28F918973B704E070DC2842F0CDB9D1B 2E3858FD8E6B1DCDB20F4D85446EAE55E53E28D698F8F6EF0B279D8D F7F58E00AC91E8CF7BC6E445E4B555385F42D9ED06ED83A0DCB6ADCF F66ABB5FB4918DFDC05F83C8D1CA22E44C1E1041F7D37553CB15E310 DBDC2724DB893B3327DCACEAB11585E156CB0686D279FD9D4C8FC274 6A7EF20C32A7F1444881A99BF68C7311D724EA4E867F9F34381C00C5 7E4390A2DE0FB699031715460A577C514036803654A5D13C3E6F44FB 088B3C2E63B8BDEB214223562DB00914ACE5818EE2ED2482F66DD375 66B6C33CB1A93A15FA2103BCC0BD0AD7A53132A36B8CBCE5211C04D2 95697033D0F9BE0D93F912A3883C92DC621A37740BE53575376786DA B8227CD62A74B28C85ACDCD65FC93EF4FD6B3EB1E5AEB392242F116C 7EBF1DBE74638F3A0E0737576171AF5BB9909C1E4564A5849F462B3F FE580E117D2E8277C0A201003A6139BF5AB125BF8B442E12E693FACB 53D5E3BDCD2582295AD5B6179CFC1E429AEE28735D4FE882AE83C747 6EF56B547F501D2234A77A2077BF3F61360899295840482CA0647D4C 0053E658083419F4CBBD2BAE777F4B7A00AB98735C31456D0EE3FE6D 6012ED3FA2E7E3554BBFD431A6DC447B5E07AF00DEB631B17463E568 B7ABB9DDDCF6C9E7BA1F74BC561B036C573A183313E591AE32ADD1FF A01CC909145154924E1C05D4439D718603B96707ACFA1E17349B8D27 C35CDBEB4F529A5B6BCC46938A74622740616E0C82E71CA6F03A3A6E A89AE11EB4D138A55EE22B439F502A4DF61651093E5D04BD28BE75BF 478FB5334D09734E4B48F9513B9ED8C1FA8E106C6B7E94320180D2C6 54B980AB947196031767F8025FF010A7250F67A8D93DC7F63C6AB6B6 60CE02510BF2BA6941659908B652893E815FB6FA2C72D8EF3A904060 D42C1F9EFF2AE64419C27DCA97ECF0C5B010CE43D52F8C31834B31F3 34F94A0D518094863818BAEAB173BB6C9127F71A4A9AF53D2ADE3909 EC0ED6288E4ECD27CC3311310641BE7CB70F9B6FFAD9C7357A62B083 41405956EBA3993FA674E27EF91629BA13B6274AC0DBCB3DED211049 F3AB6E9ECE59D25447EDF778E58139A53A2504B0B6FB533EA8A7BE6E AF359931824C34FBF6CD37BEFAB71E08FC1258D1052799A61AAD78EE 35BBAA678CD9BE1BDCB9FD33F0858E184801E0E4E3E83D1B27306C2A B83BAF84AE69F658CA1BB27D9DA9B4E7AE629904F2E0EEFFE412BEF2 6835F0187EE5FB4304FDDDA0C1E8A21D8F75C37ACD5653D38C3E8627 9B87B44D22FB02B94308E0A1C9E92531EAE8AFCE9D514DD9969393B2 DCC52FE19F63D084162BA59FED448967C7E29006C0B1C9BD64D2E8C5 99F2F1A349B9F307C7EF9B220E63DE6AD31146D375BC074F12CC2E6E 6B611245C646D2CB2EF942D35CE8531DB705C55ABCFCB643E5D7B292 E8A332046064C08D05907016BFADE7333C0B5A9FEBD89691DCCB5096 8F464E8C965A4FEDCD5EC65C3D3625D31D7B414DAA07C4F5A38DAEEF C3F8FE066437B3DED8B7CBE2C15A5CD206B49FC82C34FDC18DAC0CCB D1057C7CF48827D588436BFD052E3067B6AC107B38DC267C25337072 6B0DB7ADEDE25F020C67AE7F16456C7A2AF72DC04A9D3FF9E4EBE252 3A1A788124391C6A7E3CAEC8C73EB68A7B5AFA01C3A2E38822B7BD1F 13C1B7EC236507596B10DA999748F66083C6870B14FA6B241805E16A B6516C52D0F411FAD563ED69B57A063D77936ED323372A1207F7524E 568F6CDBB71091010FB5383E998D3880177096C61EB1A23E16FA2BA9 D6DCC4C7D1765A3121301A7B2D68760BF90FA28C9962B8E35DAB7F54 FC5FA641E6C7C07805F811F6DF136E4842CF7D4AE0335C8C6930CBDE 32BBF68C4C05A75FC4548CC51FDBD977523EEA8D69A80D7120790E59 FFB6396A8A6DB4878B4E3E3FE2190159B50E2EF57028EC77360BE8FD 0325CE6AF2A0A664FBBE8EC64B90774A61E259F753B053ECD2E3F9CE 4F195CDEE748A7D56B7245A2CA7B7998FE7C9B36BDE4DCBB616A7796 8455F11F042D6D9E5912638F53534AF82568A6BE645B37A5D00A0EEF 9723908344B2796E5260BEAC9187D5003AAFC09A22FAEF40DD64C889 361D1869DFA590FD4A067E1B34C88130CCDDF3FEEE45C4152BE43609 1E3280D2DF5BF218E1A19C6258999B0EAB850674EC5EBAD5EEE1D93B 691E7CEFCD5194D5534BA2EF91D9556219F5A08A07903B3F165707A9 87C13C4C673B28044D1C76647643C0D9EE4EA5A9CA661E783C3CD109 5E407171F4F71E40C14BCFBA4FDD990A31B1109E242DF74A20A89567 3A59F17E205D889AF060CCF5850AD21AD777FE8E25DB82F189CDA7F4 383085A35E95E4A97249DA56D87B7F54757D785437207C5469784CE2 C5A4EAECF0CDB56AF6A8952CD3118436B794182B0ACBE17A89A5B6B0 CB7D0CB848CFFE629FA3A6A55FFB9E8822725F89CA7A868545EB6B56 88137188786D631D06ADA4BB04AD456680CB6BD0215E5BD9AA06CEF9 DECF71BD1F4837DE157A0E7AC0C46BD8C1D48FD75B48456B45EEEE62 9C74DEBF39FBB251C578AF9FAC00C2A966398037DF7C580EB3F8A00B 46C4FDD3B28DC259DE09199805E15F7C822677FCAD0891DDF9A292D4 18F92FEBB18D5EF999CAA77AF84A47A5F4A3EE4B1065E627FD6A0545 3E0FB914E33118D34CA9B1E25D0182561DB7A7C8F3B1C7DDA03CE434 2298629955C91095E6925E467C8567F4520FDBC986E64F62D7C154C6 D3BD0444141F0EC5A872D6D7190E1171C476C80B2E3B9FADE59C4152 01C284D73548C1F099F25A43FB4E14834C75D71AAD5038C8C2448ECE E85E535405374ACCEC5B2871276E064A73702DE4916D7B784906AF99 6757285CBB4AEECC25C9438787342DF987F16727069C72218C84E2C9 A1CE2C5F2BB46E340AEBB265EBEFACFC1A99450E3474F8D2CC14A561 7985CFC1C70ABA028E347BD7BE0C5403675310263AFD2AB8CC006FEB 487FD77FF73BF03B84E962D4E9E0C24F6EFB6B045423F129E0525C54 AA0663C34524008F3A2F06BA6DEA62CC763523241FA5FD9390047327 327FBE08F8F2D0E89E1083BB44973AD5C05AC887DA1F635111B00113 76BCCD217EEB2DC3BC569F735134502B9ED72086DFBBB91EE58A102F 8568BF10110D447C5C68771385BB14A56B7865B1626DAC4B8C60C17B F147A85759E4873FDC0256F6564E160C9225CAF60DC187EA2AE2D400 1C12015F714740421221C79C10E56CDA4B98D7B721D15E545E78F663 714EF95A021758AAFA31C53E6EA9AB928ACF55E3A0BF9B49D1F991E6 AC876DDEA607AC91B632EEF4840C34CE7777A8B73883B6864AB51D8C 9A800187E9B12FBE393EF861577E0BE5EA12403DDD202A7D2E080AC6 D24867636BC7106B01AF7829306CBC3A636F83DA0D5782F038D194E7 96A892B1B07519B4833E3FCC62188098BD7B3F9F797F1A716EFA8208 AB2A034CC2F247D957F17FCAD307A3E907C6284B9FF894D1A960CF63 5605D78FE922BB989FCBF105C93CC5914D4348475A55C8410B1DD68B 071983957FAE7B23C8566DE5DE0C79F50BCB172430640355935E8545 1507F0CED1BAF985BE8E87EFA7ADD72CEC928E089A4A6BA917991FA5 40F4B68B66BD12F298FF9F15998747077E83CEFAAED6E9ED08A334C8 0DBECEDAE9AD779163391F7AAD751BA7B502DE9A29F6390E1C05B829 D707263FD876D1A5D6B8052FE5661049143F6CCD6BA0868803C5D3F0 0B94D205FDBF1FB0E52B492EAA2DAC0C14F891D4CA89D16CAA89D7AA 3355BB4E94CD8379C0BE5E471CD95806E0B6D546B3816043D3B3808F AC478B385AFD3E3A74A50D38EFA321FA284C43510CA8C10C8A846305 ED11AB5A17C182054BBA8ADBFC2DF6F17C519A48E51006BAFAC393EA F639CA163B250EF7DF36ACD69FC99EE7B1954E9D489C445F0C7393CC ABBE4ED82CFE017354FF2F69C60C9C50DE37BD436B9E4D04FC49096B 00425741F9F9361F5A5C89D3864AC5D3C8334689E8E317BDADD81BE8 72F1A8EF614AE5745375E29EC1A0E2E28787AC2A2A1786AC320C66D5 791BD00CFAEF79198EE1B405F5EB918939C63FB459488827E2990995 9E573389AB21F4A02065A3BC0ECFA0032A298039DD0F21E1951358BA 8D655732FC940E1354B1C9735D79DD788180ED99CC2238297A780267 A5BF4DB254B72F03FFDD87B1E1876B956C118194B207BF273FC6D99C 8631D598FB39903CAE7E90B617ED8CD9FB3C27D73FE5376340FE7C01 218C2A15A5FA4D430F877E005D07C9BC69D162A7B0276F770DB00F06 2ADC72F329A82A5E6BB170499FDB50161EC4E8CEB8FB2A0320721DB0 D210A1F72CD1C6AD9FA8FFB5C85066808D7C88500B30EFF0E05409DE 770839F628EB52AAE627AA8E9A549EBB577C2BD90288769CA026B379 0FD2048AA97FC32B5D14D528EA90CEB4518E54ED54985CA47804BF17 337FECE08B14F4BE3456D74546386D894AA471EA164CAB9B3261D92E 5ED63C61C106545CA8247F0FCB2B01284305DFE546EDD070DBFEF2CF 4DB93E508D8802DB86557AE42FC48FDC914B4A0D9483B4880BAEFFC6 1C34A5D48322CFDFCAE7AC726DCF55724750D033517AD00CE13D19A0 39418DF8A23A05283336B598B84E7D131D9E51ECF00FACA8398DE34E B8422F18F149FEA650C07FF3E95D33C4774936C56906003D8CB1EF75 52A0B27723A77EACB1F1A6D0E5B9AD3327BE8E168FAEA2B438BE2062 BC182E74A6117E703E98D9AA2A0D771000A241B065D03A1E2630D557 879928A7B68B8A287FADEC4FCF8CCD091DC034657E08FFCABA224D72 0B2929EA5A8A84966E4C4A2CB322F8A9D5378914C9400178ED00B79C 4A53ADF4FC5EDFB66E6E61E1A3277A0D92914A16AF328585F360216C 6D3514D2EFA1A710F68B442FA035ED78F57BB3949A4D159DBBCBEE5C C734B4F1F17E04E70674F192F079D5270F1F19B53EF2CFED9DE81D6B 7D1AA9F8E3ED8800B45ED4A3A110DF60BF6D0C26891BE05378F214DE F3FB68C937977A8E91DFF2AF6C33D5264514A9401ED00D47D8B2173F 7FE12BE2433359E9C1E455B69405F84D397CE89ECF41598C34EC2D2C 15326FCA242F48EDB6741E8A9AEE351F449C05697B8005AEEA6679CD EEF281CA22A32CEA717A769AF48FF7E3A46A9796B86C5C5FFD71449D 42A46D890AB3696005C0132EFDC24D97E6C78AF550A3E0C475E8F4EC C69C9E8DA9BA494A0EADDF1ADAA5606287400772BB205EE5216E8125 02993DE510A88DB1B12884BB83020DC5372097E1E9C323AD2EE0D811 E4C6161E086F471D1CD0E5DAD9657145C620F78EDF98DC4EDABAF82A CDD472FB7251F17FC354C824882AC8529AEE91836A80B89EFD006D23 4F5CFA9E486317CA6433457937EC50B6C1EFDF55B0776D29B8C36F70 67ECEA41D62B7E57D7C2C12FEAFF83380CB96423AFA0BA51DA333FEE DF3969F7E6095893E99714D55409F266D85EDDA8A6677F319EED020F 20CE41A03337D42A1C1FCE7C26C951A6C8B128343375E3BF99969188 E0AAA485749DD92FE14CE8882B3B4CDA3C7E7FBC08702407F057C9C2 AE0EC540E553ADC118D9AFD51AEF7303C3A128D01E432D292FB1510A 29979E4028A7F02869397C73B571FA3F84A09A9CB70CC52C36CEC79D 3D5331113594F1C842E75C87C0A79A745AD2B26F7B673CB57790B0B0 734E399AA0A835F3FF711F45BFF3CF6B97CDB74A5A1B53F9CDC0547F 04C5076D20B178AB4D01465D9B96E23C28A269A4786FA7C33FFFCFCD AB07B8CD88E7AA3CB670D9301D535FB42ECF9B85B0D8A7431A2CB123 7F2899AF67E1CF09819E01E1CBB2EDAB0CD1AE2FC6E07E7B194EE18F 8821D144DCCC49D0550E6AFE464FDC7ED36903AB42A2BFDAEE5FAF95 B909742E3F30D567D09B928A61E23B30970E8AEF268FD27CC1A76BAE 51E95EBA7A04CC574DB34127F41F48AD0F60F3CB522DE070B533C0B0 060275E300D767B7F767C4AA3FA465DC24B84F2CFD8AD4A61038D225 CA4DC038201C8D094EA1B9443338A351D9BC43FA73059EB3C2C173A5 647046441DC3AD6F71FE1A37E90095B6D1799E5D749E1953417477B0 70A2465EFBED1A5267A9AA4EC2FD10B609039690FBCF9EA57E875803 1BCE78B8ADF94C539753E35DE5E8E300A527E7EC9C04E3B6E7E56F86 F32400B25895C90AD3E03CA49226548F6808A70081CD75D99BB561DA 5390F2D3418C4079311549F89E7E4E6539AC904756A7557DE633C817 9DF1B9B98C8AC5763C3854EE0743EF600BBB4F698FAC7982B5944E81 DE5B84903DE5D692E00A390291A4FD85E6080CEE16B5AC1DC70348F4 F037F7C3A87E003AF3ECBB184AD9E8F0802E66748E3CBAA73D286424 2278A7C12F5A741FA4A2BDD65302DDB14DC2F466FF960082E4281593 22115FDAE1F8022CBB1F58DF88CC724FCE517512F87BCF4DD7EB1BD5 DDA30BAAE2CDDFE95059F19680C51089F4EFFB3C6B8BC66CBB5B9157 4D352DB346C260BA58BBD6C1EA29EBE4D03335B3E7B34B2DA5AE1C69 CEBC4DB7822752AC827AF8934C9EFF227B72844626BB97ADCFE1DD7A 4407320C3D81C136759F5DF02FB50719B5D7078F15CBD37D25A2F9C3 88E98EA4D33CDA3977A886B97D607B2FF1D564E2B9D6A044B40FB5EB F0B46ED087287F9FA0A9D4382C98965004011815EFCC28ECD159D68A D96932A35FDEA0EFE3CEB317CC537A55E7464B066A6FDA767F872EA0 2C12FF8C89686236273BA562E4EC6FCF0E166190814DBC08DD30654A 84DB902FCBFBDA00C09BB4EF56A3A54139FB230618426675D6661866 EF870E26DAA0F275E5C680EA4B8AA5CC048D1F4C93CE3A28ED6D2B67 5336CB20A00FF06AD6CF40ED779B93E3BCB71227BFB374F58C96D69A 874008D82295316EBD6394DAFC393922DE1719DAE26A1A309CC42065 35C88A55DA7C4A0F7CFA29A9D0F21BB9DC4D8448FCB5D807D3700276 9FD786525FC5F365E2EC2DACEA3287F0D203B3DF87A3CB09562FCB8B 45BB6AC955FF94C4B72F3B18F0DF78648B5A339A0BCCBEB35D8E5BD9 CF58D1D77E957790F18E2BF6018E32080BCA6BD34EFEC9760518C9E6 5416DBD9EC0E7D9F242892FC45B66E862298FBAB0D1855B762D1C505 072D06FAB0FA99CC518D8830E6FA0AEF5977E116606874DFEF1756ED 555798DAAA3FE8078A19E892B94DB166BA6A99C63C79F1F62AF6A319 601CC304CA52A8883ECFC3647C069B832169D91BCE1145995B514CA7 3D70EDC34A3887E5217279251946241447B7AAC95DDE21FAF82AC2C0 44B0013E7577877A8ED5320F8E874058D96EAAC621566A0994D762EA 58C9A3A9029645273D27AF538215B3CF672FAB49838D87CAAB2A91C9 B80E8E80306F73143A00D6AF61037D196E593D585892835BF6B87ECE 1EF5D439780BEB20CB674F5B885CC368EBAFF8D4BA43BCA4962A09D6 DCB771BAEF7E3DF9
diff --git a/bin/tests/system/unknown/ns1/broken1.db b/bin/tests/system/unknown/ns1/broken1.db
new file mode 100644
index 0000000..cee3832
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken1.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+a A \# 5 0A000001
diff --git a/bin/tests/system/unknown/ns1/broken2.db b/bin/tests/system/unknown/ns1/broken2.db
new file mode 100644
index 0000000..b06ce83
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken2.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+a A \# 4 0A00000100
diff --git a/bin/tests/system/unknown/ns1/broken3.db b/bin/tests/system/unknown/ns1/broken3.db
new file mode 100644
index 0000000..24c0aed
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken3.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+a A \# 5 0A00000100
diff --git a/bin/tests/system/unknown/ns1/broken4.db b/bin/tests/system/unknown/ns1/broken4.db
new file mode 100644
index 0000000..448bc4b
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken4.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+soa SOA \# 32 026E73013300 04726F6F74C4 00000001 00000001 00000001 00000001 00000001
diff --git a/bin/tests/system/unknown/ns1/broken5.db b/bin/tests/system/unknown/ns1/broken5.db
new file mode 100644
index 0000000..b868a6c
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken5.db
@@ -0,0 +1,23 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+any TYPE255 \# 2 AB CD
diff --git a/bin/tests/system/unknown/ns1/class10.hints b/bin/tests/system/unknown/ns1/class10.hints
new file mode 100644
index 0000000..cf78245
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/class10.hints
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+. NS ns.
diff --git a/bin/tests/system/unknown/ns1/example-class10.db b/bin/tests/system/unknown/ns1/example-class10.db
new file mode 100644
index 0000000..ba69aad
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/example-class10.db
@@ -0,0 +1,31 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+
+a1 A \# 4 0A000001
+a2 CLASS10 A \# 4 0A000001
+
+txt1 TXT \# 6 0568656C6C6F
+txt2 TXT "hello"
+txt3 CLASS10 TXT \# 6 0568656C6C6F
+txt4 CLASS10 TXT "hello"
+
+unk1 TYPE123 \# 1 00
+unk2 CLASS10 TYPE123 \# 1 00
diff --git a/bin/tests/system/unknown/ns1/example-in.db b/bin/tests/system/unknown/ns1/example-in.db
new file mode 100644
index 0000000..9b4b8ec
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/example-in.db
@@ -0,0 +1,56 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+a1 A \# 4 0A000001
+a2 A \# 4 0A 00 00 01
+a3 CLASS1 A 10.0.0.1
+a4 CLASS1 A \# 4 0A000001
+a5 TYPE1 10.0.0.1
+a6 TYPE1 \# 4 0A000001
+a7 CLASS1 TYPE1 10.0.0.1
+a8 CLASS1 TYPE1 \# 4 0A000001
+a9 IN TYPE1 10.0.0.1
+a10 IN TYPE1 \# 4 0A000001
+a11 IN TYPE1 \# 4 0a000001
+a12 IN A \# 4 0A000001
+
+null IN NULL \# 1 00
+empty IN NULL \# 0
+empty IN TYPE124 \# 0
+
+emptyplus IN TYPE125 \# 0
+emptyplus IN TYPE125 \# 1 11
+
+txt1 IN TXT "hello"
+txt2 CLASS1 TXT "hello"
+txt3 IN TYPE16 "hello"
+txt4 CLASS1 TYPE16 "hello"
+txt5 TXT \# 6 0568656C6C6F
+txt6 TYPE16 \# 6 0568656C6C6F
+txt7 IN TXT \# 6 0568656C6C6F
+txt8 IN TXT "\#" 2 0145
+txt9 IN TXT \# text
+
+unk1 TYPE123 \# 1 00
+unk2 CLASS1 TYPE123 \# 1 00
+unk3 IN TYPE123 \# 1 00
+$INCLUDE large.db
diff --git a/bin/tests/system/unknown/ns1/large.db b/bin/tests/system/unknown/ns1/large.db
new file mode 100644
index 0000000..ada9930
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/large.db
@@ -0,0 +1,3011 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+large IN TYPE45234 \# 48000 ( 45841674994e4f5e4ba43aada754d631
+ dfb7e12155e7f10c551032b3e56ed5ba
+ 5136c15cda201e7e5e54fb60a99388b6
+ 1a565c1cf74cd8aae1aee7fbeb54cebe
+ e065cf2b1b317f67277ae733183c668b
+ a81a7efec322d36fb5cc6293ad7f7ae3
+ 544a7c64d404c4eeb1b889e9780a213b
+ d548a018be2e1b6a3b8840d714ddb8c0
+ a66beaa4c2a1471d216ad0eb8d2c8849
+ 60d30fd3fad058c47eace42aab0f0d40
+ a690ca3baf9616b7373b889788e89175
+ 7ae0eeaccd291d87d05daed8631d1ebf
+ 9202f81659754ca11221e902a69c7bf0
+ 039310edf5305ace5404ddd02163be0a
+ 22334879a27bfa7702e13d06f1588726
+ 1a12abfd0c01966fa67f97ed38c521db
+ cff8a2aa8daf53f1eaa7991b6767da0e
+ 68b2ebb38beb8f1aadaa30c1185870da
+ d0091e7af0bbed453ce081ba5dc87ca5
+ a764592ed7312c6a26f7e358ef35182a
+ 49763a61c9a0c5dbddcf199251381215
+ 51eb3c3ced9f529f03a85429f42f7550
+ 3efa6e1301aa7ad9b29c5aaaa1ef6ee5
+ bbe9e2639d65baf98a6b06243483a245
+ 3969f65f9a0dad3d8630522079b8c107
+ 9e28057d63696739b71f57ee85ab20a5
+ 96865d77ef70412c7a4be7d9d5a4eb13
+ 709f0ec1af6a4cf962364761ebd62efb
+ 4f16ee843c1b214944eff2c81563c4ac
+ 4c854c32972df761f17fdcac3e40e027
+ 57fdf1fa57f77e1c86c3d488b02d4634
+ 501801be4f929ffde0ed07112093d901
+ 8d59cee1733bfdc8a968a831d42b95c0
+ 87a578e3c6eefacfa1c9089072ab490d
+ 631b2d00cb75cb33586917f103842856
+ ca2f5ccd449465b4a86a37f8147d6269
+ 69f02dafacd4ba81b680e5dc288037ad
+ a3be902e2ef9c129710200ac93f5d3bf
+ 1c1418b65d98bdf101d38d9b2c5f25a3
+ d09a4638dcc2c0d0cf411f3ed747e674
+ 5ac7a8be03ea2ee990979cf3b8398c4b
+ fb058012de25fbf0e1081c4205afc54d
+ 3bda63565bc0bc3f6af91f083abc26ac
+ 7047e2759f28525498ae6461a1f66b90
+ 0fde5d8cd6c842c587f28620444ad5bd
+ 3b522f0294c14e2279b5c577f3f41c15
+ a723a20259805aa18360f6b954b75d98
+ beecd0c0a0ad151b0027cca891932adf
+ ca9b7eca33fd585031c188f8d851e3bb
+ c8552f340e1319553bfe776975baee6a
+ cf025b8c4849c0a430049734114b7534
+ 5228d19846b39580f1c328068a4b36c4
+ 3ef13380be7e54060acd9494ee99908f
+ 57e779a4c20728135d509b52d5066cc7
+ bac77f1c4fcf81e9f0c7cf621593e90f
+ 398c56b14fddc74f62a4854655cb27b1
+ dc94a83f9a4a52055ea74ea3129f88cb
+ 8d01870bfd5157cb966cfa4121e018c2
+ dd72f363dfa5011d1072fd9350dde79b
+ ec213520cd68ccea356ee24b2c3e8487
+ 1540c410353e9514188a46771b07b2b0
+ e261287d353a8d55a71077b4b509fb99
+ c80d7d07f6739cbc9ed82a5a40e624c0
+ 860a42049585c0abc164b6e5e726da58
+ b6faf8384e0c8e9a03bae074415335ba
+ c4e72aad561cb77a8d7aad25c67f3d74
+ f38b62f43a2012fbe62c0def6be94809
+ 8dbcbb0f06769663b8e6a7c0d88ac914
+ dbb8baa785f4509b2decad57f85516d2
+ aef23a24202b4123f4ce41e97653b5f3
+ 8e7e092c8ebfdc36a46d204237ae7148
+ 4f4249740c2eca7beace1699ccaac0da
+ a6ad8c1a0c5aeb59086c2179a235085d
+ 0c68942c8fbd67ec7fcf627049df4790
+ 757f40d7d027fbeae4a358edd5867c7f
+ 5671046038e3086d76d3e22f868dbe60
+ c64eb123bbf15358fd7d5b6511cedecf
+ a701494b143f77f7463d8e3099b811e8
+ ab53092b3ef6e995a655086bcf61eb77
+ 3900d425132a04530befc404f5bc27d9
+ 8dd2367bb815580f8bb7cbef47936806
+ 48959a44a6cd216196a4bd61d1cc4432
+ 6869877e2be943c6c7bb95b854117b1a
+ 0b00d33083afe54461024bd791b2724b
+ ed82edd289f9376c7e0502627e1e3672
+ 345dc53f1f25afb60568ca28c84b9214
+ d32fb5d805cdd31324640519c3dd0b65
+ 19fa93ab15d734fc0c5abbfa90c910c9
+ 0c3f38b0688b584b6285427f760414c9
+ 445b415fe433908035081f5ca081ab53
+ cc7c2701f65a18a5e64eba887bad3343
+ 2735c1e62ad2b35f0a258892d919835d
+ fa523e2bac6ddebdc0c576401f21d937
+ 711d774153a7ec42125d24d115240fad
+ b90fe0061d9ec041ef2905e4aa3e81c4
+ 53572df0f72a43d070492261dcad2817
+ 4f8b16979db03c2f96d9e53cbfef510a
+ 1bb5d6cfbc4f92a9e94c0c018738e2a9
+ 30922603083124284b076fc1f93afb20
+ 878ccf756c8de07dc6d01c273ff26081
+ 36a8dce64ba4287cc19e35b72b40a32b
+ 435f3bfbe94a97f0972aebb4c54d95f4
+ 993eb831307d22647a1eb7c525fd470f
+ b9ca13d3404ca5ecff99e87b73c5b88f
+ d4a905220db8d183c325e7d27a4d70f7
+ 1469ed347ab68a9f7f1a5ea235bcd9f9
+ bbbef91a9df227109d715941f54ea464
+ c9f8a9d0724bd4c9772023b086bd521c
+ 516449c780500cb33630ae28cf02c19c
+ 0958faee545b953ca46217b7ad600679
+ acd85dcfeccf4012aa9d5a7e1a1b1a43
+ c7d9a91f8766ed3a5ef61a7a0840bee2
+ b8eeccd5932cb1438a7aa271ce6906bd
+ c3d9230ab8d0b095be53869b37455d0b
+ ac413f518e39767f23fc669aa0742b8b
+ 5196fedd1284c27d05372f4653618962
+ 468ae24a6c575daea152d036619adb96
+ 5487d0631b6182a0ebdd5aac519abbc1
+ cbe766283788e8fce8ce91760edb4cda
+ c1636de694364fed377b9dd5512bb258
+ ff28533ca454ee161e69a58f7964a88a
+ fafe768340ed78896d02fcc6d0009072
+ 8c86c3c21cf4b89eeb975e2a674b64da
+ 5bc5d05f6d647252e7b3394031bc9b45
+ 65c466e5d9b8d9c2dd96a9950ae0d879
+ bfd8c343709968f0d4a885d9c0a4ad22
+ b08fa3cb093dcd583afd49966cb842f3
+ e739fc665ae78550914896a2d8f66072
+ 6e02b7847afaf327990a3478362c091f
+ 2b0bf7dd8afd4f935141e63c7c4a680b
+ b02bf84ba0e2fbce5fcacf1cd51c7732
+ e97a358dbff58dc07ae2cfc5f66ef5a8
+ 532f31bfcfa86886751ecfe4d3234c3e
+ c84eabcb9de56bd72847e894ac95103f
+ eb7de2c89780e7377ed61a1bd813f649
+ 57419bd798632aa7b5a43d5e90463fe5
+ db8373a91487e71ab990c0b68c4f8630
+ 5a3cb78216c98188d9c4ff715d7cc72b
+ d4b64253b4a894b2b9a3f7aa6c41a1ed
+ 2a7cc3553c3716c6d3ca42e4746a1801
+ 93ff49e0b8063412ef9df6217c97d30f
+ b7ecc5abacf22e08105b0b09807b3f3c
+ df66a695f46f5ace7fff41208859ca38
+ 610f6a91368685c9ef8e68958acab3c7
+ f198a484acd6592cdd0f1507af662a61
+ e9fe8eb40efeebed64888802978952dd
+ 21c9d903b2be0845c3611a138c2750b1
+ 35d0d55fae5ae23a8274da034e28d2b7
+ 760f82ab2f83ab1cd34d9c45f7fb6352
+ 7845704a4e68cf578c8604f269f70db8
+ f4462980eeaaa40ac20076fdddfa2f2f
+ 31ae7e031388ed6bcbf0da39fd210351
+ c956151c5a69b8db3ecba80b6da822a8
+ 58e8d5abc24d3afbade4b8fac50cd36f
+ 3926af3cc6917d2a54a83540bbc96eca
+ dbcdba189849b07b865538b3b4fe142d
+ 2dfc0dec688da44b3c0b8c4605a00cc8
+ 26bd5826a8e43f225e75d246de2c8963
+ 94ac9169746689010f2e958029f874a0
+ 84813663bf14a38111685457842be856
+ 6c634fe7bd34a0846b82929dc357f06b
+ a186a3a6917521881a1b84473b9d6be8
+ c10dda27655bcef81ac6e717cca29e9e
+ 0f6a02578b7a6f97cec7b600785c4ace
+ 6eafe9f7f604f7540538f96501467456
+ bf132d1f52555de292c21e3aa5fc24cd
+ 57e2a65e742e2fec311f3cbd19b9b4f8
+ e9c5a66191f4c19b8f641d9c7fa58338
+ f179b533dcbf6a88849e4bd01b094b5b
+ 8b09bbf3095f683029dfa61a4c91a582
+ df0380aa4a0abc97a7ba9735bc7c2894
+ ae6883b42cdca772626c31088c1684f6
+ 4dea810199c2d48a5467db001ba4e274
+ c0f7a5e762cc615a91fe537b356c7d76
+ d24d310ef4d6d1e19f1788fed740686e
+ 9bce08e6b06b99a3bb71004775639924
+ 20fc70bb75b783820df34c3f7595e7ef
+ c3e225ea5f2b33c05f515e1d3b4da67b
+ 0dd461e1a82260b6d2b7a0a43265a800
+ 3a5fd13f57cf05878211c6e1eb8c635a
+ 2c8d1533f0260fad1df4fa41ce398e09
+ 74a5ea54aebecf6e9ae57562baa826c9
+ 831c56cab61565e2697e96f563d55b75
+ b48a4fb6f32c02ebc2bfec9fd519c396
+ fff42f1c4953dcd2ede87f62ea90cdb1
+ acbac2b187ef71047de4477514612593
+ fd7f849e4190a59bc147ea07b794e088
+ 0ea37f5f27aa5fa78905f64956682538
+ 90699e319f14d54996e36e1f6dded0c9
+ 552605ad9d20f8f4e6dd26fdb7fc6814
+ 15f15d47e4997995a671f85f56e54a14
+ 6d1e16c7909b0efd42cafb92f12b9f4f
+ 88157a68ccf8dcf3295ae65d26dd5323
+ 3cd414f73881a5fed934c577b7c66f48
+ 4965e1ea507f2fdb20141a9c6458f222
+ 65e26ce6ac906b4bd43f178331328bea
+ 55c61e737f2f130e51f0ed343a9e9709
+ 036abe6338446b8ca7b9cd831f4c6390
+ 8fcb6eb134626f89df0a134f9f7cd196
+ bc96a5ddd2b2cc5530220d4708d5d2fc
+ 55eb64ecc1b668970e7df11faeb37826
+ 30a3792089e2a0443631aec02cf8078c
+ 8cacb3bbfff7304670b391690ae1a29b
+ 445a46cf78b84d26e830b8d072c2f0a2
+ 292cf29ae11f509855c1972d5f86a137
+ 73fe91954b2eb5c8e75b9554c082fe65
+ ea01d0d6794d621b231db56dd59eeebe
+ 4d71144b966c19b402dbaa25d051f9dc
+ ab7f063142d35123d9ca28a89a4cf3e7
+ 71095f794f6a7d495870ac9f47d1e024
+ b5341c931590225b76931999c9d341d8
+ cdea4d0443d719e09ed227584243480b
+ 618246a318addf475a70f3be57c3278e
+ 23d48874e26824864abe829ca2318dde
+ c436d182040f014d4fbcb1fbdbf2ab82
+ b613b7ddb45dc7635796a6ab203f8d9a
+ 6a04c08b40be8452b4058eb6199ff68c
+ a8a570f1a179ed662e4fbc1ddb8364cc
+ abdb7d25eb9bfa6844d4d379fff7161f
+ 13d287af0b6b9ef3d2c164bc63d412f0
+ 4cc3ddbeda6d973838b329108388ef70
+ 0e42e232009782d380127200412e2767
+ 1df2b17d5d7fa517ce12c66d6b84b113
+ 65611cb11e0bf27b06f3b86c4b4572e6
+ 3702dad0a3f9784656d16f7b731951fa
+ efd190b4f7e0322871a2733c30670c31
+ 1db6f8c24e51c747525d04e551dfe1ec
+ 6a20e796d0b7f4be73896895fd6bf922
+ b02bdc0c1412317ac0975d0cbc8c5a01
+ f17f842c9cdef7cdb02055425bb1ee0f
+ be46bab2fb6c3d3e3d86eb066edd23b5
+ 7f18c3b9fec9c6c3d8d41b77dada06f0
+ 8890490354f95e97fecee7f6bde50325
+ f659971d8940c6b299531ec9e07413cd
+ b92ea26db7ae21a151cd59bfe72b8a19
+ 998384ee8985cc47544edc79f5f266f0
+ 887664db09136792e75dfbc306db725e
+ 5d1089de94e3305a3db61b799a22ebea
+ 3a72c52a9eaa89a2983f47fd0c685445
+ d30c6023c855613f33e023e1a7312076
+ 2816b70ca46fe2bf0c14b9706da2f993
+ fe00053ac68280337b92fe344695da64
+ cae061541164bcadaefaecee529aef20
+ f053010426633aad07a98d8d6453ad01
+ 64951d85c5db7965f6b845c01ee4b13d
+ a933cb152151e8052bd6052b22ced3f3
+ ce96040a23b6661ae078930970cd342d
+ 2464c0638c7988d06a5ddf9130fd4148
+ a8221febf8200323c42890e57ad3c60a
+ e443c72f60388f755bd0f8d8082bc7cc
+ 7c26b280b6c186fee3e7161793be25c8
+ 373d7714e1db51f9af53809cde5c1141
+ a183a84643b4d8cd3d1777e9f5c70f08
+ 22c115f2c663d2c02315eb183caa4122
+ 703e24792756ffa86077feb7e4fde230
+ 4ccb5a8ae1b2bb506699ebff1067c50e
+ 835f8cacb46e0fc93216764f999687f6
+ bc9f93516b777391d03cb2c74dcab8f5
+ a3cd2f0c2715548f8eb36b1b138d0d95
+ 9513884ce3b6a4f7a835943687c92d9e
+ 95c9bd30aeece528c9965c4c927f21f5
+ 84f37b42075188d24e2ede898e55a6e3
+ 3b7357792ba7fabef7cb09e1814d6f2d
+ d1d5c8d029d2421ee6fd905b393d9d47
+ ad6b9f2805ec387154e88251c2e066a9
+ eb378e00c7ee4e52872dcd718c67308c
+ 6388bf175ec90ff818f49c4f80633dba
+ 8351d0f162a5ffcd9642e553e6763dfb
+ 97b52899ffbd4614568eb13a730b1adb
+ a54a41445e70bc6f1bc5723fd236b133
+ b966ee67d9604efcbc828eaee587598d
+ afc81f0c71efe2d5d07c41959df2636b
+ 3b3054903534d678e436382ea38d8d24
+ 041b7a254dddb783ffa19aa7c128d5a9
+ 32bc8ac3e04df72305cee70433d4920c
+ 35d22b21d2dcfa2a4640b7afa4134c15
+ 30ca677d175de1be666b24408ca698aa
+ c57a5d9dd41b9737ce9cf73c3027ad2c
+ 50d80ae4b3966b00459ef11505297e09
+ 6b86933efa71830b010fbc41d7832de0
+ da01e9edddb1aea400f535cc4b601e80
+ f95e17e0fa104bcf16a3c4514a8f2f6a
+ fc59669b1f2de45895a6ce3800823f3a
+ fab29e44077f5b4689240d10e62c1282
+ b6f8e15f922e02cc2d9cbb40f2722fb6
+ efd6c8e921575df9a46d3fa7e014b0e9
+ 1e1204f4081052d93a0871c35ce92b92
+ ff3c49f90fc42727d5c9405540dc8406
+ 499fe053fd146423a888e1a3e0728c69
+ 381e0a2221adc4d0bf9b51f7ddd4a8ea
+ 74bfdf20054b935998de4cc852faf089
+ 07f5c2a33686eff3572d55e6227a3cb9
+ c463d0cf6a2a617516ed7f5993f4530b
+ 46d2791902e12daf36a73c6ca7b6d486
+ 592c2e85b2fe942492240e3b6012a8d1
+ f28d37f1f2b43cd94d7b93aa56de82d4
+ 135a84190272ccb9a6ab606d5a929f0b
+ c2b0d0485429f2b8066307e0404ff7eb
+ fd02eff231838d43bfe1d8ecb77372ab
+ ce6daa1a48b37c9d30d94c12e81388b1
+ 0845b62bb311325929a21712930c5d61
+ d058f5f8abce4c198ddc482034407b7f
+ 360ba1a65b2e3b3037c06c3cad7c706c
+ db45ab39c9317be281bdf524c2ffdb29
+ c6b3be40b91b62cb7735a463829c4cb8
+ bad28ceda3d8b955791e75b8405a6c03
+ 9615dbd9dee3ba95f922bca586a39119
+ fec0f510fcc5c5ce70c9d6b09cb0a47f
+ 314c09c3735c7e7c74784ef20953111f
+ 3eb067547167a78827072356df64c101
+ f536a075a2aca016e13a9f8695e2e7c0
+ 9e56be291a75958c3de58351e50124dc
+ b4846c97b58427c344b773b27f5d49f4
+ b781a13c87adaca9fae45bf53a8e9f6a
+ 8485d476297dd31ad7c635dc4bf775d2
+ f869e79e3e92f0af0ab2f0c9c610e76b
+ 8a83998eee7eab21d3b6f4280754f165
+ 3d076df87fd2c41fb744f41d20f54063
+ 1dfa55adad22879abe3498a425c035e6
+ 24bd8032fc55f131319152da21a415ec
+ fdfbde3a847f86ee4221d7c84d76f56a
+ da0d8895f2545bb4b3f4176934a4c07e
+ 22921b23934b7e08993102d33094042a
+ fa053c95ab0254a0f8dcd9305569c270
+ cec22e49db90462320cfd05642ee9fbc
+ a1a9f28d0ad119cdfe19b7a7902f039f
+ fc484795a0379fe0c83743b915863881
+ 1be89cfaa14a10f3ed22249d5a57c4af
+ e42314f71445b7146cb4698bbd4d65c7
+ f399481e131990245eb34495e490d747
+ 50cf9ca38ad44c767ad2b653ea501727
+ 7d688cf40e036717e46b379d004b4f70
+ 5dfb93cb10a821d8b3d02df61f3b3e71
+ 25c3464bb30cbe4d41e8203a6ff27005
+ 9e2c32dfb7b9084d23182c98334ed88f
+ 7494d5f4415e9ffcb5c282f6ee8c43d2
+ 5eb4bf38b855da2e956f215616e66a21
+ 5bd62e834b150bdd0a9c16da61fe88fd
+ 5ea186f9543bf71d3a7bed4ba24b4b91
+ dcd1736d71b926f642a8bda5c8918737
+ 95e19865d13d41640293c6f04d6300ec
+ 7594630e8f4b962ee4fd9a19a19f5ea9
+ d0bdf87306a580a6ccdc995ebac0d9a6
+ fefc145f3c1254679d61b2550db75b3e
+ 05ec44bb7b7e1db2eddce79788ee430c
+ 9f394401127a6925cd8686a6eb48df58
+ 7b3d97c5a1a093d0a510ffcdfd99c243
+ a84da3b2ebdf1f9ac84b19d2385777aa
+ 74f4d99069628e9b0300035816906b45
+ ff35c4e255c6cae2131cbaaddff7ee88
+ d8df8a70b4dfa16b4ee08b95725b3430
+ 1c5760422b395cfc6ff2e8bcaca5d336
+ 8b184c25bd1d1f9e3eef8acf67ecee3b
+ 3a2848ad8f930a54474016512b5eed31
+ 2a0a6e1e4130b430bfc602ca6cadca95
+ 38a60ec4e797b0f7d72fca7f4e63d32c
+ 7226b0e5dec95595b648df8682769deb
+ ceebc0451f562cbc4954753da83decd9
+ 88c045b44558aa69b0daacd20507de0e
+ 1d17fd0e81aa483364956c285d6d75de
+ 2e85c7291d70f17ef44d85444b44f734
+ 8d9f2bf3b8778d0e75ff2a45e815be9b
+ 82c8fb97e26575fea32d8d458f7776e1
+ 8406f60a2f0be74921272c095be2e3a1
+ 108b2e1b598a1b1b9440197363ef48e1
+ 23279157f233141c90e127aad98ce050
+ 42318765c6fd3625f8d20d6bc269b78f
+ 1489ec5dd8747abd96631f85fac2537a
+ f9e4ded1cf292262a59a9abeaa4644aa
+ e2ef5f1e78c332a2a7eca12ffab4db02
+ efe11c5e008d1831bc9f31ef392d9fab
+ a7c2311e362649fde64ea9dde3dbe955
+ 6b8c534835681665e7440b624d7f43bf
+ aa01f4a911654aaa28728aebb7eb433c
+ 753e2cf25b7b42291454e3e0010ff9d6
+ 2bdd0e2b211cb53963a4c477af23c452
+ 862200bff51f233e036526f51f6aef66
+ e923f58ae7611badbf47c4e13eb509a7
+ bed7371ba0e1c86adb8c120006dbcb34
+ 5f8f2b47cb48d0b905cdf3e323e5b63f
+ 48e3d8d9d4143744ef2598ebc3343a3c
+ b86afe9de6d14611797e1cdee2e75325
+ 9002796bb75378705105e4cea49f77f3
+ fc4beb16aa8524fbb12b9e5d65e40578
+ 07e689ae0cf73afb5c391adaf34c37bf
+ cd230195cb4fd80fe5a9594643399266
+ 36670ee65b1fa05ec1b11cd59439e0b1
+ c0f903519cb63012b04f2eeb8fd0628b
+ 30cd19aaa5afb965565cddea0df6828e
+ 4729fb154f20d15a071922ae6036a423
+ 150302ae477c6234b53a5189bc0b0314
+ 09cebe716e6b63f5ac51618c00422fdb
+ 410c322aff0d16ad43e1744cb84e2e8c
+ 73b997b0c6eec3276b83a9a7cd61a2c2
+ 5f07684aa602251b5ce4a5b1d04580e3
+ 8ee3f84b579185082a24de6e0f341891
+ a1dd9dec8d13fbc99bd27393762504ac
+ 7ff22f4cacdfc24f60e86afa9f5eeea3
+ 260fa150a6e9e5582f9a38e8c5fd1bba
+ e91149e86ee9c923ca3bbd9c9197aa77
+ 7edc9881e48bdc7797d78ea7ab0f2653
+ d01a5b6575ea262d6b9f8446f12c8829
+ aff4d0ab393386c34a4b7c76b561279b
+ 1853541f108c5bcfcbfa409b11ba8f07
+ 3e5609a175bb5d721239de7c62c0f7d2
+ 623f3aa685dbe9a68d46fc1c44c97e91
+ 77034de301246e605000f780c37a8c3c
+ 5d2dee05ab24a14ae99ef9703e46c184
+ 6bf4e0943d69cc6e26dbf2e6d8520199
+ bc8722bba0a04d7e0be38e5426e6321e
+ 87196b60827c152df6c3fee15390807e
+ 29dfdf95c167ebe1c798ad241e0cf628
+ c124390ec99a12d2787534e8a7f465d6
+ 0ed174dde1a549a6048f967e02bbd385
+ 07433f1767c62aea91bade805fbf81dc
+ 1016429b1781f5709830765152140780
+ ea7afcaebc050105577002752ebc5fad
+ f6a480c39a400f2a4b4e4d3177ac56f9
+ 77a834b61ec159e3e418b13c593bda9d
+ 1d8adf700a6e56666dcee95f0d78eef5
+ e7b376f3cc271fd509d6caf1aad7f8f3
+ 9692fc9f089a0b602da1f6738f3dfe72
+ 4ab46043196ff29a05438cfd3e8ccc75
+ 8b3cbca2359691e96b8bda93456d8478
+ fbaf17fbee09f8b92f73deb36686cd00
+ f1c56d2c0e8a622761467008e5561ced
+ 20783c8cfe58c0bd2f0d2d37d95758b8
+ f384d1cb53c0c78743f6f592cc12222e
+ 40cc3439ff88bc4fce1f3f8644903477
+ 17db9cd92188282d71efd9af49a24af4
+ 8613ccd21e37fe703dc9eddf154fb4f6
+ e5a9aa1a7cf9efad397db7d37fe5b5ee
+ e0ed05d52a2b8a9be809b08bf9e37ba2
+ 4c112ca7ffb04eb8a5ebf84c8fcbb11b
+ 3ccf5a74b315678843fedaff528b2819
+ ed53df3956bdcfdd430f4f17fae4f5da
+ 66381f01bdb4173835c20fb5a53a56cf
+ a9c2e7f9dff8afb151b99c87e4e66479
+ 4463076f0ed01e753dc83f59e20d43f6
+ 87794b73c87943a83044d7a6dda34f5e
+ 59fdfd08f8da7f50f849ee986473b3e4
+ bba7fb04e059ff72c0182d2d79b51308
+ 22e270317f17fbe2275f50a2f267c0af
+ 86262c93c08c70f40789fba2f163680a
+ ae1c441a5b473da610d97cb77978fd26
+ 0c02533d59a25b941d0eb332bb831128
+ ee68c4c8d132e35b19ea4cb70028611f
+ 9c94252323537e24da9548e2ca8c753d
+ 5325e9412ee2145dacc6e39d75d481fc
+ 06e21257fad4eed7b6945d89c4512bda
+ 4ca60cc509551dcd36d9e8b43d3100ae
+ e532848a82ca9a30d280cb08445ac370
+ 3aecf12f2f5d386a3b530f7bec78bda5
+ b8660c1231e798170e7fc85e3731d952
+ 02588d386f7a95ac980318dd66204b10
+ ccac46e3018485f06b99d315d9d00767
+ ccf6be2dcf76ba07a36ad7fe8d4bebcf
+ fbf0e3f0f1e4019911d55e256d97899d
+ 2e2ae17047d0ae8b33b87466ddae25d5
+ 09c118d843ac99de2dcbb4bf65b5cb47
+ 3dc64e7703618d19518420a5508f2905
+ d9c3e460f7a564deb07735cb97b8ca7d
+ 25ee81da547b24b328ad02477c436050
+ cee4aa368ebbb8f6af1e18df725ba14f
+ 75f0ed274bbdfd33cb70284902352bcc
+ 20fd778f261ab0b8e95773cbd0c885da
+ b1b5b04c5b030b52740fb17898425751
+ 9ece427d3e3b5ce6ec9d2bf2e3ba311b
+ cf81f2f68ff2c60f18a7d2328c9bdad1
+ 6ba1804267dec7594a0a202cdbe6b75a
+ 3d01b851322ab4b271df76336da7558e
+ 1b86e50b488d72c65bdec1c8c91befeb
+ b18a7e792645298e0492842bde70f404
+ d70321191a05e7e18e88de01a4faf665
+ 33dc61f17b3e5c09bed484ccb11e4e99
+ 86247d417b7957acca5d52d8a54667b5
+ 2d5fb7f86a498533b5daba6de302e3ef
+ fa384bb1a7dc3d655db991ad96675c0e
+ 211a43ab076494ac22328b7ac6af9f68
+ b5d1b61e411e832e20963a59ac3381f0
+ f7b0220e9d0b7644c13b4f342f3d913c
+ 0cd40c166c8f205552ba0d40aa3ce753
+ 6a73f0e37c56f6cf6ec05ad23f4514a0
+ 42456da61a93c4feee283dee4d064592
+ 19fd5b9cc646564599a8374d118cf501
+ 26ee5750334eb053ed02f165d2088e93
+ 1c448d01b019e99bc6278d28ad51707a
+ f1fdced96868db164023b620360980f4
+ 1b799dfe5128743d9e846a93cc7e90aa
+ b95fe6cc11c19a7dd63479a64de91792
+ 93bf80146b3843e4bf4cdd5862dfddc1
+ c08a7606d2f9581697154cb62776fab5
+ 635162ef47e8243d82c42167e3a2d36c
+ e13dc37dce1d6013b8a909df50110a50
+ 3bc53784ec0790a24cee85349d94c8dc
+ a95b5471271a1bddf96c9cea5ddff0e4
+ 97f3d0e13b4eabea8663ed398ce1b093
+ f734e6739b9b2a580bb207b29b8cef0d
+ feec03338f6ded40fc15302d52cb3f9f
+ 0f0655461ff2ca6b478f11fbf5b818b5
+ d7793e6d4395855f14f8a9f1614ebe7c
+ 01653f784a5afc96de462284f3d69537
+ 85bdd41d3dbdc1ea583b12a61ab17ac8
+ 827313b01248778f76f2b8b8fc6cf3b8
+ 8beb8d177531348a0ac0543beedd87db
+ 164b6e8d791aa04b2133306a93535726
+ 967986ee6701ef923c6c31b38076ac56
+ 8eb86aca9c9612dee1b106e882bb11a4
+ 6e7021ef694a16da53cffbd5d4d2fa9f
+ 010c65351bacf8b0def5a64ee32004fa
+ e90f4e9f37809344e1bc7e695403b844
+ 7c15b5366d1d267b7a21651e0dccca74
+ 5cf75570ab1d8a57b2bb6851fdd41904
+ be0200cba44536e370e923f76bfda606
+ 01e2e841ff09a689bb648c39a2cec056
+ b221f33ef0c21178febf4e59ae1a1019
+ 918ab6b0a2b491b94794f8ff121d6fcf
+ ee902526f5386360ca48ef37fac49161
+ 8e7416ad1cea19358bf23a0808d17f4c
+ 8526e524b02f76ec858d7f58c081d849
+ 15cf7f289e3a5aea019a4536122a50b2
+ 1af468fa23e709bba3752d3592819f17
+ 4a77bd95330f1734a60303f8c04b17c9
+ 7e5451e3b500f9706d53643a6877fa70
+ 4172a2b04c0ef3cd5e8276184afb11ef
+ 47892c1ffdfd796d183da535a983a763
+ 34e611d01ef57633c7c8ab9a7e6194c5
+ e5190d47053ce62de7872fe24a536e10
+ c7d9f4700f1793edc71eac3a4e885d7d
+ 34943b3e158b69378c2ae1db1022d1f7
+ 6167cdd66ceaa97e1000975ddaa3d829
+ 3aa9cc2122c9ce145974eb4c39b68273
+ 06ab4631d12534497b8c10dbc0c3b758
+ 00a4f7e31f096ff1e3c3e6ec6007b8bd
+ 82271e412e4894320025a7f2c37c555e
+ eed34b433132b93d780fb5cc7aad1172
+ 8e53017565bacd1fd26d078a1454a50b
+ ff4d55d2bcbfb9fc3aaa810bd848fc0c
+ 29cda6a112162686ce96517aa43c0b99
+ 4a2e95fb603efeedb25ebaffa5776437
+ 4e51d1caa9b792ab922a55a0889b4875
+ 1f5e2baf8644cfbd3c78aae5c705cb8b
+ 8ecd507d79b14955807565988f8db697
+ dbdd28aebc2baaf4b1ff54154f44aaf2
+ f478548ae693230b82712790f3bcb0dc
+ 0913d4efa562582c55d97b4000819777
+ 23487b46b56860fc090ae27a01b5506a
+ d351c283ae7908714528fdb7d23653b7
+ 10dc093567892214f2c9fcb716a3de1d
+ b734b495784079043f86984c7bf28df2
+ a21dd7cf926e8812611888674de191cd
+ 2ecee86f2cda1a5ea144f0bb7b76202d
+ 21566507eb386b0de37ced06898e93b3
+ a69d7f5e8acbd89f9e106b5519be4db8
+ 63e4e332cad22b5b9465f9a83ad5cdaf
+ 9ed1921338601dc36efd67a481c145a6
+ 4e417d122b2577d5a4821b0e95c5e227
+ 04fb390b2de004b880e885898321bd56
+ 96353a9e221c9ab694797054acc98787
+ 678188007ed2f52c649809234f5c8968
+ 08703c5320dadb6d09b7ed83d955a313
+ 9bdb3de6cf343d77bcb0c99397ec2666
+ 0aadc1b01bc00d005a5ab832259d00f6
+ a28b5e62da422d37868237c75604e483
+ bd5d977a87ed6095fc4604e498938b12
+ 3c9efe9e93f8a2b19f0780db7f75454b
+ cdd36285cc994b516191645b81f99041
+ 2a950fc7e6fae28efed0dad9fb749ec7
+ b82bf450283a76d627f911db39ea0b5a
+ ab29256e23556a41629d5c39f721b132
+ 32a60b52581ab4e6584141792c7caf43
+ 2e1da87da74fe9f4bbbaac01b83d2ee2
+ bd29d6fede81a2c2e894b993402c8dbf
+ aa35228fa5f37c8b462dda4001009e00
+ d06b10b2694d9099496c9d2f51146eeb
+ 2158a14068afb818c1e28629337d3dc5
+ 0dafbdad00ff4c8ae6d3391911c25562
+ 8b7b94e2be41ec7154e25208687e305e
+ 94a102bc83cf8156c3e460f21cc6877d
+ ec8b7a868c374ae5db60a90208605594
+ 8b52aa6167ce257f5590bb7f1b38bd43
+ 4f3b28278a4da0dbc249e22987b7c86e
+ 491b222cc60431571b9d6129322abe7f
+ 0bbdc63e48faa0c6f595ce02d9379986
+ 1ffa16ee7c4e7e6d70db222cc7122ed2
+ a567e596e20731d5df7342cc8a69184c
+ 0b7db62a9d95d2eb893a3b262d036944
+ 92452340d18b8fa36d2eb728a13b13a7
+ cf48d3c7e13040bd20d006ec57e779df
+ f9ac004db4a4408ee86405496ce28817
+ 7422b222c186a3845c0c1e218d2ccb57
+ 0fe29478da4cd071e7adf135eb1762f5
+ c66ae15dca6efbf93385236b82c84454
+ ecf904a121119add36c5fb70549f2bce
+ 09633094c61368f5de53b22fb772c38e
+ ef77a74fbbe1246cad6e4ef324517299
+ 1c45d7deaab0c0e1c0a33ca2297eb507
+ a3c6833afbc7b0a6af1e101f19fabe27
+ 4c2271c5fa9a4674094418d5897d570f
+ 95b2483979e904aca9eb76d80263cd63
+ 9c93e6abd84d0340cc3553735f0c068d
+ 653a274686a33264e85ce37336a8dd88
+ da61be72aff9775e44d043b75d11bc8c
+ 7d7ba9c4934548446156bf927e8e070a
+ f4085fe8a832e6bdb8c1a0361ecd792d
+ 8059b4f2fd3eb9c9c1342b444f219f44
+ 068e3d2649536efdd72eab8b2ba7a3ee
+ 20d0e95167dd263f2e4d3134a0a9d7ed
+ 987dcf6aa3c3ae8f295acc75c2f3200f
+ 5ed5ecb87e34d3be0a052bed44089128
+ ad60d4f00b637d5c1ca9db2367067f3f
+ fe616ce6e9209bdaaeb3eb8f57c63efc
+ 63186be7e4e097c4354e3c8e94b91b61
+ 166b3bc3d3978e720818be12b4944b00
+ f4a3798673e644953256dc41fa44bc08
+ 24859493d54b3df7dd9218bf5a0d5be9
+ 50093ed39f63832a82484b4eccb02e1b
+ eadff1390a8d78037b565cb75f1373c9
+ b03aad7805a9e3d79cf2877127ba9e1f
+ f84d66f76d4926cffb1791910f52393d
+ d1ca3b2de172014c08dbaf02f16bfee6
+ f2a1f67cd69bfe6ef9aec8df4d725efb
+ 693caa2a7b744d749f545f8bfbcf3757
+ bc39047499829b319748d2949a72938f
+ f0071ae3336334a981be8dacacedf5b3
+ c4ac2563cc8991f7e5db47e433646369
+ f9d6e7318226e2eef40c0d392f202ac5
+ 2ee1b23c058206ff826cdd85bff1d8ca
+ 6320512147c3e41bde7ab06d38a55648
+ 590f5ae5389ecc643172130e458826be
+ d9e11fcf376c019b7b9b662dd7a84f2c
+ c8b06ad6aac5353eba572c4f53d29381
+ cfe8b8815d8889d9da82118feb52dd4a
+ 369848396418f955c71ed2f568cb98d2
+ 4c4c2eed1c47993ce6e03d2ddc4f6ab0
+ 7f05e37a01014cad1ab3e225eae6da4a
+ 8cf665e60b0d45872daf193a5ff85177
+ 7426541ae4e0a6756df40e89a34977dd
+ b976c577366e38b922308e926da7eff9
+ 3fb32cb6483f347f2cf97da028a7973e
+ 29a324be87a2d0a87f2133c9e49a7fa9
+ 543b2a8d0b1214e0560cc5d25da0b843
+ 172d31d08d21d17af073008b555e3db7
+ 753b9ed413446733756ce47548109b5f
+ 5ab39a586a9ddd008084ccecee5e7a34
+ 7489336ab3b5816e8993e2288f8c2567
+ f7d4288d7228cce48c091965b45fee76
+ 6217cc45b7d61beff7941098196507f1
+ ee8aa526a42873070111de21053a2266
+ 4b79066e6318a8ad2b28a5790641130c
+ f641bac1e25496e33f3665cd317bdbfa
+ 06794e97bcfa6c7f802dfe399a2c442d
+ 58edcd7f9db7e51e68e742910a0039b3
+ 08b1daa24b0091920c2f96af5f1b893b
+ 145e833d05e5138756d2b00262cb7da3
+ f29a345cc11adb647d3a5bf300a14139
+ d8d736eeda87e390fb6107275f4f759d
+ b864b61f2690a7c4ce05f8ccac507f64
+ a494f1c2d13f5d22af2a93b1ece5bca3
+ de764919f6d3d6dfcefda9f4ab99821b
+ 5d1f2aa26efe5f4ebd1e6448fd1e1809
+ f68e48a44b12c5a91718a297da0745a3
+ 9f4c4b188c81a1112217c8f401d2c1a7
+ 91942ff2170b658a762a3e6ae768a209
+ e38d2e150968460789ce3998708884e0
+ 15a09d95b9cea3d02e2d79d79af00b90
+ d5c261e4f558246f68cff10a8d844950
+ 40ff507cb9e5b9fa3e2e730371b667de
+ 3311f441ab53a6ae38a7fdc6d123f236
+ 320eadf7d9855204098a26602163a374
+ 7e8f23cdd3c140f4ae01deb412e59f7f
+ 60157f5ab58bbd3147206b96d449f0dd
+ d14c0d5f135e8da55b451fb330b42b5c
+ b2b4259e0ec123c3111843f5ade3873a
+ 89a2286d5b59b3897b49595962869f5d
+ e3a5057cf15775f0558de9c1e0398102
+ 39b9e2ca65fa6b435c1c6a972c12c74c
+ 5e467b2e1fa78c5a7a45ea1687e7f4c5
+ b8b6b2337b11e1b7da0e3b03de83fa0c
+ 110f25624d75fb6154a1325228c82d54
+ f001792b0eff004d698f37fb14b82406
+ 3df051969e409447d4990afec6de3ad7
+ 7e582c84ddd8f44f6dba17c79b4ceab1
+ 1b7189db90b2dd571be84557e52053bb
+ 7bf5482fe3dc1348d7f9581687195d8d
+ 0f9c834db3c1f9bbbd53132e7bb48acc
+ 27b2982e1dde1c5b82d5705d0cccd02f
+ 8e17c2cb0b27fdd6346fbe90b3d1db5d
+ 8dbfc48cc3bd59cc8593b30a1fd2a23e
+ 0d27ab3f654471fa980d2e923749ea3a
+ 10447d920b8a9ca77c4376dd00ce035e
+ 486590fff276e3073ccfd0d45c548c74
+ 6bb986cd091e82f4e649ac614c52e87f
+ d8a8b8f86948e5daa2dd56e3e45c7abf
+ c4b69a38ecd60596c21e8ea1861faf0d
+ a12e7d99da1f84f379cc686f0e3b32b9
+ 801f4562cfb0cbcca656fcd6954aa720
+ cf1995b58314f974ba9984ca98266662
+ 9431028ce709edcda13de3e7929e4587
+ d0acb7a4b55d99dee00cb98decf73f6a
+ 1f1fc1992bbb0c3115b02b0033926b89
+ a83fe3189f51390d0d5434efe43096f6
+ c287a0a06051f918bb48b5161f8c7628
+ 6896f4577d76b38561fc750972978cf1
+ d5ee1d6433a97d9e709be8fa658df0e5
+ 8e7baec34fbfcbf93dc6b7a1d1cba86f
+ 77f169f9a9b60eceb2ee503694b57d8a
+ 35d491424190a6cf7660f6a4d9607ea7
+ 0b4f0ee1583b5ef898dcdc826f0e9baf
+ b5ba8f5968de14d0c961fe4a47c327bb
+ 14c573dd9051cc01688d541ee78cae8c
+ 3396cf35d8e7536a3027f4dbff12e078
+ b98fa11fd2545005d0288b5c57a854a3
+ f8fe4d08dfac51ef84d165b9eecf7108
+ c69da8b9b0ddc294f651bcc08f28fce6
+ 8982394e92fd6e3ecfd242e8d26cd69f
+ 898a21a6f476eec6196074a4a401e57c
+ 1e123373d2c6038778101fcbf6dd6024
+ 314eac1a3ac562f5b756bb124925426e
+ 1152bfdc6bdb18359fe3620ba2438034
+ e4246572127b287f16059fa0c0f7d378
+ bf07ac9956138bedb33d261f39336823
+ 2ea60caf6261fd3b4f4bf8b642540320
+ ac98d3114aa11d1094b70778f0f889e0
+ 9421009b0eea4d36b7fe90a23cf6c5ab
+ c4078311f3c9bf3a3a38bf093a4b5e91
+ 3b96922b54ab0cb8658f73afbcd2cd43
+ 68ce25742460e70f59d1ad49100561f5
+ 32dd0b2dd8f88b4fbbae7f3af495a0af
+ c0b1ff9119f8ba3f982756c2b13e970b
+ a7a22da1a80e05b5d5f836de4319d554
+ 1c9dd84a50fc0049207f35d3d470dc0d
+ 5fd84f2fe286de12839399ceef4fd992
+ 2734d5cac4a5464a61fc21e9b1c5d48f
+ 7247e209dbefa6ef4ed9743cfc8fe4d0
+ 46f949b82b2ae4cda5640d8d7c4d1073
+ 5ca83af3b6e592e4189ca6a139cf59d8
+ 4e29044993d030824d59396514fcce07
+ 1980086fdd311a070154c042d55f63aa
+ 2b53b045458e619fdc692ff7df5b1502
+ 40beb5d9a94859d0429ddc7e63e7e773
+ 34783de6f7cd2ae69dffef85ab5ff5c5
+ debd0073734a6045bc13a339596c19fa
+ eefe2f2df20a44a7aeaa7e995a2e5666
+ d23d06d06dc7c4d2315c889f6e5b0a3b
+ 8f9edd732063fa685fba9566bd7893bc
+ 75ff75db360da205aa1a474a5419f63e
+ 2983ae201affa9362910ba1792b57388
+ 7a83497bb06c166d6a70775e07b21494
+ 9003f9a017414bb67119294b3960ae2e
+ 1b8218112669f43907fcb364a0ff799b
+ c6c3f51431cc52bd96ebbd2e2762617a
+ ec18a39cb47cdd492625ed46ce56f7ee
+ a2238afe29c27b269c77975733c1d037
+ ba89b601c02c6f47a62921f0921fb98c
+ 0b0d785297e67431132c3da0b6dff585
+ 2f00e7e5563b90cf7f1ec86e193ce64f
+ 1634e9dcff5da7e677d9f5183554b210
+ ba9ffe473ae1157f05f0d830695ff56d
+ 646eeeebcec0a946488797e934dda791
+ d6eca75770633cd6f70cfde8a65dcc06
+ 7812447794e2f641989edebada881158
+ 2e935c61b7c1f2c6e6d37ca561d64423
+ f6582b0dc20cd0a77401566afac743b6
+ ac237da980ed723b96ecd77857523a5f
+ ab5b078e9b9c5ab801e924f2a7f55e3a
+ 0eb3fcf54348e33ebfdc9d1b5ab96630
+ c5f64aec15a0f8033cd87e398a5b4088
+ e10bd024ea739495330980853245cf5f
+ 6ccdfc90f154972857b03a7baa03eb4c
+ 513f267a00565e3a7e61734511b3f38c
+ d4858349b61c6f24b34f73323f02c57a
+ b456df142728d6a0fb7378e6b1bee9e0
+ f79e9ae3a4b9baebc7ff3bcc5bdd6c0b
+ 59a6971a3eebb3271dd2053b2ceed6a4
+ c6ac3ffbd20390064d48126bd7459aa3
+ 1f5c576b82b93ef6c7a7484f556d2415
+ 8b6f061ee683c71ce1f7f0d39f3ead7b
+ d230be59a8f5aa38c1b6bdb2a6341d02
+ 444da8e010b2cd52f857fc7f1824f70a
+ 10ce6687410f6b33e5a30bb2344d32a5
+ 644b694054e27acf2fa6416e80694e35
+ 5b829b0c2ee2b2ca9ec24908d2d3f1c1
+ c199844178767de8cef61482ff6d6077
+ 5d9df3648d3bd784d4378af83e0d1074
+ 6b64d2b5445eb38f80fa2103a246f5f9
+ 53a90c9779eedc77e036420daa0bc94a
+ 8542ead9b39969450299c95a873732aa
+ 0a52ffaa8e726e11e7120e2805b40698
+ a6b06a0a05312fccca61ca85dd506c10
+ 9e19be7b57ae8cb67033fe2c2d13afa1
+ 1759c8baf5fff5f8fba7d58089e9bc5c
+ 3c2bc37e4d9c4a47d41cc11fdf2ecb99
+ 652c81dcc099a1e977e7c71f3b0099a4
+ 4d4bd5e6a479c3f7d7db6dabcab08869
+ 80a74675592a1eb8bfb6dbc33ce0b7ec
+ 358cfdc77c00dfc14744e069b29ac7b9
+ 1eab4b1a07a281a9cb1ab90d98322797
+ fb64b1516a257627ab1c87d09e7f56ed
+ 5e216a879999ef857aa1c1b4577d9811
+ 47832186a7ccecc9e0c1686741304b78
+ 64f6f69135b0212cc44cf061ea743ad7
+ f1ddb6124c095a7984d0ce10f6436600
+ 8d27a2eb9a480df823094be00d83f2e3
+ 8b043d003b79f576fe8b84a0ea144bae
+ 9bacf73a9cf5e591b53517cf9afffdb1
+ 00ccdeb7a0823fbab165fbebd986a960
+ 5bd82699e2e7022f96980944ccfc4af8
+ 8d55d75794f96b2b8d6d036cc0690bf5
+ 1d8d8d78f6c1bc2a520515a6f4bafbfd
+ 9acd3cba166804a7b80253f24503d9ba
+ e6a774c5be16e7db0f84ded4a2347fd4
+ 3a94f747a85c1fc487b9c8fea43c39b5
+ 8049fd2e54f1e046321e694755cbec4b
+ 1f987c5470e47068c8ec5a81e08d495f
+ 8ffc8a8954cc1f236bffc730e92d359e
+ 987b68fbdff3eecb88473befa193f8fa
+ 3f975ed623be3600c39713f6cf3cc7d5
+ 5cf38a6dd333ce76d15e4898a874fbb0
+ 50dd0358fcc315d3847bc136280a9172
+ 0c259deaf74293ba8269011133302ef6
+ a5ae3d640b00cead988e71805d5714e6
+ 903681afe422572a93490b20b9abbf2a
+ 581f82a9e8f13d5d89bf2b3a4eb4e05f
+ 72a66ad879b590a38c2121602270555e
+ e32e0845f1dd6db4af24de314971a6bb
+ 12b50f371d833dff51193f5536206903
+ f77cd091a76b551a2f0cfa8adb9922fd
+ 782fdafa235da37df81eee601cf96a98
+ fd60aed68f57421cb5b4c5ac0e628d00
+ ab047874ab021e8b3577dc05d5f10f00
+ 0019018f3d1673751a1aa220756e5ff5
+ 202e192eb560e331e41471a47a42c5b7
+ 4be579b849c59ca91bf3e0a2f1efa936
+ 2aa08e8d3008895892896643434329df
+ cfde3ec2d1430efdba50316b59e38779
+ c7bbfbbe07cb5a04a540c646f5101cec
+ 51219b1e07a09872b2463a29f5240722
+ 07cacd407e14901beb9fbaecddea72cf
+ 683d04ca4e7eee27f1f3258c108e6270
+ d3df012065259540bcb9b4a030a0bc58
+ 74037afef6ca161eb235749d7759521b
+ 4ce2e8b1f154bdfd74688b61762ee06c
+ 7456d132af20b3f3cec654d43fa9e953
+ 46d977c733fae94edbc22c9b62d64272
+ 3dcddf022ad58a8beb77126c1af8df6c
+ 7dead320a8ebe2ffd3ae76f6ad07b046
+ 44447855e301a094750dc73788b6c51e
+ 2d46801ed40558e66aed0bfa732a381b
+ f019f1255ef7c5e2c247c68596d06e76
+ 0145433a64d9a3eee2f541cdcb064706
+ 1b17f061401d49d54438d6c53381a504
+ 35dd00385deae225e6d2365efee8164b
+ 729bd567b3435605c2752469c1824b2c
+ 4995c7078086746a1b5ccad4cf9862ea
+ 315049fb561c236f360070c6c89fb15d
+ e38bc5b012c8ccb250bc28f28ff9e2b7
+ e2bb02761f8c8fb7f3e170ae06593493
+ aabd931e6e673128685ec38ace2c7a61
+ 968581f6b09eef0ab22f054cbc41186b
+ 8ee853465ee31eb7baf8d725ce1ad62e
+ bf64c3fb4fa361dd4dd0a1db75de295c
+ 195968b1d4dd700be5724721b60013b5
+ cb4664094c6137d7dead7aed2f6b3949
+ 864a80f4e443f8e8f6df2dd3dcd98d87
+ 474efc2aec2e9adeb2d7e1cee0870a04
+ d4494f084b844432533475b3522b3709
+ b51a9494be94285c2a60a7afbd570fad
+ 313beb1971fb009c2e32f5d89ad2019f
+ 369aee7c63cc50ddf1604c3f604490d7
+ 92ab81776570d1915801a1c4557b3d56
+ 04fe60fec7b2d74b907fc55385b0d92f
+ 736f02857f0cd36262b4cfc1ec3cf1cc
+ 696c3bd18d7d6fb54ec07f9ad64ef8f4
+ 205ee64633764c86200c97dd48ad5f8c
+ 4346a9d434b5dc494362a16a034e4f44
+ 00f20e6ad6d3f79b532a8c2b69685210
+ 5c30feb90bb018170f2f778b0610eb5b
+ 0d59e6e6c4f2b50fd96587e9f73b46a4
+ ecf57607bf52cd7c05f790a76fe57137
+ 34bdb54a37645fd5a22114010fdaadc9
+ 013932e4aadf0bdadd09193d2014e96e
+ 1bc0137b382819d2941a8fcd34ea252c
+ f4d863b33a8ee186f43a22595fd84e47
+ e8f3d23ba60b719f92a4d122c445673a
+ e08703a968f0145de30f626f6ccbc81a
+ 361178e464ed170654a179a2ff84560d
+ 97ffd3730e49837ea71c0290dfbd2d3b
+ b959dfc0a8b2ba1ac7a9404e3d25bcf4
+ ede38919323561122c295754666471b3
+ 2f0a110c01802776c354dcf3ce8d25a5
+ 20375a58de14a8b119b1dfc3e5ad19b3
+ 3997fcfab2c8d12d64cbf62337b37c8c
+ ccfcf529adf7935977de3aef6f2341cc
+ c5f95545630ffa14603d16f9782aceab
+ 73e582d85f9ed590cf7da278857bc1c0
+ f90bcf5a9d136e2363da9c6de091ea25
+ ea4759a80c9d704af410896c909fc262
+ 5ab5ec578527320fc5ac3408d2881000
+ b84a9f15c3166b34c0c5193962f70c26
+ 0b4b90b71860057b2be4b00c26c21442
+ dd155f6a1b74f6bbc123fed8d806e0d3
+ 488844f1e3f937296c4d110f75c653b2
+ db2978dd56c6a849443d623454465bf1
+ cd37b7abc683ab97689eef35b147c1c5
+ bf01714579f1374646455c90cd04ccb4
+ 0fb6eea80586b58f49d5a8a072d9f803
+ aec8a744ec570d64eb3a8f65d7a9484a
+ be50a2406e0a87345fb415ca1c63fe08
+ 2b3412ef0345ba0b1db9230fa701aaf4
+ 5c9b2b05933acd316084bdd3f59befda
+ 9b7a3e8b8c40ed537a041e78c31de1b1
+ 04b3fee5800bc8e8c5efa07813dcb06e
+ 920ed7fd99008337e1b8e3c9f789f81a
+ 430bcbc1aaf6c341ff56bf5889928730
+ 68441be9662c5cf0b3bbaaa0f391921e
+ 792d44d0092d6217cf5141eba59aa0bb
+ e42a15a84d73465c0aa2b4b22a4abec7
+ c8c4eeb4176bfb7a2e240dcba57c2f8d
+ 4416fccc11363767eeb8333340126ed9
+ 4a3367e0d9926cdf95340a7bab9eb145
+ 920656fe1c89d70fbf3b918a8905c8aa
+ c45141fbcb88296a286df74f9c616361
+ 6fa2c502222f0f6b46faafa66366bf35
+ 27451270fb0f93e70218844644fe8703
+ cf367fd492b5b9470d4a3b5297538f4e
+ 6928513656f960d41b59578e5b507110
+ 9d7c7ce6d9fad1f2f83b4e6dd187f362
+ cb66212a0c4eee8c4ac72bc9c65e4c5d
+ 812d320bfb6f717c791fe71b0c79bf38
+ 01ea097aac1f4ff7cf8a2b30a7662c7d
+ 65934201c6b103304795e918618ecc2d
+ 22c3f53dc1ee88738b17561538b0b1bd
+ 3d0a3f7cd8cb7a0ae79e25e225ee38f0
+ 0ac7a058653c2099574b1724c6a3270b
+ e506ed154afb4f6f040faa3c48701cd4
+ e12fa1eefaacbca94ab0626c210d5d7e
+ dd088fc4d4fda8f655f9c1b8363e437c
+ a688953af2926644f1e8cdb71f7d69d3
+ 4598b6beea3f671a1c970d5f85f56c06
+ cc72c9cd218d6ebfe5478f2f45a18735
+ 3404c8484bc6a8a2fc5476272657369a
+ b0361000bb1a92da51edec7665300439
+ 3c2a277573f05ed450e6708e3a575820
+ 2d6dc8eb004d733bb1b4353c7b179fbd
+ 3098fe467539c7414d6a7ed11ec35fb4
+ 6b57a73f45b90a5042b44a5183acf28f
+ aa4dac84611eb07fb59700b14ce74205
+ c63edf329deac51a22348aff3fb75096
+ 19e87828b3cb4f036a6bd2213e32c0c9
+ de4725932763b76f8cd20884e28b0c63
+ 446625c29f0ada0821ebb988b45e6be8
+ 92228a97a5725d1df726442fbae48ea9
+ 49fffef89b71279d1eab17d60afcc221
+ d4e1f576adeb025d0a41033cc97ecf71
+ 1ac17ff3057d88382420ec045f81013a
+ b9bd441606b282c6f3b94fc1427c18d9
+ 47dcd875364193c551e667cdc9e17f84
+ 87ded8a99a419dbd1798c5de16035835
+ a78ba5a03810686a9d3197205ae34e1a
+ 01a6038e0c834d1104a151d49fb25851
+ b74750785862a17188631e1f3d26eaf3
+ b596414299a0b2b15e313d2f10968455
+ 4a07406601bf3e578dfc26f10551aa6f
+ 6be4409cc137640a37f5c5d664fa54c4
+ 3ce9a2d89e00500a8cac417f0df0ae17
+ 6e602ecb3033774f73a12ff5cd6ddf27
+ 2c121c4d5db01e14aaf14c5360f6a966
+ 0189b7c3371a59b9f4ce1aab0e926a05
+ c60fad09755de43b56ff268b93c030d4
+ 904b2f0f5351b9db07a72511d0046234
+ 88ba7a9dd9af3be9f1718f473e6bda56
+ 2f5a593cca040d61b05d23ec05593ae8
+ f97a285766f99a6fb7636c8db9c6bdfa
+ eaee5305e1541f4733ca6b585031af83
+ e139c38f0289a03ad13b15db21ea0eb9
+ 4a89c0684aa656ebc9c8df0fcce8e2b6
+ 0f7a7cdb6d03bb0525ffd979deac326f
+ 26a22ad34fd324155e57920a6f8eff15
+ c4c9e88022e0c00f0919a10827e52ab8
+ fe8791793bc010b6c97a2083e59ad33a
+ e602acaddc49ce67fae1e96fb5d472d8
+ 7cea78857c185ff052dbd4d6edec0af6
+ ce8ae267e99002af16e8af1f85a7d9a0
+ 40a0112eef52d76a1620b44873497866
+ 76f944397020c071edd06b1be2b149c1
+ d600dc4ec2491988f2961b5b3c54d29f
+ 534f31b227bdbd4622c2ade53f75d03a
+ e038b39eaba343d169ce8cd047302305
+ 198c288a1a70317d107d10226b0eaad2
+ 732e109bcf9347a7b3b7c26b3e0a00d8
+ 72745db72f48a708b4d7350f8244ab91
+ d5d68e3096c629278f1b70b6cb09b551
+ 44039bb90f099c32924e19a062d66bc7
+ ddd1f1411274e59e7c0a965bcc87cd10
+ 7a96525fe31a1f4d2ffe636ce5621a55
+ e3496411a08dc86d9e05d197733b463a
+ e2e0f096cbd0a26ec13ae6efb5ba6938
+ 48cbf327e40c3ee9658a79e46035397f
+ b34ac4c21209ebaac96ea35edb264173
+ ae3a99a9f1f6fa1a4395bd181f8186b4
+ 70a1115cb3ef224d6c31653247b49ebb
+ d009b596b92c09cb6ea002d25c9aed4f
+ ee593bbb0f16c04e80a5816edee19498
+ 5b3e92d9a0ca307e86413501278dbe46
+ b959317b27fb041ccd960138333181f4
+ 04c346bf706c4c6bbffd712e62e60fcb
+ 5aa4671632909aa91ba4cf34cf335d01
+ 311b050fe6f1a97d986fdd787591d979
+ 44e33a7ed5c70e0c224621de30de8afd
+ fdd4ab2d715931bee9a14affe00911d7
+ c2a18c8a7c1441094c316cc43cc3e46d
+ cfd2d9a75760a347cb4baede5e5fad6b
+ 86a5b48453eca73f5ab138cb16925fc3
+ e5f4a9d641e7b15d0040b68d5558969a
+ 441cd7ad54586d42d5e083b3457c96b7
+ 8f75276619876d45e9505274f6c0014f
+ a872db6dd7cdb2d3a4f3fa2cc9f0af9a
+ d9059019cff3abe2fd87e003861c53be
+ 5f2c60f4a2b070f77c2e577995a52144
+ 7f326fc52d80137bd1c37e9c8ebebc5c
+ 535d313f8ad4e15346d858629b759bb0
+ e3d32e6eb0830971324b66767c3d0a53
+ 6813f6899b0c4ac4cb05b17a93c239d4
+ 6379e3ae660bd771543cbe9ce43096b3
+ e46d30816e620a5429da6b0c3f07a6db
+ c409b32c976aec55199c856f2df6b076
+ 457f10e7cc358d07241aee41dbd5ea49
+ 6fdbe74478fd85ff4648631bbddebeee
+ 5b5a5bfa7fc67f7cc60ea08424c43f6b
+ ebd8d3a9f84cd654f71b159f0029367f
+ 4f13dfee75a0de78dc9c09a81cd5f154
+ 5c526d99d245ab00380c961deb2a31ea
+ d63333fcd5799fc409ef7f879f361036
+ abd2f90505aa485d39afda3d70850ca0
+ 5b829080b9f509bbe4c9db2f1648d0ab
+ 7d313ca424248e869c22b43735642616
+ b45292a01ce7db1f9e9604f71a627559
+ de4e91600b3772e83ec4783dcf5efaff
+ 69754f0b8c048729e63cb5723fbfd75c
+ e026f2308c71f813cdb1a846aca4e2e4
+ 12b00366049351512d6c4d69e266f204
+ 4e1638c8c2287b46a1f02a82fc6821d5
+ 8031d8d93fa1e879787428b8655446f5
+ 4e42f8438d3163e7784e5ab7356eee6e
+ 330b43cbe86892c5683b6383bc5f316d
+ bcc1ba062a3e805b2da091aaa4b75a59
+ 116151038e46df5467ef80b7c047f9c8
+ a565da2e831279136a5b86b71aea6db1
+ 9437d4b3d366653671605d6244b2be7d
+ 0cabb0d2b7516fcbed8e11d50e5bf022
+ 7bd5c90f53d4e6b154460323a1ca5739
+ d18dd50eed67fce861399586fe0ec142
+ e6bb5d426517a869740ae6208a75b196
+ eb61c75efeb2bed0736be74a4bef3e9d
+ f6c6ad97904c42ae1a2a344b3c6d9301
+ 620dd86d00552fd2026d70afe443c43c
+ 7ab5ac247972aeecca551186cf11d7aa
+ cedaab0809d5c7a3fc90cd6fefca458f
+ debf338f239b2df628fbaf0c39c742e7
+ 941e960faaaad85750955f0e3d5a29d9
+ 415cb1d5f018a665b691ae95e9cf90a6
+ beb6000b88cc5ff886d56f81f0f38535
+ 502e5d7af269fb988d05ae1cc92ba397
+ d485404de4bfee81361a1355eb539358
+ 0ca7bb5e7d8b7fc97b93daafd65b6ac6
+ 99fd61b071c0152777b89b8ffe8b0413
+ d2846004794ba8226673f67af131708f
+ 6d3818c32d2410e2c7c5a2e53c3fbdea
+ 32d5acb55ba78c464147120e3b4bd25a
+ ec1ac207d1d50bc18251db79c44492c0
+ 022e6a709b6a1e500f3cf207b1bb185a
+ 17fe29e49457467f9966b9590c9d8f06
+ d1a91489000887ce35efece384f60d42
+ e5df79ba4bcb3c526c9d9f00d18ef37a
+ 3c86377f3dc23f8e4183023e1f3a4995
+ 08faa998b316dfdf25052c434096db41
+ 9da17e1c9aafb767a25f4c4098d369fa
+ 1205b459c63d568985c959e2774c413e
+ 3f07a0dd295674c3561b7d636ab8c525
+ 2d57813fa17475ffa44c29799c146e6d
+ d7472278728a7108c6949a583412b6ab
+ 04c61a71c4d20d549312d280c90015cc
+ 4f0da2a81ccffb2c996eb3b2d3e61ba3
+ fb2543a7d290f637f8714149c2c2bef2
+ 473b00ae18b2105937112b35df78372d
+ fd81555034c642db14ebd87fc191e5c4
+ ce134c94be62bcefc2e7f489525fe2ed
+ 229a1d67fd4a97eedcafd219dac1266f
+ d546daae56e0d46fc0712e48c1000423
+ fa65d835a95bfeb5963c6f9d4ff32452
+ 71c08443a1796767746b31cccd75ff27
+ ff99b440f7d995ca43dfc9397e889a02
+ 5a1da79040903fb840c08a4270eac3aa
+ 3800b4a76c2f5dacb46a723667c28947
+ 8a14bf83b9922691fd34463dcbcb3d18
+ 1609927bf831b415a9c7dac9d9fddd30
+ 29d51b4681f1933138ed10ace174ab3a
+ e848bcfb545db6eb201543c8e02e39c6
+ 250e2088df30e1f1ce534a43b71f8886
+ 9cd657a2ad469d501e2aab3235509e2b
+ 14dac47a34a518a7464e8f3c48362a17
+ cd29c84638b6699ce87fd070d6dd5871
+ 654834f1d3c5f3faa6adf480858816ad
+ 5e076109c5a38c78762e9043d981e794
+ f429ef4f1a1fd9de0ee383ac0bce9f1d
+ e7a2526bb140de68643fc2a167fe19d6
+ 37c5c5133c08141691ab24a2d62324ef
+ a1901f933dae04bc0cd9fd35ed515c20
+ 6d84d465fd6f8eeed765e5df1b1ab951
+ b079e470f06ad449996bf3a2e1db3710
+ c852588b8517717c7c1b471a7246e259
+ 7a3b9ae45b0d91140429c0cd3be63e3a
+ 02846c57443d64cd97ef7bac41debc1f
+ 01d20529e50bbaed79d03ecfe2abc348
+ 20dca71c0318952b02dafd08cfcf9895
+ e3b0d27be12f7c58bbf4744808df115d
+ 182592a855ea10e2ee226bd16896cd06
+ e3b8dd5f8225ccb90796bfa15e1efa92
+ 697e19a8a887d208c725086c2c99f576
+ e60cc9dc9627736894c24d61de8ffe75
+ 59801cfe1fa0a9333c796ed251b323be
+ 792348dbf7b76af08dd1b9efd65bce33
+ dc030034493901583b0c03f2345e089f
+ 413c9af5b7f6177d7816451d67ab7c06
+ e97eddfa1bdc8498cac4c914d56949ed
+ dbc80fedd3ca6a0e040cb0028fb98d8d
+ ee20d6de9574d28c60f262c920c07351
+ c7ca300492b198fa880af738f5709c02
+ c28694d97dd36aec78eaa0008118c333
+ bd2d87bf5c2e990a37e74a18fbc9854a
+ 4e84f7e7ea11d724f44b67ccc618fb8e
+ b65ddf3b6464c38536a181d502ef617a
+ e7cd74286848353031aec28487fe8868
+ 74a952623e8828fd6e457f54d82d6e42
+ b8185b9bf0b194080ae5aeb7e5cb4528
+ 818d6e7e8120f6192124cd3eb37f16d5
+ c703f4404f23e47517aa63be0f3f690e
+ f9cf742030c78c49574d749bce2a11b6
+ 83c70fe2303b1de06187b68aa5051b05
+ 94a35fbfa937532830755326f66af7a0
+ a85da7a6ed52da2d9dfe3bdaa640f9cc
+ dad017a692c54c94b36354ccd3b982d3
+ 172e0049d2a08eaed97b665da9ab2b1c
+ 7ac4f35d56842c2382dd8e7fa6034528
+ d22dc6cb353163c4acfe65fb9d6d1ae9
+ ec0d195cb3dc6e69541eb2a2fd2aaff2
+ c898480f56f3fdb6da1536316e3558be
+ 99dabbdff3ac094851b231ac5c38da0b
+ e56759445c9457def0919162358d40d2
+ 459a1c171c97ca15ea33995ea13d59ac
+ a27ce038596a7cf8b6894b68d41741a1
+ 6a6283caa365383d005829d4c7eeb999
+ 3c45ad4239a47c77d2d13a6968b0e7d7
+ a98050703dee5ca2130caa5657945504
+ 7faa2b40ca0bd6f3a52bc609192e4718
+ de98aac908ead2186923a4a00a30430c
+ 811cda380612ae0f7bffc188eec94b0d
+ 8042c5b404c636f365cb67927aa3e34a
+ 88731abccb5cbdab1f0ed06a58ae06b6
+ 96471b4973a69f7d617325d2af132c53
+ 1d09f391047fe45a847165755d777ad4
+ c52659bebeba01c68b18246bebbfed5f
+ 2ab0a9f6aac6eae83a6fb3efe20fa2c5
+ 372932ae7986205ece9cc68187adabae
+ 272c5435ebb0c9383da2c42128d5440d
+ de2ee847dddd247fb2eeba35479d96fe
+ 24d9ac3b8d761b76dd77fe7f7a6a5717
+ 0b17f79d6eb338cb45c3959dd1f98cb3
+ 511e22cf57f13a3a08eaf7c5a08bc4ce
+ 364cb9bf9cdbf10c43bbd00a8c992dec
+ 55813d23b43937ce195cd48d33490a9c
+ 513263c3273d0f343bae0494e23fa0d1
+ 64d17e8fb65fe37423d5d5a63f794616
+ 9b7bcda55d8cd4e25bcb09ec34a23d67
+ 419fe5d36e27992887a9b53cc0bf8439
+ 6122934fe1597e0ef2cea9ce8538d8fb
+ 0d7c47aab6299222778c971a6c9de945
+ f0f9eaeb3de40fcfa5578d0ea917f5d3
+ 8da1ac99d411323fef23d9088126dd6e
+ 9de32aeaebee1d24581ec433c3e22ee1
+ 202a789bc0a447b71a92442fdf8fe581
+ 952fea7383046526719a0b52f2210b37
+ 20ae25c08aa8cdadf1a8caf9d480851d
+ 615310e4aff0ccf25d2f4400bc0b32e9
+ df26b0528f995f44ef7959b61eeafe90
+ 271f7badc53c8b0acf7484336f88fdd7
+ 08f5d51febb18ee1ec608cee42f556b7
+ eeade7b4c3519f2b2c74259e41a9d272
+ 5e9528890ac11acb73925180b5b72921
+ 4bfebbb73ba3e4b6ceb1e9f9bf092d20
+ bc4642dca9876400f433cf48b0a22ce4
+ 13f773791abfe6dd3563f4fa2c90bc20
+ 275f1b3c6e460f203cfb17ff6c729036
+ a96ee4037afa701dc0ccdc05120167fb
+ 3926ee618d13f07bddfc44d0e1ed392d
+ 082cee181683c66ae1838339722b9c2f
+ 6b3a8c4b66e49c27133b3c1a24b26064
+ 974ed97513281adb98de209158f9ecfa
+ ef6bee9bc2fa310a8c4fe947e4d3e5a1
+ e69fb3117fc7cea9b34ef02d337dd723
+ 37d6831bc73db7e97e0eec37c2de6de4
+ 1e9cb8c1b470cf38d074db911dfdd598
+ 8f9816266526b9c0c857b0c70bdd2feb
+ fa46c3740696976bb93e3323bb288334
+ 988777bf1472667aeb25951d4baee405
+ 5c996ea9bb50b1987e52ee4a8fab2280
+ dd1679e037d77cb3a6c82b0d195f0e9d
+ c13257966d29336e5d11dd9b584be0ae
+ ccc0f9e01c680126d630618dcc4fc42b
+ e574470ecfc9a68e9d18a2b0148c40fd
+ ec0c11d0e4141e1590c23bbf315fb411
+ bb445920ef5db6cb38ed2cc5392f7504
+ 0291a06a1afb131c580e481abd844482
+ e3a53eb416215e54548635766723a1ba
+ c7246c02c342fd25cf680d5cfe247281
+ 6dab546dc9cfa192c3b1c2e602fe87b7
+ e6b64f288e62fbac4a5efb9496300c39
+ 95ed7b80105b76bf7522ce26605b87f0
+ df6b098435a71eaaf1cc52aeafb0b74b
+ f6787500976be3265bf4d44403c55ed2
+ 8979a7a9770aa921451528769e2bb344
+ 698b410a6d66fd9b6932e3e2d74d073d
+ 0d5de7704c38d5480c24fdab10c9388c
+ fd262dfc02d6d945d4c1cb13abe06fc2
+ dd3273910b1adde85c982d0d3ed9e93d
+ 7694479b818591c267b9ccb0cc4f7d97
+ 3476ae8d622faf2a837759d1c0ba9771
+ 707cc22ed5e7a6096eefee61ed7c8545
+ 405da40cacc403983c17ea620c6aa2e7
+ e9e4395c84cbd83a506126be9cce711b
+ 2bd83f806277de4f6ce7c73bb4cf34e2
+ 6abcfe9b07ebd7e0efbebe91365a5c66
+ 446cc4ced906706d43f1556ca9a92804
+ e7ac0c777ac349b0e093778cf278e191
+ cc60475bfeb837819e33644635f5d422
+ d0a6ca871e1c784e1902195ea4c16d21
+ f268186d35cc02b60d8c4fb8bb764b7a
+ 220101401a6fb1c46aeff1c9777a6bef
+ b252a19d41543e4df2f6e5021db40cd6
+ eb98fb2f788061f7cfa33df67f3871d1
+ cd3dea5dfa9998946ec250f89ef09093
+ 2b850450874d8a527e4d7131f4403783
+ a1d814461aab61aec75904793fba241c
+ a0b0472367caf44ff2aae947c33fce5b
+ 9b0ed7d5304ffa5b35ce371fa5cd4847
+ b03629f31014bd48cbc32fa8847ec326
+ 90b5123f5c94ec0aa601e63b4981bc4d
+ 2c6c0baccf670c10b420a61df84a8307
+ dded712d1d58e3a7201e849a1efde6d9
+ e0608a0d545f0ad897b5ddf1d6051e45
+ 52116604602c51d7f3109a0128c3a643
+ 9a8365cc44bd1ee3ad461b36b2fc6392
+ 2cc623d13d4f9397906e3d63d467faa5
+ 93765cdb77190abc1a10c393f9dcdf28
+ e930538b7758ad608305c12159801431
+ 28138857db62ccc0bcb132df5e1cd9df
+ 969704ab715f23407e3fc13698a3ce52
+ 0d3e861b37b4e5b75657e49ae98e1156
+ 1d94a5841d91ab0589063a09f7e5667c
+ fde1b7102592722cbd48b7053c6f3793
+ 00d166fc2c415fd87bb0bf000b382e0d
+ aeea49e208caa99bbfe93413113103f2
+ d699389df89ac43ae184de78fc873bf7
+ 8e8b5d7784304860e3d4bbb34af21a5c
+ 075963ed405e1b3c641a908a65394a11
+ 741b35dbc419c1a74e95662e769d8967
+ 896a88f8637b15a946db082543f06458
+ d56f69361e913c907b9fcf4ce8b71a82
+ 5af82a05d654a642efa96264c7cdd311
+ 6271d4eff4771104fb52d28e0a189b12
+ 9c8112e2ddaec629d46c392be3934540
+ 8163fc98ea57539bfe5f634c06cb123f
+ 60f59216e0fc9884bae5b81c2bca5809
+ 65571374417de68d49774cbd0eb24aa7
+ ec136b4e638bfd2f4b3830830be61827
+ 32b98c345fd7fce1c023cdf804456e6f
+ 833ddcaac126dfb8e1f3a3bf294ddfbf
+ 9119af1f9faa2fbdd3751a17f1f6d5fd
+ f003f8f8d9a4edb06adce6ec5c905ea4
+ e0843814b2095e35d8531d33664bc720
+ 0e01c0d193bc46eea908d0be537882bd
+ 1d448b49a04325cccfd49e66ab328313
+ 4861280c0f5affab381b216a3e009caa
+ 1bbed05e8ac7638439fc904c24e1b518
+ d66c1180f428032c65646d94150aaca0
+ 7c3a33e7a5d5201c01aad171bcdce2ca
+ 91c630e4080257ffeba9089a0cc1e43b
+ ef8c479e2b593789a56f5b95df4f9e94
+ 7c31bf01d85fc148a38f469a022c1021
+ 105340199d37de15026b849a263f0d88
+ e895594901a00ae80efc3c421d60b587
+ 2b6a9704d5503bbb8ce868a4381009be
+ 99e6095a13290159e2af932fb4659319
+ 84e3d4e24f210919a5497eefbf5da850
+ 3bb8c4b2a0d99e424fdb4a0c716b6941
+ 71d3c3d91f519f89b0761d42d5f2fec8
+ 84c13350740f35dd8b3ce72bf006bdb1
+ 846753965d479863899381e8ed53a63d
+ f2382503e52be6f676766f610feb8985
+ 74d70196b4c8cdd8bc0e07146da50f8b
+ f3a2526d73dc3a5b21aa6e9f9536b4eb
+ afe0d4576f21b6ebf7ece5e7a4088e5f
+ b1d954c769f2c6109e8026e82161c144
+ f217f028a0ed2678dfeb772fd0a04b00
+ 82fa8deb751981ae7a093988c4249b41
+ 420340375ca7c7c7f6d448f7df237af1
+ 3c201e0cebee4914ec6a70d519bcddde
+ bd35c38e37fbdd2c0e27e188df01c34e
+ ee39ad4e5462b3a99be16037b050b18d
+ a11ddc8b13a1ea1e2dc4cac5139f166c
+ c9834b60bae7c86fdd22c8fe7642c99a
+ 70971ec1d69bdaf231a1298ce119e220
+ 592824e13b798afb582a742d0a7efbde
+ 3c24f93a5182cea371b3c87fafcf6e1b
+ 1afeb8945f4b410cbfdf96596890cfd7
+ 1b1455e99821be651a23e7fd0c20a98e
+ dea39addff2576b01cc0965c5a9ce4e6
+ 9a62bb9baf812b33d0ca0bcafc46d95f
+ 6d8c574f492f7a7a064fb98245d13d87
+ 5f120fd9087623e837434032d086c32f
+ 64db0cff06f50c0ad9c42b5a1125152e
+ 79e349cb69dd3d34359063eddb7836af
+ 513fff225c2153e088215cf07dda9b72
+ dc40d08c46afcf99ee7cf76e2eea6de4
+ 03ff5067a18b49404e2879ae524e9dc5
+ 860524328b3cda5a847181c48c6e9984
+ 9c1c237e53cffc7762cd9c42d56e8f7d
+ 5f6660fd33e3f610e1b06590efd9a704
+ 9a8ed27ee52e5e03baef4ac0433ca441
+ 7ba36deb9eff5f697f7e9123f02139bc
+ 2bba0420162aa91d73c943f5557f8f7f
+ c499fbfb31906a59f147ba8d43c969ce
+ 9aa3733c5fcb3913347292a6960b4852
+ 4445d579b57f428aed99d4a04756ff77
+ 10ee6266975dc4a160aba4d9f1b60563
+ 9415cdb1a877331f58a4093044a32d48
+ 219bbf62f9f0fa1c4d7852c56344898d
+ 62ef07bc23939eea10ba4419b3253003
+ 079acbd1a647276abc929f3655b8b5cc
+ d2824d3f3187c22ee0e052da18bf1255
+ 2ee6e0f2d3bdf834c3961fb679db9eae
+ 21cb2a9a0446543fb2055b455117d692
+ 6948f64318e65406e9f3b641dca9757a
+ 6b1d9264c8b05947786a45fd3071b814
+ 9c984235e32315717997dec5fbd23d96
+ a889035d419e534dd5950ae8d127c3a5
+ edb8aee4f55b4b1993c42bb071b51622
+ f91570cc5e85e21ffb09eedcc141a10c
+ 7d422b1252d0e4d2670435f40bbd6e17
+ 0ded4e9cc9dfa23456303838ae2180e8
+ f77d3c1b0a4c24d30b8bc0f1c325d9c7
+ ad8d422904c2ade453b3857ea1392a48
+ 9ad0ab255259fd102d31aa48379a7f39
+ cbfd3cc9c37f914a998cf99562cf6b33
+ 2c10462bcb36734ffff19bebaf0f3c5b
+ 153ca2cdc9fbb3615d8beb36794f6eb1
+ 7631be53558120c121431d47ccdf594c
+ 40941600200106d02df2eb4962d1e1ef
+ c34040ad301e7942a7ae647574203704
+ 9e63580033fea82a0ac72757542db2b0
+ 57f5358b3562691856369ae66dfb1711
+ ff957342acea44c76ec40ee5f1339bdd
+ 85794d374e7b31489a0338de87ff1e40
+ b2ca5906ea91ef1adb7c1c5ae7b08cf4
+ 1911fa9b70c6321c931484ffa9b50589
+ 05437f4e0234991a404a10d113361e9d
+ cb5367b9b916a034a43df172c8266554
+ 1f04d4c5f00bfda45ac07f39054682e2
+ 95a1d9d3a0d31295cb86eea198f1e41b
+ 4b0314f8b87d2a80450ab5079ad1b05c
+ 35ff1473d5a91ba7293597661fa20aea
+ daffcae57ab2ef23865884adc629918e
+ 070e197efc89ce5e5b7dcce6d49b8ebd
+ 227078c28c70238a5ffc011bd5452df7
+ 581e88099dd72037d52c2b76614cd160
+ 789b735a366e14893d0ce00c396471a9
+ 02836aa47418f47b067b0b20b059b36f
+ 79a2a58d24ffc02e59e699b9b9a6aba5
+ 6980048cd7fcccf1aca6d54c11d87912
+ 93adc2b8d434088fbd57b28859badf09
+ 7a51296e695ffb2cbb5b7a63c84581a0
+ d7259e8ab5582517bd0441d1ac982148
+ 5444ee4b96f59ebd2229191b70f3fd0e
+ 93a9865ed6010f423c4a7cdef90f8214
+ 7062202a639c9deb1bb88dbd32445584
+ 1ffe4bb22e8f4641c2cb76f511257834
+ b6780ae2661c39aa77322d4bd5c42f42
+ 57005517170ac9184bd49a6e9005d090
+ 260b0da6020b45b0905f12670666c59e
+ 0a9c90f6ad5ad5d9d8e11c419b07ac90
+ d0a4229a01932262e6dcd386efc5e0f7
+ 22e1d943727d1055b7eb8458f0d807b1
+ 90471affc226c88676e8dd42d1c04b00
+ 7bc8f686da9c2c8f7cc5243dee76136e
+ ca5f488ff7f41f0470b17181abd0e844
+ e5758478d00a43f03b5e44f864c730a9
+ 5c59a485af034fd76a416cfc23fcd2d0
+ fe90465bc5cdac67673fc638c4c80529
+ 7d84d2499cd43f668db50a3fb1f138f3
+ 8b77b60dd0f2e9e273fa2c3b5eda2f54
+ 65c6ecee1183c446343a6e1f7fe96cfc
+ f32e1d5a7dbc57bb78a3957c3b5ce993
+ 7f22d30357d12692085ed0f67b8cbd23
+ 48371a5ed34cef4e0aaf3e8cc67fde4d
+ 9d7915909232843d989ca2c276125d72
+ c1eaed4a82eb9bf96d74690609c5fbaa
+ dddb9e7f3069aa0a3c2b9c61008b916b
+ f1c864323bd174b0b71eb35ec9390ed1
+ fdf3065da917981435d1db5135d7e3eb
+ 2458ab541cb0853e208140238d6c41d0
+ b56935bbde440e30ddda7eb955e7eb07
+ f45aeb80e28ac4c6b2e9e3e369003730
+ ceb00102d3c8579ed03ce514b3b14cde
+ fa5128992daf363dde067a1deaaebfbd
+ 2c813f4c3b5537a59583d1967742e7f0
+ ad62735422c5e81aff0e07912a210ed8
+ 5f79e061273aa7ae5e32689ec9c87a3b
+ cc0e8f5d825f25c4919420c47a453563
+ 0f8871d0a76b526bff22a3978ff61fc7
+ 5f9c0ff9cd7cf840d4c1f0f37e643d16
+ e62e7500a29344d69817af3c839e722f
+ 32252ae14f93353734ba946fb7985fa9
+ 6f459ea65c9ec94442eb6f405f109791
+ 9fb892e0bd7df0dca04c41c59759f623
+ 80e5bf439cc05c3eeb11628431c44027
+ f494d54139bfd38934c8a08b724edf36
+ 06d6b6359098325a2799f554fe8599a6
+ b74d81eb2cc70ed7035b878246fa7128
+ 652175ab8775f07294a83676587037ac
+ acf5f5c83028af110188d19824c0ec19
+ 48d7a6ce803fdde30c11a760ace49df1
+ e8c138160004095a6e8a8f20b3139cae
+ 9e1968a26d70c34ab01c05b26f1757b2
+ 2bb1b13ab16a73ef7cd495571d436f71
+ 5e20b66124cb5daac27ca33898f7e24b
+ 5b349a40c1886584e31699bdc3c67fd0
+ 7d3100df15eb9e35d168b72681b74a8a
+ 40bdb8eb8e62d1e30a7179b7b755245f
+ 4f9c72e3676e0c5122c0ac9ea955702e
+ 90451070281257b040943ada79f84023
+ 414ac82a074809b43d0efd0b7a30e25b
+ 1300d898548735ef3c1d2eb412f7520c
+ 1b06291ac7333de55080bf6a541af3d4
+ ee50c1fc507da9052acdb7de663094bd
+ 53fea7743cf10a80bd8bf14269d2d299
+ 4f13de0c810ae6c47b5d6a4cc05de866
+ 95a9984acc560225bd62df0dfca5c6c2
+ 9dd1a67352f6ae590896b8fdb6c1a710
+ 7f19a0c2821d3d99c2d1f0f47f36a313
+ f2317e38a8fccffcbf53dee02867d05c
+ f0e061df2e15bfa0f048230208434035
+ cbca81fe29ad9e4ef0503a7bd9874670
+ 17e1860ec56fe01be07f3b617288cd6f
+ c7d838747eef297c2a1b451d9a641218
+ 2fdae162dd959541da3f3025cd05897d
+ fc00d0ff54040f107ca5fbbba7f6d891
+ aee880347d7cd5dc8c4a4db50b838b4a
+ 60acf965b2a9e669a024b2886faa5cd3
+ 161b24e228e6181f553b12814c45815b
+ 42763664538d9e5b24092f36f972f7af
+ 849a2b92c75a31a9b9a8ee9d520f22af
+ f3986cffc7df7b1959b313eb8346e336
+ b612264d9884632336acd303bc2a3772
+ ba3fed7c3388984fe4b10ce3a6e8cf00
+ 00e4c7657b989735c62a0389b395dd39
+ 075781df21505a2eecad6782940c2b25
+ 34d602bbf09bed5033df4f797e9a4182
+ 1cbb9fb0785e41f6d59652c96c39fef0
+ 91dde2db2f4f656c4f125faefe2811ce
+ 658bcd1fd6f3a4fe90898bc7456b05a9
+ 4b74fd97bfd00414425b93875bf4acd3
+ fba06008e77de01142d737b9ab1142a8
+ ccbeda8686f18e2e3f11741a7a1b66ba
+ 934d5c737d13bb2804ac7d6efe8ebd2c
+ 24eeee2a309dca022fc8cb847b21f6d8
+ fe0647b3022ee76264788bfbd609d396
+ 61f59c0219764372e19b3dc316a99a98
+ 8786553d48c2ac8e56f4ede5a7044e9a
+ 286a417150dbe9ce80a34c703e3568fd
+ dd2d00dd499c321915c77bb1d21a8119
+ 403f65a53486d7fd6630cf54dbc5b37f
+ c9f9f610c707a573b7282c829a63e845
+ 8883a959e00b054db2d16fc8fec6e87b
+ 0dcc37666e796704b1fc7ccb348364f1
+ 03ea04ecef12179c8ef9f0fdf0aaadb8
+ d19b425587c3a49250456610cd123ee0
+ 1c2270a45e1dd7c4b11738c02c394e5a
+ 879a5b919803856b95d7a2543d200f39
+ 49cccf2e078a11f186934f059e664c40
+ 31b27dd42280d90116fd64a3ea6a0a8c
+ fc8623cfebabe8f9b827e72042f1f4b1
+ c21345f4b63294d764e14f12003a8a8a
+ 48a80dc1d4700696899d042475f4c194
+ 7eeef5b7539b9dcc334b3d63ea1c6019
+ bd27586f8e9a216d960599738e35e027
+ 3e051939ed91253b108abc058f8c7c8e
+ a9104214e5effea4b0c82e116ab82cb3
+ 9c0b5fe8d3c291b5acd370849fb787dc
+ ba0e274e5473ecc9fabd1ba452df90ff
+ f45344844ed5fecfdb1fc48470bc88f3
+ fc7a41afb030f4c09159c5be9452facf
+ a507b619013d52241aec38ae14ad4b7b
+ bce34696892850a5f3c84ee901912f61
+ 54fb4ee62eff8c336fef6d51cfaab514
+ 9daee26a235b8039c3eb5c295735270e
+ 98aaee1fb981772586968e5fb50f535e
+ b75b37c044df1117f40cebece416fc5e
+ 6fbe8cc7c0bde05373d63d65b7c7d54f
+ 10b0421d3195ce2886945003086697f8
+ 374750788bb2a4b741ed5b159166b27a
+ 98f80ecee8a3fdeb5f8c3f18294877d7
+ 5295268e8233f7b406ba230ad904f06c
+ 0a586ad8725e9c5b70ea59dc91f0a74d
+ 9d54509b9a419bba2a27be35a6736b9b
+ 677aef1c030a0d4c50c93c0d6e7c8239
+ 75c087da2b45172b6d1268c9abbfc259
+ 0e1db3b7563617856526015eb926cd99
+ f1a7caa16833ad364996156c5514b79a
+ f5e49825203826e7ceca020e628f6434
+ 689bd64d99007f5a80b79d335fa48fce
+ 4d30341e06d27af4a23c62c611afdb01
+ 36b687828e03a4e00303f1cbe91e8309
+ 4e837b58a8a77888b522964ad29748dd
+ 451a464f6998d08674b447a9f5f371d1
+ 2d197f6b3b650ab17df4d2a66b6838eb
+ 918ff353da90c8e8e40a717825bebfb5
+ 182abb212c0c6c637d06e5ce588eced4
+ 11ff0be5427995c2ac8b3afa8c09b453
+ a576998a97bb1142b0553e617e6f8064
+ f5a7a6993c8021df7adf633d138d865a
+ 5b31d610f333dcd85ed7ec98f3ec0ac2
+ 3a4929de69822c6a618994946e90a8f2
+ e40d51937b8a224bc52261acc2f52332
+ 121991141279f7f3b3f8f6ef74b780a2
+ 59e7d67e6768a163683892d5a1d580c9
+ 2e152a0e74268896256ef5b8780df3c6
+ 407da5d962431d2531c24f17c079d276
+ 63380a819e7f34dc7805367e9bd7de7d
+ d10b03b6aec312a16155e3c30307cb2b
+ 4caa567cfae5b5233a7f2068a160a3cd
+ 618758ac107c839eb0090ed6c95c037f
+ 20a8fa474a3370f83f6d6ffc90345d6e
+ 667b4ab3bdd77ddfaa8919c41ac03323
+ d6fd8a20fcf8767bae66f32f34820bd3
+ e221b09ef542881efb953076d2731eda
+ 05ed1d98beff5d5e65bf60da4633058f
+ 029aaaa24838f500db30401e8364dbde
+ 335b50fc2858116fbf432cd294fa90b2
+ 606d4341cb27a1ada1a9155a3de83ca4
+ 2c296c7a63c71d9f19e0fbacdb814cff
+ dd13f39817b26776a2ce6f16d9f42d4d
+ 9548e8afc89c69a89e993a0ee84db177
+ 0601370532bad928414bbba386a9841c
+ f5e4014212fda34b2a8655bef5695fe9
+ 0846089e03201b75aad11d065157d5de
+ 991587a2608f780f7572b890c7a62572
+ 7f1aca828015e8fa993a69da47c04dc5
+ d4d0996c33d3d7cc71640f8d68dce4f1
+ 8be91d1ea2b6216c9a6409a633cd1ec7
+ ebc6a9aba9eda8461dd9bf84dd6a1501
+ 65fee2a177948d523815f6e59d14789a
+ db89d3f66d383e8a76cb5ebc5adaaedc
+ 5cfa373d8343434f05774defce89935f
+ 52e00e7728022f4cc0993b56c3f1e295
+ ded438b94937dc889b6ef5bf766853c3
+ b1df3377a767e8fc823a7fbba0b10388
+ cada8b2eb8b95e3f0de6c82954801f5c
+ b186086f2b8509a0855981d729e6d30d
+ b04cd14816d49719e2632a17fc4347b9
+ 223f2f8cc53b30d5100d44b73a3334a6
+ d09b26768a8bbbe8944e3102ad02e03b
+ fe383811ea33df134d49bd468d0cab8c
+ 5cbfc6e9fae490cbde48dacfa1eb50ab
+ c990ff18a27a547d1a0ca01047092b5a
+ e65b261d302d08dcdc68b950e862ec53
+ 87f14f93787f92c6bd83a0fd71e68f5b
+ 52a1fab2b3aa24d140417820c6aeab4e
+ 47e377c6f1c1bfd8b026cad25c9a8525
+ 7c1cd506dc1b64b6eebf9fb43bf5f2bf
+ af064ab6b2f7b88bf47f33dc910b58f7
+ 0df314886fbac6df0001d07290ef00cf
+ aebbb85f6eadffc37195a56e59102123
+ 8830d13c8d3d15d6f0d907ffa75ac355
+ 0e9579fcf1468267b39cf88071444aa4
+ 760ae81272622229b101e641daf041b0
+ 3ad672773c2aa190150d82a36751ad47
+ 9bd0664ba3a24bb7f512b4c381c11392
+ 27086effd89e2bede2d6a4b773d4cf80
+ fd47c8653e82c4e815b263d9cbca16a7
+ 3bb26cc0110eb27fff14d4843f4f220c
+ d4275ca4db009d0e84b88f099ff620e4
+ 366f236fa4b901e80fd0f0ba16444414
+ 92781fb7d0ced88824e89baf97371d2e
+ 2628c023209aa34ff0bf775a631c0a4e
+ fa797eee95c056bc5d8a777f23d1ced3
+ 0daea27d7fc1aea65aef9d9fe614608f
+ 2c10136a5898b6062d8e67ea4a990c60
+ 51d35fd493b61db67b8cbff577d02385
+ de5474dafc7a77f994a4a202bb823114
+ 7bc48428422b0c83dd812dda0a734860
+ da56fb2b33118fe4761dd77991ffb5ee
+ c959359a1173863475523751c814765f
+ cc34999d896b661ac2c4255a739da44e
+ d2930db07c3205e5f9deada0d03a8443
+ 00b029e83fc09b54001d2df2c7b429d7
+ 5bdef94e8b742932ce08bdd43f995481
+ ec91acd2e6329cb4d52af3c0104a2d75
+ ad8a48cf078ac58c34c68545b3705eed
+ bbf07106692087ecf206da308f0d380a
+ 083fe85c00668d2d24cfd46b1e649aae
+ 5cd8bacc15561d73e2a70dff2a8991d5
+ 01a632ec0beca18d4aaed1cae8698c44
+ 8e265e30d4a2d5fed417fae8be697f80
+ 6a1b6c7343b1f27842f0c6aaff1e57fe
+ 911e22e9c140e95bad02ae3932cb6775
+ 5cbaae80b04f51f16cde511d4746d003
+ b8e32f08ed60bbf2b23d470ca8887100
+ 484c7035b166046bdf37efb9ee219cc2
+ 79afd2d67fab6b513e939f8af616da43
+ 52c0d41fa58542f3e2dee21045503eb2
+ 7cf2abfedc38a0e1e0d16a736262b49c
+ 62bc00c699d9828da30a39226509b0a8
+ ee7b49d8041776a4dea7e2176080c2f8
+ 45fa73505693b4043545a949276a9c10
+ abf5326c1c3a715b407054a2fc1e4cdb
+ 0beaf16b0321b3acf88f403c36ffcc00
+ ff6b3b7250a6ad1651720e923e25a7f7
+ 4ae64d3d1be80bdf917bf26103d72514
+ 362c2f33cb3e053a704bc84ab472b728
+ 75da0f9ed556cccc4a631d6fd3f69535
+ 8f6882ac54ebb7e5a3e6254de5764ac6
+ 71cde8aa32393c7e8537d446905347e7
+ 23e322230781ab9ca9e4bbe0ca57f769
+ cf9d081592f5f1baf4636d8ac9d4c6d7
+ 99189b42a1ffa321ffdf40f3ef366f85
+ 8565e9dfc6e7b4f24caebb851e9b9262
+ a0c15e9d762a5fb810e7edb02a84607b
+ 3c4163cc6c6073ec86f6059fb8d99438
+ aedebe72c2e9c610c61fb4d3f3a7d826
+ 7b3896bc71c66eaaa62e5bf4b8e08bf9
+ aea839362030bbf98381ee0ef98c659e
+ a4702cda5cfd09e4119fbe6411d7277e
+ d2a19d528b5599d63e655508d2f30b9f
+ 4b1aea1ebcd02fb6674a46f1041f69b9
+ 9a914c828692fd69556db3430cfdc927
+ ad6b54d36ac7846ca6300c9f9c67e943
+ 60c122cddc65d58dd6e5918fb01739ea
+ 99414a71a27e163505b38141bffeeed0
+ 87c7f4f7736305cb1cf2fd867c0c5bd6
+ cae0b0b85096768fdb5f5a589acad5a6
+ f32af707c1b3f13d199fa3cafb6166ce
+ 6bdcdf9b8e32e1b654f28721cbfba93e
+ bc1ff077899d43f1b94fa04bb1985832
+ 1825b1749cbb3a14fc0eec06cf47eb84
+ 82065c393f94096435174e8fde959ade
+ 68f4706793d264e0f395500e5d5498d4
+ 9970ee0b7cc9fa65e0eedf8d149eab53
+ eb39da143896f63e74ade5d25e680ac0
+ 40931be13cfcefad7b2ec72b6a600cea
+ dcb964be5b8f4855578ce89e549b0be1
+ 75655efd6bdd65b609f4be6d0f50fc1e
+ 8c9570bfd40634ff3c048f9ae41f035a
+ 9c6104962b612ba966a42036468165d6
+ f36feeb1ccaaec8b6f875af7a25a756d
+ fcca73a7d3005cb5cdaea38932c6d2d0
+ 8e2f9f994f242af5c008e2602fa3a899
+ ee9017e03fc785b14b3eef947d052a42
+ 0c08f3cb4c38982581f9c648a9a10782
+ e08da4d2273e7e58fc62f58edb673599
+ da1b2623076eb1717dd43c37c6b7bd26
+ 4c8d8bf76622ea962dc883845265731d
+ 8f52e350107eb2a99dc5902878a4c927
+ d62d735db14f7a64bfde3cd3ebe1069f
+ 119bf042263ccf3fea4e85322ab0b2bb
+ e85f422947542fa19c5f6dadf21224e8
+ cb1857616133518a7a9ea51f2ce7ceb5
+ fe34d21c906e8caeda6683f24648714c
+ 16b1074365811d3ba273fe9c6dc1f5ee
+ b4a4d054f8ae4f3dc5ba11db27cde3e4
+ 3aa711fb5826773a798caa3f4c89c68b
+ aea03086b33be4b309155147d0a041ba
+ 2d167e5214f98b1dfd615869906eb712
+ 1fd87a006e915c0844e6429c0d33cf38
+ ab6dd15d65de8791de57cfcf44cb7216
+ 8458b5794d269722f3b5e62ef70ca375
+ a47a02608767ec866c76df92bae24693
+ 69a708d8751ac546aeb83b96a25a0591
+ 0786314c1f4b70d386563d3576dd76f3
+ 6ae6db2eb1c6c689470d22be69a2d8e5
+ a555302de90c95d01b60e4280842d524
+ 4442428fea4e66c379b66833b1c33a78
+ e82a1d3e7c58f85507e74d9beb799a6c
+ 82da54c42b61b457737d515a6451b061
+ 3e5e9f211a8baad0521e744d1bf16282
+ 3ada566cf838da5b9e24bf537427036e
+ d1da1e22a592884be2212b599f374fe8
+ 9db77561a9d1e962180d1a399b30e2a0
+ cb587be0a89913ef46f8497ac202bca8
+ 279df44b00c790f9d8f960f6dc8ffb68
+ c55da5bf5ea94ce5978ab72f42c7a598
+ 34ce133b3954448e4cf3558027240537
+ 7b8c7d8e4ddf8c2940ff996975be0086
+ d659df8f80c06a4872bf7243ade2aa7c
+ b4b8c7682861acdf7db34133e75f5431
+ 2905faa6dee3090b18ac993525c8d73b
+ 3e03f4dd6c56da112de976e7bc66d067
+ 4e907eae9a87b48b3ecff34a28f72224
+ e5c40723cd68b8d29ee9e8fac5139873
+ 94a7d352c3593063dd2c9738f581f9b2
+ d9da62bcaac80aef3887b50c1ff45275
+ 7ae4c3359ce43bf06e9a2e8472c11049
+ d28b8f192413e1d71edca372076e17e2
+ 5bbd0cf7785198dfb693da5c0934b38f
+ a8914fe39459adae99063d7a032fe057
+ 259c59b4529cb9123ec4f722bae2eece
+ 3cdb935b1988c5af5abd60d6c81bbcba
+ 2c6a95508c1a326b373e1076722a169f
+ a0cd7e61fce7251e3c3f23b0e3a8319d
+ 094ea5f3826983d37278a8d4c8b55e53
+ d72c13d99eab19b4e4a73a134854fda9
+ a7846a341379c7f45087f19372edcb5c
+ 56a22145ac925b530b94a98e3fe8e026
+ 4543fdfbfd5882dd3d0ec7e168261f67
+ 52d303203bd02f618c7e0ecdd0b547e6
+ a7a14b0712721fd323db9b4446b29843
+ f2b48555dd79acfe9fa9b99f5fd2ca5d
+ 0a7dfb6a67942e8ab05a399e1b453b0f
+ 044d2823c29aeef6d1d41e573814535b
+ 02bd11a664f1a99b8b6a8f2a27c46997
+ b087e006ecbdea939ebd7569a7607227
+ 832f9d2c71c750061ef132bcc8957ff6
+ 1c2ed16130475272d92a27f9a8b2d297
+ 3532ad7ad2735df45b8d00f138b7066e
+ d8b3570252732317bb95960ce831b7a2
+ 41b6f24b417d6cbc4a646ae3c9bc9761
+ db05c88727979f305f506e42d02d2e26
+ 0ff074e0f6470fb2b59f5195f631ad49
+ ea2d99cb4f9f1b61741dd1ca696a11fb
+ 1233ff672b99114b9ecbf0463b0ad9e2
+ 3ad6f5cc478725f377c540b5e22a28fa
+ 9e97904dc470aa808e7561a051e14954
+ c9332e955d5bd699c2ad7a81014d67f1
+ 8c040fdcbfeea1bb54965680fdde66d8
+ 7ecdbe20978171b8fbad8825010b9ef8
+ c35db3d238370f8e71ace3ab9084fed2
+ 4b3d5a640962944b086709e28b085690
+ 36edcffc0146551e3563035a3451db13
+ 729eb19b7fc4cf759356c985b4e0b201
+ fdf9d38bb515f7c097991a402ed75b30
+ 82f3d008c28c9787f7aac141a86c2f54
+ 96b7bef71c97bb2f7b83ef4661e93815
+ 1f671deaf116c8ea2ed81e7eac34f08e
+ cadaca87303207ac889699328d38bb32
+ 16670f7131b2fd271d45da62a29e8abc
+ 019453b9cb78c7f8f9551c842e562bcd
+ 120bdeb148b662e64ac469786721608e
+ cc6e4a060d762fd45866e4680c1f79f9
+ f0e9865ed6874d1099db9dd4b4287ae3
+ 8dd74aaa414d1a9b096c771a34d85ad4
+ 7a6f81a2df990beb9b60d9d0f756bcd4
+ 677c65b0e44af76ebaafc8432d163344
+ d3e90786def2d86203fcb4af72c38325
+ 7b0353e75fdedf6090a9714feb34eb93
+ af5ca7b6f535aace6abf802154747f4a
+ 6e60c062386ccd3c265cad4b573d7167
+ f30c8f981d605a55ea2c961f2499af83
+ e66796058a184d6a4626debbce8f9bb7
+ 905c2e4836ab874f3e13fbf9e42ee9a7
+ be38a4f5af9047602a753f85d767c266
+ e5050e26c59d8ed651029e80c1954c05
+ 50c2df9c1a8fe1bea4ac26fdfb53a9eb
+ 04111d1cae0aab623ec16ff6b858e6aa
+ ff69129931e4827d4a347e49a6da79e8
+ b9bf6efbf534954b17d2373027ebd43f
+ ec24b15d62432cbc1e02a666e371ba6c
+ 45b6eddc31b1f9d49c0591371bd10832
+ 42487379ce8c5825c246a5bb703bc694
+ f452640c015c313a35fae0ef72174682
+ 7b59a825a179145fd7b0a3fe2764a21f
+ c2962f705cafa1a4ba334bf23e158a06
+ df43290ef7250b50dd0deecceac2e87e
+ 0fc964aa4f917cd16a1d9b752d7635b4
+ d6e10a5934c080f2937fe884068d99bb
+ 0e19cf20f23ef214217dd94a7837a108
+ 5f528bf97e41629651bab980a7ca3619
+ b0105fd4cc944d37cbd261b9bac5b8c8
+ fc21423f259ec3e32392c315ed607182
+ a4a33c6c5278938e534f570084ee9549
+ 7bbbf15aab9759c1bb2e4d67e9f5f811
+ 2ec75627c47a78d27e84aacdb4072fe1
+ f419eb4795bd0d400ce2bfc84a5f9621
+ a3c5765fb5c078bf8f663559f60812d9
+ 9fb66a9c0f3a7d0a7fcc1fd6fc3d4fd2
+ 33e447f883f9a94645368271605bd679
+ a47dde00560c7c9a1fb228047c4e153b
+ e666d5e851c1d24f039e2d59a90e6ae9
+ f9b355ac8789679061b875fef53a1145
+ 6b664f0d311d7334454d5c1f8ec7695f
+ 6f1563671aa29efb2655c85e263ab1bd
+ 71b631834bd87553501e14c59b8144cf
+ 20ee7804031aeb1aea1255ba64e9510a
+ 2ecfac608882751ed574e6c21228b9b5
+ 4caa4442a3c58d723f97445a296f98d7
+ 88171fc4e516cbbd6f8f5055ed36e595
+ 58abde1ff07d8a9134409a38e35ac02f
+ 80f71fd7b7b0ff3cd89eb4e595d2a650
+ 9c2ea0f9a4f1037aa19ca7e8e6a73a1b
+ 2058b9e265951b7e911762933727f083
+ 463e4e5668af8dfd49fa6d52bb556788
+ d28b004346597e76f5cbcdfb26cec90d
+ 1a60d84ba0e8898f8e41d20fded761ef
+ 62f42247a8b055df9819719e8cd6335b
+ 8e4f37923a250347057e1dd7a680e205
+ b5bf3d3069e8c9766a18eb7c78f7fcfb
+ 8fa80949a4bb08ae1b9c5d510e14a2b5
+ 289cd975981ba5f5db009c1638646f75
+ ba53f969394ed5cfb9da72ac0b01fdb9
+ ce377aebaec33b88ed052d67bd5d2bc6
+ 0d3f6b19c408b661150fbc7335d17a7c
+ dc955079c13b88c59f68c594baa601e4
+ d8996ed317fd900f28280261cf74ed5d
+ f089961f8a2eda457de8a99bdf34e4d5
+ 87fd1571306cc78d44c8d6493b7717b1
+ 384997dedb7fd787befc843054eee75e
+ 21590a3063797def0cb04d63dff36e7c
+ a8b9e983da41006f0bcd2c6fbc79b638
+ da293dfbf73eb5b1c85ee8981a84fd25
+ bc65649fbe8f8bde55661ce466b8cd2a
+ 4dd1f4c4c9753e6c8513acbc6a1b42c3
+ d98a01667d4ead79af8c6f8e3cf159fa
+ 77e8399d7ac470e0f83f9600321d1cbc
+ 9b03c4d3ccadd54183a24abab381a5a6
+ 51bac93624f9aabbf2c9b823d6828d7f
+ acb4155423b9fbc17145352ccba30b8b
+ 409d25fc6617072f369d58d4bf543806
+ e81204d8162a4b612f4428667bba3509
+ 24457be6cb0bbc6c3a47c60255158cf5
+ 8a17ca4b9878bf9d63d474611da7f967
+ 7c2f285707b90eb1576d799be450daf7
+ 3acf59bae5b08d0fd3ae1594a4f41621
+ 55d5064bf76c11f0823a37986039c3c7
+ 1d822142aadd2aba828ab63a839abf54
+ 65761006a8099d9a9303e129c9474c27
+ 3dc721bbf5daf9ffabbf2ae22344d46d
+ aa398aaf736e78f82cd072be69d1129c
+ 8cd75ecb3d9aaaa28202b6ee2f2fde58
+ 359ba2f67da7e35e8bbb3eee3fd84a96
+ ff9a746ae8d28163f86c5e1d875f4d14
+ f6965ac7e193d4b620731772a29ab5c4
+ a43f78184cf21c59addb1a3ef559579d
+ 94c5890c5ff2812c4ce552a6b657ebad
+ 60df9d721804a0ab68633dd0d5036670
+ 128d6853cc5fc13e64d37bd6db01177f
+ 916d108bc7996db91e9d2592a8ab1ceb
+ d7e20c904e4eea1b6a94a1e33cee5fc3
+ f36b89e3541c66a8cfe799480e134f86
+ 010170cf81f4659a3db698b1405135a2
+ ea171fc04104d27ad12d2917c2e82c81
+ d0a3a2682f2d4b812203dc4230a8ea95
+ 0502b2dc983dcc1af813854306b1f148
+ dff156fea2fa8f3dce4dbed065049d4e
+ b7a08f550832d5c08294645b093499d3
+ 84f0d3f1ed15811d958c47fd4377edc7
+ e6b742969802e17a92ef8d02e0f421f5
+ e03181deab5f4b78fc5a6f42478fc2c1
+ a197017078493f57eafad29f2b3b1b7f
+ 5cc7e77cf28974ac9ca06ff329b73f5f
+ 856dd6c0d9f10643ac7865fd045fa861
+ b09b6e0fe10f280b5a270d8099904301
+ c5964e0a6d8197700438f2cc67ae69d2
+ d2a168c3ca11564c7d0a9a2975b06868
+ 3275c05ad633381f7905940b2a986206
+ 5498c4d900ff82a1b453ac584196dec3
+ adc1c79f3adafe12c0ac943ae215a5d4
+ 3a6723b26d50e9fc116761ca497e23c1
+ 11a58543d971cff43ec16c72ed9b075f
+ 2b9076d7644e8ba30a0ac3af89557dec
+ 6b22ab5bc084620223376f5904e138b9
+ c5c3e5f40021e2e02df7755e7efa268f
+ 8c7ad5f21381ed940c0879f16b22dc27
+ 461d742af570348222e912d56342db6f
+ 9fb0270492b67486de15142839817f2c
+ a7551e518576a3725863b2a64244664b
+ a8a3d5ebfdd5a116efb6e1557c5de44d
+ 5d24eb9fb7da6c9470ea52d22343d5d4
+ 83d1a43bbca1d87de2d4f9fe1921beae
+ c00349e6165d009d6d7b94290c4b4965
+ 86e251f0ebe3a9279f2142f064f1194c
+ 744a491e60d5fdc748e7fdac3e26fc9b
+ 467536ad4b52f079e0a5eea8e8118b6f
+ 7a4e468a8bab55ade9f58675341c24a3
+ 11a4900033d67cee0313b42c50745f8f
+ 904480cb1c902b2b323629a35e848a79
+ 4863ed560dbc9640c4883f823eb60671
+ d3bdee51b7b055800442b4d671a77d9e
+ da588534c13d4d008cde28f41e73ebf7
+ a7bade42a535dc5fad570d376f3ba797
+ 2e3aea75f0240120f96e349425fb2e91
+ f83ebb789e394efdb5ee5f4fdbc16222
+ 891a10c1360450b10de27abcf890dbac
+ 751c6e7fe5b15655cb9fa1f56cecf70b
+ 5367fd8ddf3da647ca99f1f5b6b31e75
+ efc048bbd2217a0540f3a2d8da122870
+ 49e9813646d1ca97f0632f237f667a19
+ c566d33fdbc0c9df6b3ef98a95a9763c
+ 045772f5d6f027e251bcdacc89647236
+ f00fdc39976cb33d184d8aa6517e3a1c
+ 32e3e0ae4d5bddbca3c1558266f4f6df
+ 3e3d0f3140ab4e853d8ee049da7e0faa
+ 01436af7303412a050c52df06a44acd9
+ 67fcca0ff2c17ba1a19954852a87044b
+ 3580e873b2052731538db055dce460bc
+ 360e9f0ce9e2586c08e656e35889daad
+ 8d3908e1a9e453e3dd9091ed58a34a68
+ b03e7fd0a4187f62e2019d03570101dd
+ a32549578649d4f03e6ede20e5ac2128
+ f3c22c1eeff0949a02a22ed2f1af71bc
+ 665acb7da162193a80c2a54376b8031a
+ 39faf4a775fd67106bb0c6c3bcf53429
+ ee5c7a4cb4a26ba915cd8b4e5f229448
+ 0e5ae7869d15698f5f7d17e8b202bb52
+ 33409a94b4bacb49180dcb9bac6e481d
+ 8373c949c301c777926043f7e7ea1b1e
+ be7108dcebde026af9640ae1c327c8dc
+ 078c77b212974359142850d46cd909a1
+ fb3f75a2554fb850af5329301e9614d9
+ acc9ffd1878e3042b433a312fa905d31
+ 5e1238425e6518a1c58e589a8bd98765
+ bd66b8b6e7cfcbaf15a2c55551f5c8d7
+ d8fb28d8aedd5be8e7f11e3ae40ad4a4
+ 096e932189076c76a03a70cdde79f077
+ 15747563f02097638c51c46ebed7b009
+ db9501440b3180fb663c600b3882334a
+ e8f072667dea45245c9f7379a06b6b50
+ ca49488e18ce4fb65e1c9a212fb325f5
+ b9276fabb2213ab09b19868544b4c670
+ 8829006017553bee76c43e9cc6bb0863
+ 256fff9549648c1e8a955d819aa1bffe
+ 33429da7b38f484b3054d980730d79bd
+ 09db98b5984fc1f42c30f8d45ad5e590
+ bff6919847c829f0c475c06fe529536f
+ 2eb414d3b59217f53407068f5bd06a3d
+ 53063d49f5b7d573dedd6754badb32ed
+ 2717560e485f22ce57dda48526773855
+ 0753af539487355f2b34f498831d9dba
+ 3b8da5a856b80905e2bfd9ce7c56a588
+ 356e61dfcad0506c21f1149d23b660c9
+ 99bcd3bb351fefaed9a018900290796b
+ 1513f92666b78214aa5201eebd2de23a
+ ec103d41e059d8145cc0434138b1d9a5
+ 3cbd63859139b67b0bc7759c7c0cb068
+ fe09a5c30894158705dc14295f8b38de
+ aa4403115b7bad9d334252f4eb5b1dbb
+ c05092939d7519dd0d4782be10db23a0
+ f545854fee6c98b87448010f0339eda1
+ 3c2a3983ad9b299e33cd2dec279889a8
+ 718d881b43d3f02f1707cf0841d302d9
+ b83ec2b61b667c8b9937925dfe24e102
+ e33e4c8fac736bd708774fb52c57dd0c
+ 5e1db648cce6d62d02f2eb184c624ea8
+ 21b2c07d02e4c9de1fbb9ae82d93ec4b
+ ca6f025aaeec532618592ed2c0383bca
+ c2ebf9029b14ba099afbdf4dcad63b1f
+ efffe0850e54d4b55173d3289b1baeaa
+ 4590477365b42bf7688fe4269653702c
+ 6d212f9dbe304a421a28b3804b86244f
+ e0ff9b33cdc4a51c2e8c79179a807acc
+ 2bb31b048323722acab36dccb835b57f
+ 653c3e0cae7c0dbe61e799923b1447ac
+ e41b35ffc3958e424e28c7a2fb01f331
+ 1065d0ae69e4846132e4ae170ba493e4
+ 784444652efe40adb2b6d007d2291cbe
+ 3456d373112a7acac4b666fc4a63ea4d
+ 956a36efa4a1ccbba22fd9f239d26ac6
+ 3dde4c7730cf3ea43fdd8b783c92dc3b
+ a69f8bd07c1b712c7a156deede7eaf14
+ 33fff654a9b05bef9a8563de6f1aa4ce
+ c9fa05a953b70a404f42ec7620fc75ac
+ 88a5b77535c4c4198ad2b6b9283c6ee7
+ 6dd3e891cd0b036e7bec726bb7cab22c
+ c5f4b236a43a9e32042d88f35eacaefe
+ 750b1e8aef0a84683804f54ff9d047dd
+ d81b84902d79d1fc9228f43229289b9e
+ f2e4ec606a4c4010b7558545873bfdda
+ ada8b68f82c8fc5ba39416abb87fdf4c
+ 46828037d7e72e93475866fdcc0799d3
+ a655504055cd6c1598cba627bf38651a
+ 1476a794e10b99428c9c142767db3060
+ 6ce64e94450a5b9628f86e7e8539b850
+ 6716b13410ad9a55a31afa4ac8b6f752
+ 29764151ad85eae01be4f26b1200e3b5
+ e33b5bdf05dc1b5ef8c52abe7a48d970
+ 8f910f52e4b80696713ed53acc929334
+ 933b98e37351aaea6c55f8b95900a713
+ 9ce569946d5fad0fedf1b41f79adc82b
+ 9c59a163ded1dbbefd939357e65a1ef5
+ 951f44754937a75a1690b8fd775e9c71
+ fb1a2a7f436d68747a86ca7845ec52b6
+ 66cd4fb95d429d049628becc224a9f6c
+ 32247ce0591b2a47ed979a0ce60e9344
+ b74eb25252e8b0c23ad7b23398ccc46f
+ f807522b1fa091b990b585bc53ffa68e
+ 7431e486ba118204246f2cf9f274ab6d
+ f21274fed4f717dcfe9fcfe491735145
+ 8529444392b87e29e93ff4c09c025492
+ 42726ddfc6fd78071f10566fd5e2c959
+ 70e9c918ff77521a4f7a7611ccd02e3b
+ bdf47e61f4d560bc81a58ca5a1af4f44
+ fe03e2f4a2c69321fc36c74d1430f475
+ 336ebc2fd630410073f8fbc0059cb233
+ d9fbec770e8d13faa60e3d595f95b57e
+ 1902a2a30edfa5bf6bb260f51c129558
+ d90ad6977065b4af30351a3aeac19b21
+ 1f7a293b1d65502d9276117474c45649
+ a5465c7fcbb6a42f5d32f0ab4afb1760
+ b3a0a8ab37585e39c82bae87d244d12c
+ b4c4b1bf6c5a80a221a01e6e0dd7546b
+ 2cab0afe248d4d25d3a4745a41e711bd
+ 4dbc2b8a9d35bf6ab1be4a18c8867ed0
+ 36291f70137d392f4f899ee877911720
+ 5fd7a38fa6de5343fbd9a7d4827684f3
+ e1a098e89e05fc75af6aaf0a09d6808c
+ 5d03b07213edcee5c4f6fb88e01bf2e7
+ d3e05e01ef3ea6544349f95cf44250dc
+ ec069931cbba04ec85f7e1c076ab5633
+ c5ecb80f27dffce287d1daf86a20dc42
+ ffb6b5af9e68d7be433ad875c27465ee
+ d2ec83b1d04a338be17e545a95e29f1a
+ 449a46a7efaf78683897600ca9716bba
+ c5c4891c84ef7509cb125dea633533f8
+ 5680d3f0a166da6f7c3c1212d1aac387
+ eda156a94329704804b271a10d1f10fb
+ 04ce39a3937558389463dfef3ed005cc
+ 13a4ebd17b0ba4196d5b6abcb0db7a3c
+ 14e2d2afe3f32e192b464973d9a18f86
+ 63e757ff0e9452d5562650122e874b92
+ ef2a18a2a4713ee13976cf6fb3a05831
+ 0c506c2ae9f332c19672f9d4e3a3f502
+ 4e3a1ff20f5d41aaddbd8ca359f873f5
+ 1443db1866b41a99661f621fcc3d3c8e
+ e093b8b0a7cae480e622b4f4f6eab7c0
+ c6eefeb0bf9d50fbfc92ccf194c94320
+ 130dc684ceeff99c84d72cd78574467c
+ 992c4b3427ed49cfad72d89d9c774820
+ a73a631d7afe42de41f14270ea4d8b8e
+ 5eafa6cbc142103386b1f7da86d931af
+ cb2d0acccbef2192ffb1305e953c169b
+ 9f905ec48f2b3de5c34a3e1e5ca738b1
+ 59789f41e6e7737557952de547ea39f9
+ 840ae12a8576167e83856040c28a2712
+ 10890723c44d87e0cb26e3e839bb2e6e
+ 02b9e8ed31c4b6a31006916c79cf8edc
+ db711d7a47662405a80f891b2a668d00
+ 60308b91f8e8013270437c6d4f6f0812
+ eb3b32b458c929c39ff0fbbb805cd5d0
+ d7959edab74ad3a7454e7e61bd78894c
+ 895a42ed3791b13e0b191770a46e72a4
+ f51f44698269753086e67f45a2482320
+ 66a9a4ba472f4041198a1d8cc10e79e6
+ 3713e614c7297938504cafc69caa6eab
+ 6a5e2935af8c9df0da863897ad5e1d3b
+ b76accbac7b1ccc06a049106bafa1035
+ 2c61193abc577bbfe44b9022fefd6606
+ 247f4f4f9048aa990d72e1a50af93153
+ 459e0b94422b8f68e12fbcc6af7434a7
+ 1c6a335c814b6e9fe15d82e946f600e2
+ 69bb0a4030d06c96f3eceb502a26b8ab
+ f68911e279c19cd67cf450c80df60b85
+ 4c32bdcf7a50e8ee76b7352d3428ac4b
+ c99a656b3026258ea0ed27ff22e0734e
+ c1c2bb9aca0041819d055928f5f7da7f
+ 924120f763d7511e8def8a793c01e804
+ 335a26b972f39dfac9d14f2c48861d13
+ e699fac9b8fb6168415f22deed1060ce
+ ff7d57fa8dee3bd1b0b3a76273b5167a
+ af10582fa0e060dd351b51349045981e
+ 9fe9b1ab707da5b2e9f428fae3dfc605
+ 9bec1aa3d62a51d0357a34d098528fee
+ b7de58f2b5eddf4ad6d1eacd54020174
+ 85724e9d0e3c97d04b1b6c8982aa6c77
+ 2e5397af42a9695579bc9d3a046a9002
+ 2bee564cc514a90f86c576eb55553c2b
+ 8479b61f5a419c182f21a923d23c2d13
+ 4efc59feacf5ba4dd70140973c3a9676
+ a3c609541c6658aeb7708a589c38155d
+ 5b1663d2de1ec37cc21a9f457fb1ba12
+ 9d457e60e4b53d0b616e20442de58539
+ e152051fc692dc03503c8b7d9b692d67
+ 7f4307fa4320c70f30b58462521dd143
+ 77a93cbd4df48db3d4b760749ae4cd14
+ 83ec01e299ce9baa8f2eed6fce78a4f7
+ aaec915df289a330f6ca522fb43ddb69
+ 7223f2196ade088c674b7c9f3b35732f
+ ae629df23b30b406be180e276f281c01
+ 7410d45eb7113b9916747fd7f219f9be
+ 0e56f96c42bd81fcf4227b874a988076
+ 0f078175267e1b277bd8207c28a442aa
+ 3f8469b372337a770edb7191391fe68e
+ b7ba7bf1d226071de3472f27d99a10e0
+ ca2c286607b9c40ae6409f8b0730a778
+ 835c2a8753f98c34c9e2e17d48973826
+ a2e834502544a2bc5aa5b291bd62cb7a
+ 7801fbc3ddcf209eedb7cfe29582cc34
+ c19b270dd99ed9522c9cc24da86bd0d7
+ 8656de4215f96c29c3a54913b1174f09
+ 41e92493166e0a403abf332c932ba48f
+ 86e45011409c4896e0c232ace0ceb73d
+ c4a0ee5d1c04c08a8b0270ddbeb4b6a2
+ 89d25691575e56b3cf540d19e264226c
+ 56a371c6ef9f3aa728b7645249c056aa
+ ee478209f14d149dc7bec272f2c54bd4
+ cce1c7402d4c7398443df26adb28e660
+ 4e471509c3153c8fca1fce5009ef6816
+ e4b910790741b0fcce6a9ed97351a80d
+ 9b25f368b295800dce909253e4ef9d1c
+ b5a95e62995ac52b01336e4386e97e83
+ ea8b3b739a2789a1e868a2143e4700b8
+ 52f5da11b315dc87e97a930806e5800d
+ 14fa676631861f1a599bb4a3dbbef0e1
+ c13b9950021d5ca4c627376c461eff35
+ 93a6879d2195861a18ff58b7ddc9cf45
+ 71048b0d186378d8e5c8cfdeffdc61e5
+ 8bf65018bcdbac16a8094b1027fc4c06
+ dba77d1e0546fbeb6e774f165fea1de5
+ 5e431e7484b3ba7e5cb87335064523af
+ 3f963e354579de41ac03ef1e0e17be23
+ a828616afa2a5592646c77d3ae58d206
+ b43441515e68fe8565269ebca7a49f91
+ 7b9b4a2dd763b42b40cc6fe8eb50aa1d
+ 1549e59505fe642e6e1ce4b01f6c4030
+ 890b0bc5a9defd7fae92701b75f27a40
+ cc2604837f484fd10b43258390197cab
+ 581ec283ffb5ec62d9c5c76e8e2ef345
+ d6dda73c22c204fef8b409ef760106c7
+ 33efe17de5a3bd05be0ca58dcc3936d7
+ 3d08daebcec605ea46eba48d12b975c0
+ b0a0f0be7ca5fa80fbd5a4bfdd0bb29c
+ f66e67046f27c54d317f39da01d1efb0
+ c8ce55c2940652084105e1ca58792b59
+ ecd8f40b20032b296cc6a2f7e0c43fb2
+ 2febd76b86114035d2448cb8a75a6f7d
+ 86a6046c75a1d78436a02365400599d1
+ 86c5430d9be1136122e99598223b3533
+ 1759fad347878d0aa1cf09e3286bcef6
+ 6456fe5e7ac1497cfce78d9ed8ce0834
+ d4b1ca51c9283e949703ab45bd68ecb4
+ a8ac8d4d41c4003624ef72cffb191ee2
+ 29dd36108d6fc7f9ad9165fda7515c71
+ 76ee90384f2e7a64590167227a7dd7e8
+ b4b14533b439af85b5c37561923f6879
+ 3c50e9cadcc18502ad7c97a1f5f657dc
+ d89a2d6804b29dc00f7da2ffa7175406
+ 7057ae28977890f97a8318bd1a17d997
+ 3f7a7a6756120b75e5394eca829e0cb0
+ 7eebd914f168b9a529dd6e9974a37455
+ 8a11fa847271673bfc5cb1ba235f76b2
+ 32f9b5318fb12d9a2923d426a38cfddb
+ a2102622793db7324342018372cde495
+ ae7398f78cdc02cb493415b45ab6ad72
+ 86b946cec69c12160e9b818ae32712a8
+ 9183b159f5684f666b96699f30a12b1c
+ 08d47078e22b2ea0d353384e7f436188
+ c170cc558675339796871c1abcc826b8
+ b4ce4e8f4f30623bdb564f5dd5ff813a
+ 072f7605d93e9e5751b10ada68dfecdc
+ 18de63dbcbe91a220913995be1dea18b
+ 9f29fcc648f34af6a842b4de6543f126
+ 9796ad55e950f40626876356c6764cee
+ a1ca4edeac30dee6f7b9adeac0a2d31d
+ 81f9e508163b88f1525022f1edd91184
+ 132e37d33232bfdfb52e5c214b3a64ef
+ 91727910a09e9b67d8b6a2b365fd1db5
+ a8479243fe9bac4e8eee2c374907dca0
+ 614cb91d0e57d0ccad93e1a8fa87e7a3
+ 3afdd5a76973bb79f175ccc021d9f8cf
+ 54064e8c3ecbdf9a05078af1b377f47d
+ 4ef8b4974b70e60b2138cb4a5dfdc283
+ 437c3bbf867b8f685b270e45d848e765
+ d77a2f75b4dba216b9b069f546a1bc4a
+ 9532a1fc3bcfef83c27017d15cdb60cf
+ 679f6655e12e4056cf73bd529675d0da
+ 67eb6eb4f176584970e38093b6976120
+ 6baa0aada82f54b40b247f726cb45af8
+ f9f78a5e024d8b4eaabe5a94e7e91680
+ 3af9a3a394c005ca752b8f15af811cba
+ 87fc7c9573083f01f3158a36baa0f740
+ 21af11582955006e1ae2af18152c1b56
+ a936bc28ca6fb688f8452e92e21458a0
+ 7fa1961734eb3bdee276533c3a0c6f63
+ f107198758c85e201b9234ea8bba5b19
+ 086709ef903ad6afa1095b184a0f9222
+ c31670cb7aa942d8a6eefd29dae378c6
+ 726a2bc655172bb2b54dc9f657ab074c
+ 41c7e55f133dfd8f34f41d33ba199879
+ ccb9d30d85cd9896f1e38e850864e596
+ f1f544bf541ee35be669d934847f639c
+ 2a4f63f233b3aa954dcfe747f4ef9144
+ 1e131bfb422efc900557a06e505e97c8
+ 14f4e6b479114702de14aa83f2c47136
+ bbab260177eb5236f2229a9715b0f776
+ a851bbaa815e41e36bb1495127b117a4
+ d1fd5535fadd38397a7530d6986dc93a
+ b3d600cac4a8ff163a38c4a9a0c1ccdb
+ aed7ce4eba7e7383943a40dd79b125db
+ eb9f3d395406a4686cb6d65be1b570fd
+ 036fd33350544582d0dbe1cc1e34b9fa
+ 284887c2d1a30315b960c3a49924d6fd
+ 2ea7b8d945376d2343fda5e4ce43518a
+ 89dd7fb206172de267b4c44e48060937
+ e70af5ab2d5bdccc0307c73da4294498
+ 6f63965777688c0f95a3292c3880c33e
+ f116bf1a66a54dc7f2a16a1ef19b1054
+ b816a5877cefd469d62e8feaad2501e8
+ 085693fdb8e932316fda51f22025c915
+ 39d062d7b4c684445d43293164710173
+ 392cb06069d154eeda76750e40b9f670
+ 6f5ef42e07a61bea2326f0321dbd9370
+ 37f7b64c9605e70a18bd208af6c1a785
+ 7beadd2014b5250da344673bb3b9b49f
+ 31bbd5d485fae2f6440446fdab895b14
+ e9f0b50412c7ebebf5fa0894b2ae507c
+ 5e20730e26c442a37dc9e19c6743eced
+ 3c34f8de97350358f7f7f913c18739d8
+ ba42c968214f593a75ea1207489a9ebe
+ 13968c9144e3abb57bf5192fedc358af
+ b15568fe93f44f8567d3791c9c8b0c87
+ 002bb87b57327258079465f75dcbb2e5
+ 1183e501b22c1f3913d390681da4c428
+ 02141f4074bc6c9b1a67151b7d3417c0
+ 2df7981cc56f9ee9e41a88cc6eedec05
+ be86cf98606238799d07f6b49c3a642d
+ 9596837588c04aed9c71e28c2ac29a30
+ a2f0cd9b7086ac9ee0a7e5d5b608b39d
+ 420943c608e2d98c56daa31d5a4cfa13
+ 271b0908fc940db2384c96364dee50be
+ 3e2109667164a27413d21076ac449688
+ 305f92e20b616753cbdf6c798b82728b
+ f08806a797243e66ad698a794800ba9c
+ 2fce1c7be98536ce31b9d3a758335838
+ a0a866be9e7704758891ec67c40202d3
+ 2aac05c8ff1cdbd7264b95cc6bd1915d
+ d4e8449904484ed252cb601329d543c0
+ 03166222f215ec3494ddafdd8ab1a951
+ bf490d708df98a390abf303b55d1edd9
+ 18f450da38bcf9464a719281768dc097
+ 0067c3fc7fce33d821ebe8b10834e9b0
+ b03b1768de41fc060dcadc47ce15cd39
+ cee8d5bd40e61e20f714549104994816
+ e060f444c245486d2c40e9c8dc7c6945
+ e1ad680b7691062b8aa75b33b564ea72
+ 1a61113e7d01643d444536a32cb2b4ce
+ be5a67a9b72913904fdb87534db3ef35
+ a912fa0f7f6a82737c390f0ec79ec77a
+ e386499a2f533a160d187e570a072b96
+ e70226c7a48cb1386ad6a28c9d880122
+ 7554b1f7f2dd800a992a772ce50e90a3
+ 17f810d89bc73c7c3e1bc8a0cc8e5648
+ b29634a225f9fee3c828cd03b76b7202
+ 5d7c3d64c48066501d19f340d5f3a03a
+ 52dfeb7bf65e3e1f14371f3f2e985d71
+ 7d17f7f21bed39e6b54b0157a9134925
+ c61fd0ffc82691f336afa1a61196a609
+ 0b75aac567a00146500587587ce2910f
+ 00e1103a701b2db75436417c21b58af4
+ 706f03827f6d7513bc1b2b6894673726
+ 78bf5f2b695762d632d7c4ed4754b96a
+ 0c36e0142e54fdf3502c0bbda611309f
+ d9a58ff6005db674933b903188644724
+ e76a277001ecafcfe896ce4174a22a5a
+ 2c74237421e1b699fbe8ed4cd7483c60
+ 8e07737249d89402082619db1e25dd8e
+ 67940591d7891433278928e39db1c227
+ 6fa278393aa4a6a70e703f7fe91775d1
+ 686a2d4adc155325625db56bc58621b5
+ 4c00f2f02324160dbcf54909c06ccb68
+ df9ded544a887960617d68783a79747c
+ 405276fade0416a978eba6de0ca107f4
+ a6308ac04210092af44e186687102f0e
+ 9d6e67b305f8e12814b6f5886208bbfc
+ 6f9b930e631939310a00d5af89117545
+ aed7750c70029d04043f3a6fb4af2ac0
+ faefa5e04ad5df52efc079366c0ddd72
+ 2341e8cf9b818a6ec4d0deab785b6bcd
+ e5295289f593b589d42f42c519f4e76a
+ 41381ae96ce6dd556c8542c631dc2e7b
+ fbca030b0ce40a9a8287fa5d0a541993
+ 24f7b62f54752351761edae30f5fb9f6
+ e4ffc7967e5d97ae10b42a2b4134215d
+ 0d5ecf2a322e54e0b5384db19b7c02c7
+ 3895dc4b9e501d67ae4a97a88f4ef6b8
+ 0d40dad748925d00c7b012e7e1243d18
+ 81b5c5c8c2d498b5edf194f79cb7eec7
+ 5888b732b1a90a10ab005f7a8acb9bfd
+ 3277fc66fd9ea207ac7333c8cecf32ca
+ c49313cff854e118efa62123b130d9bd
+ 5e25175bdaa70593e7967b3b8ba69e6e
+ 2931e865c8b02931b68b127507ff1c1c
+ b5c9003735ff40ec8e14f5749b0bf8cc
+ 2c9bf44a3b3c20b9d0443986e148c6e0
+ df05e01ba061b693607d46ed3611da71
+ 8bcc060fa93fd15e71671a473e68050d
+ 07c99a39a1d49716f0f9fca49f100569
+ 7f61b37531ebeace897c7d091a2531a0
+ 0970bbf02d0059a2847b661227387a03
+ 6b7f0c0896370deeb75f2a4a818abc64
+ 4bfb1f489d40484230e4c7caca7d42e8
+ c460cd52062390087852fd9c86bd7985
+ 62d85e59fc56d6c3e2805060dda74746
+ 77e651b9fd9985e787cf7ce47cb6479b
+ 05fb243d3883e006240b96f477ba4007
+ 4928a85395d99b3959306f3c4a5cd2ab
+ 3c3c933a804f3d76b5c4b00cd06929ea
+ fbaebdd5de8fddad126b74557c341f9c
+ 4b6fcca925ce81867193157d6f926fa9
+ 123d9395eb2ee2f89ff78c5237b06660
+ 70576ca90d329802c4099175605feedd
+ d5e292351174101a8fc32487b5824348
+ 5598d38494544a77de056debd1157c4f
+ 908d3ab4327f3e9e8817ece2f03b5ab1
+ 0f1dcbda9cafda6d048fa78404b65dab
+ a32c276982b16d3db545ad0d190926c0
+ 973767583651b468f205988b86ec95d0
+ ac4aac7f7785a7d5af1b81e1295c5ebc
+ 8e45de27205477d7640eedb312b113ec
+ 52b4145a008f33ff771553fce0816b98
+ 9ad8a413bef0ef37243ba0dd410113cc
+ ca14c4d8f1ec2549c2cdabd69d64d6d6
+ 832565afa7eea21a22817bd4511f3218
+ 5000eb4fe42928ed2d5409c3c9b119ce
+ 31b9775ad9d827a7ea14b2d523d1f4ca
+ 581cb0d01b1f9bc27d73526325945be4
+ 9ede71fd6cbcb5ea2050607af8b1a213
+ 23b930ce47a74b3e61c0485ad29c28f4
+ 40639650465bb32507c6db63e7ed3210
+ 2aec8b1da1625458bf605085e5960c0a
+ f9e0c5fca29bc4d13e8cfc888dd599b0
+ c1a9879441757ff845fae462aba8a6de
+ 8d6608fd29ef9347a3e7130486d3ed5e
+ 2d0d175dda1d150f36aa1028193b8ac4
+ ee5d4996d4dd2053b8f1da595e597b4c
+ cec71cd9d62ccc2a67b0f290bca0d022
+ 94c3c41d16ca801746acab24891ec531
+ 211e61049c8cc041d85db2d138654370
+ 480e6a1d85cf1dd5b30ffa43dd7e2b7e
+ 4bf556c650b87d4c23ae83f6a74874d3
+ fe7f57fc1e5d2b044a9e5865f7052254
+ 5e8e96e581ef01689ccc10da5896f4ee
+ 05db3a7dd50bcd373d322cef906efedf
+ edb8d8d14f45fe3beabccb1ff2105594
+ eaab31696e1ec571855e57084b53c661
+ 8adc0790babe725a8d263927abc32864
+ fcba5bacc591eb4a165c95223f23c0f0
+ ed46c9d841e7ab66ae4214b2afdf5ca8
+ 0537d60dff114de78ae94d32557a1088
+ f45d01060921d6fd801330e1e3ff1ad0
+ e974b91765b082358be77cc4c5445dc4
+ 7a56dac09b4875f9043f5e6156e39dea
+ f3d44a752ddbd33397a7b42a52a70faa
+ da56b32d90bdf808550e4fd51dfdd21b
+ 52477f1b776f4cf8c438c1ac87abaff9
+ 2ad95dfe91d71290f3fb55b9ae26f56c
+ bc0e114cc4dbf7280977deb850826fe3
+ 7cd28fd3bc7bc4096abc02ac2288d45e
+ 746bde2bbeb93a2ae256f350787a4353
+ 27d48ae4ac669b4de56d6ce7b7affa7b
+ 65330baefa7b88b4754be553b805674e
+ 6cba41ea64866a26dd15eef29b9d20ae
+ dfe4a5351cec523950cf031215f0221c
+ 5267edd8482913c24122e59d5da63d29
+ 00ebdda36011998383bc7f098a5fc03e
+ 2b00cf4ca1096ae6d12a728154629b48
+ 8481b5f14724301af4dae2b0b042c01c
+ dcebeb157c99f0104315f2dbdb7e778d
+ 8a5d13d3e8ea38115827d3ebb063384a
+ a5d78ab644dcf525488aba367a987f35
+ 5fe5d097cc650bfe8dacef6d44837d21
+ c691815af3c7dd9b859483e0c1ca7d0f
+ 93f86038e90c90b6eb28e2114073741b
+ 7d08e4a2461e41bcb5caf526eea7e225
+ 233dfb74f4ed35b526b026814401d41c
+ d9557bc49104a5daed3e60202c0aa20a
+ be8c3fa72b32afa3ed7903e0dab77702
+ 35cc0cf5278785d0807615f946222912
+ 80f231995bf31d923a99c8c88e5780f3
+ d2b699aedeb371b726c4307e9a2ebefb
+ 08c69660a8522c4158f68a4e4cbecdc7
+ e7cfa75f2b43c59a79ab62db3694a93c
+ bc7dc316719d7f510c8634217726e8ce
+ bca5e34eecd0732f6557bb602278bc2f
+ 38f7dcc35cb55b5ea732c93c996d6f39
+ 46c42b8d69937d8b0de6d5265fdb301a
+ d88507be97e2a1c3778526b063aee095
+ 493c1597f4a70206121cfc5e3d8e3dc3
+ f0b8483a89267c22715eb78aeeeb3ba0
+ 51cfb9229532abe0acbafab980ea8f91
+ 52564cbfc27a0eef1235c7c3e7b31a0c
+ 4a58351898cf5edfb0e83d3d2ba69a9b
+ 31f85c2340f7cfec40561785a4edc427
+ ab784a9b10628aa433e9db78c8a927d7
+ 6f3bf55ed5e77233da80aa72ba63884b
+ f588c25de63d20dd208a1b2cf5b9b6a2
+ 262250da09afbea29745575efd08be41
+ 566b9a410134d2ffe716ad1e15e6fe57
+ 82fdcd0de6ab8ca699c80da41d77273e
+ d1d1e1119d271e14d607aba17bd00904
+ c81a850d537bc63be50705e1d445713c
+ d869f781d2b9e49eb0f15e6c2d493b8c
+ d62c34b92fc1170d7d9c988b2f637a34
+ 06025893bf4254c9a29c5aba31be7e0a
+ 230cfae88c26cdf166119fcf45a556d9
+ 6faae67ddb5c85315374398a4b40708d
+ d8b02580f7e0e1f7c25ca4bd0d8b2d09
+ c9683f13e2479708a65e6cf48de2b613
+ e7809a8b480efd915f0900c9b56921df
+ c54cba5cd8cd3fe2f7a6fd3bed529418
+ 0d6583d6450f6032a0689b9035bc4fd1
+ d267704e83915d7484eee88ec1f05e3b
+ 0a10557fa4dcb2ba23b768d4023032d6
+ 86a4bc2bbffd10c23a371fe7231b39f8
+ c252fad8b1456cfbfa83ee4cdb918605
+ 7809abf067aab8da36ebc07f8e14f75b
+ 74d4f3d29207ff4351adc4603cc0717e
+ a6ca061ffd682293eac803decfb64604
+ ea830700c4c8aa7350e18db6bcb61d92
+ cc27de15bc80cdeda44615a3cda1466a
+ 10a641f6e75487be6dcd3a1552ddb74f
+ d12f926d7cad9f0d61c46290933aec59
+ 022d924c42f0c809813c78189124276c
+ d3a40b7a9d71ae793e635f809b198dc1
+ 1d6b58b320f37058406faa181a6c82cf
+ 99ef4820634a2a11731b7df9aead2240
+ cb70f66c978b6a460e7fa7a3225916c6
+ 6935fd7b75505436ded0c4d7138b2405
+ 78811eeae0b58221f9526a9749f83c56
+ 855380972c0231979168cc0eccbf6189
+ f6688a8a4fe3e64ec3b68afb42261e9c
+ cb3b28931cd56cd8216fc6a74d967220
+ 640455c31f9f1b85d11beb593bd1cb17
+ 20ca0c99e4342f3f7cf627acceafc9dd
+ ddf48aaa6beb59be6f351b2c59030ee4
+ 61fe1baab532d326edd5e8e3ef1ac266
+ a8420252996a4348cd51da8b0d478a51
+ e9d4c187d8f22dfdbf917119029b9876
+ 037a97af6add6c5ad9031941700e69ac
+ ec93810da968945606840fff4c4150c1
+ 8b95afd0b3c349d303448f8b66723c06
+ 866e2512a5f1e9a1a47bfdbcebed8fce
+ 69c00a74c3b5d5c4f348a102040763cc
+ b0038fb8535670c24fcc1a6810806443
+ 941e02d6f76dcc070fb1314d209e8b98
+ f932e703aa5371f962d9b17d622a72e3
+ c4fdfeb247359da41e6123799d58f2c1
+ fe4e2e3e0037fd6e85b652e1da41719b
+ 9d14526d9eb990526757de1eb64e22d4
+ d20284cde61ce186212d7e0d5b9cca32
+ 651342c26500dc018b92b98934273308
+ 1ccba272671a251232c953fca368da31
+ 9915d2694855eef15b476dfbfd829517
+ 6c966550589a2974d9581bff36a47158
+ 8fd305d1d0fa70425323be771b7ab965
+ ffc4533cedbba10740d0e61da4e121b1
+ 0cced3b3061c17fde0d225e9ba9d2e14
+ 4da8a1258c588e5a2906b84ea306cd35
+ 26752cbd977970b021c96adf28d76a40
+ bdca678bc76160ff20ce1fb3c0db80e6
+ fdbf0cfccd9445225e93059ac708514e
+ df91b75563a78c43740d59d79702e3ad
+ d3284a5a4853f3d4f8134ab7487c8ac8
+ bbe1fab1ae90aff36cd4cd80605d737d
+ 12321aa4971b3dc9047f582aad5d31ce
+ 27767d7207ebfeec89794c54fcd3f3d6
+ 86f9acf563264151dec93e083cf0aa32
+ fdd65ffb2c77511e882a40fd8bf2bd33
+ 0319f7f8f32a96d4f00638527ab2debb
+ bd4f605de0e272a45eeb0b1b7add8e9b
+ 9888efa1cc4f6d9d70e120a3a4987823
+ 2141eb0b4651db7c22525d35b4a4e861
+ 93612eecd4aed19ce22b4ce5261549cc
+ 0acd2f3bb53bbaa1c86e852722148d4f
+ 70d67ed095ffdb4502348d9fe6b0c094
+ 7901806939747bf0f6442ee8f6a15220
+ c18386fee0b96dce544c999f297f6770
+ d0e7ce701cb0671d52703b3515a0b06e
+ 0677fef304dbb931a0193e9e3fde242d
+ 3323f70f455e63c3c62077eb1b98275b
+ 954d7e9b6bcf63fc8dd21c8c5f1675fc
+ 2cdad0622f0907828b0b4a9da5ae29f9
+ 114b6ab2d174d228d6db1802d9940f96
+ 03c9a5d9ba6c039ec3c268911bb4cedf
+ d292f4768902416e62fe498e94da5453
+ fa26a54de35db5a8a6bc78bdd2465521
+ 352678553b5d34839f6f406f752be2ad
+ 1900b40c32f8bc2f6916e41bdee04c74
+ 68ebccc9512224536ab00b56b9a3d05e
+ 26898b068ca08f81e5f0fea43edfbbb5
+ d5b8f2fa4da62cb2b1679120eef305ad
+ dec0e059d5cf7914fe9016e8ab9456ae
+ 6ab9aaf8ed676950eae9553f3149203a
+ 5fa85a9d1123fb24a1082b88f78f3275
+ 6396a4535f71848d114f71c76a6ca881
+ 032dfa961a3294d1e1e6450b786c0613
+ 44411a7ccb4b729c7428a1ee4fb07483
+ 17d5b286c6b5e2c810bddc6b641472d9
+ 5fd9e078eee54b18f171f0d39398f014
+ 6468d89190d3e68beea430ee60f3db8b
+ 9785e020e9446f5370f6b08e458e9645
+ 8ab2b5b235e20159b4ca8ad88d95c46b
+ a933b4cb26219f8d47ee769478a0a253
+ 4d3c2f23793a2d14857394e32bbcdb24
+ 683b2fda15a5aa61a35b60585f11f076
+ 09481e5c5ee2edc11e9904a9f71d351f
+ e4a3d96870f591001f1b2fe0732ca1b4
+ 8c5d27570d946b469817b63c2edf55c4
+ 68b9132cec0cca2492d7712641178491
+ fca52eedd6ab8b0b718dbf9b4bf42f75
+ 94026165a7b0b3734697a3042bea76ea
+ 2a7f1ce622fe9cc678f25f9a0781dbae
+ 9cea0e57eb3b6709c49243731731fd72
+ ad96b1fc0806402b84452a3f19740fe4
+ 4c906a5da93db8c7f94ac62e0b28ee59
+ f7c565fc8b2104a26513dbb2be75397d
+ 30ece1e1a95a052ed6fe74fd3df7151f
+ 81a1372a1d9e46c3917c658fb090b16f
+ 417d23b89694a4ac3ca3f84f13dc2cb0
+ 3a8236128f1f078f4d7fa7338b59d89a
+ 139f858d0fff7ea5c3258ed71d60bb39
+ 0859137ddbe2980f5bec8f9199462688
+ f104b31b528f38873b13334510f70939
+ 45904d9067424e276b2bf49d50a2f942
+ 3c1c439b6a2c8a1b28fc1266a0662bde
+ 76b45cf05dc5a4ff161362a2d2ca4309
+ 6587e27406905f9fb4eb121b6c664aa9
+ a30a06a139359dbd0d1dec4ad960c434
+ db5d5c0edee56a187194b4a32add3c60
+ 203b99e60d2436fe785baff789250ddd
+ 5957598c6587c128a173ce8ad632f240
+ 83384c00d3fd47f1c871c61e1499eb54
+ 96f24cf3136762b32b167fc59c1b0fa0
+ f2ea467768fa763f3321a271d57802bb
+ 1d6b939c80e21e1610ff92045b7eafdb
+ 32d340be7ed9b6aacd6fc0e08a361072
+ c2a4b38b1b4ed8a89efabe98afa5e799
+ 6b89977b347421d1690cb7bdf44a183a
+ d003eaf2ce01786b4378c97d98260e20
+ b46c6c546eab906677a6ab8651f167ac
+ 459093bcfb23f9526490d4112830d5a6
+ 5224043a4e5b05f8268db23752bf4f86
+ 57a21fe92036d96dad7399be6984c4f7
+ 9456a477fb0bdb71ee00565814e721bd
+ 4e029d7f6d944c60ed9af3851db74ae5
+ 686438974c6dc8a7802e9e77bc2411ef
+ 3b38fe979bb9e095df9ea1c0d40d67df
+ d91d74a2d710224a5b45c41cb31e4c9d
+ 5a060500f3d12f42d0196b5b80ab1125
+ 3dc5a4a5d03aeb6465b10988e1476286
+ 95fcca43d7ec2e0a1e826234bf4824c5
+ 6bffe3098eea53db2df0c5a8daca7902
+ 6f2491b84257d7a52bf54192db6556a8
+ aec8f6279ce2228361a331936bbefe96
+ d0c2690447afe5b9fe503c06af0b4f39
+ 408ef34b077d5dfcf3cd939d01cdda9b
+ 1daa9f3d03ec36502931458255dc7aa2
+ 1316204170701aed92e3b34c9ee55595
+ 78f5032500060d4b6498561ba57204cb
+ fdd89c7a680ef087a7a7f8a64b8a6bbf
+ 209b5412f57ff65b89ee8268f1799dd0
+ 5caf2e9136ca70c3388a679b7b63b3cf
+ 4e57073fd09c73188944870a77788326
+ 0a393d64ffb9408df70e6e750c83db8e
+ a21b73cf988ee723d83762b6bd053197
+ 25a0f66e321b5b2f8936392063e9654f
+ 9d2900c8d90021152f0bbbfff50557ae
+ 78427fe065dcf4fe2ebd2052ad5f6931
+ 31ee1a0dd630fe5739745813e96fdf07
+ 688ba86ea00660876f75acb35544d336
+ e6909f1b892259246cba5e1ecd9527cd
+ 73849da318ce566220ef751020dc952e
+ 8b06eeb64a2f37c5f2d56158dfed4bd9
+ acd8b93df7bd665cf2a46c49e0cc2396
+ 1e2af74553298d21f12516c2655777ea
+ c267f02aef794dd329b242a3445b1074
+ 66cca029f061a4c49dc9f6f9f0071c0c
+ a17cd3f7bfa41cab168723e10c2c5003
+ d1b480fd765e3da8e956c5dc309c1c2f
+ ca0024117a1c8f819d46b3e1f253c209
+ ed735b954289563731b6846e6a7be8af
+ 802bdb6b27104ef6be8b743e32fa95fd
+ a605a0941650cdf22c424d9e78b499c9
+ 81058ea5e0af0892b2bc3dbb85835a6d
+ 71e382e1e48ced52f9d3f03a87129b0e
+ e4d436de062ab9aa6a1a4006daa7ae07
+ 77a62ea822e3ae64e759e51d15958807
+ f64b3504b1b6ba34a712e1ccb0ab8d0d
+ aaad5a2b8529c77b7a5be1c65c34afff
+ 6ad15b5e5b5aa92153ef83d9437ffed0
+ 5db0c2c94f95e3c2a7dc959e458999e6
+ 0288d2cb0838da67450b9d441bc74fc4
+ dd9ec10cda172d381721c03c8458ef33
+ d16a915d098ef47d8e6f7eb9ffd03e93
+ 310836aa04b2abe81a24a35142b056ff
+ 2aa4022948b1a8e9f75974107091f722
+ 2cb87d31c8f0c30528a6e05b83f7a5cd
+ 84de98ca779e97fe1030e1c4f7ac3150
+ a8e1d51b94bfe9da9b79885b7a91e7b5
+ 810bac58f2ee96181193ab0798b20013
+ c82cc538fbc9ab780807ebd9eccd3390
+ d356514618e89f54bcfd858cf524c3d8
+ d23a71b08388ba389d02508ce402b6b2
+ eb752b22e5bb4121fb278299c4fe418d
+ 6f46ae17fbd53032f40f9961fb30fa6a
+ 22833b1bd555ca39bdf5b8620b337d2a
+ 33a27d2e7674e781cf43002842feb5b0
+ c52fbb1c3329023a79c826d7598118ce
+ 2af4ac2efb1dc99800cd58523c027c76
+ c8c54d938d7817219b93b8b6e5297569
+ 03c7bd93c5dac1a0557677b11714dae7
+ ccdfa35630f0969f90f8f1dedba31091
+ 8c969775a2c41b7ff75ea219c3380e5f
+ 987bc88daefcb43c1a6e3ecb9cc5c2f2
+ 3ff11633b2413a462785a59098681677
+ 156798d5d3c418f546bbca6cd301df97
+ a1214c57bfcff791e1317651ae8db9a5
+ 3bf8086310a8d596a73c406e0393e3f5
+ 0213213e794700635ed2fb683b44a15f
+ 234a626ad7cdf828f76b5892fe107ff2
+ fe81c672aa74fb906b71310470e42d61
+ a1b10f73fe95bf92f5d8c14f7b106952
+ a8482707a14e74d236da9fc6db8ec56c
+ 267816c04205d265863bbafd5fe274de
+ c567505e418ac3a835d3005b170c8eb8
+ 3c7d52d4717175d464e11adce0b713e4
+ 7058a43e3f7ed261f4eab44bbd46f66c
+ b23b485a885222884f4a9f0181b362d7
+ adaf1f8b3e5ea25b35bd2c35dea1261b
+ d90bfad6ac6dfd0005e7770a6a710492
+ 3a17c62331ea9203eb445f04750d8570
+ 573a0d1e33776887e8954456b69701c0
+ 8cb0d5718e7d4a952ae0366ff86d342d
+ d377a242eb2d63c700c70846bb57a2c8
+ 4fb302c812286a1a1173fe167ba14490
+ 883c0f24bf9a355c6fb85ebb7d041e7e
+ db809ee920f6c81560a42d6326f380dd
+ bdaeb8e5639e30e6cecdc88009f10ad9
+ adc010badabb231137dae2d9ff2c6c06
+ d7efa835c83df828c26e73737d1c3e9b
+ 36ef80d13b159674884a6e7d805a4d3a
+ be061084cfcae2bf413e3c6cf471e45f
+ cf8b4c6d4de5a374239b0146cdfc535f
+ fa5959f83403d2b6b145904dd649d2f4
+ cbe5a42947897443c6390392822e452c
+ 198130c2ee38b1f8fbdaab0789ef7f57
+ 8e669ed58152266b18f4c1287ab7d6cf
+ 7d3e5c4d65b96dca9092f3b1158684ad
+ 5872e4da8935b16a5e35d2eef99fe06b
+ 11b222cbad282820b51f62d562a57e63
+ d37bce7a33df0706abaa826370a3b71a
+ cef42b59c54a1610d8232dbc9a6a9f00
+ 2614185e9af14433454867f743175565
+ e0d267cf17b7a4f10c097849776e17d1
+ a655876a7ffe75f0e8d120d1097811d5
+ a63e3b717d7149342cee643e6c8e3c2f
+ 2e3e4340d1788cfb463109c7de0ab94a
+ 0d7a2f3b30383aceb9f18dabb95b4ad5
+ 9ed2ee79ab232f259122b91c8fb49094
+ eff359edf1abf842ff8e8e135c427b4c
+ e0ab68715758c45dec71ddd0a5ed3023
+ a0592b38b6cdfda92340b3446f08dd44
+ 97e142ab4e5eabd02226806a8bbc375a
+ bd13ef6fb1a0a56461f1bab4dd13985b
+ 40f89bd14a165e5bdd4ccc7b1ad70e74
+ 3ffc13ed28f918973b704e070dc2842f
+ 0cdb9d1b2e3858fd8e6b1dcdb20f4d85
+ 446eae55e53e28d698f8f6ef0b279d8d
+ f7f58e00ac91e8cf7bc6e445e4b55538
+ 5f42d9ed06ed83a0dcb6adcff66abb5f
+ b4918dfdc05f83c8d1ca22e44c1e1041
+ f7d37553cb15e310dbdc2724db893b33
+ 27dcaceab11585e156cb0686d279fd9d
+ 4c8fc2746a7ef20c32a7f1444881a99b
+ f68c7311d724ea4e867f9f34381c00c5
+ 7e4390a2de0fb699031715460a577c51
+ 4036803654a5d13c3e6f44fb088b3c2e
+ 63b8bdeb214223562db00914ace5818e
+ e2ed2482f66dd37566b6c33cb1a93a15
+ fa2103bcc0bd0ad7a53132a36b8cbce5
+ 211c04d295697033d0f9be0d93f912a3
+ 883c92dc621a37740be53575376786da
+ b8227cd62a74b28c85acdcd65fc93ef4
+ fd6b3eb1e5aeb392242f116c7ebf1dbe
+ 74638f3a0e0737576171af5bb9909c1e
+ 4564a5849f462b3ffe580e117d2e8277
+ c0a201003a6139bf5ab125bf8b442e12
+ e693facb53d5e3bdcd2582295ad5b617
+ 9cfc1e429aee28735d4fe882ae83c747
+ 6ef56b547f501d2234a77a2077bf3f61
+ 360899295840482ca0647d4c0053e658
+ 083419f4cbbd2bae777f4b7a00ab9873
+ 5c31456d0ee3fe6d6012ed3fa2e7e355
+ 4bbfd431a6dc447b5e07af00deb631b1
+ 7463e568b7abb9dddcf6c9e7ba1f74bc
+ 561b036c573a183313e591ae32add1ff
+ a01cc909145154924e1c05d4439d7186
+ 03b96707acfa1e17349b8d27c35cdbeb
+ 4f529a5b6bcc46938a74622740616e0c
+ 82e71ca6f03a3a6ea89ae11eb4d138a5
+ 5ee22b439f502a4df61651093e5d04bd
+ 28be75bf478fb5334d09734e4b48f951
+ 3b9ed8c1fa8e106c6b7e94320180d2c6
+ 54b980ab947196031767f8025ff010a7
+ 250f67a8d93dc7f63c6ab6b660ce0251
+ 0bf2ba6941659908b652893e815fb6fa
+ 2c72d8ef3a904060d42c1f9eff2ae644
+ 19c27dca97ecf0c5b010ce43d52f8c31
+ 834b31f334f94a0d518094863818baea
+ b173bb6c9127f71a4a9af53d2ade3909
+ ec0ed6288e4ecd27cc3311310641be7c
+ b70f9b6ffad9c7357a62b08341405956
+ eba3993fa674e27ef91629ba13b6274a
+ c0dbcb3ded211049f3ab6e9ece59d254
+ 47edf778e58139a53a2504b0b6fb533e
+ a8a7be6eaf359931824c34fbf6cd37be
+ fab71e08fc1258d1052799a61aad78ee
+ 35bbaa678cd9be1bdcb9fd33f0858e18
+ 4801e0e4e3e83d1b27306c2ab83baf84
+ ae69f658ca1bb27d9da9b4e7ae629904
+ f2e0eeffe412bef26835f0187ee5fb43
+ 04fddda0c1e8a21d8f75c37acd5653d3
+ 8c3e86279b87b44d22fb02b94308e0a1
+ c9e92531eae8afce9d514dd9969393b2
+ dcc52fe19f63d084162ba59fed448967
+ c7e29006c0b1c9bd64d2e8c599f2f1a3
+ 49b9f307c7ef9b220e63de6ad31146d3
+ 75bc074f12cc2e6e6b611245c646d2cb
+ 2ef942d35ce8531db705c55abcfcb643
+ e5d7b292e8a332046064c08d05907016
+ bfade7333c0b5a9febd89691dccb5096
+ 8f464e8c965a4fedcd5ec65c3d3625d3
+ 1d7b414daa07c4f5a38daeefc3f8fe06
+ 6437b3ded8b7cbe2c15a5cd206b49fc8
+ 2c34fdc18dac0ccbd1057c7cf48827d5
+ 88436bfd052e3067b6ac107b38dc267c
+ 253370726b0db7adede25f020c67ae7f
+ 16456c7a2af72dc04a9d3ff9e4ebe252
+ 3a1a788124391c6a7e3caec8c73eb68a
+ 7b5afa01c3a2e38822b7bd1f13c1b7ec
+ 236507596b10da999748f66083c6870b
+ 14fa6b241805e16ab6516c52d0f411fa
+ d563ed69b57a063d77936ed323372a12
+ 07f7524e568f6cdbb71091010fb5383e
+ 998d3880177096c61eb1a23e16fa2ba9
+ d6dcc4c7d1765a3121301a7b2d68760b
+ f90fa28c9962b8e35dab7f54fc5fa641
+ e6c7c07805f811f6df136e4842cf7d4a
+ e0335c8c6930cbde32bbf68c4c05a75f
+ c4548cc51fdbd977523eea8d69a80d71
+ 20790e59ffb6396a8a6db4878b4e3e3f
+ e2190159b50e2ef57028ec77360be8fd
+ 0325ce6af2a0a664fbbe8ec64b90774a
+ 61e259f753b053ecd2e3f9ce4f195cde
+ e748a7d56b7245a2ca7b7998fe7c9b36
+ bde4dcbb616a77968455f11f042d6d9e
+ 5912638f53534af82568a6be645b37a5
+ d00a0eef9723908344b2796e5260beac
+ 9187d5003aafc09a22faef40dd64c889
+ 361d1869dfa590fd4a067e1b34c88130
+ ccddf3feee45c4152be436091e3280d2
+ df5bf218e1a19c6258999b0eab850674
+ ec5ebad5eee1d93b691e7cefcd5194d5
+ 534ba2ef91d9556219f5a08a07903b3f
+ 165707a987c13c4c673b28044d1c7664
+ 7643c0d9ee4ea5a9ca661e783c3cd109
+ 5e407171f4f71e40c14bcfba4fdd990a
+ 31b1109e242df74a20a895673a59f17e
+ 205d889af060ccf5850ad21ad777fe8e
+ 25db82f189cda7f4383085a35e95e4a9
+ 7249da56d87b7f54757d785437207c54
+ 69784ce2c5a4eaecf0cdb56af6a8952c
+ d3118436b794182b0acbe17a89a5b6b0
+ cb7d0cb848cffe629fa3a6a55ffb9e88
+ 22725f89ca7a868545eb6b5688137188
+ 786d631d06ada4bb04ad456680cb6bd0
+ 215e5bd9aa06cef9decf71bd1f4837de
+ 157a0e7ac0c46bd8c1d48fd75b48456b
+ 45eeee629c74debf39fbb251c578af9f
+ ac00c2a966398037df7c580eb3f8a00b
+ 46c4fdd3b28dc259de09199805e15f7c
+ 822677fcad0891ddf9a292d418f92feb
+ b18d5ef999caa77af84a47a5f4a3ee4b
+ 1065e627fd6a05453e0fb914e33118d3
+ 4ca9b1e25d0182561db7a7c8f3b1c7dd
+ a03ce4342298629955c91095e6925e46
+ 7c8567f4520fdbc986e64f62d7c154c6
+ d3bd0444141f0ec5a872d6d7190e1171
+ c476c80b2e3b9fade59c415201c284d7
+ 3548c1f099f25a43fb4e14834c75d71a
+ ad5038c8c2448ecee85e535405374acc
+ ec5b2871276e064a73702de4916d7b78
+ 4906af996757285cbb4aeecc25c94387
+ 87342df987f16727069c72218c84e2c9
+ a1ce2c5f2bb46e340aebb265ebefacfc
+ 1a99450e3474f8d2cc14a5617985cfc1
+ c70aba028e347bd7be0c540367531026
+ 3afd2ab8cc006feb487fd77ff73bf03b
+ 84e962d4e9e0c24f6efb6b045423f129
+ e0525c54aa0663c34524008f3a2f06ba
+ 6dea62cc763523241fa5fd9390047327
+ 327fbe08f8f2d0e89e1083bb44973ad5
+ c05ac887da1f635111b0011376bccd21
+ 7eeb2dc3bc569f735134502b9ed72086
+ dfbbb91ee58a102f8568bf10110d447c
+ 5c68771385bb14a56b7865b1626dac4b
+ 8c60c17bf147a85759e4873fdc0256f6
+ 564e160c9225caf60dc187ea2ae2d400
+ 1c12015f714740421221c79c10e56cda
+ 4b98d7b721d15e545e78f663714ef95a
+ 021758aafa31c53e6ea9ab928acf55e3
+ a0bf9b49d1f991e6ac876ddea607ac91
+ b632eef4840c34ce7777a8b73883b686
+ 4ab51d8c9a800187e9b12fbe393ef861
+ 577e0be5ea12403ddd202a7d2e080ac6
+ d24867636bc7106b01af7829306cbc3a
+ 636f83da0d5782f038d194e796a892b1
+ b07519b4833e3fcc62188098bd7b3f9f
+ 797f1a716efa8208ab2a034cc2f247d9
+ 57f17fcad307a3e907c6284b9ff894d1
+ a960cf635605d78fe922bb989fcbf105
+ c93cc5914d4348475a55c8410b1dd68b
+ 071983957fae7b23c8566de5de0c79f5
+ 0bcb172430640355935e85451507f0ce
+ d1baf985be8e87efa7add72cec928e08
+ 9a4a6ba917991fa540f4b68b66bd12f2
+ 98ff9f15998747077e83cefaaed6e9ed
+ 08a334c80dbecedae9ad779163391f7a
+ ad751ba7b502de9a29f6390e1c05b829
+ d707263fd876d1a5d6b8052fe5661049
+ 143f6ccd6ba0868803c5d3f00b94d205
+ fdbf1fb0e52b492eaa2dac0c14f891d4
+ ca89d16caa89d7aa3355bb4e94cd8379
+ c0be5e471cd95806e0b6d546b3816043
+ d3b3808fac478b385afd3e3a74a50d38
+ efa321fa284c43510ca8c10c8a846305
+ ed11ab5a17c182054bba8adbfc2df6f1
+ 7c519a48e51006bafac393eaf639ca16
+ 3b250ef7df36acd69fc99ee7b1954e9d
+ 489c445f0c7393ccabbe4ed82cfe0173
+ 54ff2f69c60c9c50de37bd436b9e4d04
+ fc49096b00425741f9f9361f5a5c89d3
+ 864ac5d3c8334689e8e317bdadd81be8
+ 72f1a8ef614ae5745375e29ec1a0e2e2
+ 8787ac2a2a1786ac320c66d5791bd00c
+ faef79198ee1b405f5eb918939c63fb4
+ 59488827e29909959e573389ab21f4a0
+ 2065a3bc0ecfa0032a298039dd0f21e1
+ 951358ba8d655732fc940e1354b1c973
+ 5d79dd788180ed99cc2238297a780267
+ a5bf4db254b72f03ffdd87b1e1876b95
+ 6c118194b207bf273fc6d99c8631d598
+ fb39903cae7e90b617ed8cd9fb3c27d7
+ 3fe5376340fe7c01218c2a15a5fa4d43
+ 0f877e005d07c9bc69d162a7b0276f77
+ 0db00f062adc72f329a82a5e6bb17049
+ 9fdb50161ec4e8ceb8fb2a0320721db0
+ d210a1f72cd1c6ad9fa8ffb5c8506680
+ 8d7c88500b30eff0e05409de770839f6
+ 28eb52aae627aa8e9a549ebb577c2bd9
+ 0288769ca026b3790fd2048aa97fc32b
+ 5d14d528ea90ceb4518e54ed54985ca4
+ 7804bf17337fece08b14f4be3456d745
+ 46386d894aa471ea164cab9b3261d92e
+ 5ed63c61c106545ca8247f0fcb2b0128
+ 4305dfe546edd070dbfef2cf4db93e50
+ 8d8802db86557ae42fc48fdc914b4a0d
+ 9483b4880baeffc61c34a5d48322cfdf
+ cae7ac726dcf55724750d033517ad00c
+ e13d19a039418df8a23a05283336b598
+ b84e7d131d9e51ecf00faca8398de34e
+ b8422f18f149fea650c07ff3e95d33c4
+ 774936c56906003d8cb1ef7552a0b277
+ 23a77eacb1f1a6d0e5b9ad3327be8e16
+ 8faea2b438be2062bc182e74a6117e70
+ 3e98d9aa2a0d771000a241b065d03a1e
+ 2630d557879928a7b68b8a287fadec4f
+ cf8ccd091dc034657e08ffcaba224d72
+ 0b2929ea5a8a84966e4c4a2cb322f8a9
+ d5378914c9400178ed00b79c4a53adf4
+ fc5edfb66e6e61e1a3277a0d92914a16
+ af328585f360216c6d3514d2efa1a710
+ f68b442fa035ed78f57bb3949a4d159d
+ bbcbee5cc734b4f1f17e04e70674f192
+ f079d5270f1f19b53ef2cfed9de81d6b
+ 7d1aa9f8e3ed8800b45ed4a3a110df60
+ bf6d0c26891be05378f214def3fb68c9
+ 37977a8e91dff2af6c33d5264514a940
+ 1ed00d47d8b2173f7fe12be2433359e9
+ c1e455b69405f84d397ce89ecf41598c
+ 34ec2d2c15326fca242f48edb6741e8a
+ 9aee351f449c05697b8005aeea6679cd
+ eef281ca22a32cea717a769af48ff7e3
+ a46a9796b86c5c5ffd71449d42a46d89
+ 0ab3696005c0132efdc24d97e6c78af5
+ 50a3e0c475e8f4ecc69c9e8da9ba494a
+ 0eaddf1adaa5606287400772bb205ee5
+ 216e812502993de510a88db1b12884bb
+ 83020dc5372097e1e9c323ad2ee0d811
+ e4c6161e086f471d1cd0e5dad9657145
+ c620f78edf98dc4edabaf82acdd472fb
+ 7251f17fc354c824882ac8529aee9183
+ 6a80b89efd006d234f5cfa9e486317ca
+ 6433457937ec50b6c1efdf55b0776d29
+ b8c36f7067ecea41d62b7e57d7c2c12f
+ eaff83380cb96423afa0ba51da333fee
+ df3969f7e6095893e99714d55409f266
+ d85edda8a6677f319eed020f20ce41a0
+ 3337d42a1c1fce7c26c951a6c8b12834
+ 3375e3bf99969188e0aaa485749dd92f
+ e14ce8882b3b4cda3c7e7fbc08702407
+ f057c9c2ae0ec540e553adc118d9afd5
+ 1aef7303c3a128d01e432d292fb1510a
+ 29979e4028a7f02869397c73b571fa3f
+ 84a09a9cb70cc52c36cec79d3d533111
+ 3594f1c842e75c87c0a79a745ad2b26f
+ 7b673cb57790b0b0734e399aa0a835f3
+ ff711f45bff3cf6b97cdb74a5a1b53f9
+ cdc0547f04c5076d20b178ab4d01465d
+ 9b96e23c28a269a4786fa7c33fffcfcd
+ ab07b8cd88e7aa3cb670d9301d535fb4
+ 2ecf9b85b0d8a7431a2cb1237f2899af
+ 67e1cf09819e01e1cbb2edab0cd1ae2f
+ c6e07e7b194ee18f8821d144dccc49d0
+ 550e6afe464fdc7ed36903ab42a2bfda
+ ee5faf95b909742e3f30d567d09b928a
+ 61e23b30970e8aef268fd27cc1a76bae
+ 51e95eba7a04cc574db34127f41f48ad
+ 0f60f3cb522de070b533c0b0060275e3
+ 00d767b7f767c4aa3fa465dc24b84f2c
+ fd8ad4a61038d225ca4dc038201c8d09
+ 4ea1b9443338a351d9bc43fa73059eb3
+ c2c173a5647046441dc3ad6f71fe1a37
+ e90095b6d1799e5d749e1953417477b0
+ 70a2465efbed1a5267a9aa4ec2fd10b6
+ 09039690fbcf9ea57e8758031bce78b8
+ adf94c539753e35de5e8e300a527e7ec
+ 9c04e3b6e7e56f86f32400b25895c90a
+ d3e03ca49226548f6808a70081cd75d9
+ 9bb561da5390f2d3418c4079311549f8
+ 9e7e4e6539ac904756a7557de633c817
+ 9df1b9b98c8ac5763c3854ee0743ef60
+ 0bbb4f698fac7982b5944e81de5b8490
+ 3de5d692e00a390291a4fd85e6080cee
+ 16b5ac1dc70348f4f037f7c3a87e003a
+ f3ecbb184ad9e8f0802e66748e3cbaa7
+ 3d2864242278a7c12f5a741fa4a2bdd6
+ 5302ddb14dc2f466ff960082e4281593
+ 22115fdae1f8022cbb1f58df88cc724f
+ ce517512f87bcf4dd7eb1bd5dda30baa
+ e2cddfe95059f19680c51089f4effb3c
+ 6b8bc66cbb5b91574d352db346c260ba
+ 58bbd6c1ea29ebe4d03335b3e7b34b2d
+ a5ae1c69cebc4db7822752ac827af893
+ 4c9eff227b72844626bb97adcfe1dd7a
+ 4407320c3d81c136759f5df02fb50719
+ b5d7078f15cbd37d25a2f9c388e98ea4
+ d33cda3977a886b97d607b2ff1d564e2
+ b9d6a044b40fb5ebf0b46ed087287f9f
+ a0a9d4382c98965004011815efcc28ec
+ d159d68ad96932a35fdea0efe3ceb317
+ cc537a55e7464b066a6fda767f872ea0
+ 2c12ff8c89686236273ba562e4ec6fcf
+ 0e166190814dbc08dd30654a84db902f
+ cbfbda00c09bb4ef56a3a54139fb2306
+ 18426675d6661866ef870e26daa0f275
+ e5c680ea4b8aa5cc048d1f4c93ce3a28
+ ed6d2b675336cb20a00ff06ad6cf40ed
+ 779b93e3bcb71227bfb374f58c96d69a
+ 874008d82295316ebd6394dafc393922
+ de1719dae26a1a309cc4206535c88a55
+ da7c4a0f7cfa29a9d0f21bb9dc4d8448
+ fcb5d807d37002769fd786525fc5f365
+ e2ec2dacea3287f0d203b3df87a3cb09
+ 562fcb8b45bb6ac955ff94c4b72f3b18
+ f0df78648b5a339a0bccbeb35d8e5bd9
+ cf58d1d77e957790f18e2bf6018e3208
+ 0bca6bd34efec9760518c9e65416dbd9
+ ec0e7d9f242892fc45b66e862298fbab
+ 0d1855b762d1c505072d06fab0fa99cc
+ 518d8830e6fa0aef5977e116606874df
+ ef1756ed555798daaa3fe8078a19e892
+ b94db166ba6a99c63c79f1f62af6a319
+ 601cc304ca52a8883ecfc3647c069b83
+ 2169d91bce1145995b514ca73d70edc3
+ 4a3887e5217279251946241447b7aac9
+ 5dde21faf82ac2c044b0013e7577877a
+ 8ed5320f8e874058d96eaac621566a09
+ 94d762ea58c9a3a9029645273d27af53
+ 8215b3cf672fab49838d87caab2a91c9
+ b80e8e80306f73143a00d6af61037d19
+ 6e593d585892835bf6b87ece1ef5d439
+ 780beb20cb674f5b885cc368ebaff8d4
+ ba43bca4962a09d6dcb771baef7e3df9 )
diff --git a/bin/tests/system/unknown/ns1/named.conf.in b/bin/tests/system/unknown/ns1/named.conf.in
new file mode 100644
index 0000000..a4b98db
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/named.conf.in
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+};
+
+view "in" {
+ zone "example." {
+ type primary;
+ file "example-in.db";
+ };
+
+ zone "broken1." {
+ type primary;
+ file "broken1.db";
+ };
+
+ zone "broken2." {
+ type primary;
+ file "broken2.db";
+ };
+
+ zone "broken3." {
+ type primary;
+ file "broken3.db";
+ };
+
+ zone "broken4." {
+ type primary;
+ file "broken4.db";
+ };
+
+ zone "broken5." {
+ type primary;
+ file "broken5.db";
+ };
+};
+
+view "class10" class10 {
+ zone "." class10 {
+ type hint;
+ file "class10.hints";
+ };
+
+ zone "example." class10 {
+ type primary;
+ file "example-class10.db";
+ };
+};
diff --git a/bin/tests/system/unknown/ns2/named.conf.in b/bin/tests/system/unknown/ns2/named.conf.in
new file mode 100644
index 0000000..af81836
--- /dev/null
+++ b/bin/tests/system/unknown/ns2/named.conf.in
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+};
+
+view "in" {
+ zone "example." {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "example-in.bk";
+ };
+};
diff --git a/bin/tests/system/unknown/ns3/named.conf.in b/bin/tests/system/unknown/ns3/named.conf.in
new file mode 100644
index 0000000..ae20a68
--- /dev/null
+++ b/bin/tests/system/unknown/ns3/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+};
+
+view "in" {
+ zone "example." {
+ type secondary;
+ primaries { 10.53.0.1; };
+ inline-signing yes;
+ auto-dnssec maintain;
+ file "example-in.bk";
+ };
+};
diff --git a/bin/tests/system/unknown/ns3/sign.sh b/bin/tests/system/unknown/ns3/sign.sh
new file mode 100644
index 0000000..7a8b097
--- /dev/null
+++ b/bin/tests/system/unknown/ns3/sign.sh
@@ -0,0 +1,20 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+zone=example
+rm -f K${zone}.+*+*.key
+rm -f K${zone}.+*+*.private
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone)
+keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone)
diff --git a/bin/tests/system/unknown/setup.sh b/bin/tests/system/unknown/setup.sh
new file mode 100644
index 0000000..0c043bf
--- /dev/null
+++ b/bin/tests/system/unknown/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+
+(cd ns3; $SHELL -e sign.sh)
diff --git a/bin/tests/system/unknown/tests.sh b/bin/tests/system/unknown/tests.sh
new file mode 100644
index 0000000..f52b50e
--- /dev/null
+++ b/bin/tests/system/unknown/tests.sh
@@ -0,0 +1,235 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+DIGOPTS="-p ${PORT}"
+
+dig_cmd() {
+ # shellcheck disable=SC2086
+ "$DIG" $DIGOPTS "$@" | grep -v '^;'
+}
+
+n=$((n+1))
+echo_i "querying for various representations of an IN A record ($n)"
+for i in 1 2 3 4 5 6 7 8 9 10 11 12
+do
+ ret=0
+ dig_cmd +short @10.53.0.1 a$i.example a in > dig.out.$i.test$n
+ echo 10.0.0.1 | diff - dig.out.$i.test$n || ret=1
+ if [ $ret != 0 ]
+ then
+ echo_i "#$i failed"
+ fi
+ status=$((status + ret))
+done
+
+n=$((n+1))
+echo_i "querying for various representations of an IN TXT record ($n)"
+for i in 1 2 3 4 5 6 7
+do
+ ret=0
+ dig_cmd +short @10.53.0.1 txt$i.example txt in > dig.out.$i.test$n
+ echo '"hello"' | diff - dig.out.$i.test$n || ret=1
+ if [ $ret != 0 ]
+ then
+ echo_i "#$i failed"
+ fi
+ status=$((status + ret))
+done
+
+n=$((n+1))
+echo_i "querying for various representations of an IN TYPE123 record ($n)"
+for i in 1 2 3
+do
+ ret=0
+ dig_cmd +short @10.53.0.1 unk$i.example type123 in > dig.out.$i.test$n
+ echo '\# 1 00' | diff - dig.out.$i.test$n || ret=1
+ if [ $ret != 0 ]
+ then
+ echo_i "#$i failed"
+ fi
+ status=$((status + ret))
+done
+
+n=$((n+1))
+echo_i "querying for NULL record ($n)"
+ret=0
+dig_cmd +short @10.53.0.1 null.example null in > dig.out.test$n
+echo '\# 1 00' | diff - dig.out.test$n || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "querying for empty NULL record ($n)"
+ret=0
+dig_cmd +short @10.53.0.1 empty.example null in > dig.out.test$n
+echo '\# 0' | diff - dig.out.test$n || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "querying for various representations of a CLASS10 TYPE1 record ($n)"
+for i in 1 2
+do
+ ret=0
+ dig_cmd +short @10.53.0.1 a$i.example a class10 > dig.out.$i.test$n
+ echo '\# 4 0A000001' | diff - dig.out.$i.test$n || ret=1
+ if [ $ret != 0 ]
+ then
+ echo_i "#$i failed"
+ fi
+ status=$((status + ret))
+done
+
+n=$((n+1))
+echo_i "querying for various representations of a CLASS10 TXT record ($n)"
+for i in 1 2 3 4
+do
+ ret=0
+ dig_cmd +short @10.53.0.1 txt$i.example txt class10 > dig.out.$i.test$n
+ echo '"hello"' | diff - dig.out.$i.test$n || ret=1
+ if [ $ret != 0 ]
+ then
+ echo_i "#$i failed"
+ fi
+ status=$((status + ret))
+done
+
+n=$((n+1))
+echo_i "querying for various representations of a CLASS10 TYPE123 record ($n)"
+for i in 1 2
+do
+ ret=0
+ dig_cmd +short @10.53.0.1 unk$i.example type123 class10 > dig.out.$i.test$n
+ echo '\# 1 00' | diff - dig.out.$i.test$n || ret=1
+ if [ $ret != 0 ]
+ then
+ echo_i "#$i failed"
+ fi
+ status=$((status + ret))
+done
+
+n=$((n+1))
+echo_i "querying for SOAs of zone that should have failed to load ($n)"
+for i in 1 2 3 4
+do
+ ret=0
+ $DIG $DIGOPTS @10.53.0.1 broken$i. soa in > dig.out.$i.test$n || ret=1
+ grep "SERVFAIL" dig.out.$i.test$n > /dev/null || ret=1
+ if [ $ret != 0 ]
+ then
+ echo_i "#$i failed"
+ fi
+ status=$((status + ret))
+done
+
+n=$((n+1))
+echo_i "checking large unknown record loading on primary ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ ret=0
+ dig_cmd @10.53.0.1 +tcp +short large.example TYPE45234 > dig.out.$i.test$n
+ diff -s large.out dig.out.$i.test$n > /dev/null || { ret=1 ; echo_i "diff failed"; }
+ [ "$ret" -eq 0 ] && break
+ sleep 1
+done
+[ $ret = 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "checking large unknown record loading on secondary ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ ret=0
+ dig_cmd @10.53.0.2 +tcp +short large.example TYPE45234 > dig.out.$i.test$n
+ diff -s large.out dig.out.$i.test$n > /dev/null || { ret=1 ; echo_i "diff failed"; }
+ [ "$ret" -eq 0 ] && break
+ sleep 1
+done
+[ $ret = 0 ] || echo_i "failed"
+status=$((status + ret))
+
+echo_i "stop and restart secondary"
+stop_server ns2
+start_server --noclean --restart --port ${PORT} ns2
+
+# server may be answering queries before zones are loaded,
+# so retry a few times if this query fails
+n=$((n+1))
+echo_i "checking large unknown record loading on secondary ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ ret=0
+ dig_cmd @10.53.0.2 +tcp +short large.example TYPE45234 > dig.out.$i.test$n
+ diff -s large.out dig.out.$i.test$n > /dev/null || { ret=1 ; echo_i "diff failed"; }
+ [ "$ret" -eq 0 ] && break
+ sleep 1
+done
+[ $ret = 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "checking large unknown record loading on inline secondary ($n)"
+ret=0
+dig_cmd @10.53.0.3 +tcp +short large.example TYPE45234 > dig.out.test$n
+diff large.out dig.out.test$n > /dev/null || { ret=1 ; echo_i "diff failed"; }
+[ $ret = 0 ] || echo_i "failed"
+status=$((status + ret))
+
+echo_i "stop and restart inline secondary"
+stop_server ns3
+start_server --noclean --restart --port ${PORT} ns3
+
+# server may be answering queries before zones are loaded,
+# so retry a few times if this query fails
+n=$((n+1))
+echo_i "checking large unknown record loading on inline secondary ($n)"
+for try in 0 1 2 3 4 5 6 7 8 9; do
+ ret=0
+ dig_cmd @10.53.0.3 +tcp +short large.example TYPE45234 > dig.out.$i.test$n
+ diff large.out dig.out.$i.test$n > /dev/null || { ret=1 ; echo_i "diff failed"; }
+ [ "$ret" -eq 0 ] && break
+ sleep 1
+done
+[ $ret = 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that '"'"\\#"'"' is not treated as the unknown escape sequence ($n)"
+ret=0
+dig_cmd @10.53.0.1 +tcp +short txt8.example txt > dig.out.test$n
+echo '"#" "2" "0145"' | diff - dig.out.test$n || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that 'TXT \# text' is not treated as the unknown escape sequence ($n)"
+ret=0
+dig_cmd @10.53.0.1 +tcp +short txt9.example txt > dig.out.test$n
+echo '"#" "text"' | diff - dig.out.test$n || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "check that 'TYPE353 \# cat' produces 'not a valid number' ($n)"
+ret=0
+$CHECKZONE nan.bad zones/nan.bad > check.out 2>&1 && ret=1
+grep "not a valid number" check.out > /dev/null || ret=1
+[ $ret = 0 ] || echo_i "failed"
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/unknown/tests_sh_unknown.py b/bin/tests/system/unknown/tests_sh_unknown.py
new file mode 100644
index 0000000..fe1f451
--- /dev/null
+++ b/bin/tests/system/unknown/tests_sh_unknown.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_unknown(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/unknown/zones/nan.bad b/bin/tests/system/unknown/zones/nan.bad
new file mode 100644
index 0000000..4381f88
--- /dev/null
+++ b/bin/tests/system/unknown/zones/nan.bad
@@ -0,0 +1,12 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 IN TYPE353 \# cat 010101010101010101
diff --git a/bin/tests/system/upforwd/ans4/ans.pl b/bin/tests/system/upforwd/ans4/ans.pl
new file mode 100644
index 0000000..000be56
--- /dev/null
+++ b/bin/tests/system/upforwd/ans4/ans.pl
@@ -0,0 +1,363 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# This is the name server from hell. It provides canned
+# responses based on pattern matching the queries, and
+# can be reprogrammed on-the-fly over a TCP connection.
+#
+# The server listens for control connections on port 5301.
+# A control connection is a TCP stream of lines like
+#
+# /pattern/
+# name ttl type rdata
+# name ttl type rdata
+# ...
+# /pattern/
+# name ttl type rdata
+# name ttl type rdata
+# ...
+#
+# There can be any number of patterns, each associated
+# with any number of response RRs. Each pattern is a
+# Perl regular expression.
+#
+# Each incoming query is converted into a string of the form
+# "qname qtype" (the printable query domain name, space,
+# printable query type) and matched against each pattern.
+#
+# The first pattern matching the query is selected, and
+# the RR following the pattern line are sent in the
+# answer section of the response.
+#
+# Each new control connection causes the current set of
+# patterns and responses to be cleared before adding new
+# ones.
+#
+# The server handles UDP and TCP queries. Zone transfer
+# responses work, but must fit in a single 64 k message.
+#
+# Now you can add TSIG, just specify key/key data with:
+#
+# /pattern <key> <key_data>/
+# name ttl type rdata
+# name ttl type rdata
+#
+# Note that this data will still be sent with any request for
+# pattern, only this data will be signed. Currently, this is only
+# done for TCP.
+
+
+use IO::File;
+use IO::Socket;
+use Data::Dumper;
+use Net::DNS;
+use Net::DNS::Packet;
+use strict;
+
+# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early
+local $SIG{PIPE} = 'IGNORE';
+
+# Flush logged output after every line
+local $| = 1;
+
+my $server_addr = "10.53.0.4";
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!";
+
+my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $localport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+print "listening on $server_addr:$localport.\n";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";;
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+#my @answers = ();
+my @rules;
+sub handleUDP {
+ my ($buf) = @_;
+ my $packet;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+
+ # get the existing signature if any, and clear the additional section
+ my $prev_tsig;
+ while (my $rr = $packet->pop("additional")) {
+ if ($rr->type eq "TSIG") {
+ $prev_tsig = $rr;
+ }
+ }
+
+ my $r;
+ foreach $r (@rules) {
+ my $pattern = $r->{pattern};
+ my($dbtype, $key_name, $key_data) = split(/ /,$pattern);
+ print "[handleUDP] $dbtype, $key_name, $key_data \n";
+ if ("$qname $qtype" =~ /$dbtype/) {
+ my $a;
+ foreach $a (@{$r->{answer}}) {
+ $packet->push("answer", $a);
+ }
+ if(defined($key_name) && defined($key_data)) {
+ # Sign the packet
+ print " Signing the response with " .
+ "$key_name/$key_data\n";
+ my $tsig = Net::DNS::RR->
+ new("$key_name TSIG $key_data");
+
+ # These kluges are necessary because Net::DNS
+ # doesn't know how to sign responses. We
+ # clear compnames so that the TSIG key and
+ # algorithm name won't be compressed, and
+ # add one to arcount because the signing
+ # function will attempt to decrement it,
+ # which is incorrect in a response. Finally
+ # we set request_mac to the previous digest.
+ $packet->{"compnames"} = {};
+ $packet->{"header"}{"arcount"} += 1;
+ if (defined($prev_tsig)) {
+ my $rmac = pack('n H*',
+ $prev_tsig->mac_size,
+ $prev_tsig->mac);
+ $tsig->{"request_mac"} =
+ unpack("H*", $rmac);
+ }
+
+ $packet->sign_tsig($tsig);
+ }
+ last;
+ }
+ }
+ #$packet->print;
+
+ return $packet->data;
+}
+
+# namelen:
+# given a stream of data, reads a DNS-formatted name and returns its
+# total length, thus making it possible to skip past it.
+sub namelen {
+ my ($data) = @_;
+ my $len = 0;
+ my $label_len = 0;
+ do {
+ $label_len = unpack("c", $data);
+ $data = substr($data, $label_len + 1);
+ $len += $label_len + 1;
+ } while ($label_len != 0);
+ return ($len);
+}
+
+# packetlen:
+# given a stream of data, reads a DNS wire-format packet and returns
+# its total length, making it possible to skip past it.
+sub packetlen {
+ my ($data) = @_;
+ my $q;
+ my $rr;
+
+ my ($header, $offset) = Net::DNS::Header->parse(\$data);
+ for (1 .. $header->qdcount) {
+ ($q, $offset) = Net::DNS::Question->parse(\$data, $offset);
+ }
+ for (1 .. $header->ancount) {
+ ($rr, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ for (1 .. $header->nscount) {
+ ($rr, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ for (1 .. $header->arcount) {
+ ($rr, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ return $offset;
+}
+
+# sign_tcp_continuation:
+# This is a hack to correct the problem that Net::DNS has no idea how
+# to sign multiple-message TCP responses. Several data that are included
+# in the digest when signing a query or the first message of a response are
+# omitted when signing subsequent messages in a TCP stream.
+#
+# Net::DNS::Packet->sign_tsig() has the ability to use a custom signing
+# function (specified by calling Packet->sign_func()). We use this
+# function as the signing function for TCP continuations, and it removes
+# the unwanted data from the digest before calling the default sign_hmac
+# function.
+sub sign_tcp_continuation {
+ my ($key, $data) = @_;
+
+ # copy out first two bytes: size of the previous MAC
+ my $rmacsize = unpack("n", $data);
+ $data = substr($data, 2);
+
+ # copy out previous MAC
+ my $rmac = substr($data, 0, $rmacsize);
+ $data = substr($data, $rmacsize);
+
+ # try parsing out the packet information
+ my $plen = packetlen($data);
+ my $pdata = substr($data, 0, $plen);
+ $data = substr($data, $plen);
+
+ # remove the keyname, ttl, class, and algorithm name
+ $data = substr($data, namelen($data));
+ $data = substr($data, 6);
+ $data = substr($data, namelen($data));
+
+ # preserve the TSIG data
+ my $tdata = substr($data, 0, 8);
+
+ # prepare a new digest and sign with it
+ $data = pack("n", $rmacsize) . $rmac . $pdata . $tdata;
+ return Net::DNS::RR::TSIG::sign_hmac($key, $data);
+}
+
+sub handleTCP {
+ my ($buf) = @_;
+ my $packet;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+
+ # get the existing signature if any, and clear the additional section
+ my $prev_tsig;
+ my $signer;
+ while (my $rr = $packet->pop("additional")) {
+ if ($rr->type eq "TSIG") {
+ $prev_tsig = $rr;
+ }
+ }
+
+ my @results = ();
+ my $count_these = 0;
+
+ my $r;
+ foreach $r (@rules) {
+ my $pattern = $r->{pattern};
+ my($dbtype, $key_name, $key_data) = split(/ /,$pattern);
+ print "[handleTCP] $dbtype, $key_name, $key_data \n";
+ if ("$qname $qtype" =~ /$dbtype/) {
+ $count_these++;
+ my $a;
+ foreach $a (@{$r->{answer}}) {
+ $packet->push("answer", $a);
+ }
+ if(defined($key_name) && defined($key_data)) {
+ # sign the packet
+ print " Signing the data with " .
+ "$key_name/$key_data\n";
+
+ my $tsig = Net::DNS::RR->
+ new("$key_name TSIG $key_data");
+
+ # These kluges are necessary because Net::DNS
+ # doesn't know how to sign responses. We
+ # clear compnames so that the TSIG key and
+ # algorithm name won't be compressed, and
+ # add one to arcount because the signing
+ # function will attempt to decrement it,
+ # which is incorrect in a response. Finally
+ # we set request_mac to the previous digest.
+ $packet->{"compnames"} = {};
+ $packet->{"header"}{"arcount"} += 1;
+ if (defined($prev_tsig)) {
+ my $rmac = pack('n H*',
+ $prev_tsig->mac_size,
+ $prev_tsig->mac);
+ $tsig->{"request_mac"} =
+ unpack("H*", $rmac);
+ }
+
+ $tsig->sign_func($signer) if defined($signer);
+ $packet->sign_tsig($tsig);
+ $signer = \&sign_tcp_continuation;
+
+ my $copy =
+ Net::DNS::Packet->new(\($packet->data));
+ $prev_tsig = $copy->pop("additional");
+ }
+ #$packet->print;
+ push(@results,$packet->data);
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ }
+ }
+ print " A total of $count_these patterns matched\n";
+ return \@results;
+}
+
+# Main
+my $rin;
+my $rout;
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($tcpsock), 1) = 1;
+ vec($rin, fileno($udpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($udpsock), 1)) {
+ printf "UDP request\n";
+ my $buf;
+ $udpsock->recv($buf, 512);
+ } elsif (vec($rout, fileno($tcpsock), 1)) {
+ my $conn = $tcpsock->accept;
+ my $buf;
+ for (;;) {
+ my $lenbuf;
+ my $n = $conn->sysread($lenbuf, 2);
+ last unless $n == 2;
+ my $len = unpack("n", $lenbuf);
+ $n = $conn->sysread($buf, $len);
+ }
+ sleep(1);
+ }
+}
diff --git a/bin/tests/system/upforwd/clean.sh b/bin/tests/system/upforwd/clean.sh
new file mode 100644
index 0000000..2641c43
--- /dev/null
+++ b/bin/tests/system/upforwd/clean.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f dig.out.ns1* dig.out.ns2 dig.out.ns1 dig.out.ns3 dig.out.ns1.after
+rm -f ns1/*.jnl ns2/*.jnl ns3/*.jnl ns1/example.db ns2/*.bk ns3/*.bk
+rm -f ns3/noprimary1.db
+rm -f ns3/dnstap.out*
+rm -f ns3/dnstap.conf
+rm -f dnstap.out*
+rm -f dnstapread.out*
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.conf
+rm -f */ans.run
+rm -f Ksig0.example2.*
+rm -f keyname keyname.err
+rm -f ns*/named.lock
+rm -f ns1/example2.db
+rm -f ns*/managed-keys.bind*
+rm -f nsupdate.out.*
+rm -f ns*/named.run.prev
diff --git a/bin/tests/system/upforwd/knowngood.after1 b/bin/tests/system/upforwd/knowngood.after1
new file mode 100644
index 0000000..7fc424c
--- /dev/null
+++ b/bin/tests/system/upforwd/knowngood.after1
@@ -0,0 +1,10 @@
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 2 3600 1200 604800 7200
+example. 3600 IN NS ns2.example.
+example. 3600 IN NS ns3.example.
+ns1.example. 3600 IN A 10.53.0.1
+ns2.example. 3600 IN A 10.53.0.2
+ns3.example. 3600 IN A 10.53.0.3
+updated.example. 600 IN TXT "Foo"
+updated.example. 600 IN A 10.10.10.1
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 2 3600 1200 604800 7200
+
diff --git a/bin/tests/system/upforwd/knowngood.after2 b/bin/tests/system/upforwd/knowngood.after2
new file mode 100644
index 0000000..eab7a2c
--- /dev/null
+++ b/bin/tests/system/upforwd/knowngood.after2
@@ -0,0 +1,11 @@
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 3 3600 1200 604800 7200
+example. 3600 IN NS ns2.example.
+example. 3600 IN NS ns3.example.
+ns1.example. 3600 IN A 10.53.0.1
+ns2.example. 3600 IN A 10.53.0.2
+ns3.example. 3600 IN A 10.53.0.3
+unsigned.example. 600 IN TXT "Foo"
+unsigned.example. 600 IN A 10.10.10.1
+updated.example. 600 IN TXT "Foo"
+updated.example. 600 IN A 10.10.10.1
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 3 3600 1200 604800 7200
diff --git a/bin/tests/system/upforwd/knowngood.before b/bin/tests/system/upforwd/knowngood.before
new file mode 100644
index 0000000..4bde819
--- /dev/null
+++ b/bin/tests/system/upforwd/knowngood.before
@@ -0,0 +1,8 @@
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 1 3600 1200 604800 7200
+example. 3600 IN NS ns2.example.
+example. 3600 IN NS ns3.example.
+ns1.example. 3600 IN A 10.53.0.1
+ns2.example. 3600 IN A 10.53.0.2
+ns3.example. 3600 IN A 10.53.0.3
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 1 3600 1200 604800 7200
+
diff --git a/bin/tests/system/upforwd/knowngood.ns2.before b/bin/tests/system/upforwd/knowngood.ns2.before
new file mode 100644
index 0000000..bb3c355
--- /dev/null
+++ b/bin/tests/system/upforwd/knowngood.ns2.before
@@ -0,0 +1,6 @@
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 1 3600 1200 604800 7200
+example. 3600 IN NS ns2.example.
+ns1.example. 3600 IN A 10.53.0.1
+ns2.example. 3600 IN A 10.53.0.2
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 1 3600 1200 604800 7200
+
diff --git a/bin/tests/system/upforwd/ns1/example1.db b/bin/tests/system/upforwd/ns1/example1.db
new file mode 100644
index 0000000..04c47f2
--- /dev/null
+++ b/bin/tests/system/upforwd/ns1/example1.db
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 SOA n1.example. hostmaster.ns1.example. (
+ 1 3600 1200 604800 7200 )
+ NS ns2.example.
+ NS ns3.example.
+ns1 A 10.53.0.1
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/upforwd/ns1/named.conf.in b/bin/tests/system/upforwd/ns1/named.conf.in
new file mode 100644
index 0000000..822621e
--- /dev/null
+++ b/bin/tests/system/upforwd/ns1/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+key "update.example." {
+ algorithm "hmac-md5";
+ secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
+};
+
+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 yes;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-update { key update.example.; 10.53.0.3; };
+};
+
+zone "example2" {
+ type primary;
+ file "example2.db";
+ allow-update { key sig0.example2.; };
+};
diff --git a/bin/tests/system/upforwd/ns2/named.conf.in b/bin/tests/system/upforwd/ns2/named.conf.in
new file mode 100644
index 0000000..df4121b
--- /dev/null
+++ b/bin/tests/system/upforwd/ns2/named.conf.in
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "example" {
+ type secondary;
+ file "example.bk";
+ primaries { 10.53.0.1; };
+};
+
+zone "example2" {
+ type secondary;
+ file "example2.bk";
+ primaries { 10.53.0.1; };
+};
diff --git a/bin/tests/system/upforwd/ns3/named1.conf.in b/bin/tests/system/upforwd/ns3/named1.conf.in
new file mode 100644
index 0000000..b142537
--- /dev/null
+++ b/bin/tests/system/upforwd/ns3/named1.conf.in
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ include "dnstap.conf";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type secondary;
+ file "example.bk";
+ allow-update-forwarding { 10.53.0.1; };
+ primaries { 10.53.0.1; };
+};
+
+zone "example2" {
+ type secondary;
+ file "example2.bk";
+ allow-update-forwarding { 10.53.0.1; };
+ primaries { 10.53.0.1; };
+};
+
+zone "example3" {
+ type secondary;
+ file "example3.bk";
+ allow-update-forwarding { 10.53.0.1; };
+ primaries { 10.53.0.1; };
+};
+
+zone "noprimary" {
+ type secondary;
+ file "noprimary1.db";
+ allow-update-forwarding { any; };
+ masterfile-format text;
+ primaries { 10.53.0.4; };
+};
diff --git a/bin/tests/system/upforwd/ns3/named2.conf.in b/bin/tests/system/upforwd/ns3/named2.conf.in
new file mode 100644
index 0000000..1fe3e04
--- /dev/null
+++ b/bin/tests/system/upforwd/ns3/named2.conf.in
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ tls-port @TLSPORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on tls ephemeral { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ update-quota 1;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type secondary;
+ file "example.bk";
+ allow-update-forwarding { any; };
+ primaries { 10.53.0.1; };
+};
diff --git a/bin/tests/system/upforwd/ns3/noprimary.db b/bin/tests/system/upforwd/ns3/noprimary.db
new file mode 100644
index 0000000..c27e154
--- /dev/null
+++ b/bin/tests/system/upforwd/ns3/noprimary.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 141235 3600 1200 86400 1200
+@ 0 NS ns4
+ns4 0 A 10.53.0.4
diff --git a/bin/tests/system/upforwd/setup.sh b/bin/tests/system/upforwd/setup.sh
new file mode 100644
index 0000000..f2719ba
--- /dev/null
+++ b/bin/tests/system/upforwd/setup.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+cp -f ns1/example1.db ns1/example.db
+cp -f ns3/noprimary.db ns3/noprimary1.db
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named1.conf.in ns3/named.conf
+
+if $FEATURETEST --enable-dnstap
+then
+ cat <<'EOF' > ns3/dnstap.conf
+ dnstap-identity "ns3";
+ dnstap-version "xxx";
+ dnstap-output file "dnstap.out";
+ dnstap { all; };
+EOF
+else
+ echo "/* DNSTAP NOT ENABLED */" >ns3/dnstap.conf
+fi
+
+
+#
+# SIG(0) required cryptographic support which may not be configured.
+#
+keyname=$($KEYGEN -q -n HOST -a ${DEFAULT_ALGORITHM} -b 1024 -T KEY sig0.example2 2>keyname.err)
+if test -n "$keyname"
+then
+ cat ns1/example1.db $keyname.key > ns1/example2.db
+ echo $keyname > keyname
+else
+ cat ns1/example1.db > ns1/example2.db
+fi
+cat_i < keyname.err
diff --git a/bin/tests/system/upforwd/tests.sh b/bin/tests/system/upforwd/tests.sh
new file mode 100644
index 0000000..9b49fbd
--- /dev/null
+++ b/bin/tests/system/upforwd/tests.sh
@@ -0,0 +1,295 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# ns1 = stealth primary
+# ns2 = secondary with update forwarding disabled; not currently used
+# ns3 = secondary with update forwarding enabled
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../common/rndc.conf"
+
+status=0
+n=1
+capture_dnstap() {
+ retry_quiet 20 test -f ns3/dnstap.out && mv ns3/dnstap.out dnstap.out.$n
+ $RNDCCMD -s 10.53.0.3 dnstap -reopen
+}
+
+uq_equals_ur() {
+ "$DNSTAPREAD" dnstap.out.$n |
+ awk '$3 == "UQ" { UQ+=1 } $3 == "UR" { UR += 1 } END { print UQ+0, UR+0 }' > dnstapread.out$n
+ read UQ UR < dnstapread.out$n
+ echo_i "UQ=$UQ UR=$UR"
+ test $UQ -eq $UR || return 1
+}
+
+echo_i "waiting for servers to be ready for testing ($n)"
+for i in 1 2 3 4 5 6 7 8 9 10
+do
+ ret=0
+ $DIG +tcp -p ${PORT} example. @10.53.0.1 soa > dig.out.ns1 || ret=1
+ grep "status: NOERROR" dig.out.ns1 > /dev/null || ret=1
+ $DIG +tcp -p ${PORT} example. @10.53.0.2 soa > dig.out.ns2 || ret=1
+ grep "status: NOERROR" dig.out.ns2 > /dev/null || ret=1
+ $DIG +tcp -p ${PORT} example. @10.53.0.3 soa > dig.out.ns3 || ret=1
+ grep "status: NOERROR" dig.out.ns3 > /dev/null || ret=1
+ test $ret = 0 && break
+ sleep 1
+done
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+echo_i "fetching primary copy of zone before update ($n)"
+ret=0
+$DIG $DIGOPTS example.\
+ @10.53.0.1 axfr > dig.out.ns1 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+echo_i "fetching secondary 1 copy of zone before update ($n)"
+$DIG $DIGOPTS example.\
+ @10.53.0.2 axfr > dig.out.ns2 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+echo_i "fetching secondary 2 copy of zone before update ($n)"
+ret=0
+$DIG $DIGOPTS example.\
+ @10.53.0.3 axfr > dig.out.ns3 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+echo_i "comparing pre-update copies to known good data ($n)"
+ret=0
+digcomp knowngood.before dig.out.ns1 || ret=1
+digcomp knowngood.before dig.out.ns2 || ret=1
+digcomp knowngood.before dig.out.ns3 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+echo_i "updating zone (signed) ($n)"
+ret=0
+$NSUPDATE -y update.example:c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K -- - <<EOF || ret=1
+local 10.53.0.1
+server 10.53.0.3 ${PORT}
+update add updated.example. 600 A 10.10.10.1
+update add updated.example. 600 TXT Foo
+send
+EOF
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+echo_i "sleeping 15 seconds for server to incorporate changes"
+sleep 15
+
+echo_i "fetching primary copy of zone after update ($n)"
+ret=0
+$DIG $DIGOPTS example.\
+ @10.53.0.1 axfr > dig.out.ns1 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+echo_i "fetching secondary 1 copy of zone after update ($n)"
+ret=0
+$DIG $DIGOPTS example.\
+ @10.53.0.2 axfr > dig.out.ns2 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+echo_i "fetching secondary 2 copy of zone after update ($n)"
+ret=0
+$DIG $DIGOPTS example.\
+ @10.53.0.3 axfr > dig.out.ns3 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+echo_i "comparing post-update copies to known good data ($n)"
+ret=0
+digcomp knowngood.after1 dig.out.ns1 || ret=1
+digcomp knowngood.after1 dig.out.ns2 || ret=1
+digcomp knowngood.after1 dig.out.ns3 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+echo_i "checking 'forwarding update for zone' is logged ($n)"
+ret=0
+grep "forwarding update for zone 'example/IN'" ns3/named.run > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+if $FEATURETEST --enable-dnstap
+then
+ echo_i "checking DNSTAP logging of UPDATE forwarded update replies ($n)"
+ ret=0
+ capture_dnstap
+ uq_equals_ur || ret=1
+ if [ $ret != 0 ] ; then echo_i "failed"; fi
+ status=$((status + ret))
+ n=$((n + 1))
+fi
+
+echo_i "updating zone (unsigned) ($n)"
+ret=0
+$NSUPDATE -- - <<EOF || ret=1
+local 10.53.0.1
+server 10.53.0.3 ${PORT}
+update add unsigned.example. 600 A 10.10.10.1
+update add unsigned.example. 600 TXT Foo
+send
+EOF
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+echo_i "sleeping 15 seconds for server to incorporate changes"
+sleep 15
+
+echo_i "fetching primary copy of zone after update ($n)"
+ret=0
+$DIG $DIGOPTS example.\
+ @10.53.0.1 axfr > dig.out.ns1 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+echo_i "fetching secondary 1 copy of zone after update ($n)"
+ret=0
+$DIG $DIGOPTS example.\
+ @10.53.0.2 axfr > dig.out.ns2 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+echo_i "fetching secondary 2 copy of zone after update ($n)"
+ret=0
+$DIG $DIGOPTS example.\
+ @10.53.0.3 axfr > dig.out.ns3 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+echo_i "comparing post-update copies to known good data ($n)"
+ret=0
+digcomp knowngood.after2 dig.out.ns1 || ret=1
+digcomp knowngood.after2 dig.out.ns2 || ret=1
+digcomp knowngood.after2 dig.out.ns3 || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+
+if $FEATURETEST --enable-dnstap
+then
+ echo_i "checking DNSTAP logging of UPDATE forwarded update replies ($n)"
+ ret=0
+ capture_dnstap
+ uq_equals_ur || ret=1
+ if [ $ret != 0 ] ; then echo_i "failed"; fi
+ status=$((status + ret))
+ n=$((n + 1))
+fi
+n=$((n + 1))
+
+if test -f keyname
+then
+ echo_i "checking update forwarding to with sig0 ($n)"
+ ret=0
+ keyname=$(cat keyname)
+ $NSUPDATE -k $keyname.private -- - <<EOF
+ local 10.53.0.1
+ server 10.53.0.3 ${PORT}
+ zone example2
+ update add unsigned.example2. 600 A 10.10.10.1
+ update add unsigned.example2. 600 TXT Foo
+ send
+EOF
+ $DIG -p ${PORT} unsigned.example2 A @10.53.0.1 > dig.out.ns1.test$n
+ grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+ if [ $ret != 0 ] ; then echo_i "failed"; fi
+ status=$((status + ret))
+ n=$((n + 1))
+
+ if $FEATURETEST --enable-dnstap
+ then
+ echo_i "checking DNSTAP logging of UPDATE forwarded update replies ($n)"
+ ret=0
+ capture_dnstap
+ uq_equals_ur || ret=1
+ if [ $ret != 0 ] ; then echo_i "failed"; fi
+ status=$((status + ret))
+ n=$((n + 1))
+ fi
+fi
+
+echo_i "attempting an update that should be rejected by ACL ($n)"
+ret=0
+{
+ $NSUPDATE -- - << EOF
+ local 10.53.0.2
+ server 10.53.0.3 ${PORT}
+ update add another.unsigned.example. 600 A 10.10.10.2
+ update add another.unsigned.example. 600 TXT Bar
+ send
+EOF
+} > nsupdate.out.$n 2>&1 && ret=1
+grep REFUSED nsupdate.out.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+echo_i "checking update forwarding to dead primary ($n)"
+count=0
+ret=0
+while [ $count -lt 5 -a $ret -eq 0 ]
+do
+(
+$NSUPDATE -- - <<EOF
+local 10.53.0.1
+server 10.53.0.3 ${PORT}
+zone noprimary
+update add unsigned.noprimary. 600 A 10.10.10.1
+update add unsigned.noprimary. 600 TXT Foo
+send
+EOF
+) > /dev/null 2>&1 &
+ $DIG -p ${PORT} +noadd +notcp +noauth noprimary. @10.53.0.3 soa > dig.out.ns3 || ret=1
+ grep "status: NOERROR" dig.out.ns3 > /dev/null || ret=1
+ count=$((count + 1))
+done
+if [ $ret != 0 ] ; then echo_i "failed"; status=$((status + ret)); fi
+n=$((n + 1))
+
+if $FEATURETEST --enable-dnstap
+then
+ echo_i "checking DNSTAP logging of UPDATE forwarded update replies ($n)"
+ ret=0
+ capture_dnstap
+ uq_equals_ur && ret=1
+ if [ $ret != 0 ] ; then echo_i "failed"; fi
+ status=$((status + ret))
+ n=$((n + 1))
+fi
+
+n=$((n + 1))
+ret=0
+echo_i "attempting updates that should exceed quota ($n)"
+# lower the update quota to 1.
+copy_setports ns3/named2.conf.in ns3/named.conf
+rndc_reconfig ns3 10.53.0.3
+nextpart ns3/named.run > /dev/null
+for loop in 1 2 3 4 5 6 7 8 9 10; do
+{
+ $NSUPDATE -- - > /dev/null 2>&1 <<END
+ local 10.53.0.1
+ server 10.53.0.3 ${PORT}
+ update add txt-$loop.unsigned.example 300 IN TXT Whatever
+ send
+END
+} &
+done
+wait_for_log 10 "too many DNS UPDATEs queued" ns3/named.run || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/upforwd/tests_sh_upforwd.py b/bin/tests/system/upforwd/tests_sh_upforwd.py
new file mode 100644
index 0000000..35bcc64
--- /dev/null
+++ b/bin/tests/system/upforwd/tests_sh_upforwd.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_upforwd(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/verify/clean.sh b/bin/tests/system/verify/clean.sh
new file mode 100644
index 0000000..767ca77
--- /dev/null
+++ b/bin/tests/system/verify/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.lock
+rm -f verify.out*
+rm -f zones/*.bad
+rm -f zones/*.good
+rm -f zones/*.out*
+rm -f zones/*.tmp
+rm -f zones/K*
+rm -f zones/dsset-*
diff --git a/bin/tests/system/verify/setup.sh b/bin/tests/system/verify/setup.sh
new file mode 100644
index 0000000..08af706
--- /dev/null
+++ b/bin/tests/system/verify/setup.sh
@@ -0,0 +1,16 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+(cd zones && $SHELL genzones.sh)
diff --git a/bin/tests/system/verify/tests.sh b/bin/tests/system/verify/tests.sh
new file mode 100644
index 0000000..d40780a
--- /dev/null
+++ b/bin/tests/system/verify/tests.sh
@@ -0,0 +1,113 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+failed () {
+ cat verify.out.$n | sed 's/^/D:/';
+ echo_i "failed";
+ status=1;
+}
+
+n=0
+status=0
+
+for file in zones/*.good
+do
+ n=$((n + 1))
+ zone=$(expr "$file" : 'zones/\(.*\).good')
+ echo_i "checking supposedly good zone: $zone ($n)"
+ ret=0
+ case $zone in
+ zsk-only.*) only=-z;;
+ ksk-only.*) only=-z;;
+ *) only=;;
+ esac
+ $VERIFY ${only} -o $zone $file > verify.out.$n 2>&1 || ret=1
+ [ $ret = 0 ] || failed
+done
+
+for file in zones/*.bad
+do
+ n=$((n + 1))
+ zone=$(expr "$file" : 'zones/\(.*\).bad')
+ echo_i "checking supposedly bad zone: $zone ($n)"
+ ret=0
+ dumpit=0
+ case $zone in
+ zsk-only.*) only=-z;;
+ ksk-only.*) only=-z;;
+ *) only=;;
+ esac
+ expect1= expect2=
+ case $zone in
+ *.dnskeyonly)
+ expect1="DNSKEY is not signed"
+ ;;
+ *.expired)
+ expect1="signature has expired"
+ expect2="No self-signed .*DNSKEY found"
+ ;;
+ *.ksk-expired)
+ expect1="signature has expired"
+ expect2="No self-signed .*DNSKEY found"
+ ;;
+ *.out-of-zone-nsec|*.below-bottom-of-zone-nsec|*.below-dname-nsec)
+ expect1="unexpected NSEC RRset at"
+ ;;
+ *.nsec.broken-chain)
+ expect1="Bad NSEC record for.*, next name mismatch"
+ ;;
+ *.bad-bitmap)
+ expect1="bit map mismatch"
+ ;;
+ *.missing-empty)
+ expect1="Missing NSEC3 record for";
+ ;;
+ unsigned)
+ expect1="Zone contains no DNSSEC keys"
+ ;;
+ *.extra-nsec3)
+ expect1="Expected and found NSEC3 chains not equal";
+ ;;
+ *)
+ dumpit=1
+ ;;
+ esac
+ $VERIFY ${only} -o $zone $file > verify.out.$n 2>&1 && ret=1
+ grep "${expect1:-.}" verify.out.$n > /dev/null || ret=1
+ grep "${expect2:-.}" verify.out.$n > /dev/null || ret=1
+ [ $ret = 0 ] || failed
+ [ $dumpit = 1 ] && cat verify.out.$n
+done
+
+n=$((n + 1))
+echo_i "checking error message when -o is not used and a SOA record not at top of zone is found ($n)"
+ret=0
+# When -o is not used, origin is set to zone file name, which should cause an error in this case
+$VERIFY zones/ksk+zsk.nsec.good > verify.out.$n 2>&1 && ret=1
+grep "not at top of zone" verify.out.$n > /dev/null || ret=1
+grep "use -o to specify a different zone origin" verify.out.$n > /dev/null || ret=1
+[ $ret = 0 ] || failed
+
+n=$((n + 1))
+echo_i "checking error message when an invalid -o is specified and a SOA record not at top of zone is found ($n)"
+ret=0
+$VERIFY -o invalid.origin zones/ksk+zsk.nsec.good > verify.out.$n 2>&1 && ret=1
+grep "not at top of zone" verify.out.$n > /dev/null || ret=1
+grep "use -o to specify a different zone origin" verify.out.$n > /dev/null && ret=1
+[ $ret = 0 ] || failed
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/verify/tests_sh_verify.py b/bin/tests/system/verify/tests_sh_verify.py
new file mode 100644
index 0000000..2fd0c5c
--- /dev/null
+++ b/bin/tests/system/verify/tests_sh_verify.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_verify(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/verify/zones/genzones.sh b/bin/tests/system/verify/zones/genzones.sh
new file mode 100644
index 0000000..494174d
--- /dev/null
+++ b/bin/tests/system/verify/zones/genzones.sh
@@ -0,0 +1,247 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+SYSTESTDIR=verify
+
+dumpit () {
+ echo_d "${debug}: dumping ${1}"
+ cat "${1}" | cat_d
+}
+
+setup () {
+ echo_i "setting up $2 zone: $1"
+ debug="$1"
+ zone="$1"
+ file="$1.$2"
+ n=$((${n:-0} + 1))
+}
+
+# A unsigned zone should fail validation.
+setup unsigned bad
+cp unsigned.db unsigned.bad
+
+# A set of nsec zones.
+setup zsk-only.nsec good
+$KEYGEN -a ${DEFAULT_ALGORITHM} ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -SP -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup ksk-only.nsec good
+$KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -SPz -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup ksk+zsk.nsec good
+$KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
+$KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
+$SIGNER -SPx -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup ksk+zsk.nsec.apex-dname good
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg1.out$n) || dumpit kg1.out$n
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cp unsigned.db ${file}.tmp
+echo "@ DNAME data" >> ${file}.tmp
+$SIGNER -SP -o ${zone} -f ${file} ${file}.tmp > s.out$n || dumpit s.out$n
+
+# A set of nsec3 zones.
+setup zsk-only.nsec3 good
+$KEYGEN -a ${DEFAULT_ALGORITHM} ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -3 - -SP -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup ksk-only.nsec3 good
+$KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -3 - -SPz -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup ksk+zsk.nsec3 good
+$KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
+$KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
+$SIGNER -3 - -SPx -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup ksk+zsk.optout good
+$KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
+$KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
+$SIGNER -3 - -A -SPx -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup ksk+zsk.nsec3.apex-dname good
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg1.out$n) || dumpit kg1.out$n
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cp unsigned.db ${file}.tmp
+echo "@ DNAME data" >> ${file}.tmp
+$SIGNER -3 - -SP -o ${zone} -f ${file} ${file}.tmp > s.out$n || dumpit s.out$n
+
+#
+# generate an NSEC record like
+# aba NSEC FOO ...
+# then downcase all the FOO records so the next name in the database
+# becomes foo when the zone is loaded.
+#
+setup nsec-next-name-case-mismatch good
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cat << EOF > ${zone}.tmp
+\$TTL 0
+@ IN SOA foo . ( 1 28800 7200 604800 1800 )
+@ NS foo
+\$include $ksk.key
+\$include $zsk.key
+FOO AAAA ::1
+FOO A 127.0.0.2
+aba CNAME FOO
+EOF
+$SIGNER -zP -o ${zone} -f ${file}.tmp ${zone}.tmp > s.out$n || dumpit s.out$n
+sed 's/^FOO\./foo\./' < ${file}.tmp > ${file}
+
+# A set of zones with only DNSKEY records.
+setup zsk-only.dnskeyonly bad
+key1=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2>kg.out) || dumpit kg.out$n
+cat unsigned.db $key1.key > ${file}
+
+setup ksk-only.dnskeyonly bad
+key1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2>kg.out) || dumpit kg.out$n
+cat unsigned.db $key1.key > ${file}
+
+setup ksk+zsk.dnskeyonly bad
+key1=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2>kg.out) || dumpit kg.out$n
+key2=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2>kg.out) || dumpit kg.out$n
+cat unsigned.db $key1.key $key2.key > ${file}
+
+# A set of zones with expired records
+s="-s -2678400"
+setup zsk-only.nsec.expired bad
+$KEYGEN -a ${DEFAULT_ALGORITHM} ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -SP ${s} -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup ksk-only.nsec.expired bad
+$KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -SPz ${s} -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup ksk+zsk.nsec.expired bad
+$KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
+$KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
+$SIGNER -SP ${s} -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup zsk-only.nsec3.expired bad
+$KEYGEN -a ${DEFAULT_ALGORITHM} ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -3 - ${s} -SP -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup ksk-only.nsec3.expired bad
+$KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
+$SIGNER -3 - ${s} -SPz -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+setup ksk+zsk.nsec3.expired bad
+$KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
+$KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
+$SIGNER -3 - ${s} -SPx -o ${zone} -f ${file} unsigned.db > s.out$n || dumpit s.out$n
+
+# ksk expired
+setup ksk+zsk.nsec.ksk-expired bad
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg1.out$n) || dumpit kg1.out$n
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cat unsigned.db $ksk.key $zsk.key > $file
+$SIGNER -Px -o ${zone} -f ${file} ${file} $zsk > s.out$n || dumpit s.out$n
+$SIGNER ${s} -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n || dumpit s.out$n
+now=$(date -u +%Y%m%d%H%M%S)
+exp=$(awk '$4 == "RRSIG" && $5 == "DNSKEY" { print $9;}' ${file})
+[ "${exp:-40001231246060}" -lt ${now:-0} ] || dumpit $file
+
+setup ksk+zsk.nsec3.ksk-expired bad
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg1.out$n) || dumpit kg1.out$n
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cat unsigned.db $ksk.key $zsk.key > $file
+$SIGNER -3 - -Px -o ${zone} -f ${file} ${file} $zsk > s.out$n || dumpit s.out$n
+$SIGNER -3 - ${s} -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n || dumpit s.out$n
+now=$(date -u +%Y%m%d%H%M%S)
+exp=$(awk '$4 == "RRSIG" && $5 == "DNSKEY" { print $9;}' ${file})
+[ "${exp:-40001231246060}" -lt ${now:-0} ] || dumpit $file
+
+# broken nsec chain
+setup ksk+zsk.nsec.broken-chain bad
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg1.out$n) || dumpit kg1.out$n
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cat unsigned.db $ksk.key $zsk.key > $file
+$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n || dumpit s.out$n
+awk '$4 == "NSEC" { $5 = "'$zone'."; print } { print }' ${file} > ${file}.tmp
+$SIGNER -Px -Z nonsecify -o ${zone} -f ${file} ${file}.tmp $zsk > s.out$n || dumpit s.out$n
+
+# bad nsec bitmap
+setup ksk+zsk.nsec.bad-bitmap bad
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg1.out$n) || dumpit kg1.out$n
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cat unsigned.db $ksk.key $zsk.key > $file
+$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n || dumpit s.out$n
+awk '$4 == "NSEC" && /SOA/ { $6=""; print } { print }' ${file} > ${file}.tmp
+$SIGNER -Px -Z nonsecify -o ${zone} -f ${file} ${file}.tmp $zsk > s.out$n || dumpit s.out$n
+
+# extra NSEC record out side of zone
+setup ksk+zsk.nsec.out-of-zone-nsec bad
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg1.out$n) || dumpit kg1.out$n
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cat unsigned.db $ksk.key $zsk.key > $file
+$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n || dumpit s.out$n
+echo "out-of-zone. 3600 IN NSEC ${zone}. A" >> ${file}
+$SIGNER -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file} $zsk > s.out$n || dumpit s.out$n
+
+# extra NSEC record below bottom of zone
+setup ksk+zsk.nsec.below-bottom-of-zone-nsec bad
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg1.out$n) || dumpit kg1.out$n
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cat unsigned.db $ksk.key $zsk.key > $file
+$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n || dumpit s.out$n
+echo "ns.sub.${zone}. 3600 IN NSEC ${zone}. A AAAA" >> ${file}
+$SIGNER -Px -Z nonsecify -O full -o ${zone} -f ${file}.tmp ${file} $zsk > s.out$n || dumpit s.out$n
+# dnssec-signzone signs any node with a NSEC record.
+awk '$1 ~ /^ns.sub/ && $4 == "RRSIG" && $5 != "NSEC" { next; } { print; }' ${file}.tmp > ${file}
+
+# extra NSEC record below DNAME
+setup ksk+zsk.nsec.below-dname-nsec bad
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg1.out$n) || dumpit kg1.out$n
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cat unsigned.db $ksk.key $zsk.key > $file
+$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n || dumpit s.out$n
+echo "sub.dname.${zone}. 3600 IN NSEC ${zone}. TXT" >> ${file}
+$SIGNER -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file} $zsk > s.out$n || dumpit s.out$n
+
+# missing NSEC3 record at empty node
+# extract the hash fields from the empty node's NSEC 3 record then fix up
+# the NSEC3 chain to remove it
+setup ksk+zsk.nsec3.missing-empty bad
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg1.out$n) || dumpit kg1.out$n
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cat unsigned.db $ksk.key $zsk.key > $file
+$SIGNER -3 - -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n || dumpit s.out$n
+a=$(awk '$4 == "NSEC3" && NF == 9 { split($1, a, "."); print a[1]; }' ${file})
+b=$(awk '$4 == "NSEC3" && NF == 9 { print $9; }' ${file})
+awk '
+$4 == "NSEC3" && $9 == "'$a'" { $9 = "'$b'"; print; next; }
+$4 == "NSEC3" && NF == 9 { next; }
+{ print; }' ${file} > ${file}.tmp
+$SIGNER -3 - -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file}.tmp $zsk > s.out$n || dumpit s.out$n
+
+# extra NSEC3 record
+setup ksk+zsk.nsec3.extra-nsec3 bad
+zsk=$($KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} 2> kg1.out$n) || dumpit kg1.out$n
+ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2> kg2.out$n) || dumpit kg2.out$n
+cat unsigned.db $ksk.key $zsk.key > $file
+$SIGNER -3 - -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n || dumpit s.out$n
+awk '
+BEGIN {
+ ZONE="'${zone}'.";
+}
+$4 == "NSEC3" && NF == 9 {
+ $1 = "H9P7U7TR2U91D0V0LJS9L1GIDNP90U3H." ZONE;
+ $9 = "H9P7U7TR2U91D0V0LJS9L1GIDNP90U3I";
+ print;
+}' ${file} > ${file}.tmp
+cat ${file}.tmp >> ${file}
+rm -f ${file}.tmp
+$SIGNER -3 - -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file} $zsk > s.out$n || dumpit s.out$n
diff --git a/bin/tests/system/verify/zones/unsigned.db b/bin/tests/system/verify/zones/unsigned.db
new file mode 100644
index 0000000..1e7cd2b
--- /dev/null
+++ b/bin/tests/system/verify/zones/unsigned.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA . . 0 0 0 2419200 3600 ; 28 day expire
+@ NS .
+data A 1.2.3.4
+dname DNAME data
+longttl 2419200 A 1.2.3.4
+sub.dname TXT sub.dname
+sub.empty TXT sub.empty
+sub NS ns.sub
+ns.sub A 1.2.3.4
+ns.sub AAAA 2002::1.2.3.4
+ns.sub WKS 1.2.3.4 udp domain
+other.sub TXT other.sub
+secure NS secure
+secure DS 1312 50 100 96EEB2FFD9B00CD4694E78278B5EFDAB0A80446567B69F634DA078F0
+secure A 1.2.3.4
+secure AAAA 2002::1.2.3.4
+out-of-zone. A 1.2.3.4
diff --git a/bin/tests/system/views/clean.sh b/bin/tests/system/views/clean.sh
new file mode 100644
index 0000000..d644c2a
--- /dev/null
+++ b/bin/tests/system/views/clean.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f ns*/named.conf
+rm -f ns3/example.bk dig.out.ns?.?
+rm -f ns2/example.db ns3/internal.bk
+rm -f -- */*.jnl
+rm -f -- */named.memstats
+rm -f -- */named.run */named.run.prev
+rm -f ns2/external/K*
+rm -f ns2/external/inline.db.jbk
+rm -f ns2/external/inline.db.signed
+rm -f ns2/external/inline.db.signed.jnl
+rm -f ns2/internal/K*
+rm -f ns2/internal/inline.db.jbk
+rm -f ns2/internal/inline.db.signed
+rm -f ns2/internal/inline.db.signed.jnl
+rm -f ns2/zones.conf
+rm -f ns2/db.* ns2/K*
+rm -f dig.out.external dig.out.internal
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
diff --git a/bin/tests/system/views/ns1/named.conf.in b/bin/tests/system/views/ns1/named.conf.in
new file mode 100644
index 0000000..888b9b0
--- /dev/null
+++ b/bin/tests/system/views/ns1/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/views/ns1/root.db b/bin/tests/system/views/ns1/root.db
new file mode 100644
index 0000000..17780d1
--- /dev/null
+++ b/bin/tests/system/views/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/views/ns2/1.10.in-addr.arpa.db b/bin/tests/system/views/ns2/1.10.in-addr.arpa.db
new file mode 100644
index 0000000..7ca723d
--- /dev/null
+++ b/bin/tests/system/views/ns2/1.10.in-addr.arpa.db
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ IN SOA . . 0 0 0 0 0
+@ IN NS .
diff --git a/bin/tests/system/views/ns2/clone.db b/bin/tests/system/views/ns2/clone.db
new file mode 100644
index 0000000..0f2de76
--- /dev/null
+++ b/bin/tests/system/views/ns2/clone.db
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA mname1. . (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ IN NS ns2
+ns2 IN A 10.53.0.2
+
+a IN A 10.1.0.1
+child IN NS ns3.child
+ns3.child IN A 10.53.0.3
diff --git a/bin/tests/system/views/ns2/example1.db b/bin/tests/system/views/ns2/example1.db
new file mode 100644
index 0000000..4d60ce3
--- /dev/null
+++ b/bin/tests/system/views/ns2/example1.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+$ORIGIN example.
+a A 10.0.0.1
+ MX 10 mail.example.
+
+mail A 10.0.0.2
diff --git a/bin/tests/system/views/ns2/example2.db b/bin/tests/system/views/ns2/example2.db
new file mode 100644
index 0000000..966240e
--- /dev/null
+++ b/bin/tests/system/views/ns2/example2.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.4
+
+$ORIGIN example.
+a A 10.0.0.1
+ MX 10 mail.example.
+
+mail A 10.0.0.2
diff --git a/bin/tests/system/views/ns2/external/inline.db b/bin/tests/system/views/ns2/external/inline.db
new file mode 100644
index 0000000..16d53b9
--- /dev/null
+++ b/bin/tests/system/views/ns2/external/inline.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+inline. IN SOA mname1. . (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+inline. NS ns2.inline.
+ns2.inline. A 10.53.0.2
+inline. NS ns3.inline.
+ns3.inline. A 10.53.0.3
+
+$ORIGIN inline.
+a A 10.1.0.1
+ MX 10 extmail.inline.
+
+extmail A 10.1.0.2
diff --git a/bin/tests/system/views/ns2/internal.db b/bin/tests/system/views/ns2/internal.db
new file mode 100644
index 0000000..4f1014f
--- /dev/null
+++ b/bin/tests/system/views/ns2/internal.db
@@ -0,0 +1,30 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.1.0.1
+ MX 10 intmail.example.
+
+intmail A 10.1.0.2
diff --git a/bin/tests/system/views/ns2/internal/inline.db b/bin/tests/system/views/ns2/internal/inline.db
new file mode 100644
index 0000000..7a30873
--- /dev/null
+++ b/bin/tests/system/views/ns2/internal/inline.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+inline. IN SOA mname1. . (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+inline. NS ns2.inline.
+ns2.inline. A 10.53.0.2
+inline. NS ns3.inline.
+ns3.inline. A 10.53.0.3
+
+$ORIGIN inline.
+a A 10.1.0.1
+ MX 10 intmail.inline.
+
+intmail A 10.1.0.2
diff --git a/bin/tests/system/views/ns2/named1.conf.in b/bin/tests/system/views/ns2/named1.conf.in
new file mode 100644
index 0000000..4a257c0
--- /dev/null
+++ b/bin/tests/system/views/ns2/named1.conf.in
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+ allow-update { any; };
+};
+
+zone "inline" {
+ type primary;
+ file "external/inline.db";
+ key-directory "external";
+ auto-dnssec maintain;
+ inline-signing yes;
+ dnssec-dnskey-kskonly no;
+};
diff --git a/bin/tests/system/views/ns2/named2.conf.in b/bin/tests/system/views/ns2/named2.conf.in
new file mode 100644
index 0000000..8a4d773
--- /dev/null
+++ b/bin/tests/system/views/ns2/named2.conf.in
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view "internal" {
+ match-clients { 10.53.0.2;
+ 10.53.0.3; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "example" {
+ type primary;
+ file "internal.db";
+ allow-update { any; };
+ };
+
+ zone "clone" {
+ type primary;
+ file "clone.db";
+ allow-update { any; };
+ };
+
+ zone "1.10.in-addr.arpa" {
+ type primary;
+ file "1.10.in-addr.arpa.db";
+ };
+
+ zone "inline" {
+ type primary;
+ file "internal/inline.db";
+ key-directory "internal";
+ auto-dnssec maintain;
+ inline-signing yes;
+ dnssec-dnskey-kskonly no;
+ };
+};
+
+view "external" {
+ match-clients { any; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "example" {
+ type primary;
+ file "example.db";
+ };
+
+ zone "clone" {
+ in-view internal;
+ forward only;
+ forwarders { 10.53.0.5; };
+ };
+
+ zone "1.10.in-addr.arpa" {
+ in-view internal;
+ };
+
+ zone "inline" {
+ type primary;
+ file "external/inline.db";
+ key-directory "external";
+ auto-dnssec maintain;
+ inline-signing yes;
+ dnssec-dnskey-kskonly no;
+ };
+};
diff --git a/bin/tests/system/views/ns2/named3.conf.in b/bin/tests/system/views/ns2/named3.conf.in
new file mode 100644
index 0000000..d84cda9
--- /dev/null
+++ b/bin/tests/system/views/ns2/named3.conf.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "zones.conf";
diff --git a/bin/tests/system/views/ns3/child.clone.db b/bin/tests/system/views/ns3/child.clone.db
new file mode 100644
index 0000000..9b90023
--- /dev/null
+++ b/bin/tests/system/views/ns3/child.clone.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns3. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS ns3
+@ TXT This is NS3.
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/views/ns3/internal.db b/bin/tests/system/views/ns3/internal.db
new file mode 100644
index 0000000..c93c2b0
--- /dev/null
+++ b/bin/tests/system/views/ns3/internal.db
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.1.0.1
+ MX 10 intmail.example.
+
+intmail A 10.1.0.2
diff --git a/bin/tests/system/views/ns3/named1.conf.in b/bin/tests/system/views/ns3/named1.conf.in
new file mode 100644
index 0000000..b4fbf41
--- /dev/null
+++ b/bin/tests/system/views/ns3/named1.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ allow-update { any; };
+ file "internal.db";
+};
+
+zone "child.clone" {
+ type primary;
+ file "child.clone.db";
+};
diff --git a/bin/tests/system/views/ns3/named2.conf.in b/bin/tests/system/views/ns3/named2.conf.in
new file mode 100644
index 0000000..0ef2009
--- /dev/null
+++ b/bin/tests/system/views/ns3/named2.conf.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "internal.bk";
+};
+
+zone "child.clone" {
+ type primary;
+ file "child.clone.db";
+};
diff --git a/bin/tests/system/views/ns5/child.clone.db b/bin/tests/system/views/ns5/child.clone.db
new file mode 100644
index 0000000..e29143b
--- /dev/null
+++ b/bin/tests/system/views/ns5/child.clone.db
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns3. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS ns3
+@ TXT This is NS5.
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/views/ns5/named.conf.in b/bin/tests/system/views/ns5/named.conf.in
new file mode 100644
index 0000000..4c4ee4e
--- /dev/null
+++ b/bin/tests/system/views/ns5/named.conf.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port @PORT@;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "child.clone" {
+ type primary;
+ file "child.clone.db";
+};
diff --git a/bin/tests/system/views/setup.sh b/bin/tests/system/views/setup.sh
new file mode 100644
index 0000000..e0cca83
--- /dev/null
+++ b/bin/tests/system/views/setup.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+cp -f ns2/example1.db ns2/example.db
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named1.conf.in ns2/named.conf
+copy_setports ns3/named1.conf.in ns3/named.conf
+copy_setports ns5/named.conf.in ns5/named.conf
+
+#
+# We remove k1 and k2 as KEYGEN is deterministic when given the
+# same source of "random" data and we want different keys for
+# internal and external instances of inline.
+#
+$KEYGEN -K ns2/internal -a ${DEFAULT_ALGORITHM} -q inline > /dev/null 2>&1
+$KEYGEN -K ns2/internal -a ${DEFAULT_ALGORITHM} -qfk inline > /dev/null 2>&1
+k1=$($KEYGEN -K ns2/external -a ${DEFAULT_ALGORITHM} -q inline 2> /dev/null)
+k2=$($KEYGEN -K ns2/external -a ${DEFAULT_ALGORITHM} -qfk inline 2> /dev/null)
+$KEYGEN -K ns2/external -a ${DEFAULT_ALGORITHM} -q inline > /dev/null 2>&1
+$KEYGEN -K ns2/external -a ${DEFAULT_ALGORITHM} -qfk inline > /dev/null 2>&1
+test -n "$k1" && rm -f ns2/external/"$k1".*
+test -n "$k2" && rm -f ns2/external/"$k2".*
diff --git a/bin/tests/system/views/tests.sh b/bin/tests/system/views/tests.sh
new file mode 100644
index 0000000..06cb3b1
--- /dev/null
+++ b/bin/tests/system/views/tests.sh
@@ -0,0 +1,189 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+dig_with_opts() {
+ "$DIG" +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd +noauth -p "${PORT}" "$@"
+}
+
+dig_with_shortopts() {
+ "$DIG" +tcp +short -p "${PORT}" "$@"
+}
+
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+
+echo_i "fetching a.example from ns2's initial configuration"
+dig_with_opts a.example. @10.53.0.2 any > dig.out.ns2.1 || status=1
+
+echo_i "fetching a.example from ns3's initial configuration"
+dig_with_opts a.example. @10.53.0.3 any > dig.out.ns3.1 || status=1
+
+echo_i "copying in new configurations for ns2 and ns3"
+rm -f ns2/named.conf ns3/named.conf ns2/example.db
+cp -f ns2/example2.db ns2/example.db
+copy_setports ns2/named2.conf.in ns2/named.conf
+copy_setports ns3/named2.conf.in ns3/named.conf
+
+echo_i "reloading ns2 and ns3 with rndc"
+nextpart ns2/named.run > /dev/null
+nextpart ns3/named.run > /dev/null
+rndc_reload ns2 10.53.0.2
+rndc_reload ns3 10.53.0.3
+
+echo_i "wait for reload to complete"
+ret=0
+_check_reload() (
+ nextpartpeek ns2/named.run | grep "all zones loaded" > /dev/null && \
+ nextpartpeek ns3/named.run | grep "all zones loaded" > /dev/null && \
+ nextpartpeek ns3/named.run | grep "zone_dump: zone example/IN: enter" > /dev/null
+)
+retry_quiet 10 _check_reload || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "fetching a.example from ns2's 10.53.0.4, source address 10.53.0.4"
+dig_with_opts -b 10.53.0.4 a.example. @10.53.0.4 any > dig.out.ns4.2 || status=1
+
+echo_i "fetching a.example from ns2's 10.53.0.2, source address 10.53.0.2"
+dig_with_opts -b 10.53.0.2 a.example. @10.53.0.2 any > dig.out.ns2.2 || status=1
+
+echo_i "fetching a.example from ns3's 10.53.0.3, source address defaulted"
+dig_with_opts @10.53.0.3 a.example. any > dig.out.ns3.2 || status=1
+
+echo_i "comparing ns3's initial a.example to one from reconfigured 10.53.0.2"
+digcomp dig.out.ns3.1 dig.out.ns2.2 || status=1
+
+echo_i "comparing ns3's initial a.example to one from reconfigured 10.53.0.3"
+digcomp dig.out.ns3.1 dig.out.ns3.2 || status=1
+
+echo_i "comparing ns2's initial a.example to one from reconfigured 10.53.0.4"
+digcomp dig.out.ns2.1 dig.out.ns4.2 || status=1
+
+echo_i "comparing ns2's initial a.example to one from reconfigured 10.53.0.3"
+echo_i "(should be different)"
+if $PERL ../digcomp.pl dig.out.ns2.1 dig.out.ns3.2 >/dev/null
+then
+ echo_i "no differences found. something's wrong."
+ status=1
+fi
+
+echo_i "updating cloned zone in internal view"
+$NSUPDATE << EOF
+server 10.53.0.2 ${PORT}
+zone clone
+update add b.clone. 300 in a 10.1.0.3
+send
+EOF
+echo_i "sleeping to allow update to take effect"
+sleep 5
+
+echo_i "verifying update affected both views"
+ret=0
+one=$(dig_with_shortopts -b 10.53.0.2 @10.53.0.2 b.clone a)
+two=$(dig_with_shortopts -b 10.53.0.4 @10.53.0.2 b.clone a)
+if [ "$one" != "$two" ]; then
+ echo_i "'$one' does not match '$two'"
+ ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "verifying forwarder in cloned zone works"
+ret=0
+one=$(dig_with_shortopts -b 10.53.0.2 @10.53.0.2 child.clone txt)
+two=$(dig_with_shortopts -b 10.53.0.4 @10.53.0.2 child.clone txt)
+three=$(dig_with_shortopts @10.53.0.3 child.clone txt)
+four=$(dig_with_shortopts @10.53.0.5 child.clone txt)
+echo "$three" | grep NS3 > /dev/null || { ret=1; echo_i "expected response from NS3 got '$three'"; }
+echo "$four" | grep NS5 > /dev/null || { ret=1; echo_i "expected response from NS5 got '$four'"; }
+if [ "$one" = "$two" ]; then
+ echo_i "'$one' matches '$two'"
+ ret=1
+fi
+if [ "$one" != "$three" ]; then
+ echo_i "'$one' does not match '$three'"
+ ret=1
+fi
+if [ "$two" != "$four" ]; then
+ echo_i "'$two' does not match '$four'"
+ ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "verifying inline zones work with views"
+ret=0
+wait_for_signed() {
+ "$DIG" -p "${PORT}" @10.53.0.2 -b 10.53.0.2 +dnssec DNSKEY inline > dig.out.internal
+ "$DIG" -p "${PORT}" @10.53.0.2 -b 10.53.0.5 +dnssec DNSKEY inline > dig.out.external
+ grep "ANSWER: 4," dig.out.internal > /dev/null || return 1
+ grep "ANSWER: 4," dig.out.external > /dev/null || return 1
+ return 0
+}
+retry_quiet 10 wait_for_signed || ret=1
+int=$(awk '$4 == "DNSKEY" { print $8 }' dig.out.internal | sort)
+ext=$(awk '$4 == "DNSKEY" { print $8 }' dig.out.external | sort)
+test "$int" != "$ext" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "verifying adding of multiple inline zones followed by reconfiguration works"
+
+[ ! -f ns2/zones.conf ] && touch ns2/zones.conf
+copy_setports ns2/named3.conf.in ns2/named.conf
+
+i=1
+while [ $i -lt 50 ]; do
+ ret=0
+ zone_name=$(printf "example%03d.com" $i)
+
+ # Add a new zone to the configuration.
+ cat >> ns2/zones.conf <<-EOF
+ zone "${zone_name}" {
+ type primary;
+ file "db.${zone_name}";
+ dnssec-dnskey-kskonly yes;
+ auto-dnssec maintain;
+ inline-signing yes;
+ };
+ EOF
+
+ # Create a master file for the zone.
+ cat > "ns2/db.${zone_name}" <<-EOF
+ \$TTL 86400
+ @ IN SOA localhost. hostmaster.localhost (
+ 1612542642 ; serial
+ 12H ; refresh
+ 1H ; retry
+ 2w ; expiry
+ 1h ; minimum
+ )
+ @ IN NS localhost
+ localhost IN A 127.0.0.1
+ EOF
+
+ $KEYGEN -q -Kns2 -fk -aecdsa256 "${zone_name}" > /dev/null
+ $RNDCCMD 10.53.0.2 reconfig || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; break; fi
+ i=$((i + 1))
+done
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ "$status" -eq 0 ] || exit 1
diff --git a/bin/tests/system/views/tests_sh_views.py b/bin/tests/system/views/tests_sh_views.py
new file mode 100644
index 0000000..bfaacf4
--- /dev/null
+++ b/bin/tests/system/views/tests_sh_views.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_views(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/wildcard/clean.sh b/bin/tests/system/wildcard/clean.sh
new file mode 100644
index 0000000..c690ade
--- /dev/null
+++ b/bin/tests/system/wildcard/clean.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f ns*/named.run
+rm -f ns*/named.conf
+rm -f ns1/K*
+rm -f ns1/*.db
+rm -f ns1/*.signed
+rm -f ns1/dsset-*
+rm -f ns1/keyset-*
+rm -f ns1/trusted.conf
+rm -f ns1/private.nsec.conf
+rm -f ns1/private.nsec3.conf
+rm -f ns1/signer.err
+rm -f */named.memstats
+rm -f dig.out.ns*.test*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/wildcard/ns1/allwild.db.in b/bin/tests/system/wildcard/ns1/allwild.db.in
new file mode 100644
index 0000000..71575c3
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/allwild.db.in
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN allwild.test.
+allwild.test. 3600 IN SOA . . 0 0 0 0 0
+allwild.test. 3600 NS ns.example.test.
+*.allwild.test. 3600 A 192.0.2.1
diff --git a/bin/tests/system/wildcard/ns1/dlv.db.in b/bin/tests/system/wildcard/ns1/dlv.db.in
new file mode 100644
index 0000000..6156de6
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/dlv.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA a.root-servers.nil. hostmaster.root-servers.nil. 1 1800 900 604800 86400
+@ NS a.root-servers.nil.
diff --git a/bin/tests/system/wildcard/ns1/example.db.in b/bin/tests/system/wildcard/ns1/example.db.in
new file mode 100644
index 0000000..36616cb
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/example.db.in
@@ -0,0 +1,25 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN example.
+example. 3600 IN SOA . . 0 0 0 0 0
+example. 3600 NS ns.example.com.
+example. 3600 NS ns.example.net.
+*.example. 3600 TXT "this is a wildcard"
+*.example. 3600 MX 10 host1.example.
+sub.*.example. 3600 TXT "this is not a wildcard"
+host1.example. 3600 A 192.0.2.1
+_ssh._tcp.host1.example. 3600 SRV 0 0 22 host1.example.
+_ssh._tcp.host2.example. 3600 SRV 0 0 22 host2.example.
+subdel.example. 3600 NS ns.example.com.
+subdel.example. 3600 NS ns.example.net.
+
+_foo._udp.*.example. 3600 IN SRV 0 1 9 old-slow-box.example.
diff --git a/bin/tests/system/wildcard/ns1/named.conf.in b/bin/tests/system/wildcard/ns1/named.conf.in
new file mode 100644
index 0000000..ac02abf
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/named.conf.in
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "." { type primary; file "root.db.signed"; };
+
+/*
+ * RFC 4592 example zone.
+ */
+zone "allwild.test" { type primary; file "allwild.db"; };
+zone "example" { type primary; file "example.db"; };
+zone "nsec" { type primary; file "nsec.db.signed"; };
+zone "private.nsec" { type primary; file "private.nsec.db.signed"; };
+
+/*
+ * The contents of nsec3 and private.nsec3 are specially chosen to
+ * have separate NSEC3 records for the "no qname proof" and the
+ * "closest encloser proof".
+ */
+zone "nsec3" { type primary; file "nsec3.db.signed"; };
+zone "private.nsec3" { type primary; file "private.nsec3.db.signed"; };
diff --git a/bin/tests/system/wildcard/ns1/nsec.db.in b/bin/tests/system/wildcard/ns1/nsec.db.in
new file mode 100644
index 0000000..8869ab9
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/nsec.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA a.root-servers.nil. hostmaster.root-servers.nil. 1 1800 900 604800 86400
+@ NS a.root-servers.nil.
+private NS a.root-servers.nil.
+*.wild CNAME a.
+a.wild A 1.2.3.5
diff --git a/bin/tests/system/wildcard/ns1/nsec3.db.in b/bin/tests/system/wildcard/ns1/nsec3.db.in
new file mode 100644
index 0000000..8869ab9
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/nsec3.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA a.root-servers.nil. hostmaster.root-servers.nil. 1 1800 900 604800 86400
+@ NS a.root-servers.nil.
+private NS a.root-servers.nil.
+*.wild CNAME a.
+a.wild A 1.2.3.5
diff --git a/bin/tests/system/wildcard/ns1/private.nsec.db.in b/bin/tests/system/wildcard/ns1/private.nsec.db.in
new file mode 100644
index 0000000..b7cc222
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/private.nsec.db.in
@@ -0,0 +1,16 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA a.root-servers.nil. hostmaster.root-servers.nil. 1 1800 900 604800 86400
+@ NS a.root-servers.nil.
+*.wild CNAME a.
+a.wild A 1.2.3.5
diff --git a/bin/tests/system/wildcard/ns1/private.nsec3.db.in b/bin/tests/system/wildcard/ns1/private.nsec3.db.in
new file mode 100644
index 0000000..566b3f8
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/private.nsec3.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA a.root-servers.nil. hostmaster.root-servers.nil. 1 1800 900 604800 86400
+@ NS a.root-servers.nil.
+b A 1.2.3.4
+*.wild CNAME a.
+a.wild A 1.2.3.5
diff --git a/bin/tests/system/wildcard/ns1/root.db.in b/bin/tests/system/wildcard/ns1/root.db.in
new file mode 100644
index 0000000..ffeb0a6
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/root.db.in
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 120
+@ SOA a.root-servers.nil hostmaster.root-servers.nil 1 1800 900 604800 86400
+@ NS a.root-servers.nil
+a.root-servers.nil A 10.53.0.1
+nsec NS a.root-servers.nil
+nsec3 NS a.root-servers.nil
diff --git a/bin/tests/system/wildcard/ns1/sign.sh b/bin/tests/system/wildcard/ns1/sign.sh
new file mode 100755
index 0000000..d414bb1
--- /dev/null
+++ b/bin/tests/system/wildcard/ns1/sign.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../../conf.sh
+
+SYSTESTDIR=wildcard
+
+dssets=
+
+# RFC 4592 example zone.
+cp allwild.db.in allwild.db
+cp example.db.in example.db
+
+zone=nsec
+infile=nsec.db.in
+zonefile=nsec.db
+outfile=nsec.db.signed
+dssets="$dssets dsset-${zone}."
+
+keyname1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -n zone $zone 2> /dev/null)
+keyname2=$($KEYGEN -f KSK -a ${DEFAULT_ALGORITHM} -n zone $zone 2> /dev/null)
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+zone=private.nsec
+infile=private.nsec.db.in
+zonefile=private.nsec.db
+outfile=private.nsec.db.signed
+
+keyname1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -n zone $zone 2> /dev/null)
+keyname2=$($KEYGEN -f KSK -a ${DEFAULT_ALGORITHM} -n zone $zone 2> /dev/null)
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+keyfile_to_static_ds $keyname2 > private.nsec.conf
+
+zone=nsec3
+infile=nsec3.db.in
+zonefile=nsec3.db
+outfile=nsec3.db.signed
+dssets="$dssets dsset-${zone}."
+
+keyname1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -n zone $zone 2> /dev/null)
+keyname2=$($KEYGEN -f KSK -a ${DEFAULT_ALGORITHM} -n zone $zone 2> /dev/null)
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -3 - -H 10 -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+zone=private.nsec3
+infile=private.nsec3.db.in
+zonefile=private.nsec3.db
+outfile=private.nsec3.db.signed
+
+keyname1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -n zone $zone 2> /dev/null)
+keyname2=$($KEYGEN -f KSK -a ${DEFAULT_ALGORITHM} -n zone $zone 2> /dev/null)
+
+cat $infile $keyname1.key $keyname2.key > $zonefile
+
+$SIGNER -3 - -H 10 -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+keyfile_to_static_ds $keyname2 > private.nsec3.conf
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+outfile=root.db.signed
+
+keyname1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -n zone $zone 2> /dev/null)
+keyname2=$($KEYGEN -f KSK -a ${DEFAULT_ALGORITHM} -n zone $zone 2> /dev/null)
+
+cat $infile $keyname1.key $keyname2.key $dssets >$zonefile
+
+$SIGNER -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
+echo_i "signed $zone"
+
+keyfile_to_static_ds $keyname2 > trusted.conf
diff --git a/bin/tests/system/wildcard/ns2/named.conf.in b/bin/tests/system/wildcard/ns2/named.conf.in
new file mode 100644
index 0000000..a9a2a70
--- /dev/null
+++ b/bin/tests/system/wildcard/ns2/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/wildcard/ns3/named.conf.in b/bin/tests/system/wildcard/ns3/named.conf.in
new file mode 100644
index 0000000..0b958fa
--- /dev/null
+++ b/bin/tests/system/wildcard/ns3/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+};
+
+include "../ns1/trusted.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/wildcard/ns4/named.conf.in b/bin/tests/system/wildcard/ns4/named.conf.in
new file mode 100644
index 0000000..b125fa7
--- /dev/null
+++ b/bin/tests/system/wildcard/ns4/named.conf.in
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ notify yes;
+ forward only;
+ forwarders { 10.53.0.2; };
+};
+
+include "../ns1/trusted.conf";
+include "../ns1/private.nsec.conf";
+include "../ns1/private.nsec3.conf";
diff --git a/bin/tests/system/wildcard/ns5/named.conf.in b/bin/tests/system/wildcard/ns5/named.conf.in
new file mode 100644
index 0000000..1cd358d
--- /dev/null
+++ b/bin/tests/system/wildcard/ns5/named.conf.in
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.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;
+ dnssec-validation yes;
+ notify yes;
+};
+
+include "../ns1/trusted.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/wildcard/setup.sh b/bin/tests/system/wildcard/setup.sh
new file mode 100644
index 0000000..8c7adfe
--- /dev/null
+++ b/bin/tests/system/wildcard/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/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
+
+(cd ns1 && $SHELL -e sign.sh)
diff --git a/bin/tests/system/wildcard/tests.sh b/bin/tests/system/wildcard/tests.sh
new file mode 100644
index 0000000..b956874
--- /dev/null
+++ b/bin/tests/system/wildcard/tests.sh
@@ -0,0 +1,282 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
+
+n=$((n + 1))
+echo_i "checking that NSEC wildcard non-existence proof is returned auth ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.nsec +norec @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep -i 'a\.wild\.nsec\..*NSEC.*nsec\..*NSEC' dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NSEC wildcard non-existence proof is returned non-validating ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.nsec @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep -i 'a\.wild\.nsec\..*NSEC.*nsec\..*NSEC' dig.out.ns2.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NSEC wildcard non-existence proof is returned validating ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.nsec @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep -i 'a\.wild\.nsec\..*NSEC.*nsec\..*NSEC' dig.out.ns3.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NSEC wildcard non-existence proof is returned validating + CD ($n)"
+ret=0
+$DIG $DIGOPTS +cd a b.wild.nsec @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep -i 'a\.wild\.nsec\..*NSEC.*nsec\..*NSEC' dig.out.ns5.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns5.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+n=$((n + 1))
+
+echo_i "checking that returned NSEC wildcard non-existence proof validates ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.nsec @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep -i 'a\.wild\.nsec\..*NSEC.*nsec\..*NSEC' dig.out.ns4.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NSEC wildcard non-existence proof is returned private, validating ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.private.nsec @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep -i 'a\.wild\.private\.nsec\..*NSEC.*private\.nsec\..*NSEC' dig.out.ns3.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that returned NSEC wildcard non-existence proof for private zone validates ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.private.nsec @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep -i 'a\.wild\.private\.nsec\..*NSEC.*private\.nsec\..*NSEC' dig.out.ns4.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NSEC3 wildcard non-existence proof is returned auth ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.nsec3 +norec @10.53.0.1 > dig.out.ns1.test$n || ret=1
+grep -i 'O3TJ8D9AJ54CBTFCQCJ3QK49CH7SF6H9\.nsec3\..*V5DLFB6UJNHR94LQ61FO607KGK12H88A' dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NSEC3 wildcard non-existence proof is returned non-validating ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.nsec3 @10.53.0.2 > dig.out.ns2.test$n || ret=1
+grep -i 'O3TJ8D9AJ54CBTFCQCJ3QK49CH7SF6H9\.nsec3\..*V5DLFB6UJNHR94LQ61FO607KGK12H88A' dig.out.ns2.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns2.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NSEC3 wildcard non-existence proof is returned validating ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.nsec3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep -i 'O3TJ8D9AJ54CBTFCQCJ3QK49CH7SF6H9\.nsec3\..*V5DLFB6UJNHR94LQ61FO607KGK12H88A' dig.out.ns3.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NSEC3 wildcard non-existence proof is returned validating + CD ($n)"
+ret=0
+$DIG $DIGOPTS +cd a b.wild.nsec3 @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep -i 'O3TJ8D9AJ54CBTFCQCJ3QK49CH7SF6H9\.nsec3\..*V5DLFB6UJNHR94LQ61FO607KGK12H88A' dig.out.ns5.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns5.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that returned NSEC3 wildcard non-existence proof validates ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.nsec3 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep -i 'O3TJ8D9AJ54CBTFCQCJ3QK49CH7SF6H9\.nsec3\..*V5DLFB6UJNHR94LQ61FO607KGK12H88A' dig.out.ns4.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that NSEC3 wildcard non-existence proof is returned private, validating ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.private.nsec3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
+grep -i 'UDBSP4R8OUOT6HSO39VD8B5LMOSHRD5N\.private\.nsec3\..*NSEC3.*ASDRUIB7GO00OR92S5OUGI404LT27RNU' dig.out.ns3.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns3.test$n > /dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that returned NSEC3 wildcard non-existence proof for private zone validates ($n)"
+ret=0
+$DIG $DIGOPTS a b.wild.private.nsec3 @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep -i 'UDBSP4R8OUOT6HSO39VD8B5LMOSHRD5N\.private\.nsec3\..*NSEC3.*ASDRUIB7GO00OR92S5OUGI404LT27RNU' dig.out.ns4.test$n > /dev/null || ret=1
+grep -i 'flags:.* ad[ ;]' dig.out.ns4.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking RFC 4592 responses ..."
+
+n=$((n + 1))
+echo_i "checking RFC 4592: host3.example. QTYPE=MX, QCLASS=IN ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 host3.example. MX IN > dig.out.ns1.test$n || ret=1
+grep '^host3.example..*IN.MX.10 host1.example.' dig.out.ns1.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking RFC 4592: host3.example. QTYPE=A, QCLASS=IN ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 host3.example. A IN > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking RFC 4592: foo.bar.example. QTYPE=TXT, QCLASS=IN ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 foo.bar.example TXT IN > dig.out.ns1.test$n || ret=1
+grep '^foo.bar.example..*IN.TXT."this is a wildcard"' dig.out.ns1.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "ANSWER: 1," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking RFC 4592: host1.example. QTYPE=MX, QCLASS=IN ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 host1.example MX IN > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking RFC 4592: host1.example. QTYPE=MX, QCLASS=IN ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 host1.example MX IN > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking RFC 4592: sub.*.example. QTYPE=MX, QCLASS=IN ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 "sub.*.example." MX IN > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking RFC 4592: _telnet._tcp.host1.example. QTYPE=SRV, QCLASS=IN ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 _telnet._tcp.host1.example. SRV IN > dig.out.ns1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking RFC 4592: host.subdel.example. QTYPE=A, QCLASS=IN ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 host.subdel.example A IN > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns1.test$n > /dev/null || ret=1
+grep "AUTHORITY: 2," dig.out.ns1.test$n > /dev/null || ret=1
+grep "subdel.example..*IN.NS.ns.example.com." dig.out.ns1.test$n > /dev/null || ret=1
+grep "subdel.example..*IN.NS.ns.example.net." dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking RFC 4592: ghost.*.example. QTYPE=MX, QCLASS=IN ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 "ghost.*.example" MX IN > dig.out.ns1.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking RFC 4592: _foo._udp.bar.example. QTYPE=SRV, QCLASS=IN ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 "_foo._udp.bar.example" SRV IN > dig.out.ns1.test$n || ret=1
+grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
+grep "ANSWER: 0," dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "check wild card expansions by code point ($n)"
+ret=0
+i=0
+while test $i -lt 256
+do
+ x=$(expr 00$i : '.*\(...\)$' || true)
+ $DIG $DIGOPTS @10.53.0.1 "\\$x.example" TXT > dig.out.ns1.$x.test$n
+ if test $i -le 32 -o $i -ge 127
+ then
+ grep '^\\'"$x"'\.example\..*TXT.*"this is a wildcard"$' dig.out.ns1.$x.test$n > /dev/null || { echo_i "code point $x failed" ; ret=1; }
+ # "=34 $=36 (=40 )=41 .=46 ;=59 \=92 @=64
+ elif test $i -eq 34 -o $i -eq 36 -o $i -eq 40 -o $i -eq 41 -o \
+ $i -eq 46 -o $i -eq 59 -o $i -eq 64 -o $i -eq 92
+ then
+ case $i in
+ 34) a='"';;
+ 36) a='$';;
+ 40) a='(';;
+ 41) a=')';;
+ 46) a='\.';;
+ 59) a=';';;
+ 64) a='@';;
+ 92) a='\\';;
+ *) a=''; echo_i "code point $x failed" ; ret=1 ;;
+ esac
+ grep '^\\'"$a"'\.example.*.*TXT.*"this is a wildcard"$' dig.out.ns1.$x.test$n > /dev/null || { echo_i "code point $x failed" ; ret=1; }
+ else
+ grep '^\\' dig.out.ns1.$x.test$n && { echo_i "code point $x failed" ; ret=1; }
+ fi
+ i=$((i + 1))
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/wildcard/tests_sh_wildcard.py b/bin/tests/system/wildcard/tests_sh_wildcard.py
new file mode 100644
index 0000000..89a9fef
--- /dev/null
+++ b/bin/tests/system/wildcard/tests_sh_wildcard.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_wildcard(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/wildcard/tests_wildcard.py b/bin/tests/system/wildcard/tests_wildcard.py
new file mode 100755
index 0000000..66166f2
--- /dev/null
+++ b/bin/tests/system/wildcard/tests_wildcard.py
@@ -0,0 +1,112 @@
+#!/usr/bin/python3
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+"""
+Example property-based test for wildcard synthesis.
+Verifies that otherwise-empty zone with single wildcard record * A 192.0.2.1
+produces synthesized answers for <random_label>.test. A, and returns NODATA for
+<random_label>.test. when rdtype is not A.
+
+Limitations - untested properties:
+ - expansion works with multiple labels
+ - asterisk in qname does not cause expansion
+ - empty non-terminals prevent expansion
+ - or more generally any existing node prevents expansion
+ - DNSSEC record inclusion
+ - possibly others, see RFC 4592 and company
+ - content of authority & additional sections
+ - flags beyond RCODE
+ - special behavior of rdtypes like CNAME
+"""
+import pytest
+
+pytest.importorskip("dns")
+import dns.message
+import dns.name
+import dns.query
+import dns.rcode
+import dns.rdataclass
+import dns.rdatatype
+import dns.rrset
+
+pytest.importorskip("hypothesis")
+from hypothesis import given
+from hypothesis.strategies import binary, integers
+
+
+# labels of a zone with * A 192.0.2.1 wildcard
+WILDCARD_ZONE = ("allwild", "test", "")
+WILDCARD_RDTYPE = dns.rdatatype.A
+WILDCARD_RDATA = "192.0.2.1"
+IPADDR = "10.53.0.1"
+TIMEOUT = 5 # seconds, just a sanity check
+
+
+# Helpers
+def is_nonexpanding_rdtype(rdtype):
+ """skip meta types to avoid weird rcodes caused by AXFR etc.; RFC 6895"""
+ return not (
+ rdtype == WILDCARD_RDTYPE
+ or dns.rdatatype.is_metatype(rdtype) # known metatypes: OPT ...
+ or 128 <= rdtype <= 255
+ ) # unknown meta types
+
+
+def tcp_query(where, port, qname, qtype):
+ querymsg = dns.message.make_query(qname, qtype)
+ assert len(querymsg.question) == 1
+ return querymsg, dns.query.tcp(querymsg, where, port=port, timeout=TIMEOUT)
+
+
+def query(where, port, label, rdtype):
+ labels = (label,) + WILDCARD_ZONE
+ qname = dns.name.Name(labels)
+ return tcp_query(where, port, qname, rdtype)
+
+
+# Tests
+@given(
+ label=binary(min_size=1, max_size=63),
+ rdtype=integers(min_value=0, max_value=65535).filter(is_nonexpanding_rdtype),
+)
+def test_wildcard_rdtype_mismatch(label, rdtype, named_port):
+ """any label non-matching rdtype must result in to NODATA"""
+ check_answer_nodata(*query(IPADDR, named_port, label, rdtype))
+
+
+def check_answer_nodata(querymsg, answer):
+ assert querymsg.is_response(answer), str(answer)
+ assert answer.rcode() == dns.rcode.NOERROR, str(answer)
+ assert answer.answer == [], str(answer)
+
+
+@given(label=binary(min_size=1, max_size=63))
+def test_wildcard_match(label, named_port):
+ """any label with maching rdtype must result in wildcard data in answer"""
+ check_answer_noerror(*query(IPADDR, named_port, label, WILDCARD_RDTYPE))
+
+
+def check_answer_noerror(querymsg, answer):
+ assert querymsg.is_response(answer), str(answer)
+ assert answer.rcode() == dns.rcode.NOERROR, str(answer)
+ assert len(querymsg.question) == 1, str(answer)
+ expected_answer = [
+ dns.rrset.from_text(
+ querymsg.question[0].name,
+ 300, # TTL, ignored by dnspython comparison
+ dns.rdataclass.IN,
+ WILDCARD_RDTYPE,
+ WILDCARD_RDATA,
+ )
+ ]
+ assert answer.answer == expected_answer, str(answer)
diff --git a/bin/tests/system/xfer/ans5/badkeydata b/bin/tests/system/xfer/ans5/badkeydata
new file mode 100644
index 0000000..8dc80fb
--- /dev/null
+++ b/bin/tests/system/xfer/ans5/badkeydata
@@ -0,0 +1,10 @@
+/SOA tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+/AXFR tsig_key abcd1234ffff/
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+/AXFR tsig_key abcd1234ffff/
+nil. 300 NS ns.nil.
+nil. 300 TXT "bad keydata AXFR"
+a.nil. 60 A 10.0.0.61
+/AXFR tsig_key abcd1234ffff/
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
diff --git a/bin/tests/system/xfer/ans5/badmessageid b/bin/tests/system/xfer/ans5/badmessageid
new file mode 100644
index 0000000..e0dc041
--- /dev/null
+++ b/bin/tests/system/xfer/ans5/badmessageid
@@ -0,0 +1,10 @@
+/SOA tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+/AXFR tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+/AXFR bad-id tsig_key LSAnCU+Z/
+nil. 300 NS ns.nil.
+nil. 300 TXT "bad message id"
+a.nil. 60 A 10.0.0.61
+/AXFR bad-id tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
diff --git a/bin/tests/system/xfer/ans5/goodaxfr b/bin/tests/system/xfer/ans5/goodaxfr
new file mode 100644
index 0000000..e5ccd43
--- /dev/null
+++ b/bin/tests/system/xfer/ans5/goodaxfr
@@ -0,0 +1,10 @@
+/SOA tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+/AXFR tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+/AXFR tsig_key LSAnCU+Z/
+nil. 300 NS ns.nil.
+nil. 300 TXT "initial AXFR"
+a.nil. 60 A 10.0.0.61
+/AXFR tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
diff --git a/bin/tests/system/xfer/ans5/partial b/bin/tests/system/xfer/ans5/partial
new file mode 100644
index 0000000..e7eff8e
--- /dev/null
+++ b/bin/tests/system/xfer/ans5/partial
@@ -0,0 +1,11 @@
+/SOA tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+/AXFR tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+/AXFR/
+nil. 300 NS ns.nil.
+nil. 300 TXT "partially signed AXFR"
+a.nil. 60 A 10.0.0.61
+b.nil. 60 A 10.0.0.62
+/AXFR/
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
diff --git a/bin/tests/system/xfer/ans5/soamismatch b/bin/tests/system/xfer/ans5/soamismatch
new file mode 100644
index 0000000..14cfa41
--- /dev/null
+++ b/bin/tests/system/xfer/ans5/soamismatch
@@ -0,0 +1,10 @@
+/SOA tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+/AXFR tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+/AXFR tsig_key LSAnCU+Z/
+nil. 300 NS ns.nil.
+nil. 300 TXT "SOA mismatch AXFR"
+a.nil. 60 A 10.0.0.61
+/AXFR tsig_key LSAnCU+Z/
+nil. 300 SOA whatever. other. 1 300 300 604800 300
diff --git a/bin/tests/system/xfer/ans5/unknownkey b/bin/tests/system/xfer/ans5/unknownkey
new file mode 100644
index 0000000..da7889b
--- /dev/null
+++ b/bin/tests/system/xfer/ans5/unknownkey
@@ -0,0 +1,11 @@
+/SOA bad_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 5 300 300 604800 300
+/AXFR bad_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 5 300 300 604800 300
+/AXFR bad_key LSAnCU+Z/
+nil. 300 NS ns.nil.
+nil. 300 TXT "unknown key AXFR"
+a.nil. 60 A 10.0.0.61
+b.nil. 60 A 10.0.0.62
+/AXFR bad_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 5 300 300 604800 300
diff --git a/bin/tests/system/xfer/ans5/unsigned b/bin/tests/system/xfer/ans5/unsigned
new file mode 100644
index 0000000..3fe04db
--- /dev/null
+++ b/bin/tests/system/xfer/ans5/unsigned
@@ -0,0 +1,11 @@
+/SOA tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 2 300 300 604800 300
+/AXFR/
+nil. 300 SOA ns.nil. root.nil. 2 300 300 604800 300
+/AXFR/
+nil. 300 NS ns.nil.
+nil. 300 TXT "unsigned AXFR"
+a.nil. 60 A 10.0.0.61
+b.nil. 60 A 10.0.0.62
+/AXFR/
+nil. 300 SOA ns.nil. root.nil. 2 300 300 604800 300
diff --git a/bin/tests/system/xfer/ans5/wrongkey b/bin/tests/system/xfer/ans5/wrongkey
new file mode 100644
index 0000000..af120b0
--- /dev/null
+++ b/bin/tests/system/xfer/ans5/wrongkey
@@ -0,0 +1,11 @@
+/SOA unused_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 6 300 300 604800 300
+/AXFR unused_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 6 300 300 604800 300
+/AXFR unused_key LSAnCU+Z/
+nil. 300 NS ns.nil.
+nil. 300 TXT "incorrect key AXFR"
+a.nil. 60 A 10.0.0.61
+b.nil. 60 A 10.0.0.62
+/AXFR unused_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 6 300 300 604800 300
diff --git a/bin/tests/system/xfer/ans5/wrongname b/bin/tests/system/xfer/ans5/wrongname
new file mode 100644
index 0000000..346ac3d
--- /dev/null
+++ b/bin/tests/system/xfer/ans5/wrongname
@@ -0,0 +1,10 @@
+/SOA tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+/AXFR tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+/AXFR tsig_key LSAnCU+Z ns.wrong./
+nil. 300 NS ns.nil.
+nil. 300 TXT "wrong question AXFR"
+a.nil. 60 A 10.0.0.61
+/AXFR tsig_key LSAnCU+Z/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
diff --git a/bin/tests/system/xfer/axfr-stats.good b/bin/tests/system/xfer/axfr-stats.good
new file mode 100644
index 0000000..264af09
--- /dev/null
+++ b/bin/tests/system/xfer/axfr-stats.good
@@ -0,0 +1,3 @@
+messages=16
+records=10003
+bytes=218227
diff --git a/bin/tests/system/xfer/clean.sh b/bin/tests/system/xfer/clean.sh
new file mode 100644
index 0000000..effdda8
--- /dev/null
+++ b/bin/tests/system/xfer/clean.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f */ans.run
+rm -f */named.conf
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.run.prev
+rm -f axfr.out
+rm -f dig.out.*
+rm -f ns*/managed-keys.bind*
+rm -f ns*/named.lock
+rm -f ns1/dot-fallback.db
+rm -f ns1/edns-expire.db
+rm -f ns1/ixfr-too-big.db ns1/ixfr-too-big.db.jnl
+rm -f ns1/sec.db ns2/sec.db
+rm -f ns2/example.db ns2/tsigzone.db ns2/example.db.jnl ns2/dot-fallback.db
+rm -f ns2/mapped.db
+rm -f ns3/example.bk ns3/xfer-stats.bk ns3/tsigzone.bk ns3/example.bk.jnl
+rm -f ns3/mapped.bk
+rm -f ns3/primary.bk ns3/primary.bk.jnl
+rm -f ns4/*.db ns4/*.jnl
+rm -f ns6/*.db ns6/*.bk ns6/*.jnl
+rm -f ns7/*.db ns7/*.bk ns7/*.jnl
+rm -f ns8/large.db ns8/small.db
+rm -f stats.*
+rm -f wait_for_message.*
diff --git a/bin/tests/system/xfer/dig1.good b/bin/tests/system/xfer/dig1.good
new file mode 100644
index 0000000..9fa5437
--- /dev/null
+++ b/bin/tests/system/xfer/dig1.good
@@ -0,0 +1,178 @@
+example. 86400 IN SOA ns2.example. hostmaster.example. 1397051952 5 5 1814400 3600
+example. 3600 IN NS ns2.example.
+example. 3600 IN NS ns3.example.
+a01.example. 3600 IN A 0.0.0.0
+a02.example. 3600 IN A 255.255.255.255
+a601.example. 3600 IN A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+a601.example. 3600 IN A6 64 ::ffff:ffff:ffff:ffff foo.
+a601.example. 3600 IN A6 127 ::1 foo.
+a601.example. 3600 IN A6 128 .
+aaaa01.example. 3600 IN AAAA ::1
+aaaa02.example. 3600 IN AAAA fd92:7065:b8e:ffff::5
+afsdb01.example. 3600 IN AFSDB 0 hostname.example.
+afsdb02.example. 3600 IN AFSDB 65535 .
+amtrelay01.example. 3600 IN AMTRELAY 0 0 0
+amtrelay02.example. 3600 IN AMTRELAY 0 1 0
+amtrelay03.example. 3600 IN AMTRELAY 0 0 1 0.0.0.0
+amtrelay04.example. 3600 IN AMTRELAY 0 0 2 ::
+amtrelay05.example. 3600 IN AMTRELAY 0 0 3 example.net.
+amtrelay06.example. 3600 IN AMTRELAY \# 2 0004
+apl01.example. 3600 IN APL !1:10.0.0.1/32 1:10.0.0.0/24
+apl02.example. 3600 IN APL
+atma01.example. 3600 IN ATMA +61200000000
+atma02.example. 3600 IN ATMA +61200000000
+atma03.example. 3600 IN ATMA 1234567890abcdef
+atma04.example. 3600 IN ATMA fedcba0987654321
+avc.example. 3600 IN AVC "foo:bar"
+caa01.example. 3600 IN CAA 0 issue "ca.example.net; policy=ev"
+caa02.example. 3600 IN CAA 128 tbs "Unknown"
+caa03.example. 3600 IN CAA 128 tbs ""
+cdnskey01.example. 3600 IN CDNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+cds01.example. 3600 IN CDS 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+cert01.example. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+cname01.example. 3600 IN CNAME cname-target.
+cname02.example. 3600 IN CNAME cname-target.example.
+cname03.example. 3600 IN CNAME .
+csync01.example. 3600 IN CSYNC 0 0 A NS AAAA
+csync02.example. 3600 IN CSYNC 0 0
+dhcid01.example. 3600 IN DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA=
+dhcid02.example. 3600 IN DHCID AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQdWL3b/NaiUDlW2No=
+dhcid03.example. 3600 IN DHCID AAABxLmlskllE0MVjd57zHcWmEH3pCQ6VytcKD//7es/deY=
+dlv.example. 3600 IN DLV 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+dname01.example. 3600 IN DNAME dname-target.
+dname02.example. 3600 IN DNAME dname-target.example.
+dname03.example. 3600 IN DNAME .
+doa01.example. 3600 IN DOA 1234567890 1234567890 1 "image/gif" R0lGODlhKAAZAOMCAGZmZgBmmf///zOZzMz//5nM/zNmmWbM/5nMzMzMzACZ/////////////////////yH5BAEKAA8ALAAAAAAoABkAAATH8IFJK5U2a4337F5ogRkpnoCJrly7PrCKyh8c3HgAhzT35MDbbtO7/IJIHbGiOiaTxVTpSVWWLqNq1UVyapNS1wd3OAxug0LhnCubcVhsxysQnOt4ATpvvzHlFzl1AwODhWeFAgRpen5/UhheAYMFdUB4SFcpGEGGdQeCAqBBLTuSk30EeXd9pEsAbKGxjHqDSE0Sp6ixN4N1BJmbc7lIhmsBich1awPAjkY1SZR8bJWrz382SGqIBQQFQd4IsUTaX+ceuudPEQA7
+doa02.example. 3600 IN DOA 0 1 2 "" aHR0cHM6Ly93d3cuaXNjLm9yZy8=
+ds01.example. 3600 IN NS ns42.example.
+ds01.example. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13
+ds02.example. 3600 IN NS ns43.example.
+ds02.example. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390
+eid01.example. 3600 IN EID 1289AB
+eui48.example. 3600 IN EUI48 01-23-45-67-89-ab
+eui64.example. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef
+gid01.example. 3600 IN GID \# 1 03
+unspec01.example. 3600 IN UNSPEC \# 1 04
+gpos01.example. 3600 IN GPOS "-22.6882" "116.8652" "250.0"
+gpos02.example. 3600 IN GPOS "" "" ""
+hinfo01.example. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02.example. 3600 IN HINFO "PC" "NetBSD"
+hip1.example. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
+hip2.example. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com.
+https0.example. 3600 IN HTTPS 0 example.net.
+https1.example. 3600 IN HTTPS 1 . port=60
+ipseckey01.example. 3600 IN IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey02.example. 3600 IN IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey03.example. 3600 IN IPSECKEY 10 1 2 192.0.2.3 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey04.example. 3600 IN IPSECKEY 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey05.example. 3600 IN IPSECKEY 10 2 2 2001:db8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+isdn01.example. 3600 IN ISDN "isdn-address"
+isdn02.example. 3600 IN ISDN "isdn-address" "subaddress"
+isdn03.example. 3600 IN ISDN "isdn-address"
+isdn04.example. 3600 IN ISDN "isdn-address" "subaddress"
+dnskey01.example. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+keydata.example. 3600 IN TYPE65533 \# 0
+keydata.example. 3600 IN TYPE65533 \# 6 010203040506
+keydata.example. 3600 IN TYPE65533 \# 18 010203040506010203040506010203040506
+kx01.example. 3600 IN KX 10 kdc.example.
+kx02.example. 3600 IN KX 10 .
+loc01.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+l32.example. 3600 IN L32 10 1.2.3.4
+l64.example. 3600 IN L64 10 14:4fff:ff20:ee64
+lp.example. 3600 IN LP 10 example.net.
+nid.example. 3600 IN NID 10 14:4fff:ff20:ee64
+mb01.example. 3600 IN MG madname.example.
+mb02.example. 3600 IN MG .
+mg01.example. 3600 IN MG mgmname.example.
+mg02.example. 3600 IN MG .
+minfo01.example. 3600 IN MINFO rmailbx.example. emailbx.example.
+minfo02.example. 3600 IN MINFO . .
+mr01.example. 3600 IN MR mrname.example.
+mr02.example. 3600 IN MR .
+mx01.example. 3600 IN MX 10 mail.example.
+mx02.example. 3600 IN MX 10 .
+naptr01.example. 3600 IN NAPTR 0 0 "" "" "" .
+naptr02.example. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+nimloc01.example. 3600 IN NIMLOC 1289AB
+ninfo01.example. 3600 IN NINFO "foo"
+ninfo02.example. 3600 IN NINFO "foo" "bar"
+ninfo03.example. 3600 IN NINFO "foo"
+ninfo04.example. 3600 IN NINFO "foo" "bar"
+ninfo05.example. 3600 IN NINFO "foo bar"
+ninfo06.example. 3600 IN NINFO "foo bar"
+ninfo07.example. 3600 IN NINFO "foo bar"
+ninfo08.example. 3600 IN NINFO "foo\010bar"
+ninfo09.example. 3600 IN NINFO "foo\010bar"
+ninfo10.example. 3600 IN NINFO "foo bar"
+ninfo11.example. 3600 IN NINFO "\"foo\""
+ninfo12.example. 3600 IN NINFO "\"foo\""
+ninfo13.example. 3600 IN NINFO "foo;"
+ninfo14.example. 3600 IN NINFO "foo;"
+ninfo15.example. 3600 IN NINFO "bar\\;"
+ns2.example. 3600 IN A 10.53.0.2
+ns3.example. 3600 IN A 10.53.0.3
+nsap-ptr01.example. 3600 IN NSAP-PTR .
+nsap-ptr01.example. 3600 IN NSAP-PTR foo.
+nsap01.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsec01.example. 3600 IN NSEC a.secure.nil. NS SOA MX LOC RRSIG NSEC DNSKEY
+nsec02.example. 3600 IN NSEC . NSAP-PTR NSEC
+nsec03.example. 3600 IN NSEC . A
+nsec04.example. 3600 IN NSEC . TYPE127
+openpgpkey.example. 3600 IN OPENPGPKEY AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+ptr01.example. 3600 IN PTR example.
+px01.example. 3600 IN PX 65535 foo. bar.
+px02.example. 3600 IN PX 65535 . .
+rkey01.example. 3600 IN RKEY 0 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+rp01.example. 3600 IN RP mbox-dname.example. txt-dname.example.
+rp02.example. 3600 IN RP . .
+rt01.example. 3600 IN RT 0 intermediate-host.example.
+rt02.example. 3600 IN RT 65535 .
+rrsig01.example. 3600 IN RRSIG NSEC 1 3 3600 20000102030405 19961211100908 2143 foo.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+spf01.example. 3600 IN SPF "v=spf1 -all"
+spf02.example. 3600 IN SPF "v=spf1" " -all"
+sshfp01.example. 3600 IN SSHFP 4 2 C76D8329954DA2835751E371544E963EFDA099080D6C58DD2BFD9A31 6E162C83
+sshfp02.example. 3600 IN SSHFP 1 2 BF29468C83AC58CCF8C85AB7B3BEB054ECF1E38512B8353AB36471FA 88961DCC
+sink01.example. 3600 IN SINK 1 0 0
+sink02.example. 3600 IN SINK 8 0 2 l4ik
+smimea.example. 3600 IN SMIMEA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC
+srv01.example. 3600 IN SRV 0 0 0 .
+srv02.example. 3600 IN SRV 65535 65535 65535 old-slow-box.example.
+svcb0.example. 3600 IN SVCB 0 example.net.
+svcb1.example. 3600 IN SVCB 1 . port=60
+ta.example. 3600 IN TA 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+talink0.example. 3600 IN TALINK . talink1.example.
+talink1.example. 3600 IN TALINK talink0.example. talink2.example.
+talink2.example. 3600 IN TALINK talink2.example. .
+tlsa.example. 3600 IN TLSA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC
+txt01.example. 3600 IN TXT "foo"
+txt02.example. 3600 IN TXT "foo" "bar"
+txt03.example. 3600 IN TXT "foo"
+txt04.example. 3600 IN TXT "foo" "bar"
+txt05.example. 3600 IN TXT "foo bar"
+txt06.example. 3600 IN TXT "foo bar"
+txt07.example. 3600 IN TXT "foo bar"
+txt08.example. 3600 IN TXT "foo\010bar"
+txt09.example. 3600 IN TXT "foo\010bar"
+txt10.example. 3600 IN TXT "foo bar"
+txt11.example. 3600 IN TXT "\"foo\""
+txt12.example. 3600 IN TXT "\"foo\""
+txt13.example. 3600 IN TXT "foo;"
+txt14.example. 3600 IN TXT "foo;"
+txt15.example. 3600 IN TXT "bar\\;"
+uid01.example. 3600 IN UID \# 1 02
+uinfo01.example. 3600 IN UINFO \# 1 01
+uri01.example. 3600 IN URI 10 20 "https://www.isc.org/"
+uri02.example. 3600 IN URI 30 40 "https://www.isc.org/HolyCowThisSureIsAVeryLongURIRecordIDontEvenKnowWhatSomeoneWouldEverWantWithSuchAThingButTheSpecificationRequiresThatWesupportItSoHereWeGoTestingItLaLaLaLaLaLaLaSeriouslyThoughWhyWouldYouEvenConsiderUsingAURIThisLongItSeemsLikeASillyIdeaButEnhWhatAreYouGonnaDo/"
+uri03.example. 3600 IN URI 30 40 ""
+wks01.example. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23
+wks02.example. 3600 IN WKS 10.0.0.1 17 0 1 2 53
+wks03.example. 3600 IN WKS 10.0.0.2 6 65535
+x2501.example. 3600 IN X25 "123456789"
+zonemd01.example. 3600 IN ZONEMD 2019020700 1 1 C220B8A6ED5728A971902F7E3D4FD93ADEEA88B0453C2E8E8C863D46 5AB06CF34EB95B266398C98B59124FA239CB7EEB
+zonemd02.example. 3600 IN ZONEMD 2019020700 1 2 08CFA1115C7B948C4163A901270395EA226A930CD2CBCF2FA9A5E6EB 85F37C8A4E114D884E66F176EAB121CB02DB7D652E0CC4827E7A3204 F166B47E5613FD27
+8f1tmio9avcom2k0frp92lgcumak0cad.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C 8FPNS2UCT7FBS643THP2B77PEQ77K6IU A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
+kcd3juae64f9c5csl1kif1htaui7un0g.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C KD5MN2M20340DGO0BL7NTSB8JP4BSC7E
+mr5ukvsk1l37btu4q7b1dfevft4hkqdk.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C MT38J6VG7S0SN5G17MCUF6IQIKFUAJ05 A AAAA RRSIG
+example. 86400 IN SOA ns2.example. hostmaster.example. 1397051952 5 5 1814400 3600
diff --git a/bin/tests/system/xfer/dig2.good b/bin/tests/system/xfer/dig2.good
new file mode 100644
index 0000000..2229f9c
--- /dev/null
+++ b/bin/tests/system/xfer/dig2.good
@@ -0,0 +1,178 @@
+example. 86400 IN SOA ns2.example. hostmaster.example. 1397051953 5 5 1814400 3600
+example. 3600 IN NS ns2.example.
+example. 3600 IN NS ns3.example.
+a01.example. 3600 IN A 0.0.0.1
+a02.example. 3600 IN A 255.255.255.255
+a601.example. 3600 IN A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+a601.example. 3600 IN A6 64 ::ffff:ffff:ffff:ffff foo.
+a601.example. 3600 IN A6 127 ::1 foo.
+a601.example. 3600 IN A6 128 .
+aaaa01.example. 3600 IN AAAA ::1
+aaaa02.example. 3600 IN AAAA fd92:7065:b8e:ffff::5
+afsdb01.example. 3600 IN AFSDB 0 hostname.example.
+afsdb02.example. 3600 IN AFSDB 65535 .
+amtrelay01.example. 3600 IN AMTRELAY 0 0 0
+amtrelay02.example. 3600 IN AMTRELAY 0 1 0
+amtrelay03.example. 3600 IN AMTRELAY 0 0 1 0.0.0.1
+amtrelay04.example. 3600 IN AMTRELAY 0 0 2 ::
+amtrelay05.example. 3600 IN AMTRELAY 0 0 3 example.net.
+amtrelay06.example. 3600 IN AMTRELAY \# 2 0004
+apl01.example. 3600 IN APL !1:10.0.0.1/32 1:10.0.0.1/24
+apl02.example. 3600 IN APL
+atma01.example. 3600 IN ATMA +61200000000
+atma02.example. 3600 IN ATMA +61200000000
+atma03.example. 3600 IN ATMA 1234567890abcdef
+atma04.example. 3600 IN ATMA fedcba0987654321
+avc.example. 3600 IN AVC "foo:bar"
+caa01.example. 3600 IN CAA 0 issue "ca.example.net; policy=ev"
+caa02.example. 3600 IN CAA 128 tbs "Unknown"
+caa03.example. 3600 IN CAA 128 tbs ""
+cdnskey01.example. 3600 IN CDNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+cds01.example. 3600 IN CDS 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+cert01.example. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+cname01.example. 3600 IN CNAME cname-target.
+cname02.example. 3600 IN CNAME cname-target.example.
+cname03.example. 3600 IN CNAME .
+csync01.example. 3600 IN CSYNC 0 0 A NS AAAA
+csync02.example. 3600 IN CSYNC 0 0
+dhcid01.example. 3600 IN DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA=
+dhcid02.example. 3600 IN DHCID AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQdWL3b/NaiUDlW2No=
+dhcid03.example. 3600 IN DHCID AAABxLmlskllE0MVjd57zHcWmEH3pCQ6VytcKD//7es/deY=
+dlv.example. 3600 IN DLV 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+dname01.example. 3600 IN DNAME dname-target.
+dname02.example. 3600 IN DNAME dname-target.example.
+dname03.example. 3600 IN DNAME .
+doa01.example. 3600 IN DOA 1234567890 1234567890 1 "image/gif" R0lGODlhKAAZAOMCAGZmZgBmmf///zOZzMz//5nM/zNmmWbM/5nMzMzMzACZ/////////////////////yH5BAEKAA8ALAAAAAAoABkAAATH8IFJK5U2a4337F5ogRkpnoCJrly7PrCKyh8c3HgAhzT35MDbbtO7/IJIHbGiOiaTxVTpSVWWLqNq1UVyapNS1wd3OAxug0LhnCubcVhsxysQnOt4ATpvvzHlFzl1AwODhWeFAgRpen5/UhheAYMFdUB4SFcpGEGGdQeCAqBBLTuSk30EeXd9pEsAbKGxjHqDSE0Sp6ixN4N1BJmbc7lIhmsBich1awPAjkY1SZR8bJWrz382SGqIBQQFQd4IsUTaX+ceuudPEQA7
+doa02.example. 3600 IN DOA 0 1 2 "" aHR0cHM6Ly93d3cuaXNjLm9yZy8=
+ds01.example. 3600 IN NS ns42.example.
+ds01.example. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13
+ds02.example. 3600 IN NS ns43.example.
+ds02.example. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390
+eid01.example. 3600 IN EID 1289AB
+eui48.example. 3600 IN EUI48 01-23-45-67-89-ab
+eui64.example. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef
+gid01.example. 3600 IN GID \# 1 03
+unspec01.example. 3600 IN UNSPEC \# 1 04
+gpos01.example. 3600 IN GPOS "-22.6882" "116.8652" "250.0"
+gpos02.example. 3600 IN GPOS "" "" ""
+hinfo01.example. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02.example. 3600 IN HINFO "PC" "NetBSD"
+ipseckey01.example. 3600 IN IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey02.example. 3600 IN IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey03.example. 3600 IN IPSECKEY 10 1 2 192.0.2.3 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey04.example. 3600 IN IPSECKEY 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+ipseckey05.example. 3600 IN IPSECKEY 10 2 2 2001:db8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==
+isdn01.example. 3600 IN ISDN "isdn-address"
+isdn02.example. 3600 IN ISDN "isdn-address" "subaddress"
+isdn03.example. 3600 IN ISDN "isdn-address"
+isdn04.example. 3600 IN ISDN "isdn-address" "subaddress"
+hip1.example. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
+hip2.example. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com.
+dnskey01.example. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+https0.example. 3600 IN HTTPS 0 example.net.
+https1.example. 3600 IN HTTPS 1 . port=60
+keydata.example. 3600 IN TYPE65533 \# 0
+keydata.example. 3600 IN TYPE65533 \# 6 010203040506
+keydata.example. 3600 IN TYPE65533 \# 18 010203040506010203040506010203040506
+kx01.example. 3600 IN KX 10 kdc.example.
+kx02.example. 3600 IN KX 10 .
+loc01.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+l32.example. 3600 IN L32 10 1.2.3.4
+l64.example. 3600 IN L64 10 14:4fff:ff20:ee64
+lp.example. 3600 IN LP 10 example.net.
+nid.example. 3600 IN NID 10 14:4fff:ff20:ee64
+mb01.example. 3600 IN MG madname.example.
+mb02.example. 3600 IN MG .
+mg01.example. 3600 IN MG mgmname.example.
+mg02.example. 3600 IN MG .
+minfo01.example. 3600 IN MINFO rmailbx.example. emailbx.example.
+minfo02.example. 3600 IN MINFO . .
+mr01.example. 3600 IN MR mrname.example.
+mr02.example. 3600 IN MR .
+mx01.example. 3600 IN MX 10 mail.example.
+mx02.example. 3600 IN MX 10 .
+naptr01.example. 3600 IN NAPTR 0 0 "" "" "" .
+naptr02.example. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo.
+nimloc01.example. 3600 IN NIMLOC 1289AB
+ninfo01.example. 3600 IN NINFO "foo"
+ninfo02.example. 3600 IN NINFO "foo" "bar"
+ninfo03.example. 3600 IN NINFO "foo"
+ninfo04.example. 3600 IN NINFO "foo" "bar"
+ninfo05.example. 3600 IN NINFO "foo bar"
+ninfo06.example. 3600 IN NINFO "foo bar"
+ninfo07.example. 3600 IN NINFO "foo bar"
+ninfo08.example. 3600 IN NINFO "foo\010bar"
+ninfo09.example. 3600 IN NINFO "foo\010bar"
+ninfo10.example. 3600 IN NINFO "foo bar"
+ninfo11.example. 3600 IN NINFO "\"foo\""
+ninfo12.example. 3600 IN NINFO "\"foo\""
+ninfo13.example. 3600 IN NINFO "foo;"
+ninfo14.example. 3600 IN NINFO "foo;"
+ninfo15.example. 3600 IN NINFO "bar\\;"
+ns2.example. 3600 IN A 10.53.0.2
+ns3.example. 3600 IN A 10.53.0.3
+nsap-ptr01.example. 3600 IN NSAP-PTR .
+nsap-ptr01.example. 3600 IN NSAP-PTR foo.
+nsap01.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsec01.example. 3600 IN NSEC a.secure.nil. NS SOA MX LOC RRSIG NSEC DNSKEY
+nsec02.example. 3600 IN NSEC . NSAP-PTR NSEC
+nsec03.example. 3600 IN NSEC . A
+nsec04.example. 3600 IN NSEC . TYPE127
+openpgpkey.example. 3600 IN OPENPGPKEY AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+ptr01.example. 3600 IN PTR example.
+px01.example. 3600 IN PX 65535 foo. bar.
+px02.example. 3600 IN PX 65535 . .
+rkey01.example. 3600 IN RKEY 0 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+rp01.example. 3600 IN RP mbox-dname.example. txt-dname.example.
+rp02.example. 3600 IN RP . .
+rt01.example. 3600 IN RT 0 intermediate-host.example.
+rt02.example. 3600 IN RT 65535 .
+rrsig01.example. 3600 IN RRSIG NSEC 1 3 3600 20000102030405 19961211100908 2143 foo.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+sink01.example. 3600 IN SINK 1 0 0
+sink02.example. 3600 IN SINK 8 0 2 l4ik
+smimea.example. 3600 IN SMIMEA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC
+spf01.example. 3600 IN SPF "v=spf1 -all"
+spf02.example. 3600 IN SPF "v=spf1" " -all"
+srv01.example. 3600 IN SRV 0 0 0 .
+srv02.example. 3600 IN SRV 65535 65535 65535 old-slow-box.example.
+sshfp01.example. 3600 IN SSHFP 4 2 C76D8329954DA2835751E371544E963EFDA099080D6C58DD2BFD9A31 6E162C83
+sshfp02.example. 3600 IN SSHFP 1 2 BF29468C83AC58CCF8C85AB7B3BEB054ECF1E38512B8353AB36471FA 88961DCC
+svcb0.example. 3600 IN SVCB 0 example.net.
+svcb1.example. 3600 IN SVCB 1 . port=60
+ta.example. 3600 IN TA 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
+talink0.example. 3600 IN TALINK . talink1.example.
+talink1.example. 3600 IN TALINK talink0.example. talink2.example.
+talink2.example. 3600 IN TALINK talink2.example. .
+tlsa.example. 3600 IN TLSA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC
+txt01.example. 3600 IN TXT "foo"
+txt02.example. 3600 IN TXT "foo" "bar"
+txt03.example. 3600 IN TXT "foo"
+txt04.example. 3600 IN TXT "foo" "bar"
+txt05.example. 3600 IN TXT "foo bar"
+txt06.example. 3600 IN TXT "foo bar"
+txt07.example. 3600 IN TXT "foo bar"
+txt08.example. 3600 IN TXT "foo\010bar"
+txt09.example. 3600 IN TXT "foo\010bar"
+txt10.example. 3600 IN TXT "foo bar"
+txt11.example. 3600 IN TXT "\"foo\""
+txt12.example. 3600 IN TXT "\"foo\""
+txt13.example. 3600 IN TXT "foo;"
+txt14.example. 3600 IN TXT "foo;"
+txt15.example. 3600 IN TXT "bar\\;"
+uid01.example. 3600 IN UID \# 1 02
+uinfo01.example. 3600 IN UINFO \# 1 01
+uri01.example. 3600 IN URI 10 20 "https://www.isc.org/"
+uri02.example. 3600 IN URI 30 40 "https://www.isc.org/HolyCowThisSureIsAVeryLongURIRecordIDontEvenKnowWhatSomeoneWouldEverWantWithSuchAThingButTheSpecificationRequiresThatWesupportItSoHereWeGoTestingItLaLaLaLaLaLaLaSeriouslyThoughWhyWouldYouEvenConsiderUsingAURIThisLongItSeemsLikeASillyIdeaButEnhWhatAreYouGonnaDo/"
+uri03.example. 3600 IN URI 30 40 ""
+wks01.example. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23
+wks02.example. 3600 IN WKS 10.0.0.1 17 0 1 2 53
+wks03.example. 3600 IN WKS 10.0.0.2 6 65535
+x2501.example. 3600 IN X25 "123456789"
+zonemd01.example. 3600 IN ZONEMD 2019020700 1 1 C220B8A6ED5728A971902F7E3D4FD93ADEEA88B0453C2E8E8C863D46 5AB06CF34EB95B266398C98B59124FA239CB7EEB
+zonemd02.example. 3600 IN ZONEMD 2019020700 1 2 08CFA1115C7B948C4163A901270395EA226A930CD2CBCF2FA9A5E6EB 85F37C8A4E114D884E66F176EAB121CB02DB7D652E0CC4827E7A3204 F166B47E5613FD27
+8f1tmio9avcom2k0frp92lgcumak0cad.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C 8FPNS2UCT7FBS643THP2B77PEQ77K6IU A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
+kcd3juae64f9c5csl1kif1htaui7un0g.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C KD5MN2M20340DGO0BL7NTSB8JP4BSC7E
+mr5ukvsk1l37btu4q7b1dfevft4hkqdk.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C MT38J6VG7S0SN5G17MCUF6IQIKFUAJ05 A AAAA RRSIG
+example. 86400 IN SOA ns2.example. hostmaster.example. 1397051953 5 5 1814400 3600
diff --git a/bin/tests/system/xfer/dig3.good b/bin/tests/system/xfer/dig3.good
new file mode 100644
index 0000000..d58c421
--- /dev/null
+++ b/bin/tests/system/xfer/dig3.good
@@ -0,0 +1,6 @@
+dot-fallback. 5 IN SOA ns1.dot-fallback. hostmaster.dot-fallback. 1 3600 3600 3600 3600
+dot-fallback. 5 IN NS ns1.dot-fallback.
+a01.dot-fallback. 5 IN A 1.1.1.1
+a02.dot-fallback. 5 IN A 255.255.255.255
+ns1.dot-fallback. 5 IN A 10.53.0.1
+dot-fallback. 5 IN SOA ns1.dot-fallback. hostmaster.dot-fallback. 1 3600 3600 3600 3600
diff --git a/bin/tests/system/xfer/knowngood.mapped b/bin/tests/system/xfer/knowngood.mapped
new file mode 100644
index 0000000..5fcd00b
--- /dev/null
+++ b/bin/tests/system/xfer/knowngood.mapped
@@ -0,0 +1,26 @@
+
+; <<>> DiG 9.10.2-P3 <<>> -p 5300 axfr mapped @10.53.0.3
+;; global options: +cmd
+mapped. 3600 IN SOA . . 0 0 0 2147483647 0
+example.aa. 3600 IN A 1.2.3.4
+example1.aa. 3600 IN A 1.2.3.4
+example.bb. 3600 IN A 1.2.3.4
+example1.bb. 3600 IN A 1.2.3.4
+example.com. 3600 IN A 1.2.3.4
+example1.com. 3600 IN A 1.2.3.4
+bar.dd. 3600 IN A 1.2.3.4
+foo.ee. 3600 IN A 1.2.3.4
+foo.ff. 3600 IN A 1.2.3.4
+foo.gg. 3600 IN A 1.2.3.4
+foo.hh. 3600 IN A 1.2.3.4
+foo.ii. 3600 IN A 1.2.3.4
+foo.jj. 3600 IN A 1.2.3.4
+foo.kk. 3600 IN A 1.2.3.4
+foo.ll. 3600 IN A 1.2.3.4
+mapped. 3600 IN NS .
+mapped. 3600 IN SOA . . 0 0 0 2147483647 0
+;; Query time: 4 msec
+;; SERVER: 10.53.0.3#5300(10.53.0.3)
+;; WHEN: Tue Feb 16 14:38:25 EST 2016
+;; XFR size: 18 records (messages 1, bytes 468)
+
diff --git a/bin/tests/system/xfer/ns1/axfr-max-idle-time.db b/bin/tests/system/xfer/ns1/axfr-max-idle-time.db
new file mode 100644
index 0000000..252925f
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/axfr-max-idle-time.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA . . 0 0 0 0 0
+@ IN NS .
+$GENERATE 1-5000 host$ TXT data-$
diff --git a/bin/tests/system/xfer/ns1/axfr-max-transfer-time.db b/bin/tests/system/xfer/ns1/axfr-max-transfer-time.db
new file mode 100644
index 0000000..252925f
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/axfr-max-transfer-time.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA . . 0 0 0 0 0
+@ IN NS .
+$GENERATE 1-5000 host$ TXT data-$
diff --git a/bin/tests/system/xfer/ns1/axfr-too-big.db b/bin/tests/system/xfer/ns1/axfr-too-big.db
new file mode 100644
index 0000000..37987a6
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/axfr-too-big.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA . . 0 0 0 0 0
+@ IN NS .
+$GENERATE 1-29 host$ A 1.2.3.$
diff --git a/bin/tests/system/xfer/ns1/dot-fallback.db.in b/bin/tests/system/xfer/ns1/dot-fallback.db.in
new file mode 100644
index 0000000..997f5ba
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/dot-fallback.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 5
+
+@ IN SOA ns1 hostmaster 1 3600 3600 3600 3600
+@ NS ns1
+ns1 A 10.53.0.1
+a01 A 1.1.1.1
+a02 A 255.255.255.255
+
diff --git a/bin/tests/system/xfer/ns1/ixfr-too-big.db.in b/bin/tests/system/xfer/ns1/ixfr-too-big.db.in
new file mode 100644
index 0000000..c192316
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/ixfr-too-big.db.in
@@ -0,0 +1,18 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ IN SOA . . 0 0 0 0 0
+@ IN NS ns1
+@ IN NS ns6
+ns1 IN A 10.53.0.1
+ns6 IN A 10.53.0.6
+$GENERATE 1-25 host$ A 1.2.3.$
diff --git a/bin/tests/system/xfer/ns1/named1.conf.in b/bin/tests/system/xfer/ns1/named1.conf.in
new file mode 100644
index 0000000..d7ce420
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/named1.conf.in
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "secondary" {
+ type primary;
+ file "sec.db";
+};
+
+zone "edns-expire" {
+ type primary;
+ file "edns-expire.db";
+};
+
+zone "axfr-max-transfer-time" {
+ type primary;
+ file "axfr-max-transfer-time.db";
+};
+
+zone "axfr-max-idle-time" {
+ type primary;
+ file "axfr-max-idle-time.db";
+};
+
+zone "axfr-too-big" {
+ type primary;
+ file "axfr-too-big.db";
+};
+
+zone "ixfr-too-big" {
+ type primary;
+ allow-update { any; };
+ file "ixfr-too-big.db";
+};
+
+zone "xfer-stats" {
+ type primary;
+ file "xfer-stats.db";
+};
+
+zone "dot-fallback" {
+ type primary;
+ file "dot-fallback.db";
+};
diff --git a/bin/tests/system/xfer/ns1/named2.conf.in b/bin/tests/system/xfer/ns1/named2.conf.in
new file mode 100644
index 0000000..b349c33
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/named2.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "axfr-max-transfer-time" {
+ type primary;
+ file "axfr-max-transfer-time.db";
+};
diff --git a/bin/tests/system/xfer/ns1/named3.conf.in b/bin/tests/system/xfer/ns1/named3.conf.in
new file mode 100644
index 0000000..05af961
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/named3.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+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;
+ dnssec-validation no;
+ notify yes;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "axfr-max-idle-time" {
+ type primary;
+ file "axfr-max-idle-time.db";
+};
diff --git a/bin/tests/system/xfer/ns1/root.db b/bin/tests/system/xfer/ns1/root.db
new file mode 100644
index 0000000..58a675c
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/root.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+tsigzone. NS ns2.tsigzone.
+ns2.tsigzone. A 10.53.0.2
diff --git a/bin/tests/system/xfer/ns1/xfer-stats.db b/bin/tests/system/xfer/ns1/xfer-stats.db
new file mode 100644
index 0000000..42e1c9c
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/xfer-stats.db
@@ -0,0 +1,15 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 3600
+@ SOA . . 0 0 0 0 0
+@ NS .
+$GENERATE 1-10000 $ TXT $
diff --git a/bin/tests/system/xfer/ns2/mapped.db.in b/bin/tests/system/xfer/ns2/mapped.db.in
new file mode 100644
index 0000000..d928d69
--- /dev/null
+++ b/bin/tests/system/xfer/ns2/mapped.db.in
@@ -0,0 +1,28 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+mapped. 3600 IN SOA . . 0 0 0 2147483647 0
+example.aa. 3600 IN A 1.2.3.4
+example1.aa. 3600 IN A 1.2.3.4
+example.bb. 3600 IN A 1.2.3.4
+example1.bb. 3600 IN A 1.2.3.4
+example.com. 3600 IN A 1.2.3.4
+example1.com. 3600 IN A 1.2.3.4
+bar.dd. 3600 IN A 1.2.3.4
+foo.ee. 3600 IN A 1.2.3.4
+foo.ff. 3600 IN A 1.2.3.4
+foo.gg. 3600 IN A 1.2.3.4
+foo.hh. 3600 IN A 1.2.3.4
+foo.ii. 3600 IN A 1.2.3.4
+foo.jj. 3600 IN A 1.2.3.4
+foo.kk. 3600 IN A 1.2.3.4
+foo.ll. 3600 IN A 1.2.3.4
+mapped. 3600 IN NS .
diff --git a/bin/tests/system/xfer/ns2/named.conf.in b/bin/tests/system/xfer/ns2/named.conf.in
new file mode 100644
index 0000000..b81bd1c
--- /dev/null
+++ b/bin/tests/system/xfer/ns2/named.conf.in
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key tsigzone. {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+acl tzkey {
+ key tsigzone.;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type primary;
+ file "tsigzone.db";
+ allow-transfer { tzkey; };
+};
+
+zone "secondary" {
+ type secondary;
+ file "sec.db";
+ primaries { 10.53.0.1; };
+ masterfile-format text;
+};
+
+zone "mapped" {
+ type secondary;
+ file "mapped.db";
+ masterfile-format text;
+ primaries { 10.53.0.100; };
+};
+
+zone "dot-fallback" {
+ type secondary;
+ file "dot-fallback.db";
+ primaries {
+ 10.53.0.1 tls ephemeral;
+ 10.53.0.1;
+ };
+};
diff --git a/bin/tests/system/xfer/ns2/sec.db.in b/bin/tests/system/xfer/ns2/sec.db.in
new file mode 100644
index 0000000..7978598
--- /dev/null
+++ b/bin/tests/system/xfer/ns2/sec.db.in
@@ -0,0 +1,19 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 5
+
+@ IN SOA ns1 hostmaster 1 5 5 5 5
+@ NS ns1
+ns1 A 10.53.0.1
+a01 A 1.1.1.1
+a02 A 255.255.255.255
+
diff --git a/bin/tests/system/xfer/ns3/named.conf.in b/bin/tests/system/xfer/ns3/named.conf.in
new file mode 100644
index 0000000..16d0759
--- /dev/null
+++ b/bin/tests/system/xfer/ns3/named.conf.in
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+key tsigzone. {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "example.bk";
+};
+
+zone "primary" {
+ type secondary;
+ transfer-source 10.53.0.3 port @EXTRAPORT1@;
+ primaries { 10.53.0.6; };
+ file "primary.bk";
+};
+
+server 10.53.0.2 {
+ keys { tsigzone.; };
+};
+
+zone "tsigzone" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "tsigzone.bk";
+ allow-transfer { key tsigzone.; };
+};
+
+zone "mapped" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ masterfile-format raw;
+ file "mapped.bk";
+};
+
+zone "xfer-stats" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "xfer-stats.bk";
+};
diff --git a/bin/tests/system/xfer/ns4/named.conf.base b/bin/tests/system/xfer/ns4/named.conf.base
new file mode 100644
index 0000000..35311e1
--- /dev/null
+++ b/bin/tests/system/xfer/ns4/named.conf.base
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ blackhole { none; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+key unused_key. {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+key tsig_key. {
+ secret "LSAnCU+Z";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/xfer/ns4/root.db.in b/bin/tests/system/xfer/ns4/root.db.in
new file mode 100644
index 0000000..29ee0ec
--- /dev/null
+++ b/bin/tests/system/xfer/ns4/root.db.in
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 0 SOA . . 0 0 0 0 0
+@ 0 NS .
+@ 0 A 10.53.0.4
diff --git a/bin/tests/system/xfer/ns6/named.args b/bin/tests/system/xfer/ns6/named.args
new file mode 100644
index 0000000..2be062b
--- /dev/null
+++ b/bin/tests/system/xfer/ns6/named.args
@@ -0,0 +1 @@
+-D xfer-ns6 -X named.lock -m record -c named.conf -d 99 -g -U 4 -T maxcachesize=2097152 -T transferinsecs
diff --git a/bin/tests/system/xfer/ns6/named.conf.in b/bin/tests/system/xfer/ns6/named.conf.in
new file mode 100644
index 0000000..87397b0
--- /dev/null
+++ b/bin/tests/system/xfer/ns6/named.conf.in
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ 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.6; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ ixfr-from-differences primary;
+ check-integrity no;
+ tcp-idle-timeout 600;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "primary" {
+ type primary;
+ file "primary.db";
+};
+
+zone "secondary" {
+ type secondary;
+ notify no;
+ primaries { 10.53.0.1; };
+ file "sec.bk";
+};
+
+zone "edns-expire" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "edns-expire.bk";
+};
+
+zone "axfr-max-transfer-time" {
+ type secondary;
+ max-transfer-time-in 1; # this is tested as seconds, when used with '-T transferinsecs'
+ primaries { 10.53.0.1; };
+ file "axfr-max-transfer-time.bk";
+};
+
+zone "axfr-max-idle-time" {
+ type secondary;
+ max-transfer-idle-in 50; # this is tested as seconds, when used with '-T transferinsecs'
+ primaries { 10.53.0.1; };
+ file "axfr-max-idle-time.bk";
+};
+
+zone "axfr-too-big" {
+ type secondary;
+ max-records 30;
+ primaries { 10.53.0.1; };
+ file "axfr-too-big.bk";
+};
+
+zone "ixfr-too-big" {
+ type secondary;
+ max-records 30;
+ primaries { 10.53.0.1; };
+ file "ixfr-too-big.bk";
+};
diff --git a/bin/tests/system/xfer/ns7/named.conf.in b/bin/tests/system/xfer/ns7/named.conf.in
new file mode 100644
index 0000000..47a9b05
--- /dev/null
+++ b/bin/tests/system/xfer/ns7/named.conf.in
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ 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.7; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+ ixfr-from-differences secondary;
+ check-integrity no;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "primary2" {
+ type primary;
+ file "primary2.db";
+};
+
+zone "secondary" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "sec.bk";
+};
+
+zone "edns-expire" {
+ type secondary;
+ primaries { 10.53.0.6; };
+ file "edns-expire.bk";
+};
diff --git a/bin/tests/system/xfer/ns8/example.db b/bin/tests/system/xfer/ns8/example.db
new file mode 100644
index 0000000..8e8ccb9
--- /dev/null
+++ b/bin/tests/system/xfer/ns8/example.db
@@ -0,0 +1,24 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+$INCLUDE large.db
+$INCLUDE small.db
diff --git a/bin/tests/system/xfer/ns8/named.conf.in b/bin/tests/system/xfer/ns8/named.conf.in
new file mode 100644
index 0000000..831e934
--- /dev/null
+++ b/bin/tests/system/xfer/ns8/named.conf.in
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "../../common/rndc.key";
+
+controls {
+ inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+options {
+ query-source address 10.53.0.8;
+ notify-source 10.53.0.8;
+ transfer-source 10.53.0.8;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.8; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+ transfer-message-size 1024;
+};
+
+key key1. {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+acl tzkey {
+ key key1.;
+};
+
+zone "example." {
+ type primary;
+ file "example.db";
+ allow-transfer { tzkey; };
+};
diff --git a/bin/tests/system/xfer/prereq.sh b/bin/tests/system/xfer/prereq.sh
new file mode 100644
index 0000000..c7b7828
--- /dev/null
+++ b/bin/tests/system/xfer/prereq.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+# macOS ships with Net::DNS 0.74 which does not work with
+# HMAC-SHA256, despite the workarounds in ans.pl
+
+if perl -MNet::DNS -e 'exit $Net::DNS::VERSION >= 1.0'
+then
+ version=$(perl -MNet::DNS -e 'print $Net::DNS::VERSION')
+ echo_i "perl Net::DNS $version is too old - skipping xfer test"
+ exit 1
+fi
+
+exit 0
diff --git a/bin/tests/system/xfer/setup.sh b/bin/tests/system/xfer/setup.sh
new file mode 100644
index 0000000..ff64d8f
--- /dev/null
+++ b/bin/tests/system/xfer/setup.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 1 6 7 >ns1/sec.db
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 1 6 7 >ns1/edns-expire.db
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 3 >ns2/example.db
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 3 >ns2/tsigzone.db
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 6 3 >ns6/primary.db
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 7 >ns7/primary2.db
+
+cp -f ns4/root.db.in ns4/root.db
+$PERL -e 'for ($i=0;$i<10000;$i++){ printf("x%u 0 in a 10.53.0.1\n", $i);}' >> ns4/root.db
+
+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
+copy_setports ns6/named.conf.in ns6/named.conf
+copy_setports ns7/named.conf.in ns7/named.conf
+copy_setports ns8/named.conf.in ns8/named.conf
+
+copy_setports ns4/named.conf.base ns4/named.conf
+
+cp ns1/dot-fallback.db.in ns1/dot-fallback.db
+
+cp ns2/sec.db.in ns2/sec.db
+touch -t 200101010000 ns2/sec.db
+
+cp ns2/mapped.db.in ns2/mapped.db
+
+$PERL -e 'for ($i=0;$i<4096;$i++){ printf("name%u 259200 A 1.2.3.4\nname%u 259200 TXT \"Hello World %u\"\n", $i, $i, $i);}' > ns8/small.db
+$PERL -e 'printf("large IN TYPE45234 \\# 48000 "); for ($i=0;$i<16*3000;$i++) { printf("%02x", $i % 256); } printf("\n");' > ns8/large.db
+
+cp -f ns1/ixfr-too-big.db.in ns1/ixfr-too-big.db
diff --git a/bin/tests/system/xfer/tests.sh b/bin/tests/system/xfer/tests.sh
new file mode 100755
index 0000000..f012d8b
--- /dev/null
+++ b/bin/tests/system/xfer/tests.sh
@@ -0,0 +1,627 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+NS_PARAMS="-X named.lock -m record -c named.conf -d 99 -g -U 4 -T maxcachesize=2097152"
+
+status=0
+n=0
+
+n=$((n+1))
+echo_i "testing basic zone transfer functionality (from primary) ($n)"
+tmp=0
+$DIG $DIGOPTS example. @10.53.0.2 axfr > dig.out.ns2.test$n || tmp=1
+grep "^;" dig.out.ns2.test$n | cat_i
+digcomp dig1.good dig.out.ns2.test$n || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "testing basic zone transfer functionality (from secondary) ($n)"
+tmp=0
+#
+# Spin to allow the zone to transfer.
+#
+wait_for_xfer () {
+ ZONE=$1
+ SERVER=$2
+ $DIG $DIGOPTS $ZONE @$SERVER axfr > dig.out.test$n || return 1
+ grep "^;" dig.out.test$n > /dev/null && return 1
+ return 0
+}
+retry_quiet 25 wait_for_xfer example. 10.53.0.3 || tmp=1
+grep "^;" dig.out.test$n | cat_i
+digcomp dig1.good dig.out.test$n || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "testing zone transfer functionality (fallback to DNS after DoT failed) ($n)"
+tmp=0
+retry_quiet 25 wait_for_xfer dot-fallback. 10.53.0.2 || tmp=1
+grep "^;" dig.out.test$n | cat_i
+digcomp dig3.good dig.out.test$n || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "testing TSIG signed zone transfers ($n)"
+tmp=0
+$DIG $DIGOPTS tsigzone. @10.53.0.2 axfr -y tsigzone.:1234abcd8765 > dig.out.ns2.test$n || tmp=1
+grep "^;" dig.out.ns2.test$n | cat_i
+
+#
+# Spin to allow the zone to transfer.
+#
+wait_for_xfer_tsig () {
+ $DIG $DIGOPTS tsigzone. @10.53.0.3 axfr -y tsigzone.:1234abcd8765 > dig.out.ns3.test$n || return 1
+ grep "^;" dig.out.ns3.test$n > /dev/null && return 1
+ return 0
+}
+retry_quiet 25 wait_for_xfer_tsig || tmp=1
+grep "^;" dig.out.ns3.test$n | cat_i
+digcomp dig.out.ns2.test$n dig.out.ns3.test$n || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+echo_i "reload servers for in preparation for ixfr-from-differences tests"
+
+rndc_reload ns1 10.53.0.1
+rndc_reload ns2 10.53.0.2
+rndc_reload ns3 10.53.0.3
+rndc_reload ns6 10.53.0.6
+rndc_reload ns7 10.53.0.7
+
+sleep 2
+
+echo_i "updating primary zones for ixfr-from-differences tests"
+
+$PERL -i -p -e '
+ s/0\.0\.0\.0/0.0.0.1/;
+ s/1397051952/1397051953/
+' ns1/sec.db
+
+rndc_reload ns1 10.53.0.1
+
+$PERL -i -p -e '
+ s/0\.0\.0\.0/0.0.0.1/;
+ s/1397051952/1397051953/
+' ns2/example.db
+
+rndc_reload ns2 10.53.0.2
+
+$PERL -i -p -e '
+ s/0\.0\.0\.0/0.0.0.1/;
+ s/1397051952/1397051953/
+' ns6/primary.db
+
+rndc_reload ns6 10.53.0.6
+
+$PERL -i -p -e '
+ s/0\.0\.0\.0/0.0.0.1/;
+ s/1397051952/1397051953/
+' ns7/primary2.db
+
+rndc_reload ns7 10.53.0.7
+
+sleep 3
+
+n=$((n+1))
+echo_i "testing zone is dumped after successful transfer ($n)"
+tmp=0
+$DIG $DIGOPTS +noall +answer +multi @10.53.0.2 \
+ secondary. soa > dig.out.ns2.test$n || tmp=1
+grep "1397051952 ; serial" dig.out.ns2.test$n > /dev/null 2>&1 || tmp=1
+grep "1397051952 ; serial" ns2/sec.db > /dev/null 2>&1 || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "testing ixfr-from-differences yes; ($n)"
+tmp=0
+
+echo_i "wait for reloads..."
+wait_for_reloads() (
+ $DIG $DIGOPTS @10.53.0.6 +noall +answer soa primary > dig.out.soa1.ns6.test$n
+ grep "1397051953" dig.out.soa1.ns6.test$n > /dev/null || return 1
+ $DIG $DIGOPTS @10.53.0.1 +noall +answer soa secondary > dig.out.soa2.ns1.test$n
+ grep "1397051953" dig.out.soa2.ns1.test$n > /dev/null || return 1
+ $DIG $DIGOPTS @10.53.0.2 +noall +answer soa example > dig.out.soa3.ns2.test$n
+ grep "1397051953" dig.out.soa3.ns2.test$n > /dev/null || return 1
+ return 0
+)
+retry_quiet 20 wait_for_reloads || tmp=1
+
+echo_i "wait for transfers..."
+wait_for_transfers() (
+ a=0 b=0 c=0 d=0
+ $DIG $DIGOPTS @10.53.0.3 +noall +answer soa example > dig.out.soa1.ns3.test$n
+ grep "1397051953" dig.out.soa1.ns3.test$n > /dev/null && a=1
+ $DIG $DIGOPTS @10.53.0.3 +noall +answer soa primary > dig.out.soa2.ns3.test$n
+ grep "1397051953" dig.out.soa2.ns3.test$n > /dev/null && b=1
+ $DIG $DIGOPTS @10.53.0.6 +noall +answer soa secondary > dig.out.soa3.ns6.test$n
+ grep "1397051953" dig.out.soa3.ns6.test$n > /dev/null && c=1
+ [ $a -eq 1 -a $b -eq 1 -a $c -eq 1 ] && return 0
+
+ # re-notify if necessary
+ $RNDCCMD 10.53.0.6 notify primary 2>&1 | sed 's/^/ns6 /' | cat_i
+ $RNDCCMD 10.53.0.1 notify secondary 2>&1 | sed 's/^/ns1 /' | cat_i
+ $RNDCCMD 10.53.0.2 notify example 2>&1 | sed 's/^/ns2 /' | cat_i
+ return 1
+)
+retry_quiet 20 wait_for_transfers || tmp=1
+
+$DIG $DIGOPTS example. \
+ @10.53.0.3 axfr > dig.out.ns3.test$n || tmp=1
+grep "^;" dig.out.ns3.test$n | cat_i
+
+digcomp dig2.good dig.out.ns3.test$n || tmp=1
+
+# ns3 has a journal iff it received an IXFR.
+test -f ns3/example.bk || tmp=1
+test -f ns3/example.bk.jnl || tmp=1
+
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "testing ixfr-from-differences primary; (primary zone) ($n)"
+tmp=0
+
+$DIG $DIGOPTS primary. \
+ @10.53.0.6 axfr > dig.out.ns6.test$n || tmp=1
+grep "^;" dig.out.ns6.test$n | cat_i
+
+$DIG $DIGOPTS primary. \
+ @10.53.0.3 axfr > dig.out.ns3.test$n || tmp=1
+grep "^;" dig.out.ns3.test$n > /dev/null && cat_i < dig.out.ns3.test$n
+
+digcomp dig.out.ns6.test$n dig.out.ns3.test$n || tmp=1
+
+# ns3 has a journal iff it received an IXFR.
+test -f ns3/primary.bk || tmp=1
+test -f ns3/primary.bk.jnl || tmp=1
+
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "testing ixfr-from-differences primary; (secondary zone) ($n)"
+tmp=0
+
+$DIG $DIGOPTS secondary. \
+ @10.53.0.6 axfr > dig.out.ns6.test$n || tmp=1
+grep "^;" dig.out.ns6.test$n | cat_i
+
+$DIG $DIGOPTS secondary. \
+ @10.53.0.1 axfr > dig.out.ns1.test$n || tmp=1
+grep "^;" dig.out.ns1.test$n | cat_i
+
+digcomp dig.out.ns6.test$n dig.out.ns1.test$n || tmp=1
+
+# ns6 has a journal iff it received an IXFR.
+test -f ns6/sec.bk || tmp=1
+test -f ns6/sec.bk.jnl && tmp=1
+
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "testing ixfr-from-differences secondary; (secondary zone) ($n)"
+tmp=0
+
+# ns7 has a journal iff it generates an IXFR.
+test -f ns7/primary2.db || tmp=1
+test -f ns7/primary2.db.jnl && tmp=1
+
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "testing ixfr-from-differences secondary; (secondary zone) ($n)"
+tmp=0
+
+$DIG $DIGOPTS secondary. \
+ @10.53.0.1 axfr > dig.out.ns1.test$n || tmp=1
+grep "^;" dig.out.ns1.test$n | cat_i
+
+$DIG $DIGOPTS secondary. \
+ @10.53.0.7 axfr > dig.out.ns7.test$n || tmp=1
+grep "^;" dig.out.ns7.test$n | cat_i
+
+digcomp dig.out.ns7.test$n dig.out.ns1.test$n || tmp=1
+
+# ns7 has a journal iff it generates an IXFR.
+test -f ns7/sec.bk || tmp=1
+test -f ns7/sec.bk.jnl || tmp=1
+
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "check that a multi-message uncompressable zone transfers ($n)"
+$DIG axfr . -p ${PORT} @10.53.0.4 | grep SOA > axfr.out
+if test $(wc -l < axfr.out) != 2
+then
+ echo_i "failed"
+ status=$((status+1))
+fi
+
+# now we test transfers with assorted TSIG glitches
+DIGCMD="$DIG $DIGOPTS @10.53.0.4"
+
+sendcmd() {
+ send 10.53.0.5 "$EXTRAPORT1"
+}
+
+echo_i "testing that incorrectly signed transfers will fail..."
+n=$((n+1))
+echo_i "initial correctly-signed transfer should succeed ($n)"
+
+sendcmd < ans5/goodaxfr
+
+# Initially, ns4 is not authoritative for anything.
+# Now that ans is up and running with the right data, we make ns4
+# a secondary for nil.
+
+cat <<EOF >>ns4/named.conf
+zone "nil" {
+ type secondary;
+ file "nil.db";
+ primaries { 10.53.0.5 key tsig_key; };
+};
+EOF
+
+nextpart ns4/named.run >/dev/null
+
+rndc_reload ns4 10.53.0.4
+
+wait_for_soa() (
+ $DIGCMD nil. SOA > dig.out.ns4.test$n
+ grep SOA dig.out.ns4.test$n > /dev/null
+)
+retry_quiet 10 wait_for_soa
+
+nextpart ns4/named.run | grep "Transfer status: success" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=$((status+1))
+}
+
+$DIGCMD nil. TXT | grep 'initial AXFR' >/dev/null || {
+ echo_i "failed"
+ status=$((status+1))
+}
+
+n=$((n+1))
+echo_i "unsigned transfer ($n)"
+
+sendcmd < ans5/unsigned
+sleep 1
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+nextpart ns4/named.run | grep "Transfer status: expected a TSIG or SIG(0)" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=$((status+1))
+}
+
+$DIGCMD nil. TXT | grep 'unsigned AXFR' >/dev/null && {
+ echo_i "failed"
+ status=$((status+1))
+}
+
+n=$((n+1))
+echo_i "bad keydata ($n)"
+
+sendcmd < ans5/badkeydata
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+nextpart ns4/named.run | grep "Transfer status: tsig verify failure" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=$((status+1))
+}
+
+$DIGCMD nil. TXT | grep 'bad keydata AXFR' >/dev/null && {
+ echo_i "failed"
+ status=$((status+1))
+}
+
+n=$((n+1))
+echo_i "partially-signed transfer ($n)"
+
+sendcmd < ans5/partial
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+nextpart ns4/named.run | grep "Transfer status: expected a TSIG or SIG(0)" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=$((status+1))
+}
+
+$DIGCMD nil. TXT | grep 'partially signed AXFR' >/dev/null && {
+ echo_i "failed"
+ status=$((status+1))
+}
+
+n=$((n+1))
+echo_i "unknown key ($n)"
+
+sendcmd < ans5/unknownkey
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+nextpart ns4/named.run | grep "tsig key 'tsig_key': key name and algorithm do not match" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=$((status+1))
+}
+
+$DIGCMD nil. TXT | grep 'unknown key AXFR' >/dev/null && {
+ echo_i "failed"
+ status=$((status+1))
+}
+
+n=$((n+1))
+echo_i "incorrect key ($n)"
+
+sendcmd < ans5/wrongkey
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+nextpart ns4/named.run | grep "tsig key 'tsig_key': key name and algorithm do not match" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=$((status+1))
+}
+
+$DIGCMD nil. TXT | grep 'incorrect key AXFR' >/dev/null && {
+ echo_i "failed"
+ status=$((status+1))
+}
+
+n=$((n+1))
+echo_i "bad question section ($n)"
+
+sendcmd < ans5/wrongname
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+nextpart ns4/named.run | grep "question name mismatch" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=$((status+1))
+}
+
+$DIGCMD nil. TXT | grep 'wrong question AXFR' >/dev/null && {
+ echo_i "failed"
+ status=$((status+1))
+}
+
+n=$((n+1))
+echo_i "bad message id ($n)"
+
+sendcmd < ans5/badmessageid
+
+# Uncomment to see AXFR stream with mismatching IDs.
+# $DIG $DIGOPTS @10.53.0.5 -y tsig_key:LSAnCU+Z nil. AXFR +all
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+nextpart ns4/named.run | grep "unexpected message id" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=$((status+1))
+}
+
+$DIGCMD nil. TXT | grep 'bad message id' >/dev/null && {
+ echo_i "failed"
+ status=$((status+1))
+}
+
+n=$((n+1))
+echo_i "mismatched SOA ($n)"
+
+sendcmd < ans5/soamismatch
+
+$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
+
+sleep 2
+
+nextpart ns4/named.run | grep "Transfer status: FORMERR" > /dev/null || {
+ echo_i "failed: expected status was not logged"
+ status=$((status+1))
+}
+
+$DIGCMD nil. TXT | grep 'SOA mismatch AXFR' >/dev/null && {
+ echo_i "failed"
+ status=$((status+1))
+}
+
+n=$((n+1))
+echo_i "check that we ask for and get a EDNS EXPIRE response ($n)"
+# force a refresh query
+$RNDCCMD 10.53.0.7 refresh edns-expire 2>&1 | sed 's/^/ns7 /' | cat_i
+sleep 10
+
+# there may be multiple log entries so get the last one.
+expire=$(awk '/edns-expire\/IN: got EDNS EXPIRE of/ { x=$9 } END { print x }' ns7/named.run)
+test ${expire:-0} -gt 0 -a ${expire:-0} -lt 1814400 || {
+ echo_i "failed (expire=${expire:-0})"
+ status=$((status+1))
+}
+
+n=$((n+1))
+echo_i "test smaller transfer TCP message size ($n)"
+$DIG $DIGOPTS example. @10.53.0.8 axfr \
+ -y key1.:1234abcd8765 > dig.out.msgsize.test$n || status=1
+
+bytes=$(wc -c < dig.out.msgsize.test$n)
+if [ $bytes -ne 459357 ]; then
+ echo_i "failed axfr size check"
+ status=$((status+1))
+fi
+
+num_messages=$(cat ns8/named.run | grep "sending TCP message of" | wc -l)
+if [ $num_messages -le 300 ]; then
+ echo_i "failed transfer message count check"
+ status=$((status+1))
+fi
+
+n=$((n+1))
+echo_i "test mapped zone with out of zone data ($n)"
+tmp=0
+$DIG -p ${PORT} txt mapped @10.53.0.3 > dig.out.1.test$n
+grep "status: NOERROR," dig.out.1.test$n > /dev/null || tmp=1
+stop_server ns3
+start_server --noclean --restart --port ${PORT} ns3
+check_mapped () {
+ $DIG -p ${PORT} txt mapped @10.53.0.3 > dig.out.2.test$n
+ grep "status: NOERROR," dig.out.2.test$n > /dev/null || return 1
+ $DIG -p ${PORT} axfr mapped @10.53.0.3 > dig.out.3.test$n
+ digcomp knowngood.mapped dig.out.3.test$n || return 1
+ return 0
+}
+retry_quiet 10 check_mapped || tmp=1
+[ "$tmp" -ne 0 ] && echo_i "failed"
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "test that a zone with too many records is rejected (AXFR) ($n)"
+tmp=0
+grep "'axfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "test that a zone with too many records is rejected (IXFR) ($n)"
+tmp=0
+nextpart ns6/named.run > /dev/null
+$NSUPDATE << EOF
+zone ixfr-too-big
+server 10.53.0.1 ${PORT}
+update add the-31st-record.ixfr-too-big 0 TXT this is it
+send
+EOF
+msg="'ixfr-too-big/IN' from 10.53.0.1#${PORT}: Transfer status: too many records"
+wait_for_log 10 "$msg" ns6/named.run || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "checking whether dig calculates AXFR statistics correctly ($n)"
+tmp=0
+# Loop until the secondary server manages to transfer the "xfer-stats" zone so
+# that we can both check dig output and immediately proceed with the next test.
+# Use -b so that we can discern between incoming and outgoing transfers in ns3
+# logs later on.
+wait_for_xfer() (
+ $DIG $DIGOPTS +noedns +stat -b 10.53.0.2 @10.53.0.3 xfer-stats. AXFR > dig.out.ns3.test$n
+ grep "; Transfer failed" dig.out.ns3.test$n > /dev/null || return 0
+ return 1
+)
+if retry_quiet 10 wait_for_xfer; then
+ get_dig_xfer_stats dig.out.ns3.test$n > stats.dig
+ diff axfr-stats.good stats.dig || tmp=1
+else
+ echo_i "timed out waiting for zone transfer"
+fi
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+# Note: in the next two tests, we use ns3 logs for checking both incoming and
+# outgoing transfer statistics as ns3 is both a secondary server (for ns1) and a
+# primary server (for dig queries from the previous test) for "xfer-stats".
+n=$((n+1))
+echo_i "checking whether named calculates incoming AXFR statistics correctly ($n)"
+tmp=0
+get_named_xfer_stats ns3/named.run 10.53.0.1 xfer-stats "Transfer completed" > stats.incoming
+diff axfr-stats.good stats.incoming || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "checking whether named calculates outgoing AXFR statistics correctly ($n)"
+tmp=0
+check_xfer_stats() {
+ get_named_xfer_stats ns3/named.run 10.53.0.2 xfer-stats "AXFR ended" > stats.outgoing
+ diff axfr-stats.good stats.outgoing > /dev/null
+}
+retry_quiet 10 check_xfer_stats || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+n=$((n+1))
+echo_i "test that transfer-source uses port option correctly ($n)"
+tmp=0
+grep "10.53.0.3#${EXTRAPORT1} (primary): query 'primary/SOA/IN' approved" ns6/named.run > /dev/null || tmp=1
+if test $tmp != 0 ; then echo_i "failed"; fi
+status=$((status+tmp))
+
+wait_for_message() (
+ nextpartpeek ns6/named.run > wait_for_message.$n
+ grep -F "$1" wait_for_message.$n >/dev/null
+)
+
+nextpart ns6/named.run > /dev/null
+
+n=$((n+1))
+echo_i "test max-transfer-time-in with 1 second timeout ($n)"
+stop_server ns1
+copy_setports ns1/named2.conf.in ns1/named.conf
+start_server --noclean --restart --port ${PORT} ns1 -- "-D xfer-ns1 $NS_PARAMS -T transferinsecs -T transferslowly"
+sleep 1
+$RNDCCMD 10.53.0.6 retransfer axfr-max-transfer-time 2>&1 | sed 's/^/ns6 /' | cat_i
+tmp=0
+retry_quiet 10 wait_for_message "maximum transfer time exceeded: timed out" || tmp=1
+status=$((status+tmp))
+
+nextpart ns6/named.run > /dev/null
+
+n=$((n+1))
+echo_i "test max-transfer-idle-in with 50 seconds timeout ($n)"
+stop_server ns1
+copy_setports ns1/named3.conf.in ns1/named.conf
+start_server --noclean --restart --port ${PORT} ns1 -- "-D xfer-ns1 $NS_PARAMS -T transferinsecs -T transferstuck"
+sleep 1
+start=$(date +%s)
+$RNDCCMD 10.53.0.6 retransfer axfr-max-idle-time 2>&1 | sed 's/^/ns6 /' | cat_i
+tmp=0
+retry_quiet 60 wait_for_message "maximum idle time exceeded: timed out" || tmp=1
+if [ $tmp -eq 0 ]; then
+ now=$(date +%s)
+ diff=$((now - start))
+ # we expect a timeout in 50 seconds
+ test $diff -lt 50 && tmp=1
+ test $diff -ge 59 && tmp=1
+ if test $tmp != 0 ; then echo_i "unexpected diff value: ${diff}"; fi
+fi
+status=$((status+tmp))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/xfer/tests_sh_xfer.py b/bin/tests/system/xfer/tests_sh_xfer.py
new file mode 100644
index 0000000..c83d6e9
--- /dev/null
+++ b/bin/tests/system/xfer/tests_sh_xfer.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_xfer(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/xferquota/clean.sh b/bin/tests/system/xferquota/clean.sh
new file mode 100644
index 0000000..9cc4057
--- /dev/null
+++ b/bin/tests/system/xferquota/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Clean up after zone transfer quota tests.
+#
+
+rm -f ns1/zone*.example.db ns1/zones.conf
+rm -f ns2/zone*.example.bk ns2/zones.conf
+rm -f dig.out.* ns2/changing.bk
+rm -f ns1/changing.db
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/xferquota/ns1/changing1.db b/bin/tests/system/xferquota/ns1/changing1.db
new file mode 100644
index 0000000..0b5e893
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/changing1.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+
+@ IN SOA dns1.changing. postmaster.changing. (
+ 1 ;; serial
+ 3600 ;; refresh period
+ 1800 ;; retry interval
+ 604800 ;; expire time
+ 600 ) ;; default TTL
+
+ IN NS dns1.changing.
+ NS dns2.changing.
+
+dns1 IN A 10.53.0.1
+dns2 IN A 10.53.0.2
+
+a IN A 10.0.0.1
diff --git a/bin/tests/system/xferquota/ns1/changing2.db b/bin/tests/system/xferquota/ns1/changing2.db
new file mode 100644
index 0000000..33dd7f4
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/changing2.db
@@ -0,0 +1,27 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+
+@ IN SOA dns1.changing. postmaster.changing. (
+ 2 ;; serial
+ 3600 ;; refresh period
+ 1800 ;; retry interval
+ 604800 ;; expire time
+ 600 ) ;; default TTL
+
+ IN NS dns1.changing.
+ NS dns2.changing.
+
+dns1 IN A 10.53.0.1
+dns2 IN A 10.53.0.2
+
+a IN A 10.0.0.2
diff --git a/bin/tests/system/xferquota/ns1/named.conf.in b/bin/tests/system/xferquota/ns1/named.conf.in
new file mode 100644
index 0000000..e868318
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/named.conf.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
+
+zone "changing." {
+ type primary;
+ file "changing.db";
+};
+
+include "zones.conf";
diff --git a/bin/tests/system/xferquota/ns1/root.db b/bin/tests/system/xferquota/ns1/root.db
new file mode 100644
index 0000000..c5049f4
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/root.db
@@ -0,0 +1,29 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+changing. NS dns1.changing.
+ A 10.53.0.1
+ NS dns2.changing.
+ A 10.53.0.2
diff --git a/bin/tests/system/xferquota/ns2/example.db b/bin/tests/system/xferquota/ns2/example.db
new file mode 100644
index 0000000..e1d2b82
--- /dev/null
+++ b/bin/tests/system/xferquota/ns2/example.db
@@ -0,0 +1,146 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 2000042795 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+* MX 10 mail
+a TXT "foo foo foo"
+ PTR foo.net.
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+dnskey01 DNSKEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" ":(.*):\\1:" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsec01 NSEC a.secure ( NS SOA MX RRSIG DNSKEY LOC NSEC )
+nsec02 NSEC . ( NSAP-PTR NSEC )
+nsec03 NSEC . ( A )
+nsec04 NSEC . ( 127 )
+ptr01 PTR example.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.
+ns A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+rrsig01 RRSIG NSEC 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nsec"
+$ORIGIN u.example.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/xferquota/ns2/named.conf.in b/bin/tests/system/xferquota/ns2/named.conf.in
new file mode 100644
index 0000000..f21938e
--- /dev/null
+++ b/bin/tests/system/xferquota/ns2/named.conf.in
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+ notify no;
+
+ transfers-in 5;
+ transfers-per-ns 5;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "changing." {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "changing.bk";
+};
+
+include "zones.conf";
diff --git a/bin/tests/system/xferquota/setup.pl b/bin/tests/system/xferquota/setup.pl
new file mode 100644
index 0000000..ab5450c
--- /dev/null
+++ b/bin/tests/system/xferquota/setup.pl
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Set up test data for zone transfer quota tests.
+#
+use FileHandle;
+
+my $priconf = new FileHandle("ns1/zones.conf", "w") or die;
+my $secconf = new FileHandle("ns2/zones.conf", "w") or die;
+
+for ($z = 0; $z < 300; $z++) {
+ my $zn = sprintf("zone%06d.example", $z);
+ print $priconf "zone \"$zn\" { type primary; file \"$zn.db\"; };\n";
+ print $secconf "zone \"$zn\" { type secondary; file \"$zn.bk\"; masterfile-format text; primaries { 10.53.0.1; }; };\n";
+ my $fn = "ns1/$zn.db";
+ my $f = new FileHandle($fn, "w") or die "open: $fn: $!";
+ print $f "\$TTL 300
+\@ IN SOA ns1 . 1 300 120 3600 86400
+ NS ns1
+ NS ns2
+ns1 A 10.53.0.1
+ns2 A 10.53.0.2
+ MX 10 mail1.isp.example.
+ MX 20 mail2.isp.example.
+www A 10.0.0.1
+xyzzy A 10.0.0.2
+";
+ $f->close;
+}
diff --git a/bin/tests/system/xferquota/setup.sh b/bin/tests/system/xferquota/setup.sh
new file mode 100644
index 0000000..55e34b9
--- /dev/null
+++ b/bin/tests/system/xferquota/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Set up test data for zone transfer quota tests.
+#
+
+. ../conf.sh
+
+$PERL setup.pl
+
+cp -f ns1/changing1.db ns1/changing.db
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
diff --git a/bin/tests/system/xferquota/tests.sh b/bin/tests/system/xferquota/tests.sh
new file mode 100755
index 0000000..46dfba0
--- /dev/null
+++ b/bin/tests/system/xferquota/tests.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+#
+# Perform tests
+#
+
+count=0
+ticks=0
+while [ $count != 300 ]; do
+ if [ $ticks = 1 ]; then
+ echo_i "Changing test zone..."
+ cp -f ns1/changing2.db ns1/changing.db
+ kill -HUP $(cat ns1/named.pid)
+ fi
+ sleep 1
+ ticks=$((ticks + 1))
+ seconds=$((ticks * 1))
+ if [ $ticks = 360 ]; then
+ echo_i "Took too long to load zones"
+ exit 1
+ fi
+ count=$(cat ns2/zone*.bk | grep xyzzy | wc -l)
+ echo_i "Have $count zones up in $seconds seconds"
+done
+
+status=0
+
+$DIG $DIGOPTS zone000099.example. @10.53.0.1 axfr > dig.out.ns1 || status=1
+
+$DIG $DIGOPTS zone000099.example. @10.53.0.2 axfr > dig.out.ns2 || status=1
+
+digcomp dig.out.ns1 dig.out.ns2 || status=1
+
+sleep 15
+
+$DIG $DIGOPTS a.changing. @10.53.0.1 a > dig.out.ns1 || status=1
+
+$DIG $DIGOPTS a.changing. @10.53.0.2 a > dig.out.ns2 || status=1
+
+digcomp dig.out.ns1 dig.out.ns2 || status=1
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/xferquota/tests_sh_xferquota.py b/bin/tests/system/xferquota/tests_sh_xferquota.py
new file mode 100644
index 0000000..762e182
--- /dev/null
+++ b/bin/tests/system/xferquota/tests_sh_xferquota.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_xferquota(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/zero/ans5/ans.pl b/bin/tests/system/zero/ans5/ans.pl
new file mode 100644
index 0000000..3ca1083
--- /dev/null
+++ b/bin/tests/system/zero/ans5/ans.pl
@@ -0,0 +1,81 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+#
+# Don't respond if the "norespond" file exists; otherwise respond to
+# any A or AAAA query.
+#
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.5",
+ LocalPort => $localport, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+my $octet = 0;
+
+for (;;) {
+ $sock->recv($buf, 512);
+
+ print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
+
+ my $packet;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ print "REQUEST:\n";
+ $packet->print;
+
+ $packet->header->qr(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+
+ $packet->header->aa(1);
+ if ($qtype eq "A") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 0 A 192.0.2." . $octet));
+ $octet = $octet + 1;
+ } elsif ($qtype eq "AAAA") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname .
+ " 300 AAAA 2001:db8:beef::1"));
+ }
+
+ $sock->send($packet->data);
+ print "RESPONSE:\n";
+ $packet->print;
+ print "\n";
+}
diff --git a/bin/tests/system/zero/clean.sh b/bin/tests/system/zero/clean.sh
new file mode 100644
index 0000000..2ef5727
--- /dev/null
+++ b/bin/tests/system/zero/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f */named.conf
+rm -f */named.run
+rm -f */named.memstats
+rm -f ns2/example.db
+rm -f ns4/example.bk
+rm -f dig.out*
+rm -f query.list
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/zero/ns1/named.conf.in b/bin/tests/system/zero/ns1/named.conf.in
new file mode 100644
index 0000000..1334c85
--- /dev/null
+++ b/bin/tests/system/zero/ns1/named.conf.in
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
diff --git a/bin/tests/system/zero/ns1/root.db b/bin/tests/system/zero/ns1/root.db
new file mode 100644
index 0000000..fbcb3e2
--- /dev/null
+++ b/bin/tests/system/zero/ns1/root.db
@@ -0,0 +1,26 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ SOA ns1. hostmaster.warn.example. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.
+ns1. A 10.53.0.1
+;
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns4.example.
+ns4.example. A 10.53.0.4
+increment. NS incrementns.
+incrementns. A 10.53.0.5
+tld. NS ns2.tld.
+ns2.tld. A 10.53.0.2
+
diff --git a/bin/tests/system/zero/ns2/named.args b/bin/tests/system/zero/ns2/named.args
new file mode 100644
index 0000000..4b7aad6
--- /dev/null
+++ b/bin/tests/system/zero/ns2/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 1 -D zero-ns2 -X named.lock -g -T maxcachesize=2097152
diff --git a/bin/tests/system/zero/ns2/named.conf.in b/bin/tests/system/zero/ns2/named.conf.in
new file mode 100644
index 0000000..751eafd
--- /dev/null
+++ b/bin/tests/system/zero/ns2/named.conf.in
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "example" {
+ type primary;
+ file "example.db";
+};
+
+zone "tld" {
+ type primary;
+ file "tld.db";
+};
diff --git a/bin/tests/system/zero/ns2/tld.db b/bin/tests/system/zero/ns2/tld.db
new file mode 100644
index 0000000..0ffeb05
--- /dev/null
+++ b/bin/tests/system/zero/ns2/tld.db
@@ -0,0 +1,20 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 1
+@ 300 SOA ns2.tld. hostmaster.ns2.tld. 0 1 1 1 1
+@ 300 NS ns2.tld.
+ns2 300 A 10.53.0.2
+;
+; The TTL of these delegation records needs to 1.
+;
+one 1 NS ns4.one.tld.
+ns4.one 1 A 10.53.0.4
diff --git a/bin/tests/system/zero/ns3/named.args b/bin/tests/system/zero/ns3/named.args
new file mode 100644
index 0000000..e6f6060
--- /dev/null
+++ b/bin/tests/system/zero/ns3/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 1 -D zero-ns3 -X named.lock -g -T maxcachesize=2097152
diff --git a/bin/tests/system/zero/ns3/named.conf.in b/bin/tests/system/zero/ns3/named.conf.in
new file mode 100644
index 0000000..7e0d1d7
--- /dev/null
+++ b/bin/tests/system/zero/ns3/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ servfail-ttl 0;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
diff --git a/bin/tests/system/zero/ns3/root.hint b/bin/tests/system/zero/ns3/root.hint
new file mode 100644
index 0000000..206e952
--- /dev/null
+++ b/bin/tests/system/zero/ns3/root.hint
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+. NS ns1.
+ns1. A 10.53.0.1
diff --git a/bin/tests/system/zero/ns4/named.args b/bin/tests/system/zero/ns4/named.args
new file mode 100644
index 0000000..bd59f13
--- /dev/null
+++ b/bin/tests/system/zero/ns4/named.args
@@ -0,0 +1 @@
+-m record -c named.conf -d 1 -D zero-ns4 -X named.lock -g -T maxcachesize=2097152
diff --git a/bin/tests/system/zero/ns4/named.conf.in b/bin/tests/system/zero/ns4/named.conf.in
new file mode 100644
index 0000000..fc8fec6
--- /dev/null
+++ b/bin/tests/system/zero/ns4/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation yes;
+};
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "example.bk";
+};
+
+zone "one.tld" {
+ type primary;
+ file "one.tld.db";
+};
diff --git a/bin/tests/system/zero/ns4/one.tld.db b/bin/tests/system/zero/ns4/one.tld.db
new file mode 100644
index 0000000..491ba87
--- /dev/null
+++ b/bin/tests/system/zero/ns4/one.tld.db
@@ -0,0 +1,17 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 1
+; The TTL of all these records needs to be 1.
+@ 1 SOA ns4.one.tld. hostmaster.ns4.tld. 0 1 1 1 1
+@ 1 NS ns4.one.tld.
+ns4 1 A 10.53.0.4
+www 1 A 10.53.0.4
diff --git a/bin/tests/system/zero/setup.sh b/bin/tests/system/zero/setup.sh
new file mode 100644
index 0000000..bf58ee5
--- /dev/null
+++ b/bin/tests/system/zero/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
+
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 4 | sed -e 's/^$TTL 3600$/$TTL 0 ; force TTL to zero/' -e 's/86400.IN SOA/0 SOA/' > ns2/example.db
diff --git a/bin/tests/system/zero/tests.sh b/bin/tests/system/zero/tests.sh
new file mode 100644
index 0000000..f5e2038
--- /dev/null
+++ b/bin/tests/system/zero/tests.sh
@@ -0,0 +1,123 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+#shellcheck source=conf.sh
+. ../conf.sh
+
+dig_with_opts() {
+ "$DIG" -p "${PORT}" "$@"
+}
+
+wait_for_pid() (
+ for pid in "$@"; do
+ kill -0 "$pid" 2>/dev/null && return 1
+ done
+ return 0
+)
+
+status=0
+n=0
+
+n=$((n+1))
+echo_i "check lookups against TTL=0 records ($n)"
+i=0
+ret=0
+passes=10
+dig_with_opts @10.53.0.2 axfr example | grep -v "^ds0" | \
+awk '$2 == "0" { print "-q", $1, $4; print "-q", "zzz"$1, $4;}' > query.list
+
+# add 1/5 second per query
+timeout=$(($(wc -l < query.list) / 5))
+while [ $i -lt $passes ]
+do
+ (dig_with_opts -d +qr @10.53.0.3 -f query.list > "dig.out$i.1.test$n" 2>&1) & pid1="$!"
+ (dig_with_opts -d +qr @10.53.0.3 -f query.list > "dig.out$i.2.test$n" 2>&1) & pid2="$!"
+ (dig_with_opts -d +qr @10.53.0.3 -f query.list > "dig.out$i.3.test$n" 2>&1) & pid3="$!"
+ (dig_with_opts -d +qr @10.53.0.3 -f query.list > "dig.out$i.4.test$n" 2>&1) & pid4="$!"
+ (dig_with_opts -d +qr @10.53.0.3 -f query.list > "dig.out$i.5.test$n" 2>&1) & pid5="$!"
+ (dig_with_opts -d +qr @10.53.0.3 -f query.list > "dig.out$i.6.test$n" 2>&1) & pid6="$!"
+
+ retry_quiet "$timeout" wait_for_pid "$pid1" "$pid2" "$pid3" "$pid4" "$pid5" "$pid6" || { echo_i "wait_for_pid failed"; ret=1; }
+ kill -TERM "$pid1" "$pid2" "$pid3" "$pid4" "$pid5" "$pid6" 2>/dev/null || true
+
+ wait "$pid1" || { echo_i "wait $pid1 (dig.out$i.1.test$n) failed with $?"; ret=1; }
+ wait "$pid2" || { echo_i "wait $pid2 (dig.out$i.2.test$n) failed with $?"; ret=1; }
+ wait "$pid3" || { echo_i "wait $pid3 (dig.out$i.3.test$n) failed with $?"; ret=1; }
+ wait "$pid4" || { echo_i "wait $pid4 (dig.out$i.4.test$n) failed with $?"; ret=1; }
+ wait "$pid5" || { echo_i "wait $pid5 (dig.out$i.5.test$n) failed with $?"; ret=1; }
+ wait "$pid6" || { echo_i "wait $pid6 (dig.out$i.6.test$n) failed with $?"; ret=1; }
+
+ grep "status: SERVFAIL" "dig.out$i.1.test$n" > /dev/null && ret=1
+ grep "status: SERVFAIL" "dig.out$i.2.test$n" > /dev/null && ret=1
+ grep "status: SERVFAIL" "dig.out$i.3.test$n" > /dev/null && ret=1
+ grep "status: SERVFAIL" "dig.out$i.4.test$n" > /dev/null && ret=1
+ grep "status: SERVFAIL" "dig.out$i.5.test$n" > /dev/null && ret=1
+ grep "status: SERVFAIL" "dig.out$i.6.test$n" > /dev/null && ret=1
+ [ $ret = 1 ] && break
+ i=$((i+1))
+ echo_i "successfully completed pass $i of $passes"
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+repeat_query() (
+ i=0
+ while [ "$i" -lt "$1" ]; do
+ dig_with_opts +short "@$2" "$3" | tee "dig.out$i.test$n" || return 1
+ i=$((i+1))
+ done
+)
+
+count_unique() (
+ repeat_query "$@" | sort -u | wc -l
+)
+
+n=$((n+1))
+echo_i "check repeated recursive lookups of non recurring TTL=0 responses get new values ($n)"
+ret=0
+repeats=9
+count=$(count_unique "$repeats" 10.53.0.3 foo.increment)
+if [ "$count" -ne "$repeats" ] ; then echo_i "failed (count=$count, repeats=$repeats)"; ret=1; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check lookups against TTL=1 records ($n)"
+i=0
+passes=10
+ret=0
+while [ $i -lt $passes ]
+do
+ dig_with_opts @10.53.0.3 www.one.tld > "dig.out$i.1.test$n" || ret=1
+ dig_with_opts @10.53.0.3 www.one.tld > "dig.out$i.2.test$n" || ret=1
+ dig_with_opts @10.53.0.3 www.one.tld > "dig.out$i.3.test$n" || ret=1
+ dig_with_opts @10.53.0.3 www.one.tld > "dig.out$i.4.test$n" || ret=1
+ dig_with_opts @10.53.0.3 www.one.tld > "dig.out$i.5.test$n" || ret=1
+ dig_with_opts @10.53.0.3 www.one.tld > "dig.out$i.6.test$n" || ret=1
+ grep "status: SERVFAIL" "dig.out$i.1.test$n" > /dev/null && ret=1
+ grep "status: SERVFAIL" "dig.out$i.2.test$n" > /dev/null && ret=1
+ grep "status: SERVFAIL" "dig.out$i.3.test$n" > /dev/null && ret=1
+ grep "status: SERVFAIL" "dig.out$i.4.test$n" > /dev/null && ret=1
+ grep "status: SERVFAIL" "dig.out$i.5.test$n" > /dev/null && ret=1
+ grep "status: SERVFAIL" "dig.out$i.6.test$n" > /dev/null && ret=1
+ [ $ret = 1 ] && break
+ i=$((i+1))
+ echo_i "successfully completed pass $i of $passes"
+ sleep 1
+done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "exit status: $status"
+[ "$status" -eq 0 ] || exit 1
diff --git a/bin/tests/system/zero/tests_sh_zero.py b/bin/tests/system/zero/tests_sh_zero.py
new file mode 100644
index 0000000..0e8ceb2
--- /dev/null
+++ b/bin/tests/system/zero/tests_sh_zero.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_zero(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/zonechecks/a.db b/bin/tests/system/zonechecks/a.db
new file mode 100644
index 0000000..62d1ee7
--- /dev/null
+++ b/bin/tests/system/zonechecks/a.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS 127.0.0.1
+127.0.0.1 3600 IN A 127.0.0.1
diff --git a/bin/tests/system/zonechecks/aaaa.db b/bin/tests/system/zonechecks/aaaa.db
new file mode 100644
index 0000000..75724d6
--- /dev/null
+++ b/bin/tests/system/zonechecks/aaaa.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS ::1
+::1 3600 IN AAAA ::1
diff --git a/bin/tests/system/zonechecks/bigserial.db b/bin/tests/system/zonechecks/bigserial.db
new file mode 100644
index 0000000..200573a
--- /dev/null
+++ b/bin/tests/system/zonechecks/bigserial.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 IN SOA ns hostmaster 3003113544 3600 1200 604800 3600
+@ 3600 IN NS ns
+ns 3600 IN A 10.53.0.1
diff --git a/bin/tests/system/zonechecks/clean.sh b/bin/tests/system/zonechecks/clean.sh
new file mode 100644
index 0000000..ed4012a
--- /dev/null
+++ b/bin/tests/system/zonechecks/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+rm -f *.out
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f */*.db */*.db.signed */K*.key */K*.private */*.jnl */dsset-*
+rm -f */signer.err
+rm -f rndc.out.*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind* ns*/*.mkeys*
diff --git a/bin/tests/system/zonechecks/cname.db b/bin/tests/system/zonechecks/cname.db
new file mode 100644
index 0000000..2e8a123
--- /dev/null
+++ b/bin/tests/system/zonechecks/cname.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS ns
+ns 3600 IN CNAME @
diff --git a/bin/tests/system/zonechecks/dname.db b/bin/tests/system/zonechecks/dname.db
new file mode 100644
index 0000000..b2859d1
--- /dev/null
+++ b/bin/tests/system/zonechecks/dname.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS ns
+@ 3600 IN DNAME .
diff --git a/bin/tests/system/zonechecks/noaddress.db b/bin/tests/system/zonechecks/noaddress.db
new file mode 100644
index 0000000..f656197
--- /dev/null
+++ b/bin/tests/system/zonechecks/noaddress.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS ns
+ns 3600 IN TXT this name has no address records
diff --git a/bin/tests/system/zonechecks/ns1/named.conf.in b/bin/tests/system/zonechecks/ns1/named.conf.in
new file mode 100644
index 0000000..03bc918
--- /dev/null
+++ b/bin/tests/system/zonechecks/ns1/named.conf.in
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// 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;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+view unused {
+ match-clients { none; };
+
+ zone "duplicate.example" {
+ type primary;
+ file "duplicate.db";
+ };
+};
+
+view primary {
+ match-clients { any; };
+
+ zone "primary.example" {
+ type primary;
+ file "primary.db";
+ allow-update { any; };
+ allow-transfer { any; };
+ auto-dnssec maintain;
+ };
+
+ zone "bigserial.example" {
+ type primary;
+ file "bigserial.db";
+ };
+
+ zone "reload.example" {
+ type primary;
+ file "reload.db";
+ };
+
+ zone "duplicate.example" {
+ type primary;
+ file "duplicate.db";
+ };
+};
diff --git a/bin/tests/system/zonechecks/ns2/named.conf.in b/bin/tests/system/zonechecks/ns2/named.conf.in
new file mode 100644
index 0000000..5ecf68b
--- /dev/null
+++ b/bin/tests/system/zonechecks/ns2/named.conf.in
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "primary.example" {
+ type secondary;
+ primaries { 10.53.0.1; };
+ file "sec.db";
+};
diff --git a/bin/tests/system/zonechecks/nxdomain.db b/bin/tests/system/zonechecks/nxdomain.db
new file mode 100644
index 0000000..853325d
--- /dev/null
+++ b/bin/tests/system/zonechecks/nxdomain.db
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS ns
+; There are no records at all with the ownername of "ns".
diff --git a/bin/tests/system/zonechecks/setup.sh b/bin/tests/system/zonechecks/setup.sh
new file mode 100644
index 0000000..76e8a19
--- /dev/null
+++ b/bin/tests/system/zonechecks/setup.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+. ../conf.sh
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 1 > ns1/primary.db
+$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 1 > ns1/duplicate.db
+cp bigserial.db ns1/
+cd ns1
+touch primary.db.signed
+echo '$INCLUDE "primary.db.signed"' >> primary.db
+$KEYGEN -a ${DEFAULT_ALGORITHM} -q primary.example > /dev/null 2>&1
+$KEYGEN -a ${DEFAULT_ALGORITHM} -qfk primary.example > /dev/null 2>&1
+$SIGNER -SD -o primary.example primary.db > /dev/null \
+ 2> signer.err || cat signer.err
+echo '$INCLUDE "soa.db"' > reload.db
+echo '@ 0 NS .' >> reload.db
+echo '@ 0 SOA . . 1 0 0 0 0' > soa.db
diff --git a/bin/tests/system/zonechecks/tests.sh b/bin/tests/system/zonechecks/tests.sh
new file mode 100644
index 0000000..958bfed
--- /dev/null
+++ b/bin/tests/system/zonechecks/tests.sh
@@ -0,0 +1,258 @@
+#!/bin/sh
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+. ../conf.sh
+
+DIGOPTS="-p ${PORT}"
+RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
+
+status=0
+
+#
+echo_i "checking that we detect a NS which refers to a CNAME"
+if $CHECKZONE . cname.db > cname.out 2>&1
+then
+ echo_i "failed (status)"; status=$((status + 1))
+else
+ if grep "is a CNAME" cname.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=$((status + 1))
+ fi
+fi
+
+#
+echo_i "checking that we detect a NS which is below a DNAME"
+if $CHECKZONE . dname.db > dname.out 2>&1
+then
+ echo_i "failed (status)"; status=$((status + 1))
+else
+ if grep "is below a DNAME" dname.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=$((status + 1))
+ fi
+fi
+
+#
+echo_i "checking that we detect a NS which has no address records (A/AAAA)"
+if $CHECKZONE . noaddress.db > noaddress.out
+then
+ echo_i "failed (status)"; status=$((status + 1))
+else
+ if grep "has no address records" noaddress.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=$((status + 1))
+ fi
+fi
+
+#
+echo_i "checking that we detect a NS which has no records"
+if $CHECKZONE . nxdomain.db > nxdomain.out
+then
+ echo_i "failed (status)"; status=$((status + 1))
+else
+ if grep "has no address records" noaddress.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=$((status + 1))
+ fi
+fi
+
+#
+echo_i "checking that we detect a NS which looks like a A record (fail)"
+if $CHECKZONE -n fail . a.db > a.out 2>&1
+then
+ echo_i "failed (status)"; status=$((status + 1))
+else
+ if grep "appears to be an address" a.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=$((status + 1))
+ fi
+fi
+
+#
+echo_i "checking that we detect a NS which looks like a A record (warn=default)"
+if $CHECKZONE . a.db > a.out 2>&1
+then
+ if grep "appears to be an address" a.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=$((status + 1))
+ fi
+else
+ echo_i "failed (status)"; status=$((status + 1))
+fi
+
+#
+echo_i "checking that we detect a NS which looks like a A record (ignore)"
+if $CHECKZONE -n ignore . a.db > a.out 2>&1
+then
+ if grep "appears to be an address" a.out > /dev/null
+ then
+ echo_i "failed (message)"; status=$((status + 1))
+ else
+ :
+ fi
+else
+ echo_i "failed (status)"; status=$((status + 1))
+fi
+
+#
+echo_i "checking that we detect a NS which looks like a AAAA record (fail)"
+if $CHECKZONE -n fail . aaaa.db > aaaa.out 2>&1
+then
+ echo_i "failed (status)"; status=$((status + 1))
+else
+ if grep "appears to be an address" aaaa.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=$((status + 1))
+ fi
+fi
+
+#
+echo_i "checking that we detect a NS which looks like a AAAA record (warn=default)"
+if $CHECKZONE . aaaa.db > aaaa.out 2>&1
+then
+ if grep "appears to be an address" aaaa.out > /dev/null
+ then
+ :
+ else
+ echo_i "failed (message)"; status=$((status + 1))
+ fi
+else
+ echo_i "failed (status)"; status=$((status + 1))
+fi
+
+#
+echo_i "checking that we detect a NS which looks like a AAAA record (ignore)"
+if $CHECKZONE -n ignore . aaaa.db > aaaa.out 2>&1
+then
+ if grep "appears to be an address" aaaa.out > /dev/null
+ then
+ echo_i "failed (message)"; status=$((status + 1))
+ else
+ :
+ fi
+else
+ echo_i "failed (status)"; status=$((status + 1))
+fi
+
+#
+echo_i "checking 'rdnc zonestatus' output"
+ret=0
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $RNDCCMD 10.53.0.1 zonestatus primary.example > rndc.out.pri 2>&1
+ grep "zone not loaded" rndc.out.pri > /dev/null || break
+ sleep 1
+done
+checkfor() {
+ grep "$1" $2 > /dev/null || {
+ ret=1;
+ echo_i "missing string '$1' from '$2'"
+ }
+}
+checkfor "name: primary.example" rndc.out.pri
+checkfor "type: primary" rndc.out.pri
+checkfor "files: primary.db, primary.db.signed" rndc.out.pri
+checkfor "serial: " rndc.out.pri
+checkfor "nodes: " rndc.out.pri
+checkfor "last loaded: " rndc.out.pri
+checkfor "secure: yes" rndc.out.pri
+checkfor "inline signing: no" rndc.out.pri
+checkfor "key maintenance: automatic" rndc.out.pri
+checkfor "next key event: " rndc.out.pri
+checkfor "next resign node: " rndc.out.pri
+checkfor "next resign time: " rndc.out.pri
+checkfor "dynamic: yes" rndc.out.pri
+checkfor "frozen: no" rndc.out.pri
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $RNDCCMD 10.53.0.2 zonestatus primary.example > rndc.out.sec 2>&1
+ grep "zone not loaded" rndc.out.sec > /dev/null || break
+ sleep 1
+done
+checkfor "name: primary.example" rndc.out.sec
+checkfor "type: secondary" rndc.out.sec
+checkfor "files: sec.db" rndc.out.sec
+checkfor "serial: " rndc.out.sec
+checkfor "nodes: " rndc.out.sec
+checkfor "next refresh: " rndc.out.sec
+checkfor "expires: " rndc.out.sec
+checkfor "secure: yes" rndc.out.sec
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $RNDCCMD 10.53.0.1 zonestatus reload.example > rndc.out.prereload 2>&1
+ grep "zone not loaded" rndc.out.prereload > /dev/null || break
+ sleep 1
+done
+checkfor "files: reload.db, soa.db$" rndc.out.prereload
+echo "@ 0 SOA . . 2 0 0 0 0" > ns1/soa.db
+$RNDCCMD 10.53.0.1 reload reload.example | sed 's/^/ns1 /' | cat_i
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS reload.example SOA @10.53.0.1 > dig.out
+ grep " 2 0 0 0 0" dig.out >/dev/null && break
+ sleep 1
+done
+$RNDCCMD 10.53.0.1 zonestatus reload.example > rndc.out.postreload 2>&1
+checkfor "files: reload.db, soa.db$" rndc.out.postreload
+sleep 1
+echo "@ 0 SOA . . 3 0 0 0 0" > ns1/reload.db
+echo "@ 0 NS ." >> ns1/reload.db
+rndc_reload ns1 10.53.0.1 reload.example
+for i in 0 1 2 3 4 5 6 7 8 9
+do
+ $DIG $DIGOPTS reload.example SOA @10.53.0.1 > dig.out
+ grep " 3 0 0 0 0" dig.out >/dev/null && break
+ sleep 1
+done
+$RNDCCMD 10.53.0.1 zonestatus reload.example > rndc.out.removeinclude 2>&1
+checkfor "files: reload.db$" rndc.out.removeinclude
+
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking 'rdnc zonestatus' with duplicated zone name"
+ret=0
+$RNDCCMD 10.53.0.1 zonestatus duplicate.example > rndc.out.duplicate 2>&1 && ret=1
+checkfor "zone 'duplicate.example' was found in multiple views" rndc.out.duplicate
+$RNDCCMD 10.53.0.1 zonestatus duplicate.example in primary > rndc.out.duplicate 2>&1 || ret=1
+checkfor "name: duplicate.example" rndc.out.duplicate
+$RNDCCMD 10.53.0.1 zonestatus nosuchzone.example > rndc.out.duplicate 2>&1 && ret=1
+checkfor "no matching zone 'nosuchzone.example' in any view" rndc.out.duplicate
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "checking 'rdnc zonestatus' with big serial value"
+ret=0
+$RNDCCMD 10.53.0.1 zonestatus bigserial.example > rndc.out.bigserial 2>&1
+checkfor "serial: 3003113544" rndc.out.bigserial
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/zonechecks/tests_sh_zonechecks.py b/bin/tests/system/zonechecks/tests_sh_zonechecks.py
new file mode 100644
index 0000000..28a7bb1
--- /dev/null
+++ b/bin/tests/system/zonechecks/tests_sh_zonechecks.py
@@ -0,0 +1,14 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+def test_zonechecks(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/test_client.c b/bin/tests/test_client.c
new file mode 100644
index 0000000..ad6a4c7
--- /dev/null
+++ b/bin/tests/test_client.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <isc/managers.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/netmgr.h>
+#include <isc/os.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+typedef enum {
+ UDP,
+ TCP,
+ DOT,
+ HTTPS_POST,
+ HTTPS_GET,
+ HTTP_POST,
+ HTTP_GET
+} protocol_t;
+
+static const char *protocols[] = { "udp", "tcp",
+ "dot", "https-post",
+ "https-get", "http-plain-post",
+ "http-plain-get" };
+
+static isc_mem_t *mctx = NULL;
+static isc_nm_t *netmgr = NULL;
+
+static protocol_t protocol;
+static const char *address;
+static const char *port;
+static int family = AF_UNSPEC;
+static isc_sockaddr_t sockaddr_local;
+static isc_sockaddr_t sockaddr_remote;
+static int workers;
+static int timeout;
+static uint8_t messagebuf[2 * 65536];
+static isc_region_t message = { .length = 0, .base = messagebuf };
+static int out = -1;
+
+static isc_tlsctx_t *tls_ctx = NULL;
+
+static isc_result_t
+parse_port(const char *input) {
+ char *endptr = NULL;
+ long val = strtol(input, &endptr, 10);
+
+ if ((*endptr != '\0') || (val <= 0) || (val >= 65536)) {
+ return (ISC_R_BADNUMBER);
+ }
+
+ port = input;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+parse_protocol(const char *input) {
+ for (size_t i = 0; i < ARRAY_SIZE(protocols); i++) {
+ if (!strcasecmp(input, protocols[i])) {
+ protocol = i;
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ return (ISC_R_BADNUMBER);
+}
+
+static isc_result_t
+parse_address(const char *input) {
+ struct in6_addr in6;
+ struct in_addr in;
+
+ if (inet_pton(AF_INET6, input, &in6) == 1) {
+ family = AF_INET6;
+ address = input;
+ return (ISC_R_SUCCESS);
+ }
+
+ if (inet_pton(AF_INET, input, &in) == 1) {
+ family = AF_INET;
+ address = input;
+ return (ISC_R_SUCCESS);
+ }
+
+ return (ISC_R_BADADDRESSFORM);
+}
+
+static int
+parse_workers(const char *input) {
+ char *endptr = NULL;
+ long val = strtol(input, &endptr, 10);
+
+ if ((*endptr != '\0') || (val <= 0) || (val >= 128)) {
+ return (ISC_R_BADNUMBER);
+ }
+
+ workers = val;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+parse_timeout(const char *input) {
+ char *endptr = NULL;
+ long val = strtol(input, &endptr, 10);
+
+ if ((*endptr != '\0') || (val <= 0) || (val >= 120)) {
+ return (ISC_R_BADNUMBER);
+ }
+
+ timeout = (in_port_t)val * 1000;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+parse_input(const char *input) {
+ int in = -1;
+
+ if (!strcmp(input, "-")) {
+ in = 0;
+ } else {
+ in = open(input, O_RDONLY);
+ }
+ RUNTIME_CHECK(in >= 0);
+
+ message.length = read(in, message.base, sizeof(messagebuf));
+
+ close(in);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+parse_output(const char *input) {
+ if (!strcmp(input, "-")) {
+ out = 1;
+ } else {
+ out = open(input, O_WRONLY | O_CREAT,
+ S_IRUSR | S_IRGRP | S_IROTH);
+ }
+ RUNTIME_CHECK(out >= 0);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+parse_options(int argc, char **argv) {
+ char buf[ISC_NETADDR_FORMATSIZE];
+
+ /* Set defaults */
+ RUNTIME_CHECK(parse_protocol("UDP") == ISC_R_SUCCESS);
+ RUNTIME_CHECK(parse_port("53000") == ISC_R_SUCCESS);
+ RUNTIME_CHECK(parse_address("::0") == ISC_R_SUCCESS);
+ workers = isc_os_ncpus();
+
+ while (true) {
+ int c;
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "port", required_argument, NULL, 'p' },
+ { "address", required_argument, NULL, 'a' },
+ { "protocol", required_argument, NULL, 'P' },
+ { "workers", required_argument, NULL, 'w' },
+ { "timeout", required_argument, NULL, 't' },
+ { "input", required_argument, NULL, 'i' },
+ { "output", required_argument, NULL, 'o' },
+ { 0, 0, NULL, 0 }
+ };
+
+ c = getopt_long(argc, argv, "a:p:P:w:t:i:o:", long_options,
+ &option_index);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'a':
+ RUNTIME_CHECK(parse_address(optarg) == ISC_R_SUCCESS);
+ break;
+
+ case 'p':
+ RUNTIME_CHECK(parse_port(optarg) == ISC_R_SUCCESS);
+ break;
+
+ case 'P':
+ RUNTIME_CHECK(parse_protocol(optarg) == ISC_R_SUCCESS);
+ break;
+
+ case 'w':
+ RUNTIME_CHECK(parse_workers(optarg) == ISC_R_SUCCESS);
+ break;
+
+ case 't':
+ RUNTIME_CHECK(parse_timeout(optarg) == ISC_R_SUCCESS);
+ break;
+
+ case 'i':
+ RUNTIME_CHECK(parse_input(optarg) == ISC_R_SUCCESS);
+ break;
+
+ case 'o':
+ RUNTIME_CHECK(parse_output(optarg) == ISC_R_SUCCESS);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ {
+ struct addrinfo hints = {
+ .ai_family = family,
+ .ai_socktype = (protocol == UDP) ? SOCK_DGRAM
+ : SOCK_STREAM,
+ };
+ struct addrinfo *result = NULL;
+ int r = getaddrinfo(address, NULL, &hints, &result);
+ RUNTIME_CHECK(r == 0);
+
+ for (struct addrinfo *rp = result; rp != NULL; rp = rp->ai_next)
+ {
+ RUNTIME_CHECK(isc_sockaddr_fromsockaddr(&sockaddr_local,
+ rp->ai_addr) ==
+ ISC_R_SUCCESS);
+ }
+ freeaddrinfo(result);
+ }
+
+ {
+ struct addrinfo hints = {
+ .ai_family = family,
+ .ai_socktype = (protocol == UDP) ? SOCK_DGRAM
+ : SOCK_STREAM,
+ };
+ struct addrinfo *result = NULL;
+ int r = getaddrinfo(argv[optind], port, &hints, &result);
+ RUNTIME_CHECK(r == 0);
+
+ for (struct addrinfo *rp = result; rp != NULL; rp = rp->ai_next)
+ {
+ RUNTIME_CHECK(isc_sockaddr_fromsockaddr(
+ &sockaddr_remote, rp->ai_addr) ==
+ ISC_R_SUCCESS);
+ }
+ freeaddrinfo(result);
+ }
+
+ isc_sockaddr_format(&sockaddr_local, buf, sizeof(buf));
+
+ printf("Will connect from %s://%s", protocols[protocol], buf);
+
+ isc_sockaddr_format(&sockaddr_remote, buf, sizeof(buf));
+
+ printf(" to %s, %d workers\n", buf, workers);
+}
+
+static void
+_signal(int sig, void (*handler)(int)) {
+ struct sigaction sa = { .sa_handler = handler };
+
+ RUNTIME_CHECK(sigfillset(&sa.sa_mask) == 0);
+ RUNTIME_CHECK(sigaction(sig, &sa, NULL) >= 0);
+}
+
+static void
+setup(void) {
+ sigset_t sset;
+
+ _signal(SIGPIPE, SIG_IGN);
+ _signal(SIGHUP, SIG_DFL);
+ _signal(SIGTERM, SIG_DFL);
+ _signal(SIGINT, SIG_DFL);
+
+ RUNTIME_CHECK(sigemptyset(&sset) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGHUP) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGINT) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGTERM) == 0);
+ RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
+
+ isc_mem_create(&mctx);
+
+ isc_managers_create(mctx, workers, 0, &netmgr, NULL, NULL);
+}
+
+static void
+teardown(void) {
+ if (out > 0) {
+ close(out);
+ }
+
+ isc_managers_destroy(&netmgr, NULL, NULL);
+ isc_mem_destroy(&mctx);
+ if (tls_ctx) {
+ isc_tlsctx_free(&tls_ctx);
+ }
+}
+
+static void
+waitforsignal(void) {
+ sigset_t sset;
+ int sig;
+
+ RUNTIME_CHECK(sigemptyset(&sset) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGHUP) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGINT) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGTERM) == 0);
+ RUNTIME_CHECK(sigwait(&sset, &sig) == 0);
+
+ fprintf(stderr, "Shutting down...\n");
+}
+
+static void
+read_cb(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
+ void *cbarg) {
+ isc_nmhandle_t *readhandle = cbarg;
+
+ REQUIRE(handle != NULL);
+ REQUIRE(eresult == ISC_R_SUCCESS || eresult == ISC_R_CANCELED ||
+ eresult == ISC_R_EOF);
+ REQUIRE(cbarg != NULL);
+
+ fprintf(stderr, "%s(..., %s, ...)\n", __func__,
+ isc_result_totext(eresult));
+
+ if (eresult == ISC_R_SUCCESS) {
+ printf("RECEIVED %u bytes\n", region->length);
+ if (out >= 0) {
+ ssize_t len = write(out, region->base, region->length);
+ close(out);
+ REQUIRE((size_t)len == region->length);
+ }
+ }
+
+ isc_nmhandle_detach(&readhandle);
+ kill(getpid(), SIGTERM);
+}
+
+static void
+send_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
+ REQUIRE(handle != NULL);
+ REQUIRE(eresult == ISC_R_SUCCESS || eresult == ISC_R_CANCELED ||
+ eresult == ISC_R_EOF);
+ REQUIRE(cbarg == NULL);
+}
+
+static void
+connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
+ isc_nmhandle_t *readhandle = NULL;
+
+ REQUIRE(handle != NULL);
+ UNUSED(cbarg);
+
+ fprintf(stderr, "ECHO_CLIENT:%s:%s\n", __func__,
+ isc_result_totext(eresult));
+
+ if (eresult != ISC_R_SUCCESS) {
+ kill(getpid(), SIGTERM);
+ return;
+ }
+
+ isc_nmhandle_attach(handle, &readhandle);
+ isc_nm_read(handle, read_cb, readhandle);
+ isc_nm_send(handle, &message, send_cb, NULL);
+}
+
+static void
+run(void) {
+ switch (protocol) {
+ case UDP:
+ isc_nm_udpconnect(netmgr, &sockaddr_local, &sockaddr_remote,
+ connect_cb, NULL, timeout, 0);
+ break;
+ case TCP:
+ isc_nm_tcpdnsconnect(netmgr, &sockaddr_local, &sockaddr_remote,
+ connect_cb, NULL, timeout, 0);
+ break;
+ case DOT: {
+ isc_tlsctx_createclient(&tls_ctx);
+
+ isc_nm_tlsdnsconnect(netmgr, &sockaddr_local, &sockaddr_remote,
+ connect_cb, NULL, timeout, 0, tls_ctx,
+ NULL);
+ break;
+ }
+#if HAVE_LIBNGHTTP2
+ case HTTP_GET:
+ case HTTPS_GET:
+ case HTTPS_POST:
+ case HTTP_POST: {
+ bool is_https = (protocol == HTTPS_POST ||
+ protocol == HTTPS_GET);
+ bool is_post = (protocol == HTTPS_POST ||
+ protocol == HTTP_POST);
+ char req_url[256];
+ isc_nm_http_makeuri(is_https, &sockaddr_remote, NULL, 0,
+ ISC_NM_HTTP_DEFAULT_PATH, req_url,
+ sizeof(req_url));
+ if (is_https) {
+ isc_tlsctx_createclient(&tls_ctx);
+ }
+ isc_nm_httpconnect(netmgr, &sockaddr_local, &sockaddr_remote,
+ req_url, is_post, connect_cb, NULL, tls_ctx,
+ NULL, timeout, 0);
+ } break;
+#endif
+ default:
+ UNREACHABLE();
+ }
+
+ waitforsignal();
+}
+
+int
+main(int argc, char **argv) {
+ parse_options(argc, argv);
+
+ setup();
+
+ run();
+
+ teardown();
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/bin/tests/test_server.c b/bin/tests/test_server.c
new file mode 100644
index 0000000..3dedf6a
--- /dev/null
+++ b/bin/tests/test_server.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <getopt.h>
+#include <netinet/in.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <isc/managers.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/netmgr.h>
+#include <isc/os.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+typedef enum { UDP, TCP, DOT, HTTPS, HTTP } protocol_t;
+
+static const char *protocols[] = { "udp", "tcp", "dot", "https", "http-plain" };
+
+static isc_mem_t *mctx = NULL;
+static isc_nm_t *netmgr = NULL;
+
+static protocol_t protocol;
+static in_port_t port;
+static isc_netaddr_t netaddr;
+static isc_sockaddr_t sockaddr __attribute__((unused));
+static int workers;
+
+static isc_tlsctx_t *tls_ctx = NULL;
+
+static void
+read_cb(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
+ void *cbarg);
+static void
+send_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg);
+
+static isc_result_t
+parse_port(const char *input) {
+ char *endptr = NULL;
+ long val = strtol(input, &endptr, 10);
+
+ if ((*endptr != '\0') || (val <= 0) || (val >= 65536)) {
+ return (ISC_R_BADNUMBER);
+ }
+
+ port = (in_port_t)val;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+parse_protocol(const char *input) {
+ for (size_t i = 0; i < ARRAY_SIZE(protocols); i++) {
+ if (!strcasecmp(input, protocols[i])) {
+ protocol = i;
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ return (ISC_R_BADNUMBER);
+}
+
+static isc_result_t
+parse_address(const char *input) {
+ struct in6_addr in6;
+ struct in_addr in;
+
+ if (inet_pton(AF_INET6, input, &in6) == 1) {
+ isc_netaddr_fromin6(&netaddr, &in6);
+ return (ISC_R_SUCCESS);
+ }
+
+ if (inet_pton(AF_INET, input, &in) == 1) {
+ isc_netaddr_fromin(&netaddr, &in);
+ return (ISC_R_SUCCESS);
+ }
+
+ return (ISC_R_BADADDRESSFORM);
+}
+
+static int
+parse_workers(const char *input) {
+ char *endptr = NULL;
+ long val = strtol(input, &endptr, 10);
+
+ if ((*endptr != '\0') || (val <= 0) || (val >= 128)) {
+ return (ISC_R_BADNUMBER);
+ }
+
+ workers = val;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+parse_options(int argc, char **argv) {
+ char buf[ISC_NETADDR_FORMATSIZE];
+
+ /* Set defaults */
+ RUNTIME_CHECK(parse_protocol("UDP") == ISC_R_SUCCESS);
+ RUNTIME_CHECK(parse_port("53000") == ISC_R_SUCCESS);
+ RUNTIME_CHECK(parse_address("::1") == ISC_R_SUCCESS);
+ workers = isc_os_ncpus();
+
+ while (true) {
+ int c;
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "port", required_argument, NULL, 'p' },
+ { "address", required_argument, NULL, 'a' },
+ { "protocol", required_argument, NULL, 'P' },
+ { "workers", required_argument, NULL, 'w' },
+ { 0, 0, NULL, 0 }
+ };
+
+ c = getopt_long(argc, argv, "a:p:P:w:", long_options,
+ &option_index);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'a':
+ RUNTIME_CHECK(parse_address(optarg) == ISC_R_SUCCESS);
+ break;
+
+ case 'p':
+ RUNTIME_CHECK(parse_port(optarg) == ISC_R_SUCCESS);
+ break;
+
+ case 'P':
+ RUNTIME_CHECK(parse_protocol(optarg) == ISC_R_SUCCESS);
+ break;
+
+ case 'w':
+ RUNTIME_CHECK(parse_workers(optarg) == ISC_R_SUCCESS);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ isc_sockaddr_fromnetaddr(&sockaddr, &netaddr, port);
+
+ isc_sockaddr_format(&sockaddr, buf, sizeof(buf));
+
+ printf("Will listen at %s://%s, %d workers\n", protocols[protocol], buf,
+ workers);
+}
+
+static void
+_signal(int sig, void (*handler)(int)) {
+ struct sigaction sa = { .sa_handler = handler };
+
+ RUNTIME_CHECK(sigfillset(&sa.sa_mask) == 0);
+ RUNTIME_CHECK(sigaction(sig, &sa, NULL) >= 0);
+}
+
+static void
+setup(void) {
+ sigset_t sset;
+
+ _signal(SIGPIPE, SIG_IGN);
+ _signal(SIGHUP, SIG_DFL);
+ _signal(SIGTERM, SIG_DFL);
+ _signal(SIGINT, SIG_DFL);
+
+ RUNTIME_CHECK(sigemptyset(&sset) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGHUP) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGINT) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGTERM) == 0);
+ RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
+
+ isc_mem_create(&mctx);
+
+ isc_managers_create(mctx, workers, 0, &netmgr, NULL, NULL);
+}
+
+static void
+teardown(void) {
+ isc_managers_destroy(&netmgr, NULL, NULL);
+ isc_mem_destroy(&mctx);
+ if (tls_ctx) {
+ isc_tlsctx_free(&tls_ctx);
+ }
+}
+
+static void
+test_server_yield(void) {
+ sigset_t sset;
+ int sig;
+
+ RUNTIME_CHECK(sigemptyset(&sset) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGHUP) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGINT) == 0);
+ RUNTIME_CHECK(sigaddset(&sset, SIGTERM) == 0);
+ RUNTIME_CHECK(sigwait(&sset, &sig) == 0);
+
+ fprintf(stderr, "Shutting down...\n");
+}
+
+static void
+read_cb(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
+ void *cbarg) {
+ isc_region_t *reply = NULL;
+
+ REQUIRE(handle != NULL);
+ REQUIRE(eresult == ISC_R_SUCCESS);
+ UNUSED(cbarg);
+
+ fprintf(stderr, "RECEIVED %u bytes\n", region->length);
+
+ if (region->length >= 12) {
+ /* long enough to be a DNS header, set QR bit */
+ ((uint8_t *)region->base)[2] ^= 0x80;
+ }
+
+ reply = isc_mem_get(mctx, sizeof(isc_region_t) + region->length);
+ reply->length = region->length;
+ reply->base = (uint8_t *)reply + sizeof(isc_region_t);
+ memmove(reply->base, region->base, region->length);
+
+ isc_nm_send(handle, reply, send_cb, reply);
+ return;
+}
+
+static void
+send_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
+ isc_region_t *reply = cbarg;
+
+ REQUIRE(handle != NULL);
+ REQUIRE(eresult == ISC_R_SUCCESS);
+
+ isc_mem_put(mctx, cbarg, sizeof(isc_region_t) + reply->length);
+}
+
+static isc_result_t
+accept_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
+ REQUIRE(handle != NULL);
+ REQUIRE(eresult == ISC_R_SUCCESS);
+ UNUSED(cbarg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+run(void) {
+ isc_result_t result;
+ isc_nmsocket_t *sock = NULL;
+
+ switch (protocol) {
+ case UDP:
+ result = isc_nm_listenudp(netmgr, &sockaddr, read_cb, NULL, 0,
+ &sock);
+ break;
+ case TCP:
+ result = isc_nm_listentcpdns(netmgr, &sockaddr, read_cb, NULL,
+ accept_cb, NULL, 0, 0, NULL,
+ &sock);
+ break;
+ case DOT: {
+ isc_tlsctx_createserver(NULL, NULL, &tls_ctx);
+
+ result = isc_nm_listentlsdns(netmgr, &sockaddr, read_cb, NULL,
+ accept_cb, NULL, 0, 0, NULL,
+ tls_ctx, &sock);
+ break;
+ }
+#if HAVE_LIBNGHTTP2
+ case HTTPS:
+ case HTTP: {
+ bool is_https = protocol == HTTPS;
+ isc_nm_http_endpoints_t *eps = NULL;
+ if (is_https) {
+ isc_tlsctx_createserver(NULL, NULL, &tls_ctx);
+ }
+ eps = isc_nm_http_endpoints_new(mctx);
+ result = isc_nm_http_endpoints_add(
+ eps, ISC_NM_HTTP_DEFAULT_PATH, read_cb, NULL, 0);
+
+ if (result == ISC_R_SUCCESS) {
+ result = isc_nm_listenhttp(netmgr, &sockaddr, 0, NULL,
+ tls_ctx, eps, 0, &sock);
+ }
+ isc_nm_http_endpoints_detach(&eps);
+ } break;
+#endif
+ default:
+ UNREACHABLE();
+ }
+ REQUIRE(result == ISC_R_SUCCESS);
+
+ test_server_yield();
+
+ isc_nm_stoplistening(sock);
+ isc_nmsocket_close(&sock);
+}
+
+int
+main(int argc, char **argv) {
+ parse_options(argc, argv);
+
+ setup();
+
+ run();
+
+ teardown();
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/bin/tests/wire_test.c b/bin/tests/wire_test.c
new file mode 100644
index 0000000..5b079ce
--- /dev/null
+++ b/bin/tests/wire_test.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/message.h>
+
+int parseflags = 0;
+isc_mem_t *mctx = NULL;
+bool printmemstats = false;
+bool dorender = false;
+
+static void
+process_message(isc_buffer_t *source);
+
+static isc_result_t
+printmessage(dns_message_t *msg);
+
+static void
+CHECKRESULT(isc_result_t result, const char *msg) {
+ if (result != ISC_R_SUCCESS) {
+ printf("%s: %s\n", msg, isc_result_totext(result));
+
+ exit(1);
+ }
+}
+
+static int
+fromhex(char c) {
+ if (c >= '0' && c <= '9') {
+ return (c - '0');
+ } else if (c >= 'a' && c <= 'f') {
+ return (c - 'a' + 10);
+ } else if (c >= 'A' && c <= 'F') {
+ return (c - 'A' + 10);
+ }
+
+ fprintf(stderr, "bad input format: %02x\n", c);
+ exit(3);
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "wire_test [-b] [-d] [-p] [-r] [-s]\n");
+ fprintf(stderr, " [-m {usage|trace|record|size|mctx}]\n");
+ fprintf(stderr, " [filename]\n\n");
+ fprintf(stderr, "\t-b\tBest-effort parsing (ignore some errors)\n");
+ fprintf(stderr, "\t-d\tRead input as raw binary data\n");
+ fprintf(stderr, "\t-p\tPreserve order of the records in messages\n");
+ fprintf(stderr, "\t-r\tAfter parsing, re-render the message\n");
+ fprintf(stderr, "\t-s\tPrint memory statistics\n");
+ fprintf(stderr, "\t-t\tTCP mode - ignore the first 2 bytes\n");
+}
+
+static isc_result_t
+printmessage(dns_message_t *msg) {
+ isc_buffer_t b;
+ char *buf = NULL;
+ int len = 1024;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ do {
+ buf = isc_mem_get(mctx, len);
+
+ isc_buffer_init(&b, buf, len);
+ result = dns_message_totext(msg, &dns_master_style_debug, 0,
+ &b);
+ if (result == ISC_R_NOSPACE) {
+ isc_mem_put(mctx, buf, len);
+ len *= 2;
+ } else if (result == ISC_R_SUCCESS) {
+ printf("%.*s\n", (int)isc_buffer_usedlength(&b), buf);
+ }
+ } while (result == ISC_R_NOSPACE);
+
+ if (buf != NULL) {
+ isc_mem_put(mctx, buf, len);
+ }
+
+ return (result);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_buffer_t *input = NULL;
+ bool need_close = false;
+ bool tcp = false;
+ bool rawdata = false;
+ isc_result_t result;
+ uint8_t c;
+ FILE *f;
+ int ch;
+
+#define CMDLINE_FLAGS "bdm:prst"
+ /*
+ * Process memory debugging argument first.
+ */
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case 'm':
+ if (strcasecmp(isc_commandline_argument, "record") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ }
+ if (strcasecmp(isc_commandline_argument, "trace") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
+ }
+ if (strcasecmp(isc_commandline_argument, "usage") == 0)
+ {
+ isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = true;
+
+ isc_mem_create(&mctx);
+
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case 'b':
+ parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
+ break;
+ case 'd':
+ rawdata = true;
+ break;
+ case 'm':
+ break;
+ case 'p':
+ parseflags |= DNS_MESSAGEPARSE_PRESERVEORDER;
+ break;
+ case 'r':
+ dorender = true;
+ break;
+ case 's':
+ printmemstats = true;
+ break;
+ case 't':
+ tcp = true;
+ break;
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc >= 1) {
+ f = fopen(argv[0], "r");
+ if (f == NULL) {
+ fprintf(stderr, "%s: fopen failed\n", argv[0]);
+ exit(1);
+ }
+ need_close = true;
+ } else {
+ f = stdin;
+ }
+
+ isc_buffer_allocate(mctx, &input, 64 * 1024);
+
+ if (rawdata) {
+ while (fread(&c, 1, 1, f) != 0) {
+ result = isc_buffer_reserve(&input, 1);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_buffer_putuint8(input, (uint8_t)c);
+ }
+ } else {
+ char s[BUFSIZ];
+
+ while (fgets(s, sizeof(s), f) != NULL) {
+ char *rp = s, *wp = s;
+ size_t i, len = 0;
+
+ while (*rp != '\0') {
+ if (*rp == '#') {
+ break;
+ }
+ if (*rp != ' ' && *rp != '\t' && *rp != '\r' &&
+ *rp != '\n')
+ {
+ *wp++ = *rp;
+ len++;
+ }
+ rp++;
+ }
+ if (len == 0U) {
+ continue;
+ }
+ if (len % 2 != 0U) {
+ fprintf(stderr, "bad input format: %lu\n",
+ (unsigned long)len);
+ exit(1);
+ }
+
+ rp = s;
+ for (i = 0; i < len; i += 2) {
+ c = fromhex(*rp++);
+ c *= 16;
+ c += fromhex(*rp++);
+ result = isc_buffer_reserve(&input, 1);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_buffer_putuint8(input, (uint8_t)c);
+ }
+ }
+ }
+
+ if (need_close) {
+ fclose(f);
+ }
+
+ if (tcp) {
+ while (isc_buffer_remaininglength(input) != 0) {
+ unsigned int tcplen;
+
+ if (isc_buffer_remaininglength(input) < 2) {
+ fprintf(stderr, "premature end of packet\n");
+ exit(1);
+ }
+ tcplen = isc_buffer_getuint16(input);
+
+ if (isc_buffer_remaininglength(input) < tcplen) {
+ fprintf(stderr, "premature end of packet\n");
+ exit(1);
+ }
+ process_message(input);
+ }
+ } else {
+ process_message(input);
+ }
+
+ isc_buffer_free(&input);
+
+ if (printmemstats) {
+ isc_mem_stats(mctx, stdout);
+ }
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
+
+static void
+process_message(isc_buffer_t *source) {
+ dns_message_t *message;
+ isc_result_t result;
+ int i;
+
+ message = NULL;
+ dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message);
+
+ result = dns_message_parse(message, source, parseflags);
+ if (result == DNS_R_RECOVERABLE) {
+ result = ISC_R_SUCCESS;
+ }
+ CHECKRESULT(result, "dns_message_parse failed");
+
+ result = printmessage(message);
+ CHECKRESULT(result, "printmessage() failed");
+
+ if (printmemstats) {
+ isc_mem_stats(mctx, stdout);
+ }
+
+ if (dorender) {
+ unsigned char b2[64 * 1024];
+ isc_buffer_t buffer;
+ dns_compress_t cctx;
+
+ isc_buffer_init(&buffer, b2, sizeof(b2));
+
+ /*
+ * XXXMLG
+ * Changing this here is a hack, and should not be done in
+ * reasonable application code, ever.
+ */
+ message->from_to_wire = DNS_MESSAGE_INTENTRENDER;
+
+ for (i = 0; i < DNS_SECTION_MAX; i++) {
+ message->counts[i] = 0; /* Another hack XXX */
+ }
+
+ result = dns_compress_init(&cctx, -1, mctx);
+ CHECKRESULT(result, "dns_compress_init() failed");
+
+ result = dns_message_renderbegin(message, &cctx, &buffer);
+ CHECKRESULT(result, "dns_message_renderbegin() failed");
+
+ result = dns_message_rendersection(message,
+ DNS_SECTION_QUESTION, 0);
+ CHECKRESULT(result, "dns_message_rendersection(QUESTION) "
+ "failed");
+
+ result = dns_message_rendersection(message, DNS_SECTION_ANSWER,
+ 0);
+ CHECKRESULT(result, "dns_message_rendersection(ANSWER) failed");
+
+ result = dns_message_rendersection(message,
+ DNS_SECTION_AUTHORITY, 0);
+ CHECKRESULT(result, "dns_message_rendersection(AUTHORITY) "
+ "failed");
+
+ result = dns_message_rendersection(message,
+ DNS_SECTION_ADDITIONAL, 0);
+ CHECKRESULT(result, "dns_message_rendersection(ADDITIONAL) "
+ "failed");
+
+ dns_message_renderend(message);
+
+ dns_compress_invalidate(&cctx);
+
+ message->from_to_wire = DNS_MESSAGE_INTENTPARSE;
+ dns_message_detach(&message);
+
+ printf("Message rendered.\n");
+ if (printmemstats) {
+ isc_mem_stats(mctx, stdout);
+ }
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message);
+
+ result = dns_message_parse(message, &buffer, parseflags);
+ CHECKRESULT(result, "dns_message_parse failed");
+
+ result = printmessage(message);
+ CHECKRESULT(result, "printmessage() failed");
+ }
+ dns_message_detach(&message);
+}
diff --git a/bin/tools/Makefile.am b/bin/tools/Makefile.am
new file mode 100644
index 0000000..d7b8e4a
--- /dev/null
+++ b/bin/tools/Makefile.am
@@ -0,0 +1,58 @@
+include $(top_srcdir)/Makefile.top
+
+AM_CPPFLAGS += \
+ $(LIBISC_CFLAGS) \
+ $(LIBDNS_CFLAGS)
+
+LDADD += \
+ $(LIBDNS_LIBS) \
+ $(LIBISC_LIBS)
+
+bin_PROGRAMS = \
+ arpaname \
+ mdig \
+ named-journalprint \
+ named-rrchecker \
+ nsec3hash
+
+arpaname_LDADD = \
+ $(LIBISC_LIBS)
+
+mdig_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBBIND9_CFLAGS)
+
+mdig_LDADD = \
+ $(LIBBIND9_LIBS) \
+ $(LIBISCCFG_LIBS) \
+ $(LIBDNS_LIBS) \
+ $(LIBISC_LIBS)
+
+if HAVE_DNSTAP
+bin_PROGRAMS += \
+ dnstap-read
+
+dnstap_read_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(DNSTAP_CFLAGS) \
+ -I$(top_builddir)/lib/dns
+
+dnstap_read_LDADD = \
+ $(LIBDNS_LIBS) \
+ $(LIBISC_LIBS) \
+ $(DNSTAP_LIBS)
+endif
+
+if HAVE_LMDB
+bin_PROGRAMS += \
+ named-nzd2nzf
+
+named_nzd2nzf_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LMDB_CFLAGS)
+
+named_nzd2nzf_LDADD = \
+ $(LIBISC_LIBS) \
+ $(LMDB_LIBS)
+
+endif
diff --git a/bin/tools/Makefile.in b/bin/tools/Makefile.in
new file mode 100644
index 0000000..aa0a14b
--- /dev/null
+++ b/bin/tools/Makefile.in
@@ -0,0 +1,968 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Hey Emacs, this is -*- makefile-automake -*- file!
+# vim: filetype=automake
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HOST_MACOS_TRUE@am__append_1 = \
+@HOST_MACOS_TRUE@ -Wl,-flat_namespace
+
+bin_PROGRAMS = arpaname$(EXEEXT) mdig$(EXEEXT) \
+ named-journalprint$(EXEEXT) named-rrchecker$(EXEEXT) \
+ nsec3hash$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2)
+@HAVE_DNSTAP_TRUE@am__append_2 = \
+@HAVE_DNSTAP_TRUE@ dnstap-read
+
+@HAVE_LMDB_TRUE@am__append_3 = \
+@HAVE_LMDB_TRUE@ named-nzd2nzf
+
+subdir = bin/tools
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4/ax_jemalloc.m4 \
+ $(top_srcdir)/m4/ax_lib_lmdb.m4 \
+ $(top_srcdir)/m4/ax_perl_module.m4 \
+ $(top_srcdir)/m4/ax_posix_shell.m4 \
+ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_python_module.m4 \
+ $(top_srcdir)/m4/ax_restore_flags.m4 \
+ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+@HAVE_DNSTAP_TRUE@am__EXEEXT_1 = dnstap-read$(EXEEXT)
+@HAVE_LMDB_TRUE@am__EXEEXT_2 = named-nzd2nzf$(EXEEXT)
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+arpaname_SOURCES = arpaname.c
+arpaname_OBJECTS = arpaname.$(OBJEXT)
+arpaname_DEPENDENCIES = $(LIBISC_LIBS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+dnstap_read_SOURCES = dnstap-read.c
+dnstap_read_OBJECTS = dnstap_read-dnstap-read.$(OBJEXT)
+am__DEPENDENCIES_1 =
+@HAVE_DNSTAP_TRUE@dnstap_read_DEPENDENCIES = $(LIBDNS_LIBS) \
+@HAVE_DNSTAP_TRUE@ $(LIBISC_LIBS) $(am__DEPENDENCIES_1)
+mdig_SOURCES = mdig.c
+mdig_OBJECTS = mdig-mdig.$(OBJEXT)
+mdig_DEPENDENCIES = $(LIBBIND9_LIBS) $(LIBISCCFG_LIBS) $(LIBDNS_LIBS) \
+ $(LIBISC_LIBS)
+named_journalprint_SOURCES = named-journalprint.c
+named_journalprint_OBJECTS = named-journalprint.$(OBJEXT)
+named_journalprint_LDADD = $(LDADD)
+named_journalprint_DEPENDENCIES = $(LIBDNS_LIBS) $(LIBISC_LIBS)
+named_nzd2nzf_SOURCES = named-nzd2nzf.c
+named_nzd2nzf_OBJECTS = named_nzd2nzf-named-nzd2nzf.$(OBJEXT)
+@HAVE_LMDB_TRUE@named_nzd2nzf_DEPENDENCIES = $(LIBISC_LIBS) \
+@HAVE_LMDB_TRUE@ $(am__DEPENDENCIES_1)
+named_rrchecker_SOURCES = named-rrchecker.c
+named_rrchecker_OBJECTS = named-rrchecker.$(OBJEXT)
+named_rrchecker_LDADD = $(LDADD)
+named_rrchecker_DEPENDENCIES = $(LIBDNS_LIBS) $(LIBISC_LIBS)
+nsec3hash_SOURCES = nsec3hash.c
+nsec3hash_OBJECTS = nsec3hash.$(OBJEXT)
+nsec3hash_LDADD = $(LDADD)
+nsec3hash_DEPENDENCIES = $(LIBDNS_LIBS) $(LIBISC_LIBS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/arpaname.Po \
+ ./$(DEPDIR)/dnstap_read-dnstap-read.Po \
+ ./$(DEPDIR)/mdig-mdig.Po ./$(DEPDIR)/named-journalprint.Po \
+ ./$(DEPDIR)/named-rrchecker.Po \
+ ./$(DEPDIR)/named_nzd2nzf-named-nzd2nzf.Po \
+ ./$(DEPDIR)/nsec3hash.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = arpaname.c dnstap-read.c mdig.c named-journalprint.c \
+ named-nzd2nzf.c named-rrchecker.c nsec3hash.c
+DIST_SOURCES = arpaname.c dnstap-read.c mdig.c named-journalprint.c \
+ named-nzd2nzf.c named-rrchecker.c nsec3hash.c
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = test-recursive unit-recursive \
+ doc-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
+CMOCKA_LIBS = @CMOCKA_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURL = @CURL@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEVELOPER_MODE = @DEVELOPER_MODE@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FSTRM_CAPTURE = @FSTRM_CAPTURE@
+FUZZ_LDFLAGS = @FUZZ_LDFLAGS@
+FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@
+JEMALLOC_LIBS = @JEMALLOC_LIBS@
+JSON_C_CFLAGS = @JSON_C_CFLAGS@
+JSON_C_LIBS = @JSON_C_LIBS@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LATEXMK = @LATEXMK@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBCAP_LIBS = @LIBCAP_LIBS@
+LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@
+LIBIDN2_LIBS = @LIBIDN2_LIBS@
+LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@
+LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUV_CFLAGS = @LIBUV_CFLAGS@
+LIBUV_LIBS = @LIBUV_LIBS@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
+LIPO = @LIPO@
+LMDB_CFLAGS = @LMDB_CFLAGS@
+LMDB_LIBS = @LMDB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@
+MAXMINDDB_LIBS = @MAXMINDDB_LIBS@
+MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@
+MKDIR_P = @MKDIR_P@
+NC = @NC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTEST = @PYTEST@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+READLINE_CFLAGS = @READLINE_CFLAGS@
+READLINE_LIBS = @READLINE_LIBS@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINX_BUILD = @SPHINX_BUILD@
+STD_CFLAGS = @STD_CFLAGS@
+STD_CPPFLAGS = @STD_CPPFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+VERSION = @VERSION@
+XELATEX = @XELATEX@
+XSLTPROC = @XSLTPROC@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CFLAGS = \
+ $(STD_CFLAGS)
+
+AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \
+ -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS)
+AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1)
+LDADD = $(LIBDNS_LIBS) $(LIBISC_LIBS)
+LIBISC_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/lib/isc/include \
+ -I$(top_builddir)/lib/isc/include
+
+LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la
+LIBDNS_CFLAGS = \
+ -I$(top_srcdir)/lib/dns/include \
+ -I$(top_builddir)/lib/dns/include
+
+LIBDNS_LIBS = \
+ $(top_builddir)/lib/dns/libdns.la
+
+LIBNS_CFLAGS = \
+ -I$(top_srcdir)/lib/ns/include
+
+LIBNS_LIBS = \
+ $(top_builddir)/lib/ns/libns.la
+
+LIBIRS_CFLAGS = \
+ -I$(top_srcdir)/lib/irs/include
+
+LIBIRS_LIBS = \
+ $(top_builddir)/lib/irs/libirs.la
+
+LIBISCCFG_CFLAGS = \
+ -I$(top_srcdir)/lib/isccfg/include
+
+LIBISCCFG_LIBS = \
+ $(top_builddir)/lib/isccfg/libisccfg.la
+
+LIBISCCC_CFLAGS = \
+ -I$(top_srcdir)/lib/isccc/include/
+
+LIBISCCC_LIBS = \
+ $(top_builddir)/lib/isccc/libisccc.la
+
+LIBBIND9_CFLAGS = \
+ -I$(top_srcdir)/lib/bind9/include
+
+LIBBIND9_LIBS = \
+ $(top_builddir)/lib/bind9/libbind9.la
+
+arpaname_LDADD = \
+ $(LIBISC_LIBS)
+
+mdig_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(LIBBIND9_CFLAGS)
+
+mdig_LDADD = \
+ $(LIBBIND9_LIBS) \
+ $(LIBISCCFG_LIBS) \
+ $(LIBDNS_LIBS) \
+ $(LIBISC_LIBS)
+
+@HAVE_DNSTAP_TRUE@dnstap_read_CPPFLAGS = \
+@HAVE_DNSTAP_TRUE@ $(AM_CPPFLAGS) \
+@HAVE_DNSTAP_TRUE@ $(DNSTAP_CFLAGS) \
+@HAVE_DNSTAP_TRUE@ -I$(top_builddir)/lib/dns
+
+@HAVE_DNSTAP_TRUE@dnstap_read_LDADD = \
+@HAVE_DNSTAP_TRUE@ $(LIBDNS_LIBS) \
+@HAVE_DNSTAP_TRUE@ $(LIBISC_LIBS) \
+@HAVE_DNSTAP_TRUE@ $(DNSTAP_LIBS)
+
+@HAVE_LMDB_TRUE@named_nzd2nzf_CPPFLAGS = \
+@HAVE_LMDB_TRUE@ $(AM_CPPFLAGS) \
+@HAVE_LMDB_TRUE@ $(LMDB_CFLAGS)
+
+@HAVE_LMDB_TRUE@named_nzd2nzf_LDADD = \
+@HAVE_LMDB_TRUE@ $(LIBISC_LIBS) \
+@HAVE_LMDB_TRUE@ $(LMDB_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tools/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bin/tools/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/Makefile.top $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+arpaname$(EXEEXT): $(arpaname_OBJECTS) $(arpaname_DEPENDENCIES) $(EXTRA_arpaname_DEPENDENCIES)
+ @rm -f arpaname$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(arpaname_OBJECTS) $(arpaname_LDADD) $(LIBS)
+
+dnstap-read$(EXEEXT): $(dnstap_read_OBJECTS) $(dnstap_read_DEPENDENCIES) $(EXTRA_dnstap_read_DEPENDENCIES)
+ @rm -f dnstap-read$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(dnstap_read_OBJECTS) $(dnstap_read_LDADD) $(LIBS)
+
+mdig$(EXEEXT): $(mdig_OBJECTS) $(mdig_DEPENDENCIES) $(EXTRA_mdig_DEPENDENCIES)
+ @rm -f mdig$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(mdig_OBJECTS) $(mdig_LDADD) $(LIBS)
+
+named-journalprint$(EXEEXT): $(named_journalprint_OBJECTS) $(named_journalprint_DEPENDENCIES) $(EXTRA_named_journalprint_DEPENDENCIES)
+ @rm -f named-journalprint$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(named_journalprint_OBJECTS) $(named_journalprint_LDADD) $(LIBS)
+
+named-nzd2nzf$(EXEEXT): $(named_nzd2nzf_OBJECTS) $(named_nzd2nzf_DEPENDENCIES) $(EXTRA_named_nzd2nzf_DEPENDENCIES)
+ @rm -f named-nzd2nzf$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(named_nzd2nzf_OBJECTS) $(named_nzd2nzf_LDADD) $(LIBS)
+
+named-rrchecker$(EXEEXT): $(named_rrchecker_OBJECTS) $(named_rrchecker_DEPENDENCIES) $(EXTRA_named_rrchecker_DEPENDENCIES)
+ @rm -f named-rrchecker$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(named_rrchecker_OBJECTS) $(named_rrchecker_LDADD) $(LIBS)
+
+nsec3hash$(EXEEXT): $(nsec3hash_OBJECTS) $(nsec3hash_DEPENDENCIES) $(EXTRA_nsec3hash_DEPENDENCIES)
+ @rm -f nsec3hash$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(nsec3hash_OBJECTS) $(nsec3hash_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arpaname.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnstap_read-dnstap-read.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mdig-mdig.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/named-journalprint.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/named-rrchecker.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/named_nzd2nzf-named-nzd2nzf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nsec3hash.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+dnstap_read-dnstap-read.o: dnstap-read.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnstap_read_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dnstap_read-dnstap-read.o -MD -MP -MF $(DEPDIR)/dnstap_read-dnstap-read.Tpo -c -o dnstap_read-dnstap-read.o `test -f 'dnstap-read.c' || echo '$(srcdir)/'`dnstap-read.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dnstap_read-dnstap-read.Tpo $(DEPDIR)/dnstap_read-dnstap-read.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnstap-read.c' object='dnstap_read-dnstap-read.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnstap_read_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dnstap_read-dnstap-read.o `test -f 'dnstap-read.c' || echo '$(srcdir)/'`dnstap-read.c
+
+dnstap_read-dnstap-read.obj: dnstap-read.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnstap_read_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dnstap_read-dnstap-read.obj -MD -MP -MF $(DEPDIR)/dnstap_read-dnstap-read.Tpo -c -o dnstap_read-dnstap-read.obj `if test -f 'dnstap-read.c'; then $(CYGPATH_W) 'dnstap-read.c'; else $(CYGPATH_W) '$(srcdir)/dnstap-read.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dnstap_read-dnstap-read.Tpo $(DEPDIR)/dnstap_read-dnstap-read.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnstap-read.c' object='dnstap_read-dnstap-read.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnstap_read_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dnstap_read-dnstap-read.obj `if test -f 'dnstap-read.c'; then $(CYGPATH_W) 'dnstap-read.c'; else $(CYGPATH_W) '$(srcdir)/dnstap-read.c'; fi`
+
+mdig-mdig.o: mdig.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mdig_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mdig-mdig.o -MD -MP -MF $(DEPDIR)/mdig-mdig.Tpo -c -o mdig-mdig.o `test -f 'mdig.c' || echo '$(srcdir)/'`mdig.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mdig-mdig.Tpo $(DEPDIR)/mdig-mdig.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mdig.c' object='mdig-mdig.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mdig_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mdig-mdig.o `test -f 'mdig.c' || echo '$(srcdir)/'`mdig.c
+
+mdig-mdig.obj: mdig.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mdig_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mdig-mdig.obj -MD -MP -MF $(DEPDIR)/mdig-mdig.Tpo -c -o mdig-mdig.obj `if test -f 'mdig.c'; then $(CYGPATH_W) 'mdig.c'; else $(CYGPATH_W) '$(srcdir)/mdig.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mdig-mdig.Tpo $(DEPDIR)/mdig-mdig.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mdig.c' object='mdig-mdig.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mdig_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mdig-mdig.obj `if test -f 'mdig.c'; then $(CYGPATH_W) 'mdig.c'; else $(CYGPATH_W) '$(srcdir)/mdig.c'; fi`
+
+named_nzd2nzf-named-nzd2nzf.o: named-nzd2nzf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(named_nzd2nzf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT named_nzd2nzf-named-nzd2nzf.o -MD -MP -MF $(DEPDIR)/named_nzd2nzf-named-nzd2nzf.Tpo -c -o named_nzd2nzf-named-nzd2nzf.o `test -f 'named-nzd2nzf.c' || echo '$(srcdir)/'`named-nzd2nzf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/named_nzd2nzf-named-nzd2nzf.Tpo $(DEPDIR)/named_nzd2nzf-named-nzd2nzf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='named-nzd2nzf.c' object='named_nzd2nzf-named-nzd2nzf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(named_nzd2nzf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o named_nzd2nzf-named-nzd2nzf.o `test -f 'named-nzd2nzf.c' || echo '$(srcdir)/'`named-nzd2nzf.c
+
+named_nzd2nzf-named-nzd2nzf.obj: named-nzd2nzf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(named_nzd2nzf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT named_nzd2nzf-named-nzd2nzf.obj -MD -MP -MF $(DEPDIR)/named_nzd2nzf-named-nzd2nzf.Tpo -c -o named_nzd2nzf-named-nzd2nzf.obj `if test -f 'named-nzd2nzf.c'; then $(CYGPATH_W) 'named-nzd2nzf.c'; else $(CYGPATH_W) '$(srcdir)/named-nzd2nzf.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/named_nzd2nzf-named-nzd2nzf.Tpo $(DEPDIR)/named_nzd2nzf-named-nzd2nzf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='named-nzd2nzf.c' object='named_nzd2nzf-named-nzd2nzf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(named_nzd2nzf_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o named_nzd2nzf-named-nzd2nzf.obj `if test -f 'named-nzd2nzf.c'; then $(CYGPATH_W) 'named-nzd2nzf.c'; else $(CYGPATH_W) '$(srcdir)/named-nzd2nzf.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+test-local:
+unit-local:
+doc-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/arpaname.Po
+ -rm -f ./$(DEPDIR)/dnstap_read-dnstap-read.Po
+ -rm -f ./$(DEPDIR)/mdig-mdig.Po
+ -rm -f ./$(DEPDIR)/named-journalprint.Po
+ -rm -f ./$(DEPDIR)/named-rrchecker.Po
+ -rm -f ./$(DEPDIR)/named_nzd2nzf-named-nzd2nzf.Po
+ -rm -f ./$(DEPDIR)/nsec3hash.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+doc: doc-am
+
+doc-am: doc-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/arpaname.Po
+ -rm -f ./$(DEPDIR)/dnstap_read-dnstap-read.Po
+ -rm -f ./$(DEPDIR)/mdig-mdig.Po
+ -rm -f ./$(DEPDIR)/named-journalprint.Po
+ -rm -f ./$(DEPDIR)/named-rrchecker.Po
+ -rm -f ./$(DEPDIR)/named_nzd2nzf-named-nzd2nzf.Po
+ -rm -f ./$(DEPDIR)/nsec3hash.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+test: test-am
+
+test-am: test-local
+
+uninstall-am: uninstall-binPROGRAMS
+
+unit: unit-am
+
+unit-am: unit-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir doc-am doc-local dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \
+ uninstall-am uninstall-binPROGRAMS unit-am unit-local
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/tools/arpaname.c b/bin/tools/arpaname.c
new file mode 100644
index 0000000..cfbe187
--- /dev/null
+++ b/bin/tools/arpaname.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stdio.h>
+
+#include <isc/net.h>
+#include <isc/print.h>
+
+#define UNUSED(x) (void)(x)
+
+int
+main(int argc, char *argv[]) {
+ unsigned char buf[16];
+ int i;
+
+ UNUSED(argc);
+
+ while (argv[1]) {
+ if (inet_pton(AF_INET6, argv[1], buf) == 1) {
+ for (i = 15; i >= 0; i--) {
+ fprintf(stdout, "%X.%X.", buf[i] & 0xf,
+ (buf[i] >> 4) & 0xf);
+ }
+ fprintf(stdout, "IP6.ARPA\n");
+ argv++;
+ continue;
+ }
+ if (inet_pton(AF_INET, argv[1], buf) == 1) {
+ fprintf(stdout, "%u.%u.%u.%u.IN-ADDR.ARPA\n", buf[3],
+ buf[2], buf[1], buf[0]);
+ argv++;
+ continue;
+ }
+ return (1);
+ }
+ fflush(stdout);
+ return (ferror(stdout));
+}
diff --git a/bin/tools/arpaname.rst b/bin/tools/arpaname.rst
new file mode 100644
index 0000000..00ed897
--- /dev/null
+++ b/bin/tools/arpaname.rst
@@ -0,0 +1,35 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: arpaname
+.. program:: arpaname
+.. _man_arpaname:
+
+arpaname - translate IP addresses to the corresponding ARPA names
+-----------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`arpaname` {*ipaddress* ...}
+
+Description
+~~~~~~~~~~~
+
+:program:`arpaname` translates IP addresses (IPv4 and IPv6) to the
+corresponding IN-ADDR.ARPA or IP6.ARPA names.
+
+See Also
+~~~~~~~~
+
+BIND 9 Administrator Reference Manual.
diff --git a/bin/tools/dnstap-read.c b/bin/tools/dnstap-read.c
new file mode 100644
index 0000000..f6abeeb
--- /dev/null
+++ b/bin/tools/dnstap-read.c
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions of this code were adapted from dnstap-ldns:
+ *
+ * Copyright (c) 2014 by Farsight Security, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <protobuf-c/protobuf-c.h>
+
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/hex.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/dnstap.h>
+#include <dns/fixedname.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.h>
+
+#include "dnstap.pb-c.h"
+
+isc_mem_t *mctx = NULL;
+bool memrecord = false;
+bool printmessage = false;
+bool hexmessage = false;
+bool yaml = false;
+
+const char *program = "dnstap-read";
+
+#define CHECKM(op, msg) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ fprintf(stderr, "%s: %s: %s\n", program, msg, \
+ isc_result_totext(result)); \
+ goto cleanup; \
+ } \
+ } while (0)
+
+noreturn static void
+fatal(const char *format, ...);
+
+static void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fprintf(stderr, "%s: fatal: ", program);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "dnstap-read [-mpxy] [filename]\n");
+ fprintf(stderr, "\t-m\ttrace memory allocations\n");
+ fprintf(stderr, "\t-p\tprint the full DNS message\n");
+ fprintf(stderr, "\t-x\tuse hex format to print DNS message\n");
+ fprintf(stderr, "\t-y\tprint YAML format (implies -p)\n");
+}
+
+static void
+print_dtdata(dns_dtdata_t *dt) {
+ isc_result_t result;
+ isc_buffer_t *b = NULL;
+
+ isc_buffer_allocate(mctx, &b, 2048);
+ if (b == NULL) {
+ fatal("out of memory");
+ }
+
+ CHECKM(dns_dt_datatotext(dt, &b), "dns_dt_datatotext");
+ printf("%.*s\n", (int)isc_buffer_usedlength(b),
+ (char *)isc_buffer_base(b));
+
+cleanup:
+ if (b != NULL) {
+ isc_buffer_free(&b);
+ }
+}
+
+static void
+print_hex(dns_dtdata_t *dt) {
+ isc_buffer_t *b = NULL;
+ isc_result_t result;
+ size_t textlen;
+
+ if (dt->msg == NULL) {
+ return;
+ }
+
+ textlen = (dt->msgdata.length * 2) + 1;
+ isc_buffer_allocate(mctx, &b, textlen);
+ if (b == NULL) {
+ fatal("out of memory");
+ }
+
+ result = isc_hex_totext(&dt->msgdata, 0, "", b);
+ CHECKM(result, "isc_hex_totext");
+
+ printf("%.*s\n", (int)isc_buffer_usedlength(b),
+ (char *)isc_buffer_base(b));
+
+cleanup:
+ if (b != NULL) {
+ isc_buffer_free(&b);
+ }
+}
+
+static void
+print_packet(dns_dtdata_t *dt, const dns_master_style_t *style) {
+ isc_buffer_t *b = NULL;
+ isc_result_t result;
+
+ if (dt->msg != NULL) {
+ size_t textlen = 2048;
+
+ isc_buffer_allocate(mctx, &b, textlen);
+ if (b == NULL) {
+ fatal("out of memory");
+ }
+
+ for (;;) {
+ isc_buffer_reserve(&b, textlen);
+ if (b == NULL) {
+ fatal("out of memory");
+ }
+
+ result = dns_message_totext(dt->msg, style, 0, b);
+ if (result == ISC_R_NOSPACE) {
+ isc_buffer_clear(b);
+ textlen *= 2;
+ continue;
+ } else if (result == ISC_R_SUCCESS) {
+ printf("%.*s", (int)isc_buffer_usedlength(b),
+ (char *)isc_buffer_base(b));
+ isc_buffer_free(&b);
+ } else {
+ isc_buffer_free(&b);
+ CHECKM(result, "dns_message_totext");
+ }
+ break;
+ }
+ }
+
+cleanup:
+ if (b != NULL) {
+ isc_buffer_free(&b);
+ }
+}
+
+static void
+print_yaml(dns_dtdata_t *dt) {
+ Dnstap__Dnstap *frame = dt->frame;
+ Dnstap__Message *m = frame->message;
+ const ProtobufCEnumValue *ftype, *mtype;
+ static bool first = true;
+
+ ftype = protobuf_c_enum_descriptor_get_value(
+ &dnstap__dnstap__type__descriptor, frame->type);
+ if (ftype == NULL) {
+ return;
+ }
+
+ if (!first) {
+ printf("---\n");
+ } else {
+ first = false;
+ }
+
+ printf("type: %s\n", ftype->name);
+
+ if (frame->has_identity) {
+ printf("identity: %.*s\n", (int)frame->identity.len,
+ frame->identity.data);
+ }
+
+ if (frame->has_version) {
+ printf("version: %.*s\n", (int)frame->version.len,
+ frame->version.data);
+ }
+
+ if (frame->type != DNSTAP__DNSTAP__TYPE__MESSAGE) {
+ return;
+ }
+
+ printf("message:\n");
+
+ mtype = protobuf_c_enum_descriptor_get_value(
+ &dnstap__message__type__descriptor, m->type);
+ if (mtype == NULL) {
+ return;
+ }
+
+ printf(" type: %s\n", mtype->name);
+
+ if (!isc_time_isepoch(&dt->qtime)) {
+ char buf[100];
+ isc_time_formatISO8601(&dt->qtime, buf, sizeof(buf));
+ printf(" query_time: !!timestamp %s\n", buf);
+ }
+
+ if (!isc_time_isepoch(&dt->rtime)) {
+ char buf[100];
+ isc_time_formatISO8601(&dt->rtime, buf, sizeof(buf));
+ printf(" response_time: !!timestamp %s\n", buf);
+ }
+
+ if (dt->msgdata.base != NULL) {
+ printf(" message_size: %zub\n", (size_t)dt->msgdata.length);
+ } else {
+ printf(" message_size: 0b\n");
+ }
+
+ if (m->has_socket_family) {
+ const ProtobufCEnumValue *type =
+ protobuf_c_enum_descriptor_get_value(
+ &dnstap__socket_family__descriptor,
+ m->socket_family);
+ if (type != NULL) {
+ printf(" socket_family: %s\n", type->name);
+ }
+ }
+
+ printf(" socket_protocol: %s\n", dt->tcp ? "TCP" : "UDP");
+
+ if (m->has_query_address) {
+ ProtobufCBinaryData *ip = &m->query_address;
+ char buf[100];
+
+ (void)inet_ntop(ip->len == 4 ? AF_INET : AF_INET6, ip->data,
+ buf, sizeof(buf));
+ printf(" query_address: \"%s\"\n", buf);
+ }
+
+ if (m->has_response_address) {
+ ProtobufCBinaryData *ip = &m->response_address;
+ char buf[100];
+
+ (void)inet_ntop(ip->len == 4 ? AF_INET : AF_INET6, ip->data,
+ buf, sizeof(buf));
+ printf(" response_address: \"%s\"\n", buf);
+ }
+
+ if (m->has_query_port) {
+ printf(" query_port: %u\n", m->query_port);
+ }
+
+ if (m->has_response_port) {
+ printf(" response_port: %u\n", m->response_port);
+ }
+
+ if (m->has_query_zone) {
+ isc_result_t result;
+ dns_fixedname_t fn;
+ dns_name_t *name;
+ isc_buffer_t b;
+ dns_decompress_t dctx;
+
+ name = dns_fixedname_initname(&fn);
+
+ isc_buffer_init(&b, m->query_zone.data, m->query_zone.len);
+ isc_buffer_add(&b, m->query_zone.len);
+
+ dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
+ result = dns_name_fromwire(name, &b, &dctx, 0, NULL);
+ if (result == ISC_R_SUCCESS) {
+ printf(" query_zone: ");
+ dns_name_print(name, stdout);
+ printf("\n");
+ }
+ }
+
+ if (dt->msg != NULL) {
+ dt->msg->indent.count = 2;
+ dt->msg->indent.string = " ";
+ printf(" %s:\n", ((dt->type & DNS_DTTYPE_QUERY) != 0)
+ ? "query_message_data"
+ : "response_message_data");
+
+ print_packet(dt, &dns_master_style_yaml);
+
+ printf(" %s: |\n", ((dt->type & DNS_DTTYPE_QUERY) != 0)
+ ? "query_message"
+ : "response_message");
+ print_packet(dt, &dns_master_style_indent);
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ dns_message_t *message = NULL;
+ isc_buffer_t *b = NULL;
+ dns_dtdata_t *dt = NULL;
+ dns_dthandle_t *handle = NULL;
+ int rv = 0, ch;
+
+ while ((ch = isc_commandline_parse(argc, argv, "mpxy")) != -1) {
+ switch (ch) {
+ case 'm':
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ memrecord = true;
+ break;
+ case 'p':
+ printmessage = true;
+ break;
+ case 'x':
+ hexmessage = true;
+ break;
+ case 'y':
+ yaml = true;
+ break;
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc < 1) {
+ fatal("no file specified");
+ }
+
+ isc_mem_create(&mctx);
+
+ CHECKM(dns_dt_open(argv[0], dns_dtmode_file, mctx, &handle),
+ "dns_dt_openfile");
+
+ for (;;) {
+ isc_region_t input;
+ uint8_t *data;
+ size_t datalen;
+
+ result = dns_dt_getframe(handle, &data, &datalen);
+ if (result == ISC_R_NOMORE) {
+ break;
+ } else {
+ CHECKM(result, "dns_dt_getframe");
+ }
+
+ input.base = data;
+ input.length = datalen;
+
+ if (b != NULL) {
+ isc_buffer_free(&b);
+ }
+ isc_buffer_allocate(mctx, &b, 2048);
+ if (b == NULL) {
+ fatal("out of memory");
+ }
+
+ result = dns_dt_parse(mctx, &input, &dt);
+ if (result != ISC_R_SUCCESS) {
+ isc_buffer_free(&b);
+ continue;
+ }
+
+ if (yaml) {
+ print_yaml(dt);
+ } else if (hexmessage) {
+ print_dtdata(dt);
+ print_hex(dt);
+ } else if (printmessage) {
+ print_dtdata(dt);
+ print_packet(dt, &dns_master_style_debug);
+ } else {
+ print_dtdata(dt);
+ }
+
+ dns_dtdata_free(&dt);
+ }
+
+cleanup:
+ if (dt != NULL) {
+ dns_dtdata_free(&dt);
+ }
+ if (handle != NULL) {
+ dns_dt_close(&handle);
+ }
+ if (message != NULL) {
+ dns_message_detach(&message);
+ }
+ if (b != NULL) {
+ isc_buffer_free(&b);
+ }
+ isc_mem_destroy(&mctx);
+
+ exit(rv);
+}
diff --git a/bin/tools/dnstap-read.rst b/bin/tools/dnstap-read.rst
new file mode 100644
index 0000000..a595682
--- /dev/null
+++ b/bin/tools/dnstap-read.rst
@@ -0,0 +1,58 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: dnstap-read
+.. program:: dnstap-read
+.. _man_dnstap-read:
+
+dnstap-read - print dnstap data in human-readable form
+------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`dnstap-read` [**-m**] [**-p**] [**-x**] [**-y**] {file}
+
+Description
+~~~~~~~~~~~
+
+:program:`dnstap-read` reads ``dnstap`` data from a specified file and prints
+it in a human-readable format. By default, ``dnstap`` data is printed in
+a short summary format, but if the :option:`-y` option is specified, a
+longer and more detailed YAML format is used.
+
+Options
+~~~~~~~
+
+.. option:: -m
+
+ This option indicates trace memory allocations, and is used for debugging memory leaks.
+
+.. option:: -p
+
+ This option prints the text form of the DNS
+ message that was encapsulated in the ``dnstap`` frame, after printing the ``dnstap`` data.
+
+.. option:: -x
+
+ This option prints a hex dump of the wire form
+ of the DNS message that was encapsulated in the ``dnstap`` frame, after printing the ``dnstap`` data.
+
+.. option:: -y
+
+ This option prints ``dnstap`` data in a detailed YAML format.
+
+See Also
+~~~~~~~~
+
+:iscman:`named(8) <named>`, :iscman:`rndc(8) <rndc>`, BIND 9 Administrator Reference Manual.
diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c
new file mode 100644
index 0000000..ae3fd86
--- /dev/null
+++ b/bin/tools/mdig.c
@@ -0,0 +1,2249 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/attributes.h>
+#include <isc/base64.h>
+#include <isc/hash.h>
+#include <isc/hex.h>
+#include <isc/log.h>
+#include <isc/managers.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/netmgr.h>
+#include <isc/nonce.h>
+#include <isc/parseint.h>
+#include <isc/portset.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/dispatch.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/request.h>
+#include <dns/resolver.h>
+#include <dns/types.h>
+#include <dns/view.h>
+
+#include <bind9/getaddresses.h>
+
+#define CHECK(str, x) \
+ { \
+ if ((x) != ISC_R_SUCCESS) { \
+ fprintf(stderr, "mdig: %s failed with %s\n", (str), \
+ isc_result_totext(x)); \
+ exit(-1); \
+ } \
+ }
+
+#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
+
+#define ADD_STRING(b, s) \
+ { \
+ if (strlen(s) >= isc_buffer_availablelength(b)) \
+ return ((ISC_R_NOSPACE)); \
+ else \
+ isc_buffer_putstr(b, s); \
+ }
+
+#define MXNAME (DNS_NAME_MAXTEXT + 1)
+#define COMMSIZE 0xffff
+#define OUTPUTBUF 32767
+#define MAXPORT 0xffff
+#define PORT 53
+#define MAXTIMEOUT 0xffff
+#define TCPTIMEOUT 10
+#define UDPTIMEOUT 5
+#define MAXTRIES 0xffffffff
+
+static isc_mem_t *mctx = NULL;
+static dns_requestmgr_t *requestmgr = NULL;
+static const char *batchname = NULL;
+static FILE *batchfp = NULL;
+static bool burst = false;
+static bool have_ipv4 = false;
+static bool have_ipv6 = false;
+static bool have_src = false;
+static bool tcp_mode = false;
+static bool besteffort = true;
+static bool display_short_form = false;
+static bool display_headers = true;
+static bool display_comments = true;
+static int display_rrcomments = 0;
+static bool display_ttlunits = true;
+static bool display_ttl = true;
+static bool display_class = true;
+static bool display_crypto = true;
+static bool display_multiline = false;
+static bool display_question = true;
+static bool display_answer = true;
+static bool display_authority = true;
+static bool display_additional = true;
+static bool display_unknown_format = false;
+static bool yaml = false;
+static bool continue_on_error = false;
+static uint32_t display_splitwidth = 0xffffffff;
+static isc_sockaddr_t srcaddr;
+static char *server = NULL;
+static isc_sockaddr_t dstaddr;
+static in_port_t port = 53;
+static unsigned char cookie_secret[33];
+static int onfly = 0;
+static char hexcookie[81];
+
+struct query {
+ char textname[MXNAME]; /*% Name we're going to be
+ * looking up */
+ bool recurse;
+ bool have_aaonly;
+ bool have_adflag;
+ bool have_cdflag;
+ bool have_zflag;
+ bool dnssec;
+ bool expire;
+ bool send_cookie;
+ char *cookie;
+ bool nsid;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ uint16_t udpsize;
+ int16_t edns;
+ dns_ednsopt_t *ednsopts;
+ unsigned int ednsoptscnt;
+ unsigned int ednsflags;
+ isc_sockaddr_t *ecs_addr;
+ unsigned int timeout;
+ unsigned int udptimeout;
+ unsigned int udpretries;
+ ISC_LINK(struct query) link;
+};
+static struct query default_query;
+static ISC_LIST(struct query) queries;
+
+#define EDNSOPTS 100U
+/*% opcode text */
+static const char *const opcodetext[] = {
+ "QUERY", "IQUERY", "STATUS", "RESERVED3",
+ "NOTIFY", "UPDATE", "RESERVED6", "RESERVED7",
+ "RESERVED8", "RESERVED9", "RESERVED10", "RESERVED11",
+ "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15"
+};
+
+/*% return code text */
+static const char *const rcodetext[] = {
+ "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP",
+ "REFUSED", "YXDOMAIN", "YXRRSET", "NXRRSET", "NOTAUTH",
+ "NOTZONE", "RESERVED11", "RESERVED12", "RESERVED13", "RESERVED14",
+ "RESERVED15", "BADVERS"
+};
+
+/*% safe rcodetext[] */
+static char *
+rcode_totext(dns_rcode_t rcode) {
+ static char buf[sizeof("?65535")];
+ union {
+ const char *consttext;
+ char *deconsttext;
+ } totext;
+
+ if (rcode >= (sizeof(rcodetext) / sizeof(rcodetext[0]))) {
+ snprintf(buf, sizeof(buf), "?%u", rcode);
+ totext.deconsttext = buf;
+ } else {
+ totext.consttext = rcodetext[rcode];
+ }
+ return (totext.deconsttext);
+}
+
+/* receive response event handler */
+static void
+recvresponse(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result;
+ dns_message_t *query = NULL, *response = NULL;
+ unsigned int parseflags = 0;
+ isc_buffer_t *msgbuf = NULL, *buf = NULL;
+ unsigned int len = OUTPUTBUF;
+ dns_master_style_t *style = NULL;
+ unsigned int styleflags = 0;
+ dns_messagetextflag_t flags;
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+ query = reqev->ev_arg;
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "response failed with %s\n",
+ isc_result_totext(reqev->result));
+ if (continue_on_error) {
+ goto cleanup;
+ } else {
+ exit(-1);
+ }
+ }
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+
+ parseflags |= DNS_MESSAGEPARSE_PRESERVEORDER;
+ if (besteffort) {
+ parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
+ parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
+ }
+
+ msgbuf = dns_request_getanswer(reqev->request);
+ result = dns_request_getresponse(reqev->request, response, parseflags);
+ CHECK("dns_request_getresponse", result);
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ if (yaml) {
+ styleflags |= DNS_STYLEFLAG_YAML;
+ response->indent.string = " ";
+ response->indent.count = 3;
+ } else {
+ if (display_comments) {
+ styleflags |= DNS_STYLEFLAG_COMMENT;
+ }
+ if (display_unknown_format) {
+ styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
+ }
+ if (display_rrcomments > 0) {
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+ if (display_ttlunits) {
+ styleflags |= DNS_STYLEFLAG_TTL_UNITS;
+ }
+ if (!display_ttl) {
+ styleflags |= DNS_STYLEFLAG_NO_TTL;
+ }
+ if (!display_class) {
+ styleflags |= DNS_STYLEFLAG_NO_CLASS;
+ }
+ if (!display_crypto) {
+ styleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ }
+ if (display_multiline) {
+ styleflags |= DNS_STYLEFLAG_OMIT_OWNER;
+ styleflags |= DNS_STYLEFLAG_OMIT_CLASS;
+ styleflags |= DNS_STYLEFLAG_REL_DATA;
+ styleflags |= DNS_STYLEFLAG_OMIT_TTL;
+ styleflags |= DNS_STYLEFLAG_TTL;
+ styleflags |= DNS_STYLEFLAG_MULTILINE;
+ styleflags |= DNS_STYLEFLAG_COMMENT;
+ /* Turn on rrcomments unless explicitly disabled */
+ if (display_rrcomments >= 0) {
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+ }
+ }
+ if (display_multiline || (!display_ttl && !display_class)) {
+ result = dns_master_stylecreate(&style, styleflags, 24, 24, 24,
+ 32, 80, 8, display_splitwidth,
+ mctx);
+ } else if (!display_ttl || !display_class) {
+ result = dns_master_stylecreate(&style, styleflags, 24, 24, 32,
+ 40, 80, 8, display_splitwidth,
+ mctx);
+ } else {
+ result = dns_master_stylecreate(&style, styleflags, 24, 32, 40,
+ 48, 80, 8, display_splitwidth,
+ mctx);
+ }
+ CHECK("dns_master_stylecreate2", result);
+
+ flags = 0;
+ if (!display_headers) {
+ flags |= DNS_MESSAGETEXTFLAG_NOHEADERS;
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+ }
+ if (!display_comments) {
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+ }
+
+ isc_buffer_allocate(mctx, &buf, len);
+
+ if (yaml) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+ uint16_t sport;
+ char *hash;
+ int pf;
+
+ printf("-\n");
+ printf(" type: MESSAGE\n");
+ printf(" message:\n");
+
+ if (((response->flags & DNS_MESSAGEFLAG_RD) != 0) &&
+ ((response->flags & DNS_MESSAGEFLAG_RA) != 0))
+ {
+ printf(" type: RECURSIVE_RESPONSE\n");
+ } else {
+ printf(" type: AUTH_RESPONSE\n");
+ }
+
+ printf(" message_size: %ub\n",
+ isc_buffer_usedlength(msgbuf));
+
+ pf = isc_sockaddr_pf(&dstaddr);
+ if (pf == PF_INET || pf == PF_INET6) {
+ printf(" socket_family: %s\n",
+ pf == PF_INET ? "INET" : "INET6");
+
+ printf(" socket_protocol: %s\n",
+ tcp_mode ? "TCP" : "UDP");
+
+ sport = isc_sockaddr_getport(&dstaddr);
+ isc_sockaddr_format(&dstaddr, sockstr, sizeof(sockstr));
+ hash = strchr(sockstr, '#');
+ if (hash != NULL) {
+ *hash = '\0';
+ }
+ printf(" response_address: \"%s\"\n", sockstr);
+ printf(" response_port: %u\n", sport);
+ }
+
+ if (have_src) {
+ sport = isc_sockaddr_getport(&srcaddr);
+ isc_sockaddr_format(&srcaddr, sockstr, sizeof(sockstr));
+ hash = strchr(sockstr, '#');
+ if (hash != NULL) {
+ *hash = '\0';
+ }
+ printf(" query_address: \"%s\"\n", sockstr);
+ printf(" query_port: %u\n", sport);
+ }
+
+ printf(" %s:\n", "response_message_data");
+ result = dns_message_headertotext(response, style, flags, buf);
+ CHECK("dns_message_headertotext", result);
+ } else if (display_comments && !display_short_form) {
+ printf(";; Got answer:\n");
+
+ if (display_headers) {
+ printf(";; ->>HEADER<<- opcode: %s, status: %s, "
+ "id: %u\n",
+ opcodetext[response->opcode],
+ rcode_totext(response->rcode), response->id);
+ printf(";; flags:");
+ if ((response->flags & DNS_MESSAGEFLAG_QR) != 0) {
+ printf(" qr");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_AA) != 0) {
+ printf(" aa");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_TC) != 0) {
+ printf(" tc");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_RD) != 0) {
+ printf(" rd");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_RA) != 0) {
+ printf(" ra");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_AD) != 0) {
+ printf(" ad");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_CD) != 0) {
+ printf(" cd");
+ }
+ if ((response->flags & 0x0040U) != 0) {
+ printf("; MBZ: 0x4");
+ }
+
+ printf("; QUERY: %u, ANSWER: %u, "
+ "AUTHORITY: %u, ADDITIONAL: %u\n",
+ response->counts[DNS_SECTION_QUESTION],
+ response->counts[DNS_SECTION_ANSWER],
+ response->counts[DNS_SECTION_AUTHORITY],
+ response->counts[DNS_SECTION_ADDITIONAL]);
+
+ if ((response->flags & DNS_MESSAGEFLAG_RD) != 0 &&
+ (response->flags & DNS_MESSAGEFLAG_RA) == 0)
+ {
+ printf(";; WARNING: recursion requested "
+ "but not available\n");
+ }
+ }
+ }
+
+repopulate_buffer:
+
+ if (display_comments && display_headers && !display_short_form) {
+ result = dns_message_pseudosectiontotext(
+ response, DNS_PSEUDOSECTION_OPT, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ buftoosmall:
+ len += OUTPUTBUF;
+ isc_buffer_free(&buf);
+ isc_buffer_allocate(mctx, &buf, len);
+ goto repopulate_buffer;
+ }
+ CHECK("dns_message_pseudosectiontotext", result);
+ }
+
+ if (display_question && display_headers && !display_short_form) {
+ result = dns_message_sectiontotext(
+ response, DNS_SECTION_QUESTION, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_sectiontotext", result);
+ }
+
+ if (display_answer && !display_short_form) {
+ result = dns_message_sectiontotext(response, DNS_SECTION_ANSWER,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_sectiontotext", result);
+ } else if (display_answer) {
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ isc_result_t loopresult;
+ dns_name_t empty_name;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int answerstyleflags = 0;
+
+ if (!display_crypto) {
+ answerstyleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ }
+ if (display_unknown_format) {
+ answerstyleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
+ }
+
+ dns_name_init(&empty_name, NULL);
+ result = dns_message_firstname(response, DNS_SECTION_ANSWER);
+ if (result != ISC_R_NOMORE) {
+ CHECK("dns_message_firstname", result);
+ }
+
+ for (;;) {
+ if (result == ISC_R_NOMORE) {
+ break;
+ }
+ CHECK("dns_message_nextname", result);
+ name = NULL;
+ dns_message_currentname(response, DNS_SECTION_ANSWER,
+ &name);
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tofmttext(
+ &rdata, NULL, answerstyleflags,
+ 0, 60, " ", buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_rdata_tofmttext", result);
+ loopresult =
+ dns_rdataset_next(rdataset);
+ dns_rdata_reset(&rdata);
+ if (strlen("\n") >=
+ isc_buffer_availablelength(buf))
+ {
+ goto buftoosmall;
+ }
+ isc_buffer_putstr(buf, "\n");
+ }
+ }
+ result = dns_message_nextname(response,
+ DNS_SECTION_ANSWER);
+ }
+ }
+
+ if (display_authority && !display_short_form) {
+ result = dns_message_sectiontotext(
+ response, DNS_SECTION_AUTHORITY, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_sectiontotext", result);
+ }
+
+ if (display_additional && !display_short_form) {
+ result = dns_message_sectiontotext(
+ response, DNS_SECTION_ADDITIONAL, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_sectiontotext", result);
+ }
+
+ if (display_additional && !display_short_form && display_headers) {
+ /*
+ * Only print the signature on the first record.
+ */
+ result = dns_message_pseudosectiontotext(
+ response, DNS_PSEUDOSECTION_TSIG, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_pseudosectiontotext", result);
+ result = dns_message_pseudosectiontotext(
+ response, DNS_PSEUDOSECTION_SIG0, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_pseudosectiontotext", result);
+ }
+
+ if (display_headers && display_comments && !display_short_form && !yaml)
+ {
+ printf("\n");
+ }
+
+ printf("%.*s", (int)isc_buffer_usedlength(buf),
+ (char *)isc_buffer_base(buf));
+ isc_buffer_free(&buf);
+
+cleanup:
+ fflush(stdout);
+ if (style != NULL) {
+ dns_master_styledestroy(&style, mctx);
+ }
+ if (query != NULL) {
+ dns_message_detach(&query);
+ }
+ if (response != NULL) {
+ dns_message_detach(&response);
+ }
+ dns_request_destroy(&reqev->request);
+ isc_event_free(&event);
+
+ if (--onfly == 0) {
+ isc_app_shutdown();
+ }
+ return;
+}
+
+/*%
+ * Add EDNS0 option record to a message. Currently, the only supported
+ * options are UDP buffer size, the DO bit, and EDNS options
+ * (e.g., NSID, COOKIE, client-subnet)
+ */
+static void
+add_opt(dns_message_t *msg, uint16_t udpsize, uint16_t edns, unsigned int flags,
+ dns_ednsopt_t *opts, size_t count) {
+ dns_rdataset_t *rdataset = NULL;
+ isc_result_t result;
+
+ result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
+ opts, count);
+ CHECK("dns_message_buildopt", result);
+ result = dns_message_setopt(msg, rdataset);
+ CHECK("dns_message_setopt", result);
+}
+
+static void
+compute_cookie(unsigned char *cookie, size_t len) {
+ /* XXXMPA need to fix, should be per server. */
+ INSIST(len >= 8U);
+ memmove(cookie, cookie_secret, 8);
+}
+
+static isc_result_t
+sendquery(struct query *query, isc_task_t *task) {
+ dns_request_t *request = NULL;
+ dns_message_t *message = NULL;
+ dns_name_t *qname = NULL;
+ dns_rdataset_t *qrdataset = NULL;
+ isc_result_t result;
+ dns_fixedname_t queryname;
+ isc_buffer_t buf;
+ unsigned int options;
+
+ onfly++;
+
+ dns_fixedname_init(&queryname);
+ isc_buffer_init(&buf, query->textname, strlen(query->textname));
+ isc_buffer_add(&buf, strlen(query->textname));
+ result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf,
+ dns_rootname, 0, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
+
+ message->opcode = dns_opcode_query;
+ if (query->recurse) {
+ message->flags |= DNS_MESSAGEFLAG_RD;
+ }
+ if (query->have_aaonly) {
+ message->flags |= DNS_MESSAGEFLAG_AA;
+ }
+ if (query->have_adflag) {
+ message->flags |= DNS_MESSAGEFLAG_AD;
+ }
+ if (query->have_cdflag) {
+ message->flags |= DNS_MESSAGEFLAG_CD;
+ }
+ if (query->have_zflag) {
+ message->flags |= 0x0040U;
+ }
+ message->rdclass = query->rdclass;
+ message->id = (unsigned short)(random() & 0xFFFF);
+
+ result = dns_message_gettempname(message, &qname);
+ CHECK("dns_message_gettempname", result);
+
+ result = dns_message_gettemprdataset(message, &qrdataset);
+ CHECK("dns_message_gettemprdataset", result);
+
+ dns_name_clone(dns_fixedname_name(&queryname), qname);
+ dns_rdataset_makequestion(qrdataset, query->rdclass, query->rdtype);
+ ISC_LIST_APPEND(qname->list, qrdataset, link);
+ dns_message_addname(message, qname, DNS_SECTION_QUESTION);
+
+ if (query->udpsize > 0 || query->dnssec || query->edns > -1 ||
+ query->ecs_addr != NULL)
+ {
+ dns_ednsopt_t opts[EDNSOPTS + DNS_EDNSOPTIONS];
+ unsigned int flags;
+ int i = 0;
+ char ecsbuf[20];
+ unsigned char cookie[40];
+
+ if (query->udpsize == 0) {
+ query->udpsize = 1232;
+ }
+ if (query->edns < 0) {
+ query->edns = 0;
+ }
+
+ if (query->nsid) {
+ INSIST(i < DNS_EDNSOPTIONS);
+ opts[i].code = DNS_OPT_NSID;
+ opts[i].length = 0;
+ opts[i].value = NULL;
+ i++;
+ }
+
+ if (query->ecs_addr != NULL) {
+ uint8_t addr[16], family;
+ uint32_t plen;
+ struct sockaddr *sa;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ size_t addrl;
+ isc_buffer_t b;
+
+ sa = &query->ecs_addr->type.sa;
+ plen = query->ecs_addr->length;
+
+ /* Round up prefix len to a multiple of 8 */
+ addrl = (plen + 7) / 8;
+
+ INSIST(i < DNS_EDNSOPTIONS);
+ opts[i].code = DNS_OPT_CLIENT_SUBNET;
+ opts[i].length = (uint16_t)addrl + 4;
+ CHECK("isc_buffer_allocate", result);
+ isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf));
+ if (sa->sa_family == AF_INET) {
+ family = 1;
+ sin = (struct sockaddr_in *)sa;
+ memmove(addr, &sin->sin_addr, 4);
+ if ((plen % 8) != 0) {
+ addr[addrl - 1] &= ~0U
+ << (8 - (plen % 8));
+ }
+ } else {
+ family = 2;
+ sin6 = (struct sockaddr_in6 *)sa;
+ memmove(addr, &sin6->sin6_addr, 16);
+ }
+
+ /* Mask off last address byte */
+ if (addrl > 0 && (plen % 8) != 0) {
+ addr[addrl - 1] &= ~0U << (8 - (plen % 8));
+ }
+
+ /* family */
+ isc_buffer_putuint16(&b, family);
+ /* source prefix-length */
+ isc_buffer_putuint8(&b, plen);
+ /* scope prefix-length */
+ isc_buffer_putuint8(&b, 0);
+ /* address */
+ if (addrl > 0) {
+ isc_buffer_putmem(&b, addr, (unsigned)addrl);
+ }
+
+ opts[i].value = (uint8_t *)ecsbuf;
+ i++;
+ }
+
+ if (query->send_cookie) {
+ INSIST(i < DNS_EDNSOPTIONS);
+ opts[i].code = DNS_OPT_COOKIE;
+ if (query->cookie != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, cookie, sizeof(cookie));
+ result = isc_hex_decodestring(query->cookie,
+ &b);
+ CHECK("isc_hex_decodestring", result);
+ opts[i].value = isc_buffer_base(&b);
+ opts[i].length = isc_buffer_usedlength(&b);
+ } else {
+ compute_cookie(cookie, 8);
+ opts[i].length = 8;
+ opts[i].value = cookie;
+ }
+ i++;
+ }
+
+ if (query->expire) {
+ INSIST(i < DNS_EDNSOPTIONS);
+ opts[i].code = DNS_OPT_EXPIRE;
+ opts[i].length = 0;
+ opts[i].value = NULL;
+ i++;
+ }
+
+ if (query->ednsoptscnt != 0) {
+ memmove(&opts[i], query->ednsopts,
+ sizeof(dns_ednsopt_t) * query->ednsoptscnt);
+ i += query->ednsoptscnt;
+ }
+
+ flags = query->ednsflags;
+ flags &= ~DNS_MESSAGEEXTFLAG_DO;
+ if (query->dnssec) {
+ flags |= DNS_MESSAGEEXTFLAG_DO;
+ }
+ add_opt(message, query->udpsize, query->edns, flags, opts, i);
+ }
+
+ options = 0;
+ if (tcp_mode) {
+ options |= DNS_REQUESTOPT_TCP;
+ }
+
+ request = NULL;
+ result = dns_request_create(
+ requestmgr, message, have_src ? &srcaddr : NULL, &dstaddr,
+ options, NULL, query->timeout, query->udptimeout,
+ query->udpretries, task, recvresponse, message, &request);
+ CHECK("dns_request_create", result);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+sendqueries(isc_task_t *task, isc_event_t *event) {
+ struct query *query = (struct query *)event->ev_arg;
+
+ isc_event_free(&event);
+
+ while (query != NULL) {
+ struct query *next = ISC_LIST_NEXT(query, link);
+
+ sendquery(query, task);
+ query = next;
+ }
+
+ if (onfly == 0) {
+ isc_app_shutdown();
+ }
+ return;
+}
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage: mdig @server {global-opt} host\n"
+ " {local-opt} [ host {local-opt} [...]]\n"
+ "\nUse \"mdig -h\" (or \"mdig -h | more\") "
+ "for complete list of options\n");
+ exit(1);
+}
+
+/*% help */
+static void
+help(void) {
+ printf("Usage: mdig @server {global-opt} host\n"
+ " {local-opt} [ host {local-opt} [...]]\n"
+ "Where:\n"
+ " anywhere opt is one of:\n"
+ " -f filename (batch mode)\n"
+ " -h (print help and exit)\n"
+ " -v (print version and exit)\n"
+ " global opt is one of:\n"
+ " -4 (use IPv4 query transport "
+ "only)\n"
+ " -6 (use IPv6 query transport "
+ "only)\n"
+ " -b address[#port] (bind to source "
+ "address/port)\n"
+ " -p port (specify port number)\n"
+ " -m (enable memory usage "
+ "debugging)\n"
+ " +[no]vc (TCP mode)\n"
+ " +[no]tcp (TCP mode, alternate "
+ "syntax)\n"
+ " +[no]besteffort (Try to parse even "
+ "illegal "
+ "messages)\n"
+ " +[no]cl (Control display of class "
+ "in records)\n"
+ " +[no]comments (Control display of "
+ "comment lines)\n"
+ " +[no]rrcomments (Control display of "
+ "per-record "
+ "comments)\n"
+ " +[no]crypto (Control display of "
+ "cryptographic "
+ "fields in records)\n"
+ " +[no]question (Control display of "
+ "question)\n"
+ " +[no]answer (Control display of "
+ "answer)\n"
+ " +[no]authority (Control display of "
+ "authority)\n"
+ " +[no]additional (Control display of "
+ "additional)\n"
+ " +[no]short (Disable everything "
+ "except "
+ "short\n"
+ " form of answer)\n"
+ " +[no]ttlid (Control display of ttls "
+ "in records)\n"
+ " +[no]ttlunits (Display TTLs in "
+ "human-readable units)\n"
+ " +[no]unknownformat (Print RDATA in RFC 3597 "
+ "\"unknown\" format)\n"
+ " +[no]all (Set or clear all display "
+ "flags)\n"
+ " +[no]multiline (Print records in an "
+ "expanded format)\n"
+ " +[no]split=## (Split hex/base64 fields "
+ "into chunks)\n"
+ " local opt is one of:\n"
+ " -c class (specify query class)\n"
+ " -t type (specify query type)\n"
+ " -x dot-notation (shortcut for reverse "
+ "lookups)\n"
+ " +timeout=### (Set query timeout) "
+ "[UDP=5,TCP=10]\n"
+ " +udptimeout=### (Set timeout before UDP "
+ "retry)\n"
+ " +tries=### (Set number of UDP "
+ "attempts) [3]\n"
+ " +retry=### (Set number of UDP "
+ "retries) [2]\n"
+ " +bufsize=### (Set EDNS0 Max UDP packet "
+ "size)\n"
+ " +subnet=addr (Set edns-client-subnet "
+ "option)\n"
+ " +[no]edns[=###] (Set EDNS version) [0]\n"
+ " +ednsflags=### (Set EDNS flag bits)\n"
+ " +ednsopt=###[:value] (Send specified EDNS "
+ "option)\n"
+ " +noednsopt (Clear list of +ednsopt "
+ "options)\n"
+ " +[no]recurse (Recursive mode)\n"
+ " +[no]aaonly (Set AA flag in query "
+ "(+[no]aaflag))\n"
+ " +[no]adflag (Set AD flag in query)\n"
+ " +[no]cdflag (Set CD flag in query)\n"
+ " +[no]zflag (Set Z flag in query)\n"
+ " +[no]dnssec (Request DNSSEC records)\n"
+ " +[no]expire (Request time to expire)\n"
+ " +[no]cookie[=###] (Send a COOKIE option)\n"
+ " +[no]nsid (Request Name "
+ "Server ID)\n");
+}
+
+noreturn static void
+fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+static void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fflush(stdout);
+ fprintf(stderr, "mdig: ");
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(-2);
+}
+
+static isc_result_t
+parse_uint_helper(uint32_t *uip, const char *value, uint32_t max,
+ const char *desc, int base) {
+ uint32_t n;
+ isc_result_t result = isc_parse_uint32(&n, value, base);
+ if (result == ISC_R_SUCCESS && n > max) {
+ result = ISC_R_RANGE;
+ }
+ if (result != ISC_R_SUCCESS) {
+ printf("invalid %s '%s': %s\n", desc, value,
+ isc_result_totext(result));
+ return (result);
+ }
+ *uip = n;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc) {
+ return (parse_uint_helper(uip, value, max, desc, 10));
+}
+
+static isc_result_t
+parse_xint(uint32_t *uip, const char *value, uint32_t max, const char *desc) {
+ return (parse_uint_helper(uip, value, max, desc, 0));
+}
+
+static void
+newopts(struct query *query) {
+ size_t len = sizeof(query->ednsopts[0]) * EDNSOPTS;
+ size_t i;
+
+ query->ednsopts = isc_mem_allocate(mctx, len);
+
+ for (i = 0; i < EDNSOPTS; i++) {
+ query->ednsopts[i].code = 0;
+ query->ednsopts[i].length = 0;
+ query->ednsopts[i].value = NULL;
+ }
+}
+
+static void
+save_opt(struct query *query, char *code, char *value) {
+ uint32_t num;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ if (query->ednsopts == NULL) {
+ newopts(query);
+ }
+
+ if (query->ednsoptscnt == EDNSOPTS) {
+ fatal("too many ednsopts");
+ }
+
+ result = parse_uint(&num, code, 65535, "ednsopt");
+ if (result != ISC_R_SUCCESS) {
+ fatal("bad edns code point: %s", code);
+ }
+
+ query->ednsopts[query->ednsoptscnt].code = num;
+ query->ednsopts[query->ednsoptscnt].length = 0;
+ query->ednsopts[query->ednsoptscnt].value = NULL;
+
+ if (value != NULL) {
+ char *buf;
+ buf = isc_mem_allocate(mctx, strlen(value) / 2 + 1);
+ isc_buffer_init(&b, buf, strlen(value) / 2 + 1);
+ result = isc_hex_decodestring(value, &b);
+ CHECK("isc_hex_decodestring", result);
+ query->ednsopts[query->ednsoptscnt].value = isc_buffer_base(&b);
+ query->ednsopts[query->ednsoptscnt].length =
+ isc_buffer_usedlength(&b);
+ }
+
+ query->ednsoptscnt++;
+}
+
+static isc_result_t
+parse_netprefix(isc_sockaddr_t **sap, const char *value) {
+ isc_sockaddr_t *sa = NULL;
+ struct in_addr in4;
+ struct in6_addr in6;
+ uint32_t netmask = 0xffffffff;
+ char *slash = NULL;
+ bool parsed = false;
+ char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX/128")];
+
+ if (strlcpy(buf, value, sizeof(buf)) >= sizeof(buf)) {
+ fatal("invalid prefix '%s'\n", value);
+ }
+
+ slash = strchr(buf, '/');
+ if (slash != NULL) {
+ isc_result_t result;
+ *slash = '\0';
+ result = isc_parse_uint32(&netmask, slash + 1, 10);
+ if (result != ISC_R_SUCCESS) {
+ fatal("invalid prefix length in '%s': %s\n", value,
+ isc_result_totext(result));
+ }
+ } else if (strcmp(value, "0") == 0) {
+ netmask = 0;
+ }
+
+ sa = isc_mem_allocate(mctx, sizeof(*sa));
+ if (inet_pton(AF_INET6, buf, &in6) == 1) {
+ parsed = true;
+ isc_sockaddr_fromin6(sa, &in6, 0);
+ if (netmask > 128) {
+ netmask = 128;
+ }
+ } else if (inet_pton(AF_INET, buf, &in4) == 1) {
+ parsed = true;
+ isc_sockaddr_fromin(sa, &in4, 0);
+ if (netmask > 32) {
+ netmask = 32;
+ }
+ } else if (netmask != 0xffffffff) {
+ int i;
+
+ for (i = 0; i < 3 && strlen(buf) < sizeof(buf) - 2; i++) {
+ strlcat(buf, ".0", sizeof(buf));
+ if (inet_pton(AF_INET, buf, &in4) == 1) {
+ parsed = true;
+ isc_sockaddr_fromin(sa, &in4, 0);
+ break;
+ }
+ }
+
+ if (netmask > 32) {
+ netmask = 32;
+ }
+ }
+
+ if (!parsed) {
+ fatal("invalid address '%s'", value);
+ }
+
+ sa->length = netmask;
+ *sap = sa;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Append 'len' bytes of 'text' at '*p', failing with
+ * ISC_R_NOSPACE if that would advance p past 'end'.
+ */
+static isc_result_t
+append(const char *text, int len, char **p, char *end) {
+ if (len > end - *p) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(*p, text, len);
+ *p += len;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+reverse_octets(const char *in, char **p, char *end) {
+ const char *dot = strchr(in, '.');
+ int len;
+ if (dot != NULL) {
+ isc_result_t result;
+ result = reverse_octets(dot + 1, p, end);
+ CHECK("reverse_octets", result);
+ result = append(".", 1, p, end);
+ CHECK("append", result);
+ len = (int)(dot - in);
+ } else {
+ len = strlen(in);
+ }
+ return (append(in, len, p, end));
+}
+
+static void
+get_reverse(char *reverse, size_t len, const char *value) {
+ int r;
+ isc_result_t result;
+ isc_netaddr_t addr;
+
+ addr.family = AF_INET6;
+ r = inet_pton(AF_INET6, value, &addr.type.in6);
+ if (r > 0) {
+ /* This is a valid IPv6 address. */
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ unsigned int options = 0;
+
+ name = dns_fixedname_initname(&fname);
+ result = dns_byaddr_createptrname(&addr, options, name);
+ CHECK("dns_byaddr_createptrname2", result);
+ dns_name_format(name, reverse, (unsigned int)len);
+ return;
+ } else {
+ /*
+ * Not a valid IPv6 address. Assume IPv4.
+ * Construct the in-addr.arpa name by blindly
+ * reversing octets whether or not they look like
+ * integers, so that this can be used for RFC2317
+ * names and such.
+ */
+ char *p = reverse;
+ char *end = reverse + len;
+ result = reverse_octets(value, &p, end);
+ CHECK("reverse_octets", result);
+ /* Append .in-addr.arpa. and a terminating NUL. */
+ result = append(".in-addr.arpa.", 15, &p, end);
+ CHECK("append", result);
+ return;
+ }
+}
+
+/*%
+ * We're not using isc_commandline_parse() here since the command line
+ * syntax of mdig is quite a bit different from that which can be described
+ * by that routine.
+ * XXX doc options
+ */
+
+static void
+plus_option(char *option, struct query *query, bool global) {
+ isc_result_t result;
+ char *cmd, *value, *last = NULL, *code;
+ uint32_t num;
+ bool state = true;
+ size_t n;
+
+ INSIST(option != NULL);
+
+ if ((cmd = strtok_r(option, "=", &last)) == NULL) {
+ printf(";; Invalid option %s\n", option);
+ return;
+ }
+ if (strncasecmp(cmd, "no", 2) == 0) {
+ cmd += 2;
+ state = false;
+ }
+ /* parse the rest of the string */
+ value = strtok_r(NULL, "", &last);
+
+#define FULLCHECK(A) \
+ do { \
+ size_t _l = strlen(cmd); \
+ if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \
+ goto invalid_option; \
+ } while (0)
+#define FULLCHECK2(A, B) \
+ do { \
+ size_t _l = strlen(cmd); \
+ if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \
+ (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \
+ goto invalid_option; \
+ } while (0)
+#define GLOBAL() \
+ do { \
+ if (!global) \
+ goto global_option; \
+ } while (0)
+
+ switch (cmd[0]) {
+ case 'a':
+ switch (cmd[1]) {
+ case 'a': /* aaonly / aaflag */
+ FULLCHECK2("aaonly", "aaflag");
+ query->have_aaonly = state;
+ break;
+ case 'd':
+ switch (cmd[2]) {
+ case 'd': /* additional */
+ FULLCHECK("additional");
+ display_additional = state;
+ break;
+ case 'f': /* adflag */
+ case '\0': /* +ad is a synonym for +adflag */
+ FULLCHECK("adflag");
+ query->have_adflag = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'l': /* all */
+ FULLCHECK("all");
+ GLOBAL();
+ display_question = state;
+ display_answer = state;
+ display_authority = state;
+ display_additional = state;
+ display_comments = state;
+ display_rrcomments = state ? 1 : -1;
+ break;
+ case 'n': /* answer */
+ FULLCHECK("answer");
+ GLOBAL();
+ display_answer = state;
+ break;
+ case 'u': /* authority */
+ FULLCHECK("authority");
+ GLOBAL();
+ display_authority = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'b':
+ switch (cmd[1]) {
+ case 'e': /* besteffort */
+ FULLCHECK("besteffort");
+ GLOBAL();
+ besteffort = state;
+ break;
+ case 'u':
+ switch (cmd[2]) {
+ case 'f': /* bufsize */
+ FULLCHECK("bufsize");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&num, value, COMMSIZE,
+ "buffer size");
+ CHECK("parse_uint(buffer size)", result);
+ query->udpsize = num;
+ break;
+ case 'r': /* burst */
+ FULLCHECK("burst");
+ GLOBAL();
+ burst = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'c':
+ switch (cmd[1]) {
+ case 'd': /* cdflag */
+ switch (cmd[2]) {
+ case 'f': /* cdflag */
+ case '\0': /* +cd is a synonym for +cdflag */
+ FULLCHECK("cdflag");
+ query->have_cdflag = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'l': /* cl */
+ FULLCHECK("cl");
+ GLOBAL();
+ display_class = state;
+ break;
+ case 'o': /* comments */
+ switch (cmd[2]) {
+ case 'm':
+ FULLCHECK("comments");
+ GLOBAL();
+ display_comments = state;
+ break;
+ case 'n':
+ FULLCHECK("continue");
+ GLOBAL();
+ continue_on_error = state;
+ break;
+ case 'o':
+ FULLCHECK("cookie");
+ if (state && query->edns == -1) {
+ query->edns = 0;
+ }
+ query->send_cookie = state;
+ if (value != NULL) {
+ n = strlcpy(hexcookie, value,
+ sizeof(hexcookie));
+ if (n >= sizeof(hexcookie)) {
+ fatal("COOKIE data too large");
+ }
+ query->cookie = hexcookie;
+ } else {
+ query->cookie = NULL;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ FULLCHECK("crypto");
+ GLOBAL();
+ display_crypto = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'd':
+ switch (cmd[1]) {
+ case 'n': /* dnssec */
+ FULLCHECK("dnssec");
+ if (state && query->edns == -1) {
+ query->edns = 0;
+ }
+ query->dnssec = state;
+ break;
+ case 's': /* dscp */
+ /* obsolete */
+ FULLCHECK("dscp");
+ fprintf(stderr, ";; +dscp option is obsolete "
+ "and has no effect");
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'e':
+ switch (cmd[1]) {
+ case 'd':
+ switch (cmd[2]) {
+ case 'n':
+ switch (cmd[3]) {
+ case 's':
+ switch (cmd[4]) {
+ case 0:
+ FULLCHECK("edns");
+ if (!state) {
+ query->edns = -1;
+ break;
+ }
+ if (value == NULL) {
+ query->edns = 0;
+ break;
+ }
+ result = parse_uint(&num, value,
+ 255,
+ "edns");
+ CHECK("parse_uint(edns)",
+ result);
+ query->edns = num;
+ break;
+ case 'f':
+ FULLCHECK("ednsflags");
+ if (!state) {
+ query->ednsflags = 0;
+ break;
+ }
+ if (value == NULL) {
+ query->ednsflags = 0;
+ break;
+ }
+ result = parse_xint(
+ &num, value, 0xffff,
+ "ednsflags");
+ CHECK("parse_xint(ednsflags)",
+ result);
+ query->ednsflags = num;
+ break;
+ case 'o':
+ FULLCHECK("ednsopt");
+ if (!state) {
+ query->ednsoptscnt = 0;
+ break;
+ }
+ code = NULL;
+ if (value != NULL) {
+ code = strtok_r(value,
+ ":",
+ &last);
+ }
+ if (code == NULL) {
+ fatal("ednsopt no "
+ "code point "
+ "specified");
+ }
+ value = strtok_r(NULL, "\0",
+ &last);
+ save_opt(query, code, value);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'x':
+ FULLCHECK("expire");
+ query->expire = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'm': /* multiline */
+ FULLCHECK("multiline");
+ GLOBAL();
+ display_multiline = state;
+ break;
+ case 'n':
+ FULLCHECK("nsid");
+ if (state && query->edns == -1) {
+ query->edns = 0;
+ }
+ query->nsid = state;
+ break;
+ case 'q':
+ FULLCHECK("question");
+ GLOBAL();
+ display_question = state;
+ break;
+ case 'r':
+ switch (cmd[1]) {
+ case 'e':
+ switch (cmd[2]) {
+ case 'c': /* recurse */
+ FULLCHECK("recurse");
+ query->recurse = state;
+ break;
+ case 't': /* retry / retries */
+ FULLCHECK2("retry", "retries");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&query->udpretries, value,
+ MAXTRIES - 1, "udpretries");
+ CHECK("parse_uint(udpretries)", result);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ FULLCHECK("rrcomments");
+ GLOBAL();
+ display_rrcomments = state ? 1 : -1;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 's':
+ switch (cmd[1]) {
+ case 'h':
+ FULLCHECK("short");
+ GLOBAL();
+ display_short_form = state;
+ if (state) {
+ display_question = false;
+ display_answer = true;
+ display_authority = false;
+ display_additional = false;
+ display_comments = false;
+ display_rrcomments = -1;
+ }
+ break;
+ case 'p': /* split */
+ FULLCHECK("split");
+ GLOBAL();
+ if (value != NULL && !state) {
+ goto invalid_option;
+ }
+ if (!state) {
+ display_splitwidth = 0;
+ break;
+ } else if (value == NULL) {
+ break;
+ }
+
+ result = parse_uint(&display_splitwidth, value, 1023,
+ "split");
+ if ((display_splitwidth % 4) != 0) {
+ display_splitwidth =
+ ((display_splitwidth + 3) / 4) * 4;
+ fprintf(stderr,
+ ";; Warning, split must be "
+ "a multiple of 4; adjusting "
+ "to %u\n",
+ display_splitwidth);
+ }
+ /*
+ * There is an adjustment done in the
+ * totext_<rrtype>() functions which causes
+ * splitwidth to shrink. This is okay when we're
+ * using the default width but incorrect in this
+ * case, so we correct for it
+ */
+ if (display_splitwidth) {
+ display_splitwidth += 3;
+ }
+ CHECK("parse_uint(split)", result);
+ break;
+ case 'u': /* subnet */
+ FULLCHECK("subnet");
+ if (state && value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ if (query->ecs_addr != NULL) {
+ isc_mem_free(mctx, query->ecs_addr);
+ query->ecs_addr = NULL;
+ }
+ break;
+ }
+ if (query->edns == -1) {
+ query->edns = 0;
+ }
+ result = parse_netprefix(&query->ecs_addr, value);
+ CHECK("parse_netprefix", result);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 't':
+ switch (cmd[1]) {
+ case 'c': /* tcp */
+ FULLCHECK("tcp");
+ GLOBAL();
+ tcp_mode = state;
+ break;
+ case 'i': /* timeout */
+ FULLCHECK("timeout");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&query->timeout, value, MAXTIMEOUT,
+ "timeout");
+ CHECK("parse_uint(timeout)", result);
+ if (query->timeout == 0) {
+ query->timeout = 1;
+ }
+ break;
+ case 'r':
+ FULLCHECK("tries");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&query->udpretries, value, MAXTRIES,
+ "udpretries");
+ CHECK("parse_uint(udpretries)", result);
+ if (query->udpretries > 0) {
+ query->udpretries -= 1;
+ }
+ break;
+ case 't':
+ switch (cmd[2]) {
+ case 'l':
+ switch (cmd[3]) {
+ case 0:
+ case 'i': /* ttlid */
+ FULLCHECK2("ttl", "ttlid");
+ GLOBAL();
+ display_ttl = state;
+ break;
+ case 'u': /* ttlunits */
+ FULLCHECK("ttlunits");
+ GLOBAL();
+ display_ttl = true;
+ display_ttlunits = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'u':
+ switch (cmd[1]) {
+ case 'd':
+ FULLCHECK("udptimeout");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&query->udptimeout, value,
+ MAXTIMEOUT, "udptimeout");
+ CHECK("parse_uint(udptimeout)", result);
+ break;
+ case 'n':
+ FULLCHECK("unknownformat");
+ display_unknown_format = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'v':
+ FULLCHECK("vc");
+ GLOBAL();
+ tcp_mode = state;
+ break;
+ case 'y': /* yaml */
+ FULLCHECK("yaml");
+ yaml = state;
+ if (state) {
+ display_rrcomments = state;
+ }
+ break;
+ case 'z': /* zflag */
+ FULLCHECK("zflag");
+ query->have_zflag = state;
+ break;
+ global_option:
+ fprintf(stderr, "Ignored late global option: +%s\n", option);
+ break;
+ default:
+ invalid_option:
+ need_value:
+ fprintf(stderr, "Invalid option: +%s\n", option);
+ usage();
+ }
+ return;
+}
+
+/*%
+ * #true returned if value was used
+ */
+static const char *single_dash_opts = "46himv";
+static const char *dash_opts = "46bcfhiptvx";
+static bool
+dash_option(const char *option, char *next, struct query *query, bool global,
+ bool *setname) {
+ char opt;
+ const char *value;
+ isc_result_t result;
+ bool value_from_next;
+ isc_consttextregion_t tr;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ char textname[MXNAME];
+ struct in_addr in4;
+ struct in6_addr in6;
+ in_port_t srcport;
+ char *hash;
+ uint32_t num;
+
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ /*
+ * Since the -[46hiv] options do not take an argument,
+ * account for them (in any number and/or combination)
+ * if they appear as the first character(s) of an opt.
+ */
+ opt = option[0];
+ switch (opt) {
+ case '4':
+ GLOBAL();
+ if (have_ipv4) {
+ isc_net_disableipv6();
+ have_ipv6 = false;
+ } else {
+ fatal("can't find IPv4 networking");
+ UNREACHABLE();
+ return (false);
+ }
+ break;
+ case '6':
+ GLOBAL();
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = false;
+ } else {
+ fatal("can't find IPv6 networking");
+ UNREACHABLE();
+ return (false);
+ }
+ break;
+ case 'h':
+ help();
+ exit(0);
+ break;
+ case 'i':
+ /* deprecated */
+ break;
+ case 'm':
+ /*
+ * handled by preparse_args()
+ */
+ break;
+ case 'v':
+ fprintf(stderr, "mDiG %s\n", PACKAGE_VERSION);
+ exit(0);
+ break;
+ }
+ if (strlen(option) > 1U) {
+ option = &option[1];
+ } else {
+ return (false);
+ }
+ }
+ opt = option[0];
+ if (strlen(option) > 1U) {
+ value_from_next = false;
+ value = &option[1];
+ } else {
+ value_from_next = true;
+ value = next;
+ }
+ if (value == NULL) {
+ goto invalid_option;
+ }
+ switch (opt) {
+ case 'b':
+ GLOBAL();
+ hash = strchr(value, '#');
+ if (hash != NULL) {
+ result = parse_uint(&num, hash + 1, MAXPORT,
+ "port number");
+ CHECK("parse_uint(srcport)", result);
+ srcport = num;
+ *hash = '\0';
+ } else {
+ srcport = 0;
+ }
+ if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) {
+ isc_sockaddr_fromin6(&srcaddr, &in6, srcport);
+ isc_net_disableipv4();
+ } else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) {
+ isc_sockaddr_fromin(&srcaddr, &in4, srcport);
+ isc_net_disableipv6();
+ } else {
+ if (hash != NULL) {
+ *hash = '#';
+ }
+ fatal("invalid address %s", value);
+ }
+ if (hash != NULL) {
+ *hash = '#';
+ }
+ have_src = true;
+ return (value_from_next);
+ case 'c':
+ tr.base = value;
+ tr.length = strlen(value);
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)&tr);
+ CHECK("dns_rdataclass_fromtext", result);
+ query->rdclass = rdclass;
+ return (value_from_next);
+ case 'f':
+ batchname = value;
+ return (value_from_next);
+ case 'p':
+ GLOBAL();
+ result = parse_uint(&num, value, MAXPORT, "port number");
+ CHECK("parse_uint(port)", result);
+ port = num;
+ return (value_from_next);
+ case 't':
+ tr.base = value;
+ tr.length = strlen(value);
+ result = dns_rdatatype_fromtext(&rdtype,
+ (isc_textregion_t *)&tr);
+ CHECK("dns_rdatatype_fromtext", result);
+ query->rdtype = rdtype;
+ return (value_from_next);
+ case 'x':
+ get_reverse(textname, sizeof(textname), value);
+ strlcpy(query->textname, textname, sizeof(query->textname));
+ query->rdtype = dns_rdatatype_ptr;
+ query->rdclass = dns_rdataclass_in;
+ *setname = true;
+ return (value_from_next);
+ global_option:
+ fprintf(stderr, "Ignored late global option: -%s\n", option);
+ usage();
+ default:
+ invalid_option:
+ fprintf(stderr, "Invalid option: -%s\n", option);
+ usage();
+ }
+ UNREACHABLE();
+ return (false);
+}
+
+static struct query *
+clone_default_query(void) {
+ struct query *query;
+
+ query = isc_mem_allocate(mctx, sizeof(struct query));
+ memmove(query, &default_query, sizeof(struct query));
+ if (default_query.ecs_addr != NULL) {
+ size_t len = sizeof(isc_sockaddr_t);
+
+ query->ecs_addr = isc_mem_allocate(mctx, len);
+ memmove(query->ecs_addr, default_query.ecs_addr, len);
+ }
+
+ if (query->timeout == 0) {
+ query->timeout = tcp_mode ? TCPTIMEOUT : UDPTIMEOUT;
+ }
+
+ return (query);
+}
+
+/*%
+ * Because we may be trying to do memory allocation recording, we're going
+ * to need to parse the arguments for the -m *before* we start the main
+ * argument parsing routine.
+ *
+ * I'd prefer not to have to do this, but I am not quite sure how else to
+ * fix the problem. Argument parsing in mdig involves memory allocation
+ * by its nature, so it can't be done in the main argument parser.
+ */
+static void
+preparse_args(int argc, char **argv) {
+ int rc;
+ char **rv;
+ char *option;
+ bool ipv4only = false, ipv6only = false;
+
+ rc = argc;
+ rv = argv;
+ for (rc--, rv++; rc > 0; rc--, rv++) {
+ if (rv[0][0] != '-') {
+ continue;
+ }
+ option = &rv[0][1];
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ switch (option[0]) {
+ case 'm':
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE |
+ ISC_MEM_DEBUGRECORD;
+ break;
+ case '4':
+ if (ipv6only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv4only = true;
+ break;
+ case '6':
+ if (ipv4only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv6only = true;
+ break;
+ }
+ option = &option[1];
+ }
+ if (strlen(option) == 0U) {
+ continue;
+ }
+ /* Look for dash value option. */
+ if (strpbrk(option, dash_opts) != &option[0] ||
+ strlen(option) > 1U)
+ {
+ /* Error or value in option. */
+ continue;
+ }
+ /* Dash value is next argument so we need to skip it. */
+ rc--, rv++;
+ /* Handle missing argument */
+ if (rc == 0) {
+ break;
+ }
+ }
+}
+
+static void
+parse_args(bool is_batchfile, int argc, char **argv) {
+ struct query *query = NULL;
+ char batchline[MXNAME];
+ int bargc;
+ char *bargv[64];
+ int rc;
+ char **rv;
+ bool global = true;
+ char *last;
+
+ /*
+ * The semantics for parsing the args is a bit complex; if
+ * we don't have a host yet, make the arg apply globally,
+ * otherwise make it apply to the latest host. This is
+ * a bit different than the previous versions, but should
+ * form a consistent user interface.
+ *
+ * First, create a "default query" which won't actually be used
+ * anywhere, except for cloning into new queries
+ */
+
+ if (!is_batchfile) {
+ default_query.textname[0] = 0;
+ default_query.recurse = true;
+ default_query.have_aaonly = false;
+ default_query.have_adflag = true; /*XXX*/
+ default_query.have_cdflag = false;
+ default_query.have_zflag = false;
+ default_query.dnssec = false;
+ default_query.expire = false;
+ default_query.send_cookie = false;
+ default_query.cookie = NULL;
+ default_query.nsid = false;
+ default_query.rdtype = dns_rdatatype_a;
+ default_query.rdclass = dns_rdataclass_in;
+ default_query.udpsize = 0;
+ default_query.edns = 0; /*XXX*/
+ default_query.ednsopts = NULL;
+ default_query.ednsoptscnt = 0;
+ default_query.ednsflags = 0;
+ default_query.ecs_addr = NULL;
+ default_query.timeout = 0;
+ default_query.udptimeout = 0;
+ default_query.udpretries = 2;
+ ISC_LINK_INIT(&default_query, link);
+ }
+
+ if (is_batchfile) {
+ /* Processing '-f batchfile'. */
+ query = clone_default_query();
+ global = false;
+ } else {
+ query = &default_query;
+ }
+
+ rc = argc;
+ rv = argv;
+ for (rc--, rv++; rc > 0; rc--, rv++) {
+ if (strncmp(rv[0], "%", 1) == 0) {
+ break;
+ }
+ if (rv[0][0] == '@') {
+ if (server != NULL) {
+ fatal("server already set to @%s", server);
+ }
+ server = &rv[0][1];
+ } else if (rv[0][0] == '+') {
+ plus_option(&rv[0][1], query, global);
+ } else if (rv[0][0] == '-') {
+ bool setname = false;
+
+ if (rc <= 1) {
+ if (dash_option(&rv[0][1], NULL, query, global,
+ &setname))
+ {
+ rc--;
+ rv++;
+ }
+ } else {
+ if (dash_option(&rv[0][1], rv[1], query, global,
+ &setname))
+ {
+ rc--;
+ rv++;
+ }
+ }
+ if (setname) {
+ if (query == &default_query) {
+ query = clone_default_query();
+ }
+ ISC_LIST_APPEND(queries, query, link);
+
+ default_query.textname[0] = 0;
+ query = clone_default_query();
+ global = false;
+ }
+ } else {
+ /*
+ * Anything which isn't an option
+ */
+ if (query == &default_query) {
+ query = clone_default_query();
+ }
+ strlcpy(query->textname, rv[0],
+ sizeof(query->textname));
+ ISC_LIST_APPEND(queries, query, link);
+
+ query = clone_default_query();
+ global = false;
+ /* XXX Error message */
+ }
+ }
+
+ /*
+ * If we have a batchfile, read the query list from it.
+ */
+ if ((batchname != NULL) && !is_batchfile) {
+ if (strcmp(batchname, "-") == 0) {
+ batchfp = stdin;
+ } else {
+ batchfp = fopen(batchname, "r");
+ }
+ if (batchfp == NULL) {
+ perror(batchname);
+ fatal("couldn't open batch file '%s'", batchname);
+ }
+ while (fgets(batchline, sizeof(batchline), batchfp) != 0) {
+ if (batchline[0] == '\r' || batchline[0] == '\n' ||
+ batchline[0] == '#' || batchline[0] == ';')
+ {
+ continue;
+ }
+ for (bargc = 1, bargv[bargc] = strtok_r(
+ batchline, " \t\r\n", &last);
+ (bargc < 14) && bargv[bargc]; bargc++,
+ bargv[bargc] = strtok_r(NULL, " \t\r\n", &last))
+ {
+ /* empty body */
+ }
+
+ bargv[0] = argv[0];
+ parse_args(true, bargc, (char **)bargv);
+ }
+ if (batchfp != stdin) {
+ fclose(batchfp);
+ }
+ }
+ if (query != &default_query) {
+ if (query->ecs_addr != NULL) {
+ isc_mem_free(mctx, query->ecs_addr);
+ }
+ isc_mem_free(mctx, query);
+ }
+}
+
+/*
+ * Try honoring the operating system's preferred ephemeral port range.
+ */
+static void
+set_source_ports(dns_dispatchmgr_t *manager) {
+ isc_portset_t *v4portset = NULL, *v6portset = NULL;
+ in_port_t udpport_low, udpport_high;
+ isc_result_t result;
+
+ result = isc_portset_create(mctx, &v4portset);
+ if (result != ISC_R_SUCCESS) {
+ fatal("isc_portset_create (v4) failed");
+ }
+
+ result = isc_net_getudpportrange(AF_INET, &udpport_low, &udpport_high);
+ if (result != ISC_R_SUCCESS) {
+ fatal("isc_net_getudpportrange (v4) failed");
+ }
+
+ isc_portset_addrange(v4portset, udpport_low, udpport_high);
+
+ result = isc_portset_create(mctx, &v6portset);
+ if (result != ISC_R_SUCCESS) {
+ fatal("isc_portset_create (v6) failed");
+ }
+ result = isc_net_getudpportrange(AF_INET6, &udpport_low, &udpport_high);
+ if (result != ISC_R_SUCCESS) {
+ fatal("isc_net_getudpportrange (v6) failed");
+ }
+
+ isc_portset_addrange(v6portset, udpport_low, udpport_high);
+
+ result = dns_dispatchmgr_setavailports(manager, v4portset, v6portset);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_dispatchmgr_setavailports failed");
+ }
+
+ isc_portset_destroy(mctx, &v4portset);
+ isc_portset_destroy(mctx, &v6portset);
+}
+
+/*% Main processing routine for mdig */
+int
+main(int argc, char *argv[]) {
+ struct query *query = NULL;
+ isc_result_t result;
+ isc_sockaddr_t bind_any;
+ isc_log_t *lctx = NULL;
+ isc_logconfig_t *lcfg = NULL;
+ isc_nm_t *netmgr = NULL;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_task_t *task = NULL;
+ dns_dispatchmgr_t *dispatchmgr = NULL;
+ dns_dispatch_t *dispatchvx = NULL;
+ dns_view_t *view = NULL;
+ unsigned int i;
+ int ns;
+
+ RUNCHECK(isc_app_start());
+
+ if (isc_net_probeipv4() == ISC_R_SUCCESS) {
+ have_ipv4 = true;
+ }
+ if (isc_net_probeipv6() == ISC_R_SUCCESS) {
+ have_ipv6 = true;
+ }
+ if (!have_ipv4 && !have_ipv6) {
+ fatal("could not find either IPv4 or IPv6");
+ }
+
+ preparse_args(argc, argv);
+
+ isc_mem_create(&mctx);
+ isc_log_create(mctx, &lctx, &lcfg);
+
+ RUNCHECK(dst_lib_init(mctx, NULL));
+ isc_nonce_buf(cookie_secret, sizeof(cookie_secret));
+
+ ISC_LIST_INIT(queries);
+ parse_args(false, argc, argv);
+ if (server == NULL) {
+ fatal("a server '@xxx' is required");
+ }
+
+ ns = 0;
+ result = bind9_getaddresses(server, port, &dstaddr, 1, &ns);
+ if (result != ISC_R_SUCCESS) {
+ fatal("couldn't get address for '%s': %s", server,
+ isc_result_totext(result));
+ }
+
+ if (isc_sockaddr_pf(&dstaddr) == PF_INET && have_ipv6) {
+ isc_net_disableipv6();
+ have_ipv6 = false;
+ } else if (isc_sockaddr_pf(&dstaddr) == PF_INET6 && have_ipv4) {
+ isc_net_disableipv4();
+ have_ipv4 = false;
+ }
+ if (have_ipv4 && have_ipv6) {
+ fatal("can't choose between IPv4 and IPv6");
+ }
+
+ isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr, NULL);
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
+
+ set_source_ports(dispatchmgr);
+
+ if (have_ipv4) {
+ isc_sockaddr_any(&bind_any);
+ } else {
+ isc_sockaddr_any6(&bind_any);
+ }
+ RUNCHECK(dns_dispatch_createudp(
+ dispatchmgr, have_src ? &srcaddr : &bind_any, &dispatchvx));
+
+ RUNCHECK(dns_requestmgr_create(
+ mctx, taskmgr, dispatchmgr, have_ipv4 ? dispatchvx : NULL,
+ have_ipv6 ? dispatchvx : NULL, &requestmgr));
+
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+
+ query = ISC_LIST_HEAD(queries);
+ RUNCHECK(isc_app_onrun(mctx, task, sendqueries, query));
+
+ /*
+ * Stall to the start of a new second.
+ */
+ if (burst) {
+ isc_time_t start, now;
+ RUNCHECK(isc_time_now(&start));
+ /*
+ * Sleep to 1ms of the end of the second then run a busy loop
+ * until the second changes.
+ */
+ do {
+ RUNCHECK(isc_time_now(&now));
+ if (isc_time_seconds(&start) == isc_time_seconds(&now))
+ {
+ int us = US_PER_SEC -
+ (isc_time_nanoseconds(&now) /
+ NS_PER_US);
+ if (us > US_PER_MS) {
+ usleep(us - US_PER_MS);
+ }
+ } else {
+ break;
+ }
+ } while (1);
+ }
+
+ (void)isc_app_run();
+
+ dns_view_detach(&view);
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+
+ dns_dispatch_detach(&dispatchvx);
+ dns_dispatchmgr_detach(&dispatchmgr);
+
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+
+ isc_managers_destroy(&netmgr, &taskmgr, NULL);
+
+ dst_lib_destroy();
+
+ isc_log_destroy(&lctx);
+
+ query = ISC_LIST_HEAD(queries);
+ while (query != NULL) {
+ struct query *next = ISC_LIST_NEXT(query, link);
+
+ if (query->ednsopts != NULL) {
+ for (i = 0; i < EDNSOPTS; i++) {
+ if (query->ednsopts[i].value != NULL) {
+ isc_mem_free(mctx,
+ query->ednsopts[i].value);
+ }
+ }
+ isc_mem_free(mctx, query->ednsopts);
+ }
+ if (query->ecs_addr != NULL) {
+ isc_mem_free(mctx, query->ecs_addr);
+ query->ecs_addr = NULL;
+ }
+ isc_mem_free(mctx, query);
+ query = next;
+ }
+
+ if (default_query.ecs_addr != NULL) {
+ isc_mem_free(mctx, default_query.ecs_addr);
+ }
+
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tools/mdig.rst b/bin/tools/mdig.rst
new file mode 100644
index 0000000..33948d1
--- /dev/null
+++ b/bin/tools/mdig.rst
@@ -0,0 +1,375 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: mdig
+.. program:: mdig
+.. _man_mdig:
+
+mdig - DNS pipelined lookup utility
+-----------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`mdig` {@server} [**-f** filename] [**-h**] [**-v**] [ [**-4**] | [**-6**] ] [**-m**] [**-b** address] [**-p** port#] [**-c** class] [**-t** type] [**-i**] [**-x** addr] [plusopt...]
+
+:program:`mdig` {**-h**}
+
+:program:`mdig` [@server] {global-opt...} { {local-opt...} {query} ...}
+
+Description
+~~~~~~~~~~~
+
+:program:`mdig` is a multiple/pipelined query version of :iscman:`dig`: instead of
+waiting for a response after sending each query, it begins by sending
+all queries. Responses are displayed in the order in which they are
+received, not in the order the corresponding queries were sent.
+
+:program:`mdig` options are a subset of the :iscman:`dig` options, and are divided
+into "anywhere options," which can occur anywhere, "global options," which
+must occur before the query name (or they are ignored with a warning),
+and "local options," which apply to the next query on the command line.
+
+The ``@server`` option is a mandatory global option. It is the name or IP
+address of the name server to query. (Unlike :iscman:`dig`, this value is not
+retrieved from ``/etc/resolv.conf``.) It can be an IPv4 address in
+dotted-decimal notation, an IPv6 address in colon-delimited notation, or
+a hostname. When the supplied ``server`` argument is a hostname,
+:program:`mdig` resolves that name before querying the name server.
+
+:program:`mdig` provides a number of query options which affect the way in
+which lookups are made and the results displayed. Some of these set or
+reset flag bits in the query header, some determine which sections of
+the answer get printed, and others determine the timeout and retry
+strategies.
+
+Each query option is identified by a keyword preceded by a plus sign
+(``+``). Some keywords set or reset an option. These may be preceded by
+the string ``no`` to negate the meaning of that keyword. Other keywords
+assign values to options like the timeout interval. They have the form
+``+keyword=value``.
+
+Anywhere Options
+~~~~~~~~~~~~~~~~
+
+.. option:: -f
+
+ This option makes :program:`mdig` operate in batch mode by reading a list
+ of lookup requests to process from the file ``filename``. The file
+ contains a number of queries, one per line. Each entry in the file
+ should be organized in the same way they would be presented as queries
+ to :program:`mdig` using the command-line interface.
+
+.. option:: -h
+
+ This option causes :program:`mdig` to print detailed help information, with the full list
+ of options, and exit.
+
+.. option:: -v
+
+ This option causes :program:`mdig` to print the version number and exit.
+
+Global Options
+~~~~~~~~~~~~~~
+
+.. option:: -4
+
+ This option forces :program:`mdig` to only use IPv4 query transport.
+
+.. option:: -6
+
+ This option forces :program:`mdig` to only use IPv6 query transport.
+
+.. option:: -b address
+
+ This option sets the source IP address of the query to
+ ``address``. This must be a valid address on one of the host's network
+ interfaces or "0.0.0.0" or "::". An optional port may be specified by
+ appending "#<port>"
+
+.. option:: -m
+
+ This option enables memory usage debugging.
+
+.. option:: -p port#
+
+ This option is used when a non-standard port number is to be
+ queried. ``port#`` is the port number that :program:`mdig` sends its
+ queries to, instead of the standard DNS port number 53. This option is
+ used to test a name server that has been configured to listen for
+ queries on a non-standard port number.
+
+The global query options are:
+
+.. option:: +additional, +noadditional
+
+ This option displays [or does not display] the additional section of a reply. The
+ default is to display it.
+
+.. option:: +all, +noall
+
+ This option sets or clears all display flags.
+
+.. option:: +answer, +noanswer
+
+ This option displays [or does not display] the answer section of a reply. The default
+ is to display it.
+
+.. option:: +authority, +noauthority
+
+ This option displays [or does not display] the authority section of a reply. The
+ default is to display it.
+
+.. option:: +besteffort, +nobesteffort
+
+ This option attempts to display [or does not display] the contents of messages which are malformed. The
+ default is to not display malformed answers.
+
+.. option:: +burst
+
+ This option delays queries until the start of the next second.
+
+.. option:: +cl, +nocl
+
+ This option displays [or does not display] the CLASS when printing the record.
+
+.. option:: +comments, +nocomments
+
+ This option toggles the display of comment lines in the output. The default is to
+ print comments.
+
+.. option:: +continue, +nocontinue
+
+ This option toggles continuation on errors (e.g. timeouts).
+
+.. option:: +crypto, +nocrypto
+
+ This option toggles the display of cryptographic fields in DNSSEC records. The
+ contents of these fields are unnecessary to debug most DNSSEC
+ validation failures and removing them makes it easier to see the
+ common failures. The default is to display the fields. When omitted,
+ they are replaced by the string "[omitted]"; in the DNSKEY case, the
+ key ID is displayed as the replacement, e.g., ``[ key id = value ]``.
+
+.. option:: +dscp=value
+
+ This option formerly set the DSCP value used when sending a query.
+ It is now obsolete, and has no effect.
+
+.. option:: +multiline, +nomultiline
+
+ This option toggles printing of records, like the SOA records, in a verbose multi-line format
+ with human-readable comments. The default is to print each record on
+ a single line, to facilitate machine parsing of the :program:`mdig` output.
+
+.. option:: +question, +noquestion
+
+ This option prints [or does not print] the question section of a query when an answer
+ is returned. The default is to print the question section as a
+ comment.
+
+.. option:: +rrcomments, +norrcomments
+
+ This option toggles the display of per-record comments in the output (for example,
+ human-readable key information about DNSKEY records). The default is
+ not to print record comments unless multiline mode is active.
+
+.. option:: +short, +noshort
+
+ This option provides [or does not provide] a terse answer. The default is to print the answer in a
+ verbose form.
+
+.. option:: +split=W
+
+ This option splits long hex- or base64-formatted fields in resource records into
+ chunks of ``W`` characters (where ``W`` is rounded up to the nearest
+ multiple of 4). ``+nosplit`` or ``+split=0`` causes fields not to be
+ split. The default is 56 characters, or 44 characters when
+ multiline mode is active.
+
+.. option:: +tcp, +notcp
+
+ This option uses [or does not use] TCP when querying name servers. The default behavior
+ is to use UDP.
+
+.. option:: +ttlid, +nottlid
+
+ This option displays [or does not display] the TTL when printing the record.
+
+.. option:: +ttlunits, +nottlunits
+
+ This option displays [or does not display] the TTL in friendly human-readable time
+ units of "s", "m", "h", "d", and "w", representing seconds, minutes,
+ hours, days, and weeks. This implies +ttlid.
+
+.. option:: +vc, +novc
+
+ This option uses [or does not use] TCP when querying name servers. This alternate
+ syntax to :option:`+tcp` is provided for backwards compatibility. The
+ ``vc`` stands for "virtual circuit".
+
+Local Options
+~~~~~~~~~~~~~
+
+.. option:: -c class
+
+ This option sets the query class to ``class``. It can be any valid
+ query class which is supported in BIND 9. The default query class is
+ "IN".
+
+.. option:: -t type
+
+ This option sets the query type to ``type``. It can be any valid
+ query type which is supported in BIND 9. The default query type is "A",
+ unless the :option:`-x` option is supplied to indicate a reverse lookup with
+ the "PTR" query type.
+
+.. option:: -x addr
+
+ Reverse lookups - mapping addresses to names - are simplified by
+ this option. ``addr`` is an IPv4 address in dotted-decimal
+ notation, or a colon-delimited IPv6 address. :program:`mdig` automatically
+ performs a lookup for a query name like ``11.12.13.10.in-addr.arpa`` and
+ sets the query type and class to PTR and IN respectively. By default,
+ IPv6 addresses are looked up using nibble format under the IP6.ARPA
+ domain.
+
+The local query options are:
+
+.. option:: +aaflag, +noaaflag
+
+ This is a synonym for :option:`+aaonly`, :option:`+noaaonly`.
+
+.. option:: +aaonly, +noaaonly
+
+ This sets the ``aa`` flag in the query.
+
+.. option:: +adflag, +noadflag
+
+ This sets [or does not set] the AD (authentic data) bit in the query. This
+ requests the server to return whether all of the answer and authority
+ sections have all been validated as secure, according to the security
+ policy of the server. AD=1 indicates that all records have been
+ validated as secure and the answer is not from a OPT-OUT range. AD=0
+ indicates that some part of the answer was insecure or not validated.
+ This bit is set by default.
+
+.. option:: +bufsize=B
+
+ This sets the UDP message buffer size advertised using EDNS0 to ``B``
+ bytes. The maximum and minimum sizes of this buffer are 65535 and 0
+ respectively. Values outside this range are rounded up or down
+ appropriately. Values other than zero cause a EDNS query to be
+ sent.
+
+.. option:: +cdflag, +nocdflag
+
+ This sets [or does not set] the CD (checking disabled) bit in the query. This
+ requests the server to not perform DNSSEC validation of responses.
+
+.. option:: +cookie=####, +nocookie
+
+ This sends [or does not send] a COOKIE EDNS option, with an optional value. Replaying a COOKIE
+ from a previous response allows the server to identify a previous
+ client. The default is ``+nocookie``.
+
+.. option:: +dnssec, +nodnssec
+
+ This requests that DNSSEC records be sent by setting the DNSSEC OK (DO) bit in
+ the OPT record in the additional section of the query.
+
+.. option:: +edns[=#], +noedns
+
+ This specifies [or does not specify] the EDNS version to query with. Valid values are 0 to 255.
+ Setting the EDNS version causes an EDNS query to be sent.
+ ``+noedns`` clears the remembered EDNS version. EDNS is set to 0 by
+ default.
+
+.. option:: +ednsflags[=#], +noednsflags
+
+ This sets the must-be-zero EDNS flag bits (Z bits) to the specified value.
+ Decimal, hex, and octal encodings are accepted. Setting a named flag
+ (e.g. DO) is silently ignored. By default, no Z bits are set.
+
+.. option:: +ednsopt[=code[:value]], +noednsopt
+
+ This specifies [or does not specify] an EDNS option with code point ``code`` and an optional payload
+ of ``value`` as a hexadecimal string. ``+noednsopt`` clears the EDNS
+ options to be sent.
+
+.. option:: +expire, +noexpire
+
+ This toggles sending of an EDNS Expire option.
+
+.. option:: +nsid, +nonsid
+
+ This toggles inclusion of an EDNS name server ID request when sending a query.
+
+.. option:: +recurse, +norecurse
+
+ This toggles the setting of the RD (recursion desired) bit in the query.
+ This bit is set by default, which means :program:`mdig` normally sends
+ recursive queries.
+
+.. option:: +retry=T
+
+ This sets the number of times to retry UDP queries to server to ``T``
+ instead of the default, 2. Unlike :option:`+tries`, this does not include
+ the initial query.
+
+.. option:: +subnet=addr[/prefix-length], +nosubnet
+
+ This sends [or does not send] an EDNS Client Subnet option with the specified IP
+ address or network prefix.
+
+``mdig +subnet=0.0.0.0/0``, or simply ``mdig +subnet=0``
+ This sends an EDNS client-subnet option with an empty address and a source
+ prefix-length of zero, which signals a resolver that the client's
+ address information must *not* be used when resolving this query.
+
+.. option:: +timeout=T
+
+ This sets the timeout for a query to ``T`` seconds. The default timeout is
+ 5 seconds for UDP transport and 10 for TCP. An attempt to set ``T``
+ to less than 1 results in a query timeout of 1 second being
+ applied.
+
+.. option:: +tries=T
+
+ This sets the number of times to try UDP queries to server to ``T``
+ instead of the default, 3. If ``T`` is less than or equal to zero,
+ the number of tries is silently rounded up to 1.
+
+.. option:: +udptimeout=T
+
+ This sets the timeout between UDP query retries to ``T``.
+
+.. option:: +unknownformat, +nounknownformat
+
+ This prints [or does not print] all RDATA in unknown RR-type presentation format (see :rfc:`3597`).
+ The default is to print RDATA for known types in the type's
+ presentation format.
+
+.. option:: +yaml, +noyaml
+
+ This toggles printing of the responses in a detailed YAML format.
+
+.. option:: +zflag, +nozflag
+
+ This sets [or does not set] the last unassigned DNS header flag in a DNS query.
+ This flag is off by default.
+
+See Also
+~~~~~~~~
+
+:iscman:`dig(1) <dig>`, :rfc:`1035`.
diff --git a/bin/tools/named-journalprint.c b/bin/tools/named-journalprint.c
new file mode 100644
index 0000000..402163d
--- /dev/null
+++ b/bin/tools/named-journalprint.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <stdlib.h>
+
+#include <isc/commandline.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/journal.h>
+#include <dns/log.h>
+#include <dns/types.h>
+
+const char *progname = NULL;
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage: %s [-dux] journal\n", progname);
+ exit(1);
+}
+
+/*
+ * Setup logging to use stderr.
+ */
+static isc_result_t
+setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) {
+ isc_logdestination_t destination;
+ isc_logconfig_t *logconfig = NULL;
+ isc_log_t *log = NULL;
+
+ isc_log_create(mctx, &log, &logconfig);
+ isc_log_setcontext(log);
+ dns_log_init(log);
+ dns_log_setcontext(log);
+
+ destination.file.stream = errout;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC, &destination, 0);
+
+ RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL) ==
+ ISC_R_SUCCESS);
+
+ *logp = log;
+ return (ISC_R_SUCCESS);
+}
+
+int
+main(int argc, char **argv) {
+ char *file;
+ isc_mem_t *mctx = NULL;
+ isc_result_t result;
+ isc_log_t *lctx = NULL;
+ uint32_t flags = 0U;
+ int ch;
+ bool compact = false;
+ bool downgrade = false;
+ bool upgrade = false;
+ unsigned int serial = 0;
+ char *endp = NULL;
+
+ progname = argv[0];
+ while ((ch = isc_commandline_parse(argc, argv, "c:dux")) != -1) {
+ switch (ch) {
+ case 'c':
+ compact = true;
+ serial = strtoul(isc_commandline_argument, &endp, 0);
+ if (endp == isc_commandline_argument || *endp != 0) {
+ fprintf(stderr, "invalid serial: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+ case 'd':
+ downgrade = true;
+ break;
+ case 'u':
+ upgrade = true;
+ break;
+ case 'x':
+ flags |= DNS_JOURNAL_PRINTXHDR;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc != 1) {
+ usage();
+ }
+ file = argv[0];
+
+ isc_mem_create(&mctx);
+ RUNTIME_CHECK(setup_logging(mctx, stderr, &lctx) == ISC_R_SUCCESS);
+
+ if (upgrade) {
+ flags = DNS_JOURNAL_COMPACTALL;
+ result = dns_journal_compact(mctx, file, 0, flags, 0);
+ } else if (downgrade) {
+ flags = DNS_JOURNAL_COMPACTALL | DNS_JOURNAL_VERSION1;
+ result = dns_journal_compact(mctx, file, 0, flags, 0);
+ } else if (compact) {
+ flags = 0;
+ result = dns_journal_compact(mctx, file, serial, flags, 0);
+ } else {
+ result = dns_journal_print(mctx, flags, file, stdout);
+ if (result == DNS_R_NOJOURNAL) {
+ fprintf(stderr, "%s\n", isc_result_totext(result));
+ }
+ }
+ isc_log_destroy(&lctx);
+ isc_mem_detach(&mctx);
+ return (result != ISC_R_SUCCESS ? 1 : 0);
+}
diff --git a/bin/tools/named-journalprint.rst b/bin/tools/named-journalprint.rst
new file mode 100644
index 0000000..9d56801
--- /dev/null
+++ b/bin/tools/named-journalprint.rst
@@ -0,0 +1,66 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: named-journalprint
+.. program:: named-journalprint
+.. _man_named-journalprint:
+
+named-journalprint - print zone journal in human-readable form
+--------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`named-journalprint` [-c serial] [**-dux**] {journal}
+
+Description
+~~~~~~~~~~~
+
+:program:`named-journalprint` scans the contents of a zone journal file,
+printing it in a human-readable form, or, optionally, converting it
+to a different journal file format.
+
+Journal files are automatically created by :iscman:`named` when changes are
+made to dynamic zones (e.g., by :iscman:`nsupdate`). They record each addition
+or deletion of a resource record, in binary format, allowing the changes
+to be re-applied to the zone when the server is restarted after a
+shutdown or crash. By default, the name of the journal file is formed by
+appending the extension ``.jnl`` to the name of the corresponding zone
+file.
+
+:program:`named-journalprint` converts the contents of a given journal file
+into a human-readable text format. Each line begins with ``add`` or ``del``,
+to indicate whether the record was added or deleted, and continues with
+the resource record in master-file format.
+
+The ``-c`` (compact) option provides a mechanism to reduce the size of
+a journal by removing (most/all) transactions prior to the specified
+serial number. Note: this option *must not* be used while :iscman:`named` is
+running, and can cause data loss if the zone file has not been updated
+to contain the data being removed from the journal. Use with extreme caution.
+
+The ``-x`` option causes additional data about the journal file to be
+printed at the beginning of the output and before each group of changes.
+
+The ``-u`` (upgrade) and ``-d`` (downgrade) options recreate the journal
+file with a modified format version. The existing journal file is
+replaced. ``-d`` writes out the journal in the format used by
+versions of BIND up to 9.16.11; ``-u`` writes it out in the format used
+by versions since 9.16.13. (9.16.12 is omitted due to a journal-formatting
+bug in that release.) Note that these options *must not* be used while
+:iscman:`named` is running.
+
+See Also
+~~~~~~~~
+
+:iscman:`named(8) <named>`, :iscman:`nsupdate(1) <nsupdate>`, BIND 9 Administrator Reference Manual.
diff --git a/bin/tools/named-nzd2nzf.c b/bin/tools/named-nzd2nzf.c
new file mode 100644
index 0000000..630b65b
--- /dev/null
+++ b/bin/tools/named-nzd2nzf.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef HAVE_LMDB
+#error This program requires the LMDB library.
+#endif /* ifndef HAVE_LMDB */
+
+#include <lmdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/print.h>
+
+#include <dns/view.h>
+
+int
+main(int argc, char *argv[]) {
+ int status;
+ const char *path;
+ MDB_env *env = NULL;
+ MDB_txn *txn = NULL;
+ MDB_cursor *cursor = NULL;
+ MDB_dbi dbi;
+ MDB_val key, data;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: named-nzd2nzf <nzd-path>\n");
+ exit(1);
+ }
+
+ path = argv[1];
+
+ status = mdb_env_create(&env);
+ if (status != MDB_SUCCESS) {
+ fprintf(stderr, "named-nzd2nzf: mdb_env_create: %s",
+ mdb_strerror(status));
+ exit(1);
+ }
+
+ status = mdb_env_open(env, path, DNS_LMDB_FLAGS, 0600);
+ if (status != MDB_SUCCESS) {
+ fprintf(stderr, "named-nzd2nzf: mdb_env_open: %s",
+ mdb_strerror(status));
+ exit(1);
+ }
+
+ status = mdb_txn_begin(env, 0, MDB_RDONLY, &txn);
+ if (status != MDB_SUCCESS) {
+ fprintf(stderr, "named-nzd2nzf: mdb_txn_begin: %s",
+ mdb_strerror(status));
+ exit(1);
+ }
+
+ status = mdb_dbi_open(txn, NULL, 0, &dbi);
+ if (status != MDB_SUCCESS) {
+ fprintf(stderr, "named-nzd2nzf: mdb_dbi_open: %s",
+ mdb_strerror(status));
+ exit(1);
+ }
+
+ status = mdb_cursor_open(txn, dbi, &cursor);
+ if (status != MDB_SUCCESS) {
+ fprintf(stderr, "named-nzd2nzf: mdb_cursor_open: %s",
+ mdb_strerror(status));
+ exit(1);
+ }
+
+ for (status = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
+ status == MDB_SUCCESS;
+ status = mdb_cursor_get(cursor, &key, &data, MDB_NEXT))
+ {
+ if (key.mv_data == NULL || key.mv_size == 0 ||
+ data.mv_data == NULL || data.mv_size == 0)
+ {
+ fprintf(stderr,
+ "named-nzd2nzf: empty column found in "
+ "database '%s'",
+ path);
+ exit(1);
+ }
+
+ /* zone zonename { config; }; */
+ printf("zone \"%.*s\" %.*s;\n", (int)key.mv_size,
+ (char *)key.mv_data, (int)data.mv_size,
+ (char *)data.mv_data);
+ }
+
+ mdb_cursor_close(cursor);
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ exit(0);
+}
diff --git a/bin/tools/named-nzd2nzf.rst b/bin/tools/named-nzd2nzf.rst
new file mode 100644
index 0000000..9711f8d
--- /dev/null
+++ b/bin/tools/named-nzd2nzf.rst
@@ -0,0 +1,45 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: named-nzd2nzf
+.. program:: named-nzd2nzf
+.. _man_named-nzd2nzf:
+
+named-nzd2nzf - convert an NZD database to NZF text format
+----------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`named-nzd2nzf` {filename}
+
+Description
+~~~~~~~~~~~
+
+:program:`named-nzd2nzf` converts an NZD database to NZF format and prints it
+to standard output. This can be used to review the configuration of
+zones that were added to :iscman:`named` via :option:`rndc addzone`. It can also be
+used to restore the old file format when rolling back from a newer
+version of BIND to an older version.
+
+Arguments
+~~~~~~~~~
+
+.. option:: filename
+
+ This is the name of the ``.nzd`` file whose contents should be printed.
+
+See Also
+~~~~~~~~
+
+BIND 9 Administrator Reference Manual.
diff --git a/bin/tools/named-rrchecker.c b/bin/tools/named-rrchecker.c
new file mode 100644
index 0000000..4d8a318
--- /dev/null
+++ b/bin/tools/named-rrchecker.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/attributes.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+
+static isc_mem_t *mctx;
+static isc_lex_t *lex;
+
+static isc_lexspecials_t specials;
+
+noreturn static void
+usage(void);
+
+static void
+usage(void) {
+ fprintf(stderr, "usage: named-rrchecker [-o origin] [-hpCPTu]\n");
+ fprintf(stderr, "\t-h: print this help message\n");
+ fprintf(stderr, "\t-o origin: set origin to be used when "
+ "interpreting the record\n");
+ fprintf(stderr, "\t-p: print the record in canonical format\n");
+ fprintf(stderr, "\t-C: list the supported class names\n");
+ fprintf(stderr, "\t-P: list the supported private type names\n");
+ fprintf(stderr, "\t-T: list the supported standard type names\n");
+ fprintf(stderr, "\t-u: print the record in unknown record format\n");
+ exit(0);
+}
+
+static void
+cleanup(void) {
+ if (lex != NULL) {
+ isc_lex_close(lex);
+ isc_lex_destroy(&lex);
+ }
+ if (mctx != NULL) {
+ isc_mem_destroy(&mctx);
+ }
+}
+
+noreturn static void
+fatal(const char *format, ...);
+
+static void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fprintf(stderr, "named-rrchecker: ");
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fputc('\n', stderr);
+ cleanup();
+ exit(1);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_token_t token;
+ isc_result_t result;
+ int c;
+ unsigned int options = 0;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ char text[256 * 1024];
+ char data[64 * 1024];
+ isc_buffer_t tbuf;
+ isc_buffer_t dbuf;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ bool doexit = false;
+ bool once = false;
+ bool print = false;
+ bool unknown = false;
+ unsigned int t;
+ char *origin = NULL;
+ dns_fixedname_t fixed;
+ dns_name_t *name = NULL;
+
+ while ((c = isc_commandline_parse(argc, argv, "ho:puCPT")) != -1) {
+ switch (c) {
+ case 'o':
+ origin = isc_commandline_argument;
+ break;
+
+ case 'p':
+ print = true;
+ break;
+
+ case 'u':
+ unknown = true;
+ break;
+
+ case 'C':
+ for (t = 1; t <= 0xfeffu; t++) {
+ if (dns_rdataclass_ismeta(t)) {
+ continue;
+ }
+ dns_rdataclass_format(t, text, sizeof(text));
+ if (strncmp(text, "CLASS", 4) != 0) {
+ fprintf(stdout, "%s\n", text);
+ }
+ }
+ exit(0);
+
+ case 'P':
+ for (t = 0xff00; t <= 0xfffeu; t++) {
+ if (dns_rdatatype_ismeta(t)) {
+ continue;
+ }
+ dns_rdatatype_format(t, text, sizeof(text));
+ if (strncmp(text, "TYPE", 4) != 0) {
+ fprintf(stdout, "%s\n", text);
+ }
+ }
+ doexit = true;
+ break;
+
+ case 'T':
+ for (t = 1; t <= 0xfeffu; t++) {
+ if (dns_rdatatype_ismeta(t)) {
+ continue;
+ }
+ dns_rdatatype_format(t, text, sizeof(text));
+ if (strncmp(text, "TYPE", 4) != 0) {
+ fprintf(stdout, "%s\n", text);
+ }
+ }
+ doexit = true;
+ break;
+
+ case '?':
+ case 'h':
+ /* Does not return. */
+ usage();
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", argv[0],
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+ if (doexit) {
+ exit(0);
+ }
+
+ isc_mem_create(&mctx);
+ RUNTIME_CHECK(isc_lex_create(mctx, 256, &lex) == ISC_R_SUCCESS);
+
+ /*
+ * Set up to lex DNS master file.
+ */
+
+ specials['('] = 1;
+ specials[')'] = 1;
+ specials['"'] = 1;
+ isc_lex_setspecials(lex, specials);
+ options = ISC_LEXOPT_EOL;
+ isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
+
+ RUNTIME_CHECK(isc_lex_openstream(lex, stdin) == ISC_R_SUCCESS);
+
+ if (origin != NULL) {
+ name = dns_fixedname_initname(&fixed);
+ result = dns_name_fromstring(name, origin, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_name_fromstring: %s",
+ isc_result_totext(result));
+ }
+ }
+
+ while ((result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER,
+ &token)) == ISC_R_SUCCESS)
+ {
+ if (token.type == isc_tokentype_eof) {
+ break;
+ }
+ if (token.type == isc_tokentype_eol) {
+ continue;
+ }
+ if (once) {
+ fatal("extra data");
+ }
+ /*
+ * Get class.
+ */
+ if (token.type == isc_tokentype_number) {
+ rdclass = (dns_rdataclass_t)token.value.as_ulong;
+ if (token.value.as_ulong > 0xffffu) {
+ fatal("class value too big %lu",
+ token.value.as_ulong);
+ }
+ if (dns_rdataclass_ismeta(rdclass)) {
+ fatal("class %lu is a meta value",
+ token.value.as_ulong);
+ }
+ } else if (token.type == isc_tokentype_string) {
+ result = dns_rdataclass_fromtext(
+ &rdclass, &token.value.as_textregion);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdataclass_fromtext: %s",
+ isc_result_totext(result));
+ }
+ if (dns_rdataclass_ismeta(rdclass)) {
+ fatal("class %.*s(%d) is a meta value",
+ (int)token.value.as_textregion.length,
+ token.value.as_textregion.base, rdclass);
+ }
+ } else {
+ fatal("unexpected token %u", token.type);
+ }
+
+ result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER,
+ &token);
+ if (result != ISC_R_SUCCESS) {
+ break;
+ }
+ if (token.type == isc_tokentype_eol) {
+ continue;
+ }
+ if (token.type == isc_tokentype_eof) {
+ break;
+ }
+
+ /*
+ * Get type.
+ */
+ if (token.type == isc_tokentype_number) {
+ rdtype = (dns_rdatatype_t)token.value.as_ulong;
+ if (token.value.as_ulong > 0xffffu) {
+ fatal("type value too big %lu",
+ token.value.as_ulong);
+ }
+ if (dns_rdatatype_ismeta(rdtype)) {
+ fatal("type %lu is a meta value",
+ token.value.as_ulong);
+ }
+ } else if (token.type == isc_tokentype_string) {
+ result = dns_rdatatype_fromtext(
+ &rdtype, &token.value.as_textregion);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdatatype_fromtext: %s",
+ isc_result_totext(result));
+ }
+ if (dns_rdatatype_ismeta(rdtype)) {
+ fatal("type %.*s(%d) is a meta value",
+ (int)token.value.as_textregion.length,
+ token.value.as_textregion.base, rdtype);
+ }
+ } else {
+ fatal("unexpected token %u", token.type);
+ }
+
+ isc_buffer_init(&dbuf, data, sizeof(data));
+ result = dns_rdata_fromtext(&rdata, rdclass, rdtype, lex, name,
+ 0, mctx, &dbuf, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdata_fromtext: %s",
+ isc_result_totext(result));
+ }
+ once = true;
+ }
+ if (result != ISC_R_EOF) {
+ fatal("eof not found");
+ }
+ if (!once) {
+ fatal("no records found");
+ }
+
+ if (print) {
+ isc_buffer_init(&tbuf, text, sizeof(text));
+ result = dns_rdataclass_totext(rdclass, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdataclass_totext: %s",
+ isc_result_totext(result));
+ }
+ isc_buffer_putstr(&tbuf, "\t");
+ result = dns_rdatatype_totext(rdtype, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdatatype_totext: %s",
+ isc_result_totext(result));
+ }
+ isc_buffer_putstr(&tbuf, "\t");
+ result = dns_rdata_totext(&rdata, NULL, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdata_totext: %s",
+ isc_result_totext(result));
+ }
+
+ printf("%.*s\n", (int)tbuf.used, (char *)tbuf.base);
+ fflush(stdout);
+ }
+
+ if (unknown) {
+ isc_buffer_init(&tbuf, text, sizeof(text));
+ result = dns_rdataclass_tounknowntext(rdclass, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdataclass_tounknowntext: %s",
+ isc_result_totext(result));
+ }
+ isc_buffer_putstr(&tbuf, "\t");
+ result = dns_rdatatype_tounknowntext(rdtype, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdatatype_tounknowntext: %s",
+ isc_result_totext(result));
+ }
+ isc_buffer_putstr(&tbuf, "\t");
+ result = dns_rdata_tofmttext(&rdata, NULL,
+ DNS_STYLEFLAG_UNKNOWNFORMAT, 0, 0,
+ "", &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdata_tofmttext: %sn",
+ isc_result_totext(result));
+ }
+
+ printf("%.*s\n", (int)tbuf.used, (char *)tbuf.base);
+ fflush(stdout);
+ }
+
+ cleanup();
+ return (0);
+}
diff --git a/bin/tools/named-rrchecker.rst b/bin/tools/named-rrchecker.rst
new file mode 100644
index 0000000..28da236
--- /dev/null
+++ b/bin/tools/named-rrchecker.rst
@@ -0,0 +1,62 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: named-rrchecker
+.. program:: named-rrchecker
+.. _man_named-rrchecker:
+
+named-rrchecker - syntax checker for individual DNS resource records
+--------------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`named-rrchecker` [**-h**] [**-o** origin] [**-p**] [**-u**] [**-C**] [**-T**] [**-P**]
+
+Description
+~~~~~~~~~~~
+
+:program:`named-rrchecker` reads a individual DNS resource record from standard
+input and checks whether it is syntactically correct.
+
+Options
+~~~~~~~
+
+.. option:: -h
+
+ This option prints out the help menu.
+
+.. option:: -o origin
+
+ This option specifies the origin to be used when interpreting
+ the record.
+
+.. option:: -p
+
+ This option prints out the resulting record in canonical form. If there
+ is no canonical form defined, the record is printed in unknown
+ record format.
+
+.. option:: -u
+
+ This option prints out the resulting record in unknown record form.
+
+.. option:: -C, -T, -P
+
+ These options print out the known class, standard type,
+ and private type mnemonics, respectively.
+
+See Also
+~~~~~~~~
+
+:rfc:`1034`, :rfc:`1035`, :iscman:`named(8) <named>`.
diff --git a/bin/tools/nsec3hash.c b/bin/tools/nsec3hash.c
new file mode 100644
index 0000000..a6a5ec3
--- /dev/null
+++ b/bin/tools/nsec3hash.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/attributes.h>
+#include <isc/base32.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/file.h>
+#include <isc/hex.h>
+#include <isc/iterated_hash.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/nsec3.h>
+#include <dns/types.h>
+
+const char *program = "nsec3hash";
+
+noreturn static void
+fatal(const char *format, ...);
+
+static void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fprintf(stderr, "%s: ", program);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+static void
+check_result(isc_result_t result, const char *message) {
+ if (result != ISC_R_SUCCESS) {
+ fatal("%s: %s", message, isc_result_totext(result));
+ }
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage: %s salt algorithm iterations domain\n",
+ program);
+ fprintf(stderr, " %s -r algorithm flags iterations salt domain\n",
+ program);
+ exit(1);
+}
+
+typedef void
+nsec3printer(unsigned algo, unsigned flags, unsigned iters, const char *saltstr,
+ const char *domain, const char *digest);
+
+static void
+nsec3hash(nsec3printer *nsec3print, const char *algostr, const char *flagstr,
+ const char *iterstr, const char *saltstr, const char *domain) {
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t buffer;
+ isc_region_t region;
+ isc_result_t result;
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char salt[DNS_NSEC3_SALTSIZE];
+ unsigned char text[1024];
+ unsigned int hash_alg;
+ unsigned int flags;
+ unsigned int length;
+ unsigned int iterations;
+ unsigned int salt_length;
+ const char dash[] = "-";
+
+ if (strcmp(saltstr, "-") == 0) {
+ salt_length = 0;
+ salt[0] = 0;
+ } else {
+ isc_buffer_init(&buffer, salt, sizeof(salt));
+ result = isc_hex_decodestring(saltstr, &buffer);
+ check_result(result, "isc_hex_decodestring(salt)");
+ salt_length = isc_buffer_usedlength(&buffer);
+ if (salt_length > DNS_NSEC3_SALTSIZE) {
+ fatal("salt too long");
+ }
+ if (salt_length == 0) {
+ saltstr = dash;
+ }
+ }
+ hash_alg = atoi(algostr);
+ if (hash_alg > 255U) {
+ fatal("hash algorithm too large");
+ }
+ flags = flagstr == NULL ? 0 : atoi(flagstr);
+ if (flags > 255U) {
+ fatal("flags too large");
+ }
+ iterations = atoi(iterstr);
+ if (iterations > 0xffffU) {
+ fatal("iterations to large");
+ }
+
+ name = dns_fixedname_initname(&fixed);
+ isc_buffer_constinit(&buffer, domain, strlen(domain));
+ isc_buffer_add(&buffer, strlen(domain));
+ result = dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL);
+ check_result(result, "dns_name_fromtext() failed");
+
+ dns_name_downcase(name, name, NULL);
+ length = isc_iterated_hash(hash, hash_alg, iterations, salt,
+ salt_length, name->ndata, name->length);
+ if (length == 0) {
+ fatal("isc_iterated_hash failed");
+ }
+ region.base = hash;
+ region.length = length;
+ isc_buffer_init(&buffer, text, sizeof(text));
+ isc_base32hexnp_totext(&region, 1, "", &buffer);
+ isc_buffer_putuint8(&buffer, '\0');
+
+ nsec3print(hash_alg, flags, iterations, saltstr, domain, (char *)text);
+}
+
+static void
+nsec3hash_print(unsigned algo, unsigned flags, unsigned iters,
+ const char *saltstr, const char *domain, const char *digest) {
+ UNUSED(flags);
+ UNUSED(domain);
+
+ fprintf(stdout, "%s (salt=%s, hash=%u, iterations=%u)\n", digest,
+ saltstr, algo, iters);
+}
+
+static void
+nsec3hash_rdata_print(unsigned algo, unsigned flags, unsigned iters,
+ const char *saltstr, const char *domain,
+ const char *digest) {
+ fprintf(stdout, "%s NSEC3 %u %u %u %s %s\n", domain, algo, flags, iters,
+ saltstr, digest);
+}
+
+int
+main(int argc, char *argv[]) {
+ bool rdata_format = false;
+ int ch;
+
+ while ((ch = isc_commandline_parse(argc, argv, "-r")) != -1) {
+ switch (ch) {
+ case 'r':
+ rdata_format = true;
+ break;
+ case '-':
+ isc_commandline_index -= 1;
+ goto skip;
+ default:
+ break;
+ }
+ }
+
+skip:
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (rdata_format) {
+ if (argc != 5) {
+ usage();
+ }
+ nsec3hash(nsec3hash_rdata_print, argv[0], argv[1], argv[2],
+ argv[3], argv[4]);
+ } else {
+ if (argc != 4) {
+ usage();
+ }
+ nsec3hash(nsec3hash_print, argv[1], NULL, argv[2], argv[0],
+ argv[3]);
+ }
+ return (0);
+}
diff --git a/bin/tools/nsec3hash.rst b/bin/tools/nsec3hash.rst
new file mode 100644
index 0000000..43a8d64
--- /dev/null
+++ b/bin/tools/nsec3hash.rst
@@ -0,0 +1,70 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. This Source Code Form is subject to the terms of the Mozilla Public
+.. License, v. 2.0. If a copy of the MPL was not distributed with this
+.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. iscman:: nsec3hash
+.. program:: nsec3hash
+.. _man_nsec3hash:
+
+nsec3hash - generate NSEC3 hash
+-------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`nsec3hash` {salt} {algorithm} {iterations} {domain}
+
+:program:`nsec3hash` **-r** {algorithm} {flags} {iterations} {salt} {domain}
+
+Description
+~~~~~~~~~~~
+
+:program:`nsec3hash` generates an NSEC3 hash based on a set of NSEC3
+parameters. This can be used to check the validity of NSEC3 records in a
+signed zone.
+
+If this command is invoked as ``nsec3hash -r``, it takes arguments in
+order, matching the first four fields of an NSEC3 record followed by the
+domain name: ``algorithm``, ``flags``, ``iterations``, ``salt``, ``domain``. This makes it
+convenient to copy and paste a portion of an NSEC3 or NSEC3PARAM record
+into a command line to confirm the correctness of an NSEC3 hash.
+
+Arguments
+~~~~~~~~~
+
+.. option:: salt
+
+ This is the salt provided to the hash algorithm.
+
+.. option:: algorithm
+
+ This is a number indicating the hash algorithm. Currently the only supported
+ hash algorithm for NSEC3 is SHA-1, which is indicated by the number
+ 1; consequently "1" is the only useful value for this argument.
+
+.. option:: flags
+
+ This is provided for compatibility with NSEC3 record presentation format, but
+ is ignored since the flags do not affect the hash.
+
+.. option:: iterations
+
+ This is the number of additional times the hash should be performed.
+
+.. option:: domain
+
+ This is the domain name to be hashed.
+
+See Also
+~~~~~~~~
+
+BIND 9 Administrator Reference Manual, :rfc:`5155`.